[cvxopt] 26/64: Imported Upstream version 1.1.2

Andreas Tille tille at debian.org
Wed Jul 20 11:23:51 UTC 2016


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository cvxopt.

commit 1a9f7caf24ca4e83b0ec94737afbc37f0b4954bb
Author: Andreas Tille <tille at debian.org>
Date:   Wed Jul 20 08:26:57 2016 +0200

    Imported Upstream version 1.1.2
---
 INSTALL                                            |    2 +-
 LICENSE                                            |   10 +-
 doc/Makefile                                       |   86 +-
 doc/blas.tex                                       |  754 -----
 doc/c-api.tex                                      |  194 --
 doc/coneprog.tex                                   | 1863 -----------
 doc/copyright.tex                                  |   46 -
 doc/cvxopt.tex                                     |  104 -
 doc/fftw.tex                                       |  162 -
 doc/figures/floorplan.pdf                          |  Bin 19279 -> 0 bytes
 doc/figures/normappr.pdf                           |  Bin 23044 -> 0 bytes
 doc/figures/portfolio1.pdf                         |  Bin 22566 -> 0 bytes
 doc/figures/portfolio2.pdf                         |  Bin 24206 -> 0 bytes
 doc/intro.tex                                      |   55 -
 doc/lapack.tex                                     | 1220 -------
 doc/matrices.tex                                   | 1363 --------
 doc/modeling.tex                                   |  747 -----
 doc/printing.tex                                   |  116 -
 doc/solvers.tex                                    | 1145 -------
 doc/source/.static/cvxopt.css                      |  630 ++++
 doc/source/blas.rst                                |  924 ++++++
 doc/source/c-api.rst                               |  218 ++
 doc/source/coneprog.rst                            | 2147 ++++++++++++
 doc/source/conf.py                                 |  182 ++
 doc/source/copyright.rst                           |   53 +
 doc/source/fftw.rst                                |  185 ++
 doc/source/floorplan.png                           |  Bin 0 -> 9062 bytes
 doc/source/index.rst                               |   23 +
 doc/source/intro.rst                               |   71 +
 doc/source/lapack.rst                              | 1660 ++++++++++
 doc/source/matrices.rst                            | 1198 +++++++
 doc/source/modeling.rst                            |  808 +++++
 doc/source/normappr.png                            |  Bin 0 -> 24912 bytes
 doc/source/portfolio1.png                          |  Bin 0 -> 46408 bytes
 doc/source/portfolio2.png                          |  Bin 0 -> 28141 bytes
 doc/source/printing.rst                            |  113 +
 doc/source/solvers.rst                             | 1299 ++++++++
 doc/source/spsolvers.rst                           |  647 ++++
 doc/spsolvers.tex                                  |  563 ----
 examples/book/README                               |    5 +-
 examples/book/chap6/robls                          |    6 +-
 examples/doc/README                                |    9 +-
 examples/doc/chap10/l1svc                          |    2 +-
 examples/doc/chap10/lp                             |    2 +-
 examples/doc/chap10/normappr                       |    2 +-
 examples/doc/chap10/roblp                          |    2 +-
 examples/doc/chap4/acent                           |    3 +-
 examples/doc/chap7/covsel                          |    3 +-
 examples/doc/chap8/conelp                          |    2 +-
 examples/doc/chap8/coneqp                          |    4 +-
 examples/doc/chap8/l1                              |    2 +-
 examples/doc/chap8/l1regls                         |    5 +-
 examples/doc/chap8/lp                              |    2 +-
 examples/doc/chap8/mcsdp                           |    2 +-
 examples/doc/chap8/portfolio                       |    2 +-
 examples/doc/chap8/qcl1                            |    3 +-
 examples/doc/chap8/sdp                             |    2 +-
 examples/doc/chap8/socp                            |    2 +-
 examples/doc/chap9/acent                           |    3 +-
 examples/doc/chap9/acent2                          |    3 +-
 examples/doc/chap9/floorplan                       |    2 +-
 examples/doc/chap9/gp                              |    2 +-
 examples/doc/chap9/l2ac                            |    2 +-
 examples/doc/chap9/robls                           |    3 +-
 src/C/SuiteSparse/CHOLMOD/Doc/ChangeLog            |   11 +
 src/C/SuiteSparse/CHOLMOD/Include/cholmod_core.h   |    4 +-
 src/C/SuiteSparse/CHOLMOD/README.txt               |    2 +-
 src/C/SuiteSparse/README.txt                       |   44 +-
 src/C/SuiteSparse/README_cvxopt                    |    2 +-
 src/C/SuiteSparse/UFconfig/UFconfig.h              |   28 +-
 src/C/SuiteSparse/UFconfig/UFconfig.mk             |    3 +
 src/C/SuiteSparse/UMFPACK/Doc/ChangeLog            |   15 +
 src/C/SuiteSparse/UMFPACK/Doc/QuickStart.tex       |   23 +-
 src/C/SuiteSparse/UMFPACK/Doc/UserGuide.stex       |   88 +-
 src/C/SuiteSparse/UMFPACK/Include/umfpack.h        |    8 +-
 .../SuiteSparse/UMFPACK/Include/umfpack_symbolic.h |   33 +-
 src/C/SuiteSparse/UMFPACK/Lib/GNUmakefile          |    3 +
 src/C/SuiteSparse/UMFPACK/Source/umf_2by2.c        |    6 +
 src/C/SuiteSparse/UMFPACK/Source/umf_dump.c        |   12 +-
 src/C/SuiteSparse/UMFPACK/Source/umf_dump.h        |    4 +-
 src/C/SuiteSparse/UMFPACK/Source/umf_kernel_init.c |   16 +-
 .../SuiteSparse/UMFPACK/Source/umf_local_search.c  |   10 +-
 src/C/SuiteSparse/UMFPACK/Source/umf_singletons.c  |   14 +-
 .../SuiteSparse/UMFPACK/Source/umfpack_qsymbolic.c |   53 +-
 .../UMFPACK/Source/umfpack_report_control.c        |    2 +
 .../UMFPACK/Source/umfpack_report_info.c           |    8 +-
 .../UMFPACK/Source/umfpack_report_symbolic.c       |    6 +-
 src/C/SuiteSparse/UMFPACK/Source/umfpack_tictoc.c  |   15 +
 src/C/SuiteSparse/UMFPACK/Source/umfpack_timer.c   |   15 +
 src/C/amd.c                                        |   52 +-
 src/C/base.c                                       | 1092 +++----
 src/C/blas.c                                       | 1189 ++++---
 src/C/blas_redefines.h                             |   11 +
 src/C/cholmod.c                                    |  386 +--
 src/C/cvxopt.h                                     |   42 +-
 src/C/dense.c                                      | 1426 ++++----
 src/C/dsdp.c                                       |  152 +-
 src/C/fftw.c                                       |  348 +-
 src/C/glpk.c                                       |  180 +-
 src/C/gsl.c                                        |   46 +-
 src/C/lapack.c                                     | 3262 +++++++++++-------
 src/C/misc.h                                       |   18 +-
 src/C/misc_solvers.c                               |  356 +-
 src/C/sparse.c                                     | 3448 ++++++++++----------
 src/C/umfpack.c                                    |  166 +-
 src/python/__init__.py                             |    4 +-
 src/python/coneprog.py                             |  332 +-
 src/python/cvxprog.py                              |    4 +-
 src/python/info.py                                 |   12 +-
 src/python/misc.py                                 |    6 +-
 src/python/modeling.py                             |    6 +-
 src/python/mosek.py                                |    4 +-
 src/python/printing.py                             |    8 +-
 src/python/solvers.py                              |    4 +-
 src/setup.py                                       |   25 +-
 115 files changed, 17286 insertions(+), 14381 deletions(-)

diff --git a/INSTALL b/INSTALL
index 3151188..8b86791 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,4 +1,4 @@
-Installation instructions for CVXOPT Version 1.1.
+Installation instructions for CVXOPT Version 1.1.2.
 
 The package requires version 2.5 or newer of Python, and is built from 
 source, so the header files and libraries for Python must be installed, 
diff --git a/LICENSE b/LICENSE
index 84eaa3e..461f174 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-CVXOPT version 1.1.  Copyright (c) 2004-2008 J. Dahl and L. Vandenberghe.
+CVXOPT version 1.1.2  Copyright (c) 2004-2009 J. Dahl and L. Vandenberghe.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -17,12 +17,12 @@ For further information, see <http://www.gnu.org/licenses/>.
 The CVXOPT distribution includes source code for a subset of the 
 SuiteSparse suite of sparse matrix algorithms, including:
 
-- AMD Version 2.2.0. Copyright (c) 2007 by Timothy A. Davis, Patrick R. 
+- AMD Version 2.2. Copyright (c) 2007 by Timothy A. Davis, Patrick R. 
   Amestoy, and Iain S. Duff.
-- CHOLMOD Version 1.7.0 Copyright (c) 2005-2007 by University of Florida,
+- CHOLMOD Version 1.7.1 Copyright (c) 2005-2009 by University of Florida,
   Timothy A. Davis and W. Hager.
-- COLAMD version 2.7.0. Copyright (c) 1998-2007 by Timothy A. Davis.
-- UMFPACK Version 5.2.0. Copyright (c) 1995-2006 by Timothy A. Davis.
+- COLAMD version 2.7.  Copyright (c) 1998-2007 by Timothy A. Davis.
+- UMFPACK Version 5.4.0. Copyright (c) 1994-2009 by Timothy A. Davis.
 
 These packages are licensed under the terms of the GNU General Public 
 License, version 2 or higher (UMFPACK, the Supernodal module of CHOLMOD)
diff --git a/doc/Makefile b/doc/Makefile
old mode 100755
new mode 100644
index fa24b80..0b09677
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -1,16 +1,70 @@
-SOURCES	= cvxopt.tex intro.tex matrices.tex blas.tex lapack.tex fftw.tex \
-	spsolvers.tex modeling.tex solvers.tex coneprog.tex c-api.tex 
-
-all: html 
-
-html: Makefile $(SOURCES) 
-	htlatex cvxopt.tex "html,3,info" 
-	tex4ht -f/cvxopt  -i/usr/share/texmf/tex4ht/ht-fonts/ \
-            -e/usr/share/texmf/tex4ht/tex4ht.env
-	t4ht -dhtml/ -f/cvxopt.tex -e/usr/share/texmf/tex4ht/tex4ht.env
-	rm -rf *.html *.4ct *.4tc *.css *.dvi *.idv *.tmp log *.toc *.aux \
-            *.lg *.xref *.png *.log
-
-clean:	
-	rm -rf *.html *.4ct *.4tc *.css *.dvi *.idv *.tmp *.log *.toc \
-            *.aux *.lg *.xref *.png *.log html/* 
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html      to make standalone HTML files"
+	@echo "  pickle    to make pickle files (usable by e.g. sphinx-web)"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview over all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+
+clean:
+	-rm -rf build/*
+
+html:
+	mkdir -p build/html build/doctrees
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
+	@echo
+	@echo "Build finished. The HTML pages are in build/html."
+
+pickle:
+	mkdir -p build/pickle build/doctrees
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files or run"
+	@echo "  sphinx-web build/pickle"
+	@echo "to start the sphinx-web server."
+
+web: pickle
+
+htmlhelp:
+	mkdir -p build/htmlhelp build/doctrees
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in build/htmlhelp."
+
+latex:
+	mkdir -p build/latex build/doctrees
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in build/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	mkdir -p build/changes build/doctrees
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes
+	@echo
+	@echo "The overview file is in build/changes."
+
+linkcheck:
+	mkdir -p build/linkcheck build/doctrees
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in build/linkcheck/output.txt."
diff --git a/doc/blas.tex b/doc/blas.tex
deleted file mode 100644
index dd91095..0000000
--- a/doc/blas.tex
+++ /dev/null
@@ -1,754 +0,0 @@
-\chapter{The BLAS Interface (\module{cvxopt.blas})}\label{chap:blas} 
-The \module{cvxopt.blas} module provides an interface to the 
-double-precision real and complex Basic Linear Algebra Subprograms 
-(BLAS).  The names and calling sequences of the Python functions in 
-the interface closely match the corresponding Fortran BLAS routines 
-(described in the references below) and their functionality is exactly 
-the same.  
-
-Many of the operations performed by the BLAS routines can be 
-implemented in a more straightforward way by using the matrix 
-arithmetic of section~\ref{s-arithmetic}, combined with the slicing 
-and indexing of section~\ref{s-indexing}.
-As an example, \samp{C = A*B} gives the same result as the BLAS
-call \samp{gemm(A,B,C)}.
-The BLAS interface offers two advantages.  First, some of the 
-functions it includes are not easily implemented using the basic 
-matrix arithmetic.  For example, BLAS includes functions that 
-efficiently exploit symmetry or triangular matrix structure.
-Second, there is a performance difference that can be significant for 
-large matrices.   Although our implementation of the basic matrix 
-arithmetic makes internal calls to BLAS, it also often requires 
-creating temporary matrices to store intermediate results.  
-The BLAS functions on the other hand always operate directly
-on their matrix arguments and never require any copying to temporary 
-matrices.  Thus they can be viewed as generalizations of the in-place 
-matrix addition and scalar multiplication of 
-section~\ref{s-arithmetic} to more complicated operations.
-
-\textbf{See also:}
-\BIT
-\item \seetext{C. L. Lawson, R. J. Hanson, D. R. Kincaid, F. T. Krogh, 
-Basic Linear Algebra Subprograms for Fortran Use,
-ACM Transactions on Mathematical Software, 5(3), 309-323, 1975.}
-\item \seetext{J. J. Dongarra, J. Du Croz, S. Hammarling, R. J. Hanson,
-An Extended Set of Fortran Basic Linear Algebra Subprograms,
-ACM Transactions on Mathematical Software, 14(1), 1-17, 1988.}
-\item \seetext{J. J. Dongarra, J. Du Croz, S. Hammarling, I. Duff,
-A Set of Level 3 Basic Linear Algebra Subprograms,
-ACM Transactions on Mathematical Software, 16(1), 1-17, 1990.}
-\EIT
-
-\section{Matrix Classes} \label{s-conventions}
-
-The BLAS exploit several types of matrix structure: symmetric, 
-Hermitian, triangular, and banded.   We represent all these matrix 
-classes by dense real or complex \mtrx\ objects, with additional 
-arguments that specify the structure.
-
-\begin{description}
-\item[Vector] 
-A real or complex \tm{n}-vector is represented by a \mtrx\ of type 
-\dtc\ or \ztc\ and length \tm{n}, with the entries of the vector stored in 
-column-major order. 
-
-\item[General matrix]
-A general real or complex \tm{m} by \tm{n} matrix is represented by 
-a real or complex \mtrx\ of size (\tm{m}, \tm{n}).
-
-\item[Symmetric matrix]
-A real or complex symmetric matrix of order \tm{n} is represented
-by a real or complex \mtrx\ of size (\tm{n}, \tm{n}), and a character 
-argument \var{uplo} with two possible values:  
-\code{'L'} and \code{'U'}.
-If \var{uplo} is \code{'L'}, the lower triangular part of the
-symmetric matrix is stored; if \var{uplo} is \code{'U'}, the upper
-triangular part is stored.  A square \mtrx\ {\var X} of size 
-({\it n}, {\it n}) can therefore be used to represent the symmetric 
-matrices
-\BEAS
-&  \left[\begin{array}{ccccc}
-X[0,0]   & X[1,0]   & X[2,0]   & \cdots & X[n-1,0] \\
-X[1,0]   & X[1,1]   & X[2,1]   & \cdots & X[n-1,1] \\
-X[2,0]   & X[2,1]   & X[2,2]   & \cdots & X[n-1,2] \\
-\vdots   & \vdots   & \vdots   & \ddots & \vdots \\
-X[n-1,0] & X[n-1,1] & X[n-1,2] & \cdots & X[n-1,n-1]
-\end{array}\right] & \mbox{if uplo = 'L'}, \\
-& \left[\begin{array}{ccccc}
-X[0,0]   & X[0,1]   & X[0,2]   & \cdots & X[0,n-1] \\
-X[0,1]   & X[1,1]   & X[1,2]   & \cdots & X[1,n-1] \\
-X[0,2]   & X[1,2]   & X[2,2]   & \cdots & X[2,n-1] \\
-\vdots   & \vdots   & \vdots   & \ddots & \vdots \\
-X[0,n-1] & X[1,n-1] & X[2,n-1] & \cdots & X[n-1,n-1]
-\end{array}\right] & \mbox{if uplo = U'}. 
-\EEAS
-
-\item[Complex Hermitian matrix]
-A complex Hermitian matrix of order \tm{n} is represented
-by a \mtrx\ of type \ztc\ and size (\tm{n}, \tm{n}), and
-a character argument \var{uplo} with the same meaning as for symmetric 
-matrices.
-A complex \mtrx\ {\var X} of size (\tm{n}, \tm{n}) can represent the 
-Hermitian  matrices
-\BEAS
-&
-\left[\begin{array}{ccccc}
-\Re X[0,0]   & \bar X[1,0]   & \bar X[2,0]   & \cdots & \bar X[n-1,0] \\
-X[1,0]   & \Re X[1,1]   & \bar X[2,1]   & \cdots & \bar X[n-1,1] \\
-X[2,0]   & X[2,1]   & \Re X[2,2]   & \cdots & \bar X[n-1,2] \\
-\vdots   & \vdots   & \vdots   & \ddots & \vdots \\
-X[n-1,0] & X[n-1,1] & X[n-1,2] & \cdots & \Re X[n-1,n-1]
-\end{array}\right] & \mbox{if uplo = 'L'}, \\
-& \left[\begin{array}{ccccc}
-\Re X[0,0]   & X[0,1]   & X[0,2]   & \cdots & X[0,n-1] \\
-\bar X[0,1]   & \Re X[1,1]   & X[1,2]   & \cdots & X[1,n-1] \\
-\bar X[0,2]   & \bar X[1,2]   & \Re X[2,2]   & \cdots & X[2,n-1] \\
-\vdots   & \vdots   & \vdots   & \ddots & \vdots \\
-\bar X[0,n-1] & \bar X[1,n-1] & \bar X[2,n-1] & \cdots & \Re X[n-1,n-1]
-\end{array}\right] & \mbox{if uplo = 'U'}.
-\EEAS
-
-\item[Triangular matrix]
-A real or complex triangular matrix of order \tm{n} is represented
-by a real or complex \mtrx\ of size (\tm{n}, \tm{n}), and two 
-character arguments: an argument \var{uplo} with possible values 
-\code{'L'} and \code{'U'} to distinguish between lower and upper 
-triangular matrices, and an argument \var{diag} with possible values 
-\code{'U'} and \code{'N'} to distinguish between unit and non-unit 
-triangular matrices.  A square \mtrx\ {\var X} of size 
-(\tm{n}, \tm{n}) can represent the triangular matrices
-\BEAS
-& \left[\begin{array}{ccccc}
-X[0,0]   & 0        & 0        & \cdots & 0 \\
-X[1,0]   & X[1,1]   & 0        & \cdots & 0 \\
-X[2,0]   & X[2,1]   & X[2,2]   & \cdots & 0 \\
-\vdots   & \vdots   & \vdots   & \ddots & \vdots \\
-X[n-1,0] & X[n-1,1] & X[n-1,2] & \cdots & X[n-1,n-1]
-\end{array}\right] & \mbox{if uplo = 'L' and diag = 'N'}, \\
-& \left[\begin{array}{ccccc}
-1   & 0   & 0   & \cdots & 0 \\
-X[1,0]   & 1   & 0   & \cdots & 0 \\
-X[2,0]   & X[2,1]   & 1   & \cdots & 0 \\
-\vdots   & \vdots   & \vdots   & \ddots & \vdots \\
-X[n-1,0] & X[n-1,1] & X[n-1,2] & \cdots & 1
-\end{array}\right] & \mbox{if uplo = 'L' and diag = 'U'}, \\
-& \left[\begin{array}{ccccc}
-X[0,0]   & X[0,1]   & X[0,2]   & \cdots & X[0,n-1] \\
-0   & X[1,1]   & X[1,2]   & \cdots & X[1,n-1] \\
-0   & 0   & X[2,2]   & \cdots & X[2,n-1] \\
-\vdots   & \vdots   & \vdots   & \ddots & \vdots \\
-0 & 0 & 0 & \cdots & X[n-1,n-1]
-\end{array}\right] & \mbox{if uplo = 'U' and diag = 'N'}, \\
-& \left[\begin{array}{ccccc}
-1   & X[0,1]   & X[0,2]   & \cdots & X[0,n-1] \\
-0   & 1   & X[1,2]   & \cdots & X[1,n-1] \\
-0   & 0   & 1   & \cdots & X[2,n-1] \\
-\vdots   & \vdots   & \vdots   & \ddots & \vdots \\
-0 & 0 & 0 & \cdots & 1
-\end{array}\right] & \mbox{if uplo = 'U' and diag = 'U'}.
-\EEAS
-
-\item[General band matrix]
-A general real or complex \tm{m} by \tm{n} band matrix  with \tm{\s{k}{l}}
-subdiagonals and \tm{\s{k}{u}} superdiagonals is represented by a real or 
-complex \mtrx\ \var{X} of size (\tm{\s{k}{l}+\s{k}{u}+1}, \tm{n}), 
-and the two integers \tm{m} and \tm{\s{k}{l}}.   
-The diagonals of the band matrix are stored in the rows of \var{X}, 
-starting at the top diagonal, and shifted horizontally so that the 
-entries of the 
-\tm{k}th column of the band matrix are stored in column \tm{k} of 
-{\var X}.  A \mtrx\ {\var X} of size (\tm{\s{k}{l}+\s{k}{u}+1}, \tm{n}) 
-therefore represents the \tm{m} by \tm{n} band matrix
-\[
-\left[ \begin{array}{ccccccc}
-X[k_u,0]     & X[k_u-1,1]     & X[k_u-2,2]     & \cdots & X[0,k_u] & 0               & \cdots \\
-X[k_u+1,0]   & X[k_u,1]       & X[k_u-1,2]     & \cdots & X[1,k_u] & X[0,k_u+1]   & \cdots \\
-X[k_u+2,0]   & X[k_u+1,1]     & X[k_u,2]       & \cdots & X[2,k_u] & X[1,k_u+1] & \cdots \\ 
- \vdots      & \vdots         &  \vdots        & \ddots & \vdots   & \vdots          & \ddots  \\
-X[k_u+k_l,0] & X[k_u+k_l-1,1] & X[k_u+k_l-2,2] & \cdots &  &  & \\
-0            & X[k_u+k_l,1]   & X[k_u+k_l-1,2] & \cdots &  &  & \\
-\vdots       & \vdots         & \vdots         & \ddots &  &  & 
-\end{array}\right].
-\]
-
-\item[Symmetric band matrix]
-A real or complex symmetric band matrix of order \tm{n} with \tm{k}
-subdiagonals, is represented by a real or complex matrix \var{X} of 
-size (\tm{k+1}, \tm{n}), and an argument {\it uplo} to indicate 
-whether the subdiagonals ({\it uplo} is \code{'L'}) or superdiagonals 
-({\it uplo} is \code{'U'}) are stored.
-The \tm{k+1} diagonals are stored as rows of \var{X}, starting at the top 
-diagonal (\ie, the main diagonal if {\it uplo} is \code{'L'},  or
-the \tm{k}th superdiagonal if {\it uplo} is \code{'U'}) and shifted
-horizontally so that the entries of the 
-\tm{k}th column of the band matrix are stored in column \tm{k} of 
-{\var X}.  A \mtrx\ \var{X} of size (\tm{k+1}, \tm{n}) can therefore
-represent the band matrices 
-\BEAS
-& \left[ \begin{array}{ccccccc}
-X[0,0] & X[1,0]   & X[2,0]   & \cdots & X[k,0]   & 0        & \cdots \\
-X[1,0] & X[0,1]   & X[1,1]   & \cdots & X[k-1,1] & X[k,1]   & \cdots \\
-X[2,0] & X[1,1]   & X[0,2]   & \cdots & X[k-2,2] & X[k-1,2] & \cdots \\
-\vdots & \vdots   &  \vdots  & \ddots & \vdots   & \vdots   & \ddots \\
-X[k,0] & X[k-1,1] & X[k-2,2] & \cdots &  &  & \\
-0      & X[k,1]   & X[k-1,2] & \cdots &  &  & \\
-\vdots & \vdots   & \vdots   & \ddots &  &  & 
-\end{array}\right] & \mbox{if uplo = 'L'}, \\
-& 
-\left[ \begin{array}{ccccccc}
-X[k,0]   & X[k-1,1] & X[k-2,2] & \cdots & X[0,k] & 0        & \cdots \\
-X[k-1,1] & X[k,1]   & X[k-1,2] & \cdots & X[1,k] & X[0,k+1] & \cdots \\
-X[k-2,2] & X[k-1,2] & X[k,2]   & \cdots & X[2,k] & X[1,k+1] & \cdots \\
-\vdots   & \vdots   & \vdots   & \ddots & \vdots & \vdots   & \ddots \\
-X[0,k]   & X[1,k]   & X[2,k]   & \cdots &  &  & \\
-0        & X[0,k+1] & X[1,k+1] & \cdots &  &  & \\
-\vdots   & \vdots   & \vdots   & \ddots &  &  & 
-\end{array}\right] & \mbox{if uplo='U'}.
-\EEAS
-
-\item[Hermitian  band matrix]
-A complex Hermitian band matrix of order \tm{n} with \tm{k} 
-subdiagonals is represented by a complex matrix of size 
-(\tm{k+1}, \tm{n}) and an argument \var{uplo}, with the same meaning
-as for symmetric band matrices.  
-A \mtrx\ \var{X} of size (\tm{k+1}, \tm{n}) can represent the band
-matrices 
-\BEAS
-& \left[ \begin{array}{ccccccc}
-\Re X[0,0] & \bar X[1,0]   & \bar X[2,0]   & \cdots & \bar X[k,0]   & 0        & \cdots \\
-X[1,0] & \Re X[0,1]   & \bar X[1,1]   & \cdots & \bar X[k-1,1] & \bar X[k,1]   & \cdots \\
-X[2,0] & X[1,1]   & \Re X[0,2]   & \cdots & \bar X[k-2,2] & \bar X[k-1,2] & \cdots \\
-\vdots & \vdots   &  \vdots  & \ddots & \vdots   & \vdots   & \ddots \\
-X[k,0] & X[k-1,1] & X[k-2,2] & \cdots &  &  & \\
-0      & X[k,1]   & X[k-1,2] & \cdots &  &  & \\
-\vdots & \vdots   & \vdots   & \ddots &  &  & 
-\end{array}\right] & \mbox{if uplo = 'L'}, \\
-& 
-\left[ \begin{array}{ccccccc}
-\Re X[k,0]   & X[k-1,1] & X[k-2,2] & \cdots & X[0,k] & 0        & \cdots \\
-\bar X[k-1,1] & \Re X[k,1]   & X[k-1,2] & \cdots & X[1,k] & X[0,k+1] & \cdots \\
-\bar X[k-2,2] & \bar X[k-1,2] & \Re X[k,2]   & \cdots & X[2,k] & X[1,k+1] & \cdots \\
-\vdots   & \vdots   & \vdots   & \ddots & \vdots & \vdots   & \ddots \\
-\bar X[0,k]   & \bar X[1,k]   & \bar X[2,k]   & \cdots &  &  & \\
-0        & \bar X[0,k+1] & \bar X[1,k+1] & \cdots &  &  & \\
-\vdots   & \vdots   & \vdots   & \ddots &  &  & 
-\end{array}\right] & \mbox{if uplo='U'}.
-\EEAS
-
-\item[Triangular band matrix]
-A triangular band matrix of order \tm{n} with \tm{k} subdiagonals or
-superdiagonals is represented by a real complex matrix of size 
-(\tm{k+1}, \tm{n}) and two character arguments \var{uplo} and 
-\var{diag}, with similar conventions as for symmetric band matrices. 
-A \mtrx\ \var{X} of size (\tm{k+1}, \tm{n}) can represent the band
-matrices 
-\BEAS
-& \left[ \begin{array}{cccc}
-X[0,0] & 0        & 0        & \cdots \\
-X[1,0] & X[0,1]   & 0        & \cdots  \\
-X[2,0] & X[1,1]   & X[0,2]   & \cdots \\
-\vdots & \vdots   & \vdots   & \ddots \\
-X[k,0] & X[k-1,1] & X[k-2,2] & \cdots \\
-0      & X[k,1]   & X[k-1,1] & \cdots \\
-\vdots & \vdots   & \vdots   & \ddots 
-\end{array}\right] & \mbox{if uplo = 'L' and diag = 'N'},  \\
-& \left[ \begin{array}{cccc}
-1      & 0        & 0        & \cdots \\
-X[1,0] & 1        & 0        & \cdots  \\
-X[2,0] & X[1,1]   & 1        & \cdots \\
-\vdots & \vdots   & \vdots   & \ddots \\
-X[k,0] & X[k-1,1] & X[k-2,2] & \cdots \\
-0      & X[k,1]   & X[k-1,2] & \cdots \\
-\vdots & \vdots   & \vdots   & \ddots 
-\end{array}\right] & \mbox{if uplo = 'L'  and diag = 'U'}, \\
-& \left[ \begin{array}{ccccccc}
-X[k,0] & X[k-1,1] & X[k-2,3] & \cdots & X[0,k]  & 0        & \cdots\\
-0      & X[k,1]   & X[k-1,2] & \cdots & X[1,k]  & X[0,k+1] & \cdots \\
-0      & 0        & X[k,2]   & \cdots & X[2,k]  & X[1,k+1] & \cdots \\
-\vdots & \vdots   &  \vdots  & \ddots & \vdots  & \vdots   & \ddots  
-\end{array}\right] & \mbox{if uplo = 'U' and diag = 'N'}, \\
-& \left[ \begin{array}{ccccccc}
-1      & X[k-1,1] & X[k-2,3] & \cdots & X[0,k]  & 0        & \cdots\\
-0      & 1        & X[k-1,2] & \cdots & X[1,k]  & X[0,k+1] & \cdots \\
-0      & 0        & 1        & \cdots & X[2,k]  & X[1,k+1] & \cdots \\
-\vdots & \vdots   &  \vdots  & \ddots & \vdots  & \vdots   & \ddots  
-\end{array}\right] & \mbox{if uplo = 'U' and diag = 'U'}.
-\EEAS
-\end{description}
-
-When discussing BLAS functions in the following sections we will
-omit several less important optional arguments that can 
-be used to select submatrices for in-place operations. 
-The complete specification is  documented in the docstrings of the 
-source code, and can be viewed with the \program{pydoc} help program.
-
-\section{Level 1 BLAS} \label{s-blas1}
-The level 1 functions implement vector operations.  
-
-\begin{funcdesc}{scal}{alpha, x}
-Scales a vector by a constant: 
-\[ 
-x := \alpha x.
-\]
-If \var{x} is a real \mtrx, the scalar argument \var{alpha} must be a 
-Python \intgr\ or \flt.  If \var{x} is complex, \var{alpha} can be an 
-\intgr, \flt, or \cmplx.
-\end{funcdesc}
-
-\begin{funcdesc}{nrm2}{x}
-Euclidean norm of a vector:  returns 
-\[
- \|x\|_2.
-\]  
-\end{funcdesc}
-
-\begin{funcdesc}{asum}{x}
-1-Norm of a vector: returns 
-\[
-\|x\|_1 \quad \mbox{(\tm{x} real)}, \qquad  
-\|\Re x\|_1 + \|\Im x\|_1 \quad \mbox{(\tm{x} complex)}.
-\]
-\end{funcdesc}
-
-\begin{funcdesc}{iamax}{x}
-Returns 
-\[
- \argmax_{k=0,\ldots,n-1} |x_k| \quad \mbox{(\tm{x} real)}, \qquad
- \argmax_{k=0,\ldots,n-1} |\Re x_k| + |\Im x_k| \quad 
- \mbox{(\tm{x} complex)}. 
-\]
-If more than one coefficient achieves the maximum, the index of the 
-first \tm{k} is returned.  
-\end{funcdesc}
-
-\begin{funcdesc}{swap}{x, y}
-Interchanges two vectors:
-\[
-  x \leftrightarrow y.
-\]
-\var{x} and \var{y} are matrices of the same type (\dtc\ or \ztc).
-\end{funcdesc}
-
-\begin{funcdesc}{copy}{x, y}
-Copies a vector to another vector:
-\[
- y := x.
-\]
-\var{x} and \var{y} are matrices of the same type (\dtc\ or \ztc).
-\end{funcdesc}
-
-\begin{funcdesc}{axpy}{x, y\optional{,alpha=1.0}}
-Constant times a vector plus a vector:  
-\[ 
-y := \alpha x + y.
-\]
-\var{x} and \var{y} are matrices of the same type (\dtc\ or \ztc).
-If \var{x} is real, the scalar argument \var{alpha} must be a Python 
-\intgr\ or \flt.  If \var{x} is complex, \var{alpha} can be an \intgr, 
-\flt, or \cmplx.  
-\end{funcdesc}
-
-\begin{funcdesc}{dot}{x, y}
-Returns 
-\[ 
-x^Hy. 
-\]  
-\var{x} and \var{y} are matrices of the same type (\dtc\ or \ztc).
-\end{funcdesc}
-
-\begin{funcdesc}{dotu}{x, y}
-Returns 
-\[ 
-x^Ty. 
-\]  
-\var{x} and \var{y} are matrices of the same type (\dtc\ or \ztc).
-\end{funcdesc}
-
-
-\section{Level 2 BLAS} \label{s-blas2}
-The level 2 functions implement matrix-vector products and 
-rank-1 and rank-2 matrix updates.
-Different types of matrix structure can be exploited using the 
-conventions of section~\ref{s-conventions}. 
-
-\begin{funcdesc}{gemv}{A, x, y\optional{, trans='N'\optional{, 
-alpha=1.0\optional{, beta=0.0}}}}
-Matrix-vector product with a general matrix:  
-\[ 
-y := \alpha Ax + \beta y \quad (\mathrm{trans} = \mathrm{'N'}),
-  \qquad 
-y := \alpha A^T x + \beta y \quad (\mathrm{trans} = \mathrm{'T'}), 
-  \qquad
-y := \alpha A^H x + \beta y \quad (\mathrm{trans} = \mathrm{'C'}). 
-\]
-The arguments \var{A}, \var{x} and {\var y} must have the same type 
-(\dtc\ or \ztc).  Complex values of \var{alpha} and \var{beta} are only
-allowed if \var{A} is complex. 
-\end{funcdesc}
-
-\begin{funcdesc}{symv}{A, x, y\optional{, uplo='L'\optional{, 
-alpha=1.0\optional{, beta=0.0}}}}
-Matrix-vector  product with a real symmetric matrix:  
-\[
-   y := \alpha A x + \beta y,
-\]
-where \tm{A} is a real symmetric matrix.  
-The arguments \var{A}, \var{x} and {\var y} must have 
-type \dtc\ and \var{alpha} and \var{beta} must be real.
-\end{funcdesc}
-
-\begin{funcdesc}{hemv}{A, x, y\optional{, uplo='L'\optional{, 
-alpha=1.0\optional{, beta=0.0}}}}
-Matrix-vector  product with a real symmetric or complex Hermitian 
-matrix: 
-\[
-   y := \alpha A x + \beta y,
-\]
-where \tm{A} is real symmetric or complex Hermitian.
-The arguments \var{A}, \var{x} and {\var y} must have the same
-type (\dtc\ or \ztc).  
-Complex values of \var{alpha} and \var{beta} are only
-allowed if \var{A} is complex. 
-\end{funcdesc}
-
-\begin{funcdesc}{trmv}{A, x\optional{, uplo='L'\optional{, 
-trans='N'\optional{, diag='N'}}}}
-Matrix-vector  product with a triangular matrix: 
-\[ 
-x := Ax \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
-x := A^T x \quad (\mathrm{trans} = \mathrm{'T'}), \qquad
-x := A^H x \quad (\mathrm{trans} = \mathrm{'C'}), 
-\]
-where \tm{A} is square and triangular.
-The arguments \var{A} and \var{x} must have the same type (\dtc\ or \ztc).
-\end{funcdesc}
-
-\begin{funcdesc}{trsv}{A, x\optional{, uplo='L'\optional{, 
-trans='N'\optional{, diag='N'}}}}
-Solution of a nonsingular triangular set of linear equations:
-\[ 
-x := A^{-1}x \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
-x := A^{-T}x \quad (\mathrm{trans} = \mathrm{'T'}), \qquad 
-x := A^{-H}x \quad (\mathrm{trans} = \mathrm{'C'}), 
-\]
-where \tm{A} is square and triangular with nonzero diagonal 
-elements.  The arguments \var{A} and \var{x} must have the same type 
-(\dtc\ or \ztc).
-\end{funcdesc}
-
-\begin{funcdesc}{gbmv}{A, m, kl, x, y\optional{, trans='N'
-\optional{, alpha=1.0\optional{, beta=0.0}}}}
-Matrix-vector product with a general band matrix:
-\[ 
-y := \alpha Ax + \beta y \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
-y := \alpha A^T x + \beta y \quad (\mathrm{trans} = \mathrm{'T'}), 
-\qquad 
-y := \alpha A^H x + \beta y \quad (\mathrm{trans} = \mathrm{'C'}),
-\]
-where  \tm{A} is a rectangular band matrix with \tm{m} rows and 
-\tm{\s{k}{l}} subdiagonals.
-The arguments \var{A}, \var{x} and {\var y} must have the same
-type (\dtc\ or \ztc).
-Complex values of \var{alpha} and \var{beta} are only allowed if \var{A} is
- complex.
-\end{funcdesc}
-
-\begin{funcdesc}{sbmv}{A, x, y\optional{, uplo='L'\optional{, 
-alpha=1.0\optional{, beta=0.0}}}}
-Matrix-vector  product with a real symmetric band matrix:
-\[
- y := \alpha Ax + \beta y,
-\]
-where \tm{A} is a real symmetric band matrix.
-The arguments \var{A}, \var{x} and {\var y} must have type \dtc\ and 
-\var{alpha} and \var{beta} must be real.
-\end{funcdesc}
-
-\begin{funcdesc}{hbmv}{A, x, y\optional{, uplo='L'\optional{, 
-alpha=1.0\optional{, beta=0.0}}}}
-Matrix-vector  product with a real symmetric or complex Hermitian 
-band matrix:
-\[
- y := \alpha Ax + \beta y,
-\]
-where \tm{A} is a real symmetric or complex Hermitian band matrix.
-The arguments \var{A}, \var{x} and {\var y} must have the same type
-(\dtc\ or \ztc).  
-Complex values of \var{alpha} and \var{beta} are only allowed if 
-\var{A} is complex. 
-\end{funcdesc}
-
-\begin{funcdesc}{tbmv}{A, x\optional{, uplo='L'\optional{, 
-trans\optional{, diag}}}}
-Matrix-vector  product with a triangular band matrix:
-\[
-x := Ax \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
-x := A^T x \quad (\mathrm{trans} = \mathrm{'T'}), \qquad 
-x := A^H x \quad (\mathrm{trans} = \mathrm{'C'}). 
-\]
-The arguments \var{A} and \var{x} must have the same type 
-(\dtc\ or \ztc).  
-\end{funcdesc}
-
-\begin{funcdesc}{tbsv}{A, x\optional{, uplo='L'\optional{, 
-trans\optional{, diag}}}}
-Solution of a triangular banded set of linear equations:
-\[
-x := A^{-1}x \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
-x := A^{-T} x \quad (\mathrm{trans} = \mathrm{'T'}), \qquad
-x := A^{-H} x \quad (\mathrm{trans} = \mathrm{'T'}), 
-\]
-where \tm{A} is a triangular band matrix of with nonzero diagonal 
-elements.
-The arguments \var{A} and \var{x} must have the same type 
-(\dtc\ or \ztc).  
-\end{funcdesc}
-
-\begin{funcdesc}{ger}{x, y, A\optional{, alpha=1.0}}
-General rank-1 update:
-\[ 
-A := A + \alpha x y^H,
-\]
-where \tm{A} is a general matrix.
-The arguments \var{A}, \var{x} and \var{y} must have the same type 
-(\dtc\ or \ztc).  
-Complex values of \var{alpha} are only allowed if \var{A} is complex.
-\end{funcdesc}
-
-\begin{funcdesc}{geru}{x, y, A\optional{, alpha=1.0}}
-General rank-1 update:
-\[ 
-A := A + \alpha x y^T, 
-\]
-where \tm{A} is a general matrix.
-The arguments \var{A}, \var{x} and \var{y} must have the same type 
-(\dtc\ or \ztc).  
-Complex values of \var{alpha} are only allowed if \var{A} is complex.
-\end{funcdesc}
-
-\begin{funcdesc}{syr}{x, A\optional{, uplo='L'\optional{, alpha=1.0}}}
-Symmetric rank-1 update:
-\[
- A := A + \alpha xx^T,
-\]
-where \tm{A} is a real symmetric matrix.
-The arguments \var{A} and \var{x} must have type \dtc.  
-\var{alpha} must be a real number.
-\end{funcdesc}
-
-\begin{funcdesc}{her}{x, A\optional{, uplo='L'\optional{, alpha=1.0}}}
-Hermitian rank-1 update:
-\[
- A := A + \alpha xx^H, 
-\]
-where \tm{A} is a real symmetric or complex Hermitian matrix.
-The arguments \var{A} and \var{x} must have the same type 
-(\dtc\ or \ztc).  
-\var{alpha} must be a real number.
-\end{funcdesc}
-
-\begin{funcdesc}{syr2}{x, y, A\optional{, uplo='L'\optional{, 
-alpha=1.0}}}
-Symmetric rank-2  update:
-\[
- A := A + \alpha (xy^T + yx^T),
-\]
-where \tm{A} is a real symmetric matrix.
-The arguments \var{A}, \var{x} and \var{y} must have type \dtc.  
-\var{alpha} must be real.
-\end{funcdesc}
-
-\begin{funcdesc}{her2}{x, y, A\optional{, uplo='L'\optional{, 
-alpha=1.0}}}
-Symmetric rank-2  update:
-\[
- A := A + \alpha xy^H + \bar \alpha yx^H,
-\]
-where \tm{A} is a a real symmetric or complex Hermitian matrix.
-The arguments \var{A}, \var{x} and \var{y} must have the same type  
-(\dtc\ or \ztc).  
-Complex values of \var{alpha} are only allowed if \var{A} is complex.
-\end{funcdesc}
-
-As an example, the following code multiplies the tridiagonal matrix
-\[
-A = \left[\begin{array}{rrrr}
-  1 &  6 &  0 & 0 \\ 
-  2 & -4 &  3 & 0 \\ 
-  0 & -3 & -1 & 1 
-  \end{array}\right]
-\]
-with the vector {\it x} = (1,-1,2,-2).
-\begin{verbatim}
->>> from cvxopt import matrix
->>> from cvxopt.blas import gbmv
->>> A = matrix([[0., 1., 2.],  [6., -4., -3.],  [3., -1., 0.],  [1., 0., 0.]])
->>> x = matrix([1., -1., 2., -2.])
->>> y = matrix(0., (3,1))
->>> gbmv(A, 3, 1, x, y)
->>> print y
-[-5.00e+00]
-[ 1.20e+01]
-[-1.00e+00]
-\end{verbatim}
-
-The following example illustrates the use of \function{tbsv()}.
-\begin{verbatim}
->>> from cvxopt import matrix
->>> from cvxopt.blas import tbsv
->>> A = matrix([-6., 5., -1., 2.], (1,4))
->>> x = matrix(1.0, (4,1))
->>> tbsv(A, x)  # x := diag(A)^{-1}*x
->>> print x
-[-1.67e-01]
-[ 2.00e-01]
-[-1.00e+00]
-[ 5.00e-01]
-\end{verbatim}
-
-
-\section{Level 3 BLAS} \label{s-blas3}
-The level 3 BLAS include functions for matrix-matrix multiplication.
-
-\begin{funcdesc}{gemm}{A, B, C\optional{, transA='N'\optional{, 
-transB='N'\optional{, alpha=1.0\optional{, beta=0.0}}}}}
-Matrix-matrix product of two general matrices:  
-\[
-  C := \alpha \op(A) \op(B) + \beta C 
-\]
-where
-\[
-\op(A) =  \left\{ \begin{array}{ll}
- A & \mathrm{transA} = \mathrm{'N'} \\
- A^T & \mathrm{transA} = \mathrm{'T'} \\
- A^H & \mathrm{transA} = \mathrm{'C'} \end{array} \right.
-\qquad
-\op(B) =  \left\{ \begin{array}{ll}
- B & \mathrm{transB} = \mathrm{'N'} \\
- B^T & \mathrm{transB} = \mathrm{'T'} \\
- B^H & \mathrm{transB} = \mathrm{'C'}. \end{array} \right.
-\]
-The arguments \var{A}, \var{B} and \var{C} must have the same type 
-(\dtc\ or \ztc).
-Complex values of \var{alpha} and \var{beta} are only allowed 
-if \var{A} is complex.
-\end{funcdesc}
-
-\begin{funcdesc}{symm}{A, B, C\optional{, side='L'\optional{, 
-uplo='L'\optional{, alpha=1.0\optional{,  beta=0.0}}}}}
-Product of a real or complex symmetric matrix \tm{A} and a general 
-matrix \tm{B}:
-\[
- C := \alpha AB + \beta C \quad (\mathrm{side} = \mathrm{'L'}), \qquad 
- C := \alpha BA + \beta C \quad (\mathrm{side} = \mathrm{'R'}). 
-\]
-The arguments \var{A}, \var{B} and \var{C} must have the same type 
-(\dtc\ or \ztc).  Complex values of \var{alpha} and \var{beta} are 
-only allowed if \var{A} is complex.
-\end{funcdesc}
-
-\begin{funcdesc}{hemm}{A, B, C\optional{, side='L'\optional{, 
-uplo='L'\optional{, alpha=1.0\optional{,  beta=0.0}}}}}
-Product of a real symmetric or complex Hermitian matrix {\it A} and a 
-general matrix {\it B}:
-\[
- C := \alpha AB + \beta C \quad (\mathrm{side} = \mathrm{'L'}), \qquad 
- C := \alpha BA + \beta C \quad (\mathrm{side} = \mathrm{'R'}). 
-\]
-The arguments \var{A}, \var{B} and \var{C} must have the same type 
-(\dtc\ or \ztc).
-Complex values of \var{alpha} and \var{beta} are only allowed if 
-\var{A} is complex.
-\end{funcdesc}
-
-\begin{funcdesc}{trmm}{A, B\optional{, side='L'\optional{, 
-uplo='L'\optional{, transA='N'\optional{, diag='N'\optional{, 
-alpha=1.0}}}}}}
-Product of a triangular matrix {\it A} and a general matrix {\it B}:
-\[
- B := \alpha\op(A)B \quad (\mathrm{side} = \mathrm{'L'}), \qquad 
- B := \alpha B\op(A) \quad (\mathrm{side} = \mathrm{'R'}), \qquad 
- \op(A) =  \left\{ \begin{array}{ll}
- A & \mathrm{transA} = \mathrm{'N'} \\
- A^T & \mathrm{transA} = \mathrm{'T'} \\
- A^H & \mathrm{transA} = \mathrm{'C'}. \end{array} \right.
-\]
-The arguments \var{A} and \var{B} must have the same type (\dtc\ or 
-\ztc).   Complex values of \var{alpha} are only allowed if \var{A} is 
-complex.
-\end{funcdesc}
-
-\begin{funcdesc}{trsm}{A, B\optional{, side='L'\optional{, 
-uplo='L'\optional{, transA='N'\optional{, diag='N'\optional{, 
-alpha=1.0}}}}}}
-Solution of a nonsingular triangular system of equations:
-\[
- B := \alpha \op(A)^{-1}B \quad (\mathrm{side} = \mathrm{'L'}), \qquad 
- B := \alpha B\op(A)^{-1} \quad (\mathrm{side} = \mathrm{'R'}), \qquad 
- \op(A) =  \left\{ \begin{array}{ll}
- A & \mathrm{transA} = \mathrm{'N'} \\
- A^T & \mathrm{transA} = \mathrm{'T'} \\
- A^H & \mathrm{transA} = \mathrm{'C'}, \end{array} \right.
-\]
-where \tm{A} is triangular and \tm{B} is a general matrix.
-The arguments \var{A} and \var{B} must have the same type (\dtc\ or 
-\ztc).   Complex values of \var{alpha} are only allowed if \var{A} is 
-complex.
-\end{funcdesc}
-
-\begin{funcdesc}{syrk}{A, C\optional{, uplo='L'\optional{, 
-trans='N'\optional{, alpha=1.0\optional{, beta=0.0}}}}}
-Rank-{\it k} update of a real or complex symmetric matrix {\it C}:
-\[
- C := \alpha AA^T + \beta C \quad (\mathrm{trans} = \mathrm{'N'}), 
- \qquad 
- C := \alpha A^TA + \beta C \quad (\mathrm{trans} = \mathrm{'T'}), 
-\]
-where \tm{A} is a general matrix.
-The arguments \var{A} and \var{C} must have the same type (\dtc\ or 
-\ztc).  Complex values of \var{alpha} and \var{beta} are only allowed 
-if \var{A} is complex.
-\end{funcdesc}
-
-\begin{funcdesc}{herk}{A, C\optional{, uplo='L'\optional{, 
-trans='N'\optional{, alpha=1.0\optional{, beta=0.0}}}}}
-Rank-\tm{k} update of a real symmetric or complex Hermitian matrix \tm{C}:
-\[
- C := \alpha AA^H + \beta C \quad (\mathrm{trans} = \mathrm{'N'}), 
- \qquad 
- C := \alpha A^HA + \beta C \quad (\mathrm{trans} = \mathrm{'C'}),
-\]
-where \tm{A} is a general matrix.
-The arguments \var{A} and \var{C} must have the same type (\dtc\ or
-\ztc).  \var{alpha} and \var{beta} must be real.
-\end{funcdesc}
-
-\begin{funcdesc}{syr2k}{A, B, C\optional{, uplo='L'\optional{, 
-trans='N'\optional{, alpha=1.0\optional{, beta=0.0}}}}}
-Rank-{\it 2k} update of a real or complex symmetric matrix {\it C}:
-\[
- C := \alpha (AB^T + BA^T) + \beta C \quad 
-  (\mathrm{trans} = \mathrm{'N'}), \qquad 
- C := \alpha (A^TB + B^TA) + \beta C \quad 
-  (\mathrm{trans} = \mathrm{'T'}). 
-\]
-\tm{A} and \tm{B} are general real or complex matrices.
-The arguments \var{A}, \var{B} and \var{C} must have the same
-type.  Complex values of \var{alpha} and \var{beta} are only 
-allowed if \var{A} is complex.
-\end{funcdesc}
-
-\begin{funcdesc}{her2k}{A, B, C\optional{, uplo='L'\optional{, 
-trans='N'\optional{, alpha=1.0\optional{ beta=0.0}}}}}
-Rank-\tm{2k} update of a real symmetric or complex Hermitian matrix \tm{C}:
-\[
- C := \alpha AB^H + \bar \alpha BA^H + \beta C \quad 
-  (\mathrm{trans} = \mathrm{'N'}), \qquad 
- C := \alpha A^HB + \bar\alpha B^HA + \beta C \quad 
-  (\mathrm{trans} = \mathrm{'C'}), 
-\]
-where \tm{A} and \tm{B} are general matrices.
-The arguments \var{A}, \var{B} and \var{C} must have the same type 
-(\dtc\ or \ztc).  Complex values of \var{alpha} are only allowed if 
-\var{A} is complex.  \var{beta} must be real.
-\end{funcdesc}
diff --git a/doc/c-api.tex b/doc/c-api.tex
deleted file mode 100644
index 8bfcdb8..0000000
--- a/doc/c-api.tex
+++ /dev/null
@@ -1,194 +0,0 @@
-\chapter{C API}\label{chap:c-api}
-The API can be used to extend CVXOPT with interfaces to 
-external C routines and libraries. 
-A C program that creates or manipulates the dense or sparse matrix
-objects defined in CVXOPT must include the 
-\file{cvxopt.h} header file in the \file{src} directory of the 
-distribution.
-
-Before the C API can be used in an extension module it must be
-initialized by calling the macro \function{import\_cvxopt}. 
-As an example
-we show the module initialization from the \module{cvxopt.blas} module,
-which itself uses the API:
-\begin{verbatim}
-PyMODINIT_FUNC initblas(void)
-{
-  PyObject *m;
-
-  m = Py_InitModule3("cvxopt.blas", blas_functions, blas__doc__);
-
-  if (import_cvxopt() < 0)
-    return;
-}
-\end{verbatim}
-  
-
-\section{Dense Matrices}
-As can be seen from the header file \file{cvxopt.h}, a \mtrx\ is
-essentially a  structure with four fields.
-The fields \cdata{nrows} and \cdata{ncols} are two integers that 
-specify the dimensions.
-The \cdata{id} field controls the type of the matrix and can have 
-values \constant{DOUBLE}, \constant{INT} and \constant{COMPLEX}. 
-The \cdata{buffer} field is an array that contains the matrix elements 
-stored contiguously in column-major order. 
-
-The following C functions can be used to create matrices.
-\begin{cfuncdesc}{matrix *}{Matrix\_New}{int nrows, int ncols, int id}
-Returns a \mtrx\ object of type \var{id} with \var{nrows} rows
-and \var{ncols} columns. The elements of the matrix are uninitialized.
-\end{cfuncdesc}
-
-\begin{cfuncdesc}{matrix *}{Matrix\_NewFromMatrix}{matrix *src, int id}
-Returns a copy of the matrix \var{src} converted to type \var{id}. 
-The following type conversions are allowed: \itc\ to \dtc,
-\itc\ to \ztc\ and \dtc\  to \ztc.
-\end{cfuncdesc}
-
-\begin{cfuncdesc}{matrix *}{Matrix\_NewFromSequence}{PyListObject *x, int id}
-Creates a matrix of type \var{id} from the Python sequence type \var{x}. The
-returned matrix has size \code{(len(\var{x}),1)}.  
-The size can be changed by modifying the \member{nrows} and 
-\member{ncols} fields of the returned matrix.
-\end{cfuncdesc}
-
-To illustrate the creation and manipulation of dense matrices (as well
-as the Python C API), we show the code for the \function{uniform()} 
-function from \module{cvxopt.random} described in 
-section~\ref{s-random}.
-\begin{verbatim}
-PyObject * uniform(PyObject *self, PyObject *args, PyObject *kwrds) 
-{
-  matrix *obj;
-  int i, nrows, ncols = 1;
-  double a = 0, b = 1;
-  char *kwlist[] = {"nrows", "ncols", "a", "b", NULL};
-
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "i|idd", kwlist, 
-          &nrows, &ncols, &a, &b)) return NULL;
-  
-  if ((nrows<0) || (ncols<0)) {
-    PyErr_SetString(PyExc_TypeError, "dimensions must be non-negative");
-    return NULL;
-  }
-  
-  if (!(obj = Matrix_New(nrows, ncols, DOUBLE)))
-    return PyErr_NoMemory();
-  
-  for (i = 0; i < nrows*ncols; i++)
-    MAT_BUFD(obj)[i] = Uniform(a,b);
-  
-  return (PyObject *)obj;
-}
-\end{verbatim}
-
-\section{Sparse Matrices}
-Sparse matrices are stored in compressed column storage (CCS) 
-format.   For a general  \var{nrows} by \var{ncols} sparse matrix with 
-\var{nnz} nonzero entries this means the following.  The sparsity
-pattern and the nonzero values are stored in three fields:
-\begin{description}
-\item[values:] A \dtc\ or \ztc\ matrix of size \code{(\var{nnz},1)} 
- with the nonzero entries of the matrix stored columnwise.  
-\item[rowind:] An array of integers of length \var{nnz} containing the
-row indices of the nonzero entries, stored in the same order as 
-\var{values}.
-\item[colptr:] An array of integers of length \code{\var{ncols}+1} with
-for each column of the matrix the index of the first element in 
-\var{values} from that column.  More precisely, 
-\code{\var{colptr}[0]} is \code{0}, and for 
-\code{\var{k} = 0, 1, \ldots, \var{ncols}-1},
-\code{\var{colptr}[k+1]} is equal to \code{\var{colptr}[k]} plus the 
-number of nonzeros in column \tm{k} of the matrix.
-Thus, \code{\var{colptr}[\var{ncols}]} is equal to \var{nnz}, the 
-number of nonzero entries.
-\end{description}
-
-For example, for the matrix
-\[ 
-A=\left [\begin{array}{cccc}
-    1 & 0 & 0 & 5\\
-    2 & 0 & 4 & 0\\
-    0 & 0 & 0 & 6\\
-    3 & 0 & 0 & 0
-\end{array}\right]
-\] 
-the elements of \var{values}, \var{rowind} and \var{colptr} are:
-\begin{quote}
-  \var{values}: 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, \qquad  
-  \var{rowind}: 0, 1,3, 1, 0, 2, \qquad 
-  \var{colptr}: 0, 3, 3, 4, 6.
-\end{quote}
-It is crucial that for each column the row indices in \var{rowind} are
-sorted; the equivalent representation 
-\begin{quote}
-  \var{values}: 3.0, 2.0, 1.0, 4.0, 5.0, 6.0, \qquad  
-  \var{rowind}: 3, 1, 0, 1, 0, 2, \qquad 
-  \var{colptr}: 0, 3, 3, 4, 6
-\end{quote}
-is not allowed (and will likely cause the program to crash).
-
-The \cdata{nzmax} field specifies the number of non-zero elements the
-matrix can store.  It is equal to the length of \var{rowind} and 
-\var{values}; this number can be larger that 
-\code{\var{colptr}[\var{nrows}]}, but never less. 
-This field makes it possible to preallocate a certain amount of 
-memory to avoid reallocations if the matrix is constructed
-sequentially by filling in elements. 
-In general the \var{nzmax} field can safely be ignored, however, since 
-it will always be adjusted automatically as the number of non-zero 
-elements grows.
-
-The \cdata{id} field controls the type of the matrix and can have 
-values \constant{DOUBLE} and \constant{COMPLEX}. 
-
-Sparse matrices are created using the following functions from the API. 
-\begin{cfuncdesc}{spmatrix *}{SpMatrix\_New}{int nrows, int ncols, int
-    nzmax, int id} 
-  Returns a sparse zero matrix with \var{nrows} rows and
-  \var{ncols} columns. \var{nzmax} is the number of elements that will
-  be allocated (the length of the \var{values} and \var{rowind}
-  fields).  
-\end{cfuncdesc}
-
-\begin{cfuncdesc}{spmatrix *}{SpMatrix\_NewFromMatrix}{spmatrix *src, int
-    id}
-  Returns a copy the sparse matrix \var{src}. 
-\end{cfuncdesc}
-
-\begin{cfuncdesc}{spmatrix *}{SpMatrix\_NewFromIJV}{matrix *I, matrix *J, 
-    matrix *V, int nrows, int ncols, int nzmax, int id}
-  Creates a sparse matrix with \var{nrows} rows and \var{ncols}
-  columns from a triplet description. \var{I} and \var{J}
-  must be integer matrices and \var{V} either a double or complex matrix,
-  or \constant{NULL}. If \var{V} is \constant{NULL} the values of the 
-  entries in the matrix are undefined, otherwise they are
-  specified by \var{V}.  Repeated entries in \var{V} are summed. 
-  The number of allocated elements is given by \var{nzmax}, which is 
-  adjusted if it is smaller than the required amount. 
-\end{cfuncdesc}
-
-We illustrate use of the sparse matrix class by listing the source
-code for the \function{real()} method, which returns the real part of
-a sparse matrix: 
-
-\begin{verbatim}
-static PyObject * spmatrix_real(spmatrix *self) {
-
-  if (SP_ID(self) != COMPLEX) 
-    return (PyObject *)SpMatrix_NewFromMatrix(self, 0, SP_ID(self));
-  
-  spmatrix *ret = SpMatrix_New(SP_NROWS(self), SP_NCOLS(self), 
-      SP_NNZ(self), DOUBLE);
-  if (!ret) return PyErr_NoMemory();
-
-  int i;
-  for (i=0; i < SP_NNZ(self); i++) 
-    SP_VALD(ret)[i] = creal(SP_VALZ(self)[i]);
-  
-  memcpy(SP_COL(ret), SP_COL(self), (SP_NCOLS(self)+1)*sizeof(int_t));
-  memcpy(SP_ROW(ret), SP_ROW(self), SP_NNZ(self)*sizeof(int_t));
-  return (PyObject *)ret;
-}
-\end{verbatim}
diff --git a/doc/coneprog.tex b/doc/coneprog.tex
deleted file mode 100644
index 6e4acd9..0000000
--- a/doc/coneprog.tex
+++ /dev/null
@@ -1,1863 +0,0 @@
-\chapter{Cone Programming (\module{cvxopt.solvers})}
-\label{chap:coneprog}
-
-In this chapter we consider convex optimization problems of the form
-\[
- \begin{array}{ll}
- \mbox{minimize}   & (1/2) x^TPx + q^T x \\
- \mbox{subject to} & G x \preceq h \\ & Ax = b.
- \end{array}
-\]
-The linear inequality is a generalized inequality with respect to a 
-proper convex cone.  It may include componentwise vector inequalities, 
-second-order cone inequalities, and linear matrix inequalities.  
-
-The main solvers are \function{conelp()} and \function{coneqp()},
-described in sections~\ref{s-conelp} and~\ref{s-coneqp}.
-The function \function{conelp()} is restricted to problems with
-linear cost functions, and can detect primal and dual infeasibility.
-The function \function{coneqp()} solves the general quadratic problem, 
-but requires the problem to be strictly primal and dual feasible.
-For convenience (and backward compatibility), simpler interfaces to these
-function are also provided that handle pure linear programs, 
-quadratic programs, second-order cone programs, and semidefinite 
-programs.  These are described in 
-sections~\ref{s-lpsolver}--\ref{s-sdpsolver}.
-In section~\ref{s-conelp-struct} we explain how custom solvers
-can be implemented that exploit structure in cone programs.  
-The last two sections describe optional interfaces to external solvers, 
-and the algorithm parameters that control the cone programming solvers.
-
-\section{Linear Cone Programs} \label{s-conelp}
-
-\begin{funcdesc}{conelp}{c, G, h\optional{, dims\optional{, A, b\optional{,
-primalstart\optional{, dualstart\optional{, kktsolver}}}}}}
-Solves a pair of primal and dual cone programs
-\[ 
- \begin{array}[t]{ll}
- \mbox{minimize} & c^T x \\
- \mbox{subject to} & G x + s = h \\ & Ax = b \\ & s \succeq 0
- \end{array}
-\qquad\qquad\qquad\qquad
- \begin{array}[t]{ll}
- \mbox{maximize} & -h^T z - b^T y \\
- \mbox{subject to} & G^T z + A^T y + c = 0 \\
-   & z \succeq 0.
- \end{array}
-\]
-The primal variables are \tm{x} and \tm{s}.  
-The dual variables are \tm{y} and \tm{z}.  The inequalities are 
-interpreted as $s \in C$, $z\in C$, where \tm{C} is a cone defined as a 
-Cartesian product of a nonnegative orthant, a number of second-order 
-cones, and a number of positive semidefinite cones:
-\[
-C = C_0 \times C_1 \times \cdots \times C_M \times C_{M+1} \times
- \cdots \times C_{M+N}
-\]
-with
-\[
-C_0 = 
- \{ u \in \reals^l \;| \; u_k \geq 0, \; k=1, \ldots,l\}, \qquad 
-C_{k+1} = \{ (u_0, u_1) \in \reals \times \reals^{r_{k}-1} \; | \;
-   u_0 \geq \|u_1\|_2 \},  \quad k=0,\ldots, M-1, \qquad 
-C_{k+M+1} = \left\{ \svec(u) \; | \;
-  u \in \symm^{t_k}_+ \right\}, \quad k=0,\ldots,N-1.
-\]
-In this definition, $\svec(u)$ denotes a symmetric matrix \tm{u} stored 
-as a vector in column major order.  The structure of \tm{C} is specified 
-by \var{dims}.  This argument is a dictionary with three fields. 
-\begin{description}
-\item[\var{dims['l']}:] \tm{l}, the dimension of the nonnegative orthant
- (a nonnegative integer).
-\item[\var{dims['q']}:] $[r_0, \ldots, r_{M-1}]$, 
- a list with the dimensions of the second-order cones (positive integers).
-\item[\var{dims['s']}:] $[t_0, \ldots, t_{N-1}]$, 
- a list with the dimensions of the positive semidefinite cones
- (nonnegative integers).
-\end{description}
-The default value of \var{dims} is \code{\{'l': G.size[0], 'q': [], 
-'s': []\}}, \ie, by default the inequality is interpreted as a 
-componentwise vector inequality. 
-
-The arguments \var{c}, \var{h} and \var{b} are real single-column dense 
-matrices.  \var{G} and \var{A} are real dense or sparse matrices.
-The number of rows of \var{G} and \var{h} is equal to
-\[
- K = l + \sum_{k=0}^{M-1} r_k + \sum_{k=0}^{N-1} t_k^2.
-\]
-The columns of \var{G} and \var{h} are vectors in
-\[
-\reals^l \times \reals^{r_0} \times \cdots \times 
-\reals^{r_{M-1}} \times \reals^{t_0^2}  \times \cdots \times 
-\reals^{t_{N-1}^2},
-\]
-where the last \tm{N} components represent symmetric matrices stored in 
-column major order.  The strictly upper triangular entries of these 
-matrices are not accessed (i.e.,  the symmetric matrices are stored
-in the 'L'-type column major order used in the \module{blas} and
-\module{lapack} modules).
-The default values for \var{A} and \var{b} are matrices with 
-zero rows, meaning that there are no equality constraints.  
-
-\var{primalstart} is a dictionary with keys \code{'x'} and \code{'s'}, 
-used as an optional primal starting point.   
-\code{primalstart['x']} and 
-\code{primalstart['s']} are real dense matrices of size
-\tm{(n,1)} and \tm{(K,1)}, respectively, where \tm{n} is the
-length of \var{c}.
-The vector \code{primalstart['s']} must be strictly positive with respect
-to the cone \tm{C}.
-
-\var{dualstart} is a dictionary with keys \code{'y'} and \code{'z'}, 
-used as an optional dual starting point.
-\code{dualstart['y']} and 
-\code{dualstart['z']} are real dense matrices of size
-\tm{(p,1)} and \tm{(K,1)}, respectively, where \tm{p} is the 
-number of rows in \var{A}.
-The vector \code{dualstart['s']} must be strictly positive with respect
-to the cone \tm{C}.
-
-The role of the optional argument \var{kktsolver} is explained in 
-section~\ref{s-conelp-struct}.  
-
-\function{conelp()} returns a dictionary that contains the result and 
-information about the accuracy of the solution.
-The most important fields have keys \code{'status'}, 
-\code{'x'}, \code{'s'}, \code{'y'}, \code{'z'}.  
-The \code{'status'} field  is a string with possible values
-\code{'optimal'}, \code{'primal infeasible'}, \code{'dual infeasible'}
-and \code{'unknown'}.  The meaning of the \code{'x'}, \code{'s'}, 
-\code{'y'}, \code{'z'} fields depends on the value of \code{'status'}.
-\begin{description}
-\item[\code{'optimal'}] In this case the \code{'x'}, \code{'s'}, 
-\code{'y'} and \code{'z'} entries contain the primal and dual solutions,
-which approximately satisfy
-\[
- Gx + s = h, \qquad Ax=b, \qquad G^T z  + A^T y + c = 0, \qquad 
- s \succeq 0, \qquad z \succeq 0,  \qquad s^T z =0.
-\]
-The other entries in the output dictionary summarize the accuracy
-with which these optimality conditions are satisfied.
-The fields \code{'primal objective'}, \code{'dual objective'}, and
-\code{'gap'} give the primal objective \tm{c^Tx}, dual objective
-\tm{-h^Tz - b^Ty}, and the gap \tm{s^Tz}.  The field \code{'relative gap'}
-is the relative gap, defined as
-\[
- \frac{s^Tz}{\max\{-c^Tx, -h^Tz-b^Ty\}} \quad \mbox{if} \quad
- \max\{-c^Tx, -h^Tz-b^Ty\} > 0
-\]
-and \None\ otherwise.  The fields \code{'primal infeasibility'} 
-and \code{'dual infeasibility'} are the residuals in the primal and dual
-equality constraints, defined as
-\[
- \max\{ \frac{\|Gx+s-h\|}{\max\{1, \|h\|\}}, 
-  \frac{\|Ax-b\|}{\max\{1,\|b\|\}} \}, \qquad
- \frac{\|G^Tz + A^Ty + c\|}{\max\{1, \|c\|\}}, 
-\]
-respectively.
-
-\item[\code{'primal infeasible'}]
-The \code{'x'} and \code{'s'} entries are \None, and the \code{'y'}, 
-\code{'z'} entries provide an approximate certificate of 
-infeasibility, \ie, vectors that approximately satisfy
-\[
- G^T z + A^T y = 0, \qquad h^T z + b^T y = -1, \qquad z \succeq 0.
-\]
-The field \code{'residual as primal infeasibility certificate'} gives
-the residual 
-\[
- \frac{\|G^Tz + A^Ty\|}{\max\{1, \|c\|\}}.
-\]
-
-\item[\code{'dual infeasible'}]  
-The \code{'y'} and \code{'z'} entries are \None, and the \code{'x'} 
-and \code{'s'} entries contain an approximate certificate of dual 
-infeasibility 
-\[
- Gx + s = 0, \qquad Ax=0, \qquad  c^T x = -1, \qquad s \succeq 0.
-\]
-The field \code{'residual as dual infeasibility certificate'} gives
-the residual 
-\[
- \max\{ \frac{\|Gx + s\|}{\max\{1, \|h\|\}},
- \frac{\|Ax\|}{\max\{1,\|b\|\}} \}.
-\]
-
-\item[\code{'unknown'}] 
-This indicates that the algorithm terminated 
-early due to numerical difficulties or because the maximum number 
-of iterations was reached. 
-The \code{'x'}, \code{'s'}, \code{'y'}, \code{'z'} entries 
-contain the iterates when the algorithm terminated.
-Whether these entries are useful, as approximate solutions or certificates
-of primal and dual infeasibility, can be determined from the other fields 
-in the dictionary.
-The fields \code{'primal objective'}, \code{'dual objective'}, 
-\code{'gap'}, \code{'relative gap'}, \code{'primal infeasibility'},
-\code{'dual infeasibility'} are defined as when \code{'status'} is
-\code{'optimal'}.
-The field \code{'residual as primal infeasibility certificate'} is defined
-as
-\[
-\frac{\|G^Tz+A^Ty\|}{-(h^Tz + b^Ty) \max\{1, \|h\| \}}.
-\]
-if \tm{h^Tz+b^Ty < 0}, and \None\ otherwise.  A small value of this 
-residual indicates that \tm{y} and \tm{z}, divided by \tm{-h^Tz-b^Ty}, are 
-an approximate proof of primal infeasibility.
-The field \code{'residual as dual infeasibility certificate'} is defined
-as
-\[
-\max\{\frac{\|Gx+s\|}{-c^Tx \max\{1,\|h\|\}}, 
- \frac{\|Ax\|}{-c^Tx \max\{1,\|b\|\}}\}
-\]
-if \tm{c^Tx < 0}, and as \None\ otherwise.
-A small value indicates that \tm{x} and \tm{s},
-divided by \tm{-c^Tx} are an approximate proof of dual infeasibility.  
-\end{description}
-
-It is required that 
-\[
-\Rank(A) = p, \qquad 
-\Rank(\left[\begin{array}{c} G \\ A \end{array}\right]) = n,
-\]
-where \tm{p} is the number or rows of \tm{A} and \tm{n} is the number of 
-columns of \tm{G} and \tm{A}.
-\end{funcdesc}
-
-As an example we solve the problem
-\[
-\begin{array}{ll}
-\mbox{minimize}   &  -6x_1 - 4x_2 - 5x_3 \\*[1ex]
-\mbox{subject to} & 16x_1 - 14x_2 + 5x_3 \leq -3 \\*[1ex]
-  & 7x_1 + 2x_2 \leq 5 \\*[1ex]
-  & \left( (8x_1 + 13x_2 - 12x_3 - 2)^2 + (-8x_1 + 18x_2 + 6x_3 - 14)^2
- + (x_1 - 3x_2 - 17x_3 - 13)^2\right)^{1/2} \leq -24x_1 - 7x_2 + 15x_3 + 12 \\*[1ex]
- &  (x_1^2 + x_2^2 + x_3^2)^{1/2} \leq 10  \\*[1ex]
- & \left[\begin{array}{ccc}
- 7x_1 + 3x_2 + 9x_3  & -5x_1 + 13x_2 + 6x_3 &   x_1 - 6x_2 -6x_3 \\
--5x_1 + 13x_2 + 6x_3 &  x_1 + 12x_2 -7x_3 & -7x_1 -10x_2 - 7x_3 \\
- x_1 - 6x_2 -6x_3 & -7x_1 -10x_2 -7 x_3 & 
--4x_1 -28 x_2 -11x_3 \end{array}\right]  
-\preceq 
-\left[\begin{array}{ccc}
-68  & -30 & -19 \\
--30 & 99  &  23 \\
--19 & 23  & 10 \end{array}\right].
-\end{array} 
-\]
-
-\begin{verbatim}
->>> from cvxopt import matrix, solvers
->>> c = matrix([-6., -4., -5.])
->>> G = matrix([[ 16., 7.,  24.,  -8.,   8.,  -1.,  0., -1.,  0.,  0.,   7.,  -5.,   1.,  -5.,   1.,  -7.,   1.,   -7.,  -4.], 
-                [-14., 2.,   7., -13., -18.,   3.,  0.,  0., -1.,  0.,   3.,  13.,  -6.,  13.,  12., -10.,  -6.,  -10., -28.],
-                [  5., 0., -15.,  12.,  -6.,  17.,  0.,  0.,  0., -1.,   9.,   6.,  -6.,   6.,  -7.,  -7.,  -6.,   -7., -11.]])
->>> h = matrix( [ -3., 5.,  12.,  -2., -14., -13., 10.,  0.,  0.,  0.,  68., -30., -19., -30.,  99.,  23., -19.,   23.,  10.] )
->>> dims = {'l': 2, 'q': [4, 4], 's': [3]}
->>> sol = solvers.conelp(c, G, h, dims)
->>> sol['status']
-'optimal'
->>> print sol['x']
-[-1.22e+00]
-[ 9.66e-02]
-[ 3.58e+00]
->>> print sol['z']
-[ 9.30e-02]
-[ 2.04e-08]
-[ 2.35e-01]
-[ 1.33e-01]
-[-4.74e-02]
-[ 1.88e-01]
-[ 2.79e-08]
-[ 1.85e-09]
-[-6.32e-10]
-[-7.59e-09]
-[ 1.26e-01]
-[ 8.78e-02]
-[-8.67e-02]
-[ 8.78e-02]
-[ 6.13e-02]
-[-6.06e-02]
-[-8.67e-02]
-[-6.06e-02]
-[ 5.98e-02]
-\end{verbatim}
-
-Only the entries of \var{G} and \var{h} defining the lower triangular 
-portions of the coefficients in the linear matrix inequalities are 
-accessed.  We obtain the same result if we define \var{G} and \var{h} as 
-below. 
-\begin{verbatim}
->>> G = matrix([[ 16., 7.,  24.,  -8.,   8.,  -1.,  0., -1.,  0.,  0.,   7.,  -5.,   1.,  0.,   1.,  -7.,  0.,  0.,  -4.], 
-                [-14., 2.,   7., -13., -18.,   3.,  0.,  0., -1.,  0.,   3.,  13.,  -6.,  0.,  12., -10.,  0.,  0., -28.],
-                [  5., 0., -15.,  12.,  -6.,  17.,  0.,  0.,  0., -1.,   9.,   6.,  -6.,  0.,  -7.,  -7.,  0.,  0., -11.]])
->>> h = matrix( [ -3., 5.,  12.,  -2., -14., -13., 10.,  0.,  0.,  0.,  68., -30., -19.,  0.,  99.,  23.,  0.,  0.,  10.] )
-\end{verbatim}
-
-\section{Quadratic Cone Programs} \label{s-coneqp}
-\begin{funcdesc}{coneqp}{P, q\optional{, G, h\optional{, 
- dims\optional{, A, b\optional{, initvals\optional{, kktsolver}}}}}}
-Solves a pair of primal and dual quadratic cone programs
-\[ %\label{e-coneqp}
- \begin{array}[t]{ll}
- \mbox{minimize} & (1/2) x^T Px + q^T x \\
- \mbox{subject to} & G x + s = h \\ & Ax = b \\ & s \succeq 0
- \end{array}
-\qquad\qquad\qquad\qquad
- \begin{array}[t]{ll}
- \mbox{maximize} & -(1/2) (q+G^Tz+A^Ty)^T P^\dagger
-            (q+G^Tz+A^Ty) -h^T z - b^T y \\
- \mbox{subject to} & q + G^T z + A^T y \in \Range(P) \\ & z \succeq 0.
- \end{array}
-\]
-The primal variables are \tm{x} and the slack variable \tm{s}.  
-The dual variables are \tm{y} and \tm{z}.  The inequalities are 
-interpreted as $s \in C$, $z\in C$, where \tm{C} is a cone defined as a 
-Cartesian product of a nonnegative orthant, a number of second-order 
-cones, and a number of positive semidefinite cones:
-\[
-C = C_0 \times C_1 \times \cdots \times C_M \times C_{M+1} \times
- \cdots \times C_{M+N}
-\]
-with
-\[
-C_0 = \{ u \in \reals^l \;| \; u_k \geq 0, \; k=1, \ldots,l\}, \qquad 
-C_{k+1} = \{ (u_0, u_1) \in \reals \times \reals^{r_{k}-1} \; | \;
-   u_0 \geq \|u_1\|_2 \},  \quad k=0,\ldots, M-1, \qquad 
-C_{k+M+1} = \left\{ \svec(u) \; | \;
-  u \in \symm^{t_k}_+ \right\}, \quad k=0,\ldots,N-1.
-\]
-In this definition, $\svec(u)$ denotes a symmetric matrix \tm{u} stored as
-a vector in column major order.  The structure of \tm{C} is specified by 
-\var{dims}.  This argument is a dictionary with three fields. 
-\begin{description}
-\item[\var{dims['l']}:] \tm{l}, the dimension of the nonnegative orthant
- (a nonnegative integer).
-\item[\var{dims['q']}:] $[r_0, \ldots, r_{M-1}]$, 
- a list with the dimensions of the second-order cones (positive integers).
-\item[\var{dims['s']}:] $[t_0, \ldots, t_{N-1}]$, 
- a list with the dimensions of the positive semidefinite cones
- (nonnegative integers).
-\end{description}
-The default value of \var{dims} is \code{\{'l': G.size[0], 'q': [], 
-'s': []\}}, \ie, by default the inequality is interpreted as a 
-componentwise vector inequality. 
-
-\var{P} is a square dense or sparse real matrix, representing a 
-positive semidefinite symmetric matrix in \code{'L'} storage, \ie, only 
-the lower triangular part of \var{P} is referenced.  
-\var{q} is a real single-column dense matrix.
-
-The arguments \var{h} and \var{b} are real single-column dense 
-matrices.  \var{G} and \var{A} are real dense or sparse matrices.
-The number of rows of \var{G} and \var{h} is equal to
-\[
- K = l + \sum_{k=0}^{M-1} r_k + \sum_{k=0}^{N-1} t_k^2.
-\]
-The columns of \var{G} and \var{h} are vectors in
-\[
-\reals^l \times \reals^{r_0} \times \cdots \times 
-\reals^{r_{M-1}} \times \reals^{t_0^2}  \times \cdots \times 
-\reals^{t_{N-1}^2},
-\]
-where the last \tm{N} components represent symmetric matrices stored in 
-column major order.  The strictly upper triangular entries of these 
-matrices are not accessed (i.e.,  the symmetric matrices are stored
-in the 'L'-type column major order used in the \module{blas} and
-\module{lapack} modules).
-The default values for \var{G}, \var{h}, \var{A} and \var{b} are 
-matrices with zero rows, meaning that there are no inequality or
-equality constraints.  
-
-\var{initvals} is a dictionary with keys \code{'x'}, \code{'s'}, 
-\code{'y'}, \code{'z'} used as an optional starting point.   
-The vectors \code{initvals['s']} and \code{initvals['z']} 
-must be strictly positive with respect to the cone \tm{C}.
-If the argument \var{initvals} or any the four entries in it are missing, 
-default starting points are used for the corresponding variables.
-
-The role of the optional argument \var{kktsolver} is explained in 
-section~\ref{s-conelp-struct}.  
-
-\function{coneqp()} returns a dictionary that contains the result and 
-information about the accuracy of the solution.
-The most important fields have keys \code{'status'}, 
-\code{'x'}, \code{'s'}, \code{'y'}, \code{'z'}.  
-The \code{'status'} field  is a string with possible values
-\code{'optimal'} and \code{'unknown'}.  
-\begin{description}
-\item[\code{'optimal'}] In this case the \code{'x'}, \code{'s'}, 
-\code{'y'} and \code{'z'} entries contain primal and dual 
-solutions, which approximately satisfy
-\[
- Gx+s = h, \qquad Ax = b, \qquad Px + G^Tz + A^T y + c = 0, \qquad
- s \succeq 0, \qquad z \succeq 0, \qquad s^T z  = 0.
-\]
-\item[\code{'unknown'}] 
-This indicates that the algorithm terminated 
-early due to numerical difficulties or because the maximum number 
-of iterations was reached. 
-The \code{'x'}, \code{'s'}, \code{'y'}, \code{'z'} entries 
-contain the iterates when the algorithm terminated.
-\end{description}
-The other entries in the output dictionary summarize the accuracy
-with which the optimality conditions are satisfied.
-The fields \code{'primal objective'}, \code{'dual objective'}, and
-\code{'gap'} give the primal objective \tm{c^Tx}, the dual objective
-calculated as 
-\[
- (1/2) x^TPx + q^T x + z^T(Gx-h) + y^T(Ax-b)
-\]
-and the gap \tm{s^Tz}.  The field \code{'relative gap'}
-is the relative gap, defined as
-\[
- \frac{s^Tz}{-\mbox{primal objective}}
- \quad \mbox{if\ } \mbox{primal objective} < 0, \qquad
- \frac{s^Tz}{\mbox{dual objective}}
- \quad \mbox{if\ } \mbox{dual objective} > 0, \qquad
-\]
-and \None\ otherwise.  The fields \code{'primal infeasibility'} 
-and \code{'dual infeasibility'} are the residuals in the primal and dual
-equality constraints, defined as
-\[
- \max\{ \frac{\|Gx+s-h\|}{\max\{1, \|h\|\}}, 
-  \frac{\|Ax-b\|}{\max\{1,\|b\|\}} \}, \qquad
-  \frac{\|Px + G^Tz + A^Ty + q\|}{\max\{1, \|q\|\}}, 
-\]
-respectively.
-
-It is required that the problem is solvable and that 
-\[
-\Rank(A) = p, \qquad 
-\Rank(\left[\begin{array}{c} P \\ G \\ A \end{array}\right]) = n,
-\]
-where \tm{p} is the number or rows of \tm{A} and \tm{n} is the number of 
-columns of \tm{G} and \tm{A}.
-\end{funcdesc}
-
-As an example, we solve a constrained least-squares problem
-\[
- \begin{array}{ll}
- \mbox{minimize} & \|Ax - b\|_2^2 \\
- \mbox{subject to} &  x \succeq 0 \\
-    & \|x\|_2 \leq 1 
- \end{array}
-\]
-with 
-\[
- A = \left[ \begin{array}{rrr}
-  0.3 &  0.6 & -0.3 \\
- -0.4 &  1.2 &  0.0   \\
- -0.2 & -1.7 &  0.6  \\
- -0.4 &  0.3 & -1.2 \\
-  1.3 & -0.3 & -2.0 
- \end{array} \right], \qquad 
- b = \left[ \begin{array}{r} 1.5 \\ 0.0 \\ -1.2 \\ -0.7 \\ 0.0 
- \end{array} \right]. 
-\]
-\begin{verbatim}
->>> from cvxopt import matrix, solvers
->>> A = matrix([ [ .3, -.4,  -.2,  -.4,  1.3 ], 
-                 [ .6, 1.2, -1.7,   .3,  -.3 ],
-                 [-.3,  .0,   .6, -1.2, -2.0 ] ])
->>> b = matrix([ 1.5, .0, -1.2, -.7, .0])
->>> m, n = A.size
->>> I = matrix(0.0, (n,n))
->>> I[::n+1] = 1.0
->>> G = matrix([-I, matrix(0.0, (1,n)), I])
->>> h = matrix(n*[0.0] + [1.0] + n*[0.0])
->>> dims = {'l': n, 'q': [n+1], 's': []}
->>> x = solvers.coneqp(A.T*A, -A.T*b, G, h, dims)['x']
->>> print x
-[ 7.26e-01]
-[ 6.18e-01]
-[ 3.03e-01]
-\end{verbatim}
-
-\section{Linear Programming} \label{s-lpsolver}
-The function \function{lp()} is an interface to \function{conelp()} for 
-linear programs.  It also provides the option of using the linear 
-programming solvers from GLPK or MOSEK.
-
-\begin{funcdesc}{lp}{c, G, h\optional{, A, b\optional{, 
-solver\optional{, primalstart\optional{, dualstart}}}}}
-Solves the pair of primal and dual linear programs
-\[
- \begin{array}[t]{ll}
- \mbox{minimize} & c^T x \\
- \mbox{subject to} & G x + s = h \\ & Ax = b \\ & s \succeq 0
- \end{array}
- \qquad\qquad
- \begin{array}[t]{ll}
- \mbox{maximize} & -h^T z - b^T y \\
- \mbox{subject to} & G^T z + A^T y + c = 0 \\
-   & z \succeq 0.
- \end{array}
-\]
-The inequalities are componentwise vector inequalities.
-
-The \var{solver} argument is used to choose among three solvers.  
-When it is omitted or \None, the CVXOPT function \function{conelp()} is 
-used.   The external solvers GLPK and MOSEK (if installed) can be selected
-by setting \code{\var{solver} = 'glpk'} or \code{\var{solver} = 'mosek'}; 
-see section~\ref{s-external}.  
-The meaning of the other arguments and the return value are the same as 
-for \function{conelp()} called with 
-\code{dims = \{'l': G.size[0], 'q': [], 's': []\}}. 
-
-The initial values are ignored when \code{solver} \code{'mosek'} or 
-\code{'glpk'}.
-With the GLPK option, the solver does not return certificates of
-primal or dual infeasibility: if the status is
-\code{'primal infeasible'} or \code{'dual infeasible'}, all entries of 
-the output dictionary are \None.
-If the GLPK or MOSEK solvers are used, and the code returns with
-status \code{'unknown'}, all the other fields in the output dictionary
-are \None.
-\end{funcdesc}
-
-As a simple example we solve the LP
-\[
- \begin{array}[t]{ll}
-  \mbox{minimize} & -4x_1 - 5x_2 \\
-  \mbox{subject to} &  2x_1 + x_2 \leq 3 \\
- & x_1 + 2x_2 \leq 3 \\
- & x_1 \geq 0, \quad x_2 \geq 0.
- \end{array} 
-\]
-\begin{verbatim}
->>> from cvxopt import matrix, solvers
->>> c = matrix([-4., -5.])
->>> G = matrix([[2., 1., -1., 0.], [1., 2., 0., -1.]])
->>> h = matrix([3., 3., 0., 0.])
->>> sol = solvers.lp(c, G, h)
->>> print sol['x']
-[ 1.00e+00]
-[ 1.00e+00]
-\end{verbatim}
-
-\section{Quadratic Programming} \label{s-qp}
-The function \function{qp()} is an interface to \function{coneqp()} for 
-quadratic programs.  It also provides the option of using the quadratic 
-programming solver from MOSEK.
-\begin{funcdesc}{qp}{P, q\optional{, G, h \optional{, A, b\optional{,
-solver\optional{, initvals}}}}}
-Solves the pair of primal and dual convex quadratic programs 
-\[
-\begin{array}[t]{ll}
-\mbox{minimize} & (1/2) x^TPx + q^T x \\
-\mbox{subject to} & Gx \preceq h \\ & Ax = b.
-\end{array}
-\qquad\qquad\qquad\qquad
- \begin{array}[t]{ll}
- \mbox{maximize} & -(1/2) (q+G^Tz+A^Ty)^T P^\dagger
-            (q+G^Tz+A^Ty) -h^T z - b^T y \\
- \mbox{subject to} & q + G^T z + A^T y \in \Range(P) \\ & z \succeq 0.
- \end{array}
-\]
-The inequalities are componentwise vector inequalities.
-
-The default CVXOPT solver is used when the \var{solver} argument
-is absent or \None.  The MOSEK solver (if installed) can be 
-selected by setting 
-\code{\var{solver} = 'mosek'}; see section~\ref{s-external}.
-The meaning of the other arguments and the return value is the same as 
-for \function{coneqp()} called with 
-\code{dims = \{'l': G.size[0], 'q': [], 's': []\}}.
-
-When the \code{solver = 'mosek'} is used the initial values are ignored,
-and the \code{'status'} string in the solution dictionary 
-can take four possible values: \code{'optimal'},
-\code{'unknown'}.
-\code{'primal infeasible'}, \code{'dual infeasible'}. 
-\begin{description}
-\item [\code{'primal infeasible'}]  
-This means that a certificate of primal infeasibility has been found.   
-The \code{'x'} and \code{'s'} 
-entries are \None, and the
-\code{'z'} and \code{'y'} entries are vectors that approximately satisfy
-\[
- G^Tz + A^T y = 0, \qquad h^Tz + b^Ty = -1, \qquad z \succeq 0.
-\]
-
-\item [\code{'dual infeasible'}]  This means that a certificate of
-dual infeasibility has been found.   The \code{'z'} and \code{'y'}
-entries are \None, and the \code{'x'} and \code{'s'} entries are
-vectors that approximately satisfy
-\[
- Px = 0, \qquad q^Tx = -1, \qquad Gx + s = 0, \qquad Ax=0, \qquad
- s \succeq  0.
-\]
-\end{description}
-\end{funcdesc}
-
-As an example we compute the trade-off curve on page 187
-of the book \citetitle{http://www.stanford.edu/\%7Eboyd/cvxbook}{Convex 
-Optimization}, by solving the quadratic program 
-\[
-\begin{array}{ll}
-\mbox{minimize} & -\bar p^T x + \mu x^T S x \\
-\mbox{subject to} & \ones^T x = 1, \quad x \succeq 0
-\end{array}
-\]
-for a sequence of positive values of {\it mu}. 
-The code below computes the trade-off curve and produces two figures 
-using the \ulink{Matplotlib}{http://matplotlib.sourceforge.net} package.
-\begin{center}
-\includegraphics[width=10cm]{figures/portfolio1.eps}
-\hspace*{\fill}
-\includegraphics[width=10cm]{figures/portfolio2.eps}
-\end{center}
-
-\begin{verbatim}
-from math import sqrt
-from cvxopt import matrix
-from cvxopt.blas import dot 
-from cvxopt.solvers import qp
-import pylab
-
-# Problem data.
-n = 4
-S = matrix([[ 4e-2,  6e-3, -4e-3,    0.0 ], 
-            [ 6e-3,  1e-2,  0.0,     0.0 ],
-            [-4e-3,  0.0,   2.5e-3,  0.0 ],
-            [ 0.0,   0.0,   0.0,     0.0 ]])
-pbar = matrix([.12, .10, .07, .03])
-G = matrix(0.0, (n,n))
-G[::n+1] = -1.0
-h = matrix(0.0, (n,1))
-A = matrix(1.0, (1,n))
-b = matrix(1.0)
-
-# Compute trade-off.
-N = 100
-mus = [ 10**(5.0*t/N-1.0) for t in xrange(N) ]
-portfolios = [ qp(mu*S, -pbar, G, h, A, b)['x'] for mu in mus ]
-returns = [ dot(pbar,x) for x in portfolios ]
-risks = [ sqrt(dot(x, S*x)) for x in portfolios ]
-
-# Plot trade-off curve and optimal allocations.
-pylab.figure(1, facecolor='w')
-pylab.plot(risks, returns)
-pylab.xlabel('standard deviation')
-pylab.ylabel('expected return')
-pylab.axis([0, 0.2, 0, 0.15])
-pylab.title('Risk-return trade-off curve (fig 4.12)')
-pylab.yticks([0.00, 0.05, 0.10, 0.15])
-
-pylab.figure(2, facecolor='w')
-c1 = [ x[0] for x in portfolios ] 
-c2 = [ x[0] + x[1] for x in portfolios ]
-c3 = [ x[0] + x[1] + x[2] for x in portfolios ] 
-c4 = [ x[0] + x[1] + x[2] + x[3] for x in portfolios ]
-pylab.fill(risks + [.20], c1 + [0.0], '#F0F0F0') 
-pylab.fill(risks[-1::-1] + risks, c2[-1::-1] + c1, facecolor = '#D0D0D0') 
-pylab.fill(risks[-1::-1] + risks, c3[-1::-1] + c2, facecolor = '#F0F0F0') 
-pylab.fill(risks[-1::-1] + risks, c4[-1::-1] + c3, facecolor = '#D0D0D0') 
-pylab.axis([0.0, 0.2, 0.0, 1.0])
-pylab.xlabel('standard deviation')
-pylab.ylabel('allocation')
-pylab.text(.15,.5,'x1')
-pylab.text(.10,.7,'x2')
-pylab.text(.05,.7,'x3')
-pylab.text(.01,.7,'x4')
-pylab.title('Optimal allocations (fig 4.12)')
-pylab.show()
-\end{verbatim}
-
-
-\section{Second-Order Cone Programming} \label{s-socpsolver}
-The function \function{socp()} is a simpler interface to 
-\function{conelp()} for cone programs with no linear matrix inequality 
-constraints.
-
-\begin{funcdesc}{socp}{c\optional{, Gl, hl\optional{, Gq, hq\optional{, 
- A, b\optional{, solver\optional{, primalstart\optional{, dualstart}}}}}}}
-Solves the pair of primal and dual second-order cone programs
-\[
- \begin{array}[t]{ll}
- \mbox{minimize} & c^T x \\
- \mbox{subject to} 
-   & G_k x + s_k = h_k, \quad k = 0, \ldots, M  \\ 
-   & Ax = b \\ 
-   & s_0 \succeq 0 \\
-   & s_{k0} \geq \|s_{k1}\|_2, \quad k = 1, \ldots, M
- \end{array}
- \qquad\qquad
- \begin{array}[t]{ll}
- \mbox{maximize} & - \sum_{k=0}^M h_k^Tz_k - b^T y \\
- \mbox{subject to} & \sum_{k=0}^M G_k^T z_k + A^T y + c = 0 \\
-   & z_0 \succeq 0 \\
-   & z_{k0} \geq \|z_{k1}\|_2, \quad k=1,\ldots,M.
- \end{array}
-\]
-The inequalities 
-\[
-  s_0 \succeq 0, \qquad z_0 \succeq 0
-\]
-are componentwise vector inequalities. 
-In the other inequalities, it is assumed that the variables are partitioned
-as
-\[
- s_k = (s_{k0}, s_{k1}) \in\reals\times\reals^{r_{k}-1}, \qquad 
- z_k = (z_{k0}, z_{k1}) \in\reals\times\reals^{r_{k}-1}, \qquad
- k=1,\ldots,M.
-\]
-The input argument \var{c} is a real single-column dense matrix.
-The arguments \var{Gl} and \var{hl} are the coefficient matrix 
-\tm{\s{G}{0}} and the righthand side \tm{\s{h}{0}} 
-of the componentwise inequalities.
-\var{Gl} is a real dense or sparse matrix; \var{hl} is a real single-column
-dense matrix.   The default values for \var{Gl} and \var{hl} are matrices
-with zero rows.
-
-The argument \var{Gq} is a list of \tm{M} dense or sparse matrices 
-\tm{\s{G}{1}}, \ldots, \tm{\s{G}{M}}. 
-The argument \var{hq} is a list of \tm{M} dense single-column matrices 
-\tm{\s{h}{1}}, \ldots, \tm{\s{h}{M}}.  
-The elements of \var{Gq} and \var{hq} must have at least one row.
-The default values of \var{Gq} and \var{hq} are empty lists.
-
-\var{A} is dense or sparse matrix and \var{b} is a single-column dense 
-matrix.  The default values for \var{A} and \var{b} are matrices with 
-zero rows. 
-
-The \var{solver} argument is used to choose between two
-solvers: the CVXOPT \function{conelp()} solver 
-(used when \var{solver} is absent or
-equal to \None) and the external solver MOSEK 
-(\code{\var{solver}='mosek'}); see section~\ref{s-external}.
-With the \code{'mosek'} option the code does not accept problems with 
-equality constraints.
-
-\var{primalstart} and \var{dualstart} are dictionaries with optional 
-primal, respectively, dual starting points.
-\var{primalstart} has elements \code{'x'}, \code{'sl'}, \code{'sq'}.
-\code{primalstart['x']} and \code{primalstart['sl']} are single-column
- dense matrices with the initial values of \tm{x} and \tm{\s{s}{0}}; 
-\code{primalstart['sq']} is a list of single-column matrices with the
-initial values of \tm{\s{s}{1}}, \ldots, \tm{\s{s}{M}}.
-The initial values must satisfy the inequalities in the primal problem 
-strictly, but not necessarily the equality constraints.
-
-\var{dualstart} has elements \code{'y'}, \code{'zl'}, \code{'zq'}.
-\code{dualstart['y']} and \code{dualstart['zl']} are single-column dense 
-matrices with the initial values of \tm{y} and \tm{\s{z}{0}}.
-\code{dualstart['zq']} is a list of single-column matrices with the 
-initial values of \tm{\s{z}{1}}, \ldots, \tm{\s{z}{M}}.  These values must
-satisfy the dual inequalities strictly, but not necessarily the equality
-constraint.
-
-The arguments \var{primalstart} and \var{dualstart} are ignored when 
-the MOSEK solver is used.
-
-\function{socp()} returns a dictionary that include entries with
-keys \var{'status'},
-\code{'x'}, \code{'sl'}, \code{'sq'}, \code{'y'}, \code{'zl'}, \code{'zq'},
-The \code{'sl'} and \code{'zl'} fields are matrices with the primal 
-slacks and dual variables associated with the componentwise linear 
-inequalities.
-The \code{'sq'} and \code{'zq'} fields are lists with the primal slacks 
-and dual variables associated with the second-order cone inequalities.
-The other entries in the output dictionary have the same meaning as
-in the output of \function{conelp()}.
-\end{funcdesc}
-
-As an example, we solve  the second-order cone program
-\[
-\begin{array}{ll}
-\mbox{minimize} & -2x_1 + x_2 + 5x_3 \\*[2ex]
-\mbox{subject to} 
- & \left\| \left[\begin{array}{c}
-   -13 x_1 + 3x_2 + 5x_3 - 3 \\ -12 x_1 + 12x_2 - 6x_3 - 2
-   \end{array}\right] \right\|_2 \leq -12 x_1 - 6 x_2 + 5x_3 - 12  \\*[2ex]
- & \left\| \left[\begin{array}{c}
- -3x_1 + 6x_2 + 2x_3 \\ x_1 + 9x_2 + 2x_3 + 3 \\ -x_1 - 19 x_2 + 3 x_3 - 42
-   \end{array}\right] \right\|_2 \leq 
-   -3x_1 + 6x_2 - 10x_3 + 27.
-\end{array}
-\]
-\begin{verbatim}
->>> from cvxopt import matrix, solvers
->>> c = matrix([-2., 1., 5.])
->>> G = [ matrix( [[12., 13., 12.], [6., -3., -12.], [-5., -5., 6.]] ) ]
->>> G += [ matrix( [[3., 3., -1., 1.], [-6., -6., -9., 19.], [10., -2., -2., -3.]] ) ]
->>> h = [ matrix( [-12., -3., -2.] ),  matrix( [27., 0., 3., -42.] ) ]
->>> sol = solvers.socp(c, Gq = G, hq = h)
->>> sol['status']
-optimal
->>> print sol['x']
-[-5.02e+00]
-[-5.77e+00]
-[-8.52e+00]
->>> print sol['zq'][0]
-[ 1.34e+00]
-[-7.63e-02]
-[-1.34e+00]
->>> print sol['zq'][1]
-[ 1.02e+00]
-[ 4.02e-01]
-[ 7.80e-01]
-[-5.17e-01]
-\end{verbatim}
-
-
-\section{Semidefinite Programming} \label{s-sdpsolver}
-The function \function{sdp()} is a simple interface to 
-\function{conelp()} for cone programs with no second-order cone 
-constraints.
-It also provides the option of using the DSDP semidefinite programming
-solver.
-
-\begin{funcdesc}{sdp}{c\optional{, Gl, hl\optional{, 
- Gs, hs\optional{, A, b\optional{, solver\optional{, 
- primalstart\optional{, dualstart}}}}}}}
-
-Solves the pair of primal and dual semidefinite programs
-\[
- \begin{array}[t]{ll}
- \mbox{minimize} & c^T x \\
- \mbox{subject to} 
-   & G_0 x + s_0 = h_0 \\
-   & G_k x + \svec{(s_k)} = \svec{(h_k)}, \quad k = 1, \ldots, N  \\ 
-   & Ax = b \\ 
-   & s_0 \succeq 0 \\
-   & s_k \succeq 0, \quad k=1,\ldots,N
- \end{array}
- \qquad\qquad
- \begin{array}[t]{ll}
- \mbox{maximize} & - h_0^Tz_0 - \sum_{k=1}^N \Tr(h_kz_k) - b^T y \\
- \mbox{subject to} & 
-  G_0^Tz_0 + \sum_{k=1}^N G_k^T \svec(z_k) + A^T y + c = 0 \\
-   & z_0 \succeq 0 \\
-   & z_k \succeq 0, \quad k=1,\ldots,N.
- \end{array}
-\]
-The inequalities 
-\[
-   s_0 \succeq 0, \qquad z_0 \succeq 0
-\]
-are componentwise vector inequalities.   The other inequalities
-are matrix inequalities (\ie, the require the lefthand sides 
-to be positive semidefinite).
-We use the notation $\svec(z)$ to denote a symmetric matrix \tm{z} 
-stored in column major order as a column vector.
-
-The input argument \var{c} is a real single-column dense matrix.
-The arguments \var{Gl} and \var{hl} are the coefficient matrix 
-\tm{\s{G}{0}} and the righthand side \tm{\s{h}{0}} of the 
-componentwise inequalities.
-\var{Gl} is a real dense or sparse matrix; \var{hl} is a real single-column
-dense matrix.   The default values for \var{Gl} and \var{hl} are matrices
-with zero rows.
-
-\var{Gs} and \var{hs} are lists of length \tm{N} that specify the 
-linear matrix inequality constraints.
-\var{Gs} is a list of \tm{N} dense or sparse real matrices  
-\tm{\s{G}{1}}, \ldots, \tm{\s{G}{M}}.
-The columns of these matrices can be interpreted as 
-symmetric matrices stored in column major order, using the BLAS 'L'-type
-storage (\ie, only the entries corresponding to lower triangular positions
-are accessed). 
-\var{hs} is a list of \tm{N} dense symmetric matrices \tm{\s{h}{1}},
-\ldots, \tm{\s{h}{N}}.
-Only the lower triangular elements of these matrices are accessed.
-The default values for \code{Gs} and \code{hs} are empty lists.
-
-\var{A} is a dense or sparse matrix and \var{b} is a single-column dense 
-matrix.  The default values for \var{A} and \var{b} are matrices with 
-zero rows. 
-
-The \var{solver} argument is used to choose between two
-solvers: the CVXOPT \function{conelp()} solver 
-(used when \var{solver} is absent or
-equal to \None) and the external solver DSDP5 
-(\code{\var{solver}='dsdp'}); see section~\ref{s-external}.
-With the \code{'dsdp'} option the code does not accept problems with 
-equality constraints.
-
-The optional argument \var{primalstart} is a dictionary with keys 
-\code{'x'}, \code{'sl'}, and \code{'ss'}, used as an optional primal 
-starting point. 
-\code{primalstart['x']} and \code{primalstart['sl']} are single-column
-dense matrices with the initial values of \tm{x} and \tm{\s{s}{0}}; 
-\code{primalstart['ss']} is a list of square matrices with the
-initial values of \tm{\s{s}{1}}, \ldots, \tm{\s{s}{N}}.
-The initial values must satisfy the inequalities in the primal problem 
-strictly, but not necessarily the equality constraints.
-
-\var{dualstart} is a dictionary with keys \code{'y'}, \code{'zl'}, 
-\code{'zs'}, used as an optional dual starting point.
-\code{dualstart['y']} and \code{dualstart['zl']} are single-column dense 
-matrices with the initial values of \tm{y} and \tm{\s{z}{0}}.
-\code{dualstart['zs']} is a list of square matrices with the 
-initial values of \tm{\s{z}{1}}, \ldots, \tm{\s{z}{N}}.  These values must
-satisfy the dual inequalities strictly, but not necessarily the equality
-constraint.
-
-The arguments \var{primalstart} and \var{dualstart} are ignored when 
-the DSDP solver is used.
-
-\function{sdp()} returns a dictionary that includes entries with keys 
-\code{'status'}, \code{'x'}, \code{'sl'}, \code{'ss'}, \code{'y'}, 
-\code{'zl'},  \code{'ss'}.
-The \code{'sl'} and \code{'zl'} fields are matrices with the primal 
-slacks and dual variables associated with the componentwise linear 
-inequalities.
-The \code{'ss'} and \code{'zs'} fields are lists with the primal slacks 
-and dual variables associated with the second-order cone inequalities.
-The other entries in the output dictionary have the same meaning as in the
-output of \function{conelp()}.
-\end{funcdesc}
-
-We illustrate the calling sequence with a small example.
-\[
-\begin{array}{ll}
-\mbox{minimize} & x_1 - x_2 + x_3 \\
-\mbox{subject to} & 
-  x_1 \left[ \begin{array}{cc} -7 &  -11 \\ -11 &  3
- \end{array}\right] + 
-  x_2 \left[ \begin{array}{cc}
-  7 & -18 \\ -18 & 8 \end{array}\right] + 
-  x_3 \left[ \begin{array}{cc}
-  -2 & -8 \\ -8 & 1 
- \end{array}\right] \preceq  
- \left[ \begin{array}{cc} 
- 33 & -9 \\ -9 & 26 \end{array}\right] \\*[1ex]
-& x_1 \left[ \begin{array}{ccc} 
- -21 & -11 & 0  \\ -11 & 10 & 8 \\ 0 & 8 & 5
- \end{array}\right] + 
- x_2 \left[ \begin{array}{ccc} 
- 0 & 10  & 16 \\
-10 & -10 & -10 \\
-16 & -10 & 3 
- \end{array}\right] + 
- x_3 \left[ \begin{array}{ccc} 
- -5  & 2 & -17 \\
- 2  & -6 & -7 \\
- -17 & 8 & 6 
- \end{array}\right]  
-\preceq  \left[ \begin{array}{ccc}
- 14 &  9 & 40 \\
-  9  & 91 & 10 \\
- 40 & 10 & 15
-\end{array} \right]
-\end{array}
-\]
-\begin{verbatim}
->>> from cvxopt import matrix, solvers
->>> c = matrix([1.,-1.,1.])
->>> G = [ matrix([[-7., -11., -11., 3.], 
-                  [ 7., -18., -18., 8.], 
-                  [-2.,  -8.,  -8., 1.]]) ]
->>> G += [ matrix([[-21., -11.,   0., -11.,  10.,   8.,   0.,   8., 5.], 
-                   [  0.,  10.,  16.,  10., -10., -10.,  16., -10., 3.], 
-                   [ -5.,   2., -17.,   2.,  -6.,   8., -17.,  -7., 6.]]) ]
->>> h = [ matrix([[33., -9.], [-9., 26.]]) ]
->>> h += [ matrix([[14., 9., 40.], [9., 91., 10.], [40., 10., 15.]]) ]
->>> sol = solvers.sdp(c, Gs=G, hs=h)  
->>> print sol['x']
-[-3.68e-01]
-[ 1.90e+00]
-[-8.88e-01]
->>> print sol['zs'][0]
-[ 3.96e-03 -4.34e-03]
-[-4.34e-03  4.75e-03]
->>> print sol['zs'][1]
-[ 5.58e-02 -2.41e-03  2.42e-02]
-[-2.41e-03  1.04e-04 -1.05e-03]
-[ 2.42e-02 -1.05e-03  1.05e-02]
-\end{verbatim}
-Only the entries in \var{Gs} and \var{hs} that correspond to lower 
-triangular entries need to be provided, so in the example \var{h} and 
-\var{G} may also be defined as follows.
-\begin{verbatim}
->>> G = [ matrix([[-7., -11., 0., 3.], 
-                  [ 7., -18., 0., 8.], 
-                  [-2.,  -8., 0., 1.]]) ]
->>> G += [ matrix([[-21., -11.,   0., 0.,  10.,   8., 0., 0., 5.], 
-                   [  0.,  10.,  16., 0., -10., -10., 0., 0., 3.], 
-                   [ -5.,   2., -17., 0.,  -6.,   8., 0., 0., 6.]]) ]
->>> h = [ matrix([[33., -9.], [0., 26.]]) ]
->>> h += [ matrix([[14., 9., 40.], [0., 91., 10.], [0., 0., 15.]]) ]
-\end{verbatim}
-
-
-\section{Exploiting Structure} \label{s-conelp-struct}
-By default, the functions \function{conelp()} and \function{coneqp()} 
-exploit no problem 
-structure except (to some limited extent) sparsity.  
-Two mechanisms are provided for implementing customized solvers that 
-take advantage of problem structure.
-
-\begin{description}
-\item[\emph{Providing a function for solving KKT equations.}]
-The most expensive step of each iteration of 
-\function{conelp()} or \function{coneqp()} is the
-solution of a set of linear equations (`KKT equations') of the form
-\BEQ \label{e-conelp-kkt}
- \left[\begin{array}{ccc}
-  P & A^T & G^T \\
-  A & 0   & 0  \\
-  G & 0   & -W^T W \end{array}\right]
- \left[\begin{array}{c} u_x \\ u_y \\ u_z \end{array}\right]
- = \left[\begin{array}{c} b_x \\ b_y \\ b_z \end{array}\right]
-\EEQ
-(with \tm{P=0} in \function{conelp()}).
-The matrix \tm{W} depends on the current iterates and is defined as 
-follows.  We use the notation of sections~\ref{s-conelp} 
-and~\ref{s-coneqp}.  Let 
-\[
- u = \left(u_\mathrm{l}, \; u_{\mathrm{q},0}, \; \ldots, \; 
- u_{\mathrm{q},M-1}, \; \svec{(u_{\mathrm{s},0})}, \; \ldots, \; 
-  \svec{(u_{\mathrm{s},N-1})}\right), \qquad
- u_\mathrm{l} \in\reals^l, \qquad 
- u_{\mathrm{q},k} \in\reals^{r_k}, \quad k = 0,\ldots,M-1, \qquad 
- u_{\mathrm{s},k} \in\symm^{t_k},  \quad k = 0,\ldots,N-1.
-\]
-Then \tm{W} is a block-diagonal matrix, 
-\[
- Wu = \left( W_\mathrm{l} u_\mathrm{l}, \;
- W_{\mathrm{q},0} u_{\mathrm{q},0}, \; \ldots, \;
- W_{\mathrm{q},M-1} u_{\mathrm{q},M-1},\; 
- W_{\mathrm{s},0} \svec{(u_{\mathrm{s},0})}, \; \ldots, \;
- W_{\mathrm{s},N-1} \svec{(u_{\mathrm{s},N-1})} \right)
-\]
-with the following diagonal blocks.
-\BIT
-\item The first block is a \emph{positive diagonal scaling} with a 
- vector \tm{d}:
-\[
-  W_\mathrm{l} = \diag(d), \qquad W_\mathrm{l}^{-1} = \diag(d)^{-1}.
-\]
-This transformation is symmetric:
-\[
-  W_\mathrm{l}^T = W_\mathrm{l}. 
-\]
-
-\item The next \tm{M} blocks are positive multiples of \emph{hyperbolic 
- Householder transformations}:
-\[
-  W_{\mathrm{q},k} = \beta_k ( 2 v_k v_k^T - J),
- \qquad
-  W_{\mathrm{q},k}^{-1} = \frac{1}{\beta_k} ( 2 Jv_k v_k^T J - J),
- \qquad k = 0,\ldots,M-1,
-\]
-where
-\[
- \beta_k > 0, \qquad v_{k0} > 0, \qquad 
- v_k^T Jv_k = 1, \qquad J = \left[\begin{array}{cc}
-   1 & 0 \\ 0 & -I \end{array}\right].
-\]
-These transformations are also symmetric:
-\[
-  W_{\mathrm{q},k}^T = W_{\mathrm{q},k}. 
-\]
-
-\item The last \tm{N} blocks are \emph{congruence transformations} with 
- nonsingular matrices:
-\[
-  W_{\mathrm{s},k} \svec{(u_{\mathrm{s},k})} = 
-  \svec{(r_k^T u_{\mathrm{s},k} r_k)}, \qquad
-  W_{\mathrm{s},k}^{-1} \svec{(u_{\mathrm{s},k})} = 
- \svec{(r_k^{-T} u_{\mathrm{s},k} r_k^{-1})}, \qquad
- k = 0,\ldots,N-1.
-\]
-In  general, this operation is not symmetric: 
-\[
-  W_{\mathrm{s},k}^T \svec{(u_{\mathrm{s},k})} = 
-  \svec{(r_k u_{\mathrm{s},k} r_k^T)}, \qquad
- \qquad
-  W_{\mathrm{s},k}^{-T} \svec{(u_{\mathrm{s},k})} = 
- \svec{(r_k^{-1} u_{\mathrm{s},k} r_k^{-T})}, \qquad
- \qquad
- k = 0,\ldots,N-1.
-\]
-\EIT
-It is often possible to exploit problem structure to 
-solve~(\ref{e-conelp-kkt}) faster than by 
-standard methods.  The last argument \var{kktsolver} of 
-\function{conelp()} and \function{coneqp()} allows the user to 
-supply a Python  function for 
-solving the KKT equations.
-This function will be called as \samp{f = kktsolver(W)}, where 
-\var{W} is a dictionary that contains the parameters of the scaling:
-
-\BIT
-\item \code{W['d']} is the positive vector that defines the diagonal
- scaling.   \code{W['di']} is its componentwise inverse.
-\item \code{W['beta']} and \code{W['v']} are lists of length \tm{M} with 
- the coefficients and vectors that define the hyperbolic Householder 
- transformations.
-\item \code{W['r']} is a list of length \tm{N} with the matrices that
- define the the congruence transformations.  
- \code{W['rti']} is  a list of length \tm{N} with the transposes of the 
- inverses of the matrices in \code{W['r']}.
-\EIT
-
-The function call \samp{f = kktsolver(W)} should return a routine
-for solving the KKT system~(\ref{e-conelp-kkt}) defined by \var{W}.
-It will be called as \samp{f(bx, by, bz)}.
-On entry, \var{bx}, \var{by}, \var{bz} contain the righthand side.  
-On exit, they should contain the solution of the KKT system, with 
-the last component scaled, \ie, on exit,
-\[
-  b_x := u_x, \qquad b_y := u_y, \qquad b_z := W u_z.
-\]
-In other words, the function returns the solution of
-\[
- \left[\begin{array}{ccc}
-  P & A^T & G^TW^{-1} \\
-  A & 0   & 0  \\
-  G & 0   & -W^T \end{array}\right]
- \left[\begin{array}{c} \hat u_x \\ \hat u_y \\ \hat u_z \end{array}\right]
- = \left[\begin{array}{c} b_x \\ b_y \\ b_z \end{array}\right].
-\]
-
-\item[\emph{Specifying constraints via Python functions}.]
-In the default use of \function{conelp()} and \function{coneqp()}, the 
-linear constraints and the quadratic term in the objective are 
-parameterized by CVXOPT matrices \var{G}, \var{A}, \var{P}.  It is 
-possible to specify these parameters via Python functions that evaluate 
-the corresponding matrix-vector products and their adjoints.
-
-If the argument \var{G} of \function{conelp()} or \function{coneqp()} 
-is a Python function, it should be defined as follows:
-\begin{funcdesc}{\var{G}}{\var{x}, \var{y} \optional{, 
-\var{alpha}\optional{, \var{beta}\optional{, \var{trans}}}}} 
-This evaluates the matrix-vector products
-\[
-y := \alpha Gx + \beta y \quad 
-  (\mathrm{trans} = \mathrm{'N'}), \qquad
-y := \alpha G^T x + \beta y \quad 
- (\mathrm{trans} = \mathrm{'T'}).
-\]
-The default values of the optional arguments must be
-\code{alpha = 1.0}, \code{beta = 0.0}, \code{trans = 'N'}.
-\end{funcdesc}
-
-Similarly, if the argument \var{A} is a Python function, then it must
-be defined as follows.
-\begin{funcdesc}{\var{A}}{\var{x}, \var{y} \optional{, 
-\var{alpha}\optional{, \var{beta}\optional{, \var{trans}}}}} 
-This evaluates the matrix-vector products
-\[
-y := \alpha Ax + \beta y \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
-y := \alpha A^T x + \beta y \quad (\mathrm{trans} = \mathrm{'T'}).
-\]
-The default values of the optional arguments must be
-\code{alpha = 1.0}, \code{beta = 0.0}, \code{trans = 'N'}.
-\end{funcdesc}
-
-If the argument \var{P} of \function{coneqp()} is a Python function,
-then it must be defined as follows:
-\begin{funcdesc}{\var{P}}{\var{x}, \var{y} \optional{, 
-\var{alpha}\optional{, \var{beta}}}} 
-This evaluates the matrix-vector products
-\[
-y := \alpha Px + \beta y.
-\]
-The default values of the optional arguments must be
-\code{alpha = 1.0}, \code{beta = 0.0}. 
-\end{funcdesc}
-
-If \var{G}, \var{A} or \var{P} are Python functions, then the argument 
-\var{kktsolver} must also be provided.
-\end{description}
-
-We illustrate these features with three applications.
-
-\begin{description}
-\item[Example: 1-norm approximation]
-
-The optimization problem
-\[
- \begin{array}{ll}
- \mbox{minimize} & \|Pu-q\|_1
- \end{array}
-\]
-can be formulated as a linear program
-\[
- \begin{array}{ll}
- \mbox{minimize} & \ones^T v \\
- \mbox{subject to} & -v \preceq Pu - q  \preceq v.
- \end{array}
-\]
-By exploiting the structure in the inequalities, the cost of 
-an iteration of an interior-point method can be reduced
-to the cost of least-squares problem of the same dimensions. 
-(See section 11.8.2 in the book 
-\citetitle{http://www.stanford.edu/\%7Eboyd/cvxbook}{Convex 
-Optimization}.)
-The code belows takes advantage of this fact.
-
-\begin{verbatim}
-from cvxopt import blas, lapack, solvers, matrix, spmatrix, mul, div
-
-def l1(P, q):
-    """
-
-    Returns the solution u, w of the l1 approximation problem
-
-        (primal) minimize    ||P*u - q||_1       
-    
-        (dual)   maximize    q'*w
-                 subject to  P'*w = 0
-                             ||w||_infty <= 1.
-    """
-
-    m, n = P.size
-
-    # Solve the equivalent LP 
-    #
-    #     minimize    [0; 1]' * [u; v]
-    #     subject to  [P, -I; -P, -I] * [u; v] <= [q; -q]
-    #
-    #     maximize    -[q; -q]' * z 
-    #     subject to  [P', -P']*z  = 0
-    #                 [-I, -I]*z + 1 = 0 
-    #                 z >= 0.
-    
-    c = matrix(n*[0.0] + m*[1.0])
-
-    def G(x, y, alpha = 1.0, beta = 0.0, trans = 'N'):    
-
-        if trans=='N':
-            # y := alpha * [P, -I; -P, -I] * x + beta*y
-            u = P*x[:n]
-            y[:m] = alpha * ( u - x[n:]) + beta * y[:m]
-            y[m:] = alpha * (-u - x[n:]) + beta * y[m:]
-
-        else:
-            # y := alpha * [P', -P'; -I, -I] * x + beta*y
-            y[:n] =  alpha * P.T * (x[:m] - x[m:]) + beta * y[:n]
-            y[n:] = -alpha * (x[:m] + x[m:]) + beta * y[n:]
-
-    h = matrix([q, -q])
-    dims = {'l': 2*m, 'q': [], 's': []}
-
-    def F(W): 
-
-        """
-        Returns a function f(x, y, z) that solves
-       
-            [ 0  0  P'      -P'      ] [ x[:n] ]   [ bx[:n] ]
-            [ 0  0 -I       -I       ] [ x[n:] ]   [ bx[n:] ]
-            [ P -I -D1^{-1}  0       ] [ z[:m] ] = [ bz[:m] ]
-            [-P -I  0       -D2^{-1} ] [ z[m:] ]   [ bz[m:] ]
-        
-        where D1 = diag(di[:m])^2, D2 = diag(di[m:])^2 and di = W['di'].
-        """
-        
-        # Factor A = 4*P'*D*P where D = d1.*d2 ./(d1+d2) and d1 = di[:m].^2, d2 = di[m:].^2.
-
-        di = W['di']
-        d1, d2 = di[:m]**2, di[m:]**2
-        D = div( mul(d1,d2), d1+d2 )  
-        A = P.T * spmatrix(4*D, range(m), range(m)) * P
-        lapack.potrf(A)
-
-        def f(x, y, z):
-
-            """
-            On entry bx, bz are stored in x, z.  On exit x, z contain the solution, 
-            with z scaled: z./di is returned instead of z. 
-            """"
-
-            # Solve for x[:n]:
-            #
-            #    A*x[:n] = bx[:n] + P' * ( ((D1-D2)*(D1+D2)^{-1})*bx[n:]
-            #              + (2*D1*D2*(D1+D2)^{-1}) * (bz[:m] - bz[m:]) ).
-
-            x[:n] += P.T * ( mul(div(d1-d2, d1+d2), x[n:]) + mul(2*D, z[:m]-z[m:]) )
-            lapack.potrs(A, x)
-
-            # x[n:] := (D1+D2)^{-1} * (bx[n:] - D1*bz[:m] - D2*bz[m:] + (D1-D2)*P*x[:n])
-
-            u = P*x[:n]
-            x[n:] =  div(x[n:] - mul(d1, z[:m]) - mul(d2, z[m:]) + mul(d1-d2, u), d1+d2)
-
-            # z[:m] := d1[:m] .* ( P*x[:n] - x[n:] - bz[:m])
-            # z[m:] := d2[m:] .* (-P*x[:n] - x[n:] - bz[m:]) 
-
-            z[:m] = mul(d[:m],  u - x[n:] - z[:m])
-            z[m:] = mul(d[m:], -u - x[n:] - z[m:])
-
-        return f
-
-    sol = solvers.conelp(c, G, h, dims, kktsolver = F) 
-    return sol['x'][:n],  sol['z'][m:] - sol['z'][:m]    
-\end{verbatim}
-
-\item[Example: SDP with diagonal linear term]
-
-The SDP
-\[
- \begin{array}{ll}
- \mbox{minimize} & \ones^T x \\
- \mbox{subject to} & W + \diag(x) \succeq 0 
- \end{array} 
-\]
-can be solved efficiently by exploiting properties of the diag operator.
-
-\begin{verbatim}
-from cvxopt import blas, lapack, solvers, matrix
-
-def mcsdp(w):
-    """
-    Returns solution x, z to 
-
-        (primal)  minimize    sum(x)
-                  subject to  w + diag(x) >= 0
-
-        (dual)    maximize    -tr(w*z)
-                  subject to  diag(z) = 1
-                              z >= 0.
-    """
-
-    n = w.size[0]
-    c = matrix(1.0, (n,1))
-
-    def G(x, y, alpha = 1.0, beta = 0.0, trans = 'N'):
-        """
-            y := alpha*(-diag(x)) + beta*y.   
-        """
-
-        if trans=='N':
-            # x is a vector; y is a symmetric matrix in column major order.
-            y *= beta
-            y[::n+1] -= alpha * x
-
-        else:   
-            # x is a symmetric matrix in column major order; y is a vector.
-            y *= beta
-            y -= alpha * x[::n+1] 
-	 
-
-    def cngrnc(r, x, alpha = 1.0):
-        """
-        Congruence transformation
-
-            x := alpha * r'*x*r.
-
-        r and x are square matrices.
-        """
-
-        # Scale diagonal of x by 1/2.  
-        x[::n+1] *= 0.5
-    
-        # a := tril(x)*r 
-        a = +r
-        tx = matrix(x, (n,n))
-        blas.trmm(tx, a, side = 'L')
-
-        # x := alpha*(a*r' + r*a') 
-        blas.syr2k(r, a, tx, trans = 'T', alpha = alpha)
-        x[:] = tx[:]
-
-    dims = {'l': 0, 'q': [], 's': [n]}
-
-    def F(W):
-        """
-        Returns a function f(x, y, z) that solves 
-
-                      -diag(z)     = bx
-            -diag(x) - r*r'*z*r*r' = bz
-
-        where r = W['r'][0] = W['rti'][0]^{-T}.
-        """
-   
-        rti = W['rti'][0]
-
-        # t = rti*rti' as a nonsymmetric matrix.
-        t = matrix(0.0, (n,n))
-        blas.gemm(rti, rti, t, transB = 'T') 
-
-        # Cholesky factorization of tsq = t.*t.
-        tsq = t**2
-        lapack.potrf(tsq)
-
-        def f(x, y, z):
-            """
-            On entry, x contains bx, y is empty, and z contains bz stored 
-            in column major order.
-            On exit, they contain the solution, with z scaled 
-            (vec(r'*z*r) is returned instead of z).
-
-            We first solve 
-            
-               ((rti*rti') .* (rti*rti')) * x = bx - diag(t*bz*t)
-           
-            and take z = - rti' * (diag(x) + bz) * rti.
-            """
-
-            # tbst := t * bz * t
-            tbst = +z
-            cngrnc(t, tbst) 
-
-            # x := x - diag(tbst) = bx - diag(rti*rti' * bz * rti*rti')
-            x -= tbst[::n+1]
-
-            # x := (t.*t)^{-1} * x = (t.*t)^{-1} * (bx - diag(t*bz*t))
-            lapack.potrs(tsq, x)
-
-            # z := z + diag(x) = bz + diag(x)
-            z[::n+1] += x 
-
-            # z := -vec(rti' * z * rti) 
-            #    = -vec(rti' * (diag(x) + bz) * rti 
-            cngrnc(rti, z, alpha = -1.0)
-
-        return f
-
-    sol = solvers.conelp(c, G, w[:], dims, kktsolver = F) 
-    return sol['x'], sol['z']
-
-\end{verbatim}
-
-\item[Example: Minimizing 1-norm subject to a 2-norm constraint]
-In the second example, we use a similar trick to solve the problem
-\[
- \begin{array}{ll}
- \mbox{minimize} & \|u\|_1 \\
- \mbox{subject to} & \|Au - b\|_2 \leq 1.
- \end{array}
-\]
-The code below is efficient, if we assume that the number of 
-rows in \tm{A} is greater than or equal to the number of columns.
-
-\begin{verbatim}
-def qcl1(A, b):
-    """
-    Returns the solution u, z of
-
-        (primal)  minimize    || u ||_1       
-                  subject to  || A * u - b ||_2  <= 1
-
-        (dual)    maximize    b^T z - ||z||_2
-                  subject to  || A'*z ||_inf <= 1.
-
-    Exploits structure, assuming A is m by n with m >= n. 
-    """
-
-    m, n = A.size
-
-    # Solve equivalent cone LP with variables x = [u; v].
-    #
-    #     minimize    [0; 1]' * x 
-    #     subject to  [ I  -I ] * x <=  [  0 ]   (componentwise)
-    #                 [-I  -I ] * x <=  [  0 ]   (componentwise)
-    #                 [ 0   0 ] * x <=  [  1 ]   (SOC)
-    #                 [-A   0 ]         [ -b ]
-    #
-    #     maximize    -t + b' * w
-    #     subject to  z1 - z2 = A'*w
-    #                 z1 + z2 = 1
-    #                 z1 >= 0,  z2 >=0,  ||w||_2 <= t.
-     
-    c = matrix(n*[0.0] + n*[1.0])
-    h = matrix( 0.0, (2*n + m + 1, 1))
-    h[2*n] = 1.0
-    h[2*n+1:] = -b
-
-    def G(x, y, alpha = 1.0, beta = 0.0, trans = 'N'):    
-        y *= beta
-        if trans=='N':
-            # y += alpha * G * x 
-            y[:n] += alpha * (x[:n] - x[n:2*n]) 
-            y[n:2*n] += alpha * (-x[:n] - x[n:2*n]) 
-            y[2*n+1:] -= alpha * A*x[:n] 
-
-        else:
-            # y += alpha * G'*x 
-            y[:n] += alpha * (x[:n] - x[n:2*n] - A.T * x[-m:])  
-            y[n:] -= alpha * (x[:n] + x[n:2*n]) 
-
-
-    def Fkkt(W): 
-        """
-        Returns a function f(x, y, z) that solves
-        
-            [ 0   G'   ] [ x ] = [ bx ]
-            [ G  -W'*W ] [ z ]   [ bz ].
-        """
-
-        # First factor 
-        #
-        #     S = G' * W**-1 * W**-T * G
-        #       = [0; -A]' * W3^-2 * [0; -A] + 4 * (W1**2 + W2**2)**-1 
-        #
-        # where
-        #
-        #     W1 = diag(d1) with d1 = W['d'][:n] = 1 ./ W['di'][:n]  
-        #     W2 = diag(d2) with d2 = W['d'][n:] = 1 ./ W['di'][n:]  
-        #     W3 = beta * (2*v*v' - J),  W3^-1 = 1/beta * (2*J*v*v'*J - J)  
-        #        with beta = W['beta'][0], v = W['v'][0], J = [1, 0; 0, -I].
-  
-        # As = W3^-1 * [ 0 ; -A ] = 1/beta * ( 2*J*v * v' - I ) * [0; A]
-        beta, v = W['beta'][0], W['v'][0]
-        As = 2 * v * (v[1:].T * A)
-        As[1:,:] *= -1.0
-        As[1:,:] -= A
-        As /= beta
-      
-        # S = As'*As + 4 * (W1**2 + W2**2)**-1
-        S = As.T * As 
-        d1, d2 = W['d'][:n], W['d'][n:]       
-        d = 4.0 * (d1**2 + d2**2)**-1
-        S[::n+1] += d
-        lapack.potrf(S)
-
-        def f(x, y, z):
-
-            # z := - W**-T * z 
-            z[:n] = -div( z[:n], d1 )
-            z[n:2*n] = -div( z[n:2*n], d2 )
-            z[2*n:] -= 2.0*v*( v[0]*z[2*n] - blas.dot(v[1:], z[2*n+1:]) ) 
-            z[2*n+1:] *= -1.0
-            z[2*n:] /= beta
-
-            # x := x - G' * W**-1 * z
-            x[:n] -= div(z[:n], d1) - div(z[n:2*n], d2) + As.T * z[-(m+1):]
-            x[n:] += div(z[:n], d1) + div(z[n:2*n], d2) 
-
-            # Solve for x[:n]:
-            #
-            #    S*x[:n] = x[:n] - (W1**2 - W2**2)(W1**2 + W2**2)^-1 * x[n:]
-            
-            x[:n] -= mul( div(d1**2 - d2**2, d1**2 + d2**2), x[n:]) 
-            lapack.potrs(S, x)
-            
-            # Solve for x[n:]:
-            #
-            #    (d1**-2 + d2**-2) * x[n:] = x[n:] + (d1**-2 - d2**-2)*x[:n]
-             
-            x[n:] += mul( d1**-2 - d2**-2, x[:n])
-            x[n:] = div( x[n:], d1**-2 + d2**-2)
-
-            # z := z + W^-T * G*x 
-            z[:n] += div( x[:n] - x[n:2*n], d1) 
-            z[n:2*n] += div( -x[:n] - x[n:2*n], d2) 
-            z[2*n:] += As*x[:n]
-
-        return f
-
-    dims = {'l': 2*n, 'q': [m+1], 's': []}
-    sol = solvers.conelp(c, G, h, dims, kktsolver = Fkkt)
-    if sol['status'] == 'optimal':
-        return sol['x'][:n],  sol['z'][-m:]
-    else:
-        return None, None
-\end{verbatim}
-
-\item[Example: 1-norm regularized least-squares] 
-As an example that illustrates how structure can be exploited
-in \function{coneqp()}, we consider the 1-norm regularized 
-least-squares problem
-\[
-\begin{array}{ll}
-\mbox{minimize} & \|Ax - y\|_2^2 + \|x\|_1
-\end{array}
-\]
-with variable \tm{x}.  The problem is equivalent to the quadratic 
-program
-\[
- \begin{array}{ll}
- \mbox{minimize} & \|Ax - y\|_2^2 + \ones^T u \\
- \mbox{subject to} & -u \preceq x \preceq u
- \end{array}
-\]
-with variables \tm{x} and \tm{u}.  The implementation below is 
-efficient when \tm{A} has many more columns than rows. 
-
-\begin{verbatim}
-from cvxopt import matrix, spdiag, mul, div, blas, lapack, solvers, sqrt
-import math
-
-def l1regls(A, y):
-    """
-    
-    Returns the solution of l1-norm regularized least-squares problem
-  
-        minimize || A*x - y ||_2^2  + || x ||_1.
-
-    """
-
-    m, n = A.size
-    q = matrix(1.0, (2*n,1))
-    q[:n] = -2.0 * A.T * y
-
-    def P(u, v, alpha = 1.0, beta = 0.0 ):
-        """
-            v := alpha * 2.0 * [ A'*A, 0; 0, 0 ] * u + beta * v 
-        """
-        v *= beta
-        v[:n] += alpha * 2.0 * A.T * (A * u[:n])
-
-
-    def G(u, v, alpha=1.0, beta=0.0, trans='N'):
-        """
-            v := alpha*[I, -I; -I, -I] * u + beta * v  (trans = 'N' or 'T')
-        """
-
-        v *= beta
-        v[:n] += alpha*(u[:n] - u[n:])
-        v[n:] += alpha*(-u[:n] - u[n:])
-
-    h = matrix(0.0, (2*n,1))
-
-
-    # Customized solver for the KKT system 
-    #
-    #     [  2.0*A'*A  0    I      -I     ] [x[:n] ]     [bx[:n] ]
-    #     [  0         0   -I      -I     ] [x[n:] ]  =  [bx[n:] ].
-    #     [  I        -I   -D1^-1   0     ] [zl[:n]]     [bzl[:n]]
-    #     [ -I        -I    0      -D2^-1 ] [zl[n:]]     [bzl[n:]]
-    #
-    # where D1 = W['di'][:n]**2, D2 = W['di'][:n]**2.
-    #    
-    # We first eliminate zl and x[n:]:
-    #
-    #     ( 2*A'*A + 4*D1*D2*(D1+D2)^-1 ) * x[:n] = 
-    #         bx[:n] - (D2-D1)*(D1+D2)^-1 * bx[n:] + 
-    #         D1 * ( I + (D2-D1)*(D1+D2)^-1 ) * bzl[:n] - 
-    #         D2 * ( I - (D2-D1)*(D1+D2)^-1 ) * bzl[n:]           
-    #
-    #     x[n:] = (D1+D2)^-1 * ( bx[n:] - D1*bzl[:n]  - D2*bzl[n:] ) 
-    #         - (D2-D1)*(D1+D2)^-1 * x[:n]         
-    #
-    #     zl[:n] = D1 * ( x[:n] - x[n:] - bzl[:n] )
-    #     zl[n:] = D2 * (-x[:n] - x[n:] - bzl[n:] ).
-    #
-    # The first equation has the form
-    #
-    #     (A'*A + D)*x[:n]  =  rhs
-    #
-    # and is equivalent to
-    #
-    #     [ D    A' ] [ x:n] ]  = [ rhs ]
-    #     [ A   -I  ] [ v    ]    [ 0   ].
-    #
-    # It can be solved as 
-    #
-    #     ( A*D^-1*A' + I ) * v = A * D^-1 * rhs
-    #     x[:n] = D^-1 * ( rhs - A'*v ).
-
-    S = matrix(0.0, (m,m))
-    Asc = matrix(0.0, (m,n))
-    v = matrix(0.0, (m,1))
-
-    def Fkkt(W):
-
-        # Factor 
-        #
-        #     S = A*D^-1*A' + I 
-        #
-        # where D = 2*D1*D2*(D1+D2)^-1, D1 = d[:n]**-2, D2 = d[n:]**-2.
-
-        d1, d2 = W['di'][:n]**2, W['di'][n:]**2
-
-        # ds is square root of diagonal of D
-        ds = math.sqrt(2.0) * div( mul( W['di'][:n], W['di'][n:]), sqrt(d1+d2) )
-        d3 =  div(d2 - d1, d1 + d2)
-     
-        # Asc = A*diag(d)^-1/2
-        Asc = A * spdiag(ds**-1)
-
-        # S = I + A * D^-1 * A'
-        blas.syrk(Asc, S)
-        S[::m+1] += 1.0 
-        lapack.potrf(S)
-
-        def g(x, y, z):
-
-            x[:n] = 0.5 * ( x[:n] - mul(d3, x[n:]) + 
-                mul(d1, z[:n] + mul(d3, z[:n])) - mul(d2, z[n:] - 
-                mul(d3, z[n:])) )
-            x[:n] = div( x[:n], ds) 
-
-            # Solve
-            #
-            #     S * v = 0.5 * A * D^-1 * ( bx[:n] - 
-            #         (D2-D1)*(D1+D2)^-1 * bx[n:] + 
-            #         D1 * ( I + (D2-D1)*(D1+D2)^-1 ) * bzl[:n] - 
-            #         D2 * ( I - (D2-D1)*(D1+D2)^-1 ) * bzl[n:] )
-                
-            blas.gemv(Asc, x, v)
-            lapack.potrs(S, v)
-            
-            # x[:n] = D^-1 * ( rhs - A'*v ).
-            blas.gemv(Asc, v, x, alpha=-1.0, beta=1.0, trans='T')
-            x[:n] = div(x[:n], ds)
-
-            # x[n:] = (D1+D2)^-1 * ( bx[n:] - D1*bzl[:n]  - D2*bzl[n:] ) 
-            #         - (D2-D1)*(D1+D2)^-1 * x[:n]         
-            x[n:] = div( x[n:] - mul(d1, z[:n]) - mul(d2, z[n:]), d1+d2 )\
-                - mul( d3, x[:n] )
-                
-            # zl[:n] = D1^1/2 * (  x[:n] - x[n:] - bzl[:n] )
-            # zl[n:] = D2^1/2 * ( -x[:n] - x[n:] - bzl[n:] ).
-            z[:n] = mul( W['di'][:n],  x[:n] - x[n:] - z[:n] ) 
-            z[n:] = mul( W['di'][n:], -x[:n] - x[n:] - z[n:] ) 
-
-        return g
-
-    return solvers.coneqp(P, q, G, h, kktsolver = Fkkt)['x'][:n]
-\end{verbatim}
-\end{description}
-
-
-\section{Optional Solvers} \label{s-external}
-CVXOPT includes optional interfaces to several other optimization 
-libraries.
-
-\begin{description}
-\item[GLPK] \function{lp()} with the \code{solver='glpk'} option uses 
-the simplex algorithm in 
-\ulink{GLPK (GNU Linear Programming Kit)}{http://www.gnu.org/software/glpk/glpk.html}.   
-
-\item[MOSEK] \function{lp()} and \function{socp()} with the 
- \code{solver='mosek'} option use 
- \ulink{MOSEK}{http://www.mosek.com} version 5.  
-
-\item[DSDP] \function{sdp()} with the \code{solver='dsdp'} option uses 
-the \ulink{DSDP5.8}{http://www-unix.mcs.anl.gov/DSDP} solver.  
-\end{description}
-GLPK, MOSEK and DSDP are not included in the CVXOPT distribution and 
-need to be installed separately.  
-
-
-\section{Algorithm Parameters} \label{s-parameters}
-In this section we list some algorithm control parameters that can 
-be modified without editing the source code.  
-These control parameters are accessible via the dictionary 
-\member{solvers.options}.  By default the dictionary 
-is empty and the default values of the parameters are used.
-
-One can change the parameters in the default solvers by 
-adding entries with the following key values.  
-\begin{description}
-\item[\code{'show\_progress'}]  
-\True\  or \False; turns the output to the screen on or off 
-(default: \True).
-\item[\code{'maxiters'}] maximum number of iterations (default: 100).
-\item[\code{'abstol'}] absolute accuracy (default: \code{1e-7}).
-\item[\code{'reltol'}] relative accuracy (default: \code{1e-6}).
-\item[\code{'feastol'}] tolerance for feasibility conditions (default:
-\code{1e-7}).
-\item[\code{'refinement'}] number of iterative refinement steps when
- solving KKT equations (default: 0 if the problem has no second-order
- cone or matrix inequality constraints; 1 otherwise).
-\end{description}
-For example the command
-\begin{verbatim}
->>> from cvxopt import solvers
->>> solvers.options['show_progress'] = False
-\end{verbatim}
-turns off the screen output during calls to the solvers.
-
-The tolerances \var{abstol}, \var{reltol} and \var{feastol} have the
-following meaning.   \function{conelp()} terminates with 
-status \code{'optimal'} if
-\[
-s \succeq 0, \qquad z \succeq 0, \qquad 
-\qquad 
- \frac{\|Gx + s - h\|_2} {\max\{1,\|h\|_2\}} \leq \epsilon_\mathrm{feas}, 
-\qquad 
-\frac{\|Ax-b\|_2}{\max\{1,\|b\|_2\}} \leq \epsilon_\mathrm{feas}, 
-\qquad
-\frac{\|G^Tz +  A^Ty + c\|_2}{\max\{1,\|c\|_2\}} \leq 
- \epsilon_\mathrm{feas}, 
-\]
-and
-\[
- s^T z \leq \epsilon_\mathrm{abs} \qquad \mbox{or} \qquad
-\left( \min\left\{c^Tx,  h^T z + b^Ty \right\} < 0 \quad \mbox{and} \quad
- \frac{s^Tz} {-\min\{c^Tx, h^Tz + b^T y\}} \leq \epsilon_\mathrm{rel} 
-\right).
-\]
-It returns with status  \code{'primal infeasible'} if 
-\[
-z \succeq 0, \qquad
-\qquad \frac{\|G^Tz +A^Ty\|_2}{\max\{1, \|c\|_2\}} \leq 
- \epsilon_\mathrm{feas}, 
- \qquad h^Tz +b^Ty = -1.
-\]
-It returns with status \code{'dual infeasible'} if 
-\[
-s \succeq 0, \qquad
-\qquad
-\frac{\|Gx+s\|_2}{\max\{1, \|h\|_2\}} \leq \epsilon_\mathrm{feas}, \qquad
-\frac{\|Ax\|_2}{\max\{1, \|b\|_2\}} \leq \epsilon_\mathrm{feas},  \qquad
-c^Tx = -1.
-\]
-The functions \function{lp()}, \function{socp()} and \function{sdp()} call 
-\function{conelp()} and hence use the same stopping criteria.
-
-The function \function{coneqp()} terminates with 
-status \code{'optimal'} if
-\[
-s \succeq 0, \qquad z \succeq 0, \qquad 
-\qquad 
- \frac{\|Gx + s - h\|_2} {\max\{1,\|h\|_2\}} \leq \epsilon_\mathrm{feas}, 
-\qquad 
-\frac{\|Ax-b\|_2}{\max\{1,\|b\|_2\}} \leq \epsilon_\mathrm{feas}, 
-\qquad
-\frac{\|Px + G^Tz +  A^Ty + q\|_2}{\max\{1,\|q\|_2\}} \leq 
- \epsilon_\mathrm{feas}, 
-\]
-and
-\[
-s^T z \leq \epsilon_\mathrm{abs}
-\qquad \mbox{or} \qquad \left( \frac{1}{2}x^TPx + q^Tx < 0, \quad 
-\mbox{and}\quad \frac{s^Tz} {-(1/2)x^TPx - q^Tx} \leq 
-\epsilon_\mathrm{rel} \right)
-\qquad \mbox{or} \qquad
-\left( L(x,y,z) > 0 \quad \mbox{and} \quad \frac{s^Tz}
-{L(x,y,z)} \leq \epsilon_\mathrm{rel} \right)
-\]
-where
-\[
-L(x,y,z) = \frac{1}{2}x^TPx + q^Tx  + z^T (Gx-h) + y^T(Ax-b).
-\]
-The function \function{qp()} calls \function{coneqp()} and hence uses 
-the same stopping criteria.
-
-The control parameters listed in the GLPK documentation are 
-set to their default values and can be customized by making 
-an entry in \member{solvers.options}.
-The keys in the dictionary are strings with the name of the GLPK 
-parameter.  For example, the command
-\begin{verbatim}
->>> from cvxopt import solvers 
->>> solvers.options['LPX_K_MSGLEV'] = 0
-\end{verbatim}
-turns off the screen output subsequent calls \function{lp()} with 
-the \code{'glpk'} option.
-
-The MOSEK interior-point algorithm parameters are set to their default 
-values.  They can be modified by adding an entry 
-\code{solvers.options['MOSEK']}.  This entry is a dictionary with 
-MOSEK parameter/value pairs, with the parameter names imported from
-\module{pymosek}.  For details see Section 14.1.3 of the 
-\ulink{MOSEK Python API Manual}{http://www.mosek.com/fileadmin/products/5_0/tools/doc/html/pyapi/index.html}.
-
-For example the commands
-\begin{verbatim}
->>> from cvxopt import solvers 
->>> import pymosek
->>> solvers.options['MOSEK'] = {pymosek.iparam.log: 0}
-\end{verbatim}
-turn off the screen output during calls of  \function{lp()} 
-or \function{socp()} with the \code{'mosek'} option.
-
-The following control parameters in \member{solvers.options} affect the 
-execution of the DSDP algorithm:
-\begin{description}
-\item[\code{'DSDP\_Monitor'}] the interval (in number of iterations)
- at which output is printed to the screen
-(default: 0).
-\item[\code{'DSDP\_MaxIts'}] maximum number of iterations.
-\item[\code{'DSDP\_GapTolerance'}] relative accuracy (default: 
-\code{1e-5}).
-\end{description}
diff --git a/doc/copyright.tex b/doc/copyright.tex
deleted file mode 100644
index 30b6933..0000000
--- a/doc/copyright.tex
+++ /dev/null
@@ -1,46 +0,0 @@
-\chapter*{Copyright and License}
-
-Copyright \copyright{2004-2008} J. Dahl \& L. Vandenberghe. 
-
-CVXOPT is free software; you can redistribute it and/or modify
-it under the terms of the 
-\ulink{GNU General Public License}{http://www.gnu.org/licenses/gpl-3.0.html}
-as published by the Free Software Foundation; either version 3 of the 
-License, or (at your option) any later version.
-
-CVXOPT 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
-\ulink{GNU General Public License}{http://www.gnu.org/licenses/gpl-3.0.html}
-for more details. \\
-
-\hrule 
-
-The CVXOPT distribution includes source code for part of the SuiteSparse 
-suite of sparse matrix algorithms, including:
-\BIT
-\item AMD Version 2.2.0.  
- Copyright (c) 2007 by Timothy A.\ Davis, Patrick R.\ Amestoy, and 
- Iain S.\ Duff.  
-\item CHOLMOD Version 1.7.0.  
- Copyright (c) 2005-2007 by University of Florida, Timothy A. Davis 
- and W. Hager.
-\item COLAMD Version 2.7.0.  Copyright (c) 1998-2007 by Timothy A.\ Davis.
-\item UMFPACK Version 5.2.0.  Copyright (c) 1995-2006 by Timothy A.\  Davis.
-\EIT
-
-These packages are licensed under the terms of the 
-\ulink{GNU General Public License, version 2 or higher}
-{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} 
-(UMFPACK, the Supernodal module of CHOLMOD) and the
-\ulink{GNU Lesser General Public License, version 2.1 or higher}
-{http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html} 
-(the other CHOLMOD modules, AMD, COLAMD).
-For copyright and license details, consult the README files in the source 
-directories or the website listed below.
-
-\begin{quote}
-Availability: \ulink{www.cise.ufl.edu/research/sparse}
-{http://www.cise.ufl.edu/research/sparse}.
-\end{quote}
diff --git a/doc/cvxopt.tex b/doc/cvxopt.tex
deleted file mode 100644
index d76a5d5..0000000
--- a/doc/cvxopt.tex
+++ /dev/null
@@ -1,104 +0,0 @@
-\documentclass{book}
-\usepackage{graphicx}
-
-\def\BIT{\begin{itemize}}
-\def\EIT{\end{itemize}}
-\def\BEQ{\begin{equation}}
-\def\EEQ{\end{equation}}
-\def\reals{{\mbox{\bf R}}}
-\def\complex{{\mbox{\bf C}}}
-\newcommand{\eg}{{\rm e.g.}}
-\newcommand{\ie}{{\rm i.e.}}
-\newcommand{\BEA}{\begin{eqnarray}}
-\newcommand{\EEA}{\end{eqnarray}}
-\newcommand{\BEAS}{\begin{eqnarray*}}
-\newcommand{\EEAS}{\end{eqnarray*}}
-\newcommand{\Rank}{\mathop{\bf rank}}
-\newcommand{\Tr}{\mathop{\mathbf{tr}}}
-\newcommand{\lse}{\mathop{\mathbf{lse}}}
-\newcommand{\diag}{\mbox{\bf diag}\,}
-\newcommand{\ones}{{\bf 1}}
-\newcommand{\argmax}{\mathop{\mathrm{argmax}}}
-\renewcommand{\Rank}{\mathop{\mathrm{rank}}}
-\newcommand{\symm}{{\mbox{\bf S}}}  
-\newcommand{\op}{\mathop{\mathrm{op}}}
-\newcommand{\svec}{\mathop{\mathbf{vec}}}
-\newcommand{\Range}{\mbox{\textrm{range}}}
-
-% In-line formulas are typeset differently in tex4ht and latex2html.
-\newcommand{\tm}[1]{$#1$}
-%\newcommand{\tm}[1]{\textit{#1}}
-\newcommand{\s}[2]{#1_#2}
-%\newcommand{\s}[2]{{#1}\_{#2}}
-
-% redefine Python markup
-\newcommand{\code}[1]{{\tt #1}}
-\newcommand{\pytype}[1]{{\tt #1}}
-\newcommand{\cdata}[1]{{\tt #1}}
-\newcommand{\var}[1]{{\tt #1}}
-\newcommand{\samp}[1]{"{\tt #1}"}
-\newcommand{\module}[1]{{\tt #1}}
-\newcommand{\class}[1]{{\tt #1}}
-\newcommand{\function}[1]{{\tt #1}}
-\newcommand{\member}[1]{{\tt #1}}
-\newcommand{\program}[1]{{\rm #1}}
-\newcommand{\optional}[1]{{\rm [}#1{\rm ]}}
-\newcommand{\file}[1]{{\tt #1}} 
-\newcommand{\ctype}[1]{{\tt #1}}
-\newcommand{\constant}[1]{{\tt #1}}
-\newenvironment{cfuncdesc}[3]{\par{\tt #1}%
-    {\bf #2}({\tt #3})\begin{list}{}{}\item[]}{\end{list}}
-\newenvironment{classdesc}[2]{\par{\bf #1}%
-    ({\tt #2})\begin{list}{}{}\item[]}{\end{list}}
-\newenvironment{funcdesc}[2]{\par{\bf #1}%
-    ({\tt #2})\begin{list}{}{}\item[]}{\end{list}}
-\newenvironment{memberdesc}[1]{\par{\bf #1}%
-    \begin{list}{}{}\item[]}{\end{list}}
-\newenvironment{methoddesc}[1]{\par{\bf #1}()%
-    \begin{list}{}{}\item[]}{\end{list}}
-\newcommand{\seetext}[1]{#1} 
-\newcommand{\htmladdnormallink}[2]{\Link[#2]{}{}{#1}\EndLink} 
-\newcommand{\ulink}[2]{\htmladdnormallink{#1}{#2}} 
-\newcommand{\seelink}[3]{\htmladdnormallink{#2}{#1}} 
-\newcommand{\citetitle}[2]{\htmladdnormallink{#2}{#1}} 
-
-% constants
-\newcommand{\dtc}{\code{'d'}}
-\newcommand{\itc}{\code{'i'}}
-\newcommand{\ztc}{\code{'z'}}
-\newcommand{\None}{\code{None}}
-\newcommand{\True}{\code{True}}
-\newcommand{\False}{\code{False}}
-
-% types
-\newcommand{\flt}{\pytype{float}}
-\newcommand{\chr}{\pytype{char}}
-\newcommand{\intgr}{\pytype{integer}}
-\newcommand{\cmplx}{\pytype{complex}}
-\newcommand{\mtrx}{\class{matrix}}
-\newcommand{\spmtrx}{\class{spmatrix}}
-
-\parindent 0pt
-
-\title{CVXOPT User's Guide} 
-\author{Joachim Dahl \& Lieven Vandenberghe}
-\date{Release 1.1 -- October 15, 2008} 
-\begin{document}
-\Configure{crosslinks*}{next}{prev}{up}{}
-
-\maketitle
-
-\input{copyright}
-\input{intro}
-\input{matrices}
-\input{blas}
-\input{lapack}
-\input{fftw}
-\input{spsolvers}
-\input{coneprog}
-\input{solvers}
-\input{modeling}
-\appendix
-\input{c-api}
-\input{printing}
-\end{document}
diff --git a/doc/fftw.tex b/doc/fftw.tex
deleted file mode 100644
index f5d6c1f..0000000
--- a/doc/fftw.tex
+++ /dev/null
@@ -1,162 +0,0 @@
-\chapter{Discrete Transforms (\module{cvxopt.fftw})} \label{c-fftw}
-
-The \module{cvxopt.fftw} module is an interface to the FFTW library
-and contains routines for discrete Fourier, cosine, and sine 
-transforms.  This module is optional, and only installed when 
-the FFTW library is made available during the CVXOPT installation.
-
-\textbf{See also:}
-\seelink{http://www.fftw.org}{FFTW3 code, documentation, copyright and
-license.}{}
-
-\section{Discrete Fourier Transform} 
-\begin{funcdesc}{dft}{X}
-Replaces the columns of a dense complex matrix with their discrete 
-Fourier transforms:  if \var{X} has {\it n} rows,
-\[
-  X[k,:] := \sum_{j=0}^{n-1} e^{-2\pi j k \sqrt{-1}/n} X[j,:],
- \qquad k=0,\ldots,n-1.
-\]
-\end{funcdesc}
-
-\begin{funcdesc}{idft}{X}
-Replaces the columns of a dense complex matrix with their inverse 
-discrete Fourier transforms: if \var{X} has {\it n} rows,
-\[
-  X[k,:] := 
- \frac{1}{n} \sum_{j=0}^{n-1} e^{2\pi j k \sqrt{-1}/n} X[j,:],
-  \qquad k=0,\ldots,n-1.
-\]
-\end{funcdesc}
-
-The module also includes a discrete \tm{N}-dimensional Fourier transform.
-The input matrix is interpreted as an \tm{N}-dimensional
-matrix stored in column-major order. The discrete \tm{N}-dimensional 
-Fourier transform computes the corresponding one-dimensional transform 
-along each dimension.  For example, 
-the two-dimensional transform applies a one-dimensional transform to 
-all the columns of the matrix, followed by a one-dimensional transform
-to all the rows of the matrix. 
-
-\begin{funcdesc}{dftn}{X\optional{, dims=X.size}}
-Replaces a dense complex matrix with its \tm{N}-dimensional
-discrete Fourier transform. The dimensions of the \tm{N}-dimensional
-matrix are given by the \tm{N}-tuple \var{dim}. 
-The two-dimensional transform is computed as \code{dftn(X, X.size)}. 
-\end{funcdesc}
-
-\begin{funcdesc}{idftn}{X\optional{, dims=X.size}}
-Replaces a dense complex \tm{N}-dimensional matrix with its inverse 
-\tm{N}-dimensional discrete Fourier transform. The dimensions of the matrix
-are given by the tuple \var{dim}. The two-dimensional inverse transform 
-is computed as \code{idftn(X, X.size)}.
-\end{funcdesc}
-
-\section{Discrete Cosine Transform} 
-\begin{funcdesc}{dct}{X\optional{, type=2}}
-Replaces the columns of a dense real matrix with their discrete
-cosine transforms.  The second argument, an integer between 1 and 4,
-denotes the type of transform (DCT-I, DCT-II, DCT-III, DCT-IV).
-The DCT-I transform requires that the row dimension of \var{X} is at 
-least 2.
-These transforms are defined as follows 
-(for a matrix with {\it n} rows).
-\BEAS
-\mbox{DCT-I:} \qquad
- X[k,:]  & := & X[0,:] + (-1)^k X[n-1,:] + 
- 2 \sum_{j=1}^{n-2} X[j,:] \cos(\pi j k /(n-1)), 
- \qquad k=0,\ldots,n-1.\\
-\mbox{DCT-II:} \qquad
- X[k,:]  & := & 2 \sum_{j=0}^{n-1} X[j,:] \cos(\pi(j+1/2)k/n), 
- \qquad k=0,\ldots,n-1.\\
-\mbox{DCT-III:} \qquad
- X[k,:]  & := & X[0,:] + 2 \sum_{j=1}^{n-1} X[j,:] \cos(\pi j(k+1/2)/n),
- \qquad k=0,\ldots,n-1.\\
-\mbox{DCT-IV:} \qquad
- X[k,:]  & := & 2 \sum_{j=0}^{n-1} X[j,:] \cos(\pi (j+1/2)(k+1/2)/n), 
- \qquad k=0,\ldots,n-1.
-\EEAS
-\end{funcdesc}
-
-\begin{funcdesc}{idct}{X\optional{, type=2}}
-Replaces the columns of a dense real matrix with the inverses
-of the discrete cosine transforms defined above.  
-\end{funcdesc}
-
-The module also includes a discrete \tm{N}-dimensional cosine transform.
-The input matrix is interpreted as an \tm{N}-dimensional
-matrix stored in column-major order. 
-The discrete \tm{N}-dimensional cosine transform computes the corresponding 
-one-dimensional transform along each dimension.  For example, 
-the two-dimensional transform applies a one-dimensional transform to 
-all the rows of the matrix, followed by a one-dimensional transform
-to all the columns of the matrix. 
-
-\begin{funcdesc}{dctn}{X\optional{, dims=X.size\optional{, type=2}}}
-Replaces a dense real matrix with its \tm{N}-dimensional
-discrete cosine transform. The dimensions of the \tm{N}-dimensional
-matrix are given by the \tm{N}-tuple \var{dim}. 
-The two-dimensional transform is computed as \code{dctn(X, X.size)}. 
-\end{funcdesc}
-
-\begin{funcdesc}{idctn}{X\optional{, dims=X.size\optional{, type=2}}}
-Replaces a dense real \tm{N}-dimensional matrix with its inverse 
-\tm{N}-dimensional discrete cosine transform. The dimensions of the matrix
-are given by the tuple \var{dim}.  The two-dimensional inverse transform 
-is computed as \code{idctn(X, X.size)}.
-\end{funcdesc}
-
-\section{Discrete Sine Transform} 
-\begin{funcdesc}{dst}{X, dims\optional{, type=1}}
-Replaces the columns of a dense real matrix with their discrete
-sine transforms.  The second argument, an integer between 1 and 4,
-denotes the type of transform (DST-I, DST-II, DST-III, DST-IV).
-These transforms are defined as follows 
-(for a matrix with {\it n} rows).
-\BEAS
-\mbox{DST-I:} \qquad
- X[k,:] & := & 
- 2 \sum_{j=0}^{n-1} X[j,:] \sin(\pi(j+1)(k+1)/(n+1)), 
- \qquad k=0,\ldots,n-1.\\
-\mbox{DST-II:} \qquad
- X[k,:]  & := & 2 \sum_{j=0}^{n-1} X[j,:] \sin(\pi(j+1/2)(k+1)/n), 
- \qquad k=0,\ldots,n-1.\\
-\mbox{DST-III:} \qquad
- X[k,:]  & := & (-1)^k X[n-1,:] + 2 \sum_{j=0}^{n-2} 
- X[j,:] \sin(\pi(j+1)(k+1/2)/n), 
- \qquad k=0,\ldots,n-1. \\
-\mbox{DST-IV:} \qquad
- X[k,:]  & := & 2 \sum_{j=0}^{n-1} X[j,:] \sin(\pi (j+1/2)(k+1/2)/n), 
- \qquad k=0,\ldots,n-1.
-\EEAS
-\end{funcdesc}
-
-\begin{funcdesc}{idst}{X, dims\optional{, type=1}}
-Replaces the columns of a dense real matrix with the inverses
-of the discrete sine transforms defined above.  
-\end{funcdesc}
-
-The module also includes a discrete \tm{N}-dimensional sine transform.
-The input matrix is interpreted as an \tm{N}-dimensional
-matrix stored in column-major order.  
-The discrete \tm{N}-dimensional sine transform computes the corresponding 
-one-dimensional transform along each dimension.  For example, 
-the two-dimensional transform applies a one-dimensional transform to 
-all the rows of the matrix, followed by a one-dimensional transform
-to all the columns of the matrix. 
-
-\begin{funcdesc}{dstn}{X\optional{, dims=X.size\optional{, type=2}}}
-Replaces a dense real matrix with its \tm{N}-dimensional
-discrete sine transform. The dimensions of the \tm{N}-dimensional
-matrix are given by the \tm{N}-tuple \var{dim}. 
-The two-dimensional transform is computed as 
-\code{dstn(X, X.size)}. 
-\end{funcdesc}
-
-\begin{funcdesc}{idstn}{X\optional{, dims=X.size\optional{, type=2}}}
-Replaces a dense real \tm{N}-dimensional matrix with its inverse 
-\tm{N}-dimensional discrete sine transform. 
-The dimensions of the matrix are given by the tuple \var{dim}. 
-The two-dimensional inverse transform is computed as 
-\code{idstn(X, X.size)}.
-\end{funcdesc}
diff --git a/doc/figures/floorplan.pdf b/doc/figures/floorplan.pdf
deleted file mode 100644
index 9338306..0000000
Binary files a/doc/figures/floorplan.pdf and /dev/null differ
diff --git a/doc/figures/normappr.pdf b/doc/figures/normappr.pdf
deleted file mode 100644
index b2bca3c..0000000
Binary files a/doc/figures/normappr.pdf and /dev/null differ
diff --git a/doc/figures/portfolio1.pdf b/doc/figures/portfolio1.pdf
deleted file mode 100644
index 64db667..0000000
Binary files a/doc/figures/portfolio1.pdf and /dev/null differ
diff --git a/doc/figures/portfolio2.pdf b/doc/figures/portfolio2.pdf
deleted file mode 100644
index 352c7ca..0000000
Binary files a/doc/figures/portfolio2.pdf and /dev/null differ
diff --git a/doc/intro.tex b/doc/intro.tex
deleted file mode 100644
index 4ad5423..0000000
--- a/doc/intro.tex
+++ /dev/null
@@ -1,55 +0,0 @@
-\chapter{Introduction}\label{chap:intro}
-
-CVXOPT is a free software package for convex optimization based on
-the Python programming language.
-It can be used with the interactive Python interpreter, 
-on the command line by executing Python scripts, or integrated in 
-other software via Python extension modules.
-Its main purpose is to make the development of software for convex 
-optimization applications straightforward by building on Python's 
-extensive standard library and on the strengths of Python as a 
-high-level programming language.  
-
-CVXOPT extends the built-in Python objects with two matrix objects: 
-a \mtrx\ object for dense matrices and an \spmtrx\ object for sparse 
-matrices.  These two matrix types are introduced in 
-chapter~\ref{chap:matrix} of this user's guide, together with the 
-arithmetic operations and functions defined for them.  
-The following chapters~\ref{chap:blas}--\ref{c-spsolvers} describe
-interfaces to several libraries for dense and sparse matrix computations. 
-The CVXOPT optimization routines are described in 
-chapters~\ref{chap:coneprog}--\ref{chap:modeling}.
-These include convex optimization solvers written in Python, 
-interfaces to a few other optimization libraries, and a modeling tool 
-for piecewise-linear convex optimization problems.
-
-CVXOPT is organized in different modules.  
-\begin{description}
-\item[\module{cvxopt.blas}] Interface to most of the double-precision 
- real and complex BLAS (chapter~\ref{chap:blas}).
-\item[\module{cvxopt.lapack}] Interface to dense double-precision 
- real and complex linear equation solvers and eigenvalue routines 
- from LAPACK (chapter~\ref{chap:lapack}).
-\item[\module{cvxopt.fftw}] An optional interface to the 
- discrete transform routines from FFTW (section~\ref{c-fftw}). 
-\item[\module{cvxopt.amd}]  Interface to the approximate minimum degree
- ordering routine from AMD (chapter~\ref{s-orderings}).
-\item[\module{cvxopt.umfpack}] Interface to the sparse LU solver 
- from UMFPACK (section~\ref{s-umfpack}).
-\item[\module{cvxopt.cholmod}] Interface to the sparse Cholesky 
- solver from CHOLMOD (section~\ref{s-cholmod}).
-\item[\module{cvxopt.solvers}] Convex optimization routines
- and optional interfaces to solvers from GLPK, MOSEK, and DSDP5
- (chapters~\ref{chap:coneprog} and~\ref{chap:solvers}).
-\item[\module{cvxopt.modeling}]  Routines for specifying and solving 
- linear programs and convex optimization problems with piecewise-linear 
- cost and constraint functions (chapter~\ref{chap:modeling}).
-\item[\module{cvxopt.info}] Defines a string \code{version} with
- the version number of the CVXOPT installation and a function 
- \function{license()} that prints the CVXOPT license.  
-\item[\module{cvxopt.printing}] Contains functions and parameters that
- control how matrices are formatted. 
-\end{description}
-The modules are described in detail in this manual and in the 
-on-line Python help facility \program{pydoc}.  Several example scripts 
-are included in the distribution. 
diff --git a/doc/lapack.tex b/doc/lapack.tex
deleted file mode 100644
index d03e34c..0000000
--- a/doc/lapack.tex
+++ /dev/null
@@ -1,1220 +0,0 @@
-\chapter{The LAPACK Interface (\module{cvxopt.lapack})}
-\label{chap:lapack}
-
-The module \module{cvxopt.lapack} includes functions for 
-solving dense sets of linear equations, for the corresponding matrix 
-factorizations (LU, Cholesky, $\mathrm{LDL^T}$),
-for solving least-squares and least-norm problems, for QR 
-factorization, for symmetric eigenvalue problems, singular 
-value decomposition, and Schur factorization.  
-
-In this chapter we briefly describe the Python calling sequences.
-For further details on the underlying LAPACK functions we refer to the 
-LAPACK Users' Guide and manual pages.  
-
-The BLAS conventional storage scheme of section~\ref{s-conventions} is 
-used. As in the previous chapter, we omit from the function definitions
-less important arguments that are useful for selecting submatrices. 
-The complete definitions are documented in the docstrings in the 
-source code.
-
-\textbf{See also:}
-\seelink{http://www.netlib.org/lapack/lug/lapack_lug.html}{LAPACK 
-Users' Guide, Third Edition, SIAM, 1999}{}.
-
-
-\section{General Linear Equations}
-\begin{funcdesc}{gesv}{A, B\optional{, ipiv=None}}
-Solves
-\[ 
-   A X = B,
-\]
-where \tm{A} and \tm{B} are real or complex matrices, with \tm{A}
-square and nonsingular.  On exit, \var{B} is replaced by the solution.  
-The arguments \var{A} and \var{B} must have the same type (\dtc\ or
-\ztc).  
-The optional argument \var{ipiv} is an integer matrix of length at 
-least \tm{n}.  
-If \var{ipiv} is provided, then \function{gesv()} solves the system, 
-replaces \var{A} with its triangular factors, and returns the 
-permutation matrix in \var{ipiv}.
-If \var{ipiv} is not specified, then \function{gesv()} solves the
-system but does not return the LU factorization and does not 
-modify \var{A}.  
-For example,
-\begin{verbatim}
->>> gesv(A, B)
-\end{verbatim}
-solves the system without modifying \var{A} and returns the solution 
-in \var{B}.
-\begin{verbatim}
->>> gesv(A, B, ipiv)
-\end{verbatim}
-returns the solution in \var{B} and also returns the details of the 
-LU factorization in \var{A} and \var{ipiv}.
-
-Raises an \code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{getrf}{A, ipiv}
-LU factorization of a general, possibly rectangular, real or
-complex matrix,  
-\[
-  A = PLU 
-\]
-where \tm{A} is \tm{m} by \tm{n}.
-The argument \var{ipiv} is an integer matrix of length at least
-\tm{\min\{m, n\}}.
-On exit, the lower triangular part of \var{A} is replaced by \tm{L},
-the upper triangular part by \tm{U}, and the permutation matrix is 
-returned in \var{ipiv}.
-Raises an \code{ArithmeticError} if the matrix is not full rank.
-\end{funcdesc}
-
-\begin{funcdesc}{getrs}{A, ipiv, B\optional{, trans='N'}}
-Solves a general set of linear equations
-\[
- AX=B \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
- A^TX=B \quad (\mathrm{trans} = \mathrm{'T'}), \qquad 
- A^HX=B \quad (\mathrm{trans} = \mathrm{'C'}), 
-\]
-given the LU factorization computed by \function{gesv()} or 
-\function{getrf()}.
-On entry, \var{A} and \var{ipiv} must contain the factorization
-as computed by \function{gesv()} or \function{getrf()}.  
-On exit, \var{B} is overwritten with the solution. 
-\var{B} must have the same type as \var{A}.
-\end{funcdesc}
-
-\begin{funcdesc}{getri}{A, ipiv}
-Computes the inverse of a matrix.
-On entry, \var{A} and \var{ipiv} must contain the factorization
-as computed by \function{gesv()} or \function{getrf()}.  On exit, 
-\var{A} contains the inverse.
-\end{funcdesc}
-
-In the following example we compute
-\[
- x = (A^{-1} + A^{-T})b
-\]
-for randomly generated problem data, factoring the coefficient matrix 
-once.
-\begin{verbatim}
->>> from cvxopt import matrix, normal
->>> from cvxopt.lapack import gesv, getrs
->>> n = 10
->>> A = normal(n,n)
->>> b = normal(n)
->>> ipiv = matrix(0, (n,1))
->>> x = +b
->>> gesv(A, x, ipiv)               # x = A^{-1}*b 
->>> x2 = +b
->>> getrs(A, ipiv, x2, trans='T')  # x2 = A^{-T}*b
->>> x += x2
-\end{verbatim}
-
-Separate functions are provided for equations with band matrices.
-\begin{funcdesc}{gbsv}{A, kl, B\optional{, ipiv=None}}
-Solves
-\[ 
-   A X = B,
-\]
-where \tm{A} and \tm{B} are real or complex matrices, with \tm{A}
-\tm{n} by \tm{n} and banded with \tm{\s{k}{l}} subdiagonals.  
-The arguments \var{A} and \var{B} must have the same type (\dtc\ or
-\ztc).  
-
-The optional argument \var{ipiv} is an integer matrix of length at 
-least \tm{n}.
-If \var{ipiv} is provided, then \var{A} must have 
-\tm{2\s{k}{l} + \s{k}{u} + 1} rows.  On entry the diagonals of \tm{A} are
-stored in rows \tm{\s{k}{l} + 1} to 
-\tm{2\s{k}{l} + \s{k}{u} +1} of \var{A}, using the BLAS format for 
-general band matrices (see section~\ref{s-conventions}).
-On exit, the factorization is returned in {\var A} and \var{ipiv}.
-
-If \var{ipiv} is not provided, then \var{A} must have 
-\tm{\s{k}{l} + \s{k}{u} + 1} rows.  
-On entry the diagonals of \tm{A} are stored in the 
-rows of \var{A}, following the standard format for general band matrices. 
-In this case, \function{gbsv()} does not modify \var{A} on exit and does
-not return the factorization.
-
-On exit, \var{B} is replaced by the solution \tm{X}.  
-Raises an \code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{gbtrf}{A, m, kl, ipiv}
-LU factorization of a general \tm{m} by \tm{n} real or complex band 
-matrix with \tm{\s{k}{l}} subdiagonals.
-The matrix is stored using the BLAS format for general band matrices
-(see section~\ref{s-conventions}), by providing the 
-diagonals (stored as rows of a \tm{\s{k}{u} + \s{k}{l} + 1} by 
-\tm{n} matrix),
-the number of rows \tm{m}, and the number of subdiagonals \tm{\s{k}{l}}.
-The argument \var{ipiv} is an integer matrix of length at least
-\tm{\min\{m, n\}}.
-On exit, \var{A} and \var{ipiv} contain the details of the factorization.
-Raises an \code{ArithmeticError} if the matrix is not full rank.
-\end{funcdesc}
-
-\begin{funcdesc}{gbtrs}{A, kl, ipiv, B\optional{, trans='N'}}
-Solves a set of linear equations 
-\[
- AX=B \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
- A^TX=B \quad (\mathrm{trans} = \mathrm{'T'}), \qquad 
- A^HX=B \quad (\mathrm{trans} = \mathrm{'C'}), 
-\]
-with \tm{A} a general band matrix with \tm{\s{k}{l}} subdiagonals, 
-given the LU factorization computed by 
-\function{gbsv()} or \function{gbtrf()}.
-On entry, \var{A} and \var{ipiv} must contain the factorization
-as computed by \function{gbsv()} or \function{gbtrf()}.  
-On exit, \var{B} is overwritten with the solution. 
-\var{B} must have the same type as \var{A}.
-\end{funcdesc}
-
-As an example, we solve a linear equation with
-\[
- A = \left[ \begin{array}{cccc}
- 1 & 2 & 0 & 0 \\
- 3 & 4 & 5 & 0 \\
- 6 & 7 & 8 & 9 \\
- 0 & 10 & 11 & 12 
- \end{array}\right], \qquad  x = \left[\begin{array}{c} 1 \\ 1 \\ 1 \\ 1
- \end{array}\right].
-\]
-\begin{verbatim}
->>> from cvxopt import matrix
->>> from cvxopt.lapack import gbsv, gbtrf, gbtrs
->>> n, kl, ku = 4, 2, 1
->>> A = matrix([[0., 1., 3., 6.], [2., 4., 7., 10.], [5., 8., 11., 0.], [9., 12., 0., 0.]])
->>> x = matrix(1.0, (4,1))
->>> gbsv(A, kl, x)
->>> print x
-[ 7.14e-02]
-[ 4.64e-01]
-[-2.14e-01]
-[-1.07e-01]
-\end{verbatim}
-The code below illustrates how one can reuse the factorization returned
-by \function{gbsv()}. 
-\begin{verbatim}
->>> Ac = matrix(0.0, (2*kl+ku+1,n))
->>> Ac[kl:,:] = A
->>> ipiv = matrix(0, (n,1))
->>> x = matrix(1.0, (4,1))
->>> gbsv(Ac, kl, x, ipiv)                 # solves A*x = 1
->>> print x
-[ 7.14e-02]
-[ 4.64e-01]
-[-2.14e-01]
-[-1.07e-01]
->>> x = matrix(1.0, (4,1))
->>> gbtrs(Ac, kl, ipiv, x, trans='T')     # solve A^T*x = 1
->>> print x
-[ 7.14e-02]
-[ 2.38e-02]
-[ 1.43e-01]
-[-2.38e-02]
-\end{verbatim}
-An alternative method uses \function{gbtrf()} for the factorization.
-\begin{verbatim}
->>> Ac[kl:,:] = A
->>> gbtrf(Ac, n, kl, ipiv)                 
->>> x = matrix(1.0, (4,1))
->>> gbtrs(Ac, kl, ipiv, x)                # solve A^T*x = 1
->>> print x                 
-[ 7.14e-02]
-[ 4.64e-01]
-[-2.14e-01]
-[-1.07e-01]
->>> x = matrix(1.0, (4,1))
->>> gbtrs(Ac, kl, ipiv, x, trans='T')     # solve A^T*x = 1
->>> print x
-[ 7.14e-02]
-[ 2.38e-02]
-[ 1.43e-01]
-[-2.38e-02]
-\end{verbatim}
-
-The following functions can be used for tridiagonal matrices. They use a 
-simpler matrix format, that stores the diagonals in three separate 
-vectors.
-
-\begin{funcdesc}{gtsv}{dl, d, du, B)}
-Solves
-\[ 
-   A X = B,
-\]
-where \tm{A} is an \tm{n} by \tm{n} tridiagonal matrix, 
-with subdiagonal stored as a matrix \var{dl} of length \tm{n-1}, 
-diagonal stored as a matrix \var{d} of length \tm{n}, and superdiagonal 
-stored as a matrix \var{du} of length \tm{n-1}.  
-The four arguments must have the same type (\dtc\ or \ztc).
-On exit \var{dl}, \var{d}, \var{du} are overwritten with the details of 
-the LU factorization of \tm{A}, and \var{B} is overwritten with the solution 
-\tm{X}.  
-Raises an \code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{gttrf}{dl, d, du, du2, ipiv}
-LU factorization of an \tm{n} by \tm{n} tridiagonal matrix with
-subdiagonal \tm{\s{d}{l}}, diagonal \tm{d} and superdiagonal \tm{\s{d}{u}}.
-\var{dl}, \var{d} and \var{du} must have the same type.
-\var{du2} is a matrix of length \tm{n-2}, and of the same type as 
-\var{dl}.
-\var{ipiv} is an \itc\ matrix of length \tm{n}.
-On exit, the five arguments contain the details of the factorization.
-Raises an \code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{pttrs}{dl, d, du, du2, ipiv, B\optional{, trans='N'}}
-Solves a set of linear equations 
-\[
- AX=B \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
- A^TX=B \quad (\mathrm{trans} = \mathrm{'T'}), \qquad 
- A^HX=B \quad (\mathrm{trans} = \mathrm{'C'}), 
-\]
-where \tm{A} is an \tm{n} by \tm{n} tridiagonal matrix.
-The arguments \var{dl}, \var{d}, \var{du}, \var{du2} and \var{ipiv}
-contain the details of the LU factorization as returned by 
-\function{gttrf()}.
-On exit, \var{B} is overwritten with the solution \tm{X}. 
-\var{B} must have the same type as \var{dl}.
-\end{funcdesc}
-
-
-\section{Positive Definite Linear Equations}
-\begin{funcdesc}{posv}{A, B\optional{, uplo='L'}}
-Solves
-\[ 
-   A X = B,
-\]
-where \tm{A} is a real symmetric or complex Hermitian positive 
-definite matrix.
-On exit, \var{B} is replaced by the solution, and \var{A} is 
-overwritten with the Cholesky factor.
-The matrices \var{A} and \var{B} must have the same type (\dtc\ or 
-\ztc).
-Raises an \code{ArithmeticError} if the matrix is not positive definite.
-\end{funcdesc}
-
-\begin{funcdesc}{potrf}{A\optional{, uplo='L'}}
-Cholesky factorization 
-\[
- A = LL^T \qquad \mbox{or} \qquad A = LL^H
-\]
-of a positive definite real symmetric or complex Hermitian matrix \tm{A}.  
-On exit, the lower triangular part of \var{A} 
-(if \var{uplo} is \code{'L'}) or the upper triangular part 
-(if \var{uplo} is \code{'U'}) is overwritten with the Cholesky factor 
-or its (conjugate) transpose.
-Raises an \code{ArithmeticError} if the matrix is not positive definite.
-\end{funcdesc}
-
-\begin{funcdesc}{potrs}{A, B\optional{, uplo='L'}}
-Solves a set of linear equations
-\[
- AX=B
-\]
-with a positive definite real symmetric or complex Hermitian matrix,
-given the Cholesky factorization computed by 
-\function{posv()} or \function{potrf()}.
-On entry, \var{A} contains the triangular factor, as computed by
-\function{posv()} or \function{potrf()}.  On exit, \var{B} is replaced 
-by the solution.
-\var{B} must have the same type as \var{A}.
-\end{funcdesc}
-
-\begin{funcdesc}{potri}{A\optional{, uplo='L'}} 
-Computes the inverse of a positive definite matrix.
-On entry, \var{A} contains the Cholesky factorization computed 
-by \function{potrf()} or \function{posv()}. On exit, it contains
-the inverse.
-\end{funcdesc}
-
-As an example, we use \function{posv()} to solve the linear system
-\BEQ \label{e-kkt-example}
- \left[ \begin{array}{cc}
- -\diag(d)^2  & A \\
- A^T  & 0 \end{array} \right]
- \left[ \begin{array}{c} x_1 \\ x_2 \end{array} \right]
- = \left[ \begin{array}{c} b_1 \\ b_2 \end{array} \right]
-\EEQ
-by block-elimination. 
-We first pick a random problem.
-\begin{verbatim}
->>> from cvxopt import matrix, div, normal, uniform
->>> from cvxopt.blas import syrk, gemv
->>> from cvxopt.lapack import posv
->>> m, n = 100, 50  
->>> A = normal(m,n)
->>> b1, b2 = normal(m), normal(n)
->>> d = uniform(m)
-\end{verbatim}
-We then solve the equations 
-\[
- A^T \diag(d)^{-2}A x_2 = b_2 + A^T \diag(d)^{-2} b_1, \qquad
- \diag(d)^2 x_1 = Ax_2 - b_1.
-\]
-\begin{verbatim}
->>> Asc = div(A, d[:, n*[0]])                # Asc := diag(d)^{-1}*A
->>> B = matrix(0.0, (n,n))
->>> syrk(Asc, B, trans='T')                  # B := Asc^T * Asc = A^T * diag(d)^{-2} * A
->>> x1 = div(b1, d)                          # x1 := diag(d)^{-1}*b1
->>> x2 = +b2
->>> gemv(Asc, x1, x2, trans='T', beta=1.0)   # x2 := x2 + Asc^T*x1 = b2 + A^T*diag(d)^{-2}*b1 
->>> posv(B, x2)                              # x2 := B^{-1}*x2 = B^{-1}*(b2 + A^T*diag(d)^{-2}*b1)
->>> gemv(Asc, x2, x1, beta=-1.0)             # x1 := Asc*x2 - x1 = diag(d)^{-1} * (A*x2 - b1)
->>> x1 = div(x1, d)                          # x1 := diag(d)^{-1}*x1 = diag(d)^{-2} * (A*x2 - b1)
-\end{verbatim}
-
-There are separate routines for equations with positive definite band 
-matrices.
-\begin{funcdesc}{pbsv}{A, B\optional{, uplo='L'}}
-Solves
-\[
- AX=B
-\]
-where \tm{A} is a real symmetric or complex Hermitian positive definite
-band matrix.  On entry, the diagonals of \tm{A} are stored in \var{A}, 
-using the BLAS format for symmetric or Hermitian band matrices
-(see section~\ref{s-conventions}).  On exit, \var{B} is replaced by the
-solution, and \var{A} is overwritten with the Cholesky factor (in the
-BLAS format for triangular band matrices).  The matrices \var{A} and 
-\var{B} must have the same type (\dtc\ or \ztc).
-Raises an \code{ArithmeticError} if the matrix is not positive definite.
-\end{funcdesc}
-
-\begin{funcdesc}{pbtrf}{A\optional{, uplo='L'}}
-Cholesky factorization 
-\[
- A = LL^T \qquad \mbox{or} \qquad A = LL^H
-\]
-of a positive definite real symmetric or complex Hermitian band matrix
-\tm{A}.  On entry, the diagonals of \tm{A} are stored in \var{A}, 
-using the BLAS format for symmetric or Hermitian band matrices.
-On exit, \var{A} contains the Cholesky factor, in the BLAS format
-for triangular band matrices.
-Raises an \code{ArithmeticError} if the matrix is not positive definite.
-\end{funcdesc}
-
-\begin{funcdesc}{pbtrs}{A, B\optional{, uplo='L'}}
-Solves a set of linear equations
-\[
- AX=B
-\]
-with a positive definite real symmetric or complex Hermitian band matrix,
-given the Cholesky factorization computed by \function{pbsv()} or 
-\function{pbtrf()}.
-On entry, \var{A} contains the triangular factor, as computed by
-\function{pbsv()} or \function{pbtrf()}.  On exit, \var{B} is replaced 
-by the solution.  \var{B} must have the same type as \var{A}.
-\end{funcdesc}
-
-The following functions are useful for tridiagonal systems.
-
-\begin{funcdesc}{ptsv}{d, e, B}
-Solves
-\[ 
-   A X = B,
-\]
-where \tm{A} is an \tm{n} by \tm{n} positive definite real symmetric 
-or complex Hermitian tridiagonal matrix.  Its diagonal 
-is stored as a \dtc\ matrix \var{d} of length \tm{n} and 
-its subdiagonal as a \dtc\ or \ztc\ matrix \var{e} of length \tm{n-1}.
-The arguments \var{e} and \var{B} must have the same type.  
-On exit \var{d} contains the diagonal elements of \tm{D} in 
-the $\mathrm{LDL^T}$ or $\mathrm{LDL^H}$ factorization 
-of \tm{A}, and \var{e} contains the subdiagonal elements of the unit 
-lower bidiagonal matrix \tm{L}.  
-\var{B} is overwritten with the solution \tm{X}.  
-Raises an \code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{pttrf}{d, e}
-$\mathrm{LDL^T}$ or $\mathrm{LDL^H}$ factorization of an \tm{n} by 
-\tm{n} positive definite real symmetric or complex Hermitian tridiagonal 
-matrix \tm{A}.
-On entry, the argument \var{d} is a \dtc\ matrix with the diagonal elements
-of \tm{A}.  The argument \var{e} is \dtc\ or \ztc\ matrix with
-the subdiagonal elements of \tm{A}.
-On exit \var{d} contains the diagonal elements of \tm{D}, and \var{e} 
-contains the subdiagonal elements of the unit lower bidiagonal matrix 
-\tm{L}.  Raises an \code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{gttrs}{d, e, B\optional{, uplo='L'}}
-Solves a set of linear equations 
-\[
- AX=B 
-\]
-where \tm{A} is an \tm{n} by \tm{n} positive definite real symmetric 
-or complex Hermitian tridiagonal matrix, given its $\mathrm{LDL^T}$ or 
-$\mathrm{LDL^H}$ factorization.
-The argument \var{d} is the diagonal of the diagonal matrix \tm{D}.
-The argument \var{uplo} only matters for complex matrices.
-If \var{uplo} is \code{'L'}, then on exit \var{e} contains the subdiagonal 
-elements of the unit bidiagonal matrix \tm{L}.
-If \var{uplo} is \code{'U'}, then \var{e} contains the complex
-conjugates of the elements of the unit bidiagonal matrix \tm{L}.
-On exit, \var{B} is overwritten with the solution \tm{X}. 
-\var{B} must have the same type as \var{e}.
-\end{funcdesc}
-
-
-\section{Symmetric and Hermitian Linear Equations}
-\begin{funcdesc}{sysv}{A, B\optional{, ipiv=None\optional{, uplo='L'}}}
-Solves
-\[
- AX=B
-\] 
-where \tm{A} is a real or complex symmetric matrix  of order \tm{n}.
-On exit, \var{B} is replaced by the solution.  
-The matrices \var{A} and \var{B} must have the same type (\dtc\ or 
-\ztc).
-The optional argument \var{ipiv} is an integer matrix of length at 
-least equal to \tm{n}.
-If \var{ipiv} is provided, \function{sysv()} solves the system and 
-returns the factorization in \var{A} and \var{ipiv}.
-If \var{ipiv} is not specified, \function{sysv()} solves the
-system but does not return the factorization and does not modify 
-\var{A}.
-Raises an \code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{sytrf}{A, ipiv\optional{, uplo='L'}}
-$\mathrm{LDL^T}$ factorization 
-\[
- PAP^T = LDL^T
-\]
-of a real or complex symmetric matrix \tm{A} of order \tm{n}.
-\var{ipiv} is an \itc\ matrix of length at least \tm{n}.
-On exit, \var{A} and \var{ipiv} contain the factorization.
-Raises an \code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{sytrs}{A, ipiv, B\optional{, uplo='L'}}
-Solves 
-\[
-  A X = B
-\]
-given the $\mathrm{LDL^T}$ factorization computed by 
-\function{sytrf()} or \function{sysv()}. \var{B} must have the same
-type as \var{A}.
-\end{funcdesc}
-
-\begin{funcdesc}{sytri}{A, ipiv\optional{, uplo='L'}}
-Computes the inverse of a real or complex symmetric matrix.
-On entry, \var{A} and \var{ipiv} contain the $\mathrm{LDL^T}$ 
-factorization computed by \function{sytrf()} or \function{sysv()}. 
-On exit, \var{A} contains the inverse.
-\end{funcdesc}
-
-\begin{funcdesc}{hesv}{A, B\optional{, ipiv=\None\optional{, uplo='L'}}}
-Solves
-\[
- A X = B
-\]
-where \tm{A} is a real symmetric or complex Hermitian of order \tm{n}.
-On exit, \var{B} is replaced by the solution.
-The matrices \var{A} and \var{B} must have the same type (\dtc\ or 
-\ztc).
-The optional argument \var{ipiv} is an integer matrix of length at 
-least \tm{n}.  
-If \var{ipiv} is provided, then \function{hesv()} solves the system and 
-returns the factorization in \var{A} and \var{ipiv}.
-If \var{ipiv} is not specified, then \function{hesv()} solves the
-system but does not return the factorization and does not modify 
-\var{A}.
-Raises an \code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{hetrf}{A, ipiv\optional{, uplo='L'}}
-$\mathrm{LDL^H}$ factorization 
-\[
- PAP^T = LDL^H
-\]
-of a real symmetric or complex Hermitian matrix of order \tm{n}.
-\var{ipiv} is an \itc\ matrix of length at least \tm{n}.
-On exit, \var{A} and \var{ipiv} contain the factorization.
-Raises an \code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{hetrs}{A, ipiv, B\optional{, uplo='L'}}
-Solves 
-\[
- A X = B
-\]
-given the $\mathrm{LDL^H}$ factorization computed by 
-\function{hetrf()} or \function{hesv()}.
-\end{funcdesc}
-
-\begin{funcdesc}{hetri}{A, ipiv\optional{, uplo='L'}}
-Computes the inverse of a real symmetric or complex Hermitian  matrix.
-On entry, \var{A} and \var{ipiv} contain the $\mathrm{LDL^H}$ 
-factorization computed by \function{hetrf()} or \function{hesv()}. 
-On exit, \var{A} contains the inverse.
-\end{funcdesc}
-
-As an example we solve the KKT system~(\ref{e-kkt-example}).
-\begin{verbatim}
->>> from cvxopt.lapack import sysv
->>> K = matrix(0.0, (m+n,m+n))
->>> K[: (m+n)*m : m+n+1] = -d**2
->>> K[:m, m:] = A
->>> x = matrix(0.0, (m+n,1))
->>> x[:m], x[m:] = b1, b2
->>> sysv(K, x, uplo='U')   
-\end{verbatim}
-
-\section{Triangular Linear Equations}
-
-\begin{funcdesc}{trtrs}{A, B\optional{, uplo='L'\optional{, 
-trans='N'\optional{, diag='N'}}}}
-Solves a triangular set of equations
-\[
- AX=B \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
- A^TX=B \quad (\mathrm{trans} = \mathrm{'T'}), \qquad 
- A^HX=B \quad (\mathrm{trans} = \mathrm{'C'}), 
-\]
-where \tm{A} is real or complex and triangular of order \tm{n}, 
-and \var{B} is a matrix with \tm{n} rows.
-\var{A} and \var{B} are matrices with the same type (\dtc\ or \ztc).
-\function{trtrs()} is similar to \function{blas.trsm()}, except
-that it raises an \code{ArithmeticError} if a diagonal element of 
-\var{A} is zero (whereas \function{blas.trsm()} returns \code{inf}
-values).
-\end{funcdesc}
-
-\begin{funcdesc}{trtri}{A\optional{, uplo='L'\optional{, diag='N'}}}
-Computes the inverse of a real or complex triangular matrix \tm{A}.  
-On exit, \var{A} contains the inverse.
-\end{funcdesc}
-
-\begin{funcdesc}{tbtrs}{A, B\optional{, uplo='L'\optional{, 
-trans='T'\optional{,diag='N'}}}}
-Solves a triangular set of equations
-\[
- AX=B \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
- A^TX=B \quad (\mathrm{trans} = \mathrm{'T'}), \qquad 
- A^HX=B \quad (\mathrm{trans} = \mathrm{'C'}), 
-\]
-where \tm{A} is real or complex triangular band matrix of order \tm{n}, 
-and \var{B} is a matrix with \tm{n} rows.
-The diagonals of \tm{A} are stored in \var{A} using the BLAS conventions 
-for triangular band matrices. 
-\var{A} and \var{B} are matrices with the same type (\dtc\ or \ztc).
-On exit, \var{B} is replaced by the solution \tm{X}.
-\end{funcdesc}
-
-\section{Least-Squares and Least-Norm Problems}
-\begin{funcdesc}{gels}{A, B\optional{, trans='N'}}
-Solves least-squares and least-norm problems with a full rank 
-\tm{m} by \tm{n} matrix \tm{A}.
-
-\begin{enumerate}
-\item \var{trans} is \code{'N'}.  If \tm{m} is greater than or equal
-to \tm{n}, \function{gels()} solves the least-squares problem
-\[
- \begin{array}{ll} 
- \mbox{minimize} & \|AX-B\|_F.
- \end{array} 
-\]
-If \tm{m} is less than or equal to \tm{n}, \function{gels()} solves 
-the least-norm problem
-\[
- \begin{array}{ll} 
- \mbox{minimize} & \|X\|_F \\
- \mbox{subject to} & AX = B.
- \end{array}
-\]
-
-\item \var{trans} is \code{'T'} or \code{'C'} and \var{A} and \var{B}
-are real.  If \tm{m} is greater than or equal to \tm{n},
-\function{gels()} solves the least-norm problem
-\[
- \begin{array}{ll} 
- \mbox{minimize} & \|X\|_F \\
- \mbox{subject to} & A^TX=B.
- \end{array}
-\]
-If \tm{m} is less than or equal to \tm{n}, \function{gels()} solves 
-the least-squares problem
-\[
- \begin{array}{ll} 
- \mbox{minimize} & \|A^TX-B\|_F.
- \end{array}
-\]
-
-\item \var{trans} is \code{'C'} and \var{A} and \var{B}
-are complex. If \tm{m} is greater than or equal to \tm{n}, 
-\function{gels()} solves the least-norm problem
-\[
- \begin{array}{ll} 
- \mbox{minimize} & \|X\|_F \\
- \mbox{subject to} & A^HX=B.
- \end{array}
-\]
-If \tm{m} is less than or equal to \tm{n}, \function{gels()} solves 
-the least-squares problem
-\[
- \begin{array}{ll} 
- \mbox{minimize} & \|A^HX-B\|_F.
- \end{array}
-\]
-\end{enumerate}
-\var{A} and \var{B} must have the same typecode (\dtc\ or \ztc).
-\var{trans} = \code{'T'} is not allowed if \var{A} is complex.
-On exit, the solution \tm{X} is stored as the leading submatrix 
-of \var{B}.
-The array \var{A} is overwritten with details of the QR or the LQ 
-factorization of \tm{A}.
-Note that \function{gels()} does not check whether \tm{A} is full rank.
-\end{funcdesc}
-
-\begin{funcdesc}{geqrf}{A, tau}
-QR factorization of a real or complex matrix \var{A}:
-\[
-  A = Q R.
-\]
-If \var{A} is \tm{m} by \tm{n}, then \tm{Q} is \tm{m} by \tm{m} 
-and orthogonal/unitary, and \tm{R} is \tm{m} by \tm{n}
-and upper triangular (if \tm{m} is greater than or equal to \tm{n}), 
-or upper trapezoidal (if \tm{m} is less than or equal to \tm{n}).  
-\var{tau}  is a matrix of the same type as {\var A} and of length at 
-least \tm{\min\{m, n\}}.
-On exit, \tm{R} is stored in the upper triangular part of \var{A}.
-The matrix \tm{Q} is stored as a product of \tm{\min\{m, n\}}
-elementary reflectors in the first \tm{\min\{m,n\}} columns 
-of \var{A} and in \var{tau}.
-\end{funcdesc}
-
-\begin{funcdesc}{ormqr}{A, tau, C\optional{, side='L'\optional{, 
-trans='N'}}}
-Product with a real orthogonal matrix:
-\[
- C := \op(Q)C \quad (\mathrm{side} = \mathrm{'L'}), \qquad 
- C := C\op(Q) \quad (\mathrm{side} = \mathrm{'R'}), \qquad 
- \op(Q) =  \left\{ \begin{array}{ll}
- Q & \mathrm{trans} = \mathrm{'N'} \\
- Q^T & \mathrm{trans} = \mathrm{'T'},
-\end{array}\right.
-\]
-where \tm{Q} is square and orthogonal.  
-\tm{Q} is stored in \var{A} and \var{tau} as a product 
-of min\{\var{A}.\member{size}[0], \var{A}.\member{size}[1]\} 
-elementary reflectors, as computed by \function{geqrf()}.
-\end{funcdesc}
-
-\begin{funcdesc}{unmqr}{A, tau, C\optional{, side='L'\optional{, 
-trans='N'}}}
-Product with a real orthogonal or complex unitary matrix:
-\[
- C := \op(Q)C \quad (\mathrm{side} = \mathrm{'L'}), \qquad 
- C := C\op(Q) \quad (\mathrm{side} = \mathrm{'R'}), \qquad 
- \op(Q) =  \left\{ \begin{array}{ll}
- Q & \mathrm{trans} = \mathrm{'N'} \\
- Q^T & \mathrm{trans} = \mathrm{'T'} \\
- Q^H & \mathrm{trans} = \mathrm{'C'},
-\end{array}\right.
-\]
-\tm{Q} is square and orthogonal or unitary.  
-\tm{Q} is stored in \var{A} and \var{tau} as a product of 
-min\{\var{A}.\member{size}[0], \var{A}.\member{size}[1]\} 
-elementary reflectors, as computed by \function{geqrf()}.
-The arrays \var{A}, \var{tau} and \var{C} must have the same type.
-\code{\var{trans} = 'T'} is only allowed if the typecode is \dtc.
-\end{funcdesc}
-
-
-In the following example, we solve a least-squares problem 
-by a direct call to \function{gels()}, and by separate calls to 
-\function{geqrf()}, \function{ormqr()}, and \function{trtrs()}.
-\begin{verbatim}
->>> from cvxopt import random, blas, lapack, matrix
->>> m, n = 10, 5
->>> A, b = random.normal(m,n), random.normal(m,1)
->>> x1 = +b
->>> lapack.gels(+A, x1)                  # x1[:n] minimizes ||A*x1[:n] - b||_2
->>> tau = matrix(0.0, (n,1)) 
->>> lapack.geqrf(A, tau)                 # A = [Q1, Q2] * [R1; 0]
->>> x2 = +b
->>> lapack.ormqr(A, tau, x2, trans='T')  # x2 := [Q1, Q2]' * b
->>> lapack.trtrs(A[:n,:], x2, uplo='U')  # x2[:n] := R1^{-1}*x2[:n]
->>> blas.nrm2(x1[:n] - x2[:n])
-3.0050798580569307e-16
-\end{verbatim}
-
-
-\section{Symmetric and Hermitian Eigenvalue Decomposition}
-The first four routines compute all or selected  eigenvalues and 
-eigenvectors of a real symmetric matrix \tm{A}:
-\[
- A = V\diag(\lambda)V^T,\qquad  V^TV = I.
-\]
-
-\begin{funcdesc}{syev}{A, W\optional{, jobz='N'\optional{, uplo='L'}}}
-Eigenvalue decomposition of a real symmetric matrix of order \tm{n}.
-\var{W} is a real matrix of length at least \tm{n}.
-On exit, \var{W} contains the eigenvalues in ascending order.
-If \var{jobz} is \code{'V'}, the eigenvectors are also computed
-and returned in \var{A}.
-If \var{jobz} is \code{'N'}, the eigenvectors are not returned and the 
-contents of \var{A} are destroyed.
-Raises an \code{ArithmeticError} if the eigenvalue decomposition fails.
-\end{funcdesc}
-
-\begin{funcdesc}{syevd}{A, W\optional{, jobz='N'\optional{, uplo='L'}}}
-This is an alternative to \function{syev()}, based on a different
-algorithm.  It is faster on large problems, but also uses more memory.
-\end{funcdesc}
-
-\begin{funcdesc}{syevx}{A, W\optional{, jobz='N'\optional{, 
-range='A'\optional{, uplo='L'\optional{, vl=0.0, vu=0.0\optional{, 
-il=1, iu=1\optional{, Z=\None}}}}}}}
-Computes selected eigenvalues and eigenvectors of a real symmetric 
-matrix \var{A} of order \tm{n}.
-
-\var{W} is a real matrix of length at least \tm{n}.
-On exit, \var{W} contains the eigenvalues in ascending order.
-If \var{range} is \code{'A'}, all the eigenvalues are computed.
-If \var{range} is \code{'I'}, eigenvalues \tm{\s{i}{l}} through 
-\tm{\s{i}{u}}
-are computed, where $1 \leq i_l \leq i_u \leq n$. 
-If \var{range} is \code{'V'}, the eigenvalues in the interval 
-\tm{(\s{v}{l},\s{v}{u}]} are computed. 
-
-If \var{jobz} is \code{'V'}, the (normalized) eigenvectors are 
-computed, and returned in \var{Z}.  If \var{jobz} is \code{'N'}, the 
-eigenvectors are not computed.  In both cases, the contents of \var{A} 
-are destroyed on exit.
-\var{Z} is optional (and not referenced) if \var{jobz} is \code{'N'}.
-It is required if \var{jobz} is \code{'V'} and must have at least
-\tm{n} columns if \var{range} is \code{'A'} or \code{'V'} and  at
-least \tm{\s{i}{u}-\s{i}{l}+1} columns if \var{range} is \code{'I'}.
-
-\function{syevx()} returns the number of computed eigenvalues.
-\end{funcdesc}
-
-\begin{funcdesc}{syevr}{A, W\optional{, jobz='N'\optional{, 
-range='A'\optional{, uplo='L'\optional{, vl=0.0, vu=0.0\optional{, 
-il=1, iu=n\optional{, Z=\None}}}}}}}
-This is an alternative to \function{syevx()}. 
-\function{syevr()} is the most recent LAPACK routine for symmetric 
-eigenvalue problems, and expected to supersede the three other 
-routines in future releases.
-\end{funcdesc}
-
-The next four routines can be used to compute eigenvalues and 
-eigenvectors for complex Hermitian matrices:
-\[
- A = V\diag(\lambda)V^H,\qquad  V^HV = I.
-\]
-For real symmetric matrices they are identical to the corresponding
-\function{syev\_()} routines.
-
-\begin{funcdesc}{heev}{A, W\optional{, jobz='N'\optional{, uplo='L'}}}
-Eigenvalue decomposition of a real symmetric or complex Hermitian
-matrix of order \tm{n}.
-The calling sequence is identical to \function{syev()}, except that 
-\var{A} can be real or complex.
-\end{funcdesc}
-
-\begin{funcdesc}{heevd}{A, W\optional{, jobz='N'\optional{, uplo='L'}}}
-This is an alternative to \function{heev()}. 
-\end{funcdesc}
-
-\begin{funcdesc}{heevx}{A, W\optional{, jobz='N'\optional{, 
-range='A'\optional{, uplo='L'\optional{, vl=0.0, vu=0.0 \optional{, 
-il=1, iu=n\optional{, Z=\None}}}}}}}
-Computes selected eigenvalues and eigenvectors of a real symmetric 
-or complex Hermitian matrix of order \tm{n}.
-The calling sequence is identical to \function{syevx()},
-except that \var{A} can be real or complex.
-\var{Z} must have the same type as \var{A}.
-\end{funcdesc}
-
-\begin{funcdesc}{heevr}{A, W\optional{, jobz='N'\optional{, 
-range='A'\optional{, uplo='L'\optional{, vl=0.0, vu=0.0\optional{, 
-il=1, iu=n\optional{, Z=\None}}}}}}}
-This is an alternative to \function{heevx()}. 
-\end{funcdesc}
-
-\section{Generalized Symmetric Definite Eigenproblems}
-Three types of generalized eigenvalue problems can be solved:
-\BEQ \label{e-gevd}
- AZ = BZ\diag(\lambda)\quad \mbox{(type 1)}, \qquad 
- ABZ = Z\diag(\lambda) \quad \mbox{(type 2)}, \qquad 
- BAZ = Z\diag(\lambda) \quad \mbox{(type 3)}, 
-\EEQ
-with \tm{A} and \tm{B} real symmetric or complex Hermitian, and \tm{B} positive 
-definite.
-The matrix of eigenvectors is normalized as follows:
-\[
- Z^H BZ = I \quad \mbox{(types 1 and 2)}, \qquad 
- Z^H B^{-1}Z = I \quad \mbox{(type 3)}.
-\]
-
-\begin{funcdesc}{sygv}{A, B, W\optional{, itype=1\optional{, 
-jobz='N'\optional{, uplo='L'}}}}
-Solves the generalized eigenproblem~(\ref{e-gevd}) for real symmetric 
-matrices of order \tm{n}, stored in real matrices \var{A} and \var{B}.
-\var{itype} is an integer with possible values 1, 2, 3, and specifies
-the type of eigenproblem.
-\var{W} is a real matrix of length at least \tm{n}.
-On exit, it contains the eigenvalues in ascending order.
-On exit, \var{B} contains the Cholesky factor of \tm{B}.
-If \var{jobz} is \code{'V'}, the eigenvectors are computed
-and returned in \var{A}.
-If \var{jobz} is \code{'N'}, the eigenvectors are not returned and the 
-contents of \var{A} are destroyed.
-\end{funcdesc}
-
-\begin{funcdesc}{hegv}{A, B, W\optional{, itype=1\optional{, 
-jobz='N'\optional{, uplo='L'}}}}
-Generalized eigenvalue problem~(\ref{e-gevd}) of real symmetric or 
-complex Hermitian matrix of order \tm{n}.
-The calling sequence is identical to \function{sygv()},
-except that \var{A} and \var{B} can be real or complex.
-\end{funcdesc}
-
-
-\section{Singular Value Decomposition}
-
-\begin{funcdesc}{gesvd}{A, S\optional{, jobu='N'\optional{, 
-jobvt='N'\optional{, U=\None\optional{, Vt=\None}}}}}
-Singular value decomposition 
-\[
- A = U \Sigma V^T, \qquad A = U \Sigma V^H
-\]
-of a real or complex \tm{m} by \tm{n} matrix \var{A}.
-
-\var{S} is a real matrix of length at least \tm{\min\{m, n\}}.
-On exit, its first  \tm{\min\{m, n\}} elements are the 
-singular values in descending order.
-
-The argument \var{jobu} controls how many left singular vectors are
-computed.  The possible values are \code{'N'}, \code{'A'}, \code{'S'} 
-and \code{'O'}. 
-If \var{jobu} is \code{'N'}, no left singular vectors are 
-computed.
-If \var{jobu} is \code{'A'}, all left singular vectors are computed 
-and returned as columns of \var{U}.
-If \var{jobu} is \code{'S'}, the first \tm{\min\{m, n\}} left 
-singular vectors are computed and returned as columns of \var{U}.
-If \var{jobu} is \code{'O'}, the first \tm{\min\{m, n\}} left 
-singular vectors are computed and returned as columns of \var{A}.
-The argument \var{U} is \None\ (if \var{jobu} is \code{'N'}
-or \code{'A'}) or a matrix of the same type as \var{A}.
-
-The argument \var{jobvt} controls how many right singular vectors are
-computed.  The possible values are \code{'N'}, \code{'A'}, \code{'S'} 
-and \code{'O'}. 
-If \var{jobvt} is \code{'N'}, no right singular vectors are 
-computed.  If \var{jobvt} is \code{'A'}, all right singular vectors 
-are computed and returned as rows of \var{Vt}.
-If \var{jobvt} is \code{'S'}, the first \tm{\min\{m, n\}} right 
-singular vectors are computed and their (conjugate) transposes are
-returned as rows of \var{Vt}.
-If \var{jobvt} is \code{'O'}, the first \tm{\min\{m, n\}} right 
-singular vectors are computed and their (conjugate) transposes 
-are returned as rows of \var{A}.
-Note that the (conjugate) transposes of the right singular vectors 
-(\ie, the matrix $V^H$) are returned in \var{Vt} or \var{A}.
-The argument \var{Vt} can be \None\ (if \var{jobvt} is \code{'N'}
-or \code{'A'}) or a matrix of the same type as \var{A}.
-
-On exit, the contents of \var{A} are destroyed.
-\end{funcdesc}
-
-\begin{funcdesc}{gesdd}{A, S\optional{, jobz='N'\optional{, 
-U=\None\optional{, Vt=\None}}}} 
-Singular value decomposition of a real or complex \tm{m} by \tm{n} 
-matrix \var{A}.  This function is based on a divide-and-conquer 
-algorithm and is faster than \function{gesvd()}.
-
-\var{S} is a real matrix of length at least \tm{\min\{m, n\}}.
-On exit, its first \tm{\min\{m, n\}} elements are the 
-singular values in descending order.
-
-The argument \var{jobz} controls how many singular vectors are
-computed.  The possible values are \code{'N'}, \code{'A'}, \code{'S'} 
-and \code{'O'}. 
-If \var{jobz} is \code{'N'}, no singular vectors are computed.
-If \var{jobz} is \code{'A'}, all \tm{m} left singular vectors are 
-computed and returned as columns of \var{U} and all \tm{n} right 
-singular vectors are computed and returned as rows of \var{Vt}.
-If \var{jobz} is \code{'S'}, the first \tm{\min\{m, n\}} left 
-and right singular vectors are computed and returned as columns of 
-\var{U} and rows of \var{Vt}.
-If \var{jobz} is \code{'O'} and \tm{m} is greater than or equal
-to \tm{n}, the first \tm{n} left singular vectors are returned as
-columns of \var{A} and the \tm{n} right singular vectors are returned
-as rows of \var{Vt}.  If \var{jobz} is \code{'O'} and \tm{m} is less 
-than \tm{n}, the \tm{m} left singular vectors are returned as columns
-of \var{U} and the first \tm{m} right singular vectors are returned 
-as rows of \var{A}.  
-Note that the (conjugate) transposes of the right singular vectors 
-are returned in \var{Vt} or \var{A}.
-
-The argument \var{U} can be \None\ (if \var{jobz} is \code{'N'}
-or \code{'A'} of \var{jobz} is \code{'O'} and \tm{m} is greater than
-or equal to  \tm{n})  or a matrix of the same type as \var{A}.
-The argument \var{Vt} can be \None\ (if \var{jobz} is \code{'N'}
-or \code{'A'} or \var{jobz} is \code{'O'} and \tm{m} is less than
-\tm{n}) or a matrix of the same type as \var{A}.
-
-On exit, the contents of \var{A} are destroyed.
-\end{funcdesc}
-
-\section{Schur and Generalized Schur Factorization}
-\begin{funcdesc}{gees}{A\optional{, w=\None\optional{, 
-V=\None\optional{, select=\None}}}}
-Computes the Schur factorization 
-\[
- A = V S V^T \quad \mbox{($A$ real)}, \qquad 
- A = V S V^H \quad \mbox{($A$ complex)}
-\]
-of a real or complex \tm{n} by \tm{n} matrix \tm{A}.  
-If \tm{A} is real, the matrix of Schur vectors \tm{V} is orthogonal, 
-and \tm{S} is a real upper quasi-triangular matrix with 1 by 1 or 2 by 2 
-diagonal blocks.  The 2 by 2 blocks correspond to complex conjugate pairs
-of eigenvalues of \tm{A}.
-If \tm{A} is complex, the matrix of Schur vectors \tm{V} is unitary, 
-and \tm{S} is a complex upper triangular matrix with the eigenvalues of
-\tm{A} on the diagonal.
-
-The optional argument \var{w} is a complex matrix of length at least 
-\tm{n}.  If it is provided, the eigenvalues of \var{A} are returned in 
-\var{w}.
-The optional argument \var{V} is an \tm{n} by \tm{n} matrix of the same
-type as \var{A}.  If it is provided, then the Schur vectors are returned
-in \var{V}.
-
-The argument \var{select} is an optional ordering routine.
-It must be a Python function that can be called as \samp{f(s)} with
-a complex argument \var{s}, and returns \True\ or \False.
-The eigenvalues for which \var{select} returns \True\ will be 
-selected to appear first along the diagonal.
-(In the real Schur factorization, if either one of a complex conjugate
-pair of eigenvalues is selected, then both are selected.)
-
-On exit, \var{A} is replaced with the matrix \tm{S}.
-The function \function{gees()} returns an integer equal to the number 
-of eigenvalues that were selected by the ordering routine.
-If \var{select} is \None, then \function{gees()} returns 0.
-\end{funcdesc}
-
-As an example we compute the complex Schur form of the matrix
-\[
- A = \left[\begin{array}{rrrrr}
-   -7 &  -11 & -6  & -4 &  11 \\
-    5 &  -3  &  3  & -12 & 0 \\
-   11 &  11  & -5  & -14 & 9 \\
-   -4 &   8  &  0  &  8 &  6 \\
-   13 & -19  & -12 & -8 & 10 
- \end{array}\right].
-\] 
-\begin{verbatim}
->>> A = matrix([[-7., 5., 11., -4., 13.], [-11., -3., 11., 8., -19.], [-6., 3., -5., 0., -12.], [-4., -12., -14., 8., -8.], [11., 0., 9., 6., 10.]])
->>> S = matrix(A, tc='z')
->>> w = matrix(0.0, (5,1), 'z')
->>> gees(S, w)
-0
->>> print S
-[ 5.67e+00+j1.69e+01 -2.13e+01+j2.85e+00  1.40e+00+j5.88e+00 -4.19e+00+j2.05e-01  3.19e+00-j1.01e+01]
-[ 0.00e+00-j0.00e+00  5.67e+00-j1.69e+01  1.09e+01+j5.93e-01 -3.29e+00-j1.26e+00 -1.26e+01+j7.80e+00]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  1.27e+01+j3.43e-17 -6.83e+00+j2.18e+00  5.31e+00-j1.69e+00]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00 -1.31e+01-j0.00e+00 -2.60e-01-j0.00e+00]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00 -7.86e+00-j0.00e+00]
->>> print w
-[ 5.67e+00+j1.69e+01]
-[ 5.67e+00-j1.69e+01]
-[ 1.27e+01+j3.43e-17]
-[-1.31e+01-j0.00e+00]
-[-7.86e+00-j0.00e+00]
-\end{verbatim}
-An ordered Schur factorization with the eigenvalues in the left
-half of the complex plane ordered first, can be computed as follows. 
-\begin{verbatim}
->>> S = matrix(A, tc='z')
->>> def F(x): return (x.real < 0.0)
-...
->>> gees(S, w, select = F)
-2
->>> print S
-[-1.31e+01-j0.00e+00 -1.72e-01+j7.93e-02 -2.81e+00+j1.46e+00  3.79e+00-j2.67e-01  5.14e+00-j4.84e+00]
-[ 0.00e+00-j0.00e+00 -7.86e+00-j0.00e+00 -1.43e+01+j8.31e+00  5.17e+00+j8.79e+00  2.35e+00-j7.86e-01]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  5.67e+00+j1.69e+01 -1.71e+01-j1.41e+01  1.83e+00-j4.63e+00]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  5.67e+00-j1.69e+01 -8.75e+00+j2.88e+00]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  1.27e+01+j3.43e-17]
->>> print w
-[-1.31e+01-j0.00e+00]
-[-7.86e+00-j0.00e+00]
-[ 5.67e+00+j1.69e+01]
-[ 5.67e+00-j1.69e+01]
-[ 1.27e+01+j3.43e-17]
-\end{verbatim}
-
-
-\begin{funcdesc}{gges}{A, B\optional{, a=\None, b=\None\optional{, 
-Vl=\None\optional{, Vr=\None\optional{, select=\None}}}}}
-Computes the generalized Schur factorization 
-\[
- A = V_l S V_r^T, \quad B = V_l T V_r^T \quad \mbox{($A$ and $B$ real)}, 
- \qquad 
- A = V_l S V_r^H, \quad B = V_l T V_r^H, \quad \mbox{($A$ and $B$ complex)}
-\]
-of a pair of real or complex \tm{n} by \tm{n} matrices \tm{A}, \tm{B}.  
-If \tm{A} and \tm{B} are real, then the matrices of left and right Schur 
-vectors \tm{\s{V}{l}} and \tm{\s{V}{r}} are orthogonal, 
-\tm{S} is a real upper quasi-triangular matrix with 1 by 1 or 2 by 2 
-diagonal blocks, and \tm{T} is a real triangular matrix with nonnegative
-diagonal.  The 2 by 2 blocks along the diagonal of \tm{S} correspond to 
-complex conjugate pairs of generalized eigenvalues of \tm{A}, \tm{B}.
-If \tm{A} and \tm{B} are complex, the matrices of left and right Schur 
-vectors \tm{\s{V}{l}} and \tm{\s{V}{r}} are unitary, \tm{S} is complex 
-upper triangular, and \tm{T} is complex upper triangular with 
-nonnegative real diagonal.  
-
-The optional arguments \var{a} and \var{b} are \ztc\ and \dtc\ matrices 
-of length at least \tm{n}.  If these are provided, the generalized
-eigenvalues of \var{A}, \var{B} are returned in \var{a} and \var{b}.
-(The generalized eigenvalues are the ratios \var{a[k] / b[k]}.) 
-The optional arguments \var{Vl} and \var{Vr} are \tm{n} by \tm{n} matrices
-of the same type as \var{A} and \var{B}.  If they are provided, then the 
-left Schur vectors are returned in \var{Vl} and the right Schur vectors
-are returned in \var{Vr}.
-
-The argument \var{select} is an optional ordering routine.
-It must be a Python function that can be called as \samp{f(x,y)} with
-a complex argument \var{x} and a real argument \var{y}, and returns 
-\True\ or \False.
-The eigenvalues for which \var{select} returns \True\ will be 
-selected to appear first on the diagonal.
-(In the real Schur factorization, if either one of a complex conjugate
-pair of eigenvalues is selected, then both are selected.)
-
-On exit, \var{A} is replaced with the matrix \tm{S} and 
-\var{B} is replaced with the matrix \tm{T}.
-The function \function{gges()} returns an integer equal to the number 
-of eigenvalues that were selected by the ordering routine.
-If \var{select} is \None, then \function{gges()} returns 0.
-\end{funcdesc}
-
-As an example, we compute the generalized complex Schur form of the
-matrix \tm{A} of the previous example, and 
-\[
- B = \left[\begin{array}{ccccc}
-  1 & 0 & 0 & 0 & 0 \\
-  0 & 1 & 0 & 0 & 0 \\
-  0 & 0 & 1 & 0 & 0 \\
-  0 & 0 & 0 & 1 & 0 \\
-  0 & 0 & 0 & 0 & 0 \end{array}\right].
-\]
-\begin{verbatim}
->>> A = matrix([[-7., 5., 11., -4., 13.], [-11., -3., 11., 8., -19.], [-6., 3., -5., 0., -12.], [-4., -12., -14., 8., -8.], [11., 0., 9., 6., 10.]])
->>> B = matrix(0.0, (5,5))
->>> B[:19:6] = 1.0
->>> S = matrix(A, tc='z')
->>> T = matrix(B, tc='z')
->>> a = matrix(0.0, (5,1), 'z')
->>> b = matrix(0.0, (5,1))
->>> gges(S, T, a, b)
-0
->>> print S
-[ 6.64e+00-j8.87e+00 -7.81e+00-j7.53e+00  6.16e+00-j8.51e-01  1.18e+00+j9.17e+00  5.88e+00-j4.51e+00]
-[ 0.00e+00-j0.00e+00  8.48e+00+j1.13e+01 -2.12e-01+j1.00e+01  5.68e+00+j2.40e+00 -2.47e+00+j9.38e+00]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00 -1.39e+01-j0.00e+00  6.78e+00-j0.00e+00  1.09e+01-j0.00e+00]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00 -6.62e+00-j0.00e+00 -2.28e-01-j0.00e+00]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00 -2.89e+01-j0.00e+00]
->>> print T
-[ 6.46e-01-j0.00e+00  4.29e-01-j4.79e-02  2.02e-01-j3.71e-01  1.08e-01-j1.98e-01 -1.95e-01+j3.58e-01]
-[ 0.00e+00-j0.00e+00  8.25e-01-j0.00e+00 -2.17e-01+j3.11e-01 -1.16e-01+j1.67e-01  2.10e-01-j3.01e-01]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  7.41e-01-j0.00e+00 -3.25e-01-j0.00e+00  5.87e-01-j0.00e+00]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  8.75e-01-j0.00e+00  4.84e-01-j0.00e+00]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00]
->>> print a
-[ 6.64e+00-j8.87e+00]
-[ 8.48e+00+j1.13e+01]
-[-1.39e+01-j0.00e+00]
-[-6.62e+00-j0.00e+00]
-[-2.89e+01-j0.00e+00]
->>> print b
-[ 6.46e-01]
-[ 8.25e-01]
-[ 7.41e-01]
-[ 8.75e-01]
-[ 0.00e+00]
-\end{verbatim}
-
-
-\section{Example: Analytic Centering}
-The analytic centering problem is defined as
-\[
- \begin{array}{ll}
-  \mbox{minimize} & -\sum_{i=1}^m \log(b_i-a_i^Tx).
- \end{array}
-\]
-In the code below we solve the problem using Newton's method.
-At each iteration the Newton direction is computed by solving 
-a positive definite set of linear equations
-\[
- A^T \diag(b-Ax)^{-2} A v = -\diag(b-Ax)^{-1}\ones
-\]
-(where \tm{A} has rows $a_i^T$), and a suitable step size is determined 
-by a backtracking line search.
-
-We use the level-3 BLAS function \function{syrk()} to form the Hessian 
-matrix and the LAPACK function \function{posv()} to solving the Newton
-system.   The code can be further optimized by replacing the 
-matrix-vector products with the level-2 BLAS function \function{gemv()}.
-
-\begin{verbatim}
-from cvxopt import matrix, log, mul, div, blas, lapack, random
-from math import sqrt
-
-def acent(A,b):
-    """  
-    Returns the analytic center of A*x <= b.
-    We assume that b > 0 and the feasible set is bounded.
-    """
-
-    MAXITERS = 100
-    ALPHA = 0.01
-    BETA = 0.5
-    TOL = 1e-8
-
-    m, n = A.size
-    x = matrix(0.0, (n,1))
-    H = matrix(0.0, (n,n))
-
-    for iter in xrange(MAXITERS):
-        
-        # Gradient is g = A^T * (1./(b-A*x)).
-        d = (b - A*x)**-1
-        g = A.T * d
-
-        # Hessian is H = A^T * diag(d)^2 * A.
-        Asc = mul( d[:,n*[0]], A )
-        blas.syrk(Asc, H, trans='T')
-
-        # Newton step is v = -H^-1 * g.
-        v = -g
-        lapack.posv(H, v)
-
-        # Terminate if Newton decrement is less than TOL.
-        lam = blas.dot(g, v)
-        if sqrt(-lam) < TOL: return x
-
-        # Backtracking line search.
-        y = mul(A*v, d)
-        step = 1.0
-        while 1-step*max(y) < 0: step *= BETA 
-        while True:
-            if -sum(log(1-step*y)) < ALPHA*step*lam: break
-            step *= BETA
-        x += step*v
-\end{verbatim}
diff --git a/doc/matrices.tex b/doc/matrices.tex
deleted file mode 100644
index 471c0ad..0000000
--- a/doc/matrices.tex
+++ /dev/null
@@ -1,1363 +0,0 @@
-\chapter{Dense and Sparse Matrices}\label{chap:matrix}
-
-This chapter describes the two CVXOPT matrix types: 
-\mtrx\ objects, used for dense matrix computations, 
-and \spmtrx\ objects, used for sparse matrix computations.
-
-\section{Dense Matrices}\label{s-creating-matrices}
-A dense matrix is created by calling the function \function{matrix()}. 
-The arguments specify the values of the coefficients, the
-dimensions, and the type (integer, double or complex) of the matrix.
-
-\begin{funcdesc}{matrix}{x\optional{, size\optional{, tc}}}
-\var{size} is a tuple of length two with the matrix dimensions.
-The number of rows and/or the number of columns can be zero.
-
-\var{tc} stands for typecode. The possible values are \itc, \dtc\ and 
-\ztc, for integer, real (double) and complex matrices, respectively.  
-
-\var{x} can be a number, a sequence of numbers, a dense or sparse 
-matrix, a one- or two-dimensional \program{NumPy} array, or a list of
-lists of matrices and numbers.  
-\BIT
-\item If \var{x} is a number (Python \intgr, \flt\ or \cmplx), a matrix
-is created with the dimensions specified by \var{size} and with all the 
-coefficients equal to \var{x}.  
-The default value of \var{size} is \tm{(1,1)}, and the default value
-of \var{tc} is the type of \var{x}.
-If necessary, the type of \var{x} is converted (from integer to double
-when used to create a matrix of type \dtc, and from integer or
-double to complex when used to create a matrix of type \ztc).
-
-\begin{verbatim}
->>> from cvxopt import matrix
->>> A = matrix(1, (1,4))   
->>> print A
-[ 1  1  1  1]
->>> A = matrix(1.0, (1,4))   
->>> print A
-[ 1.00e+00  1.00e+00  1.00e+00  1.00e+00]
->>> A = matrix(1+1j)     
->>> print A
-[ 1.00e+00+j1.00e+00]
-\end{verbatim}
-
-\item If \var{x} is a sequence of numbers (list, tuple, \module{array}
-array, xrange object, one-dimensional \program{NumPy} array, \ldots),
-then the numbers are interpreted as the coefficients of a matrix in 
-column-major order.  The length of \var{x} must be equal to the product 
-of \code{size[0]} and \code{size[1]}.
-If \var{size} is not specified, a matrix with one column is created. 
-If \var{tc} is not specified, it is determined from the elements of 
-\var{x} (and if that is impossible, for example because \var{x} is
-an empty list, a value \itc\ is used).  
-Type conversion takes place as for scalar \var{x}.
-
-The following example shows several ways to define the same integer 
-matrix.
-\begin{verbatim}
->>> A = matrix([0, 1, 2, 3], (2,2))  
->>> A = matrix((0, 1, 2, 3), (2,2))  
->>> A = matrix(xrange(4), (2,2))
->>> from array import array
->>> A = matrix(array('i', [0,1,2,3]), (2,2))
->>> print A
-[ 0  2]
-[ 1  3]
-\end{verbatim}
-
-\item If \var{x} is a dense or sparse matrix, or a two-dimensional 
-\program{NumPy} array of type \itc, 
-\dtc\ or \ztc, then the  coefficients of \var{x} are copied, in 
-column-major order, to a new matrix of the given size.  
-The total number of elements in the new matrix (the product of 
-\code{size[0]} and \code{size[1]}) must be the same as the product of  
-the dimensions of \var{x}.  If \var{size} is not specified, the 
-dimensions of \var{x} are used.  
-The default value of \var{tc} is the type of \var{x}. 
-Type conversion takes place when the type of \var{x} differs from 
-\var{tc}, in a similar way as for scalar \var{x}.  
-
-\begin{verbatim}
->>> A = matrix([1., 2., 3., 4., 5., 6.], (2,3))  
->>> print A
-[ 1.00e+00  3.00e+00  5.00e+00]
-[ 2.00e+00  4.00e+00  6.00e+00]
->>> B = matrix(A, (3,2))  
->>> print B
-[ 1.00e+00  4.00e+00]
-[ 2.00e+00  5.00e+00]
-[ 3.00e+00  6.00e+00]
->>> C = matrix(B, tc='z')      
->>> print C
-[ 1.00e+00-j0.00e+00  4.00e+00-j0.00e+00]
-[ 2.00e+00-j0.00e+00  5.00e+00-j0.00e+00]
-[ 3.00e+00-j0.00e+00  6.00e+00-j0.00e+00]
->>> from numpy import array
->>> x = array([[1., 2., 3.], [4., 5., 6.]])
->>> x
-array([[ 1.  2.  3.]
-       [ 4.  5.  6.]])
->>> print matrix(x)
-[ 1.00e+00  2.00e+00  3.00e+00]
-[ 4.00e+00  5.00e+00  6.00e+00]
-\end{verbatim}
-
-\item If \var{x} is a list of lists of dense or sparse matrices 
-and numbers (Python \intgr, \flt\ or \cmplx), 
-then each element of \var{x} is interpreted as a 
-block-column stored in column-major order. 
-If \var{size} is not specified, the block-columns are juxtaposed
-to obtain a matrix with \code{len(\var{x})} block-columns.
-If \var{size} is specified, then the matrix with \code{len(\var{x})}
-block-columns is resized by copying its elements in column-major order 
-into a matrix of the dimensions given by \var{size}.  
-If \var{tc} is not specified, it is determined from the elements of 
-\var{x} (and if that is impossible, for example because \var{x} is
-a list of empty lists, a value \itc\ is used).  
-The same rules for type conversion apply as for scalar \var{x}.
-
-\begin{verbatim}
->>> print matrix([[1., 2.], [3., 4.], [5., 6.]])
-[ 1.00e+00  3.00e+00  5.00e+00]
-[ 2.00e+00  4.00e+00  6.00e+00]
->>> A1 = matrix([1, 2], (2,1))
->>> B1 = matrix([6, 7, 8, 9, 10, 11], (2,3))
->>> B2 = matrix([12, 13, 14, 15, 16, 17], (2,3))
->>> B3 = matrix([18, 19, 20], (1,3))
->>> C = matrix([[A1, 3.0, 4.0, 5.0], [B1, B2, B3]])
->>> print C
-[ 1.00e+00  6.00e+00  8.00e+00  1.00e+01]
-[ 2.00e+00  7.00e+00  9.00e+00  1.10e+01]
-[ 3.00e+00  1.20e+01  1.40e+01  1.60e+01]
-[ 4.00e+00  1.30e+01  1.50e+01  1.70e+01]
-[ 5.00e+00  1.80e+01  1.90e+01  2.00e+01]
-\end{verbatim}
-
-A matrix with a single block-column can be represented by a single 
-list (\ie, if \var{x} is a list of lists, and has length one, 
-then the argument \code{\var{x}} can be replaced by \code{\var{x}[0]}).
-\begin{verbatim}
->>> D = matrix([B1, B2, B3])
->>> print D
-[  6   8  10]
-[  7   9  11]
-[ 12  14  16]
-[ 13  15  17]
-[ 18  19  20]
-\end{verbatim}
-\EIT
-\end{funcdesc}
-
-\section{Sparse Matrices} \label{s-creating-spmatrix}
-A general \spmtrx\ object can be thought of as a \emph{triplet 
-description} of a sparse matrix, \ie, a list of entries of the matrix, 
-with for each entry the value, row index, and column index.  
-Entries that are not included in the list are assumed to be zero.  
-For example, the sparse matrix
-\BEQ \label{e-sparse-A}
- A = \left[ \begin{array}{rrrrr}
-  0 & 2 & 0 & 0 & 3 \\
-  2 & 0 & 0 & 0 & 0 \\
- -1 & -2 & 0 & 4 & 0 \\
-  0 & 0 & 1 & 0 & 0 \end{array} \right]
-\EEQ
-has the triplet description 
-\[
-  (2,1,0), \qquad (-1,2,0), \qquad (2,0,1), \qquad (-2,2,1), \qquad
-  (1,3,2), \qquad (4,2,3), \qquad (3,0,4).
-\]
-The list may include entries with a zero value, so triplet
-descriptions are not necessarily unique.
-The list
-\[
-  (2,1,0), \qquad (-1,2,0), \qquad (0,3,0), \qquad (2,0,1), \qquad 
- (-2,2,1), \qquad (1,3,2), \qquad (4,2,3), \qquad (3,0,4)
-\]
-is another triplet description of the same matrix.
-
-An \spmtrx\ object corresponds to a particular triplet 
-description of a sparse matrix.  We will refer to the entries in
-the triplet description as the \emph{nonzero entries} of the object, 
-even though they may have a numerical value zero.
-
-Three functions are provided to create sparse matrices. 
-The first, \function{spmatrix()}, constructs a sparse matrix from 
-a triplet description. 
-\begin{funcdesc}{spmatrix}{x, I, J\optional{, size\optional{, tc}}}
-
-\var{I} and \var{J} are sequences of integers (lists, tuples, 
-\module{array} arrays, xrange objects, \ldots) or integer matrices 
-(\mtrx\ objects with typecode \itc), containing the row and column 
-indices of the nonzero entries.  
-The lengths of \var{I} and \var{J} must be  equal.  If they 
-are matrices, they are treated as lists of indices stored in 
-column-major order, \ie, as lists \code{list(\var{I})}, respectively, 
-\code{list(\var{J})}. 
-
-\var{size} is a tuple of nonnegative integers with the row and column 
-dimensions of the matrix.
-The \var{size} argument is only needed when creating a matrix with 
-a zero last row or last column.  If \var{size} is not specified, it 
-is determined from \var{I} and \var{J}:
-the default value for \code{\var{size}[0]} is max(\var{I})+1 
-if \var{I} is nonempty and zero otherwise.  
-The default value for \code{\var{size}[1]} is 
-max(\var{J})+1 if \var{J} is nonempty and zero otherwise.
-
-\var{tc} is the typecode, \dtc\ or \ztc, for double and complex 
-matrices, respectively.   Integer sparse matrices are not implemented.
-
-\var{x} can be a number, a sequence of numbers, or a dense matrix.  
-This argument specifies the numerical values of the nonzero entries.
-\BIT
-\item If \var{x} is a number (Python \intgr, \flt\ or \cmplx), 
-a matrix is created with the sparsity pattern defined by \var{I} and 
-\var{J}, and nonzero entries initialized to the value of \var{x}.  
-The default value of \var{tc} is \dtc\ if \var{x} is \intgr\ or \flt,
-and \ztc\ if \var{x} is \cmplx.  
-
-The following code creates a 4 by 4 sparse identity matrix.
-\begin{verbatim}
->>> from cvxopt import spmatrix
->>> A = spmatrix(1.0, range(4), range(4))
->>> print A  
-[ 1.00e+00     0         0         0    ]
-[    0      1.00e+00     0         0    ]
-[    0         0      1.00e+00     0    ]
-[    0         0         0      1.00e+00]
-\end{verbatim}
-
-\item If \var{x} is a sequence of numbers, a sparse matrix is created 
-with the entries of \var{x} copied to the entries indexed by \var{I} 
-and \var{J}.  The list \var{x} must have the same length as \var{I} and 
-\var{J}.
-The default value of \var{tc} is determined from the elements of 
-\var{x}: 
-\dtc\ if \var{x} contains integers and floating-point numbers or
-if \var{x} is an empty list,
-and \ztc\ if \var{x} contains at least one complex number.
-
-As an example, the matrix~(\ref{e-sparse-A}) can be created as follows.
-\begin{verbatim}
->>> A = spmatrix([2,-1,2,-2,1,4,3], [1,2,0,2,3,2,0], [0,0,1,1,2,3,4])
->>> print A 
-[    0      2.00e+00     0         0      3.00e+00]
-[ 2.00e+00     0         0         0         0    ]
-[-1.00e+00 -2.00e+00     0      4.00e+00     0    ]
-[    0         0      1.00e+00     0         0    ]
-\end{verbatim}
-
-\item If \var{x} is a dense matrix, a sparse matrix is created with 
-all the entries of \var{x} copied, in column-major order, to the 
-entries indexed by \var{I} and \var{J}.
-The matrix \var{x} must have the same length as \var{I} and \var{J}.
-The default value of \var{tc} is \dtc\ if \var{x} is an \itc\ or \dtc\
-matrix, and \ztc\ otherwise.
-\EIT
-
-If \var{I} and \var{J} contain repeated entries, the corresponding 
-values of the coefficients are added.
-\end{funcdesc}
-
-The function \function{sparse()} constructs a sparse matrix from
-a block-matrix description.
-   
-\begin{funcdesc}{sparse}{x\optional{, tc}}
-\var{tc} is the typecode, \dtc\ or \ztc, for double and complex 
-matrices, respectively.
-  
-\var{x} can be a \mtrx, \spmtrx, or a list of lists of matrices 
-(\mtrx\ or \spmtrx\ objects) and numbers (Python \intgr, \flt\ or 
-\cmplx). 
-\BIT
-\item If \var{x} is a \mtrx\ or \spmtrx\ object, then a sparse matrix 
-of the same size and the same numerical value is created. 
-Numerical zeros in \var{x} are treated as structural zeros and removed 
-from the triplet description of the new sparse matrix.
-
-\item If \var{x} is a list of lists of matrices (\mtrx\ or \spmtrx) 
-and numbers (Python \intgr, \flt\ or \cmplx) then each element of 
-\var{x} is interpreted as a (block-)column matrix stored in 
-colum-major order, and a block-matrix is constructed by juxtaposing
-the \code{len(\var{x})} block-columns
-(as in \function{matrix()}, see section~\ref{s-creating-matrices}). 
-Numerical zeros are removed from the triplet description of the new 
-matrix.  
-\EIT
-\begin{verbatim}
->>> from cvxopt import matrix, spmatrix, sparse
->>> A = matrix([[1., 2., 0.], [2., 1., 2.], [0., 2., 1.]])
->>> print A
-[ 1.00e+00  2.00e+00  0.00e+00]
-[ 2.00e+00  1.00e+00  2.00e+00]
-[ 0.00e+00  2.00e+00  1.00e+00]
->>> B = spmatrix([], [], [], (3,3))
->>> print B
-[0 0 0]
-[0 0 0]
-[0 0 0]
->>> C = spmatrix([3, 4, 5], [0, 1, 2], [0, 1, 2])
->>> print C
-[ 3.00e+00     0         0    ]
-[    0      4.00e+00     0    ]
-[    0         0      5.00e+00]
->>> D = sparse([[A, B], [B, C]])
->>> print D
-[ 1.00e+00  2.00e+00     0         0         0         0    ]
-[ 2.00e+00  1.00e+00  2.00e+00     0         0         0    ]
-[    0      2.00e+00  1.00e+00     0         0         0    ]
-[    0         0         0      3.00e+00     0         0    ]
-[    0         0         0         0      4.00e+00     0    ]
-[    0         0         0         0         0      5.00e+00]
-\end{verbatim}
-A matrix with a single block-column can be represented by a single list.
-\begin{verbatim}
->>> D = sparse([A, C])
->>> print D
-[ 1.00e+00  2.00e+00     0    ]
-[ 2.00e+00  1.00e+00  2.00e+00]
-[    0      2.00e+00  1.00e+00]
-[ 3.00e+00     0         0    ]
-[    0      4.00e+00     0    ]
-[    0         0      5.00e+00]
-\end{verbatim}
-\end{funcdesc}
-
-The function \function{spdiag()} constructs a block-diagonal
-sparse matrix from a list of matrices.
-\begin{funcdesc}{spdiag}{x}
-\var{x} is a dense or sparse matrix with a single row or column, or a 
-list of square dense or sparse matrices or scalars.  
-If \var{x} is matrix, a sparse diagonal matrix is returned with 
-the entries of \var{x} on its diagonal.
-If \var{x} is list, a sparse block-diagonal matrix is returned with
-the elements in the list as its diagonal blocks.
-  
-\begin{verbatim}
->>> from cvxopt import matrix, spmatrix, spdiag
->>> A = 3.0
->>> B = matrix([[1,-2],[-2,1]])
->>> C = spmatrix([1,1,1,1,1],[0,1,2,0,0,],[0,0,0,1,2])
->>> D = spdiag([A, B, C])
->>> print D
-[ 3.00e+00     0         0         0         0         0    ]
-[    0      1.00e+00 -2.00e+00     0         0         0    ]
-[    0     -2.00e+00  1.00e+00     0         0         0    ]
-[    0         0         0      1.00e+00  1.00e+00  1.00e+00]
-[    0         0         0      1.00e+00     0         0    ]
-[    0         0         0      1.00e+00     0         0    ]
-\end{verbatim}
-\end{funcdesc}
-
-
-\section{Arithmetic Operations} 
-\label{s-arithmetic} \label{s-spmatrix-arith}
-The following table lists the arithmetic operations defined for 
-dense and sparse matrices.  
-In the table \var{A} and \var{B} are dense or sparse matrices 
-of compatible dimensions, 
-\var{c} is a scalar (a Python number or a dense 1 by 1 matrix), 
-\var{D} is a dense matrix, and \var{e} is a Python number.
-
-\begin{center}
-\begin{tabular}{l|l}
-\hline
-Unary plus/minus & \code{+\var{A}}, \code{-\var{A}} \\ \hline 
-Addition & \code{\var{A} + \var{B}}, \code{\var{A} + \var{c}}, 
-    \code{\var{c} + \var{A}}\\ \hline 
-Subtraction & \code{\var{A} - \var{B}}, \code{\var{A} - \var{c}}, 
-    \code{\var{c} - \var{A}}\\ \hline 
-Matrix multiplication & \code{{\var{A} * \var{B}}} \\ \hline
-Scalar multiplication and division & \code{\var{c} * \var{A}}, 
-    \code{\var{A} * \var{c}}, \code{\var{A} / \var{c}} \\ \hline 
-Remainder after division & \code{\var{D} \% \var{c}} \\ \hline 
-Elementwise exponentiation  & \code{\var{D}**\var{e}} \\ \hline 
-\end{tabular}
-\end{center}
-
-If one of the operands is integer (a scalar \intgr\ or a matrix of 
-type \itc) and the other operand is double (a scalar \flt\ or a matrix 
-of type \dtc), then the integer operand is converted to double, and the 
-result is a matrix of type \dtc.
-If one of the operands is integer or double, and the other operand is 
-complex (a scalar \cmplx\ or a matrix of type \ztc), 
-then the first operand is converted to complex, and the result is 
-a matrix of type \ztc.  
-(An exception to this rule is elementwise exponentiation:
-the result of \code{\var{D}**\var{e}} is a real matrix if \var{D} 
-and \var{e} are integer.)
-
-Addition, subtraction, and matrix multiplication with two matrix operands 
-result in a sparse matrix if both matrices are sparse, and in a dense 
-matrix otherwise.
-The result of a scalar multiplication or division is dense 
-if \var{A} is dense, and sparse if \var{A} is sparse.
-Postmultiplying a matrix with a number \var{c} means the same as 
-premultiplying, \ie, scalar multiplication.  Dividing a matrix by 
-\var{c} means dividing all entries by \var{c}.  
-
-If \var{c} in the expressions \code{\var{A} + \var{c}}, 
-\code{\var{c} + \var{A}}, \code{\var{A} - \var{c}}, 
-\code{\var{c} - \var{A}} is a number, then it is interpreted as a 
-dense matrix with the same dimensions as \var{A}, type given by the type 
-of \var{c}, and all entries equal to \var{c}.
-If \var{c}  is a 1 by 1 dense matrix and \var{A} is not 1 by 1, 
-then \var{c} is interpreted as a dense matrix with the same size of 
-\var{A} and all entries equal to \code{\var{c}[0]}.
-
-If \var{c} is a 1 by 1 dense matrix, then, if possible, the products 
-\code{\var{c} * \var{A}} and \code{\var{A} * \var{c}} are interpreted as 
-matrix-matrix products.
-If the product cannot be interpreted as a matrix-matrix product
-(because the dimensions of \var{A} are incompatible), then the product is 
-interpreted as the scalar multiplication with \code{\var{c}[0]}.
-The division \code{\var{A}/\var{c}} and remainder 
-\code{\var{A} \% \var{c}} with \var{c} a 1 by 1 matrix are always 
-interpreted as \code{\var{A} / \var{c}[0]}, resp.,
-\code{\var{A} \% \var{c}[0]}.
-
-Note that Python rounds the result of an integer division towards minus 
-infinity.
-
-The following in-place operations are also defined, but only if 
-they do not change the type (sparse or dense, integer, real, or complex) of the 
-matrix \var{A}.  
-These in-place operations do not return a new matrix but modify the 
-existing object \var{A}.
-\begin{center}\begin{tabular}{l|l} \hline
- In-place addition & 
-    \code{\var{A} += \var{B}}, \code{\var{A} += \var{c}} \\ \hline
- In-place subtraction & 
-    \code{\var{A} -= \var{B}}, \code{\var{A} -= \var{c}} \\ \hline   
- In-place scalar multiplication and division & 
-    \code{\var{A} *= \var{c}}, \code{\var{A} /= \var{c}} \\ \hline
- In-place remainder & \code{\var{A} \%= \var{c}} \\ \hline
-\end{tabular}\end{center}
-For example, if \var{A} has typecode \itc, then \code{\var{A} += \var{B}} 
-is allowed if \var{B} has typecode \itc.
-It is not allowed if \var{B} has typecode \dtc\ or \ztc\ because the 
-addition \code{\var{A} + \var{B}} results in a \dtc\ or \ztc\ matrix of 
-and therefore cannot be assigned to \var{A} without changing its type.
-As another example, if \var{A} is a sparse matrix, then
-\samp{\var{A} += 1.0} is not allowed because the 
-operation \samp{\var{A} = \var{A} + 1.0} results in a dense matrix, 
-so it cannot be assigned to \var{A} without changing its type.
-
-In-place matrix-matrix products are not allowed.  (Except when \var{c} is 
-a 1 by 1 dense matrix, in which case \code{\var{A} *= \var{c}} is 
-interpreted as the scalar product \code{\var{A} *= \var{c}[0]}.)
-
-In-place remainder is only defined for dense \var{A}.
-
-It is important to know when a matrix operation creates
-a new object.  The following rules apply.
-\begin{itemize}
-\item A simple assignment (\samp{A = B}) is given the standard 
-Python interpretation, \ie, it assigns to the variable \var{A} a 
-reference (or pointer) to the object referenced by \var{B}.
-\begin{verbatim}
->>> B = matrix([[1.,2.], [3.,4.]])  
->>> print B
-[ 1.00e+00  3.00e+00]
-[ 2.00e+00  4.00e+00]
->>> A = B
->>> A[0,0] = -1 
->>> print B   # modifying A[0,0] also modified B[0,0]
-[-1.00e+00  3.00e+00]
-[ 2.00e+00  4.00e+00]
-\end{verbatim}
-
-\item The regular (\ie, not in-place) arithmetic operations always 
-return new objects.   
-\begin{verbatim}
->>> B = matrix([[1.,2.], [3.,4.]])  
->>> A = +B
->>> A[0,0] = -1 
->>> print B   # modifying A[0,0] does not modify B[0,0]
-[ 1.00e+00  3.00e+00]
-[ 2.00e+00  4.00e+00]
-\end{verbatim}
-
-\item  The in-place operations directly modify the coefficients of the 
- existing matrix object and do not create a new object. 
-\begin{verbatim}
->>> B = matrix([[1.,2.], [3.,4.]])  
->>> A = B
->>> A *= 2
->>> print B   # in-place operation also changed B
-[ 2.00e+00  6.00e+00]
-[ 4.00e+00  8.00e+00]
->>> A = 2*A
->>> print B   # regular operation creates a new A, so does not change B
-[ 2.00e+00  6.00e+00]
-[ 4.00e+00  8.00e+00]
-\end{verbatim}
-\end{itemize}
-
-
-%\begin{verbatim}
-%>>> B.V += 1.0   # add 1 to the nonzero entries
-%>>> print B
-%[ 2.00e+00  8.00e+00     0         0    ]
-%[    0      9.00e+00  7.00e+00     0    ]
-%[    0         0      5.00e+00     0    ]
-%[    0         0         0         0    ]
-%\end{verbatim}
-
-
-\section{Indexing and Slicing} \label{s-indexing}
-Matrices can be indexed using one or two arguments.  In single-argument
-indexing of a matrix \var{A}, the index runs from 
-\code{-len(\var{A})} to \code{len(\var{A})-1}, and is interpreted as an
-index in the one-dimensional array of coefficients of \var{A} 
-in column-major order.   Negative indices have the standard Python 
-interpretation: for negative \var{k}, \code{\var{A}[\var{k}]} is the 
-same element as  \code{\var{A}[len(\var{A})+\var{k}]}.
-
-Four different types of one-argument indexing are implemented.
-\begin{enumerate}
-\item The index can be a single integer.  This returns a 
-number, \eg, \code{\var{A}[0]} is the first element of \var{A}.
-
-\item The index can be an integer matrix.  This returns a 
-column matrix: the command \samp{A[matrix([0,1,2,3])]} 
-returns the 4 by 1 matrix consisting of the first four elements of
-\var{A}.   The size of the index matrix is ignored: 
-\samp{A[matrix([0,1,2,3], (2,2))]} returns the same 4 by 1 matrix.
-
-\item The index can be a list of integers.  This returns a column 
-matrix, \eg, \code{\var{A}[[0,1,2,3]]} is the 4 by 1 matrix consisting 
-of elements 0, 1, 2, 3 of \var{A}.   
-
-\item The index can be a Python slice.  This returns a matrix with one 
-column (possibly 0 by 1, or 1 by 1).  For example, \code{\var{A}[::2]} 
-is the column matrix defined by taking every other element of \var{A}, 
-stored in column-major order.  
-\code{\var{A}[0:0]} is a matrix with size (0,1).
-\end{enumerate}
-Thus, single-argument indexing returns a scalar (if the index is an 
-integer), or a matrix with one column.  This is consistent with the 
-interpretation that single-argument indexing accesses the matrix in 
-column-major order.
-
-Note that an index list or an index matrix are equivalent,
-but they are both useful, especially when we perform operations on 
-index sets.  For example, if \var{I} and \var{J} are lists then 
-\code{\var{I}+\var{J}} is the concatenated list, and \code{2*\var{I}} 
-is \var{I} repeated twice.  If they are matrices, these operations are 
-interpreted as arithmetic operations.
-For large index sets, indexing with integer matrices is also faster 
-than indexing with lists. 
-
-The following example illustrates one-argument indexing.
-\begin{verbatim}
->>> from cvxopt import matrix, spmatrix
->>> A = matrix(range(16), (4,4), 'd')
->>> print A
-[ 0.00e+00  4.00e+00  8.00e+00  1.20e+01]
-[ 1.00e+00  5.00e+00  9.00e+00  1.30e+01]
-[ 2.00e+00  6.00e+00  1.00e+01  1.40e+01]
-[ 3.00e+00  7.00e+00  1.10e+01  1.50e+01]
->>> A[4]
-4.0
->>> I = matrix([0, 5, 10, 15])
->>> print A[I]      # the diagonal
-[ 0.00e+00]
-[ 5.00e+00]
-[ 1.00e+01]
-[ 1.50e+01]
->>> I = [0,2];  J = [1,3]
->>> print A[2*I+J]  # duplicate I and append J
-[ 0.00e+00]
-[ 2.00e+00]
-[ 0.00e+00]
-[ 2.00e+00]
-[ 1.00e+00]
-[ 3.00e+00]
->>> I = matrix([0, 2]);  J =  matrix([1, 3])
->>> print A[2*I+J]  # multiply I by 2 and add J
-[ 1.00e+00]
-[ 7.00e+00]
->>> print A[4::4]   # get every fourth element skipping the first four  
-[ 4.00e+00]
-[ 8.00e+00]
-[ 1.20e+01]
-\end{verbatim}
-
-In two-argument indexing the arguments can be any combinations of the
-four types listed above.  The first argument indexes the rows of 
-the matrix and the second argument indexes the columns.  If both 
-indices are scalars, then a scalar is returned.  In all other cases, 
-a matrix is returned.  We continue the example.
-\begin{verbatim}
->>> print A[:,1]
-[ 4.00e+00]
-[ 5.00e+00]
-[ 6.00e+00]
-[ 7.00e+00]
->>> J = matrix([0, 2])
->>> print A[J,J]
-[ 0.00e+00  8.00e+00]
-[ 2.00e+00  1.00e+01]
->>> print A[:2, -2:]   
-[ 8.00e+00  1.20e+01]
-[ 9.00e+00  1.30e+01]
->>> A = spmatrix([0,2,-1,2,-2,1], [0,1,2,0,2,1], [0,0,0,1,1,2]) 
->>> print A[:, [0,1]]
-[ 0.00e+00  2.00e+00]
-[ 2.00e+00     0    ]
-[-1.00e+00 -2.00e+00]
->>> B = spmatrix([0,2*1j,0,-2], [1,2,1,2], [0,0,1,1,])
->>> print B[-2:,-2:]
-[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00]
-[ 0.00e+00+j2.00e+00 -2.00e+00-j0.00e+00]
-\end{verbatim}
-
-Expressions of the form \code{\var{A}[\var{I}]} or 
-\code{\var{A}[\var{I},\var{J}]} can also appear on the lefthand side 
-of an assignment.   
-The righthand side must be a scalar (\ie, a number or a 1 by 1 dense
-matrix), a sequence of numbers, or a dense or sparse matrix. 
-If the righthand side is a scalar, it is interpreted as a dense
-matrix with identical entries and the dimensions of the lefthand side.
-If the righthand side is a sequence of numbers (list, tuple, 
-\module{array} array, xrange object, \ldots) its values are 
-interpreted as the coefficients of a dense matrix in column-major order.  
-If the righthand side is a matrix (\mtrx\ or \spmtrx), it must 
-have the same size as the lefthand side.  Sparse matrices are 
-converted to dense in the assignment to a dense matrix.
-
-Indexed assignments are only allowed if they do not change the type of 
-the matrix.  For example, if \var{A} is a matrix with type \dtc, then 
-\code{\var{A}[\var{I}] = \var{B}} is only permitted if \var{B} is 
-an \intgr, a \flt, or a matrix of type \itc\ or \dtc.
-If \var{A} is an integer matrix, then \code{\var{A}[\var{I}] = \var{B}} 
-is only permitted if \var{B} is an \intgr\  or an integer matrix.
-
-The following examples illustrate indexed assignment.
-\begin{verbatim}
->>> A = matrix(range(16), (4,4))
->>> A[::2,::2] = matrix([[-1, -2], [-3, -4]])
->>> print A
-[ -1   4  -3  12]
-[  1   5   9  13]
-[ -2   6  -4  14]
-[  3   7  11  15]
->>> A[::5] += 1
->>> print A
-[  0   4  -3  12]
-[  1   6   9  13]
-[ -2   6  -3  14]
-[  3   7  11  16]
->>> A[0,:] = -1, 1, -1, 1
->>> print A
-[ -1   1  -1   1]
-[  1   6   9  13]
-[ -2   6  -3  14]
-[  3   7  11  16]
->>> A[2:,2:] = xrange(4)
->>> print A
-[ -1   1  -1   1]
-[  1   6   9  13]
-[ -2   6   0   2]
-[  3   7   1   3]
-\end{verbatim}
-
-\begin{verbatim}
->>> A = spmatrix([0,2,-1,2,-2,1], [0,1,2,0,2,1], [0,0,0,1,1,2]) 
->>> print A
-[ 0.00e+00  2.00e+00     0    ]
-[ 2.00e+00     0      1.00e+00]
-[-1.00e+00 -2.00e+00     0    ]
->>> C = spmatrix([10,-20,30], [0,2,1], [0,0,1])
->>> print C
-[ 1.00e+01     0    ]
-[    0      3.00e+01]
-[-2.00e+01     0    ]
->>> A[:,0] = C[:,0]
->>> print A
-[ 1.00e+01  2.00e+00     0    ]
-[    0         0      1.00e+00]
-[-2.00e+01 -2.00e+00     0    ]
->>> D = matrix(range(6), (3,2))
->>> A[:,0] = D[:,0]
->>> print A
-[ 0.00e+00  2.00e+00     0    ]
-[ 1.00e+00     0      1.00e+00]
-[ 2.00e+00 -2.00e+00     0    ]
->>> A[:,0] = 1
->>> print A
-[ 1.00e+00  2.00e+00     0    ]
-[ 1.00e+00     0      1.00e+00]
-[ 1.00e+00 -2.00e+00     0    ]
->>> A[:,0] = 0
->>> print A
-[ 0.00e+00  2.00e+00     0    ]
-[ 0.00e+00     0      1.00e+00]
-[ 0.00e+00 -2.00e+00     0    ]
-\end{verbatim}
-
-
-\section{Attributes and Methods} 
-Dense and sparse matrices have the following attributes.
-
-\begin{memberdesc}{size}
-A tuple with the dimensions of the matrix. The size of the matrix
-can be changed by altering this attribute, as long as the number
-of elements in the matrix remains unchanged.  
-\end{memberdesc} 
-
-\begin{memberdesc}{typecode}
-A \ctype{char}, either \itc, \dtc, or \ztc, for integer, real,
-and complex matrices, respectively.  A read-only attribute.
-\end{memberdesc} 
-
-\begin{methoddesc}{trans}
-Returns the transpose of the matrix as a new matrix.
-One can also use \code{A.T} instead of \code{A.trans()}.
-\end{methoddesc}
-
-\begin{methoddesc}{ctrans}
-Returns the conjugate transpose of the matrix as a new matrix.
-One can also use \code{A.H} instead of \code{A.ctrans()}.
-\end{methoddesc}
-
-\begin{methoddesc}{real}
-For complex matrices, returns the real part as a real matrix.
-For integer and real matrices, returns a copy of the matrix.
-\end{methoddesc}
-
-\begin{methoddesc}{imag}
-For complex matrices, returns the imaginary part as a real matrix.
-For integer and real matrices, returns an integer or real zero matrix.
-\end{methoddesc}
-
-In addition, sparse matrices have the following attributes.
-\begin{memberdesc}{V}
-A single-column dense matrix containing the numerical values of the 
-nonzero entries in column-major order.  Making an assignment to 
-the attribute is an efficient way of changing the values of the sparse 
-matrix, without changing the sparsity pattern.
-
-When the attribute \member{V} is read, a \emph{copy} of \member{V} is 
-returned, as a new dense matrix. 
-This implies, for example, that an indexed assignment 
-\samp{A.V[I] = B} does not work, or at least 
-cannot be used to modify \var{A}.  Instead the attribute \code{V}\ 
-will be read and returned as a new matrix; then the elements of this 
-new matrix are modified.
-\end{memberdesc} 
-
-\begin{memberdesc}{I}
-A single-column integer dense matrix with the row indices of the entries in
-\code{V}.  A read-only attribute.
-\end{memberdesc} 
-
-\begin{memberdesc}{J}
-A single-column integer dense matrix with the column indices of the entries
-in \code{V}.  A read-only attribute.
-\end{memberdesc} 
-
-\begin{memberdesc}{CCS}
-A triplet (column pointers, row indices, values) with the 
-compressed-column-storage 
-representation of the matrix.  A read-only attribute.  This attribute
-can be used to export sparse matrices to other packages such as MOSEK.
-\end{memberdesc} 
-
-The next example below illustrates assignments to \member{V}.
-\begin{verbatim}
->>> from cvxopt import spmatrix, matrix
->>> A = spmatrix(range(5), [0,1,1,2,2], [0,0,1,1,2])
->>> print A
-[ 0.00e+00     0         0    ]
-[ 1.00e+00  2.00e+00     0    ]
-[    0      3.00e+00  4.00e+00]
->>> B = spmatrix(A.V, A.J, A.I, (4,4))  # transpose and add a zero row and column
->>> print B
-[ 0.00e+00  1.00e+00     0         0    ]
-[    0      2.00e+00  3.00e+00     0    ]
-[    0         0      4.00e+00     0    ]
-[    0         0         0         0    ]
->>> B.V = matrix([1., 7., 8., 6., 4.])   # assign new values to nonzero entries
->>> print B
-[ 1.00e+00  7.00e+00     0         0    ]
-[    0      8.00e+00  6.00e+00     0    ]
-[    0         0      4.00e+00     0    ]
-[    0         0         0         0    ]
-\end{verbatim}
-
-The following attributes and methods are defined for dense matrices.
-\begin{memberdesc}{\_\_array\_struct\_\_}
-A PyCObject implementing the \program{NumPy} array interface  
-(see section~\ref{s-array-interface} for details).
-\end{memberdesc} 
-
-\begin{funcdesc}{tofile}{f}
-Writes the elements of the matrix in column-major order to a binary 
-file \var{f}. 
-\end{funcdesc}
-
-\begin{funcdesc}{fromfile}{f}
-Reads the contents of a binary file \var{f} into the matrix object.
-\end{funcdesc}
-
-The last two methods are illustrated in the following examples.
-\begin{verbatim}
->>> from cvxopt import matrix, spmatrix
->>> A = matrix([[1.,2.,3.], [4.,5.,6.]])  
->>> print A
-[ 1.00e+00  4.00e+00]
-[ 2.00e+00  5.00e+00]
-[ 3.00e+00  6.00e+00]
->>> f = open('mat.bin','w')
->>> A.tofile(f)
->>> f.close()
->>> B = matrix(0.0, (2,3))
->>> f = open('mat.bin','r')
->>> B.fromfile(f)
->>> f.close()
->>> print B
-[ 1.00e+00  3.00e+00  5.00e+00]
-[ 2.00e+00  4.00e+00  6.00e+00]
-\end{verbatim}
-
-\begin{verbatim}
->>> A = spmatrix(range(5), [0,1,1,2,2], [0,0,1,1,2])
->>> f = open('test.bin','w')
->>> A.V.tofile(f)  
->>> A.I.tofile(f) 
->>> A.J.tofile(f)
->>> f.close()
->>> f = open('test.bin','r')
->>> V = matrix(0.0, (5,1));  V.fromfile(f)  
->>> I = matrix(0, (5,1));  I.fromfile(f)  
->>> J = matrix(0, (5,1));  J.fromfile(f)  
->>> B = spmatrix(V, I, J)
->>> print B
-[ 0.00e+00     0         0    ]
-[ 1.00e+00  2.00e+00     0    ]
-[    0      3.00e+00  4.00e+00]
-\end{verbatim}
-Note that the \function{dump()} and \function{load()} functions in 
-the \module{pickle} module offer a convenient alternative for writing
-matrices to files and reading matrices from files.
-
-
-\section{Built-In Functions} \label{s-builtinfuncs}
-Many Python built-in functions and operations can be used with matrix 
-arguments.  We list some useful examples.
-
-\begin{funcdesc}{len}{x}
-If \var{x} is a dense matrix, returns the product of the number of rows 
-and the number of columns.
-If \var{x} is a sparse matrix, returns the number of nonzero entries.
-\end{funcdesc}
-
-\begin{funcdesc}{bool}{\optional{x}}
-Returns \False\ if \var{x} is a zero matrix and \True\ otherwise.
-\end{funcdesc}
-
-\begin{funcdesc}{max}{x}
-If \var{x} is a dense matrix, returns the maximum element of \var{x}.
-If \var{x} is a sparse, returns the maximum nonzero element of \var{x}.
-\end{funcdesc}
-
-\begin{funcdesc}{min}{x}
-If \var{x} is a dense matrix, returns the minimum element of \var{x}.
-If \var{x} is a sparse matrix, returns the minimum nonzero element of 
-\var{x}.
-\end{funcdesc}
-
-\begin{funcdesc}{abs}{x}
-Returns a matrix with the absolute values of the elements of \var{x}.
-\end{funcdesc}
-
-\begin{funcdesc}{sum}{x\optional{, start=0.0}}
-Returns the sum of \var{start} and the elements of \var{x}.
-\end{funcdesc}
-
-Dense and sparse matrices can be used as  arguments to the 
-\function{list()}, \function{tuple()}, \function{zip()}, 
-\function{map()}, and \function{filter()} functions described in 
-section 2.1 of the Python Library Reference.  
-However, one should note that when used with sparse matrix arguments, 
-these functions only consider the nonzero entries.
-For example, \code{list(\var{A})} and \code{tuple(\var{A})} 
-construct a list, respectively a tuple, from the elements of \var{A} 
-if \var{A} is dense, and of the nonzero elements of \var{A} if \var{A} is 
-sparse.
-
-\code{zip(\var{A}, \var{B}, \ldots)} returns a list of tuples, 
-with the {\it i}th tuple containing the {\it i}th elements 
-(or nonzero elements) of \var{A}, \var{B}, \ldots.   
-\begin{verbatim}
->>> from cvxopt import matrix
->>> A = matrix([[-11., -5., -20.], [-6., -0., 7.]])
->>> B = matrix(range(6), (3,2))
->>> list(A)
-[-11.0, -5.0, -20.0, -6.0, 0.0, 7.0]
->>> tuple(B)
-(0, 1, 2, 3, 4, 5)
->>> zip(A, B)
-[(-11.0, 0), (-5.0, 1), (-20.0, 2), (-6.0, 3), (0.0, 4), (7.0, 5)]
-\end{verbatim}
-
-\code{map(\var{f},\var{A})}, where \var{f} is a function and \var{A} 
-is a dense matrix, returns a list constructed by applying \var{f} to each 
-element of \var{A}.  If \var{A} is sparse, the function \var{f} is applied to 
-each nonzero element of \var{A}.
-Multiple arguments can be provided, for example, 
-as in \code{map(\var{f},\var{A},\var{B})}, if \var{f} is a function 
-with two arguments.
-In the following example, we return an integer 0-1 matrix with the
-result of an elementwise comparison.
-\begin{verbatim}
->>> A = matrix([ [0.5, -0.1, 2.0], [1.5, 0.2, -0.1], [0.3, 1.0, 0.0]]) 
->>> print A
-[ 5.00e-01  1.50e+00  3.00e-01]
-[-1.00e-01  2.00e-01  1.00e+00]
-[ 2.00e+00 -1.00e-01  0.00e+00]
->>> print matrix(map(lambda x: 0 <= x <= 1, A), A.size)
-[ 1  0  1]
-[ 0  1  1]
-[ 0  0  1]
-\end{verbatim}
-
-\code{filter(\var{f},\var{A})}, where \var{f} is a function and 
-\var{A} is a matrix, returns a list containing the elements of \var{A} 
-(or nonzero elements of \var{A} is \var{A} is sparse)
-for which \var{f} is true.
-\begin{verbatim}
->>> filter(lambda x: x%2, A)         # list of odd elements in A
-[5, -7, -1, -5, 1, 5, -1, -3, -7]
->>> filter(lambda x: -2 < x < 3, A)  # list of elements between -2 and 3
-[-1, 2, 1, 2, -1, 2]
-\end{verbatim}
-
-It is also possible to iterate over matrix elements, as illustrated in
-the following example.
-\begin{verbatim}
->>> A = matrix([[5, -3], [9, 11]])
->>> for x in A: print max(x,0)
-...
-5
-0
-9
-11
->>> [max(x,0) for x in A]
-[5, 0, 9, 11]
-\end{verbatim}
-
-The expression \samp{\var{x} in \var{A}} returns \True\ if an element 
-of \var{A} (or a nonzero element of \var{A} if \var{A} is sparse)
-is equal to \var{x} and \False\ otherwise.
-
-\section{Other Matrix Functions} \label{s-otherfuncs}
-The following functions can be imported from \module{cvxopt}.
-\begin{funcdesc}{sqrt}{x}
-The elementwise square root of a dense matrix \var{x}.  The result is 
-returned as a real matrix if \var{x} is an integer or real matrix and 
-as a complex matrix if \var{x} is a complex matrix.  Raises an 
-exception when \var{x} is an integer or real matrix with negative 
-elements.
-
-As an example we take the elementwise square root of the sparse matrix
-\BEQ \label{e-spA-example}
- A = \left[ \begin{array}{rrrrr}
-  0 & 2 & 0 & 0 & 3 \\
-  2 & 0 & 0 & 0 & 0 \\
-  1 & 2 & 0 & 4 & 0 \\
-  0 & 0 & 1 & 0 & 0 \end{array} \right]
-\EEQ
-\begin{verbatim}
->>> from cvxopt import spmatrix, sqrt
->>> A = spmatrix([2,1,2,2,1,3,4], [1,2,0,2,3,0,2], [0,0,1,1,2,3,3]) 
->>> B = spmatrix(sqrt(A.V), A.I, A.J)
->>> print B
-[    0      1.41e+00     0      1.73e+00]
-[ 1.41e+00     0         0         0    ]
-[ 1.00e+00  1.41e+00     0      2.00e+00]
-[    0         0      1.00e+00     0    ]
-\end{verbatim}
-\end{funcdesc}
-
-\begin{funcdesc}{sin}{x}
-The sine function applied elementwise to a dense matrix \var{x}.  
-The result is returned as a real matrix if \var{x} is an integer
-or real matrix and as a complex matrix otherwise.  
-\end{funcdesc}
-
-\begin{funcdesc}{cos}{x}
-The cosine function applied elementwise to a dense matrix \var{x}.  
-The result is returned as a real matrix if \var{x} is an integer
-or real matrix and as a complex matrix otherwise.  
-\end{funcdesc}
-
-\begin{funcdesc}{exp}{x}
-The exponential function applied elementwise to a dense matrix \var{x}.  
-The result is returned as a real matrix if \var{x} is an integer 
-or real matrix and as a complex matrix otherwise.  
-\end{funcdesc}
-
-\begin{funcdesc}{log}{x}
-The natural logarithm applied elementwise to a dense matrix \var{x}.  
-The result is returned as a real matrix if \var{x} is an integer
-or real matrix and as a complex matrix otherwise.  
-Raises an exception when \var{x} is an integer or real matrix with 
-nonnegative elements, or a complex matrix with zero elements.
-\end{funcdesc}
-
-\begin{funcdesc}{mul}{x0, \optional{, x1 \optional{, x2 \ldots}}}
-If the arguments are dense or sparse matrices of the same size,
-returns the elementwise product of its arguments.  The result is a sparse
-matrix if one or more of its arguments is sparse, and a dense matrix 
-otherwise.
-
-If the arguments include scalars, a scalar product with the scalar is made.
-(A 1 by 1 dense matrix is treated as a scalar if the dimensions of the 
-other arguments are not all 1 by 1.)
-
-\function{mul()} can also be called with an iterable (list, tuple, xrange 
-object, or generator) as its single argument, if the iterable generates 
-a list of dense or sparse matrices or scalars.
-
-\begin{verbatim}
->>> from cvxopt import matrix, spmatrix, mul
->>> A = matrix([[1.0, 2.0], [3.0, 4.0]])
->>> B = spmatrix([2.0, 3.0], [0, 1], [0, 1])
->>> print mul(A, B, -1.0)
-[-2.00e+00     0    ]
-[    0     -1.20e+01]
-\end{verbatim}
-
-\begin{verbatim}
->>> print mul( matrix([k, k+1]) for k in [1,2,3] )
-[  6]
-[ 24]
-\end{verbatim}
-\end{funcdesc}
-
-\begin{funcdesc}{div}{x, y}
-Returns the elementwise division of \var{x} by \var{y}.  
-\var{x} is a dense or sparse matrix, or a scalar
-(Python number of 1 by 1 dense matrix).
-\var{y} is a dense matrix or a scalar.
-\end{funcdesc}
-
-\begin{funcdesc}{max}{x0\optional{, x1\optional{, x2 \ldots}}}
-When called with a single matrix argument, returns the maximum of the 
-elements of the matrix (including the zero entries, if the matrix is 
-sparse).  
-
-When called with multiple arguments, the arguments must be matrices of 
-the same size, or scalars, and the elementwise maximum is returned.   
-A 1 by 1 dense matrix is
-treated as a scalar if the other arguments are not all 1 by 1.
-If one of the arguments is scalar, and the other arguments are not all 1 
-by 1, then the scalar argument is interpreted as a dense matrix with all 
-its entries equal to the scalar.
-
-The result is a sparse matrix if all its arguments are sparse matrices.  
-The result is a number if all its arguments are numbers.
-The result is a dense matrix if at least one of the arguments is a dense 
-matrix.
-
-\function{max()} can also be called with an iterable (list, tuple, xrange 
-object, or generator) as its single argument, if the iterable generates a 
-list of dense or sparse matrices or scalars.
-\begin{verbatim}
->>> from cvxopt import matrix, spmatrix, max
->>> A = spmatrix([2, -3], [0, 1], [0, 1])
->>> print max(A, -A, 1)
-[ 2.00e+00  1.00e+00]
-[ 1.00e+00  3.00e+00]
-\end{verbatim}
-
-It is important to note the difference between this \function{max()}
-and the built-in \function{max()}, explained in the previous section.
-\begin{verbatim}
->>> from cvxopt import spmatrix
->>> A = spmatrix([-1.0, -2.0], [0,1], [0,1])
->>> max(A)          # built-in max of a sparse matrix takes maximum over nonzero elements
--1.0
->>> max(A, -1.5)
-Traceback (most recent call last):
-  File "<stdin>", line 1, in <module>
-NotImplementedError: matrix comparison not implemented
->>> from cvxopt import max
->>> max(A)          # cvxopt.max takes maximum over all the  elements
-0.0
->>> print max(A, -1.5)
-[-1.00e+00  0.00e+00]
-[ 0.00e+00 -1.50e+00]
-\end{verbatim}
-\end{funcdesc}
-
-\begin{funcdesc}{min}{x0\optional{, x1\optional{, x2 \ldots}}}
-When called with a single matrix argument, returns the minimum of the 
-elements of the matrix (including the zero entries, if the matrix is 
-sparse).  
-
-When called with multiple arguments, the arguments must be matrices of 
-the same size, or scalars, and the elementwise maximum is returned.   
-A 1 by 1 dense matrix is
-treated as a scalar if the other arguments are not all 1 by 1.
-If one of the arguments is scalar, and the other arguments are not 
-all 1 by 1, then the scalar argument is interpreted as a dense matrix with all its entries 
-equal to the scalar.
-
-\function{min()} can also be called with an iterable (list, tuple, 
-xrange object, or generator) as its single argument, if the iterable 
-generates a list of dense or sparse matrices or scalars.
-\end{funcdesc}
-
-
-\section{Randomly Generated Matrices} 
-\label{s-random}
-The \module{cvxopt} module provides two functions \function{normal()} 
-and \function{uniform()} for generating
-randomly distributed matrices.  The default installation relies on
-the pseudo-random number generators in the Python standard 
-library \module{random}.  Alternatively, the random number generators in 
-the \ulink{GNU Scientific Library (GSL)}{http://www.gnu.org/software/gsl}
-can be used, if this option is selected during the installation of CVXOPT.
-The random matrix functions based on GSL are faster than the default 
-functions based on the \module{random} module.
-
-\begin{funcdesc}{normal}{nrows\optional{, ncols\optional{, 
- mean\optional{, std}}}}
-Returns a type \dtc\ dense matrix of size \var{nrows} by 
-\var{ncols} with elements chosen from a normal distribution 
-with mean \var{mean} and standard deviation \var{std}.
-The default values for the optional arguments are 
-\var{ncols}=1, \var{mean}=0.0, \var{std}=1.0.
-\end{funcdesc}
-
-\begin{funcdesc}{uniform}{nrows\optional{, ncols\optional{, 
-  a\optional{, b}}}}
-Returns a type \dtc\ dense matrix of size \var{nrows} by 
-\var{ncols} matrix with elements uniformly distributed 
-between \var{a} and \var{b}.
-The default values for the optional arguments are 
-\var{ncols}=1, \var{a}=0.0, \var{b}=1.0.
-\end{funcdesc}
-
-\begin{funcdesc}{setseed}{\optional{value}}
-Sets the state of the random number generator.  \var{value} must be an 
-integer.  If \var{value} is absent or equal to zero, the value is taken 
-from the system clock.  
-If the Python random number generators are used, this is equivalent
-to \function{random.seed(value)}.
-\end{funcdesc}
-
-\begin{funcdesc}{getseed}{}
-Returns the current state of the random number generator.  
-This function is only available if the GSL random number generators are 
-installed.   
-(The state of the random number generators in the Python \module{random} 
-module can be managed via the functions \function{random.getstate()} and 
-\function{random.setstate()}.)
-\end{funcdesc}
-
-
-\section{The NumPy Array Interface} \label{s-array-interface}
-
-The CVXOPT \mtrx\ object is compatible with the \program{NumPy} Array 
-Interface, 
-which allows Python objects that represent multidimensional 
-arrays to exchange data using information stored in the 
-attribute \code{\_\_array\_struct\_\_}.  
-
-\textbf{See also:}
-\BIT
-\item \seelink{http://numpy.scipy.org/array_interface.shtml}
-{NumPy Array Interface Specification}{}
-\item \seelink{http://numpy.scipy.org}{NumPy home page}{}
-\EIT
-
-As already mentioned in section~\ref{s-creating-matrices},
-a two-dimensional array object (for example, a \program{NumPy} matrix or
-two-dimensional array) can be converted to a CVXOPT \mtrx\ object by using 
-the \function{matrix()} constructor.
-Conversely, CVXOPT matrices can be used as array-like objects
-in \program{NumPy}.  The following example illustrates the 
-compatibility of CVXOPT matrices and \program{NumPy} arrays. 
-\begin{verbatim}
->>> from cvxopt import matrix
->>> a = matrix(range(6), (2,3), 'd')
->>> print a
-[ 0.00e+00  2.00e+00  4.00e+00]
-[ 1.00e+00  3.00e+00  5.00e+00]
->>> from numpy import array
->>> b = array(a)
->>> b
-array([[ 0.  2.  4.]
-       [ 1.  3.  5.]])
->>> a*b
-array([[  0.   4.  16.]
-       [  1.   9.  25.]])
->>> from numpy import mat
->>> c = mat(a)
->>> c
-matrix([[ 0.  2.  4.]
-        [ 1.  3.  5.]])
->>> a.T * c 
-matrix([[  1.,   3.,   5.],
-        [  3.,  13.,  23.],
-        [  5.,  23.,  41.]])
-\end{verbatim}
-In the first product, \code{a*b} is interpreted as \program{NumPy} array 
-multiplication, \ie, componentwise multiplication.
-The second product \code{a.T*c} is interpreted as \program{NumPy} matrix 
-multiplication, \ie, standard matrix multiplication.
-
-
-\iffalse
-\section{Sparse BLAS Functions}
-The \module{cvxopt.base} module includes a few arithmetic functions 
-that extend functions from \module{cvxopt.blas} to sparse matrices.
-These functions are faster than the corresponding operations 
-implemented using the overloaded arithmetic described 
-in~section~\ref{s-spmatrix-arith}.
-They also work in-place, \ie, they modify their arguments without 
-creating new objects.
-
-
-\begin{funcdesc}{gemv}{A, x, y\optional{, trans='N'\optional{, 
-  alpha=1.0\optional{, beta=0.0}}}}
-Matrix-vector product with a general dense or sparse matrix:
-\[ 
-y := \alpha Ax + \beta y \quad (\mathrm{trans} = \mathrm{'N'}),
-  \qquad 
-y := \alpha A^T x + \beta y \quad (\mathrm{trans} = \mathrm{'T'}), 
-  \qquad
-y := \alpha A^H x + \beta y \quad (\mathrm{trans} = \mathrm{'C'}). 
-\]
-If \var{A} is a dense matrix, this is identical to 
-\function{blas.gemv()}.  If \var{A} is sparse, the result is the same 
-as when \function{blas.gemv()} is called with \code{matrix(A)} as 
-argument, however, without explicitly converting \var{A} to dense.
-\end{funcdesc}
-
-\begin{funcdesc}{symv}{A, x, y\optional{, uplo='L'\optional{, 
-alpha=1.0\optional{, beta=0.0}}}} 
-Matrix-vector product with a dense or sparse real symmetric matrix:
-\[
-   y := \alpha A x + \beta y.
-\]
-If \var{A} is a dense matrix, this is identical to 
-\function{blas.symv()}.  If \var{A} is sparse, the result is the same 
-as when \function{blas.symv()} is called with \code{matrix(A)} as 
-argument, however, without explicitly converting \var{A} to dense.
-\end{funcdesc}
-
-\begin{funcdesc}{gemm}{A, B, C\optional{, transA='N'\optional{, 
-transB='N'\optional{, alpha=1.0\optional{, beta=0.0\optional{, 
-partial=False}}}}}}
-Matrix-matrix product of two general sparse or dense matrices:
-\[
-  C := \alpha \op(A) \op(B) + \beta C 
-\]
-where
-\[
-\op(A) =  \left\{ \begin{array}{ll}
- A & \mathrm{transA} = \mathrm{'N'} \\
- A^T & \mathrm{transA} = \mathrm{'T'} \\
- A^H & \mathrm{transA} = \mathrm{'C'} \end{array} \right.
-\qquad
-\op(B) =  \left\{ \begin{array}{ll}
- B & \mathrm{transB} = \mathrm{'N'} \\
- B^T & \mathrm{transB} = \mathrm{'T'} \\
- B^H & \mathrm{transB} = \mathrm{'C'}. \end{array} \right.
-\]
-If \var{A}, \var{B} and \var{C} are dense matrices, this is 
-identical to \function{blas.gemm()}, described in section~\ref{s-blas3},
-and the argument \var{partial} is ignored.
-
-If \var{A} and/or \var{B} are sparse and \var{C} is dense, the result
-is the same as when \function{blas.gemm()} is called with
-\code{matrix(A)} and \code{matrix(B)} as arguments, without explicitly 
-converting  \var{A} and \var{B} to dense.
-The argument \var{partial} is ignored.
-
-If \var{C} is a sparse matrix, the matrix-matrix product in the
-definition of \function{blas.gemm()} is computed, but as a sparse 
-matrix.  
-If \var{partial} is \False, the result is stored in \var{C}, 
-and the sparsity pattern of \var{C} is  modified if necessary.
-If \var{partial} is \True, the operation only updates the nonzero
-elements in \var{C}, even if the sparsity pattern of \var{C} differs
-from that of the matrix product.  
-\end{funcdesc}
-
-\begin{funcdesc}{syrk}{A, C\optional{, uplo='L'\optional{, 
-trans='N'\optional{, alpha=1.0\optional{, beta=0.0\optional{, 
-partial=False}}}}}}
-Rank-\tm{k} update of a sparse or dense real or complex symmetric
-matrix:
-\[
- C := \alpha AA^T + \beta C \quad (\mathrm{trans} = \mathrm{'N'}), 
- \qquad 
- C := \alpha A^TA + \beta C \quad (\mathrm{trans} = \mathrm{'T'}), 
-\]
-If \var{A} and \var{C} are dense, this is identical to 
-\function{blas.syrk()}, described in section~\ref{s-blas3},
-and the argument \var{partial} is ignored.
-
-If \var{A} is sparse and \var{C} is dense, the result is the same as 
-when \function{blas.syrk()} is called with \code{matrix(A)} as 
-argument, without explicitly converting  \var{A} to dense.  
-The argument \var{partial} is ignored.
-
-If \var{C} is sparse, the product in the definition of 
-\function{blas.syrk()} is computed, but as a sparse matrix.  
-If \var{partial} is \False, the result is stored in \var{C}, 
-and the sparsity pattern of \var{C} is  modified if necessary.
-If \var{partial} is \True, the operation only updates the nonzero
-elements in \var{C}, even if the sparsity pattern of \var{C} differs
-from that of the matrix product.  
-\end{funcdesc}
-
-In the following example, we first compute 
-\[
-C =  A^TB, \qquad
-A = \left[ \begin{array}{ccc}
-0 & 1 & 0 \\ 1 & 0 & 1 \\ 0 & 1 & 0 \\ 1 & 0 & 0 \end{array}\right],
-\qquad
-B = \left[ \begin{array}{ccc}
-   0 & -1 & 0 \\ 2 & 0 & 2 \\ 0 & 3 & 0 \\ 2 & 0 & 0 
-   \end{array}\right].
-\]
-\begin{verbatim}
->>> from cvxopt.base import spmatrix, gemm
->>> A = spmatrix(1, [1,3,0,2,1], [0,0,1,1,2])
->>> B = spmatrix([2,2,-1,3,2], [1,3,0,2,1], [0,0,1,1,2])
->>> C = spmatrix([], [], [], size=(3,3))
->>> gemm(A, B, C, transA='T')
->>> print C
-[ 4.00e+00     0      2.00e+00]
-[    0      2.00e+00     0    ]
-[ 2.00e+00     0      2.00e+00]
-\end{verbatim}
-Now suppose we want to replace \var{C}  with
-\[
-C = A^TD, \qquad 
-D = \left[ \begin{array}{ccc}
-   0 & 1 & 0 \\ 3 & 0 & -2 \\ 0 & 1 & 0 \\ 4 & 0 & 0 
-   \end{array}\right].
-\]
-The new matrix has the same sparsity pattern as \var{C}, so we can 
-use \function{gemm()} with the \code{partial=True} option.
-This saves time in large sparse matrix multiplications when the 
-sparsity pattern of the result is known beforehand.
-\begin{verbatim}
->>> D = spmatrix([3,4,1,1,-2], [1,3,0,2,1], [0,0,1,1,2])
->>> gemm(A, D, C, transA='T', partial=True)
->>> print C
-[ 7.00e+00     0     -2.00e+00]
-[    0      2.00e+00     0    ]
-[ 3.00e+00     0     -2.00e+00]
-\end{verbatim}
-\fi
diff --git a/doc/modeling.tex b/doc/modeling.tex
deleted file mode 100644
index 275f547..0000000
--- a/doc/modeling.tex
+++ /dev/null
@@ -1,747 +0,0 @@
-\chapter{Modeling (\module{cvxopt.modeling})}
-\label{chap:modeling}
-The module \module{cvxopt.modeling} can be used to specify and solve 
-optimization problems  with convex piecewise-linear objective and 
-constraint functions.  Using this modeling tool, one can specify an 
-optimization problem by first defining the optimization variables 
-(see section~\ref{s-variables}),
-and then specifying the objective and constraint functions 
-using linear operations (vector addition and subtraction,
-matrix-vector multiplication, indexing and slicing)
-and nested evaluations of \function{max()}, \function{min()}, 
-\function{abs()} and \function{sum()} (see section~\ref{s-functions}).
-
-A more general Python modeling package is 
-\seelink{http://cvxmod.net}{CVXMOD}{}.
-
-\section{Variables} \label{s-variables}
-Optimization variables are represented by \pytype{variable} objects.
-
-\begin{classdesc}{variable}{\optional{size\optional{, name}}}
-A vector variable.  The first argument is the dimension of the
-vector (a positive integer with default value 1). 
-The second argument is a string with a name for the variable.
-The name is optional and has default value \code{""}. It is only used 
-when displaying variables (or objects that depend on variables, such 
-as functions or constraints) 
-using \function{print} statements, when calling the built-in functions
-\function{repr()}  or \function{str()}, or when writing linear programs
-to MPS files.
-\end{classdesc}
-The function \function{len()} returns the length of a 
-\pytype{variable}.  A \pytype{variable} \var{x} has two attributes.
-\begin{memberdesc}{name}
-The name of the variable.  
-\end{memberdesc}
-
-\begin{memberdesc}{value}
-Either \None\  or a dense \dtc\ matrix of size \code{len(\var{x})} by 1.
-
-The attribute \var{x}.\member{value} is set to \None\ when the 
-variable \var{x} is created.   It can be given a numerical value later, 
-typically by solving an LP that has \var{x} as one of its variables.   
-One can also make an explicit assignment 
-\code{\var{x}.\member{value} = \var{y}}.  The
-assigned value \var{y} must be an \intgr\ or \flt, or a 
-dense \dtc\ matrix of size (\code{len(\var{x})},1). 
-If \var{y} is an \intgr\ or \flt\, all the elements of 
-\var{x}.\member{value} are set to the value of \var{y}.
-\end{memberdesc}
-
-\begin{verbatim}
->>> from cvxopt import matrix
->>> from cvxopt.modeling import variable
->>> x = variable(3,'a')
->>> len(x)
-3
->>> print x.name
-a
->>> print x.value 
-None
->>> x.value = matrix([1.,2.,3.])
->>> print x.value
-[ 1.00e+00]
-[ 2.00e+00]
-[ 3.00e+00]
->>> x.value = 1
->>> print x.value
-[ 1.00e+00]
-[ 1.00e+00]
-[ 1.00e+00]
-\end{verbatim}
-
-
-\section{Functions} \label{s-functions}
-Objective and constraint functions can be defined via overloaded 
-operations on variables and other functions.  A function \var{f} is 
-interpreted as a column vector, with length \code{len(\var{f})} 
-and with a value that depends on the values of its variables.  
-Functions have two public attributes.  
-\begin{methoddesc}{variables}
-Returns a copy of the list of variables of the function.
-\end{methoddesc}
-
-\begin{methoddesc}{value}
-The function value.  If any of the variables of \var{f} has value 
-\None, then \var{f}.\function{value()} returns \None.
-Otherwise, it returns a dense \dtc\ matrix of size 
-(\code{len(\var{f}),1}) with the function value computed from the 
-\member{value} attributes of the variables of \var{f}.  
-\end{methoddesc}
-
-Three types of functions are supported: affine, convex 
-piecewise-linear and concave piecewise-linear.
-
-\textbf{Affine functions} represent vector valued functions of the form
-\[
- f(x_1,\ldots,x_n) = A_1 x_1 + \cdots + A_n x_n + b.
-\]
-The coefficients can be scalars or dense or sparse matrices. The 
-constant term is a scalar or a column vector.
-
-Affine functions result from the following operations.
-\begin{description}
-\item[Unary operations]
-For a variable \var{x}, the unary operation \code{+\var{x}} results in 
-an affine function with \var{x} as variable, coefficient 1.0, and 
-constant term 0.0.  The unary operation \code{-\var{x}} returns an 
-affine function with \var{x} as variable, coefficient -1.0, and 
-constant term 0.0.  For an affine function \var{f}, \code{+\var{f}} is 
-a copy of \var{f}, and \code{-\var{f}} is a copy of \var{f} with the 
-signs of its coefficients and constant term reversed.
-
-\item[Addition and subtraction]
-Sums and differences of affine functions, variables and constants 
-result in new affine functions.
-The constant terms in the sum can be of type \intgr\ or \flt, or
-dense or sparse \dtc\ matrices with one column. 
-
-The rules for addition and subtraction follow the conventions for 
-matrix addition and subtraction in sections~\ref{s-arithmetic}
-and~\ref{s-spmatrix-arith}, with variables and affine functions 
-interpreted as dense \dtc\ matrices with one column.
-In particular, a scalar term (\intgr, \flt, 1 by 1 dense \dtc\ matrix, 
-variable of length 1, or affine function of length 1) can be added 
-to an affine function or variable of length greater than 1.
-
-\item[Multiplication]
-Suppose \var{v} is an affine function or a variable, and \var{a} is 
-an \intgr, \flt, sparse or dense \dtc\ matrix.  The products 
-\code{\var{a}*\var{v}} and  \code{\var{v}*\var{a}} are 
-valid affine functions whenever the product is allowed under the rules 
-for matrix and scalar multiplication  of sections~\ref{s-arithmetic} 
-and~\ref{s-spmatrix-arith}, with \var{v} interpreted as a \dtc\ matrix 
-with one column.
-In particular, the product \code{\var{a}*\var{v}} is defined if 
-\var{a} is a scalar (\intgr, \flt\ or 1 by 1 dense \dtc\ matrix), 
-or a matrix (dense or sparse) with 
-\code{\var{a}.\member{size}[1] = len(\var{v})}.   
-The operation \code{\var{v}*\var{a}} is defined if \var{a} is scalar,
-or if \code{len(\var{v})} = 1 and \var{a} is a matrix with one 
-column.
-
-\item[Inner products]
-The following two functions return scalar affine functions defined
-as inner products of a constant vector with  a variable or affine
-function.
-\begin{funcdesc}{sum}{v}
-The argument is an affine function or a variable.  The result is an
-affine function of length 1, with the sum of the components of the
-argument \var{v}.  
-\end{funcdesc}
-
-\begin{funcdesc}{dot}{u,v}
-If \var{v} is a variable or affine function and \var{u} is a \dtc\
-matrix of size  (\code{len(\var{v})},1), then 
-\code{dot(\var{u},\var{v})} and \code{dot(\var{v},\var{u})} are 
-equivalent to \code{\var{u}.\function{trans()}*\var{v}}.
-
-If \var{u} and \var{v} are dense matrices, then 
-\code{dot(\var{u},\var{v})} 
-is equivalent to the function \code{blas.dot(\var{u},\var{v})} 
-defined in section~\ref{s-blas1}, \ie, it returns the inner product of 
-the two matrices.
-\end{funcdesc}
-\end{description}
-
-In the following example, the variable \var{x} has length 1 and
-\var{y} has length 2.
-The functions \var{f} and \var{g} are given by
-\BEAS
- f(x,y) & = & \left[ \begin{array}{c} 2 \\ 2 \end{array}\right] x 
-  + y + \left[ \begin{array}{c} 3 \\ 3 \end{array}\right], \\
- g(x,y) & = &
-  \left[ \begin{array}{cc} 1 & 3 \\ 2 & 4 \end{array}\right] f(x,y)
-  + \left[ \begin{array}{cc} 1 & 1 \\ 1 & 1 \end{array} \right] y + 
-  \left[ \begin{array}{c} 1 \\ -1 \end{array} \right] \\
- & = & \left[ \begin{array}{c} 8 \\ 12 \end{array}\right] x 
-  + \left[ \begin{array}{cc} 2 & 4 \\ 3 & 5 \end{array}\right] y
-  + \left[ \begin{array}{c} 13 \\ 17\end{array}\right].
-\EEAS
-\begin{verbatim}
->>> from cvxopt.modeling import variable
->>> x = variable(1,'x')
->>> y = variable(2,'y')
->>> f = 2*x + y + 3  
->>> A = matrix([[1., 2.], [3.,4.]])
->>> b = matrix([1.,-1.])
->>> g = A*f + sum(y) + b 
->>> print g
-affine function of length 2
-constant term:
-[ 1.30e+01]
-[ 1.70e+01]
-linear term: linear function of length 2
-coefficient of variable(2,'y'):
-[ 2.00e+00  4.00e+00]
-[ 3.00e+00  5.00e+00]
-coefficient of variable(1,'x'):
-[ 8.00e+00]
-[ 1.20e+01]
-\end{verbatim}
-
-\begin{description}
-\item[In-place operations] 
-For an affine function \var{f} the operations \code{\var{f} += \var{u}} 
-and \code{\var{f} -= \var{u}}, with \var{u} a constant, a variable or 
-an affine function, are allowed if they do not change the length of 
-\var{f}, \ie, if \var{u} has length \code{len(\var{f})} or length 1.
-In-place multiplication \code{\var{f} *= \var{u}} and division 
-\code{\var{f} /= \var{u}} are allowed if \var{u} is an \intgr, \flt, or 
-1 by 1 matrix.
-\end{description}
-
-\begin{description}
-\item[Indexing and slicing] Variables and affine functions admit 
-single-argument indexing of the four types described in 
-section~\ref{s-indexing}.  The result of an indexing or slicing 
-operation is an affine function.  
-\end{description}
-
-\begin{verbatim}
->>> x = variable(4,'x')
->>> f = x[::2]
->>> print f 
-linear function of length 2
-linear term: linear function of length 2
-coefficient of variable(4,'x'):
-[ 1.00e+00     0         0         0    ]
-[    0         0      1.00e+00     0    ]
->>> y = variable(3,'x')
->>> g = matrix(range(12),(3,4),'d')*x - 3*y + 1
->>> print g[0] + g[2]
-affine function of length 1
-constant term:
-[ 2.00e+00]
-linear term: linear function of length 1
-coefficient of variable(4,'x'):
-[ 2.00e+00  8.00e+00  1.40e+01  2.00e+01]
-coefficient of variable(3,'x'):
-[-3.00e+00     0     -3.00e+00]
-\end{verbatim}
-
-
-The general expression of a \textbf{convex piecewise-linear} function is
-\[
- f(x_1,\ldots,x_n) = b + A_1 x_1 + \cdots + A_n x_n + 
-  \sum_{k=1}^K \max (y_1, y_2, \ldots, y_{m_k}).
-\]
-The maximum in this expression is a componentwise maximum of its 
-vector arguments, which can be constant vectors, variables, affine 
-functions or convex piecewise-linear functions.
-The general expression for a \textbf{concave piecewise-linear} function
-is
-\[
- f(x_1,\ldots,x_n) = b + A_1 x_1 + \cdots + A_n x_n + 
-  \sum_{k=1}^K \min (y_1, y_2, \ldots, y_{m_k}).
-\]
-Here the arguments of the \function{min()} can be constants, variables, 
-affine functions or concave piecewise-linear functions.
-
-Piecewise-linear functions can be created using the following 
-operations.
-\begin{description}
-\item[Maximum]  If the arguments in 
-\code{\var{f} = max(\var{y1},\var{y2}, \ldots)} 
-do not include any variables or functions, then the Python built-in 
-\function{max()} is evaluated.  
-
-If one or more of the arguments are variables or functions, 
-\function{max()} returns a piecewise-linear function defined as the 
-elementwise maximum of its arguments. 
-In other words, \code{\var{f}[\var{k}] = 
-max(\var{y1}[\var{k}],\var{y2}[\var{k}], \ldots)} 
-for \var{k}=0, \ldots, \code{len(\var{f})-1}.
-The length of \var{f} is equal to the maximum of the lengths of the 
-arguments.  Each argument must have length equal to 
-\code{len(\var{f})} or length one.  
-Arguments with length one are interpreted as vectors of 
-length \code{len(\var{f})} with identical entries.
-
-The arguments can be scalars of type \intgr\ or \flt, 
-dense \dtc\ matrices with one column, variables, affine functions or 
-convex piecewise-linear functions.
- 
-With one argument, \code{\var{f} = max(\var{u})} is interpreted as
-\code{\var{f} = max(\var{u}[0],\var{u}[1],\ldots,
-\var{u}[\function{len}(\var{u})-1])}.  
-
-\item[Minimum] Similar to \function{max()} but returns a concave 
-piecewise-linear function.  The arguments can be scalars of type 
-\intgr\ or \flt, dense \dtc\ matrices with one column, 
-variables, affine functions or concave piecewise-linear functions.
-
-\item[Absolute value] 
-If \var{u} is a variable or affine function then 
-\code{\var{f} = abs(\var{u})} returns the convex piecewise-linear 
-function \code{max(\var{u},-\var{u})}.
-
-\item[Unary plus and minus] \code{+\var{f}}\ creates a copy of \var{f}.
-\code{-\var{f}}\ is a concave piecewise-linear function if \var{f} is 
-convex and a convex piecewise-linear function if \var{f} is concave.
-
-\item[Addition and subtraction]  Sums and differences involving 
-piecewise-linear functions are allowed if they result in convex
-or concave functions. For example, one can add two convex or two
-concave functions, but not a convex and a concave function.
-The command \code{sum(\var{f})} is equivalent
-to \code{\var{f}[0] + \var{f}[1] + \ldots + \var{f}[len(\var{f})-1]}.
-
-\item[Multiplication] Scalar multiplication \code{\var{a}*\var{f}} of a 
-piecewise-linear function \var{f} is defined if \var{a}
-is an \intgr, \flt, 1 by 1 \dtc\ matrix. 
-Matrix-matrix multiplications \code{\var{a}*\var{f}} or 
-\code{\var{f}*\var{a}} are only defined if \var{a} is a dense or 
-sparse 1 by 1 matrix.
-
-\item[Indexing and slicing] Piecewise-linear functions admit 
-single-argument indexing of the four types described in 
-section~\ref{s-indexing}.  The result of an indexing or slicing 
-operation is a new piecewise-linear function.
-\end{description}
-
-In the following example, \var{f} is the 1-norm of a vector
-variable \var{x} of length 10, \var{g} is its infinity-norm and 
-\var{h} is the function
-\[
-  h(x) = \sum_k  \phi(x[k]),\qquad
-  \phi(u) = \left\{\begin{array}{ll}
-     0 & |u| \leq 1 \\
-    |u|-1  & 1 \leq |u| \leq 2 \\
-    2|u|-3  & |u| \geq 2. \end{array}\right.
-\]
-\begin{verbatim}
->>> from cvxopt.modeling import variable, max
->>> x = variable(10, 'x')
->>> f = sum(abs(x))    
->>> g = max(abs(x))   
->>> h = sum(max(0, abs(x)-1, 2*abs(x)-3))  
-\end{verbatim}
-
-\begin{description}
-\item[In-place operations]
-If \var{f} is piecewise-linear then the in-place operations  
-\code{\var{f} += \var{u}}, \code{\var{f} -= \var{u}}, 
-\code{\var{f} *= \var{u}}, \code{\var{f} /= \var{u}} are defined if the 
-corresponding expanded operations \code{\var{f} = \var{f}+\var{u}}, 
-\code{\var{f} = \var{f}-\var{u}}, \code{\var{f} = \var{f}*\var{u}}
-and \code{\var{f} = \var{f}/\var{u}} are defined and if they do not 
-change the length of \var{f}.
-\end{description}
-
-\section{Constraints}
-Linear equality and inequality constraints of the form
-\[
-  f(x_1,\ldots,x_n) = 0, \qquad f(x_1,\ldots,x_n) \preceq  0, 
-\]
-where \tm{f} is a convex function, are represented by \pytype{constraint}
-objects.  Equality constraints are created by expressions of the form 
-\begin{quote}
-\code{\var{f1} == \var{f2}}. 
-\end{quote}
-Here \var{f1} and \var{f2} can be any objects for which the 
-difference \code{\var{f1}-\var{f2}} yields an affine function.  
-Inequality constraints are created by expressions of the form 
-\begin{quote}
-\code{\var{f1} <= \var{f2}}, \qquad \code{\var{f2} >= \var{f1}},
-\end{quote}
-where \var{f1} and \var{f2} can be any objects for which the difference 
-\code{\var{f1}-\var{f2}} yields a convex piecewise-linear function.  
-The comparison operators first convert the expressions to 
-\code{\var{f1}-\var{f2} == 0}, resp.\, \code{\var{f1}-\var{f2} <= 0},
-and then return a new \pytype{constraint}\ object with constraint 
-function
-\code{\var{f1}-\var{f2}}.
-
-In the following example we create three constraints
-\[
-  0 \preceq x \preceq \ones, \qquad \ones^T x = 2,
-\]
-for a variable of length 5.
-\begin{verbatim}
->>> x = variable(5,'x')
->>> c1 = (x <= 1)
->>> c2 = (x >= 0)
->>> c3 = (sum(x) == 2)
-\end{verbatim}
-
-The built-in function \function{len()} returns the dimension of the
-constraint function.
-
-Constraints have four public attributes.
-\begin{methoddesc}{type}
-Returns \code{'='} if the constraint is an equality constraint,
-and \code{'<'} if the constraint is an inequality constraint.
-\end{methoddesc}
-
-\begin{methoddesc}{value}
-Returns the value of the constraint function.  
-\end{methoddesc}
-
-\begin{memberdesc}{multiplier}
-For a constraint \var{c}, \var{c}.\member{multiplier} is a 
-\pytype{variable} object of dimension \code{len(\var{c})}.   
-It is used to represent the Lagrange multiplier or dual variable 
-associated with the constraint.
-Its value is initialized as \None, and can be modified
-by making an assignment to \var{c}.\member{multiplier}.\member{value}.
-\end{memberdesc}
-
-\begin{memberdesc}{name}
-The name of the constraint.  Changing the name of a constraint
-also changes the name of the multiplier of \var{c}.
-For example, the command \code{\var{c}.\member{name} = 'newname'} also 
-changes
-\var{c}.\member{multiplier}.\member{name} to \code{'newname\_mul'}.
-\end{memberdesc}
-
-
-\section{Optimization Problems} \label{s-lp}
-
-Optimization problems are be constructed by calling the following
-function.
-\begin{classdesc}{op}{\optional{objective\optional{, constraints\optional{, name}}}}
-The first argument specifies the objective function to be minimized.
-It can be an affine or convex piecewise-linear function with length 1, 
-a \pytype{variable} with length 1, or a scalar constant
-(\intgr, \flt\ or 1 by 1 dense \dtc\ matrix).  The default value is
-\code{0.0}.
-
-The second argument is a single \pytype{constraint}, or a list of 
-\pytype{constraint} objects.  The default value is an empty list.
-
-The third argument is a string with a name for the problem.
-The default value is the empty string.
-\end{classdesc}
-
-The following attributes and methods are useful for examining
-and modifying optimization problems.
-
-\begin{memberdesc}{objective}
-The objective or cost function.  One can write to this 
-attribute to change the objective of an existing problem.  
-\end{memberdesc}
-
-\begin{methoddesc}{variables}
-Returns a list of the variables of the problem.
-\end{methoddesc}
-
-\begin{methoddesc}{constraints}
-Returns a list of the constraints.
-\end{methoddesc}
-
-\begin{methoddesc}{inequalities}
-Returns a list of the inequality constraints.
-\end{methoddesc}
-
-\begin{methoddesc}{equalities}
-Returns a list of the equality constraints.
-\end{methoddesc}
-
-\begin{funcdesc}{delconstraint}{c}
-Deletes constraint {\tt c} from the problem.
-\end{funcdesc}
-
-\begin{funcdesc}{addconstraint}{c}
-Adds constraint {\tt c} to the problem.
-\end{funcdesc}
-
-An optimization problem with convex piecewise-linear objective and
-constraints can be solved by calling the method \function{solve()}.
-
-\begin{funcdesc}{solve}{\optional{format\optional{, solver}}} 
-This function converts the optimization problem to a linear program
-in matrix form and then solves it using the solver described in 
-section~\ref{s-lpsolver}.
-
-The first argument is either \code{'dense'} or \code{'sparse'}, and 
-denotes the matrix types used in the matrix representation of the LP.
-The default value is \code{'dense'}.
-
-The second argument is either \None. \code{'glpk'} or \code{'mosek'},
-and selects one of three available LP solvers: the default solver 
-written in Python, the GLPK solver (if installed) or the
-MOSEK LP solver (if installed); see section~\ref{s-lpsolver}.
-The default value  is \None.
-
-The solver reports the outcome of optimization by setting 
-the attribute \var{self}.\member{status} and by modifying  
-the \member{value} attributes of the variables and the constraint 
-multipliers of the problem.
-\BIT
-\item If the problem is solved to optimality, 
-\var{self}.\member{status} is set to \code{'optimal'}.  
-The \member{value} attributes of the variables in the problem  are set 
-to their computed solutions, and the \member{value} attributes of the 
-multipliers of the constraints of the problem are set to the computed 
-dual optimal solution.
-
-\item If it is determined that the problem is infeasible, 
-\var{self}.\member{status} is set to \code{'primal infeasible'}.  
-The \member{value} attributes of the variables are set to \None.
-The \member{value} attributes of the 
-multipliers of the constraints of the problem are set to a certificate 
-of primal infeasibility.
-With the \code{'glpk'} option, \function{solve()}
-does not provide certificates of infeasibility.
-
-\item If it is determined that the problem is dual infeasible, 
-\var{self}.\member{status} is set to \code{'dual infeasible'}.  
-The \member{value} attributes of the multipliers of the constraints of 
-the problem are set to \None.
-The \member{value} attributes of the 
-variables are set to a certificate of dual infeasibility. 
-With the \code{'glpk'} option, \function{solve()} does not provide 
-certificates of infeasibility.
-
-\item If the problem was not solved successfully,
-\var{self}.\member{status} is set to \code{'unknown'}.  
-The \member{value} attributes of the variables and the constraint
-multipliers are set to \None.
-\EIT
-\end{funcdesc}
-We refer to section~\ref{s-lpsolver} for details on the algorithms and
-the different solver options.
-
-As an example we solve the LP
-\[
- \begin{array}{ll}
-  \mbox{minimize} & -4x - 5y \\
-  \mbox{subject to} &  2x +y \leq 3 \\
- &  x +2y \leq 3 \\
- & x \geq 0, \quad y \geq 0.
- \end{array}
-\]
-\begin{verbatim}
->>> from cvxopt.modeling import op
->>> x = variable()
->>> y = variable()
->>> c1 = ( 2*x+y <= 3 ) 
->>> c2 = ( x+2*y <= 3 )
->>> c3 = ( x >= 0 )
->>> c4 = ( y >= 0 ) 
->>> lp1 = op(-4*x-5*y, [c1,c2,c3,c4]) 
->>> lp1.solve()
->>> lp1.status
-'optimal'
->>> print lp1.objective.value()
-[-9.00e+00]
->>> print x.value
-[ 1.00e+00]
->>> print y.value
-[ 1.00e+00]
->>> print c1.multiplier.value
-[ 1.00e+00]
->>> print c2.multiplier.value
-[ 2.00e+00]
->>> print c3.multiplier.value
-[ 2.87e-08]
->>> print c4.multiplier.value
-[ 2.80e-08]
-\end{verbatim}
-
-We can solve the same LP in  matrix form as follows.
-\begin{verbatim}
->>> from cvxopt.modeling import op, dot
->>> x = variable(2)
->>> A = matrix([[2.,1.,-1.,0.], [1.,2.,0.,-1.]])
->>> b = matrix([3.,3.,0.,0.])
->>> c = matrix([-4.,-5.])
->>> ineq = ( A*x <= b )
->>> lp2 = op(dot(c,x), ineq)
->>> lp2.solve()
->>> print lp2.objective.value()
-[-9.00e+00]
->>> print x.value
-[ 1.00e+00]
-[ 1.00e+00]
->>> print ineq.multiplier.value
-[1.00e+00]
-[2.00e+00]
-[2.87e-08]
-[2.80e-08]
-\end{verbatim}
-
-The \pytype{op} class also includes two methods for writing and reading
-files in 
-\ulink{MPS format}{http://www-fp.mcs.anl.gov/otc/Guide/OptWeb/continuous/constrained/linearprog/mps.html}.
-
-\begin{funcdesc}{tofile}{filename}
-If the problem is an LP, writes it to the file \code{'filename'} using 
-the MPS format.  Row and column labels are assigned based on the 
-variable and constraint names in the LP.  
-\end{funcdesc}
-
-\begin{funcdesc}{fromfile}{filename}
-Reads the LP from the file \code{'filename'}.  The file must be 
-a fixed-format MPS file.  Some features of the MPS format are not 
-supported: comments beginning with dollar signs,
-the row types 'DE', 'DL', 'DG', and 'DN', and the capability of
-reading multiple righthand side, bound or range vectors.
-\end{funcdesc}
-
-
-\section{Examples}
-
-\begin{description}
-\item[Norm and Penalty Approximation]
-
-In the first example we solve the norm approximation problems
-\[
- \begin{array}{ll} 
- \mbox{minimize} & \|Ax - b\|_\infty,
- \end{array} \qquad
- \begin{array}{ll} 
- \mbox{minimize} & \|Ax - b\|_1
- \end{array},
-\]
-and the penalty approximation problem
-\[
- \begin{array}{ll} 
- \mbox{minimize} & \sum_k \phi((Ax-b)_k), 
- \end{array} \qquad
- \phi(u) = \left\{\begin{array}{ll}
-    0 & |u| \leq 3/4 \\
-   |u|-3/4  & 3/4 \leq |u| \leq 3/2 \\
-   2|u|-9/4  & |u| \geq 3/2.\end{array}\right.
-\]
-We use randomly generated data.
-
-The code uses the \ulink{Matplotlib}{http://matplotlib.sourceforge.net}
-package for plotting the histograms of the residual vectors for the
-two solutions.  It generates the figure shown below.
-
-\begin{verbatim}
-from cvxopt import normal
-from cvxopt.modeling import variable, op, max, sum
-import pylab
-
-m, n = 500, 100
-A = normal(m,n)
-b = normal(m)
-
-x1 = variable(n)
-op(max(abs(A*x1-b))).solve()
-
-x2 = variable(n)
-op(sum(abs(A*x2-b))).solve()
-
-x3 = variable(n)
-op(sum(max(0, abs(A*x3-b)-0.75, 2*abs(A*x3-b)-2.25))).solve()
-
-pylab.subplot(311)
-pylab.hist(A*x1.value-b, m/5)
-pylab.subplot(312)
-pylab.hist(A*x2.value-b, m/5)
-pylab.subplot(313)
-pylab.hist(A*x3.value-b, m/5)
-pylab.show()
-\end{verbatim}
-
-\begin{center}
-\includegraphics[width=15cm]{figures/normappr.eps}
-\end{center}
-
-Equivalently, we can formulate and solve the problems as LPs.
-\begin{verbatim}
-t = variable()
-x1 = variable(n)
-op(t, [-t <= A*x1-b, A*x1-b<=t]).solve()
-
-u = variable(m)
-x2 = variable(n)
-op(sum(u), [-u <= A*x2+b, A*x2+b <= u]).solve()
-
-v = variable(m)
-x3 = variable(n)
-op(sum(v), [v >= 0, v >= A*x3+b-0.75, v >= -(A*x3+b)-0.75, v >= 2*(A*x3-b)-2.25, v >= -2*(A*x3-b)-2.25]).solve()
-\end{verbatim}
-
-
-\item[Robust Linear Programming]
-The robust LP
-\[
- \begin{array}{ll}
- \mbox{minimize} & c^T x \\
- \mbox{subject to} & \sup_{\|v\|_\infty \leq 1} 
-    (a_i+v)^T x \leq b_i, \qquad i=1,\ldots,m
- \end{array}
-\]
-is equivalent to the problem
-\[
- \begin{array}{ll}
- \mbox{minimize} & c^Tx \\
- \mbox{subject to} & a_i^Tx + \|x\|_1 \leq b_i, \qquad i=1,\ldots,m.
- \end{array}
-\]
-The following code computes the solution and the solution of
-the equivalent LP
-\[
- \begin{array}{ll}
- \mbox{minimize} & c^Tx \\
- \mbox{subject to} & a_i^Tx + \ones^Ty \leq b_i, \qquad i=1,\ldots,m \\
-& -y \preceq x \preceq y
-\end{array}
-\]
-for randomly generated data.
-
-\begin{verbatim}
-from cvxopt import normal, uniform
-from cvxopt.modeling import variable, dot, op, sum 
-
-m, n = 500, 100
-A = normal(m,n)
-b = uniform(m)
-c = normal(n)
-
-x = variable(n)
-op(dot(c,x), A*x+sum(abs(x)) <= b).solve()
-
-x2 = variable(n)
-y = variable(n)
-op(dot(c,x2), [A*x2+sum(y) <= b, -y <= x2, x2 <= y]).solve()
-\end{verbatim}
-
-
-\item[1-Norm Support Vector Classifier]
-
-The following problem arises in classification:
-\[
-\begin{array}{ll}
-\mbox{minimize} & \|x\|_1 + \ones^Tu \\
-\mbox{subject to} & Ax \succeq \ones -u \\
-& u \succeq 0.
-\end{array}
-\]
-It can be solved as follows.
-\begin{verbatim}
-x = variable(A.size[1],'x')
-u = variable(A.size[0],'u')
-op(sum(abs(x)) + sum(u), [A*x >= 1-u, u >= 0]).solve()
-\end{verbatim}
-An equivalent unconstrained formulation is
-\begin{verbatim}
-x = variable(A.size[1],'x')
-op(sum(abs(x)) + sum(max(0,1-A*x))).solve()
-\end{verbatim}
-\end{description}
diff --git a/doc/printing.tex b/doc/printing.tex
deleted file mode 100644
index cf02b60..0000000
--- a/doc/printing.tex
+++ /dev/null
@@ -1,116 +0,0 @@
-\chapter{Matrix Formatting (\module{cvxopt.printing})}
-\label{chap:printing}
-
-This appendix describes ways to customize the formatting of CVXOPT matrices.
-
-As with other Python objects, the functions 
-\function{repr()} and \function{str()} return strings with printable
-representations of matrices.  
-The command \code{"print A"} calls the function \function{str(A)}, whereas
-the command \code{"A"} calls \function{repr(A)}.
-The following example illustrates the default formatting of dense matrices.
-\begin{verbatim}
->>> from cvxopt import matrix 
->>> A = matrix(range(50), (5,10), 'd')
->>> A  
-<5x10 matrix, tc='d'>
->>> print A
-[ 0.00e+00  5.00e+00  1.00e+01  1.50e+01  2.00e+01  2.50e+01  3.00e+01 ... ]
-[ 1.00e+00  6.00e+00  1.10e+01  1.60e+01  2.10e+01  2.60e+01  3.10e+01 ... ]
-[ 2.00e+00  7.00e+00  1.20e+01  1.70e+01  2.20e+01  2.70e+01  3.20e+01 ... ]
-[ 3.00e+00  8.00e+00  1.30e+01  1.80e+01  2.30e+01  2.80e+01  3.30e+01 ... ]
-[ 4.00e+00  9.00e+00  1.40e+01  1.90e+01  2.40e+01  2.90e+01  3.40e+01 ... ]
-\end{verbatim}
-The format is parameterized by the dictionary \member{options} in the 
-module \module{cvxopt.printing}.  
-The parameters \code{options['iformat']} and \code{options['dformat']}
-determine, respectively, how integer and double/complex numbers are 
-printed.  The entries are Python format strings with default 
-values \code{'\% .2e'}\ for \dtc\ and \ztc\ matrices and \code{'\% i'}\ for 
-\itc\ matrices. 
-The parameters \code{options['width']} and \code{options['height']}
-specify the maximum number of columns and rows that are shown. 
-If \code{'width'} is set to a negative value, all columns are displayed.
-If \code{'height'} is set to a negative value, all rows are displayed.
-The default values of \code{'width'} and \code{'height'} are 7 and -1,
-respectively.
-\begin{verbatim}
->>> from cvxopt import printing
->>> printing.options
-{'width': 7, 'dformat': '% .2e', 'iformat': '% i', 'height': -1}
->>> printing.options['dformat'] = '%.1f'
->>> printing.options['width'] = -1
->>> print A
-[ 0.0  5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0]
-[ 1.0  6.0 11.0 16.0 21.0 26.0 31.0 36.0 41.0 46.0]
-[ 2.0  7.0 12.0 17.0 22.0 27.0 32.0 37.0 42.0 47.0]
-[ 3.0  8.0 13.0 18.0 23.0 28.0 33.0 38.0 43.0 48.0]
-[ 4.0  9.0 14.0 19.0 24.0 29.0 34.0 39.0 44.0 49.0]
-\end{verbatim}
-
-In order to make the built-in Python functions \function{repr()} and 
-\function{str()} accessible for further customization, two functions
-are provided in \module{cvxopt}.  
-The function \function{cvxopt.matrix\_repr()} is used when \function{repr()}
-is called with a matrix argument;
-and \function{cvxopt.matrix\_str()} is used when \function{str()}
-is called with a matrix argument.  By default, the functions are set to
-\function{printing.matrix\_repr\_default()} and
-\function{printing.matrix\_str\_default()}, respectively,
-but they can be redefined to any other Python functions. 
-For example, if we prefer \code{"A"} to return the same output
-as \code{"print A"}, we can simply redefine 
-\function{cvxopt..matrix\_repr()} as shown below.
-\begin{verbatim}
->>> import cvxopt
->>> from cvxopt import matrix, printing
->>> A = matrix(range(4), (2,2), 'd')
->>> A
-<2x2 matrix, tc='d'>
->>> cvxopt.matrix_repr = printing.matrix_str_default
->>> A
-[ 0.00e+00  2.00e+00]
-[ 1.00e+00  3.00e+00]
-\end{verbatim}
-
-The formatting for sparse matrices is similar.  
-The functions \function{repr()} and \function{str()} for sparse
-matrices are \function{cvxopt.spmatrix\_repr()} 
-and \function{cvxopt.spmatrix\_str()}, respectively.
-By default, they are set to \function{printing.spmatrix\_repr\_default()}
-and \function{printing.spmatrix\_repr\_str()}.
-
-\begin{verbatim}
->>> import cvxopt
->>> from cvxopt import printing, spmatrix 
->>> A = spmatrix(range(5), range(5), range(5), (5,10))
->>> A
-<5x10 sparse matrix, tc='d', nnz=5>
->>> print A
-[ 0.00e+00     0         0         0         0         0         0     ... ]
-[    0      1.00e+00     0         0         0         0         0     ... ]
-[    0         0      2.00e+00     0         0         0         0     ... ]
-[    0         0         0      3.00e+00     0         0         0     ... ]
-[    0         0         0         0      4.00e+00     0         0     ... ]
-
->>> cvxopt.spmatrix_repr = printing.spmatrix_str_default
->>> A
-[ 0.00e+00     0         0         0         0         0         0     ... ]
-[    0      1.00e+00     0         0         0         0         0     ... ]
-[    0         0      2.00e+00     0         0         0         0     ... ]
-[    0         0         0      3.00e+00     0         0         0     ... ]
-[    0         0         0         0      4.00e+00     0         0     ... ]
-\end{verbatim}
-
-As can be seen from the example, the default behaviour is to print
-the entire matrix including structural zeros. An alternative triplet 
-printing style is defined in \function{printing.spmatrix\_str\_triplet}. 
-\begin{verbatim}
->>> cvxopt.spmatrix_str = printing.spmatrix_str_triplet
->>> print A
-(0,0)  0.00e+00
-(1,1)  1.00e+00
-(2,2)  2.00e+00
-(3,3)  3.00e+00
-(4,4)  4.00e+00
-\end{verbatim}
diff --git a/doc/solvers.tex b/doc/solvers.tex
deleted file mode 100644
index 7311b10..0000000
--- a/doc/solvers.tex
+++ /dev/null
@@ -1,1145 +0,0 @@
-\chapter{Nonlinear Convex Optimization (\module{cvxopt.solvers})}
-\label{chap:solvers}
-
-In this chapter we consider nonlinear convex 
-optimization problems of the form 
-\[ 
- \begin{array}{ll}
- \mbox{minimize} & f_0(x) \\
- \mbox{subject to} & f_k(x) \leq 0, \quad k=1,\ldots,m \\
-  & G x \preceq h  \\ 
-  & A x = b.
- \end{array}
-\]
-The functions \tm{\s{f}{k}} convex and twice differentiable and the linear
-inequalities are generalized inequalities with respect to a proper convex 
-cone, defined as a product of a nonnegative orthant, second-order cones, 
-and positive semidefinite cones.   
-
-The basic functions are \function{cp()} and \function{cpl()}, described in 
-sections~\ref{s-cp} and~\ref{s-cpl}.   A simpler interface for geometric 
-programming problems is discussed in section~\ref{s-gp}.
-In section~\ref{s-nlcp} we explain how custom solvers can be implemented 
-that exploit structure in specific classes of problems.
-The last section describes the algorithm parameters that control the 
-solvers.
-
-\section{Problems with Nonlinear Objectives} \label{s-cp}
-
-\begin{funcdesc}{cp}{F\optional{, G, h\optional{, dims\optional{, 
-A, b\optional{, kktsolver}}}}}
-Solves a convex optimization problem
-\BEQ \label{e-nlcp}
- \begin{array}{ll}
- \mbox{minimize} & f_0(x) \\
- \mbox{subject to} & f_k(x) \leq 0, \quad k=1,\ldots,m \\
-  & G x \preceq h  \\ 
-  & A x = b,
- \end{array}
-\EEQ
-The argument \var{F} is a function that evaluates the objective and 
-nonlinear constraint functions.  It must handle the following calling 
-sequences.
-
-\begin{itemize}
-\item \code{F()} returns a tuple (\var{m}, \var{x0}), where \var{m} is 
- the number of nonlinear constraints and \var{x0} is a point in the 
- domain of \tm{f}.  \var{x0} is a dense real matrix of size (\tm{n}, 1).
-
-\item \code{F(x)}, with \var{x} a dense real matrix of size (\tm{n},1), 
- returns a tuple (\var{f}, \var{Df}).  
- \var{f} is a dense real matrix of size \tm{(m+1,1)}, with 
- \code{\var{f}[\var{k}]} equal to \tm{\s{f}{k}(x)}. 
- (If \tm{m} is zero, \var{f} can also be returned as a number.)
- \var{Df} is a dense or sparse real matrix of size \tm{(m+1, n)} 
- with \code{\var{Df}[\var{k},:]} equal to the transpose of the gradient
- $\nabla f_k(x)$.  If \var{x} is not in the domain of \tm{f}, \code{F(x)} 
- returns \None\ or a tuple (\None,\None).
-
-\item \code{F(x,z)}, with \var{x} a dense real matrix of size 
- (\tm{n},1) and \var{z} a positive dense real matrix of size 
- (\tm{m}+1,1) returns a tuple (\var{f}, \var{Df}, \var{H}).  
- \var{f} and \var{Df} are defined as above.  
- \var{H} is a square dense or sparse real matrix of size (\tm{n}, \tm{n}), 
- whose lower triangular part contains the lower triangular part of
- \[
-  z_0 \nabla^2f_0(x) + z_1 \nabla^2f_1(x) + \cdots + z_m \nabla^2f_m(x).
- \]
- If \var{F} is called with two arguments, it can be assumed that 
- \tm{x} is in the domain of \tm{f}.
-\end{itemize}
-The linear inequalities are with respect to a cone \tm{C} defined as a 
-Cartesian product of a nonnegative orthant, a number of second-order 
-cones, and a number of positive semidefinite cones:
-\[
-C = C_0 \times C_1 \times \cdots \times C_M \times C_{M+1} \times
- \cdots \times C_{M+N}
-\]
-with
-\[
-C_0 = 
- \{ u \in \reals^l \;| \; u_k \geq 0, \; k=1, \ldots,l\}, \qquad 
-C_{k+1} = \{ (u_0, u_1) \in \reals \times \reals^{r_{k}-1} \; | \;
-   u_0 \geq \|u_1\|_2 \},  \quad k=0,\ldots, M-1, \qquad 
-C_{k+M+1} = \left\{ \svec(u) \; | \;
-  u \in \symm^{t_k}_+ \right\}, \quad k=0,\ldots,N-1.
-\]
-Here $\svec(u)$ denotes a symmetric matrix \tm{u} stored as a vector 
-in column major order.  
-
-The arguments \var{h} and \var{b} are real single-column dense 
-matrices.  \var{G} and \var{A} are real dense or sparse matrices.
-The default values for \var{A} and \var{b} are sparse matrices with 
-zero rows, meaning that there are no equality constraints.  
-The number of rows of \var{G} and \var{h} is equal to
-\[
- K = l + \sum_{k=0}^{M-1} r_k + \sum_{k=0}^{N-1} t_k^2.
-\]
-The columns of \var{G} and \var{h} are vectors in
-\[
-\reals^l \times \reals^{r_0} \times \cdots \times 
-\reals^{r_{M-1}} \times \reals^{t_0^2}  \times \cdots \times 
-\reals^{t_{N-1}^2},
-\]
-where the last \tm{N} components represent symmetric matrices stored in 
-column major order.  The strictly upper triangular entries of these 
-matrices are not accessed (i.e.,  the symmetric matrices are stored
-in the 'L'-type column major order used in the \module{blas} and
-\module{lapack} modules).
-
-The argument \var{dims} is a dictionary with the dimensions of the 
-cones.  It has three fields. 
-\begin{description}
-\item[\var{dims['l']}:] \tm{l}, the dimension of the nonnegative orthant
- (a nonnegative integer).
-\item[\var{dims['q']}:] $[r_0, \ldots, r_{M-1}]$, 
-a list with the dimensions of the second-order cones (positive integers).
-\item[\var{dims['s']}:] $[t_0, \ldots, t_{N-1}]$, 
-a list with the dimensions of the positive semidefinite cones
-(nonnegative integers).
-\end{description}
-
-The default value of \var{dims} is 
-\code{\{'l': h.size[0], 'q': [], 's': []\}}, \ie, the default assumption
-is that the linear inequalities are componentwise inequalities.
-
-The role of the optional argument \var{kktsolver} is explained in 
-section~\ref{s-nlcp}.  
-
-\function{cp()} returns a dictionary that contains the 
-result and information about the accuracy of the solution.
-The most important fields have keys \code{'status'}, 
-\code{'x'}, \code{'snl'}, \code{'sl'}, \code{'y'}, \code{'znl'}, 
-\code{'zl'}. 
-The possible values of the \code{'status'} key are:
-\begin{description}
-\item[\code{'optimal'}]  In this case the 
-\code{'x'} entry of the dictionary is the primal optimal solution,
-  the \code{'snl'} and \code{'sl'} entries are the corresponding
- slacks in the nonlinear and linear inequality constraints, and the 
-\code{'znl'}, \code{'zl'} and \code{'y'} entries are the optimal 
- values of the dual variables associated with the nonlinear 
- inequalities, the linear inequalities, and the linear equality 
- constraints.  These vectors approximately satisfy the 
- Karush-Kuhn-Tucker (KKT) conditions
-\[
- \nabla f_0(x) +  D\tilde f(x)^T z_\mathrm{nl} + 
- G^T z_\mathrm{l} + A^T y = 0, \qquad
-\tilde f(x) + s_\mathrm{nl} = 0, \quad k=1,\ldots,m, \qquad
- Gx + s_\mathrm{l} = h, \qquad
- Ax = b, 
-\]
-where $\tilde f = (f_1,\ldots, f_m)$,
-\[
-s_\mathrm{nl}\succeq 0, \qquad s_\mathrm{l}\succeq 0, \qquad 
-z_\mathrm{nl} \succeq 0, \qquad z_\mathrm{l} \succeq 0, \qquad
-s_\mathrm{nl}^T z_\mathrm{nl} +  s_\mathrm{l}^T z_\mathrm{l} = 0.
-\]
-
-\item[\code{'unknown'}] This indicates that the algorithm terminated 
-before a solution was found, due to numerical difficulties or because 
-the maximum number of iterations was reached.
-The \code{'x'}, \code{'snl'}, \code{'sl'}, \code{'y'}, \code{'znl'} and 
-\code{'zl'} contain the iterates when the algorithm terminated.
-\end{description}
-\function{cp()} solves the problem by applying \function{cpl()} to the 
-epigraph form problem
-\[
- \begin{array}{ll}
- \mbox{minimize} & t \\ 
- \mbox{subject to} & f_0(x) \leq t  \\ 
-   & f_k(x) \leq 0, \quad k =1, \ldots, m \\
-   & Gx \preceq h \\
-   & Ax = b.
- \end{array}
-\]
-The other entries in the output dictionary of \function{cp()} describe
-the accuracy of the solution and are copied from the output of 
-\function{cpl()} applied to this epigraph form problem.
-
-\function{cp()} requires that the problem is strictly primal and dual
-feasible and that 
-\[
-\Rank(A) = p, \qquad 
-\Rank\left(\left[\begin{array}{cccccc} 
-\sum_{k=0}^m z_k \nabla^2 f_k(x) & A^T &
- \nabla f_1(x) & \cdots \nabla f_m(x) & G^T \end{array}\right]\right) = n,
-\]
-for all \tm{x} and all positive \tm{z}. 
-\end{funcdesc}
-
-
-\begin{description}
-\item[Example: equality constrained analytic centering]
-
-The equality constrained analytic centering problem is defined as
-\[
- \begin{array}{ll}
- \mbox{minimize} & -\sum_{i=1}^m \log x_i \\
- \mbox{subject to} & Ax = b. 
- \end{array}
-\]
-The function \function{acent()} defined  below solves the problem, 
-assumping it is solvable.
-
-\begin{verbatim}
-from cvxopt import solvers, matrix, spdiag, log
-
-def acent(A, b):
-    m, n = A.size
-    def F(x=None, z=None):
-        if x is None: return 0, matrix(1.0, (n,1))
-        if min(x) <= 0.0: return None
-        f = -sum(log(x))
-        Df = -(x**-1).T 
-        if z is None: return f, Df
-        H = spdiag(z[0] * x**-2)
-        return f, Df, H
-    return solvers.cp(F, A=A, b=b)['x']
-\end{verbatim}
-
-\item[Example: robust least-squares]
-
-The function \function{robls()} defined below solves the unconstrained 
-problem
-\[
-\begin{array}{ll}
-\mbox{minimize} &  \sum_{k=1}^m \phi((Ax-b)_k), 
-\end{array} \qquad \mbox{where} \quad A \in\reals^{m\times n}, \quad
-\phi(u) = \sqrt{\rho + u^2}.
-\]
-
-\begin{verbatim}
-from cvxopt import solvers, matrix, spdiag, sqrt, div
-
-def robls(A, b, rho): 
-    m, n = A.size
-    def F(x=None, z=None):
-        if x is None: return 0, matrix(0.0, (n,1))
-        y = A*x-b
-        w = sqrt(rho + y**2)
-        f = sum(w)
-        Df = div(y, w).T * A 
-        if z is None: return f, Df 
-        H = A.T * spdiag(z[0]*rho*(w**-3)) * A
-        return f, Df, H
-    return solvers.cp(F)['x']
-\end{verbatim}
-
-\item[Example: analytic centering with cone constraints]
-\[
- \begin{array}{ll}
- \mbox{minimize} & - \log(1-x_1^2) - \log(1-x_2^2) - \log(1-x_3^2) \\*[1ex]
- \mbox{subject to} & \|x\|_2 \leq 1 \\*[1ex]
- &   x_1 \left[\begin{array}{rrr} 
-   -21 & -11 & 0 \\ -11 & 10 & 8 \\ 0 & 8 & 5 
-  \end{array}\right] +
-   x_2 \left[\begin{array}{rrr} 
-   0 & 10 & 16 \\ 10 & -10 & -10 \\ 16 & -10 & 3 
-  \end{array}\right] +
-   x_3 \left[\begin{array}{rrr} 
-   -5 & 2 & -17 \\ 2 & -6 & 8 \\ -17 & -7 & 6 
-  \end{array}\right] \preceq \left[\begin{array}{rrr}
-   20 & 10 & 40 \\ 10 & 80 & 10 \\ 40 & 10 & 15 \end{array}\right].
- \end{array}
-\]
-
-\begin{verbatim}
-from cvxopt import matrix, log, div, spdiag, solvers
-
-def F(x = None, z = None):
-     if x is None:  return 0, matrix(0.0, (3,1)) 
-     if max(abs(x)) >= 1.0:  return None
-     u = 1 - x**2
-     val = -sum(log(u))
-     Df = div(2*x, u).T
-     if z is None:  return val, Df
-     H = spdiag(2 * z[0] * div(1 + u**2, u**2))
-     return val, Df, H
-
-G = matrix([ [0., -1.,  0.,  0., -21., -11.,   0., -11.,  10.,   8.,   0.,   8., 5.], 
-             [0.,  0., -1.,  0.,   0.,  10.,  16.,  10., -10., -10.,  16., -10., 3.], 
-             [0.,  0.,  0., -1.,  -5.,   2., -17.,   2.,  -6.,   8., -17.,  -7., 6.] ])  
-h = matrix([1.0, 0.0, 0.0, 0.0, 20., 10., 40., 10., 80., 10., 40., 10., 15.])
-dims = {'l': 0, 'q': [4], 's':  [3]}
-sol = solvers.cp(F, G, h, dims)
-print sol['x']
-[ 4.11e-01]
-[ 5.59e-01]
-[-7.20e-01]
-\end{verbatim}
-\end{description}
-
-
-\section{Problems with Linear Objectives} \label{s-cpl}
-
-\begin{funcdesc}{cpl}{c, F\optional{, G, h\optional{, dims\optional{, 
-A, b\optional{, kktsolver}}}}}
-Solves a convex optimization problem with a linear objective
-\[
- \begin{array}{ll}
- \mbox{minimize} & c^T x \\
- \mbox{subject to} & f_k(x) \leq 0, \quad k=0,\ldots,m-1 \\
-  & G x \preceq h  \\ 
-  & A x = b.
- \end{array}
-\]
-
-\var{c} is a real single-column dense matrix.  
-
-\var{F} is a function that evaluates the nonlinear constraint functions.  
-It must handle the following calling sequences.
-
-\begin{itemize}
-\item \code{F()} returns a tuple (\var{m}, \var{x0}), where \tm{m} is 
- the number of nonlinear constraints and \var{x0} is a point in the 
- domain of \tm{f}.  \var{x0} is a dense real matrix of size (\tm{n}, 1).
-
-\item \code{F(x)}, with \var{x} a dense real matrix of size \tm{(n, 1)}, 
- returns a tuple (\var{f}, \var{Df}).  \var{f} is a dense real matrix of 
- size (\tm{m}, 1), with \code{\var{f}[\var{k}]} equal to \tm{\s{f}{k}(x)}. 
- \var{Df} is a dense or sparse real matrix of size \tm{(m,n)} 
- with \code{\var{Df}[\var{k},:]} equal to the transpose of the gradient
- $\nabla f_k(x)$.
- If \var{x} is not in the domain of \tm{f}, \code{F(x)} returns 
- \None\ or a tuple (\None,\None).
-
-\item \code{F(x,z)}, with \var{x} a dense real matrix of size 
- (\tm{n},1) and \var{z} a positive dense real matrix of size 
- (\tm{m},1) returns a tuple (\var{f}, \var{Df}, \var{H}).  
- \var{f} and \var{Df} are defined as above.  
- \var{H} is a square dense or sparse real matrix of size 
- (\tm{n},\tm{n}), whose lower triangular part contains the lower 
- triangular part of
- \[
-  z_0 \nabla^2f_0(x) + z_1 \nabla^2f_1(x) + \cdots + 
- z_{m-1} \nabla^2f_{m-1}(x).
- \]
- If \var{F} is called with two arguments, it can be assumed that 
- \tm{x} is in the domain of \tm{f}.
-\end{itemize}
-The linear inequalities are with respect to a cone \tm{C} defined as a 
-Cartesian product of a nonnegative orthant, a number of second-order 
-cones, and a number of positive semidefinite cones:
-\[
-C = C_0 \times C_1 \times \cdots \times C_M \times C_{M+1} \times
- \cdots \times C_{M+N}
-\]
-with
-\[
-C_0 = 
- \{ u \in \reals^l \;| \; u_k \geq 0, \; k=1, \ldots,l\}, \qquad 
-C_{k+1} = \{ (u_0, u_1) \in \reals \times \reals^{r_{k}-1} \; | \;
-   u_0 \geq \|u_1\|_2 \},  \quad k=0,\ldots, M-1, \qquad 
-C_{k+M+1} = \left\{ \svec(u) \; | \;
-  u \in \symm^{t_k}_+ \right\}, \quad k=0,\ldots,N-1.
-\]
-Here $\svec(u)$ denotes a symmetric matrix \tm{u} stored as a vector 
-in column major order.  
-
-The arguments \var{h} and \var{b} are real single-column dense 
-matrices.  \var{G} and \var{A} are real dense or sparse matrices.
-The default values for \var{A} and \var{b} are sparse matrices with 
-zero rows, meaning that there are no equality constraints.  
-The number of rows of \var{G} and \var{h} is equal to
-\[
- K = l + \sum_{k=0}^{M-1} r_k + \sum_{k=0}^{N-1} t_k^2.
-\]
-The columns of \var{G} and \var{h} are vectors in
-\[
-\reals^l \times \reals^{r_0} \times \cdots \times 
-\reals^{r_{M-1}} \times \reals^{t_0^2}  \times \cdots \times 
-\reals^{t_{N-1}^2},
-\]
-where the last \tm{N} components represent symmetric matrices stored in 
-column major order.  The strictly upper triangular entries of these 
-matrices are not accessed (i.e.,  the symmetric matrices are stored
-in the 'L'-type column major order used in the \module{blas} and
-\module{lapack} modules).
-
-The argument \var{dims} is a dictionary with the dimensions of the 
-cones.  It has three fields. 
-\begin{description}
-\item[\var{dims['l']}:] \tm{l}, the dimension of the nonnegative orthant
- (a nonnegative integer).
-\item[\var{dims['q']}:] $[r_0, \ldots, r_{M-1}]$, 
-a list with the dimensions of the second-order cones (positive integers).
-\item[\var{dims['s']}:] $[t_0, \ldots, t_{N-1}]$, 
-a list with the dimensions of the positive semidefinite cones
-(nonnegative integers).
-\end{description}
-
-The default value of \var{dims} is 
-\code{\{'l': h.size[0], 'q': [], 's': []\}}, \ie, the default assumption
-is that the linear inequalities are componentwise inequalities.
-
-The role of the optional argument \var{kktsolver} is explained in 
-section~\ref{s-nlcp}.  
-
-\function{cpl()} returns a dictionary that contains the 
-result and information about the accuracy of the solution.
-The most important fields have keys \code{'status'}, 
-\code{'x'}, \code{'snl'}, \code{'sl'}, \code{'y'}, \code{'znl'}, 
-\code{'zl'}. 
-The possible values of the \code{'status'} key are:
-\begin{description}
-\item[\code{'optimal'}]  In this case the 
-\code{'x'} entry of the dictionary is the primal optimal solution,
-  the \code{'snl'} and \code{'sl'} entries are the corresponding
- slacks in the nonlinear and linear inequality constraints, and the 
-\code{'znl'}, \code{'zl'} and \code{'y'} entries are the optimal 
- values of the dual variables associated with the nonlinear 
- inequalities, the linear inequalities, and the linear equality 
- constraints.  These vectors approximately satisfy the 
- Karush-Kuhn-Tucker (KKT) conditions
-\[
- c +  Df(x)^T z_\mathrm{nl} + G^T z_\mathrm{l} + A^T y = 0, \qquad
- f(x) + s_\mathrm{nl} = 0, \quad k=1,\ldots,m, \qquad
- Gx + s_\mathrm{l} = h, \qquad Ax = b, 
-\]
-\[
-s_\mathrm{nl}\succeq 0, \qquad s_\mathrm{l}\succeq 0, \qquad 
-z_\mathrm{nl} \succeq 0, \qquad z_\mathrm{l} \succeq 0, \qquad
-s_\mathrm{nl}^T z_\mathrm{nl} +  s_\mathrm{l}^T z_\mathrm{l} = 0.
-\]
-
-\item[\code{'unknown'}] 
-This indicates that the algorithm terminated 
-before a solution was found, due to numerical difficulties or because 
-the maximum number of iterations was reached.
-The \code{'x'}, \code{'snl'}, \code{'sl'}, \code{'y'}, \code{'znl'} and 
-\code{'zl'} contain the iterates when the algorithm terminated.
-\end{description}
-The other entries in the output dictionary describe the accuracy
-of the solution. 
-The entries \code{'primal objective'}, \code{'dual objective'}, 
-\code{'gap'}, and
-\code{'relative gap'}, give the primal objective \tm{c^Tx},
-the dual objective calculated as
-\[
-   c^Tx + z_\mathrm{nl}^T f(x) + z_\mathrm{l}^T (Gx - h) + y^T(Ax-b),
-\]
-the duality gap 
-\[
-  s_\mathrm{nl}^T z_\mathrm{nl} +  s_\mathrm{l}^T z_\mathrm{l},
-\]
-and the relative gap.  The relative gap is defined as 
-\[
- \frac{\mbox{gap}}{-\mbox{primal objective}}
- \quad \mbox{if\ } \mbox{primal objective} < 0, \qquad
- \frac{\mbox{gap}}{\mbox{dual objective}}
- \quad \mbox{if\ } \mbox{dual objective} > 0, \qquad
-\]
-and \None\ otherwise.  The entry with key \code{'primal infeasibility'}
-gives the residual in the primal constraints, 
-\[
-\frac{\| ( f(x) + s_{\mathrm{nl}},  Gx + s_\mathrm{l} - h, 
- Ax-b ) \|_2} 
-{\max\{1, \| ( f(x_0) + \ones,  
-Gx_0 + \ones-h, Ax_0-b) \|_2 \}} 
-\]
-where \tm{\s{x}{0}} is the point returned by \code{F()}. 
-The entry with key \code{'dual infeasibility'} gives the residual
-\[
-\frac{\| c +  Df(x)^Tz_\mathrm{nl} + 
- G^Tz_\mathrm{l} + A^T y \|_2 }
-{\max\{ 1, 
-\| c + Df(x_0)^T\ones + G^T\ones \|_2 \}} 
-\leq \epsilon_\mathrm{feas}. 
-\]
-
-\function{cpl()} requires that the problem is strictly primal and
-dual feasible and that 
-\[
-\Rank(A) = p, \qquad 
-\Rank\left(\left[\begin{array}{cccccc} 
-\sum_{k=0}^{m-1} z_k \nabla^2 f_k(x) & A^T &
- \nabla f_0(x) & \cdots \nabla f_{m-1}(x) & G^T \end{array}\right]\right) 
- = n,
-\]
-for all \tm{x} and all positive \tm{z}. 
-\end{funcdesc}
-
-
-\begin{description}
-\item[Example: floor planning]
-
-This example is the floor planning problem of section 8.8.2 in the book 
-\seelink{http://www.stanford.edu/\%7eboyd/cvxbook}{Convex Optimization}{}: 
-\[
-\begin{array}{ll}
- \mbox{minimize} & W + H \\
- \mbox{subject to} & A_{\mathrm{min}, k}/h_k - w_k \leq 0, 
-        \quad k=1,\ldots, 5  \\ 
-   &  x_1 \geq 0, \quad x_2 \geq 0,  \quad x_4 \geq 0 \\
-   & x_1 + w_1 + \rho \leq x_3, \quad x_2 + w_2 + \rho \leq x_3, \quad 
-     x_3 + w_3 + \rho \leq x_5, \quad x_4 + w_4 + \rho \leq x_5, \quad
-     x_5 + w_5 \leq W \\
-   & y_2 \geq 0,  \quad y_3 \geq 0, \quad y_5 \geq 0  \\
-   & y_2 + h_2 + \rho \leq y_1, \quad y_1 + h_1 + \rho \leq y_4, \quad 
-     y_3 + h_3 + \rho \leq y_4, \quad y_4 + h_4 \leq H, \quad
-     y_5 + h_5 \leq H \\
-   & h_k/\gamma \leq w_k \leq \gamma h_k, \quad k=1,\ldots,5.
-\end{array}
-\]
-This problem has 22 variables 
-\[
-W, \qquad H, \qquad x\in\reals^5, \qquad y\in\reals^5, \qquad
-w\in\reals^5, \qquad h\in\reals^5,
-\]
-5 nonlinear inequality constraints, and 26 linear inequality 
-constraints.  The code belows defines a function
-\function{floorplan()} that solves the problem by calling
-\function{cp()},  then applies it to  4 instances, and creates 
-a figure.
-
-\begin{verbatim}
-import pylab
-from cvxopt import solvers, matrix, spmatrix, mul, div
-
-def floorplan(Amin):
-
-    #     minimize    W+H
-    #     subject to  Amink / hk <= wk, k = 1,..., 5 
-    #                 x1 >= 0,  x2 >= 0, x4 >= 0
-    #                 x1 + w1 + rho <= x3  
-    #                 x2 + w2 + rho <= x3 
-    #                 x3 + w3 + rho <= x5  
-    #                 x4 + w4 + rho <= x5
-    #                 x5 + w5 <= W
-    #                 y2 >= 0,  y3 >= 0,  y5 >= 0 
-    #                 y2 + h2 + rho <= y1 
-    #                 y1 + h1 + rho <= y4 
-    #                 y3 + h3 + rho <= y4
-    #                 y4 + h4 <= H  
-    #                 y5 + h5 <= H
-    #                 hk/gamma <= wk <= gamma*hk,  k = 1, ..., 5
-    #
-    # 22 Variables W, H, x (5), y (5), w (5), h (5).
-    #
-    # W, H:  scalars; bounding box width and height
-    # x, y:  5-vectors; coordinates of bottom left corners of blocks
-    # w, h:  5-vectors; widths and heigths of the 5 blocks
-
-    rho, gamma = 1.0, 5.0   # min spacing, min aspect ratio
-
-    # The objective is to minimize W + H.  There are five nonlinear 
-    # constraints 
-    #
-    #     -wk + Amink / hk <= 0,  k = 1, ..., 5
-
-    c = matrix(2*[1.0] + 20*[0.0])
-
-    def F(x=None, z=None):
-        if x is None:  return 5, matrix(17*[0.0] + 5*[1.0])
-        if min(x[17:]) <= 0.0:  return None 
-        f = -x[12:17] + div(Amin, x[17:]) 
-        Df = matrix(0.0, (5,22))
-        Df[:,12:17] = spmatrix(-1.0, range(5), range(5))
-        Df[:,17:] = spmatrix(-div(Amin, x[17:]**2), range(5), range(5))
-        if z is None: return f, Df
-        H = spmatrix( 2.0* mul(z, div(Amin, x[17::]**3)), range(17,22), range(17,22) )
-        return f, Df, H
-
-    G = matrix(0.0, (26,22)) 
-    h = matrix(0.0, (26,1))
-    G[0,2] = -1.0                                       # -x1 <= 0
-    G[1,3] = -1.0                                       # -x2 <= 0 
-    G[2,5] = -1.0                                       # -x4 <= 0
-    G[3, [2, 4, 12]], h[3] = [1.0, -1.0, 1.0], -rho     # x1 - x3 + w1 <= -rho 
-    G[4, [3, 4, 13]], h[4] = [1.0, -1.0, 1.0], -rho     # x2 - x3 + w2 <= -rho 
-    G[5, [4, 6, 14]], h[5] = [1.0, -1.0, 1.0], -rho     # x3 - x5 + w3 <= -rho 
-    G[6, [5, 6, 15]], h[6] = [1.0, -1.0, 1.0], -rho     # x4 - x5 + w4 <= -rho 
-    G[7, [0, 6, 16]] = -1.0, 1.0, 1.0                   # -W + x5 + w5 <= 0
-    G[8,8] = -1.0                                       # -y2 <= 0 
-    G[9,9] = -1.0                                       # -y3 <= 0 
-    G[10,11] = -1.0                                     # -y5 <= 0 
-    G[11, [7, 8, 18]], h[11] = [-1.0, 1.0, 1.0], -rho   # -y1 + y2 + h2 <= -rho 
-    G[12, [7, 10, 17]], h[12] = [1.0, -1.0, 1.0], -rho  #  y1 - y4 + h1 <= -rho 
-    G[13, [9, 10, 19]], h[13] = [1.0, -1.0, 1.0], -rho  #  y3 - y4 + h3 <= -rho 
-    G[14, [1, 10, 20]] = -1.0, 1.0, 1.0                 # -H + y4 + h4 <= 0  
-    G[15, [1, 11, 21]] = -1.0, 1.0, 1.0                 # -H + y5 + h5 <= 0
-    G[16, [12, 17]] = -1.0, 1.0/gamma                   # -w1 + h1/gamma <= 0 
-    G[17, [12, 17]] = 1.0, -gamma                       #  w1 - gamma * h1 <= 0
-    G[18, [13, 18]] = -1.0, 1.0/gamma                   # -w2 + h2/gamma <= 0 
-    G[19, [13, 18]] = 1.0, -gamma                       #  w2 - gamma * h2 <= 0
-    G[20, [14, 18]] = -1.0, 1.0/gamma                   # -w3 + h3/gamma <= 0  
-    G[21, [14, 19]] = 1.0, -gamma                       #  w3 - gamma * h3 <= 0
-    G[22, [15, 19]] = -1.0, 1.0/gamma                   # -w4  + h4/gamma <= 0 
-    G[23, [15, 20]] = 1.0, -gamma                       #  w4 - gamma * h4 <= 0
-    G[24, [16, 21]] = -1.0, 1.0/gamma                   # -w5 + h5/gamma <= 0 
-    G[25, [16, 21]] = 1.0, -gamma                       #  w5 - gamma * h5 <= 0.0
-
-    # solve and return W, H, x, y, w, h 
-    sol = solvers.cpl(c, F, G, h)  
-    return  sol['x'][0], sol['x'][1], sol['x'][2:7], sol['x'][7:12], sol['x'][12:17], sol['x'][17:] 
-
-pylab.figure(facecolor='w')
-pylab.subplot(221)
-Amin = matrix([100., 100., 100., 100., 100.])
-W, H, x, y, w, h =  floorplan(Amin)
-for k in xrange(5):
-    pylab.fill([x[k], x[k], x[k]+w[k], x[k]+w[k]], 
-               [y[k], y[k]+h[k], y[k]+h[k], y[k]], facecolor = '#D0D0D0')
-    pylab.text(x[k]+.5*w[k], y[k]+.5*h[k], "%d" %(k+1))
-pylab.axis([-1.0, 26, -1.0, 26])
-pylab.xticks([])
-pylab.yticks([])
-
-pylab.subplot(222)
-Amin = matrix([20., 50., 80., 150., 200.])
-W, H, x, y, w, h =  floorplan(Amin)
-for k in xrange(5):
-    pylab.fill([x[k], x[k], x[k]+w[k], x[k]+w[k]], 
-               [y[k], y[k]+h[k], y[k]+h[k], y[k]], 'facecolor = #D0D0D0')
-    pylab.text(x[k]+.5*w[k], y[k]+.5*h[k], "%d" %(k+1))
-pylab.axis([-1.0, 26, -1.0, 26])
-pylab.xticks([])
-pylab.yticks([])
-
-pylab.subplot(223)
-Amin = matrix([180., 80., 80., 80., 80.])
-W, H, x, y, w, h =  floorplan(Amin)
-for k in xrange(5):
-    pylab.fill([x[k], x[k], x[k]+w[k], x[k]+w[k]], 
-               [y[k], y[k]+h[k], y[k]+h[k], y[k]], 'facecolor = #D0D0D0')
-    pylab.text(x[k]+.5*w[k], y[k]+.5*h[k], "%d" %(k+1))
-pylab.axis([-1.0, 26, -1.0, 26])
-pylab.xticks([])
-pylab.yticks([])
-
-pylab.subplot(224)
-Amin = matrix([20., 150., 20., 200., 110.])
-W, H, x, y, w, h =  floorplan(Amin)
-for k in xrange(5):
-    pylab.fill([x[k], x[k], x[k]+w[k], x[k]+w[k]], 
-               [y[k], y[k]+h[k], y[k]+h[k], y[k]], 'facecolor = #D0D0D0')
-    pylab.text(x[k]+.5*w[k], y[k]+.5*h[k], "%d" %(k+1))
-pylab.axis([-1.0, 26, -1.0, 26])
-pylab.xticks([])
-pylab.yticks([])
-
-pylab.show()
-\end{verbatim}
-
-\begin{center}
-\includegraphics[width=15cm]{figures/floorplan.eps}
-\end{center}
-\end{description}
-
-
-\section{Geometric Programming} \label{s-gp}
-\begin{funcdesc}{gp}{K, F, g \optional{, G, h \optional{, A, b}}}
-Solves a geometric program in convex form
-\[
-\begin{array}{ll}
-\mbox{minimize} & f_0(x) = \lse(F_0x+g_0) \\ 
-\mbox{subject to} & f_i(x) = \lse(F_ix+g_i) \leq 0,\quad i=1,\ldots,m \\
- & Gx \preceq h \\
- & Ax=b
-\end{array}
-\]
-where
-\[
- \lse(u) = \log \sum_k \exp(u_k), \qquad
- F = \left[ \begin{array}{cccc}
- F_0^T & F_1^T & \cdots & F_m^T \end{array}\right]^T, \qquad
- g = \left[ \begin{array}{cccc}
- g_0^T & g_1^T & \cdots & g_m^T \end{array}\right]^T, 
-\]
-and the vector inequality denotes componentwise inequality.
-\var{K} is a list of \tm{m+1} positive integers with 
-\code{\var{K}[\var i]}
-equal to the number of rows in \tm{\s{F}{i}}.
-\var{F} is a dense or sparse real matrix of 
-size \code{(sum(\var K),\var n)}.
-\var{g} is a dense real matrix with one column and the same number of
-rows as \var{F}.
-\var{G} and \var{A} are dense or sparse real matrices.
-Their default values are sparse matrices with zero rows.
-\var{h} and \var{b} are dense real matrices with one column.
-Their default values are matrices of size (0,1).
-
-\function{gp()} returns a dictionary with keys 
-\code{'status'}, \code{'x'}, \code{'snl'}, \code{'sl'}, 
-\code{'y'}, \code{'znl'} and \code{'zl'}.
-The possible values of the \code{'status'} key are:
-\begin{description}
-\item[\code{'optimal'}]  In this case the 
-\code{'x'} entry is the primal optimal solution,
-the \code{'snl'} and \code{'sl'} entries are the corresponding slacks 
-in the nonlinear and linear inequality constraints. 
-The \code{'znl'}, \code{'zl'} and \code{'y'} entries are the optimal 
-values of the dual variables associated with the nonlinear and linear 
-inequality constraints and the linear equality constraints.
-These values approximately satisfy
-\[
- \nabla f_0(x) + \sum_{k=1}^m z_{\mathrm{nl},k} 
- \nabla f_k(x) + G^T z_\mathrm{l} + A^T y = 0, \qquad
- f_k(x) + s_{\mathrm{nl},k} = 0, \quad k=1,\ldots,m,   \qquad 
- Gx + s_\mathrm{l} = h, \qquad Ax=b
-\]
-and
-\[
-s_\mathrm{nl}\succeq 0, \qquad s_\mathrm{l}\succeq 0, \qquad 
-z_\mathrm{nl} \succeq 0, \qquad z_\mathrm{l} \succeq 0, \qquad
-s_\mathrm{nl}^T z_\mathrm{nl} + s_\mathrm{l}^T z_\mathrm{l} = 0.
-\]
-
-\item[\code{'unknown'}] 
-This indicates that the algorithm terminated 
-before a solution was found, due to numerical difficulties or because 
-the maximum number of iterations was reached.
-The \code{'x'}, \code{'snl'}, \code{'sl'}, \code{'y'}, \code{'znl'} and 
-\code{'zl'} contain the iterates when the algorithm terminated.
-\end{description}
-The other entries in the output dictionary describe the accuracy
-of the solution, and are taken from the output of \function{cp()}.
-\end{funcdesc}
-
-As an example, we solve the small GP of section 2.4 of the paper 
-\citetitle{http://www.stanford.edu/\%7eboyd/\s{gp}{tutorial}.html}{A Tutorial on Geometric Programming}.  
-The  posynomial form of the problem is
-\[
- \begin{array}{ll}
- \mbox{minimize} & w^{-1} h^{-1} d^{-1} \\ 
- \mbox{subject to} 
-  & (2/A_\mathrm{wall}) hw + (2/A_\mathrm{wall})hd \leq 1  \\
-  &  (1/A_\mathrm{flr}) wd \leq 1 \\
-  &  \alpha wh^{-1} \leq 1 \\
-  &  (1/\beta) hw^{-1} \leq 1 \\
-  &  \gamma wd^{-1} \leq 1 \\
-  &   (1/\delta)dw^{-1} \leq 1
- \end{array}
-\]
-with variables \tm{h}, \tm{w}, \tm{d}.
-
-\begin{verbatim}
-from cvxopt import matrix, log, exp, solvers
-
-Aflr  = 1000.0
-Awall = 100.0
-alpha = 0.5
-beta  = 2.0
-gamma = 0.5
-delta = 2.0
-
-F = matrix( [[-1., 1., 1., 0., -1.,  1.,  0.,  0.], 
-             [-1., 1., 0., 1.,  1., -1.,  1., -1.], 
-             [-1., 0., 1., 1.,  0.,  0., -1.,  1.]])
-g = log( matrix( [1.0, 2/Awall, 2/Awall, 1/Aflr, alpha, 1/beta, gamma, 1/delta]) )
-K = [1, 2, 1, 1, 1, 1, 1]
-h, w, d = exp( solvers.gp(K, F, g)['x'] )
-\end{verbatim}
-
-
-\section{Exploiting Structure} \label{s-nlcp}
-By default, the functions \function{cp()} and \function{cpl()} do not
-exploit problem structure.
-Two mechanisms are provided for implementing customized solvers that 
-take advantage of problem structure.
-
-\begin{description}
-\item[\emph{Providing a function for solving KKT equations.}]
-The most expensive step of each iteration of \function{cp()} is the
-solution of a set of linear equations (`KKT equations') of the form
-\BEQ \label{e-cp-kkt}
- \left[\begin{array}{ccc}
-  H & A^T & \tilde G^T \\
-  A & 0   & 0  \\
-  \tilde G & 0   & -W^T W \end{array}\right]
- \left[\begin{array}{c} u_x \\ u_y \\ u_z \end{array}\right]
- = \left[\begin{array}{c} b_x \\ b_y \\ b_z \end{array}\right],
-\EEQ
-where 
-\[
- H = \sum_{k=0}^m z_k \nabla^2f_k(x), \qquad
- \tilde G = \left[\begin{array}{cccc}
- \nabla f_1(x) & \cdots & \nabla f_m(x) & G^T \end{array}\right]^T.
-\]
-
-The matrix \tm{W} depends on the current iterates and is defined as 
-follows.  Suppose 
-\[
- u = \left(u_\mathrm{nl}, \; u_\mathrm{l}, \; u_{\mathrm{q},0}, \; 
-  \ldots, \; 
- u_{\mathrm{q},M-1}, \; \svec{(u_{\mathrm{s},0})}, \; \ldots, \; 
-  \svec{(u_{\mathrm{s},N-1})}\right), \qquad
- u_\mathrm{nl} \in\reals^m, \qquad 
- u_\mathrm{l} \in\reals^l, \qquad 
- u_{\mathrm{q},k} \in\reals^{r_k}, \quad k = 0,\ldots,M-1, \qquad 
- u_{\mathrm{s},k} \in\symm^{t_k},  \quad k = 0,\ldots,N-1.
-\]
-Then \tm{W} is a block-diagonal matrix, 
-\[
- Wu = \left( W_\mathrm{nl} u_\mathrm{nl}, \; 
- W_\mathrm{l} u_\mathrm{l}, \;
- W_{\mathrm{q},0} u_{\mathrm{q},0}, \; \ldots, \;
- W_{\mathrm{q},M-1} u_{\mathrm{q},M-1},\; 
- W_{\mathrm{s},0} \svec{(u_{\mathrm{s},0})}, \; \ldots, \;
- W_{\mathrm{s},N-1} \svec{(u_{\mathrm{s},N-1})} \right)
-\]
-with the following diagonal blocks.
-\BIT
-\item The first block is a \emph{positive diagonal scaling} with a 
- vector $d_{\mathrm{nl}}$:
-\[
-  W_\mathrm{nl} = \diag(d_\mathrm{nl}), 
- \qquad W_\mathrm{nl}^{-1} = \diag(d_\mathrm{nl})^{-1}.
-\]
-This transformation is symmetric:
-\[
-  W_\mathrm{nl}^T = W_\mathrm{nl}. 
-\]
-
-\item The second block is a \emph{positive diagonal scaling} with a 
- vector $d_{\mathrm{l}}$:
-\[
-  W_\mathrm{l} = \diag(d_\mathrm{l}), 
- \qquad W_\mathrm{l}^{-1} = \diag(d_\mathrm{l})^{-1}.
-\]
-This transformation is symmetric:
-\[
-  W_\mathrm{l}^T = W_\mathrm{l}. 
-\]
-
-\item The next \tm{M} blocks are positive multiples of \emph{hyperbolic 
- Householder transformations}:
-\[
-  W_{\mathrm{q},k} = \beta_k ( 2 v_k v_k^T - J),
- \qquad
-  W_{\mathrm{q},k}^{-1} = \frac{1}{\beta_k} ( 2 Jv_k v_k^T J - J),
- \qquad k = 0,\ldots,M-1,
-\]
-where
-\[
- \beta_k > 0, \qquad v_{k0} > 0, \qquad 
- v_k^T Jv_k = 1, \qquad J = \left[\begin{array}{cc}
-   1 & 0 \\ 0 & -I \end{array}\right].
-\]
-These transformations are also symmetric:
-\[
-  W_{\mathrm{q},k}^T = W_{\mathrm{q},k}. 
-\]
-
-\item The last \tm{N} blocks are \emph{congruence transformations} with 
- nonsingular matrices:
-\[
-  W_{\mathrm{s},k} \svec{(u_{\mathrm{s},k})} = 
-  \svec{(r_k^T u_{\mathrm{s},k} r_k)}, \qquad
-  W_{\mathrm{s},k}^{-1} \svec{(u_{\mathrm{s},k})} = 
- \svec{(r_k^{-T} u_{\mathrm{s},k} r_k^{-1})}, \qquad
- k = 0,\ldots,N-1.
-\]
-In  general, this operation is not symmetric, and
-\[
-  W_{\mathrm{s},k}^T \svec{(u_{\mathrm{s},k})} = 
-  \svec{(r_k u_{\mathrm{s},k} r_k^T)}, \qquad
- \qquad
-  W_{\mathrm{s},k}^{-T} \svec{(u_{\mathrm{s},k})} = 
- \svec{(r_k^{-1} u_{\mathrm{s},k} r_k^{-T})}, \qquad
- \qquad
- k = 0,\ldots,N-1.
-\]
-\EIT
-It is often possible to exploit problem structure
-to solve~(\ref{e-cp-kkt}) faster than by 
-standard methods.  The last argument \var{kktsolver} of 
-\function{cp()} allows the user to supply a Python  function for 
-solving the KKT equations.
-This function will be called as \samp{f = kktsolver(x, z, W)}. 
-The argument \var{x} is the point at which the derivatives in the
-KKT matrix are evaluated.  \var{z} is a positive vector of 
-length it \tm{m + 1}, containing the coefficients in the 1,1 block \tm{H}.
-\var{W} is a dictionary that contains the parameters of the scaling:
-
-\BIT
-\item \code{W['dnl']} is the positive vector that defines the diagonal
- scaling for the nonlinear inequalities.   
- \code{W['dnli']} is its componentwise inverse.
-\item \code{W['d']} is the positive vector that defines the diagonal
- scaling for the componentwise linear inequalities.   
- \code{W['di']} is its componentwise inverse.
-\item \code{W['beta']} and \code{W['v']} are lists of length \tm{M} with 
- the coefficients and vectors that define the hyperbolic Householder 
- transformations.
-\item \code{W['r']} is a list of length \tm{N} with the matrices that
- define the the congruence transformations.  
- \code{W['rti']} is  a list of length \tm{N} with the transposes of the 
- inverses of the matrices in \code{W['r']}.
-\EIT
-
-The function call \samp{f = kktsolver(x, z, W)} should return a routine
-for solving the KKT system~(\ref{e-cp-kkt}) defined by \var{x}, \var{z}, 
-\var{W}.
-It will be called as \samp{f(bx, by, bz)}.
-On entry, \var{bx}, \var{by}, \var{bz} contain the righthand side.  
-On exit, they should contain the solution of the KKT system, with 
-the last component scaled, \ie, on exit,
-\[
-  b_x := u_x, \qquad b_y := u_y, \qquad b_z := W u_z.
-\]
-
-The role of the argument \var{kktsolver} in the function \function{cpl()}
-is similar, except that in~(\ref{e-cp-kkt}),
-\[
- H = \sum_{k=0}^{m-1} z_k \nabla^2f_k(x), \qquad
- \tilde G = \left[\begin{array}{cccc}
- \nabla f_0(x) & \cdots & \nabla f_{m-1}(x) & G^T \end{array}\right]^T.
-\]
-
-\item[\emph{Specifying constraints via Python functions}.]
-In the default use of \function{cp()}, the arguments \var{G} and 
-\var{A} are the coefficient matrices in the constraints 
-of~(\ref{e-cp-kkt}).
-It is also possible to specify these matrices by providing Python 
-functions that evaluate the corresponding matrix-vector products and 
-their adjoints.
-
-If the argument \var{G} of \function{conelp()} is a Python
-function, it should be defined as follows:
-\begin{funcdesc}{\var{G}}{\var{u}, \var{v} \optional{, 
-\var{alpha}\optional{, \var{beta}\optional{, \var{trans}}}}} 
-This evaluates the matrix-vector products
-\[
-v := \alpha Gu + \beta v \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
-v := \alpha G^T u + \beta v \quad (\mathrm{trans} = \mathrm{'T'}).
-\]
-The default values of the optional arguments must be
-\code{alpha = 1.0}, \code{beta = 0.0}, \code{trans = 'N'}.
-\end{funcdesc}
-
-Similarly, if the argument \var{A} is a Python function, then it must
-be defined as follows.
-\begin{funcdesc}{\var{A}}{\var{u}, \var{v} \optional{, 
-\var{alpha}\optional{, \var{beta}\optional{, \var{trans}}}}} 
-This evaluates the matrix-vector products
-\[
-v := \alpha Au + \beta v \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
-v := \alpha A^T u + \beta v \quad (\mathrm{trans} = \mathrm{'T'}).
-\]
-The default values of the optional arguments must be
-\code{alpha = 1.0}, \code{beta = 0.0}, \code{trans = 'N'}.
-\end{funcdesc}
-
-In a similar way, when the first argument \var{F()} of \function{cp()}
-returns matrices of first derivatives or second derivatives 
-\var{Df}, \var{H}, these matrices can be specified as Python functions.
-If \var{Df} is a Python function, it should be defined as follows:
-\begin{funcdesc}{\var{Df}}{\var{u}, \var{v} \optional{, 
-\var{alpha}\optional{, \var{beta}\optional{, \var{trans}}}}} 
-This evaluates the matrix-vector products
-\[
-v := \alpha Df(x) u + \beta v \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
-v := \alpha Df(x)^T u + \beta v \quad (\mathrm{trans} = \mathrm{'T'}).
-\]
-The default values of the optional arguments must be
-\code{alpha = 1.0}, \code{beta = 0.0}, \code{trans = 'N'}.
-\end{funcdesc}
-
-If \var{H} is a Python function, it should be defined as follows:
-\begin{funcdesc}{\var{H}}{\var{u}, \var{v} \optional{, 
-\var{alpha}\optional{, \var{beta}}}} 
-This evaluates the matrix-vector product
-\[
-v := \alpha H u + \beta v.
-\]
-The default values of the optional arguments must be
-\code{alpha = 1.0}, \code{beta = 0.0}, \code{trans = 'N'}.
-\end{funcdesc}
-
-If \var{G}, \var{A}, \var{Df}, or \var{H} are Python functions, then 
-the argument \var{kktsolver} must also be provided.
-\end{description}
-
-As an example, we consider the unconstrained problem
-\[
- \begin{array}{ll}
- \mbox{minimize} & (1/2)\|Ax-b\|_2^2 - \sum_{i=1}^n \log(1-x_i^2)
- \end{array}
-\]
-where \tm{A} is an \tm{m} by \tm{n} matrix with \tm{m} less than \tm{n}.  
-The Hessian of the objective is diagonal plus a low-rank term:
-\[
-  H = A^TA + \diag(d), \qquad d_i = \frac{2(1+x_i^2)}{(1-x_i^2)^2}.
-\]
-We can exploit this property when solving~(\ref{e-cp-kkt}) by applying
-the matrix inversion lemma. We first solve  
-\[
- (A \diag(d)^{-1}A^T + I) v = (1/z_0) A \diag(d)^{-1}b_x, \qquad
-\]
-and then obtain
-\[
- u_x = \diag(d)^{-1}(b_x/z_0 - A^T v).
-\]
-The following code follows this method.  It also uses BLAS functions
-for matrix-matrix and matrix-vector products.
-
-\begin{verbatim}
-from cvxopt import matrix, spdiag, mul, div, log, blas, lapack, solvers, base
-
-def l2ac(A, b):
-    """
-    Solves
-
-        minimize  (1/2) * ||A*x-b||_2^2 - sum log (1-xi^2)
-
-    assuming A is m x n with m << n.
-    """
-
-    m, n = A.size
-    def F(x = None, z = None):
-        if x is None: 
-            return 0, matrix(0.0, (n,1))
-        if max(abs(x)) >= 1.0: 
-            return None 
-        # r = A*x - b
-        r = -b
-        blas.gemv(A, x, r, beta = -1.0)
-        w = x**2
-        f = 0.5 * blas.nrm2(r)**2  - sum(log(1-w))
-        # gradf = A'*r + 2.0 * x ./ (1-w)
-        gradf = div(x, 1.0 - w)
-        blas.gemv(A, r, gradf, trans = 'T', beta = 2.0)
-        if z is None:
-            return f, gradf.T
-        else:
-            def Hf(u, v, alpha = 1.0, beta = 0.0):
-               # v := alpha * (A'*A*u + 2*((1+w)./(1-w)).*u + beta *v
-               v *= beta
-               v += 2.0 * alpha * mul(div(1.0+w, (1.0-w)**2), u)
-               blas.gemv(A, u, r)
-               blas.gemv(A, r, v, alpha = alpha, beta = 1.0, trans = 'T')
-            return f, gradf.T, Hf
-
-
-    # Custom solver for the Newton system
-    #
-    #     z[0]*(A'*A + D)*x = bx
-    #
-    # where D = 2 * (1+x.^2) ./ (1-x.^2).^2.  We apply the matrix inversion
-    # lemma and solve this as
-    #    
-    #     (A * D^-1 *A' + I) * v = A * D^-1 * bx / z[0]
-    #     D * x = bx / z[0] - A'*v.
-
-    S = matrix(0.0, (m,m))
-    v = matrix(0.0, (m,1))
-    def Fkkt(x, z, W):
-        ds = (2.0 * div(1 + x**2, (1 - x**2)**2))**-0.5
-        Asc = spdiag(ds) * A
-        blas.syrk(Asc, S)
-        S[::m+1] += 1.0 
-        lapack.potrf(S)
-        a = z[0]
-        def g(x, y, z):
-            x[:] = mul(x, ds) / a
-            blas.gemv(Asc, x, v)
-            lapack.potrs(S, v)
-            blas.gemv(Asc, v, x, alpha = -1.0, beta = 1.0, trans = 'T')
-            x[:] = mul(x, ds)  
-        return g
-
-    return solvers.cp(F, kktsolver = Fkkt)['x']
-\end{verbatim}
-
-
-\section{Algorithm Parameters} \label{s-parameters2}
-The following algorithm control parameters are accessible via the 
-dictionary \member{solvers.options}.  By default the dictionary 
-is empty and the default values of the parameters are used.
-
-One can change the parameters in the default solvers by 
-adding entries with the following key values.  
-\begin{description}
-\item[\code{'show\_progress'}]  
-\True\  or \False; turns the output to the screen on or off  
-(default: \True).
-\item[\code{'maxiters'}] maximum number of iterations (default: 100).
-\item[\code{'abstol'}] absolute accuracy (default: \code{1e-7}).
-\item[\code{'reltol'}] relative accuracy (default: \code{1e-6}).
-\item[\code{'feastol'}] tolerance for feasibility conditions (default:
-\code{1e-7}).
-\item[\code{'refinement'}] number of iterative refinement steps when
- solving KKT equations (default: 1).
-\end{description}
-For example the command
-\begin{verbatim}
->>> from cvxopt import solvers
->>> solvers.options['show_progress'] = False
-\end{verbatim}
-turns off the screen output during calls to the solvers.
-The tolerances \var{abstol}, \var{reltol} and \var{feastol} have the
-following meaning in \function{nlcp()}. 
-
-\function{cpl()} returns with status \code{'optimal'} if
-\[
-\frac{\| c +  Df(x)^Tz_\mathrm{nl} + 
- G^Tz_\mathrm{l} + A^T y \|_2 }
-{\max\{ 1, 
-\| c + Df(x_0)^T\ones + G^T\ones \|_2 \}} 
-\leq \epsilon_\mathrm{feas}, \qquad
-\frac{\| ( f(x) + s_{\mathrm{nl}},  Gx + s_\mathrm{l} - h, 
- Ax-b ) \|_2} 
-{\max\{1, \| ( f(x_0) + \ones,  
-Gx_0 + \ones-h, Ax_0-b) \|_2 \}} \leq \epsilon_\mathrm{feas}  
-\]
-where \tm{\s{x}{0}} is the point returned by \code{F()}, and
-\[
-\mathrm{gap} \leq \epsilon_\mathrm{abs}
-\qquad \mbox{or} \qquad \left( c^Tx < 0, \quad
-\frac{\mathrm{gap}} {-c^Tx} \leq \epsilon_\mathrm{rel} \right)
-\qquad \mbox{or} \qquad
-\left( L(x,y,z) > 0, \quad \frac{\mathrm{gap}}
-{L(x,y,z)} \leq \epsilon_\mathrm{rel} \right)
-\]
-where
-\[
- \mathrm{gap} = 
-\left[\begin{array}{c} s_\mathrm{nl} \\ s_\mathrm{l} 
-\end{array}\right]^T
-\left[\begin{array}{c} z_\mathrm{nl} \\ z_\mathrm{l} 
-\end{array}\right],
-\qquad
-L(x,y,z) = c^Tx + z_\mathrm{nl}^T f(x) + z_\mathrm{l}^T (Gx-h) + y^T(Ax-b).
-\]
-The functions \function{cp()} and \function{gp()} 
-call \function{cpl()} and hence use the same stopping criteria
-(with \tm{\s{x}{0}=0} for \function{gp()}).
-
-The MOSEK interior-point algorithm parameters are set to their default 
-values.  They can be modified by adding an entry 
-\code{solvers.options['MOSEK']}.  This entry is a dictionary with 
-MOSEK parameter/value pairs, with the parameter names imported from
-\module{pymosek}.  For details see Section 14.1.3 of the 
-\ulink{MOSEK Python API Manual}{http://www.mosek.com/fileadmin/products/5_0/tools/doc/html/pyapi/index.html}.
-
-
-For example the commands
-\begin{verbatim}
->>> from cvxopt import solvers 
->>> import pymosek
->>> solvers.options['MOSEK'] = {pymosek.iparam.log: 0}
-\end{verbatim}
-turn off the screen output during calls of  \function{qp()} 
-with the \code{'mosek'} option.
diff --git a/doc/source/.static/cvxopt.css b/doc/source/.static/cvxopt.css
new file mode 100644
index 0000000..1a7f740
--- /dev/null
+++ b/doc/source/.static/cvxopt.css
@@ -0,0 +1,630 @@
+/*
+ * Alternate Sphinx design
+ * Originally created by Armin Ronacher for Werkzeug, adapted by Georg 
+ * Brandl. 
+ * Adapted for CVXOPT.
+ */
+
+body {
+    font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 'Verdana', sans-serif;
+    font-size: 14px;
+    letter-spacing: -0.01em;
+    line-height: 150%;
+    text-align: center;
+    /* background-color: #AFC1C4; */
+    /* background-color: #BFD1D4; */
+    color: black;
+    /* border: 1px solid #aaa; */
+    margin: 0px 20px 0px 20px;
+    /* min-width: 740px; */
+    min-width: 800px; */
+}
+
+a {
+/*    color: #CA7900; */
+    color: black;
+    text-decoration: underline;
+}
+
+a:hover {
+/*    color: #2491CF; */
+    text-decoration: underline;
+}
+
+li[class="toctree-l1"] a, div.sphinxsidebar a {
+    text-decoration: none !important;
+}
+li[class="toctree-l1"] a:hover, div.sphinxsidebar a:hover {
+    text-decoration: underline !important;
+    color: black !important;
+}
+li[class="toctree-l1"] ul {
+    list-style-type: circle;
+}
+
+div.sphinxsidebarwrapper h3 a:hover {
+    text-decoration: none !important;
+    color: white !important;
+}
+
+pre {
+    font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+    font-size: 0.95em;
+    letter-spacing: 0.015em;
+    padding: 0.5em;
+    border: 1px solid #ccc;
+    background-color: #f8f8f8; 
+}
+
+td.linenos pre {
+    padding: 0.5em 0;
+    border: 0;
+    background-color: transparent;
+    color: #aaa;
+}
+
+table.highlighttable {
+    margin-left: 0.5em;
+}
+
+table.highlighttable td {
+    padding: 0 0.5em 0 0.5em;
+}
+
+cite, code {
+    font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+    font-size: 0.95em;
+    letter-spacing: 0.01em;
+}
+
+hr {
+    border: 1px solid #abc;
+    margin: 2em;
+}
+
+tt {
+    font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+}
+
+/* function names */
+tt.descname { 
+    font-style: normal;
+    background-color: transparent;
+    font-weight: bold;
+    font-size: 1.2em;
+    border: 0;
+}
+
+/* module name prepended to function name*/
+tt.descclassname {  
+    font-style: normal;
+    background-color: transparent;
+    border: 0;
+}
+
+/* variables in function argument list and definition, :samp: */
+tt.docutils.literal, dl.function em {  
+    font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+    font-style: italic;
+    background-color: transparent;
+    border: 0;
+}
+
+/* function name in reference, and literals */
+tt.xref.docutils.literal {  
+    font-style: normal;
+    background-color: transparent;
+    font-weight: bold;
+    border: 0;
+}
+
+a tt {
+    background-color: transparent;
+    font-weight: bold;
+    border: 0;
+/*    color: #CA7900; */
+}
+
+/*
+a tt:hover {
+    color: #2491CF; 
+}
+*/
+
+
+.field-list ul {
+    margin: 0;
+    padding-left: 1em;
+}
+
+.field-list p {
+    margin: 0;
+}
+
+dl {
+    margin-bottom: 15px;
+}
+
+
+
+dd p {
+    margin-top: 0px;
+}
+
+dd ul, dd table {
+    margin-bottom: 10px;
+}
+
+dd {
+    margin-top: 3px;
+    margin-bottom: 10px;
+    margin-left: 30px;
+}
+
+.refcount {
+    color: #060;
+}
+
+dt:target,
+.highlight {
+    background-color: #fbe54e;
+}
+
+dl.glossary dt {
+    font-weight: bold;
+    font-size: 1.1em;
+}
+
+pre {
+    line-height: 120%;
+}
+
+pre a {
+    color: inherit;
+    text-decoration: underline;
+}
+
+.first {
+    margin-top: 0 !important;
+}
+
+div.document {
+    background-color: white;
+    text-align: left;
+/*    background-image: url(contents.png); */
+/*    background-repeat: repeat-x; */
+}
+
+/*
+div.documentwrapper {
+    width: 100%;
+}
+*/
+
+div.clearer {
+    clear: both;
+}
+
+div.related h3 {
+    display: none;
+}
+
+div.related ul {
+/*    background-image: url(navigation.png); */
+    height: 2em;
+    list-style: none;
+    border-top: 1px solid #ddd; 
+    border-bottom: 1px solid #ddd; 
+    margin: 0;
+    padding-left: 10px;
+}
+
+div.related ul li {
+    margin: 0;
+    padding: 0;
+    height: 2em;
+    float: left;
+}
+
+div.related ul li.right {
+    float: right;
+    margin-right: 5px;
+}
+
+div.related ul li a {
+    margin: 0;
+    padding: 0 5px 0 5px;
+    line-height: 1.75em;
+/*    color: #EE9816; */
+    text-decoration: none;  
+}
+
+div.related ul li a:hover {
+/*    color: #3CA8E7;  */
+    text-decoration: underline;  
+}
+
+div.body {
+    margin: 0;
+    padding: 0.5em 20px 20px 20px;
+}
+
+div.documentwrapper{
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+/*     margin: 0 240px 0 0; */
+    margin: 0 0 0 240px; 
+    border-left: 1px solid #ccc;
+}
+
+/*
+div.body a {
+    text-decoration: underline; 
+    text-decoration: none;  
+}
+*/
+
+div.body a:hover {
+    color: #2491CF;  
+}
+
+div.sphinxsidebar {
+    margin: 0;
+    padding: 0.5em 15px 15px 0; 
+    width: 210px;
+    float: left; 
+    text-align: left;
+    margin-left: -100%; 
+}
+
+div.sphinxsidebar h4, div.sphinxsidebar h3 {
+    margin: 1em 0 .2em 0;
+/*    font-size: 0.9em; */
+    font-size: 1.1em; 
+
+    padding: 0.1em 0 0.1em 0.5em; 
+    color: white; 
+    border: 1px solid #86989B; 
+    background-color: #AFC1C4;  
+}
+
+div.sphinxsidebar h3 a {
+    color: white; 
+}
+
+div.sphinxsidebar ul {
+    padding-left: 1.5em;
+    margin-top: 7px;
+    list-style: none;
+    padding: 0;
+    line-height: 130%;
+}
+
+div.sphinxsidebar ul ul {
+    list-style: square;
+    margin-left: 20px;
+}
+
+p {
+    margin: 0.8em 0 0.5em 0;
+}
+
+p.rubric {
+    font-weight: bold;
+}
+
+div.sidebar {
+    margin: 0 0 0.5em 1em;
+    border: 1px solid #ddb;
+    padding: 7px 7px 0 7px;
+    background-color: #ffe;
+    width: 40%;
+    float: right;
+}
+
+div.quotebar {
+    background-color: #f8f8f8;
+    max-width: 250px;
+    float: right;
+    padding: 2px 7px;
+    border: 1px solid #ccc;
+}
+
+p.sidebar-title {
+    font-weight: bold;
+}
+
+div.topic {
+    background-color: #f8f8f8;
+    border: 1px solid #ccc;
+    padding: 7px 7px 0 7px;
+    margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+    font-size: 1.1em;
+    font-weight: bold;
+}
+
+h1 {
+    margin: 0;
+    padding: 0.7em 0 0.3em 0;
+    font-size: 1.5em;
+    color: #11557C; 
+}
+
+h2 {
+    margin: 1.3em 0 0.2em 0;
+    font-size: 1.35em;
+    padding: 0;
+    color: #11557C; 
+}
+
+h3 {
+    margin: 1em 0 -0.3em 0;
+    font-size: 1.2em;
+}
+
+div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
+    color: black!important;
+}
+
+h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
+    display: none;
+    margin: 0 0 0 0.3em;
+    padding: 0 0.2em 0 0.2em;
+    color: #aaa!important;
+}
+
+h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
+h5:hover a.anchor, h6:hover a.anchor {
+    display: inline;
+}
+
+h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
+h5 a.anchor:hover, h6 a.anchor:hover {
+    color: #777;
+    background-color: #eee;
+}
+
+table {
+    border-collapse: collapse;
+    margin: 0 -0.5em 0 -0.5em;
+}
+
+table.docutils{
+    margin-left: auto;
+    margin-right: auto;
+    width: 60%;
+    margin-top: 1em;
+    margin-bottom: 1em;
+}
+
+table td, table th {
+    padding: 0.2em 0.5em 0.2em 0.5em;
+}
+
+div.footer {
+/*    background-color: #E3EFF1; */
+    color: #86989B;
+    padding: 3px 8px 3px 0;
+    clear: both;
+    font-size: 0.8em;
+    text-align: right;
+}
+
+div.footer a {
+    color: #86989B;
+    text-decoration: underline;
+}
+
+div.pagination {
+    margin-top: 2em;
+    padding-top: 0.5em;
+    border-top: 1px solid black;
+    text-align: center;
+}
+
+div.sphinxsidebar ul.toc {
+    margin: 1em 0 1em 0;
+    padding: 0 0 0 0.5em;
+    list-style: none;
+}
+
+div.sphinxsidebar ul.toc li {
+    margin: 0.5em 0 0.5em 0;
+    font-size: 0.9em;
+    line-height: 130%;
+}
+
+div.sphinxsidebar ul.toc li p {
+    margin: 0;
+    padding: 0;
+}
+
+div.sphinxsidebar ul.toc ul {
+    margin: 0.2em 0 0.2em 0;
+    padding: 0 0 0 1.8em;
+}
+
+div.sphinxsidebar ul.toc ul li {
+    padding: 0;
+}
+
+div.admonition, div.warning {
+    font-size: 0.9em;
+    margin: 1em 0 0 0;
+    border: 1px solid #86989B;
+    background-color: #f7f7f7;
+}
+
+div.admonition p, div.warning p {
+    margin: 0.5em 1em 0.5em 1em;
+    padding: 0;
+}
+
+div.admonition pre, div.warning pre {
+    margin: 0.4em 1em 0.4em 1em;
+}
+
+div.admonition p.admonition-title,
+div.warning p.admonition-title {
+    margin: 0;
+    padding: 0.1em 0 0.1em 0.5em;
+    color: white;
+    border-bottom: 1px solid #86989B;
+    font-weight: bold;
+    background-color: #AFC1C4;
+}
+
+div.warning {
+    border: 1px solid #940000;
+}
+
+div.warning p.admonition-title {
+    background-color: #CF0000;
+    border-bottom-color: #940000;
+}
+
+div.admonition ul, div.admonition ol,
+div.warning ul, div.warning ol {
+    margin: 0.1em 0.5em 0.5em 3em;
+    padding: 0;
+}
+
+div.versioninfo {
+    margin: 1em 0 0 0;
+    border: 1px solid #ccc;
+    background-color: #DDEAF0;
+    padding: 8px;
+    line-height: 1.3em;
+    font-size: 0.9em;
+}
+
+
+a.headerlink {
+    color: #c60f0f!important;
+    font-size: 1em;
+    margin-left: 6px;
+    padding: 0 4px 0 4px;
+    text-decoration: none!important;
+    visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink {
+    visibility: visible;
+}
+
+a.headerlink:hover {
+    background-color: #ccc;
+    color: white!important;
+}
+
+table.indextable td {
+    text-align: left;
+    vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+table.indextable tr.pcap {
+    height: 10px;
+}
+
+table.indextable tr.cap {
+    margin-top: 10px;
+    background-color: #f2f2f2;
+}
+
+img.toggler {
+    margin-right: 3px;
+    margin-top: 3px;
+    cursor: pointer;
+}
+
+form.pfform {
+    margin: 10px 0 20px 0;
+}
+
+table.contentstable {
+    width: 90%;
+}
+
+table.contentstable p.biglink {
+    line-height: 150%;
+}
+
+a.biglink {
+    font-size: 1.3em;
+}
+
+span.linkdescr {
+    font-style: italic;
+    padding-top: 5px;
+    font-size: 90%;
+}
+
+ul.search {
+    margin: 10px 0 0 20px;
+    padding: 0;
+}
+
+ul.search li {
+    padding: 5px 0 5px 20px;
+    background-image: url(file.png);
+    background-repeat: no-repeat;
+    background-position: 0 7px;
+}
+
+ul.search li a {
+    font-weight: bold;
+}
+
+ul.search li div.context {
+    color: #888;
+    margin: 2px 0 0 30px;
+    text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+    font-weight: bold;
+}
+
+img.math {
+    vertical-align: middle;
+}
+
+div.math {
+    text-align: center;
+}
+
+span.eqno {
+    float: right;
+}
+
+img.logo {
+    border: 0;
+}
+
+span.raise {
+  vertical-align:super;
+  font-size: .7em;
+}
+
+ul {
+    list-style-type: disc;
+}
+
+
diff --git a/doc/source/blas.rst b/doc/source/blas.rst
new file mode 100644
index 0000000..22c3a15
--- /dev/null
+++ b/doc/source/blas.rst
@@ -0,0 +1,924 @@
+.. _c-blas:
+
+******************
+The BLAS Interface
+******************
+
+The :mod:`cvxopt.blas` module provides an interface to the double-precision
+real and complex Basic Linear Algebra Subprograms (BLAS).  The names and 
+calling sequences of the Python functions in the interface closely match 
+the corresponding Fortran BLAS routines (described in the references below)
+and their functionality is exactly the same.  Many of the operations 
+performed by the BLAS routines can be implemented in a more straightforward
+way by using the matrix arithmetic of the section :ref:`s-arithmetic`, 
+combined with the slicing and indexing of the section :ref:`s-indexing`.
+As an example, ``C = A * B`` gives the same result as the BLAS call 
+``gemm(A, B, C)``.  The BLAS interface offers two advantages.  First, 
+some of the functions it includes are not easily implemented using the 
+basic matrix arithmetic.  For example, BLAS includes functions that 
+efficiently exploit symmetry or triangular matrix structure.  Second, there
+is a performance difference that can be significant for large matrices.   
+Although our implementation of the basic matrix arithmetic makes internal 
+calls to BLAS, it also often requires creating temporary matrices to store 
+intermediate results.  The BLAS functions on the other hand always operate 
+directly on their matrix arguments and never require any copying to 
+temporary matrices.  Thus they can be viewed as generalizations of the 
+in-place matrix addition and scalar multiplication of the section 
+:ref:`s-arithmetic` to more complicated operations.
+
+.. seealso::
+
+    * C. L. Lawson, R. J. Hanson, D. R. Kincaid, F. T. Krogh, 
+      Basic Linear Algebra Subprograms for Fortran Use,
+      ACM Transactions on Mathematical Software, 5(3), 309-323, 1975.
+
+    * J. J. Dongarra, J. Du Croz, S. Hammarling, R. J. Hanson,
+      An Extended Set of Fortran Basic Linear Algebra Subprograms,
+      ACM Transactions on Mathematical Software, 14(1), 1-17, 1988.
+
+    * J. J. Dongarra, J. Du Croz, S. Hammarling, I. Duff,
+      A Set of Level 3 Basic Linear Algebra Subprograms,
+      ACM Transactions on Mathematical Software, 16(1), 1-17, 1990.
+
+
+.. _s-conventions:
+
+Matrix Classes 
+==============
+
+The BLAS exploit several types of matrix structure: symmetric, Hermitian, 
+triangular, and banded.   We represent all these matrix classes by dense 
+real or complex :class:`matrix <cvxopt.matrix>` objects, with additional 
+arguments that specify the structure.
+
+
+**Vector** 
+    A real or complex :math:`n`-vector is represented by a :class:`matrix`
+    of type :const:`'d'` or :const:`'z'` and length :math:`n`, with the 
+    entries of the vector stored in column-major order. 
+
+
+**General matrix**
+    A general real or complex :math:`m` by :math:`n` matrix is represented 
+    by a real or complex :class:`matrix` of size (:math:`m`, :math:`n`).
+
+
+**Symmetric matrix**
+    A real or complex symmetric matrix of order :math:`n` is represented
+    by a real or complex :class:`matrix` of size (:math:`n`, :math:`n`), 
+    and a character argument ``uplo``  with two possible values:  
+    :const:`'L'` and :const:`'U'`.  If ``uplo``  is :const:`'L'`, the lower
+    triangular part of the symmetric matrix is stored; if ``uplo`` is 
+    :const:`'U'`, the upper triangular part is stored.  A square 
+    :class:`matrix` ``X`` of size (:math:`n`, :math:`n`) can therefore be 
+    used to represent the symmetric matrices
+
+    .. math::
+
+        \left[\begin{array}{ccccc}
+            X[0,0]   & X[1,0]   & X[2,0]   & \cdots & X[n-1,0] \\
+            X[1,0]   & X[1,1]   & X[2,1]   & \cdots & X[n-1,1] \\
+            X[2,0]   & X[2,1]   & X[2,2]   & \cdots & X[n-1,2] \\
+            \vdots   & \vdots   & \vdots   & \ddots & \vdots \\
+            X[n-1,0] & X[n-1,1] & X[n-1,2] & \cdots & X[n-1,n-1]
+        \end{array}\right] \quad \mbox{(uplo = 'L')}, 
+
+        \left[\begin{array}{ccccc}
+            X[0,0]   & X[0,1]   & X[0,2]   & \cdots & X[0,n-1] \\
+            X[0,1]   & X[1,1]   & X[1,2]   & \cdots & X[1,n-1] \\
+            X[0,2]   & X[1,2]   & X[2,2]   & \cdots & X[2,n-1] \\
+            \vdots   & \vdots   & \vdots   & \ddots & \vdots \\
+            X[0,n-1] & X[1,n-1] & X[2,n-1] & \cdots & X[n-1,n-1]
+        \end{array}\right] \quad \mbox{(uplo = U')}. 
+
+    
+**Complex Hermitian matrix**
+    A complex Hermitian matrix of order :math:`n` is represented by a 
+    :class:`matrix` of type :const:`'z'` and size (:math:`n`, :math:`n`), 
+    and a character argument ``uplo``  with the same meaning as for 
+    symmetric matrices.  A complex :class:`matrix` ``X`` of size 
+    (:math:`n`, :math:`n`) can represent the Hermitian  matrices
+
+    .. math::
+
+        \left[\begin{array}{ccccc}
+            \Re X[0,0]   & \bar X[1,0]   & \bar X[2,0] & \cdots & 
+                \bar X[n-1,0] \\
+            X[1,0]   & \Re X[1,1]   & \bar X[2,1]   & \cdots & 
+                \bar X[n-1,1] \\
+            X[2,0]   & X[2,1]   & \Re X[2,2]   & \cdots & \bar X[n-1,2] \\
+                \vdots   & \vdots   & \vdots   & \ddots & \vdots \\
+            X[n-1,0] & X[n-1,1] & X[n-1,2] & \cdots & \Re X[n-1,n-1]
+        \end{array}\right] \quad \mbox{(uplo = 'L')},
+
+        \left[\begin{array}{ccccc}
+            \Re X[0,0]   & X[0,1]   & X[0,2]   & \cdots & X[0,n-1] \\
+            \bar X[0,1]   & \Re X[1,1]   & X[1,2]   & \cdots & X[1,n-1] \\
+            \bar X[0,2]   & \bar X[1,2]   & \Re X[2,2]   & \cdots & 
+                X[2,n-1] \\
+            \vdots   & \vdots   & \vdots   & \ddots & \vdots \\
+            \bar X[0,n-1] & \bar X[1,n-1] & \bar X[2,n-1] & \cdots & 
+                \Re X[n-1,n-1]
+        \end{array}\right] \quad \mbox{(uplo = 'U')}.
+
+    
+**Triangular matrix**
+    A real or complex triangular matrix of order :math:`n` is represented
+    by a real or complex :class:`matrix` of size (:math:`n`, :math:`n`), 
+    and two character arguments: an argument ``uplo``  with possible values
+    :const:`'L'` and :const:`'U'` to distinguish between lower and upper 
+    triangular matrices, and an argument ``diag``  with possible values 
+    :const:`'U'` and :const:`'N'` to distinguish between unit and non-unit 
+    triangular matrices.  A square :class:`matrix` ``X`` of size 
+    (:math:`n`, :math:`n`) can represent the triangular matrices
+
+    .. math::
+
+        \left[\begin{array}{ccccc}
+            X[0,0]   & 0        & 0        & \cdots & 0 \\
+            X[1,0]   & X[1,1]   & 0        & \cdots & 0 \\
+            X[2,0]   & X[2,1]   & X[2,2]   & \cdots & 0 \\
+            \vdots   & \vdots   & \vdots   & \ddots & \vdots \\
+            X[n-1,0] & X[n-1,1] & X[n-1,2] & \cdots & X[n-1,n-1]
+        \end{array}\right] \quad \mbox{(uplo = 'L', diag = 'N')}, 
+
+        \left[\begin{array}{ccccc}
+            1   & 0   & 0   & \cdots & 0 \\
+            X[1,0]   & 1   & 0   & \cdots & 0 \\
+            X[2,0]   & X[2,1]   & 1   & \cdots & 0 \\
+            \vdots   & \vdots   & \vdots   & \ddots & \vdots \\
+            X[n-1,0] & X[n-1,1] & X[n-1,2] & \cdots & 1
+        \end{array}\right] \quad \mbox{(uplo = 'L', diag = 'U')}, 
+
+        \left[\begin{array}{ccccc}
+            X[0,0]   & X[0,1]   & X[0,2]   & \cdots & X[0,n-1] \\
+            0   & X[1,1]   & X[1,2]   & \cdots & X[1,n-1] \\
+            0   & 0   & X[2,2]   & \cdots & X[2,n-1] \\
+            \vdots   & \vdots   & \vdots   & \ddots & \vdots \\
+            0 & 0 & 0 & \cdots & X[n-1,n-1]
+        \end{array}\right] \quad \mbox{(uplo = 'U', diag = 'N')}, 
+
+        \left[\begin{array}{ccccc}
+            1   & X[0,1]   & X[0,2]   & \cdots & X[0,n-1] \\
+            0   & 1   & X[1,2]   & \cdots & X[1,n-1] \\
+            0   & 0   & 1   & \cdots & X[2,n-1] \\
+            \vdots   & \vdots   & \vdots   & \ddots & \vdots \\
+            0 & 0 & 0 & \cdots & 1
+        \end{array}\right] \quad \mbox{(uplo = 'U', diag = 'U')}.
+
+    
+**General band matrix**
+    A general real or complex :math:`m` by :math:`n` band matrix  with 
+    :math:`k_l` subdiagonals and :math:`k_u` superdiagonals is represented 
+    by a real or complex :class:`matrix` ``X`` of size 
+    (:math:`k_l + k_u + 1`, :math:`n`), and the two integers :math:`m` and 
+    :math:`k_l`.   The diagonals of the band matrix are stored in the rows 
+    of ``X``, starting at the top diagonal, and shifted horizontally so that
+    the entries of column :math:`k` of the band matrix are stored in column
+    :math:`k` of ``X``.  A :class:`matrix` ``X`` of size 
+    (:math:`k_l + k_u + 1`, :math:`n`) therefore represents the :math:`m` 
+    by :math:`n` band matrix
+
+    .. math::
+
+        \left[ \begin{array}{ccccccc}
+            X[k_u,0]     & X[k_u-1,1]   & X[k_u-2,2]     & \cdots & 
+                X[0,k_u] & 0               & \cdots \\
+            X[k_u+1,0]   & X[k_u,1]     & X[k_u-1,2]     & \cdots & 
+                X[1,k_u] & X[0,k_u+1]   & \cdots \\
+            X[k_u+2,0]   & X[k_u+1,1]     & X[k_u,2]       & \cdots & 
+                X[2,k_u] & X[1,k_u+1] & \cdots \\ 
+            \vdots      & \vdots         &  \vdots        & \ddots & 
+                \vdots   & \vdots          & \ddots  \\
+            X[k_u+k_l,0] & X[k_u+k_l-1,1] & X[k_u+k_l-2,2] & \cdots &  
+                &  & \\
+            0            & X[k_u+k_l,1]   & X[k_u+k_l-1,2] & \cdots &  
+                &  & \\
+            \vdots       & \vdots         & \vdots         & \ddots &  
+                &  & 
+        \end{array}\right].
+
+    
+**Symmetric band matrix**
+    A real or complex symmetric band matrix of order :math:`n` with 
+    :math:`k` subdiagonals, is represented by a real or complex matrix ``X``
+    of size (:math:`k+1`, :math:`n`), and an argument ``uplo`` to indicate 
+    whether the subdiagonals (``uplo`` is :const:`'L'`) or superdiagonals 
+    (``uplo`` is :const:`'U'`) are stored.  The :math:`k+1` diagonals are 
+    stored as rows of ``X``, starting at the top diagonal (i.e., the main 
+    diagonal if ``uplo`` is :const:`'L'`,  or the :math:`k`-th superdiagonal
+    if ``uplo`` is :const:`'U'`) and shifted horizontally so that the 
+    entries of the :math:`k`-th column of the band matrix are stored in 
+    column :math:`k` of ``X``.  A :class:`matrix` ``X`` of size 
+    (:math:`k+1`, :math:`n`) can therefore represent the band matrices 
+
+    .. math::
+        
+        \left[ \begin{array}{ccccccc}
+            X[0,0] & X[1,0]   & X[2,0]   & \cdots & X[k,0]   & 0
+                & \cdots \\
+            X[1,0] & X[0,1]   & X[1,1]   & \cdots & X[k-1,1] & X[k,1]   
+                & \cdots \\
+            X[2,0] & X[1,1]   & X[0,2]   & \cdots & X[k-2,2] & X[k-1,2] 
+                & \cdots \\
+            \vdots & \vdots   &  \vdots  & \ddots & \vdots   & \vdots   
+                & \ddots \\
+            X[k,0] & X[k-1,1] & X[k-2,2] & \cdots &  &  & \\
+            0      & X[k,1]   & X[k-1,2] & \cdots &  &  & \\
+            \vdots & \vdots   & \vdots   & \ddots &  &  & 
+        \end{array}\right] \quad \mbox{(uplo = 'L')}, 
+
+        \left[ \begin{array}{ccccccc}
+            X[k,0]   & X[k-1,1] & X[k-2,2] & \cdots & X[0,k] & 0        
+                 & \cdots \\
+            X[k-1,1] & X[k,1]   & X[k-1,2] & \cdots & X[1,k] & X[0,k+1] 
+                 & \cdots \\
+            X[k-2,2] & X[k-1,2] & X[k,2]   & \cdots & X[2,k] & X[1,k+1] 
+                 & \cdots \\
+            \vdots   & \vdots   & \vdots   & \ddots & \vdots & \vdots   
+                 & \ddots \\
+            X[0,k]   & X[1,k]   & X[2,k]   & \cdots &  &  & \\
+            0        & X[0,k+1] & X[1,k+1] & \cdots &  &  & \\
+            \vdots   & \vdots   & \vdots   & \ddots &  &  & 
+        \end{array}\right] \quad \mbox{(uplo='U')}.
+
+       
+**Hermitian  band matrix**
+    A complex Hermitian band matrix of order :math:`n` with :math:`k` 
+    subdiagonals is represented by a complex matrix of size 
+    (:math:`k+1`, :math:`n`) and an argument ``uplo``, with the same meaning
+    as for symmetric band matrices.  A :class:`matrix` ``X`` of size 
+    (:math:`k+1`, :math:`n`) can represent the band matrices 
+
+    .. math::
+
+        \left[ \begin{array}{ccccccc}
+            \Re X[0,0] & \bar X[1,0]   & \bar X[2,0]   & \cdots & 
+                \bar X[k,0]   & 0        & \cdots \\
+            X[1,0] & \Re X[0,1]   & \bar X[1,1]   & \cdots & 
+                \bar X[k-1,1] & \bar X[k,1]   & \cdots \\
+            X[2,0] & X[1,1]   & \Re X[0,2]   & \cdots & 
+                \bar X[k-2,2] & \bar X[k-1,2] & \cdots \\
+            \vdots & \vdots   &  \vdots  & \ddots & \vdots   
+                & \vdots   & \ddots \\
+            X[k,0] & X[k-1,1] & X[k-2,2] & \cdots &  &  & \\
+            0      & X[k,1]   & X[k-1,2] & \cdots &  &  & \\
+            \vdots & \vdots   & \vdots   & \ddots &  &  & 
+        \end{array}\right] \quad \mbox{(uplo = 'L')}, 
+
+        \left[ \begin{array}{ccccccc}
+            \Re X[k,0]   & X[k-1,1] & X[k-2,2] & \cdots & X[0,k] & 
+                0        & \cdots \\
+            \bar X[k-1,1] & \Re X[k,1]   & X[k-1,2] & \cdots & 
+                X[1,k] & X[0,k+1] & \cdots \\
+            \bar X[k-2,2] & \bar X[k-1,2] & \Re X[k,2]   & \cdots & 
+                X[2,k] & X[1,k+1] & \cdots \\
+            \vdots   & \vdots   & \vdots   & \ddots & \vdots & 
+                \vdots   & \ddots \\
+            \bar X[0,k]   & \bar X[1,k]   & \bar X[2,k]   & \cdots &  
+                &  & \\
+            0        & \bar X[0,k+1] & \bar X[1,k+1] & \cdots &  &  & \\
+            \vdots   & \vdots   & \vdots   & \ddots &  &  & 
+        \end{array}\right] \quad \mbox{(uplo='U')}.
+
+
+**Triangular band matrix**
+    A triangular band matrix of order :math:`n` with :math:`k` subdiagonals
+    or superdiagonals is represented by a real complex matrix of size 
+    (:math:`k+1`, :math:`n`) and two character arguments ``uplo``  and 
+    ``diag``, with similar conventions as for symmetric band matrices. 
+    A :class:`matrix` ``X`` of size (:math:`k+1`, :math:`n`) can represent 
+    the band matrices 
+
+    .. math::
+
+        \left[ \begin{array}{cccc}
+            X[0,0] & 0        & 0        & \cdots \\
+            X[1,0] & X[0,1]   & 0        & \cdots  \\
+            X[2,0] & X[1,1]   & X[0,2]   & \cdots \\
+            \vdots & \vdots   & \vdots   & \ddots \\
+            X[k,0] & X[k-1,1] & X[k-2,2] & \cdots \\
+            0      & X[k,1]   & X[k-1,1] & \cdots \\
+            \vdots & \vdots   & \vdots   & \ddots 
+        \end{array}\right] \quad \mbox{(uplo = 'L', diag = 'N')}, 
+
+        \left[ \begin{array}{cccc}
+            1      & 0        & 0        & \cdots \\
+            X[1,0] & 1        & 0        & \cdots  \\
+            X[2,0] & X[1,1]   & 1        & \cdots \\
+            \vdots & \vdots   & \vdots   & \ddots \\
+            X[k,0] & X[k-1,1] & X[k-2,2] & \cdots \\
+            0      & X[k,1]   & X[k-1,2] & \cdots \\
+            \vdots & \vdots   & \vdots   & \ddots 
+        \end{array}\right] \quad \mbox{(uplo = 'L', diag = 'U')},
+
+        \left[ \begin{array}{ccccccc}
+            X[k,0] & X[k-1,1] & X[k-2,3] & \cdots & X[0,k]  & 
+                0        & \cdots\\
+            0      & X[k,1]   & X[k-1,2] & \cdots & X[1,k]  & 
+                X[0,k+1] & \cdots \\
+            0      & 0        & X[k,2]   & \cdots & X[2,k]  & 
+                X[1,k+1] & \cdots \\
+            \vdots & \vdots   &  \vdots  & \ddots & \vdots  & 
+                \vdots   & \ddots  
+        \end{array}\right] \quad \mbox{(uplo = 'U', diag = 'N')},
+
+        \left[ \begin{array}{ccccccc}
+            1      & X[k-1,1] & X[k-2,3] & \cdots & X[0,k]  & 
+                0        & \cdots\\
+            0      & 1        & X[k-1,2] & \cdots & X[1,k]  & 
+                X[0,k+1] & \cdots \\
+            0      & 0        & 1        & \cdots & X[2,k]  & 
+                X[1,k+1] & \cdots \\
+            \vdots & \vdots   &  \vdots  & \ddots & \vdots  & 
+                \vdots   & \ddots  
+        \end{array}\right] \quad \mbox{(uplo = 'U', diag = 'U')}.
+
+
+When discussing BLAS functions in the following sections we will omit 
+several less important optional arguments that can be used to select 
+submatrices for in-place operations.  The complete specification is  
+documented in the docstrings of the source code, and can be viewed with the
+:program:`pydoc` help program.
+
+
+.. _s-blas-1:
+
+Level 1 BLAS
+============
+
+The level 1 functions implement vector operations.  
+
+.. function:: cvxopt.blas.scal(alpha, x)
+
+    Scales a vector by a constant: 
+
+    .. math::
+
+        x := \alpha x.
+    
+    If ``x`` is a real :class:`matrix`, the scalar argument ``alpha`` must 
+    be a Python integer or float.  If ``x`` is complex, ``alpha`` can be an 
+    integer, float, or complex.
+
+
+.. function:: cvxopt.blas.nrm2(x)
+
+    Euclidean norm of a vector:  returns 
+
+    .. math::
+
+        \|x\|_2.
+
+
+.. function:: cvxopt.blas.asum(x)
+
+    1-Norm of a vector: returns 
+
+    .. math::
+
+        \|x\|_1 \quad \mbox{($x$ real)}, \qquad  
+        \|\Re x\|_1 + \|\Im x\|_1 \quad \mbox{($x$ complex)}.
+
+
+.. function:: cvxopt.blas.iamax(x)
+
+    Returns 
+
+    .. math::
+ 
+        \mathop{\rm argmax}_{k=0,\ldots,n-1} |x_k| \quad \mbox{($x$ real)}, 
+        \qquad
+        \mathop{\rm argmax}_{k=0,\ldots,n-1} |\Re x_k| + |\Im x_k| \quad 
+            \mbox{($x$ complex)}. 
+
+
+    If more than one coefficient achieves the maximum, the index of the 
+    first :math:`k` is returned.  
+
+
+.. function:: cvxopt.blas.swap(x, y)
+
+    Interchanges two vectors:
+
+    .. math::
+
+        x \leftrightarrow y.
+
+    ``x``  and ``y`` are matrices of the same type (:const:`'d'` or 
+    :const:`'z'`).
+    
+
+.. function:: cvxopt.blas.copy(x, y)
+
+    Copies a vector to another vector:
+
+    .. math::
+
+        y := x.
+    
+    ``x`` and ``y`` are matrices of the same type (:const:`'d'` or 
+    :const:`'z'`).
+
+
+.. function:: cvxopt.blas.axpy(x, y[, alpha = 1.0])
+
+    Constant times a vector plus a vector:  
+
+    .. math::
+
+        y := \alpha x + y.
+    
+    ``x`` and ``y`` are matrices of the same type (:const:`'d'` or 
+    :const:`'z'`).  If ``x`` is real, the scalar argument ``alpha`` must be 
+    a Python integer or float.  If ``x`` is complex, ``alpha`` can be an 
+    integer, float, or complex.  
+
+
+.. function:: cvxopt.blas.dot(x, y)
+
+    Returns 
+
+    .. math::
+
+        x^Hy. 
+
+    ``x`` and ``y`` are matrices of the same type (:const:`'d'` or 
+    :const:`'z'`).  
+
+
+.. function:: cvxopt.blas.dotu(x, y)
+
+    Returns 
+
+    .. math::
+
+        x^Ty. 
+    
+    ``x`` and ``y`` are matrices of the same type (:const:`'d'` or 
+    :const:`'z'`).
+
+
+
+.. _s-blas-2:
+
+Level 2 BLAS
+============
+
+The level 2 functions implement matrix-vector products and rank-1 and 
+rank-2 matrix updates.  Different types of matrix structure can be exploited
+using the conventions of the section :ref:`s-conventions`. 
+
+.. function:: cvxopt.blas.gemv(A, x, y[, trans = 'N', alpha = 1.0, beta = 0.0])
+
+    Matrix-vector product with a general matrix:  
+
+    .. math::
+        
+        y & := \alpha Ax + \beta y \quad 
+            (\mathrm{trans} = \mathrm{'N'}), \\
+        y & := \alpha A^T x + \beta y \quad 
+            (\mathrm{trans} = \mathrm{'T'}),  \\
+        y & := \alpha A^H x + \beta y \quad 
+            (\mathrm{trans} = \mathrm{'C'}). 
+
+    The arguments ``A``, ``x``, and ``y`` must have the same type 
+    (:const:`'d'` or :const:`'z'`).  Complex values of ``alpha`` and 
+    ``beta`` are only allowed if ``A`` is complex. 
+
+
+.. function:: cvxopt.blas.symv(A, x, y[, uplo = 'L', alpha = 1.0, beta = 0.0])
+
+    Matrix-vector  product with a real symmetric matrix:  
+
+    .. math::
+
+        y := \alpha A x + \beta y,
+
+    where :math:`A` is a real symmetric matrix.  The arguments ``A``, 
+    ``x``, and ``y`` must have type :const:`'d'`, and ``alpha`` and 
+    ``beta`` must be real.
+
+
+.. function:: cvxopt.blas.hemv(A, x, y[, uplo = 'L', alpha = 1.0, beta = 0.0])
+
+    Matrix-vector  product with a real symmetric or complex Hermitian 
+    matrix: 
+
+    .. math::
+
+        y := \alpha A x + \beta y,
+
+    where :math:`A` is real symmetric or complex Hermitian.  The arguments 
+    ``A``, ``x``, ``y`` must have the same type (:const:`'d'` or 
+    :const:`'z'`).  Complex values of ``alpha`` and ``beta`` are only
+    allowed if ``A``  is complex. 
+
+
+.. function:: cvxopt.blas.trmv(A, x[, uplo = 'L', trans = 'N', diag = 'N'])
+
+    Matrix-vector  product with a triangular matrix: 
+
+    .. math::
+
+        x & := Ax \quad (\mathrm{trans} = \mathrm{'N'}), \\
+        x & := A^T x \quad (\mathrm{trans} = \mathrm{'T'}), \\
+        x & := A^H x \quad (\mathrm{trans} = \mathrm{'C'}), 
+
+    where :math:`A` is square and triangular.  The arguments ``A`` and 
+    ``x`` must have the same type (:const:`'d'` or :const:`'z'`).
+
+
+.. function:: cvxopt.blas.trsv(A, x[, uplo = 'L', trans = 'N', diag = 'N'])
+
+    Solution of a nonsingular triangular set of linear equations:
+
+    .. math::
+   
+        x & := A^{-1}x \quad (\mathrm{trans} = \mathrm{'N'}), \\
+        x & := A^{-T}x \quad (\mathrm{trans} = \mathrm{'T'}), \\
+        x & := A^{-H}x \quad (\mathrm{trans} = \mathrm{'C'}), 
+
+    where :math:`A` is square and triangular with nonzero diagonal elements.
+    The arguments ``A``  and ``x`` must have the same type (:const:`'d'` or
+    :const:`'z'`).
+
+
+.. function:: cvxopt.blas.gbmv(A, m, kl, x, y[, trans = 'N', alpha = 1.0, beta = 0.0])
+    
+    Matrix-vector product with a general band matrix:
+
+    .. math::
+
+        y & := \alpha Ax + \beta y \quad 
+            (\mathrm{trans} = \mathrm{'N'}), \\
+        y & := \alpha A^T x + \beta y \quad
+            (\mathrm{trans} = \mathrm{'T'}),  \\
+        y & := \alpha A^H x + \beta y \quad 
+            (\mathrm{trans} = \mathrm{'C'}),
+
+    where  :math:`A` is a rectangular band matrix with :math:`m` rows and 
+    :math:`k_l` subdiagonals.  The arguments ``A``, ``x``, ``y``  must have 
+    the same type (:const:`'d'` or :const:`'z'`).  Complex values of 
+    ``alpha``  and ``beta``  are only allowed if ``A`` is complex.
+
+
+.. function:: cvxopt.blas.sbmv(A, x, y[, uplo = 'L', alpha = 1.0, beta = 0.0])
+
+    Matrix-vector  product with a real symmetric band matrix:
+
+    .. math::
+ 
+        y := \alpha Ax + \beta y,
+
+    where :math:`A`  is a real symmetric band matrix.  The arguments 
+    ``A``, ``x``, ``y``  must have type :const:`'d'`, and ``alpha`` and 
+    ``beta`` must be real.
+
+
+.. function:: cvxopt.blas.hbmv(A, x, y[, uplo = 'L', alpha = 1.0, beta = 0.0])
+
+    Matrix-vector  product with a real symmetric or complex Hermitian band 
+    matrix:
+
+    .. math::
+
+        y := \alpha Ax + \beta y,
+
+    where :math:`A` is a real symmetric or complex Hermitian band matrix.
+    The arguments ``A``, ``x``,  ``y``  must have the same type
+    (:const:`'d'` or :const:`'z'`).  Complex values of ``alpha`` and 
+    ``beta``  are only allowed if ``A``  is complex. 
+
+
+.. function:: cvxopt.blas.tbmv(A, x[, uplo = 'L', trans = 'N',  diag = 'N'])
+
+    Matrix-vector  product with a triangular band matrix:
+
+    .. math::
+
+        x & := Ax \quad (\mathrm{trans} = \mathrm{'N'}), \\
+        x & := A^T x \quad (\mathrm{trans} = \mathrm{'T'}), \\
+        x & := A^H x \quad (\mathrm{trans} = \mathrm{'C'}). 
+
+    The arguments ``A`` and ``x``  must have the same type (:const:`'d'` or
+    :const:`'z'`).
+
+
+.. function:: cvxopt.blas.tbsv(A, x[, uplo = 'L', trans = 'N', diag = 'N'])
+
+    Solution of a triangular banded set of linear equations:
+
+    .. math::
+
+        x & := A^{-1}x \quad (\mathrm{trans} = \mathrm{'N'}), \\
+        x & := A^{-T} x \quad (\mathrm{trans} = \mathrm{'T'}), \\
+        x & := A^{-H} x \quad (\mathrm{trans} = \mathrm{'T'}), 
+
+    where :math:`A` is a triangular band matrix of with nonzero diagonal 
+    elements.  The arguments ``A``  and ``x``  must have the same type 
+    (:const:`'d'` or :const:`'z'`).
+
+
+.. function:: cvxopt.blas.ger(x, y, A[, alpha = 1.0])
+
+    General rank-1 update:
+
+    .. math::
+
+        A := A + \alpha x y^H,
+
+    where :math:`A` is a general matrix.  The arguments ``A``, ``x``, and 
+    ``y``  must have the same type (:const:`'d'` or :const:`'z'`).  Complex
+    values of ``alpha``  are only allowed if ``A``  is complex.
+
+
+.. function:: cvxopt.blas.geru(x, y, A[, alpha = 1.0])
+
+    General rank-1 update:
+
+    .. math::
+
+        A := A + \alpha x y^T, 
+
+    where :math:`A` is a general matrix.  The arguments ``A``, ``x``,  and 
+    ``y``  must have the same type (:const:`'d'` or :const:`'z'`).  Complex
+    values of ``alpha``  are only allowed if ``A``  is complex.
+
+
+.. function:: cvxopt.blas.syr(x, A[, uplo = 'L', alpha = 1.0])
+
+    Symmetric rank-1 update:
+
+    .. math::
+ 
+        A := A + \alpha xx^T,
+
+    where :math:`A` is a real symmetric matrix.  The arguments ``A``  and 
+    ``x``  must have type :const:`'d'`.  ``alpha``  must be a real number.
+
+
+.. function:: cvxopt.blas.her(x, A[, uplo = 'L', alpha = 1.0])
+
+    Hermitian rank-1 update:
+
+    .. math::
+
+        A := A + \alpha xx^H, 
+
+    where :math:`A` is a real symmetric or complex Hermitian matrix.  The 
+    arguments ``A``  and ``x``  must have the same type (:const:`'d'` or 
+    :const:`'z'`).  ``alpha``  must be a real number.
+
+
+.. function:: cvxopt.blas.syr2(x, y, A[, uplo = 'L', alpha = 1.0])
+
+    Symmetric rank-2  update:
+
+    .. math::
+
+        A := A + \alpha (xy^T + yx^T),
+
+    where :math:`A` is a real symmetric matrix.  The arguments ``A``, ``x``,
+    and ``y`` must have type :const:`'d'`.  ``alpha``  must be real.
+
+
+.. function:: cvxopt.blas.her2(x, y, A[, uplo = 'L', alpha = 1.0])
+
+    Symmetric rank-2  update:
+
+    .. math::
+
+        A := A + \alpha xy^H + \bar \alpha yx^H,
+
+    where :math:`A` is a a real symmetric or complex Hermitian matrix.
+    The arguments ``A``, ``x``, and ``y`` must have the same type  
+    (:const:`'d'` or :const:`'z'`).  Complex values of ``alpha`` are only 
+    allowed if ``A`` is complex.
+
+
+As an example, the following code multiplies the tridiagonal matrix
+
+.. math::
+
+    A = \left[\begin{array}{rrrr}
+          1 &  6 &  0 & 0 \\ 
+          2 & -4 &  3 & 0 \\ 
+          0 & -3 & -1 & 1 
+    \end{array}\right]
+
+with the vector :math:`x = (1,-1,2,-2)`.
+
+>>> from cvxopt import matrix
+>>> from cvxopt.blas import gbmv
+>>> A = matrix([[0., 1., 2.],  [6., -4., -3.],  [3., -1., 0.],  [1., 0., 0.]])
+>>> x = matrix([1., -1., 2., -2.])
+>>> y = matrix(0., (3,1))
+>>> gbmv(A, 3, 1, x, y)
+>>> print y
+[-5.00e+00]
+[ 1.20e+01]
+[-1.00e+00]
+
+
+The following example illustrates the use of 
+:func:`tbsv <cvxopt.blas.tbsv>`.
+
+>>> from cvxopt import matrix
+>>> from cvxopt.blas import tbsv
+>>> A = matrix([-6., 5., -1., 2.], (1,4))
+>>> x = matrix(1.0, (4,1))
+>>> tbsv(A, x)  # x := diag(A)^{-1}*x
+>>> print x
+[-1.67e-01]
+[ 2.00e-01]
+[-1.00e+00]
+[ 5.00e-01]
+
+
+.. _s-blas-3:
+
+Level 3 BLAS 
+============
+
+The level 3 BLAS include functions for matrix-matrix multiplication.
+
+.. function:: cvxopt.blas.gemm(A, B, C[, transA = 'N', transB = 'N', alpha = 1.0, beta = 0.0])
+
+    Matrix-matrix product of two general matrices:  
+
+    .. math::
+
+        \newcommand{\op}{\mathop{\mathrm{op}}}
+        C := \alpha \op(A) \op(B) + \beta C 
+
+    where
+
+    .. math::
+
+        \newcommand{\op}{\mathop{\mathrm{op}}}
+        \op(A) =  \left\{ \begin{array}{ll}
+            A & \mathrm{transA} = \mathrm{'N'} \\
+            A^T & \mathrm{transA} = \mathrm{'T'} \\
+            A^H & \mathrm{transA} = \mathrm{'C'} \end{array} \right.
+        \qquad
+        \op(B) =  \left\{ \begin{array}{ll}
+            B & \mathrm{transB} = \mathrm{'N'} \\
+            B^T & \mathrm{transB} = \mathrm{'T'} \\
+            B^H & \mathrm{transB} = \mathrm{'C'}. \end{array} \right.
+
+    The arguments ``A``, ``B``, and ``C`` must have the same type 
+    (:const:`'d'` or :const:`'z'`).  Complex values of ``alpha`` and 
+    ``beta`` are only allowed if ``A`` is complex.
+
+
+.. function:: cvxopt.blas.symm(A, B, C[, side = 'L', uplo = 'L', alpha =1.0,  beta = 0.0])
+
+    Product of a real or complex symmetric matrix :math:`A` and a general 
+    matrix :math:`B`:
+
+    .. math::
+
+        C & := \alpha AB + \beta C \quad (\mathrm{side} = \mathrm{'L'}), \\
+        C & := \alpha BA + \beta C \quad (\mathrm{side} = \mathrm{'R'}). 
+
+    The arguments ``A``, ``B``, and ``C``  must have the same type 
+    (:const:`'d'` or :const:`'z'`).  Complex values of ``alpha``  and 
+    ``beta`` are only allowed if ``A`` is complex.
+
+
+.. function:: cvxopt.blas.hemm(A, B, C[, side = 'L', uplo = 'L', alpha = 1.0,  beta = 0.0])
+
+    Product of a real symmetric or complex Hermitian matrix :math:`A` and a 
+    general matrix :math:`B`:
+
+    .. math::
+ 
+        C & := \alpha AB + \beta C \quad (\mathrm{side} = \mathrm{'L'}), \\
+        C & := \alpha BA + \beta C \quad (\mathrm{side} = \mathrm{'R'}). 
+
+    The arguments ``A``, ``B``,  and ``C`` must have the same type 
+    (:const:`'d'` or :const:`'z'`).  Complex values of ``alpha`` and 
+    ``beta``  are only allowed if ``A`` is complex.
+
+
+.. function:: cvxopt.blas.trmm(A, B[, side = 'L', uplo = 'L', transA = 'N', diag = 'N', alpha = 1.0])
+
+    Product of a triangular matrix :math:`A` and a general matrix :math:`B`:
+
+    .. math::
+
+        \newcommand{\op}{\mathop{\mathrm{op}}} 
+        \begin{split}
+        B & := \alpha\op(A)B \quad (\mathrm{side} = \mathrm{'L'}), \\ 
+        B & := \alpha B\op(A) \quad (\mathrm{side} = \mathrm{'R'}) 
+        \end{split}
+
+    where
+
+    .. math::
+
+        \newcommand{\op}{\mathop{\mathrm{op}}}
+        \op(A) =  \left\{ \begin{array}{ll}
+             A & \mathrm{transA} = \mathrm{'N'} \\
+             A^T & \mathrm{transA} = \mathrm{'T'} \\
+             A^H & \mathrm{transA} = \mathrm{'C'}. \end{array} \right.
+
+    The arguments ``A`` and ``B`` must have the same type (:const:`'d'` or 
+    :const:`'z'`).  Complex values of ``alpha`` are only allowed if ``A`` 
+    is complex.
+
+
+.. function:: cvxopt.blas.trsm(A, B[, side = 'L', uplo = 'L', transA = 'N', diag = 'N', alpha = 1.0])
+
+    Solution of a nonsingular triangular system of equations:
+
+    .. math::
+ 
+        \newcommand{\op}{\mathop{\mathrm{op}}}
+        \begin{split}
+        B & := \alpha \op(A)^{-1}B \quad (\mathrm{side} = \mathrm{'L'}), \\
+        B & := \alpha B\op(A)^{-1} \quad (\mathrm{side} = \mathrm{'R'}), 
+        \end{split}
+        
+    where
+
+    .. math::
+
+        \newcommand{\op}{\mathop{\mathrm{op}}}
+        \op(A) =  \left\{ \begin{array}{ll}
+            A & \mathrm{transA} = \mathrm{'N'} \\
+            A^T & \mathrm{transA} = \mathrm{'T'} \\
+            A^H & \mathrm{transA} = \mathrm{'C'}, \end{array} \right.
+
+    :math:`A` is triangular and :math:`B` is a general matrix.  The 
+    arguments ``A`` and ``B`` must have the same type (:const:`'d'` or 
+    :const:`'z'`).  Complex values of ``alpha`` are only allowed if ``A`` 
+    is complex.
+
+
+.. function:: cvxopt.blas.syrk(A, C[, uplo = 'L', trans = 'N', alpha = 1.0, beta = 0.0])
+
+    Rank-:math:`k` update of a real or complex symmetric matrix :math:`C`:
+
+    .. math::
+
+        C & := \alpha AA^T + \beta C \quad 
+            (\mathrm{trans} = \mathrm{'N'}),  \\
+        C & := \alpha A^TA + \beta C \quad 
+            (\mathrm{trans} = \mathrm{'T'}), 
+
+    where :math:`A` is a general matrix.  The arguments ``A`` and ``C`` 
+    must have the same type (:const:`'d'` or :const:`'z'`).  Complex values
+    of ``alpha``  and ``beta`` are only allowed if ``A`` is complex.
+
+
+.. function:: cvxopt.blas.herk(A, C[, uplo = 'L', trans = 'N', alpha = 1.0, beta = 0.0])
+
+    Rank-:math:`k` update of a real symmetric or complex Hermitian matrix 
+    :math:`C`:
+
+    .. math::
+
+        C & := \alpha AA^H + \beta C \quad 
+            (\mathrm{trans} = \mathrm{'N'}), \\
+        C & := \alpha A^HA + \beta C \quad 
+            (\mathrm{trans} = \mathrm{'C'}),
+
+    where :math:`A` is a general matrix.  The arguments ``A`` and ``C`` 
+    must have the same type (:const:`'d'` or :const:`'z'`).  ``alpha`` and 
+    ``beta`` must be real.
+
+
+.. function:: cvxopt.blas.syr2k(A, B, C[, uplo = 'L', trans = 'N', alpha = 1.0, beta = 0.0])
+
+    Rank-:math:`2k` update of a real or complex symmetric matrix :math:`C`:
+
+    .. math::
+
+        C & := \alpha (AB^T + BA^T) + \beta C \quad 
+            (\mathrm{trans} = \mathrm{'N'}), \\
+        C & := \alpha (A^TB + B^TA) + \beta C \quad 
+            (\mathrm{trans} = \mathrm{'T'}). 
+
+    :math:`A` and :math:`B` are general real or complex matrices.  The 
+    arguments ``A``, ``B``, and ``C`` must have the same type.  Complex 
+    values of ``alpha``  and ``beta`` are only allowed if ``A`` is complex.
+
+
+.. function:: cvxopt.blas.her2k(A, B, C[, uplo = 'L', trans = 'N', alpha = 1.0, beta = 0.0])
+
+    Rank-:math:`2k` update of a real symmetric or complex Hermitian matrix 
+    :math:`C`:
+
+    .. math::
+
+        C & := \alpha AB^H + \bar \alpha BA^H + \beta C \quad 
+            (\mathrm{trans} = \mathrm{'N'}), \\
+        C & := \alpha A^HB + \bar\alpha B^HA + \beta C \quad 
+            (\mathrm{trans} = \mathrm{'C'}), 
+
+    where :math:`A` and :math:`B` are general matrices.  The arguments 
+    ``A``, ``B``, and ``C`` must have the same type (:const:`'d'` or 
+    :const:`'z'`).   Complex values of ``alpha`` are only allowed if ``A`` 
+    is complex.  ``beta`` must be real.
diff --git a/doc/source/c-api.rst b/doc/source/c-api.rst
new file mode 100644
index 0000000..412b8a5
--- /dev/null
+++ b/doc/source/c-api.rst
@@ -0,0 +1,218 @@
+.. _c-capi:
+
+*****
+C API
+*****
+
+The API can be used to extend CVXOPT with interfaces to external C routines
+and libraries.  A C program that creates or manipulates the dense or sparse
+matrix objects defined in CVXOPT must include the :const:`cvxopt.h` header 
+file in the :const:`src` directory of the distribution.
+
+Before the C API can be used in an extension module it must be initialized 
+by calling the macro :cmacro:`import_cvxopt`.  As an example we show the 
+module initialization from the :mod:`cvxopt.blas` module, which itself uses
+the API:
+
+.. highlight:: c
+
+::
+
+    PyMODINIT_FUNC initblas(void)
+    {
+      PyObject *m;
+
+      m = Py_InitModule3("cvxopt.blas", blas_functions, blas__doc__);
+
+      if (import_cvxopt() < 0)
+        return;
+    }
+
+  
+Dense Matrices
+==============
+
+As can be seen from the header file :const:`cvxopt.h`, a :class:`matrix` is
+essentially a  structure with four fields.  The fields :cmember:`nrows` and 
+:cmember:`ncols` are two integers that specify the dimensions.  The 
+:cmember:`id` field controls the type of the matrix and can have values 
+:const:`DOUBLE`, :const:`INT`, and :const:`COMPLEX`.  The :cmember:`buffer`
+field is an array that contains the matrix elements stored contiguously in 
+column-major order. 
+
+The following C functions can be used to create matrices.
+
+.. cfunction:: matrix * Matrix_New(int nrows, int ncols, int id)
+
+    Returns a :class:`matrix` object of type `id` with `nrows` rows and 
+    `ncols` columns.  The elements of the matrix are uninitialized.
+
+
+.. cfunction:: matrix * Matrix_NewFromMatrix(matrix *src, int id)
+
+    Returns a copy of the matrix `src` converted to type `id`.  The 
+    following type conversions are allowed:  :const:`'i'` to :const:`'d'`,
+    :const:`'i'` to :const:`'z'`, and :const:`'d'`  to :const:`'z'`.
+
+
+.. cfunction:: matrix * Matrix_NewFromSequence(PyListObject *x, int id)
+
+    Creates a matrix of type `id` from the Python sequence type `x`. The
+    returned matrix has size ``(len(x), 1)``.  The size can be changed 
+    by modifying the :cmember:`nrows` and :cmember:`ncols` fields of the 
+    returned matrix.
+
+
+To illustrate the creation and manipulation of dense matrices (as well as 
+the Python C API), we show the code for the :func:`cvxopt.uniform` function 
+described in the section :ref:`s-random`.
+
+::
+
+    PyObject * uniform(PyObject *self, PyObject *args, PyObject *kwrds) 
+    {
+      matrix *obj;
+      int i, nrows, ncols = 1;
+      double a = 0, b = 1;
+      char *kwlist[] = {"nrows", "ncols", "a", "b", NULL};
+
+      if (!PyArg_ParseTupleAndKeywords(args, kwrds, "i|idd", kwlist, 
+              &nrows, &ncols, &a, &b)) return NULL;
+      
+      if ((nrows<0) || (ncols<0)) {
+        PyErr_SetString(PyExc_TypeError, "dimensions must be non-negative");
+        return NULL;
+      }
+      
+      if (!(obj = Matrix_New(nrows, ncols, DOUBLE)))
+        return PyErr_NoMemory();
+      
+      for (i = 0; i < nrows*ncols; i++)
+        MAT_BUFD(obj)[i] = Uniform(a,b);
+      
+      return (PyObject *)obj;
+    }
+
+
+Sparse Matrices
+===============
+
+Sparse matrices are stored in compressed column storage (CCS) format.  For 
+a general `nrows` by `ncols` sparse matrix with `nnz` nonzero entries this 
+means the following.  The sparsity pattern and the nonzero values are 
+stored in three fields:
+
+:cmember:`values` 
+    A :const:`'d'` or :const:`'z'` matrix of size ``(nnz,1)``  with the 
+    nonzero entries of the matrix stored columnwise.  
+
+:cmember:`rowind` 
+    An array of integers of length `nnz` containing the row indices of 
+    the nonzero entries, stored in the same order as :cmember:`values`.
+
+:cmember:`colptr` 
+    An array of integers of length `ncols` + 1 with for each column of the 
+    matrix the index of the first element in :cmember:`values` from that 
+    column.  More precisely, ``colptr[0]`` is :const:`0`, and for 
+    k = 0, 1, ..., `ncols` - 1, ``colptr[k+1]`` is equal to 
+    ``colptr[k]`` plus the number of nonzeros in column `k` of the
+    matrix.  Thus, ``colptr[ncols]`` is equal to `nnz`, the number of 
+    nonzero entries.
+
+
+For example, for the matrix
+
+.. math::
+
+    A=\left [\begin{array}{cccc}
+        1 & 0 & 0 & 5\\
+        2 & 0 & 4 & 0\\
+        0 & 0 & 0 & 6\\
+        3 & 0 & 0 & 0
+    \end{array}\right]
+
+the elements of :cmember:`values`, :cmember:`rowind`, and :cmember:`colptr` 
+are:
+
+:cmember:`values`:
+    1.0, 2.0, 3.0, 4.0, 5.0, 6.0
+
+:cmember:`rowind`:
+    0, 1,3, 1, 0, 2
+
+:cmember:`colptr`: 
+    0, 3, 3, 4, 6.
+
+It is crucial that for each column the row indices in :cmember:`rowind` are
+sorted; the equivalent representation 
+
+:cmember:`values`:
+    3.0, 2.0, 1.0, 4.0, 5.0, 6.0
+
+:cmember:`rowind`:
+    3, 1, 0, 1, 0, 2
+
+:cmember:`colptr`: 
+    0, 3, 3, 4, 6
+
+is not allowed (and will likely cause the program to crash).
+
+The :cmember:`nzmax` field specifies the number of non-zero elements the
+matrix can store.  It is equal to the length of :cmember:`rowind` and 
+:cmember:`values`; this number can be larger that ``colptr[nrows]``, 
+but never less.  This field makes it possible to preallocate a certain 
+amount of memory to avoid reallocations if the matrix is constructed
+sequentially by filling in elements.  In general the :cmember:`nzmax` field
+can safely be ignored, however, since it will always be adjusted 
+automatically as the number of non-zero elements grows.
+
+The :cmember:`id` field controls the type of the matrix and can have 
+values :const:`DOUBLE` and :const:`COMPLEX`. 
+
+Sparse matrices are created using the following functions from the API. 
+
+.. cfunction:: spmatrix * SpMatrix_New(int nrows, int ncols, int nzmax, int id) 
+
+  Returns a sparse zero matrix with `nrows` rows and `ncols` columns. 
+  `nzmax` is the number of elements that will be allocated (the length of 
+  the :cmember:`values` and :cmember:`rowind` fields).  
+
+
+.. cfunction:: spmatrix * SpMatrix_NewFromMatrix(spmatrix *src, int id)
+
+      Returns a copy the sparse matrix \var{src}. 
+
+
+.. cfunction:: spmatrix * SpMatrix_NewFromIJV(matrix *I, matrix *J, matrix *V, int nrows, int ncols, int nzmax, int id)
+
+    Creates a sparse matrix with `nrows` rows and `ncols` columns from a 
+    triplet description.  `I` and `J` must be integer matrices and `V` 
+    either a double or complex matrix, or :const:`NULL`. If `V` is 
+    :const:`NULL` the values of the entries in the matrix are undefined, 
+    otherwise they are specified by `V`.  Repeated entries in `V` are 
+    summed.  The number of allocated elements is given by `nzmax`, which is 
+    adjusted if it is smaller than the required amount. 
+
+We illustrate use of the sparse matrix class by listing the source
+code for the :attr:`real` method, which returns the real part of
+a sparse matrix: 
+
+::
+
+    static PyObject * spmatrix_real(spmatrix *self) {
+
+      if (SP_ID(self) != COMPLEX) 
+        return (PyObject *)SpMatrix_NewFromMatrix(self, 0, SP_ID(self));
+      
+      spmatrix *ret = SpMatrix_New(SP_NROWS(self), SP_NCOLS(self), 
+          SP_NNZ(self), DOUBLE);
+      if (!ret) return PyErr_NoMemory();
+
+      int i;
+      for (i=0; i < SP_NNZ(self); i++) 
+        SP_VALD(ret)[i] = creal(SP_VALZ(self)[i]);
+      
+      memcpy(SP_COL(ret), SP_COL(self), (SP_NCOLS(self)+1)*sizeof(int_t));
+      memcpy(SP_ROW(ret), SP_ROW(self), SP_NNZ(self)*sizeof(int_t));
+      return (PyObject *)ret;
+    }
diff --git a/doc/source/coneprog.rst b/doc/source/coneprog.rst
new file mode 100644
index 0000000..574bf06
--- /dev/null
+++ b/doc/source/coneprog.rst
@@ -0,0 +1,2147 @@
+.. _c-coneprog:
+
+****************
+Cone Programming
+****************
+
+In this chapter we consider convex optimization problems of the form
+
+.. math:: 
+
+    \begin{array}{ll}
+    \mbox{minimize}   & (1/2) x^TPx + q^T x \\
+    \mbox{subject to} & G x \preceq h \\ 
+                      & Ax = b.
+    \end{array}
+
+The linear inequality is a generalized inequality with respect to a 
+proper convex cone.  It may include componentwise vector inequalities, 
+second-order cone inequalities, and linear matrix inequalities.  
+
+The main solvers are :func:`conelp <cvxopt.solvers.conelp>` and 
+:func:`coneqp <cvxopt.solvers.coneqp>`, described in the
+sections :ref:`s-conelp` and :ref:`s-coneqp`.  The function 
+:func:`conelp` is restricted to problems with linear cost functions, and 
+can detect primal and dual infeasibility.  The function :func:`coneqp` 
+solves the general quadratic problem, but requires the problem to be 
+strictly primal and dual feasible.  For convenience (and backward 
+compatibility), simpler interfaces to these function are also provided 
+that handle pure linear programs, quadratic programs, second-order cone 
+programs, and semidefinite programs.  These are described in the sections
+:ref:`s-lpsolver`, :ref:`s-qp`, :ref:`s-socpsolver`, :ref:`s-sdpsolver`.  
+In the section :ref:`s-conelp-struct` we explain how custom solvers can 
+be implemented that exploit structure in cone programs.  The last two 
+sections describe optional interfaces to external solvers, and the 
+algorithm parameters that control the cone programming solvers.
+
+
+.. _s-conelp:
+
+Linear Cone Programs 
+====================
+
+.. function:: cvxopt.solvers.conelp(c, G, h[, dims[, A, b[, primalstart[, dualstart[, kktsolver]]]]])
+
+    Solves a pair of primal and dual cone programs
+
+    .. math::
+    
+        \begin{array}[t]{ll}
+        \mbox{minimize}   & c^T x \\
+        \mbox{subject to} & G x + s = h \\ 
+                          & Ax = b \\ 
+                          & s \succeq 0
+        \end{array}
+        \qquad\qquad
+        \begin{array}[t]{ll}
+        \mbox{maximize}   & -h^T z - b^T y \\
+        \mbox{subject to} & G^T z + A^T y + c = 0 \\
+                          & z \succeq 0.
+        \end{array}
+   
+    The primal variables are :math:`x` and :math:`s`.  The dual variables  
+    are :math:`y`, :math:`z`.  The inequalities are interpreted as 
+    :math:`s \in C`, :math:`z\in C`, where :math:`C` is a cone defined as 
+    a Cartesian product of a nonnegative orthant, a number of second-order
+    cones, and a number of positive semidefinite cones:
+
+    .. math::
+
+        C = C_0 \times C_1 \times \cdots \times C_M \times C_{M+1} \times
+            \cdots \times C_{M+N}
+
+    with
+
+    .. math::
+
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        \newcommand{\svec}{\mathop{\mathbf{vec}}}
+        \newcommand{\symm}{{\mbox{\bf S}}}
+        \begin{split}
+            C_0 & = 
+                \{ u \in \reals^l \;| \; u_k \geq 0, \; k=1, \ldots,l\}, \\
+            C_{k+1} & = \{ (u_0, u_1) \in \reals \times \reals^{r_{k}-1} 
+                \; | \; u_0 \geq \|u_1\|_2 \},  \quad k=0,\ldots, M-1, \\
+            C_{k+M+1} &= \left\{ \svec(u) \; | \; u \in \symm^{t_k}_+ 
+                \right\}, \quad k=0,\ldots,N-1.
+        \end{split}
+
+    In this definition, :math:`\mathbf{vec}(u)` denotes a symmetric matrix
+    :math:`u` stored as a vector in column major order.  The structure of 
+    :math:`C` is specified by ``dims``.  This argument is a dictionary with
+    three fields. 
+   
+    ``dims['l']``: 
+        :math:`l`, the dimension of the nonnegative orthant (a nonnegative
+        integer).
+
+    ``dims['q']``: 
+        :math:`[r_0, \ldots, r_{M-1}]`, a list with the dimensions of the 
+        second-order cones (positive integers).
+
+    ``dims['s']``: 
+        :math:`[t_0, \ldots, t_{N-1}]`, a list with the dimensions of the 
+        positive semidefinite cones (nonnegative integers).
+    
+    The default value of ``dims`` is 
+    ``{'l': G.size[0], 'q': [], 's': []}``, 
+    i.e., by default the 
+    inequality is interpreted as a componentwise vector inequality. 
+
+    The arguments ``c``, ``h``, and ``b`` are real single-column dense 
+    matrices.  ``G`` and ``A`` are real dense or sparse matrices.  The 
+    number of rows of ``G`` and ``h`` is equal to
+
+    .. math::
+    
+        K = l + \sum_{k=0}^{M-1} r_k + \sum_{k=0}^{N-1} t_k^2.
+   
+    The columns of ``G`` and ``h`` are vectors in
+
+    .. math::
+
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        \reals^l \times \reals^{r_0} \times \cdots \times 
+        \reals^{r_{M-1}} \times \reals^{t_0^2}  \times \cdots \times 
+        \reals^{t_{N-1}^2},
+
+    where the last :math:`N` components represent symmetric matrices 
+    stored in column major order.  The strictly upper triangular entries 
+    of these matrices are not accessed (i.e.,  the symmetric matrices are 
+    stored in the :const:`'L'`-type column major order used in the 
+    :mod:`blas` and :mod:`lapack` modules).  The default values for ``A`` 
+    and ``b`` are matrices with zero rows, meaning that there are no 
+    equality constraints.  
+
+    ``primalstart`` is a dictionary with keys :const:`'x'` and 
+    :const:`'s'`, used as an optional primal starting point.   
+    ``primalstart['x']`` and ``primalstart['s']`` are real dense 
+    matrices of size (:math:`n`, 1) and (:math:`K`, 1), respectively, 
+    where :math:`n` is the length of ``c``.  The vector 
+    ``primalstart['s']`` must be strictly positive with respect
+    to the cone :math:`C`.
+
+    ``dualstart`` is a dictionary with keys :const:`'y'` and :const:`'z'`, 
+    used as an optional dual starting point.  ``dualstart['y']`` and 
+    ``dualstart['z']`` are real dense matrices of size (:math:`p`, 1) 
+    and (:math:`K`, 1), respectively, where :math:`p` is the number of 
+    rows in ``A``.  The vector ``dualstart['s']`` must be strictly 
+    positive with respect to the cone :math:`C`.
+
+    The role of the optional argument ``kktsolver`` is explained in 
+    the section :ref:`s-conelp-struct`.  
+
+    :func:`conelp` returns a dictionary that contains the result and 
+    information about the accuracy of the solution.  The most important 
+    fields have keys :const:`'status'`, :const:`'x'`, :const:`'s'`, 
+    :const:`'y'`, :const:`'z'`.  The :const:`'status'` field  is a string 
+    with possible values :const:`'optimal'`, :const:`'primal infeasible'`,
+    :const:`'dual infeasible'`, and :const:`'unknown'`.  The meaning of 
+    the :const:`'x'`, :const:`'s'`, :const:`'y'`, :const:`'z'` fields 
+    depends on the value of :const:`'status'`.
+
+
+    :const:`'optimal'` 
+        In this case the :const:`'x'`, :const:`'s'`, :const:`'y'`, and 
+        :const:`'z'` entries contain the primal and dual solutions, which 
+        approximately satisfy
+
+        .. math::
+        
+            Gx + s = h, \qquad Ax = b, \qquad G^T z  + A^T y + c = 0,
+         
+            s \succeq 0, \qquad z \succeq 0, \qquad  s^T z = 0.
+
+        The other entries in the output dictionary summarize the accuracy
+        with which these optimality conditions are satisfied.  The fields 
+        :const:`'primal objective'`, :const:`'dual objective'`, and
+        :const:`'gap'` give the primal objective :math:`c^Tx`, dual 
+        objective :math:`-h^Tz - b^Ty`, and the gap :math:`s^Tz`.  The 
+        field :const:`'relative gap'` is the relative gap, defined as
+        
+        .. math::
+
+            \frac{ s^Tz }{ \max\{ -c^Tx, -h^Tz-b^Ty \} } 
+            \quad \mbox{if} \quad \max\{ -c^Tx, -h^Tz-b^Ty \} > 0
+        
+        and :const:`None` otherwise.  The fields 
+        :const:`'primal infeasibility'` and :const:`'dual infeasibility'` 
+        are the residuals in the primal and dual equality constraints, 
+        defined as
+
+        .. math::
+        
+            \max\{ \frac{ \|Gx+s-h\|_2 }{ \max\{1, \|h\|_2\} }, 
+                \frac{ \|Ax-b\|_2 }{ \max\{1,\|b\|_2\} } \}, \qquad
+            \frac{ \|G^Tz + A^Ty + c\|_2 }{ \max\{1, \|c\|_2\} }, 
+        
+        respectively.
+
+    :const:`'primal infeasible'`
+        The :const:`'x'` and :const:`'s'` entries are :const:`None`, and 
+        the :const:`'y'`, :const:`'z'` entries provide an approximate 
+        certificate of infeasibility, i.e., vectors that approximately 
+        satisfy
+
+        .. math::
+        
+            G^T z + A^T y = 0, \qquad h^T z + b^T y = -1, \qquad 
+            z \succeq 0.
+        
+        The field :const:`'residual as primal infeasibility certificate'` 
+        gives the residual 
+
+        .. math::
+        
+            \frac{ \|G^Tz + A^Ty\|_2 }{ \max\{1, \|c\|_2\} }.
+        
+
+    :const:`'dual infeasible'`  
+        The :const:`'y'` and :const:`'z'` entries are :const:`None`, and 
+        the :const:`'x'` and :const:`'s'` entries contain an approximate 
+        certificate of dual infeasibility 
+
+        .. math::
+        
+            Gx + s = 0, \qquad Ax=0, \qquad  c^T x = -1, \qquad 
+            s \succeq 0.
+        
+        The field :const:`'residual as dual infeasibility certificate'` 
+        gives the residual 
+
+        .. math::
+        
+            \max\{ \frac{ \|Gx + s\|_2 }{ \max\{1, \|h\|_2\} },
+            \frac{ \|Ax\|_2 }{ \max\{1, \|b\|_2\} } \}.
+        
+
+    :const:`'unknown'` 
+        This indicates that the algorithm terminated early due to 
+        numerical difficulties or because the maximum number of iterations 
+        was reached.  The :const:`'x'`, :const:`'s'`, :const:`'y'`, 
+        :const:`'z'` entries contain the iterates when the algorithm 
+        terminated.  Whether these entries are useful, as approximate 
+        solutions or certificates of primal and dual infeasibility, can be
+        determined from the other fields in the dictionary.
+
+        The fields :const:`'primal objective'`, :const:`'dual objective'`, 
+        :const:`'gap'`, :const:`'relative gap'`, 
+        :const:`'primal infeasibility'`,
+        :const:`'dual infeasibility'` are defined as when :const:`'status'`
+        is :const:`'optimal'`.  The field 
+        :const:`'residual as primal infeasibility certificate'` is defined
+        as
+        
+        .. math::
+
+            \frac{ \|G^Tz+A^Ty\|_2 }{ -(h^Tz + b^Ty) \max\{1, \|h\|_2 \} }.
+        
+        if :math:`h^Tz+b^Ty < 0`, and :const:`None` otherwise.  A small 
+        value of this residual indicates that :math:`y` and :math:`z`, 
+        divided by :math:`-h^Tz-b^Ty`, are an approximate proof of primal 
+        infeasibility.  The field 
+        :const:`'residual as dual infeasibility certificate'` is defined as
+
+        .. math::
+        
+            \max\{ \frac{ \|Gx+s\|_2 }{ -c^Tx \max\{ 1, \|h\|_2 \} }, 
+            \frac{ \|Ax\|_2 }{ -c^Tx \max\{1,\|b\|_2\} }\}
+        
+        if :math:`c^Tx < 0`, and as :const:`None` otherwise.  A small value
+        indicates that :math:`x` and :math:`s`, divided by :math:`-c^Tx` 
+        are an approximate proof of dual infeasibility.  
+
+    It is required that 
+
+    .. math::
+    
+        \newcommand{\Rank}{\mathop{\bf rank}}
+        \Rank(A) = p, \qquad 
+        \Rank(\left[\begin{array}{c} G \\ A \end{array}\right]) = n,
+   
+    where :math:`p` is the number or rows of :math:`A` and :math:`n` is 
+    the number of columns of :math:`G` and :math:`A`.
+
+
+As an example we solve the problem
+
+.. math::
+
+    \begin{array}{ll}
+    \mbox{minimize}   &  -6x_1 - 4x_2 - 5x_3 \\*[1ex]
+    \mbox{subject to} 
+        & 16x_1 - 14x_2 + 5x_3 \leq -3 \\*[1ex]
+        & 7x_1 + 2x_2 \leq 5 \\*[1ex]
+        & \left\| \left[ \begin{array}{c}
+             8x_1 + 13x_2 - 12x_3 - 2  \\
+            -8x_1 + 18x_2 +  6x_3 - 14 \\
+              x_1 -  3x_2 - 17x_3 - 13 \end{array}\right] \right\|_2
+            \leq -24x_1 - 7x_2 + 15x_3 + 12 \\*[3ex]
+        & \left\| \left[ 
+          \begin{array}{c} x_1 \\ x_2 \\ x_3 \end{array}
+          \right] \right\|_2 \leq 10 \\*[3ex]
+        & \left[\begin{array}{ccc}
+           7x_1 +  3x_2 + 9x_3 & -5x_1 + 13x_2 + 6x_3 &   
+               x_1 - 6x_2 - 6x_3\\
+          -5x_1 + 13x_2 + 6x_3 &   x_1 + 12x_2 - 7x_3 & 
+              -7x_1 -10x_2 - 7x_3\\
+           x_1 - 6x_2 -6x_3 & -7x_1 -10x_2 -7 x_3 & 
+              -4x_1 -28 x_2 -11x_3 
+           \end{array}\right]  
+    \preceq \left[\begin{array}{ccc}
+        68  & -30 & -19 \\
+       -30 & 99  &  23 \\
+       -19 & 23  & 10 \end{array}\right].
+    \end{array} 
+
+
+>>> from cvxopt import matrix, solvers
+>>> c = matrix([-6., -4., -5.])
+>>> G = matrix([[ 16., 7.,  24.,  -8.,   8.,  -1.,  0., -1.,  0.,  0.,   
+                   7.,  -5.,   1.,  -5.,   1.,  -7.,   1.,   -7.,  -4.], 
+                [-14., 2.,   7., -13., -18.,   3.,  0.,  0., -1.,  0.,   
+                   3.,  13.,  -6.,  13.,  12., -10.,  -6.,  -10., -28.],
+                [  5., 0., -15.,  12.,  -6.,  17.,  0.,  0.,  0., -1.,   
+                   9.,   6.,  -6.,   6.,  -7.,  -7.,  -6.,   -7., -11.]])
+>>> h = matrix( [ -3., 5.,  12.,  -2., -14., -13., 10.,  0.,  0.,  0.,  
+                  68., -30., -19., -30.,  99.,  23., -19.,   23.,  10.] )
+>>> dims = {'l': 2, 'q': [4, 4], 's': [3]}
+>>> sol = solvers.conelp(c, G, h, dims)
+>>> sol['status']
+'optimal'
+>>> print sol['x']
+[-1.22e+00]
+[ 9.66e-02]
+[ 3.58e+00]
+>>> print sol['z']
+[ 9.30e-02]
+[ 2.04e-08]
+[ 2.35e-01]
+[ 1.33e-01]
+[-4.74e-02]
+[ 1.88e-01]
+[ 2.79e-08]
+[ 1.85e-09]
+[-6.32e-10]
+[-7.59e-09]
+[ 1.26e-01]
+[ 8.78e-02]
+[-8.67e-02]
+[ 8.78e-02]
+[ 6.13e-02]
+[-6.06e-02]
+[-8.67e-02]
+[-6.06e-02]
+[ 5.98e-02]
+
+
+Only the entries of ``G`` and ``h`` defining the lower triangular portions
+of the coefficients in the linear matrix inequalities are accessed.  We 
+obtain the same result if we define ``G`` and ``h`` as below. 
+
+
+>>> G = matrix([[ 16., 7.,  24.,  -8.,   8.,  -1.,  0., -1.,  0.,  0.,   
+                   7.,  -5.,   1.,  0.,   1.,  -7.,  0.,  0.,  -4.], 
+                [-14., 2.,   7., -13., -18.,   3.,  0.,  0., -1.,  0.,   
+                   3.,  13.,  -6.,  0.,  12., -10.,  0.,  0., -28.],
+                [  5., 0., -15.,  12.,  -6.,  17.,  0.,  0.,  0., -1.,   
+                   9.,   6.,  -6.,  0.,  -7.,  -7.,  0.,  0., -11.]])
+>>> h = matrix( [ -3., 5.,  12.,  -2., -14., -13., 10.,  0.,  0.,  0.,  
+                  68., -30., -19.,  0.,  99.,  23.,  0.,  0.,  10.] )
+
+
+.. _s-coneqp: 
+
+Quadratic Cone Programs 
+=======================
+
+.. function:: cvxopt.solvers.coneqp(P, q[, G, h[, dims[, A, b[, initvals[, kktsolver]]]]])
+
+    Solves a pair of primal and dual quadratic cone programs
+
+    .. math::
+
+        \begin{array}[t]{ll}
+        \mbox{minimize}   & (1/2) x^T Px + q^T x \\
+        \mbox{subject to} & G x + s = h \\ 
+                          & Ax = b \\ 
+                          & s \succeq 0
+        \end{array}
+
+    and
+        
+    .. math::
+
+        \newcommand{\Range}{\mbox{\textrm{range}}}
+        \begin{array}[t]{ll}
+        \mbox{maximize}   & -(1/2) (q+G^Tz+A^Ty)^T P^\dagger
+                           (q+G^Tz+A^Ty) -h^T z - b^T y \\
+        \mbox{subject to} & q + G^T z + A^T y \in \Range(P) \\ 
+                          & z \succeq 0.
+        \end{array}
+
+    The primal variables are :math:`x` and the slack variable :math:`s`.  
+    The dual variables are :math:`y` and :math:`z`.  The inequalities are
+    interpreted as :math:`s \in C`, :math:`z\in C`, where :math:`C` is a 
+    cone defined as a Cartesian product of a nonnegative orthant, a number
+    of second-order cones, and a number of positive semidefinite cones:
+
+    .. math::
+
+        C = C_0 \times C_1 \times \cdots \times C_M \times C_{M+1} \times
+            \cdots \times C_{M+N}
+
+    with
+
+    .. math::
+
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        \newcommand{\svec}{\mathop{\mathbf{vec}}}
+        \newcommand{\symm}{{\mbox{\bf S}}}
+        \begin{split}
+            C_0 & = 
+                \{ u \in \reals^l \;| \; u_k \geq 0, \; k=1, \ldots,l\}, \\
+            C_{k+1} & = \{ (u_0, u_1) \in \reals \times \reals^{r_{k}-1} 
+                \; | \; u_0 \geq \|u_1\|_2 \},  \quad k=0,\ldots, M-1, \\
+            C_{k+M+1} &= \left\{ \svec(u) \; | \; u \in \symm^{t_k}_+ 
+                \right\}, \quad k=0,\ldots,N-1.
+        \end{split}
+
+
+    In this definition, :math:`\mathbf{vec}(u)` denotes a symmetric matrix
+    :math:`u` stored as a vector in column major order.  The structure of 
+    :math:`C` is specified by ``dims``.  This argument is a dictionary with
+    three fields. 
+
+    ``dims['l']``:
+        :math:`l`, the dimension of the nonnegative orthant (a nonnegative
+        integer).
+
+    ``dims['q']``: 
+        :math:`[r_0, \ldots, r_{M-1}]`, a list with the dimensions of the 
+        second-order cones (positive integers).
+
+    ``dims['s']``: 
+        :math:`[t_0, \ldots, t_{N-1}]`, a list with the dimensions of the 
+        positive semidefinite cones (nonnegative integers).
+
+    The default value of ``dims`` is ``{'l': G.size[0], 'q': [], 
+    's': []}``, i.e., by default the inequality is interpreted as a 
+    componentwise vector inequality. 
+
+    ``P`` is a square dense or sparse real matrix, representing a positive 
+    semidefinite symmetric matrix in :const:`'L'` storage, i.e., only the 
+    lower triangular part of ``P`` is referenced.  ``q`` is a real 
+    single-column dense matrix.
+
+    The arguments ``h`` and ``b`` are real single-column dense matrices.  
+    ``G`` and ``A`` are real dense or sparse matrices.  The number of rows
+    of ``G`` and ``h`` is equal to
+
+    .. math::
+    
+        K = l + \sum_{k=0}^{M-1} r_k + \sum_{k=0}^{N-1} t_k^2.
+    
+    The columns of ``G`` and ``h`` are vectors in
+    
+    .. math::
+
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        \reals^l \times \reals^{r_0} \times \cdots \times 
+        \reals^{r_{M-1}} \times \reals^{t_0^2}  \times \cdots \times 
+        \reals^{t_{N-1}^2},
+    
+    where the last :math:`N` components represent symmetric matrices stored
+    in column major order.  The strictly upper triangular entries of these 
+    matrices are not accessed (i.e.,  the symmetric matrices are stored
+    in the :const:`'L'`-type column major order used in the :mod:`blas` and
+    :mod:`lapack` modules).  The default values for ``G``, ``h``, ``A``,
+    and ``b`` are matrices with zero rows, meaning that there are no 
+    inequality or equality constraints.  
+
+    ``initvals`` is a dictionary with keys :const:`'x'`, :const:`'s'`, 
+    :const:`'y'`, :const:`'z'` used as an optional starting point.  The 
+    vectors ``initvals['s']`` and ``initvals['z']`` must be 
+    strictly positive with respect to the cone :math:`C`.  If the argument
+    ``initvals`` or any the four entries in it are missing, default 
+    starting points are used for the corresponding variables.
+
+    The role of the optional argument ``kktsolver`` is explained in the
+    section :ref:`s-conelp-struct`.  
+
+    :func:`coneqp` returns a dictionary that contains the result and 
+    information about the accuracy of the solution.  The most important 
+    fields have keys :const:`'status'`, :const:`'x'`, :const:`'s'`, 
+    :const:`'y'`, :const:`'z'`.  The :const:`'status'` field  is a string 
+    with possible values :const:`'optimal'` and :const:`'unknown'`.  
+
+    :const:`'optimal'` 
+        In this case the :const:`'x'`, :const:`'s'`, :const:`'y'`, and 
+        :const:`'z'` entries contain primal and dual solutions, which 
+        approximately satisfy
+
+        .. math::
+        
+            Gx+s = h, \qquad Ax = b, \qquad Px + G^Tz + A^T y + c = 0,
+
+            s \succeq 0, \qquad z \succeq 0, \qquad s^T z  = 0.
+  
+
+    :const:`'unknown'` 
+        This indicates that the algorithm terminated early due to numerical
+        difficulties or because the maximum number of iterations was 
+        reached.  The :const:`'x'`, :const:`'s'`, :const:`'y'`, 
+        :const:`'z'` entries contain the iterates when the algorithm 
+        terminated.
+
+    The other entries in the output dictionary summarize the accuracy
+    with which the optimality conditions are satisfied.  The fields 
+    :const:`'primal objective'`, :const:`'dual objective'`, and
+    :const:`'gap'` give the primal objective :math:`c^Tx`, the dual 
+    objective calculated as 
+
+    .. math::
+
+        (1/2) x^TPx + q^T x + z^T(Gx-h) + y^T(Ax-b)
+    
+    and the gap :math:`s^Tz`.  The field :const:`'relative gap'` is the 
+    relative gap, defined as
+
+    .. math::
+    
+        \frac{s^Tz}{-\mbox{primal objective}}
+        \quad \mbox{if\ } \mbox{primal objective} < 0, \qquad
+        \frac{s^Tz}{\mbox{dual objective}}
+        \quad \mbox{if\ } \mbox{dual objective} > 0, \qquad
+
+    and :const:`None` otherwise.  The fields 
+    :const:`'primal infeasibility'` and :const:`'dual infeasibility'` are 
+    the residuals in the primal and dual equality constraints, defined as
+
+    .. math::
+
+        \max\{ \frac{\|Gx+s-h\|_2}{\max\{1, \|h\|_2\}}, 
+        \frac{\|Ax-b\|_2}{\max\{1,\|b\|_2\}} \}, \qquad
+        \frac{\|Px + G^Tz + A^Ty + q\|_2}{\max\{1, \|q\|_2\}}, 
+
+    respectively.
+
+    It is required that the problem is solvable and that 
+
+    .. math::
+
+        \newcommand{\Rank}{\mathop{\bf rank}}
+        \Rank(A) = p, \qquad 
+        \Rank(\left[\begin{array}{c} P \\ G \\ A \end{array}\right]) = n,
+    
+    where :math:`p` is the number or rows of :math:`A` and :math:`n` is the
+    number of columns of :math:`G` and :math:`A`.
+
+
+As an example, we solve a constrained least-squares problem
+
+.. math::
+
+    \begin{array}{ll}
+    \mbox{minimize}   & \|Ax - b\|_2^2 \\
+    \mbox{subject to} &  x \succeq 0 \\
+                      & \|x\|_2 \leq 1 
+    \end{array}
+
+with 
+
+.. math::
+    A = \left[ \begin{array}{rrr}
+        0.3 &  0.6 & -0.3 \\
+       -0.4 &  1.2 &  0.0 \\
+       -0.2 & -1.7 &  0.6 \\
+       -0.4 &  0.3 & -1.2 \\
+        1.3 & -0.3 & -2.0 
+       \end{array} \right], \qquad 
+    b = \left[ \begin{array}{r} 1.5 \\ 0.0 \\ -1.2 \\ -0.7 \\ 0.0 
+        \end{array} \right]. 
+
+>>> from cvxopt import matrix, solvers
+>>> A = matrix([ [ .3, -.4,  -.2,  -.4,  1.3 ], 
+                 [ .6, 1.2, -1.7,   .3,  -.3 ],
+                 [-.3,  .0,   .6, -1.2, -2.0 ] ])
+>>> b = matrix([ 1.5, .0, -1.2, -.7, .0])
+>>> m, n = A.size
+>>> I = matrix(0.0, (n,n))
+>>> I[::n+1] = 1.0
+>>> G = matrix([-I, matrix(0.0, (1,n)), I])
+>>> h = matrix(n*[0.0] + [1.0] + n*[0.0])
+>>> dims = {'l': n, 'q': [n+1], 's': []}
+>>> x = solvers.coneqp(A.T*A, -A.T*b, G, h, dims)['x']
+>>> print x
+[ 7.26e-01]
+[ 6.18e-01]
+[ 3.03e-01]
+
+
+.. _s-lpsolver:
+
+Linear Programming
+==================
+
+The function :func:`lp <cvxopt.solvers.lp>` is an interface to 
+:func:`conelp <cvxopt.solvers.conelp>` for linear 
+programs.  It also provides the option of using the linear programming 
+solvers from GLPK or MOSEK.
+
+.. function:: cvxopt.solvers.lp(c, G, h[, A, b[, solver[, primalstart[, dualstart]]]])
+
+    Solves the pair of primal and dual linear programs
+
+    .. math::
+    
+        \begin{array}[t]{ll}
+        \mbox{minimize}   & c^T x \\
+        \mbox{subject to} & G x + s = h \\ 
+                          & Ax = b \\ 
+                          & s \succeq 0
+        \end{array}
+        \qquad\qquad
+        \begin{array}[t]{ll}
+        \mbox{maximize}   & -h^T z - b^T y \\
+        \mbox{subject to} & G^T z + A^T y + c = 0 \\
+                          & z \succeq 0.
+        \end{array}
+   
+    The inequalities are componentwise vector inequalities.
+
+    The ``solver`` argument is used to choose among three solvers.  When 
+    it is omitted or :const:`None`, the CVXOPT function 
+    :func:`conelp <cvxopt.solvers.conelp>` is 
+    used.  The external solvers GLPK and MOSEK (if installed) can be 
+    selected by setting ``solver`` to :const:`'glpk'` or :const:`'mosek'`; 
+    see the section :ref:`s-external`.  The meaning of the other 
+    arguments and the return value are the same as for 
+    :func:`conelp` called with 
+    ``dims`` equal to ``{'l': G.size[0], 'q': [], 's': []}``. 
+
+    The initial values are ignored when ``solver`` is :const:`'mosek'` or 
+    :const:`'glpk'`.  With the GLPK option, the solver does not return 
+    certificates of primal or dual infeasibility: if the status is
+    :const:`'primal infeasible'` or :const:`'dual infeasible'`, all entries
+    of the output dictionary are :const:`None`.  If the GLPK or MOSEK 
+    solvers are used, and the code returns with status :const:`'unknown'`, 
+    all the other fields in the output dictionary are :const:`None`.
+
+As a simple example we solve the LP
+
+.. math::
+
+    \begin{array}[t]{ll}
+    \mbox{minimize}   & -4x_1 - 5x_2 \\
+    \mbox{subject to} &  2x_1 + x_2 \leq 3 \\
+                      & x_1 + 2x_2 \leq 3 \\
+                      & x_1 \geq 0, \quad x_2 \geq 0.
+    \end{array} 
+
+
+>>> from cvxopt import matrix, solvers
+>>> c = matrix([-4., -5.])
+>>> G = matrix([[2., 1., -1., 0.], [1., 2., 0., -1.]])
+>>> h = matrix([3., 3., 0., 0.])
+>>> sol = solvers.lp(c, G, h)
+>>> print sol['x']
+[ 1.00e+00]
+[ 1.00e+00]
+
+
+.. _s-qp:
+
+Quadratic Programming
+=====================
+
+The function :func:`qp <cvxopt.solvers.qp>` is an interface to 
+:func:`coneqp <cvxopt.solvers.coneqp>` for quadratic 
+programs.  It also provides the option of using the quadratic programming 
+solver from MOSEK.
+
+.. function:: cvxopt.solvers.qp(P, q[, G, h[, A, b[, solver[, initvals]]]])
+
+    Solves the pair of primal and dual convex quadratic programs 
+
+    .. math::
+    
+        \begin{array}[t]{ll}
+        \mbox{minimize} & (1/2) x^TPx + q^T x \\
+        \mbox{subject to} & Gx \preceq h \\ & Ax = b
+        \end{array}
+
+    and
+
+    .. math::
+    
+        \newcommand{\Range}{\mbox{\textrm{range}}}
+        \begin{array}[t]{ll}
+        \mbox{maximize}   & -(1/2) (q+G^Tz+A^Ty)^T P^\dagger
+                             (q+G^Tz+A^Ty) -h^T z - b^T y \\
+        \mbox{subject to} & q + G^T z + A^T y \in \Range(P) \\ 
+                          & z \succeq 0.
+        \end{array}
+  
+    The inequalities are componentwise vector inequalities.
+
+    The default CVXOPT solver is used when the ``solver`` argument is 
+    absent or :const:`None`.  The MOSEK solver (if installed) can be 
+    selected by setting ``solver`` to :const:`'mosek'`; see the 
+    section :ref:`s-external`.  The meaning of the other arguments and the
+    return value is the same as for 
+    :func:`coneqp <cvxopt.solvers.coneqp>` called with `dims` 
+    equal to ``{'l': G.size[0], 'q': [], 's': []}``.
+
+    When ``solver`` is :const:`'mosek'`, the initial values are ignored,
+    and the :const:`'status'` string in the solution dictionary can take 
+    four possible values: :const:`'optimal'`, :const:`'unknown'`.
+    :const:`'primal infeasible'`, :const:`'dual infeasible'`. 
+
+    :const:`'primal infeasible'`  
+        This means that a certificate of primal infeasibility has been 
+        found.  The :const:`'x'` and :const:`'s'` entries are 
+        :const:`None`, and the :const:`'z'` and :const:`'y'` entries are 
+        vectors that approximately satisfy
+
+        .. math:: 
+        
+            G^Tz + A^T y = 0, \qquad h^Tz + b^Ty = -1, \qquad z \succeq 0.
+        
+
+    :const:`'dual infeasible'`  
+        This means that a certificate of dual infeasibility has been found.
+        The :const:`'z'` and :const:`'y'` entries are :const:`None`, and 
+        the :const:`'x'` and :const:`'s'` entries are vectors that 
+        approximately satisfy
+
+        .. math:: 
+        
+            Px = 0, \qquad q^Tx = -1, \qquad Gx + s = 0, \qquad Ax=0, 
+            \qquad s \succeq  0.
+        
+
+As an example we compute the trade-off curve on page 187 of the book 
+`Convex Optimization <http://www.stanford.edu/~boyd/cvxbook>`_,
+by solving the quadratic program 
+
+.. math::
+
+    \newcommand{\ones}{{\bf 1}}
+    \begin{array}{ll}
+    \mbox{minimize}   & -\bar p^T x + \mu x^T S x \\
+    \mbox{subject to} & \ones^T x = 1, \quad x \succeq 0
+    \end{array}
+
+for a sequence of positive values of :math:`\mu`.  The code below computes 
+the trade-off curve and produces two figures using the 
+`Matplotlib <http://matplotlib.sourceforge.net>`_ package.
+
+.. image:: portfolio2.png
+   :width: 400px
+
+.. image:: portfolio1.png
+   :width: 400px
+
+::
+
+    from math import sqrt
+    from cvxopt import matrix
+    from cvxopt.blas import dot 
+    from cvxopt.solvers import qp
+    import pylab
+
+    # Problem data.
+    n = 4
+    S = matrix([[ 4e-2,  6e-3, -4e-3,    0.0 ], 
+                [ 6e-3,  1e-2,  0.0,     0.0 ],
+                [-4e-3,  0.0,   2.5e-3,  0.0 ],
+                [ 0.0,   0.0,   0.0,     0.0 ]])
+    pbar = matrix([.12, .10, .07, .03])
+    G = matrix(0.0, (n,n))
+    G[::n+1] = -1.0
+    h = matrix(0.0, (n,1))
+    A = matrix(1.0, (1,n))
+    b = matrix(1.0)
+
+    # Compute trade-off.
+    N = 100
+    mus = [ 10**(5.0*t/N-1.0) for t in xrange(N) ]
+    portfolios = [ qp(mu*S, -pbar, G, h, A, b)['x'] for mu in mus ]
+    returns = [ dot(pbar,x) for x in portfolios ]
+    risks = [ sqrt(dot(x, S*x)) for x in portfolios ]
+
+    # Plot trade-off curve and optimal allocations.
+    pylab.figure(1, facecolor='w')
+    pylab.plot(risks, returns)
+    pylab.xlabel('standard deviation')
+    pylab.ylabel('expected return')
+    pylab.axis([0, 0.2, 0, 0.15])
+    pylab.title('Risk-return trade-off curve (fig 4.12)')
+    pylab.yticks([0.00, 0.05, 0.10, 0.15])
+
+    pylab.figure(2, facecolor='w')
+    c1 = [ x[0] for x in portfolios ] 
+    c2 = [ x[0] + x[1] for x in portfolios ]
+    c3 = [ x[0] + x[1] + x[2] for x in portfolios ] 
+    c4 = [ x[0] + x[1] + x[2] + x[3] for x in portfolios ]
+    pylab.fill(risks + [.20], c1 + [0.0], '#F0F0F0') 
+    pylab.fill(risks[-1::-1] + risks, c2[-1::-1] + c1, facecolor = '#D0D0D0') 
+    pylab.fill(risks[-1::-1] + risks, c3[-1::-1] + c2, facecolor = '#F0F0F0') 
+    pylab.fill(risks[-1::-1] + risks, c4[-1::-1] + c3, facecolor = '#D0D0D0') 
+    pylab.axis([0.0, 0.2, 0.0, 1.0])
+    pylab.xlabel('standard deviation')
+    pylab.ylabel('allocation')
+    pylab.text(.15,.5,'x1')
+    pylab.text(.10,.7,'x2')
+    pylab.text(.05,.7,'x3')
+    pylab.text(.01,.7,'x4')
+    pylab.title('Optimal allocations (fig 4.12)')
+    pylab.show()
+
+
+
+.. _s-socpsolver:
+
+Second-Order Cone Programming
+=============================
+
+The function :func:`socp <cvxopt.solvers.socp>` is a simpler interface to 
+:func:`conelp <cvxopt.solvers.coneqp>` for 
+cone programs with no linear matrix inequality constraints.
+
+.. function:: cvxopt.solvers.socp(c[, Gl, hl[, Gq, hq[, A, b[, solver[, primalstart[, dualstart]]]]]])
+
+    Solves the pair of primal and dual second-order cone programs
+    
+    .. math::
+
+        \begin{array}[t]{ll}
+        \mbox{minimize}   & c^T x \\
+        \mbox{subject to} & G_k x + s_k = h_k, \quad k = 0, \ldots, M  \\ 
+                          & Ax = b \\ 
+                          & s_0 \succeq 0 \\
+                          & s_{k0} \geq \|s_{k1}\|_2, \quad k = 1,\ldots,M
+        \end{array}
+     
+    and
+
+    .. math::
+
+        \begin{array}[t]{ll}
+        \mbox{maximize}   & - \sum_{k=0}^M h_k^Tz_k - b^T y \\
+        \mbox{subject to} & \sum_{k=0}^M G_k^T z_k + A^T y + c = 0 \\
+                          & z_0 \succeq 0 \\
+                          & z_{k0} \geq \|z_{k1}\|_2, \quad k=1,\ldots,M.
+        \end{array}
+
+    The inequalities 
+
+    .. math::
+
+        s_0 \succeq 0, \qquad z_0 \succeq 0
+
+    are componentwise vector inequalities.  In the other inequalities, it 
+    is assumed that the variables are partitioned as
+
+    .. math::
+    
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        s_k = (s_{k0}, s_{k1}) \in\reals\times\reals^{r_{k}-1}, \qquad 
+        z_k = (z_{k0}, z_{k1}) \in\reals\times\reals^{r_{k}-1}, \qquad
+        k=1,\ldots,M.
+
+    The input argument ``c`` is a real single-column dense matrix.  The 
+    arguments ``Gl`` and ``hl`` are the coefficient matrix :math:`G_0` and 
+    the righthand side :math:`h_0` of the componentwise inequalities.
+    ``Gl`` is a real dense or sparse matrix; ``hl`` is a real single-column
+    dense matrix.  The default values for ``Gl`` and ``hl`` are matrices 
+    with zero rows.
+
+    The argument ``Gq`` is a list of :math:`M` dense or sparse matrices 
+    :math:`G_1`, ..., :math:`G_M`.  The argument ``hq`` is a list of 
+    :math:`M` dense single-column matrices :math:`h_1`, \ldots, 
+    :math:`h_M`.  The elements of ``Gq`` and ``hq`` must have at least one
+    row.  The default values of ``Gq`` and ``hq`` are empty lists.
+
+    ``A`` is dense or sparse matrix and ``b`` is a single-column dense 
+    matrix.  The default values for ``A`` and ``b`` are matrices with 
+    zero rows. 
+
+    The ``solver`` argument is used to choose between two solvers: the 
+    CVXOPT :func:`conelp <cvxopt.solvers.conelp>` solver (used when 
+    ``solver`` is absent or equal 
+    to :const:`None` and the external solver MOSEK (``solver`` is 
+    :const:`'mosek'`); see the section :ref:`s-external`.  With the 
+    :const:`'mosek'` option the code does not accept problems with equality
+    constraints.
+
+    ``primalstart`` and ``dualstart`` are dictionaries with optional 
+    primal, respectively, dual starting points.  ``primalstart`` has 
+    elements :const:`'x'`, :const:`'sl'`, :const:`'sq'`.  
+    ``primalstart['x']`` and ``primalstart['sl']`` are 
+    single-column dense matrices with the initial values of :math:`x` and 
+    :math:`s_0`;  ``primalstart['sq']`` is a list of single-column 
+    matrices with the initial values of :math:`s_1`, \ldots, :math:`s_M`.
+    The initial values must satisfy the inequalities in the primal problem 
+    strictly, but not necessarily the equality constraints.
+
+    ``dualstart`` has elements :const:`'y'`, :const:`'zl'`, :const:`'zq'`.
+    ``dualstart['y']`` and ``dualstart['zl']`` are single-column 
+    dense matrices with the initial values of :math:`y` and :math:`z_0`.
+    ``dualstart['zq']`` is a list of single-column matrices with the 
+    initial values of :math:`z_1`, \ldots, :math:`z_M`.  These values must
+    satisfy the dual inequalities strictly, but not necessarily the 
+    equality constraint.
+
+    The arguments ``primalstart`` and ``dualstart`` are ignored when the 
+    MOSEK solver is used.
+
+    :func:`socp` returns a dictionary that include entries with keys 
+    :const:`'status'`, :const:`'x'`, :const:`'sl'`, :const:`'sq'`, 
+    :const:`'y'`, :const:`'zl'`, :const:`'zq'`.  The :const:`'sl'` and 
+    :const:`'zl'` fields are matrices with the primal slacks and dual 
+    variables associated with the componentwise linear inequalities.
+    The :const:`'sq'` and :const:`'zq'` fields are lists with the primal 
+    slacks and dual variables associated with the second-order cone 
+    inequalities.  The other entries in the output dictionary have the 
+    same meaning as in the output of 
+    :func:`conelp <cvxopt.solvers.conelp>`.
+
+
+As an example, we solve  the second-order cone program
+
+.. math::
+    \begin{array}{ll}
+    \mbox{minimize}   & -2x_1 + x_2 + 5x_3 \\*[2ex]
+    \mbox{subject to} & \left\| \left[\begin{array}{c}
+        -13 x_1 +  3 x_2 + 5 x_3 - 3 \\ 
+        -12 x_1 + 12 x_2 - 6 x_3 - 2 \end{array}\right] \right\|_2 
+         \leq -12 x_1 - 6 x_2 + 5x_3 - 12  \\*[2ex]
+                       & \left\| \left[\begin{array}{c}
+         -3 x_1 +  6 x_2 + 2 x_3    \\ 
+            x_1 +  9 x_2 + 2 x_3 + 3 \\ 
+           -x_1 - 19 x_2 + 3 x_3 - 42 \end{array}\right] \right\|_2 
+         \leq -3x_1 + 6x_2 - 10x_3 + 27.
+    \end{array}
+
+
+>>> from cvxopt import matrix, solvers
+>>> c = matrix([-2., 1., 5.])
+>>> G = [ matrix( [[12., 13., 12.], [6., -3., -12.], [-5., -5., 6.]] ) ]
+>>> G += [ matrix( [[3., 3., -1., 1.], [-6., -6., -9., 19.], [10., -2., -2., -3.]] ) ]
+>>> h = [ matrix( [-12., -3., -2.] ),  matrix( [27., 0., 3., -42.] ) ]
+>>> sol = solvers.socp(c, Gq = G, hq = h)
+>>> sol['status']
+optimal
+>>> print sol['x']
+[-5.02e+00]
+[-5.77e+00]
+[-8.52e+00]
+>>> print sol['zq'][0]
+[ 1.34e+00]
+[-7.63e-02]
+[-1.34e+00]
+>>> print sol['zq'][1]
+[ 1.02e+00]
+[ 4.02e-01]
+[ 7.80e-01]
+[-5.17e-01]
+
+
+.. _s-sdpsolver:
+
+Semidefinite Programming
+========================
+
+The function :func:`sdp <cvxopt.solvers.sdp>` is a simple interface to 
+:func:`conelp <cvxopt.solvers.conelp>` for cone 
+programs with no second-order cone constraints.  It also provides the 
+option of using the DSDP semidefinite programming solver.
+
+.. function:: cvxopt.solvers.sdp(c[, Gl, hl[, Gs, hs[, A, b[, solver[, primalstart[, dualstart]]]]]])
+
+    Solves the pair of primal and dual semidefinite programs
+
+    .. math::
+    
+        \newcommand{\svec}{\mathop{\mathbf{vec}}}
+        \begin{array}[t]{ll}
+        \mbox{minimize}   & c^T x \\
+        \mbox{subject to} & G_0 x + s_0 = h_0 \\
+                          & G_k x + \svec{(s_k)} = \svec{(h_k)}, 
+                            \quad k = 1, \ldots, N  \\ 
+                          & Ax = b \\ 
+                          & s_0 \succeq 0 \\
+                          & s_k \succeq 0, \quad k=1,\ldots,N
+        \end{array}
+
+    and
+
+    .. math::
+
+        \newcommand{\Tr}{\mathop{\mathbf{tr}}}
+        \newcommand{\svec}{\mathop{\mathbf{vec}}}
+        \begin{array}[t]{ll}
+        \mbox{maximize}   & -h_0^Tz_0 - \sum_{k=1}^N \Tr(h_kz_k) - b^Ty \\
+        \mbox{subject to} & G_0^Tz_0 + \sum_{k=1}^N G_k^T \svec(z_k) + 
+                             A^T y + c = 0 \\
+                          & z_0 \succeq 0 \\
+                          & z_k \succeq 0, \quad k=1,\ldots,N.
+        \end{array}
+
+    The inequalities 
+    
+    .. math::
+       
+        s_0 \succeq 0, \qquad z_0 \succeq 0
+
+    are componentwise vector inequalities.  The other inequalities are 
+    matrix inequalities (\ie, the require the lefthand sides to be positive
+    semidefinite).  We use the notation :math:`\mathbf{vec}(z)` to denote 
+    a symmetric matrix :math:`z` stored in column major order as a column 
+    vector.
+
+    The input argument ``c`` is a real single-column dense matrix.  The 
+    arguments ``Gl`` and ``hl`` are the coefficient matrix :math:`G_0` and
+    the righthand side :math:`h_0` of the componentwise inequalities.
+    ``Gl`` is a real dense or sparse matrix;  ``hl`` is a real 
+    single-column dense matrix.   The default values for ``Gl`` and ``hl``
+    are matrices with zero rows.
+
+    ``Gs`` and ``hs`` are lists of length :math:`N` that specify the 
+    linear matrix inequality constraints.  ``Gs`` is a list of :math:`N` 
+    dense or sparse real matrices :math:`G_1`, \ldots, :math:`G_M`.  The 
+    columns of these matrices can be interpreted as symmetric matrices 
+    stored in column major order, using the BLAS :const:`'L'`-type storage
+    (i.e., only the entries corresponding to lower triangular positions
+    are accessed).  ``hs`` is a list of :math:`N` dense symmetric matrices
+    :math:`h_1`, \ldots, :math:`h_N`.  Only the lower triangular elements 
+    of these matrices are accessed.  The default values for ``Gs`` and 
+    ``hs`` are empty lists.
+
+    ``A`` is a dense or sparse matrix and ``b`` is a single-column dense 
+    matrix.  The default values for ``A`` and ``b`` are matrices with zero 
+    rows. 
+
+    The ``solver`` argument is used to choose between two solvers: the 
+    CVXOPT :func:`conelp <cvxopt.solvers.conelp>` solver 
+    (used when ``solver`` is absent or equal 
+    to :const:`None`) and the external solver DSDP5 (``solver`` is 
+    :const:`'dsdp'`); see the section :ref:`s-external`.  With the 
+    :const:`'dsdp'` option the code does not accept problems with equality
+    constraints.
+
+    The optional argument ``primalstart`` is a dictionary with keys 
+    :const:`'x'`, :const:`'sl'`, and :const:`'ss'`, used as an optional 
+    primal starting point.  ``primalstart['x']`` and 
+    ``primalstart['sl']`` are single-column dense matrices with the 
+    initial values of :math:`x` and :math:`s_0`; 
+    ``primalstart['ss']`` is a list of square matrices with the initial
+    values of :math:`s_1`, \ldots, :math:`s_N`.  The initial values must 
+    satisfy the inequalities in the primal problem strictly, but not 
+    necessarily the equality constraints.
+
+    ``dualstart`` is a dictionary with keys :const:`'y'`, :const:`'zl'`, 
+    :const:`'zs'`, used as an optional dual starting point.  
+    ``dualstart['y']`` and ``dualstart['zl']`` are single-column 
+    dense matrices with the initial values of :math:`y` and :math:`z_0`.
+    ``dualstart['zs']`` is a list of square matrices with the initial 
+    values of :math:`z_1`, \ldots, :math:`z_N`.  These values must satisfy
+    the dual inequalities strictly, but not necessarily the equality 
+    constraint.
+
+    The arguments ``primalstart`` and ``dualstart`` are ignored when the 
+    DSDP solver is used.
+
+    :func:`sdp` returns a dictionary that includes entries with keys 
+    :const:`'status'`, :const:`'x'`, :const:`'sl'`, :const:`'ss'`, 
+    :const:`'y'`, :const:`'zl'`, :const:`'ss'`.  The :const:`'sl'` and 
+    :const:`'zl'` fields are matrices with the primal slacks and dual  
+    variables associated with the componentwise linear inequalities.
+    The :const:`'ss'` and :const:`'zs'` fields are lists with the primal 
+    slacks and dual variables associated with the second-order cone 
+    inequalities.  The other entries in the output dictionary have the 
+    same meaning as in the output of 
+    :func:`conelp <cvxopt.solvers.conelp>`.
+
+We illustrate the calling sequence with a small example.
+
+    .. math::
+
+        \begin{array}{ll}
+        \mbox{minimize}   & x_1 - x_2 + x_3 \\
+        \mbox{subject to} 
+            & x_1 \left[ \begin{array}{cc} 
+                      -7 &  -11 \\ -11 &  3
+                  \end{array}\right] + 
+              x_2 \left[ \begin{array}{cc}
+                      7 & -18 \\ -18 & 8 
+                  \end{array}\right] + 
+              x_3 \left[ \begin{array}{cc}
+                      -2 & -8 \\ -8 & 1 
+                  \end{array}\right] \preceq  
+              \left[ \begin{array}{cc} 
+                      33 & -9 \\ -9 & 26 
+                  \end{array}\right] \\*[1ex]
+              & x_1 \left[ \begin{array}{ccc} 
+                      -21 & -11 & 0 \\ 
+                      -11 &  10 & 8 \\ 
+                        0 &   8 & 5
+                  \end{array}\right] + 
+              x_2 \left[ \begin{array}{ccc} 
+                        0 &  10 &  16 \\
+                       10 & -10 & -10 \\
+                       16 & -10 & 3 
+                  \end{array}\right] + 
+              x_3 \left[ \begin{array}{ccc} 
+                       -5  & 2 & -17 \\
+                        2  & -6 & -7 \\
+                       -17 & 8 & 6 
+                   \end{array}\right]  \preceq  
+              \left[ \begin{array}{ccc}
+                       14 &  9 & 40 \\
+                        9  & 91 & 10 \\
+                       40 & 10 & 15
+                  \end{array} \right] 
+        \end{array}
+
+>>> from cvxopt import matrix, solvers
+>>> c = matrix([1.,-1.,1.])
+>>> G = [ matrix([[-7., -11., -11., 3.], 
+                  [ 7., -18., -18., 8.], 
+                  [-2.,  -8.,  -8., 1.]]) ]
+>>> G += [ matrix([[-21., -11.,   0., -11.,  10.,   8.,   0.,   8., 5.], 
+                   [  0.,  10.,  16.,  10., -10., -10.,  16., -10., 3.], 
+                   [ -5.,   2., -17.,   2.,  -6.,   8., -17.,  -7., 6.]]) ]
+>>> h = [ matrix([[33., -9.], [-9., 26.]]) ]
+>>> h += [ matrix([[14., 9., 40.], [9., 91., 10.], [40., 10., 15.]]) ]
+>>> sol = solvers.sdp(c, Gs=G, hs=h)  
+>>> print sol['x']
+[-3.68e-01]
+[ 1.90e+00]
+[-8.88e-01]
+>>> print sol['zs'][0]
+[ 3.96e-03 -4.34e-03]
+[-4.34e-03  4.75e-03]
+>>> print sol['zs'][1]
+[ 5.58e-02 -2.41e-03  2.42e-02]
+[-2.41e-03  1.04e-04 -1.05e-03]
+[ 2.42e-02 -1.05e-03  1.05e-02]
+
+Only the entries in ``Gs`` and ``hs`` that correspond to lower triangular 
+entries need to be provided, so in the example ``h`` and ``G`` may also be
+defined as follows.
+
+>>> G = [ matrix([[-7., -11., 0., 3.], 
+                  [ 7., -18., 0., 8.], 
+                  [-2.,  -8., 0., 1.]]) ]
+>>> G += [ matrix([[-21., -11.,   0., 0.,  10.,   8., 0., 0., 5.], 
+                   [  0.,  10.,  16., 0., -10., -10., 0., 0., 3.], 
+                   [ -5.,   2., -17., 0.,  -6.,   8., 0., 0., 6.]]) ]
+>>> h = [ matrix([[33., -9.], [0., 26.]]) ]
+>>> h += [ matrix([[14., 9., 40.], [0., 91., 10.], [0., 0., 15.]]) ]
+
+
+.. _s-conelp-struct:
+
+Exploiting Structure
+====================
+
+By default, the functions 
+:func:`conelp <cvxopt.solvers.conelp>` and 
+:func:`coneqp <cvxopt.solvers.coneqp>` exploit no 
+problem structure except (to some limited extent) sparsity.  Two mechanisms
+are provided for implementing customized solvers that take advantage of 
+problem structure.
+
+
+**Providing a function for solving KKT equations**
+    The most expensive step of each iteration of 
+    :func:`conelp <cvxopt.solvers.conelp>` or 
+    :func:`coneqp <cvxopt.solvers.coneqp>` is the solution of a set of  
+    linear equations (*KKT equations*) of the form
+
+    .. math::
+        :label: e-conelp-kkt
+
+        \left[\begin{array}{ccc}
+            P & A^T & G^T \\
+            A & 0   & 0  \\
+            G & 0   & -W^T W 
+        \end{array}\right]
+        \left[\begin{array}{c} u_x \\ u_y \\ u_z \end{array}\right]
+        = 
+        \left[\begin{array}{c} b_x \\ b_y \\ b_z \end{array}\right]
+    
+    (with :math:`P = 0` in :func:`conelp`).  The matrix :math:`W` depends 
+    on the current iterates and is defined as follows.  We use the notation
+    of the sections :ref:`s-conelp` and :ref:`s-coneqp`.  Let 
+
+    .. math::
+
+        \newcommand{\svec}{\mathop{\mathbf{vec}}}
+        u = \left(u_\mathrm{l}, \; u_{\mathrm{q},0}, \; \ldots, \; 
+            u_{\mathrm{q},M-1}, \; \svec{(u_{\mathrm{s},0})}, \; 
+            \ldots, \; \svec{(u_{\mathrm{s},N-1})}\right), \qquad
+
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        \newcommand{\symm}{{\mbox{\bf S}}}
+        u_\mathrm{l} \in\reals^l, \qquad 
+        u_{\mathrm{q},k} \in\reals^{r_k}, \quad k = 0,\ldots,M-1, \qquad 
+        u_{\mathrm{s},k} \in\symm^{t_k},  \quad k = 0,\ldots,N-1.
+
+    Then :math:`W` is a block-diagonal matrix, 
+  
+    .. math::
+    
+        \newcommand{\svec}{\mathop{\mathbf{vec}}}
+        Wu = \left( W_\mathrm{l} u_\mathrm{l}, \;
+            W_{\mathrm{q},0} u_{\mathrm{q},0}, \; \ldots, \;
+            W_{\mathrm{q},M-1} u_{\mathrm{q},M-1},\; 
+            W_{\mathrm{s},0} \svec{(u_{\mathrm{s},0})}, \; \ldots, \;
+            W_{\mathrm{s},N-1} \svec{(u_{\mathrm{s},N-1})} \right)
+
+    with the following diagonal blocks.
+
+    * The first block is a *positive diagonal scaling* with a vector 
+      :math:`d`:
+
+      .. math::
+    
+          \newcommand{\diag}{\mbox{\bf diag}\,}
+          W_\mathrm{l} = \diag(d), \qquad 
+          W_\mathrm{l}^{-1} = \diag(d)^{-1}.
+    
+      This transformation is symmetric:
+
+      .. math::
+
+          W_\mathrm{l}^T = W_\mathrm{l}. 
+
+    * The next :math:`M` blocks are positive multiples of *hyperbolic 
+      Householder transformations*:
+
+      .. math::
+    
+          W_{\mathrm{q},k} = \beta_k ( 2 v_k v_k^T - J), \qquad
+          W_{\mathrm{q},k}^{-1} = \frac{1}{\beta_k} ( 2 Jv_k v_k^T J - J),
+          \qquad k = 0,\ldots,M-1,
+    
+      where
+
+      .. math::
+
+          \beta_k > 0, \qquad v_{k0} > 0, \qquad v_k^T Jv_k = 1, \qquad 
+          J = \left[\begin{array}{cc} 1 & 0 \\ 0 & -I \end{array}\right].
+    
+      These transformations are also symmetric:
+
+      .. math::
+    
+          W_{\mathrm{q},k}^T = W_{\mathrm{q},k}. 
+
+    * The last :math:`N` blocks are *congruence transformations* with 
+      nonsingular matrices:
+
+      .. math::
+
+          \newcommand{\svec}{\mathop{\mathbf{vec}}}
+          W_{\mathrm{s},k} \svec{(u_{\mathrm{s},k})} = 
+              \svec{(r_k^T u_{\mathrm{s},k} r_k)}, \qquad
+          W_{\mathrm{s},k}^{-1} \svec{(u_{\mathrm{s},k})} = 
+              \svec{(r_k^{-T} u_{\mathrm{s},k} r_k^{-1})}, \qquad
+          k = 0,\ldots,N-1.
+
+      In  general, this operation is not symmetric: 
+ 
+      .. math::
+
+          \newcommand{\svec}{\mathop{\mathbf{vec}}}
+          W_{\mathrm{s},k}^T \svec{(u_{\mathrm{s},k})} = 
+              \svec{(r_k u_{\mathrm{s},k} r_k^T)}, \qquad \qquad
+          W_{\mathrm{s},k}^{-T} \svec{(u_{\mathrm{s},k})} = 
+              \svec{(r_k^{-1} u_{\mathrm{s},k} r_k^{-T})}, \qquad \qquad
+          k = 0,\ldots,N-1.
+
+    It is often possible to exploit problem structure to solve 
+    :eq:`e-conelp-kkt` faster than by standard methods.  The last argument
+    ``kktsolver`` of :func:`conelp <cvxopt.solvers.conelp>` and 
+    :func:`coneqp <cvxopt.solvers.coneqp>` allows the user to 
+    supply a Python  function for solving the KKT equations.  This 
+    function will be called as ``f = kktsolver(W)``, where ``W`` is a 
+    dictionary that contains the parameters of the scaling:
+
+    * ``W['d']`` is the positive vector that defines the diagonal
+      scaling.   ``W['di']`` is its componentwise inverse.
+
+    * ``W['beta']`` and ``W['v']`` are lists of length :math:`M` 
+      with the coefficients and vectors that define the hyperbolic 
+      Householder transformations.
+
+    * ``W['r']`` is a list of length :math:`N` with the matrices that
+      define the the congruence transformations.  ``W['rti']`` is a 
+      list of length :math:`N` with the transposes of the inverses of the 
+      matrices in ``W['r']``.
+
+    The function call ``f = kktsolver(W)`` should return a routine for
+    solving the KKT system :eq:`e-conelp-kkt` defined by ``W``.  It will 
+    be called as ``f(bx, by, bz)``.  On entry, ``bx``, ``by``, ``bz`` 
+    contain the righthand side.  On exit, they should contain the solution
+    of the KKT system, with the last component scaled, i.e., on exit,
+    
+    .. math::
+
+        b_x := u_x, \qquad b_y := u_y, \qquad b_z := W u_z.
+
+    In other words, the function returns the solution of
+
+    .. math::
+
+        \left[\begin{array}{ccc}
+            P & A^T & G^TW^{-1} \\
+            A & 0   & 0  \\
+            G & 0   & -W^T 
+        \end{array}\right]
+        \left[\begin{array}{c} 
+            \hat u_x \\ \hat u_y \\ \hat u_z 
+        \end{array}\right]
+        = 
+        \left[\begin{array}{c} 
+            b_x \\ b_y \\ b_z 
+        \end{array}\right].
+
+
+**Specifying constraints via Python functions**
+    In the default use of :func:`conelp <cvxopt.solvers.conelp>` and 
+    :func:`coneqp <cvxopt.solvers.coneqp>`, the linear 
+    constraints and the quadratic term in the objective are parameterized 
+    by CVXOPT matrices ``G``, ``A``, ``P``.  It is possible to specify 
+    these parameters via Python functions that evaluate the corresponding 
+    matrix-vector products and their adjoints.
+
+    * If the argument ``G`` of :func:`conelp` or :func:`coneqp` is a 
+      Python function, then 
+      ``G(x, y[, alpha = 1.0, beta = 0.0, trans = 'N'])`` 
+      should evaluate the matrix-vector products
+
+        .. math::
+
+            y := \alpha Gx + \beta y \quad 
+                (\mathrm{trans} = \mathrm{'N'}), \qquad
+            y := \alpha G^T x + \beta y \quad 
+                (\mathrm{trans} = \mathrm{'T'}).
+
+    * Similarly, if the argument ``A`` is a Python function, then 
+      ``A(x, y[, alpha = 1.0, beta = 0.0, trans = 'N'])`` 
+      should evaluate the matrix-vector products
+
+        .. math::
+
+            y := \alpha Ax + \beta y \quad 
+                (\mathrm{trans} = \mathrm{'N'}), \qquad
+            y := \alpha A^T x + \beta y \quad 
+                (\mathrm{trans} = \mathrm{'T'}).
+
+    * If the argument ``P`` of :func:`coneqp` is a Python function, then 
+      ``P(x, y[, alpha = 1.0, beta = 0.0])`` 
+      should evaluate the matrix-vector products
+
+        .. math::
+
+            y := \alpha Px + \beta y.
+
+    If ``G``, ``A``, or ``P`` are Python functions, then the argument 
+    ``kktsolver`` must also be provided.
+
+
+We illustrate these features with three applications.
+
+**Example: 1-norm approximation**
+
+    The optimization problem
+
+    .. math::
+
+        \begin{array}{ll}
+        \mbox{minimize} & \|Pu-q\|_1
+        \end{array}
+
+    can be formulated as a linear program
+
+    .. math::
+
+        \newcommand{\ones}{{\bf 1}}
+        \begin{array}{ll}
+        \mbox{minimize} & \ones^T v \\
+        \mbox{subject to} & -v \preceq Pu - q  \preceq v.
+        \end{array}
+
+    By exploiting the structure in the inequalities, the cost of an 
+    iteration of an interior-point method can be reduced to the cost of 
+    least-squares problem of the same dimensions.  (See section 11.8.2 in 
+    the book 
+    `Convex Optimization <http://www.stanford.edu/~boyd/cvxbook>`_.) 
+    The code below takes advantage of this fact.
+
+    :: 
+
+        from cvxopt import blas, lapack, solvers, matrix, spmatrix, mul, div
+
+        def l1(P, q):
+            """
+
+            Returns the solution u, w of the l1 approximation problem
+
+                (primal) minimize    ||P*u - q||_1       
+            
+                (dual)   maximize    q'*w
+                         subject to  P'*w = 0
+                                     ||w||_infty <= 1.
+            """
+
+            m, n = P.size
+
+            # Solve the equivalent LP 
+            #
+            #     minimize    [0; 1]' * [u; v]
+            #     subject to  [P, -I; -P, -I] * [u; v] <= [q; -q]
+            #
+            #     maximize    -[q; -q]' * z 
+            #     subject to  [P', -P']*z  = 0
+            #                 [-I, -I]*z + 1 = 0 
+            #                 z >= 0.
+            
+            c = matrix(n*[0.0] + m*[1.0])
+
+            def G(x, y, alpha = 1.0, beta = 0.0, trans = 'N'):    
+
+                if trans=='N':
+                    # y := alpha * [P, -I; -P, -I] * x + beta*y
+                    u = P*x[:n]
+                    y[:m] = alpha * ( u - x[n:]) + beta * y[:m]
+                    y[m:] = alpha * (-u - x[n:]) + beta * y[m:]
+
+                else:
+                    # y := alpha * [P', -P'; -I, -I] * x + beta*y
+                    y[:n] =  alpha * P.T * (x[:m] - x[m:]) + beta * y[:n]
+                    y[n:] = -alpha * (x[:m] + x[m:]) + beta * y[n:]
+
+            h = matrix([q, -q])
+            dims = {'l': 2*m, 'q': [], 's': []}
+
+            def F(W): 
+
+                """
+                Returns a function f(x, y, z) that solves
+               
+                    [ 0  0  P'      -P'      ] [ x[:n] ]   [ bx[:n] ]
+                    [ 0  0 -I       -I       ] [ x[n:] ]   [ bx[n:] ]
+                    [ P -I -D1^{-1}  0       ] [ z[:m] ] = [ bz[:m] ]
+                    [-P -I  0       -D2^{-1} ] [ z[m:] ]   [ bz[m:] ]
+                
+                where D1 = diag(di[:m])^2, D2 = diag(di[m:])^2 and di = W['di'].
+                """
+                
+                # Factor A = 4*P'*D*P where D = d1.*d2 ./(d1+d2) and 
+                # d1 = di[:m].^2, d2 = di[m:].^2.
+
+                di = W['di']
+                d1, d2 = di[:m]**2, di[m:]**2
+                D = div( mul(d1,d2), d1+d2 )  
+                A = P.T * spmatrix(4*D, range(m), range(m)) * P
+                lapack.potrf(A)
+
+                def f(x, y, z):
+
+                    """
+                    On entry bx, bz are stored in x, z.  On exit x, z contain the solution, 
+                    with z scaled: z./di is returned instead of z. 
+                    """"
+
+                    # Solve for x[:n]:
+                    #
+                    #    A*x[:n] = bx[:n] + P' * ( ((D1-D2)*(D1+D2)^{-1})*bx[n:]
+                    #              + (2*D1*D2*(D1+D2)^{-1}) * (bz[:m] - bz[m:]) ).
+
+                    x[:n] += P.T * ( mul(div(d1-d2, d1+d2), x[n:]) + mul(2*D, z[:m]-z[m:]) )
+                    lapack.potrs(A, x)
+
+                    # x[n:] := (D1+D2)^{-1} * (bx[n:] - D1*bz[:m] - D2*bz[m:] + (D1-D2)*P*x[:n])
+
+                    u = P*x[:n]
+                    x[n:] =  div(x[n:] - mul(d1, z[:m]) - mul(d2, z[m:]) + mul(d1-d2, u), d1+d2)
+
+                    # z[:m] := d1[:m] .* ( P*x[:n] - x[n:] - bz[:m])
+                    # z[m:] := d2[m:] .* (-P*x[:n] - x[n:] - bz[m:]) 
+
+                    z[:m] = mul(d[:m],  u - x[n:] - z[:m])
+                    z[m:] = mul(d[m:], -u - x[n:] - z[m:])
+
+                return f
+
+            sol = solvers.conelp(c, G, h, dims, kktsolver = F) 
+            return sol['x'][:n],  sol['z'][m:] - sol['z'][:m]    
+
+
+**Example: SDP with diagonal linear term**
+
+    The SDP
+
+    .. math::
+
+        \newcommand{\diag}{\mbox{\bf diag}\,}
+        \newcommand{\ones}{{\bf 1}}
+        \begin{array}{ll}
+        \mbox{minimize} & \ones^T x \\
+        \mbox{subject to} & W + \diag(x) \succeq 0 
+        \end{array} 
+
+    can be solved efficiently by exploiting properties of the diag 
+    operator.
+
+    :: 
+
+        from cvxopt import blas, lapack, solvers, matrix
+
+        def mcsdp(w):
+            """
+            Returns solution x, z to 
+
+                (primal)  minimize    sum(x)
+                          subject to  w + diag(x) >= 0
+
+                (dual)    maximize    -tr(w*z)
+                          subject to  diag(z) = 1
+                                      z >= 0.
+            """
+
+            n = w.size[0]
+            c = matrix(1.0, (n,1))
+
+            def G(x, y, alpha = 1.0, beta = 0.0, trans = 'N'):
+                """
+                    y := alpha*(-diag(x)) + beta*y.   
+                """
+
+                if trans=='N':
+                    # x is a vector; y is a symmetric matrix in column major order.
+                    y *= beta
+                    y[::n+1] -= alpha * x
+
+                else:   
+                    # x is a symmetric matrix in column major order; y is a vector.
+                    y *= beta
+                    y -= alpha * x[::n+1] 
+                 
+
+            def cngrnc(r, x, alpha = 1.0):
+                """
+                Congruence transformation
+
+                    x := alpha * r'*x*r.
+
+                r and x are square matrices.
+                """
+
+                # Scale diagonal of x by 1/2.  
+                x[::n+1] *= 0.5
+            
+                # a := tril(x)*r 
+                a = +r
+                tx = matrix(x, (n,n))
+                blas.trmm(tx, a, side = 'L')
+
+                # x := alpha*(a*r' + r*a') 
+                blas.syr2k(r, a, tx, trans = 'T', alpha = alpha)
+                x[:] = tx[:]
+
+            dims = {'l': 0, 'q': [], 's': [n]}
+
+            def F(W):
+                """
+                Returns a function f(x, y, z) that solves 
+
+                              -diag(z)     = bx
+                    -diag(x) - r*r'*z*r*r' = bz
+
+                where r = W['r'][0] = W['rti'][0]^{-T}.
+                """
+           
+                rti = W['rti'][0]
+
+                # t = rti*rti' as a nonsymmetric matrix.
+                t = matrix(0.0, (n,n))
+                blas.gemm(rti, rti, t, transB = 'T') 
+
+                # Cholesky factorization of tsq = t.*t.
+                tsq = t**2
+                lapack.potrf(tsq)
+
+                def f(x, y, z):
+                    """
+                    On entry, x contains bx, y is empty, and z contains bz stored 
+                    in column major order.
+                    On exit, they contain the solution, with z scaled 
+                    (vec(r'*z*r) is returned instead of z).
+
+                    We first solve 
+                    
+                       ((rti*rti') .* (rti*rti')) * x = bx - diag(t*bz*t)
+                   
+                    and take z = - rti' * (diag(x) + bz) * rti.
+                    """
+
+                    # tbst := t * bz * t
+                    tbst = +z
+                    cngrnc(t, tbst) 
+
+                    # x := x - diag(tbst) = bx - diag(rti*rti' * bz * rti*rti')
+                    x -= tbst[::n+1]
+
+                    # x := (t.*t)^{-1} * x = (t.*t)^{-1} * (bx - diag(t*bz*t))
+                    lapack.potrs(tsq, x)
+
+                    # z := z + diag(x) = bz + diag(x)
+                    z[::n+1] += x 
+
+                    # z := -vec(rti' * z * rti) 
+                    #    = -vec(rti' * (diag(x) + bz) * rti 
+                    cngrnc(rti, z, alpha = -1.0)
+
+                return f
+
+            sol = solvers.conelp(c, G, w[:], dims, kktsolver = F) 
+            return sol['x'], sol['z']
+
+
+**Example: Minimizing 1-norm subject to a 2-norm constraint**
+    In the second example, we use a similar trick to solve the problem
+
+    .. math::
+
+        \begin{array}{ll}
+        \mbox{minimize}   & \|u\|_1 \\
+        \mbox{subject to} & \|Au - b\|_2 \leq 1.
+        \end{array}
+
+    The code below is efficient, if we assume that the number of rows in 
+    :math:`A` is greater than or equal to the number of columns.
+
+    ::
+
+        def qcl1(A, b):
+            """
+            Returns the solution u, z of
+
+                (primal)  minimize    || u ||_1       
+                          subject to  || A * u - b ||_2  <= 1
+
+                (dual)    maximize    b^T z - ||z||_2
+                          subject to  || A'*z ||_inf <= 1.
+
+            Exploits structure, assuming A is m by n with m >= n. 
+            """
+
+            m, n = A.size
+
+            # Solve equivalent cone LP with variables x = [u; v].
+            #
+            #     minimize    [0; 1]' * x 
+            #     subject to  [ I  -I ] * x <=  [  0 ]   (componentwise)
+            #                 [-I  -I ] * x <=  [  0 ]   (componentwise)
+            #                 [ 0   0 ] * x <=  [  1 ]   (SOC)
+            #                 [-A   0 ]         [ -b ]
+            #
+            #     maximize    -t + b' * w
+            #     subject to  z1 - z2 = A'*w
+            #                 z1 + z2 = 1
+            #                 z1 >= 0,  z2 >=0,  ||w||_2 <= t.
+             
+            c = matrix(n*[0.0] + n*[1.0])
+            h = matrix( 0.0, (2*n + m + 1, 1))
+            h[2*n] = 1.0
+            h[2*n+1:] = -b
+
+            def G(x, y, alpha = 1.0, beta = 0.0, trans = 'N'):    
+                y *= beta
+                if trans=='N':
+                    # y += alpha * G * x 
+                    y[:n] += alpha * (x[:n] - x[n:2*n]) 
+                    y[n:2*n] += alpha * (-x[:n] - x[n:2*n]) 
+                    y[2*n+1:] -= alpha * A*x[:n] 
+
+                else:
+                    # y += alpha * G'*x 
+                    y[:n] += alpha * (x[:n] - x[n:2*n] - A.T * x[-m:])  
+                    y[n:] -= alpha * (x[:n] + x[n:2*n]) 
+
+
+            def Fkkt(W): 
+                """
+                Returns a function f(x, y, z) that solves
+                
+                    [ 0   G'   ] [ x ] = [ bx ]
+                    [ G  -W'*W ] [ z ]   [ bz ].
+                """
+
+                # First factor 
+                #
+                #     S = G' * W**-1 * W**-T * G
+                #       = [0; -A]' * W3^-2 * [0; -A] + 4 * (W1**2 + W2**2)**-1 
+                #
+                # where
+                #
+                #     W1 = diag(d1) with d1 = W['d'][:n] = 1 ./ W['di'][:n]  
+                #     W2 = diag(d2) with d2 = W['d'][n:] = 1 ./ W['di'][n:]  
+                #     W3 = beta * (2*v*v' - J),  W3^-1 = 1/beta * (2*J*v*v'*J - J)  
+                #        with beta = W['beta'][0], v = W['v'][0], J = [1, 0; 0, -I].
+          
+                # As = W3^-1 * [ 0 ; -A ] = 1/beta * ( 2*J*v * v' - I ) * [0; A]
+                beta, v = W['beta'][0], W['v'][0]
+                As = 2 * v * (v[1:].T * A)
+                As[1:,:] *= -1.0
+                As[1:,:] -= A
+                As /= beta
+              
+                # S = As'*As + 4 * (W1**2 + W2**2)**-1
+                S = As.T * As 
+                d1, d2 = W['d'][:n], W['d'][n:]       
+                d = 4.0 * (d1**2 + d2**2)**-1
+                S[::n+1] += d
+                lapack.potrf(S)
+
+                def f(x, y, z):
+
+                    # z := - W**-T * z 
+                    z[:n] = -div( z[:n], d1 )
+                    z[n:2*n] = -div( z[n:2*n], d2 )
+                    z[2*n:] -= 2.0*v*( v[0]*z[2*n] - blas.dot(v[1:], z[2*n+1:]) ) 
+                    z[2*n+1:] *= -1.0
+                    z[2*n:] /= beta
+
+                    # x := x - G' * W**-1 * z
+                    x[:n] -= div(z[:n], d1) - div(z[n:2*n], d2) + As.T * z[-(m+1):]
+                    x[n:] += div(z[:n], d1) + div(z[n:2*n], d2) 
+
+                    # Solve for x[:n]:
+                    #
+                    #    S*x[:n] = x[:n] - (W1**2 - W2**2)(W1**2 + W2**2)^-1 * x[n:]
+                    
+                    x[:n] -= mul( div(d1**2 - d2**2, d1**2 + d2**2), x[n:]) 
+                    lapack.potrs(S, x)
+                    
+                    # Solve for x[n:]:
+                    #
+                    #    (d1**-2 + d2**-2) * x[n:] = x[n:] + (d1**-2 - d2**-2)*x[:n]
+                     
+                    x[n:] += mul( d1**-2 - d2**-2, x[:n])
+                    x[n:] = div( x[n:], d1**-2 + d2**-2)
+
+                    # z := z + W^-T * G*x 
+                    z[:n] += div( x[:n] - x[n:2*n], d1) 
+                    z[n:2*n] += div( -x[:n] - x[n:2*n], d2) 
+                    z[2*n:] += As*x[:n]
+
+                return f
+
+            dims = {'l': 2*n, 'q': [m+1], 's': []}
+            sol = solvers.conelp(c, G, h, dims, kktsolver = Fkkt)
+            if sol['status'] == 'optimal':
+                return sol['x'][:n],  sol['z'][-m:]
+            else:
+                return None, None
+
+
+**Example: 1-norm regularized least-squares** 
+    As an example that illustrates how structure can be exploited in 
+    :func:`coneqp <cvxopt.solvers.coneqp>`, we consider the 1-norm 
+    regularized least-squares problem
+
+    .. math::
+
+        \begin{array}{ll}
+        \mbox{minimize} & \|Ax - y\|_2^2 + \|x\|_1
+        \end{array}
+
+    with variable :math:`x`.  The problem is equivalent to the quadratic 
+    program
+
+    .. math::
+
+        \newcommand{\ones}{{\bf 1}}
+        \begin{array}{ll}
+        \mbox{minimize} & \|Ax - y\|_2^2 + \ones^T u \\
+        \mbox{subject to} & -u \preceq x \preceq u
+        \end{array}
+
+    with variables :math:`x` and :math:`u`.  The implementation below is 
+    efficient when :math:`A` has many more columns than rows. 
+
+    ::
+
+        from cvxopt import matrix, spdiag, mul, div, blas, lapack, solvers, sqrt
+        import math
+
+        def l1regls(A, y):
+            """
+            
+            Returns the solution of l1-norm regularized least-squares problem
+          
+                minimize || A*x - y ||_2^2  + || x ||_1.
+
+            """
+
+            m, n = A.size
+            q = matrix(1.0, (2*n,1))
+            q[:n] = -2.0 * A.T * y
+
+            def P(u, v, alpha = 1.0, beta = 0.0 ):
+                """
+                    v := alpha * 2.0 * [ A'*A, 0; 0, 0 ] * u + beta * v 
+                """
+                v *= beta
+                v[:n] += alpha * 2.0 * A.T * (A * u[:n])
+
+
+            def G(u, v, alpha=1.0, beta=0.0, trans='N'):
+                """
+                    v := alpha*[I, -I; -I, -I] * u + beta * v  (trans = 'N' or 'T')
+                """
+
+                v *= beta
+                v[:n] += alpha*(u[:n] - u[n:])
+                v[n:] += alpha*(-u[:n] - u[n:])
+
+            h = matrix(0.0, (2*n,1))
+
+
+            # Customized solver for the KKT system 
+            #
+            #     [  2.0*A'*A  0    I      -I     ] [x[:n] ]     [bx[:n] ]
+            #     [  0         0   -I      -I     ] [x[n:] ]  =  [bx[n:] ].
+            #     [  I        -I   -D1^-1   0     ] [zl[:n]]     [bzl[:n]]
+            #     [ -I        -I    0      -D2^-1 ] [zl[n:]]     [bzl[n:]]
+            #
+            # where D1 = W['di'][:n]**2, D2 = W['di'][n:]**2.
+            #    
+            # We first eliminate zl and x[n:]:
+            #
+            #     ( 2*A'*A + 4*D1*D2*(D1+D2)^-1 ) * x[:n] = 
+            #         bx[:n] - (D2-D1)*(D1+D2)^-1 * bx[n:] + 
+            #         D1 * ( I + (D2-D1)*(D1+D2)^-1 ) * bzl[:n] - 
+            #         D2 * ( I - (D2-D1)*(D1+D2)^-1 ) * bzl[n:]           
+            #
+            #     x[n:] = (D1+D2)^-1 * ( bx[n:] - D1*bzl[:n]  - D2*bzl[n:] ) 
+            #         - (D2-D1)*(D1+D2)^-1 * x[:n]         
+            #
+            #     zl[:n] = D1 * ( x[:n] - x[n:] - bzl[:n] )
+            #     zl[n:] = D2 * (-x[:n] - x[n:] - bzl[n:] ).
+            #
+            # The first equation has the form
+            #
+            #     (A'*A + D)*x[:n]  =  rhs
+            #
+            # and is equivalent to
+            #
+            #     [ D    A' ] [ x:n] ]  = [ rhs ]
+            #     [ A   -I  ] [ v    ]    [ 0   ].
+            #
+            # It can be solved as 
+            #
+            #     ( A*D^-1*A' + I ) * v = A * D^-1 * rhs
+            #     x[:n] = D^-1 * ( rhs - A'*v ).
+
+            S = matrix(0.0, (m,m))
+            Asc = matrix(0.0, (m,n))
+            v = matrix(0.0, (m,1))
+
+            def Fkkt(W):
+
+                # Factor 
+                #
+                #     S = A*D^-1*A' + I 
+                #
+                # where D = 2*D1*D2*(D1+D2)^-1, D1 = d[:n]**-2, D2 = d[n:]**-2.
+
+                d1, d2 = W['di'][:n]**2, W['di'][n:]**2
+
+                # ds is square root of diagonal of D
+                ds = math.sqrt(2.0) * div( mul( W['di'][:n], W['di'][n:]), sqrt(d1+d2) )
+                d3 =  div(d2 - d1, d1 + d2)
+             
+                # Asc = A*diag(d)^-1/2
+                Asc = A * spdiag(ds**-1)
+
+                # S = I + A * D^-1 * A'
+                blas.syrk(Asc, S)
+                S[::m+1] += 1.0 
+                lapack.potrf(S)
+
+                def g(x, y, z):
+
+                    x[:n] = 0.5 * ( x[:n] - mul(d3, x[n:]) + 
+                        mul(d1, z[:n] + mul(d3, z[:n])) - mul(d2, z[n:] - 
+                        mul(d3, z[n:])) )
+                    x[:n] = div( x[:n], ds) 
+
+                    # Solve
+                    #
+                    #     S * v = 0.5 * A * D^-1 * ( bx[:n] - 
+                    #         (D2-D1)*(D1+D2)^-1 * bx[n:] + 
+                    #         D1 * ( I + (D2-D1)*(D1+D2)^-1 ) * bzl[:n] - 
+                    #         D2 * ( I - (D2-D1)*(D1+D2)^-1 ) * bzl[n:] )
+                        
+                    blas.gemv(Asc, x, v)
+                    lapack.potrs(S, v)
+                    
+                    # x[:n] = D^-1 * ( rhs - A'*v ).
+                    blas.gemv(Asc, v, x, alpha=-1.0, beta=1.0, trans='T')
+                    x[:n] = div(x[:n], ds)
+
+                    # x[n:] = (D1+D2)^-1 * ( bx[n:] - D1*bzl[:n]  - D2*bzl[n:] ) 
+                    #         - (D2-D1)*(D1+D2)^-1 * x[:n]         
+                    x[n:] = div( x[n:] - mul(d1, z[:n]) - mul(d2, z[n:]), d1+d2 )\
+                        - mul( d3, x[:n] )
+                        
+                    # zl[:n] = D1^1/2 * (  x[:n] - x[n:] - bzl[:n] )
+                    # zl[n:] = D2^1/2 * ( -x[:n] - x[n:] - bzl[n:] ).
+                    z[:n] = mul( W['di'][:n],  x[:n] - x[n:] - z[:n] ) 
+                    z[n:] = mul( W['di'][n:], -x[:n] - x[n:] - z[n:] ) 
+
+                return g
+
+            return solvers.coneqp(P, q, G, h, kktsolver = Fkkt)['x'][:n]
+
+
+.. _s-external:
+
+Optional Solvers
+================
+
+CVXOPT includes optional interfaces to several other optimization 
+libraries.
+
+**GLPK** 
+    :func:`lp <cvxopt.solvers.lp>` with the ``solver`` option set to 
+    :const:`'glpk'` uses the 
+    simplex algorithm in `GLPK (GNU Linear Programming Kit) 
+    <http://www.gnu.org/software/glpk/glpk.html>`_.
+
+**MOSEK** 
+    :func:`lp <cvxopt.solvers.lp>`, :func:`socp <cvxopt.solvers.socp>`,
+    and :func:`qp <cvxopt.solvers.qp>` with the ``solver`` option
+    set to :const:`'mosek'` option use `MOSEK <http://www.mosek.com>`_
+    version 5.
+
+**DSDP** 
+    :func:`sdp <cvxopt.solvers.sdp>` with the ``solver`` option set to 
+    :const:`'dsdp'` uses 
+    the `DSDP5.8 <http://www-unix.mcs.anl.gov/DSDP>`_.  
+
+GLPK, MOSEK and DSDP are not included in the CVXOPT distribution and 
+need to be installed separately.  
+
+
+.. _s-parameters:
+
+Algorithm Parameters
+====================
+
+In this section we list some algorithm control parameters that can be 
+modified without editing the source code.  These control parameters are 
+accessible via the dictionary :attr:`solvers.options`.  By default the 
+dictionary is empty and the default values of the parameters are used.
+
+One can change the parameters in the default solvers by 
+adding entries with the following key values.  
+
+:const:`'show_progress'`  
+    :const:`True` or :const:`False`; turns the output to the screen on or 
+    off (default: :const:`True`).
+
+:const:`'maxiters'` 
+    maximum number of iterations (default: :const:`100`).
+
+:const:`'abstol'` 
+    absolute accuracy (default: :const:`1e-7`).
+
+:const:`'reltol'` 
+    relative accuracy (default: :const:`1e-6`).
+
+:const:`'feastol'`
+    tolerance for feasibility conditions (default: :const:`1e-7`).
+
+:const:`'refinement'` 
+    number of iterative refinement steps when solving KKT equations 
+    (default: :const:`0` if the problem has no second-order cone or matrix 
+    inequality constraints; :const:`1` otherwise).
+
+For example the command
+
+>>> from cvxopt import solvers
+>>> solvers.options['show_progress'] = False
+
+turns off the screen output during calls to the solvers.
+
+The tolerances :const:`'abstol'`, :const:`'reltol'` and :const:`'feastol'` 
+have the following meaning.  :func:`conelp <cvxopt.solvers.conelp>` 
+terminates with status :const:`'optimal'` if
+
+.. math::
+
+    s \succeq 0, \qquad 
+    \frac{\|Gx + s - h\|_2} {\max\{1,\|h\|_2\}} \leq 
+        \epsilon_\mathrm{feas}, \qquad 
+    \frac{\|Ax-b\|_2}{\max\{1,\|b\|_2\}} \leq \epsilon_\mathrm{feas}, 
+        \qquad
+
+and
+
+.. math::
+
+    z \succeq 0, \qquad
+    \frac{\|G^Tz +  A^Ty + c\|_2}{\max\{1,\|c\|_2\}} \leq 
+        \epsilon_\mathrm{feas}, 
+
+and
+
+.. math::
+
+    s^T z \leq \epsilon_\mathrm{abs} \qquad \mbox{or} \qquad
+    \left( \min\left\{c^Tx,  h^T z + b^Ty \right\} < 0 \quad 
+        \mbox{and} \quad
+    \frac{s^Tz} {-\min\{c^Tx, h^Tz + b^T y\}} \leq \epsilon_\mathrm{rel} 
+    \right).
+
+It returns with status :const:`'primal infeasible'` if 
+
+.. math::
+
+    z \succeq 0, \qquad \qquad 
+    \frac{\|G^Tz +A^Ty\|_2}{\max\{1, \|c\|_2\}} \leq 
+        \epsilon_\mathrm{feas}, \qquad 
+    h^Tz +b^Ty = -1.
+
+It returns with status :const:`'dual infeasible'` if 
+
+.. math::
+
+    s \succeq 0, \qquad \qquad
+    \frac{\|Gx+s\|_2}{\max\{1, \|h\|_2\}} \leq \epsilon_\mathrm{feas}, 
+    \qquad
+    \frac{\|Ax\|_2}{\max\{1, \|b\|_2\}} \leq \epsilon_\mathrm{feas}, 
+    \qquad c^Tx = -1.
+
+The functions :func:`lp <cvxopt.solvers.lp`, 
+:func:`socp <cvxopt.solvers.socp>` and 
+:func:`sdp <cvxopt.solvers.sdp>` call :func:`conelp` 
+and hence use the same stopping criteria.
+
+The function :func:`coneqp <cvxopt.solvers.coneqp>` terminates with 
+status :const:`'optimal'` if
+
+.. math::
+
+    s \succeq 0, \qquad 
+    \frac{\|Gx + s - h\|_2} {\max\{1,\|h\|_2\}} \leq 
+        \epsilon_\mathrm{feas}, \qquad 
+    \frac{\|Ax-b\|_2}{\max\{1,\|b\|_2\}} \leq \epsilon_\mathrm{feas}, 
+
+and
+
+.. math::
+    z \succeq 0, \qquad 
+    \frac{\|Px + G^Tz +  A^Ty + q\|_2}{\max\{1,\|q\|_2\}} \leq 
+        \epsilon_\mathrm{feas}, 
+
+and at least one of the following three conditions is satisfied:
+
+.. math:: 
+
+    s^T z \leq \epsilon_\mathrm{abs} 
+
+or
+
+.. math::
+
+    \left( \frac{1}{2}x^TPx + q^Tx < 0, \quad 
+    \mbox{and}\quad \frac{s^Tz} {-(1/2)x^TPx - q^Tx} \leq 
+        \epsilon_\mathrm{rel} \right) 
+
+or
+
+.. math::
+    \left( L(x,y,z) > 0 \quad \mbox{and} \quad \frac{s^Tz}
+        {L(x,y,z)} \leq \epsilon_\mathrm{rel} \right).
+
+Here
+
+.. math::
+
+    L(x,y,z) = \frac{1}{2}x^TPx + q^Tx  + z^T (Gx-h) + y^T(Ax-b).
+
+The function :func:`qp <cvxopt.solvers.qp>` calls 
+:func:`coneqp` and hence uses the same 
+stopping criteria.
+
+The control parameters listed in the GLPK documentation are set to their 
+default values and can be customized by making an entry in 
+:attr:`solvers.options`.  The keys in the dictionary are strings with the 
+name of the GLPK parameter.  For example, the command
+
+>>> from cvxopt import solvers 
+>>> solvers.options['LPX_K_MSGLEV'] = 0
+
+turns off the screen output subsequent calls 
+:func:`lp <cvxopt.solvers.lp>` with the :const:`'glpk'` option.
+
+The MOSEK interior-point algorithm parameters are set to their default 
+values.  They can be modified by adding an entry 
+:attr:`solvers.options['MOSEK']`.  This entry is a dictionary with 
+MOSEK parameter/value pairs, with the parameter names imported from
+:mod:`pymosek`.  For details see Section 14.1.3 of the 
+`MOSEK Python API Manual <http://www.mosek.com/fileadmin/products/5_0/tools/doc/html/pyapi/index.html>`_.
+
+For example the commands
+
+>>> from cvxopt import solvers 
+>>> import pymosek
+>>> solvers.options['MOSEK'] = {pymosek.iparam.log: 0}
+
+turn off the screen output during calls of 
+:func:`lp` or :func:`socp` with
+the :const:`'mosek'` option.
+
+The following control parameters in :attr:`solvers.options` affect the 
+execution of the DSDP algorithm:
+
+:const:`'DSDP_Monitor'` 
+    the interval (in number of iterations) at which output is printed to 
+    the screen (default: :const:`0`).
+
+:const:`'DSDP_MaxIts'` 
+    maximum number of iterations.
+
+:const:`'DSDP_GapTolerance'` 
+    relative accuracy (default: :const:`1e-5`).
diff --git a/doc/source/conf.py b/doc/source/conf.py
new file mode 100644
index 0000000..9aa5334
--- /dev/null
+++ b/doc/source/conf.py
@@ -0,0 +1,182 @@
+# -*- coding: utf-8 -*-
+#
+# CVXOPT documentation build configuration file, created by
+# sphinx-quickstart on Sat Dec 27 20:54:35 2008.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default value; values that are commented out
+# serve to show the default value.
+
+import sys, os
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+#sys.path.append(os.path.abspath('some/directory'))
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.pngmath']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['.templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'CVXOPT'
+#copyright = '2004-2009, Joachim Dahl, Lieven Vandenberghe'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '1.1.1'
+# The full version, including alpha/beta/rc tags.
+release = '1.1.1'
+
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directories, that shouldn't be searched
+# for source files.
+#exclude_dirs = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+add_function_parentheses = False
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+add_module_names = False
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'cvxopt.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+html_title = "CVXOPT User's Guide"
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+html_short_title = "user's guide"
+
+# The name of an image file (within the static path) to place at the top of
+# the sidebar.
+html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['.static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+html_last_updated_fmt = ''
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+html_use_modindex = False
+
+# If false, no index is generated.
+html_use_index = False
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+html_copy_source = False
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'CVXOPTdoc'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+latex_documents = [
+  ('index', 'CVXOPT.tex', 'CVXOPT Documentation',
+   'Joachim Dahl, Lieven Vandenberghe', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
diff --git a/doc/source/copyright.rst b/doc/source/copyright.rst
new file mode 100644
index 0000000..770d9d2
--- /dev/null
+++ b/doc/source/copyright.rst
@@ -0,0 +1,53 @@
+.. role:: raw-html(raw)
+    :format: html
+
+*********************
+Copyright and License
+*********************
+
+:raw-html:`©` 2004-2009 J. Dahl and L. Vandenberghe. 
+
+
+CVXOPT is free software; you can redistribute it and/or modify it under 
+the terms of the 
+`GNU General Public License <http://www.gnu.org/licenses/gpl-3.0.html>`_
+as published by the Free Software Foundation; either version 3 of the 
+License, or (at your option) any later version.
+
+CVXOPT 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 General Public License <http://www.gnu.org/licenses/gpl-3.0.html>`_
+for more details. 
+
+
+.. raw:: html
+   
+   <hr>
+
+The CVXOPT distribution includes the source code of part of the 
+`SuiteSparse <http://www.cise.ufl.edu/research/sparse>`_
+collection of sparse matrix algorithms.  The copyright and license 
+information for the included libraries is as follows.
+
+* **AMD** Version 2.2.  Copyright (c) 2007 by Timothy A.  Davis, 
+  Patrick R.  Amestoy, and Iain S. Duff.  
+
+* **CHOLMOD** Version 1.7.1.  Copyright (c) 2005-2009 by the
+  University of Florida, Timothy A. Davis, and W. Hager.
+
+* **COLAMD** Version 2.7.  Copyright (c) 1998-2007 by Timothy A. Davis.
+
+* **UMFPACK** Version 5.4.0.  Copyright (c) 1994-2009 by Timothy A. Davis.
+
+UMFPACK and the Supernodal module of CHOLMOD are licensed under the terms 
+of the `GNU General Public License, version 2 
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>`_ or higher.
+The other CHOLMOD modules, AMD, and COLAMD are licensed under the terms of 
+the `GNU Lesser General Public License, version 2.1 
+<http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>`_ or higher.
+For more details, consult the README files in the source directories or 
+the documentation at 
+`www.cise.ufl.edu/research/sparse <http://www.cise.ufl.edu/research/sparse>`_.
+
diff --git a/doc/source/fftw.rst b/doc/source/fftw.rst
new file mode 100644
index 0000000..c174495
--- /dev/null
+++ b/doc/source/fftw.rst
@@ -0,0 +1,185 @@
+.. _c-fftw:
+
+*******************
+Discrete Transforms
+*******************
+
+The :mod:`cvxopt.fftw` module is an interface to the FFTW library and 
+contains routines for discrete Fourier, cosine, and sine transforms.  
+This module is optional, and only installed when the FFTW library is made 
+available during the CVXOPT installation.
+
+.. seealso:: 
+
+    `FFTW3 code, documentation, copyright and license 
+    <http://www.fftw.org>`_
+
+
+Discrete Fourier Transform 
+==========================
+
+.. function:: cvxopt.fftw.dft(X)
+
+    Replaces the columns of a dense complex matrix with their discrete 
+    Fourier transforms:  if ``X`` has :math:`n` rows,
+
+    .. math::
+
+        X[k,:] := \sum_{j=0}^{n-1} e^{-2\pi j k \sqrt{-1}/n} X[j,:],
+            \qquad k=0,\ldots,n-1.
+
+.. function:: cvxopt.fftw.idft(X)
+
+    Replaces the columns of a dense complex matrix with their inverse 
+    discrete Fourier transforms: if ``X`` has :math:`n` rows,
+
+    .. math::
+    
+        X[k,:] := 
+            \frac{1}{n} \sum_{j=0}^{n-1} e^{2\pi j k \sqrt{-1}/n} X[j,:],
+            \qquad k=0,\ldots,n-1.
+   
+
+The module also includes a discrete *N*-dimensional Fourier transform.
+The input matrix is interpreted as an *N*-dimensional matrix stored 
+in column-major order.  The discrete *N*-dimensional Fourier transform
+computes the corresponding one-dimensional transform along each dimension. 
+For example, the two-dimensional transform applies a one-dimensional 
+transform to all the columns of the matrix, followed by a one-dimensional 
+transform to all the rows of the matrix. 
+
+.. function:: cvxopt.fftw.dftn(X[, dims = X.size])
+
+    Replaces a dense complex matrix with its *N*-dimensional discrete
+    Fourier transform.  The dimensions of the *N*-dimensional matrix 
+    are given by the *N*-tuple ``dims``.  The two-dimensional transform is 
+    computed as ``dftn(X, X.size)``. 
+
+
+.. function:: cvxopt.fftw.idftn(X[, dims = X.size])
+
+    Replaces a dense complex *N*-dimensional matrix with its inverse 
+    *N*-dimensional discrete Fourier transform.  The dimensions of the 
+    matrix are given by the tuple ``dims``. The two-dimensional inverse 
+    transform is computed as ``idftn(X, X.size)``.
+
+
+Discrete Cosine Transform
+=========================
+
+.. function:: cvxopt.fftw.dct(X[, type = 2])
+
+    Replaces the columns of a dense real matrix with their discrete
+    cosine transforms.  The second argument, an integer between 1 and 4,
+    denotes the type of transform (DCT-I, DCT-II, DCT-III, DCT-IV).
+    The DCT-I transform requires that the row dimension of ``X`` is at 
+    least 2.  These transforms are defined as follows (for a matrix with 
+    :math:`n` rows).
+
+    .. math::
+
+        \mbox{DCT-I:} \qquad 
+            X[k,:] & := X[0,:] + (-1)^k X[n-1,:] + 
+                2 \sum_{j=1}^{n-2} X[j,:] \cos(\pi j k /(n-1)), 
+                \qquad k=0,\ldots,n-1.\\
+        \mbox{DCT-II:} \qquad
+            X[k,:] & := 2 \sum_{j=0}^{n-1} X[j,:] \cos(\pi(j+1/2)k/n), 
+               \qquad k=0,\ldots,n-1.\\
+        \mbox{DCT-III:} \qquad
+            X[k,:] & := 
+                X[0,:] + 2 \sum_{j=1}^{n-1} X[j,:] \cos(\pi j(k+1/2)/n),
+                \qquad k=0,\ldots,n-1.\\
+        \mbox{DCT-IV:} \qquad
+            X[k,:] & := 
+                2 \sum_{j=0}^{n-1} X[j,:] \cos(\pi (j+1/2)(k+1/2)/n), 
+                \qquad k=0,\ldots,n-1.
+
+
+.. function:: cvxopt.fftw.idct(X[, type = 2])
+
+    Replaces the columns of a dense real matrix with the inverses
+    of the discrete cosine transforms defined above.  
+
+
+The module also includes a discrete *N*-dimensional cosine transform.
+The input matrix is interpreted as an *N*-dimensional matrix stored 
+in column-major order.  The discrete *N*-dimensional cosine transform
+computes the corresponding one-dimensional transform along each dimension. 
+For example, the two-dimensional transform applies a one-dimensional 
+transform to all the rows of the matrix, followed by a one-dimensional 
+transform to all the columns of the matrix. 
+
+
+.. function:: cvxopt.fftw.dctn(X[, dims = X.size, type = 2])
+
+    Replaces a dense real matrix with its *N*-dimensional discrete cosine 
+    transform. The dimensions of the *N*-dimensional matrix are given by  
+    the *N*-tuple ``dims``.  The two-dimensional transform is computed as 
+    ``dctn(X, X.size)``. 
+
+
+.. function:: cvxopt.fftw.idctn(X[, dims = X.size, type = 2])
+
+    Replaces a dense real *N*-dimensional matrix with its inverse 
+    *N*-dimensional discrete cosine transform. The dimensions of the 
+    matrix are given by the tuple ``dims``.  The two-dimensional inverse 
+    transform is computed as ``idctn(X, X.size)``.
+
+
+Discrete Sine Transform 
+=======================
+
+.. function:: cvxopt.fftw.dst(X, dims[, type = 1])
+
+    Replaces the columns of a dense real matrix with their discrete
+    sine transforms.  The second argument, an integer between 1 and 4,
+    denotes the type of transform (DST-I, DST-II, DST-III, DST-IV).
+    These transforms are defined as follows (for a matrix with :math:`n` 
+    rows).
+
+    .. math::
+       
+        \mbox{DST-I:} \qquad
+            X[k,:] & := 
+                2 \sum_{j=0}^{n-1} X[j,:] \sin(\pi(j+1)(k+1)/(n+1)), 
+                \qquad k=0,\ldots,n-1.\\
+        \mbox{DST-II:} \qquad
+            X[k,:] & := 2 \sum_{j=0}^{n-1} X[j,:] \sin(\pi(j+1/2)(k+1)/n), 
+                \qquad k=0,\ldots,n-1.\\
+        \mbox{DST-III:} \qquad
+            X[k,:] & := (-1)^k X[n-1,:] + 2 \sum_{j=0}^{n-2} 
+                X[j,:] \sin(\pi(j+1)(k+1/2)/n), \qquad k=0,\ldots,n-1. \\
+        \mbox{DST-IV:} \qquad
+            X[k,:] & := 
+                2 \sum_{j=0}^{n-1} X[j,:] \sin(\pi (j+1/2)(k+1/2)/n), 
+                \qquad k=0,\ldots,n-1.
+
+
+.. function:: cvxopt.fftw.idst(X, dims[, type = 1])
+
+    Replaces the columns of a dense real matrix with the inverses of the 
+    discrete sine transforms defined above.  
+
+
+The module also includes a discrete *N*-dimensional sine transform.  The 
+input matrix is interpreted as an *N*-dimensional matrix stored in 
+column-major order.  The discrete *N*-dimensional sine transform computes 
+the corresponding one-dimensional transform along each dimension.  For 
+example, the two-dimensional transform applies a one-dimensional 
+transform to all the rows of the matrix, followed by a one-dimensional 
+transform to all the columns of the matrix. 
+
+.. function:: cvxopt.fftw.dstn(X[, dims = X.size, type = 2])
+
+    Replaces a dense real matrix with its *N*-dimensional discrete sine 
+    transform. The dimensions of the *N*-dimensional matrix are given by 
+    the *N*-tuple ``dims``.  The two-dimensional transform is computed as 
+    ``dstn(X, X.size)``. 
+
+
+.. function:: cvxopt.fftw.idstn(X[, dims = X.size, type = 2])
+
+    Replaces a dense real *N*-dimensional matrix with its inverse 
+    *N*-dimensional discrete sine transform.  The dimensions of the 
+    matrix are given by the tuple ``dims``.  The two-dimensional inverse 
+    transform is computed as ``idstn(X, X.size)``.
diff --git a/doc/source/floorplan.png b/doc/source/floorplan.png
new file mode 100644
index 0000000..e712437
Binary files /dev/null and b/doc/source/floorplan.png differ
diff --git a/doc/source/index.rst b/doc/source/index.rst
new file mode 100644
index 0000000..fa84d05
--- /dev/null
+++ b/doc/source/index.rst
@@ -0,0 +1,23 @@
+######
+CVXOPT 
+######
+
+**Release 1.1.2 -- December 15, 2009**
+
+**Joachim Dahl & Lieven Vandenberghe**
+
+.. toctree::
+
+    copyright.rst
+    intro.rst
+    matrices.rst
+    blas.rst
+    lapack.rst
+    fftw.rst
+    spsolvers.rst
+    coneprog.rst
+    solvers.rst
+    modeling.rst
+    c-api.rst
+    printing.rst
+
diff --git a/doc/source/intro.rst b/doc/source/intro.rst
new file mode 100644
index 0000000..27c90c5
--- /dev/null
+++ b/doc/source/intro.rst
@@ -0,0 +1,71 @@
+.. _intro:
+
+************
+Introduction
+************
+
+CVXOPT is a free software package for convex optimization based on the 
+Python programming language.  It can be used with the interactive Python 
+interpreter, on the command line by executing Python scripts, or integrated
+in other software via Python extension modules.  Its main purpose is to 
+make the development of software for convex optimization applications 
+straightforward by building on Python's extensive standard library and on 
+the strengths of Python as a high-level programming language.  
+
+CVXOPT extends the built-in Python objects with two matrix objects: a 
+:class:`matrix <cvxopt.matrix>`  object for dense matrices and an 
+:class:`spmatrix <cvxopt.spmatrix>` object for sparse matrices.  These two 
+matrix types are introduced in the chapter :ref:`c-matrices`, together 
+with the arithmetic operations and functions defined for them.  The 
+following chapters (:ref:`c-blas` and :ref:`c-spsolvers`) describe 
+interfaces to several libraries for dense and sparse matrix computations.  
+The CVXOPT optimization routines are described in the chapters 
+:ref:`c-coneprog` and :ref:`c-modeling`.
+These include convex optimization solvers written in Python, 
+interfaces to a few other optimization libraries, and a modeling tool 
+for piecewise-linear convex optimization problems.
+
+CVXOPT is organized in different modules.  
+
+:mod:`cvxopt.blas <cvxopt.blas>` 
+  Interface to most of the double-precision real and complex BLAS 
+  (:ref:`c-blas`).
+
+:mod:`cvxopt.lapack <cvxopt.lapack>`
+  Interface to dense double-precision real and complex linear equation 
+  solvers and eigenvalue routines from LAPACK (:ref:`c-lapack`).
+
+:mod:`cvxopt.fftw <cvxopt.fftw>` 
+  An optional interface to the discrete transform routines from FFTW 
+  (:ref:`c-fftw`). 
+
+:mod:`cvxopt.amd <cvxopt.amd>`  
+  Interface to the approximate minimum degree ordering routine from AMD 
+  (:ref:`s-orderings`).
+
+:mod:`cvxopt.umfpack <cvxopt.umfpack>` 
+  Interface to the sparse LU solver from UMFPACK (:ref:`s-umfpack`).
+
+:mod:`cvxopt.cholmod <cvxopt.cholmod>`  
+  Interface to the sparse Cholesky solver from CHOLMOD (:ref:`s-cholmod`).
+
+:mod:`cvxopt.solvers <cvxopt.solvers>` 
+  Convex optimization routines and optional interfaces to solvers from 
+  GLPK, MOSEK, and DSDP5 (:ref:`c-coneprog` and :ref:`c-solvers`).
+
+:mod:`cvxopt.modeling <cvxopt.modeling>`   
+  Routines for specifying and solving linear programs and convex 
+  optimization problems with piecewise-linear cost and constraint functions
+  (:ref:`c-modeling`).
+
+:mod:`cvxopt.info <cvxopt.info>`  
+  Defines a string :const:`version` with the version number of the CVXOPT 
+  installation and a function :func:`license` that prints the CVXOPT 
+  license.  
+
+:mod:`cvxopt.printing <cvxopt.printing>` 
+  Contains functions and parameters that control how matrices are formatted.
+
+The modules are described in detail in this manual and in the on-line Python
+help facility :program:`pydoc`.  Several example scripts are included in 
+the distribution. 
diff --git a/doc/source/lapack.rst b/doc/source/lapack.rst
new file mode 100644
index 0000000..5a575a8
--- /dev/null
+++ b/doc/source/lapack.rst
@@ -0,0 +1,1660 @@
+.. role:: raw-html(raw)
+   :format: html
+
+.. _c-lapack:
+
+********************
+The LAPACK Interface
+********************
+
+The module :mod:`cvxopt.lapack` includes functions for solving dense sets 
+of linear equations, for the corresponding matrix factorizations (LU, 
+Cholesky, :raw-html:`LDL<sup><small>T</small></sup>`),
+for solving least-squares and least-norm problems, for 
+QR factorization, for symmetric eigenvalue problems, singular value 
+decomposition, and Schur factorization.  
+
+In this chapter we briefly describe the Python calling sequences.  For 
+further details on the underlying LAPACK functions we refer to the LAPACK 
+Users' Guide and manual pages.  
+
+The BLAS conventional storage scheme of the section :ref:`s-conventions` 
+is used. As in the previous chapter, we omit from the function definitions
+less important arguments that are useful for selecting submatrices.  The 
+complete definitions are documented in the docstrings in the source code.
+
+.. seealso:: 
+
+    `LAPACK Users' Guide, Third Edition, SIAM, 1999
+    <http://www.netlib.org/lapack/lug/lapack_lug.html>`_
+
+
+General Linear Equations
+========================
+
+.. function:: cvxopt.lapack.gesv(A, B[, ipiv = None])
+
+    Solves
+    
+    .. math::
+
+        A X = B,
+
+    where :math:`A` and :math:`B` are real or complex matrices, with 
+    :math:`A` square and nonsingular.  
+
+    The arguments ``A`` and ``B`` must have the same type (:const:`'d'` 
+    or :const:`'z'`).  On entry, ``B``  contains the righthand side 
+    :math:`B`; on exit it contains the solution :math:`X`.  The optional 
+    argument ``ipiv`` is an integer matrix of length at least :math:`n`.  
+    If ``ipiv`` is provided, then :func:`gesv` solves the system, replaces
+    ``A`` with the triangular factors in an LU factorization, and returns 
+    the permutation matrix in ``ipiv``.  If ``ipiv`` is not specified, 
+    then :func:`gesv` solves the system but does not return the LU 
+    factorization and does not modify ``A``.  
+
+    Raises an :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.lapack.getrf(A, ipiv)
+
+    LU factorization of a general, possibly rectangular, real or
+    complex matrix,  
+ 
+    .. math::
+    
+        A = PLU, 
+
+    where :math:`A` is :math:`m` by :math:`n`.  
+
+    The argument ``ipiv`` is an integer matrix of length at least 
+    min{:math:`m`, :math:`n`}.  On exit, the lower triangular part of 
+    ``A`` is replaced by :math:`L`, the upper triangular part by :math:`U`,
+    and the permutation matrix is returned in ``ipiv``.
+
+    Raises an :exc:`ArithmeticError` if the matrix is not full rank.
+
+
+.. function:: cvxopt.lapack.getrs(A, ipiv, B[, trans = 'N'])
+
+    Solves a general set of linear equations
+
+    .. math::
+     
+        AX & = B  \quad (\mathrm{trans} = \mathrm{'N'}), \\ 
+        A^TX & = B \quad (\mathrm{trans} = \mathrm{'T'}), \\
+        A^HX & = B \quad (\mathrm{trans} = \mathrm{'C'}), 
+    
+    given the LU factorization computed by 
+    :func:`gesv <cvxopt.lapack.gesv>` or 
+    :func:`getrf <cvxopt.lapack.getrf>`.
+
+    On entry, ``A`` and ``ipiv`` must contain the factorization as computed
+    by :func:`gesv` or :func:`getrf`.  On entry, ``B`` contains the 
+    righthand side :math:`B`; on exit it contains the solution :math:`X`.
+    ``B`` must have the same type as ``A``.
+
+
+.. function:: cvxopt.lapack.getri(A, ipiv)
+
+    Computes the inverse of a matrix.  
+
+    On entry, ``A`` and ``ipiv`` must contain the factorization as computed
+    by :func:`gesv <cvxopt.lapack.gesv>` or 
+    :func:`getrf <cvxopt.lapack.getrf>`.  On exit, ``A`` contains the 
+    matrix inverse.
+
+
+In the following example we compute
+
+.. math::
+
+    x = (A^{-1} + A^{-T})b
+
+for randomly generated problem data, factoring the coefficient matrix once.
+
+>>> from cvxopt import matrix, normal
+>>> from cvxopt.lapack import gesv, getrs
+>>> n = 10
+>>> A = normal(n,n)
+>>> b = normal(n)
+>>> ipiv = matrix(0, (n,1))
+>>> x = +b
+>>> gesv(A, x, ipiv)               # x = A^{-1}*b 
+>>> x2 = +b
+>>> getrs(A, ipiv, x2, trans='T')  # x2 = A^{-T}*b
+>>> x += x2
+
+
+Separate functions are provided for equations with band matrices.
+
+.. function:: cvxopt.lapack.gbsv(A, kl, B[, ipiv = None])
+
+    Solves
+
+    .. math::
+
+        A X = B,
+    
+    where :math:`A` and :math:`B` are real or complex matrices, with 
+    :math:`A` :math:`n` by :math:`n` and banded with :math:`k_l` 
+    subdiagonals.  
+
+    The arguments ``A`` and ``B`` must have the same type (:const:`'d'` 
+    or :const:`'z'`).  On entry, ``B`` contains the righthand side 
+    :math:`B`; on exit it contains the solution :math:`X`.  The optional 
+    argument ``ipiv`` is an integer matrix of length at least :math:`n`.  
+    If ``ipiv`` is provided, then ``A`` must have :math:`2k_l + k_u + 1` 
+    rows.  On entry the diagonals of :math:`A` are stored in rows 
+    :math:`k_l + 1` to :math:`2k_l + k_u + 1` of ``A``, using the BLAS 
+    format for general band matrices (see the section 
+    :ref:`s-conventions`).  On exit, the factorization is returned in 
+    ``A`` and ``ipiv``.  If ``ipiv`` is not provided, then ``A`` must have
+    :math:`k_l + k_u + 1` rows.  On entry the diagonals of :math:`A` are 
+    stored in the rows of ``A``, following the standard BLAS format for 
+    general band matrices.  In this case, :func:`gbsv` does not modify 
+    ``A`` and does not return the factorization.
+
+    Raises an :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.lapack.gbtrf(A, m, kl, ipiv)
+
+    LU factorization of a general :math:`m` by :math:`n` real or complex 
+    band matrix with :math:`k_l` subdiagonals.
+
+    The matrix is stored using the BLAS format for general band matrices 
+    (see the section :ref:`s-conventions`), by providing the diagonals 
+    (stored as rows of a :math:`k_u + k_l + 1` by :math:`n` matrix ``A``),
+    the number of rows :math:`m`, and the number of subdiagonals 
+    :math:`k_l`.  The argument ``ipiv`` is an integer matrix of length at 
+    least min{:math:`m`, :math:`n`}.  On exit, ``A`` and ``ipiv`` contain 
+    the details of the factorization.
+
+    Raises an :exc:`ArithmeticError` if the matrix is not full rank.
+
+
+.. function:: cvxopt.lapack.gbtrs({A, kl, ipiv, B[, trans = 'N'])
+
+    Solves a set of linear equations 
+   
+    .. math::
+
+        AX   & = B \quad (\mathrm{trans} = \mathrm{'N'}), \\
+        A^TX & = B \quad (\mathrm{trans} = \mathrm{'T'}), \\
+        A^HX & = B \quad (\mathrm{trans} = \mathrm{'C'}), 
+
+    with :math:`A` a general band matrix with :math:`k_l` subdiagonals, 
+    given the LU factorization computed by 
+    :func:`gbsv <cvxopt.lapack.gbsv>` or 
+    :func:`gbtrf <cvxopt.lapack.gbtrf>`.
+
+    On entry, ``A`` and ``ipiv`` must contain the factorization as computed
+    by :func:`gbsv` or :func:`gbtrf`.  On entry, ``B`` contains the 
+    righthand side :math:`B`; on exit it contains the solution :math:`X`.
+    ``B`` must have the same type as ``A``.
+
+
+As an example, we solve a linear equation with
+
+.. math::
+
+    A = \left[ \begin{array}{cccc}
+        1 & 2 & 0 & 0 \\
+        3 & 4 & 5 & 0 \\
+        6 & 7 & 8 & 9 \\
+        0 & 10 & 11 & 12 
+        \end{array}\right], \qquad  
+    B = \left[\begin{array}{c} 1 \\ 1 \\ 1 \\ 1 \end{array}\right].
+
+>>> from cvxopt import matrix
+>>> from cvxopt.lapack import gbsv, gbtrf, gbtrs
+>>> n, kl, ku = 4, 2, 1
+>>> A = matrix([[0., 1., 3., 6.], [2., 4., 7., 10.], [5., 8., 11., 0.], [9., 12., 0., 0.]])
+>>> x = matrix(1.0, (4,1))
+>>> gbsv(A, kl, x)
+>>> print x
+[ 7.14e-02]
+[ 4.64e-01]
+[-2.14e-01]
+[-1.07e-01]
+
+The code below illustrates how one can reuse the factorization returned
+by :func:`gbsv <cvxopt.lapack.gbsv>`. 
+
+>>> Ac = matrix(0.0, (2*kl+ku+1,n))
+>>> Ac[kl:,:] = A
+>>> ipiv = matrix(0, (n,1))
+>>> x = matrix(1.0, (4,1))
+>>> gbsv(Ac, kl, x, ipiv)                 # solves A*x = 1
+>>> print x
+[ 7.14e-02]
+[ 4.64e-01]
+[-2.14e-01]
+[-1.07e-01]
+>>> x = matrix(1.0, (4,1))
+>>> gbtrs(Ac, kl, ipiv, x, trans='T')     # solve A^T*x = 1
+>>> print x
+[ 7.14e-02]
+[ 2.38e-02]
+[ 1.43e-01]
+[-2.38e-02]
+
+An alternative method uses :func:`gbtrf <cvxopt.lapack.gbtrf>` for the 
+factorization.
+
+>>> Ac[kl:,:] = A
+>>> gbtrf(Ac, n, kl, ipiv)                 
+>>> x = matrix(1.0, (4,1))
+>>> gbtrs(Ac, kl, ipiv, x)                # solve A^T*x = 1
+>>> print x                 
+[ 7.14e-02]
+[ 4.64e-01]
+[-2.14e-01]
+[-1.07e-01]
+>>> x = matrix(1.0, (4,1))
+>>> gbtrs(Ac, kl, ipiv, x, trans='T')     # solve A^T*x = 1
+>>> print x
+[ 7.14e-02]
+[ 2.38e-02]
+[ 1.43e-01]
+[-2.38e-02]
+
+
+The following functions can be used for tridiagonal matrices. They use a 
+simpler matrix format, with the diagonals stored in three separate vectors.
+
+.. function:: cvxopt.lapack.gtsv(dl, d, du, B))
+
+    Solves
+
+    .. math::
+
+        A X = B,
+    
+    where :math:`A` is an :math:`n` by :math:`n` tridiagonal matrix. 
+
+    The subdiagonal of :math:`A` is stored as a matrix ``dl`` of length 
+    :math:`n-1`, the diagonal is stored as a matrix ``d`` of length 
+    :math:`n`, and the superdiagonal is stored as a matrix ``du`` of 
+    length :math:`n-1`.  The four arguments must have the same type 
+    (:const:`'d'` or :const:`'z'`).  On exit ``dl``, ``d``, ``du`` are 
+    overwritten with the details of the LU factorization of :math:`A`. 
+    On entry, ``B`` contains the righthand side :math:`B`; on exit it 
+    contains the solution :math:`X`.
+
+    Raises an :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.lapack.gttrf(dl, d, du, du2, ipiv)
+
+    LU factorization of an :math:`n` by :math:`n` tridiagonal matrix.
+
+    The subdiagonal of :math:`A` is stored as a matrix ``dl`` of length 
+    :math:`n-1`, the diagonal is stored as a matrix ``d`` of length 
+    :math:`n`, and the superdiagonal is stored as a matrix ``du`` of length
+    :math:`n-1`.  ``dl``, ``d`` and ``du`` must have the same type.  
+    ``du2`` is a matrix of length :math:`n-2`, and of the same type as 
+    ``dl``.  ``ipiv`` is an :const:`'i'` matrix of length :math:`n`.
+    On exit, the five arguments contain the details of the factorization.
+
+    Raises an :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.lapack.gttrs(dl, d, du, du2, ipiv, B[, trans = 'N'])
+
+    Solves a set of linear equations 
+
+    .. math:: 
+
+        AX   & = B \quad (\mathrm{trans} = \mathrm{'N'}), \\
+        A^TX & = B \quad (\mathrm{trans} = \mathrm{'T'}), \\
+        A^HX & = B \quad (\mathrm{trans} = \mathrm{'C'}), 
+    
+    where :math:`A` is an :math:`n` by :math:`n` tridiagonal matrix.
+
+    The arguments ``dl``, ``d``, ``du``, ``du2``, and ``ipiv`` contain 
+    the details of the LU factorization as returned by 
+    :func:`gttrf <cvxopt.lapack.gttrf>`.
+    On entry, ``B`` contains the righthand side :math:`B`; on exit it 
+    contains the solution :math:`X`.  ``B`` must have the same type as 
+    the other arguments.
+
+
+Positive Definite Linear Equations
+==================================
+
+.. function:: cvxopt.lapack.posv(A, B[, uplo = 'L'])
+
+    Solves
+
+    .. math:: 
+
+        A X = B,
+
+    where :math:`A` is a real symmetric or complex Hermitian positive 
+    definite matrix.
+
+    On exit, ``B`` is replaced by the solution, and ``A`` is overwritten 
+    with the Cholesky factor.  The matrices ``A`` and ``B`` must have 
+    the same type (:const:`'d'` or :const:`'z'`).
+
+    Raises an :exc:`ArithmeticError` if the matrix is not positive 
+    definite.
+
+
+.. function:: cvxopt.lapack.potrf(A[, uplo = 'L'])
+
+    Cholesky factorization 
+
+    .. math:: 
+
+        A = LL^T \qquad \mbox{or} \qquad A = LL^H
+
+    of a positive definite real symmetric or complex Hermitian matrix 
+    :math:`A`.  
+
+    On exit, the lower triangular part of ``A`` (if ``uplo`` is 
+    :const:`'L'`) or the upper triangular part (if ``uplo`` is 
+    :const:`'U'`) is overwritten with the Cholesky factor or its 
+    (conjugate) transpose.
+
+    Raises an :exc:`ArithmeticError` if the matrix is not positive 
+    definite.
+
+
+.. function:: cvxopt.lapack.potrs(A, B[, uplo = 'L'])
+
+    Solves a set of linear equations
+
+    .. math::
+     
+        AX = B
+
+    with a positive definite real symmetric or complex Hermitian matrix,
+    given the Cholesky factorization computed by 
+    :func:`posv <cvxopt.lapack.posv>` or 
+    :func:`potrf <cvxopt.lapack.potrf>`.
+
+    On entry, ``A`` contains the triangular factor, as computed by 
+    :func:`posv` or :func:`potrf`.  On exit, ``B`` is replaced by the 
+    solution.  ``B`` must have the same type as ``A``.
+
+
+.. function:: cvxopt.lapack.potri(A[, uplo = 'L']) 
+
+    Computes the inverse of a positive definite matrix.
+
+    On entry, ``A`` contains the Cholesky factorization computed by 
+    :func:`potrf <cvxopt.lapack.potri>` or 
+    :func:`posv <cvxopt.lapack.posv>`.  On exit, it contains the matrix 
+    inverse.
+
+
+As an example, we use :func:`posv <cvxopt.lapack.posv>` to solve the 
+linear system
+
+.. math:: 
+    :label: e-kkt-example
+
+    \newcommand{\diag}{\mathop{\bf diag}}
+    \left[ \begin{array}{cc} 
+        -\diag(d)^2  & A \\ A^T  & 0 
+    \end{array} \right]
+    \left[ \begin{array}{c} x_1 \\ x_2 \end{array} \right]
+    = 
+    \left[ \begin{array}{c} b_1 \\ b_2 \end{array} \right]
+
+by block-elimination.  We first pick a random problem.
+
+>>> from cvxopt import matrix, div, normal, uniform
+>>> from cvxopt.blas import syrk, gemv
+>>> from cvxopt.lapack import posv
+>>> m, n = 100, 50  
+>>> A = normal(m,n)
+>>> b1, b2 = normal(m), normal(n)
+>>> d = uniform(m)
+
+We then solve the equations 
+
+.. math::
+
+    \newcommand{\diag}{\mathop{\bf diag}}
+    \begin{split}
+    A^T \diag(d)^{-2}A x_2 & = b_2 + A^T \diag(d)^{-2} b_1 \\
+    \diag(d)^2 x_1 & = Ax_2 - b_1.
+    \end{split}
+
+
+>>> Asc = div(A, d[:, n*[0]])                # Asc := diag(d)^{-1}*A
+>>> B = matrix(0.0, (n,n))
+>>> syrk(Asc, B, trans='T')                  # B := Asc^T * Asc = A^T * diag(d)^{-2} * A
+>>> x1 = div(b1, d)                          # x1 := diag(d)^{-1}*b1
+>>> x2 = +b2
+>>> gemv(Asc, x1, x2, trans='T', beta=1.0)   # x2 := x2 + Asc^T*x1 = b2 + A^T*diag(d)^{-2}*b1 
+>>> posv(B, x2)                              # x2 := B^{-1}*x2 = B^{-1}*(b2 + A^T*diag(d)^{-2}*b1)
+>>> gemv(Asc, x2, x1, beta=-1.0)             # x1 := Asc*x2 - x1 = diag(d)^{-1} * (A*x2 - b1)
+>>> x1 = div(x1, d)                          # x1 := diag(d)^{-1}*x1 = diag(d)^{-2} * (A*x2 - b1)
+
+
+There are separate routines for equations with positive definite band 
+matrices.
+
+.. function:: cvxopt.lapack.pbsv(A, B[, uplo='L'])
+
+    Solves
+
+    .. math::
+
+        AX = B
+
+    where :math:`A` is a real symmetric or complex Hermitian positive 
+    definite band matrix.  
+
+    On entry, the diagonals of :math:`A` are stored in ``A``, using the 
+    BLAS format for symmetric or Hermitian band matrices (see 
+    section :ref:`s-conventions`).  On exit, ``B`` is replaced by the
+    solution, and ``A`` is overwritten with the Cholesky factor (in the
+    BLAS format for triangular band matrices).  The matrices ``A`` and 
+    ``B`` must have the same type (:const:`'d'` or :const:`'z'`).
+
+    Raises an :exc:`ArithmeticError` if the matrix is not positive 
+    definite.
+
+
+.. function:: cvxopt.lapack.pbtrf(A[, uplo = 'L'])
+
+    Cholesky factorization 
+
+    .. math::
+
+        A = LL^T \qquad \mbox{or} \qquad A = LL^H
+
+    of a positive definite real symmetric or complex Hermitian band matrix
+    :math:`A`.  
+
+    On entry, the diagonals of :math:`A` are stored in ``A``, using the 
+    BLAS format for symmetric or Hermitian band matrices.  On exit, ``A`` 
+    contains the Cholesky factor, in the BLAS format for triangular band 
+    matrices.  
+
+    Raises an :exc:`ArithmeticError` if the matrix is not positive 
+    definite.
+
+
+.. function:: cvxopt.lapack.pbtrs(A, B[, uplo = 'L'])
+
+    Solves a set of linear equations
+
+    .. math::
+
+        AX=B
+
+    with a positive definite real symmetric or complex Hermitian band 
+    matrix, given the Cholesky factorization computed by 
+    :func:`pbsv <cvxopt.lapack.pbsv>` or 
+    :func:`pbtrf <cvxopt.lapack.pbtrf>`.  
+
+    On entry, ``A`` contains the triangular factor, as computed by
+    :func:`pbsv` or :func:`pbtrf`.  On exit, ``B`` is replaced by the 
+    solution.  ``B`` must have the same type as ``A``.
+
+
+The following functions are useful for tridiagonal systems.
+
+.. function:: cvxopt.lapack.ptsv(d, e, B)
+
+    Solves
+    
+    .. math::
+
+       A X = B,
+
+    where :math:`A` is an :math:`n` by :math:`n` positive definite real 
+    symmetric or complex Hermitian tridiagonal matrix.  
+
+    The diagonal of :math:`A` is stored as a :const:`'d'` matrix ``d`` of 
+    length :math:`n` and its subdiagonal as a :const:`'d'` or :const:`'z'`
+    matrix ``e`` of length :math:`n-1`.  The arguments ``e`` and ``B`` 
+    must have the same type.  On exit ``d`` contains the diagonal elements
+    of :math:`D` in the 
+    :raw-html:`LDL<sup><small>T</small></sup>`
+    or 
+    :raw-html:`LDL<sup><small>H</small></sup>`
+    factorization of :math:`A`, and 
+    ``e`` contains the subdiagonal elements of the unit lower bidiagonal 
+    matrix :math:`L`.  ``B`` is overwritten with the solution :math:`X`.  
+    Raises an :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.lapack.pttrf(d, e)
+
+    :raw-html:`LDL<sup><small>T</small></sup>`
+    or
+    :raw-html:`LDL<sup><small>H</small></sup>`
+    factorization of an :math:`n` by :math:`n` positive 
+    definite real symmetric or complex Hermitian tridiagonal matrix 
+    :math:`A`.
+
+    On entry, the argument ``d`` is a :const:`'d'` matrix with the diagonal
+    elements of :math:`A`.  The argument ``e`` is :const:`'d'` or 
+    :const:`'z'` matrix containing the subdiagonal of :math:`A`.  On exit 
+    ``d`` contains the diagonal elements of :math:`D`, and ``e`` contains 
+    the subdiagonal elements of the unit lower bidiagonal matrix :math:`L`.
+    
+    Raises an :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.lapack.pttrs(d, e, B[, uplo = 'L'])
+
+    Solves a set of linear equations 
+
+    .. math::
+
+        AX = B 
+
+    where :math:`A` is an :math:`n` by :math:`n` positive definite real 
+    symmetric or complex Hermitian tridiagonal matrix, given its 
+    :raw-html:`LDL<sup><small>T</small></sup>`
+    or
+    :raw-html:`LDL<sup><small>H</small></sup>`
+    factorization.
+
+    The argument ``d`` is the diagonal of the diagonal matrix :math:`D`.
+    The argument ``uplo`` only matters for complex matrices.  If ``uplo`` 
+    is :const:`'L'`, then on exit ``e`` contains the subdiagonal elements 
+    of the unit bidiagonal matrix :math:`L`.  If ``uplo`` is :const:`'U'`,
+    then ``e`` contains the complex conjugates of the elements of the unit
+    bidiagonal matrix :math:`L`.  On exit, ``B`` is overwritten with the 
+    solution :math:`X`.  ``B`` must have the same type as ``e``.
+
+
+Symmetric and Hermitian Linear Equations
+========================================
+
+.. function:: cvxopt.lapack.sysv(A, B[, ipiv = None, uplo = 'L'])
+
+    Solves
+
+    .. math::
+    
+        AX = B
+    
+    where :math:`A` is a real or complex symmetric matrix  of order 
+    :math:`n`.
+
+    On exit, ``B`` is replaced by the solution.  The matrices ``A`` and 
+    ``B`` must have the same type (:const:`'d'` or :const:`'z'`).  The 
+    optional argument ``ipiv`` is an integer matrix of length at least 
+    equal to :math:`n`.  If ``ipiv`` is provided, :func:`sysv` solves the 
+    system and returns the factorization in ``A`` and ``ipiv``.  If 
+    ``ipiv`` is not specified, :func:`sysv` solves the system but does not
+    return the factorization and does not modify ``A``.
+
+    Raises an :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.lapack.sytrf(A, ipiv[, uplo = 'L'])
+
+    :raw-html:`LDL<sup><small>T</small></sup>`
+    factorization 
+
+    .. math:: 
+
+        PAP^T = LDL^T
+
+    of a real or complex symmetric matrix :math:`A` of order :math:`n`.
+
+    ``ipiv`` is an :const:`'i'` matrix of length at least :math:`n`.  On 
+    exit, ``A`` and ``ipiv`` contain the factorization.
+
+    Raises an :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.lapack.sytrs(A, ipiv, B[, uplo = 'L'])
+
+    Solves 
+
+    .. math:: 
+
+        A X = B
+
+    given the 
+    :raw-html:`LDL<sup><small>T</small></sup>`
+    factorization computed by 
+    :func:`sytrf <cvxopt.lapack.sytrf>` or 
+    :func:`sysv <cvxopt.lapack.sysv>`. ``B`` must have the same type as 
+    ``A``.
+
+
+.. function:: cvxopt.lapack.sytri(A, ipiv[, uplo = 'L'])
+
+    Computes the inverse of a real or complex symmetric matrix.
+
+    On entry, ``A`` and ``ipiv`` contain the 
+    :raw-html:`LDL<sup><small>T</small></sup>`
+    factorization computed by :func:`sytrf <cvxopt.lapack.sytrf>` or 
+    :func:`sysv <cvxopt.lapack.sysv>`.  
+    On exit, ``A`` contains the inverse.
+
+
+.. function:: cvxopt.lapack.hesv(A, B[, ipiv = None, uplo = 'L'])
+
+    Solves
+
+    .. math::
+
+        A X = B
+
+    where :math:`A` is a real symmetric or complex Hermitian of order 
+    :math:`n`.
+
+    On exit, ``B`` is replaced by the solution.  The matrices ``A`` and 
+    ``B`` must have the same type (:const:`'d'` or :const:`'z'`).  The 
+    optional argument ``ipiv`` is an integer matrix of length at least 
+    :math:`n`.  If ``ipiv`` is provided, then :func:`hesv` solves the 
+    system and returns the factorization in ``A`` and ``ipiv``.  If 
+    ``ipiv`` is not specified, then :func:`hesv` solves the system but does
+    not return the factorization and does not modify ``A``.
+
+    Raises an :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.lapack.hetrf(A, ipiv[, uplo = 'L'])
+
+    :raw-html:`LDL<sup><small>H</small></sup>`
+    factorization 
+
+    .. math:: 
+
+        PAP^T = LDL^H
+
+    of a real symmetric or complex Hermitian matrix of order :math:`n`.
+    ``ipiv`` is an :const:`'i'` matrix of length at least :math:`n`.  
+    On exit, ``A`` and ``ipiv`` contain the factorization.
+
+    Raises an :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.lapack.hetrs(A, ipiv, B[, uplo = 'L'])
+
+    Solves 
+
+    .. math::
+
+        A X = B
+    
+    given the 
+    :raw-html:`LDL<sup><small>H</small></sup>`
+    factorization computed by 
+    :func:`hetrf <cvxopt.lapack.hetrf>` or 
+    :func:`hesv <cvxopt.lapack.hesv>`.
+
+
+.. function:: cvxopt.lapack.hetri(A, ipiv[, uplo = 'L'])
+
+    Computes the inverse of a real symmetric or complex Hermitian  matrix.
+
+    On entry, ``A`` and ``ipiv`` contain the 
+    :raw-html:`LDL<sup><small>H</small></sup>`
+    factorization computed 
+    by :func:`hetrf <cvxopt.lapack.hetrf>` or 
+    :func:`hesv <cvxopt.lapack.hesv>`.  On exit, ``A`` contains the 
+    inverse.
+
+
+As an example we solve the KKT system :eq:`e-kkt-example`.
+
+>>> from cvxopt.lapack import sysv
+>>> K = matrix(0.0, (m+n,m+n))
+>>> K[: (m+n)*m : m+n+1] = -d**2
+>>> K[:m, m:] = A
+>>> x = matrix(0.0, (m+n,1))
+>>> x[:m], x[m:] = b1, b2
+>>> sysv(K, x, uplo='U')   
+
+
+Triangular Linear Equations
+===========================
+
+.. function:: cvxopt.lapack.trtrs(A, B[, uplo = 'L', trans = 'N', diag = 'N'])
+
+    Solves a triangular set of equations
+
+    .. math::
+
+        AX   & = B \quad (\mathrm{trans} = \mathrm{'N'}), \\
+        A^TX & = B \quad (\mathrm{trans} = \mathrm{'T'}), \\
+        A^HX & = B \quad (\mathrm{trans} = \mathrm{'C'}), 
+
+    where :math:`A` is real or complex and triangular of order :math:`n`, 
+    and :math:`B` is a matrix with :math:`n` rows.  
+
+    ``A`` and ``B`` are matrices with the same type (:const:`'d'` or 
+    :const:`'z'`).  :func:`trtrs` is similar to 
+    :func:`blas.trsm <cvxopt.blas.trsm>`, except 
+    that it raises an :exc:`ArithmeticError` if a diagonal element of ``A``
+    is zero (whereas :func:`blas.trsm` returns :const:`inf` values).
+
+
+.. function:: cvxopt.lapack.trtri(A[, uplo = 'L', diag = 'N'])
+
+    Computes the inverse of a real or complex triangular matrix :math:`A`.  
+    On exit, ``A`` contains the inverse.
+
+
+.. function:: cvxopt.lapack.tbtrs(A, B[, uplo = 'L', trans = 'T', diag = 'N'])
+
+    Solves a triangular set of equations
+
+    .. math:: 
+
+        AX   & = B \quad (\mathrm{trans} = \mathrm{'N'}), \\
+        A^TX & = B \quad (\mathrm{trans} = \mathrm{'T'}), \\
+        A^HX & = B \quad (\mathrm{trans} = \mathrm{'C'}), 
+
+    where :math:`A` is real or complex triangular band matrix of order 
+    :math:`n`, and :math:`B` is a matrix with :math:`n` rows.
+
+    The diagonals of :math:`A` are stored in ``A`` using the BLAS 
+    conventions for triangular band matrices.  ``A`` and ``B`` are 
+    matrices with the same type (:const:`'d'` or :const:`'z'`).  On exit, 
+    ``B`` is replaced by the solution :math:`X`.
+
+
+Least-Squares and Least-Norm Problems
+=====================================
+
+.. function:: cvxopt.lapack.gels(A, B[, trans = 'N'])
+
+    Solves least-squares and least-norm problems with a full rank :math:`m`
+    by :math:`n` matrix :math:`A`.
+
+
+    1. ``trans`` is :const:`'N'`.  If :math:`m` is greater than or equal
+       to :math:`n`, :func:`gels` solves the least-squares problem
+
+       .. math::
+
+           \begin{array}{ll} 
+           \mbox{minimize} & \|AX-B\|_F.
+           \end{array} 
+    
+       If :math:`m` is less than or equal to :math:`n`, :func:`gels` solves
+       the least-norm problem
+
+       .. math::
+
+           \begin{array}{ll} 
+           \mbox{minimize} & \|X\|_F \\
+           \mbox{subject to} & AX = B.
+           \end{array}
+
+    2. ``trans`` is :const:`'T'` or :const:`'C'` and ``A`` and ``B`` are 
+       real.  If :math:`m` is greater than or equal to :math:`n`, 
+       :func:`gels` solves the least-norm problem
+
+       .. math:: 
+    
+           \begin{array}{ll} 
+           \mbox{minimize} & \|X\|_F \\
+           \mbox{subject to} & A^TX=B.
+           \end{array}
+
+       If :math:`m` is less than or equal to :math:`n`, :func:`gels` solves
+       the least-squares problem
+
+       .. math::
+
+           \begin{array}{ll} 
+           \mbox{minimize} & \|A^TX-B\|_F.
+           \end{array}
+    
+    3. ``trans`` is :const:`'C'` and ``A`` and ``B`` are complex. If 
+       :math:`m` is greater than or equal to :math:`n`, :func:`gels` solves
+       the least-norm problem
+   
+       .. math::
+
+           \begin{array}{ll} 
+           \mbox{minimize} & \|X\|_F \\
+           \mbox{subject to} & A^HX=B.
+           \end{array}
+
+       If :math:`m` is less than or equal to :math:`n`, :func:`gels` solves
+       the least-squares problem
+
+       .. math::
+
+           \begin{array}{ll} 
+           \mbox{minimize} & \|A^HX-B\|_F.
+           \end{array}
+
+    ``A`` and ``B`` must have the same typecode (:const:`'d'` or 
+    :const:`'z'`).  ``trans`` = :const:`'T'` is not allowed if ``A`` is 
+    complex.  On exit, the solution :math:`X` is stored as the leading 
+    submatrix of ``B``.  The matrix ``A`` is overwritten with details of 
+    the QR or the LQ factorization of :math:`A`.
+
+    Note that :func:`gels` does not check whether :math:`A` is full rank.
+
+
+The following functions compute QR and LQ factorizations. 
+
+.. function:: cvxopt.lapack.geqrf(A, tau)
+
+    QR factorization of a real or complex matrix ``A``:
+
+    .. math:: 
+
+        A = Q R.
+
+    If :math:`A` is :math:`m` by :math:`n`, then :math:`Q` is :math:`m` by 
+    :math:`m` and orthogonal/unitary, and :math:`R` is :math:`m` by  
+    :math:`n` and upper triangular (if :math:`m` is greater than or equal 
+    to :math:`n`), or upper trapezoidal (if :math:`m` is less than or 
+    equal to :math:`n`).  
+
+    ``tau``  is a matrix of the same type as ``A`` and of length 
+    min{:math:`m`, :math:`n`}.  On exit, :math:`R` is stored in the upper 
+    triangular/trapezoidal part of ``A``.  The matrix :math:`Q` is stored 
+    as a product of min{:math:`m`, :math:`n`} elementary reflectors in 
+    the first min{:math:`m`, :math:`n`} columns of ``A`` and in ``tau``.
+
+
+.. function:: cvxopt.lapack.gelqf(A, tau)
+
+    LQ factorization of a real or complex matrix ``A``:
+  
+    .. math::
+
+        A = L Q.
+
+    If :math:`A` is :math:`m` by :math:`n`, then :math:`Q` is :math:`n` by 
+    :math:`n` and orthogonal/unitary, and :math:`L` is :math:`m` by 
+    :math:`n` and lower triangular (if :math:`m` is less than or equal to 
+    :math:`n`), or lower trapezoidal (if :math:`m` is greater than or equal
+    to :math:`n`).  
+
+    ``tau``  is a matrix of the same type as ``A`` and of length 
+    min{:math:`m`, :math:`n`}.  On exit, :math:`L` is stored in the lower 
+    triangular/trapezoidal part of ``A``.  The matrix :math:`Q` is stored 
+    as a product of min{:math:`m`, :math:`n`} elementary reflectors in the
+    first min{:math:`m`, :math:`n`} rows of ``A`` and in ``tau``.
+
+
+.. function:: cvxopt.lapack.geqp3(A, jpvt, tau)
+
+    QR factorization with column pivoting of a real or complex matrix 
+    :math:`A`:
+
+    .. math:: 
+
+        A P = Q R.
+
+    If :math:`A` is :math:`m` by :math:`n`, then :math:`Q` is :math:`m` 
+    by :math:`m` and orthogonal/unitary, and :math:`R` is :math:`m` by 
+    :math:`n` and upper triangular (if :math:`m` is greater than or equal 
+    to :math:`n`), or upper trapezoidal (if :math:`m` is less than or equal
+    to :math:`n`).  
+
+    ``tau`` is a matrix of the same type as ``A`` and of length 
+    min{:math:`m`, :math:`n`}.  ``jpvt`` is an integer matrix of 
+    length :math:`n`.  On entry, if ``jpvt[k]`` is nonzero, then 
+    column :math:`k` of :math:`A` is permuted to the front of :math:`AP`.
+    Otherwise, column :math:`k` is a free column.
+
+    On exit, ``jpvt`` contains the permutation :math:`P`:  the operation 
+    :math:`AP` is equivalent to ``A[:, jpvt-1]``.  :math:`R` is stored
+    in the upper triangular/trapezoidal part of ``A``.  The matrix 
+    :math:`Q` is stored as a product of min{:math:`m`, :math:`n`} 
+    elementary reflectors in the first min{:math:`m`,:math:`n`} columns 
+    of ``A`` and in ``tau``.
+
+
+In most applications, the matrix :math:`Q` is not needed explicitly, and
+it is sufficient to be able to make products with :math:`Q` or its 
+transpose.  The functions :func:`unmqr <cvxopt.lapack.unmqr>` and 
+:func:`ormqr <cvxopt.lapack.ormqr>` multiply a matrix
+with the orthogonal matrix computed by 
+:func:`geqrf <cvxopt.lapack.geqrf>`.
+
+.. function:: cvxopt.lapack.unmqr(A, tau, C[, side = 'L', trans = 'N'])
+
+    Product with a real orthogonal or complex unitary matrix:
+
+    .. math::
+
+        \newcommand{\op}{\mathop{\mathrm{op}}}
+        \begin{split}
+        C & := \op(Q)C \quad (\mathrm{side} = \mathrm{'L'}), \\
+        C & := C\op(Q) \quad (\mathrm{side} = \mathrm{'R'}), \\
+        \end{split}
+
+    where
+
+    .. math::
+
+        \newcommand{\op}{\mathop{\mathrm{op}}}
+        \op(Q) =  \left\{ \begin{array}{ll}
+            Q & \mathrm{trans} = \mathrm{'N'} \\
+            Q^T & \mathrm{trans} = \mathrm{'T'} \\
+            Q^H & \mathrm{trans} = \mathrm{'C'}.
+        \end{array}\right.
+
+    If ``A`` is :math:`m` by :math:`n`, then :math:`Q` is square of order 
+    :math:`m` and orthogonal or unitary.  :math:`Q` is stored in the first
+    min{:math:`m`, :math:`n`} columns of ``A`` and in ``tau`` as a 
+    product of min{:math:`m`, :math:`n`} elementary reflectors, as 
+    computed by :func:`geqrf <cvxopt.lapack.geqrf>`.  
+    The matrices ``A``, ``tau``, and ``C`` 
+    must have the same type.  ``trans`` = :const:`'T'` is only allowed if 
+    the typecode is :const:`'d'`.
+
+
+.. function:: cvxopt.lapack.ormqr(A, tau, C[, side = 'L', trans = 'N'])
+
+    Identical to :func:`unmqr <cvxopt.lapack.unmqr>` but works only for 
+    real matrices, and the 
+    possible values of ``trans`` are :const:`'N'` and :const:`'T'`.
+
+
+As an example, we solve a least-squares problem by a direct call to 
+:func:`gels <cvxopt.lapack.gels>`, and by separate calls to 
+:func:`geqrf <cvxopt.lapack.geqrf>`, 
+:func:`ormqr <cvxopt.lapack.ormqr>`, and 
+:func:`trtrs <cvxopt.lapack.trtrs>`.
+
+>>> from cvxopt import blas, lapack, matrix, normal
+>>> m, n = 10, 5
+>>> A, b = normal(m,n), normal(m,1)
+>>> x1 = +b
+>>> lapack.gels(+A, x1)                  # x1[:n] minimizes || A*x - b ||_2
+>>> tau = matrix(0.0, (n,1)) 
+>>> lapack.geqrf(A, tau)                 # A = [Q1, Q2] * [R1; 0]
+>>> x2 = +b
+>>> lapack.ormqr(A, tau, x2, trans='T')  # x2 := [Q1, Q2]' * x2
+>>> lapack.trtrs(A[:n,:], x2, uplo='U')  # x2[:n] := R1^{-1} * x2[:n]
+>>> blas.nrm2(x1[:n] - x2[:n])
+3.0050798580569307e-16
+
+
+The next two functions make products with the orthogonal matrix computed 
+by :func:`gelqf <cvxopt.lapack.gelqf>`.
+
+.. function:: cvxopt.lapack.unmlq(A, tau, C[, side = 'L', trans = 'N'])
+
+    Product with a real orthogonal or complex unitary matrix:
+
+    .. math::
+
+        \newcommand{\op}{\mathop{\mathrm{op}}}
+        \begin{split}
+        C & := \op(Q)C \quad (\mathrm{side} = \mathrm{'L'}), \\
+        C & := C\op(Q) \quad (\mathrm{side} = \mathrm{'R'}), \\
+        \end{split}
+
+    where
+
+    .. math::
+        \newcommand{\op}{\mathop{\mathrm{op}}}
+            \op(Q) =  \left\{ \begin{array}{ll}
+                Q & \mathrm{trans} = \mathrm{'N'}, \\
+                Q^T & \mathrm{trans} = \mathrm{'T'}, \\
+                Q^H & \mathrm{trans} = \mathrm{'C'}.
+            \end{array}\right.
+
+    If ``A`` is :math:`m` by :math:`n`, then :math:`Q` is square of order 
+    :math:`n` and orthogonal or unitary.  :math:`Q` is stored in the first
+    min{:math:`m`, :math:`n`} rows of ``A`` and in ``tau`` as a product of
+    min{:math:`m`, :math:`n`} elementary reflectors, as computed by  
+    :func:`gelqf <cvxopt.lapack.gelqf>`.  
+    The matrices ``A``, ``tau``, and ``C`` must have the 
+    same type.  ``trans`` = :const:`'T'` is only allowed if the typecode 
+    is :const:`'d'`.
+
+
+.. function:: cvxopt.lapack.ormlq(A, tau, C[, side = 'L', trans = 'N'])
+
+    Identical to :func:`unmlq <cvxopt.lapack.unmlq>` but works only for 
+    real matrices, and the 
+    possible values of ``trans`` or :const:`'N'` and :const:`'T'`.
+
+
+As an example, we solve a least-norm problem by a direct call to 
+:func:`gels <cvxopt.lapack.gels>`, and by separate calls to 
+:func:`gelqf <cvxopt.lapack.gelqf>`, 
+:func:`ormlq <cvxopt.lapack.ormlq>`, 
+and :func:`trtrs <cvxopt.lapack.trtrs>`.
+
+>>> from cvxopt import blas, lapack, matrix, normal
+>>> m, n = 5, 10
+>>> A, b = normal(m,n), normal(m,1)
+>>> x1 = matrix(0.0, (n,1))
+>>> x1[:m] = b
+>>> lapack.gels(+A, x1)                  # x1 minimizes ||x||_2 subject to A*x = b
+>>> tau = matrix(0.0, (m,1)) 
+>>> lapack.gelqf(A, tau)                 # A = [L1, 0] * [Q1; Q2] 
+>>> x2 = matrix(0.0, (n,1))
+>>> x2[:m] = b                           # x2 = [b; 0]
+>>> lapack.trtrs(A[:,:m], x2)            # x2[:m] := L1^{-1} * x2[:m]
+>>> lapack.ormlq(A, tau, x2, trans='T')  # x2 := [Q1, Q2]' * x2
+>>> blas.nrm2(x1 - x2)
+0.0
+
+
+Finally, if the matrix :math:`Q` is needed explicitly, it can be generated
+from the output of :func:`geqrf <cvxopt.lapack.geqrf>` and 
+:func:`gelqf <cvxopt.lapack.gelqf>` using one of the following functions.
+
+.. function:: cvxopt.lapack.ungqr(A, tau)
+
+    If ``A`` has size :math:`m` by :math:`n`, and ``tau`` has length 
+    :math:`k`, then, on entry, the first ``k`` columns of the matrix ``A`` 
+    and the entries of ``tau`` contai an unitary or orthogonal matrix
+    :math:`Q` of order :math:`m`, as computed by 
+    :func:`geqrf <cvxopt.lapack.geqrf>`.  On exit, 
+    the first min{:math:`m`, :math:`n`} columns of :math:`Q` are contained
+    in the leading columns of ``A``.
+
+
+.. function:: cvxopt.lapack.orgqr(A, tau)
+
+    Identical to :func:`ungqr <cvxopt.lapack.ungqr>` but works only for 
+    real matrices.
+
+
+.. function:: cvxopt.lapack.unglq(A, tau)
+
+    If ``A`` has size :math:`m` by :math:`n`, and ``tau`` has length 
+    :math:`k`, then, on entry, the first ``k`` rows of the matrix ``A`` 
+    and the entries of ``tau`` contain a unitary or orthogonal matrix
+    :math:`Q` of order :math:`n`, as computed by 
+    :func:`gelqf <cvxopt.lapack.gelqf>`.  
+    On exit, the first min{:math:`m`, :math:`n`} rows of :math:`Q` are 
+    contained in the leading rows of ``A``.
+
+
+.. function:: cvxopt.lapack.orglq(A, tau)
+
+    Identical to :func:`unglq <cvxopt.lapack.unglq>` but works only for 
+    real matrices.
+
+
+We illustrate this with the QR factorization of the matrix
+
+.. math::
+    A = \left[\begin{array}{rrr}
+        6 & -5 & 4 \\ 6 & 3 & -4 \\ 19 & -2 & 7 \\ 6 & -10 & -5 
+        \end{array} \right]
+      = \left[\begin{array}{cc}
+        Q_1 & Q_2 \end{array}\right]
+        \left[\begin{array}{c} R \\ 0 \end{array}\right]. 
+
+>>> from cvxopt import matrix, lapack
+>>> A = matrix([ [6., 6., 19., 6.], [-5., 3., -2., -10.], [4., -4., 7., -5] ])
+>>> m, n = A.size
+>>> tau = matrix(0.0, (n,1))
+>>> lapack.geqrf(A, tau)
+>>> print A[:n, :]              # Upper triangular part is R.
+[-2.17e+01  5.08e+00 -4.76e+00]
+[ 2.17e-01 -1.06e+01 -2.66e+00]
+[ 6.87e-01  3.12e-01 -8.74e+00]
+>>> Q1 = +A
+>>> lapack.orgqr(Q1, tau)
+>>> print Q1
+[-2.77e-01  3.39e-01 -4.10e-01]
+[-2.77e-01 -4.16e-01  7.35e-01]
+[-8.77e-01 -2.32e-01 -2.53e-01]
+[-2.77e-01  8.11e-01  4.76e-01]
+>>> Q = matrix(0.0, (m,m))
+>>> Q[:, :n] = A
+>>> lapack.orgqr(Q, tau)
+>>> print Q                     # Q = [ Q1, Q2]
+[-2.77e-01  3.39e-01 -4.10e-01 -8.00e-01]
+[-2.77e-01 -4.16e-01  7.35e-01 -4.58e-01]
+[-8.77e-01 -2.32e-01 -2.53e-01  3.35e-01]
+[-2.77e-01  8.11e-01  4.76e-01  1.96e-01]
+
+
+The orthogonal matrix in the factorization
+
+.. math::
+
+    A = \left[ \begin{array}{rrrr}
+        3 & -16 & -10 & -1 \\
+       -2 & -12 &  -3 &  4 \\
+        9 &  19 &   6 & -6  
+        \end{array}\right]
+      = Q \left[\begin{array}{cc} R_1 & R_2 \end{array}\right]
+
+can be generated as follows.
+
+>>> A = matrix([ [3., -2., 9.], [-16., -12., 19.], [-10., -3., 6.], [-1., 4., -6.] ])
+>>> m, n = A.size
+>>> tau = matrix(0.0, (m,1))
+>>> lapack.geqrf(A, tau)
+>>> R = +A
+>>> print R                     # Upper trapezoidal part is [R1, R2].
+[-9.70e+00 -1.52e+01 -3.09e+00  6.70e+00]
+[-1.58e-01  2.30e+01  1.14e+01 -1.92e+00]
+[ 7.09e-01 -5.57e-01  2.26e+00  2.09e+00]
+>>> lapack.orgqr(A, tau)
+>>> print A[:, :m]              # Q is in the first m columns of A.
+[-3.09e-01 -8.98e-01 -3.13e-01]
+[ 2.06e-01 -3.85e-01  9.00e-01]
+[-9.28e-01  2.14e-01  3.04e-01]
+
+
+Symmetric and Hermitian Eigenvalue Decomposition
+================================================
+
+The first four routines compute all or selected  eigenvalues and 
+eigenvectors of a real symmetric matrix :math:`A`:
+
+.. math::
+
+    \newcommand{\diag}{\mathop{\bf diag}}
+    A = V\diag(\lambda)V^T,\qquad  V^TV = I.
+
+.. function:: cvxopt.lapack.syev(A, W[, jobz = 'N', uplo = 'L'])
+
+    Eigenvalue decomposition of a real symmetric matrix of order :math:`n`.
+
+    ``W`` is a real matrix of length at least :math:`n`.  On exit, ``W`` 
+    contains the eigenvalues in ascending order.  If ``jobz`` is 
+    :const:`'V'`, the eigenvectors are also computed and returned in ``A``.
+    If ``jobz`` is :const:`'N'`, the eigenvectors are not returned and the 
+    contents of ``A`` are destroyed.
+
+    Raises an :exc:`ArithmeticError` if the eigenvalue decomposition fails.
+
+
+.. function:: cvxopt.lapack.syevd(A, W[, jobz = 'N', uplo = 'L'])
+
+    This is an alternative to :func:`syev <cvxopt.lapack.syev>`, based 
+    on a different
+    algorithm.  It is faster on large problems, but also uses more memory.
+
+
+.. function:: cvxopt.lapack.syevx(A, W[, jobz = 'N', range = 'A', uplo = 'L', vl = 0.0, vu = 0.0, il = 1, iu = 1, Z = None])
+
+    Computes selected eigenvalues and eigenvectors of a real symmetric 
+    matrix of order :math:`n`.
+
+    ``W`` is a real matrix of length at least :math:`n`.  On exit, ``W``  
+    contains the eigenvalues in ascending order.  If ``range`` is 
+    :const:`'A'`, all the eigenvalues are computed.  If ``range`` is 
+    :const:`'I'`, eigenvalues :math:`i_l` through :math:`i_u` are 
+    computed, where :math:`1 \leq i_l \leq i_u \leq n`.  If ``range`` is 
+    :const:`'V'`, the eigenvalues in the interval :math:`(v_l, v_u]` are 
+    computed. 
+
+    If ``jobz`` is :const:`'V'`, the (normalized) eigenvectors are 
+    computed, and returned in ``Z``.  If ``jobz`` is :const:`'N'`, the 
+    eigenvectors are not computed.  In both cases, the contents of ``A`` 
+    are destroyed on exit.
+
+    ``Z`` is optional (and not referenced) if ``jobz`` is :const:`'N'`.
+    It is required if ``jobz`` is :const:`'V'` and must have at least
+    :math:`n` columns if ``range`` is :const:`'A'` or :const:`'V'` and  at
+    least :math:`i_u - i_l + 1` columns if ``range`` is :const:`'I'`.
+
+    :func:`syevx` returns the number of computed eigenvalues.
+
+
+.. function:: cvxopt.lapack.syevr(A, W[, jobz = 'N', range = 'A', uplo = 'L', vl = 0.0, vu = 0.0, il = 1, iu = n, Z =  None])
+
+    This is an alternative to :func:`syevx <cvxopt.lapack.syevr>`.  
+    :func:`syevr` is the most 
+    recent LAPACK routine for symmetric eigenvalue problems, and expected 
+    to supersede the three other routines in future releases.
+
+
+The next four routines can be used to compute eigenvalues and eigenvectors 
+for complex Hermitian matrices:
+
+.. math::
+
+    \newcommand{\diag}{\mathop{\bf diag}}
+    A = V\diag(\lambda)V^H,\qquad  V^HV = I.
+
+For real symmetric matrices they are identical to the corresponding
+:func:`syev*` routines.
+
+.. function:: cvxopt.lapack.heev(A, W[, jobz = 'N', uplo = 'L'])
+
+    Eigenvalue decomposition of a real symmetric or complex Hermitian
+    matrix of order :math:`n`.
+
+    The calling sequence is identical to 
+    :func:`syev <cvxopt.lapack.syev>`,
+    except that ``A`` can be real or complex.
+
+
+.. function:: cvxopt.lapack.heevd(A, W[, jobz = 'N'[, uplo = 'L']])
+
+    This is an alternative to :func:`heev <cvxopt.lapack.heevd>`. 
+
+
+.. function:: cvxopt.lapack.heevx(A, W[, jobz = 'N', range = 'A', uplo = 'L', vl = 0.0, vu = 0.0, il = 1, iu = n, Z = None])
+
+    Computes selected eigenvalues and eigenvectors of a real symmetric 
+    or complex Hermitian matrix.
+
+    The calling sequence is identical to 
+    :func:`syevx <cvxopt.lapack.syevx>`, except that ``A`` 
+    can be real or complex.  ``Z`` must have the same type as ``A``.
+
+
+.. function:: cvxopt.lapack.heevr(A, W[, jobz = 'N', range = 'A', uplo = 'L', vl = 0.0, vu = 0.0, il = 1, iu = n, Z = None])
+
+    This is an alternative to :func:`heevx <cvxopt.lapack.heevx>`. 
+
+
+Generalized Symmetric Definite Eigenproblems
+============================================
+
+Three types of generalized eigenvalue problems can be solved:
+
+.. math:: 
+    :label: e-gevd
+
+    \newcommand{\diag}{\mathop{\bf diag}}
+    \begin{split}
+        AZ  & = BZ\diag(\lambda)\quad \mbox{(type 1)}, \\
+        ABZ & = Z\diag(\lambda) \quad \mbox{(type 2)}, \\
+        BAZ & = Z\diag(\lambda) \quad \mbox{(type 3)}, 
+    \end{split}
+
+with :math:`A` and :math:`B` real symmetric or complex Hermitian, and 
+:math:`B` is positive definite.  The matrix of eigenvectors is normalized 
+as follows:
+
+.. math::
+
+    Z^H BZ = I \quad \mbox{(types 1 and 2)}, \qquad 
+    Z^H B^{-1}Z = I \quad \mbox{(type 3)}.
+
+.. function:: cvxopt.lapack.sygv(A, B, W[, itype = 1, jobz = 'N', uplo = 'L'])
+
+    Solves the generalized eigenproblem :eq:`e-gevd` for real symmetric 
+    matrices of order :math:`n`, stored in real matrices ``A`` and ``B``.
+    ``itype`` is an integer with possible values 1, 2, 3, and specifies
+    the type of eigenproblem.  ``W`` is a real matrix of length at least 
+    :math:`n`.  On exit, it contains the eigenvalues in ascending order.
+    On exit, ``B`` contains the Cholesky factor of :math:`B`.  If ``jobz``
+    is :const:`'V'`, the eigenvectors are computed and returned in ``A``.
+    If ``jobz`` is :const:`'N'`, the eigenvectors are not returned and the 
+    contents of ``A`` are destroyed.
+
+
+.. function:: cvxopt.lapack.hegv(A, B, W[, itype = 1, jobz = 'N', uplo = 'L'])
+
+    Generalized eigenvalue problem :eq:`e-gevd` of real symmetric or 
+    complex Hermitian matrix of order :math:`n`.  The calling sequence is 
+    identical to :func:`sygv <cvxopt.lapack.sygv>`, except that 
+    ``A`` and ``B`` can be real or complex.
+
+
+
+Singular Value Decomposition
+============================
+
+.. function:: cvxopt.lapack.gesvd(A, S[, jobu = 'N', jobvt = 'N', U = None, Vt = None])
+
+    Singular value decomposition 
+    
+    .. math::
+
+        A = U \Sigma V^T, \qquad A = U \Sigma V^H
+
+    of a real or complex :math:`m` by :math:`n` matrix :math:`A`.
+
+    ``S`` is a real matrix of length at least min{:math:`m`, :math:`n`}.
+    On exit, its first  min{:math:`m`, :math:`n`} elements are the 
+    singular values in descending order.
+
+    The argument ``jobu`` controls how many left singular vectors are
+    computed.  The possible values are :const:`'N'`, :const:`'A'`, 
+    :const:`'S'` and :const:`'O'`.  If ``jobu`` is :const:`'N'`, no left 
+    singular vectors are computed.  If ``jobu`` is :const:`'A'`, all left  
+    singular vectors are computed and returned as columns of ``U``.
+    If ``jobu`` is :const:`'S'`, the first min{:math:`m`, :math:`n`} left 
+    singular vectors are computed and returned as columns of ``U``.
+    If ``jobu`` is :const:`'O'`, the first min{:math:`m`, :math:`n`} left 
+    singular vectors are computed and returned as columns of ``A``.
+    The argument ``U`` is \None\ (if ``jobu`` is :const:`'N'`
+    or :const:`'A'`) or a matrix of the same type as ``A``.
+
+    The argument ``jobvt`` controls how many right singular vectors are
+    computed.  The possible values are :const:`'N'`, :const:`'A'`, 
+    :const:`'S'` and :const:`'O'`.  If ``jobvt`` is :const:`'N'`, no right
+    singular vectors are computed.  If ``jobvt`` is :const:`'A'`, all right
+    singular vectors are computed and returned as rows of ``Vt``.
+    If ``jobvt`` is :const:`'S'`, the first min{:math:`m`, :math:`n`} 
+    right singular vectors are computed and their (conjugate) transposes 
+    are returned as rows of ``Vt``.  If ``jobvt`` is :const:`'O'`, the 
+    first min{:math:`m`, :math:`n`} right singular vectors are computed 
+    and their (conjugate) transposes are returned as rows of ``A``.
+    Note that the (conjugate) transposes of the right singular vectors 
+    (i.e., the matrix :math:`V^H`) are returned in ``Vt`` or ``A``.
+    The argument ``Vt`` can be :const:`None` (if ``jobvt`` is :const:`'N'`
+    or :const:`'A'`) or a matrix of the same type as ``A``.
+
+    On exit, the contents of ``A`` are destroyed.
+
+
+.. function:: cvxopt.lapack.gesdd(A, S[, jobz = 'N', U = None, Vt = None])
+
+    Singular value decomposition of a real or complex :math:`m` by 
+    :math:`n` matrix..  This function is based on a divide-and-conquer 
+    algorithm and is faster than :func:`gesvd <cvxopt.lapack.gesdd>`.
+
+    ``S`` is a real matrix of length at least min{:math:`m`, :math:`n`}.
+    On exit, its first min{:math:`m`, :math:`n`} elements are the 
+    singular values in descending order.
+
+    The argument ``jobz`` controls how many singular vectors are computed.
+    The possible values are :const:`'N'`, :const:`'A'`, :const:`'S'` and 
+    :const:`'O'`.  If ``jobz`` is :const:`'N'`, no singular vectors are 
+    computed.  If ``jobz`` is :const:`'A'`, all :math:`m` left singular 
+    vectors are computed and returned as columns of ``U`` and all 
+    :math:`n` right singular vectors are computed and returned as rows of 
+    ``Vt``.  If ``jobz`` is :const:`'S'`, the first 
+    min{:math:`m`, :math:`n`} left and right singular vectors are computed
+    and returned as columns of ``U`` and rows of ``Vt``.
+    If ``jobz`` is :const:`'O'` and :math:`m` is greater than or equal
+    to :math:`n`, the first :math:`n` left singular vectors are returned as
+    columns of ``A`` and the :math:`n` right singular vectors are returned
+    as rows of ``Vt``.  If ``jobz`` is :const:`'O'` and :math:`m` is less 
+    than :math:`n`, the :math:`m` left singular vectors are returned as 
+    columns of ``U`` and the first :math:`m` right singular vectors are 
+    returned as rows of ``A``.  Note that the (conjugate) transposes of 
+    the right singular vectors are returned in ``Vt`` or ``A``.
+
+    The argument ``U`` can be :const:`None` (if ``jobz`` is :const:`'N'`
+    or :const:`'A'` of ``jobz`` is :const:`'O'` and :math:`m` is greater 
+    than or equal to  :math:`n`)  or a matrix of the same type as ``A``.
+    The argument ``Vt`` can be \None\ (if ``jobz`` is :const:`'N'`
+    or :const:`'A'` or ``jobz`` is :const:`'O'` and :math`m` is less than
+    :math:`n`) or a matrix of the same type as ``A``.
+
+    On exit, the contents of ``A`` are destroyed.
+
+
+Schur and Generalized Schur Factorization
+=========================================
+
+.. function:: cvxopt.lapack.gees(A[, w = None, V = None, select = None])
+
+    Computes the Schur factorization 
+
+    .. math::
+
+        A = V S V^T \quad \mbox{($A$ real)}, \qquad 
+        A = V S V^H \quad \mbox{($A$ complex)}
+
+    of a real or complex :math:`n` by :math:`n` matrix :math:`A`.  
+
+    If :math:`A` is real, the matrix of Schur vectors :math:`V` is 
+    orthogonal, and :math:`S` is a real upper quasi-triangular matrix with
+    1 by 1 or 2 by 2 diagonal blocks.  The 2 by 2 blocks correspond to 
+    complex conjugate pairs of eigenvalues of :math:`A`.
+    If :math:`A` is complex, the matrix of Schur vectors :math:`V` is 
+    unitary, and :math:`S` is a complex upper triangular matrix with the 
+    eigenvalues of :math:`A` on the diagonal.
+
+    The optional argument ``w`` is a complex matrix of length at least 
+    :math:`n`.  If it is provided, the eigenvalues of ``A`` are returned 
+    in ``w``.  The optional argument ``V`` is an :math:`n` by :math:`n` 
+    matrix of the same type as ``A``.  If it is provided, then the Schur 
+    vectors are returned in ``V``.
+
+    The argument ``select`` is an optional ordering routine.  It must be a
+    Python function that can be called as ``f(s)`` with a complex 
+    argument ``s``, and returns :const:`True` or :const:`False`.  The 
+    eigenvalues for which ``select`` returns :const:`True` will be selected
+    to appear first along the diagonal.  (In the real Schur factorization,
+    if either one of a complex conjugate pair of eigenvalues is selected, 
+    then both are selected.)
+
+    On exit, ``A`` is replaced with the matrix :math:`S`.  The function 
+    :func:`gees` returns an integer equal to the number of eigenvalues 
+    that were selected by the ordering routine.  If ``select`` is 
+    :const:`None`, then :func:`gees` returns 0.
+
+
+As an example we compute the complex Schur form of the matrix
+
+.. math::
+
+    A = \left[\begin{array}{rrrrr}
+        -7 &  -11 & -6  & -4 &  11 \\
+         5 &  -3  &  3  & -12 & 0 \\
+        11 &  11  & -5  & -14 & 9 \\
+        -4 &   8  &  0  &  8 &  6 \\
+        13 & -19  & -12 & -8 & 10 
+        \end{array}\right].
+
+
+>>> A = matrix([[-7., 5., 11., -4., 13.], [-11., -3., 11., 8., -19.], [-6., 3., -5., 0., -12.], 
+                [-4., -12., -14., 8., -8.], [11., 0., 9., 6., 10.]])
+>>> S = matrix(A, tc='z')
+>>> w = matrix(0.0, (5,1), 'z')
+>>> lapack.gees(S, w)
+0
+>>> print S
+[ 5.67e+00+j1.69e+01 -2.13e+01+j2.85e+00  1.40e+00+j5.88e+00 -4.19e+00+j2.05e-01  3.19e+00-j1.01e+01]
+[ 0.00e+00-j0.00e+00  5.67e+00-j1.69e+01  1.09e+01+j5.93e-01 -3.29e+00-j1.26e+00 -1.26e+01+j7.80e+00]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  1.27e+01+j3.43e-17 -6.83e+00+j2.18e+00  5.31e+00-j1.69e+00]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00 -1.31e+01-j0.00e+00 -2.60e-01-j0.00e+00]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00 -7.86e+00-j0.00e+00]
+>>> print w
+[ 5.67e+00+j1.69e+01]
+[ 5.67e+00-j1.69e+01]
+[ 1.27e+01+j3.43e-17]
+[-1.31e+01-j0.00e+00]
+[-7.86e+00-j0.00e+00]
+
+An ordered Schur factorization with the eigenvalues in the left half of 
+the complex plane ordered first, can be computed as follows. 
+
+>>> S = matrix(A, tc='z')
+>>> def F(x): return (x.real < 0.0)
+...
+>>> lapack.gees(S, w, select = F)
+2
+>>> print S
+[-1.31e+01-j0.00e+00 -1.72e-01+j7.93e-02 -2.81e+00+j1.46e+00  3.79e+00-j2.67e-01  5.14e+00-j4.84e+00]
+[ 0.00e+00-j0.00e+00 -7.86e+00-j0.00e+00 -1.43e+01+j8.31e+00  5.17e+00+j8.79e+00  2.35e+00-j7.86e-01]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  5.67e+00+j1.69e+01 -1.71e+01-j1.41e+01  1.83e+00-j4.63e+00]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  5.67e+00-j1.69e+01 -8.75e+00+j2.88e+00]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  1.27e+01+j3.43e-17]
+>>> print w
+[-1.31e+01-j0.00e+00]
+[-7.86e+00-j0.00e+00]
+[ 5.67e+00+j1.69e+01]
+[ 5.67e+00-j1.69e+01]
+[ 1.27e+01+j3.43e-17]
+
+
+.. function:: cvxopt.lapack.gges(A, B[, a = None, b = None, Vl = None, Vr = None, select = None])
+     
+    Computes the generalized Schur factorization 
+
+    .. math::
+
+        A = V_l S V_r^T, \quad B = V_l T V_r^T \quad 
+            \mbox{($A$ and $B$ real)}, 
+     
+        A = V_l S V_r^H, \quad B = V_l T V_r^H, \quad 
+            \mbox{($A$ and $B$ complex)}
+
+    of a pair of real or complex :math:`n` by :math:`n` matrices 
+    :math:`A`, :math:`B`.  
+
+    If :math:`A` and :math:`B` are real, then the matrices of left and 
+    right Schur vectors :math:`V_l` and :math:`V_r` are orthogonal, 
+    :math:`S` is a real upper quasi-triangular matrix with 1 by 1 or 2 by 
+    2 diagonal blocks, and :math:`T` is a real triangular matrix with 
+    nonnegative diagonal.  The 2 by 2 blocks along the diagonal of 
+    :math:`S` correspond to complex conjugate pairs of generalized 
+    eigenvalues of :math:`A`, :math:`B`.  If :math:`A` and :math:`B` are 
+    complex, the matrices of left and right Schur vectors :math:`V_l` and 
+    :math:`V_r` are unitary, :math:`S` is complex upper triangular, and 
+    :math:`T` is complex upper triangular with nonnegative real diagonal.  
+
+    The optional arguments ``a`` and ``b`` are :const:`'z'` and 
+    :const:`'d'` matrices of length at least :math:`n`.  If these are 
+    provided, the generalized eigenvalues of ``A``, ``B`` are returned in 
+    ``a`` and ``b``.  (The generalized eigenvalues are the ratios 
+    ``a[k] / b[k]``.)  The optional arguments ``Vl`` and ``Vr`` are 
+    :math:`n` by :math:`n` matrices of the same type as ``A`` and ``B``.   
+    If they are provided, then the left Schur vectors are returned in 
+    ``Vl`` and the right Schur vectors are returned in ``Vr``.
+
+    The argument ``select`` is an optional ordering routine.  It must be 
+    a Python function that can be called as ``f(x,y)`` with a complex 
+    argument ``x`` and a real argument ``y``, and returns :const:`True` or
+    :const:`False`.  The eigenvalues for which ``select`` returns 
+    :const:`True` will be selected to appear first on the diagonal.
+    (In the real Schur factorization, if either one of a complex conjugate
+    pair of eigenvalues is selected, then both are selected.)
+
+    On exit, ``A`` is replaced with the matrix :math:`S` and ``B`` is 
+    replaced with the matrix :math:`T`.  The function :func:`gges` returns
+    an integer equal to the number of eigenvalues that were selected by 
+    the ordering routine.  If ``select`` is :const:`None`, then 
+    :func:`gges` returns 0.
+
+
+As an example, we compute the generalized complex Schur form of the 
+matrix :math:`A` of the previous example, and 
+
+.. math::
+
+    B = \left[\begin{array}{ccccc}
+        1 & 0 & 0 & 0 & 0 \\
+        0 & 1 & 0 & 0 & 0 \\
+        0 & 0 & 1 & 0 & 0 \\
+        0 & 0 & 0 & 1 & 0 \\
+        0 & 0 & 0 & 0 & 0 
+        \end{array}\right].
+
+
+>>> A = matrix([[-7., 5., 11., -4., 13.], [-11., -3., 11., 8., -19.], [-6., 3., -5., 0., -12.], 
+                [-4., -12., -14., 8., -8.], [11., 0., 9., 6., 10.]])
+>>> B = matrix(0.0, (5,5))
+>>> B[:19:6] = 1.0
+>>> S = matrix(A, tc='z')
+>>> T = matrix(B, tc='z')
+>>> a = matrix(0.0, (5,1), 'z')
+>>> b = matrix(0.0, (5,1))
+>>> lapack.gges(S, T, a, b)
+0
+>>> print S
+[ 6.64e+00-j8.87e+00 -7.81e+00-j7.53e+00  6.16e+00-j8.51e-01  1.18e+00+j9.17e+00  5.88e+00-j4.51e+00]
+[ 0.00e+00-j0.00e+00  8.48e+00+j1.13e+01 -2.12e-01+j1.00e+01  5.68e+00+j2.40e+00 -2.47e+00+j9.38e+00]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00 -1.39e+01-j0.00e+00  6.78e+00-j0.00e+00  1.09e+01-j0.00e+00]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00 -6.62e+00-j0.00e+00 -2.28e-01-j0.00e+00]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00 -2.89e+01-j0.00e+00]
+>>> print T
+[ 6.46e-01-j0.00e+00  4.29e-01-j4.79e-02  2.02e-01-j3.71e-01  1.08e-01-j1.98e-01 -1.95e-01+j3.58e-01]
+[ 0.00e+00-j0.00e+00  8.25e-01-j0.00e+00 -2.17e-01+j3.11e-01 -1.16e-01+j1.67e-01  2.10e-01-j3.01e-01]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  7.41e-01-j0.00e+00 -3.25e-01-j0.00e+00  5.87e-01-j0.00e+00]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  8.75e-01-j0.00e+00  4.84e-01-j0.00e+00]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00  0.00e+00-j0.00e+00]
+>>> print a
+[ 6.64e+00-j8.87e+00]
+[ 8.48e+00+j1.13e+01]
+[-1.39e+01-j0.00e+00]
+[-6.62e+00-j0.00e+00]
+[-2.89e+01-j0.00e+00]
+>>> print b
+[ 6.46e-01]
+[ 8.25e-01]
+[ 7.41e-01]
+[ 8.75e-01]
+[ 0.00e+00]
+
+
+
+Example: Analytic Centering
+===========================
+
+The analytic centering problem is defined as
+
+.. math::
+
+    \begin{array}{ll}
+        \mbox{minimize} & -\sum\limits_{i=1}^m \log(b_i-a_i^Tx).
+    \end{array}
+
+
+In the code below we solve the problem using Newton's method.  At each 
+iteration the Newton direction is computed by solving a positive definite 
+set of linear equations
+
+.. math::
+
+    \newcommand{\diag}{\mathop{\bf diag}}
+    \newcommand{\ones}{\mathbf 1}
+    A^T \diag(b-Ax)^{-2} A v = -\diag(b-Ax)^{-1}\ones
+
+(where :math:`A` has rows :math:`a_i^T`), and a suitable step size is 
+determined by a backtracking line search.
+
+We use the level-3 BLAS function :func:`blas.syrk <cvxopt.blas.syrk>` to 
+form the Hessian 
+matrix and the LAPACK function :func:`posv <cvxopt.lapack.posv>` to 
+solve the Newton system.  
+The code can be further optimized by replacing the matrix-vector products 
+with the level-2 BLAS function :func:`blas.gemv <cvxopt.blas.gemv>`.
+
+::
+
+    from cvxopt import matrix, log, mul, div, blas, lapack 
+    from math import sqrt
+
+    def acent(A,b):
+        """  
+        Returns the analytic center of A*x <= b.
+        We assume that b > 0 and the feasible set is bounded.
+        """
+
+        MAXITERS = 100
+        ALPHA = 0.01
+        BETA = 0.5
+        TOL = 1e-8
+
+        m, n = A.size
+        x = matrix(0.0, (n,1))
+        H = matrix(0.0, (n,n))
+
+        for iter in xrange(MAXITERS):
+            
+            # Gradient is g = A^T * (1./(b-A*x)).
+            d = (b - A*x)**-1
+            g = A.T * d
+
+            # Hessian is H = A^T * diag(d)^2 * A.
+            Asc = mul( d[:,n*[0]], A )
+            blas.syrk(Asc, H, trans='T')
+
+            # Newton step is v = -H^-1 * g.
+            v = -g
+            lapack.posv(H, v)
+
+            # Terminate if Newton decrement is less than TOL.
+            lam = blas.dot(g, v)
+            if sqrt(-lam) < TOL: return x
+
+            # Backtracking line search.
+            y = mul(A*v, d)
+            step = 1.0
+            while 1-step*max(y) < 0: step *= BETA 
+            while True:
+                if -sum(log(1-step*y)) < ALPHA*step*lam: break
+                step *= BETA
+            x += step*v
diff --git a/doc/source/matrices.rst b/doc/source/matrices.rst
new file mode 100644
index 0000000..08e10bf
--- /dev/null
+++ b/doc/source/matrices.rst
@@ -0,0 +1,1198 @@
+.. _c-matrices: 
+
+*************************
+Dense and Sparse Matrices
+*************************
+
+This chapter describes the two CVXOPT matrix types: 
+:class:`matrix <cvxopt.matrix>` objects, used for dense matrix 
+computations, and :class:`spmatrix <cvxopt.spmatrix>` objects, used for 
+sparse matrix computations.
+
+
+.. _s-dense-matrices:
+
+Dense Matrices 
+==============
+
+A dense matrix is created by calling the function :func:`matrix`.  The 
+arguments specify the values of the coefficients, the dimensions, and the 
+type (integer, double, or complex) of the matrix.
+
+.. function:: cvxopt.matrix(x[, size[, tc]])
+
+   ``size``  is a tuple of length two with the matrix dimensions.
+   The number of rows and/or the number of columns can be zero.
+
+   ``tc``  stands for type code. The possible values are :const:`'i'`, 
+   :const:`'d'`, and :const:`'z'`, for integer, real (double), and complex 
+   matrices, respectively.  
+
+   ``x``  can be a number, a sequence of numbers, a dense or sparse 
+   matrix, a one- or two-dimensional NumPy array, or a list of lists of 
+   matrices and numbers.  
+
+   * If ``x`` is a number (Python integer, float, or complex number), 
+     a matrix is created with the dimensions specified by ``size`` and 
+     with all the coefficients equal to ``x``.  
+     The default value of ``size``  is ``(1,1)``, and the default value
+     of ``tc`` is the type of ``x``.
+     If necessary, the type of ``x`` is converted (from integer to double
+     when used to create a matrix of type :const:`'d'`, and from integer or
+     double to complex when used to create a matrix of type :const:`'z'`).
+
+     >>> from cvxopt import matrix
+     >>> A = matrix(1, (1,4))   
+     >>> print A
+     [ 1  1  1  1]
+     >>> A = matrix(1.0, (1,4))   
+     >>> print A
+     [ 1.00e+00  1.00e+00  1.00e+00  1.00e+00]
+     >>> A = matrix(1+1j)     
+     >>> print A
+     [ 1.00e+00+j1.00e+00]
+
+   * If ``x`` is a sequence of numbers (list, tuple, array array, 
+     xrange object, one-dimensional NumPy array, ...),
+     then the numbers are interpreted as the coefficients of a matrix in 
+     column-major order.  The length of ``x``  must be equal to the 
+     product of ``size[0]`` and ``size[1]``.
+     If ``size``  is not specified, a matrix with one column is created. 
+     If ``tc``  is not specified, it is determined from the elements of 
+     ``x``  (and if that is impossible, for example because ``x``  is
+     an empty list, a value :const:`'i'` is used).  
+     Type conversion takes place as for scalar ``x``.
+
+     The following example shows several ways to define the same integer 
+     matrix.
+
+     >>> A = matrix([0, 1, 2, 3], (2,2))  
+     >>> A = matrix((0, 1, 2, 3), (2,2))  
+     >>> A = matrix(xrange(4), (2,2))
+     >>> from array import array
+     >>> A = matrix(array('i', [0,1,2,3]), (2,2))
+     >>> print A
+     [ 0  2]
+     [ 1  3]
+
+   * If ``x``  is a dense or sparse matrix, or a two-dimensional NumPy 
+     array of type :const:`'i'`, :const:`'d'`, or :const:`'z'`, then the  
+     coefficients of ``x``  are copied, in column-major order, to a new 
+     matrix of the given size.  
+     The total number of elements in the new matrix (the product of 
+     ``size[0]`` and ``size[1]``) must be the same as the product 
+     of  the dimensions of ``x``.  If ``size``  is not specified, the 
+     dimensions of ``x``  are used.  
+     The default value of ``tc``  is the type of ``x``. 
+     Type conversion takes place when the type of ``x`` differs from 
+     ``tc``, in a similar way as for scalar ``x``.  
+     
+     >>> A = matrix([1., 2., 3., 4., 5., 6.], (2,3))  
+     >>> print A
+     [ 1.00e+00  3.00e+00  5.00e+00]
+     [ 2.00e+00  4.00e+00  6.00e+00]
+     >>> B = matrix(A, (3,2))  
+     >>> print B
+     [ 1.00e+00  4.00e+00]
+     [ 2.00e+00  5.00e+00]
+     [ 3.00e+00  6.00e+00]
+     >>> C = matrix(B, tc='z')      
+     >>> print C
+     [ 1.00e+00-j0.00e+00  4.00e+00-j0.00e+00]
+     [ 2.00e+00-j0.00e+00  5.00e+00-j0.00e+00]
+     [ 3.00e+00-j0.00e+00  6.00e+00-j0.00e+00]
+     >>> from numpy import array
+     >>> x = array([[1., 2., 3.], [4., 5., 6.]])
+     >>> x
+     array([[ 1.  2.  3.]
+            [ 4.  5.  6.]])
+     >>> print matrix(x)
+     [ 1.00e+00  2.00e+00  3.00e+00]
+     [ 4.00e+00  5.00e+00  6.00e+00]
+     
+   * If ``x`` is a list of lists of dense or sparse matrices 
+     and numbers (Python integer, float, or complex), 
+     then each element of ``x`` is interpreted as a 
+     block-column stored in column-major order. 
+     If ``size`` is not specified, the block-columns are juxtaposed
+     to obtain a matrix with ``len(x)``  block-columns.
+     If ``size`` is specified, then the matrix with ``len(x)``
+     block-columns is resized by copying its elements in column-major 
+     order into a matrix of the dimensions given by ``size``.  
+     If ``tc`` is not specified, it is determined from the elements of 
+     ``x`` (and if that is impossible, for example because ``x`` is
+     a list of empty lists, a value :const:`'i'` is used).  
+     The same rules for type conversion apply as for scalar ``x``.
+     
+     >>> print matrix([[1., 2.], [3., 4.], [5., 6.]])
+     [ 1.00e+00  3.00e+00  5.00e+00]
+     [ 2.00e+00  4.00e+00  6.00e+00]
+     >>> A1 = matrix([1, 2], (2,1))
+     >>> B1 = matrix([6, 7, 8, 9, 10, 11], (2,3))
+     >>> B2 = matrix([12, 13, 14, 15, 16, 17], (2,3))
+     >>> B3 = matrix([18, 19, 20], (1,3))
+     >>> C = matrix([[A1, 3.0, 4.0, 5.0], [B1, B2, B3]])
+     >>> print C
+     [ 1.00e+00  6.00e+00  8.00e+00  1.00e+01]
+     [ 2.00e+00  7.00e+00  9.00e+00  1.10e+01]
+     [ 3.00e+00  1.20e+01  1.40e+01  1.60e+01]
+     [ 4.00e+00  1.30e+01  1.50e+01  1.70e+01]
+     [ 5.00e+00  1.80e+01  1.90e+01  2.00e+01]
+
+     A matrix with a single block-column can be represented by a single 
+     list (i.e., if ``x`` is a list of lists, and has length one, 
+     then the argument ``x`` can be replaced by ``x[0]``).
+
+     >>> D = matrix([B1, B2, B3])
+     >>> print D
+     [  6   8  10]
+     [  7   9  11]
+     [ 12  14  16]
+     [ 13  15  17]
+     [ 18  19  20]
+
+
+.. _s-sparse-matrices:
+
+Sparse Matrices
+===============
+
+A general :class:`spmatrix <cvxopt.spmatrix>` object can be thought of as 
+a *triplet description* of a sparse matrix, i.e., a list of entries of the
+matrix, with for each entry the value, row index, and column index.  
+Entries that are not included in the list are assumed to be zero.  
+For example, the sparse matrix
+
+.. math:: 
+
+    A = \left[ \begin{array}{rrrrr}
+        0 & 2 & 0 & 0 & 3 \\
+        2 & 0 & 0 & 0 & 0 \\
+       -1 & -2 & 0 & 4 & 0 \\
+        0 & 0 & 1 & 0 & 0 \end{array} \right]
+
+has the triplet description 
+
+.. math::
+
+    (2,1,0), \qquad (-1,2,0), \qquad (2,0,1), \qquad (-2,2,1), \qquad
+    (1,3,2), \qquad (4,2,3), \qquad (3,0,4).
+
+The list may include entries with a zero value, so triplet descriptions 
+are not necessarily unique.  The list
+
+.. math::
+
+    (2,1,0), \qquad (-1,2,0), \qquad (0,3,0), \qquad (2,0,1), \qquad 
+    (-2,2,1), \qquad (1,3,2), \qquad (4,2,3), \qquad (3,0,4)
+
+is another triplet description of the same matrix.
+
+An :class:`spmatrix` object corresponds to a particular 
+triplet description of a sparse matrix.  We will refer to the entries in
+the triplet description as the *nonzero entries* of the object, 
+even though they may have a numerical value zero.
+
+Three functions are provided to create sparse matrices. 
+The first, :func:`spmatrix`, 
+constructs a sparse matrix from a triplet description. 
+
+.. function:: cvxopt.spmatrix(x, I, J[, size[, tc]])
+
+    ``I`` and ``J`` are sequences of integers (lists, tuples, 
+    :mod:`array` arrays, xrange objects, ...) or integer matrices 
+    (:class:`matrix <cvxopt.matrix>` objects with typecode :const:`'i'`),  
+    containing the 
+    row and column indices of the nonzero entries.  
+    The lengths of ``I`` and ``J`` must be  equal.  If they are matrices, 
+    they are treated as lists of indices stored in column-major order, 
+    i.e., as lists ``list(I)``, respectively, ``list(J)``. 
+    
+    ``size`` is a tuple of nonnegative integers with the row and column 
+    dimensions of the matrix.
+    The ``size`` argument is only needed when creating a matrix with 
+    a zero last row or last column.  If ``size`` is not specified, it 
+    is determined from ``I`` and ``J``:
+    the default value for ``size[0]`` is ``max(I)+1`` if ``I`` is 
+    nonempty and zero otherwise.  
+    The default value for ``size[1]`` is ``max(J)+1`` if ``J`` is 
+    nonempty and zero otherwise.
+    
+    ``tc`` is the typecode, :const:`'d'` or :const:`'z'`, for double and 
+    complex matrices, respectively.   Integer sparse matrices are 
+    not implemented.
+    
+    ``x`` can be a number, a sequence of numbers, or a dense matrix.  
+    This argument specifies the numerical values of the nonzero entries.
+    
+    - If ``x`` is a number (Python integer, float, or complex), 
+      a matrix is created with the sparsity pattern defined by ``I`` and 
+      ``J``, and nonzero entries initialized to the value of ``x``.  
+      The default value of ``tc`` is :const:`'d'` if ``x`` is integer or 
+      float, and :const:`'z'` if ``x``  is complex.  
+      
+      The following code creates a 4 by 4 sparse identity matrix.
+        
+      >>> from cvxopt import spmatrix
+      >>> A = spmatrix(1.0, range(4), range(4))
+      >>> print A  
+         [ 1.00e+00     0         0         0    ]
+         [    0      1.00e+00     0         0    ]
+         [    0         0      1.00e+00     0    ]
+         [    0         0         0      1.00e+00]
+        
+        
+    - If ``x`` is a sequence of numbers, a sparse matrix is created 
+      with the entries of ``x`` copied to the entries indexed by ``I`` 
+      and ``J``.  The list ``x`` must have the same length as ``I`` and 
+      ``J``.
+      The default value of ``tc`` is determined from the elements of ``x``:
+      :const:`'d'` if ``x`` contains integers and floating-point numbers or
+      if ``x`` is an empty list, and :const:`'z'` if ``x`` contains at 
+      least one complex number.
+      
+      >>> A = spmatrix([2,-1,2,-2,1,4,3], [1,2,0,2,3,2,0], [0,0,1,1,2,3,4])
+      >>> print A 
+        [    0      2.00e+00     0         0      3.00e+00]
+        [ 2.00e+00     0         0         0         0    ]
+        [-1.00e+00 -2.00e+00     0      4.00e+00     0    ]
+        [    0         0      1.00e+00     0         0    ]
+        
+        
+    - If ``x`` is a dense matrix, a sparse matrix is created with 
+      all the entries of ``x`` copied, in column-major order, to the 
+      entries indexed by ``I`` and ``J``.
+      The matrix ``x`` must have the same length as ``I`` and ``J``.
+      The default value of ``tc`` is :const:`'d'` if ``x`` is an 
+      :const:`'i'` or :const:`'d'` matrix, and :const:`'z'` otherwise.  
+      If ``I`` and ``J`` contain repeated entries, the corresponding 
+      values of the coefficients are added.
+
+
+The function :func:`sparse` constructs a sparse matrix 
+from a block-matrix description.
+   
+.. function:: cvxopt.sparse(x[, tc])
+
+    ``tc`` is the typecode, :const:`'d'` or :const:`'z'`, for double and 
+    complex matrices, respectively.
+  
+    ``x`` can be a :class:`matrix`, :class:`spmatrix`, or a list of lists 
+    of matrices (:class:`matrix` or :class:`spmatrix` objects) and 
+    numbers (Python integer, float, or complex). 
+    
+    * If ``x`` is a :class:`matrix` or :class:`spmatrix` object, then a 
+      sparse matrix of the same size and the same numerical value is 
+      created.  Numerical zeros in ``x`` are treated as structural zeros 
+      and removed from the triplet description of the new sparse matrix.
+    
+    * If ``x`` is a list of lists of matrices (:class:`matrix` or 
+      :class:`spmatrix` objects) and numbers (Python integer, float, or 
+      complex) then each element of ``x`` is interpreted as a 
+      (block-)column matrix stored in colum-major order, and a
+      block-matrix is constructed by juxtaposing the ``len(x)``
+      block-columns (as in :func:`matrix <cvxopt.matrix>`).
+      Numerical zeros are removed from the triplet description of the new 
+      matrix.  
+    
+    >>> from cvxopt import matrix, spmatrix, sparse
+    >>> A = matrix([[1., 2., 0.], [2., 1., 2.], [0., 2., 1.]])
+    >>> print A
+    [ 1.00e+00  2.00e+00  0.00e+00]
+    [ 2.00e+00  1.00e+00  2.00e+00]
+    [ 0.00e+00  2.00e+00  1.00e+00]
+    >>> B = spmatrix([], [], [], (3,3))
+    >>> print B
+    [0 0 0]
+    [0 0 0]
+    [0 0 0]
+    >>> C = spmatrix([3, 4, 5], [0, 1, 2], [0, 1, 2])
+    >>> print C
+    [ 3.00e+00     0         0    ]
+    [    0      4.00e+00     0    ]
+    [    0         0      5.00e+00]
+    >>> D = sparse([[A, B], [B, C]])
+    >>> print D
+    [ 1.00e+00  2.00e+00     0         0         0         0    ]
+    [ 2.00e+00  1.00e+00  2.00e+00     0         0         0    ]
+    [    0      2.00e+00  1.00e+00     0         0         0    ]
+    [    0         0         0      3.00e+00     0         0    ]
+    [    0         0         0         0      4.00e+00     0    ]
+    [    0         0         0         0         0      5.00e+00]
+    
+    A matrix with a single block-column can be represented by a single 
+    list.
+    
+    >>> D = sparse([A, C])
+    >>> print D
+    [ 1.00e+00  2.00e+00     0    ]
+    [ 2.00e+00  1.00e+00  2.00e+00]
+    [    0      2.00e+00  1.00e+00]
+    [ 3.00e+00     0         0    ]
+    [    0      4.00e+00     0    ]
+    [    0         0      5.00e+00]
+    
+    
+The function :func:`spdiag` constructs a block-diagonal 
+sparse matrix from a list of matrices.
+
+.. function:: cvxopt.spdiag(x)
+
+    ``x`` is a dense or sparse matrix with a single row or column, or a 
+    list of square dense or sparse matrices or scalars.  
+    If ``x`` is a matrix, a sparse diagonal matrix is returned with 
+    the entries of ``x`` on its diagonal.
+    If ``x`` is list, a sparse block-diagonal matrix is returned with
+    the elements in the list as its diagonal blocks.
+      
+    >>> from cvxopt import matrix, spmatrix, spdiag
+    >>> A = 3.0
+    >>> B = matrix([[1,-2],[-2,1]])
+    >>> C = spmatrix([1,1,1,1,1],[0,1,2,0,0,],[0,0,0,1,2])
+    >>> D = spdiag([A, B, C])
+    >>> print D
+    [ 3.00e+00     0         0         0         0         0    ]
+    [    0      1.00e+00 -2.00e+00     0         0         0    ]
+    [    0     -2.00e+00  1.00e+00     0         0         0    ]
+    [    0         0         0      1.00e+00  1.00e+00  1.00e+00]
+    [    0         0         0      1.00e+00     0         0    ]
+    [    0         0         0      1.00e+00     0         0    ]
+    
+    
+
+.. _s-arithmetic:
+
+Arithmetic Operations 
+=====================
+
+The following table lists the arithmetic operations defined for dense and 
+sparse matrices.  In the table ``A`` and ``B`` are dense or sparse 
+matrices of compatible dimensions, ``c``  is a scalar (a Python number or 
+a dense 1 by 1 matrix), ``D`` is a dense matrix, and ``e`` is a Python 
+number.
+
++------------------------------------+-------------------------+
+| Unary plus/minus                   | ``+A, -A``              |
++------------------------------------+-------------------------+
+| Addition                           | ``A + B, A + c, c + A`` |
++------------------------------------+-------------------------+
+| Subtraction                        | ``A - B, A - c, c - A`` |
++------------------------------------+-------------------------+ 
+| Matrix multiplication              | ``A * B``               |
++------------------------------------+-------------------------+
+| Scalar multiplication and division | ``c * A, A * c, A / c`` |
++------------------------------------+-------------------------+    
+| Remainder after division           | ``D % c``               |
++------------------------------------+-------------------------+
+| Elementwise exponentiation         | ``D**e``                |
++------------------------------------+-------------------------+
+
+If one of the operands is integer (a scalar integer or a matrix of type
+:const:`'i'`) and the other operand is double (a scalar float or a matrix 
+of type :const:`'d'`), then the integer operand is converted to double, 
+and the result is a matrix of type :const:`'d'`.
+If one of the operands is integer or double, and the other operand is 
+complex (a scalar complex or a matrix of type :const:`'z'`), then the first 
+operand is converted to complex, and the result is a matrix of type 
+:const:`'z'`.  (An exception to this rule is elementwise exponentiation:
+the result of ``D**e`` is a real matrix if ``D`` and ``e`` are integer.)
+
+Addition, subtraction, and matrix multiplication with two matrix operands 
+result in a sparse matrix if both matrices are sparse, and in a dense 
+matrix otherwise.  The result of a scalar multiplication or division is 
+dense if ``A`` is dense, and sparse if ``A`` is sparse.  Postmultiplying 
+a matrix with a number ``c`` means the same as premultiplying, i.e., 
+scalar multiplication.  Dividing a matrix by ``c`` means dividing all its 
+entries by ``c``.  
+
+If ``c`` in the expressions ``A+c``, ``c+A``, ``A-c``, ``c-A`` is a number,
+then it is interpreted as a dense matrix with 
+the same dimensions as ``A``, type given by the type of ``c``, and all 
+its entries equal to ``c``.  If ``c``  is a 1 by 1 dense matrix and ``A`` 
+is not 1 by 1, then ``c`` is interpreted as a dense matrix with the same 
+size of ``A`` and all entries equal to ``c[0]``.
+
+If ``c`` is a 1 by 1 dense matrix, then, if possible, the products 
+``c*A`` and ``A*c`` are interpreted as matrix-matrix products.
+If the product cannot be interpreted as a matrix-matrix product
+(because the dimensions of ``A`` are incompatible), then the product is 
+interpreted as the scalar multiplication with ``c[0]``.
+The division ``A/c`` and remainder ``A%c`` with ``c`` a 
+1 by 1 matrix are always interpreted as ``A/c[0]``, resp., ``A%c[0]``.
+
+Note that Python rounds the result of an integer division towards minus 
+infinity.
+
+The following in-place operations are also defined, but only if they do 
+not change the type (sparse or dense, integer, real, or complex) of the 
+matrix ``A``.  These in-place operations do not return a new matrix but 
+modify the existing object ``A``.
+
++---------------------------------------------+--------------------+
+| In-place addition                           | ``A += B, A += c`` |
++---------------------------------------------+--------------------+
+| In-place subtraction                        | ``A -= B, A -= c`` |
++---------------------------------------------+--------------------+
+| In-place scalar multiplication and division | ``A *= c, A /= c`` |
++---------------------------------------------+--------------------+
+| In-place remainder                          | ``A %= c``         |
++---------------------------------------------+--------------------+
+
+For example, if ``A`` has typecode :const:`'i'`, then ``A += B`` is 
+allowed if ``B`` has typecode :const:`'i'`.  It is not allowed if ``B`` 
+has typecode :const:`'d'` or :const:`'z'` because the addition 
+``A+B`` results in a :const:`'d'` or :const:`'z'` matrix and 
+therefore cannot be assigned to ``A`` without changing its type.  
+As another example, if ``A`` is a sparse matrix, then ``A += 1.0`` is 
+not allowed because the operation ``A = A + 1.0`` results in a dense 
+matrix, so it cannot be assigned to ``A`` without changing its type.
+
+In-place matrix-matrix products are not allowed.  (Except when ``c`` is 
+a 1 by 1 dense matrix, in which case ``A *= c`` is interpreted as the 
+scalar product ``A *= c[0]``.)
+
+In-place remainder is only defined for dense ``A``.
+
+It is important to know when a matrix operation creates a new object.  
+The following rules apply.
+
+* A simple assignment (``A = B``) is given the standard Python 
+  interpretation, i.e., it assigns to the variable ``A`` a reference (or 
+  pointer) to the object referenced by ``B``.
+
+  >>> B = matrix([[1.,2.], [3.,4.]])  
+  >>> print B
+  [ 1.00e+00  3.00e+00]
+  [ 2.00e+00  4.00e+00]
+  >>> A = B
+  >>> A[0,0] = -1 
+  >>> print B   # modifying A[0,0] also modified B[0,0]
+  [-1.00e+00  3.00e+00]
+  [ 2.00e+00  4.00e+00]
+  
+* The regular (i.e., not in-place) arithmetic operations always return 
+  new objects.   
+  
+  >>> B = matrix([[1.,2.], [3.,4.]])  
+  >>> A = +B
+  >>> A[0,0] = -1 
+  >>> print B   # modifying A[0,0] does not modify B[0,0]
+  [ 1.00e+00  3.00e+00]
+  [ 2.00e+00  4.00e+00]
+  
+* The in-place operations directly modify the coefficients of the 
+  existing matrix object and do not create a new object. 
+  
+  >>> B = matrix([[1.,2.], [3.,4.]])  
+  >>> A = B
+  >>> A *= 2
+  >>> print B   # in-place operation also changed B
+  [ 2.00e+00  6.00e+00]
+  [ 4.00e+00  8.00e+00]
+  >>> A = 2*A
+  >>> print B   # regular operation creates a new A, so does not change B
+  [ 2.00e+00  6.00e+00]
+  [ 4.00e+00  8.00e+00]
+  
+  
+.. _s-indexing:
+
+Indexing and Slicing
+====================
+
+Matrices can be indexed using one or two arguments.  In single-argument
+indexing of a matrix ``A``, the index runs from ``-len(A)`` to 
+``len(A)-1``, and is interpreted as an index in the one-dimensional 
+array of coefficients of ``A`` in column-major order.   Negative indices 
+have the standard Python interpretation: for negative ``k``, 
+``A[k]`` is the same element as ``A[len(A) + k]``.
+
+Four different types of one-argument indexing are implemented.
+
+1. The index can be a single integer.  
+   This returns a number, e.g., ``A[0]`` is the first element of ``A``.
+
+2. The index can be an integer matrix.  This returns a column matrix: the 
+   command ``A[matrix([0,1,2,3])]`` returns the 4 by 1 matrix 
+   consisting of the first four elements of ``A``.  The size of the index 
+   matrix is ignored: ``A[matrix([0,1,2,3], (2,2))]`` returns the same 
+   4 by 1 matrix.
+
+3. The index can be a list of integers.  This returns a column matrix, 
+   e.g., ``A[[0,1,2,3]]`` is the 4 by 1 matrix consisting of elements 
+   0, 1, 2, 3 of ``A``.   
+
+4. The index can be a Python slice.  This returns a matrix with one column
+   (possibly 0 by 1, or 1 by 1).  For example, ``A[::2]`` is the column
+   matrix defined by taking every other element of ``A``, stored in 
+   column-major order.  ``A[0:0]`` is a matrix with size (0,1).
+
+Thus, single-argument indexing returns a scalar (if the index is an 
+integer), or a matrix with one column.  This is consistent with the 
+interpretation that single-argument indexing accesses the matrix in 
+column-major order.
+
+Note that an index list or an index matrix are equivalent, but they are 
+both useful, especially when we perform operations on index sets.  For 
+example, if ``I`` and ``J`` are lists then ``I+J`` is the 
+concatenated list, and ``2*I`` is ``I`` repeated twice.  If they 
+are matrices, these operations are interpreted as arithmetic operations.
+For large index sets, indexing with integer matrices is also faster 
+than indexing with lists. 
+
+The following example illustrates one-argument indexing.
+
+>>> from cvxopt import matrix, spmatrix
+>>> A = matrix(range(16), (4,4), 'd')
+>>> print A
+[ 0.00e+00  4.00e+00  8.00e+00  1.20e+01]
+[ 1.00e+00  5.00e+00  9.00e+00  1.30e+01]
+[ 2.00e+00  6.00e+00  1.00e+01  1.40e+01]
+[ 3.00e+00  7.00e+00  1.10e+01  1.50e+01]
+>>> A[4]
+4.0
+>>> I = matrix([0, 5, 10, 15])
+>>> print A[I]      # the diagonal
+[ 0.00e+00]
+[ 5.00e+00]
+[ 1.00e+01]
+[ 1.50e+01]
+>>> I = [0,2];  J = [1,3]
+>>> print A[2*I+J]  # duplicate I and append J
+[ 0.00e+00]
+[ 2.00e+00]
+[ 0.00e+00]
+[ 2.00e+00]
+[ 1.00e+00]
+[ 3.00e+00]
+>>> I = matrix([0, 2]);  J =  matrix([1, 3])
+>>> print A[2*I+J]  # multiply I by 2 and add J
+[ 1.00e+00]
+[ 7.00e+00]
+>>> print A[4::4]   # get every fourth element skipping the first four  
+[ 4.00e+00]
+[ 8.00e+00]
+[ 1.20e+01]
+
+In two-argument indexing the arguments can be any combinations of the
+four types listed above.  The first argument indexes the rows of 
+the matrix and the second argument indexes the columns.  If both 
+indices are scalars, then a scalar is returned.  In all other cases, 
+a matrix is returned.  We continue the example.
+
+>>> print A[:,1]
+[ 4.00e+00]
+[ 5.00e+00]
+[ 6.00e+00]
+[ 7.00e+00]
+>>> J = matrix([0, 2])
+>>> print A[J,J]
+[ 0.00e+00  8.00e+00]
+[ 2.00e+00  1.00e+01]
+>>> print A[:2, -2:]   
+[ 8.00e+00  1.20e+01]
+[ 9.00e+00  1.30e+01]
+>>> A = spmatrix([0,2,-1,2,-2,1], [0,1,2,0,2,1], [0,0,0,1,1,2]) 
+>>> print A[:, [0,1]]
+[ 0.00e+00  2.00e+00]
+[ 2.00e+00     0    ]
+[-1.00e+00 -2.00e+00]
+>>> B = spmatrix([0,2*1j,0,-2], [1,2,1,2], [0,0,1,1,])
+>>> print B[-2:,-2:]
+[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00]
+[ 0.00e+00+j2.00e+00 -2.00e+00-j0.00e+00]
+
+Expressions of the form ``A[I]`` or ``A[I,J]`` can also appear on 
+the lefthand side of an assignment.   The righthand side must be a scalar 
+(i.e., a number or a 1 by 1 dense matrix), a sequence of numbers, or a 
+dense or sparse matrix.  If the righthand side is a scalar, it is 
+interpreted as a dense matrix with identical entries and the dimensions of
+the lefthand side.  If the righthand side is a sequence of numbers (list, 
+tuple, :mod:`array` array, xrange object, ...) its values are interpreted 
+as the coefficients of a dense matrix in column-major order.  If the 
+righthand side is a matrix (:class:`matrix` or 
+:class:`spmatrix`), it must 
+have the same size as the lefthand side.  Sparse matrices are 
+converted to dense in the assignment to a dense matrix.
+
+Indexed assignments are only allowed if they do not change the type of 
+the matrix.  For example, if ``A`` is a matrix with type :const:`'d'`, 
+then ``A[I] = B`` is only permitted if ``B`` is an integer, a float, 
+or a matrix of type :const:`'i'` or :const:`'d'`.  If ``A`` is an integer 
+matrix, then ``A[I] = B`` is only permitted if ``B`` is an integer or 
+an integer matrix.
+
+The following examples illustrate indexed assignment.
+
+>>> A = matrix(range(16), (4,4))
+>>> A[::2,::2] = matrix([[-1, -2], [-3, -4]])
+>>> print A
+[ -1   4  -3  12]
+[  1   5   9  13]
+[ -2   6  -4  14]
+[  3   7  11  15]
+>>> A[::5] += 1
+>>> print A
+[  0   4  -3  12]
+[  1   6   9  13]
+[ -2   6  -3  14]
+[  3   7  11  16]
+>>> A[0,:] = -1, 1, -1, 1
+>>> print A
+[ -1   1  -1   1]
+[  1   6   9  13]
+[ -2   6  -3  14]
+[  3   7  11  16]
+>>> A[2:,2:] = xrange(4)
+>>> print A
+[ -1   1  -1   1]
+[  1   6   9  13]
+[ -2   6   0   2]
+[  3   7   1   3]
+>>> A = spmatrix([0,2,-1,2,-2,1], [0,1,2,0,2,1], [0,0,0,1,1,2]) 
+>>> print A
+[ 0.00e+00  2.00e+00     0    ]
+[ 2.00e+00     0      1.00e+00]
+[-1.00e+00 -2.00e+00     0    ]
+>>> C = spmatrix([10,-20,30], [0,2,1], [0,0,1])
+>>> print C
+[ 1.00e+01     0    ]
+[    0      3.00e+01]
+[-2.00e+01     0    ]
+>>> A[:,0] = C[:,0]
+>>> print A
+[ 1.00e+01  2.00e+00     0    ]
+[    0         0      1.00e+00]
+[-2.00e+01 -2.00e+00     0    ]
+>>> D = matrix(range(6), (3,2))
+>>> A[:,0] = D[:,0]
+>>> print A
+[ 0.00e+00  2.00e+00     0    ]
+[ 1.00e+00     0      1.00e+00]
+[ 2.00e+00 -2.00e+00     0    ]
+>>> A[:,0] = 1
+>>> print A
+[ 1.00e+00  2.00e+00     0    ]
+[ 1.00e+00     0      1.00e+00]
+[ 1.00e+00 -2.00e+00     0    ]
+>>> A[:,0] = 0
+>>> print A
+[ 0.00e+00  2.00e+00     0    ]
+[ 0.00e+00     0      1.00e+00]
+[ 0.00e+00 -2.00e+00     0    ]
+
+
+
+Attributes and Methods 
+======================
+
+Dense and sparse matrices have the following attributes.
+
+.. attribute:: size
+
+    A tuple with the dimensions of the matrix. The size of the matrix can 
+    be changed by altering this attribute, as long as the number of 
+    elements in the matrix remains unchanged.  
+
+.. attribute:: typecode
+
+    A character, either :const:`'i'`, :const:`'d'`, or :const:`'z'`, for 
+    integer, real, and complex matrices, respectively.  A read-only 
+    attribute.
+
+.. method:: trans()
+
+    Returns the transpose of the matrix as a new matrix.  One can also use
+    ``A.T`` instead of ``A.trans()``.
+
+.. method:: ctrans()
+
+    Returns the conjugate transpose of the matrix as a new matrix.  One 
+    can also use ``A.H`` instead of ``A.ctrans()``.
+
+.. method:: real()
+
+    For complex matrices, returns the real part as a real matrix.  For 
+    integer and real matrices, returns a copy of the matrix.
+
+.. method:: imag
+
+    For complex matrices, returns the imaginary part as a real matrix.
+    For integer and real matrices, returns an integer or real zero matrix.
+
+In addition, sparse matrices have the following attributes.
+
+.. attribute:: V
+
+    A single-column dense matrix containing the numerical values of the 
+    nonzero entries in column-major order.  Making an assignment to the 
+    attribute is an efficient way of changing the values of the sparse 
+    matrix, without changing the sparsity pattern.
+    
+    When the attribute :attr:`V <>` is read, a *copy* of :attr:`V <>` is 
+    returned, as a new dense matrix.  This implies, for example, that an 
+    indexed assignment ``A.V[I] = B`` does not work, or at least 
+    cannot be used to modify ``A``.  Instead the attribute :attr:`V <>` 
+    will be read and returned as a new matrix; then the elements of this 
+    new matrix are modified.
+
+.. attribute:: I
+
+    A single-column integer dense matrix with the row indices of the 
+    entries in :attr:`V`.  A read-only attribute.
+
+.. attribute:: J
+
+    A single-column integer dense matrix with the column indices of the 
+    entries in :attr:`V`.  A read-only attribute.
+
+.. attribute:: CCS
+
+    A triplet (column pointers, row indices, values) with the 
+    compressed-column-storage representation of the matrix.  A read-only 
+    attribute.  This attribute can be used to export sparse matrices to 
+    other packages such as MOSEK.
+
+The next example below illustrates assignments to :attr:`V`.
+
+>>> from cvxopt import spmatrix, matrix
+>>> A = spmatrix(range(5), [0,1,1,2,2], [0,0,1,1,2])
+>>> print A
+[ 0.00e+00     0         0    ]
+[ 1.00e+00  2.00e+00     0    ]
+[    0      3.00e+00  4.00e+00]
+>>> B = spmatrix(A.V, A.J, A.I, (4,4))  # transpose and add a zero row and column
+>>> print B
+[ 0.00e+00  1.00e+00     0         0    ]
+[    0      2.00e+00  3.00e+00     0    ]
+[    0         0      4.00e+00     0    ]
+[    0         0         0         0    ]
+>>> B.V = matrix([1., 7., 8., 6., 4.])   # assign new values to nonzero entries
+>>> print B
+[ 1.00e+00  7.00e+00     0         0    ]
+[    0      8.00e+00  6.00e+00     0    ]
+[    0         0      4.00e+00     0    ]
+[    0         0         0         0    ]
+
+
+The following attributes and methods are defined for dense matrices.
+
+.. attribute:: __array_struct__
+
+    A PyCObject implementing the :program:`NumPy` array interface  
+    (see the section :ref:`s-array-interface` for details).
+
+.. method:: tofile(f)
+
+    Writes the elements of the matrix in column-major order to a binary 
+    file ``f``. 
+
+.. method:: fromfile(f)
+
+    Reads the contents of a binary file ``f`` into the matrix object.
+
+The last two methods are illustrated in the following examples.
+
+>>> from cvxopt import matrix, spmatrix
+>>> A = matrix([[1.,2.,3.], [4.,5.,6.]])  
+>>> print A
+[ 1.00e+00  4.00e+00]
+[ 2.00e+00  5.00e+00]
+[ 3.00e+00  6.00e+00]
+>>> f = open('mat.bin','w')
+>>> A.tofile(f)
+>>> f.close()
+>>> B = matrix(0.0, (2,3))
+>>> f = open('mat.bin','r')
+>>> B.fromfile(f)
+>>> f.close()
+>>> print B
+[ 1.00e+00  3.00e+00  5.00e+00]
+[ 2.00e+00  4.00e+00  6.00e+00]
+>>> A = spmatrix(range(5), [0,1,1,2,2], [0,0,1,1,2])
+>>> f = open('test.bin','w')
+>>> A.V.tofile(f)  
+>>> A.I.tofile(f) 
+>>> A.J.tofile(f)
+>>> f.close()
+>>> f = open('test.bin','r')
+>>> V = matrix(0.0, (5,1));  V.fromfile(f)  
+>>> I = matrix(0, (5,1));  I.fromfile(f)  
+>>> J = matrix(0, (5,1));  J.fromfile(f)  
+>>> B = spmatrix(V, I, J)
+>>> print B
+[ 0.00e+00     0         0    ]
+[ 1.00e+00  2.00e+00     0    ]
+[    0      3.00e+00  4.00e+00]
+
+Note that the :func:`dump` and :func:`load` functions in the :mod:`pickle` 
+module offer a convenient alternative for writing matrices to files and 
+reading matrices from files.
+
+
+Built-In Functions
+==================
+
+Many Python built-in functions and operations can be used with matrix 
+arguments.  We list some useful examples.
+
+.. function:: len(x)
+
+    If ``x`` is a dense matrix, returns the product of the number of rows 
+    and the number of columns.  If ``x`` is a sparse matrix, returns the 
+    number of nonzero entries.
+
+.. function:: bool([x])
+
+    Returns :const:`False` if ``x`` is a zero matrix and :const:`True` 
+    otherwise.
+
+.. function:: max(x)
+
+    If ``x`` is a dense matrix, returns the maximum element of ``x``.
+    If ``x`` is a sparse, returns the maximum nonzero element of ``x``.
+
+.. function:: min(x)
+
+    If ``x`` is a dense matrix, returns the minimum element of ``x``.
+    If ``x`` is a sparse matrix, returns the minimum nonzero element of 
+    ``x``.
+
+.. function:: abs(x)
+
+    Returns a matrix with the absolute values of the elements of ``x``.
+
+.. function:: sum(x[, start = 0.0])
+
+    Returns the sum of ``start`` and the elements of ``x``.
+
+
+Dense and sparse matrices can be used as  arguments to the :func:`list`, 
+:func:`tuple`, :func:`zip`, :func:`map`, and :func:`filter` functions 
+described in the Python Library Reference.  
+However, one should note that when used with sparse matrix arguments, 
+these functions only consider the nonzero entries.
+For example, ``list(A)`` and ``tuple(A)`` construct a list, 
+respectively a tuple, from the elements of ``A`` if ``A`` is dense, and 
+of the nonzero elements of ``A`` if ``A`` is sparse.
+
+``zip(A, B, ...)`` returns a list of tuples, with the i-th 
+tuple containing the i-th elements (or nonzero elements) of 
+``A``, ``B``, ....   
+
+>>> from cvxopt import matrix
+>>> A = matrix([[-11., -5., -20.], [-6., -0., 7.]])
+>>> B = matrix(range(6), (3,2))
+>>> list(A)
+[-11.0, -5.0, -20.0, -6.0, 0.0, 7.0]
+>>> tuple(B)
+(0, 1, 2, 3, 4, 5)
+>>> zip(A, B)
+[(-11.0, 0), (-5.0, 1), (-20.0, 2), (-6.0, 3), (0.0, 4), (7.0, 5)]
+
+``map(f, A)``, where ``f`` is a function and ``A`` is a dense matrix, 
+returns a list constructed by applying ``f`` to each element of ``A``.  If
+``A`` is sparse, the function ``f`` is applied to each nonzero element of 
+``A``.  Multiple arguments can be provided, for example, as in 
+``map(f, A, B)``, if ``f`` is a function with two arguments.
+In the following example, we return an integer 0-1 matrix with the
+result of an elementwise comparison.
+
+>>> A = matrix([ [0.5, -0.1, 2.0], [1.5, 0.2, -0.1], [0.3, 1.0, 0.0]]) 
+>>> print A
+[ 5.00e-01  1.50e+00  3.00e-01]
+[-1.00e-01  2.00e-01  1.00e+00]
+[ 2.00e+00 -1.00e-01  0.00e+00]
+>>> print matrix(map(lambda x: 0 <= x <= 1, A), A.size)
+[ 1  0  1]
+[ 0  1  1]
+[ 0  0  1]
+
+``filter(f, A)``, where ``f`` is a function and ``A`` is a matrix, 
+returns a list containing the elements of ``A`` (or nonzero elements of 
+``A`` is ``A`` is sparse) for which ``f`` is true.
+
+>>> A = matrix([[5, -4, 10, -7], [-1, -5, -6, 2], [6, 1, 5, 2],  [-1, 2, -3, -7]])
+>>> print A
+[  5  -1   6  -1]
+[ -4  -5   1   2]
+[ 10  -6   5  -3]
+[ -7   2   2  -7]
+>>> filter(lambda x: x%2, A)         # list of odd elements in A
+[5, -7, -1, -5, 1, 5, -1, -3, -7]
+>>> filter(lambda x: -2 < x < 3, A)  # list of elements between -2 and 3
+[-1, 2, 1, 2, -1, 2]
+
+It is also possible to iterate over matrix elements, as illustrated in
+the following example.
+
+>>> A = matrix([[5, -3], [9, 11]])
+>>> for x in A: print max(x,0)
+...
+5
+0
+9
+11
+>>> [max(x,0) for x in A]
+[5, 0, 9, 11]
+
+The expression ``x in A`` returns :const:`True` if an element 
+of ``A`` (or a nonzero element of ``A`` if ``A`` is sparse)
+is equal to ``x`` and :const:`False` otherwise.
+
+
+Other Matrix Functions
+======================
+
+The following functions can be imported from CVXOPT.
+
+.. function:: cvxopt.sqrt(x)
+
+    The elementwise square root of a dense matrix ``x``.  The result is 
+    returned as a real matrix if ``x`` is an integer or real matrix and 
+    as a complex matrix if ``x`` is a complex matrix.  Raises an exception
+    when ``x`` is an integer or real matrix with negative elements.
+
+    As an example we take the elementwise square root of the sparse matrix
+
+    .. math:: 
+
+        A = \left[ \begin{array}{rrrrr}
+            0 & 2 & 0 & 0 & 3 \\
+            2 & 0 & 0 & 0 & 0 \\
+            1 & 2 & 0 & 4 & 0 \\
+            0 & 0 & 1 & 0 & 0 \end{array} \right]
+
+    >>> from cvxopt import spmatrix, sqrt
+    >>> A = spmatrix([2,1,2,2,1,3,4], [1,2,0,2,3,0,2], [0,0,1,1,2,3,3]) 
+    >>> B = spmatrix(sqrt(A.V), A.I, A.J)
+    >>> print B
+    [    0      1.41e+00     0      1.73e+00]
+    [ 1.41e+00     0         0         0    ]
+    [ 1.00e+00  1.41e+00     0      2.00e+00]
+    [    0         0      1.00e+00     0    ]
+
+
+.. function:: cvxopt.sin(x)
+
+    The sine function applied elementwise to a dense matrix ``x``.  
+    The result is returned as a real matrix if ``x`` is an integer
+    or real matrix and as a complex matrix otherwise.  
+
+.. function:: cvxopt.cos(x)
+
+    The cosine function applied elementwise to a dense matrix ``x``.  
+    The result is returned as a real matrix if ``x`` is an integer
+    or real matrix and as a complex matrix otherwise.  
+
+.. function:: cvxopt.exp(x)
+
+    The exponential function applied elementwise to a dense matrix ``x``.  
+    The result is returned as a real matrix if ``x`` is an integer 
+    or real matrix and as a complex matrix otherwise.  
+
+.. function:: cvxopt.log(x)
+
+    The natural logarithm applied elementwise to a dense matrix ``x``.  
+    The result is returned as a real matrix if ``x`` is an integer
+    or real matrix and as a complex matrix otherwise.  
+    Raises an exception when ``x`` is an integer or real matrix with 
+    nonpositive elements, or a complex matrix with zero elements.
+
+.. function:: cvxopt.mul(x0, [, x1 [, x2 ...]])
+
+    If the arguments are dense or sparse matrices of the same size, returns
+    the elementwise product of its arguments.  The result is a sparse
+    matrix if one or more of its arguments is sparse, and a dense matrix 
+    otherwise.
+
+    If the arguments include scalars, a scalar product with the scalar is 
+    made.  (A 1 by 1 dense matrix is treated as a scalar if the dimensions
+    of the other arguments are not all 1 by 1.)
+
+    :func:`mul` can also be called with an iterable 
+    (list, tuple, xrange 
+    object, or generator) as its single argument, if the iterable 
+    generates a list of dense or sparse matrices or scalars.
+
+    >>> from cvxopt import matrix, spmatrix, mul
+    >>> A = matrix([[1.0, 2.0], [3.0, 4.0]])
+    >>> B = spmatrix([2.0, 3.0], [0, 1], [0, 1])
+    >>> print mul(A, B, -1.0)
+    [-2.00e+00     0    ]
+    [    0     -1.20e+01]
+    >>> print mul( matrix([k, k+1]) for k in [1,2,3] )
+    [  6]
+    [ 24]
+
+.. function:: cvxopt.div(x, y)
+
+    Returns the elementwise division of ``x`` by ``y``.  ``x`` is a dense 
+    or sparse matrix, or a scalar (Python number of 1 by 1 dense matrix).
+    ``y`` is a dense matrix or a scalar.
+
+.. function:: cvxopt.max(x0[, x1[, x2 ...]])
+
+    When called with a single matrix argument, returns the maximum of the 
+    elements of the matrix (including the zero entries, if the matrix is 
+    sparse).  
+
+    When called with multiple arguments, the arguments must be matrices of 
+    the same size, or scalars, and the elementwise maximum is returned.   
+    A 1 by 1 dense matrix is treated as a scalar if the other arguments 
+    are not all 1 by 1.  If one of the arguments is scalar, and the other 
+    arguments are not all 1 by 1, then the scalar argument is interpreted 
+    as a dense matrix with all its entries equal to the scalar.
+    
+    The result is a sparse matrix if all its arguments are sparse matrices.
+    The result is a number if all its arguments are numbers.  The result 
+    is a dense matrix if at least one of the arguments is a dense matrix.
+    
+    :func:`max <cvxopt.max>` can also be called with an iterable 
+    (list, tuple, xrange 
+    object, or generator) as its single argument, if the iterable 
+    generates a list of dense or sparse matrices or scalars.
+    
+    >>> from cvxopt import matrix, spmatrix, max
+    >>> A = spmatrix([2, -3], [0, 1], [0, 1])
+    >>> print max(A, -A, 1)
+    [ 2.00e+00  1.00e+00]
+    [ 1.00e+00  3.00e+00]
+    
+    It is important to note the difference between this 
+    :func:`max <cvxopt.max>`
+    and the built-in :func:`max`, explained in the previous section.
+    
+    >>> from cvxopt import spmatrix
+    >>> A = spmatrix([-1.0, -2.0], [0,1], [0,1])
+    >>> max(A)          # built-in max of a sparse matrix takes maximum over nonzero elements
+    -1.0
+    >>> max(A, -1.5)
+    Traceback (most recent call last):
+      File "<stdin>", line 1, in <module>
+    NotImplementedError: matrix comparison not implemented
+    >>> from cvxopt import max
+    >>> max(A)          # cvxopt.max takes maximum over all the  elements
+    0.0
+    >>> print max(A, -1.5)
+    [-1.00e+00  0.00e+00]
+    [ 0.00e+00 -1.50e+00]
+    
+
+.. function:: cvxopt.min(x0[, x1[, x2 ...]])
+
+    When called with a single matrix argument, returns the minimum of the 
+    elements of the matrix (including the zero entries, if the matrix is 
+    sparse).  
+
+    When called with multiple arguments, the arguments must be matrices of 
+    the same size, or scalars, and the elementwise maximum is returned.   
+    A 1 by 1 dense matrix is treated as a scalar if the other arguments 
+    are not all 1 by 1.  If one of the arguments is scalar, and the other 
+    arguments are not all 1 by 1, then the scalar argument is interpreted 
+    as a dense matrix with all its entries equal to the scalar.
+    
+    :func:`min <cvxopt.min>` can also be called with an iterable 
+    (list, tuple, xrange 
+    object, or generator) as its single argument, if the iterable generates
+    a list of dense or sparse matrices or scalars.
+    
+    
+.. _s-random:
+
+Randomly Generated Matrices 
+===========================
+
+The CVXOPT package provides two functions 
+:func:`normal <cvxopt.normal>` and 
+:func:`uniform <cvxopt.uniform>` for generating randomly distributed 
+matrices.  
+The default installation relies on the pseudo-random number generators in 
+the Python standard library :mod:`random`.  Alternatively, the random 
+number generators in the 
+`GNU Scientific Library (GSL) <http://www.gnu.org/software/gsl>`_ 
+can be used, if this option is selected during the installation of CVXOPT.
+The random matrix functions based on GSL are faster than the default 
+functions based on the :mod:`random` module.
+
+.. function:: cvxopt.normal(nrows[, ncols = 1[, mean = 0.0[, std = 1.0]]])
+
+    Returns a type :const:`'d'` dense matrix of size ``nrows``  by 
+    ``ncols`` with elements chosen from a normal distribution 
+    with mean ``mean`` and standard deviation ``std``.
+
+.. function:: cvxopt.uniform(nrows[, ncols = 1[, a = 0.0[, b = 1.0]]])
+
+    Returns a type :const:`'d'` dense matrix of size ``nrows`` by 
+    ``ncols`` matrix with elements uniformly distributed between ``a`` and 
+    ``b``.
+
+.. function:: cvxopt.setseed([value])
+
+    Sets the state of the random number generator.  ``value`` must be an 
+    integer.  If ``value`` is absent or equal to zero, the value is taken 
+    from the system clock.  If the Python random number generators are 
+    used, this is equivalent to :samp:`random.seed(value)`.
+
+.. function:: cvxopt.getseed()
+
+    Returns the current state of the random number generator.  This 
+    function is only available if the GSL random number generators are 
+    installed.   (The state of the random number generators in the Python 
+    :mod:`random` module can be managed via the functions 
+    :func:`random.getstate` and :func:`random.setstate`.)
+
+
+.. _s-array-interface:
+
+The NumPy Array Interface
+=========================
+
+The CVXOPT :class:`matrix` object is compatible with the 
+NumPy Array 
+Interface, which allows Python objects that represent multidimensional 
+arrays to exchange data using information stored in the attribute 
+:attr:`__array_struct__`.  
+
+.. seealso::
+
+    * `NumPy Array Interface Specification <http://numpy.scipy.org/array_interface.shtml>`_
+
+    * `Numpy home page <http://numpy.scipy.org>`_
+
+As already mentioned in the section :ref:`s-dense-matrices`, a 
+two-dimensional array 
+object (for example, a NumPy matrix or two-dimensional array) can be 
+converted to a CVXOPT :class:`matrix` object by using 
+the :func:`matrix <cvxopt.matrix>` constructor.  
+Conversely, CVXOPT matrices can be used as array-like 
+objects in NumPy.  The following example illustrates the compatibility of 
+CVXOPT matrices and NumPy arrays. 
+
+>>> from cvxopt import matrix
+>>> a = matrix(range(6), (2,3), 'd')
+>>> print a
+[ 0.00e+00  2.00e+00  4.00e+00]
+[ 1.00e+00  3.00e+00  5.00e+00]
+>>> from numpy import array
+>>> b = array(a)
+>>> b
+array([[ 0.  2.  4.]
+       [ 1.  3.  5.]])
+>>> a*b
+array([[  0.   4.  16.]
+       [  1.   9.  25.]])
+>>> from numpy import mat
+>>> c = mat(a)
+>>> c
+matrix([[ 0.  2.  4.]
+        [ 1.  3.  5.]])
+>>> a.T * c 
+matrix([[  1.,   3.,   5.],
+        [  3.,  13.,  23.],
+        [  5.,  23.,  41.]])
+
+In the first product, ``a * b`` is interpreted as NumPy array 
+multiplication, i.e., componentwise multiplication.
+The second product ``a.T * c`` is interpreted as NumPy matrix 
+multiplication, i.e., standard matrix multiplication.
diff --git a/doc/source/modeling.rst b/doc/source/modeling.rst
new file mode 100644
index 0000000..0c1bdd1
--- /dev/null
+++ b/doc/source/modeling.rst
@@ -0,0 +1,808 @@
+.. _c-modeling:
+
+********
+Modeling
+********
+
+The module :mod:`cvxopt.modeling`  can be used to specify and solve 
+optimization problems  with convex piecewise-linear objective and 
+constraint functions.  Using this modeling tool, one can specify an 
+optimization problem by first defining the optimization variables (see the 
+section :ref:`s-variables`), and then specifying the objective and 
+constraint functions using linear operations (vector addition and 
+subtraction, matrix-vector multiplication, indexing and slicing)
+and nested evaluations of :func:`max <cvxopt.modeling.max>`, 
+:func:`min <cvxopt.modeling.min>`, 
+:func:`abs <cvxopt.modeling.abs>` and 
+:func:`sum <cvxopt.modeling.sum>` (see the section :ref:`s-functions`).
+
+A more general Python convex modeling package is 
+`CVXMOD <http://cvxmod.net>`_.
+
+.. _s-variables:
+
+Variables 
+=========
+
+Optimization variables are represented by :class:`variable` objects.
+
+.. function:: cvxopt.modeling.variable([size[, name]])
+
+    A vector variable.  The first argument is the dimension of the vector
+    (a positive integer with default value 1).  The second argument is a 
+    string with a name for the variable.  The name is optional and has 
+    default value :const:`""`. It is only used when displaying variables 
+    (or objects that depend on variables, such as functions or constraints) 
+    using :func:`print` statements, when calling the built-in functions
+    :func:`repr`  or :func:`str`, or when writing linear programs to MPS 
+    files.
+
+The function :func:`len <>` returns the length of a :class:`variable`.  
+A :class:`variable` ``x`` has two attributes.
+
+.. attribute:: name 
+
+    The name of the variable.  
+
+
+.. attribute:: value
+
+    Either :const:`None` or a dense :const:`'d'` matrix of size 
+    ``len(x)`` by 1.
+
+    The attribute ``x.value`` is set to :const:`None` when the variable
+    ``x`` is created.   It can be given a numerical value later, typically 
+    by solving an LP that has ``x`` as one of its variables.  One can also 
+    make an explicit assignment ``x.value = y``.  The assigned value 
+    ``y`` must be an integer or float, or a dense :const:`'d'` matrix of 
+    size ``(len(x), 1)``.  If ``y`` is an integer or float, all the 
+    elements of ``x.value`` are set to the value of ``y``.
+
+
+
+>>> from cvxopt import matrix
+>>> from cvxopt.modeling import variable
+>>> x = variable(3,'a')
+>>> len(x)
+3
+>>> print x.name
+a
+>>> print x.value 
+None
+>>> x.value = matrix([1.,2.,3.])
+>>> print x.value
+[ 1.00e+00]
+[ 2.00e+00]
+[ 3.00e+00]
+>>> x.value = 1
+>>> print x.value
+[ 1.00e+00]
+[ 1.00e+00]
+[ 1.00e+00]
+
+
+.. _s-functions:
+
+Functions 
+=========
+
+Objective and constraint functions can be defined via overloaded operations
+on variables and other functions.  A function ``f`` is interpreted as a 
+column vector, with length ``len(f)`` and with a value that depends on 
+the values of its variables.  Functions have two public attributes.  
+
+.. attribute:: variables
+
+    Returns a copy of the list of variables of the function.
+
+
+.. attribute:: value
+
+    The function value.  If any of the variables of ``f`` has value 
+    :const:`None`, then ``f.value()`` returns :const:`None`.  Otherwise,
+    it returns a dense :const:`'d'` matrix of size ``(len(f),1)`` with 
+    the function value computed from the :attr:`value` attributes of the 
+    variables of ``f``.  
+
+Three types of functions are supported: affine, convex piecewise-linear, 
+and concave piecewise-linear.
+
+**Affine functions** represent vector valued functions of the form
+
+.. math::
+
+    f(x_1,\ldots,x_n) = A_1 x_1 + \cdots + A_n x_n + b.
+
+The coefficients can be scalars or dense or sparse matrices. The 
+constant term is a scalar or a column vector.
+
+Affine functions result from the following operations.
+
+**Unary operations** 
+    For a variable ``x``, the unary operation ``+x`` results in an 
+    affine function with ``x`` as variable, coefficient 1.0, and constant 
+    term 0.0.  The unary operation ``-x`` returns an affine function 
+    with ``x`` as variable, coefficient -1.0, and constant term 0.0.  For 
+    an affine function ``f``, ``+f`` is a copy of ``f``, and  
+    ``-f`` is a copy of ``f`` with the signs of its coefficients and 
+    constant term reversed.
+
+**Addition and subtraction**
+    Sums and differences of affine functions, variables and constants result
+    in new affine functions.  The constant terms in the sum can be of type 
+    integer or float, or dense or sparse :const:`'d'` matrices with one 
+    column. 
+
+    The rules for addition and subtraction follow the conventions for 
+    matrix addition and subtraction in the section :ref:`s-arithmetic`, 
+    with variables and affine functions interpreted as dense :const:`'d'` 
+    matrices with one column.  In particular, a scalar term (integer, float,
+    1 by 1 dense :const:`'d'` matrix, variable of length 1, or affine 
+    function of length 1) can be added to an affine function or variable of
+    length greater than 1.
+
+**Multiplication**
+    Suppose ``v`` is an affine function or a variable, and ``a`` is an 
+    integer, float, sparse or dense :const:`'d'` matrix.  The products 
+    ``a * v`` and  ``v * a`` are valid affine functions whenever 
+    the product is allowed under the rules for matrix and scalar 
+    multiplication of the section :ref:`s-arithmetic`, with ``v`` 
+    interpreted
+    as a :const:`'d'` matrix with one column.  In particular, the product 
+    ``a * v`` is defined if ``a`` is a scalar (integer, float, or 
+    1 by 1 dense :const:`'d'` matrix), or a matrix (dense or sparse) with 
+    ``a.size[1]`` equal to ``len(v)``.   The operation ``v * a``
+    is defined if ``a`` is scalar, or if ``len(v)`` is 1 and ``a`` is a
+    matrix with one column.
+
+**Inner products**
+    The following two functions return scalar affine functions defined
+    as inner products of a constant vector with  a variable or affine
+    function.
+
+    .. function:: cvxopt.modeling.sum(v)
+
+        The argument is an affine function or a variable.  The result is an
+        affine function of length 1, with the sum of the components of the
+        argument ``v``.  
+
+    .. function:: cvxopt.modeling.dot(u, v)
+
+        If ``v`` is a variable or affine function and ``u`` is a 
+        :const:`'d'` matrix of size ``(len(v), 1)``, then 
+        ``dot(u, v)`` and ``dot(v, u)`` are equivalent to 
+        ``u.trans() * v``.
+
+        If ``u`` and ``v`` are dense matrices, then :func:`dot` 
+        is equivalent to the function :func:`blas.dot <cvxopt.blas.dot>`,
+        i.e., it returns the inner product of the two matrices.
+
+
+In the following example, the variable ``x`` has length 1 and ``y`` has 
+length 2.  The functions ``f`` and ``g`` are given by
+
+.. math::
+
+    f(x,y) &= \left[ \begin{array}{c} 2 \\ 2 \end{array}\right] x 
+        + y + \left[ \begin{array}{c} 3 \\ 3 \end{array}\right], \\
+    g(x,y) &= 
+        \left[ \begin{array}{cc} 1 & 3 \\ 2 & 4 \end{array}\right] f(x,y) +
+        \left[ \begin{array}{cc} 1 & 1 \\ 1 & 1 \end{array} \right] y + 
+        \left[ \begin{array}{c} 1 \\ -1 \end{array} \right] \\
+           &= \left[ \begin{array}{c} 8 \\ 12 \end{array}\right] x + 
+       \left[ \begin{array}{cc} 2 & 4 \\ 3 & 5 \end{array}\right] y + 
+       \left[ \begin{array}{c} 13 \\ 17\end{array}\right].
+
+
+>>> from cvxopt.modeling import variable
+>>> x = variable(1,'x')
+>>> y = variable(2,'y')
+>>> f = 2*x + y + 3  
+>>> A = matrix([[1., 2.], [3.,4.]])
+>>> b = matrix([1.,-1.])
+>>> g = A*f + sum(y) + b 
+>>> print g
+affine function of length 2
+constant term:
+[ 1.30e+01]
+[ 1.70e+01]
+linear term: linear function of length 2
+coefficient of variable(2,'y'):
+[ 2.00e+00  4.00e+00]
+[ 3.00e+00  5.00e+00]
+coefficient of variable(1,'x'):
+[ 8.00e+00]
+[ 1.20e+01]
+
+
+**In-place operations** 
+    For an affine function ``f`` the operations ``f += u`` and 
+    ``f -= u``, with ``u`` a constant, a variable or an affine function,
+    are allowed if they do not change the length of ``f``, i.e., if ``u`` 
+    has length ``len(f)`` or length 1.  In-place multiplication 
+    ``f *= u`` and division ``f /= u`` are allowed if ``u`` is an 
+    integer, float, or 1 by 1 matrix.
+
+
+**Indexing and slicing** 
+    Variables and affine functions admit single-argument indexing of the 
+    four types described in the section :ref:`s-indexing`.  The result of 
+    an indexing or slicing operation is an affine function.  
+
+
+>>> x = variable(4,'x')
+>>> f = x[::2]
+>>> print f 
+linear function of length 2
+linear term: linear function of length 2
+coefficient of variable(4,'x'):
+[ 1.00e+00     0         0         0    ]
+[    0         0      1.00e+00     0    ]
+>>> y = variable(3,'x')
+>>> g = matrix(range(12),(3,4),'d')*x - 3*y + 1
+>>> print g[0] + g[2]
+affine function of length 1
+constant term:
+[ 2.00e+00]
+linear term: linear function of length 1
+coefficient of variable(4,'x'):
+[ 2.00e+00  8.00e+00  1.40e+01  2.00e+01]
+coefficient of variable(3,'x'):
+[-3.00e+00     0     -3.00e+00]
+
+
+The general expression of a **convex piecewise-linear** function is
+
+.. math::
+
+    f(x_1,\ldots,x_n) = b + A_1 x_1 + \cdots + A_n x_n + 
+        \sum_{k=1}^K \max (y_1, y_2, \ldots, y_{m_k}).
+
+The maximum in this expression is a componentwise maximum of its vector 
+arguments, which can be constant vectors, variables, affine functions or 
+convex piecewise-linear functions.  The general expression for a 
+**concave piecewise-linear** function is
+
+.. math::
+
+    f(x_1,\ldots,x_n) = b + A_1 x_1 + \cdots + A_n x_n + 
+        \sum_{k=1}^K \min (y_1, y_2, \ldots, y_{m_k}).
+
+Here the arguments of the :func:`min <>` 
+can be constants, variables, affine 
+functions or concave piecewise-linear functions.
+
+Piecewise-linear functions can be created using the following 
+operations.
+
+**Maximum**  
+    If the arguments in ``f = max(y1, y2, ...)`` do not include any 
+    variables or functions, then the Python built-in :func:`max <>` is 
+    evaluated.  
+
+    If one or more of the arguments are variables or functions, 
+    :func:`max <>` 
+    returns a piecewise-linear function defined as the elementwise maximum 
+    of its arguments.  In other words, 
+    ``f[k] = max(y1[k], y2[k], ...)`` for ``k`` = 0, ...,  
+    ``len(f) - 1``.  The length of ``f`` is equal to the maximum of the
+    lengths of the arguments.  Each argument must have length equal to 
+    ``len(f)`` or length one.  Arguments with length one are interpreted
+    as vectors of length ``len(f)`` with identical entries.
+
+    The arguments can be scalars of type integer or float, dense 
+    :const:`'d'` matrices with one column, variables, affine functions or 
+    convex piecewise-linear functions.
+     
+    With one argument, ``f = max(u)`` is interpreted as
+    ``f = max(u[0], u[1], ..., u[len(u)-1])``.  
+
+**Minimum** 
+    Similar to :func:`max <>` but returns a concave piecewise-linear 
+    function.
+    The arguments can be scalars of type integer or float, dense 
+    :const:`'d'` matrices with one column, variables, affine functions or 
+    concave piecewise-linear functions.
+
+**Absolute value** 
+    If ``u`` is a variable or affine function then ``f = abs(u)`` 
+    returns the convex piecewise-linear function ``max(u, -u)``.
+
+**Unary plus and minus** 
+    ``+f`` creates a copy of ``f``.  ``-f`` is a concave 
+    piecewise-linear function if ``f`` is convex and a convex 
+    piecewise-linear function if ``f`` is concave.
+
+**Addition and subtraction**  
+    Sums and differences involving piecewise-linear functions are allowed 
+    if they result in convex or concave functions.  For example, one can add
+    two convex or two concave functions, but not a convex and a concave 
+    function.  The command ``sum(f)`` is equivalent to 
+    ``f[0] + f[1] + ... + f[len(f) - 1]``.
+
+**Multiplication** 
+    Scalar multiplication ``a * f`` of a piecewise-linear function ``f``
+    is defined if ``a`` is an integer, float, 1 by 1 :const:`'d'` matrix. 
+    Matrix-matrix multiplications ``a * f`` or ``f * a`` are only 
+    defined if ``a`` is a dense or sparse 1 by 1 matrix.
+
+**Indexing and slicing** 
+    Piecewise-linear functions admit single-argument indexing of the four 
+    types described in the section :ref:`s-indexing`.  The result of an 
+    indexing or slicing operation is a new piecewise-linear function.
+
+
+In the following example, ``f`` is the 1-norm of a vector variable ``x`` of 
+length 10, ``g`` is its infinity-norm, and ``h`` is the function
+
+.. math::
+
+    h(x) = \sum_k \phi(x[k]), \qquad
+    \phi(u) = \left\{\begin{array}{ll}
+        0       & |u| \leq 1 \\
+        |u|-1   & 1 \leq |u| \leq 2 \\
+        2|u|-3  & |u| \geq 2. 
+    \end{array}\right.
+
+
+>>> from cvxopt.modeling import variable, max
+>>> x = variable(10, 'x')
+>>> f = sum(abs(x))    
+>>> g = max(abs(x))   
+>>> h = sum(max(0, abs(x)-1, 2*abs(x)-3))  
+
+
+**In-place operations**
+    If ``f`` is piecewise-linear then the in-place operations  
+    ``f += u``, ``f -= u``, ``f *= u``, ``f /= u`` are 
+    defined if the corresponding expanded operations ``f = f + u``, 
+    ``f = f - u``, ``f = f * u``, and ``f = f/u`` are defined 
+    and if they do not change the length of ``f``.
+
+
+.. _s-constraints:
+
+Constraints
+===========
+
+Linear equality and inequality constraints of the form
+
+.. math::
+
+    f(x_1,\ldots,x_n) = 0, \qquad f(x_1,\ldots,x_n) \preceq  0, 
+
+where :math:`f` is a convex function, are represented by :class:`constraint`
+objects.  Equality constraints are created by expressions of the form 
+
+::
+
+    f1 == f2 
+
+Here ``f1`` and ``f2`` can be any objects for which the difference 
+``f1 - f2`` yields an affine function.  Inequality constraints are 
+created by expressions of the form 
+
+::
+
+    f1 <= f2 
+    f2 >= f1
+
+where ``f1`` and ``f2`` can be any objects for which the difference 
+``f1 - f2`` yields a convex piecewise-linear function.  The comparison 
+operators first convert the expressions to ``f1 - f2 == 0``, resp., 
+``f1 - f2 <= 0``, and then return a new :class:`constraint` object with
+constraint function ``f1 - f2``.
+
+In the following example we create three constraints
+
+.. math::
+
+    \newcommand{\ones}{{\bf 1}}
+    0 \preceq x \preceq \ones, \qquad \ones^T x = 2,
+
+for a variable of length 5.
+
+>>> x = variable(5,'x')
+>>> c1 = (x <= 1)
+>>> c2 = (x >= 0)
+>>> c3 = (sum(x) == 2)
+
+
+The built-in function :func:`len <>` returns the dimension of the 
+constraint function.
+
+Constraints have four public attributes.
+
+.. attribute:: type
+
+    Returns :const:`'='` if the constraint is an equality constraint, and 
+    **'<'** if the constraint is an inequality constraint.
+
+
+.. attribute:: value 
+
+    Returns the value of the constraint function.  
+
+
+.. attribute:: multiplier
+
+    For a constraint ``c``, ``c.multiplier`` is a :class:`variable` 
+    object of dimension ``len(c)``.  It is used to represent the 
+    Lagrange multiplier or dual variable associated with the constraint.
+    Its value is initialized as :const:`None`, and can be modified by making
+    an assignment to ``c.multiplier.value``.
+
+
+.. attribute:: name
+
+    The name of the constraint.  Changing the name of a constraint also 
+    changes the name of the multiplier of ``c``.  For example, the command  
+    ``c.name = 'newname'`` also changes
+    ``c.multiplier.name`` to ``'newname_mul'``.
+
+
+
+.. _s-lp:
+
+Optimization Problems 
+=====================
+
+Optimization problems are be constructed by calling the following
+function.
+
+.. function:: cvxopt.modeling.op([objective[, constraints[, name]]])
+
+    The first argument specifies the objective function to be minimized.
+    It can be an affine or convex piecewise-linear function with length 1, 
+    a :class:`variable` with length 1, or a scalar constant (integer, float,
+    or 1 by 1 dense :const:`'d'` matrix).  The default value is 0.0.
+
+    The second argument is a single :class:`constraint`, or a list of 
+    :class:`constraint` objects.  The default value is an empty list.
+
+    The third argument is a string with a name for the problem.
+    The default value is the empty string.
+
+The following attributes and methods are useful for examining
+and modifying optimization problems.
+
+.. attribute:: objective
+
+    The objective or cost function.  One can write to this attribute to 
+    change the objective of an existing problem.  
+
+
+.. method:: variables
+
+    Returns a list of the variables of the problem.
+
+
+.. method:: constraints
+
+    Returns a list of the constraints.
+
+
+.. method:: inequalities
+
+    Returns a list of the inequality constraints.
+
+
+.. method:: equalities
+
+    Returns a list of the equality constraints.
+
+
+.. method:: delconstraint(c)
+
+    Deletes constraint ``c`` from the problem.
+
+
+.. :: addconstraint(c)
+
+    Adds constraint ``c`` to the problem.
+
+
+An optimization problem with convex piecewise-linear objective and
+constraints can be solved by calling the method :func:`solve`.
+
+.. method:: solve([format[, solver]]) 
+
+    This function converts the optimization problem to a linear program in 
+    matrix form and then solves it using the solver described in 
+    the section :ref:`s-lpsolver`.
+
+    The first argument is either :const:`'dense'` or :const:`'sparse'`, and 
+    denotes the matrix types used in the matrix representation of the LP.
+    The default value is :const:`'dense'`.
+
+    The second argument is either :const:`None`, :const:`'glpk'`, or 
+    :const:`'mosek'`, and selects one of three available LP solvers: the 
+    default solver written in Python, the GLPK solver (if installed) or the
+    MOSEK LP solver (if installed); see the section :ref:`s-lpsolver`.  The 
+    default value is :const:`None`.
+
+    The solver reports the outcome of optimization by setting the attribute 
+    :attr:`self.status` and by modifying the :attr:`value` attributes of 
+    the variables and the constraint multipliers of the problem.
+
+
+    * If the problem is solved to optimality, :attr:`self.status` is set to
+      :const:`'optimal'`.  The :attr:`value` attributes of the variables in
+      the problem  are set to their computed solutions, and the 
+      :attr:`value` attributes of the multipliers of the constraints of the
+      problem are set to the computed dual optimal solution.
+
+    * If it is determined that the problem is infeasible, 
+      :attr:`self.status` is set to :const:`'primal infeasible'`.  
+      The :attr:`value` attributes of the variables are set to 
+      :const:`None`.  The :attr:`value` attributes of the multipliers of 
+      the constraints of the problem are set to a certificate of primal 
+      infeasibility.  With the :const:`'glpk'` option, :func:`solve` does 
+      not provide certificates of infeasibility.
+
+    * If it is determined that the problem is dual infeasible, 
+      :attr:`self.status` is set to :const:`'dual infeasible'`.  
+      The :attr:`value` attributes of the multipliers of the constraints of 
+      the problem are set to :const:`None`.  The :attr:`value` attributes 
+      of the variables are set to a certificate of dual infeasibility. 
+      With the :const:`'glpk'` option, :func:`solve` does not provide 
+      certificates of infeasibility.
+
+    * If the problem was not solved successfully, :attr:`self.status` is set
+      to :const:`'unknown'`.  The :attr:`value` attributes of the variables
+      and the constraint multipliers are set to :const:`None`.
+
+We refer to the section :ref:`s-lpsolver` for details on the algorithms and
+the different solver options.
+
+As an example we solve the LP
+
+.. math::
+     \begin{array}{ll}
+     \mbox{minimize}   & -4x - 5y \\
+     \mbox{subject to} &  2x +y \leq 3 \\
+                       &  x +2y \leq 3 \\
+                       & x \geq 0, \quad y \geq 0.
+     \end{array}
+
+
+>>> from cvxopt.modeling import op
+>>> x = variable()
+>>> y = variable()
+>>> c1 = ( 2*x+y <= 3 ) 
+>>> c2 = ( x+2*y <= 3 )
+>>> c3 = ( x >= 0 )
+>>> c4 = ( y >= 0 ) 
+>>> lp1 = op(-4*x-5*y, [c1,c2,c3,c4]) 
+>>> lp1.solve()
+>>> lp1.status
+'optimal'
+>>> print lp1.objective.value()
+[-9.00e+00]
+>>> print x.value
+[ 1.00e+00]
+>>> print y.value
+[ 1.00e+00]
+>>> print c1.multiplier.value
+[ 1.00e+00]
+>>> print c2.multiplier.value
+[ 2.00e+00]
+>>> print c3.multiplier.value
+[ 2.87e-08]
+>>> print c4.multiplier.value
+[ 2.80e-08]
+
+
+We can solve the same LP in  matrix form as follows.
+
+>>> from cvxopt.modeling import op, dot
+>>> x = variable(2)
+>>> A = matrix([[2.,1.,-1.,0.], [1.,2.,0.,-1.]])
+>>> b = matrix([3.,3.,0.,0.])
+>>> c = matrix([-4.,-5.])
+>>> ineq = ( A*x <= b )
+>>> lp2 = op(dot(c,x), ineq)
+>>> lp2.solve()
+>>> print lp2.objective.value()
+[-9.00e+00]
+>>> print x.value
+[ 1.00e+00]
+[ 1.00e+00]
+>>> print ineq.multiplier.value
+[1.00e+00]
+[2.00e+00]
+[2.87e-08]
+[2.80e-08]
+
+
+The :class:`op` class also includes two methods for writing and reading
+files in 
+`MPS format <http://www-fp.mcs.anl.gov/otc/Guide/OptWeb/continuous/constrained/linearprog/mps.html>`_.
+
+.. method:: tofile(filename)
+
+    If the problem is an LP, writes it to the file `filename` using the 
+    MPS format.  Row and column labels are assigned based on the variable 
+    and constraint names in the LP.  
+
+
+.. method:: fromfile(filename)
+
+    Reads the LP from the file `filename`.  The file must be a fixed-format
+    MPS file.  Some features of the MPS format are not supported: comments 
+    beginning with dollar signs, the row types 'DE', 'DL', 'DG', and 'DN', 
+    and the capability of reading multiple righthand side, bound or range 
+    vectors.
+
+
+Examples
+========
+
+
+**Norm and Penalty Approximation**
+
+    In the first example we solve the norm approximation problems
+
+    .. math::
+
+        \begin{array}{ll} 
+        \mbox{minimize} & \|Ax - b\|_\infty,
+        \end{array} 
+        \qquad
+        \begin{array}{ll} 
+        \mbox{minimize} & \|Ax - b\|_1
+        \end{array},
+
+    and the penalty approximation problem
+
+    .. math::
+
+        \begin{array}{ll} 
+        \mbox{minimize} & \sum_k \phi((Ax-b)_k), 
+        \end{array} \qquad
+        \phi(u) = \left\{\begin{array}{ll}
+            0        & |u| \leq 3/4 \\
+            |u|-3/4  & 3/4 \leq |u| \leq 3/2 \\
+            2|u|-9/4 & |u| \geq 3/2.
+        \end{array}\right.
+
+    We use randomly generated data.
+
+    The code uses the `Matplotlib <http://matplotlib.sourceforge.net>`_
+    package for plotting the histograms of the residual vectors for the
+    two solutions.  It generates the figure shown below.
+
+    :: 
+
+        from cvxopt import normal
+        from cvxopt.modeling import variable, op, max, sum
+        import pylab
+
+        m, n = 500, 100
+        A = normal(m,n)
+        b = normal(m)
+
+        x1 = variable(n)
+        op(max(abs(A*x1-b))).solve()
+
+        x2 = variable(n)
+        op(sum(abs(A*x2-b))).solve()
+
+        x3 = variable(n)
+        op(sum(max(0, abs(A*x3-b)-0.75, 2*abs(A*x3-b)-2.25))).solve()
+
+        pylab.subplot(311)
+        pylab.hist(A*x1.value-b, m/5)
+        pylab.subplot(312)
+        pylab.hist(A*x2.value-b, m/5)
+        pylab.subplot(313)
+        pylab.hist(A*x3.value-b, m/5)
+        pylab.show()
+
+
+    .. image:: normappr.png
+       :width: 600px
+
+
+    Equivalently, we can formulate and solve the problems as LPs.
+    
+    ::
+
+        t = variable()
+        x1 = variable(n)
+        op(t, [-t <= A*x1-b, A*x1-b<=t]).solve()
+
+        u = variable(m)
+        x2 = variable(n)
+        op(sum(u), [-u <= A*x2+b, A*x2+b <= u]).solve()
+
+        v = variable(m)
+        x3 = variable(n)
+        op(sum(v), [v >= 0, v >= A*x3+b-0.75, v >= -(A*x3+b)-0.75, v >= 2*(A*x3-b)-2.25, v >= -2*(A*x3-b)-2.25]).solve()
+
+
+
+**Robust Linear Programming**
+
+    The robust LP
+
+    .. math::
+
+        \begin{array}{ll}
+        \mbox{minimize}   & c^T x \\
+        \mbox{subject to} & \sup_{\|v\|_\infty \leq 1} 
+                            (a_i+v)^T x \leq b_i, \qquad i=1,\ldots,m
+        \end{array}
+
+    is equivalent to the problem
+
+    .. math::
+
+        \begin{array}{ll}
+        \mbox{minimize} & c^Tx \\
+        \mbox{subject to} & a_i^Tx + \|x\|_1 \leq b_i, \qquad i=1,\ldots,m.
+        \end{array}
+
+    The following code computes the solution and the solution of the 
+    equivalent LP
+
+    .. math::
+
+        \newcommand{\ones}{{\bf 1}}
+        \begin{array}{ll}
+        \mbox{minimize}   & c^Tx \\
+        \mbox{subject to} & a_i^Tx + \ones^Ty \leq b_i, 
+                            \qquad i=1,\ldots,m \\
+                          & -y \preceq x \preceq y
+        \end{array}
+
+    for randomly generated data.
+
+    :: 
+
+        from cvxopt import normal, uniform
+        from cvxopt.modeling import variable, dot, op, sum 
+
+        m, n = 500, 100
+        A = normal(m,n)
+        b = uniform(m)
+        c = normal(n)
+
+        x = variable(n)
+        op(dot(c,x), A*x+sum(abs(x)) <= b).solve()
+
+        x2 = variable(n)
+        y = variable(n)
+        op(dot(c,x2), [A*x2+sum(y) <= b, -y <= x2, x2 <= y]).solve()
+
+
+
+**1-Norm Support Vector Classifier**
+
+    The following problem arises in classification:
+
+    .. math::
+
+        \newcommand{\ones}{{\bf 1}}
+        \begin{array}{ll}
+        \mbox{minimize}   & \|x\|_1 + \ones^Tu \\
+        \mbox{subject to} & Ax \succeq \ones -u \\
+                          & u \succeq 0.
+        \end{array}
+
+
+    It can be solved as follows.
+
+    ::
+
+        x = variable(A.size[1],'x')
+        u = variable(A.size[0],'u')
+        op(sum(abs(x)) + sum(u), [A*x >= 1-u, u >= 0]).solve()
+
+    An equivalent unconstrained formulation is
+
+    :: 
+
+        x = variable(A.size[1],'x')
+        op(sum(abs(x)) + sum(max(0,1-A*x))).solve()
+
diff --git a/doc/source/normappr.png b/doc/source/normappr.png
new file mode 100644
index 0000000..1a78d78
Binary files /dev/null and b/doc/source/normappr.png differ
diff --git a/doc/source/portfolio1.png b/doc/source/portfolio1.png
new file mode 100644
index 0000000..6b9491e
Binary files /dev/null and b/doc/source/portfolio1.png differ
diff --git a/doc/source/portfolio2.png b/doc/source/portfolio2.png
new file mode 100644
index 0000000..35a368f
Binary files /dev/null and b/doc/source/portfolio2.png differ
diff --git a/doc/source/printing.rst b/doc/source/printing.rst
new file mode 100644
index 0000000..b5847d1
--- /dev/null
+++ b/doc/source/printing.rst
@@ -0,0 +1,113 @@
+.. _c-printing:
+
+*****************
+Matrix Formatting
+*****************
+
+This appendix describes ways to customize the formatting of CVXOPT matrices.
+
+As with other Python objects, the functions :func:`repr` and :func:`str` 
+return strings with printable representations of matrices.  The command 
+'``print A``' executes '``str(A)``', whereas the command '``A``'
+calls '``repr(A)``'.  The following example illustrates the default 
+formatting of dense matrices.
+
+>>> from cvxopt import matrix 
+>>> A = matrix(range(50), (5,10), 'd')
+>>> A  
+<5x10 matrix, tc='d'>
+>>> print A
+[ 0.00e+00  5.00e+00  1.00e+01  1.50e+01  2.00e+01  2.50e+01  3.00e+01 ... ]
+[ 1.00e+00  6.00e+00  1.10e+01  1.60e+01  2.10e+01  2.60e+01  3.10e+01 ... ]
+[ 2.00e+00  7.00e+00  1.20e+01  1.70e+01  2.20e+01  2.70e+01  3.20e+01 ... ]
+[ 3.00e+00  8.00e+00  1.30e+01  1.80e+01  2.30e+01  2.80e+01  3.30e+01 ... ]
+[ 4.00e+00  9.00e+00  1.40e+01  1.90e+01  2.40e+01  2.90e+01  3.40e+01 ... ]
+
+The format is parameterized by the dictionary :data:`options` in the 
+module :mod:`cvxopt.printing`.  The parameters :attr:`options['iformat']` 
+and :attr:`options['dformat']` determine, respectively, how integer and 
+double/complex numbers are printed.  The entries are Python format strings 
+with default values :const:`'\% .2e'` for :const:`'d'` and :const:`'z'` 
+matrices and :const:`\% i'` for :const:`'i'` matrices.  The parameters 
+:attr:`options['width']` and :attr:`options['height']` specify the maximum 
+number of columns and rows that are shown.  If :attr:`options['width']` is 
+set to a negative value, all columns are displayed.  If 
+:attr:`options['height']` is set to a negative value, all rows are 
+displayed.  The default values of :attr:`options['width']` and 
+:attr:`options['height']` are 7 and -1, respectively.
+
+>>> from cvxopt import printing
+>>> printing.options
+{'width': 7, 'dformat': '% .2e', 'iformat': '% i', 'height': -1}
+>>> printing.options['dformat'] = '%.1f'
+>>> printing.options['width'] = -1
+>>> print A
+[ 0.0  5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0]
+[ 1.0  6.0 11.0 16.0 21.0 26.0 31.0 36.0 41.0 46.0]
+[ 2.0  7.0 12.0 17.0 22.0 27.0 32.0 37.0 42.0 47.0]
+[ 3.0  8.0 13.0 18.0 23.0 28.0 33.0 38.0 43.0 48.0]
+[ 4.0  9.0 14.0 19.0 24.0 29.0 34.0 39.0 44.0 49.0]
+
+
+In order to make the built-in Python functions :func:`repr` and :func:`str`
+accessible for further customization, two functions are provided in 
+CVXOPT.  The function :func:`cvxopt.matrix_repr` is used when 
+:func:`repr` is called with a matrix argument; and 
+:func:`cvxopt.matrix_str` is used when :func:`str` is called with a matrix 
+argument.  By default, the functions are set to 
+:func:`printing.matrix_repr_default` and
+:func:`printing.matrix_str_default`, respectively, but they can be 
+redefined to any other Python functions.  For example, if we prefer 
+``A`` to return the same output as ``print A``, we can simply 
+redefine :func:`cvxopt.matrix_repr` as shown below.
+
+>>> import cvxopt
+>>> from cvxopt import matrix, printing
+>>> A = matrix(range(4), (2,2), 'd')
+>>> A
+<2x2 matrix, tc='d'>
+>>> cvxopt.matrix_repr = printing.matrix_str_default
+>>> A
+[ 0.00e+00  2.00e+00]
+[ 1.00e+00  3.00e+00]
+
+
+The formatting for sparse matrices is similar.  The functions :func:`repr` 
+and :func:`str` for sparse matrices are :func:`cvxopt.spmatrix_repr` 
+and :func:`cvxopt.spmatrix_str`, respectively.  By default, they are set to
+:func:`printing.spmatrix_repr_default` and 
+:func:`printing.spmatrix_repr_str`.
+
+
+>>> import cvxopt
+>>> from cvxopt import printing, spmatrix 
+>>> A = spmatrix(range(5), range(5), range(5), (5,10))
+>>> A
+<5x10 sparse matrix, tc='d', nnz=5>
+>>> print A
+[ 0.00e+00     0         0         0         0         0         0     ... ]
+[    0      1.00e+00     0         0         0         0         0     ... ]
+[    0         0      2.00e+00     0         0         0         0     ... ]
+[    0         0         0      3.00e+00     0         0         0     ... ]
+[    0         0         0         0      4.00e+00     0         0     ... ]
+
+>>> cvxopt.spmatrix_repr = printing.spmatrix_str_default
+>>> A
+[ 0.00e+00     0         0         0         0         0         0     ... ]
+[    0      1.00e+00     0         0         0         0         0     ... ]
+[    0         0      2.00e+00     0         0         0         0     ... ]
+[    0         0         0      3.00e+00     0         0         0     ... ]
+[    0         0         0         0      4.00e+00     0         0     ... ]
+
+
+As can be seen from the example, the default behaviour is to print the 
+entire matrix including structural zeros. An alternative triplet printing 
+style is defined in :func:`printing.spmatrix_str_triplet`. 
+
+>>> cvxopt.spmatrix_str = printing.spmatrix_str_triplet
+>>> print A
+(0,0)  0.00e+00
+(1,1)  1.00e+00
+(2,2)  2.00e+00
+(3,3)  3.00e+00
+(4,4)  4.00e+00
diff --git a/doc/source/solvers.rst b/doc/source/solvers.rst
new file mode 100644
index 0000000..ad42e67
--- /dev/null
+++ b/doc/source/solvers.rst
@@ -0,0 +1,1299 @@
+.. _c-solvers:
+
+*****************************
+Nonlinear Convex Optimization
+*****************************
+
+In this chapter we consider nonlinear convex optimization problems of the 
+form 
+
+.. math:: 
+
+    \begin{array}{ll}
+    \mbox{minimize}   & f_0(x) \\
+    \mbox{subject to} & f_k(x) \leq 0, \quad k=1,\ldots,m \\
+                      & G x \preceq h  \\ 
+                      & A x = b.
+    \end{array}
+
+The functions :math:`f_k` are convex and twice differentiable and the 
+linear inequalities are generalized inequalities with respect to a proper 
+convex cone, defined as a product of a nonnegative orthant, second-order 
+cones, and positive semidefinite cones.   
+
+The basic functions are :func:`cp <cvxopt.solvers.cp>` and 
+:func:`cpl <cvxopt.solvers.cpl>`, described in the sections 
+:ref:`s-cp` and :ref:`s-cpl`.   A simpler interface for geometric 
+programming problems is discussed in the section :ref:`s-gp`.  
+In the section :ref:`s-nlcp` we explain how custom solvers can be 
+implemented that exploit structure in specific classes of problems.  
+The last section 
+describes the algorithm parameters that control the solvers.
+
+
+.. _s-cp:
+
+Problems with Nonlinear Objectives 
+==================================
+
+.. function:: cvxopt.solvers.cp(F[, G, h[, dims[, A, b[, kktsolver]]]])
+
+    Solves a convex optimization problem
+
+    .. math:: 
+        :label: e-nlcp
+     
+        \begin{array}{ll}
+            \mbox{minimize}   & f_0(x) \\
+            \mbox{subject to} & f_k(x) \leq 0, \quad k=1,\ldots,m \\
+                              & G x \preceq h  \\ 
+                              & A x = b.
+        \end{array}
+
+    The argument ``F`` is a function that evaluates the objective and 
+    nonlinear constraint functions.  It must handle the following calling 
+    sequences.
+
+    
+    * ``F()`` returns a tuple (``m``, ``x0``), where :math:`m` is 
+      the number of nonlinear constraints and :math:`x_0` is a point in 
+      the domain of :math:`f`.  ``x0`` is a dense real matrix of size 
+      (:math:`n`, 1).
+
+    * ``F(x)``, with ``x`` a dense real matrix of size (:math:`n`, 1), 
+      returns a tuple (``f``, ``Df``).  ``f`` is a dense real matrix of 
+      size (:math:`m+1`, 1), with ``f[k]`` equal to :math:`f_k(x)`. 
+      (If :math:`m` is zero, ``f`` can also be returned as a number.)
+      ``Df`` is a dense or sparse real matrix of size (:math:`m` + 1, 
+      :math:`n`) with ``Df[k,:]`` equal to the transpose of the 
+      gradient :math:`\nabla f_k(x)`.  If :math:`x` is not in the domain 
+      of :math:`f`, ``F(x)`` returns :const:`None` or a tuple 
+      (:const:`None`, :const:`None`).
+
+    * ``F(x,z)``, with ``x`` a dense real matrix of size (:math:`n`, 1)
+      and ``z`` a positive dense real matrix of size (:math:`m` + 1, 1) 
+      returns a tuple (``f``, ``Df``, ``H``).  ``f`` and ``Df`` are 
+      defined as above.  ``H`` is a square dense or sparse real matrix of 
+      size (:math:`n`, :math:`n`), whose lower triangular part contains 
+      the lower triangular part of
+
+      .. math::
+     
+          z_0 \nabla^2f_0(x) + z_1 \nabla^2f_1(x) + \cdots + 
+              z_m \nabla^2f_m(x).
+     
+      If ``F`` is called with two arguments, it can be assumed that 
+      :math:`x` is in the domain of :math:`f`.
+    
+    The linear inequalities are with respect to a cone :math:`C` defined 
+    as a Cartesian product of a nonnegative orthant, a number of 
+    second-order cones, and a number of positive semidefinite cones:
+
+    .. math::
+    
+        C = C_0 \times C_1 \times \cdots \times C_M \times C_{M+1} \times
+            \cdots \times C_{M+N}
+   
+    with
+
+    .. math::
+
+        
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        \newcommand{\svec}{\mathop{\mathbf{vec}}}
+        \newcommand{\symm}{{\mbox{\bf S}}}  
+        \begin{split}
+            C_0 & = 
+                \{ u \in \reals^l \;| \; u_k \geq 0, \; k=1, \ldots,l\},\\
+            C_{k+1} & = \{ (u_0, u_1) \in \reals \times \reals^{r_{k}-1} 
+                \; | \; u_0 \geq \|u_1\|_2 \},  \quad k=0,\ldots, M-1, \\
+            C_{k+M+1} & = \left\{ \svec(u) \; | \; u \in \symm^{t_k}_+ 
+                \right\}, \quad k=0,\ldots,N-1.
+        \end{split}
+
+    Here :math:`\mathbf{vec}(u)` denotes a symmetric matrix :math:`u` 
+    stored as a vector in column major order.  
+
+    The arguments ``h`` and ``b`` are real single-column dense matrices.  
+    ``G`` and ``A`` are real dense or sparse matrices.  The default values
+    for ``A`` and ``b`` are sparse matrices with zero rows, meaning that 
+    there are no equality constraints.  The number of rows of ``G`` and 
+    ``h`` is equal to
+
+    .. math::
+
+        K = l + \sum_{k=0}^{M-1} r_k + \sum_{k=0}^{N-1} t_k^2.
+    
+    The columns of ``G`` and ``h`` are vectors in
+
+    .. math::
+
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        \reals^l \times \reals^{r_0} \times \cdots \times 
+        \reals^{r_{M-1}} \times \reals^{t_0^2}  \times \cdots \times 
+        \reals^{t_{N-1}^2},
+    
+    where the last :math:`N` components represent symmetric matrices stored
+    in column major order.  The strictly upper triangular entries of these 
+    matrices are not accessed (i.e., the symmetric matrices are stored
+    in the :const:`'L'`-type column major order used in the :mod:`blas` 
+    and :mod:`lapack` modules).
+
+    The argument ``dims`` is a dictionary with the dimensions of the cones.
+    It has three fields. 
+
+    ``dims['l']``: 
+        :math:`l`, the dimension of the nonnegative orthant (a nonnegative
+        integer).
+
+    ``dims['q']``: 
+        :math:`[r_0, \ldots, r_{M-1}]`, a list with the dimensions of the 
+        second-order cones (positive integers).
+
+    ``dims['s']``: 
+        :math:`[t_0, \ldots, t_{N-1}]`, a list with the dimensions of the 
+        positive semidefinite cones (nonnegative integers).
+    
+    The default value of ``dims`` is 
+    ``{'l': h.size[0], 'q': [], 's': []}``, i.e., the default 
+    assumption is that the linear inequalities are componentwise 
+    inequalities.
+
+    The role of the optional argument ``kktsolver`` is explained in the 
+    section :ref:`s-nlcp`.  
+
+    :func:`cp` returns a dictionary that contains the result and 
+    information about the accuracy of the solution.  The most important 
+    fields have keys :const:`'status'`, :const:`'x'`, :const:`'snl'`, 
+    :const:`'sl'`, :const:`'y'`, :const:`'znl'`, :const:`'zl'`.  The 
+    possible values of the :const:`'status'` key are:
+
+    :const:`'optimal'`  
+        In this case the :const:`'x'` entry of the dictionary is the primal
+        optimal solution, the :const:`'snl'` and :const:`'sl'` entries are 
+        the corresponding slacks in the nonlinear and linear inequality 
+        constraints, and the :const:`'znl'`, :const:`'zl'` and :const:`'y'`
+        entries are the optimal values of the dual variables associated 
+        with the nonlinear inequalities, the linear inequalities, and the 
+        linear equality constraints.  These vectors approximately satisfy 
+        the Karush-Kuhn-Tucker (KKT) conditions
+
+        .. math::
+        
+            \nabla f_0(x) +  D\tilde f(x)^T z_\mathrm{nl} + 
+            G^T z_\mathrm{l} + A^T y = 0,
+
+            \tilde f(x) + s_\mathrm{nl} = 0, \quad k=1,\ldots,m, \qquad
+            Gx + s_\mathrm{l} = h, \qquad Ax = b,
+       
+            s_\mathrm{nl}\succeq 0, \qquad s_\mathrm{l}\succeq 0, \qquad 
+            z_\mathrm{nl} \succeq 0, \qquad z_\mathrm{l} \succeq 0,
+
+            s_\mathrm{nl}^T z_\mathrm{nl} +  
+            s_\mathrm{l}^T z_\mathrm{l} = 0
+
+        where :math:`\tilde f = (f_1,\ldots, f_m)`.
+    
+
+    :const:`'unknown'` 
+        This indicates that the algorithm terminated before a solution was 
+        found, due to numerical difficulties or because the maximum number
+        of iterations was reached.  The :const:`'x'`, :const:`'snl'`, 
+        :const:`'sl'`, :const:`'y'`, :const:`'znl'`, and :const:`'zl'` 
+        entries contain the iterates when the algorithm terminated.
+    
+    :func:`cp` solves the problem by applying 
+    :func:`cpl <cvxopt.solvers.cpl>` to the epigraph 
+    form problem
+
+    .. math:: 
+        \begin{array}{ll}
+        \mbox{minimize}   & t \\ 
+        \mbox{subject to} & f_0(x) \leq t  \\ 
+                          & f_k(x) \leq 0, \quad k =1, \ldots, m \\
+                          & Gx \preceq h \\
+                          & Ax = b.
+        \end{array}
+
+    The other entries in the output dictionary of :func:`cp` describe
+    the accuracy of the solution and are copied from the output of 
+    :func:`cpl <cvxopt.solvers.cpl>` applied to this epigraph form 
+    problem.
+
+    :func:`cp` requires that the problem is strictly primal and dual
+    feasible and that 
+    
+    .. math::
+    
+        \newcommand{\Rank}{\mathop{\bf rank}}
+        \Rank(A) = p, \qquad 
+        \Rank \left( \left[ \begin{array}{cccccc} 
+             \sum_{k=0}^m z_k \nabla^2 f_k(x) & A^T &
+              \nabla f_1(x) & \cdots \nabla f_m(x) & G^T 
+              \end{array} \right] \right) = n,
+    
+    for all :math:`x` and all positive :math:`z`. 
+
+
+**Example: equality constrained analytic centering**
+    The equality constrained analytic centering problem is defined as
+    
+    .. math::
+     
+        \begin{array}{ll}
+        \mbox{minimize} & -\sum_{i=1}^m \log x_i \\
+        \mbox{subject to} & Ax = b. 
+        \end{array}
+
+    The function :func:`acent` defined  below solves the problem, assuming
+    it is solvable.
+
+    :: 
+       
+        from cvxopt import solvers, matrix, spdiag, log
+
+        def acent(A, b):
+            m, n = A.size
+            def F(x=None, z=None):
+                if x is None: return 0, matrix(1.0, (n,1))
+                if min(x) <= 0.0: return None
+                f = -sum(log(x))
+                Df = -(x**-1).T 
+                if z is None: return f, Df
+                H = spdiag(z[0] * x**-2)
+                return f, Df, H
+            return solvers.cp(F, A=A, b=b)['x']
+
+
+**Example: robust least-squares**
+    The function :func:`robls` defined below solves the unconstrained 
+    problem
+    
+    .. math::
+
+        \begin{array}{ll}
+        \mbox{minimize} &  \sum_{k=1}^m \phi((Ax-b)_k), 
+        \end{array} 
+        \qquad \phi(u) = \sqrt{\rho + u^2},
+
+    where :math:`A \in\mathbf{R}^{m\times n}`.
+
+    ::
+
+        from cvxopt import solvers, matrix, spdiag, sqrt, div
+
+        def robls(A, b, rho): 
+            m, n = A.size
+            def F(x=None, z=None):
+                if x is None: return 0, matrix(0.0, (n,1))
+                y = A*x-b
+                w = sqrt(rho + y**2)
+                f = sum(w)
+                Df = div(y, w).T * A 
+                if z is None: return f, Df 
+                H = A.T * spdiag(z[0]*rho*(w**-3)) * A
+                return f, Df, H
+            return solvers.cp(F)['x']
+
+
+**Example: analytic centering with cone constraints**
+
+    .. math::
+
+         \begin{array}{ll}
+         \mbox{minimize} 
+             & -\log(1-x_1^2) -\log(1-x_2^2) -\log(1-x_3^2) \\
+         \mbox{subject to} 
+             & \|x\|_2 \leq 1 \\
+             & x_1 \left[\begin{array}{rrr} 
+                   -21 & -11 & 0 \\ -11 & 10 & 8 \\ 0 & 8 & 5 
+                    \end{array}\right] +
+               x_2 \left[\begin{array}{rrr} 
+                    0 & 10 & 16 \\ 10 & -10 & -10 \\ 16 & -10 & 3 
+                   \end{array}\right] +
+               x_3 \left[\begin{array}{rrr} 
+                   -5 & 2 & -17 \\ 2 & -6 & 8 \\ -17 & -7 & 6 
+                   \end{array}\right] 
+               \preceq \left[\begin{array}{rrr}
+                   20 & 10 & 40 \\ 10 & 80 & 10 \\ 40 & 10 & 15 
+                   \end{array}\right].
+         \end{array}
+
+    :: 
+
+        from cvxopt import matrix, log, div, spdiag, solvers
+
+        def F(x = None, z = None):
+             if x is None:  return 0, matrix(0.0, (3,1)) 
+             if max(abs(x)) >= 1.0:  return None
+             u = 1 - x**2
+             val = -sum(log(u))
+             Df = div(2*x, u).T
+             if z is None:  return val, Df
+             H = spdiag(2 * z[0] * div(1 + u**2, u**2))
+             return val, Df, H
+
+        G = matrix([ [0., -1.,  0.,  0., -21., -11.,   0., -11.,  10.,   8.,   0.,   8., 5.], 
+                     [0.,  0., -1.,  0.,   0.,  10.,  16.,  10., -10., -10.,  16., -10., 3.], 
+                     [0.,  0.,  0., -1.,  -5.,   2., -17.,   2.,  -6.,   8., -17.,  -7., 6.] ])  
+        h = matrix([1.0, 0.0, 0.0, 0.0, 20., 10., 40., 10., 80., 10., 40., 10., 15.])
+        dims = {'l': 0, 'q': [4], 's':  [3]}
+        sol = solvers.cp(F, G, h, dims)
+        print sol['x']
+        [ 4.11e-01]
+        [ 5.59e-01]
+        [-7.20e-01]
+
+
+.. _s-cpl:
+
+Problems with Linear Objectives 
+===============================
+
+.. function:: cvxopt.solvers.cpl(c, F[, G, h[, dims[, A, b[, kktsolver]]]])
+
+    Solves a convex optimization problem with a linear objective
+
+    .. math:: 
+
+        \begin{array}{ll}
+        \mbox{minimize}   & c^T x \\
+        \mbox{subject to} & f_k(x) \leq 0, \quad k=0,\ldots,m-1 \\
+                          & G x \preceq h  \\ 
+                          & A x = b.
+        \end{array}
+
+    ``c`` is a real single-column dense matrix.  
+
+    ``F`` is a function that evaluates the nonlinear constraint functions.
+    It must handle the following calling sequences.
+
+    * ``F()`` returns a tuple (``m``, ``x0``), where ``m`` is the 
+      number of nonlinear constraints and ``x0`` is a point in the domain 
+      of :math:`f`.  ``x0`` is a dense real matrix of size (:math:`n`, 1).
+
+    * ``F(x)``, with ``x`` a dense real matrix of size (:math:`n`, 1),
+      returns a tuple (``f``, ``Df``).  ``f`` is a dense real matrix of 
+      size (:math:`m`, 1), with ``f[k]`` equal to :math:`f_k(x)`. 
+      ``Df`` is a dense or sparse real matrix of size (:math:`m`, 
+      :math:`n`) with ``Df[k,:]`` equal to the transpose of the 
+      gradient :math:`\nabla f_k(x)`.  If :math:`x` is not in the domain 
+      of :math:`f`, ``F(x)`` returns :const:`None` or a tuple 
+      (:const:`None`, :const:`None`).
+
+    * ``F(x,z)``, with ``x`` a dense real matrix of size (:math:`n`, 1)
+      and ``z`` a positive dense real matrix of size (:math:`m`, 1) 
+      returns a tuple (``f``, ``Df``, ``H``).  ``f`` and ``Df`` are defined
+      as above.  ``H`` is a square dense or sparse real matrix of size 
+      (:math:`n`, :math:`n`), whose lower triangular part contains the 
+      lower triangular part of
+  
+      .. math::
+
+          z_0 \nabla^2f_0(x) + z_1 \nabla^2f_1(x) + \cdots + 
+          z_{m-1} \nabla^2f_{m-1}(x).
+
+      If ``F`` is called with two arguments, it can be assumed that 
+      :math:`x` is in the domain of :math:`f`.
+    
+    The linear inequalities are with respect to a cone :math:`C` defined as
+    a Cartesian product of a nonnegative orthant, a number of second-order 
+    cones, and a number of positive semidefinite cones:
+    
+    .. math::
+
+        C = C_0 \times C_1 \times \cdots \times C_M \times C_{M+1} \times
+        \cdots \times C_{M+N}
+    
+    with
+   
+    .. math:: 
+
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        \newcommand{\svec}{\mathop{\mathbf{vec}}}
+        \newcommand{\symm}{{\mbox{\bf S}}}  
+        \begin{split}
+        C_0 &= \{ u \in \reals^l \;| \; u_k \geq 0, \; k=1, \ldots,l\}, \\ 
+        C_{k+1} &= \{ (u_0, u_1) \in \reals \times \reals^{r_{k}-1} \; | \;
+            u_0 \geq \|u_1\|_2 \},  \quad k=0,\ldots, M-1, \\ 
+        C_{k+M+1} &= \left\{ \svec(u) \; | \;
+            u \in \symm^{t_k}_+ \right\}, \quad k=0,\ldots,N-1.
+        \end{split}
+    
+    Here :math:`\mathbf{vec}(u)` denotes a symmetric matrix :math:`u` 
+    stored as a vector in column major order.  
+
+    The arguments ``h`` and ``b`` are real single-column dense matrices.  
+    ``G`` and ``A`` are real dense or sparse matrices.  The default values
+    for ``A`` and ``b`` are sparse matrices with zero rows, meaning that 
+    there are no equality constraints.  The number of rows of ``G`` and 
+    ``h`` is equal to
+
+    .. math::
+    
+        K = l + \sum_{k=0}^{M-1} r_k + \sum_{k=0}^{N-1} t_k^2.
+    
+    The columns of ``G`` and ``h`` are vectors in
+
+    .. math:: 
+
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        \reals^l \times \reals^{r_0} \times \cdots \times 
+        \reals^{r_{M-1}} \times \reals^{t_0^2}  \times \cdots \times 
+        \reals^{t_{N-1}^2},
+    
+    where the last :math:`N` components represent symmetric matrices stored
+    in column major order.  The strictly upper triangular entries of these 
+    matrices are not accessed (i.e., the symmetric matrices are stored
+    in the :const:`'L'`-type column major order used in the :mod:`blas` and
+    :mod:`lapack` modules.
+
+    The argument ``dims`` is a dictionary with the dimensions of the cones.
+    It has three fields. 
+
+    ``dims['l']``: 
+        :math:`l`, the dimension of the nonnegative orthant (a nonnegative
+        integer).
+
+    ``dims['q']``: 
+        :math:`[r_0, \ldots, r_{M-1}]`, a list with the dimensions of the 
+        second-order cones (positive integers).
+
+    ``dims['s']``: 
+        :math:`[t_0, \ldots, t_{N-1}]`, a list with the dimensions of the 
+        positive semidefinite cones (nonnegative integers).
+
+    The default value of ``dims`` is 
+    ``{'l': h.size[0], 'q': [], 's': []}``, i.e., the default 
+    assumption is that the linear inequalities are componentwise 
+    inequalities.
+
+    The role of the optional argument ``kktsolver`` is explained in the
+    section :ref:`s-nlcp`.  
+
+    :func:`cpl` returns a dictionary that contains the result and 
+    information about the accuracy of the solution.  The most important 
+    fields have keys :const:`'status'`, :const:`'x'`, :const:`'snl'`, 
+    :const:`'sl'`, :const:`'y'`, :const:`'znl'`, :const:`'zl'`. 
+    The possible values of the :const:`'status'` key are:
+
+    :const:`'optimal'` 
+        In this case the :const:`'x'` entry of the dictionary is the primal
+        optimal solution, the :const:`'snl'` and :const:`'sl'` entries are
+        the corresponding slacks in the nonlinear and linear inequality 
+        constraints, and the :const:`'znl'`, :const:`'zl'`, and 
+        :const:`'y'` entries are the optimal values of the dual variables 
+        associated with the nonlinear inequalities, the linear 
+        inequalities, and the linear equality constraints.  These vectors 
+        approximately satisfy the Karush-Kuhn-Tucker (KKT) conditions
+        
+        .. math:: 
+
+            c +  Df(x)^T z_\mathrm{nl} + G^T z_\mathrm{l} + A^T y = 0,
+            
+            f(x) + s_\mathrm{nl} = 0, \quad k=1,\ldots,m, \qquad
+                Gx + s_\mathrm{l} = h, \qquad Ax = b,
+      
+     
+            s_\mathrm{nl}\succeq 0, \qquad s_\mathrm{l}\succeq 0, \qquad 
+                z_\mathrm{nl} \succeq 0, \qquad z_\mathrm{l} \succeq 0,
+
+            s_\mathrm{nl}^T z_\mathrm{nl} +  s_\mathrm{l}^T z_\mathrm{l} 
+                = 0.
+
+    :const:`'unknown'` 
+        This indicates that the algorithm terminated before a solution was
+        found, due to numerical difficulties or because the maximum number
+        of iterations was reached.  The :const:`'x'`, :const:`'snl'`, 
+        :const:`'sl'`, :const:`'y'`, :const:`'znl'`, and :const:`'zl'` 
+        entries contain the iterates when the algorithm terminated.
+
+    The other entries in the output dictionary describe the accuracy
+    of the solution.  The entries :const:`'primal objective'`, 
+    :const:`'dual objective'`, :const:`'gap'`, and :const:`'relative gap'`     give the primal objective :math:`c^Tx`, the dual objective, calculated 
+    as
+
+    .. math:: 
+   
+        c^Tx + z_\mathrm{nl}^T f(x) + z_\mathrm{l}^T (Gx - h) + y^T(Ax-b),
+    
+    the duality gap 
+   
+    .. math:: 
+
+        s_\mathrm{nl}^T z_\mathrm{nl} +  s_\mathrm{l}^T z_\mathrm{l},
+    
+    and the relative gap.  The relative gap is defined as 
+    
+    .. math:: 
+
+        \frac{\mbox{gap}}{-\mbox{primal objective}}
+            \quad \mbox{if\ } \mbox{primal objective} < 0, \qquad
+        \frac{\mbox{gap}}{\mbox{dual objective}}
+            \quad \mbox{if\ } \mbox{dual objective} > 0, 
+    
+    and :const:`None` otherwise.  The entry with key 
+    :const:`'primal infeasibility'` gives the residual in the primal 
+    constraints, 
+   
+    .. math::
+
+        \newcommand{\ones}{{\bf 1}}
+        \frac{\| ( f(x) + s_{\mathrm{nl}},  Gx + s_\mathrm{l} - h, 
+            Ax-b ) \|_2} {\max\{1, \| ( f(x_0) + \ones,  
+        Gx_0 + \ones-h, Ax_0-b) \|_2 \}} 
+   
+    where :math:`x_0` is the point returned by ``F()``.  The entry 
+    with key :const:`'dual infeasibility'` gives the residual
+
+    .. math::
+
+        \newcommand{\ones}{{\bf 1}}
+        \frac
+            { \| c +  Df(x)^Tz_\mathrm{nl} + G^Tz_\mathrm{l} + A^T y \|_2}
+            { \max\{ 1, \| c + Df(x_0)^T\ones + G^T\ones \|_2 \} }.
+
+    :func:`cpl` requires that the problem is strictly primal and dual 
+    feasible and that 
+
+    .. math::
+
+        \newcommand{\Rank}{\mathop{\bf rank}}
+        \Rank(A) = p, \qquad 
+        \Rank\left(\left[\begin{array}{cccccc} 
+            \sum_{k=0}^{m-1} z_k \nabla^2 f_k(x) & A^T &
+            \nabla f_0(x) & \cdots \nabla f_{m-1}(x) & G^T 
+            \end{array}\right]\right) = n,
+    
+    for all :math:`x` and all positive :math:`z`. 
+
+
+**Example: floor planning**
+    This example is the floor planning problem of section 8.8.2 in the book
+    `Convex Optimization <http://www.stanford.edu/~boyd/cvxbook>`_:
+
+    .. math:: 
+
+        \begin{array}{ll}
+        \mbox{minimize}    & W + H \\
+        \mbox{subject to} 
+            & A_{\mathrm{min}, k}/h_k - w_k \leq 0, \quad k=1,\ldots, 5 \\ 
+            & x_1 \geq 0, \quad x_2 \geq 0,  \quad x_4 \geq 0 \\
+            & x_1 + w_1 + \rho \leq x_3, \quad x_2 + w_2 + \rho \leq x_3, 
+              \quad x_3 + w_3 + \rho \leq x_5,  \\
+            & x_4 + w_4 + \rho \leq x_5, \quad x_5 + w_5 \leq W \\
+            & y_2 \geq 0,  \quad y_3 \geq 0, \quad y_5 \geq 0  \\
+            & y_2 + h_2 + \rho \leq y_1, \quad y_1 + h_1 + \rho \leq y_4, 
+              y_3 + h_3 + \rho \leq y_4, \\
+            & y_4 + h_4 \leq H, \quad y_5 + h_5 \leq H \\
+            & h_k/\gamma \leq w_k \leq \gamma h_k, \quad k=1,\ldots,5.
+        \end{array}
+
+    This problem has 22 variables 
+
+    .. math:: 
+
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        W, \qquad H, \qquad x\in\reals^5, \qquad y\in\reals^5, \qquad
+        w\in\reals^5, \qquad h\in\reals^5,
+
+    5 nonlinear inequality constraints, and 26 linear inequality 
+    constraints.  The code belows defines a function :func:`floorplan` 
+    that solves the problem by calling :func:`cp`, then applies it to 
+    4 instances, and creates a figure.
+
+    :: 
+
+        import pylab
+        from cvxopt import solvers, matrix, spmatrix, mul, div
+
+        def floorplan(Amin):
+
+            #     minimize    W+H
+            #     subject to  Amink / hk <= wk, k = 1,..., 5 
+            #                 x1 >= 0,  x2 >= 0, x4 >= 0
+            #                 x1 + w1 + rho <= x3  
+            #                 x2 + w2 + rho <= x3 
+            #                 x3 + w3 + rho <= x5  
+            #                 x4 + w4 + rho <= x5
+            #                 x5 + w5 <= W
+            #                 y2 >= 0,  y3 >= 0,  y5 >= 0 
+            #                 y2 + h2 + rho <= y1 
+            #                 y1 + h1 + rho <= y4 
+            #                 y3 + h3 + rho <= y4
+            #                 y4 + h4 <= H  
+            #                 y5 + h5 <= H
+            #                 hk/gamma <= wk <= gamma*hk,  k = 1, ..., 5
+            #
+            # 22 Variables W, H, x (5), y (5), w (5), h (5).
+            #
+            # W, H:  scalars; bounding box width and height
+            # x, y:  5-vectors; coordinates of bottom left corners of blocks
+            # w, h:  5-vectors; widths and heigths of the 5 blocks
+
+            rho, gamma = 1.0, 5.0   # min spacing, min aspect ratio
+
+            # The objective is to minimize W + H.  There are five nonlinear 
+            # constraints 
+            #
+            #     -wk + Amink / hk <= 0,  k = 1, ..., 5
+
+            c = matrix(2*[1.0] + 20*[0.0])
+
+            def F(x=None, z=None):
+                if x is None:  return 5, matrix(17*[0.0] + 5*[1.0])
+                if min(x[17:]) <= 0.0:  return None 
+                f = -x[12:17] + div(Amin, x[17:]) 
+                Df = matrix(0.0, (5,22))
+                Df[:,12:17] = spmatrix(-1.0, range(5), range(5))
+                Df[:,17:] = spmatrix(-div(Amin, x[17:]**2), range(5), range(5))
+                if z is None: return f, Df
+                H = spmatrix( 2.0* mul(z, div(Amin, x[17::]**3)), range(17,22), range(17,22) )
+                return f, Df, H
+
+            G = matrix(0.0, (26,22)) 
+            h = matrix(0.0, (26,1))
+            G[0,2] = -1.0                                       # -x1 <= 0
+            G[1,3] = -1.0                                       # -x2 <= 0 
+            G[2,5] = -1.0                                       # -x4 <= 0
+            G[3, [2, 4, 12]], h[3] = [1.0, -1.0, 1.0], -rho     # x1 - x3 + w1 <= -rho 
+            G[4, [3, 4, 13]], h[4] = [1.0, -1.0, 1.0], -rho     # x2 - x3 + w2 <= -rho 
+            G[5, [4, 6, 14]], h[5] = [1.0, -1.0, 1.0], -rho     # x3 - x5 + w3 <= -rho 
+            G[6, [5, 6, 15]], h[6] = [1.0, -1.0, 1.0], -rho     # x4 - x5 + w4 <= -rho 
+            G[7, [0, 6, 16]] = -1.0, 1.0, 1.0                   # -W + x5 + w5 <= 0
+            G[8,8] = -1.0                                       # -y2 <= 0 
+            G[9,9] = -1.0                                       # -y3 <= 0 
+            G[10,11] = -1.0                                     # -y5 <= 0 
+            G[11, [7, 8, 18]], h[11] = [-1.0, 1.0, 1.0], -rho   # -y1 + y2 + h2 <= -rho 
+            G[12, [7, 10, 17]], h[12] = [1.0, -1.0, 1.0], -rho  #  y1 - y4 + h1 <= -rho 
+            G[13, [9, 10, 19]], h[13] = [1.0, -1.0, 1.0], -rho  #  y3 - y4 + h3 <= -rho 
+            G[14, [1, 10, 20]] = -1.0, 1.0, 1.0                 # -H + y4 + h4 <= 0  
+            G[15, [1, 11, 21]] = -1.0, 1.0, 1.0                 # -H + y5 + h5 <= 0
+            G[16, [12, 17]] = -1.0, 1.0/gamma                   # -w1 + h1/gamma <= 0 
+            G[17, [12, 17]] = 1.0, -gamma                       #  w1 - gamma * h1 <= 0
+            G[18, [13, 18]] = -1.0, 1.0/gamma                   # -w2 + h2/gamma <= 0 
+            G[19, [13, 18]] = 1.0, -gamma                       #  w2 - gamma * h2 <= 0
+            G[20, [14, 18]] = -1.0, 1.0/gamma                   # -w3 + h3/gamma <= 0  
+            G[21, [14, 19]] = 1.0, -gamma                       #  w3 - gamma * h3 <= 0
+            G[22, [15, 19]] = -1.0, 1.0/gamma                   # -w4  + h4/gamma <= 0 
+            G[23, [15, 20]] = 1.0, -gamma                       #  w4 - gamma * h4 <= 0
+            G[24, [16, 21]] = -1.0, 1.0/gamma                   # -w5 + h5/gamma <= 0 
+            G[25, [16, 21]] = 1.0, -gamma                       #  w5 - gamma * h5 <= 0.0
+
+            # solve and return W, H, x, y, w, h 
+            sol = solvers.cpl(c, F, G, h)  
+            return  sol['x'][0], sol['x'][1], sol['x'][2:7], sol['x'][7:12], sol['x'][12:17], sol['x'][17:] 
+
+        pylab.figure(facecolor='w')
+        pylab.subplot(221)
+        Amin = matrix([100., 100., 100., 100., 100.])
+        W, H, x, y, w, h =  floorplan(Amin)
+        for k in xrange(5):
+            pylab.fill([x[k], x[k], x[k]+w[k], x[k]+w[k]], 
+                       [y[k], y[k]+h[k], y[k]+h[k], y[k]], facecolor = '#D0D0D0')
+            pylab.text(x[k]+.5*w[k], y[k]+.5*h[k], "%d" %(k+1))
+        pylab.axis([-1.0, 26, -1.0, 26])
+        pylab.xticks([])
+        pylab.yticks([])
+
+        pylab.subplot(222)
+        Amin = matrix([20., 50., 80., 150., 200.])
+        W, H, x, y, w, h =  floorplan(Amin)
+        for k in xrange(5):
+            pylab.fill([x[k], x[k], x[k]+w[k], x[k]+w[k]], 
+                       [y[k], y[k]+h[k], y[k]+h[k], y[k]], 'facecolor = #D0D0D0')
+            pylab.text(x[k]+.5*w[k], y[k]+.5*h[k], "%d" %(k+1))
+        pylab.axis([-1.0, 26, -1.0, 26])
+        pylab.xticks([])
+        pylab.yticks([])
+
+        pylab.subplot(223)
+        Amin = matrix([180., 80., 80., 80., 80.])
+        W, H, x, y, w, h =  floorplan(Amin)
+        for k in xrange(5):
+            pylab.fill([x[k], x[k], x[k]+w[k], x[k]+w[k]], 
+                       [y[k], y[k]+h[k], y[k]+h[k], y[k]], 'facecolor = #D0D0D0')
+            pylab.text(x[k]+.5*w[k], y[k]+.5*h[k], "%d" %(k+1))
+        pylab.axis([-1.0, 26, -1.0, 26])
+        pylab.xticks([])
+        pylab.yticks([])
+
+        pylab.subplot(224)
+        Amin = matrix([20., 150., 20., 200., 110.])
+        W, H, x, y, w, h =  floorplan(Amin)
+        for k in xrange(5):
+            pylab.fill([x[k], x[k], x[k]+w[k], x[k]+w[k]], 
+                       [y[k], y[k]+h[k], y[k]+h[k], y[k]], 'facecolor = #D0D0D0')
+            pylab.text(x[k]+.5*w[k], y[k]+.5*h[k], "%d" %(k+1))
+        pylab.axis([-1.0, 26, -1.0, 26])
+        pylab.xticks([])
+        pylab.yticks([])
+
+        pylab.show()
+
+
+    .. image:: floorplan.png
+       :width: 600px
+
+
+.. _s-gp:
+
+Geometric Programming 
+=====================
+
+.. function:: cvxopt.solvers.gp(K, F, g[, G, h[, A, b]])
+
+    Solves a geometric program in convex form
+
+    .. math::
+    
+        \newcommand{\lse}{\mathop{\mathbf{lse}}}
+        \begin{array}{ll}
+        \mbox{minimize}   & f_0(x) = \lse(F_0x+g_0) \\ 
+        \mbox{subject to} & f_i(x) = \lse(F_ix+g_i) \leq 0, 
+                            \quad i=1,\ldots,m \\
+                          & Gx \preceq h \\
+                          & Ax=b
+        \end{array}
+   
+    where
+
+    .. math::
+    
+        \newcommand{\lse}{\mathop{\mathbf{lse}}}
+        \lse(u) = \log \sum_k \exp(u_k), \qquad
+        F = \left[ \begin{array}{cccc}
+             F_0^T & F_1^T & \cdots & F_m^T 
+            \end{array}\right]^T, \qquad
+        g = \left[ \begin{array}{cccc}
+             g_0^T & g_1^T & \cdots & g_m^T 
+            \end{array}\right]^T, 
+   
+    and the vector inequality denotes componentwise inequality.
+    ``K`` is a list of :math:`m` + 1 positive integers with ``K[i]``
+    equal to the number of rows in :math:`F_i`.  ``F`` is a dense or 
+    sparse real matrix of size ``(sum(K), n)``.
+    ``g`` is a dense real matrix with one column and the same number of
+    rows as ``F``.
+    ``G`` and ``A`` are dense or sparse real matrices.  Their default 
+    values are sparse matrices with zero rows.
+    ``h`` and ``b`` are dense real matrices with one column.  Their 
+    default values are matrices of size (0, 1).
+
+    :func:`gp` returns a dictionary with keys :const:`'status'`, 
+    :const:`'x'`, :const:`'snl'`, :const:`'sl'`, :const:`'y'`, 
+    :const:`'znl'`, and :const:`'zl'`.  The possible values of the 
+    :const:`'status'` key are:
+
+    :const:`'optimal'`  
+        In this case the :const:`'x'` entry is the primal optimal solution,
+        the :const:`'snl'` and :const:`'sl'` entries are the corresponding
+        slacks in the nonlinear and linear inequality constraints.  The 
+        :const:`'znl'`, :const:`'zl'`, and :const:`'y'` entries are the 
+        optimal values of the dual variables associated with the nonlinear 
+        and linear inequality constraints and the linear equality 
+        constraints.  These values approximately satisfy
+
+        .. math::
+
+            \nabla f_0(x) + \sum_{k=1}^m z_{\mathrm{nl},k} 
+                \nabla f_k(x) + G^T z_\mathrm{l} + A^T y = 0,
+
+            f_k(x) + s_{\mathrm{nl},k} = 0, \quad k = 1,\ldots,m
+            \qquad Gx + s_\mathrm{l} = h, \qquad Ax = b,
+
+            s_\mathrm{nl}\succeq 0, \qquad s_\mathrm{l}\succeq 0, \qquad 
+            z_\mathrm{nl} \succeq 0, \qquad z_\mathrm{l} \succeq 0,
+
+            s_\mathrm{nl}^T z_\mathrm{nl} + s_\mathrm{l}^T z_\mathrm{l} =0.
+       
+
+    :const:`'unknown'` 
+        This indicates that the algorithm terminated before a solution was
+        found, due to numerical difficulties or because the maximum number
+        of iterations was reached.  The :const:`'x'`, :const:`'snl'`, 
+        :const:`'sl'`, :const:`'y'`, :const:`'znl'`, and :const:`'zl'` 
+        contain the iterates when the algorithm terminated.
+
+    The other entries in the output dictionary describe the accuracy
+    of the solution, and are taken from the output of 
+    :func:`cp <cvxopt.solvers.cp>`.
+
+
+As an example, we solve the small GP of section 2.4 of the paper 
+`A Tutorial on Geometric Programming 
+<http://www.stanford.edu/~boyd/gp_tutorial.html>`_.
+The  posynomial form of the problem is
+
+.. math::
+
+    \begin{array}{ll}
+    \mbox{minimize} 
+        & w^{-1} h^{-1} d^{-1} \\ 
+    \mbox{subject to} 
+        & (2/A_\mathrm{wall}) hw + (2/A_\mathrm{wall})hd \leq 1  \\
+        &  (1/A_\mathrm{flr}) wd \leq 1 \\
+        &  \alpha wh^{-1} \leq 1 \\
+        &  (1/\beta) hw^{-1} \leq 1 \\
+        &  \gamma wd^{-1} \leq 1 \\
+        &   (1/\delta)dw^{-1} \leq 1
+     \end{array}
+
+with variables :math:`h`, :math:`w`, :math:`d`.
+
+:: 
+
+    from cvxopt import matrix, log, exp, solvers
+
+    Aflr  = 1000.0
+    Awall = 100.0
+    alpha = 0.5
+    beta  = 2.0
+    gamma = 0.5
+    delta = 2.0
+
+    F = matrix( [[-1., 1., 1., 0., -1.,  1.,  0.,  0.], 
+                 [-1., 1., 0., 1.,  1., -1.,  1., -1.], 
+                 [-1., 0., 1., 1.,  0.,  0., -1.,  1.]])
+    g = log( matrix( [1.0, 2/Awall, 2/Awall, 1/Aflr, alpha, 1/beta, gamma, 1/delta]) )
+    K = [1, 2, 1, 1, 1, 1, 1]
+    h, w, d = exp( solvers.gp(K, F, g)['x'] )
+
+
+
+.. _s-nlcp:
+
+Exploiting Structure
+====================
+
+By default, the functions :func:`cp <cvxopt.solvers.cp>` and 
+:func:`cpl <cvxopt.solvers.cpl>` do not exploit problem
+structure.  Two mechanisms are provided for implementing customized solvers
+that take advantage of problem structure.
+
+**Providing a function for solving KKT equations**
+    The most expensive step of each iteration of 
+    :func:`cp <cvxopt.solvers.cp>` is the
+    solution of a set of linear equations (*KKT equations*) of the form
+
+    .. math::
+        :label: e-cp-kkt
+
+        \left[\begin{array}{ccc}
+            H        & A^T & \tilde G^T \\
+            A        & 0   & 0  \\
+            \tilde G & 0   & -W^T W 
+        \end{array}\right]
+        \left[\begin{array}{c} u_x \\ u_y \\ u_z \end{array}\right]
+        =   
+        \left[\begin{array}{c} b_x \\ b_y \\ b_z \end{array}\right],
+
+    where 
+
+    .. math::
+    
+        H = \sum_{k=0}^m z_k \nabla^2f_k(x), \qquad
+        \tilde G = \left[\begin{array}{cccc}
+        \nabla f_1(x) & \cdots & \nabla f_m(x) & G^T \end{array}\right]^T.
+    
+    The matrix :math:`W` depends on the current iterates and is defined as 
+    follows.  Suppose 
+
+    .. math::
+
+        \newcommand{\svec}{\mathop{\mathbf{vec}}}
+        u = \left( u_\mathrm{nl}, \; u_\mathrm{l}, \; u_{\mathrm{q},0}, \; 
+            \ldots, \; u_{\mathrm{q},M-1}, \; \svec{(u_{\mathrm{s},0})}, \;
+            \ldots, \; \svec{(u_{\mathrm{s},N-1})} \right), \qquad
+
+    where
+
+    .. math::
+
+        \newcommand{\reals}{{\mbox{\bf R}}}
+        \newcommand{\symm}{{\mbox{\bf S}}}  
+        u_\mathrm{nl} \in \reals^m, \qquad 
+        u_\mathrm{l} \in \reals^l, \qquad 
+        u_{\mathrm{q},k} \in \reals^{r_k}, \quad k = 0, \ldots, M-1, 
+        \qquad 
+        u_{\mathrm{s},k} \in \symm^{t_k},  \quad k = 0, \ldots, N-1.
+
+    Then :math:`W` is a block-diagonal matrix, 
+
+    .. math::
+    
+        \newcommand{\svec}{\mathop{\mathbf{vec}}}
+        Wu = \left( W_\mathrm{nl} u_\mathrm{nl}, \; 
+             W_\mathrm{l} u_\mathrm{l}, \;
+             W_{\mathrm{q},0} u_{\mathrm{q},0}, \; \ldots, \;
+             W_{\mathrm{q},M-1} u_{\mathrm{q},M-1},\; 
+             W_{\mathrm{s},0} \svec{(u_{\mathrm{s},0})}, \; \ldots, \;
+             W_{\mathrm{s},N-1} \svec{(u_{\mathrm{s},N-1})} \right)
+    
+    with the following diagonal blocks.
+    
+    * The first block is a *positive diagonal scaling* with a vector 
+      :math:`d_{\mathrm{nl}}`:
+
+      .. math::
+        
+          \newcommand{\diag}{\mbox{\bf diag}\,}
+          W_\mathrm{nl} = \diag(d_\mathrm{nl}), \qquad 
+          W_\mathrm{nl}^{-1} = \diag(d_\mathrm{nl})^{-1}.
+        
+      This transformation is symmetric:
+
+      .. math::
+
+          W_\mathrm{nl}^T = W_\mathrm{nl}. 
+
+    * The second block is a *positive diagonal scaling* with a vector 
+      :math:`d_{\mathrm{l}}`:
+
+      .. math:: 
+
+          \newcommand{\diag}{\mbox{\bf diag}\,}
+          W_\mathrm{l} = \diag(d_\mathrm{l}), \qquad 
+          W_\mathrm{l}^{-1} = \diag(d_\mathrm{l})^{-1}.
+        
+      This transformation is symmetric:
+       
+      .. math::
+
+          W_\mathrm{l}^T = W_\mathrm{l}. 
+
+    * The next :math:`M` blocks are positive multiples of *hyperbolic 
+      Householder transformations*:
+
+      .. math::
+
+         W_{\mathrm{q},k} = \beta_k ( 2 v_k v_k^T - J), \qquad
+         W_{\mathrm{q},k}^{-1} = \frac{1}{\beta_k} ( 2 Jv_k v_k^T J - J),
+         \qquad k = 0,\ldots,M-1,
+
+      where
+
+      .. math::
+
+         \beta_k > 0, \qquad v_{k0} > 0, \qquad v_k^T Jv_k = 1, \qquad 
+         J = \left[\begin{array}{cc} 1 & 0 \\ 0 & -I \end{array}\right].
+
+      These transformations are also symmetric:
+
+      .. math::
+
+         W_{\mathrm{q},k}^T = W_{\mathrm{q},k}. 
+
+
+    * The last :math:`N` blocks are *congruence transformations* with 
+      nonsingular matrices:
+
+      .. math::
+
+          \newcommand{\svec}{\mathop{\mathbf{vec}}}
+          W_{\mathrm{s},k} \svec{(u_{\mathrm{s},k})} = 
+              \svec{(r_k^T u_{\mathrm{s},k} r_k)}, \qquad
+          W_{\mathrm{s},k}^{-1} \svec{(u_{\mathrm{s},k})} = 
+             \svec{(r_k^{-T} u_{\mathrm{s},k} r_k^{-1})}, \qquad
+          k = 0,\ldots,N-1.
+
+      In  general, this operation is not symmetric, and
+
+      .. math::
+
+          \newcommand{\svec}{\mathop{\mathbf{vec}}}
+          W_{\mathrm{s},k}^T \svec{(u_{\mathrm{s},k})} = 
+              \svec{(r_k u_{\mathrm{s},k} r_k^T)}, \qquad
+          \qquad
+          W_{\mathrm{s},k}^{-T} \svec{(u_{\mathrm{s},k})} = 
+              \svec{(r_k^{-1} u_{\mathrm{s},k} r_k^{-T})}, \qquad
+          k = 0,\ldots,N-1.
+
+
+    It is often possible to exploit problem structure to solve 
+    :eq:`e-cp-kkt` faster than by standard methods.  The last argument 
+    ``kktsolver`` of :func:`cp <cvxopt.solvers.cp>` allows the user to 
+    supply a Python function
+    for solving the KKT equations.  This function will be called as 
+    ``f = kktsolver(x, z, W)``.  The argument ``x`` is the point at 
+    which the derivatives in the KKT matrix are evaluated.  ``z`` is a 
+    positive vector of length it :math:`m` + 1, containing the coefficients
+    in the 1,1 block :math:`H`.  ``W`` is a dictionary that contains the 
+    parameters of the scaling:
+
+    * ``W['dnl']`` is the positive vector that defines the diagonal
+      scaling for the nonlinear inequalities.  ``W['dnli']`` is its 
+      componentwise inverse.
+    * ``W['d']`` is the positive vector that defines the diagonal
+      scaling for the componentwise linear inequalities.  ``W['di']``
+      is its componentwise inverse.
+    * ``W['beta']`` and ``W['v']`` are lists of length :math:`M` 
+      with the coefficients and vectors that define the hyperbolic 
+      Householder transformations.
+    * ``W['r']`` is a list of length :math:`N` with the matrices that
+      define the the congruence transformations.  ``W['rti']`` is a 
+      list of length :math:`N` with the transposes of the inverses of the 
+      matrices in ``W['r']``.
+
+    The function call ``f = kktsolver(x, z, W)`` should return a 
+    routine for solving the KKT system :eq:`e-cp-kkt` defined by ``x``, 
+    ``z``, ``W``.  It will be called as ``f(bx, by, bz)``.
+    On entry, ``bx``, ``by``, ``bz`` contain the righthand side.  On exit,
+    they should contain the solution of the KKT system, with the last 
+    component scaled, i.e., on exit,
+
+    .. math::
+
+        b_x := u_x, \qquad b_y := u_y, \qquad b_z := W u_z.
+
+    The role of the argument ``kktsolver`` in the function 
+    :func:`cpl <cvxopt.solvers.cpl>` is similar, except that in 
+    :eq:`e-cp-kkt`,
+
+    .. math::
+
+     H = \sum_{k=0}^{m-1} z_k \nabla^2f_k(x), \qquad
+     \tilde G = \left[\begin{array}{cccc}
+     \nabla f_0(x) & \cdots & \nabla f_{m-1}(x) & G^T \end{array}\right]^T.
+
+
+**Specifying constraints via Python functions**
+    In the default use of :func:`cp <cvxopt.solvers.cp>`, the arguments 
+    ``G`` and ``A`` are the
+    coefficient matrices in the constraints of :eq:`e-cp-kkt`.  It is also 
+    possible to specify these matrices by providing Python functions that 
+    evaluate the corresponding matrix-vector products and their adjoints.
+
+    * If the argument ``G`` of :func:`cp` is a Python function, then 
+      ``G(u, v[, alpha = 1.0, beta = 0.0, trans = 'N'])`` should 
+      evaluates the matrix-vector products
+   
+        .. math::
+    
+            v := \alpha Gu + \beta v \quad 
+                (\mathrm{trans} = \mathrm{'N'}), \qquad 
+            v := \alpha G^T u + \beta v \quad 
+               (\mathrm{trans} = \mathrm{'T'}).
+    
+
+    * Similarly, if the argument ``A`` is a Python function, then 
+      ``A(u, v[, alpha = 1.0, beta = 0.0, trans = 'N'])`` should 
+      evaluate the matrix-vector products
+    
+        .. math::
+    
+           v \alpha Au + \beta v \quad 
+               (\mathrm{trans} = \mathrm{'N'}), \qquad 
+           v := \alpha A^T u + \beta v \quad 
+               (\mathrm{trans} = \mathrm{'T'}).
+
+    * In a similar way, when the first argument ``F`` of 
+      :func:`cp <cvxopt.solvers.cp>` returns matrices of first 
+      derivatives or second derivatives ``Df``, ``H``, these matrices can 
+      be specified as Python functions.  If ``Df`` is a Python function, 
+      then ``Df(u, v[, alpha = 1.0, beta = 0.0, trans = 'N'])`` should
+      evaluate the matrix-vector products
+    
+        .. math::
+
+            v := \alpha Df(x) u + \beta v \quad 
+                (\mathrm{trans} = \mathrm{'N'}), \qquad
+            v := \alpha Df(x)^T u + \beta v \quad 
+                (\mathrm{trans} = \mathrm{'T'}).
+    
+      If ``H`` is a Python function, then ``H(u, v[, alpha, beta])`` should
+      evaluate the matrix-vector product
+    
+        .. math::
+
+            v := \alpha H u + \beta v.
+    
+    If ``G``, ``A``, ``Df``, or ``H`` are Python functions, then the 
+    argument ``kktsolver`` must also be provided.
+
+
+As an example, we consider the unconstrained problem
+
+.. math::
+
+    \begin{array}{ll}
+    \mbox{minimize} & (1/2)\|Ax-b\|_2^2 - \sum_{i=1}^n \log(1-x_i^2)
+    \end{array}
+
+where :math:`A` is an :math:`m` by :math:`n` matrix with :math:`m` less 
+than :math:`n`.  The Hessian of the objective is diagonal plus a low-rank 
+term:
+
+.. math::
+
+    \newcommand{\diag}{\mbox{\bf diag}\,}
+    H = A^TA + \diag(d), \qquad d_i = \frac{2(1+x_i^2)}{(1-x_i^2)^2}.
+
+We can exploit this property when solving :eq:`e-cp-kkt` by applying
+the matrix inversion lemma. We first solve  
+
+.. math::
+
+    \newcommand{\diag}{\mbox{\bf diag}\,}
+    (A \diag(d)^{-1}A^T + I) v = (1/z_0) A \diag(d)^{-1}b_x, \qquad
+
+and then obtain
+
+.. math::
+
+    \newcommand{\diag}{\mbox{\bf diag}\,}
+    u_x = \diag(d)^{-1}(b_x/z_0 - A^T v).
+
+The following code follows this method.  It also uses BLAS functions
+for matrix-matrix and matrix-vector products.
+
+:: 
+
+    from cvxopt import matrix, spdiag, mul, div, log, blas, lapack, solvers, base
+
+    def l2ac(A, b):
+        """
+        Solves
+
+            minimize  (1/2) * ||A*x-b||_2^2 - sum log (1-xi^2)
+
+        assuming A is m x n with m << n.
+        """
+
+        m, n = A.size
+        def F(x = None, z = None):
+            if x is None: 
+                return 0, matrix(0.0, (n,1))
+            if max(abs(x)) >= 1.0: 
+                return None 
+            # r = A*x - b
+            r = -b
+            blas.gemv(A, x, r, beta = -1.0)
+            w = x**2
+            f = 0.5 * blas.nrm2(r)**2  - sum(log(1-w))
+            # gradf = A'*r + 2.0 * x ./ (1-w)
+            gradf = div(x, 1.0 - w)
+            blas.gemv(A, r, gradf, trans = 'T', beta = 2.0)
+            if z is None:
+                return f, gradf.T
+            else:
+                def Hf(u, v, alpha = 1.0, beta = 0.0):
+                   # v := alpha * (A'*A*u + 2*((1+w)./(1-w)).*u + beta *v
+                   v *= beta
+                   v += 2.0 * alpha * mul(div(1.0+w, (1.0-w)**2), u)
+                   blas.gemv(A, u, r)
+                   blas.gemv(A, r, v, alpha = alpha, beta = 1.0, trans = 'T')
+                return f, gradf.T, Hf
+
+
+        # Custom solver for the Newton system
+        #
+        #     z[0]*(A'*A + D)*x = bx
+        #
+        # where D = 2 * (1+x.^2) ./ (1-x.^2).^2.  We apply the matrix inversion
+        # lemma and solve this as
+        #    
+        #     (A * D^-1 *A' + I) * v = A * D^-1 * bx / z[0]
+        #     D * x = bx / z[0] - A'*v.
+
+        S = matrix(0.0, (m,m))
+        v = matrix(0.0, (m,1))
+        def Fkkt(x, z, W):
+            ds = (2.0 * div(1 + x**2, (1 - x**2)**2))**-0.5
+            Asc = spdiag(ds) * A
+            blas.syrk(Asc, S)
+            S[::m+1] += 1.0 
+            lapack.potrf(S)
+            a = z[0]
+            def g(x, y, z):
+                x[:] = mul(x, ds) / a
+                blas.gemv(Asc, x, v)
+                lapack.potrs(S, v)
+                blas.gemv(Asc, v, x, alpha = -1.0, beta = 1.0, trans = 'T')
+                x[:] = mul(x, ds)  
+            return g
+
+        return solvers.cp(F, kktsolver = Fkkt)['x']
+
+
+.. _s-parameters2:
+
+Algorithm Parameters 
+====================
+
+The following algorithm control parameters are accessible via the 
+dictionary :attr:`solvers.options`.  By default the dictionary 
+is empty and the default values of the parameters are used.
+
+One can change the parameters in the default solvers by 
+adding entries with the following key values.  
+
+:const:`'show_progress'` 
+    :const:`True` or :const:`False`; turns the output to the screen on or 
+    off (default: :const:`True`).
+
+:const:`'maxiters'` 
+    maximum number of iterations (default: :const:`100`).
+
+:const:`'abstol'` 
+    absolute accuracy (default: :const:`1e-7`).
+
+:const:`'reltol'` 
+    relative accuracy (default: :const:`1e-6`).
+
+:const:`'feastol'` 
+    tolerance for feasibility conditions (default: :const:`1e-7`).
+
+:const:`'refinement'` 
+    number of iterative refinement steps when solving KKT equations 
+    (default: :const:`1`).
+
+For example the command
+
+>>> from cvxopt import solvers
+>>> solvers.options['show_progress'] = False
+
+turns off the screen output during calls to the solvers.  The tolerances 
+:const:`abstol`, :const:`reltol` and :const:`feastol` have the
+following meaning in :func:`cpl <cvxopt.solvers.cpl>`. 
+
+:func:`cpl` returns with status :const:`'optimal'` if
+
+.. math:: 
+
+    \newcommand{\ones}{{\bf 1}}
+    \frac{\| c +  Df(x)^Tz_\mathrm{nl} + G^Tz_\mathrm{l} + A^T y \|_2 }
+    {\max\{ 1, \| c + Df(x_0)^T\ones + G^T\ones \|_2 \}} 
+    \leq \epsilon_\mathrm{feas}, \qquad
+    \frac{\| ( f(x) + s_{\mathrm{nl}},  Gx + s_\mathrm{l} - h, 
+     Ax-b ) \|_2} 
+    {\max\{1, \| ( f(x_0) + \ones,  
+    Gx_0 + \ones-h, Ax_0-b) \|_2 \}} \leq \epsilon_\mathrm{feas}  
+
+where :math:`x_0` is the point returned by ``F()``, and
+
+.. math::
+
+    \mathrm{gap} \leq \epsilon_\mathrm{abs}
+    \qquad \mbox{or} \qquad \left( c^Tx < 0, \quad
+    \frac{\mathrm{gap}} {-c^Tx} \leq \epsilon_\mathrm{rel} \right)
+    \qquad \mbox{or} \qquad
+    \left( L(x,y,z) > 0, \quad \frac{\mathrm{gap}}
+    {L(x,y,z)} \leq \epsilon_\mathrm{rel} \right)
+
+where
+
+.. math::
+
+    \mathrm{gap} = 
+    \left[\begin{array}{c} s_\mathrm{nl} \\ s_\mathrm{l} 
+    \end{array}\right]^T
+    \left[\begin{array}{c} z_\mathrm{nl} \\ z_\mathrm{l} 
+    \end{array}\right],
+    \qquad
+    L(x,y,z) = c^Tx + z_\mathrm{nl}^T f(x) + 
+        z_\mathrm{l}^T (Gx-h) + y^T(Ax-b).
+
+The functions :func:`cp <cvxopt.solvers.cp>` and 
+:func:`gp <cvxopt.solvers.gp>` call :func:`cpl` and hence use the
+same stopping criteria (with :math:`x_0 = 0` for :func:`gp`).
diff --git a/doc/source/spsolvers.rst b/doc/source/spsolvers.rst
new file mode 100644
index 0000000..01bc06d
--- /dev/null
+++ b/doc/source/spsolvers.rst
@@ -0,0 +1,647 @@
+.. role:: raw-html(raw)
+   :format: html
+
+.. _c-spsolvers:
+
+
+***********************
+Sparse Linear Equations
+***********************
+
+In this section we describe routines for solving sparse sets of linear 
+equations.
+
+A real symmetric or complex Hermitian sparse matrix is stored as an 
+:class:`spmatrix <cvxopt.spmatrix>` object ``X``  of size 
+(:math:`n`, :math:`n`) and an 
+additional character argument ``uplo`` with possible values :const:`'L'` 
+and :const:`'U'`.  If ``uplo`` is :const:`'L'`, the lower triangular part
+of ``X`` contains the lower triangular part of the symmetric or Hermitian 
+matrix, and the upper triangular matrix of ``X`` is ignored.  If ``uplo`` 
+is :const:`'U'`, the upper triangular part of ``X`` contains the upper 
+triangular part of the matrix, and the lower triangular matrix of ``X`` is 
+ignored.
+
+A general sparse square matrix of order :math:`n` is represented by an
+:class:`spmatrix` object of size (:math:`n`, :math:`n`).
+
+Dense matrices, which appear as righthand sides of equations, are 
+stored using the same conventions as in the BLAS and LAPACK modules.
+
+
+.. _s-orderings:
+
+Matrix Orderings
+****************
+
+CVXOPT includes an interface to the AMD library for computing approximate 
+minimum degree orderings of sparse matrices.
+
+.. seealso::
+
+    * `AMD code, documentation, copyright, and license
+      <http://www.cise.ufl.edu/research/sparse/amd>`_
+
+    * P. R. Amestoy, T. A. Davis, I. S. Duff,  Algorithm 837: AMD, An 
+      Approximate Minimum Degree Ordering Algorithm, ACM Transactions on 
+      Mathematical Software, 30(3), 381-388, 2004.
+
+
+.. function:: cvxopt.amd.order(A[, uplo = 'L'])
+
+    Computes the approximate mimimum degree ordering of a symmetric  sparse
+    matrix :math:`A`.  The ordering is returned as an integer dense matrix 
+    with length equal to the order of :math:`A`.  Its entries specify a 
+    permutation that reduces fill-in during the Cholesky factorization.
+    More precisely, if ``p = order(A)`` , then ``A[p, p]`` has 
+    sparser Cholesky factors than ``A``.   
+
+
+As an example we consider the matrix 
+
+.. math::
+
+    \left[ \begin{array}{rrrr}
+     10 &  0 & 3 &  0 \\
+      0 &  5 & 0 & -2 \\
+      3 &  0 & 5 &  0 \\
+      0 & -2 & 0 &  2 
+    \end{array}\right].
+
+
+>>> from cvxopt import spmatrix, amd 
+>>> A = spmatrix([10,3,5,-2,5,2], [0,2,1,2,2,3], [0,0,1,1,2,3])
+>>> P = amd.order(A)
+>>> print P
+[ 1]
+[ 0]
+[ 2]
+[ 3]
+
+
+.. _s-umfpack:
+
+General Linear Equations
+************************
+
+The module :mod:`cvxopt.umfpack` includes four functions for solving 
+sparse non-symmetric sets of linear equations.  They call routines from 
+the UMFPACK library, with all control options set to the default values 
+described in the UMFPACK user guide.  
+
+.. seealso::
+
+    * `UMFPACK code, documentation, copyright, and license
+      <http://www.cise.ufl.edu/research/sparse/umfpack>`_
+
+    * T. A. Davis, Algorithm 832: UMFPACK -- an unsymmetric-pattern 
+      multifrontal method with a column pre-ordering strategy, ACM 
+      Transactions on Mathematical Software, 30(2), 196-199, 2004. 
+
+
+.. function:: cvxopt.umfpack.linsolve(A, B[, trans = 'N'])
+
+    Solves a sparse set of linear equations 
+    
+    .. math::
+
+         AX & = B \quad (\mathrm{trans} = \mathrm{'N'}), \\
+         A^TX & = B \quad (\mathrm{trans} = \mathrm{'T'}), \\
+         A^HX & = B \quad (\mathrm{trans} = \mathrm{'C'}),
+    
+    where :math:`A` is a sparse matrix and :math:`B` is a dense matrix.
+    The arguments ``A`` and ``B`` must have the same type 
+    (:const:`'d'` or :const:`'z'`) as ``A``.  On exit ``B`` contains 
+    the solution.  Raises an :exc:`ArithmeticError` if the coefficient 
+    matrix is singular.
+
+In the following example we solve an equation with coefficient matrix 
+
+.. math:: 
+    :label: e-sp-Adef
+
+    A = \left[\begin{array}{rrrrr}
+        2 & 3 & 0 & 0 & 0 \\
+        3 & 0 & 4 & 0 & 6 \\
+        0 &-1 &-3 & 2 & 0 \\
+        0 & 0 & 1 & 0 & 0 \\
+        0 & 4 & 2 & 0 & 1 
+        \end{array}\right].
+
+
+>>> from cvxopt import spmatrix, matrix, umfpack 
+>>> V = [2, 3, 3, -1, 4, 4, -3, 1, 2, 2, 6, 1]
+>>> I = [0, 1, 0,  2, 4, 1,  2, 3, 4, 2, 1, 4]
+>>> J = [0, 0, 1,  1, 1, 2,  2, 2, 2, 3, 4, 4]
+>>> A = spmatrix(V,I,J)
+>>> B = matrix(1.0, (5,1))
+>>> umfpack.linsolve(A,B)
+>>> print B
+[ 5.79e-01]
+[-5.26e-02]
+[ 1.00e+00]
+[ 1.97e+00]
+[-7.89e-01]
+
+The function :func:`linsolve <cvxopt.umfpack.linsolve>`  is 
+equivalent to the following three functions called in sequence.  
+
+.. function:: cvxopt.umfpack.symbolic(A)
+
+    Reorders the columns of ``A`` to reduce fill-in and performs a symbolic 
+    LU factorization.  ``A`` is a sparse, possibly rectangular, matrix.
+    Returns the symbolic factorization as an opaque C object that can be 
+    passed on to :func:`numeric <cvxopt.umfpack.numeric>`.
+
+
+.. function:: cvxopt.umfpack.numeric(A, F)
+
+    Performs a numeric LU factorization of a sparse, possibly rectangular,
+    matrix ``A``.   The argument ``F`` is the symbolic factorization
+    computed by :func:`symbolic <cvxopt.umfpack.symbolic>` 
+    applied to the matrix ``A``,
+    or another sparse matrix with the same sparsity pattern, dimensions,
+    and type.  The numeric factorization is returned as an opaque C object 
+    that that can be passed on to 
+    :func:`solve <cvxopt.umfpack.solve>`.  Raises an
+    :exc:`ArithmeticError` if the matrix is singular.
+
+
+.. function:: cvxopt.umfpack.solve(A, F, B[, trans = 'N'])
+
+    Solves a set of linear equations
+
+    .. math:: 
+
+        AX & = B \quad (\mathrm{trans} = \mathrm{'N'}), \\
+        A^TX & = B \quad (\mathrm{trans} = \mathrm{'T'}), \\
+        A^HX & = B \quad (\mathrm{trans} = \mathrm{'C'}),
+
+    where :math:`A` is a sparse matrix and :math:`B` is a dense matrix.
+    The arguments ``A`` and ``B`` must have the same type.  The argument  
+    ``F`` is a numeric factorization computed 
+    by :func:`numeric <cvxopt.umfpack.numeric>`.  
+    On exit ``B`` is overwritten by the 
+    solution.
+
+
+These separate functions are useful for solving several sets of linear 
+equations with the same coefficient matrix and different righthand sides, 
+or with coefficient matrices that share the same sparsity pattern.
+The symbolic factorization depends only on the sparsity pattern of
+the matrix, and not on the numerical values of the nonzero coefficients. 
+The numerical factorization on the other hand depends on the sparsity 
+pattern of the matrix and on its the numerical values.
+
+As an example, suppose :math:`A` is the matrix :eq:`e-sp-Adef` and 
+
+.. math::
+
+    B = \left[\begin{array}{rrrrr}
+        4 & 3 & 0 & 0 & 0 \\
+        3 & 0 & 4 & 0 & 6 \\
+        0 &-1 &-3 & 2 & 0 \\
+        0 & 0 & 1 & 0 & 0 \\
+        0 & 4 & 2 & 0 & 2 
+        \end{array}\right],
+
+which differs from :math:`A` in its first and last entries.  The following 
+code computes
+
+.. math::
+
+    \newcommand{\ones}{\mathbf 1}
+    x = A^{-T}B^{-1}A^{-1}\ones.
+
+
+>>> from cvxopt import spmatrix, matrix, umfpack
+>>> VA = [2, 3, 3, -1, 4, 4, -3, 1, 2, 2, 6, 1]
+>>> VB = [4, 3, 3, -1, 4, 4, -3, 1, 2, 2, 6, 2]
+>>> I =  [0, 1, 0,  2, 4, 1,  2, 3, 4, 2, 1, 4]
+>>> J =  [0, 0, 1,  1, 1, 2,  2, 2, 2, 3, 4, 4]
+>>> A = spmatrix(VA, I, J)
+>>> B = spmatrix(VB, I, J)
+>>> x = matrix(1.0, (5,1))
+>>> Fs = umfpack.symbolic(A)
+>>> FA = umfpack.numeric(A, Fs)
+>>> FB = umfpack.numeric(B, Fs)
+>>> umfpack.solve(A, FA, x)
+>>> umfpack.solve(B, FB, x)
+>>> umfpack.solve(A, FA, x, trans='T')
+>>> print x
+[ 5.81e-01]
+[-2.37e-01]
+[ 1.63e+00]
+[ 8.07e+00]
+[-1.31e-01]
+
+
+.. _s-cholmod:
+
+Positive Definite Linear Equations
+**********************************
+
+:mod:`cvxopt.cholmod` is an interface to the Cholesky factorization routines
+of the CHOLMOD package.  It includes functions for Cholesky factorization 
+of sparse positive definite matrices, and for solving sparse sets of linear
+equations with positive definite matrices. 
+The routines can also be used for computing 
+:raw-html:`LDL<sup><small>T</small></sup>`
+(or 
+:raw-html:`LDL<sup><small>H</small></sup>`
+factorizations
+of symmetric indefinite matrices (with :math:`L` unit lower-triangular and 
+:math:`D` diagonal and nonsingular) if such a factorization exists.  
+
+.. seealso::
+   
+     `CHOLMOD code, documentation, copyright, and license
+     <http://www.cise.ufl.edu/research/sparse/cholmod>`_
+
+.. function:: cvxopt.cholmod.linsolve(A, B[, p = None, uplo = 'L'])
+
+    Solves
+
+    .. math::
+
+        AX = B 
+
+    with :math:`A` sparse and real symmetric or complex Hermitian.  
+
+    ``B`` is a dense matrix of the same type as ``A``.  On exit it 
+    is overwritten with the solution.  The argument ``p`` is an integer 
+    matrix with length equal to the order of :math:`A`, and specifies an 
+    optional reordering.  If ``p`` is not specified, CHOLMOD uses a 
+    reordering from the AMD library.
+
+    Raises an :exc:`ArithmeticError` if the factorization does not exist.
+
+
+As an  example, we solve 
+
+.. math:: 
+    :label: e-A-pd
+
+        \left[ \begin{array}{rrrr}
+            10 &  0 & 3 &  0 \\
+             0 &  5 & 0 & -2 \\
+             3 &  0 & 5 &  0 \\
+             0 & -2 & 0 &  2 
+        \end{array}\right] X = 
+        \left[ \begin{array}{cc} 
+             0 & 4 \\ 1 & 5 \\ 2 & 6 \\ 3 & 7
+        \end{array} \right].
+
+
+>>> from cvxopt import matrix, spmatrix, cholmod
+>>> A = spmatrix([10, 3, 5, -2, 5, 2], [0, 2, 1, 3, 2, 3], [0, 0, 1, 1, 2, 3])
+>>> X = matrix(range(8), (4,2), 'd')
+>>> cholmod.linsolve(A,X)
+>>> print X
+[-1.46e-01  4.88e-02]
+[ 1.33e+00  4.00e+00]
+[ 4.88e-01  1.17e+00]
+[ 2.83e+00  7.50e+00]
+
+
+.. function:: cvxopt.cholmod.splinsolve(A, B[, p = None, uplo = 'L'])
+
+    Similar to :func:`linsolve <cvxopt.cholmod.linsolve>` except that 
+    ``B`` is an :class:`spmatrix <cvxopt.spmatrix>` and 
+    that the solution is returned as an output argument (as a new 
+    :class:`spmatrix`).  ``B`` is not modified.
+
+
+The following code computes the inverse of the coefficient matrix 
+in :eq:`e-A-pd` as a sparse matrix.
+
+>>> X = cholmod.splinsolve(A, spmatrix(1.0,range(4),range(4)))
+>>> print X
+[ 1.22e-01     0     -7.32e-02     0    ]
+[    0      3.33e-01     0      3.33e-01]
+[-7.32e-02     0      2.44e-01     0    ]
+[    0      3.33e-01     0      8.33e-01]
+
+
+The functions :func:`linsolve <cvxopt.cholmod.linsolve>` and 
+:func:`splinsolve <cvxopt.cholmod.splinsolve>` are equivalent to 
+:func:`symbolic <cvxopt.cholmod.symbolic>` and 
+:func:`numeric <cvxopt.cholmod.numeric>` called in sequence, followed by 
+:func:`solve <cvxopt.cholmod.solve>`, respectively, 
+:func:`spsolve <cvxopt.cholmod.spsolve>`.
+
+.. function:: cvxopt.cholmod.symbolic(A[, p = None, uplo = 'L'])
+
+    Performs a symbolic analysis of a sparse real symmetric or
+    complex Hermitian matrix :math:`A` for one of the two factorizations:
+
+    .. math:: 
+        :label: e-chol-ll 
+
+        PAP^T = LL^T, \qquad PAP^T = LL^H, 
+    
+    and 
+
+    .. math:: 
+        :label: e-chol-ldl
+
+        PAP^T = LDL^T, \qquad PAP^T = LDL^H,
+
+    where :math:`P` is a permutation matrix, :math:`L` is lower triangular 
+    (unit lower triangular in the second factorization), and :math:`D` is 
+    nonsingular diagonal.  The type of factorization depends on the value 
+    of :attr:`options['supernodal']` (see below).
+
+    If ``uplo`` is :const:`'L'`, only the lower triangular part of ``A`` 
+    is accessed and the upper triangular part is ignored.
+    If ``uplo`` is :const:`'U'`, only the upper triangular part of ``A`` 
+    is accessed and the lower triangular part is ignored.
+
+    If ``p`` is not provided, a reordering from the AMD library is used.
+
+    The symbolic factorization is returned as an opaque C object that 
+    can be passed to :func:`numeric <cvxopt.cholmod.numeric>`.
+
+
+.. function:: cvxopt.cholmod.numeric(A, F)
+
+    Performs a numeric factorization of a sparse symmetric matrix 
+    as :eq:`e-chol-ll` or :eq:`e-chol-ldl`.  The argument ``F`` is the 
+    symbolic factorization computed by 
+    :func:`symbolic <cvxopt.cholmod.symbolic>` applied to 
+    the matrix ``A``, or to another sparse  matrix with the same sparsity 
+    pattern and typecode, or by 
+    :func:`numeric <cvxopt.cholmod.numeric>` applied to a matrix
+    with the same sparsity pattern and typecode as ``A``.
+
+    If ``F`` was created by a 
+    :func:`symbolic <cvxopt.cholmod.symbolic>` with ``uplo`` 
+    equal 
+    to :const:`'L'`, then only the lower triangular part of ``A`` is 
+    accessed and the upper triangular part is ignored.  If it was created 
+    with ``uplo`` equal to :const:`'U'`, then only the upper triangular 
+    part of ``A`` is accessed and the lower triangular part is ignored.
+
+    On successful exit, the factorization is stored in ``F``.
+    Raises an :exc:`ArithmeticError` if the factorization does not exist.
+
+
+.. function:: cvxopt.cholmod.solve(F, B[, sys = 0])
+
+    Solves one of the following linear equations where ``B`` is a dense 
+    matrix and ``F`` is the numeric factorization :eq:`e-chol-ll` 
+    or :eq:`e-chol-ldl` computed by 
+    :func:`numeric <cvxopt.cholmod.numeric>`.  
+    ``sys`` is an integer with values between 0 and 8. 
+
+    +---------+--------------------+ 
+    | ``sys`` | equation           | 
+    +---------+--------------------+
+    | 0       | :math:`AX = B`     |
+    +---------+--------------------+
+    | 1       | :math:`LDL^TX = B` |
+    +---------+--------------------+
+    | 2       | :math:`LDX = B`    |
+    +---------+--------------------+
+    | 3       | :math:`DL^TX=B`    | 
+    +---------+--------------------+
+    | 4       | :math:`LX=B`       |
+    +---------+--------------------+
+    | 5       | :math:`L^TX=B`     |
+    +---------+--------------------+
+    | 6       | :math:`DX=B`       |
+    +---------+--------------------+
+    | 7       | :math:`P^TX=B`     |
+    +---------+--------------------+
+    | 8       | :math:`PX=B`       |
+    +---------+--------------------+
+
+    (If ``F`` is a Cholesky factorization of the form :eq:`e-chol-ll`, 
+    :math:`D` is an identity matrix in this table.  If ``A`` is complex, 
+    :math:`L^T` should be replaced by :math:`L^H`.)
+
+    The matrix ``B`` is a dense :const:`'d'` or :const:`'z'` matrix, with 
+    the same type as ``A``.  On exit it is overwritten by the solution.
+
+
+.. function:: cvxopt.cholmod.spsolve(F, B[, sys = 0])
+
+    Similar to :func:`solve <cvxopt.cholmod.solve>`, except that ``B`` is 
+    a class:`spmatrix`, and the solution is returned as an output argument 
+    (as an :class:`spmatrix`).  ``B`` must have the same typecode as ``A``.
+
+
+For the same example as above:
+
+>>> X = matrix(range(8), (4,2), 'd')
+>>> F = cholmod.symbolic(A)
+>>> cholmod.numeric(A, F)
+>>> cholmod.solve(F, X)
+>>> print X
+[-1.46e-01  4.88e-02]
+[ 1.33e+00  4.00e+00]
+[ 4.88e-01  1.17e+00]
+[ 2.83e+00  7.50e+00]
+
+
+.. function:: cvxopt.cholmod.diag(F)
+
+    Returns the diagonal elements of the Cholesky factor :math:`L` 
+    in :eq:`e-chol-ll`, as a dense matrix of the same type as ``A``.
+    Note that this only applies to Cholesky factorizations.  The matrix 
+    :math:`D` in an :raw-html:`LDL<sup><small>T</small></sup>`
+    factorization can be retrieved via :func:`solve <cvxopt.cholmod.solve>`
+    with ``sys`` equal to 6.
+
+
+In the functions listed above, the default values of the control 
+parameters described in the CHOLMOD user guide are used, except for 
+:cdata:`Common->print` which is set to 0 instead of 3 and 
+:cdata:`Common->supernodal` which is set to 2 instead of 1.
+These parameters (and a few others) can be modified by making an 
+entry in the dictionary :attr:`cholmod.options`. 
+The meaning of these parameters is as follows.
+
+:attr:`options['supernodal']` 
+    If equal to 0, a factorization :eq:`e-chol-ldl` is computed using a 
+    simplicial algorithm.  If equal to 2, a factorization :eq:`e-chol-ll`
+    is computed using a supernodal algorithm.  If equal to 1, the most 
+    efficient of the two factorizations is selected, based on the sparsity 
+    pattern.  Default: 2.
+
+:attr:`options['print']` 
+    A nonnegative integer that controls the amount of output printed to 
+    the screen.  Default: 0 (no output).
+
+
+As an example that illustrates :func:`diag  <cvxopt.cholmod.diag>` and the 
+use of :attr:`cholmod.options`, we compute the logarithm of the determinant 
+of the coefficient matrix in :eq:`e-A-pd` by two methods.
+
+
+>>> import math
+>>> from cvxopt.cholmod import options
+>>> from cvxopt import log
+>>> F = cholmod.symbolic(A)
+>>> cholmod.numeric(A, F)
+>>> print 2.0 * sum(log(cholmod.diag(F)))
+5.50533153593
+>>> options['supernodal'] = 0
+>>> F = cholmod.symbolic(A)
+>>> cholmod.numeric(A, F)
+>>> Di = matrix(1.0, (4,1))
+>>> cholmod.solve(F, Di, sys=6)
+>>> print -sum(log(Di))
+5.50533153593
+
+
+Example: Covariance Selection
+*****************************
+
+This example illustrates the use of the routines for sparse Cholesky 
+factorization.  We consider the problem 
+
+.. math::
+    :label: e-covsel
+
+    \newcommand{\Tr}{\mathop{\bf tr}}
+    \begin{array}{ll}
+        \mbox{minimize} & -\log\det K + \Tr(KY) \\
+        \mbox{subject to} & K_{ij}=0,\quad (i,j) \not \in S.
+    \end{array}
+
+The optimization variable is a symmetric matrix :math:`K` of order 
+:math:`n` and the domain of the problem is the set of positive definite 
+matrices.  The matrix :math:`Y` and the index set :math:`S` are given.  
+We assume that all the diagonal positions are included in :math:`S`.
+This problem arises in maximum likelihood estimation of the covariance
+matrix of a zero-mean normal distribution, with constraints 
+that specify that pairs of variables are conditionally independent.
+
+We can express :math:`K` as
+
+.. math::
+
+    \newcommand{\diag}{\mathop{\bf diag}}
+    K(x) = E_1\diag(x)E_2^T+E_2\diag(x)E_1^T
+
+where :math:`x` are the nonzero elements in the lower triangular part of 
+:math:`K`, with the diagonal elements scaled by 1/2, and
+
+.. math::
+
+    E_1 = \left[ \begin{array}{cccc}
+        e_{i_1} & e_{i_2} & \cdots & e_{i_q} \end{array}\right], \qquad
+    E_2 = \left[ \begin{array}{cccc}
+        e_{j_1} & e_{j_2} & \cdots & e_{j_q} \end{array}\right], 
+
+where (:math:`i_k`, :math:`j_k`) are the positions of the nonzero entries 
+in the lower-triangular part of :math:`K`.  With this notation, we can 
+solve problem :eq:`e-covsel` by solving the unconstrained problem
+
+.. math::
+
+    \newcommand{\Tr}{\mathop{\bf tr}}
+    \begin{array}{ll}
+    \mbox{minimize} & f(x) = -\log\det K(x) + \Tr(K(x)Y).
+    \end{array}
+
+The code below implements Newton's method with a backtracking line search.  
+The gradient and Hessian of the objective function are given by
+
+.. math:: 
+
+    \newcommand{\diag}{\mathop{\bf diag}}
+    \begin{split}
+    \nabla f(x) 
+        & = 2 \diag( E_1^T (Y - K(x)^{-1}) E_2)) \\
+        & = 2\diag(Y_{IJ} - \left(K(x)^{-1}\right)_{IJ}) \\
+    \nabla^2 f(x) 
+        & = 2 (E_1^T K(x)^{-1} E_1) \circ (E_2^T K(x)^{-1} E_2) 
+            + 2 (E_1^T K(x)^{-1} E_2) \circ (E_2^T K(x)^{-1} E_1) \\
+        & = 2 \left(K(x)^{-1}\right)_{II} \circ \left(K(x)^{-1}\right)_{JJ}
+            + 2 \left(K(x)^{-1}\right)_{IJ} \circ 
+            \left(K(x)^{-1}\right)_{JI},
+    \end{split}
+
+where :math:`\circ` denotes Hadamard product.
+
+
+::
+
+    from cvxopt import matrix, spmatrix, log, mul, blas, lapack, amd, cholmod
+
+    def covsel(Y):
+        """
+        Returns the solution of
+
+             minimize    -logdet K + Tr(KY)
+             subject to  K_{ij}=0,  (i,j) not in indices listed in I,J.
+
+        Y is a symmetric sparse matrix with nonzero diagonal elements.
+        I = Y.I,  J = Y.J.
+        """
+
+        I, J = Y.I, Y.J
+        n, m = Y.size[0], len(I) 
+        N = I + J*n         # non-zero positions for one-argument indexing 
+        D = [k for k in xrange(m) if I[k]==J[k]]  # position of diagonal elements
+
+        # starting point: symmetric identity with nonzero pattern I,J
+        K = spmatrix(0, I, J) 
+        K[::n+1] = 1
+
+        # Kn is used in the line search
+        Kn = spmatrix(0, I, J)
+
+        # symbolic factorization of K 
+        F = cholmod.symbolic(K)
+
+        # Kinv will be the inverse of K
+        Kinv = matrix(0.0, (n,n))
+        
+        for iters in xrange(100):
+
+            # numeric factorization of K
+            cholmod.numeric(K, F)
+            d = cholmod.diag(F)
+
+            # compute Kinv by solving K*X = I 
+            Kinv[:] = 0
+            Kinv[::n+1] = 1
+            cholmod.solve(F, Kinv)
+
+            # solve Newton system
+            grad = 2*(Y.V - Kinv[N])
+            hess = 2*(mul(Kinv[I,J],Kinv[J,I]) + mul(Kinv[I,I],Kinv[J,J]))
+            v = -grad
+            lapack.posv(hess,v) 
+            
+            # stopping criterion
+            sqntdecr = -blas.dot(grad,v) 
+            print "Newton decrement squared:%- 7.5e" %sqntdecr
+            if (sqntdecr < 1e-12):
+                print "number of iterations: ", iters+1 
+                break
+
+            # line search
+            dx = +v
+            dx[D] *= 2      # scale the diagonal elems        
+            f = -2.0 * sum(log(d))    # f = -log det K
+            s = 1
+            for lsiter in xrange(50):
+                Kn.V = K.V + s*dx
+                try: 
+                    cholmod.numeric(Kn, F)
+                except ArithmeticError:
+                    s *= 0.5
+                else:
+                    d = cholmod.diag(F)
+                    fn = -2.0 * sum(log(d)) + 2*s*blas.dot(v,Y.V)
+                    if (fn < f - 0.01*s*sqntdecr): 
+                         break
+                    s *= 0.5
+                
+            K.V = Kn.V
+
+        return K
diff --git a/doc/spsolvers.tex b/doc/spsolvers.tex
deleted file mode 100644
index 526b5b7..0000000
--- a/doc/spsolvers.tex
+++ /dev/null
@@ -1,563 +0,0 @@
-\chapter{Sparse Linear Equations} \label{c-spsolvers}
-In this section we describe routines for solving sparse sets of linear 
-equations.
-
-A real symmetric or complex Hermitian sparse matrix is stored as
-an \spmtrx\ object \var{X}  of size (\tm{n}, \tm{n}) and an 
-additional character argument \code{uplo} with possible values 
-\code{'L'} and \code{'U'}.  
-If \code{uplo} is \code{'L'}, the lower triangular part
-of \var{X} contains the lower triangular part of the
-symmetric or Hermitian matrix, and the upper triangular matrix
-of \var{X} is ignored.
-If \code{uplo} is \code{'U'}, the upper triangular part
-of \var{X} contains the upper triangular part of the
-matrix, and the lower triangular matrix of \var{X} is ignored.
-
-A general sparse square matrix of order \tm{n} is represented by an
-\spmtrx\ object of size (\tm{n}, \tm{n}).
-
-Dense matrices, which appear as righthand sides of equations, are 
-stored using the same conventions as in the BLAS and LAPACK modules.
-
-\section{Matrix Orderings (\module{cvxopt.amd})} \label{s-orderings}
-
-CVXOPT includes an interface to the AMD library for computing 
-approximate minimum degree orderings of sparse matrices.
-
-\textbf{See also:}
-\BIT
-\item \seelink{http://www.cise.ufl.edu/research/sparse/amd}{AMD code, 
-documentation, copyright and license.}{}
-\item \seetext{P.\ R.\ Amestoy, T.\ A.\ Davis, I.\ S.\ Duff,
-Algorithm 837: AMD, An Approximate Minimum Degree Ordering Algorithm,
-ACM Transactions on Mathematical Software, 30(3), 381-388, 2004.}
-\EIT
-
-\begin{funcdesc}{order}{A\optional{, uplo='L'}}
-Computes the approximate mimimum degree ordering of a symmetric  sparse
-matrix \tm{A}.  
-The ordering is returned as an integer dense matrix with length equal 
-to the order of \var{A}.  Its entries specify a permutation that 
-reduces fill-in during the Cholesky factorization.
-More precisely, if \code{\var{p} = order(\var{A})}, then  
-\code{\var{A}[\var{p},\var{p}]} has sparser Cholesky factors 
-than \code{\var{A}}.   
-\end{funcdesc}
-
-As an example we consider the matrix 
-\[
-\left[ \begin{array}{rrrr}
- 10 &  0 & 3 &  0 \\
-  0 &  5 & 0 & -2 \\
-  3 &  0 & 5 &  0 \\
-  0 & -2 & 0 &  2 
-\end{array}\right].
-\]
-\begin{verbatim}
->>> from cvxopt import spmatrix, amd 
->>> A = spmatrix([10,3,5,-2,5,2], [0,2,1,2,2,3], [0,0,1,1,2,3])
->>> P = amd.order(A)
->>> print P
-[ 1]
-[ 0]
-[ 2]
-[ 3]
-\end{verbatim}
-
-\section{General Linear Equations (\module{cvxopt.umfpack})} 
-\label{s-umfpack}
-The module \module{cvxopt.umfpack} includes four functions for solving 
-sparse non-symmetric sets of linear equations.  
-They call routines from the UMFPACK library, with all control options 
-set to the default values described in the UMFPACK user guide.  
-
-\textbf{See also:}
-\BIT
-\item \seelink{http://www.cise.ufl.edu/research/sparse/umfpack}{UMFPACK code, documentation, copyright and license.}{}
-\item \seetext{T.\ A.\ Davis,
-Algorithm 832: UMFPACK -- an unsymmetric-pattern multifrontal method 
-with a column pre-ordering strategy,
-ACM Transactions on Mathematical Software, 30(2), 196-199, 2004.}
-\EIT
-
-\begin{funcdesc}{linsolve}{A, B\optional{, trans='N'}}
-Solves a sparse set of linear equations 
-\[
- AX = B \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
- A^TX = B \quad (\mathrm{trans} = \mathrm{'T'}), \qquad
- A^HX = B \quad (\mathrm{trans} = \mathrm{'C'}),
-\]
-where {\var A} is a sparse matrix and \var{B} is a dense matrix of
-the same type (\dtc\ or \ztc) as \var{A}.  On exit \var{B} contains 
-the solution.
-Raises an \code{ArithmeticError} exception if the coefficient matrix 
-is singular.
-\end{funcdesc}
-In the following example we solve an equation with 
-coefficient matrix 
-\BEQ \label{e-sp-Adef}
-A = \left[\begin{array}{rrrrr}
- 2 & 3 & 0 & 0 & 0 \\
- 3 & 0 & 4 & 0 & 6 \\
- 0 &-1 &-3 & 2 & 0 \\
- 0 & 0 & 1 & 0 & 0 \\
- 0 & 4 & 2 & 0 & 1 
- \end{array}\right].
-\EEQ
-\begin{verbatim}
->>> from cvxopt import spmatrix, matrix, umfpack 
->>> V = [2,3, 3,-1,4, 4,-3,1,2, 2, 6,1]
->>> I = [0,1, 0, 2,4, 1, 2,3,4, 2, 1,4]
->>> J = [0,0, 1, 1,1, 2, 2,2,2, 3, 4,4]
->>> A = spmatrix(V,I,J)
->>> B = matrix(1.0, (5,1))
->>> umfpack.linsolve(A,B)
->>> print B
-[ 5.79e-01]
-[-5.26e-02]
-[ 1.00e+00]
-[ 1.97e+00]
-[-7.89e-01]
-\end{verbatim}
-The function \function{umfpack.linsolve()} is equivalent to the 
-following three functions called in sequence.  
-\begin{funcdesc}{symbolic}{A}
-Reorders the columns of \var{A} to reduce fill-in and performs a 
-symbolic LU factorization.  \var{A} is a sparse, possibly rectangular,
-matrix.
-Returns the symbolic factorization as an opaque C object that can be 
-passed on to \function{umfpack.numeric()}.
-\end{funcdesc}
-
-\begin{funcdesc}{numeric}{A, F}
-Performs a numeric LU factorization of a sparse, possibly rectangular,
-matrix \var{A}.   The argument \var{F} is the symbolic factorization
-computed by \function{umfpack.symbolic()} applied to the matrix \var{A},
-or another sparse matrix with the same sparsity pattern, dimensions,
-and type.  The numeric factorization is returned as an opaque C object 
-that that can be passed on to \function{umfpack.solve()}.  Raises an
-\code{ArithmeticError} if the matrix is singular.
-\end{funcdesc}
-
-\begin{funcdesc}{solve}{A, F, B\optional{, trans='N'}}
-Solves a set of linear equations
-\[
- AX = B \quad (\mathrm{trans} = \mathrm{'N'}), \qquad
- A^TX = B \quad (\mathrm{trans} = \mathrm{'T'}), \qquad
- A^HX = B \quad (\mathrm{trans} = \mathrm{'C'}),
-\]
-where {\var A} is a sparse matrix and \var{B} is a dense matrix of 
-the same type as \var{A}.
-The argument \var{F} is a numeric factorization computed by 
-\function{umfpack.numeric()}.
-On exit \var{B} is overwritten by the solution.
-\end{funcdesc}
-These separate functions are useful for solving several sets
-of linear equations with the same coefficient matrix and different 
-righthand sides, or with coefficient matrices that share the same 
-sparsity pattern.
-The symbolic factorization depends only on the sparsity pattern of
-the matrix, and not on the numerical values of the nonzero 
-coefficients. 
-The numerical factorization on the other hand depends on the sparsity 
-pattern of the matrix and on its the numerical values.
-
-As an example, suppose \tm{A} is the matrix~(\ref{e-sp-Adef}) and 
-\[
-B = \left[\begin{array}{rrrrr}
- 4 & 3 & 0 & 0 & 0 \\
- 3 & 0 & 4 & 0 & 6 \\
- 0 &-1 &-3 & 2 & 0 \\
- 0 & 0 & 1 & 0 & 0 \\
- 0 & 4 & 2 & 0 & 2 
- \end{array}\right],
-\]
-which differs from \tm{A} in its first and last entries.
-The following code computes
-\[
- x = A^{-T}B^{-1}A^{-1}\ones.
-\]
-\begin{verbatim}
->>> from cvxopt import spmatrix, matrix, umfpack
->>> VA = [2,3, 3,-1,4, 4,-3,1,2, 2, 6,1]
->>> VB = [4,3, 3,-1,4, 4,-3,1,2, 2, 6,2]
->>> I =  [0,1, 0, 2,4, 1, 2,3,4, 2, 1,4]
->>> J =  [0,0, 1, 1,1, 2, 2,2,2, 3, 4,4]
->>> A = spmatrix(VA, I, J)
->>> B = spmatrix(VB, I, J)
->>> x = matrix(1.0, (5,1))
->>> Fs = umfpack.symbolic(A)
->>> FA = umfpack.numeric(A, Fs)
->>> FB = umfpack.numeric(B, Fs)
->>> umfpack.solve(A, FA, x)
->>> umfpack.solve(B, FB, x)
->>> umfpack.solve(A, FA, x, trans='T')
->>> print x
-[ 5.81e-01]
-[-2.37e-01]
-[ 1.63e+00]
-[ 8.07e+00]
-[-1.31e-01]
-\end{verbatim}
-
-\section{Positive Definite Linear Equations (\module{cvxopt.cholmod})} 
-\label{s-cholmod}
-
-\module{cvxopt.cholmod} is an interface to the Cholesky factorization 
-routines of the CHOLMOD package.
-It includes functions for Cholesky factorization of sparse positive
-definite matrices, and for solving sparse sets of linear equations with 
-positive definite matrices. 
-The routines can also be used for computing $\mathrm{LDL^T}$ 
-(or $\mathrm{LDL^H}$) factorizations of symmetric indefinite matrices 
-(with L unit lower-triangular and D diagonal and nonsingular) if 
-such a factorization exists.  
-
-\textbf{See also:}
-\seelink{http://www.cise.ufl.edu/research/sparse/cholmod}{CHOLMOD code, documentation, copyright and license.}{}
-
-\begin{funcdesc}{linsolve}{A, B\optional{, p=\None\optional{, 
-uplo='L'}}}
-Solves
-\[
- AX = B 
-\]
-with \tm{A} sparse and real symmetric or complex Hermitian.
-\var{B} is a dense matrix of the same type as \var{A}.  On exit it 
-is overwritten with the solution.
-The argument \var{p} is an integer matrix with length equal to the 
-order of \var{A}, and specifies an optional reordering of \var{A}.
-If \var{p} is not specified, CHOLMOD used a reordering from the
-AMD library.
-Raises an \code{ArithmeticError} if the factorization does not exist.
-\end{funcdesc}
-
-As an  example, we solve 
-\BEQ \label{e-A-pd}
-\left[ \begin{array}{rrrr}
- 10 &  0 & 3 &  0 \\
-  0 &  5 & 0 & -2 \\
-  3 &  0 & 5 &  0 \\
-  0 & -2 & 0 &  2 
-  \end{array}\right] X = \left[ \begin{array}{cc}
-   0 & 4 \\ 1 & 5 \\ 2 & 6 \\ 3 & 7\end{array} \right].
-\EEQ
-\begin{verbatim}
->>> from cvxopt import matrix, spmatrix, cholmod
->>> A = spmatrix([10,3, 5,-2, 5, 2], [0,2, 1,3, 2, 3], [0,0, 1,1, 2, 3])
->>> X = matrix(range(8), (4,2), 'd')
->>> cholmod.linsolve(A,X)
->>> print X
-[-1.46e-01  4.88e-02]
-[ 1.33e+00  4.00e+00]
-[ 4.88e-01  1.17e+00]
-[ 2.83e+00  7.50e+00]
-\end{verbatim}
-
-\begin{funcdesc}{splinsolve}{A, B\optional{, p=\None\optional{, 
-uplo='L'}}}
-Similar to \function{linsolve()} except that \var{B} is a sparse 
-matrix and that the solution is returned as an output 
-argument (as a new sparse matrix).  \var{B} is not modified.
-\end{funcdesc}
-
-The following code computes the inverse of the coefficient matrix 
-in~(\ref{e-A-pd}) as a sparse matrix.
-\begin{verbatim}
->>> X = cholmod.splinsolve(A, spmatrix(1.0,range(4),range(4)))
->>> print X
-[ 1.22e-01     0     -7.32e-02     0    ]
-[    0      3.33e-01     0      3.33e-01]
-[-7.32e-02     0      2.44e-01     0    ]
-[    0      3.33e-01     0      8.33e-01]
-\end{verbatim}
-
-The functions \function{linsolve()} and \function{splinsolve()} are
-equivalent to \function{symbolic()} and \function{numeric()} called in
-sequence, followed by \function{solve()}, respectively, 
-\function{spsolve()}.
-
-\begin{funcdesc}{symbolic}{A\optional{, p=\None\optional{, uplo='L'}}}
-Performs a symbolic analysis of a sparse real symmetric or
-complex Hermitian matrix \var{A} for one of the two factorizations:
-\BEQ \label{e-chol-ll}
-   PAP^T = LL^T, \qquad PAP^T = LL^H, 
-\EEQ
-and 
-\BEQ \label{e-chol-ldl}
-   PAP^T = LDL^T, \qquad PAP^T = LDL^H,
-\EEQ
-where \tm{P} is a permutation matrix, \tm{L} is lower triangular 
-(unit lower triangular in the second factorization), and 
-\tm{D} is nonsingular diagonal.  The type of factorization depends 
-on the value of \code{options['supernodal']} (see below).
-
-If \var{uplo} is \code{'L'}, only the lower triangular part of \var{A} 
-is accessed and the upper triangular part is ignored.
-If \var{uplo} is \code{'U'}, only the upper triangular part of \var{A} 
-is accessed and the lower triangular part is ignored.
-
-If \var{p} is not provided, a reordering from the AMD library is used.
-
-The symbolic factorization is returned as an opaque C object that 
-can be passed to \function{cholmod.numeric()}.
-\end{funcdesc}
-
-\begin{funcdesc}{numeric}{A, F}
-Performs a numeric factorization of a sparse symmetric matrix 
-as~(\ref{e-chol-ll}) or~(\ref{e-chol-ldl}).  
-The argument \var{F} is the symbolic factorization
-computed by \function{cholmod.symbolic()} applied to the matrix \var{A},
-or to another sparse  matrix with the same sparsity pattern and 
-typecode, or by
-\function{cholmod.numeric()} applied to a matrix with the same
-sparsity pattern and typecode as \var{A}.
-
-If \var{F} was created by a \function{cholmod.symbolic} with 
-\var{uplo} equal to \code{'L'}, then only the lower triangular part 
-of \var{A} is accessed and the upper triangular part is ignored.
-If it was created with \var{uplo} is \code{'U'}, then only the upper 
-triangular part of \var{A} is accessed and the lower triangular part 
-is ignored.
-
-On successful exit, the factorization is stored in \var{F}.
-Raises an \code{ArithmeticError} if the factorization does not
-exist.
-\end{funcdesc}
-
-\begin{funcdesc}{solve}{F, B\optional{, sys=0}}
-Solves one of the following linear equations where \var{B} is a dense 
-matrix and \var{F} is the numeric 
-factorization~(\ref{e-chol-ll}) or~(\ref{e-chol-ldl}) computed by 
-\function{cholmod\_numeric()}.  
-\var{sys} is an integer with values between 0 and 8. 
-
-\begin{center}
-\begin{tabular}{c|c|} \hline
- \var{sys} & equation \\ \hline
- 0 & $AX=B$     \\ \hline 
- 1 & $LDL^TX=B$ \\ \hline 
- 2 & $LDLX=B$   \\ \hline
- 3 & $DL^TX=B$  \\ \hline
- 4 & $LX=B$     \\ \hline 
- 5 & $L^TX=B$   \\ \hline
- 6 & $DX=B$     \\ \hline 
- 7 & $P^TX=B$   \\ \hline 
- 8 & $PX=B$  \\ \hline  
-\end{tabular}
-\end{center}
-
-(If \var{F} is a Cholesky factorization of the form~(\ref{e-chol-ll}), 
-\tm{D} is an identity matrix in this table. 
-If \var{A} is complex, $L^T$ should be replaced by $L^H$.)
-
-The matrix \var{B} is a dense \dtc\ or \ztc\ matrix, with the same type
-as \var{A}.  On exit it is overwritten by the solution.
-\end{funcdesc}
-
-\begin{funcdesc}{spsolve}{F, B\optional{, sys=0}}
-Similar to \function{solve()}, except that \var{B} is a 
-sparse matrix, and the solution is returned as an output argument
-(as a sparse matrix).  \var{B} must have the same typecode as \var{A}.
-\end{funcdesc}
-
-For the same example as above:
-\begin{verbatim}
->>> X = matrix(range(8), (4,2), 'd')
->>> F = cholmod.symbolic(A)
->>> cholmod.numeric(A, F)
->>> cholmod.solve(F, X)
->>> print X
-[-1.46e-01  4.88e-02]
-[ 1.33e+00  4.00e+00]
-[ 4.88e-01  1.17e+00]
-[ 2.83e+00  7.50e+00]
-\end{verbatim}
-
-\begin{funcdesc}{diag}{F}
-Returns the diagonal elements of the Cholesky factor \tm{L} 
-in~(\ref{e-chol-ll}), as a dense matrix of the same type as \var{A}.
-Note that this only applies to Cholesky factorizations.
-The matrix \tm{D} in an $\mathrm{LDL^T}$ factorization can be 
-retrieved via \function{cholmod.solve()} with \var{sys} equal to 6.
-\end{funcdesc}
-
-In the functions listed above, the default values of the control 
-parameters described in the CHOLMOD user guide are used, except for 
-\ctype{Common->print} which is set to 0 instead of 3
-and 
-\ctype{Common->supernodal} which is set to 2 instead of 1.
-These parameters (and a few others) can be modified by making an 
-entry in the dictionary \member{cholmod.options}. 
-The meaning of these parameters is as follows.
-\begin{description}
-\item[\code{options['supernodal']}] If equal to 0, a 
-factorization~(\ref{e-chol-ldl}) is computed using a simplicial 
-algorithm.
-If equal to 2, a factorization~(\ref{e-chol-ll}) is
-computed using a supernodal algorithm.
-If equal to 1, the most efficient of the two factorizations is
-selected, based on the sparsity pattern.  Default: 2.
-
-\item[\code{options['print']}] A nonnegative integer that controls the 
-amount of output printed to the screen.
-Default: 0 (no output).
-\end{description}
-
-As an example that illustrates \function{diag()} and the use of 
-\member{cholmod.options}, we compute the logarithm of the determinant 
-of the coefficient matrix in~(\ref{e-A-pd}) by two methods.
-\begin{verbatim}
->>> import math
->>> from cvxopt.cholmod import options
->>> from cvxopt import log
->>> F = cholmod.symbolic(A)
->>> cholmod.numeric(A, F)
->>> print 2.0 * sum(log(cholmod.diag(F)))
-5.50533153593
-\end{verbatim}
-\begin{verbatim}
->>> options['supernodal'] = 0
->>> F = cholmod.symbolic(A)
->>> cholmod.numeric(A, F)
->>> Di = matrix(1.0, (4,1))
->>> cholmod.solve(F, Di, sys=6)
->>> print -sum(log(Di))
-5.50533153593
-\end{verbatim}
-
-\section{Example: Covariance Selection}
-This example illustrates the use of the routines for sparse Cholesky 
-factorization.  We consider the problem 
-\BEQ \label{e-covsel}
- \begin{array}{ll}
- \mbox{minimize} & -\log\det K + \Tr(KY)\\
- \mbox{subject to} & K_{ij}=0,\quad (i,j) \not \in S.
- \end{array}
-\EEQ
-The optimization variable is a symmetric matrix \tm{K} of order \tm{n}
-and the domain of the problem is the set of positive definite matrices.
-The matrix \tm{Y} and the index set  \tm{S} are given.  We assume that all 
-the diagonal positions are included in \tm{S}.
-This problem arises in maximum likelihood estimation of the covariance
-matrix of a zero-mean normal distribution, with constraints 
-that specify that pairs of variables are conditionally independent.
-
-We can express \tm{K} as
-\[
-   K(x) = E_1\diag(x)E_2^T+E_2\diag(x)E_1^T
-\]
-where \tm{x} are the nonzero elements in the lower triangular part
-of \tm{K}, with the diagonal elements scaled by 1/2,
-and
-\[
- E_1 = \left[ \begin{array}{cccc}
-  e_{i_1} & e_{i_2} & \cdots & e_{i_q} \end{array}\right], \qquad
- E_2 = \left[ \begin{array}{cccc}
-  e_{j_1} & e_{j_2} & \cdots & e_{j_q} \end{array}\right], 
-\]
-where (\tm{\s{i}{k}}, \tm{\s{j}{k}}) are the positions of the nonzero 
-entries in the lower-triangular part of \tm{K}.
-With this notation, we can solve problem~(\ref{e-covsel}) by solving
-the unconstrained problem
-\[
- \begin{array}{ll}
-   \mbox{minimize} & f(x) = -\log\det K(x) + \Tr(K(x)Y).
- \end{array}
-\]
-The code below implements Newton's method with a backtracking line
-search.  The gradient and Hessian of the objective function are given 
-by
-\begin{eqnarray*}
-\nabla f(x) 
-&=& 2 \diag( E_1^T (Y - K(x)^{-1}) E_2)) \\
-&=& 2\diag(Y_{IJ} - \left(K(x)^{-1}\right)_{IJ})\\
-\nabla^2 f(x) & = & 
- 2 (E_1^T K(x)^{-1} E_1) \circ (E_2^T K(x)^{-1} E_2) 
-   + 2 (E_1^T K(x)^{-1} E_2) \circ (E_2^T K(x)^{-1} E_1) \\
-&=& 2 \left(K(x)^{-1}\right)_{II} \circ 
-      \left(K(x)^{-1}\right)_{JJ}
-   +2 \left(K(x)^{-1}\right)_{IJ} \circ 
-      \left(K(x)^{-1}\right)_{JI},
-\end{eqnarray*} 
-where \code{o} denotes Hadamard product.
-
-\begin{verbatim}
-from cvxopt import matrix, spmatrix, log, mul, blas, lapack, amd, cholmod
-
-def covsel(Y):
-    """
-    Returns the solution of
-
-         minimize    -logdet K + Tr(KY)
-         subject to  K_{ij}=0,  (i,j) not in indices listed in I,J.
-
-    Y is a symmetric sparse matrix with nonzero diagonal elements.
-    I = Y.I,  J = Y.J.
-    """
-
-    I, J = Y.I, Y.J
-    n, m = Y.size[0], len(I) 
-    N = I + J*n         # non-zero positions for one-argument indexing 
-    D = [k for k in xrange(m) if I[k]==J[k]]  # position of diagonal elements
-
-    # starting point: symmetric identity with nonzero pattern I,J
-    K = spmatrix(0, I, J) 
-    K[::n+1] = 1
-
-    # Kn is used in the line search
-    Kn = spmatrix(0, I, J)
-
-    # symbolic factorization of K 
-    F = cholmod.symbolic(K)
-
-    # Kinv will be the inverse of K
-    Kinv = matrix(0.0, (n,n))
-    
-    for iters in xrange(100):
-
-        # numeric factorization of K
-        cholmod.numeric(K, F)
-        d = cholmod.diag(F)
-
-        # compute Kinv by solving K*X = I 
-        Kinv[:] = 0
-        Kinv[::n+1] = 1
-        cholmod.solve(F, Kinv)
-
-        # solve Newton system
-        grad = 2*(Y.V - Kinv[N])
-        hess = 2*(mul(Kinv[I,J],Kinv[J,I]) + mul(Kinv[I,I],Kinv[J,J]))
-        v = -grad
-        lapack.posv(hess,v) 
-        
-        # stopping criterion
-        sqntdecr = -blas.dot(grad,v) 
-        print "Newton decrement squared:%- 7.5e" %sqntdecr
-        if (sqntdecr < 1e-12):
-            print "number of iterations: ", iters+1 
-            break
-
-        # line search
-        dx = +v
-        dx[D] *= 2      # scale the diagonal elems        
-        f = -2.0 * sum(log(d))    # f = -log det K
-        s = 1
-        for lsiter in xrange(50):
-            Kn.V = K.V + s*dx
-            try: 
-                cholmod.numeric(Kn, F)
-            except ArithmeticError:
-                s *= 0.5
-            else:
-                d = cholmod.diag(F)
-                fn = -2.0 * sum(log(d)) + 2*s*blas.dot(v,Y.V)
-                if (fn < f - 0.01*s*sqntdecr): 
-                     break
-                s *= 0.5
-            
-        K.V = Kn.V
-
-    return K
-\end{verbatim}
diff --git a/examples/book/README b/examples/book/README
index 347b2e1..2cb5233 100644
--- a/examples/book/README
+++ b/examples/book/README
@@ -2,6 +2,5 @@ This directory contains examples from the book "Convex Optimization"
 by Boyd and Vandenberghe (Cambridge University Press, 2004, and
 www.stanford.edu/~boyd/cvxbook).
 
-The scripts require the plotting library Matplotlib, available at
-matplotlib.sourceforge.net.  They were tested with Matplotlib 
-version 0.91.2.
+The scripts require the plotting library Matplotlib, available at 
+matplotlib.sourceforge.net.  
diff --git a/examples/book/chap6/robls b/examples/book/chap6/robls
index 6cc8886..e4a44da 100755
--- a/examples/book/chap6/robls
+++ b/examples/book/chap6/robls
@@ -145,13 +145,13 @@ r = P*u + q[:,notrials*[0]]
 reswc = sqrt( matrix(1.0, (1,m)) * mul(r,r) )
 
 pylab.figure(2, facecolor='w')
-pylab.hist(resls, numpy.array([0.1*k for k in xrange(50)]), fc='w', 
+pylab.hist(list(resls), numpy.array([0.1*k for k in xrange(50)]), fc='w', 
     normed=True)
 pylab.text(4.4, 0.4, 'least-squares')
-pylab.hist(restik, numpy.array([0.1*k for k in xrange(50)]), fc='#D0D0D0', 
+pylab.hist(list(restik), numpy.array([0.1*k for k in xrange(50)]), fc='#D0D0D0', 
     normed=True)
 pylab.text(2.9, 0.75, 'Tikhonov')
-pylab.hist(reswc, numpy.array([0.1*k for k in xrange(50)]), fc='#B0B0B0', 
+pylab.hist(list(reswc), numpy.array([0.1*k for k in xrange(50)]), fc='#B0B0B0', 
     normed=True)
 pylab.text(2.5, 2.0, 'robust least-squares')
 pylab.xlabel('residual')
diff --git a/examples/doc/README b/examples/doc/README
index 2a24119..12485b6 100644
--- a/examples/doc/README
+++ b/examples/doc/README
@@ -1 +1,8 @@
-This directory contains some examples from the CVXOPT documentation.
+This directory contains some examples from the following chapters of 
+the CVXOPT documentation.
+
+Chapter 4. The LAPACK interface.
+Chapter 7. Sparse linear equations.
+Chapter 8. Cone programming.
+Chapter 9. Nonlinear convex optimization.
+Chapter 10. Modeling.
diff --git a/examples/doc/chap10/l1svc b/examples/doc/chap10/l1svc
index bb45b06..8e32c23 100755
--- a/examples/doc/chap10/l1svc
+++ b/examples/doc/chap10/l1svc
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The 1-norm support vector classifier of section 10.5.
+# The 1-norm support vector classifier of section 10.5 (Examples).
 
 from cvxopt import normal, setseed
 from cvxopt.modeling import variable, op, max, sum
diff --git a/examples/doc/chap10/lp b/examples/doc/chap10/lp
index e9c35c1..4285a33 100755
--- a/examples/doc/chap10/lp
+++ b/examples/doc/chap10/lp
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The small LP of section 10.4.  
+# The small LP of section 10.4 (Optimization problems).  
 
 from cvxopt import matrix
 from cvxopt.modeling import variable, op, dot
diff --git a/examples/doc/chap10/normappr b/examples/doc/chap10/normappr
index b3bbecb..935e944 100755
--- a/examples/doc/chap10/normappr
+++ b/examples/doc/chap10/normappr
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The norm and penalty approximation problems of section 10.5.
+# The norm and penalty approximation problems of section 10.5 (Examples).
 
 from cvxopt import normal, setseed
 from cvxopt.modeling import variable, op, max, sum
diff --git a/examples/doc/chap10/roblp b/examples/doc/chap10/roblp
index 8180f81..99cda5f 100755
--- a/examples/doc/chap10/roblp
+++ b/examples/doc/chap10/roblp
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The robust LP example of section 10.5.
+# The robust LP example of section 10.5 (Examples).
 
 from cvxopt import normal, uniform  
 from cvxopt.modeling import variable, dot, op, sum  
diff --git a/examples/doc/chap4/acent b/examples/doc/chap4/acent
index 312e56c..af02707 100755
--- a/examples/doc/chap4/acent
+++ b/examples/doc/chap4/acent
@@ -1,6 +1,7 @@
 #!/usr/bin/python
 
-# The analytic centering example of section 4.9.
+# The analytic centering example at the end of chapter 4 (The LAPACK 
+# interface).
 
 from cvxopt import matrix, log, mul, div, blas, lapack, base
 from math import sqrt
diff --git a/examples/doc/chap7/covsel b/examples/doc/chap7/covsel
index a4ce66a..5b061c0 100755
--- a/examples/doc/chap7/covsel
+++ b/examples/doc/chap7/covsel
@@ -1,6 +1,7 @@
 #! /usr/bin/python
 
-# The covariance selection example of section 7.4.
+# The covariance selection example at the end of chapter 7 (Sparse linear
+# equations).
 
 from cvxopt import matrix, spmatrix, log, mul, blas, lapack, amd, cholmod
 from pickle import load
diff --git a/examples/doc/chap8/conelp b/examples/doc/chap8/conelp
index 5473b06..9a374ec 100755
--- a/examples/doc/chap8/conelp
+++ b/examples/doc/chap8/conelp
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 # 
-# The small linear cone program of section 8.1
+# The small linear cone program of section 8.1 (Linear cone programs).
 
 from cvxopt import matrix, solvers
 
diff --git a/examples/doc/chap8/coneqp b/examples/doc/chap8/coneqp
index 9643374..8f267c0 100755
--- a/examples/doc/chap8/coneqp
+++ b/examples/doc/chap8/coneqp
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 # 
-# The quadratic cone program of section 8.2
-# 
+# The quadratic cone program of section 8.2 (Quadratic cone programs).
+  
 # minimize   (1/2)*x'*A'*A*x - b'*A*x
 # subject to x >= 0
 #            ||x||_2 <= 1
diff --git a/examples/doc/chap8/l1 b/examples/doc/chap8/l1
index c294db3..4b3116c 100755
--- a/examples/doc/chap8/l1
+++ b/examples/doc/chap8/l1
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The 1-norm approximation example of section 8.7.  
+# The 1-norm approximation example of section 8.7 (Exploiting structure).  
 
 from cvxopt import blas, lapack, solvers
 from cvxopt import matrix, spdiag, mul, div, setseed, normal
diff --git a/examples/doc/chap8/l1regls b/examples/doc/chap8/l1regls
index 16b173b..9b5b3ba 100755
--- a/examples/doc/chap8/l1regls
+++ b/examples/doc/chap8/l1regls
@@ -1,6 +1,7 @@
 #!/usr/bin/python
 
-# The 1-norm regularized least-squares example of section 8.7.
+# The 1-norm regularized least-squares example of section 8.7 (Exploiting
+# structure).
 
 from cvxopt import matrix, spdiag, mul, div, sqrt, normal, setseed
 from cvxopt import blas, lapack, solvers 
@@ -46,7 +47,7 @@ def l1regls(A, y):
     #     [  I        -I   -D1^-1   0     ] [zl[:n]]     [bzl[:n]]
     #     [ -I        -I    0      -D2^-1 ] [zl[n:]]     [bzl[n:]]
     #
-    # where D1 = W['di'][:n]**2, D2 = W['di'][:n]**2.
+    # where D1 = W['di'][:n]**2, D2 = W['di'][n:]**2.
     #    
     # We first eliminate zl and x[n:]:
     #
diff --git a/examples/doc/chap8/lp b/examples/doc/chap8/lp
index 6e7d88d..d0fdb52 100755
--- a/examples/doc/chap8/lp
+++ b/examples/doc/chap8/lp
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The small LP of section 8.3.  
+# The small LP of section 8.3 (Linear programming). 
 
 from cvxopt import matrix, solvers  
 c = matrix([-4., -5.])  
diff --git a/examples/doc/chap8/mcsdp b/examples/doc/chap8/mcsdp
index 2d74ce5..666ae5e 100755
--- a/examples/doc/chap8/mcsdp
+++ b/examples/doc/chap8/mcsdp
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The SDP example of section 8.7.
+# The SDP example of section 8.7 (Exploiting structure).
 
 from cvxopt import blas, lapack, solvers, matrix, normal
 
diff --git a/examples/doc/chap8/portfolio b/examples/doc/chap8/portfolio
index bf45cee..79831fd 100755
--- a/examples/doc/chap8/portfolio
+++ b/examples/doc/chap8/portfolio
@@ -1,6 +1,6 @@
 #!/usr/bin/python
  
-# The risk-return trade-off of section 8.4.
+# The risk-return trade-off of section 8.4 (Quadratic programming).
 
 from math import sqrt
 from cvxopt import matrix
diff --git a/examples/doc/chap8/qcl1 b/examples/doc/chap8/qcl1
index b0d01ff..82887a4 100755
--- a/examples/doc/chap8/qcl1
+++ b/examples/doc/chap8/qcl1
@@ -1,6 +1,7 @@
 #!/usr/bin/python
 
-# The quadratically constrained 1-norm minimization example of section 8.7.
+# The quadratically constrained 1-norm minimization example of section 8.7
+# (Exploiting structure).
 
 from cvxopt import blas, lapack, solvers, matrix, mul, div, setseed, normal
 from math import sqrt
diff --git a/examples/doc/chap8/sdp b/examples/doc/chap8/sdp
index b0efddb..9c99605 100755
--- a/examples/doc/chap8/sdp
+++ b/examples/doc/chap8/sdp
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The small SDP of section 8.6.  
+# The small SDP of section 8.6 (Semidefinite programming).  
 
 from cvxopt import matrix, solvers  
 c = matrix([1.,-1.,1.])  
diff --git a/examples/doc/chap8/socp b/examples/doc/chap8/socp
index 300f641..f3ba272 100755
--- a/examples/doc/chap8/socp
+++ b/examples/doc/chap8/socp
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The small SOCP of section 8.5.  
+# The small SOCP of section 8.5 (Second-order cone programming).  
 
 from cvxopt import matrix, solvers 
 c = matrix([-2., 1., 5.])  
diff --git a/examples/doc/chap9/acent b/examples/doc/chap9/acent
index c6ba627..4d391ed 100755
--- a/examples/doc/chap9/acent
+++ b/examples/doc/chap9/acent
@@ -1,6 +1,7 @@
 #!/usr/bin/python
 
-# The equality constrained analytical centering example of section 9.1.  
+# The equality constrained analytical centering example of section 9.1 
+# (Problems with nonlinear objectives).
 
 from cvxopt import matrix, spmatrix, spdiag, log, normal, uniform
 from cvxopt import blas, solvers
diff --git a/examples/doc/chap9/acent2 b/examples/doc/chap9/acent2
index 281ed8b..c713759 100755
--- a/examples/doc/chap9/acent2
+++ b/examples/doc/chap9/acent2
@@ -1,6 +1,7 @@
 #!/usr/bin/python
 
-# The analytic centering with cone constraints example of section 9.1.  
+# The analytic centering with cone constraints example of section 9.1 
+# (Problems with nonlinear objectives).
 
 from cvxopt import matrix, log, div, spdiag 
 from cvxopt import solvers  
diff --git a/examples/doc/chap9/floorplan b/examples/doc/chap9/floorplan
index f97e1f7..2a40a84 100755
--- a/examples/doc/chap9/floorplan
+++ b/examples/doc/chap9/floorplan
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The floor planning example section 9.2.  
+# The floor planning example section 9.2 (Problems with linear objectives). 
 
 import pylab  
 from cvxopt import solvers, matrix, spmatrix, mul, div  
diff --git a/examples/doc/chap9/gp b/examples/doc/chap9/gp
index 6a82d30..67fb95a 100755
--- a/examples/doc/chap9/gp
+++ b/examples/doc/chap9/gp
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The small GP of section 9.3
+# The small GP of section 9.3 (Geometric programming).
 
 from cvxopt import matrix, log, exp, solvers  
  
diff --git a/examples/doc/chap9/l2ac b/examples/doc/chap9/l2ac
index 2541a26..80ca4b5 100755
--- a/examples/doc/chap9/l2ac
+++ b/examples/doc/chap9/l2ac
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# The example of section 9.4.  
+# The example of section 9.4 (Exploiting structure).. 
 
 from cvxopt import matrix, spdiag, mul, div, log, setseed, uniform, normal 
 from cvxopt import blas, lapack, solvers 
diff --git a/examples/doc/chap9/robls b/examples/doc/chap9/robls
index f33c50a..5d502d2 100755
--- a/examples/doc/chap9/robls
+++ b/examples/doc/chap9/robls
@@ -1,6 +1,7 @@
 #!/usr/bin/python
 
-# The robust least-squares example of section 9.1.  
+# The robust least-squares example of section 9.1 (Problems with nonlinear
+# objectives). 
 
 from math import sqrt, ceil, floor
 from cvxopt import solvers, blas, lapack
diff --git a/src/C/SuiteSparse/CHOLMOD/Doc/ChangeLog b/src/C/SuiteSparse/CHOLMOD/Doc/ChangeLog
index 9d1c2e6..68232ae 100644
--- a/src/C/SuiteSparse/CHOLMOD/Doc/ChangeLog
+++ b/src/C/SuiteSparse/CHOLMOD/Doc/ChangeLog
@@ -1,3 +1,14 @@
+Sept 30, 2008, version 1.7.1
+
+    * bug fix to cholmod_symmetry; it reported incorrectly if the matrix
+        had a zero-free diagonal or not.  No effect on the use of CHOLMOD in
+        MATLAB.  No effect on the mwrite function, either, which uses
+        cholmod_symmetry.  Note that the number of nonzeros on the diagonal was
+        (and still is) correctly computed.  Only effect is on the
+        UF_Index.cholcand statistic reported in the UFget index, and on the web
+        pages, for the UF Sparse Matrix Collection (the UF_Index.cholcand
+        field).  This affects the output of spsym.
+
 Sept 20, 2008, version 1.7.0
 
     * update for SuiteSparseQR:
diff --git a/src/C/SuiteSparse/CHOLMOD/Include/cholmod_core.h b/src/C/SuiteSparse/CHOLMOD/Include/cholmod_core.h
index b0a1e80..61c91ed 100644
--- a/src/C/SuiteSparse/CHOLMOD/Include/cholmod_core.h
+++ b/src/C/SuiteSparse/CHOLMOD/Include/cholmod_core.h
@@ -244,11 +244,11 @@
  *	#endif
  */
 
-#define CHOLMOD_DATE "Sept 20, 2008"
+#define CHOLMOD_DATE "Sept 30, 2008"
 #define CHOLMOD_VER_CODE(main,sub) ((main) * 1000 + (sub))
 #define CHOLMOD_MAIN_VERSION 1
 #define CHOLMOD_SUB_VERSION 7
-#define CHOLMOD_SUBSUB_VERSION 0
+#define CHOLMOD_SUBSUB_VERSION 1
 #define CHOLMOD_VERSION \
     CHOLMOD_VER_CODE(CHOLMOD_MAIN_VERSION,CHOLMOD_SUB_VERSION)
 
diff --git a/src/C/SuiteSparse/CHOLMOD/README.txt b/src/C/SuiteSparse/CHOLMOD/README.txt
index 193d758..84fb2bd 100644
--- a/src/C/SuiteSparse/CHOLMOD/README.txt
+++ b/src/C/SuiteSparse/CHOLMOD/README.txt
@@ -1,5 +1,5 @@
 CHOLMOD: a sparse CHOLesky MODification package 
-Version 1.6, Nov 1, 2007.  Copyright (c) 2005-2007.
+Version 1.7.1, March 24, 2009.  Copyright (c) 2005-2009.
 -----------------------------------------------
 
     CHOLMOD is a set of routines for factorizing sparse symmetric positive
diff --git a/src/C/SuiteSparse/README.txt b/src/C/SuiteSparse/README.txt
index c6f8f45..bbba97a 100644
--- a/src/C/SuiteSparse/README.txt
+++ b/src/C/SuiteSparse/README.txt
@@ -12,43 +12,43 @@ SuiteSparse_install.  All packages will be compiled, and several demos will be
 run.
 ================================================================================
 
-Sept 20, 2008.  SuiteSparse version 3.2.0
+May 20, 2009.  SuiteSparse version 3.4.0
 
-    AMD		approximate minimum degree ordering
+    AMD         approximate minimum degree ordering
 
-    CAMD	constrained approximate minimum degree ordering
+    CAMD        constrained approximate minimum degree ordering
 
-    COLAMD	column approximate minimum degree ordering
+    COLAMD      column approximate minimum degree ordering
 
-    CCOLAMD	constrained column approximate minimum degree ordering
+    CCOLAMD     constrained column approximate minimum degree ordering
 
-    BTF		permutation to block triangular form
+    BTF         permutation to block triangular form
 
-    KLU		sparse LU factorization, primarily for circuit simulation.
-		Requires AMD, COLAMD, and BTF.  Optionally uses CHOLMOD,
-		CAMD, CCOLAMD, and METIS.
+    KLU         sparse LU factorization, primarily for circuit simulation.
+                Requires AMD, COLAMD, and BTF.  Optionally uses CHOLMOD,
+                CAMD, CCOLAMD, and METIS.
 
-    UMFPACK	sparse LU factorization.  Requires AMD and the BLAS.
+    UMFPACK     sparse LU factorization.  Requires AMD and the BLAS.
 
-    CHOLMOD	sparse Cholesky factorization.  Requires AMD, COLAMD, CCOLAMD,
-		the BLAS, and LAPACK.  Optionally uses METIS.
+    CHOLMOD     sparse Cholesky factorization.  Requires AMD, COLAMD, CCOLAMD,
+                the BLAS, and LAPACK.  Optionally uses METIS.
 
-    UFconfig	configuration file for all the above packages.  The
-		UFconfig/UFconfig.mk is included in the Makefile's of all
-		packages.  CSparse and RBio do not use UFconfig.
+    UFconfig    configuration file for all the above packages.  The
+                UFconfig/UFconfig.mk is included in the Makefile's of all
+                packages.  CSparse and RBio do not use UFconfig.
 
-    CSparse	a concise sparse matrix package, developed for my upcoming
-		book, "Direct Methods for Sparse Linear Systems", to be
-		published by SIAM.
+    CSparse     a concise sparse matrix package, developed for my upcoming
+                book, "Direct Methods for Sparse Linear Systems", to be
+                published by SIAM.
 
-    CXSparse	CSparse Extended.  Includes support for complex matrices
-		and both int or long integers.
+    CXSparse    CSparse Extended.  Includes support for complex matrices
+                and both int or long integers.
 
-    RBio	read/write sparse matrices in Rutherford/Boeing format
+    RBio        read/write sparse matrices in Rutherford/Boeing format
 
     UFcollection    toolbox for managing the UF Sparse Matrix Collection
 
-    LPDASA	LP dual active set algorithm (to appear)
+    LPDASA      LP dual active set algorithm (to appear)
 
     MESHND      2D and 3D mesh generation and nested dissection ordering
 
diff --git a/src/C/SuiteSparse/README_cvxopt b/src/C/SuiteSparse/README_cvxopt
index 740dccf..315131e 100644
--- a/src/C/SuiteSparse/README_cvxopt
+++ b/src/C/SuiteSparse/README_cvxopt
@@ -1,4 +1,4 @@
-This is the September 20, 2008 (version 3.2.0) distribution of the 
+This is the May 20, 2009 (version 3.4.0) distribution of the 
 SuiteSparse package from www.cise.ufl.edu/research/sparse/SuiteSparse/, 
 with the following files and directories removed.
 
diff --git a/src/C/SuiteSparse/UFconfig/UFconfig.h b/src/C/SuiteSparse/UFconfig/UFconfig.h
index 54208d5..7b5e79e 100644
--- a/src/C/SuiteSparse/UFconfig/UFconfig.h
+++ b/src/C/SuiteSparse/UFconfig/UFconfig.h
@@ -76,27 +76,27 @@ extern "C" {
  * version of SuiteSparse, with another package from another version of
  * SuiteSparse, may or may not work.
  *
- * SuiteSparse Version 3.2.0 contains the following packages:
+ * SuiteSparse Version 3.4.0 contains the following packages:
  *
  *  AMD		    version 2.2.0
  *  CAMD	    version 2.2.0
  *  COLAMD	    version 2.7.1
  *  CCOLAMD	    version 2.7.1
- *  CHOLMOD	    version 1.7.0
- *  CSparse	    version 2.2.1
- *  CXSparse	    version 2.2.1
- *  KLU		    version 1.0.1
- *  BTF		    version 1.0.1
+ *  CHOLMOD	    version 1.7.1
+ *  CSparse	    version 2.2.3
+ *  CXSparse	    version 2.2.3
+ *  KLU		    version 1.1.0
+ *  BTF		    version 1.1.0
  *  LDL		    version 2.0.1
  *  UFconfig	    version number is the same as SuiteSparse
- *  UMFPACK	    version 5.2.0
- *  RBio	    version 1.1.1
- *  UFcollection    version 1.1.1
+ *  UMFPACK	    version 5.4.0
+ *  RBio	    version 1.1.2
+ *  UFcollection    version 1.2.0
  *  LINFACTOR       version 1.1.0
- *  MESHND          version 1.1.0
- *  SSMULT          version 1.1.0
+ *  MESHND          version 1.1.1
+ *  SSMULT          version 2.0.0
  *  MATLAB_Tools    no specific version number
- *  SuiteSparseQR   version 1.1.0
+ *  SuiteSparseQR   version 1.1.2
  *
  * Other package dependencies:
  *  BLAS	    required by CHOLMOD and UMFPACK
@@ -104,10 +104,10 @@ extern "C" {
  *  METIS 4.0.1	    required by CHOLMOD (optional) and KLU (optional)
  */
 
-#define SUITESPARSE_DATE "Sept 20, 2008"
+#define SUITESPARSE_DATE "May 20, 2009"
 #define SUITESPARSE_VER_CODE(main,sub) ((main) * 1000 + (sub))
 #define SUITESPARSE_MAIN_VERSION 3
-#define SUITESPARSE_SUB_VERSION 2
+#define SUITESPARSE_SUB_VERSION 4
 #define SUITESPARSE_SUBSUB_VERSION 0
 #define SUITESPARSE_VERSION \
     SUITESPARSE_VER_CODE(SUITESPARSE_MAIN_VERSION,SUITESPARSE_SUB_VERSION)
diff --git a/src/C/SuiteSparse/UFconfig/UFconfig.mk b/src/C/SuiteSparse/UFconfig/UFconfig.mk
index f2924a0..bda4c7b 100644
--- a/src/C/SuiteSparse/UFconfig/UFconfig.mk
+++ b/src/C/SuiteSparse/UFconfig/UFconfig.mk
@@ -232,6 +232,9 @@ CFLAGS = -O3 -fexceptions
 # CFLAGS = -O3 -fexceptions -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
 # CFLAGS = -O3
 # CFLAGS = -O3 -g -fexceptions
+# CFLAGS = -g -fexceptions \
+   	-Wall -W -Wshadow \
+    	-Wredundant-decls -Wdisabled-optimization -ansi
 
 # consider:
 # -fforce-addr -fmove-all-movables -freduce-all-givs -ftsp-ordering
diff --git a/src/C/SuiteSparse/UMFPACK/Doc/ChangeLog b/src/C/SuiteSparse/UMFPACK/Doc/ChangeLog
index c5bafd9..fab719a 100644
--- a/src/C/SuiteSparse/UMFPACK/Doc/ChangeLog
+++ b/src/C/SuiteSparse/UMFPACK/Doc/ChangeLog
@@ -1,3 +1,18 @@
+May 20, 2009, version 5.4.0
+
+    * bug fix in umfpack_make.m for Windows
+    * disabled 2-by-2 strategy.  It conflicts with how structurally singular
+	matrices are handled.
+
+March 24, 2009, version 5.3.0
+
+    * bug fix for 2-by-2 strategy (diagonal map) for structurally singular
+	matrices
+
+    * compiler workaround for gcc 4.2.{3,4} in umf_singletons.c
+
+    * added additional timer options in umfpack_timer.c (for POSIX)
+
 Sept 22, 2008
 
     * minor update to documentation; no change to code
diff --git a/src/C/SuiteSparse/UMFPACK/Doc/QuickStart.tex b/src/C/SuiteSparse/UMFPACK/Doc/QuickStart.tex
index 8ed941e..5be3214 100644
--- a/src/C/SuiteSparse/UMFPACK/Doc/QuickStart.tex
+++ b/src/C/SuiteSparse/UMFPACK/Doc/QuickStart.tex
@@ -18,8 +18,8 @@
 \author{Timothy A. Davis \\
 Dept. of Computer and Information Science and Engineering \\
 Univ. of Florida, Gainesville, FL}
-\title{UMFPACK Version 5.2 Quick Start Guide}
-\date{Nov 1, 2007}
+\title{UMFPACK Version 5.4.0 Quick Start Guide}
+\date{May 20, 2009}
 \maketitle
 
 %-------------------------------------------------------------------------------
@@ -35,7 +35,7 @@ Univ. of Florida, Gainesville, FL}
 \end{abstract}
 %-------------------------------------------------------------------------------
 
-UMFPACK Version 5.2, Copyright\copyright 1995-2006 by Timothy A. Davis.
+Copyright\copyright 1995-2009 by Timothy A. Davis.
 All Rights Reserved.  Refer to the UMFPACK User Guide
 for the License. See \newline
 http://www.cise.ufl.edu/research/sparse/umfpack
@@ -234,8 +234,8 @@ for more details.
 \label{Install}
 %-------------------------------------------------------------------------------
 
-You will need to install both UMFPACK v5.2 and AMD v2.2 to use UMFPACK.
-Note that UMFPACK v5.2 cannot use AMD v1.2 or earlier.
+You will need to install AMD v2.2 to use UMFPACK.
+Note that this version of UMFPACK cannot use AMD v1.2 or earlier.
 The {\tt UMFPACK} and {\tt AMD} subdirectories must be placed side-by-side
 within the same parent directory.  AMD is a stand-alone package that
 is required by UMFPACK.  UMFPACK can be compiled without the
@@ -451,15 +451,9 @@ Arguments:
                 [UMFPACK_PIVOT_TOLERANCE] (default 0.1) times the largest entry
                 in its column.
 
-            UMFPACK_STRATEGY_2BY2:  a row permutation P2 is found that places
-                large entries on the diagonal.  The matrix P2*A is then
-                factorized using the symmetric strategy, described above.
-                Refer to the User Guide for more information.
+            UMFPACK_STRATEGY_2BY2:  option disabled.
 
-        Control [UMFPACK_2BY2_TOLERANCE]:  a diagonal entry S (k,k) is
-            considered "small" if it is < tol * max (abs (S (:,k))), where S a
-            submatrix of the scaled input matrix, with pivots of zero Markowitz
-            cost removed.
+        Control [UMFPACK_2BY2_TOLERANCE]:  ignored.
 
         Control [UMFPACK_SCALE]:  This parameter is new to V4.1.  See
             umfpack_numeric.h for a description.  Only affects the 2-by-2
@@ -564,8 +558,7 @@ Arguments:
         Info [UMFPACK_SYMBOLIC_TIME]:  The CPU time taken, in seconds.
 
         Info [UMFPACK_STRATEGY_USED]: The ordering strategy used:
-            UMFPACK_STRATEGY_SYMMETRIC, UMFPACK_STRATEGY_UNSYMMETRIC, or
-            UMFPACK_STRATEGY_2BY2.
+            UMFPACK_STRATEGY_SYMMETRIC or UMFPACK_STRATEGY_UNSYMMETRIC
 \end{verbatim}
 }
 
diff --git a/src/C/SuiteSparse/UMFPACK/Doc/UserGuide.stex b/src/C/SuiteSparse/UMFPACK/Doc/UserGuide.stex
index cc5f40b..7f380cf 100644
--- a/src/C/SuiteSparse/UMFPACK/Doc/UserGuide.stex
+++ b/src/C/SuiteSparse/UMFPACK/Doc/UserGuide.stex
@@ -20,8 +20,8 @@
 \author{Timothy A. Davis \\
 Dept. of Computer and Information Science and Engineering \\
 Univ. of Florida, Gainesville, FL}
-\title{UMFPACK Version 5.2.0 User Guide}
-\date{Nov 1, 2007}
+\title{UMFPACK Version 5.4.0 User Guide}
+\date{May 20, 2009}
 \maketitle
 
 %-------------------------------------------------------------------------------
@@ -38,7 +38,7 @@ Univ. of Florida, Gainesville, FL}
 
 Technical Report TR-04-003 (revised)
 
-UMFPACK Version 5.2.0, Copyright\copyright 1995-2006 by Timothy A. Davis.
+Copyright\copyright 1995-2009 by Timothy A. Davis.
 All Rights Reserved.
 UMFPACK is available under alternate licences; contact T. Davis for details.
 
@@ -116,10 +116,9 @@ Rectangular matrices can only be factorized.
 
 UMFPACK first finds a column pre-ordering that reduces fill-in, without regard
 to numerical values.  It scales and analyzes the matrix, and then automatically
-selects one of three strategies for pre-ordering the rows and columns:
-{\em unsymmetric},
-{\em 2-by-2}, and
-{\em symmetric}.  These strategies are described below.
+selects one of two strategies for pre-ordering the rows and columns:
+{\em unsymmetric}
+and {\em symmetric}.  These strategies are described below.
 
 First, all pivots with zero Markowitz cost are eliminated and placed in the
 LU factors.  The remaining submatrix $\m{S}$ is then analyzed.
@@ -139,42 +138,13 @@ the strategy.
     An {\em entry} is a value in $\m{A}$ which is present
     in the input data structure.  All nonzeros are entries, but some entries
     may be numerically zero.
-    Rule 3: $\sigma_1 < 0.1 \implies$ unsymmetric.
-    The matrix is very unsymmetric.
-\item Let $d$ be the number of nonzero entries on the diagonal of $\m{S}$.
+    Let $d$ be the number of nonzero entries on the diagonal of $\m{S}$.
     Let $\m{S}$ be $\nu$-by-$\nu$.
-    Rule 4: $(\sigma_1 \ge 0.7) \:\wedge\: (d = \nu) \implies$ symmetric.
-    The matrix has a nearly symmetric nonzero pattern, and a zero-free
-    diagonal.
-\end{itemize}
-
-If the strategy has not yet been determined,
-the 2-by-2 strategy is attempted.  A row permutation $\m{P}_2$
-is found which attempts to reduce the number of small
-diagonal entries of $\m{P}_2 \m{S}$.
-An entry $s_{ij}$ is determined to be small if
-$|s_{ij}| < 0.01 \max |s_{*j}|$, or large otherwise.
-If $s_{ii}$ is numerically small, the method attempts to swap
-two rows $i$ and $j$, such that both $s_{ij}$ and $s_{ji}$ are large.
-Once these rows are swapped,
-they remain in place.  Let $\sigma_2$ be the symmetry of $\m{P}_2 \m{S}$,
-and let $d_2$ be the number of nonzero entries (either small or large)
-on the diagonal of $\m{P}_2 \m{S}$.
-
-\begin{itemize}
-\item Rule 5:
-    ($\sigma_2 > 1.1 \sigma_1) \:\wedge\: (d_2 > 0.9 \nu) \implies$ 2-by-2.
-    The 2-by-2 permutation has made the matrix significantly more symmetric.
-\item Rule 6: $\sigma_2 < 0.7 \sigma_1 \implies$ unsymmetric.
-    The 2-by-2 strategy has significantly deteriorated the symmetry,
-\item Rule 7: $\sigma_2 < 0.25 \implies$ unsymmetric.
-    The matrix is still very unsymmetric.
-\item Rule 8: $\sigma_2 \ge 0.51 \implies$ 2-by-2.
-    The matrix is roughly symmetric.
-\item Rule 9: $\sigma_2 \ge 0.999 \sigma_1 \implies$ 2-by-2.
-    The 2-by-2 permutation has preserved symmetry, or made it only
-    slightly worse.
-\item Rule 10: if no rule has yet triggered, use the unsymmetric strategy.
+    Rule 3: $(\sigma_1 \ge 0.7) \:\wedge\: (d \ge 0.9 \nu) \implies$ symmetric.
+    The matrix has a nearly symmetric nonzero pattern (70\% or more),
+    and a mostly-zero-free diagonal (90\% or more nonzero).
+\item Rule 4:
+    Otherwise, the unsymmetric strategy is used.
 \end{itemize}
 
 Each strategy is described below:
@@ -198,10 +168,6 @@ entry.  Within a given pivot column $j$, an entry $a_{ij}$ can be chosen if
 $|a_{ij}| \ge 0.1 \max |a_{*j}|$.  Among those numerically acceptable
 entries, the sparsest row $i$ is chosen as the pivot row.
 
-\item {\em 2-by-2}:
-The symmetric strategy (see below) is applied to the matrix $\m{P}_2 \m{S}$,
-rather than $\m{S}$.
-
 \item {\em symmetric}:
 The column ordering is computed from AMD
 \cite{AmestoyDavisDuff96,AmestoyDavisDuff03},
@@ -216,8 +182,10 @@ using the same method used by the unsymmetric strategy.
 
 \end{itemize}
 
-The symmetric and 2-by-2 strategies, and their automatic selection,
+The symmetric strategy, and their automatic selection,
 are new to Version 4.1.  Version 4.0 only used the unsymmetric strategy.
+Versions 4.1 through 5.3 included a {\em 2-by-2} ordering strategy,
+but this option has been disabled in Version 5.4.
 
 Once the strategy is selected,
 the factorization of the matrix $\m{A}$ is broken down into the factorization
@@ -255,7 +223,7 @@ COLMMD-style approximate degrees \cite{GilbertMolerSchreiber}), a pivot row can
 be selected based on sparsity-preserving criteria (low degree) as well as
 numerical considerations (relaxed threshold partial pivoting).
 
-When the symmetric or 2-by-2 strategies are used,
+When the symmetric strategy are used,
 the column preordering is not refined during numeric factorization.
 Row pivoting for sparsity and numerical accuracy is performed if the
 diagonal entry is too small.
@@ -269,10 +237,10 @@ http://www.cise.ufl.edu/tech-reports.
 %-------------------------------------------------------------------------------
 
 In addition to appearing as a Collected Algorithm of the ACM,
-UMFPACK is available at http://www.cise.ufl.edu/research/sparse.
+UMFPACK is available at \newline http://www.cise.ufl.edu/research/sparse.
 It is included as a built-in routine in MATLAB.
 Version 4.0 (in MATLAB 6.5)
-does not have the symmetric or 2-by-2 strategies and it takes
+does not have the symmetric strategy and it takes
 less advantage of the level-3
 BLAS \cite{DaydeDuff99,ACM679a,ATLAS,GotoVandeGeijn02}.
 Versions 5.x through v4.1 tend to be much faster than Version 4.0,
@@ -300,6 +268,20 @@ an old version of AMD with a newer version of UMFPACK can fail.}
 A detailed list of changes is in the {\tt ChangeLog} file.
 
 %-------------------------------------------------------------------------------
+\subsection{Version 5.4.0}
+%-------------------------------------------------------------------------------
+
+Disabled the 2-by-2 ordering strategy.
+Bug fix for \verb'umfpack_make.m' for Windows.
+
+%-------------------------------------------------------------------------------
+\subsection{Version 5.3.0}
+%-------------------------------------------------------------------------------
+
+A bug fix for structurally singular matrices, and a compiler workaround for
+gcc versions 4.2.(3 and 4).
+
+%-------------------------------------------------------------------------------
 \subsection{Version 5.2.0}
 %-------------------------------------------------------------------------------
 
@@ -998,7 +980,7 @@ behavior.  They are fully described in Section~\ref{Alternative}:
     or AMD pre-orderings.  For example, a graph partitioning-based order
     of $\m{A}\tr\m{A}$ would be suitable for UMFPACK's unsymmetric strategy.
     A partitioning of $\m{A}+\m{A}\tr$ would be suitable for UMFPACK's
-    symmetric or 2-by-2 strategies.
+    symmetric strategy.
 
 \item {\tt umfpack\_*\_wsolve}:
 
@@ -1355,7 +1337,7 @@ MATLAB & ANSI C & default & description \\
 {\tt Control(6)}  & {\tt Control[UMFPACK\_STRATEGY]} & 0 (auto) & select strategy \\
 {\tt Control(7)}  & {\tt Control[UMFPACK\_ALLOC\_INIT]} & 0.7 & initial memory allocation  \\
 {\tt Control(8)}  & {\tt Control[UMFPACK\_IRSTEP]} & 2 & max iter. refinement steps \\
-{\tt Control(13)} & {\tt Control[UMFPACK\_2BY2\_TOLERANCE]} & 0.01 & defines ``large'' entries \\
+{\tt Control(13)} & ignored & & \\
 {\tt Control(14)} & {\tt Control[UMFPACK\_FIXQ]} & 0 (auto) & fix or modify Q \\
 {\tt Control(15)} & {\tt Control[UMFPACK\_AMD\_DENSE]} & 10 & AMD dense row/column parameter \\
 {\tt Control(16)} & {\tt Control[UMFPACK\_SYM\_PIVOT\_TOLERANCE]} & 0.001 & for diagonal entries \\
@@ -2366,7 +2348,7 @@ let me know and I could consider including them:
 
 \item A method that takes time proportional to the number of nonzeros in
     $\m{A}$ to compute the symbolic factorization \cite{GilbertNgPeyton94}.
-    This would improve the performance of the symmetric and 2-by-2 strategies,
+    This would improve the performance of the symmetric strategy,
     and the unsymmetric strategy when dense rows are present.
     The current method takes
     time proportional to the number of nonzeros in the upper bound of $\m{U}$.
diff --git a/src/C/SuiteSparse/UMFPACK/Include/umfpack.h b/src/C/SuiteSparse/UMFPACK/Include/umfpack.h
index c720aba..a716e3f 100644
--- a/src/C/SuiteSparse/UMFPACK/Include/umfpack.h
+++ b/src/C/SuiteSparse/UMFPACK/Include/umfpack.h
@@ -97,10 +97,10 @@ extern "C" {
 /* Version, copyright, and license */
 /* -------------------------------------------------------------------------- */
 
-#define UMFPACK_VERSION "UMFPACK V5.2.0 (Nov 1, 2007)"
+#define UMFPACK_VERSION "UMFPACK V5.4.0 (May 20, 2009)"
 
 #define UMFPACK_COPYRIGHT \
-"UMFPACK:  Copyright (c) 2005-2006 by Timothy A. Davis.  All Rights Reserved.\n"
+"UMFPACK:  Copyright (c) 2005-2009 by Timothy A. Davis.  All Rights Reserved.\n"
 
 #define UMFPACK_LICENSE_PART1 \
 "\nUMFPACK License:\n" \
@@ -163,10 +163,10 @@ extern "C" {
  * above.
  */
 
-#define UMFPACK_DATE "Nov 1, 2007"
+#define UMFPACK_DATE "May 20, 2009"
 #define UMFPACK_VER_CODE(main,sub) ((main) * 1000 + (sub))
 #define UMFPACK_MAIN_VERSION 5
-#define UMFPACK_SUB_VERSION 2
+#define UMFPACK_SUB_VERSION 4
 #define UMFPACK_SUBSUB_VERSION 0
 #define UMFPACK_VER UMFPACK_VER_CODE(UMFPACK_MAIN_VERSION,UMFPACK_SUB_VERSION)
 
diff --git a/src/C/SuiteSparse/UMFPACK/Include/umfpack_symbolic.h b/src/C/SuiteSparse/UMFPACK/Include/umfpack_symbolic.h
index 1deacc2..9023ff3 100644
--- a/src/C/SuiteSparse/UMFPACK/Include/umfpack_symbolic.h
+++ b/src/C/SuiteSparse/UMFPACK/Include/umfpack_symbolic.h
@@ -226,10 +226,8 @@ Arguments:
 		[UMFPACK_PIVOT_TOLERANCE] (default 0.1) times the largest entry
 		in its column.
 
-	    UMFPACK_STRATEGY_2BY2:  a row permutation P2 is found that places
-		large entries on the diagonal.  The matrix P2*A is then
-		factorized using the symmetric strategy, described above.
-		Refer to the User Guide for more information.
+	    UMFPACK_STRATEGY_2BY2:  disabled (exists in earlier versions)
+                If requested, the symmetric strategy is used instead.
 
 	Control [UMFPACK_DENSE_COL]:
 	    If COLAMD is used, columns with more than
@@ -255,10 +253,7 @@ Arguments:
 	    Assuming the block size is large enough (8 or so), this parameter
 	    has a modest effect on performance.
 
-	Control [UMFPACK_2BY2_TOLERANCE]:  a diagonal entry S (k,k) is
-	    considered "small" if it is < tol * max (abs (S (:,k))), where S a
-	    submatrix of the scaled input matrix, with pivots of zero Markowitz
-	    cost removed.
+	Control [UMFPACK_2BY2_TOLERANCE]:  no longer used
 
 	Control [UMFPACK_SCALE]:  See umfpack_numeric.h for a description.
 	    Only affects the 2-by-2 strategy.  Default: UMFPACK_SCALE_SUM.
@@ -442,8 +437,7 @@ Arguments:
 	Info [UMFPACK_SYMBOLIC_WALLTIME]:  The wallclock time taken, in seconds.
 
 	Info [UMFPACK_STRATEGY_USED]: The ordering strategy used:
-	    UMFPACK_STRATEGY_SYMMETRIC, UMFPACK_STRATEGY_UNSYMMETRIC, or
-	    UMFPACK_STRATEGY_2BY2.
+	    UMFPACK_STRATEGY_SYMMETRIC or UMFPACK_STRATEGY_UNSYMMETRIC
 
 	Info [UMFPACK_ORDERING_USED]:  The ordering method used:
 	    UMFPACK_ORDERING_COLAMD or UMFPACK_ORDERING_AMD.  It can be
@@ -511,25 +505,6 @@ Arguments:
 	    factorization.  Excludes the part of the LU factorization for
 	    pivots with zero Markowitz cost.
 
-	------------------------------------------------------------------------
-	The following statistics are computed only if the 2-by-2 strategy is
-	used or attempted:
-	------------------------------------------------------------------------
-
-	Info [UMFPACK_2BY2_NWEAK]: the number of small diagonal entries in S.
-
-	Info [UMFPACK_2BY2_UNMATCHED]: the number of small diagonal entries
-	    in P2*S.
-
-	Info [UMFPACK_2BY2_PATTERN_SYMMETRY]: the symmetry of P2*S.
-
-	Info [UMFPACK_2BY2_NZ_PA_PLUS_AT]:  the number of off-diagonal entries
-	    in (P2*S)+(P2*S)'.
-
-	Info [UMFPACK_2BY2_NZDIAG]:  the number of nonzero entries on the
-	    diagonal of P2*S.
-
-
 	At the start of umfpack_*_symbolic, all of Info is set of -1, and then
 	after that only the above listed Info [...] entries are accessed.
 	Future versions might modify different parts of Info.
diff --git a/src/C/SuiteSparse/UMFPACK/Lib/GNUmakefile b/src/C/SuiteSparse/UMFPACK/Lib/GNUmakefile
index 559ed99..c6ec318 100644
--- a/src/C/SuiteSparse/UMFPACK/Lib/GNUmakefile
+++ b/src/C/SuiteSparse/UMFPACK/Lib/GNUmakefile
@@ -247,6 +247,9 @@ umfpack_gn_%.o: ../Source/umfpack_%.c $(INC)
 	$(AR) ../Lib/libumfpack.a $^
 	- $(RANLIB) ../Lib/libumfpack.a
 
+so: $(II) $(LL) $(GN) $(DI) $(DL) $(ZI) $(ZL)
+	gcc -shared -Wl,-soname,libumfpack.so -o libumfpack.so $^
+
 #-------------------------------------------------------------------------------
 # Remove all but the files in the original distribution
 #-------------------------------------------------------------------------------
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umf_2by2.c b/src/C/SuiteSparse/UMFPACK/Source/umf_2by2.c
index 0e31011..584f2cb 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umf_2by2.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umf_2by2.c
@@ -8,6 +8,8 @@
 /* web: http://www.cise.ufl.edu/research/sparse/umfpack                       */
 /* -------------------------------------------------------------------------- */
 
+/* NOTE: this code is currently disabled */
+
 /*  Not user-callable.  Computes a row permutation P so that A (P,:) has a
  *  mostly zero-free diagonal, with large entries on the diagonal.  It does this
  *  by swapping pairs of rows.  Once a row is swapped it is not swapped again.
@@ -57,6 +59,8 @@
  *  the output permutation P can also be used to swap the columns of A.
  */
 
+#if 0
+
 #include "umf_internal.h"
 #include "umf_2by2.h"
 
@@ -858,3 +862,5 @@ GLOBAL void UMF_2by2
     DEBUGm2 (("\n =============================UMF_2by2: done\n\n")) ;
 #endif
 }
+
+#endif
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umf_dump.c b/src/C/SuiteSparse/UMFPACK/Source/umf_dump.c
index 888a316..c68f198 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umf_dump.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umf_dump.c
@@ -1184,21 +1184,17 @@ GLOBAL void UMF_dump_diagonal_map
 (
     Int Diagonal_map [ ],
     Int Diagonal_imap [ ],
-    Int n1,
-    Int nn,
-    Int nempty
+    Int nn
 )
 {
     Int row, col ;
     if (Diagonal_map != (Int *) NULL)
     {
-	DEBUG2 (("\nDump the Diagonal_map: n1 "ID" nn "ID" nempty "ID"\n",
-	    n1, nn, nempty)) ;
-	for (col = n1 ; col < nn - nempty ; col++)
+	DEBUG2 (("\nDump the Diagonal_map: nn "ID"\n", nn)) ;
+	for (col = 0 ; col < nn ; col++)
 	{
 	    row = Diagonal_map [col] ;
-	    DEBUG2 (("     Diagonal_map [col = "ID"] gives "ID": ",
-		col, row)) ;
+	    DEBUG2 (("     Diagonal_map [col = "ID"] gives "ID": ", col, row)) ;
 	    row = UNFLIP (row) ;
 	    DEBUG2 ((" row "ID"\n", row)) ;
 	    ASSERT (Diagonal_imap [row] == col) ;
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umf_dump.h b/src/C/SuiteSparse/UMFPACK/Source/umf_dump.h
index 71ec745..f74d456 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umf_dump.h
+++ b/src/C/SuiteSparse/UMFPACK/Source/umf_dump.h
@@ -103,9 +103,7 @@ GLOBAL void UMF_dump_diagonal_map
 (
     Int Diagonal_map [ ],
     Int Diagonal_imap [ ],
-    Int n1,
-    Int nn,
-    Int nempty
+    Int nn
 ) ;
 
 #define UMF_DBMAX 50000
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umf_kernel_init.c b/src/C/SuiteSparse/UMFPACK/Source/umf_kernel_init.c
index ff1c69f..464c19c 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umf_kernel_init.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umf_kernel_init.c
@@ -486,17 +486,29 @@ GLOBAL Int UMF_kernel_init
 	ASSERT (n_row == n_col) ;
 	ASSERT (nempty_col == Symbolic->nempty_row) ;
 	ASSERT (nempty_col == nempty) ;
+
+#ifndef NDEBUG
 	for (i = 0 ; i < nn ; i++)
 	{
 	    Diagonal_map [i] = EMPTY ;
 	    Diagonal_imap [i] = EMPTY ;
 	}
-	for (k = n1 ; k < nn - nempty ; k++)
+#endif
+
+	for (k = 0 ; k < nn ; k++)
 	{
 	    newrow = Symbolic->Diagonal_map [k] ;
 	    Diagonal_map [k] = newrow ;
 	    Diagonal_imap [newrow] = k ;
 	}
+
+#ifndef NDEBUG
+	for (i = 0 ; i < nn ; i++)
+	{
+	    ASSERT (Diagonal_map [i] != EMPTY) ;
+	    ASSERT (Diagonal_imap [i] != EMPTY) ;
+	}
+#endif
     }
 
     /* ---------------------------------------------------------------------- */
@@ -923,7 +935,7 @@ GLOBAL Int UMF_kernel_init
     {
 	Entry aij ;
 	Int *InvCperm, newcol ;
-	UMF_dump_diagonal_map (Diagonal_map, Diagonal_imap, n1, nn, nempty) ;
+	UMF_dump_diagonal_map (Diagonal_map, Diagonal_imap, nn) ;
 	InvCperm = (Int *) malloc (n_col * sizeof (Int)) ;
 	ASSERT (InvCperm != (Int *) NULL) ;
 	for (newcol = 0 ; newcol < n_col ; newcol++)
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umf_local_search.c b/src/C/SuiteSparse/UMFPACK/Source/umf_local_search.c
index 4e7cabe..ecfb388 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umf_local_search.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umf_local_search.c
@@ -1907,14 +1907,17 @@ GLOBAL Int UMF_local_search
     /* keep track of the diagonal */
     /* ---------------------------------------------------------------------- */
 
-    if (Symbolic->prefer_diagonal
-	&& Work->pivcol < Work->n_col - Symbolic->nempty_col)
+    if (Symbolic->prefer_diagonal)
     {
 	Diagonal_map = Work->Diagonal_map ;
 	Diagonal_imap = Work->Diagonal_imap ;
 	ASSERT (Diagonal_map != (Int *) NULL) ;
 	ASSERT (Diagonal_imap != (Int *) NULL) ;
 
+#ifndef NDEBUG
+	UMF_dump_diagonal_map (Diagonal_map, Diagonal_imap, Symbolic->n_col) ;
+#endif
+
 	row2 = Diagonal_map  [Work->pivcol] ;
 	col2 = Diagonal_imap [Work->pivrow] ;
 
@@ -1944,8 +1947,7 @@ GLOBAL Int UMF_local_search
 	}
 	ASSERT (n_row == n_col) ;
 #ifndef NDEBUG
-	UMF_dump_diagonal_map (Diagonal_map, Diagonal_imap, Symbolic->n1,
-	    Symbolic->n_col, Symbolic->nempty_col) ;
+	UMF_dump_diagonal_map (Diagonal_map, Diagonal_imap, Symbolic->n_col) ;
 #endif
     }
 
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umf_singletons.c b/src/C/SuiteSparse/UMFPACK/Source/umf_singletons.c
index 8288220..663a590 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umf_singletons.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umf_singletons.c
@@ -885,17 +885,26 @@ GLOBAL Int UMF_singletons
     /* see if pruned submatrix is square and has been symmetrically permuted */
     /* ---------------------------------------------------------------------- */
 
+    /* The prior version of this code (with a "break" statement; UMFPACK 5.2)
+     * causes UMFPACK to fail when optimization is enabled with gcc version
+     * 4.2.4 in a 64-bit Linux environment.  The bug is a compiler bug, not a
+     * an UMFPACK bug.  It is fixed in gcc version 4.3.2.  However, as a
+     * workaround for the compiler, the code below has been "fixed". */
+
     if (n_row == n_col && nempty_row == nempty_col)
     {
 	/* is_sym is true if the submatrix is square, and
 	 * Rperm [n1..n_row-nempty_row-1] = Cperm [n1..n_col-nempty_col-1] */
 	is_sym = TRUE ;
-	for (s = n1 ; s < n_col - nempty_col ; s++)
+	for (s = n1 ; /* replaced the break with this test: */ is_sym &&
+            /* the remainder of this test is unchanged from v5.2.0: */
+            s < n_col - nempty_col ; s++)
 	{
 	    if (Cperm [s] != Rperm [s])
 	    {
 		is_sym = FALSE ;
-		break ;
+		/* removed a break statement here, which is OK but it tickles
+                 * the gcc 4.2.{3,4} compiler bug */
 	    }
 	}
     }
@@ -903,6 +912,7 @@ GLOBAL Int UMF_singletons
     {
 	is_sym = FALSE ;
     }
+
     DEBUGm4 (("Submatrix square and symmetrically permuted? "ID"\n", is_sym)) ;
     DEBUGm4 (("singletons "ID" row "ID" col "ID"\n", n1, n1r, n1c)) ;
     DEBUGm4 (("Empty cols "ID" rows "ID"\n", nempty_col, nempty_row)) ;
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umfpack_qsymbolic.c b/src/C/SuiteSparse/UMFPACK/Source/umfpack_qsymbolic.c
index 3e2674f..fe3967b 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umfpack_qsymbolic.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umfpack_qsymbolic.c
@@ -361,7 +361,9 @@ GLOBAL Int UMFPACK_qsymbolic
     dcol = GET_CONTROL (UMFPACK_DENSE_COL, UMFPACK_DEFAULT_DENSE_COL) ;
     nb = GET_CONTROL (UMFPACK_BLOCK_SIZE, UMFPACK_DEFAULT_BLOCK_SIZE) ;
     strategy = GET_CONTROL (UMFPACK_STRATEGY, UMFPACK_DEFAULT_STRATEGY) ;
+#if 0
     tol = GET_CONTROL (UMFPACK_2BY2_TOLERANCE, UMFPACK_DEFAULT_2BY2_TOLERANCE) ;
+#endif
     scale = GET_CONTROL (UMFPACK_SCALE, UMFPACK_DEFAULT_SCALE) ;
     force_fixQ = GET_CONTROL (UMFPACK_FIXQ, UMFPACK_DEFAULT_FIXQ) ;
     AMD_defaults (amd_Control) ;
@@ -378,7 +380,10 @@ GLOBAL Int UMFPACK_qsymbolic
     DEBUG0 (("UMFPACK_qsymbolic: nb = "ID" aggressive = "ID"\n", nb,
 	aggressive)) ;
 
+#if 0
     tol = MAX (0.0, MIN (tol,  1.0)) ;
+#endif
+
     if (scale != UMFPACK_SCALE_NONE && scale != UMFPACK_SCALE_MAX)
     {
 	scale = UMFPACK_DEFAULT_SCALE ;
@@ -825,6 +830,7 @@ GLOBAL Int UMFPACK_qsymbolic
     /* determine the initial strategy based on symmetry and nnz (diag (S)) */
     /* ---------------------------------------------------------------------- */
 
+#if 0
     if (strategy == UMFPACK_STRATEGY_AUTO)
     {
 	if (sym < 0.10)
@@ -848,6 +854,39 @@ GLOBAL Int UMFPACK_qsymbolic
 	    DEBUGm4 (("Strategy: try 2-by-2\n")) ;
 	}
     }
+#endif
+
+    /* The 2-by-2 strategy can cause an error UMFPACK_ERROR_different_pattern
+     * (-11) when factorizing a structurally singular matrix.  The problem
+     * occurs very rarely.  It's a conflict between the search of the row
+     * merge tree and the 2-by-2 pre-permutation.  Until this bug is fixed,
+     * the 2-by-2 strategy is disabled. */
+
+    if (strategy == UMFPACK_STRATEGY_AUTO)
+    {
+        if (sym >= 0.7 && nzdiag >= 0.9 * n2)
+        {
+            /* pattern is mostly symmetric (70% or more) and the diagonal is
+             * mostly zero-free (90% or more).  Use symmetric strategy. */
+	    strategy = UMFPACK_STRATEGY_SYMMETRIC ;
+	    DEBUG0 (("Strategy: select symmetric\n")) ;
+        }
+        else
+        {
+            /* otherwise use unsymmetric strategy */
+	    strategy = UMFPACK_STRATEGY_UNSYMMETRIC ;
+	    DEBUG0 (("Strategy: select unsymmetric\n")) ;
+        }
+    }
+
+    if (strategy == UMFPACK_STRATEGY_2BY2)
+    {
+        /* If the user insists on the 2-by-2 strategy, use the symmetric 
+         * strategy instead. */
+        strategy = UMFPACK_STRATEGY_SYMMETRIC ;
+    }
+
+#if 0
 
     /* ---------------------------------------------------------------------- */
     /* try the 2-by-2 strategy */
@@ -1058,6 +1097,7 @@ GLOBAL Int UMFPACK_qsymbolic
 
 	/* Fr_* no longer needed for Rp, Blen, W ] */
     }
+#endif
 
     /* ---------------------------------------------------------------------- */
     /* finalize the strategy, including fixQ and prefer_diagonal */
@@ -1073,6 +1113,7 @@ GLOBAL Int UMFPACK_qsymbolic
 	fixQ = TRUE ;
 	prefer_diagonal = TRUE ;
     }
+#if 0
     else if (strategy == UMFPACK_STRATEGY_2BY2)
     {
 	/* use Q = given Quser or Q = AMD (PA+PA'), fix Q during factorization,
@@ -1083,6 +1124,7 @@ GLOBAL Int UMFPACK_qsymbolic
 	fixQ = TRUE ;
 	prefer_diagonal = TRUE ;
     }
+#endif
     else
     {
 	/* use given Quser or COLAMD (A), refine Q during factorization,
@@ -1792,9 +1834,8 @@ GLOBAL Int UMFPACK_qsymbolic
      * by the column permutation, where "row" is a row index of the original
      * matrix A.  It is not dependent on the Rperm_2by2 permutation, which
      * only redefines the "diagonal".   Both are used to construct the
-     * Diagonal_map.  Diagonal_map only needs to be defined for
-     * k = n1 to nn - nempty, but go ahead and define it for all of
-     * k = 0 to nn */
+     * Diagonal_map.
+     */
 
     if (prefer_diagonal)
     {
@@ -1821,6 +1862,7 @@ GLOBAL Int UMFPACK_qsymbolic
 	    ASSERT (oldrow >= 0 && oldrow < nn) ;
 	    Ci [oldrow] = newrow ;
 	}
+#if 0
 	if (strategy == UMFPACK_STRATEGY_2BY2)
 	{
 	    ASSERT (Rperm_2by2 != (Int *) NULL) ;
@@ -1830,20 +1872,25 @@ GLOBAL Int UMFPACK_qsymbolic
 		/* 2-by-2 pivoting done in S */
 		oldrow = Rperm_2by2 [oldcol] ;
 		newrow = Ci [oldrow] ;
+                ASSERT (newrow >= 0 && newrow < nn) ;
 		Diagonal_map [newcol] = newrow ;
 	    }
 	}
 	else
 	{
+#endif
 	    for (newcol = 0 ; newcol < nn ; newcol++)
 	    {
 		oldcol = Cperm_init [newcol] ;
 		/* no 2-by-2 pivoting in S */
 		oldrow = oldcol ;
 		newrow = Ci [oldrow] ;
+                ASSERT (newrow >= 0 && newrow < nn) ;
 		Diagonal_map [newcol] = newrow ;
 	    }
+#if 0
 	}
+#endif
 
 #ifndef NDEBUG
 	DEBUG1 (("\nDiagonal map:\n")) ;
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_control.c b/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_control.c
index 30a51b9..8993e04 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_control.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_control.c
@@ -127,6 +127,7 @@ GLOBAL void UMFPACK_report_control
 	"        Q = COLAMD (A), Q refined during numerical\n"
 	"        factorization, and no attempt at diagonal pivoting.\n")) ;
     }
+#if 0
     else if (strategy == UMFPACK_STRATEGY_2BY2)
     {
 	PRINTF ((" (symmetric, with 2-by-2 block pivoting)\n"
@@ -135,6 +136,7 @@ GLOBAL void UMFPACK_report_control
 	"        numerical factorization, attempt to select pivots from the\n"
 	"        diagonal of P2*A.\n")) ;
     }
+#endif
     else /* auto strategy */
     {
 	strategy = UMFPACK_STRATEGY_AUTO ;
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_info.c b/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_info.c
index ac55466..a85caa6 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_info.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_info.c
@@ -202,14 +202,16 @@ GLOBAL void UMFPACK_report_info
     {
 	PRINTF (("\n    strategy used:                    symmetric\n")) ;
     }
-    else if (Info [UMFPACK_STRATEGY_USED] == UMFPACK_STRATEGY_UNSYMMETRIC)
+    else /* if (Info [UMFPACK_STRATEGY_USED] == UMFPACK_STRATEGY_UNSYMMETRIC)*/
     {
 	PRINTF (("\n    strategy used:                    unsymmetric\n")) ;
     }
+#if 0
     else if (Info [UMFPACK_STRATEGY_USED] == UMFPACK_STRATEGY_2BY2)
     {
 	PRINTF (("\n    strategy used:                    symmetric 2-by-2\n"));
     }
+#endif
 
     if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_AMD)
     {
@@ -294,6 +296,8 @@ GLOBAL void UMFPACK_report_info
     /* statistics from 2-by-2 permutation */
     /* ---------------------------------------------------------------------- */
 
+#if 0
+
     PRINT_INFO ("    2-by-2 pivoting to place large entries on diagonal:\n"
 		"        # of small diagonal entries of S:          %.0f\n",
 	Info [UMFPACK_2BY2_NWEAK]) ;
@@ -311,6 +315,8 @@ GLOBAL void UMFPACK_report_info
 	Info [UMFPACK_2BY2_NZDIAG] / n2)) ;
     }
 
+#endif
+
     /* ---------------------------------------------------------------------- */
     /* statistics from AMD */
     /* ---------------------------------------------------------------------- */
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_symbolic.c b/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_symbolic.c
index 57e134e..7b8a491 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_symbolic.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umfpack_report_symbolic.c
@@ -10,7 +10,7 @@
 
 /*
     User-callable.  Prints the Symbolic object. See umfpack_report_symbolic.h
-    for details.  Does not print new Cdeg, Rdeg, Esize, and the Diagonal_map.
+    for details.  Not all of the object is printed.
 
     Dynamic memory usage:  Allocates a size MAX (n_row,n_col)*sizeof(Int)
     workspace via a single call to UMF_malloc and then frees all of it via
@@ -85,14 +85,16 @@ GLOBAL Int UMFPACK_report_symbolic
 	{
 	    PRINTF (("symmetric")) ;
 	}
-	else if (Symbolic->strategy == UMFPACK_STRATEGY_UNSYMMETRIC)
+	else /* if (Symbolic->strategy == UMFPACK_STRATEGY_UNSYMMETRIC) */
 	{
 	    PRINTF (("unsymmetric")) ;
 	}
+#if 0
 	else if (Symbolic->strategy == UMFPACK_STRATEGY_2BY2)
 	{
 	    PRINTF (("symmetric 2-by-2")) ;
 	}
+#endif
 	PRINTF (("\n")) ;
 
 	PRINTF (("    ordering used:                              ")) ;
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umfpack_tictoc.c b/src/C/SuiteSparse/UMFPACK/Source/umfpack_tictoc.c
index 7fc5fba..62e0e07 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umfpack_tictoc.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umfpack_tictoc.c
@@ -44,6 +44,20 @@ void umfpack_toc (double stats [2])
 /* timer routines, using either times() or clock() */
 /* -------------------------------------------------------------------------- */
 
+#ifdef LIBRT
+
+/* Linux/Unix, must compile with -lrt */
+#include <time.h>
+
+void umfpack_tic (double stats [2])
+{
+    /* get the current real time and return as a double */
+    stats [0] = umfpack_timer ( ) ;
+    stats [1] = stats [0] ;
+}
+
+#else
+
 #define TINY_TIME 1e-4
 
 #ifndef NPOSIX
@@ -83,6 +97,7 @@ void umfpack_tic (double stats [2])
 }
 
 #endif
+#endif
 
 /* -------------------------------------------------------------------------- */
 
diff --git a/src/C/SuiteSparse/UMFPACK/Source/umfpack_timer.c b/src/C/SuiteSparse/UMFPACK/Source/umfpack_timer.c
index 8e46687..3818a18 100644
--- a/src/C/SuiteSparse/UMFPACK/Source/umfpack_timer.c
+++ b/src/C/SuiteSparse/UMFPACK/Source/umfpack_timer.c
@@ -30,6 +30,20 @@ double umfpack_timer ( void )
 
 #else
 
+#ifdef LIBRT
+
+#include <time.h>
+double umfpack_timer ( void ) /* returns time in seconds */
+{
+    /* get the current real time and return as a double */
+    struct timespec now ;
+    clock_gettime (CLOCK_REALTIME, &now) ;
+    return ((double) (now.tv_sec ) + (double) (now.tv_nsec) * 1e-9) ;
+}
+
+
+#else
+
 #ifdef GETRUSAGE
 
 /* -------------------------------------------------------------------------- */
@@ -83,3 +97,4 @@ double umfpack_timer ( void )
 
 #endif
 #endif
+#endif
diff --git a/src/C/amd.c b/src/C/amd.c
index a82427f..1d682c1 100644
--- a/src/C/amd.c
+++ b/src/C/amd.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -52,21 +52,21 @@ static const param_tuple AMD_PARAM_LIST[] = {
     {"AMD_AGGRESSIVE", AMD_AGGRESSIVE}
 }; /* 2 parameters */
 
-static int get_param_idx(char *str, int *idx) 
+static int get_param_idx(char *str, int *idx)
 {
     int i;
 
     for (i=0; i<2; i++) if (!strcmp(AMD_PARAM_LIST[i].name, str)) {
-        *idx =  AMD_PARAM_LIST[i].idx; 
+        *idx =  AMD_PARAM_LIST[i].idx;
         return 1;
     }
-    return 0;  
+    return 0;
 }
 
 static int set_defaults(double *control)
 {
-    int_t pos=0; 
-    int param_id; 
+    int_t pos=0;
+    int param_id;
     PyObject *param, *key, *value;
     char *keystr, err_str[100];
 
@@ -78,13 +78,13 @@ static int set_defaults(double *control)
             "dictionary");
         return 0;
     }
-    while (PyDict_Next(param, &pos, &key, &value)) 
-        if ((keystr = PyString_AsString(key)) && get_param_idx(keystr, 
+    while (PyDict_Next(param, &pos, &key, &value))
+        if ((keystr = PyString_AsString(key)) && get_param_idx(keystr,
             &param_id)) {
             if (!PyInt_Check(value) && !PyFloat_Check(value)){
                 sprintf(err_str, "invalid value for AMD parameter: "
                     "%-.20s", keystr);
-                PyErr_SetString(PyExc_ValueError, err_str); 
+                PyErr_SetString(PyExc_ValueError, err_str);
                 Py_DECREF(param);
                 return 0;
             }
@@ -95,7 +95,7 @@ static int set_defaults(double *control)
 }
 
 
-static char doc_order[] = 
+static char doc_order[] =
     "Computes the approximate minimum degree ordering of a square "
     "matrix.\n\n"
     "p = order(A, uplo='L')\n\n"
@@ -108,10 +108,10 @@ static char doc_order[] =
     "          of A is used and the upper triangular is ignored.  If\n"
     "          uplo is 'U', the upper triangular part is used and the\n"
     "          lower triangular part is ignored.\n\n"
-    "p         'i' matrix of length equal to the order of A";  
+    "p         'i' matrix of length equal to the order of A";
 
 
-static PyObject* order_c(PyObject *self, PyObject *args, 
+static PyObject* order_c(PyObject *self, PyObject *args,
     PyObject *kwrds)
 {
     spmatrix *A;
@@ -122,7 +122,7 @@ static PyObject* order_c(PyObject *self, PyObject *args,
     double control[AMD_CONTROL];
     char *kwlist[] = {"A", "uplo", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|c", kwlist, &A, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|c", kwlist, &A,
         &uplo)) return NULL;
     if (!set_defaults(control)) return NULL;
     if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)){
@@ -131,18 +131,18 @@ static PyObject* order_c(PyObject *self, PyObject *args,
         return NULL;
     }
     if (uplo != 'U' && uplo != 'L') err_char("uplo", "'L', 'U'");
-    if (!(perm = (matrix *) Matrix_New(SP_NROWS(A),1,INT)))    
+    if (!(perm = (matrix *) Matrix_New(SP_NROWS(A),1,INT)))
         return PyErr_NoMemory();
     n = SP_NROWS(A);
     for (nnz=0, j=0; j<n; j++) {
 	if (uplo == 'L'){
-            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k]<j; 
-                k++); 
+            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k]<j;
+                k++);
             nnz += SP_COL(A)[j+1] - k;
 	}
 	else {
-            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] <= j; 
-                k++); 
+            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] <= j;
+                k++);
             nnz += k - SP_COL(A)[j];
         }
     }
@@ -161,29 +161,29 @@ static PyObject* order_c(PyObject *self, PyObject *args,
 	colptr[0] = 0;
         for (j=0; j<n; j++) {
 	    if (uplo == 'L'){
-                for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && 
+                for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] &&
                     SP_ROW(A)[k] < j; k++);
 		nnz = SP_COL(A)[j+1] - k;
                 colptr[j+1] = colptr[j] + nnz;
-		memcpy(rowind + colptr[j], (int_t *) SP_ROW(A) + k, 
+		memcpy(rowind + colptr[j], (int_t *) SP_ROW(A) + k,
                     nnz*sizeof(int_t));
 	    }
 	    else {
-                for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && 
+                for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] &&
                     SP_ROW(A)[k] <= j; k++);
                 nnz = k - SP_COL(A)[j];
                 colptr[j+1] = colptr[j] + nnz;
-		memcpy(rowind + colptr[j], (int_t *) (SP_ROW(A) + 
+		memcpy(rowind + colptr[j], (int_t *) (SP_ROW(A) +
                     SP_COL(A)[j]), nnz*sizeof(int_t));
 	    }
         }
     }
     info = amd_order(n, colptr, rowind, MAT_BUFI(perm), control, NULL);
     if (alloc){
-        free(colptr);  
+        free(colptr);
         free(rowind);
     }
-    switch (info) { 
+    switch (info) {
         case AMD_OUT_OF_MEMORY:
             Py_XDECREF(perm);
             return PyErr_NoMemory();
@@ -205,7 +205,7 @@ static PyMethodDef amd_functions[] = {
 
 PyMODINIT_FUNC initamd(void)
 {
-    amd_module = Py_InitModule3("cvxopt.amd", amd_functions, 
+    amd_module = Py_InitModule3("cvxopt.amd", amd_functions,
         amd__doc__);
     PyModule_AddObject(amd_module, "options", PyDict_New());
     if (import_cvxopt() < 0) return;
diff --git a/src/C/base.c b/src/C/base.c
index 7dbc02e..71e1ea2 100644
--- a/src/C/base.c
+++ b/src/C/base.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
 
 #include "Python.h"
 #include "cvxopt.h"
-#include "misc.h" 
+#include "misc.h"
 
 #include <complexobject.h>
 
@@ -30,35 +30,35 @@ PyDoc_STRVAR(base__doc__,"Convex optimization package");
 extern PyTypeObject matrix_tp ;
 matrix * Matrix_New(int, int, int) ;
 matrix * Matrix_NewFromMatrix(matrix *, int) ;
-matrix * Matrix_NewFromSequence(PyObject *, int) ; 
+matrix * Matrix_NewFromSequence(PyObject *, int) ;
 matrix * Matrix_NewFromArrayStruct(PyObject *, int, int *) ;
 
 extern PyTypeObject spmatrix_tp ;
 spmatrix * SpMatrix_New(int_t, int_t, int, int ) ;
 spmatrix * SpMatrix_NewFromMatrix(matrix *, int) ;
-spmatrix * SpMatrix_NewFromSpMatrix(spmatrix *, int) ; 
-spmatrix * SpMatrix_NewFromIJV(matrix *, matrix *, matrix *, 
+spmatrix * SpMatrix_NewFromSpMatrix(spmatrix *, int) ;
+spmatrix * SpMatrix_NewFromIJV(matrix *, matrix *, matrix *,
     int_t, int_t, int, int) ;
 void free_ccs(ccs *) ;
 
 extern int (*sp_axpy[])(number, void *, void *, int, int, int, void **) ;
 
-extern int (*sp_gemm[])(char, char, number, void *, void *, number, void *, 
+extern int (*sp_gemm[])(char, char, number, void *, void *, number, void *,
     int, int, int, int, void **, int, int, int);
 
-extern int (*sp_gemv[])(char, int, int, number, void *, int, void *, int,  
+extern int (*sp_gemv[])(char, int, int, number, void *, int, void *, int,
     number, void *, int) ;
 
 extern int (*sp_symv[])(char, int, number, ccs *, int, void *, int,
     number, void *, int) ;
 
-extern int (*sp_syrk[])(char, char, number, void *, number, 
+extern int (*sp_syrk[])(char, char, number, void *, number,
     void *, int, int, int, int, void **) ;
 
 const int  E_SIZE[] = { sizeof(int_t), sizeof(double), sizeof(complex) };
 const char TC_CHAR[][2] = {"i","d","z"} ;
 
-/* 
+/*
  *  Helper routines and definitions to implement type transparency.
  */
 
@@ -77,7 +77,7 @@ static void write_znum(void *dest, int i, void *src, int j) {
 }
 
 void (*write_num[])(void *, int, void *, int) = {
-  write_inum, write_dnum, write_znum };
+    write_inum, write_dnum, write_znum };
 
 static PyObject * inum2PyObject(void *src, int i) {
   return Py_BuildValue("l", ((int_t *)src)[i]);
@@ -95,33 +95,33 @@ static PyObject * znum2PyObject(void *src, int i) {
 }
 
 PyObject * (*num2PyObject[])(void *, int) = {
-  inum2PyObject, dnum2PyObject, znum2PyObject };
+    inum2PyObject, dnum2PyObject, znum2PyObject };
 
 /* val_id: 0 = matrix, 1 = PyNumber */
-static int 
-convert_inum(void *dest, void *val, int val_id, int offset) 
+static int
+convert_inum(void *dest, void *val, int val_id, int offset)
 {
   if (val_id==0) { /* 1x1 matrix */
     switch (MAT_ID(val)) {
-    case INT: 
-      *(int_t *)dest = MAT_BUFI(val)[offset]; return 0; 
-      //case DOUBLE: 
-      //*(int_t *)dest = (int_t)round(MAT_BUFD(val)[offset]); return 0; 
+    case INT:
+      *(int_t *)dest = MAT_BUFI(val)[offset]; return 0;
+      //case DOUBLE:
+      //*(int_t *)dest = (int_t)round(MAT_BUFD(val)[offset]); return 0;
     default: PY_ERR_INT(PyExc_TypeError,"cannot cast argument as integer");
     }
   } else { /* PyNumber */
     if (PyInt_Check((PyObject *)val)) {
-      *(int_t *)dest = PyInt_AS_LONG((PyObject *)val); return 0; 
-    } 
+      *(int_t *)dest = PyInt_AS_LONG((PyObject *)val); return 0;
+    }
     //else if (PyFloat_Check((PyObject *)val)) {
-    //  *(int_t *)dest = roundl(PyFloat_AS_DOUBLE((PyObject *)val)); return 0; 
+    //  *(int_t *)dest = roundl(PyFloat_AS_DOUBLE((PyObject *)val)); return 0;
     //}
     else PY_ERR_INT(PyExc_TypeError,"cannot cast argument as integer");
-  }    
+  }
 }
 
-static int 
-convert_dnum(void *dest, void *val, int val_id, int offset) 
+static int
+convert_dnum(void *dest, void *val, int val_id, int offset)
 {
   if (val_id==0) { /* matrix */
     switch (MAT_ID(val)) {
@@ -131,35 +131,35 @@ convert_dnum(void *dest, void *val, int val_id, int offset)
     }
   } else { /* PyNumber */
     if (PyInt_Check((PyObject *)val) || PyFloat_Check((PyObject *)val)) {
-      *(double *)dest = PyFloat_AsDouble((PyObject *)val); 
+      *(double *)dest = PyFloat_AsDouble((PyObject *)val);
       return 0;
     }
     else PY_ERR_INT(PyExc_TypeError,"cannot cast argument as double");
-  } 
+  }
 }
 
-static int 
-convert_znum(void *dest, void *val, int val_id, int offset) 
-{  
+static int
+convert_znum(void *dest, void *val, int val_id, int offset)
+{
   if (val_id==0) { /* 1x1 matrix */
     switch (MAT_ID(val)) {
-    case INT:     
+    case INT:
       *(complex *)dest = MAT_BUFI(val)[offset]; return 0;
-    case DOUBLE:  
+    case DOUBLE:
       *(complex *)dest = MAT_BUFD(val)[offset]; return 0;
     case COMPLEX:
       *(complex *)dest = MAT_BUFZ(val)[offset]; return 0;
-    default: return -1; 
+    default: return -1;
     }
   } else { /* PyNumber */
     Py_complex c = PyComplex_AsCComplex((PyObject *)val);
     *(complex *)dest = c.real + I*c.imag;
     return 0;
-  }    
+  }
 }
 
-int (*convert_num[])(void *, void *, int, int) = { 
-  convert_inum, convert_dnum, convert_znum };
+int (*convert_num[])(void *, void *, int, int) = {
+    convert_inum, convert_dnum, convert_znum };
 
 extern void daxpy_(int *, void *, void *, int *, void *, int *) ;
 extern void zaxpy_(int *, void *, void *, int *, void *, int *) ;
@@ -171,8 +171,8 @@ static void i_axpy(int *n, void *a, void *x, int *incx, void *y, int *incy) {
   }
 }
 
-void (*axpy[])(int *, void *, void *, int *, void *, int *) = { 
-  i_axpy, daxpy_, zaxpy_ };
+void (*axpy[])(int *, void *, void *, int *, void *, int *) = {
+    i_axpy, daxpy_, zaxpy_ };
 
 extern void dscal_(int *, void *, void *, int *) ;
 extern void zscal_(int *, void *, void *, int *) ;
@@ -193,28 +193,28 @@ extern void zgemm_(char *, char *, int *, int *, int *, void *, void *,
     int *, void *, int *, void *, void *, int *) ;
 
 /* we dont implement a BLAS igemm */
-static void i_gemm(char *transA, char *transB, int *m, int *n, int *k, 
-    void *alpha, void *A, int *ldA, void *B, int *ldB, void *beta, 
-    void *C, int *ldC) 
+static void i_gemm(char *transA, char *transB, int *m, int *n, int *k,
+    void *alpha, void *A, int *ldA, void *B, int *ldB, void *beta,
+    void *C, int *ldC)
 {
   int i, j, l;
-  for (j=0; j<*n; j++) {   
-    for (i=0; i<*m; i++) {      
+  for (j=0; j<*n; j++) {
+    for (i=0; i<*m; i++) {
       ((int_t *)C)[i+j*(*m)] = 0;
       for (l=0; l<*k; l++)
-	((int_t *)C)[i+j*(*m)]+=((int_t *)A)[i+l*(*m)]*((int_t *)B)[j*(*k)+l];
-    }    
-  }  
+        ((int_t *)C)[i+j*(*m)]+=((int_t *)A)[i+l*(*m)]*((int_t *)B)[j*(*k)+l];
+    }
+  }
 }
 
-void (*gemm[])(char *, char *, int *, int *, int *, void *, void *, int *, 
+void (*gemm[])(char *, char *, int *, int *, int *, void *, void *, int *,
     void *, int *, void *, void *, int *) = { i_gemm, dgemm_, zgemm_ };
 
-extern void dgemv_(char *, int *, int *, void *, void *, int *, void *, 
+extern void dgemv_(char *, int *, int *, void *, void *, int *, void *,
     int *, void *, void *, int *);
-extern void zgemv_(char *, int *, int *, void *, void *, int *, void *, 
+extern void zgemv_(char *, int *, int *, void *, void *, int *, void *,
     int *, void *, void *, int *);
-static void (*gemv[])(char *, int *, int *, void *, void *, int *, void *, 
+static void (*gemv[])(char *, int *, int *, void *, void *, int *, void *,
     int *, void *, void *, int *) = { NULL, dgemv_, zgemv_ };
 
 extern void dsyrk_(char *, char *, int *, int *, void *, void *,
@@ -224,11 +224,11 @@ extern void zsyrk_(char *, char *, int *, int *, void *, void *,
 void (*syrk[])(char *, char *, int *, int *, void *, void *,
     int *, void *, void *, int *) = { NULL, dsyrk_, zsyrk_ };
 
-extern void dsymv_(char *, int *, void *, void *, int *, void *, int *, 
+extern void dsymv_(char *, int *, void *, void *, int *, void *, int *,
     void *, void *, int *);
-extern void zsymv_(char *, int *, void *, void *, int *, void *, int *, 
+extern void zsymv_(char *, int *, void *, void *, int *, void *, int *,
     void *, void *, int *);
-void (*symv[])(char *, int *, void *, void *, int *, void *, int *, 
+void (*symv[])(char *, int *, void *, void *, int *, void *, int *,
     void *, void *, int *) = { NULL, dsymv_, zsymv_ };
 
 static void mtx_iabs(void *src, void *dest, int n) {
@@ -245,7 +245,7 @@ static void mtx_dabs(void *src, void *dest, int n) {
 
 static void mtx_zabs(void *src, void *dest, int n) {
   int i;
-  for (i=0; i<n; i++) 
+  for (i=0; i<n; i++)
     ((double *)dest)[i] = cabs(((complex *)src)[i]);
 }
 
@@ -273,9 +273,9 @@ static int zdiv(void *dest, number a, int n) {
     PY_ERR_INT(PyExc_ZeroDivisionError, "division by zero");
 
   int _n = n, int1 = 1;
-  complex _a = 1.0/a.z; 
+  complex _a = 1.0/a.z;
   zscal_(&_n, (void *)&_a, dest, &int1);
-  return 0;  
+  return 0;
 }
 
 int (*div_array[])(void *, number, int) = { idiv, ddiv, zdiv };
@@ -292,7 +292,7 @@ static int mtx_irem(void *dest, number a, int n) {
 static int mtx_drem(void *dest, number a, int n) {
   if (a.d==0.0) PY_ERR_INT(PyExc_ZeroDivisionError, "division by zero");
   int i;
-  for (i=0; i<n; i++) 
+  for (i=0; i<n; i++)
     ((double *)dest)[i] -= floor(((double *)dest)[i]/a.d)*a.d;
 
   return 0;
@@ -304,15 +304,15 @@ int (*mtx_rem[])(void *, number, int) = { mtx_irem, mtx_drem };
 int get_id(void *val, int val_type) {
   if (!val_type) {
     if Matrix_Check((PyObject *)val)
-      return MAT_ID((matrix *)val);
-    else 
+    return MAT_ID((matrix *)val);
+    else
       return SP_ID((spmatrix *)val);
   }
-  else if (PyInt_Check((PyObject *)val)) 
+  else if (PyInt_Check((PyObject *)val))
     return INT;
   else if (PyFloat_Check((PyObject *)val))
     return DOUBLE;
-  else 
+  else
     return COMPLEX;
 }
 
@@ -341,14 +341,14 @@ static char doc_axpy[] =
 
 PyObject * base_axpy(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-  PyObject *x, *y, *partial = NULL; 
+  PyObject *x, *y, *partial = NULL;
   PyObject *ao=NULL;
   number a;
   char *kwlist[] = {"x", "y", "alpha", "partial", NULL};
-  
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|OO:axpy", kwlist, 
-	  &x, &y, &ao, &partial)) return NULL;
-  
+
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|OO:axpy", kwlist,
+      &x, &y, &ao, &partial)) return NULL;
+
   if (!Matrix_Check(x) && !SpMatrix_Check(x)) err_mtrx("x");
   if (!Matrix_Check(y) && !SpMatrix_Check(y)) err_mtrx("y");
   if (partial && !PyBool_Check(partial)) err_bool("partial");
@@ -358,29 +358,29 @@ PyObject * base_axpy(PyObject *self, PyObject *args, PyObject *kwrds)
 
   if (X_NROWS(x) != X_NROWS(y) || X_NCOLS(x) != X_NCOLS(y))
     PY_ERR_TYPE("dimensions of x and y do not match");
-  
+
   if (ao && convert_num[id](&a, ao, 1, 0)) err_type("alpha");
-  
+
   if (Matrix_Check(x) && Matrix_Check(y)) {
     int n = X_NROWS(x)*X_NCOLS(x);
-    axpy[id](&n, (ao ? &a : &One[id]), MAT_BUF(x), (int *)&One[INT], 
-	MAT_BUF(y), (int *)&One[INT]);
+    axpy[id](&n, (ao ? &a : &One[id]), MAT_BUF(x), (int *)&One[INT],
+        MAT_BUF(y), (int *)&One[INT]);
   }
   else {
 
     void *z = NULL;
-    if (sp_axpy[id]((ao ? a : One[id]), 
-	    Matrix_Check(x) ? MAT_BUF(x): ((spmatrix *)x)->obj,  
-	    Matrix_Check(y) ? MAT_BUF(y): ((spmatrix *)y)->obj,  
-	    SpMatrix_Check(x), SpMatrix_Check(y), 
-	    partial ? PyInt_AS_LONG(partial) : 0, &z))
-      return PyErr_NoMemory(); 
-
-    if (z) { 
+    if (sp_axpy[id]((ao ? a : One[id]),
+        Matrix_Check(x) ? MAT_BUF(x): ((spmatrix *)x)->obj,
+            Matrix_Check(y) ? MAT_BUF(y): ((spmatrix *)y)->obj,
+                SpMatrix_Check(x), SpMatrix_Check(y),
+                partial ? PyInt_AS_LONG(partial) : 0, &z))
+      return PyErr_NoMemory();
+
+    if (z) {
       free_ccs( ((spmatrix *)y)->obj );
       ((spmatrix *)y)->obj = z;
     }
-  } 
+  }
 
   return Py_BuildValue("");
 }
@@ -389,7 +389,7 @@ static char doc_gemm[] =
     "General matrix-matrix product.\n\n"
     "gemm(A, B, C, transA='N', transB='N', alpha=1.0, beta=0.0, \n"
     "     partial=False) \n\n"
-    "PURPOSE\n"   
+    "PURPOSE\n"
     "Computes \n"
     "C := alpha*A*B + beta*C     if transA = 'N' and transB = 'N'.\n"
     "C := alpha*A^T*B + beta*C   if transA = 'T' and transB = 'N'.\n"
@@ -401,7 +401,7 @@ static char doc_gemm[] =
     "C := alpha*A^T*B^H + beta*C if transA = 'T' and transB = 'C'.\n"
     "C := alpha*A^H*B^H + beta*C if transA = 'C' and transB = 'C'.\n"
     "If k=0, this reduces to C := beta*C.\n\n"
-    "ARGUMENTS\n\n" 
+    "ARGUMENTS\n\n"
     "A         'd' or 'z' matrix\n\n"
     "B         'd' or 'z' matrix.  Must have the same type as A.\n\n"
     "C         'd' or 'z' matrix.  Must have the same type as A.\n\n"
@@ -423,10 +423,10 @@ PyObject* base_gemm(PyObject *self, PyObject *args, PyObject *kwrds)
   int m, n, k;
   char transA='N', transB='N';
   char *kwlist[] = {"A", "B", "C", "transA", "transB", "alpha", "beta",
-		    "partial", NULL};
+      "partial", NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOO:gemm", 
-	  kwlist, &A, &B, &C, &transA, &transB, &ao, &bo, &partial))
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOO:gemm",
+      kwlist, &A, &B, &C, &transA, &transB, &ao, &bo, &partial))
     return NULL;
 
   if (!(Matrix_Check(A) || SpMatrix_Check(A)))
@@ -440,7 +440,7 @@ PyObject* base_gemm(PyObject *self, PyObject *args, PyObject *kwrds)
   if (X_ID(A) != X_ID(B) || X_ID(A) != X_ID(C) ||
       X_ID(B) != X_ID(C)) err_conflicting_ids;
 
-  if (transA != 'N' && transA != 'T' && transA != 'C') 
+  if (transA != 'N' && transA != 'T' && transA != 'C')
     err_char("transA", "'N', 'T', 'C'");
   if (transB != 'N' && transB != 'T' && transB != 'C')
     err_char("transB", "'N', 'T', 'C'");
@@ -448,7 +448,7 @@ PyObject* base_gemm(PyObject *self, PyObject *args, PyObject *kwrds)
   m = (transA == 'N') ? X_NROWS(A) : X_NCOLS(A);
   n = (transB == 'N') ? X_NCOLS(B) : X_NROWS(B);
   k = (transA == 'N') ? X_NCOLS(A) : X_NROWS(A);
-  if (k != ((transB == 'N') ? X_NROWS(B) : X_NCOLS(B)))  
+  if (k != ((transB == 'N') ? X_NROWS(B) : X_NCOLS(B)))
     PY_ERR_TYPE("dimensions of A and B do not match");
 
   if (m == 0 || n == 0) return Py_BuildValue("");
@@ -461,27 +461,27 @@ PyObject* base_gemm(PyObject *self, PyObject *args, PyObject *kwrds)
 
     int ldA = MAX(1,MAT_NROWS(A));
     int ldB = MAX(1,MAT_NROWS(B));
-    int ldC = MAX(1,MAT_NROWS(C));  
+    int ldC = MAX(1,MAT_NROWS(C));
     if (id == INT) err_invalid_id;
     gemm[id](&transA, &transB, &m, &n, &k, (ao ? &a : &One[id]),
-	MAT_BUF(A), &ldA, MAT_BUF(B), &ldB, (bo ? &b : &Zero[id]), 
-	MAT_BUF(C), &ldC);
+        MAT_BUF(A), &ldA, MAT_BUF(B), &ldB, (bo ? &b : &Zero[id]),
+        MAT_BUF(C), &ldC);
   } else {
 
     void *z = NULL;
-    if (sp_gemm[id](transA, transB, (ao ? a : One[id]), 
-	    Matrix_Check(A) ? MAT_BUF(A) : ((spmatrix *)A)->obj, 
-	    Matrix_Check(B) ? MAT_BUF(B) : ((spmatrix *)B)->obj,  
-	    (bo ? b : Zero[id]),
-	    Matrix_Check(C) ? MAT_BUF(C) : ((spmatrix *)C)->obj, 
-	    SpMatrix_Check(A), SpMatrix_Check(B), SpMatrix_Check(C), 
-	    partial ? PyInt_AS_LONG(partial) : 0, &z, m, n, k))
-      return PyErr_NoMemory(); 
-
-    if (z) { 
+    if (sp_gemm[id](transA, transB, (ao ? a : One[id]),
+        Matrix_Check(A) ? MAT_BUF(A) : ((spmatrix *)A)->obj,
+            Matrix_Check(B) ? MAT_BUF(B) : ((spmatrix *)B)->obj,
+                (bo ? b : Zero[id]),
+                Matrix_Check(C) ? MAT_BUF(C) : ((spmatrix *)C)->obj,
+                    SpMatrix_Check(A), SpMatrix_Check(B), SpMatrix_Check(C),
+                    partial ? PyInt_AS_LONG(partial) : 0, &z, m, n, k))
+      return PyErr_NoMemory();
+
+    if (z) {
       free_ccs( ((spmatrix *)C)->obj );
       ((spmatrix *)C)->obj = z;
-    }    
+    }
   }
 
   return Py_BuildValue("");
@@ -526,34 +526,34 @@ static PyObject* base_gemv(PyObject *self, PyObject *args, PyObject *kwrds)
   PyObject *A;
   PyObject *ao=NULL, *bo=NULL;
   number a, b;
-  int m=-1, n=-1, ix=1, iy=1, oA=0, ox=0, oy=0; 
-  char trans='N'; 
-  char *kwlist[] = {"A", "x", "y", "trans", "alpha", "beta", "m", "n", 
-		    "incx", "incy", "offsetA", "offsetx",
-		    "offsety", NULL};
-
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiii:gemv", 
-	  kwlist, &A, &x, &y, &trans, &ao, &bo, &m, &n, &ix, &iy, 
-	  &oA, &ox, &oy))
+  int m=-1, n=-1, ix=1, iy=1, oA=0, ox=0, oy=0;
+  char trans='N';
+  char *kwlist[] = {"A", "x", "y", "trans", "alpha", "beta", "m", "n",
+      "incx", "incy", "offsetA", "offsetx",
+      "offsety", NULL};
+
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiii:gemv",
+      kwlist, &A, &x, &y, &trans, &ao, &bo, &m, &n, &ix, &iy,
+      &oA, &ox, &oy))
     return NULL;
-  
+
   if (!Matrix_Check(A) && !SpMatrix_Check(A))
     PY_ERR(PyExc_TypeError, "A must be a dense or sparse matrix");
   if (!Matrix_Check(x)) err_mtrx("x");
   if (!Matrix_Check(y)) err_mtrx("y");
 
-  if (MAT_ID(x) == INT || MAT_ID(y) == INT || X_ID(A) == INT) 
+  if (MAT_ID(x) == INT || MAT_ID(y) == INT || X_ID(A) == INT)
     PY_ERR_TYPE("invalid matrix types");
 
   if (X_ID(A) != MAT_ID(x) || X_ID(A) != MAT_ID(y))
     err_conflicting_ids;
-  
-  if (trans != 'N' && trans != 'T' && trans != 'C') 
+
+  if (trans != 'N' && trans != 'T' && trans != 'C')
     err_char("trans", "'N','T','C'");
 
   if (ix == 0) err_nz_int("incx");
   if (iy == 0) err_nz_int("incy");
-  
+
   int id = MAT_ID(x);
   if (m < 0) m = X_NROWS(A);
   if (n < 0) n = X_NCOLS(A);
@@ -561,41 +561,41 @@ static PyObject* base_gemv(PyObject *self, PyObject *args, PyObject *kwrds)
     return Py_BuildValue("");
 
   if (oA < 0) err_nn_int("offsetA");
-  if (n > 0 && m > 0 && oA + (n-1)*MAX(1,X_NROWS(A)) + m > 
-      X_NROWS(A)*X_NCOLS(A))
+  if (n > 0 && m > 0 && oA + (n-1)*MAX(1,X_NROWS(A)) + m >
+  X_NROWS(A)*X_NCOLS(A))
     err_buf_len("A");
-  
+
   if (ox < 0) err_nn_int("offsetx");
-  if ((trans == 'N' && n > 0 && ox + (n-1)*abs(ix) + 1 > MAT_LGT(x)) || 
-      ((trans == 'T' || trans == 'C') && m > 0 && 
-	  ox + (m-1)*abs(ix) + 1 > MAT_LGT(x))) err_buf_len("x");
-  
+  if ((trans == 'N' && n > 0 && ox + (n-1)*abs(ix) + 1 > MAT_LGT(x)) ||
+      ((trans == 'T' || trans == 'C') && m > 0 &&
+          ox + (m-1)*abs(ix) + 1 > MAT_LGT(x))) err_buf_len("x");
+
   if (oy < 0) err_nn_int("offsety");
-  if ((trans == 'N' && oy + (m-1)*abs(iy) + 1 > MAT_LGT(y)) || 
-      ((trans == 'T' || trans == 'C') && 
-	  oy + (n-1)*abs(iy) + 1 > MAT_LGT(y))) err_buf_len("y");
+  if ((trans == 'N' && oy + (m-1)*abs(iy) + 1 > MAT_LGT(y)) ||
+      ((trans == 'T' || trans == 'C') &&
+          oy + (n-1)*abs(iy) + 1 > MAT_LGT(y))) err_buf_len("y");
 
   if (ao && convert_num[MAT_ID(x)](&a, ao, 1, 0)) err_type("alpha");
   if (bo && convert_num[MAT_ID(x)](&b, bo, 1, 0)) err_type("beta");
-  
+
   if (Matrix_Check(A)) {
     int ldA = MAX(1,X_NROWS(A));
     if (trans == 'N' && n == 0)
       scal[id](&m, (bo ? &b : &Zero[id]), MAT_BUF(y)+oy*E_SIZE[id], &iy);
     else if ((trans == 'T' || trans == 'C') && m == 0)
       scal[id](&n, (bo ? &b : &Zero[id]), MAT_BUF(y)+oy*E_SIZE[id], &iy);
-    else 
-      gemv[id](&trans, &m, &n, (ao ? &a : &One[id]), 
-	  MAT_BUF(A) + oA*E_SIZE[id], &ldA, 
-	  MAT_BUF(x) + ox*E_SIZE[id], &ix, (bo ? &b : &Zero[id]), 
-	  MAT_BUF(y) + oy*E_SIZE[id], &iy);
+    else
+      gemv[id](&trans, &m, &n, (ao ? &a : &One[id]),
+          MAT_BUF(A) + oA*E_SIZE[id], &ldA,
+          MAT_BUF(x) + ox*E_SIZE[id], &ix, (bo ? &b : &Zero[id]),
+          MAT_BUF(y) + oy*E_SIZE[id], &iy);
   } else {
-    if (sp_gemv[id](trans, m, n, (ao ? a : One[id]), ((spmatrix *)A)->obj, 
-	    oA, MAT_BUF(x) + ox*E_SIZE[id], ix, (bo ? b : Zero[id]), 
-	    MAT_BUF(y) + oy*E_SIZE[id], iy))
-      return PyErr_NoMemory();      
+    if (sp_gemv[id](trans, m, n, (ao ? a : One[id]), ((spmatrix *)A)->obj,
+        oA, MAT_BUF(x) + ox*E_SIZE[id], ix, (bo ? b : Zero[id]),
+        MAT_BUF(y) + oy*E_SIZE[id], iy))
+      return PyErr_NoMemory();
   }
-  
+
   return Py_BuildValue("");
 }
 
@@ -622,15 +622,15 @@ static char doc_syrk[] =
 static PyObject* base_syrk(PyObject *self, PyObject *args, PyObject *kwrds)
 {
   PyObject *A, *C, *partial=NULL, *ao=NULL, *bo=NULL;
-  number a, b; 
+  number a, b;
   char trans='N', uplo='L';
   char *kwlist[] = {"A", "C", "uplo", "trans", "alpha", "beta", "partial",
-		    NULL};
-  
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccOOO:syrk", kwlist, 
-	  &A, &C, &uplo, &trans, &ao, &bo, &partial))
+      NULL};
+
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccOOO:syrk", kwlist,
+      &A, &C, &uplo, &trans, &ao, &bo, &partial))
     return NULL;
-  
+
   if (!(Matrix_Check(A) || SpMatrix_Check(A)))
     PY_ERR_TYPE("A must be a dense or sparse matrix");
   if (!(Matrix_Check(C) || SpMatrix_Check(C)))
@@ -639,19 +639,19 @@ static PyObject* base_syrk(PyObject *self, PyObject *args, PyObject *kwrds)
   int id = X_ID(A);
   if (id == INT) PY_ERR_TYPE("invalid matrix types");
   if (id != X_ID(C)) err_conflicting_ids;
-  
+
   if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
   if (id == DOUBLE && trans != 'N' && trans != 'T' &&
       trans != 'C') err_char("trans", "'N', 'T', 'C'");
-  if (id == COMPLEX && trans != 'N' && trans != 'T') 
+  if (id == COMPLEX && trans != 'N' && trans != 'T')
     err_char("trans", "'N', 'T'");
 
   if (partial && !PyBool_Check(partial)) err_bool("partial");
-  
+
   int n = (trans == 'N') ? X_NROWS(A) : X_NCOLS(A);
   int k = (trans == 'N') ? X_NCOLS(A) : X_NROWS(A);
   if (n == 0) return Py_BuildValue("");
-  
+
   if (ao && convert_num[id](&a, ao, 1, 0)) err_type("alpha");
   if (bo && convert_num[id](&b, bo, 1, 0)) err_type("beta");
 
@@ -660,27 +660,27 @@ static PyObject* base_syrk(PyObject *self, PyObject *args, PyObject *kwrds)
     int ldA = MAX(1,MAT_NROWS(A));
     int ldC = MAX(1,MAT_NROWS(C));
 
-    syrk[id](&uplo, &trans, &n, &k, (ao ? &a : &One[id]), 
-	MAT_BUF(A), &ldA, (bo ? &b : &Zero[id]), MAT_BUF(C), &ldC);
+    syrk[id](&uplo, &trans, &n, &k, (ao ? &a : &One[id]),
+        MAT_BUF(A), &ldA, (bo ? &b : &Zero[id]), MAT_BUF(C), &ldC);
   } else {
 
     void *z = NULL;
-    if (sp_syrk[id](uplo, trans, 
-	    (ao ? a : One[id]), 
-	    Matrix_Check(A) ? MAT_BUF(A) : ((spmatrix *)A)->obj, 
-	    (bo ? b : Zero[id]),
-	    Matrix_Check(C) ? MAT_BUF(C) : ((spmatrix *)C)->obj, 
-	    SpMatrix_Check(A), SpMatrix_Check(C), 
-	    partial ? PyInt_AS_LONG(partial) : 0, 
-	    (trans == 'N' ? X_NCOLS(A) : X_NROWS(A)), &z))
-      return PyErr_NoMemory(); 
-
-    if (z) { 
+    if (sp_syrk[id](uplo, trans,
+        (ao ? a : One[id]),
+        Matrix_Check(A) ? MAT_BUF(A) : ((spmatrix *)A)->obj,
+            (bo ? b : Zero[id]),
+            Matrix_Check(C) ? MAT_BUF(C) : ((spmatrix *)C)->obj,
+                SpMatrix_Check(A), SpMatrix_Check(C),
+                partial ? PyInt_AS_LONG(partial) : 0,
+                    (trans == 'N' ? X_NCOLS(A) : X_NROWS(A)), &z))
+      return PyErr_NoMemory();
+
+    if (z) {
       free_ccs( ((spmatrix *)C)->obj );
       ((spmatrix *)C)->obj = z;
-    }    
+    }
   }
-  
+
   return Py_BuildValue("");
 }
 
@@ -715,16 +715,16 @@ static PyObject* base_symv(PyObject *self, PyObject *args, PyObject *kwrds)
   PyObject *A, *ao=NULL, *bo=NULL;
   matrix *x, *y;
   number a, b;
-  int n=-1, ix=1, iy=1, oA=0, ox=0, oy=0, ldA; 
-  char uplo='L'; 
+  int n=-1, ix=1, iy=1, oA=0, ox=0, oy=0, ldA;
+  char uplo='L';
   char *kwlist[] = {"A", "x", "y", "uplo", "alpha", "beta", "n",
-		    "incx", "incy", "offsetA", "offsetx", "offsety", NULL};
+      "incx", "incy", "offsetA", "offsetx", "offsety", NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiii:symv", 
-	  kwlist, &A, &x, &y, &uplo, &ao, &bo, &n, &ix, &iy, &oA, &ox, &oy))
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiii:symv",
+      kwlist, &A, &x, &y, &uplo, &ao, &bo, &n, &ix, &iy, &oA, &ox, &oy))
     return NULL;
 
-  if (!Matrix_Check(A) && !SpMatrix_Check(A)) 
+  if (!Matrix_Check(A) && !SpMatrix_Check(A))
     PY_ERR_TYPE("A must be a dense or sparse matrix");
 
   ldA = MAX(1,X_NROWS(A));
@@ -736,13 +736,13 @@ static PyObject* base_symv(PyObject *self, PyObject *args, PyObject *kwrds)
 
   int id = X_ID(A);
   if (id == INT) PY_ERR_TYPE("invalid matrix types");
-  
+
   if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
 
   if (ix == 0) err_nz_int("incx");
   if (iy == 0) err_nz_int("incy");
 
-  if (n < 0) { 
+  if (n < 0) {
     if (X_NROWS(A) != X_NCOLS(A)) {
       PyErr_SetString(PyExc_ValueError, "A is not square");
       return NULL;
@@ -757,70 +757,70 @@ static PyObject* base_symv(PyObject *self, PyObject *args, PyObject *kwrds)
   if (ox + (n-1)*abs(ix) + 1 > len(x)) err_buf_len("x");
   if (oy < 0) err_nn_int("offsety");
   if (oy + (n-1)*abs(iy) + 1 > len(y)) err_buf_len("y");
-    
+
   if (ao && convert_num[id](&a, ao, 1, 0)) err_type("alpha");
   if (bo && convert_num[id](&b, bo, 1, 0)) err_type("beta");
 
   if (Matrix_Check(A)) {
-    
-    symv[id](&uplo, &n, (ao ? &a : &One[id]), 
-	MAT_BUF(A) + oA*E_SIZE[id], &ldA, MAT_BUF(x) + ox*E_SIZE[id], 
-	&ix, (bo ? &b : &Zero[id]), MAT_BUF(y) + oy*E_SIZE[id], &iy);    
+
+    symv[id](&uplo, &n, (ao ? &a : &One[id]),
+        MAT_BUF(A) + oA*E_SIZE[id], &ldA, MAT_BUF(x) + ox*E_SIZE[id],
+        &ix, (bo ? &b : &Zero[id]), MAT_BUF(y) + oy*E_SIZE[id], &iy);
   }
   else {
-    
-    if (sp_symv[id](uplo, n, (ao ? a : One[id]), ((spmatrix *)A)->obj, 
-	    oA, MAT_BUF(x) + ox*E_SIZE[id], ix, 
-	    (bo ? b : Zero[id]), MAT_BUF(y) + oy*E_SIZE[id], iy))
-      return PyErr_NoMemory();      
+
+    if (sp_symv[id](uplo, n, (ao ? a : One[id]), ((spmatrix *)A)->obj,
+        oA, MAT_BUF(x) + ox*E_SIZE[id], ix,
+        (bo ? b : Zero[id]), MAT_BUF(y) + oy*E_SIZE[id], iy))
+      return PyErr_NoMemory();
   }
-  
+
   return Py_BuildValue("");
 }
 
 spmatrix * sparse_concat(PyObject *L, int id_arg) ;
 
 static char doc_sparse[] =
-  "Constructs a sparse block matrix.\n\n"
-  "sparse(x, tc = None)\n\n"
-  "PURPOSE\n"
-  "Constructs a sparse block matrix from a list of block matrices.  If a\n"
-  "single matrix is given as argument,  then the matrix is converted to\n"
-  "sparse format, optionally with a different typcode.  If a single list\n"
-  "of subblocks is specified, then a block column matrix is created;\n"
-  "otherwise when a list of lists is specified, then the inner lists\n"
-  "specify the different block-columns.  Each block element must be either\n"
-  "a dense or sparse matrix, or a scalar,  and dense matrices are converted\n"
-  "to sparse format by removing 0 elements.\n\n"
-  "ARGUMENTS\n"
-  "x       a single matrix, or a list of matrices and scalars, or a list of\n"
-  "        lists of matrices and scalars\n\n"
-  "tc      typecode character 'd' or 'z'.";
-  
+    "Constructs a sparse block matrix.\n\n"
+    "sparse(x, tc = None)\n\n"
+    "PURPOSE\n"
+    "Constructs a sparse block matrix from a list of block matrices.  If a\n"
+    "single matrix is given as argument,  then the matrix is converted to\n"
+    "sparse format, optionally with a different typcode.  If a single list\n"
+    "of subblocks is specified, then a block column matrix is created;\n"
+    "otherwise when a list of lists is specified, then the inner lists\n"
+    "specify the different block-columns.  Each block element must be either\n"
+    "a dense or sparse matrix, or a scalar,  and dense matrices are converted\n"
+    "to sparse format by removing 0 elements.\n\n"
+    "ARGUMENTS\n"
+    "x       a single matrix, or a list of matrices and scalars, or a list of\n"
+    "        lists of matrices and scalars\n\n"
+    "tc      typecode character 'd' or 'z'.";
+
 
 static PyObject *
 sparse(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
   PyObject *Objx = NULL;
   static char *kwlist[] = { "x", "tc", NULL};
-   char tc = 0;
+  char tc = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|c:sparse", kwlist, 
-	  &Objx, &tc))
+  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|c:sparse", kwlist,
+      &Objx, &tc))
     return NULL;
 
-  if (tc && !(VALID_TC_SP(tc))) PY_ERR_TYPE("tc must be 'd' or 'z'");  
+  if (tc && !(VALID_TC_SP(tc))) PY_ERR_TYPE("tc must be 'd' or 'z'");
   int id = (tc ? TC2ID(tc) : -1);
 
   spmatrix *ret = NULL;
   /* a matrix */
   if (Matrix_Check(Objx)) {
 
-    int m = MAT_NROWS(Objx), n = MAT_NCOLS(Objx);    
-    ret = SpMatrix_NewFromMatrix((matrix *)Objx, 
-	(id == -1 ? MAX(DOUBLE,MAT_ID(Objx)) : id)); 
+    int m = MAT_NROWS(Objx), n = MAT_NCOLS(Objx);
+    ret = SpMatrix_NewFromMatrix((matrix *)Objx,
+        (id == -1 ? MAX(DOUBLE,MAT_ID(Objx)) : id));
 
-    MAT_NROWS(Objx) = m; MAT_NCOLS(Objx) = n;    
+    MAT_NROWS(Objx) = m; MAT_NCOLS(Objx) = n;
   }
 
   /* sparse matrix */
@@ -830,9 +830,9 @@ sparse(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     for (jk=0; jk<SP_NCOLS(Objx); jk++) {
       for (ik=SP_COL(Objx)[jk]; ik<SP_COL(Objx)[jk+1]; ik++) {
-	if (((SP_ID(Objx) == DOUBLE) && (SP_VALD(Objx)[ik] != 0.0)) ||
-	    ((SP_ID(Objx) == COMPLEX) && (SP_VALZ(Objx)[ik] != 0.0)))
-	  nnz++;	
+        if (((SP_ID(Objx) == DOUBLE) && (SP_VALD(Objx)[ik] != 0.0)) ||
+            ((SP_ID(Objx) == COMPLEX) && (SP_VALZ(Objx)[ik] != 0.0)))
+          nnz++;
       }
     }
 
@@ -842,27 +842,27 @@ sparse(PyTypeObject *type, PyObject *args, PyObject *kwds)
     nnz = 0;
     for (jk=0; jk<SP_NCOLS(Objx); jk++) {
       for (ik=SP_COL(Objx)[jk]; ik<SP_COL(Objx)[jk+1]; ik++) {
-	if ((SP_ID(Objx) == DOUBLE) && (SP_VALD(Objx)[ik] != 0.0)) {
-	  SP_VALD(ret)[nnz] = SP_VALD(Objx)[ik];
-	  SP_ROW(ret)[nnz++] = SP_ROW(Objx)[ik];
-	  SP_COL(ret)[jk+1]++;	
-	}
-	else if ((SP_ID(Objx) == COMPLEX) && (SP_VALZ(Objx)[ik] != 0.0)) {
-	  SP_VALZ(ret)[nnz] = SP_VALZ(Objx)[ik];
-	  SP_ROW(ret)[nnz++] = SP_ROW(Objx)[ik];
-	  SP_COL(ret)[jk+1]++;	
-	}
+        if ((SP_ID(Objx) == DOUBLE) && (SP_VALD(Objx)[ik] != 0.0)) {
+          SP_VALD(ret)[nnz] = SP_VALD(Objx)[ik];
+          SP_ROW(ret)[nnz++] = SP_ROW(Objx)[ik];
+          SP_COL(ret)[jk+1]++;
+        }
+        else if ((SP_ID(Objx) == COMPLEX) && (SP_VALZ(Objx)[ik] != 0.0)) {
+          SP_VALZ(ret)[nnz] = SP_VALZ(Objx)[ik];
+          SP_ROW(ret)[nnz++] = SP_ROW(Objx)[ik];
+          SP_COL(ret)[jk+1]++;
+        }
       }
     }
-    
-    for (jk=0; jk<SP_NCOLS(Objx); jk++) 
-      SP_COL(ret)[jk+1] += SP_COL(ret)[jk];    
+
+    for (jk=0; jk<SP_NCOLS(Objx); jk++)
+      SP_COL(ret)[jk+1] += SP_COL(ret)[jk];
   }
 
   /* x is a list of lists */
-  else if (PyList_Check(Objx)) 
+  else if (PyList_Check(Objx))
     ret = sparse_concat(Objx, id);
-  
+
   else PY_ERR_TYPE("invalid matrix initialization");
 
   return (PyObject *)ret;
@@ -880,37 +880,37 @@ spdiag(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
   PyObject *diag = NULL, *Dk;
   static char *kwlist[] = { "diag", NULL};
-  
+
   if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:spdiag", kwlist, &diag))
     return NULL;
-  
+
   if ((!PyList_Check(diag) && !Matrix_Check(diag) && !SpMatrix_Check(diag)) ||
-      (Matrix_Check(diag) && 
-	  (MAT_LGT(diag) != MAX(MAT_NROWS(diag),MAT_NCOLS(diag)) )) || 
-      (SpMatrix_Check(diag) && 
-	  (SP_LGT(diag) != MAX(SP_NROWS(diag),SP_NCOLS(diag)) )) )
+      (Matrix_Check(diag) &&
+          (MAT_LGT(diag) != MAX(MAT_NROWS(diag),MAT_NCOLS(diag)) )) ||
+          (SpMatrix_Check(diag) &&
+              (SP_LGT(diag) != MAX(SP_NROWS(diag),SP_NCOLS(diag)) )) )
     PY_ERR_TYPE("invalid diag argument");
-  
+
   if (Matrix_Check(diag)) {
     int j, id = MAX(DOUBLE, MAT_ID(diag)), n = MAT_LGT(diag);
 
     spmatrix *ret = SpMatrix_New(n, n, n, id);
     if (!ret) return PyErr_NoMemory();
     SP_COL(ret)[0] = 0;
-    
+
     for (j=0; j<n; j++) {
       SP_COL(ret)[j+1] = j+1;
       SP_ROW(ret)[j] = j;
 
-      if (MAT_ID(diag) == INT)	
-	SP_VALD(ret)[j] = MAT_BUFI(diag)[j];
+      if (MAT_ID(diag) == INT)
+        SP_VALD(ret)[j] = MAT_BUFI(diag)[j];
       else if (MAT_ID(diag) == DOUBLE)
-	SP_VALD(ret)[j] = MAT_BUFD(diag)[j];
+        SP_VALD(ret)[j] = MAT_BUFD(diag)[j];
       else
-	SP_VALZ(ret)[j] = MAT_BUFZ(diag)[j];
+        SP_VALZ(ret)[j] = MAT_BUFZ(diag)[j];
     }
     return (PyObject *)ret;
-  } 
+  }
   else if (SpMatrix_Check(diag)) {
 
     int k, id = MAX(DOUBLE, SP_ID(diag)), n = SP_LGT(diag);
@@ -918,19 +918,19 @@ spdiag(PyTypeObject *type, PyObject *args, PyObject *kwds)
     spmatrix *ret = SpMatrix_New(n, n, SP_NNZ(diag), id);
     if (!ret) return PyErr_NoMemory();
     SP_COL(ret)[0] = 0;
-    
+
     for (k=0; k<SP_NNZ(diag); k++) {
-      
+
       SP_COL(ret)[SP_ROW(diag)[k]+1] = 1;
       SP_ROW(ret)[k] = SP_ROW(diag)[k];
       if (SP_ID(diag) == DOUBLE)
-	SP_VALD(ret)[k] = SP_VALD(diag)[k];
+        SP_VALD(ret)[k] = SP_VALD(diag)[k];
       else
-	SP_VALZ(ret)[k] = SP_VALZ(diag)[k];	
+        SP_VALZ(ret)[k] = SP_VALZ(diag)[k];
     }
 
     for (k=0; k<n; k++) SP_COL(ret)[k+1] += SP_COL(ret)[k];
-      
+
     return (PyObject *)ret;
 
   }
@@ -941,16 +941,16 @@ spdiag(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Dk = PyList_GET_ITEM(diag, k);
     if (!Matrix_Check(Dk) && !SpMatrix_Check(Dk) && !PyNumber_Check(Dk))
       PY_ERR_TYPE("invalid element in diag");
-    
+
     if (PyNumber_Check(Dk)) {
       int scalarid = (PyComplex_Check(Dk) ? COMPLEX :
-	  (PyFloat_Check(Dk) ? DOUBLE : INT));
+      (PyFloat_Check(Dk) ? DOUBLE : INT));
       id = MAX(id, scalarid);
       nnz += 1;
       n += 1;
     } else {
       if (X_NROWS(Dk) != X_NCOLS(Dk))
-	PY_ERR_TYPE("the elements in diag must be square");
+        PY_ERR_TYPE("the elements in diag must be square");
 
       n   += X_NCOLS(Dk);
       nnz += (Matrix_Check(Dk) ? X_NROWS(Dk)*X_NROWS(Dk) : SP_NNZ(Dk));
@@ -965,7 +965,7 @@ spdiag(PyTypeObject *type, PyObject *args, PyObject *kwds)
   n = 0, idx = 0;
   for (k=0; k<PyList_GET_SIZE(diag); k++) {
     Dk = PyList_GET_ITEM(diag, k);
-  
+
     if (PyNumber_Check(Dk)) {
       SP_COL(ret)[n+1] = SP_COL(ret)[n] + 1;
       SP_ROW(ret)[idx] = n;
@@ -979,38 +979,38 @@ spdiag(PyTypeObject *type, PyObject *args, PyObject *kwds)
     else {
       for (j=0; j<X_NCOLS(Dk); j++) {
 
-	if (Matrix_Check(Dk)) {
-	  
-	  SP_COL(ret)[j+n+1] = SP_COL(ret)[j+n] + X_NROWS(Dk);
-	  for (l=0; l<X_NROWS(Dk); l++) {
-	    SP_ROW(ret)[idx] = n + l;
-	    if (id == DOUBLE) 
-	      SP_VALD(ret)[idx] = (MAT_ID(Dk) == DOUBLE ? 
-		  MAT_BUFD(Dk)[l + j*MAT_NROWS(Dk)] :
-		  MAT_BUFI(Dk)[l + j*MAT_NROWS(Dk)]);
-	    else
-	      SP_VALZ(ret)[idx] = (MAT_ID(Dk) == COMPLEX ?
-		  MAT_BUFZ(Dk)[l + j*MAT_NROWS(Dk)] :
-		  (MAT_ID(Dk) == DOUBLE ? MAT_BUFD(Dk)[l + j*MAT_NROWS(Dk)] :
-		      MAT_BUFI(Dk)[l + j*MAT_NROWS(Dk)]));
-	    
-	    idx++;
-	  }      
-	} else {
-	  
-	  SP_COL(ret)[j+n+1] = SP_COL(ret)[j+n] + SP_COL(Dk)[j+1]-SP_COL(Dk)[j];
-	  for (l=SP_COL(Dk)[j]; l<SP_COL(Dk)[j+1]; l++) {
-	    SP_ROW(ret)[idx] = n + SP_ROW(Dk)[l];
-	    if (id == DOUBLE) 
-	      SP_VALD(ret)[idx] = SP_VALD(Dk)[l];
-	    else
-	      SP_VALZ(ret)[idx] = (SP_ID(Dk) == COMPLEX ?
-		  SP_VALZ(Dk)[l] : SP_VALD(Dk)[l]);	  
-	    idx++;
-	  }
-	}
+        if (Matrix_Check(Dk)) {
+
+          SP_COL(ret)[j+n+1] = SP_COL(ret)[j+n] + X_NROWS(Dk);
+          for (l=0; l<X_NROWS(Dk); l++) {
+            SP_ROW(ret)[idx] = n + l;
+            if (id == DOUBLE)
+              SP_VALD(ret)[idx] = (MAT_ID(Dk) == DOUBLE ?
+                  MAT_BUFD(Dk)[l + j*MAT_NROWS(Dk)] :
+              MAT_BUFI(Dk)[l + j*MAT_NROWS(Dk)]);
+            else
+              SP_VALZ(ret)[idx] = (MAT_ID(Dk) == COMPLEX ?
+                  MAT_BUFZ(Dk)[l + j*MAT_NROWS(Dk)] :
+              (MAT_ID(Dk) == DOUBLE ? MAT_BUFD(Dk)[l + j*MAT_NROWS(Dk)] :
+              MAT_BUFI(Dk)[l + j*MAT_NROWS(Dk)]));
+
+            idx++;
+          }
+        } else {
+
+          SP_COL(ret)[j+n+1] = SP_COL(ret)[j+n] + SP_COL(Dk)[j+1]-SP_COL(Dk)[j];
+          for (l=SP_COL(Dk)[j]; l<SP_COL(Dk)[j+1]; l++) {
+            SP_ROW(ret)[idx] = n + SP_ROW(Dk)[l];
+            if (id == DOUBLE)
+              SP_VALD(ret)[idx] = SP_VALD(Dk)[l];
+            else
+              SP_VALZ(ret)[idx] = (SP_ID(Dk) == COMPLEX ?
+                  SP_VALZ(Dk)[l] : SP_VALD(Dk)[l]);
+            idx++;
+          }
+        }
       }
-      n += X_NCOLS(Dk);    
+      n += X_NCOLS(Dk);
     }
   }
   return (PyObject *)ret;
@@ -1024,22 +1024,22 @@ PyObject * matrix_elem_max(PyObject *self, PyObject *args, PyObject *kwrds)
   if (!PyArg_ParseTuple(args, "OO:emax", &A, &B)) return NULL;
 
   if (!(X_Matrix_Check(A) || PyNumber_Check(A)) ||
-      !(X_Matrix_Check(B) || PyNumber_Check(B))) 
+      !(X_Matrix_Check(B) || PyNumber_Check(B)))
     PY_ERR_TYPE("arguments must be either matrices or python numbers");
-  
+
   if (PyComplex_Check(A) || (X_Matrix_Check(A) && X_ID(A)==COMPLEX))
     PY_ERR_TYPE("ordering not defined for complex numbers");
 
-  if (PyComplex_Check(B) || (X_Matrix_Check(B) && X_ID(B)==COMPLEX)) 
+  if (PyComplex_Check(B) || (X_Matrix_Check(B) && X_ID(B)==COMPLEX))
     PY_ERR_TYPE("ordering not defined for complex numbers");
- 
-  int a_is_number = PyNumber_Check(A) || 
-    (Matrix_Check(A) && MAT_LGT(A) == 1) || 
-    (SpMatrix_Check(A) && SP_LGT(A) == 1);
-  int b_is_number = PyNumber_Check(B) || 
-    (Matrix_Check(B) && MAT_LGT(B) == 1) ||
-    (SpMatrix_Check(B) && SP_LGT(B) == 1);
-  
+
+  int a_is_number = PyNumber_Check(A) ||
+      (Matrix_Check(A) && MAT_LGT(A) == 1) ||
+      (SpMatrix_Check(A) && SP_LGT(A) == 1);
+  int b_is_number = PyNumber_Check(B) ||
+      (Matrix_Check(B) && MAT_LGT(B) == 1) ||
+      (SpMatrix_Check(B) && SP_LGT(B) == 1);
+
   int ida = PyNumber_Check(A) ? PyFloat_Check(A) : X_ID(A);
   int idb = PyNumber_Check(B) ? PyFloat_Check(B) : X_ID(B);
   int id  = MAX( ida, idb );
@@ -1048,19 +1048,19 @@ PyObject * matrix_elem_max(PyObject *self, PyObject *args, PyObject *kwrds)
   if (a_is_number) {
     if (PyNumber_Check(A) || Matrix_Check(A))
       convert_num[id](&a, A, PyNumber_Check(A), 0);
-    else 
+    else
       a.d = (SP_LGT(A) ? SP_VALD(A)[0] : 0.0);
   }
   if (b_is_number) {
     if (PyNumber_Check(B) || Matrix_Check(B))
       convert_num[id](&b, B, PyNumber_Check(B), 0);
-    else 
+    else
       b.d = (SP_LGT(B) ? SP_VALD(B)[0] : 0.0);
   }
-  
+
   if ((a_is_number && b_is_number) &&
       (!X_Matrix_Check(A) && !X_Matrix_Check(B))) {
-    if (id == INT) 
+    if (id == INT)
       return Py_BuildValue("i", MAX(a.i, b.i) );
     else
       return Py_BuildValue("d", MAX(a.d, b.d) );
@@ -1071,17 +1071,17 @@ PyObject * matrix_elem_max(PyObject *self, PyObject *args, PyObject *kwrds)
       PY_ERR_TYPE("incompatible dimensions");
   }
 
-  int m = ( !a_is_number ? X_NROWS(A) : (!b_is_number ? X_NROWS(B) : 1));
-  int n = ( !a_is_number ? X_NCOLS(A) : (!b_is_number ? X_NCOLS(B) : 1));
-  
+  int_t m = ( !a_is_number ? X_NROWS(A) : (!b_is_number ? X_NROWS(B) : 1));
+  int_t n = ( !a_is_number ? X_NCOLS(A) : (!b_is_number ? X_NCOLS(B) : 1));
+
   if ((Matrix_Check(A) || a_is_number) || (Matrix_Check(B) || b_is_number)) {
 
     int freeA = SpMatrix_Check(A) && (SP_LGT(A) > 1);
     int freeB = SpMatrix_Check(B) && (SP_LGT(B) > 1);
-    if (freeA) { 
+    if (freeA) {
       if (!(A = (PyObject *)dense((spmatrix *)A)) ) return PyErr_NoMemory();
     }
-    if (freeB) { 
+    if (freeB) {
       if (!(B = (PyObject *)dense((spmatrix *)B)) ) return PyErr_NoMemory();
     }
 
@@ -1091,50 +1091,50 @@ PyObject * matrix_elem_max(PyObject *self, PyObject *args, PyObject *kwrds)
       if (freeB) { Py_DECREF(B); }
       return PyErr_NoMemory();
     }
-    int i;
+    int_t i;
     for (i=0; i<m*n; i++) {
       if (!a_is_number) convert_num[id](&a, A, 0, i);
       if (!b_is_number) convert_num[id](&b, B, 0, i);
-      
+
       if (id == INT)
-	MAT_BUFI(ret)[i] = MAX(a.i, b.i);
+        MAT_BUFI(ret)[i] = MAX(a.i, b.i);
       else
-	MAT_BUFD(ret)[i] = MAX(a.d, b.d);
+        MAT_BUFD(ret)[i] = MAX(a.d, b.d);
     }
 
     if (freeA) { Py_DECREF(A); }
-    if (freeB) { Py_DECREF(B); }    
+    if (freeB) { Py_DECREF(B); }
     return ret;
 
   } else {
-    
+
     spmatrix *ret = SpMatrix_New(m, n, 0, DOUBLE);
     if (!ret) return PyErr_NoMemory();
 
-    int j, ka = 0, kb = 0, kret = 0;
+    int_t j, ka = 0, kb = 0, kret = 0;
     for (j=0; j<n; j++) {
-      
+
       while (ka < SP_COL(A)[j+1] && kb < SP_COL(B)[j+1]) {
-	
-	if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
-	  if (SP_VALD(A)[ka++] > 0.0) SP_COL(ret)[j+1]++;
-	}
-	else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
-	  if (SP_VALD(B)[kb++] > 0.0) SP_COL(ret)[j+1]++;
-	}
-	else {
-	  SP_COL(ret)[j+1]++; ka++; kb++;
-	}
+
+        if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
+          if (SP_VALD(A)[ka++] > 0.0) SP_COL(ret)[j+1]++;
+        }
+        else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
+          if (SP_VALD(B)[kb++] > 0.0) SP_COL(ret)[j+1]++;
+        }
+        else {
+          SP_COL(ret)[j+1]++; ka++; kb++;
+        }
       }
 
       while (ka < SP_COL(A)[j+1]) {
-	if (SP_VALD(A)[ka++] > 0.0) SP_COL(ret)[j+1]++;       
+        if (SP_VALD(A)[ka++] > 0.0) SP_COL(ret)[j+1]++;
       }
 
       while (kb < SP_COL(B)[j+1]) {
-	if (SP_VALD(B)[kb++] > 0.0) SP_COL(ret)[j+1]++;       
+        if (SP_VALD(B)[kb++] > 0.0) SP_COL(ret)[j+1]++;
       }
-	
+
     }
 
     for (j=0; j<n; j++) SP_COL(ret)[j+1] += SP_COL(ret)[j];
@@ -1152,45 +1152,45 @@ PyObject * matrix_elem_max(PyObject *self, PyObject *args, PyObject *kwrds)
 
     ka = 0; kb = 0;
     for (j=0; j<n; j++) {
-      
+
       while (ka < SP_COL(A)[j+1] && kb < SP_COL(B)[j+1]) {
-	
-	if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
-	  if (SP_VALD(A)[ka] > 0.0) { 
-	    SP_ROW(ret)[kret] = SP_ROW(A)[ka];
-	    SP_VALD(ret)[kret++] = SP_VALD(A)[ka];
-	  }
-	  ka++;
-	}
-	else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
-	  if (SP_VALD(B)[kb] > 0.0) {
-	    SP_ROW(ret)[kret] = SP_ROW(B)[kb];
-	    SP_VALD(ret)[kret++] = SP_VALD(B)[kb];
-	  }
-	  kb++;
-	}
-	else {
-	  SP_ROW(ret)[kret] = SP_ROW(A)[ka];
-	  SP_VALD(ret)[kret] = MAX(SP_VALD(A)[ka], SP_VALD(B)[kb]);
-	  kret++; ka++; kb++;
-	}
+
+        if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
+          if (SP_VALD(A)[ka] > 0.0) {
+            SP_ROW(ret)[kret] = SP_ROW(A)[ka];
+            SP_VALD(ret)[kret++] = SP_VALD(A)[ka];
+          }
+          ka++;
+        }
+        else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
+          if (SP_VALD(B)[kb] > 0.0) {
+            SP_ROW(ret)[kret] = SP_ROW(B)[kb];
+            SP_VALD(ret)[kret++] = SP_VALD(B)[kb];
+          }
+          kb++;
+        }
+        else {
+          SP_ROW(ret)[kret] = SP_ROW(A)[ka];
+          SP_VALD(ret)[kret] = MAX(SP_VALD(A)[ka], SP_VALD(B)[kb]);
+          kret++; ka++; kb++;
+        }
       }
 
       while (ka < SP_COL(A)[j+1]) {
-	if (SP_VALD(A)[ka] > 0.0) {
-	    SP_ROW(ret)[kret] = SP_ROW(A)[ka];
-	    SP_VALD(ret)[kret++] = SP_VALD(A)[ka];
-	}
-	ka++;
+        if (SP_VALD(A)[ka] > 0.0) {
+          SP_ROW(ret)[kret] = SP_ROW(A)[ka];
+          SP_VALD(ret)[kret++] = SP_VALD(A)[ka];
+        }
+        ka++;
       }
 
       while (kb < SP_COL(B)[j+1]) {
-	if (SP_VALD(B)[kb] > 0.0) {
-	  SP_ROW(ret)[kret] = SP_ROW(B)[kb];
-	  SP_VALD(ret)[kret++] = SP_VALD(B)[kb];
-	}
-	kb++;
-      }	
+        if (SP_VALD(B)[kb] > 0.0) {
+          SP_ROW(ret)[kret] = SP_ROW(B)[kb];
+          SP_VALD(ret)[kret++] = SP_VALD(B)[kb];
+        }
+        kb++;
+      }
     }
 
     return (PyObject *)ret;
@@ -1203,22 +1203,22 @@ PyObject * matrix_elem_min(PyObject *self, PyObject *args, PyObject *kwrds)
   if (!PyArg_ParseTuple(args, "OO:emin", &A, &B)) return NULL;
 
   if (!(X_Matrix_Check(A) || PyNumber_Check(A)) ||
-      !(X_Matrix_Check(B) || PyNumber_Check(B))) 
+      !(X_Matrix_Check(B) || PyNumber_Check(B)))
     PY_ERR_TYPE("arguments must be either matrices or python numbers");
-  
+
   if (PyComplex_Check(A) || (X_Matrix_Check(A) && X_ID(A)==COMPLEX))
     PY_ERR_TYPE("ordering not defined for complex numbers");
 
-  if (PyComplex_Check(B) || (X_Matrix_Check(B) && X_ID(B)==COMPLEX)) 
+  if (PyComplex_Check(B) || (X_Matrix_Check(B) && X_ID(B)==COMPLEX))
     PY_ERR_TYPE("ordering not defined for complex numbers");
- 
-  int a_is_number = PyNumber_Check(A) || 
-    (Matrix_Check(A) && MAT_LGT(A) == 1) || 
-    (SpMatrix_Check(A) && SP_LGT(A) == 1);
-  int b_is_number = PyNumber_Check(B) || 
-    (Matrix_Check(B) && MAT_LGT(B) == 1) ||
-    (SpMatrix_Check(B) && SP_LGT(B) == 1);
-  
+
+  int a_is_number = PyNumber_Check(A) ||
+      (Matrix_Check(A) && MAT_LGT(A) == 1) ||
+      (SpMatrix_Check(A) && SP_LGT(A) == 1);
+  int b_is_number = PyNumber_Check(B) ||
+      (Matrix_Check(B) && MAT_LGT(B) == 1) ||
+      (SpMatrix_Check(B) && SP_LGT(B) == 1);
+
   int ida = PyNumber_Check(A) ? PyFloat_Check(A) : X_ID(A);
   int idb = PyNumber_Check(B) ? PyFloat_Check(B) : X_ID(B);
   int id  = MAX( ida, idb );
@@ -1227,19 +1227,19 @@ PyObject * matrix_elem_min(PyObject *self, PyObject *args, PyObject *kwrds)
   if (a_is_number) {
     if (PyNumber_Check(A) || Matrix_Check(A))
       convert_num[id](&a, A, PyNumber_Check(A), 0);
-    else 
+    else
       a.d = (SP_LGT(A) ? SP_VALD(A)[0] : 0.0);
   }
   if (b_is_number) {
     if (PyNumber_Check(B) || Matrix_Check(B))
       convert_num[id](&b, B, PyNumber_Check(B), 0);
-    else 
+    else
       b.d = (SP_LGT(B) ? SP_VALD(B)[0] : 0.0);
   }
 
   if ((a_is_number && b_is_number) &&
       (!X_Matrix_Check(A) && !X_Matrix_Check(B))) {
-    if (id == INT) 
+    if (id == INT)
       return Py_BuildValue("i", MIN(a.i, b.i) );
     else
       return Py_BuildValue("d", MIN(a.d, b.d) );
@@ -1250,17 +1250,17 @@ PyObject * matrix_elem_min(PyObject *self, PyObject *args, PyObject *kwrds)
       PY_ERR_TYPE("incompatible dimensions");
   }
 
-  int m = ( !a_is_number ? X_NROWS(A) : (!b_is_number ? X_NROWS(B) : 1));
-  int n = ( !a_is_number ? X_NCOLS(A) : (!b_is_number ? X_NCOLS(B) : 1));
-  
+  int_t m = ( !a_is_number ? X_NROWS(A) : (!b_is_number ? X_NROWS(B) : 1));
+  int_t n = ( !a_is_number ? X_NCOLS(A) : (!b_is_number ? X_NCOLS(B) : 1));
+
   if ((Matrix_Check(A) || a_is_number) || (Matrix_Check(B) || b_is_number)) {
 
     int freeA = SpMatrix_Check(A) && (SP_LGT(A) > 1);
     int freeB = SpMatrix_Check(B) && (SP_LGT(B) > 1);
-    if (freeA) { 
+    if (freeA) {
       if (!(A = (PyObject *)dense((spmatrix *)A)) ) return PyErr_NoMemory();
     }
-    if (freeB) { 
+    if (freeB) {
       if (!(B = (PyObject *)dense((spmatrix *)B)) ) return PyErr_NoMemory();
     }
 
@@ -1270,50 +1270,50 @@ PyObject * matrix_elem_min(PyObject *self, PyObject *args, PyObject *kwrds)
       if (freeB) { Py_DECREF(B); }
       return PyErr_NoMemory();
     }
-    int i;
+    int_t i;
     for (i=0; i<m*n; i++) {
       if (!a_is_number) convert_num[id](&a, A, 0, i);
       if (!b_is_number) convert_num[id](&b, B, 0, i);
-      
+
       if (id == INT)
-	MAT_BUFI(ret)[i] = MIN(a.i, b.i);
+        MAT_BUFI(ret)[i] = MIN(a.i, b.i);
       else
-	MAT_BUFD(ret)[i] = MIN(a.d, b.d);
+        MAT_BUFD(ret)[i] = MIN(a.d, b.d);
     }
 
     if (freeA) { Py_DECREF(A); }
-    if (freeB) { Py_DECREF(B); }    
+    if (freeB) { Py_DECREF(B); }
     return ret;
 
   } else {
-    
+
     spmatrix *ret = SpMatrix_New(m, n, 0, DOUBLE);
     if (!ret) return PyErr_NoMemory();
 
-    int j, ka = 0, kb = 0, kret = 0;
+    int_t j, ka = 0, kb = 0, kret = 0;
     for (j=0; j<n; j++) {
-      
+
       while (ka < SP_COL(A)[j+1] && kb < SP_COL(B)[j+1]) {
-	
-	if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
-	  if (SP_VALD(A)[ka++] < 0.0) SP_COL(ret)[j+1]++;
-	}
-	else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
-	  if (SP_VALD(B)[kb++] < 0.0) SP_COL(ret)[j+1]++;
-	}
-	else {
-	  SP_COL(ret)[j+1]++; ka++; kb++;
-	}
+
+        if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
+          if (SP_VALD(A)[ka++] < 0.0) SP_COL(ret)[j+1]++;
+        }
+        else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
+          if (SP_VALD(B)[kb++] < 0.0) SP_COL(ret)[j+1]++;
+        }
+        else {
+          SP_COL(ret)[j+1]++; ka++; kb++;
+        }
       }
 
       while (ka < SP_COL(A)[j+1]) {
-	if (SP_VALD(A)[ka++] < 0.0) SP_COL(ret)[j+1]++;       
+        if (SP_VALD(A)[ka++] < 0.0) SP_COL(ret)[j+1]++;
       }
 
       while (kb < SP_COL(B)[j+1]) {
-	if (SP_VALD(B)[kb++] < 0.0) SP_COL(ret)[j+1]++;       
+        if (SP_VALD(B)[kb++] < 0.0) SP_COL(ret)[j+1]++;
       }
-	
+
     }
 
     for (j=0; j<n; j++) SP_COL(ret)[j+1] += SP_COL(ret)[j];
@@ -1331,45 +1331,45 @@ PyObject * matrix_elem_min(PyObject *self, PyObject *args, PyObject *kwrds)
 
     ka = 0; kb = 0;
     for (j=0; j<n; j++) {
-      
+
       while (ka < SP_COL(A)[j+1] && kb < SP_COL(B)[j+1]) {
-	
-	if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
-	  if (SP_VALD(A)[ka] < 0.0) { 
-	    SP_ROW(ret)[kret] = SP_ROW(A)[ka];
-	    SP_VALD(ret)[kret++] = SP_VALD(A)[ka];
-	  }
-	  ka++;
-	}
-	else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
-	  if (SP_VALD(B)[kb] < 0.0) {
-	    SP_ROW(ret)[kret] = SP_ROW(B)[kb];
-	    SP_VALD(ret)[kret++] = SP_VALD(B)[kb];
-	  }
-	  kb++;
-	}
-	else {
-	  SP_ROW(ret)[kret] = SP_ROW(A)[ka];
-	  SP_VALD(ret)[kret] = MIN(SP_VALD(A)[ka], SP_VALD(B)[kb]);
-	  kret++; ka++; kb++;
-	}
+
+        if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
+          if (SP_VALD(A)[ka] < 0.0) {
+            SP_ROW(ret)[kret] = SP_ROW(A)[ka];
+            SP_VALD(ret)[kret++] = SP_VALD(A)[ka];
+          }
+          ka++;
+        }
+        else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
+          if (SP_VALD(B)[kb] < 0.0) {
+            SP_ROW(ret)[kret] = SP_ROW(B)[kb];
+            SP_VALD(ret)[kret++] = SP_VALD(B)[kb];
+          }
+          kb++;
+        }
+        else {
+          SP_ROW(ret)[kret] = SP_ROW(A)[ka];
+          SP_VALD(ret)[kret] = MIN(SP_VALD(A)[ka], SP_VALD(B)[kb]);
+          kret++; ka++; kb++;
+        }
       }
 
       while (ka < SP_COL(A)[j+1]) {
-	if (SP_VALD(A)[ka] < 0.0) {
-	    SP_ROW(ret)[kret] = SP_ROW(A)[ka];
-	    SP_VALD(ret)[kret++] = SP_VALD(A)[ka];
-	}
-	ka++;
+        if (SP_VALD(A)[ka] < 0.0) {
+          SP_ROW(ret)[kret] = SP_ROW(A)[ka];
+          SP_VALD(ret)[kret++] = SP_VALD(A)[ka];
+        }
+        ka++;
       }
 
       while (kb < SP_COL(B)[j+1]) {
-	if (SP_VALD(B)[kb] < 0.0) {
-	  SP_ROW(ret)[kret] = SP_ROW(B)[kb];
-	  SP_VALD(ret)[kret++] = SP_VALD(B)[kb];
-	}
-	kb++;
-      }	
+        if (SP_VALD(B)[kb] < 0.0) {
+          SP_ROW(ret)[kret] = SP_ROW(B)[kb];
+          SP_VALD(ret)[kret++] = SP_VALD(B)[kb];
+        }
+        kb++;
+      }
     }
 
     return (PyObject *)ret;
@@ -1382,12 +1382,12 @@ PyObject * matrix_elem_mul(matrix *self, PyObject *args, PyObject *kwrds)
   if (!PyArg_ParseTuple(args, "OO:emul", &A, &B)) return NULL;
 
   if (!(X_Matrix_Check(A) || PyNumber_Check(A)) ||
-      !(X_Matrix_Check(B) || PyNumber_Check(B))) 
+      !(X_Matrix_Check(B) || PyNumber_Check(B)))
     PY_ERR_TYPE("arguments must be either matrices or python numbers");
-   
+
   int a_is_number = PyNumber_Check(A) || (Matrix_Check(A) && MAT_LGT(A) == 1);
   int b_is_number = PyNumber_Check(B) || (Matrix_Check(B) && MAT_LGT(B) == 1);
-  
+
   int ida, idb;
   if (PyInt_Check(A)) { ida = INT; }
   else if (PyFloat_Check(A)) { ida = DOUBLE; }
@@ -1408,14 +1408,14 @@ PyObject * matrix_elem_mul(matrix *self, PyObject *args, PyObject *kwrds)
   if (a_is_number && b_is_number &&
       (!X_Matrix_Check(A) && !X_Matrix_Check(B))) {
     if (!X_Matrix_Check(A) && !X_Matrix_Check(B)) {
-      if (id == INT) 
-	return Py_BuildValue("i", a.i*b.i );
+      if (id == INT)
+        return Py_BuildValue("i", a.i*b.i );
       else if (id == DOUBLE)
-	return Py_BuildValue("d", a.d*b.d );
+        return Py_BuildValue("d", a.d*b.d );
       else {
-	number c;
-	c.z = a.z*b.z;
-	return znum2PyObject(&c, 0);
+        number c;
+        c.z = a.z*b.z;
+        return znum2PyObject(&c, 0);
       }
     }
   }
@@ -1425,63 +1425,63 @@ PyObject * matrix_elem_mul(matrix *self, PyObject *args, PyObject *kwrds)
       PY_ERR_TYPE("incompatible dimensions");
   }
 
-  int m = ( !a_is_number ? X_NROWS(A) : (!b_is_number ? X_NROWS(B) : 1));
-  int n = ( !a_is_number ? X_NCOLS(A) : (!b_is_number ? X_NCOLS(B) : 1));
-  
+  int_t m = ( !a_is_number ? X_NROWS(A) : (!b_is_number ? X_NROWS(B) : 1));
+  int_t n = ( !a_is_number ? X_NCOLS(A) : (!b_is_number ? X_NCOLS(B) : 1));
+
   if ((Matrix_Check(A) || a_is_number) && (Matrix_Check(B) || b_is_number)) {
 
     PyObject *ret = (PyObject *)Matrix_New(m, n, id);
     if (!ret) return PyErr_NoMemory();
 
-    int i;
+    int_t i;
     for (i=0; i<m*n; i++) {
       if (!a_is_number) convert_num[id](&a, A, 0, i);
       if (!b_is_number) convert_num[id](&b, B, 0, i);
-      
+
       if (id == INT)
-	MAT_BUFI(ret)[i] = a.i*b.i;
+        MAT_BUFI(ret)[i] = a.i*b.i;
       else if (id == DOUBLE)
-	MAT_BUFD(ret)[i] = a.d*b.d;
+        MAT_BUFD(ret)[i] = a.d*b.d;
       else
-	MAT_BUFZ(ret)[i] = a.z*b.z;
+        MAT_BUFZ(ret)[i] = a.z*b.z;
     }
 
     return ret;
 
-  } 
+  }
   else if (SpMatrix_Check(A) && !SpMatrix_Check(B)) {
-    
+
     PyObject *ret = (PyObject *)SpMatrix_NewFromSpMatrix((spmatrix *)A, id);
     if (!ret) return PyErr_NoMemory();
 
-    int j, k;
+    int_t j, k;
     for (j=0; j<SP_NCOLS(A); j++) {
       for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1]; k++) {
-	if (!b_is_number) convert_num[id](&b, B, 0, j*m + SP_ROW(A)[k]);
-      
-	if (id == DOUBLE)
-	  SP_VALD(ret)[k] *= b.d;
-	else
-	  SP_VALZ(ret)[k] *= b.z;
+        if (!b_is_number) convert_num[id](&b, B, 0, j*m + SP_ROW(A)[k]);
+
+        if (id == DOUBLE)
+          SP_VALD(ret)[k] *= b.d;
+        else
+          SP_VALZ(ret)[k] *= b.z;
       }
     }
 
     return ret;
   }
   else if (SpMatrix_Check(B) && !SpMatrix_Check(A)) {
-    
+
     PyObject *ret = (PyObject *)SpMatrix_NewFromSpMatrix((spmatrix *)B, id);
     if (!ret) return PyErr_NoMemory();
 
-    int j, k;
+    int_t j, k;
     for (j=0; j<SP_NCOLS(B); j++) {
       for (k=SP_COL(B)[j]; k<SP_COL(B)[j+1]; k++) {
-	if (!a_is_number) convert_num[id](&a, A, 0, j*m + SP_ROW(B)[k]);
-      
-	if (id == DOUBLE)
-	  SP_VALD(ret)[k] *= a.d;
-	else
-	  SP_VALZ(ret)[k] *= a.z;
+        if (!a_is_number) convert_num[id](&a, A, 0, j*m + SP_ROW(B)[k]);
+
+        if (id == DOUBLE)
+          SP_VALD(ret)[k] *= a.d;
+        else
+          SP_VALZ(ret)[k] *= a.z;
       }
     }
 
@@ -1489,28 +1489,28 @@ PyObject * matrix_elem_mul(matrix *self, PyObject *args, PyObject *kwrds)
   }
 
   else {
-    
+
     spmatrix *ret = SpMatrix_New(m, n, 0, id);
     if (!ret) return PyErr_NoMemory();
 
-    int j, ka = 0, kb = 0, kret = 0;
+    int_t j, ka = 0, kb = 0, kret = 0;
     for (j=0; j<n; j++) {
-      
+
       while (ka < SP_COL(A)[j+1] && kb < SP_COL(B)[j+1]) {
-	
-	if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
-	  ka++;
-	}
-	else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
-	  kb++;
-	}
-	else {
-	  SP_COL(ret)[j+1]++; ka++; kb++;
-	}
+
+        if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
+          ka++;
+        }
+        else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
+          kb++;
+        }
+        else {
+          SP_COL(ret)[j+1]++; ka++; kb++;
+        }
       }
-      
+
       ka = SP_COL(A)[j+1];
-      kb = SP_COL(B)[j+1];	
+      kb = SP_COL(B)[j+1];
     }
 
     for (j=0; j<n; j++) SP_COL(ret)[j+1] += SP_COL(ret)[j];
@@ -1528,32 +1528,32 @@ PyObject * matrix_elem_mul(matrix *self, PyObject *args, PyObject *kwrds)
 
     ka = 0; kb = 0;
     for (j=0; j<n; j++) {
-      
+
       while (ka < SP_COL(A)[j+1] && kb < SP_COL(B)[j+1]) {
-	
-	if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
-	  ka++;
-	}
-	else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
-	  kb++;
-	}
-	else {
-	  SP_ROW(ret)[kret] = SP_ROW(A)[ka];
-	  if (id == DOUBLE)
-	    SP_VALD(ret)[kret] = SP_VALD(A)[ka]*SP_VALD(B)[kb];
-	  else
-	    SP_VALZ(ret)[kret] = 
-	      (X_ID(A) == DOUBLE ? SP_VALD(A)[ka] : SP_VALZ(A)[ka])*
-	      (X_ID(B) == DOUBLE ? SP_VALD(B)[kb] : SP_VALZ(B)[kb]);
-	    
-	  kret++; ka++; kb++;
-	}
+
+        if (SP_ROW(A)[ka] < SP_ROW(B)[kb]) {
+          ka++;
+        }
+        else if (SP_ROW(A)[ka] > SP_ROW(B)[kb]) {
+          kb++;
+        }
+        else {
+          SP_ROW(ret)[kret] = SP_ROW(A)[ka];
+          if (id == DOUBLE)
+            SP_VALD(ret)[kret] = SP_VALD(A)[ka]*SP_VALD(B)[kb];
+          else
+            SP_VALZ(ret)[kret] =
+                (X_ID(A) == DOUBLE ? SP_VALD(A)[ka] : SP_VALZ(A)[ka])*
+                (X_ID(B) == DOUBLE ? SP_VALD(B)[kb] : SP_VALZ(B)[kb]);
+
+          kret++; ka++; kb++;
+        }
       }
 
       ka = SP_COL(A)[j+1];
-      kb = SP_COL(B)[j+1];	
+      kb = SP_COL(B)[j+1];
     }
-    
+
     return (PyObject *)ret;
   }
 }
@@ -1564,15 +1564,15 @@ PyObject * matrix_elem_div(matrix *self, PyObject *args, PyObject *kwrds)
   if (!PyArg_ParseTuple(args, "OO:ediv", &A, &B)) return NULL;
 
   if (!(X_Matrix_Check(A) || PyNumber_Check(A)) ||
-      !(X_Matrix_Check(B) || PyNumber_Check(B))) 
+      !(X_Matrix_Check(B) || PyNumber_Check(B)))
     PY_ERR_TYPE("arguments must be either matrices or python numbers");
-  
+
   if (SpMatrix_Check(B))
     PY_ERR_TYPE("elementwise division with sparse matrix\n");
 
   int a_is_number = PyNumber_Check(A) || (Matrix_Check(A) && MAT_LGT(A) == 1);
   int b_is_number = PyNumber_Check(B) || (Matrix_Check(B) && MAT_LGT(B) == 1);
-    
+
   int ida, idb;
   if (PyInt_Check(A)) { ida = INT; }
   else if (PyFloat_Check(A)) { ida = DOUBLE; }
@@ -1590,7 +1590,7 @@ PyObject * matrix_elem_div(matrix *self, PyObject *args, PyObject *kwrds)
   if (a_is_number) convert_num[id](&a, A, PyNumber_Check(A), 0);
   if (b_is_number) convert_num[id](&b, B, PyNumber_Check(B), 0);
 
-  if ((a_is_number && b_is_number) && 
+  if ((a_is_number && b_is_number) &&
       (!X_Matrix_Check(A) && !Matrix_Check(B))) {
     if (id == INT) {
       if (b.i == 0) PY_ERR(PyExc_ArithmeticError, "division by zero");
@@ -1615,7 +1615,7 @@ PyObject * matrix_elem_div(matrix *self, PyObject *args, PyObject *kwrds)
 
   int m = ( !a_is_number ? X_NROWS(A) : (!b_is_number ? X_NROWS(B) : 1));
   int n = ( !a_is_number ? X_NCOLS(A) : (!b_is_number ? X_NCOLS(B) : 1));
-  
+
   if ((Matrix_Check(A) || a_is_number) && (Matrix_Check(B) || b_is_number)) {
 
     if (!(ret = (PyObject *)Matrix_New(m, n, id)))
@@ -1625,48 +1625,48 @@ PyObject * matrix_elem_div(matrix *self, PyObject *args, PyObject *kwrds)
     for (i=0; i<m*n; i++) {
       if (!a_is_number) convert_num[id](&a, A, 0, i);
       if (!b_is_number) convert_num[id](&b, B, 0, i);
-      
+
       if (id == INT) {
-	if (b.i == 0) goto divzero;
-	MAT_BUFI(ret)[i] = a.i/b.i;
+        if (b.i == 0) goto divzero;
+        MAT_BUFI(ret)[i] = a.i/b.i;
       }
       else if (id == DOUBLE) {
-	if (b.d == 0) goto divzero;
-	MAT_BUFD(ret)[i] = a.d/b.d;
+        if (b.d == 0) goto divzero;
+        MAT_BUFD(ret)[i] = a.d/b.d;
       }
       else {
-	if (b.z == 0) goto divzero;
-	MAT_BUFZ(ret)[i] = a.z/b.z;
+        if (b.z == 0) goto divzero;
+        MAT_BUFZ(ret)[i] = a.z/b.z;
       }
     }
 
     return ret;
-  } 
+  }
   else { // (SpMatrix_Check(A) && !SpMatrix_Check(B)) {
-    
+
     if (!(ret = (PyObject *)SpMatrix_NewFromSpMatrix((spmatrix *)A, id)))
       return PyErr_NoMemory();
 
     int j, k;
     for (j=0; j<SP_NCOLS(A); j++) {
       for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1]; k++) {
-	if (!b_is_number) convert_num[id](&b, B, 0, j*m + SP_ROW(A)[k]);
-      
-	if (id == DOUBLE) {
-	  if (b.d == 0.0) goto divzero;
-	  SP_VALD(ret)[k] /= b.d;
-	}
-	else {
-	  if (b.z == 0.0) goto divzero;
-	  SP_VALZ(ret)[k] /= b.z;
-	}
+        if (!b_is_number) convert_num[id](&b, B, 0, j*m + SP_ROW(A)[k]);
+
+        if (id == DOUBLE) {
+          if (b.d == 0.0) goto divzero;
+          SP_VALD(ret)[k] /= b.d;
+        }
+        else {
+          if (b.z == 0.0) goto divzero;
+          SP_VALZ(ret)[k] /= b.z;
+        }
       }
     }
 
     return ret;
   }
 
- divzero:
+  divzero:
   Py_DECREF(ret);
   PY_ERR(PyExc_ArithmeticError, "division by zero");
 }
@@ -1678,40 +1678,40 @@ extern PyObject * matrix_cos(matrix *, PyObject *, PyObject *) ;
 extern PyObject * matrix_sin(matrix *, PyObject *, PyObject *) ;
 
 static PyMethodDef base_functions[] = {
-  {"exp", (PyCFunction)matrix_exp, METH_VARARGS|METH_KEYWORDS, 
-  "Computes the element-wise expontial of a matrix"},
-  {"log", (PyCFunction)matrix_log, METH_VARARGS|METH_KEYWORDS, 
-  "Computes the element-wise logarithm of a matrix"},
-  {"sqrt", (PyCFunction)matrix_sqrt, METH_VARARGS|METH_KEYWORDS, 
-  "Computes the element-wise square-root of a matrix"},
-  {"cos", (PyCFunction)matrix_cos, METH_VARARGS|METH_KEYWORDS, 
-  "Computes the element-wise cosine of a matrix"},
-  {"sin", (PyCFunction)matrix_sin, METH_VARARGS|METH_KEYWORDS, 
-  "Computes the element-wise sine of a matrix"},
-  {"axpy", (PyCFunction)base_axpy, METH_VARARGS|METH_KEYWORDS, doc_axpy},
-  {"gemm", (PyCFunction)base_gemm, METH_VARARGS|METH_KEYWORDS, doc_gemm},
-  {"gemv", (PyCFunction)base_gemv, METH_VARARGS|METH_KEYWORDS, doc_gemv},
-  {"syrk", (PyCFunction)base_syrk, METH_VARARGS|METH_KEYWORDS, doc_syrk},
-  {"symv", (PyCFunction)base_symv, METH_VARARGS|METH_KEYWORDS, doc_symv},
-  {"emul", (PyCFunction)matrix_elem_mul, METH_VARARGS|METH_KEYWORDS, 
-   "elementwise product of two matrices"},
-  {"ediv", (PyCFunction)matrix_elem_div, METH_VARARGS|METH_KEYWORDS, 
-   "elementwise division between two matrices"},
-  {"emin", (PyCFunction)matrix_elem_min, METH_VARARGS|METH_KEYWORDS, 
-   "elementwise minimum between two matrices"},
-  {"emax", (PyCFunction)matrix_elem_max, METH_VARARGS|METH_KEYWORDS, 
-   "elementwise maximum between two matrices"},
-  {"sparse", (PyCFunction)sparse, METH_VARARGS|METH_KEYWORDS, doc_sparse},
-  {"spdiag", (PyCFunction)spdiag, METH_VARARGS|METH_KEYWORDS, doc_spdiag},
-  {NULL}		/* sentinel */
+    {"exp", (PyCFunction)matrix_exp, METH_VARARGS|METH_KEYWORDS,
+        "Computes the element-wise expontial of a matrix"},
+    {"log", (PyCFunction)matrix_log, METH_VARARGS|METH_KEYWORDS,
+        "Computes the element-wise logarithm of a matrix"},
+    {"sqrt", (PyCFunction)matrix_sqrt, METH_VARARGS|METH_KEYWORDS,
+        "Computes the element-wise square-root of a matrix"},
+    {"cos", (PyCFunction)matrix_cos, METH_VARARGS|METH_KEYWORDS,
+        "Computes the element-wise cosine of a matrix"},
+    {"sin", (PyCFunction)matrix_sin, METH_VARARGS|METH_KEYWORDS,
+        "Computes the element-wise sine of a matrix"},
+    {"axpy", (PyCFunction)base_axpy, METH_VARARGS|METH_KEYWORDS, doc_axpy},
+    {"gemm", (PyCFunction)base_gemm, METH_VARARGS|METH_KEYWORDS, doc_gemm},
+    {"gemv", (PyCFunction)base_gemv, METH_VARARGS|METH_KEYWORDS, doc_gemv},
+    {"syrk", (PyCFunction)base_syrk, METH_VARARGS|METH_KEYWORDS, doc_syrk},
+    {"symv", (PyCFunction)base_symv, METH_VARARGS|METH_KEYWORDS, doc_symv},
+    {"emul", (PyCFunction)matrix_elem_mul, METH_VARARGS|METH_KEYWORDS,
+        "elementwise product of two matrices"},
+    {"ediv", (PyCFunction)matrix_elem_div, METH_VARARGS|METH_KEYWORDS,
+        "elementwise division between two matrices"},
+    {"emin", (PyCFunction)matrix_elem_min, METH_VARARGS|METH_KEYWORDS,
+        "elementwise minimum between two matrices"},
+    {"emax", (PyCFunction)matrix_elem_max, METH_VARARGS|METH_KEYWORDS,
+        "elementwise maximum between two matrices"},
+    {"sparse", (PyCFunction)sparse, METH_VARARGS|METH_KEYWORDS, doc_sparse},
+    {"spdiag", (PyCFunction)spdiag, METH_VARARGS|METH_KEYWORDS, doc_spdiag},
+    {NULL}		/* sentinel */
 };
 
 PyMODINIT_FUNC
 initbase(void)
-{  
+{
   static void *base_API[8];
   PyObject *base_mod, *c_api_object;
-  
+
   if (!(base_mod = Py_InitModule3("base", base_functions, base__doc__)))
     return;
 
@@ -1720,22 +1720,22 @@ initbase(void)
   matrix_tp.tp_free = PyObject_Del;
   if (PyType_Ready(&matrix_tp) < 0)
     return;
-  
+
   if (PyType_Ready(&matrix_tp) < 0)
     return;
-    
+
   Py_INCREF(&matrix_tp);
   if (PyModule_AddObject(base_mod, "matrix", (PyObject *) &matrix_tp) < 0)
-    return;   
+    return;
 
   spmatrix_tp.tp_alloc = PyType_GenericAlloc;
   spmatrix_tp.tp_free = PyObject_Del;
   if (PyType_Ready(&spmatrix_tp) < 0)
     return;
-    
+
   Py_INCREF(&spmatrix_tp);
   if (PyModule_AddObject(base_mod, "spmatrix", (PyObject *) &spmatrix_tp) < 0)
-    return;   
+    return;
 
   One[INT].i = 1; One[DOUBLE].d = 1.0; One[COMPLEX].z = 1.0;
 
diff --git a/src/C/blas.c b/src/C/blas.c
index fdd202d..124ee01 100644
--- a/src/C/blas.c
+++ b/src/C/blas.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -38,21 +38,21 @@ PyDoc_STRVAR(blas__doc__,"Interface to the double-precision real and "
 
 /* BLAS 1 prototypes */
 extern void dswap_(int *n, double *x, int *incx, double *y, int *incy);
-extern void zswap_(int *n, complex *x, int *incx, complex *y, 
+extern void zswap_(int *n, complex *x, int *incx, complex *y,
     int *incy);
 extern void dscal_(int *n, double *alpha, double *x, int *incx);
 extern void zscal_(int *n, complex *alpha, complex *x, int *incx);
 extern void zdscal_(int *n, double *alpha, complex *x, int *incx);
 extern void dcopy_(int *n, double *x, int *incx, double *y, int *incy);
-extern void zcopy_(int *n, complex *x, int *incx, complex *y, 
+extern void zcopy_(int *n, complex *x, int *incx, complex *y,
     int *incy);
-extern void daxpy_(int *n, double *alpha, double *x, int *incx, 
+extern void daxpy_(int *n, double *alpha, double *x, int *incx,
     double *y, int *incy);
-extern void zaxpy_(int *n, complex *alpha, complex *x, int *incx, 
+extern void zaxpy_(int *n, complex *alpha, complex *x, int *incx,
     complex *y, int *incy);
 extern double ddot_(int *n, double *x, int *incx, double *y, int *incy);
 #if USE_CBLAS_ZDOT
-extern void cblas_zdotc_sub(int n, void *x, int incx, void *y, 
+extern void cblas_zdotc_sub(int n, void *x, int incx, void *y,
     int incy, void *result);
 extern void cblas_zdotu_sub(int n, void *x, int incx, void *y, int incy,
     void *result);
@@ -66,105 +66,105 @@ extern int izamax_(int *n, complex *x, int *incx);
 
 
 /* BLAS 2 prototypes */
-extern void dgemv_(char* trans, int *m, int *n, double *alpha, 
+extern void dgemv_(char* trans, int *m, int *n, double *alpha,
     double *A, int *lda, double *x, int *incx, double *beta, double *y,
     int *incy);
-extern void zgemv_(char* trans, int *m, int *n, complex *alpha, 
-    complex *A, int *lda, complex *x, int *incx, complex *beta, 
+extern void zgemv_(char* trans, int *m, int *n, complex *alpha,
+    complex *A, int *lda, complex *x, int *incx, complex *beta,
     complex *y, int *incy);
-extern void dgbmv_(char* trans, int *m, int *n, int *kl, int *ku, 
-    double *alpha, double *A, int *lda, double *x, int *incx, 
-    double *beta, double *y,  int *incy); 
-extern void zgbmv_(char* trans, int *m, int *n, int *kl, int *ku, 
-    complex *alpha, complex *A, int *lda, complex *x, int *incx, 
-    complex *beta, complex *y,  int *incy); 
-extern void dsymv_(char *uplo, int *n, double *alpha, double *A, 
+extern void dgbmv_(char* trans, int *m, int *n, int *kl, int *ku,
+    double *alpha, double *A, int *lda, double *x, int *incx,
+    double *beta, double *y,  int *incy);
+extern void zgbmv_(char* trans, int *m, int *n, int *kl, int *ku,
+    complex *alpha, complex *A, int *lda, complex *x, int *incx,
+    complex *beta, complex *y,  int *incy);
+extern void dsymv_(char *uplo, int *n, double *alpha, double *A,
     int *lda, double *x, int *incx, double *beta, double *y, int *incy);
-extern void zhemv_(char *uplo, int *n, complex *alpha, complex *A, 
-    int *lda, complex *x, int *incx, complex *beta, complex *y, 
+extern void zhemv_(char *uplo, int *n, complex *alpha, complex *A,
+    int *lda, complex *x, int *incx, complex *beta, complex *y,
     int *incy);
 extern void dsbmv_(char *uplo, int *n, int *k, double *alpha, double *A,
     int *lda, double *x, int *incx, double *beta, double *y, int *incy);
-extern void zhbmv_(char *uplo, int *n, int *k, complex *alpha, 
-    complex *A, int *lda, complex *x, int *incx, complex *beta, 
+extern void zhbmv_(char *uplo, int *n, int *k, complex *alpha,
+    complex *A, int *lda, complex *x, int *incx, complex *beta,
     complex *y, int *incy);
-extern void dtrmv_(char *uplo, char *trans, char *diag, int *n, 
+extern void dtrmv_(char *uplo, char *trans, char *diag, int *n,
     double *A, int *lda, double *x, int *incx);
-extern void ztrmv_(char *uplo, char *trans, char *diag, int *n, 
+extern void ztrmv_(char *uplo, char *trans, char *diag, int *n,
     complex *A, int *lda, complex *x, int *incx);
-extern void dtbmv_(char *uplo, char *trans, char *diag, int *n, int *k, 
+extern void dtbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
     double *A, int *lda, double *x, int *incx);
-extern void ztbmv_(char *uplo, char *trans, char *diag, int *n, int *k, 
+extern void ztbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
     complex *A, int *lda, complex *x, int *incx);
-extern void dtrsv_(char *uplo, char *trans, char *diag, int *n, 
+extern void dtrsv_(char *uplo, char *trans, char *diag, int *n,
     double *A, int *lda, double *x, int *incx);
-extern void ztrsv_(char *uplo, char *trans, char *diag, int *n, 
+extern void ztrsv_(char *uplo, char *trans, char *diag, int *n,
     complex *A, int *lda, complex *x, int *incx);
-extern void dtbsv_(char *uplo, char *trans, char *diag, int *n, int *k, 
+extern void dtbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
     double *A, int *lda, double *x, int *incx);
-extern void ztbsv_(char *uplo, char *trans, char *diag, int *n, int *k, 
+extern void ztbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
     complex *A, int *lda, complex *x, int *incx);
-extern void dger_(int *m, int *n, double *alpha, double *x, int *incx, 
+extern void dger_(int *m, int *n, double *alpha, double *x, int *incx,
     double *y, int *incy, double *A, int *lda);
-extern void zgerc_(int *m, int *n, complex *alpha, complex *x, 
+extern void zgerc_(int *m, int *n, complex *alpha, complex *x,
     int *incx, complex *y, int *incy, complex *A, int *lda);
-extern void zgeru_(int *m, int *n, complex *alpha, complex *x, 
+extern void zgeru_(int *m, int *n, complex *alpha, complex *x,
     int *incx, complex *y, int *incy, complex *A, int *lda);
-extern void dsyr_(char *uplo, int *n, double *alpha, double *x, 
+extern void dsyr_(char *uplo, int *n, double *alpha, double *x,
     int *incx, double *A, int *lda);
-extern void zher_(char *uplo, int *n, double *alpha, complex *x, 
+extern void zher_(char *uplo, int *n, double *alpha, complex *x,
     int *incx, complex *A, int *lda);
-extern void dsyr2_(char *uplo, int *n, double *alpha, double *x, 
+extern void dsyr2_(char *uplo, int *n, double *alpha, double *x,
     int *incx, double *y, int *incy, double *A, int *lda);
-extern void zher2_(char *uplo, int *n, complex *alpha, complex *x, 
+extern void zher2_(char *uplo, int *n, complex *alpha, complex *x,
     int *incx, complex *y, int *incy, complex *A, int *lda);
 
 
 /* BLAS 3 prototypes */
-extern void dgemm_(char *transa, char *transb, int *m, int *n, int *k, 
-    double *alpha, double *A, int *lda, double *B, int *ldb, 
+extern void dgemm_(char *transa, char *transb, int *m, int *n, int *k,
+    double *alpha, double *A, int *lda, double *B, int *ldb,
     double *beta, double *C, int *ldc);
-extern void zgemm_(char *transa, char *transb, int *m, int *n, int *k, 
-    complex *alpha, complex *A, int *lda, complex *B, int *ldb, 
+extern void zgemm_(char *transa, char *transb, int *m, int *n, int *k,
+    complex *alpha, complex *A, int *lda, complex *B, int *ldb,
     complex *beta, complex *C, int *ldc);
-extern void dsymm_(char *side, char *uplo, int *m, int *n, 
-    double *alpha, double *A, int *lda, double *B, int *ldb, 
+extern void dsymm_(char *side, char *uplo, int *m, int *n,
+    double *alpha, double *A, int *lda, double *B, int *ldb,
     double *beta, double *C, int *ldc);
-extern void zsymm_(char *side, char *uplo, int *m, int *n, 
-    complex *alpha, complex *A, int *lda, complex *B, int *ldb, 
+extern void zsymm_(char *side, char *uplo, int *m, int *n,
+    complex *alpha, complex *A, int *lda, complex *B, int *ldb,
     complex *beta, complex *C, int *ldc);
-extern void zhemm_(char *side, char *uplo, int *m, int *n, 
-    complex *alpha, complex *A, int *lda, complex *B, int *ldb, 
+extern void zhemm_(char *side, char *uplo, int *m, int *n,
+    complex *alpha, complex *A, int *lda, complex *B, int *ldb,
     complex *beta, complex *C, int *ldc);
-extern void dsyrk_(char *uplo, char *trans, int *n, int *k, 
-    double *alpha, double *A, int *lda, double *beta, double *B, 
+extern void dsyrk_(char *uplo, char *trans, int *n, int *k,
+    double *alpha, double *A, int *lda, double *beta, double *B,
     int *ldb);
-extern void zsyrk_(char *uplo, char *trans, int *n, int *k, 
-    complex *alpha, complex *A, int *lda, complex *beta, complex *B, 
+extern void zsyrk_(char *uplo, char *trans, int *n, int *k,
+    complex *alpha, complex *A, int *lda, complex *beta, complex *B,
     int *ldb);
-extern void zherk_(char *uplo, char *trans, int *n, int *k, 
-    double *alpha, complex *A, int *lda, double *beta, complex *B, 
+extern void zherk_(char *uplo, char *trans, int *n, int *k,
+    double *alpha, complex *A, int *lda, double *beta, complex *B,
     int *ldb);
-extern void dsyr2k_(char *uplo, char *trans, int *n, int *k, 
-    double *alpha, double *A, int *lda, double *B, int *ldb, 
+extern void dsyr2k_(char *uplo, char *trans, int *n, int *k,
+    double *alpha, double *A, int *lda, double *B, int *ldb,
     double *beta, double *C, int *ldc);
-extern void zsyr2k_(char *uplo, char *trans, int *n, int *k, 
-    complex *alpha, complex *A, int *lda, complex *B, int *ldb, 
+extern void zsyr2k_(char *uplo, char *trans, int *n, int *k,
+    complex *alpha, complex *A, int *lda, complex *B, int *ldb,
     complex *beta, complex *C, int *ldc);
-extern void zher2k_(char *uplo, char *trans, int *n, int *k, 
-    complex *alpha, complex *A, int *lda, complex *B, int *ldb, 
+extern void zher2k_(char *uplo, char *trans, int *n, int *k,
+    complex *alpha, complex *A, int *lda, complex *B, int *ldb,
     double *beta, complex *C, int *ldc);
-extern void dtrmm_(char *side, char *uplo, char *transa, char *diag, 
-    int *m, int *n, double *alpha, double *A, int *lda, double *B, 
+extern void dtrmm_(char *side, char *uplo, char *transa, char *diag,
+    int *m, int *n, double *alpha, double *A, int *lda, double *B,
     int *ldb);
-extern void ztrmm_(char *side, char *uplo, char *transa, char *diag, 
-    int *m, int *n, complex *alpha, complex *A, int *lda, complex *B, 
+extern void ztrmm_(char *side, char *uplo, char *transa, char *diag,
+    int *m, int *n, complex *alpha, complex *A, int *lda, complex *B,
     int *ldb);
-extern void dtrsm_(char *side, char *uplo, char *transa, char *diag, 
-    int *m, int *n, double *alpha, double *A, int *lda, double *B, 
+extern void dtrsm_(char *side, char *uplo, char *transa, char *diag,
+    int *m, int *n, double *alpha, double *A, int *lda, double *B,
     int *ldb);
-extern void ztrsm_(char *side, char *uplo, char *transa, char *diag, 
-    int *m, int *n, complex *alpha, complex *A, int *lda, complex *B, 
+extern void ztrsm_(char *side, char *uplo, char *transa, char *diag,
+    int *m, int *n, complex *alpha, complex *A, int *lda, complex *B,
     int *ldb);
 
 
@@ -172,15 +172,15 @@ static int number_from_pyobject(PyObject *o, number *a, int id)
 {
     switch (id){
         case DOUBLE:
-            if (!PyInt_Check(o) && !PyLong_Check(o) && 
+            if (!PyInt_Check(o) && !PyLong_Check(o) &&
                 !PyFloat_Check(o)) return -1;
             (*a).d = PyFloat_AsDouble(o);
             return 0;
 
         case COMPLEX:
-            if (!PyInt_Check(o) && !PyLong_Check(o) && 
+            if (!PyInt_Check(o) && !PyLong_Check(o) &&
                 !PyFloat_Check(o) && !PyComplex_Check(o)) return -1;
-            (*a).z = PyComplex_RealAsDouble(o) + 
+            (*a).z = PyComplex_RealAsDouble(o) +
                 I*PyComplex_ImagAsDouble(o);
             return 0;
     }
@@ -199,19 +199,19 @@ static char doc_swap[] =
     "          len(x)>=offsetx+1 ? 1+(len(x)-offsetx-1)/|incx| : 0.\n"
     "          If the default value is used, it must be equal to\n"
     "          len(y)>=offsety+1 ? 1+(len(y)-offsetx-1)/|incy| : 0.\n\n"
-    "incx      nonzero integer\n\n" 
-    "incy      nonzero integer\n\n" 
+    "incx      nonzero integer\n\n"
+    "incy      nonzero integer\n\n"
     "offsetx   nonnegative integer\n\n"
     "offsety   nonnegative integer";
 
 static PyObject* swap(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *y; 
-    int n=-1, ix=1, iy=1, ox=0, oy=0; 
-    char *kwlist[] = {"x", "y", "n", "incx", "incy", "offsetx", 
+    matrix *x, *y;
+    int n=-1, ix=1, iy=1, ox=0, oy=0;
+    char *kwlist[] = {"x", "y", "n", "incx", "incy", "offsetx",
         "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii", kwlist,
         &x, &y, &n, &ix, &iy, &ox, &oy)) return NULL;
 
     if (!Matrix_Check(x)) err_mtrx("x");
@@ -238,7 +238,7 @@ static PyObject* swap(PyObject *self, PyObject *args, PyObject *kwrds)
     if (len(y) < oy+1+(n-1)*abs(iy)) err_buf_len("y");
 
     switch (MAT_ID(x)){
-        case DOUBLE: 
+        case DOUBLE:
             Py_BEGIN_ALLOW_THREADS
             dswap_(&n, MAT_BUFD(x)+ox, &ix, MAT_BUFD(y)+oy, &iy);
             Py_END_ALLOW_THREADS
@@ -268,18 +268,18 @@ static char doc_scal[] =
     "n         integer.  If n<0, the default value of n is used.\n"
     "          The default value is equal to\n"
     "          (len(x)>=offset+1) ? 1+(len-offset-1)/inc : 0.\n\n"
-    "inc       positive integer\n\n" 
+    "inc       positive integer\n\n"
     "offset    nonnegative integer";
 
 static PyObject* scal(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x; 
+    matrix *x;
     PyObject *ao;
-    number a; 
+    number a;
     int n=-1, ix=1, ox=0;
     char *kwlist[] = {"alpha", "x", "n", "inc", "offset", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iii", kwlist,
         &ao, &x, &n, &ix, &ox)) return NULL;
 
     if (!Matrix_Check(x)) err_mtrx("x");
@@ -290,8 +290,8 @@ static PyObject* scal(PyObject *self, PyObject *args, PyObject *kwrds)
     if (len(x) < ox+1+(n-1)*ix) err_buf_len("x");
 
     switch (MAT_ID(x)){
-        case DOUBLE: 
-            if (number_from_pyobject(ao, &a, MAT_ID(x))) 
+        case DOUBLE:
+            if (number_from_pyobject(ao, &a, MAT_ID(x)))
                 err_type("alpha");
             Py_BEGIN_ALLOW_THREADS
             dscal_(&n, &a.d, MAT_BUFD(x)+ox, &ix);
@@ -299,12 +299,12 @@ static PyObject* scal(PyObject *self, PyObject *args, PyObject *kwrds)
 	    break;
 
         case COMPLEX:
-            if (!number_from_pyobject(ao, &a, DOUBLE)) 
-                Py_BEGIN_ALLOW_THREADS	    
+            if (!number_from_pyobject(ao, &a, DOUBLE))
+                Py_BEGIN_ALLOW_THREADS
                 zdscal_(&n, &a.d, MAT_BUFZ(x)+ox, &ix);
                 Py_END_ALLOW_THREADS
-            else if (!number_from_pyobject(ao, &a, COMPLEX)) 
-                Py_BEGIN_ALLOW_THREADS	    
+            else if (!number_from_pyobject(ao, &a, COMPLEX))
+                Py_BEGIN_ALLOW_THREADS
                 zscal_(&n, &a.z, MAT_BUFZ(x)+ox, &ix);
                 Py_END_ALLOW_THREADS
             else
@@ -315,7 +315,7 @@ static PyObject* scal(PyObject *self, PyObject *args, PyObject *kwrds)
             err_invalid_id;
     }
 
-    return Py_BuildValue(""); 
+    return Py_BuildValue("");
 }
 
 
@@ -326,21 +326,21 @@ static char doc_copy[] =
     "x         'd' or 'z' matrix\n\n"
     "y         'd' or 'z' matrix.  Must have the same type as x.\n\n"
     "n         integer.  If n<0, the default value of n is used.\n"
-    "          The default value is given by\n" 
+    "          The default value is given by\n"
     "          (len(x)>=offsetx+1) ? 1+(len(x)-offsetx-1)/incx : 0\n\n"
-    "incx      nonzero integer\n\n" 
-    "incy      nonzero integer\n\n" 
+    "incx      nonzero integer\n\n"
+    "incy      nonzero integer\n\n"
     "offsetx   nonnegative integer\n\n"
     "offsety   nonnegative integer";
 
 static PyObject* copy(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *y; 
+    matrix *x, *y;
     int n=-1, ix=1, iy=1, ox=0, oy=0;
     char *kwlist[] = {"x", "y", "n", "incx", "incy", "offsetx",
         "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii", kwlist,
         &x, &y, &n, &ix, &iy, &ox, &oy))
         return NULL;
 
@@ -362,13 +362,13 @@ static PyObject* copy(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dcopy_(&n, MAT_BUFD(x)+ox, &ix, MAT_BUFD(y)+oy, &iy);
             Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zcopy_(&n, MAT_BUFZ(x)+ox, &ix, MAT_BUFZ(y)+oy, &iy);
             Py_END_ALLOW_THREADS
             break;
@@ -393,21 +393,21 @@ static char doc_axpy[] =
     "n         integer.  If n<0, the default value of n is used.\n"
     "          The default value is equal to\n"
     "          (len(x)>=offsetx+1) ? 1+(len(x)-offsetx-1)/incx : 0.\n\n"
-    "incx      nonzero integer\n\n" 
-    "incy      nonzero integer\n\n" 
+    "incx      nonzero integer\n\n"
+    "incy      nonzero integer\n\n"
     "offsetx   nonnegative integer\n\n"
     "offsety   nonnegative integer";
 
 static PyObject* axpy(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *y; 
+    matrix *x, *y;
     PyObject *ao=NULL;
     number a;
     int n=-1, ix=1, iy=1, ox=0, oy=0;
     char *kwlist[] = {"x", "y", "alpha", "n", "incx", "incy", "offsetx",
         "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Oiiiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Oiiiii", kwlist,
         &x, &y, &ao, &n, &ix, &iy, &ox, &oy)) return NULL;
 
     if (!Matrix_Check(x)) err_mtrx("x");
@@ -426,25 +426,25 @@ static PyObject* axpy(PyObject *self, PyObject *args, PyObject *kwrds)
     if (len(x) < ox + 1+(n-1)*abs(ix)) err_buf_len("x");
     if (len(y) < oy + 1+(n-1)*abs(iy)) err_buf_len("y");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d=1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
+            if (!ao) a.d=1.0;
+            Py_BEGIN_ALLOW_THREADS
             daxpy_(&n, &a.d, MAT_BUFD(x)+ox, &ix, MAT_BUFD(y)+oy, &iy);
             Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z=1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
+            if (!ao) a.z=1.0;
+            Py_BEGIN_ALLOW_THREADS
             zaxpy_(&n, &a.z, MAT_BUFZ(x)+ox, &ix, MAT_BUFZ(y)+oy, &iy);
             Py_END_ALLOW_THREADS
             break;
 
-        default: 
+        default:
             err_invalid_id;
     }
 
@@ -463,22 +463,22 @@ static char doc_dot[] =
     "          (len(x)>=offsetx+1) ? 1+(len(x)-offsetx-1)/incx : 0.\n"
     "          If the default value is used, it must be equal to\n"
     "          len(y)>=offsety+1 ? 1+(len(y)-offsetx-1)/|incy| : 0.\n\n"
-    "incx      nonzero integer\n\n" 
-    "incy      nonzero integer\n\n" 
+    "incx      nonzero integer\n\n"
+    "incy      nonzero integer\n\n"
     "offsetx   nonnegative integer\n\n"
     "offsety   nonnegative integer\n\n"
-    "Returns 0 if n=0.";  
+    "Returns 0 if n=0.";
 
 static PyObject* dot(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *y; 
+    matrix *x, *y;
     number val;
-    int n=-1, ix=1, iy=1, ox=0, oy=0; 
+    int n=-1, ix=1, iy=1, ox=0, oy=0;
     char *kwlist[] = {"x", "y", "n", "incx", "incy", "offsetx",
         "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii", kwlist, 
-        &x, &y, &n, &ix, &iy, &ox, &oy)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii", kwlist,
+        &x, &y, &n, &ix, &iy, &ox, &oy))
         return NULL;
 
     if (!Matrix_Check(x)) err_mtrx("x");
@@ -504,30 +504,30 @@ static PyObject* dot(PyObject *self, PyObject *args, PyObject *kwrds)
     if (n && len(y) < oy + 1 + (n-1)*abs(iy)) err_buf_len("y");
 
     switch (MAT_ID(x)){
-        case DOUBLE: 
+        case DOUBLE:
             Py_BEGIN_ALLOW_THREADS
-            val.d = (n==0) ? 0.0 : ddot_(&n, MAT_BUFD(x)+ox, &ix, 
+            val.d = (n==0) ? 0.0 : ddot_(&n, MAT_BUFD(x)+ox, &ix,
                 MAT_BUFD(y)+oy, &iy);
             Py_END_ALLOW_THREADS
             return Py_BuildValue("d", val.d);
 
-        case COMPLEX: 
+        case COMPLEX:
 	    if (n==0) val.z = 0.0;
 	    else
 #if USE_CBLAS_ZDOT
-                cblas_zdotc_sub(n, MAT_BUFZ(x)+ox, ix, MAT_BUFZ(y)+oy, 
+                cblas_zdotc_sub(n, MAT_BUFZ(x)+ox, ix, MAT_BUFZ(y)+oy,
                     iy, &val.z);
 #else
                 ix *= 2;
                 iy *= 2;
                 Py_BEGIN_ALLOW_THREADS
                 val.z = (ddot_(&n, MAT_BUFD(x)+2*ox, &ix,
-                    MAT_BUFD(y)+2*oy, &iy) + 
-                    ddot_(&n, MAT_BUFD(x)+2*ox + 1, &ix, 
+                    MAT_BUFD(y)+2*oy, &iy) +
+                    ddot_(&n, MAT_BUFD(x)+2*ox + 1, &ix,
                     MAT_BUFD(y)+2*oy + 1, &iy)) +
                     I*(ddot_(&n, MAT_BUFD(x)+2*ox, &ix,
-                    MAT_BUFD(y)+2*oy + 1, &iy) - 
-                    ddot_(&n, MAT_BUFD(x)+2*ox + 1, &ix, 
+                    MAT_BUFD(y)+2*oy + 1, &iy) -
+                    ddot_(&n, MAT_BUFD(x)+2*ox + 1, &ix,
                     MAT_BUFD(y)+2*oy, &iy));
                 Py_END_ALLOW_THREADS
 #endif
@@ -550,22 +550,22 @@ static char doc_dotu[] =
     "          (len(x)>=offsetx+1) ? 1+(len(x)-offsetx-1)/incx : 0.\n"
     "          If the default value is used, it must be equal to\n"
     "          len(y)>=offsety+1 ? 1+(len(y)-offsetx-1)/|incy| : 0.\n\n"
-    "incx      nonzero integer\n\n" 
-    "incy      nonzero integer\n\n" 
+    "incx      nonzero integer\n\n"
+    "incy      nonzero integer\n\n"
     "offsetx   nonnegative integer\n\n"
     "offsety   nonnegative integer\n\n"
-    "Returns 0 if n=0.";  
+    "Returns 0 if n=0.";
 
 static PyObject* dotu(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *y; 
+    matrix *x, *y;
     number val;
-    int n=-1, ix=1, iy=1, ox=0, oy=0; 
+    int n=-1, ix=1, iy=1, ox=0, oy=0;
     char *kwlist[] = {"x", "y", "n", "incx", "incy", "offsetx",
         "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii", kwlist, 
-        &x, &y, &n, &ix, &iy, &ox, &oy)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii", kwlist,
+        &x, &y, &n, &ix, &iy, &ox, &oy))
         return NULL;
 
     if (!Matrix_Check(x)) err_mtrx("x");
@@ -593,7 +593,7 @@ static PyObject* dotu(PyObject *self, PyObject *args, PyObject *kwrds)
     switch (MAT_ID(x)){
         case DOUBLE:
             Py_BEGIN_ALLOW_THREADS
-            val.d = (n==0) ? 0.0 : ddot_(&n, MAT_BUFD(x)+ox, &ix, 
+            val.d = (n==0) ? 0.0 : ddot_(&n, MAT_BUFD(x)+ox, &ix,
                 MAT_BUFD(y)+oy, &iy);
             Py_END_ALLOW_THREADS
             return Py_BuildValue("d", val.d);
@@ -603,7 +603,7 @@ static PyObject* dotu(PyObject *self, PyObject *args, PyObject *kwrds)
 	    else
 #if USE_CBLAS_ZDOT
                 Py_BEGIN_ALLOW_THREADS
-                cblas_zdotu_sub(n, MAT_BUFZ(x)+ox, ix, MAT_BUFZ(y)+oy, 
+                cblas_zdotu_sub(n, MAT_BUFZ(x)+ox, ix, MAT_BUFZ(y)+oy,
                     iy, &val.z);
                 Py_END_ALLOW_THREADS
 #else
@@ -611,12 +611,12 @@ static PyObject* dotu(PyObject *self, PyObject *args, PyObject *kwrds)
                 iy *= 2;
                 Py_BEGIN_ALLOW_THREADS
                 val.z = (ddot_(&n, MAT_BUFD(x)+2*ox, &ix,
-                    MAT_BUFD(y)+2*oy, &iy) - 
-                    ddot_(&n, MAT_BUFD(x)+2*ox + 1, &ix, 
+                    MAT_BUFD(y)+2*oy, &iy) -
+                    ddot_(&n, MAT_BUFD(x)+2*ox + 1, &ix,
                     MAT_BUFD(y)+2*oy + 1, &iy)) +
                     I*(ddot_(&n, MAT_BUFD(x)+2*ox, &ix,
-                    MAT_BUFD(y)+2*oy + 1, &iy) + 
-                    ddot_(&n, MAT_BUFD(x)+2*ox + 1, &ix, 
+                    MAT_BUFD(y)+2*oy + 1, &iy) +
+                    ddot_(&n, MAT_BUFD(x)+2*ox + 1, &ix,
                     MAT_BUFD(y)+2*oy, &iy));
                 Py_END_ALLOW_THREADS
 #endif
@@ -636,7 +636,7 @@ static char doc_nrm2[] =
     "n         integer.  If n<0, the default value of n is used.\n"
     "          The default value is equal to\n"
     "          (len(x)>=offsetx+1) ? 1+(len(x)-offsetx-1)/incx : 0.\n\n"
-    "inc       positive integer\n\n" 
+    "inc       positive integer\n\n"
     "offset    nonnegative integer\n\n"
     "Returns 0 if n=0.";
 
@@ -646,7 +646,7 @@ static PyObject* nrm2(PyObject *self, PyObject *args, PyObject *kwrds)
     int n=-1, ix=1, ox=0;
     char *kwlist[] = {"x", "n", "inc", "offset", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|iii", kwlist, &x, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|iii", kwlist, &x,
         &n, &ix, &ox)) return NULL;
 
     if (!Matrix_Check(x)) err_mtrx("x");
@@ -658,7 +658,7 @@ static PyObject* nrm2(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            return Py_BuildValue("d", dnrm2_(&n, MAT_BUFD(x)+ox, &ix)); 
+            return Py_BuildValue("d", dnrm2_(&n, MAT_BUFD(x)+ox, &ix));
 
         case COMPLEX:
             return Py_BuildValue("d", dznrm2_(&n, MAT_BUFZ(x)+ox, &ix));
@@ -678,18 +678,18 @@ static char doc_asum[] =
     "          The default value is equal to\n"
     "          n = (len(x)>=offset+1) ? 1+(len(x)-offset-1)/inc : 0.\n"
     "\n"
-    "inc       positive integer\n\n" 
+    "inc       positive integer\n\n"
     "offset    nonnegative integer\n\n"
     "Returns 0 if n=0.";
 
 static PyObject* asum(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *x;
-    int n=-1, ix=1, ox=0; 
+    int n=-1, ix=1, ox=0;
     char *kwlist[] = {"x", "n", "inc", "offset", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|iii", kwlist, 
-        &x, &n, &ix, &ox)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|iii", kwlist,
+        &x, &n, &ix, &ox))
         return NULL;
 
     if (!Matrix_Check(x)) err_mtrx("x");
@@ -728,19 +728,19 @@ static char doc_iamax[] =
     "n         integer.  If n<0, the default value of n is used.\n"
     "          The default value is equal to\n"
     "          (len(x)>=offset+1) ? 1+(len(x)-offset-1)/inc : 0.\n\n"
-    "inc       positive integer\n\n" 
+    "inc       positive integer\n\n"
     "offset    nonnegative integer\n\n"
     "In the case of ties, the index of the first maximizer is \n"
-    "returned.  If n=0, iamax returns 0."; 
+    "returned.  If n=0, iamax returns 0.";
 
 static PyObject* iamax(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *x;
-    int n=-1, ix=1, ox=0; 
+    int n=-1, ix=1, ox=0;
     char *kwlist[] = {"x", "n", "inc", "offset", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|iii", kwlist, 
-        &x, &n, &ix, &ox)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|iii", kwlist,
+        &x, &n, &ix, &ox))
         return NULL;
 
     if (!Matrix_Check(x)) err_mtrx("x");
@@ -750,19 +750,12 @@ static PyObject* iamax(PyObject *self, PyObject *args, PyObject *kwrds)
     if (n == 0) return Py_BuildValue("i", 0);
     if (len(x) < ox + 1+(n-1)*ix) err_buf_len("x");
 
-    double val;
     switch (MAT_ID(x)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS
-      	    val = idamax_(&n, MAT_BUFD(x)+ox, &ix)-1;
-            Py_END_ALLOW_THREADS
-            return Py_BuildValue("i", val);
+            return Py_BuildValue("i", idamax_(&n, MAT_BUFD(x)+ox, &ix)-1);
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS
-	    val = izamax_(&n, MAT_BUFZ(x)+ox, &ix)-1;
-            Py_END_ALLOW_THREADS
-	    return Py_BuildValue("i", val);
+	    return Py_BuildValue("i", izamax_(&n, MAT_BUFZ(x)+ox, &ix)-1);
 
         default:
             err_invalid_id;
@@ -808,13 +801,13 @@ static PyObject* gemv(PyObject *self, PyObject *args, PyObject *kwrds)
     matrix *A, *x, *y;
     PyObject *ao=NULL, *bo=NULL;
     number a, b;
-    int m=-1, n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0; 
-    char trans='N'; 
+    int m=-1, n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0;
+    char trans='N';
     char *kwlist[] = {"A", "x", "y", "trans", "alpha", "beta", "m", "n",
         "ldA", "incx", "incy", "offsetA", "offsetx", "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiiii", 
-        kwlist, &A, &x, &y, &trans, &ao, &bo, &m, &n, &ldA, &ix, &iy, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiiii",
+        kwlist, &A, &x, &y, &trans, &ao, &bo, &m, &n, &ldA, &ix, &iy,
         &oA, &ox, &oy))
         return NULL;
 
@@ -824,7 +817,7 @@ static PyObject* gemv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (MAT_ID(A) != MAT_ID(x) || MAT_ID(A) != MAT_ID(y) ||
         MAT_ID(x) != MAT_ID(y)) err_conflicting_ids;
 
-    if (trans != 'N' && trans != 'T' && trans != 'C') 
+    if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N','T','C'");
 
     if (ix == 0) err_nz_int("incx");
@@ -835,62 +828,62 @@ static PyObject* gemv(PyObject *self, PyObject *args, PyObject *kwrds)
     if ((!m && trans == 'N') || (!n && (trans == 'T' || trans == 'C')))
         return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
-    if (ldA < MAX(1,m)) err_ld("ldA"); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
+    if (ldA < MAX(1,m)) err_ld("ldA");
 
     if (oA < 0) err_nn_int("offsetA");
     if (n > 0 && m > 0 && oA + (n-1)*ldA + m > len(A)) err_buf_len("A");
 
     if (ox < 0) err_nn_int("offsetx");
-    if ((trans == 'N' && n > 0 && ox + (n-1)*abs(ix) + 1 > len(x)) || 
-	((trans == 'T' || trans == 'C') && m > 0 && 
+    if ((trans == 'N' && n > 0 && ox + (n-1)*abs(ix) + 1 > len(x)) ||
+	((trans == 'T' || trans == 'C') && m > 0 &&
         ox + (m-1)*abs(ix) + 1 > len(x))) err_buf_len("x");
 
     if (oy < 0) err_nn_int("offsety");
-    if ((trans == 'N' && oy + (m-1)*abs(iy) + 1 > len(y)) || 
-        ((trans == 'T' || trans == 'C') && 
+    if ((trans == 'N' && oy + (m-1)*abs(iy) + 1 > len(y)) ||
+        ((trans == 'T' || trans == 'C') &&
         oy + (n-1)*abs(iy) + 1 > len(y))) err_buf_len("y");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(x))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(x)))
         err_type("beta");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d=1.0; 
+            if (!ao) a.d=1.0;
             if (!bo) b.d=0.0;
             if (trans == 'N' && n == 0)
-                Py_BEGIN_ALLOW_THREADS	    
+                Py_BEGIN_ALLOW_THREADS
                 dscal_(&m, &b.d, MAT_BUFD(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             else if ((trans == 'T' || trans == 'C') && m == 0)
-                Py_BEGIN_ALLOW_THREADS	    
+                Py_BEGIN_ALLOW_THREADS
                 dscal_(&n, &b.d, MAT_BUFD(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
-            else 
-                Py_BEGIN_ALLOW_THREADS	    
-                dgemv_(&trans, &m, &n, &a.d, MAT_BUFD(A)+oA, &ldA, 
+                Py_END_ALLOW_THREADS
+            else
+                Py_BEGIN_ALLOW_THREADS
+                dgemv_(&trans, &m, &n, &a.d, MAT_BUFD(A)+oA, &ldA,
                     MAT_BUFD(x)+ox, &ix, &b.d, MAT_BUFD(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z=1.0; 
+            if (!ao) a.z=1.0;
             if (!bo) b.z=0.0;
             if (trans == 'N' && n == 0)
-                Py_BEGIN_ALLOW_THREADS	    
+                Py_BEGIN_ALLOW_THREADS
                 zscal_(&m, &b.z, MAT_BUFZ(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             else if ((trans == 'T' || trans == 'C') && m == 0)
-                Py_BEGIN_ALLOW_THREADS	    
+                Py_BEGIN_ALLOW_THREADS
                 zscal_(&n, &b.z, MAT_BUFZ(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
-            else 
-                Py_BEGIN_ALLOW_THREADS	    
-                zgemv_(&trans, &m, &n, &a.z, MAT_BUFZ(A)+oA, &ldA, 
+                Py_END_ALLOW_THREADS
+            else
+                Py_BEGIN_ALLOW_THREADS
+                zgemv_(&trans, &m, &n, &a.z, MAT_BUFZ(A)+oA, &ldA,
                     MAT_BUFZ(x)+ox, &ix, &b.z, MAT_BUFZ(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -919,7 +912,7 @@ static char doc_gbmv[] =
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix.  Must have the same type as A.\n\n"
     "m         nonnegative integer\n\n"
-    "kl        nonnegative integer\n\n"  
+    "kl        nonnegative integer\n\n"
     "x         'd' or 'z' matrix.  Must have the same type as A.\n\n"
     "y         'd' or 'z' matrix.  Must have the same type as A.\n\n"
     "trans     'N', 'T' or 'C'\n\n"
@@ -945,12 +938,12 @@ static PyObject* gbmv(PyObject *self, PyObject *args, PyObject *kwrds)
     PyObject *ao=NULL, *bo=NULL;
     number a, b;
     int m, kl, ku=-1, n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0;
-    char trans='N'; 
+    char trans='N';
     char *kwlist[] = {"A", "m", "kl", "x", "y", "trans", "alpha", "beta",
-        "n", "ku", "ldA", "incx", "incy", "offsetA", "offsetx", "offsety", 
+        "n", "ku", "ldA", "incx", "incy", "offsetA", "offsetx", "offsety",
         NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OiiOO|cOOiiiiiiii", 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OiiOO|cOOiiiiiiii",
         kwlist, &A, &m, &kl, &x, &y, &trans, &ao, &bo, &n, &ku, &ldA, &ix,
         &iy, &oA, &ox, &oy))
         return NULL;
@@ -961,74 +954,74 @@ static PyObject* gbmv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (MAT_ID(A) != MAT_ID(x) || MAT_ID(A) != MAT_ID(y) ||
         MAT_ID(x) != MAT_ID(y)) err_conflicting_ids;
 
-    if (trans != 'N' && trans != 'T' && trans != 'C') 
+    if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N', 'T', 'C'");
 
     if (ix == 0) err_nz_int("incx");
     if (iy == 0) err_nz_int("incy");
     if (n < 0) n = A->ncols;
-    if ((!m && trans == 'N') || (!n && (trans == 'T' || trans == 'C'))) 
+    if ((!m && trans == 'N') || (!n && (trans == 'T' || trans == 'C')))
        return Py_BuildValue("");
 
-    if (kl < 0) err_nn_int("kl"); 
+    if (kl < 0) err_nn_int("kl");
     if (ku < 0) ku = A->nrows - 1 - kl;
-    if (ku < 0) err_nn_int("ku"); 
+    if (ku < 0) err_nn_int("ku");
 
-    if (ldA == 0) ldA = A->nrows; 
+    if (ldA == 0) ldA = A->nrows;
     if (ldA < kl+ku+1) err_ld("ldA");
 
     if (oA < 0) err_nn_int("offsetA");
-    if (m>0 && n>0 && oA + (n-1)*ldA + kl + ku + 1 > len(A)) 
+    if (m>0 && n>0 && oA + (n-1)*ldA + kl + ku + 1 > len(A))
         err_buf_len("A");
     if (ox < 0) err_nn_int("offsetx");
-    if ((trans == 'N' && n > 0 && ox + (n-1)*abs(ix) + 1 > len(x)) || 
-        ((trans == 'T' || trans == 'C') && m > 0 && 
+    if ((trans == 'N' && n > 0 && ox + (n-1)*abs(ix) + 1 > len(x)) ||
+        ((trans == 'T' || trans == 'C') && m > 0 &&
         ox + (m-1)*abs(ix) + 1 > len(x))) err_buf_len("x");
     if (oy < 0) err_nn_int("offsety");
-    if ((trans == 'N' && oy + (m-1)*abs(iy) + 1 > len(y)) || 
-	((trans == 'T' || trans == 'C') && 
+    if ((trans == 'N' && oy + (m-1)*abs(iy) + 1 > len(y)) ||
+	((trans == 'T' || trans == 'C') &&
         oy + (n-1)*abs(iy) + 1 > len(y))) err_buf_len("y");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(x))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(x)))
         err_type("beta");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d=1.0; 
+            if (!ao) a.d=1.0;
             if (!bo) b.d=0.0;
             if (trans == 'N' && n == 0)
-                Py_BEGIN_ALLOW_THREADS	    
+                Py_BEGIN_ALLOW_THREADS
                 dscal_(&m, &b.d, MAT_BUFD(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             else if ((trans == 'T' || trans == 'C') && m == 0)
-                Py_BEGIN_ALLOW_THREADS	    
+                Py_BEGIN_ALLOW_THREADS
                 dscal_(&n, &b.d, MAT_BUFD(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
-            else 
-                Py_BEGIN_ALLOW_THREADS	    
-                dgbmv_(&trans, &m, &n, &kl, &ku, &a.d, MAT_BUFD(A)+oA, 
+                Py_END_ALLOW_THREADS
+            else
+                Py_BEGIN_ALLOW_THREADS
+                dgbmv_(&trans, &m, &n, &kl, &ku, &a.d, MAT_BUFD(A)+oA,
                     &ldA, MAT_BUFD(x)+ox, &ix, &b.d, MAT_BUFD(y)+oy, &iy);
-	        Py_END_ALLOW_THREADS	    
+	        Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z=1.0; 
+            if (!ao) a.z=1.0;
             if (!bo) b.z=0.0;
             if (trans == 'N' && n == 0)
-                Py_BEGIN_ALLOW_THREADS	    
+                Py_BEGIN_ALLOW_THREADS
                 zscal_(&m, &b.z, MAT_BUFZ(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             else if ((trans == 'T' || trans == 'C') && m == 0)
-                Py_BEGIN_ALLOW_THREADS	    
+                Py_BEGIN_ALLOW_THREADS
                 zscal_(&n, &b.z, MAT_BUFZ(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
-            else 
-                Py_BEGIN_ALLOW_THREADS	    
-                zgbmv_(&trans, &m, &n, &kl, &ku, &a.z, MAT_BUFZ(A)+oA, 
+                Py_END_ALLOW_THREADS
+            else
+                Py_BEGIN_ALLOW_THREADS
+                zgbmv_(&trans, &m, &n, &kl, &ku, &a.z, MAT_BUFZ(A)+oA,
                     &ldA, MAT_BUFZ(x)+ox, &ix, &b.z, MAT_BUFZ(y)+oy, &iy);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1070,13 +1063,13 @@ static PyObject* symv(PyObject *self, PyObject *args, PyObject *kwrds)
     matrix *A, *x, *y;
     PyObject *ao=NULL, *bo=NULL;
     number a, b;
-    int n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0; 
-    char uplo='L'; 
-    char *kwlist[] = {"A", "x", "y", "uplo", "alpha", "beta", "n", 
+    int n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0;
+    char uplo='L';
+    char *kwlist[] = {"A", "x", "y", "uplo", "alpha", "beta", "n",
         "ldA", "incx", "incy", "offsetA", "offsetx", "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiii", 
-        kwlist, &A, &x, &y, &uplo, &ao, &bo, &n, &ldA, &ix, &iy, &oA, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiii",
+        kwlist, &A, &x, &y, &uplo, &ao, &bo, &n, &ldA, &ix, &iy, &oA,
         &ox, &oy))
         return NULL;
 
@@ -1091,7 +1084,7 @@ static PyObject* symv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ix == 0) err_nz_int("incx");
     if (iy == 0) err_nz_int("incy");
 
-    if (n < 0){ 
+    if (n < 0){
         if (A->nrows != A->ncols){
             PyErr_SetString(PyExc_ValueError, "A is not square");
             return NULL;
@@ -1100,7 +1093,7 @@ static PyObject* symv(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (n == 0) return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1,n)) err_ld("ldA");
     if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
@@ -1109,19 +1102,19 @@ static PyObject* symv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oy < 0) err_nn_int("offsety");
     if (oy + (n-1)*abs(iy) + 1 > len(y)) err_buf_len("y");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(x))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(x)))
         err_type("beta");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d=1.0; 
+            if (!ao) a.d=1.0;
             if (!bo) b.d=0.0;
-            Py_BEGIN_ALLOW_THREADS	    
-            dsymv_(&uplo, &n, &a.d, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dsymv_(&uplo, &n, &a.d, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(x)+ox, &ix, &b.d, MAT_BUFD(y)+oy, &iy);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1168,13 +1161,13 @@ static PyObject* hemv(PyObject *self, PyObject *args, PyObject *kwrds)
     matrix *A, *x, *y;
     PyObject *ao=NULL, *bo=NULL;
     number a, b;
-    int n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0; 
-    char uplo='L'; 
-    char *kwlist[] = {"A", "x", "y", "uplo", "alpha", "beta", "n", 
+    int n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0;
+    char uplo='L';
+    char *kwlist[] = {"A", "x", "y", "uplo", "alpha", "beta", "n",
         "ldA", "incx", "incy", "offsetA", "offsetx", "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiii", 
-        kwlist, &A, &x, &y, &uplo, &ao, &bo, &n, &ldA, &ix, &iy, &oA, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiii",
+        kwlist, &A, &x, &y, &uplo, &ao, &bo, &n, &ldA, &ix, &iy, &oA,
         &ox, &oy))
         return NULL;
 
@@ -1189,16 +1182,16 @@ static PyObject* hemv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ix == 0) err_nz_int("incx");
     if (iy == 0) err_nz_int("incy");
 
-    if (n < 0){ 
+    if (n < 0){
         if (A->nrows != A->ncols){
             PyErr_SetString(PyExc_ValueError, "A is not square");
             return NULL;
         }
         n = A->nrows;
     }
-    if (n == 0) return Py_BuildValue(""); 
+    if (n == 0) return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1,n)) err_ld("ldA");
     if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
@@ -1207,28 +1200,28 @@ static PyObject* hemv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oy < 0) err_nn_int("offsety");
     if (oy + (n-1)*abs(iy) + 1 > len(y)) err_buf_len("y");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(x))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(x)))
         err_type("beta");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d=1.0; 
+            if (!ao) a.d=1.0;
             if (!bo) b.d=0.0;
-            Py_BEGIN_ALLOW_THREADS	    
-            dsymv_(&uplo, &n, &a.d, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dsymv_(&uplo, &n, &a.d, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(x)+ox, &ix, &b.d, MAT_BUFD(y)+oy, &iy);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z=1.0; 
+            if (!ao) a.z=1.0;
             if (!bo) b.z=0.0;
-            Py_BEGIN_ALLOW_THREADS	    
-            zhemv_(&uplo, &n, &a.z, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            zhemv_(&uplo, &n, &a.z, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(x)+ox, &ix, &b.z, MAT_BUFZ(y)+oy, &iy);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1270,13 +1263,13 @@ static PyObject* sbmv(PyObject *self, PyObject *args, PyObject *kwrds)
     matrix *A, *x, *y;
     PyObject *ao=NULL, *bo=NULL;
     number a, b;
-    int n=-1, k=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0; 
-    char uplo='L'; 
+    int n=-1, k=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0;
+    char uplo='L';
     char *kwlist[] = {"A", "x", "y", "uplo", "alpha", "beta", "n", "k",
         "ldA", "incx", "incy", "offsetA", "offsetx", "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiiii", 
-        kwlist, &A, &x, &y, &uplo, &ao, &bo, &n, &k, &ldA, &ix, &iy, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiiii",
+        kwlist, &A, &x, &y, &uplo, &ao, &bo, &n, &k, &ldA, &ix, &iy,
         &oA, &ox, &oy))
         return NULL;
 
@@ -1291,7 +1284,7 @@ static PyObject* sbmv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ix == 0) err_nz_int("incx");
     if (iy == 0) err_nz_int("incy");
 
-    if (n < 0) n = A->ncols; 
+    if (n < 0) n = A->ncols;
     if (n == 0) return Py_BuildValue("");
 
     if (k < 0) k = MAX(0, A->nrows-1);
@@ -1304,20 +1297,20 @@ static PyObject* sbmv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ox + (n-1)*abs(ix) + 1 > len(x)) err_buf_len("x");
     if (oy < 0) err_nn_int("offsety");
     if (oy + (n-1)*abs(iy) + 1 > len(y)) err_buf_len("y");
-  
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(x))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(x)))
         err_type("beta");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d=1.0; 
+            if (!ao) a.d=1.0;
             if (!bo) b.d=0.0;
-            Py_BEGIN_ALLOW_THREADS	    
-            dsbmv_(&uplo, &n, &k, &a.d, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dsbmv_(&uplo, &n, &k, &a.d, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(x)+ox, &ix, &b.d, MAT_BUFD(y)+oy, &iy);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1362,13 +1355,13 @@ static PyObject* hbmv(PyObject *self, PyObject *args, PyObject *kwrds)
     matrix *A, *x, *y;
     PyObject *ao=NULL, *bo=NULL;
     number a, b;
-    int n=-1, k=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0; 
-    char uplo='L'; 
+    int n=-1, k=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0;
+    char uplo='L';
     char *kwlist[] = {"A", "x", "y", "uplo", "alpha", "beta", "n", "k",
         "ldA", "incx", "incy", "offsetA", "offsetx", "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiiii", 
-        kwlist, &A, &x, &y, &uplo, &ao, &bo, &n, &k, &ldA, &ix, &iy, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOOiiiiiiii",
+        kwlist, &A, &x, &y, &uplo, &ao, &bo, &n, &k, &ldA, &ix, &iy,
         &oA, &ox, &oy))
         return NULL;
 
@@ -1383,7 +1376,7 @@ static PyObject* hbmv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ix == 0) err_nz_int("incx");
     if (iy == 0) err_nz_int("incy");
 
-    if (n < 0) n = A->ncols; 
+    if (n < 0) n = A->ncols;
     if (n == 0) return Py_BuildValue("");
 
     if (k < 0) k = MAX(0, A->nrows-1);
@@ -1396,29 +1389,29 @@ static PyObject* hbmv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ox + (n-1)*abs(ix) + 1 > len(x)) err_buf_len("x");
     if (oy < 0) err_nn_int("offsety");
     if (oy + (n-1)*abs(iy) + 1 > len(y)) err_buf_len("y");
-  
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(x))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(x)))
         err_type("beta");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d=1.0; 
+            if (!ao) a.d=1.0;
             if (!bo) b.d=0.0;
-            Py_BEGIN_ALLOW_THREADS	    
-            dsbmv_(&uplo, &n, &k, &a.d, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dsbmv_(&uplo, &n, &k, &a.d, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(x)+ox, &ix, &b.d, MAT_BUFD(y)+oy, &iy);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z=1.0; 
+            if (!ao) a.z=1.0;
             if (!bo) b.z=0.0;
-            Py_BEGIN_ALLOW_THREADS	    
-            zhbmv_(&uplo, &n, &k, &a.z, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            zhbmv_(&uplo, &n, &k, &a.z, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(x)+ox, &ix, &b.z, MAT_BUFZ(y)+oy, &iy);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1435,8 +1428,8 @@ static char doc_trmv[] =
     "     ldA=max(1,A.size[0]), incx=1, offsetA=0, offsetx=0)\n\n"
     "PURPOSE\n"
     "If trans is 'N', computes x := A*x.\n"
-    "If trans is 'T', computes x := A^T*x.\n" 
-    "If trans is 'C', computes x := A^H*x.\n" 
+    "If trans is 'T', computes x := A^T*x.\n"
+    "If trans is 'C', computes x := A^H*x.\n"
     "A is triangular of order n.\n\n"
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix\n\n"
@@ -1455,13 +1448,13 @@ static char doc_trmv[] =
 
 static PyObject* trmv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *x; 
+    matrix *A, *x;
     int n=-1, ldA=0, ix=1, oA=0, ox=0;
-    char uplo='L', trans='N', diag='N'; 
-    char *kwlist[] = {"A", "x", "uplo", "trans", "diag", "n", "ldA", 
+    char uplo='L', trans='N', diag='N';
+    char *kwlist[] = {"A", "x", "uplo", "trans", "diag", "n", "ldA",
         "incx", "offsetA", "offsetx", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiii", 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiii",
         kwlist, &A, &x, &uplo, &trans, &diag, &n, &ldA, &ix, &oA, &ox))
         return NULL;
 
@@ -1469,14 +1462,14 @@ static PyObject* trmv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(x)) err_mtrx("x");
     if (MAT_ID(A) != MAT_ID(x)) err_conflicting_ids;
 
-    if (trans != 'N' && trans != 'T' && trans != 'C') 
+    if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N', 'T', 'C'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (diag != 'N' && diag != 'U') err_char("diag", "'U', 'N'");
 
     if (ix == 0) err_nz_int("incx");
 
-    if (n < 0){ 
+    if (n < 0){
         if (A->nrows != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A is not square");
             return NULL;
@@ -1485,8 +1478,8 @@ static PyObject* trmv(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (n == 0) return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
-    if (ldA < MAX(1,n)) err_ld("ldA"); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
+    if (ldA < MAX(1,n)) err_ld("ldA");
     if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
     if (ox < 0) err_nn_int("offsetx");
@@ -1494,17 +1487,17 @@ static PyObject* trmv(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dtrmv_(&uplo, &trans, &diag, &n, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dtrmv_(&uplo, &trans, &diag, &n, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(x)+ox, &ix);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            ztrmv_(&uplo, &trans, &diag, &n, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            ztrmv_(&uplo, &trans, &diag, &n, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(x)+ox, &ix);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1543,14 +1536,14 @@ static char doc_tbmv[] =
 
 static PyObject* tbmv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *x; 
-    int n=-1, k=-1, ldA=0, ix=1, oA=0, ox=0; 
-    char uplo='L', trans='N', diag='N'; 
-    char *kwlist[] = {"A", "x", "uplo", "trans", "diag", "n", "k", 
+    matrix *A, *x;
+    int n=-1, k=-1, ldA=0, ix=1, oA=0, ox=0;
+    char uplo='L', trans='N', diag='N';
+    char *kwlist[] = {"A", "x", "uplo", "trans", "diag", "n", "k",
         "ldA", "incx", "offsetA", "offsetx", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiiii", 
-        kwlist, &A, &x, &uplo, &trans, &diag, &n, &k, &ldA, &ix, &oA, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiiii",
+        kwlist, &A, &x, &uplo, &trans, &diag, &n, &k, &ldA, &ix, &oA,
         &ox))
         return NULL;
 
@@ -1558,7 +1551,7 @@ static PyObject* tbmv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(x)) err_mtrx("x");
     if (MAT_ID(A) != MAT_ID(x)) err_conflicting_ids;
 
-    if (trans != 'N' && trans != 'T' && trans != 'C') 
+    if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N', 'T', 'C'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (diag != 'N' && diag != 'U') err_char("diag", "'U', 'N'");
@@ -1569,7 +1562,7 @@ static PyObject* tbmv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (n == 0) return Py_BuildValue("");
     if (k < 0) k = MAX(0,A->nrows-1);
 
-    if (ldA == 0) ldA = A->nrows; 
+    if (ldA == 0) ldA = A->nrows;
     if (ldA < k+1)  err_ld("ldA");
 
     if (oA < 0) err_nn_int("offsetA");
@@ -1579,17 +1572,17 @@ static PyObject* tbmv(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dtbmv_(&uplo, &trans, &diag, &n, &k, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dtbmv_(&uplo, &trans, &diag, &n, &k, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(x)+ox, &ix);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            ztbmv_(&uplo, &trans, &diag, &n, &k, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            ztbmv_(&uplo, &trans, &diag, &n, &k, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(x)+ox, &ix);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1623,18 +1616,18 @@ static char doc_trsv[] =
     "ldA       nonnegative integer.  ldA >= max(1,n).\n"
     "          If zero, the default value is used.\n\n"
     "incx      nonzero integer\n\n"
-    "offsetA   nonnegative integer\n\n"  
+    "offsetA   nonnegative integer\n\n"
     "offsetx   nonnegative integer";
 
 static PyObject* trsv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *x; 
+    matrix *A, *x;
     int n=-1, ldA=0, ix=1, oA=0, ox=0;
-    char uplo='L', trans='N', diag='N'; 
-    char *kwlist[] = {"A", "x", "uplo", "trans", "diag", "n", "ldA", 
+    char uplo='L', trans='N', diag='N';
+    char *kwlist[] = {"A", "x", "uplo", "trans", "diag", "n", "ldA",
         "incx", "offsetA", "offsetx", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiii", 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiii",
         kwlist, &A, &x, &uplo, &trans, &diag, &n, &ldA, &ix, &oA, &ox))
         return NULL;
 
@@ -1642,14 +1635,14 @@ static PyObject* trsv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(x)) err_mtrx("x");
     if (MAT_ID(A) != MAT_ID(x)) err_conflicting_ids;
 
-    if (trans != 'N' && trans != 'T' && trans != 'C') 
+    if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N', 'T', 'C'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (diag != 'N' && diag != 'U') err_char("diag", "'N', 'U'");
 
     if (ix == 0) err_nz_int("incx");
 
-    if (n < 0){ 
+    if (n < 0){
         if (A->nrows != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A is not square");
             return NULL;
@@ -1658,27 +1651,27 @@ static PyObject* trsv(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (n == 0) return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1,n)) err_ld("ldA");
 
-    if (oA < 0) err_nn_int("offsetA"); 
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
     if (ox < 0) err_nn_int("offsetx");
     if (ox + (n-1)*abs(ix) + 1 > len(x)) err_buf_len("x");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dtrsv_(&uplo, &trans, &diag, &n, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dtrsv_(&uplo, &trans, &diag, &n, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(x)+ox, &ix);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            ztrsv_(&uplo, &trans, &diag, &n, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            ztrsv_(&uplo, &trans, &diag, &n, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(x)+ox, &ix);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1717,14 +1710,14 @@ static char doc_tbsv[] =
 
 static PyObject* tbsv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *x; 
-    int n=-1, k=-1, ldA=0, ix=1, oA=0, ox=0; 
-    char uplo='L', trans='N', diag='N'; 
-    char *kwlist[] = {"A", "x", "uplo", "trans", "diag", "n", "k", 
+    matrix *A, *x;
+    int n=-1, k=-1, ldA=0, ix=1, oA=0, ox=0;
+    char uplo='L', trans='N', diag='N';
+    char *kwlist[] = {"A", "x", "uplo", "trans", "diag", "n", "k",
         "ldA", "incx", "offsetA", "offsetx", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiiii", 
-        kwlist, &A, &x, &uplo, &trans, &diag, &n, &k, &ldA, &ix, &oA, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiiii",
+        kwlist, &A, &x, &uplo, &trans, &diag, &n, &k, &ldA, &ix, &oA,
         &ox))
         return NULL;
 
@@ -1732,7 +1725,7 @@ static PyObject* tbsv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(x)) err_mtrx("x");
     if (MAT_ID(A) != MAT_ID(x)) err_conflicting_ids;
 
-    if (trans != 'N' && trans != 'T' && trans != 'C') 
+    if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N', 'T', 'C'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (diag != 'N' && diag != 'U') err_char("diag", "'N', 'U'");
@@ -1743,27 +1736,27 @@ static PyObject* tbsv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (n == 0) return Py_BuildValue("");
     if (k < 0) k = MAX(0, A->nrows-1);
 
-    if (ldA == 0) ldA = A->nrows; 
+    if (ldA == 0) ldA = A->nrows;
     if (ldA < k+1) err_ld("ldA");
 
     if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + k + 1 > len(A)) err_buf_len("A");
-    if (ox < 0) err_nn_int("offsetx"); 
+    if (ox < 0) err_nn_int("offsetx");
     if (ox + (n-1)*abs(ix) + 1 > len(x)) err_buf_len("x");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dtbsv_(&uplo, &trans, &diag, &n, &k, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dtbsv_(&uplo, &trans, &diag, &n, &k, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(x)+ox, &ix);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            ztbsv_(&uplo, &trans, &diag, &n, &k, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            ztbsv_(&uplo, &trans, &diag, &n, &k, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(x)+ox, &ix);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1799,14 +1792,14 @@ static char doc_ger[] =
 
 static PyObject* ger(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *x, *y; 
+    matrix *A, *x, *y;
     PyObject *ao=NULL;
     number a;
-    int m=-1, n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0; 
+    int m=-1, n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0;
     char *kwlist[] = {"x", "y", "A", "alpha", "m", "n", "incx", "incy",
         "ldA", "offsetx", "offsety", "offsetA", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|Oiiiiiiii", 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|Oiiiiiiii",
         kwlist, &x, &y, &A, &ao, &m, &n, &ix, &iy, &ldA, &ox, &oy, &oA))
         return NULL;
 
@@ -1823,7 +1816,7 @@ static PyObject* ger(PyObject *self, PyObject *args, PyObject *kwrds)
     if (n < 0) n = A->ncols;
     if (m == 0 || n == 0) return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1,m)) err_ld("ldA");
 
     if (oA < 0) err_nn_int("offsetA");
@@ -1833,24 +1826,24 @@ static PyObject* ger(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oy < 0) err_nn_int("offsety");
     if (oy + (n-1)*abs(iy) + 1 > len(y)) err_buf_len("y");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            dger_(&m, &n, &a.d, MAT_BUFD(x)+ox, &ix, MAT_BUFD(y)+oy, 
+            if (!ao) a.d = 1.0;
+            Py_BEGIN_ALLOW_THREADS
+            dger_(&m, &n, &a.d, MAT_BUFD(x)+ox, &ix, MAT_BUFD(y)+oy,
                 &iy, MAT_BUFD(A)+oA, &ldA);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z = 1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
+            if (!ao) a.z = 1.0;
+            Py_BEGIN_ALLOW_THREADS
             zgerc_(&m, &n, &a.z, MAT_BUFZ(x)+ox, &ix, MAT_BUFZ(y)+oy, &iy,
                 MAT_BUFZ(A)+oA, &ldA);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1886,14 +1879,14 @@ static char doc_geru[] =
 
 static PyObject* geru(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *x, *y; 
+    matrix *A, *x, *y;
     PyObject *ao=NULL;
     number a;
-    int m=-1, n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0; 
+    int m=-1, n=-1, ldA=0, ix=1, iy=1, oA=0, ox=0, oy=0;
     char *kwlist[] = {"x", "y", "A", "alpha", "m", "n", "incx", "incy",
         "ldA", "offsetx", "offsety", "offsetA", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|Oiiiiiiii", 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|Oiiiiiiii",
         kwlist, &x, &y, &A, &ao, &m, &n, &ix, &iy, &ldA, &ox, &oy, &oA))
         return NULL;
 
@@ -1910,7 +1903,7 @@ static PyObject* geru(PyObject *self, PyObject *args, PyObject *kwrds)
     if (n < 0) n = A->ncols;
     if (m == 0 || n == 0) return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1,m)) err_ld("ldA");
 
     if (oA < 0) err_nn_int("offsetA");
@@ -1920,24 +1913,24 @@ static PyObject* geru(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oy < 0) err_nn_int("offsety");
     if (oy + (n-1)*abs(iy) + 1 > len(y)) err_buf_len("y");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            dger_(&m, &n, &a.d, MAT_BUFD(x)+ox, &ix, MAT_BUFD(y)+oy, &iy, 
+            if (!ao) a.d = 1.0;
+            Py_BEGIN_ALLOW_THREADS
+            dger_(&m, &n, &a.d, MAT_BUFD(x)+ox, &ix, MAT_BUFD(y)+oy, &iy,
                 MAT_BUFD(A)+oA, &ldA);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z = 1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            zgeru_(&m, &n, &a.z, MAT_BUFZ(x)+ox, &ix, MAT_BUFZ(y)+oy, 
+            if (!ao) a.z = 1.0;
+            Py_BEGIN_ALLOW_THREADS
+            zgeru_(&m, &n, &a.z, MAT_BUFZ(x)+ox, &ix, MAT_BUFZ(y)+oy,
                 &iy, MAT_BUFZ(A)+oA, &ldA);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1970,12 +1963,12 @@ static char doc_syr[] =
 
 static PyObject* syr(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *x; 
+    matrix *A, *x;
     PyObject *ao=NULL;
-    number a; 
-    int n=-1, ldA=0, ix=1, oA=0, ox=0; 
-    char uplo='L'; 
-    char *kwlist[] = {"x", "A", "uplo", "alpha", "n", "incx", "ldA", 
+    number a;
+    int n=-1, ldA=0, ix=1, oA=0, ox=0;
+    char uplo='L';
+    char *kwlist[] = {"x", "A", "uplo", "alpha", "n", "incx", "ldA",
         "offsetx", "offsetA", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cOiiiii", kwlist,
@@ -1988,7 +1981,7 @@ static PyObject* syr(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (ix == 0)  err_nz_int("incx");
 
-    if (n < 0){ 
+    if (n < 0){
         if (A->nrows != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A is not square");
             return NULL;
@@ -1997,10 +1990,10 @@ static PyObject* syr(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (n == 0) return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
-    if (ldA < MAX(1,n)) err_ld("ldA"); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
+    if (ldA < MAX(1,n)) err_ld("ldA");
 
-    if (oA < 0) err_nn_int("offsetA"); 
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
     if (ox < 0) err_nn_int("offsetx");
     if (ox + (n-1)*abs(ix) + 1 > len(x)) err_buf_len("x");
@@ -2008,14 +2001,14 @@ static PyObject* syr(PyObject *self, PyObject *args, PyObject *kwrds)
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
 
     if (ao && number_from_pyobject(ao, &a, DOUBLE)) err_type("alpha");
-    if (!ao) a.d = 1.0; 
+    if (!ao) a.d = 1.0;
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsyr_(&uplo, &n, &a.d, MAT_BUFD(x)+ox, &ix, MAT_BUFD(A)+oA,
                 &ldA);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -2048,15 +2041,15 @@ static char doc_her[] =
 
 static PyObject* her(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *x; 
+    matrix *A, *x;
     PyObject *ao=NULL;
-    number a; 
-    int n=-1, ldA=0, ix=1, oA=0, ox=0; 
-    char uplo='L'; 
-    char *kwlist[] = {"x", "A", "uplo", "alpha", "n", "incx", "ldA", 
+    number a;
+    int n=-1, ldA=0, ix=1, oA=0, ox=0;
+    char uplo='L';
+    char *kwlist[] = {"x", "A", "uplo", "alpha", "n", "incx", "ldA",
         "offsetx", "offsetA", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cOiiiii", 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cOiiiii",
         kwlist, &x, &A, &uplo, &ao, &n, &ix, &ldA, &ox, &oA))
         return NULL;
 
@@ -2066,7 +2059,7 @@ static PyObject* her(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (ix == 0)  err_nz_int("incx");
 
-    if (n < 0){ 
+    if (n < 0){
         if (A->nrows != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A is not square");
             return NULL;
@@ -2075,10 +2068,10 @@ static PyObject* her(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (n == 0) return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
-    if (ldA < MAX(1,n)) err_ld("ldA"); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
+    if (ldA < MAX(1,n)) err_ld("ldA");
 
-    if (oA < 0) err_nn_int("offsetA"); 
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
     if (ox < 0) err_nn_int("offsetx");
     if (ox + (n-1)*abs(ix) + 1 > len(x)) err_buf_len("x");
@@ -2086,21 +2079,21 @@ static PyObject* her(PyObject *self, PyObject *args, PyObject *kwrds)
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
 
     if (ao && number_from_pyobject(ao, &a, DOUBLE)) err_type("alpha");
-    if (!ao) a.d = 1.0; 
+    if (!ao) a.d = 1.0;
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsyr_(&uplo, &n, &a.d, MAT_BUFD(x)+ox, &ix, MAT_BUFD(A)+oA,
                 &ldA);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zher_(&uplo, &n, &a.d, MAT_BUFZ(x)+ox, &ix, MAT_BUFZ(A)+oA,
                 &ldA);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -2119,7 +2112,7 @@ static char doc_syr2[] =
     "PURPOSE\n"
     "Computes A := A + alpha*(x*y^T + y*x^T) with A real symmetric.\n\n"
     "ARGUMENTS\n"
-    "x         'd' matrix\n\n" 
+    "x         'd' matrix\n\n"
     "y         'd' matrix\n\n"
     "A         'd' matrix\n\n"
     "uplo      'L' or 'U'\n\n"
@@ -2135,16 +2128,16 @@ static char doc_syr2[] =
 
 static PyObject* syr2(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *x, *y; 
+    matrix *A, *x, *y;
     PyObject *ao=NULL;
     number a;
-    int n=-1, ldA=0, ix=1, iy=1, ox=0, oy=0, oA=0; 
-    char uplo='L'; 
-    char *kwlist[] = {"x", "y", "A", "uplo", "alpha", "n", "incx", 
+    int n=-1, ldA=0, ix=1, iy=1, ox=0, oy=0, oA=0;
+    char uplo='L';
+    char *kwlist[] = {"x", "y", "A", "uplo", "alpha", "n", "incx",
         "incy", "ldA", "offsetx", "offsety", "offsetA", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOiiiiiii", 
-        kwlist, &x, &y, &A, &uplo, &ao, &n, &ix, &iy, &ldA, &ox, &oy, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOiiiiiii",
+        kwlist, &x, &y, &A, &uplo, &ao, &n, &ix, &iy, &ldA, &ox, &oy,
         &oA))
         return NULL;
 
@@ -2157,7 +2150,7 @@ static PyObject* syr2(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ix == 0) err_nz_int("incx");
     if (iy == 0) err_nz_int("incy");
 
-    if (n < 0){ 
+    if (n < 0){
         if (A->nrows != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A is not square");
             return NULL;
@@ -2166,8 +2159,8 @@ static PyObject* syr2(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (n == 0) return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
-    if (ldA < MAX(1,n)) err_ld("ldA"); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
+    if (ldA < MAX(1,n)) err_ld("ldA");
     if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
     if (ox < 0) err_nn_int("offsetx");
@@ -2177,16 +2170,16 @@ static PyObject* syr2(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L','U'");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
+            if (!ao) a.d = 1.0;
+            Py_BEGIN_ALLOW_THREADS
             dsyr2_(&uplo, &n, &a.d, MAT_BUFD(x)+ox, &ix, MAT_BUFD(y)+oy,
                 &iy, MAT_BUFD(A)+oA, &ldA);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -2205,8 +2198,8 @@ static char doc_her2[] =
     "Computes A := A + alpha*x*y^H + conj(alpha)*y*x^H with A \n"
     "real symmetric or complex Hermitian of order n.\n\n"
     "ARGUMENTS\n"
-    "x         'd' or 'z' matrix\n\n" 
-    "y         'd' or 'z' matrix.  Must have the same type as x.\n\n" 
+    "x         'd' or 'z' matrix\n\n"
+    "y         'd' or 'z' matrix.  Must have the same type as x.\n\n"
     "A         'd' or 'z' matrix.  Must have the same type as x.\n\n"
     "uplo      'L' or 'U'\n\n"
     "alpha     number (int, float or complex).  Complex alpha is only\n"
@@ -2222,16 +2215,16 @@ static char doc_her2[] =
 
 static PyObject* her2(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *x, *y; 
+    matrix *A, *x, *y;
     PyObject *ao=NULL;
     number a;
-    int n=-1, ldA=0, ix=1, iy=1, ox=0, oy=0, oA=0; 
-    char uplo='L'; 
-    char *kwlist[] = {"x", "y", "A", "uplo", "alpha", "n", "incx", 
+    int n=-1, ldA=0, ix=1, iy=1, ox=0, oy=0, oA=0;
+    char uplo='L';
+    char *kwlist[] = {"x", "y", "A", "uplo", "alpha", "n", "incx",
         "incy", "ldA", "offsetx", "offsety", "offsetA", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOiiiiiii", 
-        kwlist, &x, &y, &A, &uplo, &ao, &n, &ix, &iy, &ldA, &ox, &oy, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cOiiiiiii",
+        kwlist, &x, &y, &A, &uplo, &ao, &n, &ix, &iy, &ldA, &ox, &oy,
         &oA))
         return NULL;
 
@@ -2244,7 +2237,7 @@ static PyObject* her2(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ix == 0) err_nz_int("incx");
     if (iy == 0) err_nz_int("incy");
 
-    if (n < 0){ 
+    if (n < 0){
         if (A->nrows != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A is not square");
             return NULL;
@@ -2253,8 +2246,8 @@ static PyObject* her2(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (n == 0) return Py_BuildValue("");
 
-    if (ldA == 0) ldA = MAX(1,A->nrows); 
-    if (ldA < MAX(1,n)) err_ld("ldA"); 
+    if (ldA == 0) ldA = MAX(1,A->nrows);
+    if (ldA < MAX(1,n)) err_ld("ldA");
     if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
     if (ox < 0) err_nn_int("offsetx");
@@ -2264,24 +2257,24 @@ static PyObject* her2(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L','U'");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(x))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(x)))
         err_type("alpha");
 
     switch (MAT_ID(x)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
+            if (!ao) a.d = 1.0;
+            Py_BEGIN_ALLOW_THREADS
             dsyr2_(&uplo, &n, &a.d, MAT_BUFD(x)+ox, &ix, MAT_BUFD(y)+oy,
                 &iy, MAT_BUFD(A)+oA, &ldA);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z = 1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
+            if (!ao) a.z = 1.0;
+            Py_BEGIN_ALLOW_THREADS
             zher2_(&uplo, &n, &a.z, MAT_BUFZ(x)+ox, &ix, MAT_BUFZ(y)+oy,
                 &iy, MAT_BUFZ(A)+oA, &ldA);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -2298,7 +2291,7 @@ static char doc_gemm[] =
     "     m=None, n=None, k=None, ldA=max(1,A.size[0]), \n"
     "     ldB=max(1,B.size[0]), ldC=max(1,C.size[0]), offsetA=0, \n"
     "     offsetB=0, offsetC=0) \n\n"
-    "PURPOSE\n"   
+    "PURPOSE\n"
     "Computes \n"
     "C := alpha*A*B + beta*C     if transA = 'N' and transB = 'N'.\n"
     "C := alpha*A^T*B + beta*C   if transA = 'T' and transB = 'N'.\n"
@@ -2312,7 +2305,7 @@ static char doc_gemm[] =
     "The number of rows of the matrix product is m.  The number of \n"
     "columns is n.  The inner dimension is k.  If k=0, this reduces \n"
     "to C := beta*C.\n\n"
-    "ARGUMENTS\n\n" 
+    "ARGUMENTS\n\n"
     "A         'd' or 'z' matrix\n\n"
     "B         'd' or 'z' matrix.  Must have the same type as A.\n\n"
     "C         'd' or 'z' matrix.  Must have the same type as A.\n\n"
@@ -2350,12 +2343,12 @@ static PyObject* gemm(PyObject *self, PyObject *args, PyObject *kwrds)
     number a, b;
     int m=-1, n=-1, k=-1, ldA=0, ldB=0, ldC=0, oA=0, oB=0, oC=0;
     char transA='N', transB='N';
-    char *kwlist[] = {"A", "B", "C", "transA", "transB", "alpha", 
-        "beta", "m", "n", "k", "ldA", "ldB", "ldC", "offsetA", 
+    char *kwlist[] = {"A", "B", "C", "transA", "transB", "alpha",
+        "beta", "m", "n", "k", "ldA", "ldB", "ldC", "offsetA",
         "offsetB", "offsetC", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOiiiiiiiii", 
-        kwlist, &A, &B, &C, &transA, &transB, &ao, &bo, &m, &n, &k, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOiiiiiiiii",
+        kwlist, &A, &B, &C, &transA, &transB, &ao, &bo, &m, &n, &k,
         &ldA, &ldB, &ldC, &oA, &oB, &oC))
         return NULL;
 
@@ -2365,14 +2358,14 @@ static PyObject* gemm(PyObject *self, PyObject *args, PyObject *kwrds)
     if (MAT_ID(A) != MAT_ID(B) || MAT_ID(A) != MAT_ID(C) ||
         MAT_ID(B) != MAT_ID(C)) err_conflicting_ids;
 
-    if (transA != 'N' && transA != 'T' && transA != 'C') 
+    if (transA != 'N' && transA != 'T' && transA != 'C')
         err_char("transA", "'N', 'T', 'C'");
     if (transB != 'N' && transB != 'T' && transB != 'C')
         err_char("transB", "'N', 'T', 'C'");
 
     if (m < 0) m = (transA == 'N') ? A->nrows : A->ncols;
     if (n < 0) n = (transB == 'N') ? B->ncols : B->nrows;
-    if (k < 0){ 
+    if (k < 0){
         k = (transA == 'N') ? A->ncols : A->nrows;
         if (k != ((transB == 'N') ? B->nrows : B->ncols)){
              PyErr_SetString(PyExc_TypeError, "dimensions of A and B "
@@ -2391,39 +2384,39 @@ static PyObject* gemm(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (oA < 0) err_nn_int("offsetA");
     if (k > 0 && ((transA == 'N' && oA + (k-1)*ldA + m > len(A)) ||
-        ((transA == 'T' || transA == 'C') && 
+        ((transA == 'T' || transA == 'C') &&
         oA + (m-1)*ldA + k > len(A)))) err_buf_len("A");
     if (oB < 0) err_nn_int("offsetB");
     if (k > 0 && ((transB == 'N' && oB + (n-1)*ldB + k > len(B)) ||
-        ((transB == 'T' || transB == 'C') && 
+        ((transB == 'T' || transB == 'C') &&
         oB + (k-1)*ldB + n > len(B)))) err_buf_len("B");
     if (oC < 0) err_nn_int("offsetC");
     if (oC + (n-1)*ldC + m > len(C)) err_buf_len("C");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(A))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(A)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(A))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(A)))
         err_type("beta");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            if (!bo) b.d = 0.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            dgemm_(&transA, &transB, &m, &n, &k, &a.d, 
-                MAT_BUFD(A)+oA, &ldA, MAT_BUFD(B)+oB, &ldB, &b.d, 
+            if (!ao) a.d = 1.0;
+            if (!bo) b.d = 0.0;
+            Py_BEGIN_ALLOW_THREADS
+            dgemm_(&transA, &transB, &m, &n, &k, &a.d,
+                MAT_BUFD(A)+oA, &ldA, MAT_BUFD(B)+oB, &ldB, &b.d,
                 MAT_BUFD(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z = 1.0; 
-            if (!bo) b.z = 0.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            zgemm_(&transA, &transB, &m, &n, &k, &a.z, 
-                MAT_BUFZ(A)+oA, &ldA, MAT_BUFZ(B)+oB, &ldB, &b.z, 
+            if (!ao) a.z = 1.0;
+            if (!bo) b.z = 0.0;
+            Py_BEGIN_ALLOW_THREADS
+            zgemm_(&transA, &transB, &m, &n, &k, &a.z,
+                MAT_BUFZ(A)+oA, &ldA, MAT_BUFZ(B)+oB, &ldB, &b.z,
                 MAT_BUFZ(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -2445,7 +2438,7 @@ static char doc_symm[] =
     "If side is 'L', computes C := alpha*A*B + beta*C.\n"
     "If side is 'R', computes C := alpha*B*A + beta*C.\n"
     "C is m by n and A is real or complex symmetric.  (Use hemm for\n"
-    "Hermitian A).\n\n" 
+    "Hermitian A).\n\n"
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix\n\n"
     "B         'd' or 'z' matrix.  Must have the same type as A.\n\n"
@@ -2478,15 +2471,15 @@ static PyObject* symm(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *A, *B, *C;
     PyObject *ao=NULL, *bo=NULL;
-    number a, b; 
-    int m=-1, n=-1, ldA=0, ldB=0, ldC=0, oA=0, oB=0, oC = 0; 
+    number a, b;
+    int m=-1, n=-1, ldA=0, ldB=0, ldC=0, oA=0, oB=0, oC = 0;
     char side='L', uplo='L';
     char *kwlist[] = {"A", "B", "C", "side", "uplo", "alpha", "beta",
-        "m", "n", "ldA", "ldB", "ldC", "offsetA", "offsetB", "offsetC", 
+        "m", "n", "ldA", "ldB", "ldC", "offsetA", "offsetB", "offsetC",
         NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOiiiiiiii", 
-        kwlist, &A, &B, &C, &side, &uplo, &ao, &bo, &m, &n, &ldA, &ldB, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOiiiiiiii",
+        kwlist, &A, &B, &C, &side, &uplo, &ao, &bo, &m, &n, &ldA, &ldB,
         &ldC, &oA, &oB, &oC))
         return NULL;
 
@@ -2507,7 +2500,7 @@ static PyObject* symm(PyObject *self, PyObject *args, PyObject *kwrds)
             return NULL;
         }
     }
-    if (n < 0){ 
+    if (n < 0){
         n = B->ncols;
         if (side == 'R' && (n != A->nrows || n != A->ncols)){
             PyErr_SetString(PyExc_TypeError, "dimensions of A and B "
@@ -2520,11 +2513,11 @@ static PyObject* symm(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1, (side == 'L') ? m : n)) err_ld("ldA");
     if (ldB == 0) ldB = MAX(1,B->nrows);
-    if (ldB < MAX(1,m)) err_ld("ldB"); 
+    if (ldB < MAX(1,m)) err_ld("ldB");
     if (ldC == 0) ldC = MAX(1,C->nrows);
     if (ldC < MAX(1,m)) err_ld("ldC");
 
-    if (oA < 0) err_nn_int("offsetA"); 
+    if (oA < 0) err_nn_int("offsetA");
     if ((side == 'L' && oA + (m-1)*ldA + m > len(A)) ||
         (side == 'R' && oA + (n-1)*ldA + n > len(A))) err_buf_len("A");
     if (oB < 0) err_nn_int("offsetB");
@@ -2532,28 +2525,28 @@ static PyObject* symm(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oC < 0) err_nn_int("offsetC");
     if (oC + (n-1)*ldC + m > len(C)) err_buf_len("C");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(A))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(A)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(A))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(A)))
         err_type("beta");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            if (!bo) b.d = 0.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            dsymm_(&side, &uplo, &m, &n, &a.d, MAT_BUFD(A)+oA, &ldA, 
+            if (!ao) a.d = 1.0;
+            if (!bo) b.d = 0.0;
+            Py_BEGIN_ALLOW_THREADS
+            dsymm_(&side, &uplo, &m, &n, &a.d, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(B)+oB, &ldB, &b.d, MAT_BUFD(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z = 1.0; 
-            if (!bo) b.z = 0.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            zsymm_(&side, &uplo, &m, &n, &a.z, MAT_BUFZ(A)+oA, &ldA, 
+            if (!ao) a.z = 1.0;
+            if (!bo) b.z = 0.0;
+            Py_BEGIN_ALLOW_THREADS
+            zsymm_(&side, &uplo, &m, &n, &a.z, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(B)+oB, &ldB, &b.z, MAT_BUFZ(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -2608,15 +2601,15 @@ static PyObject* hemm(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *A, *B, *C;
     PyObject *ao=NULL, *bo=NULL;
-    number a, b; 
-    int m=-1, n=-1, ldA=0, ldB=0, ldC=0, oA=0, oB=0, oC = 0; 
+    number a, b;
+    int m=-1, n=-1, ldA=0, ldB=0, ldC=0, oA=0, oB=0, oC = 0;
     char side='L', uplo='L';
     char *kwlist[] = {"A", "B", "C", "side", "uplo", "alpha", "beta",
-        "m", "n", "ldA", "ldB", "ldC", "offsetA", "offsetB", "offsetC", 
+        "m", "n", "ldA", "ldB", "ldC", "offsetA", "offsetB", "offsetC",
         NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOiiiiiiii", 
-        kwlist, &A, &B, &C, &side, &uplo, &ao, &bo, &m, &n, &ldA, &ldB, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOiiiiiiii",
+        kwlist, &A, &B, &C, &side, &uplo, &ao, &bo, &m, &n, &ldA, &ldB,
         &ldC, &oA, &oB, &oC))
         return NULL;
 
@@ -2637,7 +2630,7 @@ static PyObject* hemm(PyObject *self, PyObject *args, PyObject *kwrds)
             return NULL;
         }
     }
-    if (n < 0){ 
+    if (n < 0){
         n = B->ncols;
         if (side == 'R' && (n != A->nrows || n != A->ncols)){
             PyErr_SetString(PyExc_TypeError, "dimensions of A and B "
@@ -2650,11 +2643,11 @@ static PyObject* hemm(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1, (side == 'L') ? m : n)) err_ld("ldA");
     if (ldB == 0) ldB = MAX(1,B->nrows);
-    if (ldB < MAX(1,m)) err_ld("ldB"); 
+    if (ldB < MAX(1,m)) err_ld("ldB");
     if (ldC == 0) ldC = MAX(1,C->nrows);
     if (ldC < MAX(1,m)) err_ld("ldC");
 
-    if (oA < 0) err_nn_int("offsetA"); 
+    if (oA < 0) err_nn_int("offsetA");
     if ((side == 'L' && oA + (m-1)*ldA + m > len(A)) ||
         (side == 'R' && oA + (n-1)*ldA + n > len(A))) err_buf_len("A");
     if (oB < 0) err_nn_int("offsetB");
@@ -2662,28 +2655,28 @@ static PyObject* hemm(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oC < 0) err_nn_int("offsetC");
     if (oC + (n-1)*ldC + m > len(C)) err_buf_len("C");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(A))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(A)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(A))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(A)))
         err_type("beta");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            if (!bo) b.d = 0.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            dsymm_(&side, &uplo, &m, &n, &a.d, MAT_BUFD(A)+oA, &ldA, 
+            if (!ao) a.d = 1.0;
+            if (!bo) b.d = 0.0;
+            Py_BEGIN_ALLOW_THREADS
+            dsymm_(&side, &uplo, &m, &n, &a.d, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(B)+oB, &ldB, &b.d, MAT_BUFD(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z = 1.0; 
-            if (!bo) b.z = 0.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            zhemm_(&side, &uplo, &m, &n, &a.z, MAT_BUFZ(A)+oA, &ldA, 
+            if (!ao) a.z = 1.0;
+            if (!bo) b.z = 0.0;
+            Py_BEGIN_ALLOW_THREADS
+            zhemm_(&side, &uplo, &m, &n, &a.z, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(B)+oB, &ldB, &b.z, MAT_BUFZ(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -2721,7 +2714,7 @@ static char doc_syrk[] =
     "k         integer.  If negative, the default value is used.\n"
     "          The default value is\n"
     "          k = (trans == 'N') ? A.size[1] : A.size[0].\n\n"
-    "ldA       nonnegative integer.\n"  
+    "ldA       nonnegative integer.\n"
     "          ldA >= max(1, (trans == 'N') ? n : k).  If zero,\n"
     "          the default value is used.\n\n"
     "ldC       nonnegative integer.  ldC >= max(1,n).\n"
@@ -2733,14 +2726,14 @@ static PyObject* syrk(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *A, *C;
     PyObject *ao=NULL, *bo=NULL;
-    number a, b; 
+    number a, b;
     int n=-1, k=-1, ldA=0, ldC=0, oA = 0, oC = 0;
     char trans='N', uplo='L';
-    char *kwlist[] = {"A", "C", "uplo", "trans", "alpha", "beta", "n", 
+    char *kwlist[] = {"A", "C", "uplo", "trans", "alpha", "beta", "n",
         "k", "ldA", "ldC", "offsetA", "offsetC", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccOOiiiiii", 
-        kwlist, &A, &C, &uplo, &trans, &ao, &bo, &n, &k, &ldA, &ldC, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccOOiiiiii",
+        kwlist, &A, &C, &uplo, &trans, &ao, &bo, &n, &k, &ldA, &ldC,
 	&oA, &oC))
         return NULL;
 
@@ -2751,7 +2744,7 @@ static PyObject* syrk(PyObject *self, PyObject *args, PyObject *kwrds)
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (MAT_ID(A) == DOUBLE && trans != 'N' && trans != 'T' &&
         trans != 'C') err_char("trans", "'N', 'T', 'C'");
-    if (MAT_ID(A) == COMPLEX && trans != 'N' && trans != 'T') 
+    if (MAT_ID(A) == COMPLEX && trans != 'N' && trans != 'T')
 	err_char("trans", "'N', 'T'");
 
     if (n < 0) n = (trans == 'N') ? A->nrows : A->ncols;
@@ -2764,34 +2757,34 @@ static PyObject* syrk(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldC < MAX(1,n)) err_ld("ldC");
     if (oA < 0) err_nn_int("offsetA");
     if (k > 0 && ((trans == 'N' && oA + (k-1)*ldA + n > len(A)) ||
-        ((trans == 'T' || trans == 'C') && 
+        ((trans == 'T' || trans == 'C') &&
 	oA + (n-1)*ldA + k > len(A))))
         err_buf_len("A");
-    if (oC < 0) err_nn_int("offsetC"); 
+    if (oC < 0) err_nn_int("offsetC");
     if (oC + (n-1)*ldC + n > len(C)) err_buf_len("C");
-    
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(A))) 
+
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(A)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(A))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(A)))
         err_type("beta");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            if (!bo) b.d = 0.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            dsyrk_(&uplo, &trans, &n, &k, &a.d, MAT_BUFD(A)+oA, &ldA, 
+            if (!ao) a.d = 1.0;
+            if (!bo) b.d = 0.0;
+            Py_BEGIN_ALLOW_THREADS
+            dsyrk_(&uplo, &trans, &n, &k, &a.d, MAT_BUFD(A)+oA, &ldA,
                 &b.d, MAT_BUFD(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z = 1.0; 
-            if (!bo) b.z = 0.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            zsyrk_(&uplo, &trans, &n, &k, &a.z, MAT_BUFZ(A)+oA, &ldA, 
+            if (!ao) a.z = 1.0;
+            if (!bo) b.z = 0.0;
+            Py_BEGIN_ALLOW_THREADS
+            zsyrk_(&uplo, &trans, &n, &k, &a.z, MAT_BUFZ(A)+oA, &ldA,
                 &b.z, MAT_BUFZ(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -2817,7 +2810,7 @@ static char doc_herk[] =
     "A         'd' or 'z' matrix\n\n"
     "C         'd' or 'z' matrix.  Must have the same type as A.\n\n"
     "uplo      'L' or 'U'\n\n"
-    "trans     'N' or 'C'\n\n" 
+    "trans     'N' or 'C'\n\n"
     "alpha     real number (int or float)\n\n"
     "beta      number (int, float or complex)\n\n"
     "n         integer.  If negative, the default value is used.\n"
@@ -2826,7 +2819,7 @@ static char doc_herk[] =
     "k         integer.  If negative, the default value is used.\n"
     "          The default value is\n"
     "          k = (trans == 'N') ? A.size[1] : A.size[0].\n\n"
-    "ldA       nonnegative integer.\n"  
+    "ldA       nonnegative integer.\n"
     "          ldA >= max(1, (trans == 'N') ? n : k).  If zero,\n"
     "          the default value is used.\n\n"
     "ldC       nonnegative integer.  ldC >= max(1,n).\n"
@@ -2838,14 +2831,14 @@ static PyObject* herk(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *A, *C;
     PyObject *ao=NULL, *bo=NULL;
-    number a, b; 
+    number a, b;
     int n=-1, k=-1, ldA=0, ldC=0, oA = 0, oC = 0;
     char trans='N', uplo='L';
-    char *kwlist[] = {"A", "C", "uplo", "trans", "alpha", "beta", "n", 
+    char *kwlist[] = {"A", "C", "uplo", "trans", "alpha", "beta", "n",
         "k", "ldA", "ldC", "offsetA", "offsetC", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccOOiiiiii", 
-        kwlist, &A, &C, &uplo, &trans, &ao, &bo, &n, &k, &ldA, &ldC, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccOOiiiiii",
+        kwlist, &A, &C, &uplo, &trans, &ao, &bo, &n, &k, &ldA, &ldC,
 	&oA, &oC))
         return NULL;
 
@@ -2856,7 +2849,7 @@ static PyObject* herk(PyObject *self, PyObject *args, PyObject *kwrds)
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (MAT_ID(A) == DOUBLE && trans != 'N' && trans != 'T' &&
         trans != 'C') err_char("trans", "'N', 'T', 'C'");
-    if (MAT_ID(A) == COMPLEX && trans != 'N' && trans != 'C') 
+    if (MAT_ID(A) == COMPLEX && trans != 'N' && trans != 'C')
 	err_char("trans", "'N', 'C'");
 
     if (n < 0) n = (trans == 'N') ? A->nrows : A->ncols;
@@ -2869,30 +2862,30 @@ static PyObject* herk(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldC < MAX(1,n)) err_ld("ldC");
     if (oA < 0) err_nn_int("offsetA");
     if (k > 0 && ((trans == 'N' && oA + (k-1)*ldA + n > len(A)) ||
-        ((trans == 'T' || trans == 'C') && 
+        ((trans == 'T' || trans == 'C') &&
 	oA + (n-1)*ldA + k > len(A))))
         err_buf_len("A");
-    if (oC < 0) err_nn_int("offsetC"); 
+    if (oC < 0) err_nn_int("offsetC");
     if (oC + (n-1)*ldC + n > len(C)) err_buf_len("C");
-    
+
     if (ao && number_from_pyobject(ao, &a, DOUBLE)) err_type("alpha");
     if (bo && number_from_pyobject(bo, &b, DOUBLE)) err_type("beta");
-    if (!ao) a.d = 1.0; 
-    if (!bo) b.d = 0.0; 
+    if (!ao) a.d = 1.0;
+    if (!bo) b.d = 0.0;
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dsyrk_(&uplo, &trans, &n, &k, &a.d, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dsyrk_(&uplo, &trans, &n, &k, &a.d, MAT_BUFD(A)+oA, &ldA,
                 &b.d, MAT_BUFD(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            zherk_(&uplo, &trans, &n, &k, &a.d, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            zherk_(&uplo, &trans, &n, &k, &a.d, MAT_BUFZ(A)+oA, &ldA,
                 &b.d, MAT_BUFZ(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -2927,9 +2920,9 @@ static char doc_syr2k[] =
     "          allowed if A is complex.\n\n"
     "n         integer.  If negative, the default value is used.\n"
     "          The default value is\n"
-    "          n = (trans == 'N') ? A.size[0] : A.size[1].\n" 
+    "          n = (trans == 'N') ? A.size[0] : A.size[1].\n"
     "          If the default value is used, it should be equal to\n"
-    "          (trans == 'N') ? B.size[0] : B.size[1].\n\n" 
+    "          (trans == 'N') ? B.size[0] : B.size[1].\n\n"
     "k         integer.  If negative, the default value is used.\n"
     "          The default value is\n"
     "          k = (trans == 'N') ? A.size[1] : A.size[0].\n"
@@ -2952,13 +2945,13 @@ static PyObject* syr2k(PyObject *self, PyObject *args, PyObject *kwrds)
     matrix *A, *B, *C;
     PyObject *ao=NULL, *bo=NULL;
     number a, b;
-    int n=-1, k=-1, ldA=0, ldB=0, ldC=0, oA = 0, oB = 0, oC = 0; 
+    int n=-1, k=-1, ldA=0, ldB=0, ldC=0, oA = 0, oB = 0, oC = 0;
     char trans='N', uplo='L';
     char *kwlist[] = {"A", "B", "C", "uplo", "trans", "alpha", "beta",
         "n", "k", "ldA", "ldB", "ldC", "offsetA", "offsetB", "offsetC",
         NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOiiiiiiii", 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOiiiiiiii",
         kwlist, &A, &B, &C, &uplo, &trans, &ao, &bo, &n, &k, &ldA, &ldB,
 	&ldC, &oA, &oB, &oC))
         return NULL;
@@ -2972,10 +2965,10 @@ static PyObject* syr2k(PyObject *self, PyObject *args, PyObject *kwrds)
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (MAT_ID(A) == DOUBLE && trans != 'N' && trans != 'T' &&
         trans != 'C') err_char("trans", "'N', 'T', 'C'");
-    if (MAT_ID(A) == COMPLEX && trans != 'N' && trans != 'T') 
+    if (MAT_ID(A) == COMPLEX && trans != 'N' && trans != 'T')
 	err_char("trans", "'N', 'T'");
-  
-    if (n < 0){ 
+
+    if (n < 0){
         n = (trans == 'N') ? A->nrows : A->ncols;
         if (n != ((trans == 'N') ? B->nrows : B->ncols)){
             PyErr_SetString(PyExc_TypeError, "dimensions of A and B "
@@ -3002,40 +2995,40 @@ static PyObject* syr2k(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (oA < 0) err_nn_int("offsetA");
     if (k > 0 && ((trans == 'N' && oA + (k-1)*ldA + n > len(A)) ||
-        ((trans == 'T' || trans == 'C') && 
+        ((trans == 'T' || trans == 'C') &&
 	oA + (n-1)*ldA + k > len(A))))
         err_buf_len("A");
     if (oB < 0) err_nn_int("offsetB");
     if (k > 0 && ((trans == 'N' && oB + (k-1)*ldB + n > len(B)) ||
-        ((trans == 'T' || trans == 'C') && 
+        ((trans == 'T' || trans == 'C') &&
 	oB + (n-1)*ldB + k > len(B))))
         err_buf_len("B");
     if (oC < 0) err_nn_int("offsetC");
     if (oC + (n-1)*ldC + n > len(C))  err_buf_len("C");
 
-    
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(A))) 
+
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(A)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(A))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(A)))
         err_type("beta");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            if (!bo) b.d = 0.0; 
-            Py_BEGIN_ALLOW_THREADS	    
+            if (!ao) a.d = 1.0;
+            if (!bo) b.d = 0.0;
+            Py_BEGIN_ALLOW_THREADS
             dsyr2k_(&uplo, &trans, &n, &k, &a.d, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(B)+oB, &ldB, &b.d, MAT_BUFD(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            if (!ao) a.z = 1.0; 
-            if (!bo) b.z = 0.0; 
-            Py_BEGIN_ALLOW_THREADS	    
+            if (!ao) a.z = 1.0;
+            if (!bo) b.z = 0.0;
+            Py_BEGIN_ALLOW_THREADS
             zsyr2k_(&uplo, &trans, &n, &k, &a.z, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(B)+oB, &ldB, &b.z, MAT_BUFZ(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -3070,9 +3063,9 @@ static char doc_her2k[] =
     "beta      real number (int or float)\n\n"
     "n         integer.  If negative, the default value is used.\n"
     "          The default value is\n"
-    "          n = (trans == 'N') ? A.size[0] : A.size[1].\n" 
+    "          n = (trans == 'N') ? A.size[0] : A.size[1].\n"
     "          If the default value is used, it should be equal to\n"
-    "          (trans == 'N') ? B.size[0] : B.size[1].\n\n" 
+    "          (trans == 'N') ? B.size[0] : B.size[1].\n\n"
     "k         integer.  If negative, the default value is used.\n"
     "          The default value is\n"
     "          k = (trans == 'N') ? A.size[1] : A.size[0].\n"
@@ -3095,13 +3088,13 @@ static PyObject* her2k(PyObject *self, PyObject *args, PyObject *kwrds)
     matrix *A, *B, *C;
     PyObject *ao=NULL, *bo=NULL;
     number a, b;
-    int n=-1, k=-1, ldA=0, ldB=0, ldC=0, oA = 0, oB = 0, oC = 0; 
+    int n=-1, k=-1, ldA=0, ldB=0, ldC=0, oA = 0, oB = 0, oC = 0;
     char trans='N', uplo='L';
     char *kwlist[] = {"A", "B", "C", "uplo", "trans", "alpha", "beta",
         "n", "k", "ldA", "ldB", "ldC", "offsetA", "offsetB", "offsetC",
         NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOiiiiiiii", 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ccOOiiiiiiii",
         kwlist, &A, &B, &C, &uplo, &trans, &ao, &bo, &n, &k, &ldA, &ldB,
 	&ldC, &oA, &oB, &oC))
         return NULL;
@@ -3115,10 +3108,10 @@ static PyObject* her2k(PyObject *self, PyObject *args, PyObject *kwrds)
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (MAT_ID(A) == DOUBLE && trans != 'N' && trans != 'T' &&
         trans != 'C') err_char("trans", "'N', 'T', 'C'");
-    if (MAT_ID(A) == COMPLEX && trans != 'N' && trans != 'C') 
+    if (MAT_ID(A) == COMPLEX && trans != 'N' && trans != 'C')
 	err_char("trans", "'N', 'C'");
-  
-    if (n < 0){ 
+
+    if (n < 0){
         n = (trans == 'N') ? A->nrows : A->ncols;
         if (n != ((trans == 'N') ? B->nrows : B->ncols)){
             PyErr_SetString(PyExc_TypeError, "dimensions of A and B "
@@ -3145,39 +3138,39 @@ static PyObject* her2k(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (oA < 0) err_nn_int("offsetA");
     if (k > 0 && ((trans == 'N' && oA + (k-1)*ldA + n > len(A)) ||
-        ((trans == 'T' || trans == 'C') && 
+        ((trans == 'T' || trans == 'C') &&
 	oA + (n-1)*ldA + k > len(A))))
         err_buf_len("A");
     if (oB < 0) err_nn_int("offsetB");
     if (k > 0 && ((trans == 'N' && oB + (k-1)*ldB + n > len(B)) ||
-        ((trans == 'T' || trans == 'C') && 
+        ((trans == 'T' || trans == 'C') &&
 	oB + (n-1)*ldB + k > len(B))))
         err_buf_len("B");
     if (oC < 0) err_nn_int("offsetC");
     if (oC + (n-1)*ldC + n > len(C))  err_buf_len("C");
 
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(A))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(A)))
         err_type("alpha");
-    if (bo && number_from_pyobject(bo, &b, MAT_ID(A))) 
+    if (bo && number_from_pyobject(bo, &b, MAT_ID(A)))
         err_type("beta");
-    if (!bo) b.d = 0.0; 
+    if (!bo) b.d = 0.0;
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
+            if (!ao) a.d = 1.0;
+            Py_BEGIN_ALLOW_THREADS
             dsyr2k_(&uplo, &trans, &n, &k, &a.d, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(B)+oB, &ldB, &b.d, MAT_BUFD(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-	    if (!ao) a.z = 1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
+	    if (!ao) a.z = 1.0;
+            Py_BEGIN_ALLOW_THREADS
             zher2k_(&uplo, &trans, &n, &k, &a.z, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(B)+oB, &ldB, &b.d, MAT_BUFZ(C)+oC, &ldC);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -3214,12 +3207,12 @@ static char doc_trmm[] =
     "m         integer.  If negative, the default value is used.\n"
     "          The default value is\n"
     "          m = (side == 'L') ? A.size[0] : B.size[0].\n"
-    "          If the default value is used and side is 'L', m must\n" 
+    "          If the default value is used and side is 'L', m must\n"
     "          be equal to A.size[1].\n\n"
     "n         integer.  If negative, the default value is used.\n"
     "          The default value is\n"
-    "          n = (side == 'L') ? B.size[1] : A.size[0].\n" 
-    "          If the default value is used and side is 'R', n must\n" 
+    "          n = (side == 'L') ? B.size[1] : A.size[0].\n"
+    "          If the default value is used and side is 'R', n must\n"
     "          be equal to A.size[1].\n\n"
     "ldA       nonnegative integer.\n"
     "          ldA >= max(1, (side == 'L') ? m : n).\n"
@@ -3236,10 +3229,10 @@ static PyObject* trmm(PyObject *self, PyObject *args, PyObject *kwrds)
     number a;
     int m=-1, n=-1, ldA=0, ldB=0, oA=0, oB=0;
     char side='L', uplo='L', transA='N', diag='N';
-    char *kwlist[] = {"A", "B", "side", "uplo", "transA", "diag", 
+    char *kwlist[] = {"A", "B", "side", "uplo", "transA", "diag",
         "alpha", "m", "n", "ldA", "ldB", "offsetA", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccccOiiiiii", 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccccOiiiiii",
         kwlist, &A, &B, &side, &uplo, &transA, &diag, &ao, &m, &n, &ldA,
         &ldB, &oA, &oB))
         return NULL;
@@ -3251,10 +3244,10 @@ static PyObject* trmm(PyObject *self, PyObject *args, PyObject *kwrds)
     if (side != 'L' && side != 'R') err_char("side", "'L', 'R'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (diag != 'N' && diag != 'U') err_char("diag", "'N', 'U'");
-    if (transA != 'N' && transA != 'T' && transA != 'C') 
+    if (transA != 'N' && transA != 'T' && transA != 'C')
         err_char("transA", "'N', 'T', 'C'");
 
-    if (n < 0){ 
+    if (n < 0){
         n = (side == 'L') ? B->ncols : A->nrows;
         if (side != 'L' && n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -3263,7 +3256,7 @@ static PyObject* trmm(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (m < 0){
         m = (side == 'L') ? A->nrows: B->nrows;
-        if (side == 'L' && m != A->ncols){ 
+        if (side == 'L' && m != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
             return NULL;
         }
@@ -3271,33 +3264,33 @@ static PyObject* trmm(PyObject *self, PyObject *args, PyObject *kwrds)
     if (m == 0 || n == 0) return Py_BuildValue("");
 
     if (ldA == 0) ldA = MAX(1,A->nrows);
-    if (ldA < MAX(1, (side == 'L') ? m : n)) err_ld("ldA"); 
+    if (ldA < MAX(1, (side == 'L') ? m : n)) err_ld("ldA");
     if (ldB == 0) ldB = MAX(1,B->nrows);
     if (ldB < MAX(1, m)) err_ld("ldB");
-    if (oA < 0) err_nn_int("offsetA"); 
+    if (oA < 0) err_nn_int("offsetA");
     if ((side == 'L' && oA + (m-1)*ldA + m > len(A)) ||
         (side == 'R' && oA + (n-1)*ldA + n > len(A))) err_buf_len("A");
-    if (oB < 0) err_nn_int("offsetB"); 
+    if (oB < 0) err_nn_int("offsetB");
     if (oB + (n-1)*ldB + m > len(B)) err_buf_len("B");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(A))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(A)))
         err_type("alpha");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-            Py_BEGIN_ALLOW_THREADS	    
-            dtrmm_(&side, &uplo, &transA, &diag, &m, &n, &a.d, 
+            if (!ao) a.d = 1.0;
+            Py_BEGIN_ALLOW_THREADS
+            dtrmm_(&side, &uplo, &transA, &diag, &m, &n, &a.d,
                 MAT_BUFD(A)+oA, &ldA, MAT_BUFD(B)+oB, &ldB);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
    	    if (!ao) a.z = 1.0;
-            Py_BEGIN_ALLOW_THREADS	    
-            ztrmm_(&side, &uplo, &transA, &diag, &m, &n, &a.z, 
+            Py_BEGIN_ALLOW_THREADS
+            ztrmm_(&side, &uplo, &transA, &diag, &m, &n, &a.z,
                 MAT_BUFZ(A)+oA, &ldA, MAT_BUFZ(B)+oB, &ldB);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -3315,7 +3308,7 @@ static char doc_trsm[] =
     "trsm(A, B, side='L', uplo='L', transA='N', diag='N', alpha=1.0,\n"
     "     m=None, n=None, ldA=max(1,A.size[0]), ldB=max(1,B.size[0]),\n"
     "     offsetA=0, offsetB=0)\n\n"
-    "PURPOSE\n"   
+    "PURPOSE\n"
     "Computes\n"
     "B := alpha*A^{-1}*B if transA is 'N' and side = 'L'.\n"
     "B := alpha*B*A^{-1} if transA is 'N' and side = 'R'.\n"
@@ -3346,7 +3339,7 @@ static char doc_trsm[] =
     "          be equal to A.size[1].\n\n"
     "ldA       nonnegative integer.\n"
     "          ldA >= max(1, (side == 'L') ? m : n).\n"
-    "          If zero, the default value is used.\n\n" 
+    "          If zero, the default value is used.\n\n"
     "ldB       nonnegative integer.  ldB >= max(1,m).\n"
     "          If zero, the default value is used.\n\n"
     "offsetA   nonnegative integer\n\n"
@@ -3359,10 +3352,10 @@ static PyObject* trsm(PyObject *self, PyObject *args, PyObject *kwrds)
     number a;
     int m=-1, n=-1, ldA=0, ldB=0, oA=0, oB=0;
     char side='L', uplo='L', transA='N', diag='N';
-    char *kwlist[] = {"A", "B", "side", "uplo", "transA", "diag", 
+    char *kwlist[] = {"A", "B", "side", "uplo", "transA", "diag",
         "alpha", "m", "n", "ldA", "ldB", "offsetA", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccccOiiiiii", 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccccOiiiiii",
         kwlist, &A, &B, &side, &uplo, &transA, &diag, &ao, &m, &n, &ldA,
         &ldB, &oA, &oB))
         return NULL;
@@ -3374,10 +3367,10 @@ static PyObject* trsm(PyObject *self, PyObject *args, PyObject *kwrds)
     if (side != 'L' && side != 'R') err_char("side", "'L', 'R'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (diag != 'N' && diag != 'U') err_char("diag", "'N', 'U'");
-    if (transA != 'N' && transA != 'T' && transA != 'C') 
+    if (transA != 'N' && transA != 'T' && transA != 'C')
         err_char("transA", "'N', 'T', 'C'");
 
-    if (n < 0){ 
+    if (n < 0){
         n = (side == 'L') ? B->ncols : A->nrows;
         if (side != 'L' && n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -3386,7 +3379,7 @@ static PyObject* trsm(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (m < 0){
         m = (side == 'L') ? A->nrows: B->nrows;
-        if (side == 'L' && m != A->ncols){ 
+        if (side == 'L' && m != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
             return NULL;
         }
@@ -3400,27 +3393,27 @@ static PyObject* trsm(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oA < 0) err_nn_int("offsetA");
     if ((side == 'L' && oA + (m-1)*ldA + m > len(A)) ||
         (side == 'R' && oA + (n-1)*ldA + n > len(A))) err_buf_len("A");
-    if (oB < 0) err_nn_int("offsetB"); 
+    if (oB < 0) err_nn_int("offsetB");
     if (oB < 0 || oB + (n-1)*ldB + m > len(B)) err_buf_len("B");
 
-    if (ao && number_from_pyobject(ao, &a, MAT_ID(A))) 
+    if (ao && number_from_pyobject(ao, &a, MAT_ID(A)))
         err_type("alpha");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            if (!ao) a.d = 1.0; 
-             Py_BEGIN_ALLOW_THREADS	    
-            dtrsm_(&side, &uplo, &transA, &diag, &m, &n, &a.d, 
+            if (!ao) a.d = 1.0;
+             Py_BEGIN_ALLOW_THREADS
+            dtrsm_(&side, &uplo, &transA, &diag, &m, &n, &a.d,
                 MAT_BUFD(A)+oA, &ldA, MAT_BUFD(B)+oB, &ldB);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
   	    if (!ao) a.z = 1.0;
-            Py_BEGIN_ALLOW_THREADS	    
-            ztrsm_(&side, &uplo, &transA, &diag, &m, &n, &a.z, 
+            Py_BEGIN_ALLOW_THREADS
+            ztrsm_(&side, &uplo, &transA, &diag, &m, &n, &a.z,
                 MAT_BUFZ(A)+oA, &ldA, MAT_BUFZ(B)+oB, &ldB);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
diff --git a/src/C/blas_redefines.h b/src/C/blas_redefines.h
index e07d11e..93fad66 100644
--- a/src/C/blas_redefines.h
+++ b/src/C/blas_redefines.h
@@ -104,6 +104,14 @@
 #define zgeqrf_ zgeqrf
 #define dormqr_ dormqr
 #define zunmqr_ zunmqr
+#define dorgqr_ dorgqr
+#define zungqr_ zungqr
+#define dgelqf_ dgelqf
+#define zgelqf_ zgelqf
+#define dormlq_ dormlq
+#define zunmlq_ zunmlq
+#define dorglq_ dorglq
+#define zunglq_ zunglq
 #define dtrtrs_ dtrtrs
 #define ztrtrs_ ztrtrs
 #define dgbtrf_ dgbtrf
@@ -137,9 +145,12 @@
 #define dpttrs_ dpttrs
 #define zpttrs_ zpttrs
 #define dlacpy_ dlacpy
+#define zlacpy_ zlacpy
 #define dgees_ dgees
 #define zgees_ zgees
 #define dgges_ dgges
 #define zgges_ zgges
+#define dgeqp3_ dgeqp3
+#define zgeqp3_ zgeqp3
 
 #endif
diff --git a/src/C/cholmod.c b/src/C/cholmod.c
index 8684840..605943a 100644
--- a/src/C/cholmod.c
+++ b/src/C/cholmod.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -49,7 +49,7 @@ PyDoc_STRVAR(cholmod__doc__, "Interface to the CHOLMOD library.\n\n"
 "    algorithm.  If equal to 1, the most efficient of the two\n"
 "    factorizations is selected, based on the sparsity pattern.\n\n"
 "options['print']:  A nonnegative integer that controls the amount of\n"
-"    output printed to the screen.\n\n"  
+"    output printed to the screen.\n\n"
 "options['nmethods']: A nonnegative integer that specifies how many\n"
 "    orderings are attempted prior to factorization.  If equal to 0,\n"
 "    the AMD ordering and the user-provided permutation (if any) are\n"
@@ -65,7 +65,7 @@ PyDoc_STRVAR(cholmod__doc__, "Interface to the CHOLMOD library.\n\n"
 
 
 static PyObject *cholmod_module;
-static cholmod_common Common;   
+static cholmod_common Common;
 
 static int set_options(void)
 {
@@ -73,17 +73,17 @@ static int set_options(void)
     PyObject *param, *key, *value;
     char *keystr, err_str[100];
 
-    CHOL(defaults)(&Common); 
-    Common.print = 0;         
-    Common.supernodal = 2;         
-    
+    CHOL(defaults)(&Common);
+    Common.print = 0;
+    Common.supernodal = 2;
+
     if (!(param = PyObject_GetAttrString(cholmod_module, "options")) ||
         ! PyDict_Check(param)) {
         PyErr_SetString(PyExc_AttributeError, "missing cholmod.options"
             "dictionary");
         return 0;
     }
-    while (PyDict_Next(param, &pos, &key, &value)) 
+    while (PyDict_Next(param, &pos, &key, &value))
         if ((keystr = PyString_AsString(key))) {
 
             if (!strcmp("supernodal", keystr) && PyInt_Check(value))
@@ -93,7 +93,7 @@ static int set_options(void)
             }
             else if (!strcmp("nmethods", keystr) && PyInt_Check(value))
                 Common.nmethods = (int) PyInt_AsLong(value);
-            else if (!strcmp("postorder", keystr) && 
+            else if (!strcmp("postorder", keystr) &&
                 PyBool_Check(value))
                 Common.postorder = (int) PyInt_AsLong(value);
             else if (!strcmp("dbound", keystr) && PyFloat_Check(value))
@@ -101,7 +101,7 @@ static int set_options(void)
             else {
                 sprintf(err_str, "invalid value for CHOLMOD parameter: "
                     "%-.20s", keystr);
-                PyErr_SetString(PyExc_ValueError, err_str); 
+                PyErr_SetString(PyExc_ValueError, err_str);
                 Py_DECREF(param);
                 return 0;
             }
@@ -117,43 +117,43 @@ static cholmod_sparse *pack(spmatrix *A, char uplo)
     cholmod_sparse *B;
 
     if (uplo == 'L'){
-        for (j=0; j<n; j++){ 
-            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] < j; 
+        for (j=0; j<n; j++){
+            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] < j;
                 k++);
             nnz += SP_COL(A)[j+1] - k;
         }
-        if (!(B = CHOL(allocate_sparse)(n, n, nnz, 1, 1, -1, 
-            (SP_ID(A) == DOUBLE ? CHOLMOD_REAL : CHOLMOD_COMPLEX), 
+        if (!(B = CHOL(allocate_sparse)(n, n, nnz, 1, 1, -1,
+            (SP_ID(A) == DOUBLE ? CHOLMOD_REAL : CHOLMOD_COMPLEX),
             &Common))) return 0;
         for (j=0; j<n; j++){
-            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] < j; 
+            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] < j;
                 k++);
        	    for (; k<SP_COL(A)[j+1]; k++) {
                 if (SP_ID(A) == DOUBLE)
-                    ((double *)B->x)[cnt] = SP_VALD(A)[k]; 
-                else 
-                    ((complex *)B->x)[cnt] = SP_VALZ(A)[k]; 
+                    ((double *)B->x)[cnt] = SP_VALD(A)[k];
+                else
+                    ((complex *)B->x)[cnt] = SP_VALZ(A)[k];
                 ((int_t *)B->p)[j+1]++;
                 ((int_t *)B->i)[cnt++] = SP_ROW(A)[k];
 	    }
         }
     }
     else {
-        for (j=0; j<n; j++) 
+        for (j=0; j<n; j++)
             for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] <= j;
                 k++)
                 nnz++;
-        if (!(B = CHOL(allocate_sparse)(n, n, nnz, 1, 1, 1, 
-            (SP_ID(A) == DOUBLE ? CHOLMOD_REAL : CHOLMOD_COMPLEX), 
+        if (!(B = CHOL(allocate_sparse)(n, n, nnz, 1, 1, 1,
+            (SP_ID(A) == DOUBLE ? CHOLMOD_REAL : CHOLMOD_COMPLEX),
             &Common))) return 0;
 
-        for (j=0; j<n; j++) 
-            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] <= j; 
+        for (j=0; j<n; j++)
+            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] <= j;
                 k++) {
                 if (SP_ID(A) == DOUBLE)
-                    ((double *)B->x)[cnt] = SP_VALD(A)[k]; 
-                else 
-                    ((complex *)B->x)[cnt] = SP_VALZ(A)[k]; 
+                    ((double *)B->x)[cnt] = SP_VALD(A)[k];
+                else
+                    ((complex *)B->x)[cnt] = SP_VALZ(A)[k];
             ((int_t *)B->p)[j+1]++;
             ((int_t *)B->i)[cnt++] = SP_ROW(A)[k];
         }
@@ -166,8 +166,8 @@ static cholmod_sparse *pack(spmatrix *A, char uplo)
 static cholmod_sparse * create_matrix(spmatrix *A)
 {
     cholmod_sparse *B;
-  
-    if (!(B = CHOL(allocate_sparse)(SP_NROWS(A), SP_NCOLS(A), 0, 
+
+    if (!(B = CHOL(allocate_sparse)(SP_NROWS(A), SP_NCOLS(A), 0,
         1, 0, 0, (SP_ID(A) == DOUBLE ? CHOLMOD_REAL : CHOLMOD_COMPLEX),
         &Common))) return NULL;
 
@@ -185,7 +185,7 @@ static cholmod_sparse * create_matrix(spmatrix *A)
 static void free_matrix(cholmod_sparse *A)
 {
     A->x = NULL;
-    A->i = NULL;  
+    A->i = NULL;
     CHOL(free_sparse)(&A, &Common);
 }
 
@@ -195,10 +195,10 @@ static void cvxopt_free_cholmod_factor(void *L, void *descr)
 }
 
 
-static char doc_symbolic[] = 
+static char doc_symbolic[] =
     "Symbolic Cholesky factorization of a real symmetric or Hermitian\n"
     "sparse matrix.\n\n"
-    "F = symbolic(A, p=None, uplo='L')\n\n" 
+    "F = symbolic(A, p=None, uplo='L')\n\n"
     "PURPOSE\n"
     "If cholmod.options['supernodal'] = 2, factors A as\n"
     "P*A*P^T = L*L^T or P*A*P^T = L*L^H.  This is the default value.\n"
@@ -215,35 +215,35 @@ static char doc_symbolic[] =
     "uplo      'L' or 'U'.  If uplo is 'L', only the lower triangular\n"
     "          part of A is used and the upper triangular part is\n"
     "          ignored.  If uplo is 'U', only the upper triangular\n"
-    "          part of A is used and the lower triangular part is\n" 
+    "          part of A is used and the lower triangular part is\n"
     "          ignored.\n\n"
     "F         the symbolic factorization, including the permutation,\n"
     "          as an opaque C object that can be passed to\n"
     "          cholmod.numeric\n\n";
 
-static PyObject* symbolic(PyObject *self, PyObject *args, 
+static PyObject* symbolic(PyObject *self, PyObject *args,
     PyObject *kwrds)
 {
     spmatrix *A;
     cholmod_sparse *Ac = NULL;
-    cholmod_factor *L;  
-    matrix *P=NULL; 
+    cholmod_factor *L;
+    matrix *P=NULL;
     char uplo='L';
     int n;
     char *kwlist[] = {"A", "p", "uplo", NULL};
 
     if (!set_options()) return NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|Oc", kwlist, &A, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|Oc", kwlist, &A,
         &P, &uplo)) return NULL;
-    if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)) 
+    if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A))
         PY_ERR_TYPE("A is not a square sparse matrix");
     n = SP_NROWS(A);
 
     if (P) {
         if (!Matrix_Check(P) || MAT_ID(P) != INT) err_int_mtrx("p");
         if (MAT_LGT(P) != n) err_buf_len("p");
-        if (!CHOL(check_perm)(P->buffer, n, n, &Common)) 
+        if (!CHOL(check_perm)(P->buffer, n, n, &Common))
             PY_ERR(PyExc_ValueError, "p is not a valid permutation");
     }
     if (uplo != 'U' && uplo != 'L') err_char("uplo", "'L', 'U'");
@@ -257,21 +257,21 @@ static PyObject* symbolic(PyObject *self, PyObject *args,
         else
             PyErr_SetString(PyExc_ValueError, "symbolic factorization "
                 "failed");
-            return NULL; 	    
+            return NULL;
     }
-    return (PyObject *) PyCObject_FromVoidPtrAndDesc((void *) L, 
-        SP_ID(A)==DOUBLE ?  (uplo == 'L' ?  
+    return (PyObject *) PyCObject_FromVoidPtrAndDesc((void *) L,
+        SP_ID(A)==DOUBLE ?  (uplo == 'L' ?
             "CHOLMOD FACTOR D L" : "CHOLMOD FACTOR D U") :
-            (uplo == 'L' ?  
-            "CHOLMOD FACTOR Z L" : "CHOLMOD FACTOR Z U"), 
-	    cvxopt_free_cholmod_factor);  
+            (uplo == 'L' ?
+            "CHOLMOD FACTOR Z L" : "CHOLMOD FACTOR Z U"),
+	    cvxopt_free_cholmod_factor);
 }
 
 
-static char doc_numeric[] = 
+static char doc_numeric[] =
     "Numeric Cholesky factorization of a real symmetric or Hermitian\n"
     "sparse matrix.\n\n"
-    "numeric(A, F)\n\n" 
+    "numeric(A, F)\n\n"
     "PURPOSE\n"
     "If cholmod.options['supernodal'] = 2, factors A as\n"
     "P*A*P^T = L*L^T or P*A*P^T = L*L^H.  This is the default value.\n"
@@ -308,34 +308,34 @@ static PyObject* numeric(PyObject *self, PyObject *args)
 
     if (!PyArg_ParseTuple(args, "OO", &A, &F)) return NULL;
 
-    if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)) 
+    if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A))
         PY_ERR_TYPE("A is not a sparse matrix");
 
-    if (!PyCObject_Check(F)) err_CO("F");  
+    if (!PyCObject_Check(F)) err_CO("F");
     descr = PyCObject_GetDesc(F);
     if (!descr) PY_ERR_TYPE("F is not a CHOLMOD factor");
     if (SP_ID(A) == DOUBLE){
-        if (!strcmp(descr, "CHOLMOD FACTOR D L")) 
+        if (!strcmp(descr, "CHOLMOD FACTOR D L"))
 	    uplo = 'L';
-	else if (!strcmp(descr, "CHOLMOD FACTOR D U")) 
+	else if (!strcmp(descr, "CHOLMOD FACTOR D U"))
 	    uplo = 'U';
-        else 
+        else
 	    PY_ERR_TYPE("F is not the CHOLMOD factor of a 'd' matrix");
     } else {
-        if (!strcmp(descr, "CHOLMOD FACTOR Z L")) 
+        if (!strcmp(descr, "CHOLMOD FACTOR Z L"))
 	    uplo = 'L';
-	else if (!strcmp(descr, "CHOLMOD FACTOR Z U")) 
+	else if (!strcmp(descr, "CHOLMOD FACTOR Z U"))
 	    uplo = 'U';
-        else 
+        else
 	    PY_ERR_TYPE("F is not the CHOLMOD factor of a 'z' matrix");
     }
     Lc = (cholmod_factor *) PyCObject_AsVoidPtr(F);
     if (!(Ac = pack(A, uplo))) return PyErr_NoMemory();
     CHOL(factorize) (Ac, Lc, &Common);
-    CHOL(free_sparse)(&Ac, &Common);    
+    CHOL(free_sparse)(&Ac, &Common);
 
     if (Common.status < 0) switch (Common.status) {
-        case CHOLMOD_OUT_OF_MEMORY: 
+        case CHOLMOD_OUT_OF_MEMORY:
             return PyErr_NoMemory();
 
         default:
@@ -343,15 +343,15 @@ static PyObject* numeric(PyObject *self, PyObject *args)
             return NULL;
     }
 
-    if (Common.status > 0) switch (Common.status) {   
+    if (Common.status > 0) switch (Common.status) {
         case CHOLMOD_NOT_POSDEF:
-            PyErr_SetObject(PyExc_ArithmeticError, Py_BuildValue("i", 
+            PyErr_SetObject(PyExc_ArithmeticError, Py_BuildValue("i",
                 Lc->minor));
             return NULL;
             break;
 
-        case CHOLMOD_DSMALL:  
-            /* This never happens unless we change the default value 
+        case CHOLMOD_DSMALL:
+            /* This never happens unless we change the default value
              * of Common.dbound (0.0).  */
             if (Lc->is_ll)
                 PyErr_Warn(PyExc_RuntimeWarning, "tiny diagonal "\
@@ -369,7 +369,7 @@ static PyObject* numeric(PyObject *self, PyObject *args)
 }
 
 
-static char doc_solve[] = 
+static char doc_solve[] =
     "Solves a sparse set of linear equations with a factored\n"
     "coefficient matrix and an dense matrix as right-hand side.\n\n"
     "solve(F, B, sys=0, nrhs=B.size[1], ldB=max(1,B.size[0], "
@@ -378,11 +378,11 @@ static char doc_solve[] =
     "Solves one of the following systems using the factorization\n"
     "computed by cholmod.numeric:\n\n"
     "   sys   System              sys   System\n"
-    "   0     A*X = B             5     L'*X = B\n" 
-    "   1     L*D*L'*X = B        6     D*X = B\n"       
+    "   0     A*X = B             5     L'*X = B\n"
+    "   1     L*D*L'*X = B        6     D*X = B\n"
     "   2     L*D*X = B           7     P'*X = B\n"
     "   3     D*L'*X = B          8     P*X = B\n"
-    "   4     L*X = B\n\n"       
+    "   4     L*X = B\n\n"
     "If A was factored as P*A*P' = L*L', then D = I in this table.\n"
     "B is stored using the LAPACK and BLAS conventions.  On exit it\n"
     "is overwritten with the solution.\n\n"
@@ -391,7 +391,7 @@ static char doc_solve[] =
     "          cholmod.numeric\n\n"
     "B         dense 'd' or 'z' matrix.  Must have the same type\n"
     "          as A.\n\n"
-    "sys       integer (0 <= sys <= 8)\n\n"  
+    "sys       integer (0 <= sys <= 8)\n\n"
     "nrhs      integer.  If negative, the default value is used.\n\n"
     "ldB       nonnegative integer.  ldB >= max(1,n).  If zero, the\n"
     "          default value is used.\n\n"
@@ -401,16 +401,16 @@ static PyObject* solve(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *B;
     PyObject *F;
-    int i, n, oB=0, ldB=0, nrhs=-1, sys=0; 
+    int i, n, oB=0, ldB=0, nrhs=-1, sys=0;
     char *descr;
     char *kwlist[] = {"F", "B", "sys", "nrhs", "ldB", "offsetB", NULL};
-    int sysvalues[] = { CHOLMOD_A, CHOLMOD_LDLt, CHOLMOD_LD, 
+    int sysvalues[] = { CHOLMOD_A, CHOLMOD_LDLt, CHOLMOD_LD,
         CHOLMOD_DLt, CHOLMOD_L, CHOLMOD_Lt, CHOLMOD_D, CHOLMOD_P,
         CHOLMOD_Pt };
 
     if (!set_options()) return NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiii", kwlist,
         &F, &B, &sys, &nrhs, &ldB, &oB)) return NULL;
 
     if (!PyCObject_Check(F)) err_CO("F");
@@ -418,38 +418,38 @@ static PyObject* solve(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!descr || strncmp(descr, "CHOLMOD FACTOR", 14))
         PY_ERR_TYPE("F is not a CHOLMOD factor");
     cholmod_factor *L = (cholmod_factor *) PyCObject_AsVoidPtr(F);
-    if (L->xtype == CHOLMOD_PATTERN) 
+    if (L->xtype == CHOLMOD_PATTERN)
         PY_ERR(PyExc_ValueError, "called with symbolic factor");
 
     n = L->n;
     if (L->minor<n) PY_ERR(PyExc_ArithmeticError, "singular matrix");
 
-    if (sys < 0 || sys > 8) 
+    if (sys < 0 || sys > 8)
          PY_ERR(PyExc_ValueError, "invalid value for sys");
 
     if (!Matrix_Check(B) || MAT_ID(B) == INT ||
         (MAT_ID(B) == DOUBLE && L->xtype == CHOLMOD_COMPLEX) ||
-        (MAT_ID(B) == COMPLEX && L->xtype == CHOLMOD_REAL))		
+        (MAT_ID(B) == COMPLEX && L->xtype == CHOLMOD_REAL))
             PY_ERR_TYPE("B must a dense matrix of the same numerical "
                 "type as F");
 
-    if (nrhs < 0) nrhs = MAT_NCOLS(B);  
+    if (nrhs < 0) nrhs = MAT_NCOLS(B);
     if (n == 0 || nrhs == 0) return Py_BuildValue("");
     if (ldB == 0) ldB = MAX(1,MAT_NROWS(B));
     if (ldB < MAX(1,n)) err_ld("ldB");
     if (oB < 0) err_nn_int("offsetB");
     if (oB + (nrhs-1)*ldB + n > MAT_LGT(B)) err_buf_len("B");
-  
+
     cholmod_dense *x;
-    cholmod_dense *b = CHOL(allocate_dense)(n, 1, n, 
-        (MAT_ID(B) == DOUBLE ? CHOLMOD_REAL : CHOLMOD_COMPLEX), 
+    cholmod_dense *b = CHOL(allocate_dense)(n, 1, n,
+        (MAT_ID(B) == DOUBLE ? CHOLMOD_REAL : CHOLMOD_COMPLEX),
         &Common);
     if (Common.status == CHOLMOD_OUT_OF_MEMORY) return PyErr_NoMemory();
 
-    void *b_old = b->x;    
+    void *b_old = b->x;
     for (i=0; i<nrhs; i++){
         b->x = MAT_BUF(B) + (i*ldB + oB)*E_SIZE[MAT_ID(B)];
-        x = CHOL(solve) (sysvalues[sys], L, b, &Common);  
+        x = CHOL(solve) (sysvalues[sys], L, b, &Common);
         if (Common.status != CHOLMOD_OK){
             PyErr_SetString(PyExc_ValueError, "solve step failed");
             CHOL(free_dense)(&x, &Common);
@@ -460,13 +460,13 @@ static PyObject* solve(PyObject *self, PyObject *args, PyObject *kwrds)
         CHOL(free_dense)(&x, &Common);
     }
     b->x = b_old;
-    CHOL(free_dense)(&b, &Common);  
+    CHOL(free_dense)(&b, &Common);
 
     return Py_BuildValue("");
 }
 
 
-static char doc_spsolve[] = 
+static char doc_spsolve[] =
     "Solves a sparse set of linear equations with a factored\n"
     "coefficient matrix and sparse righthand side.\n\n"
     "X = spsolve(F, B, sys=0)\n\n"
@@ -474,37 +474,37 @@ static char doc_spsolve[] =
     "Solves one of the following systems using the factorization F\n"
     "computed by cholmod.numeric:\n\n"
     "   sys   System              sys   System\n"
-    "   0     A*X = B             5     L'*X = B\n" 
-    "   1     L*D*L'*X = B        6     D*X = B\n"       
+    "   0     A*X = B             5     L'*X = B\n"
+    "   1     L*D*L'*X = B        6     D*X = B\n"
     "   2     L*D*X = B           7     P'*X = B\n"
     "   3     D*L'*X = B          8     P*X = B\n"
-    "   4     L*X = B\n\n"       
+    "   4     L*X = B\n\n"
     "If A was factored as P*A*P^T = L*L^T, then D = I in this table.\n"
     "On exit B is overwritten with the solution.\n\n"
     "ARGUMENTS\n"
     "F         the factorization object of A computed by\n"
     "          cholmod.numeric\n\n"
     "B         sparse unsymmetric matrix\n\n"
-    "sys       integer (0 <= sys <= 8)\n\n"  
+    "sys       integer (0 <= sys <= 8)\n\n"
     "X         sparse unsymmetric matrix";
 
-static PyObject* spsolve(PyObject *self, PyObject *args, 
+static PyObject* spsolve(PyObject *self, PyObject *args,
     PyObject *kwrds)
 {
     spmatrix *B, *X=NULL;
     cholmod_sparse *Bc=NULL, *Xc=NULL;
     PyObject *F;
     cholmod_factor *L;
-    int n, sys=0; 
+    int n, sys=0;
     char *descr;
     char *kwlist[] = {"F", "B", "sys", NULL};
-    int sysvalues[] = {CHOLMOD_A, CHOLMOD_LDLt, CHOLMOD_LD, 
+    int sysvalues[] = {CHOLMOD_A, CHOLMOD_LDLt, CHOLMOD_LD,
         CHOLMOD_DLt, CHOLMOD_L, CHOLMOD_Lt, CHOLMOD_D, CHOLMOD_P,
         CHOLMOD_Pt };
 
     if (!set_options()) return NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|i", kwlist, &F, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|i", kwlist, &F,
         &B, &sys)) return NULL;
 
     if (!PyCObject_Check(F)) err_CO("F");
@@ -512,45 +512,45 @@ static PyObject* spsolve(PyObject *self, PyObject *args,
     if (!descr || strncmp(descr, "CHOLMOD FACTOR", 14))
         PY_ERR_TYPE("F is not a CHOLMOD factor");
     L = (cholmod_factor *) PyCObject_AsVoidPtr(F);
-    if (L->xtype == CHOLMOD_PATTERN) 
+    if (L->xtype == CHOLMOD_PATTERN)
         PY_ERR(PyExc_ValueError, "called with symbolic factor");
     n = L->n;
     if (L->minor<n) PY_ERR(PyExc_ArithmeticError, "singular matrix");
 
-    if (sys < 0 || sys > 8) 
+    if (sys < 0 || sys > 8)
          PY_ERR(PyExc_ValueError, "invalid value for sys");
-    
-    if (!SpMatrix_Check(B) || 
+
+    if (!SpMatrix_Check(B) ||
         (SP_ID(B) == DOUBLE  && L->xtype == CHOLMOD_COMPLEX) ||
-        (SP_ID(B) == COMPLEX && L->xtype == CHOLMOD_REAL))		
+        (SP_ID(B) == COMPLEX && L->xtype == CHOLMOD_REAL))
             PY_ERR_TYPE("B must a sparse matrix of the same "
                 "numerical type as F");
-    if (SP_NROWS(B) != n) 
+    if (SP_NROWS(B) != n)
         PY_ERR(PyExc_ValueError, "incompatible dimensions for B");
 
     if (!(Bc = create_matrix(B))) return PyErr_NoMemory();
     Xc = CHOL(spsolve)(sysvalues[sys], L, Bc, &Common);
-    free_matrix(Bc);    
+    free_matrix(Bc);
     if (Common.status == CHOLMOD_OUT_OF_MEMORY) return PyErr_NoMemory();
     if (Common.status != CHOLMOD_OK)
         PY_ERR(PyExc_ValueError, "solve step failed");
-    
-    if (!(X = SpMatrix_New(Xc->nrow, Xc->ncol, 
-        ((int_t*)Xc->p)[Xc->ncol], (L->xtype == CHOLMOD_REAL ? DOUBLE : 
+
+    if (!(X = SpMatrix_New(Xc->nrow, Xc->ncol,
+        ((int_t*)Xc->p)[Xc->ncol], (L->xtype == CHOLMOD_REAL ? DOUBLE :
         COMPLEX)))) {
-        CHOL(free_sparse)(&Xc, &Common);    
+        CHOL(free_sparse)(&Xc, &Common);
         return PyErr_NoMemory();
     }
     memcpy(SP_COL(X), Xc->p, (Xc->ncol+1)*sizeof(int_t));
     memcpy(SP_ROW(X), Xc->i, ((int_t *)Xc->p)[Xc->ncol]*sizeof(int_t));
-    memcpy(SP_VAL(X), Xc->x, 
+    memcpy(SP_VAL(X), Xc->x,
         ((int_t *) Xc->p)[Xc->ncol]*E_SIZE[SP_ID(X)]);
-    CHOL(free_sparse)(&Xc, &Common);    
+    CHOL(free_sparse)(&Xc, &Common);
     return (PyObject *) X;
 }
 
 
-static char doc_linsolve[] = 
+static char doc_linsolve[] =
     "Solves a sparse positive definite set of linear equations.\n\n"
     "linsolve(A, B, p=None, uplo='L', nrhs=B.size[1], \n"
     "         ldB=max(1,B.size[0]), offsetB=0)\n\n"
@@ -563,9 +563,9 @@ static char doc_linsolve[] =
     "argument the index of the column at which the factorization\n"
     "failed.\n\n"
     "ARGUMENTS\n"
-    "A         square sparse matrix\n\n"  
+    "A         square sparse matrix\n\n"
     "B         dense 'd' or 'z' matrix.  Must have the same type\n"
-    "          as A.\n\n" 
+    "          as A.\n\n"
     "p         None, or an 'i' matrix of length n that contains\n"
     "          a permutation vector\n\n"
     "uplo      'L' or 'U'.  If uplo is 'L', only the lower triangular\n"
@@ -578,68 +578,68 @@ static char doc_linsolve[] =
     "          default value is used.\n\n"
     "offsetB   nonnegative integer";
 
-static PyObject* linsolve(PyObject *self, PyObject *args, 
+static PyObject* linsolve(PyObject *self, PyObject *args,
     PyObject *kwrds)
 {
     spmatrix *A;
-    matrix *B, *P=NULL; 
-    int i, n, nnz, oB=0, ldB=0, nrhs=-1; 
+    matrix *B, *P=NULL;
+    int i, n, nnz, oB=0, ldB=0, nrhs=-1;
     cholmod_sparse *Ac=NULL;
     cholmod_factor *L=NULL;
     cholmod_dense *x=NULL, *b=NULL;
     void *b_old;
     char uplo='L';
-    char *kwlist[] = {"A", "B", "p", "uplo", "nrhs", "ldB", "offsetB", 
+    char *kwlist[] = {"A", "B", "p", "uplo", "nrhs", "ldB", "offsetB",
         NULL};
-  
+
     if (!set_options()) return NULL;
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Ociii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Ociii", kwlist,
         &A,  &B, &P, &uplo, &nrhs, &ldB, &oB)) return NULL;
 
-    if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)) 
+    if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A))
         PY_ERR_TYPE("A is not a sparse matrix");
     n = SP_NROWS(A);
     nnz = SP_NNZ(A);
-  
+
     if (!Matrix_Check(B) || MAT_ID(B) != SP_ID(A))
         PY_ERR_TYPE("B must be a dense matrix of the same numerical "
             "type as A");
-    if (nrhs < 0) nrhs = MAT_NCOLS(B);  
+    if (nrhs < 0) nrhs = MAT_NCOLS(B);
     if (n == 0 || nrhs == 0) return Py_BuildValue("");
     if (ldB == 0) ldB = MAX(1,MAT_NROWS(B));
     if (ldB < MAX(1,n)) err_ld("ldB");
     if (oB < 0) err_nn_int("offsetB");
     if (oB + (nrhs-1)*ldB + n > MAT_LGT(B)) err_buf_len("B");
-  
+
     if (P) {
         if (!Matrix_Check(P) || MAT_ID(P) != INT) err_int_mtrx("p");
         if (MAT_LGT(P) != n) err_buf_len("p");
-        if (!CHOL(check_perm)(P->buffer, n, n, &Common)) 
+        if (!CHOL(check_perm)(P->buffer, n, n, &Common))
             PY_ERR(PyExc_ValueError, "not a valid permutation");
     }
     if (uplo != 'U' && uplo != 'L') err_char("uplo", "'L', 'U'");
-  
+
     if (!(Ac = pack(A, uplo))) return PyErr_NoMemory();
     L = CHOL(analyze_p)(Ac, P ? MAT_BUFI(P): NULL, NULL, 0, &Common);
     if (Common.status != CHOLMOD_OK){
         free_matrix(Ac);
-        CHOL(free_sparse)(&Ac, &Common);    
-        CHOL(free_factor)(&L, &Common);    
-        if (Common.status == CHOLMOD_OUT_OF_MEMORY) 
+        CHOL(free_sparse)(&Ac, &Common);
+        CHOL(free_factor)(&L, &Common);
+        if (Common.status == CHOLMOD_OUT_OF_MEMORY)
             return PyErr_NoMemory();
         else {
             PyErr_SetString(PyExc_ValueError, "symbolic factorization "
                 "failed");
-            return NULL; 	    
+            return NULL;
         }
     }
-  
+
     CHOL(factorize) (Ac, L, &Common);
-    CHOL(free_sparse)(&Ac, &Common);    
+    CHOL(free_sparse)(&Ac, &Common);
     if (Common.status < 0) {
-        CHOL(free_factor)(&L, &Common);    
+        CHOL(free_factor)(&L, &Common);
         switch (Common.status) {
-            case CHOLMOD_OUT_OF_MEMORY: 
+            case CHOLMOD_OUT_OF_MEMORY:
                 return PyErr_NoMemory();
 
             default:
@@ -648,16 +648,16 @@ static PyObject* linsolve(PyObject *self, PyObject *args,
                 return NULL;
         }
     }
-    if (Common.status > 0) switch (Common.status) {   
+    if (Common.status > 0) switch (Common.status) {
         case CHOLMOD_NOT_POSDEF:
-            PyErr_SetObject(PyExc_ArithmeticError, 
+            PyErr_SetObject(PyExc_ArithmeticError,
                 Py_BuildValue("i", L->minor));
-            CHOL(free_factor)(&L, &Common);    
+            CHOL(free_factor)(&L, &Common);
             return NULL;
             break;
 
-        case CHOLMOD_DSMALL:  
-            /* This never happens unless we change the default value 
+        case CHOLMOD_DSMALL:
+            /* This never happens unless we change the default value
              * of Common.dbound (0.0).  */
             if (L->is_ll)
                 PyErr_Warn(PyExc_RuntimeWarning, "tiny diagonal "
@@ -666,29 +666,29 @@ static PyObject* linsolve(PyObject *self, PyObject *args,
                 PyErr_Warn(PyExc_RuntimeWarning, "tiny diagonal "
                     "elements in D");
             break;
-    
+
         default:
             PyErr_Warn(PyExc_UserWarning, "");
     }
 
     if (L->minor<n) {
-        CHOL(free_factor)(&L, &Common);    
+        CHOL(free_factor)(&L, &Common);
         PY_ERR(PyExc_ArithmeticError, "singular matrix");
     }
-    b = CHOL(allocate_dense)(n, 1, n, (MAT_ID(B) == DOUBLE ? 
+    b = CHOL(allocate_dense)(n, 1, n, (MAT_ID(B) == DOUBLE ?
         CHOLMOD_REAL : CHOLMOD_COMPLEX) , &Common);
-    if (Common.status == CHOLMOD_OUT_OF_MEMORY) { 
-        CHOL(free_factor)(&L, &Common);    
-        CHOL(free_dense)(&b, &Common);    
+    if (Common.status == CHOLMOD_OUT_OF_MEMORY) {
+        CHOL(free_factor)(&L, &Common);
+        CHOL(free_dense)(&b, &Common);
         return PyErr_NoMemory();
     }
-    b_old = b->x;    
+    b_old = b->x;
     for (i=0; i<nrhs; i++) {
         b->x = MAT_BUF(B) + (i*ldB + oB)*E_SIZE[MAT_ID(B)];
         x = CHOL(solve) (CHOLMOD_A, L, b, &Common);
         if (Common.status != CHOLMOD_OK){
             PyErr_SetString(PyExc_ValueError, "solve step failed");
-            CHOL(free_factor)(&L, &Common);    
+            CHOL(free_factor)(&L, &Common);
             b->x = b_old;
             CHOL(free_dense)(&b, &Common);
             CHOL(free_dense)(&x, &Common);
@@ -699,13 +699,13 @@ static PyObject* linsolve(PyObject *self, PyObject *args,
     }
     b->x = b_old;
     CHOL(free_dense)(&b, &Common);
-    CHOL(free_factor)(&L, &Common);    
-    return Py_BuildValue("");      
+    CHOL(free_factor)(&L, &Common);
+    return Py_BuildValue("");
 }
 
 
 
-static char doc_splinsolve[] = 
+static char doc_splinsolve[] =
     "Solves a sparse positive definite set of linear equations with\n"
     "sparse righthand side.\n\n"
     "X = splinsolve(A, B, p=None, uplo='L')\n\n"
@@ -718,15 +718,15 @@ static char doc_splinsolve[] =
     "ARGUMENTS\n"
     "A         square sparse matrix.  Only the lower triangular part\n"
     "          of A is used; the upper triangular part is ignored.\n\n"
-    "B         sparse matrix of the same type as A\n\n" 
+    "B         sparse matrix of the same type as A\n\n"
     "p         None, or an 'i' matrix of length n that contains\n"
     "          a permutation vector";
 
-static PyObject* splinsolve(PyObject *self, PyObject *args, 
+static PyObject* splinsolve(PyObject *self, PyObject *args,
     PyObject *kwrds)
 {
     spmatrix *A, *B, *X;
-    matrix *P=NULL; 
+    matrix *P=NULL;
     int n, nnz;
     cholmod_sparse *Ac=NULL, *Bc=NULL, *Xc=NULL;
     cholmod_factor *L=NULL;
@@ -737,20 +737,20 @@ static PyObject* splinsolve(PyObject *self, PyObject *args,
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Oc", kwlist, &A,
         &B, &P, &uplo)) return NULL;
 
-    if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)) 
+    if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A))
         PY_ERR_TYPE("A is not a square sparse matrix");
     n = SP_NROWS(A);
     nnz = SP_NNZ(A);
 
-    if (!SpMatrix_Check(B) || SP_ID(A) != SP_ID(B)) 
+    if (!SpMatrix_Check(B) || SP_ID(A) != SP_ID(B))
         PY_ERR_TYPE("B must be a sparse matrix of the same type as A");
-    if (SP_NROWS(B) != n) 
+    if (SP_NROWS(B) != n)
         PY_ERR(PyExc_ValueError, "incompatible dimensions for B");
 
     if (P) {
         if (!Matrix_Check(P) || MAT_ID(P) != INT) err_int_mtrx("p");
         if (MAT_LGT(P) != n) err_buf_len("p");
-        if (!CHOL(check_perm)(P->buffer, n, n, &Common)) 
+        if (!CHOL(check_perm)(P->buffer, n, n, &Common))
             PY_ERR(PyExc_ValueError, "not a valid permutation");
     }
 
@@ -759,28 +759,28 @@ static PyObject* splinsolve(PyObject *self, PyObject *args,
 
     L = CHOL(analyze_p) (Ac, P ? MAT_BUFI(P): NULL, NULL, 0, &Common);
     if (Common.status != CHOLMOD_OK){
-        CHOL(free_factor)(&L, &Common);    
-        CHOL(free_sparse)(&Ac, &Common);    
+        CHOL(free_factor)(&L, &Common);
+        CHOL(free_sparse)(&Ac, &Common);
         if (Common.status == CHOLMOD_OUT_OF_MEMORY)
             return PyErr_NoMemory();
         else
             PyErr_SetString(PyExc_ValueError, "symbolic factorization "
                 "failed");
-            return NULL; 	    
+            return NULL;
     }
 
     CHOL(factorize) (Ac, L, &Common);
-    CHOL(free_sparse)(&Ac, &Common);    
-    if (Common.status > 0) switch (Common.status) {   
+    CHOL(free_sparse)(&Ac, &Common);
+    if (Common.status > 0) switch (Common.status) {
         case CHOLMOD_NOT_POSDEF:
-            PyErr_SetObject(PyExc_ArithmeticError, Py_BuildValue("i", 
+            PyErr_SetObject(PyExc_ArithmeticError, Py_BuildValue("i",
                 L->minor));
-            CHOL(free_factor)(&L, &Common);    
+            CHOL(free_factor)(&L, &Common);
             return NULL;
             break;
 
-        case CHOLMOD_DSMALL:  
-            /* This never happens unless we change the default value 
+        case CHOLMOD_DSMALL:
+            /* This never happens unless we change the default value
              * of Common.dbound (0.0).  */
             if (L->is_ll)
                 PyErr_Warn(PyExc_RuntimeWarning, "tiny diagonal "
@@ -795,43 +795,43 @@ static PyObject* splinsolve(PyObject *self, PyObject *args,
     }
 
     if (L->minor<n) {
-        CHOL(free_factor)(&L, &Common);    
+        CHOL(free_factor)(&L, &Common);
         PY_ERR(PyExc_ArithmeticError, "singular matrix");
     }
     if (!(Bc = create_matrix(B))) {
-      CHOL(free_factor)(&L, &Common);    
+      CHOL(free_factor)(&L, &Common);
       return PyErr_NoMemory();
     }
 
     Xc = CHOL(spsolve)(0, L, Bc, &Common);
-    free_matrix(Bc);    
-    CHOL(free_factor)(&L, &Common);    
+    free_matrix(Bc);
+    CHOL(free_factor)(&L, &Common);
     if (Common.status != CHOLMOD_OK){
         CHOL(free_sparse)(&Xc, &Common);
-        if (Common.status == CHOLMOD_OUT_OF_MEMORY) 
+        if (Common.status == CHOLMOD_OUT_OF_MEMORY)
             return PyErr_NoMemory();
         else
             PY_ERR(PyExc_ValueError, "solve step failed");
     }
 
-    if (!(X = SpMatrix_New(Xc->nrow, Xc->ncol, 
+    if (!(X = SpMatrix_New(Xc->nrow, Xc->ncol,
         ((int_t*)Xc->p)[Xc->ncol], SP_ID(A)))) {
-        CHOL(free_sparse)(&Xc, &Common);    
+        CHOL(free_sparse)(&Xc, &Common);
         return PyErr_NoMemory();
     }
     memcpy(SP_COL(X), (int_t *) Xc->p, (Xc->ncol+1)*sizeof(int_t));
-    memcpy(SP_ROW(X), (int_t *) Xc->i, 
+    memcpy(SP_ROW(X), (int_t *) Xc->i,
         ((int_t *) Xc->p)[Xc->ncol]*sizeof(int_t));
-    memcpy(SP_VAL(X), (double *) Xc->x, 
+    memcpy(SP_VAL(X), (double *) Xc->x,
         ((int_t *) Xc->p)[Xc->ncol]*E_SIZE[SP_ID(X)]);
-    CHOL(free_sparse)(&Xc, &Common);    
+    CHOL(free_sparse)(&Xc, &Common);
     return (PyObject *) X;
 }
 
 
-static char doc_diag[] = 
+static char doc_diag[] =
     "Returns the diagonal of a Cholesky factor.\n\n"
-    "D = diag(F)\n\n" 
+    "D = diag(F)\n\n"
     "PURPOSE\n"
     "Returns the diagonal of the Cholesky factor L in a \n"
     "factorization P*A*P^T = L*L^T or P*A*P^T = L*L^H.\n\n"
@@ -856,35 +856,35 @@ static PyObject* diag(PyObject *self, PyObject *args)
     if (!set_options()) return NULL;
     if (!PyArg_ParseTuple(args, "O", &F)) return NULL;
 
-    if (!PyCObject_Check(F)) err_CO("F"); 
+    if (!PyCObject_Check(F)) err_CO("F");
     descr = PyCObject_GetDesc(F);
     if (!descr || strncmp(descr, "CHOLMOD FACTOR", 14))
         PY_ERR_TYPE("F is not a CHOLMOD factor");
     L = (cholmod_factor *) PyCObject_AsVoidPtr(F);
 
     /* Check factorization */
-    if (L->xtype == CHOLMOD_PATTERN  || L->minor<L->n || !L->is_ll 
-        || !L->is_super) 
+    if (L->xtype == CHOLMOD_PATTERN  || L->minor<L->n || !L->is_ll
+        || !L->is_super)
         PY_ERR(PyExc_ValueError, "F must be a nonsingular supernodal "
             "Cholesky factor");
-    if (!(d = Matrix_New(L->n,1,L->xtype == CHOLMOD_REAL ? DOUBLE : 
+    if (!(d = Matrix_New(L->n,1,L->xtype == CHOLMOD_REAL ? DOUBLE :
         COMPLEX))) return PyErr_NoMemory();
 
     strt = 0;
     for (k=0; k<L->nsuper; k++){
-	/* x[L->px[k], .... ,L->px[k+1]-1] is a dense lower-triangular 
-	 * nrowx times ncols matrix.  We copy its diagonal to 
+	/* x[L->px[k], .... ,L->px[k+1]-1] is a dense lower-triangular
+	 * nrowx times ncols matrix.  We copy its diagonal to
 	 * d[strt, ..., strt+ncols-1] */
 
-        ncols = (int)((int_t *) L->super)[k+1] - 
-            ((int_t *) L->super)[k]; 
-        nrows = (int)((int_t *) L->pi)[k+1] - ((int_t *) L->pi)[k]; 
+        ncols = (int)((int_t *) L->super)[k+1] -
+            ((int_t *) L->super)[k];
+        nrows = (int)((int_t *) L->pi)[k+1] - ((int_t *) L->pi)[k];
         incy = nrows+1;
         if (MAT_ID(d) == DOUBLE)
-	    dcopy_(&ncols, ((double *) L->x) + ((int_t *) L->px)[k], 
+	    dcopy_(&ncols, ((double *) L->x) + ((int_t *) L->px)[k],
                 &incy, MAT_BUFD(d)+strt, &incx);
         else
-	    zcopy_(&ncols, ((complex *) L->x) + ((int_t *) L->px)[k], 
+	    zcopy_(&ncols, ((complex *) L->x) + ((int_t *) L->px)[k],
                 &incy, MAT_BUFZ(d)+strt, &incx);
         strt += ncols;
     }
@@ -901,22 +901,22 @@ static PyObject* getfactor(PyObject *self, PyObject *args)
 
     if (!set_options()) return NULL;
     if (!PyArg_ParseTuple(args, "O", &F)) return NULL;
-  
-    if (!PyCObject_Check(F)) err_CO("F"); 
+
+    if (!PyCObject_Check(F)) err_CO("F");
     descr = PyCObject_GetDesc(F);
     if (!descr || strncmp(descr, "CHOLMOD FACTOR", 14))
         PY_ERR_TYPE("F is not a CHOLMOD factor");
     Lf = (cholmod_factor *) PyCObject_AsVoidPtr(F);
-  
+
     /* Check factorization */
-    if (Lf->xtype == CHOLMOD_PATTERN) 
+    if (Lf->xtype == CHOLMOD_PATTERN)
         PY_ERR(PyExc_ValueError, "F must be a numeric Cholesky factor");
 
     if (!(Ls = CHOL(factor_to_sparse)(Lf, &Common)))
         return PyErr_NoMemory();
 
-    spmatrix *ret = SpMatrix_New(Ls->nrow, Ls->ncol, Ls->nzmax, 
-       (Ls->xtype == CHOLMOD_REAL ? DOUBLE : COMPLEX)); 
+    spmatrix *ret = SpMatrix_New(Ls->nrow, Ls->ncol, Ls->nzmax,
+       (Ls->xtype == CHOLMOD_REAL ? DOUBLE : COMPLEX));
     if (!ret) {
         CHOL(free_sparse)(&Ls, &Common);
         return PyErr_NoMemory();
@@ -932,27 +932,27 @@ static PyObject* getfactor(PyObject *self, PyObject *args)
 
 
 static PyMethodDef cholmod_functions[] = {
-  {"symbolic", (PyCFunction) symbolic, METH_VARARGS|METH_KEYWORDS, 
+  {"symbolic", (PyCFunction) symbolic, METH_VARARGS|METH_KEYWORDS,
    doc_symbolic},
-  {"numeric", (PyCFunction) numeric, METH_VARARGS|METH_KEYWORDS, 
+  {"numeric", (PyCFunction) numeric, METH_VARARGS|METH_KEYWORDS,
    doc_numeric},
-  {"solve", (PyCFunction) solve, METH_VARARGS|METH_KEYWORDS, 
+  {"solve", (PyCFunction) solve, METH_VARARGS|METH_KEYWORDS,
    doc_solve},
-  {"spsolve", (PyCFunction) spsolve, METH_VARARGS|METH_KEYWORDS, 
+  {"spsolve", (PyCFunction) spsolve, METH_VARARGS|METH_KEYWORDS,
    doc_spsolve},
-  {"linsolve", (PyCFunction) linsolve, METH_VARARGS|METH_KEYWORDS, 
+  {"linsolve", (PyCFunction) linsolve, METH_VARARGS|METH_KEYWORDS,
    doc_linsolve},
-  {"splinsolve", (PyCFunction) splinsolve, METH_VARARGS|METH_KEYWORDS, 
+  {"splinsolve", (PyCFunction) splinsolve, METH_VARARGS|METH_KEYWORDS,
    doc_splinsolve},
   {"diag", (PyCFunction) diag, METH_VARARGS|METH_KEYWORDS, doc_diag},
-  {"getfactor", (PyCFunction) getfactor, METH_VARARGS|METH_KEYWORDS, 
+  {"getfactor", (PyCFunction) getfactor, METH_VARARGS|METH_KEYWORDS,
    ""},
   {NULL}  /* Sentinel */
 };
 
 PyMODINIT_FUNC initcholmod(void)
 {
-    CHOL(start) (&Common);   
+    CHOL(start) (&Common);
 
     cholmod_module = Py_InitModule3("cvxopt.cholmod", cholmod_functions,
         cholmod__doc__);
diff --git a/src/C/cvxopt.h b/src/C/cvxopt.h
index 490c7f1..9c38d06 100644
--- a/src/C/cvxopt.h
+++ b/src/C/cvxopt.h
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,9 +21,11 @@
 #include "structmember.h"
 #include "blas_redefines.h"
 
+#include "assert.h"
+
 /* ANSI99 complex is disabled during build of CHOLMOD */
 
-#ifndef NO_ANSI99_COMPLEX 
+#ifndef NO_ANSI99_COMPLEX
 #include "complex.h"
 #define MAT_BUFZ(O)  ((complex *)((matrix *)O)->buffer)
 #endif
@@ -34,11 +36,11 @@
 /*
 static void * malloc_aligned(size_t size) {
   void *p = NULL;
-  if (!posix_memalign(&p, 16, size)) 
+  if (!posix_memalign(&p, 16, size))
     return p;
-  else 
-    return NULL;      
-} 
+  else
+    return NULL;
+}
 
 #define malloc(size) malloc_aligned(size)
 */
@@ -52,7 +54,7 @@ static void * malloc_aligned(size_t size) {
 typedef struct {
   PyObject_HEAD
   void *buffer;          /* in column-major-mode array of type 'id' */
-  int   nrows, ncols;    /* number of rows and columns */
+  int_t nrows, ncols;    /* number of rows and columns */
   int   id;              /* DOUBLE, INT, COMPLEX */
 } matrix;
 
@@ -71,23 +73,23 @@ typedef struct {
 
 #ifdef BASE_MODULE
 
-#define Matrix_Check(v) ((v)->ob_type == &matrix_tp) 
-#define SpMatrix_Check(v) ((v)->ob_type == &spmatrix_tp) 
+#define Matrix_Check(v) ((v)->ob_type == &matrix_tp)
+#define SpMatrix_Check(v) ((v)->ob_type == &spmatrix_tp)
 
 #else
 
 static void **cvxopt_API;
 
-#define Matrix_New (*(matrix * (*)(int, int, int)) cvxopt_API[0])
+#define Matrix_New (*(matrix * (*)(int_t, int_t, int)) cvxopt_API[0])
 #define Matrix_NewFromMatrix (*(matrix * (*)(matrix *, int)) cvxopt_API[1])
 #define Matrix_NewFromList (*(matrix * (*)(PyObject *, int)) cvxopt_API[2])
 #define Matrix_Check (*(int * (*)(void *)) cvxopt_API[3])
 
-#define SpMatrix_New (*(spmatrix * (*)(int, int, int, int)) cvxopt_API[4])
+#define SpMatrix_New (*(spmatrix * (*)(int_t, int_t, int_t, int)) cvxopt_API[4])
 #define SpMatrix_NewFromSpMatrix \
   (*(spmatrix * (*)(spmatrix *, int)) cvxopt_API[5])
 #define SpMatrix_NewFromIJV \
-  (*(spmatrix * (*)(matrix *, matrix *, matrix *, int, int, int)) \
+  (*(spmatrix * (*)(matrix *, matrix *, matrix *, int_t, int_t, int)) \
       cvxopt_API[6])
 #define SpMatrix_Check (*(int * (*)(void *)) cvxopt_API[7])
 
@@ -96,7 +98,7 @@ static int
 import_cvxopt(void)
 {
   PyObject *module = PyImport_ImportModule("cvxopt.base");
-    
+
   if (module != NULL) {
     PyObject *c_api_object = PyObject_GetAttrString(module, "_C_API");
     if (c_api_object == NULL)
@@ -111,16 +113,16 @@ import_cvxopt(void)
 #endif
 
 /*
- * Below this line are non-essential convenience macros 
+ * Below this line are non-essential convenience macros
  */
 
 #define MAT_BUF(O)   ((matrix *)O)->buffer
-#define MAT_BUFI(O)  ((int_t *)((matrix *)O)->buffer) 
+#define MAT_BUFI(O)  ((int_t *)((matrix *)O)->buffer)
 #define MAT_BUFD(O)  ((double *)((matrix *)O)->buffer)
 #define MAT_BUFZ(O)  ((complex *)((matrix *)O)->buffer)
 
-#define MAT_NROWS(O) ((matrix *)O)->nrows 
-#define MAT_NCOLS(O) ((matrix *)O)->ncols 
+#define MAT_NROWS(O) ((matrix *)O)->nrows
+#define MAT_NCOLS(O) ((matrix *)O)->ncols
 #define MAT_LGT(O)   (MAT_NROWS(O)*MAT_NCOLS(O))
 #define MAT_ID(O)    ((matrix *)O)->id
 
@@ -128,7 +130,7 @@ import_cvxopt(void)
 #define SP_NROWS(O)  ((spmatrix *)O)->obj->nrows
 #define SP_LGT(O)    (SP_NROWS(O)*SP_NCOLS(O))
 #define SP_NNZ(O)    ((spmatrix *)O)->obj->colptr[SP_NCOLS(O)]
-#define SP_ID(O)     ((spmatrix *)O)->obj->id    
+#define SP_ID(O)     ((spmatrix *)O)->obj->id
 #define SP_COL(O)    ((spmatrix *)O)->obj->colptr
 #define SP_ROW(O)    ((spmatrix *)O)->obj->rowind
 #define SP_VAL(O)    ((spmatrix *)O)->obj->values
@@ -139,4 +141,4 @@ import_cvxopt(void)
 #define CCS_NCOLS(O) ((ccs *)O)->ncols
 #define CCS_NNZ(O)   ((ccs *)O)->colptr[CCS_NCOLS(O)]
 
-#endif 
+#endif
diff --git a/src/C/dense.c b/src/C/dense.c
index c31d221..add49a0 100644
--- a/src/C/dense.c
+++ b/src/C/dense.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,28 +21,28 @@
 
 #include "Python.h"
 #include "cvxopt.h"
-#include "misc.h" 
+#include "misc.h"
 
 #include <complexobject.h>
 
 /* NumPy array protocol */
 typedef struct {
-     int version;       
-     int nd;            
-     char typekind;     
-     int itemsize;      
-     int flags;         
-     int_t *shape; 
-     int_t *strides;
-     void *data;           
- } PyArrayInterface;
-
-static const char PY_ARRAY_TC[3] = { 'i', 'f', 'c' }; 
+  int version;
+  int nd;
+  char typekind;
+  int itemsize;
+  int flags;
+  int_t *shape;
+  int_t *strides;
+  void *data;
+} PyArrayInterface;
+
+static const char PY_ARRAY_TC[3] = { 'i', 'f', 'c' };
 
 /* prototyping and forward declarations */
 extern void (*axpy[])(int *, number *, void *, int *, void *, int *) ;
 extern void (*scal[])(int *, number *, void *, int *) ;
-extern void (*gemm[])(char *, char *, int *, int *, int *, void *, void *, 
+extern void (*gemm[])(char *, char *, int *, int *, int *, void *, void *,
     int *, void *, int *, void *, void *, int *) ;
 extern void (*mtx_abs[])(void *, void *, int) ;
 extern int (*div_array[])(void *, number, int) ;
@@ -62,7 +62,7 @@ extern PyObject *base_mod;
 extern PyTypeObject spmatrix_tp ;
 
 PyTypeObject matrix_tp ;
-matrix * Matrix_NewFromNumber(int , int , int , void *, int ) ;
+matrix * Matrix_NewFromNumber(int_t , int_t , int_t , void *, int ) ;
 static PyNumberMethods matrix_as_number ;
 static PyObject * matrix_iter(matrix *) ;
 
@@ -78,24 +78,24 @@ void zgemm_(char *, char *, int *, int *, int *, complex *, complex *,
 
 
 
-static const char err_mtx_list2matrix[][35] = 
-  {"not an integer list", 
-   "not a floating point list",
-   "not a complex floating point list" };
+static const char err_mtx_list2matrix[][35] =
+    {"not an integer list",
+        "not a floating point list",
+        "not a complex floating point list" };
 
 #define free_convert_mtx_alloc(O1, O2, id) { \
-if (MAT_BUF(O1) != O2) { \
-  free(MAT_BUF(O1)); MAT_BUF(O1) = O2; MAT_ID(O1) = id; \
-  } \
+    if (MAT_BUF(O1) != O2) { \
+      free(MAT_BUF(O1)); MAT_BUF(O1) = O2; MAT_ID(O1) = id; \
+    } \
 }
 
 #define free_lists_exit(argI,argJ,I,J,ret) { \
-   if (argI && !Matrix_Check(argI)) { Py_XDECREF(I); } \
+    if (argI && !Matrix_Check(argI)) { Py_XDECREF(I); } \
     if (argJ && !Matrix_Check(argJ)) { Py_XDECREF(J); } \
     return ret; }
 
 
-static int convert_mtx(matrix *src, void *dest, int id) 
+static int convert_mtx(matrix *src, void *dest, int id)
 {
   if (PY_NUMBER((PyObject *)src))
     return convert_num[id](dest, src, 1, 0);
@@ -106,62 +106,58 @@ static int convert_mtx(matrix *src, void *dest, int id)
   }
 
   int_t i;
-  for (i=0; i<MAT_LGT(src); i++) 
-    if (convert_num[id](dest + i*E_SIZE[id], src, 0,i)) return -1;    
-  
+  for (i=0; i<MAT_LGT(src); i++)
+    if (convert_num[id](dest + i*E_SIZE[id], src, 0,i)) return -1;
+
   return 0;
 }
 
-void * convert_mtx_alloc(matrix *src, int id) 
+void * convert_mtx_alloc(matrix *src, int id)
 {
-  void *ptr;  
+  void *ptr;
   if (MAT_ID(src) == id) return MAT_BUF(src);
-  
+
   if (!(ptr = malloc(E_SIZE[id]*MAT_LGT(src)))) return NULL;
 
   int_t i;
-  for (i=0; i<MAT_LGT(src); i++) 
-    if (convert_num[id](ptr + i*E_SIZE[id], src, 0,i)) 
-    { free(ptr); return NULL; }
-  
+  for (i=0; i<MAT_LGT(src); i++)
+    if (convert_num[id](ptr + i*E_SIZE[id], src, 0,i))
+      { free(ptr); return NULL; }
+
   return ptr;
 }
 
 
 /*
   Creates an unpopulated "empty" matrix. In API
-*/
-matrix * Matrix_New(int nrows, int ncols, int id)
+ */
+matrix * Matrix_New(int_t nrows, int_t ncols, int id)
 {
   matrix *a;
   if ((nrows < 0) || (ncols < 0) || (id < INT) || (id > COMPLEX)) {
     PyErr_BadInternalCall();
     return NULL;
   }
-  
+
   if (!(a = (matrix *)matrix_tp.tp_alloc(&matrix_tp, 0)))
     return NULL;
-  
-  a->id = id; a->nrows = nrows; a->ncols = ncols;  
-  if (!(a->buffer =  malloc(E_SIZE[id]*nrows*ncols))) {
+
+  a->id = id; a->nrows = nrows; a->ncols = ncols;
+  if (!(a->buffer =  calloc(nrows*ncols,E_SIZE[id]))) {
     a->ob_type->tp_free((PyObject*)a);
     return (matrix *)PyErr_NoMemory();
   }
 
-  int i;
-  for (i=0; i<MAT_LGT(a); i++)
-    write_num[MAT_ID(a)](MAT_BUF(a), i, &Zero[MAT_ID(a)], 0);
-
   return a;
 }
 
 /*
   Creates a copy of matrix as a new object. In API.
-*/
+ */
 matrix *Matrix_NewFromMatrix(matrix *src, int id)
 {
   matrix *a;
-  
+
   if (PY_NUMBER((PyObject *)src))
     return Matrix_NewFromNumber(1, 1, id, src, 1);
 
@@ -177,24 +173,24 @@ matrix *Matrix_NewFromMatrix(matrix *src, int id)
 
 /*
   Creates a matrix from a PyArrayInterface.
-*/
+ */
 matrix *Matrix_NewFromArrayStruct(PyObject *obj, int id, int_t *ndim)
 {
   PyObject *cobj = PyObject_GetAttrString(obj, "__array_struct__");
   PyArrayInterface *src =  (PyArrayInterface *)PyCObject_AsVoidPtr(cobj);
 
-  if (src->version != 2) 
+  if (src->version != 2)
     PY_ERR(PyExc_AssertionError, "unexpected format in array structure");
-  
+
   if (src->nd != 1 && src->nd != 2)
     PY_ERR(PyExc_TypeError, "imported array must have 1 or 2 dimensions");
-  
+
   int src_id;
   switch (src->typekind) {
   case 'i' : src_id = INT; break;
   case 'f' : src_id = DOUBLE; break;
   case 'c' : src_id = COMPLEX; break;
-  default: 
+  default:
     Py_DECREF(cobj); PY_ERR_TYPE("invalid array type");
   }
 
@@ -207,7 +203,7 @@ matrix *Matrix_NewFromArrayStruct(PyObject *obj, int id, int_t *ndim)
   /* XXX: revise flags check */
   if (!(src->flags & 0x001) && !(src->flags & 0x002)) {
     Py_DECREF(cobj);
-    PY_ERR_TYPE("error converting array");    
+    PY_ERR_TYPE("error converting array");
   }
 
   *ndim = src->nd;
@@ -216,42 +212,42 @@ matrix *Matrix_NewFromArrayStruct(PyObject *obj, int id, int_t *ndim)
     Py_DECREF(cobj); return (matrix *)PyErr_NoMemory();
   }
 
-  int i, j, cnt;
-  
+  int_t i, j, cnt;
+
   for (j=0, cnt=0; j<MAT_NCOLS(a); j++) {
     for (i=0; i<src->shape[0]; i++, cnt++) {
 
       number n;
       switch (id) {
-      case INT : 
-	MAT_BUFI(a)[cnt] = 
-	  *(int_t *)(src->data+i*src->strides[0]+j*src->strides[1]); 
-	break;
+      case INT :
+        MAT_BUFI(a)[cnt] =
+            *(int_t *)(src->data+i*src->strides[0]+j*src->strides[1]);
+        break;
       case DOUBLE:
-	switch (src_id) {
-	case INT: 
-	  n.d = *(int_t *)(src->data + i*src->strides[0]+j*src->strides[1]);
-	  break;
-	case DOUBLE:
-	  n.d = *(double *)(src->data + i*src->strides[0]+j*src->strides[1]);
-	  break;
-	}
-	MAT_BUFD(a)[cnt] = n.d;
-	break;
-      case COMPLEX:
-	switch (src_id) {
-	case INT: 
-	  n.z = *(int_t *)(src->data+i*src->strides[0]+j*src->strides[1]);
-	  break;
-	case DOUBLE:
-	  n.z = *(double *)(src->data+i*src->strides[0]+j*src->strides[1]);
-	  break;
-	case COMPLEX:
-	  n.z = *(complex *)(src->data+i*src->strides[0]+j*src->strides[1]);
-	  break;
-	}
-	MAT_BUFZ(a)[cnt] = n.z;
-	break;
+        switch (src_id) {
+        case INT:
+          n.d = *(int_t *)(src->data + i*src->strides[0]+j*src->strides[1]);
+          break;
+        case DOUBLE:
+          n.d = *(double *)(src->data + i*src->strides[0]+j*src->strides[1]);
+          break;
+        }
+        MAT_BUFD(a)[cnt] = n.d;
+        break;
+        case COMPLEX:
+          switch (src_id) {
+          case INT:
+            n.z = *(int_t *)(src->data+i*src->strides[0]+j*src->strides[1]);
+            break;
+          case DOUBLE:
+            n.z = *(double *)(src->data+i*src->strides[0]+j*src->strides[1]);
+            break;
+          case COMPLEX:
+            n.z = *(complex *)(src->data+i*src->strides[0]+j*src->strides[1]);
+            break;
+          }
+          MAT_BUFZ(a)[cnt] = n.z;
+          break;
       }
     }
   }
@@ -262,41 +258,41 @@ matrix *Matrix_NewFromArrayStruct(PyObject *obj, int id, int_t *ndim)
 
 /*
   Generates a matrix with all entries equal.
-*/
+ */
 matrix *
-Matrix_NewFromNumber(int nrows, int ncols, int id, void *val, int val_id)
+Matrix_NewFromNumber(int_t nrows, int_t ncols, int_t id, void *val, int val_id)
 {
 
-  int i;
+  int_t i;
   matrix *a = Matrix_New(nrows, ncols, id);
   if (!a) return (matrix *)PyErr_NoMemory();
 
-  number n; 
+  number n;
   if (convert_num[id](&n, val, val_id, 0)) { Py_DECREF(a); return NULL; }
   for (i=0; i<MAT_LGT(a); i++) write_num[id](MAT_BUF(a), i, &n, 0);
-  
+
   return a;
 }
 
 /*
   Converts a Python list to a matrix. Part of API
-*/
-matrix * Matrix_NewFromSequence(PyObject *x, int id) 
+ */
+matrix * Matrix_NewFromSequence(PyObject *x, int id)
 {
-  int i, len = PySequence_Size(x);
+  int_t i, len = PySequence_Size(x);
   PyObject *seq = PySequence_Fast(x, "list is not iterable");
   if (!seq) return NULL;
-  
+
   if (id == -1) {
     for (i=0; i<len; i++) {
       PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
       if (!PY_NUMBER(item)) {
-	Py_DECREF(seq); PY_ERR_TYPE("non-numeric element in list");
+        Py_DECREF(seq); PY_ERR_TYPE("non-numeric element in list");
       }
-      
+
       id = MAX(id, get_id(item, 1));
-    }    
+    }
   }
 
   if (!len) return Matrix_New(0, 1, (id < 0 ? INT : id));
@@ -306,9 +302,9 @@ matrix * Matrix_NewFromSequence(PyObject *x, int id)
 
   for (i=0; i<len; i++) {
     PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
     if (!PY_NUMBER(item)) {
-      Py_DECREF(seq); Py_DECREF(L); 
+      Py_DECREF(seq); Py_DECREF(L);
       PY_ERR_TYPE("non-numeric type in list");
     }
 
@@ -323,68 +319,72 @@ matrix * Matrix_NewFromSequence(PyObject *x, int id)
   return L;
 }
 
-matrix * dense(spmatrix *self) 
+matrix * dense(spmatrix *self)
 {
-  matrix *A; 
-  int_t i, j, k; 
-  
+  matrix *A;
+  int_t j, k;
+
   if (!(A = Matrix_New(SP_NROWS(self),SP_NCOLS(self),SP_ID(self))))
     return (matrix *)PyErr_NoMemory();
 
-  for (i=0; i<SP_LGT(self); i++)
-    write_num[SP_ID(self)](MAT_BUF(A),i,&Zero,0);
+  if (SP_ID(self) == DOUBLE) {
+    for (j=0; j<SP_NCOLS(self); j++)
+      for (k=SP_COL(self)[j]; k<SP_COL(self)[j+1]; k++) {
+        MAT_BUFD(A)[SP_ROW(self)[k] + j*MAT_NROWS(A)] = SP_VALD(self)[k];
+      }
+  } else {
+    for (j=0; j<SP_NCOLS(self); j++)
+      for (k=SP_COL(self)[j]; k<SP_COL(self)[j+1]; k++) {
+        MAT_BUFZ(A)[SP_ROW(self)[k] + j*MAT_NROWS(A)] = SP_VALZ(self)[k];
+      }
+  }
 
-  for (k=0; k<SP_NCOLS(self); k++)
-    for (j=SP_COL(self)[k]; j<SP_COL(self)[k+1]; j++) {
-      write_num[SP_ID(self)](MAT_BUF(A),k*SP_NROWS(self)+SP_ROW(self)[j],
-	  SP_VAL(self), j);
-    }
   return A;
 }
 
 int convert_array(void *dest, void *src, int dest_id, int src_id, int n);
 
 matrix * dense_concat(PyObject *L, int id_arg)
-{ 
-  int m=0, n=0, mk=0, nk=0, i=0, j, id = 0;
+{
+  int_t m=0, n=0, mk=0, nk=0, i=0, j, id = 0;
   PyObject *col;
-  
-  int single_col = (PyList_GET_SIZE(L) > 0 && 
+
+  int single_col = (PyList_GET_SIZE(L) > 0 &&
       !PyList_Check(PyList_GET_ITEM(L, 0)));
 
   for (j=0; j<(single_col ? 1 : PyList_GET_SIZE(L)); j++) {
 
     col = (single_col ? L : PyList_GET_ITEM(L, j));
-    if (!PyList_Check(col))  
+    if (!PyList_Check(col))
       PY_ERR_TYPE("invalid type in list");
-    
+
     mk = 0;
     for (i=0; i<PyList_GET_SIZE(col); i++) {
       PyObject *Lij = PyList_GET_ITEM(col, i);
-      if (!Matrix_Check(Lij) && !SpMatrix_Check(Lij) && !PY_NUMBER(Lij)) 
-	PY_ERR_TYPE("invalid type in list");
+      if (!Matrix_Check(Lij) && !SpMatrix_Check(Lij) && !PY_NUMBER(Lij))
+        PY_ERR_TYPE("invalid type in list");
 
       int blk_nrows, blk_ncols;
       if (Matrix_Check(Lij) || SpMatrix_Check(Lij)) {
-	blk_nrows = X_NROWS(Lij); blk_ncols = X_NCOLS(Lij);
-	id = MAX(id, X_ID(Lij));
+        blk_nrows = X_NROWS(Lij); blk_ncols = X_NCOLS(Lij);
+        id = MAX(id, X_ID(Lij));
       } else {
-	blk_nrows = 1; blk_ncols = 1;
-	id = MAX(id, get_id(Lij,1));
+        blk_nrows = 1; blk_ncols = 1;
+        id = MAX(id, get_id(Lij,1));
       }
-	
+
       if (i==0) {
-	nk = blk_ncols; n += nk;
-	mk = blk_nrows; 
+        nk = blk_ncols; n += nk;
+        mk = blk_nrows;
       } else {
-	if (blk_ncols != nk) 
-	  PY_ERR_TYPE("incompatible dimensions of subblocks");
-	mk += blk_nrows;
+        if (blk_ncols != nk)
+          PY_ERR_TYPE("incompatible dimensions of subblocks");
+        mk += blk_nrows;
       }
     }
-    if (j==0) 
+    if (j==0)
       m = mk;
-    else if (m != mk) PY_ERR_TYPE("incompatible dimensions of subblocks");   
+    else if (m != mk) PY_ERR_TYPE("incompatible dimensions of subblocks");
   }
 
   if ((id_arg >= 0) && (id_arg < id))
@@ -399,36 +399,36 @@ matrix * dense_concat(PyObject *L, int id_arg)
   for (j=0; j<(single_col ? 1 : PyList_GET_SIZE(L)); j++) {
     col = (single_col ? L : PyList_GET_ITEM(L, j));
 
-    mk = 0;  
+    mk = 0;
     int blk_nrows = 0, blk_ncols = 0;
     for (i=0; i<PyList_GET_SIZE(col); i++) {
       PyObject *Lij = PyList_GET_ITEM(col, i);
 
       if (Matrix_Check(Lij) || SpMatrix_Check(Lij)) {
-	blk_nrows = X_NROWS(Lij); blk_ncols = X_NCOLS(Lij);
+        blk_nrows = X_NROWS(Lij); blk_ncols = X_NCOLS(Lij);
       } else {
-	blk_nrows = 1; blk_ncols = 1;
+        blk_nrows = 1; blk_ncols = 1;
       }
 
       int ik, jk;
       for (jk=0; jk<blk_ncols; jk++) {
-	
-	if (Matrix_Check(Lij)) {
-	  for (ik=0; ik<blk_nrows; ik++) 
-	    convert_num[id](MAT_BUF(A) + (mk+ik+(nk+jk)*m)*E_SIZE[id],
-		Lij, 0, ik + jk*blk_nrows);
-
-	} else if (SpMatrix_Check(Lij)) {
-	  for (ik=SP_COL(Lij)[jk]; ik<SP_COL(Lij)[jk+1]; ik++) 
-	    convert_array(MAT_BUF(A) + ((nk+jk)*m+mk+SP_ROW(Lij)[ik])*
-		E_SIZE[id], SP_VAL(Lij) + ik*E_SIZE[SP_ID(Lij)], 
-		id, SP_ID(Lij), 1);	      
-
-	} else {
-	  
-	  convert_num[id](MAT_BUF(A) + (mk+(nk+jk)*m)*E_SIZE[id], 
-	      Lij, 1, 0);
-	}
+
+        if (Matrix_Check(Lij)) {
+          for (ik=0; ik<blk_nrows; ik++)
+            convert_num[id](MAT_BUF(A) + (mk+ik+(nk+jk)*m)*E_SIZE[id],
+                Lij, 0, ik + jk*blk_nrows);
+
+        } else if (SpMatrix_Check(Lij)) {
+          for (ik=SP_COL(Lij)[jk]; ik<SP_COL(Lij)[jk+1]; ik++)
+            convert_array(MAT_BUF(A) + ((nk+jk)*m+mk+SP_ROW(Lij)[ik])*
+                E_SIZE[id], SP_VAL(Lij) + ik*E_SIZE[SP_ID(Lij)],
+                id, SP_ID(Lij), 1);
+
+        } else {
+
+          convert_num[id](MAT_BUF(A) + (mk+(nk+jk)*m)*E_SIZE[id],
+              Lij, 1, 0);
+        }
       }
       mk += blk_nrows;
     }
@@ -449,21 +449,21 @@ matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
   PyObject *Objx = NULL, *size = NULL;
   static char *kwlist[] = { "x", "size", "tc", NULL};
- 
-  int nrows=0, ncols=0;
+
+  int_t nrows=0, ncols=0;
   char tc = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOc:matrix", kwlist, 
-	  &Objx, &size, &tc))
+  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOc:matrix", kwlist,
+      &Objx, &size, &tc))
     return NULL;
 
-  if (size && !PyArg_ParseTuple(size, "ii", &nrows, &ncols)) 
+  if (size && !PyArg_ParseTuple(size, "ll", &nrows, &ncols))
     PY_ERR_TYPE("invalid dimension tuple") ;
 
-  if (nrows < 0 || ncols < 0) 
+  if (nrows < 0 || ncols < 0)
     PY_ERR_TYPE("dimensions must be non-negative");
 
-  if (tc && !(VALID_TC_MAT(tc))) PY_ERR_TYPE("tc must be 'i', 'd' or 'z'");  
+  if (tc && !(VALID_TC_MAT(tc))) PY_ERR_TYPE("tc must be 'i', 'd' or 'z'");
   int id = (tc ? TC2ID(tc) : -1);
 
   if (!Objx && size) PY_ERR_TYPE("invalid arguments");
@@ -472,21 +472,25 @@ matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
   matrix *ret = NULL;
   /* x is a number */
-  if (PY_NUMBER(Objx)) 
+  if (PY_NUMBER(Objx))
     return (PyObject *)
-      Matrix_NewFromNumber(MAX(nrows, size ? 0 : 1),
-	  MAX(ncols, size ? 0 : 1), (id == -1 ? get_id(Objx,1):id),Objx,1);
+    Matrix_NewFromNumber(MAX(nrows, size ? 0 : 1),
+        MAX(ncols, size ? 0 : 1), (id == -1 ? get_id(Objx,1):id),Objx,1);
 
   /* a matrix */
-  else if (Matrix_Check(Objx)) 
+  else if (Matrix_Check(Objx))
     ret = Matrix_NewFromMatrix((matrix *)Objx, (id == -1 ?MAT_ID(Objx):id));
-  
+
   /* sparse matrix */
   else if (SpMatrix_Check(Objx)) {
     matrix *tmp = dense((spmatrix *)Objx);
     if (!tmp) return PyErr_NoMemory();
-    ret = Matrix_NewFromMatrix(tmp, (id == -1 ? SP_ID(Objx) : id));
-    Py_DECREF(tmp);
+    if (tmp->id != id) {
+      ret = Matrix_NewFromMatrix(tmp, (id == -1 ? SP_ID(Objx) : id));
+      Py_DECREF(tmp);
+    } else {
+      ret = tmp;
+    }
   }
 
   /* PyArrayStructure */
@@ -494,12 +498,12 @@ matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     int_t ndim = 0;
     ret = Matrix_NewFromArrayStruct(Objx, id, &ndim);
   }
-  
+
   /* x is a list */
   else if (PyList_Check(Objx)) {
 
     /* first try a regular list */
-    if (!(ret = Matrix_NewFromSequence(Objx, id))) { 
+    if (!(ret = Matrix_NewFromSequence(Objx, id))) {
       PyErr_Clear();
       /* try concatenation */
       ret = dense_concat(Objx, id);
@@ -508,13 +512,13 @@ matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
   /* x is a sequence */
   else if (PySequence_Check(Objx)) {
-    ret = Matrix_NewFromSequence(Objx, id);  
+    ret = Matrix_NewFromSequence(Objx, id);
   }
   else PY_ERR_TYPE("invalid matrix initialization");
 
   if (ret && size) {
-    if (nrows*ncols == MAT_LGT(ret)) { 
-      ret->nrows=nrows; ret->ncols=ncols; 
+    if (nrows*ncols == MAT_LGT(ret)) {
+      ret->nrows=nrows; ret->ncols=ncols;
     } else {
       Py_DECREF(ret); PY_ERR_TYPE("wrong matrix dimensions");
     }
@@ -525,103 +529,18 @@ matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 PyObject *matrix_sub(PyObject *, PyObject *);
 
-static PyObject * 
-matrix_richcompare(PyObject *self, PyObject *other, int op) {
-
-  PY_ERR(PyExc_NotImplementedError, "matrix comparison not implemented");  
-}
-
-/*
-static PyObject * 
+static PyObject *
 matrix_richcompare(PyObject *self, PyObject *other, int op) {
 
-  if (((Matrix_Check(self) || SpMatrix_Check(self)) && X_ID(self)==COMPLEX) ||
-      ((Matrix_Check(other) || SpMatrix_Check(other)) && X_ID(other)==COMPLEX))
-    PY_ERR_TYPE("complex comparison not defined");
-    
-  if (PyComplex_Check(self) || PyComplex_Check(other))
-    PY_ERR_TYPE("complex comparison not defined");
-    
-  if (!Matrix_Check(self) && !SpMatrix_Check(self) && !PyNumber_Check(self)) 
-  {
-    Py_INCREF(Py_NotImplemented);
-    return Py_NotImplemented;
-  }
-
-  if (!Matrix_Check(other) && !SpMatrix_Check(other) && !PyNumber_Check(other))
-  {
-    Py_INCREF(Py_NotImplemented);
-    return Py_NotImplemented;
-  }
-      
-  if ( (Matrix_Check(self) || SpMatrix_Check(other)) &&
-      (Matrix_Check(other) || SpMatrix_Check(other)) && 
-      ((X_NROWS(self)*X_NCOLS(self) > 1) &&
-	  (X_NROWS(other)*X_NCOLS(other) > 1)) &&
-      (X_NROWS(self) != X_NROWS(other) || X_NCOLS(self) != X_NCOLS(other)) )
-    PY_ERR_TYPE("matrices in comparison must have same dimensions");
-
-  PyObject *tmp = matrix_sub(self, other);
-  if (!tmp) return PyErr_NoMemory();
-
-  PyObject *ret = (PyObject *)Matrix_New(X_NROWS(self), X_NCOLS(self), INT);
-  if (!ret) {
-    Py_DECREF(tmp); 
-    return PyErr_NoMemory();
-  }
-
-  int i;
-  switch (op) {
-  case Py_LT :
-    for (i=0; i<MAT_LGT(ret); i++) 
-      MAT_BUFI(ret)[i] = (MAT_ID(tmp) == INT ? MAT_BUFI(tmp)[i] < 0:
-	  MAT_BUFD(tmp)[i] < 0);
-    break;
-    
-  case Py_LE :
-    for (i=0; i<MAT_LGT(ret); i++) 
-      MAT_BUFI(ret)[i] = (MAT_ID(tmp) == INT ? MAT_BUFI(tmp)[i] <= 0:
-	  MAT_BUFD(tmp)[i] <= 0);
-    break;
-    
-  case Py_GT :
-    for (i=0; i<MAT_LGT(ret); i++) 
-      MAT_BUFI(ret)[i] = (MAT_ID(tmp) == INT ? MAT_BUFI(tmp)[i] > 0:
-	  MAT_BUFD(tmp)[i] > 0);
-    break;
-      
-  case Py_GE :
-    for (i=0; i<MAT_LGT(ret); i++) 
-      MAT_BUFI(ret)[i] = (MAT_ID(tmp) == INT ? MAT_BUFI(tmp)[i] >= 0:
-	  MAT_BUFD(tmp)[i] >= 0);
-    break;
-
-  case Py_EQ :
-    for (i=0; i<MAT_LGT(ret); i++) 
-      MAT_BUFI(ret)[i] = (MAT_ID(tmp) == INT ? MAT_BUFI(tmp)[i] == 0:
-	  MAT_BUFD(tmp)[i] == 0);
-    break;
-    
-  case Py_NE :
-    for (i=0; i<MAT_LGT(ret); i++) 
-      MAT_BUFI(ret)[i] = (MAT_ID(tmp) == INT ? MAT_BUFI(tmp)[i] != 0:
-	  MAT_BUFD(tmp)[i] != 0);
-    break;
-      
-  default: break;
-  }
-  
-  Py_DECREF(tmp);
-  return ret;
+  PY_ERR(PyExc_NotImplementedError, "matrix comparison not implemented");
 }
-*/
 
 static PyObject *
 matrix_str(matrix *self) {
 
   PyObject *cvxopt = PyImport_ImportModule("cvxopt");
   PyObject *str, *ret;
-  
+
   if (!(str = PyObject_GetAttrString(cvxopt, "matrix_str"))) {
     Py_DECREF(cvxopt);
     PY_ERR(PyExc_KeyError, "missing 'matrix_str' in 'cvxopt'");
@@ -633,7 +552,7 @@ matrix_str(matrix *self) {
   ret = PyObject_CallFunctionObjArgs(str, (PyObject *)self, NULL);
   Py_DECREF(str);
 
-  return ret;  
+  return ret;
 }
 
 static PyObject *
@@ -641,7 +560,7 @@ matrix_repr(matrix *self) {
 
   PyObject *cvxopt = PyImport_ImportModule("cvxopt");
   PyObject *repr, *ret;
-  
+
   if (!(repr = PyObject_GetAttrString(cvxopt, "matrix_repr"))) {
     Py_DECREF(cvxopt);
     PY_ERR(PyExc_KeyError, "missing 'matrix_repr' in 'cvxopt'");
@@ -653,23 +572,23 @@ matrix_repr(matrix *self) {
   ret = PyObject_CallFunctionObjArgs(repr, (PyObject *)self, NULL);
   Py_DECREF(repr);
 
-  return ret;  
+  return ret;
 }
 
 /*
  * This method converts different index sets into a matrix indexlist
  */
-matrix * create_indexlist(int dim, PyObject *A) 
+matrix * create_indexlist(int_t dim, PyObject *A)
 {
   matrix *x;
   int_t i, j;
 
   /* integer */
   if (PyInt_Check(A)) {
-    i = PyInt_AS_LONG(A);    
+    i = PyInt_AS_LONG(A);
     if (OUT_RNG(i,dim)) PY_ERR(PyExc_IndexError, "index out of range");
 
-    if ((x = Matrix_New(1,1,INT))) MAT_BUFI(x)[0] = i;    
+    if ((x = Matrix_New(1,1,INT))) MAT_BUFI(x)[0] = i;
     return x;
   }
   /* slice */
@@ -677,29 +596,31 @@ matrix * create_indexlist(int dim, PyObject *A)
     int_t start, stop, step, lgt;
 
     if (PySlice_GetIndicesEx((PySliceObject*)A, dim,
-	    &start, &stop, &step, &lgt) < 0) return NULL;
+        &start, &stop, &step, &lgt) < 0) return NULL;
 
     if ((x = Matrix_New(lgt, 1, INT)))
       for (i=start, j=0; j<lgt; i += step, j++) MAT_BUFI(x)[j] = i;
-
+    else {
+      return (matrix *)PyErr_NoMemory();
+    }
     return x;
-  }  
+  }
   /* Matrix index list */
   else if (Matrix_Check(A)) {
     if (MAT_ID(A) != INT) PY_ERR_TYPE("not an integer index list");
 
-    for (i=0; i<MAT_LGT(A); i++) 
+    for (i=0; i<MAT_LGT(A); i++)
       if ( OUT_RNG(MAT_BUFI(A)[i], dim) )
-	PY_ERR(PyExc_IndexError, "index out of range");
-    
+        PY_ERR(PyExc_IndexError, "index out of range");
+
     return (matrix *)A;
   }
   /* List */
   else if (PyList_Check(A)) {
     if (!(x = (matrix *)Matrix_NewFromSequence(A, INT))) return NULL;
-    
+
     return create_indexlist(dim, (PyObject *)x);
-  } 
+  }
   else PY_ERR(PyExc_TypeError, "invalid index argument");
 }
 
@@ -710,47 +631,47 @@ matrix_length(matrix *self)
 }
 
 static PyObject *
-matrix_subscr(matrix* self, PyObject* args) 
+matrix_subscr(matrix* self, PyObject* args)
 {
   matrix *Il = NULL, *Jl = NULL, *ret;
   if (PyInt_Check(args)) {
     int_t i = PyInt_AS_LONG(args);
-    if (OUT_RNG(i,MAT_LGT(self))) 
+    if (OUT_RNG(i,MAT_LGT(self)))
       PY_ERR(PyExc_IndexError, "index out of range");
 
     return num2PyObject[self->id](self->buffer, CWRAP(i,MAT_LGT(self)));
   }
 
-  else if (PyList_Check(args) || Matrix_Check(args) || PySlice_Check(args)) {  
-    
-    if (!(Il = create_indexlist(MAT_LGT(self), args))) return NULL;    
-    
-    int i;        
-    if (!(ret = Matrix_New(MAT_LGT(Il), 1, self->id) )) 
+  else if (PyList_Check(args) || Matrix_Check(args) || PySlice_Check(args)) {
+
+    if (!(Il = create_indexlist(MAT_LGT(self), args))) return NULL;
+
+    int i;
+    if (!(ret = Matrix_New(MAT_LGT(Il), 1, self->id) ))
       free_lists_exit(args,(PyObject *)NULL,Il,(PyObject *)NULL,
-	  PyErr_NoMemory());
-    
-    for (i=0; i<MAT_LGT(Il); i++) 
+          PyErr_NoMemory());
+
+    for (i=0; i<MAT_LGT(Il); i++)
       write_num[self->id](ret->buffer, i, self->buffer,
-	  CWRAP(MAT_BUFI(Il)[i],MAT_LGT(self)));
+          CWRAP(MAT_BUFI(Il)[i],MAT_LGT(self)));
 
     free_lists_exit(args,(PyObject *)NULL,Il,(PyObject *)NULL,(PyObject *)ret);
   }
-  
-  /* remainding cases are different two argument indexing */  
+
+  /* remainding cases are different two argument indexing */
   PyObject *argI = NULL, *argJ = NULL;
   if (!PyArg_ParseTuple(args, "OO", &argI,&argJ))
     PY_ERR_TYPE("invalid index arguments");
-  
+
   /* handle normal subscripts (two integers) separately */
   if (PyInt_Check(argI) && PyInt_Check(argJ)) {
-    
+
     int i = PyInt_AS_LONG(argI), j = PyInt_AS_LONG(argJ);
     if ( OUT_RNG(i, self->nrows) || OUT_RNG(j, self->ncols))
       PY_ERR(PyExc_IndexError, "index out of range");
 
-    return num2PyObject[self->id](self->buffer, 
-	CWRAP(i,self->nrows) + CWRAP(j,self->ncols)*self->nrows);
+    return num2PyObject[self->id](self->buffer,
+        CWRAP(i,self->nrows) + CWRAP(j,self->ncols)*self->nrows);
   }
 
   /* two slices, handled separately for speed */
@@ -759,27 +680,27 @@ matrix_subscr(matrix* self, PyObject* args)
     int_t colstart, colstop, colstep, collgt;
 
     if ( (PySlice_GetIndicesEx((PySliceObject*)argI, MAT_NROWS(self),
-		&rowstart, &rowstop, &rowstep, &rowlgt) < 0) ||	
-	(PySlice_GetIndicesEx((PySliceObject*)argJ, MAT_NCOLS(self),
-	    &colstart, &colstop, &colstep, &collgt) < 0)) return NULL;
-    
-    if (!(ret = Matrix_New(rowlgt, collgt, self->id))) 
+        &rowstart, &rowstop, &rowstep, &rowlgt) < 0) ||
+        (PySlice_GetIndicesEx((PySliceObject*)argJ, MAT_NCOLS(self),
+            &colstart, &colstop, &colstep, &collgt) < 0)) return NULL;
+
+    if (!(ret = Matrix_New(rowlgt, collgt, self->id)))
       return PyErr_NoMemory();
 
     int i, j, icnt, jcnt, cnt=0;
-    for (j=colstart, jcnt=0; jcnt<collgt; jcnt++, j+=colstep) 
+    for (j=colstart, jcnt=0; jcnt<collgt; jcnt++, j+=colstep)
       for (i=rowstart, icnt=0; icnt<rowlgt; icnt++, i+=rowstep) {
-	switch (self->id) {
-	case INT:
-	  MAT_BUFI(ret)[cnt++] = MAT_BUFI(self)[j*self->nrows+i];
-	  break;
-	case DOUBLE:
-	  MAT_BUFD(ret)[cnt++] = MAT_BUFD(self)[j*self->nrows+i];
-	  break;
-	case COMPLEX:
-	  MAT_BUFZ(ret)[cnt++] = MAT_BUFZ(self)[j*self->nrows+i];
-	  break;
-	}
+        switch (self->id) {
+        case INT:
+          MAT_BUFI(ret)[cnt++] = MAT_BUFI(self)[j*self->nrows+i];
+          break;
+        case DOUBLE:
+          MAT_BUFD(ret)[cnt++] = MAT_BUFD(self)[j*self->nrows+i];
+          break;
+        case COMPLEX:
+          MAT_BUFZ(ret)[cnt++] = MAT_BUFZ(self)[j*self->nrows+i];
+          break;
+        }
       }
 
     return (PyObject *)ret;
@@ -787,25 +708,25 @@ matrix_subscr(matrix* self, PyObject* args)
 
   /* remaining two indexing cases */
   if (!(Il = create_indexlist(self->nrows, argI)) ||
-      !(Jl = create_indexlist(self->ncols, argJ))) 
+      !(Jl = create_indexlist(self->ncols, argJ)))
     free_lists_exit(argI, argJ, Il, Jl, (PyObject *)NULL);
 
   int i, j, cnt;
-  if (!(ret = Matrix_New(MAT_LGT(Il), MAT_LGT(Jl), self->id))) 
+  if (!(ret = Matrix_New(MAT_LGT(Il), MAT_LGT(Jl), self->id)))
     free_lists_exit(argI, argJ, Il, Jl, PyErr_NoMemory());
-    
+
   for (j=0, cnt=0; j < MAT_LGT(Jl); j++)
     for (i=0; i < MAT_LGT(Il); i++) {
-      write_num[self->id](ret->buffer, cnt++, self->buffer, 
-	  CWRAP(MAT_BUFI(Il)[i],self->nrows) + 
-	  CWRAP(MAT_BUFI(Jl)[j],self->ncols)*self->nrows); 
+      write_num[self->id](ret->buffer, cnt++, self->buffer,
+          CWRAP(MAT_BUFI(Il)[i],self->nrows) +
+          CWRAP(MAT_BUFI(Jl)[j],self->ncols)*self->nrows);
     }
 
   free_lists_exit(argI, argJ, Il, Jl, (PyObject *)ret);
 }
 
 #define spmatrix_getitem_i(O,i,v) \
-  spmatrix_getitem_ij(O,i%SP_NROWS(O),i/SP_NROWS(O),v)
+    spmatrix_getitem_ij(O,i%SP_NROWS(O),i/SP_NROWS(O),v)
 
 int spmatrix_getitem_ij(spmatrix *, int_t, int_t, number *) ;
 
@@ -813,29 +734,29 @@ static int
 matrix_ass_subscr(matrix* self, PyObject* args, PyObject* val)
 {
   matrix *Il = NULL, *Jl = NULL;
-  int_t i, j, id = self->id, decref_val = 0, arraystruct_nd = 0;    
+  int_t i, j, id = self->id, decref_val = 0, arraystruct_nd = 0;
 
-  if (!val) PY_ERR_INT(PyExc_NotImplementedError, 
+  if (!val) PY_ERR_INT(PyExc_NotImplementedError,
       "cannot delete matrix entries");
 
   if (!(PY_NUMBER(val) || Matrix_Check(val) || SpMatrix_Check(val))) {
-    
-    if (PyObject_HasAttrString(val,"__array_struct__")) 
+
+    if (PyObject_HasAttrString(val,"__array_struct__"))
       val = (PyObject *)Matrix_NewFromArrayStruct(val, -1, &arraystruct_nd);
-    else 
+    else
       val = (PyObject *)Matrix_NewFromSequence(val, MAT_ID(self));
 
     if (!val)
-      PY_ERR_INT(PyExc_NotImplementedError, "invalid type in assignment");    
+      PY_ERR_INT(PyExc_NotImplementedError, "invalid type in assignment");
 
     decref_val = 1;
   }
 
-  if (get_id(val, (PY_NUMBER(val) ? 1 : 0)) > id) 
+  if (get_id(val, (PY_NUMBER(val) ? 1 : 0)) > id)
     PY_ERR_INT(PyExc_TypeError, "invalid type in assignment");
 
-  if (PyInt_Check(args) || PyList_Check(args) || 
-      Matrix_Check(args) || PySlice_Check(args)) {    
+  if (PyInt_Check(args) || PyList_Check(args) ||
+      Matrix_Check(args) || PySlice_Check(args)) {
 
     if (!(Il = create_indexlist(MAT_LGT(self), args))) {
       if (decref_val) { Py_DECREF(val); }
@@ -843,39 +764,39 @@ matrix_ass_subscr(matrix* self, PyObject* args, PyObject* val)
     }
     number n;
     if (PY_NUMBER(val) || (Matrix_Check(val) && MAT_LGT(val)==1)) {
-      convert_num[id](&n, val, (Matrix_Check(val) ? 0 : 1), 0);      
+      convert_num[id](&n, val, (Matrix_Check(val) ? 0 : 1), 0);
 
-      for (i=0; i<MAT_LGT(Il); i++) 
-	write_num[id](self->buffer,CWRAP(MAT_BUFI(Il)[i],MAT_LGT(self)),&n,0);
+      for (i=0; i<MAT_LGT(Il); i++)
+        write_num[id](self->buffer,CWRAP(MAT_BUFI(Il)[i],MAT_LGT(self)),&n,0);
     }
     else {
 
       if (Matrix_Check(val)) {
-	if (MAT_LGT(val) != MAT_LGT(Il) || MAT_NCOLS(val) > 1) {
-	  if (!Matrix_Check(args)) { Py_DECREF(Il); }
-	  if (decref_val) { Py_DECREF(val); }
-	  PY_ERR_INT(PyExc_TypeError, "argument has wrong size");
-	}
-     
-	for (i=0; i < MAT_LGT(Il); i++) {
-	  convert_num[id](&n, val, 0, i);
-	  write_num[id](self->buffer,
-	      CWRAP(MAT_BUFI(Il)[i], MAT_LGT(self)), &n, 0);
-	}
-      } 
+        if (MAT_LGT(val) != MAT_LGT(Il) || MAT_NCOLS(val) > 1) {
+          if (!Matrix_Check(args)) { Py_DECREF(Il); }
+          if (decref_val) { Py_DECREF(val); }
+          PY_ERR_INT(PyExc_TypeError, "argument has wrong size");
+        }
+
+        for (i=0; i < MAT_LGT(Il); i++) {
+          convert_num[id](&n, val, 0, i);
+          write_num[id](self->buffer,
+              CWRAP(MAT_BUFI(Il)[i], MAT_LGT(self)), &n, 0);
+        }
+      }
       else { /* spmatrix */
 
-	if (SP_NROWS(val) != MAT_LGT(Il) || SP_NCOLS(val) > 1) {
-	  if (!Matrix_Check(args)) { Py_DECREF(Il); }
-	  if (decref_val) { Py_DECREF(val); }
-	  PY_ERR_INT(PyExc_TypeError, "argument has wrong size");
-	}
-	
-	for (i=0; i < MAT_LGT(Il); i++) {
-	  spmatrix_getitem_i((spmatrix *)val, i, &n);
-	  write_num[id](self->buffer,
-	      CWRAP(MAT_BUFI(Il)[i], MAT_LGT(self)), &n, 0);
-	}
+        if (SP_NROWS(val) != MAT_LGT(Il) || SP_NCOLS(val) > 1) {
+          if (!Matrix_Check(args)) { Py_DECREF(Il); }
+          if (decref_val) { Py_DECREF(val); }
+          PY_ERR_INT(PyExc_TypeError, "argument has wrong size");
+        }
+
+        for (i=0; i < MAT_LGT(Il); i++) {
+          spmatrix_getitem_i((spmatrix *)val, i, &n);
+          write_num[id](self->buffer,
+              CWRAP(MAT_BUFI(Il)[i], MAT_LGT(self)), &n, 0);
+        }
       }
     }
 
@@ -885,42 +806,42 @@ matrix_ass_subscr(matrix* self, PyObject* args, PyObject* val)
 
   /* remainding cases are different two argument indexing */
   PyObject *argI = NULL, *argJ = NULL;
-  if (!PyArg_ParseTuple(args, "OO", &argI,&argJ)) 
+  if (!PyArg_ParseTuple(args, "OO", &argI,&argJ))
     PY_ERR_INT(PyExc_TypeError, "invalid index arguments");
 
   /* two slices, RHS of same type, handled separately for speed */
-  if (PySlice_Check(argI) && PySlice_Check(argJ) && 
+  if (PySlice_Check(argI) && PySlice_Check(argJ) &&
       Matrix_Check(val) && MAT_ID(val) == MAT_ID(self)) {
 
     int_t rowstart, rowstop, rowstep, rowlgt;
     int_t colstart, colstop, colstep, collgt;
 
     if ( (PySlice_GetIndicesEx((PySliceObject*)argI, MAT_NROWS(self),
-		&rowstart, &rowstop, &rowstep, &rowlgt) < 0) ||	
-	(PySlice_GetIndicesEx((PySliceObject*)argJ, MAT_NCOLS(self),
-	    &colstart, &colstop, &colstep, &collgt) < 0)) return -1;
+        &rowstart, &rowstop, &rowstep, &rowlgt) < 0) ||
+        (PySlice_GetIndicesEx((PySliceObject*)argJ, MAT_NCOLS(self),
+            &colstart, &colstop, &colstep, &collgt) < 0)) return -1;
 
     if (decref_val && MAT_LGT(val) == rowlgt*collgt) {
       MAT_NROWS(val) = rowlgt; MAT_NCOLS(val) = collgt;
     }
 
-    if (MAT_NROWS(val)!=rowlgt || MAT_NCOLS(val)!=collgt) 
-      PY_ERR_INT(PyExc_TypeError, "argument has wrong size");    
+    if (MAT_NROWS(val)!=rowlgt || MAT_NCOLS(val)!=collgt)
+      PY_ERR_INT(PyExc_TypeError, "argument has wrong size");
 
     int i, j, icnt, jcnt, cnt=0;
-    for (j=colstart, jcnt=0; jcnt<collgt; jcnt++, j+=colstep) 
+    for (j=colstart, jcnt=0; jcnt<collgt; jcnt++, j+=colstep)
       for (i=rowstart, icnt=0; icnt<rowlgt; icnt++, i+=rowstep) {
-	switch (self->id) {
-	case INT:
-	  MAT_BUFI(self)[j*self->nrows+i] = MAT_BUFI(val)[cnt++];
-	  break;
-	case DOUBLE:
-	  MAT_BUFD(self)[j*self->nrows+i] = MAT_BUFD(val)[cnt++]; 
-	  break;
-	case COMPLEX:
-	  MAT_BUFZ(self)[j*self->nrows+i] = MAT_BUFZ(val)[cnt++];
-	  break;
-	}
+        switch (self->id) {
+        case INT:
+          MAT_BUFI(self)[j*self->nrows+i] = MAT_BUFI(val)[cnt++];
+          break;
+        case DOUBLE:
+          MAT_BUFD(self)[j*self->nrows+i] = MAT_BUFD(val)[cnt++];
+          break;
+        case COMPLEX:
+          MAT_BUFZ(self)[j*self->nrows+i] = MAT_BUFZ(val)[cnt++];
+          break;
+        }
       }
 
     return 0;
@@ -932,7 +853,7 @@ matrix_ass_subscr(matrix* self, PyObject* args, PyObject* val)
     free_lists_exit(argI,argJ,Il,Jl,-1);
   }
 
-  if (decref_val && arraystruct_nd < 2 && 
+  if (decref_val && arraystruct_nd < 2 &&
       MAT_LGT(val) == MAT_LGT(Il)*MAT_LGT(Jl)) {
     MAT_NROWS(val) = MAT_LGT(Il); MAT_NCOLS(val) = MAT_LGT(Jl);
   }
@@ -943,29 +864,29 @@ matrix_ass_subscr(matrix* self, PyObject* args, PyObject* val)
       if (decref_val) { Py_DECREF(val); }
       free_lists_exit(Il,Jl,argI,argJ,-1);
     }
-    
+
     for (j=0; j < MAT_LGT(Jl); j++)
       for (i=0; i < MAT_LGT(Il); i++) {
-	write_num[id](self->buffer,CWRAP(MAT_BUFI(Il)[i],self->nrows) + 
-	    CWRAP(MAT_BUFI(Jl)[j],self->ncols)*self->nrows, &n, 0); 
-      }    
+        write_num[id](self->buffer,CWRAP(MAT_BUFI(Il)[i],self->nrows) +
+            CWRAP(MAT_BUFI(Jl)[j],self->ncols)*self->nrows, &n, 0);
+      }
   }
-  else if (Matrix_Check(val)) {    
+  else if (Matrix_Check(val)) {
     if (MAT_LGT(Il) != MAT_NROWS(val) || MAT_LGT(Jl) != MAT_NCOLS(val) ) {
       if (!Matrix_Check(argI)) { Py_DECREF(Il); }
       if (!Matrix_Check(argJ)) { Py_DECREF(Jl); }
       if (decref_val) { Py_DECREF(val); }
       PY_ERR_INT(PyExc_TypeError, "argument has wrong size");
     }
-    
+
     int cnt = 0;
     for (j=0; j < MAT_LGT(Jl); j++)
       for (i=0; i < MAT_LGT(Il); i++, cnt++) {
-	if (convert_num[id](&n, val, 0, cnt)) 
-	  free_lists_exit(argI,argJ,Il,Jl,-1);
-	
-	write_num[id](self->buffer,CWRAP(MAT_BUFI(Il)[i],self->nrows) + 
-	    CWRAP(MAT_BUFI(Jl)[j],self->ncols)*self->nrows, &n, 0);	
+        if (convert_num[id](&n, val, 0, cnt))
+          free_lists_exit(argI,argJ,Il,Jl,-1);
+
+        write_num[id](self->buffer,CWRAP(MAT_BUFI(Il)[i],self->nrows) +
+            CWRAP(MAT_BUFI(Jl)[j],self->ncols)*self->nrows, &n, 0);
       }
   }
   else { /* spmatrix */
@@ -980,9 +901,9 @@ matrix_ass_subscr(matrix* self, PyObject* args, PyObject* val)
     for (j=0; j < MAT_LGT(Jl); j++)
       for (i=0; i < MAT_LGT(Il); i++, cnt++) {
 
-	spmatrix_getitem_i((spmatrix *)val, cnt, &n);	
-	write_num[id](self->buffer,CWRAP(MAT_BUFI(Il)[i],self->nrows)  + 
-	    CWRAP(MAT_BUFI(Jl)[j],self->ncols)*self->nrows, &n, 0);	
+        spmatrix_getitem_i((spmatrix *)val, cnt, &n);
+        write_num[id](self->buffer,CWRAP(MAT_BUFI(Il)[i],self->nrows)  +
+            CWRAP(MAT_BUFI(Jl)[j],self->ncols)*self->nrows, &n, 0);
       }
   }
 
@@ -991,9 +912,9 @@ matrix_ass_subscr(matrix* self, PyObject* args, PyObject* val)
 }
 
 static PyMappingMethods matrix_as_mapping = {
-  (lenfunc)matrix_length,
-  (binaryfunc)matrix_subscr,
-  (objobjargproc)matrix_ass_subscr
+    (lenfunc)matrix_length,
+    (binaryfunc)matrix_subscr,
+    (objobjargproc)matrix_ass_subscr
 };
 
 static PyObject * matrix_transpose(matrix *self) {
@@ -1003,7 +924,7 @@ static PyObject * matrix_transpose(matrix *self) {
 
   int i, j, cnt = 0;
   for (i=0; i < ret->nrows; i++)
-    for (j=0; j < ret->ncols; j++) 
+    for (j=0; j < ret->ncols; j++)
       write_num[self->id](ret->buffer, i + j*ret->nrows, self->buffer, cnt++);
 
   return (PyObject *)ret;
@@ -1012,23 +933,23 @@ static PyObject * matrix_transpose(matrix *self) {
 static PyObject * matrix_ctranspose(matrix *self) {
 
   if (self->id != COMPLEX) return matrix_transpose(self);
-  
+
   matrix *ret = Matrix_New(self->ncols, self->nrows, self->id);
   if (!ret) return PyErr_NoMemory();
 
   int i, j, cnt = 0;
   for (i=0; i < ret->nrows; i++)
-    for (j=0; j < ret->ncols; j++)       
+    for (j=0; j < ret->ncols; j++)
       MAT_BUFZ(ret)[i + j*ret->nrows] = conj(MAT_BUFZ(self)[cnt++]);
-    
+
   return (PyObject *)ret;
 }
 
 static PyObject * matrix_real(matrix *self) {
 
-  if (self->id != COMPLEX) 
+  if (self->id != COMPLEX)
     return (PyObject *)Matrix_NewFromMatrix(self,self->id);
-  
+
   matrix *ret = Matrix_New(self->nrows, self->ncols, DOUBLE);
   if (!ret) return PyErr_NoMemory();
 
@@ -1047,10 +968,10 @@ static PyObject * matrix_imag(matrix *self) {
     ret = Matrix_NewFromNumber(self->nrows, self->ncols, self->id, a, 2);
     Py_DECREF(a);
     if (!ret) return PyErr_NoMemory();
-    
+
     return (PyObject *)ret;
   }
-    
+
   if (!(ret = Matrix_New(self->nrows, self->ncols, DOUBLE)))
     return PyErr_NoMemory();
 
@@ -1071,17 +992,17 @@ matrix_tofile(matrix *self, PyObject *args, PyObject *kwrds)
   PyObject *file_obj;
   FILE *fp;
   char *kwlist[] = {"fo",  NULL};
-  
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O", kwlist, &file_obj)) 
+
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O", kwlist, &file_obj))
     return NULL;
-  
-  if (!PyFile_Check(file_obj)) 
+
+  if (!PyFile_Check(file_obj))
     PY_ERR_TYPE("argument must a file object");
 
-  if (!(fp = PyFile_AsFile(file_obj))) 
+  if (!(fp = PyFile_AsFile(file_obj)))
     PY_ERR(PyExc_IOError,"file not open for writing");
-  
-  fwrite(self->buffer, E_SIZE[self->id], MAT_LGT(self), fp);  
+
+  if (fwrite(self->buffer, E_SIZE[self->id], MAT_LGT(self), fp)) ;
   return Py_BuildValue("");
 }
 
@@ -1096,17 +1017,17 @@ matrix_fromfile(matrix *self, PyObject *args, PyObject *kwrds)
   FILE *fp;
   char *kwlist[] = {"fo", NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O", kwlist, &file_obj)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O", kwlist, &file_obj))
     return NULL;
 
-  if (!PyFile_Check(file_obj)) 
+  if (!PyFile_Check(file_obj))
     PY_ERR_TYPE("argument must a file object");
-  if (!(fp = PyFile_AsFile(file_obj))) 
+  if (!(fp = PyFile_AsFile(file_obj)))
     PY_ERR(PyExc_IOError,"file not open for reading");
-  
+
   int n = fread(self->buffer, E_SIZE[self->id], MAT_LGT(self), fp);
 
-  if (n < MAT_LGT(self)) 
+  if (n < MAT_LGT(self))
     PY_ERR(PyExc_IOError, "could not read entire matrix");
   return Py_BuildValue("");
 }
@@ -1119,7 +1040,7 @@ matrix_getstate(matrix *self)
   if (!list || !size) {
     Py_XDECREF(list); Py_XDECREF(size); return NULL;
   }
-  
+
   PyTuple_SET_ITEM(size, 0, PyInt_FromLong(MAT_NROWS(self)));
   PyTuple_SET_ITEM(size, 1, PyInt_FromLong(MAT_NCOLS(self)));
 
@@ -1138,53 +1059,50 @@ matrix_reduce(matrix* self)
 }
 
 static PyMethodDef matrix_methods[] = {
-  {"trans", (PyCFunction)matrix_transpose, METH_NOARGS, 
-   "Returns the matrix transpose"},
-  {"ctrans", (PyCFunction)matrix_ctranspose, METH_NOARGS, 
-   "Returns the matrix conjugate transpose"},
-  {"real", (PyCFunction)matrix_real, METH_NOARGS, 
-   "Returns real part of matrix"},
-  {"imag", (PyCFunction)matrix_imag, METH_NOARGS, 
-   "Returns imaginary part of matrix"},
-  {"tofile", (PyCFunction)matrix_tofile, METH_VARARGS|METH_KEYWORDS,
-   doc_tofile},
-  {"fromfile", (PyCFunction)matrix_fromfile, METH_VARARGS|METH_KEYWORDS, 
-   doc_fromfile},
-  {"__reduce__", (PyCFunction)matrix_reduce, METH_NOARGS,
-   "__reduce__() -> (cls, state)"},
-  {NULL}  /* Sentinel */
+    {"trans", (PyCFunction)matrix_transpose, METH_NOARGS,
+        "Returns the matrix transpose"},
+        {"ctrans", (PyCFunction)matrix_ctranspose, METH_NOARGS,
+            "Returns the matrix conjugate transpose"},
+            {"real", (PyCFunction)matrix_real, METH_NOARGS,
+                "Returns real part of matrix"},
+                {"imag", (PyCFunction)matrix_imag, METH_NOARGS,
+                    "Returns imaginary part of matrix"},
+                    {"tofile", (PyCFunction)matrix_tofile, METH_VARARGS|METH_KEYWORDS, doc_tofile},
+                    {"fromfile", (PyCFunction)matrix_fromfile, METH_VARARGS|METH_KEYWORDS, doc_fromfile},
+                    {"__reduce__", (PyCFunction)matrix_reduce, METH_NOARGS, "__reduce__() -> (cls, state)"},
+                    {NULL}  /* Sentinel */
 };
 
 static PyObject *
 matrix_get_size(matrix *self, void *closure)
 {
   PyObject *t = PyTuple_New(2);
-  
+
   PyTuple_SET_ITEM(t, 0, PyInt_FromLong(self->nrows));
   PyTuple_SET_ITEM(t, 1, PyInt_FromLong(self->ncols));
-  
+
   return t;
 }
 
-static int 
+static int
 matrix_set_size(matrix *self, PyObject *value, void *closure)
 {
-  if (value == NULL) 
+  if (value == NULL)
     PY_ERR_INT(PyExc_TypeError, "size attribute cannot be deleted");
 
   if (!PyTuple_Check(value) || PyTuple_Size(value) != 2)
     PY_ERR_INT(PyExc_TypeError, "can only assign a 2-tuple to size");
 
-  if (!PyInt_Check(PyTuple_GET_ITEM(value, 0)) || 
+  if (!PyInt_Check(PyTuple_GET_ITEM(value, 0)) ||
       !PyInt_Check(PyTuple_GET_ITEM(value, 1)))
     PY_ERR_INT(PyExc_TypeError, "invalid size tuple");
-    
+
   int m = PyInt_AS_LONG(PyTuple_GET_ITEM(value, 0));
   int n = PyInt_AS_LONG(PyTuple_GET_ITEM(value, 1));
 
   if (m<0 || n<0)
     PY_ERR_INT(PyExc_TypeError, "dimensions must be non-negative");
-  
+
   if (m*n != MAT_LGT(self))
     PY_ERR_INT(PyExc_TypeError, "number of elements in matrix cannot change");
 
@@ -1208,7 +1126,7 @@ static void matrix_free_array_struct(void *a_struct, void *descr)
 }
 
 static PyObject * matrix_array_struct(matrix *self, void *closure) {
-  
+
   PyArrayInterface *a = malloc(sizeof(PyArrayInterface));
   if (!a) return PyErr_NoMemory();
 
@@ -1218,7 +1136,7 @@ static PyObject * matrix_array_struct(matrix *self, void *closure) {
     free(a->shape); free(a->strides); free(a);
     return PyErr_NoMemory();
   }
-  
+
   a->version = 2;
   a->nd = 2;
   a->typekind = PY_ARRAY_TC[self->id];
@@ -1230,8 +1148,8 @@ static PyObject * matrix_array_struct(matrix *self, void *closure) {
   a->strides[1] = self->nrows*E_SIZE[self->id];
   a->data = self->buffer;
 
-  return (PyObject *) PyCObject_FromVoidPtrAndDesc((void *) a, 
-      "CVXOPT ARRAY STRUCT", matrix_free_array_struct);  
+  return (PyObject *) PyCObject_FromVoidPtrAndDesc((void *) a,
+      "CVXOPT ARRAY STRUCT", matrix_free_array_struct);
 
 }
 
@@ -1246,66 +1164,66 @@ static PyObject * matrix_get_H(matrix *self, void *closure)
 }
 
 static PyGetSetDef matrix_getsets[] = {
-  {"size", (getter) matrix_get_size, (setter) matrix_set_size, 
-   "matrix dimensions"}, 
-  {"typecode", (getter) matrix_get_typecode, NULL, "typecode character"},
-  {"__array_struct__", (getter) matrix_array_struct, NULL,
-   "C object implementing the NumPy array protocol"},
-  {"T", (getter) matrix_get_T, NULL, "transpose"},
-  {"H", (getter) matrix_get_H, NULL, "conjugate transpose"},
-  {NULL}  /* Sentinel */
+    {"size", (getter) matrix_get_size, (setter) matrix_set_size,
+        "matrix dimensions"},
+        {"typecode", (getter) matrix_get_typecode, NULL, "typecode character"},
+        {"__array_struct__", (getter) matrix_array_struct, NULL,
+            "C object implementing the NumPy array protocol"},
+            {"T", (getter) matrix_get_T, NULL, "transpose"},
+            {"H", (getter) matrix_get_H, NULL, "conjugate transpose"},
+            {NULL}  /* Sentinel */
 };
 
 PyTypeObject matrix_tp = {
-	PyObject_HEAD_INIT(NULL)
-	0,
-	"cvxopt.base.matrix",
-	sizeof(matrix),
-	0,
-	(destructor)matrix_dealloc,	        /* tp_dealloc */
-	0,	               	                /* tp_print */
-	0,					/* tp_getattr */
-	0,					/* tp_setattr */
-	0,					/* tp_compare */
-	(reprfunc)matrix_repr,	                /* tp_repr */
-	&matrix_as_number,			/* tp_as_number */
-	0,	                                /* tp_as_sequence */
-	&matrix_as_mapping,   	                /* tp_as_mapping */
-	0,					/* tp_hash */
-	0,					/* tp_call */
-	(reprfunc)matrix_str,			/* tp_str */
-	0,		                        /* tp_getattro */
-	0,			                /* tp_setattro */
-	0,			                /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 
-	Py_TPFLAGS_CHECKTYPES,                  /* tp_flags */
-	0,					/* tp_doc */
-	0,					/* tp_traverse */
-	0,					/* tp_clear */
-	(richcmpfunc)matrix_richcompare,        /* tp_richcompare */
-	0,					/* tp_weaklistoffset */
-	(getiterfunc)matrix_iter,		/* tp_iter */
-	0,	       	                        /* tp_iternext */
-	matrix_methods,		                /* tp_methods */
-	0,			        	/* tp_members */
-	matrix_getsets,			        /* tp_getset */
-	0,		                        /* tp_base */
-	0,					/* tp_dict */
-	0,					/* tp_descr_get */
-	0,					/* tp_descr_set */
-	0,					/* tp_dictoffset */
-	0,                                      /* tp_init */
-	0,              			/* tp_alloc */
-	matrix_new,				/* tp_new */
-	0,           				/* tp_free */
+    PyObject_HEAD_INIT(NULL)
+    0,
+    "cvxopt.base.matrix",
+    sizeof(matrix),
+    0,
+    (destructor)matrix_dealloc,	        /* tp_dealloc */
+    0,	               	                /* tp_print */
+    0,					/* tp_getattr */
+    0,					/* tp_setattr */
+    0,					/* tp_compare */
+    (reprfunc)matrix_repr,	                /* tp_repr */
+    &matrix_as_number,			/* tp_as_number */
+    0,	                                /* tp_as_sequence */
+    &matrix_as_mapping,   	                /* tp_as_mapping */
+    0,					/* tp_hash */
+    0,					/* tp_call */
+    (reprfunc)matrix_str,			/* tp_str */
+    0,		                        /* tp_getattro */
+    0,			                /* tp_setattro */
+    0,			                /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+    Py_TPFLAGS_CHECKTYPES,                  /* tp_flags */
+    0,					/* tp_doc */
+    0,					/* tp_traverse */
+    0,					/* tp_clear */
+    (richcmpfunc)matrix_richcompare,        /* tp_richcompare */
+    0,					/* tp_weaklistoffset */
+    (getiterfunc)matrix_iter,		/* tp_iter */
+    0,	       	                        /* tp_iternext */
+    matrix_methods,		                /* tp_methods */
+    0,			        	/* tp_members */
+    matrix_getsets,			        /* tp_getset */
+    0,		                        /* tp_base */
+    0,					/* tp_dict */
+    0,					/* tp_descr_get */
+    0,					/* tp_descr_set */
+    0,					/* tp_dictoffset */
+    0,                                      /* tp_init */
+    0,              			/* tp_alloc */
+    matrix_new,				/* tp_new */
+    0,           				/* tp_free */
 };
 
 /**************************************************************************/
 
 static PyObject *
-matrix_add_generic(PyObject *self, PyObject *other, int inplace) 
+matrix_add_generic(PyObject *self, PyObject *other, int inplace)
 {
-  if (!(Matrix_Check(self) || PY_NUMBER(self)) || 
+  if (!(Matrix_Check(self) || PY_NUMBER(self)) ||
       !(Matrix_Check(other) || PY_NUMBER(other))) {
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
@@ -1313,19 +1231,19 @@ matrix_add_generic(PyObject *self, PyObject *other, int inplace)
 
   int id_self = get_id(self, (Matrix_Check(self) ? 0 : 1));
   int id_other = get_id(other, (Matrix_Check(other) ? 0 : 1));
-  int id = MAX(id_self,id_other);    
+  int id = MAX(id_self,id_other);
 
-  if (inplace && (id != id_self || (MAT_LGT(self)==1 && 
-	      (Matrix_Check(other) && MAT_LGT(other)!=1))))
-      PY_ERR_TYPE("invalid inplace operation");
+  if (inplace && (id != id_self || (MAT_LGT(self)==1 &&
+      (Matrix_Check(other) && MAT_LGT(other)!=1))))
+    PY_ERR_TYPE("invalid inplace operation");
 
   /* first operand is a scalar */
-  if (PY_NUMBER(self) || (Matrix_Check(self) && MAT_LGT(self)==1)) 
-  {          
-    number n;     
-    if (!inplace) { 
+  if (PY_NUMBER(self) || (Matrix_Check(self) && MAT_LGT(self)==1))
+    {
+    number n;
+    if (!inplace) {
       convert_num[id](&n,self,(Matrix_Check(self) ? 0 : 1),0);
-      
+
       matrix *ret = Matrix_NewFromMatrix((matrix *)other, id);
       if (!ret) return PyErr_NoMemory();
 
@@ -1338,19 +1256,19 @@ matrix_add_generic(PyObject *self, PyObject *other, int inplace)
 
       int int1 = 1, int0 = 0;
       axpy[id](&int1, &One[id], &n, &int0, MAT_BUF(self), &int1);
-      
+
       Py_INCREF(self);
       return self;
-    }    
-  }
+    }
+    }
   /* second operand is a scalar */
-  else if (PY_NUMBER(other) || (Matrix_Check(other) && 
-	  MAT_LGT(other)==1))       
-  {
+  else if (PY_NUMBER(other) || (Matrix_Check(other) &&
+      MAT_LGT(other)==1))
+    {
     number n;
     convert_num[id](&n,other,(Matrix_Check(other) ? 0 : 1),0);
-    
-    if (!inplace) {      
+
+    if (!inplace) {
       matrix *ret = Matrix_NewFromMatrix((matrix *)self, id);
       if (!ret) return PyErr_NoMemory();
 
@@ -1362,55 +1280,55 @@ matrix_add_generic(PyObject *self, PyObject *other, int inplace)
     else {
       int lgt = MAT_LGT(self), int1 = 1, int0 = 0;
       axpy[id](&lgt, &One[id], &n, &int0, MAT_BUF(self), &int1);
-      
+
       Py_INCREF(self);
       return self;
-    }    
-  }
-  else { /* adding two matrices */     
+    }
+    }
+  else { /* adding two matrices */
     if (MAT_NROWS(self) != MAT_NROWS(other) ||
-	MAT_NCOLS(self) != MAT_NCOLS(other))
+        MAT_NCOLS(self) != MAT_NCOLS(other))
       PY_ERR_TYPE("incompatible dimensions");
-    
+
     void *other_coerce = convert_mtx_alloc((matrix *)other, id);
     if (!other_coerce) return PyErr_NoMemory();
 
     if (!inplace) {
       matrix *ret = Matrix_NewFromMatrix((matrix *)self, id);
       if (!ret) return PyErr_NoMemory();
-            
+
       int lgt = MAT_LGT(self), int1 = 1;
-      axpy[id](&lgt, &One[id], other_coerce, &int1, MAT_BUF(ret), &int1); 
+      axpy[id](&lgt, &One[id], other_coerce, &int1, MAT_BUF(ret), &int1);
 
       if (MAT_BUF(other) != other_coerce) { free(other_coerce); }
       return (PyObject *)ret;
-    } 
+    }
     else {
       int lgt = MAT_LGT(self), int1 = 1;
-      axpy[id](&lgt, &One[id], other_coerce, &int1, MAT_BUF(self), &int1); 
-      
-      if (MAT_BUF(other) != other_coerce) { free(other_coerce); }      
+      axpy[id](&lgt, &One[id], other_coerce, &int1, MAT_BUF(self), &int1);
+
+      if (MAT_BUF(other) != other_coerce) { free(other_coerce); }
 
       Py_INCREF(self);
-      return self;      
+      return self;
     }
   }
 }
 
-PyObject * matrix_add(PyObject *self, PyObject *other) 
+PyObject * matrix_add(PyObject *self, PyObject *other)
 {
   return matrix_add_generic(self, other, 0);
 }
 
 static PyObject * matrix_iadd(PyObject *self,PyObject *other)
-{  
+{
   return matrix_add_generic(self, other, 1);
 }
 
 static PyObject *
-matrix_sub_generic(PyObject *self, PyObject *other, int inplace) 
+matrix_sub_generic(PyObject *self, PyObject *other, int inplace)
 {
-  if (!(Matrix_Check(self) || PY_NUMBER(self)) || 
+  if (!(Matrix_Check(self) || PY_NUMBER(self)) ||
       !(Matrix_Check(other) || PY_NUMBER(other))) {
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
@@ -1418,20 +1336,20 @@ matrix_sub_generic(PyObject *self, PyObject *other, int inplace)
 
   int id_self = get_id(self, (Matrix_Check(self) ? 0 : 1));
   int id_other = get_id(other, (Matrix_Check(other) ? 0 : 1));
-  int id = MAX(id_self,id_other);    
-  
-  if (inplace && (id != id_self || (MAT_LGT(self)==1 && 
-	      (Matrix_Check(other) && MAT_LGT(other)!=1))))
-      PY_ERR_TYPE("invalid inplace operation");
+  int id = MAX(id_self,id_other);
+
+  if (inplace && (id != id_self || (MAT_LGT(self)==1 &&
+      (Matrix_Check(other) && MAT_LGT(other)!=1))))
+    PY_ERR_TYPE("invalid inplace operation");
 
   /* first operand is a scalar */
-  if (PY_NUMBER(self) || (Matrix_Check(self) && MAT_LGT(self)==1)) 
-  {          
+  if (PY_NUMBER(self) || (Matrix_Check(self) && MAT_LGT(self)==1))
+    {
 
-    number n;    
-    if (!inplace) {      
+    number n;
+    if (!inplace) {
       convert_num[id](&n,self,(Matrix_Check(self) ? 0 : 1),0);
-      
+
       matrix *ret = Matrix_NewFromMatrix((matrix *)other, id);
       if (!ret) return PyErr_NoMemory();
 
@@ -1440,23 +1358,23 @@ matrix_sub_generic(PyObject *self, PyObject *other, int inplace)
       axpy[id](&lgt, &One[id], &n, &int0, ret->buffer, &int1);
       return (PyObject *)ret;
     }
-    else {       
+    else {
       convert_num[id](&n,other,(Matrix_Check(other) ? 0 : 1),0);
 
       int int1 = 1, int0 = 0;
       axpy[id](&int1, &MinusOne[id], &n, &int0, MAT_BUF(self), &int1);
-      
+
       Py_INCREF(self);
-      return self;      
-    }    
-  }
+      return self;
+    }
+    }
   /* second operand is a scalar */
-  else if (PY_NUMBER(other) || (Matrix_Check(other) &&  MAT_LGT(other)==1)) 
-  {
+  else if (PY_NUMBER(other) || (Matrix_Check(other) &&  MAT_LGT(other)==1))
+    {
     number n;
     convert_num[id](&n,other,(Matrix_Check(other) ? 0 : 1),0);
-    
-    if (!inplace) {      
+
+    if (!inplace) {
       matrix *ret = Matrix_NewFromMatrix((matrix *)self, id);
       if (!ret) return PyErr_NoMemory();
 
@@ -1468,42 +1386,42 @@ matrix_sub_generic(PyObject *self, PyObject *other, int inplace)
     else {
       int lgt = MAT_LGT(self), int1 = 1, int0 = 0;
       axpy[id](&lgt, &MinusOne[id], &n, &int0, MAT_BUF(self), &int1);
-      
+
       Py_INCREF(self);
       return self;
-    }    
-  }
-  else { /* subtracting two matrices */     
+    }
+    }
+  else { /* subtracting two matrices */
     if (MAT_NROWS(self) != MAT_NROWS(other) ||
-	MAT_NCOLS(self) != MAT_NCOLS(other))
+        MAT_NCOLS(self) != MAT_NCOLS(other))
       PY_ERR_TYPE("incompatible dimensions");
-    
+
     void *other_coerce = convert_mtx_alloc((matrix *)other, id);
     if (!other_coerce) return PyErr_NoMemory();
 
     if (!inplace) {
       matrix *ret = Matrix_NewFromMatrix((matrix *)self, id);
       if (!ret) return PyErr_NoMemory();
-            
+
       int lgt = MAT_LGT(self), int1 = 1;
-      axpy[id](&lgt, &MinusOne[id], other_coerce, &int1, MAT_BUF(ret), &int1); 
+      axpy[id](&lgt, &MinusOne[id], other_coerce, &int1, MAT_BUF(ret), &int1);
 
       if (MAT_BUF(other) != other_coerce) { free(other_coerce); }
       return (PyObject *)ret;
-    } 
+    }
     else {
       int lgt = MAT_LGT(self), int1 = 1;
-      axpy[id](&lgt,&MinusOne[id],other_coerce,&int1,MAT_BUF(self),&int1); 
-            
-      if (MAT_BUF(other) != other_coerce) { free(other_coerce); }      
-      
+      axpy[id](&lgt,&MinusOne[id],other_coerce,&int1,MAT_BUF(self),&int1);
+
+      if (MAT_BUF(other) != other_coerce) { free(other_coerce); }
+
       Py_INCREF(self);
-      return self;      
+      return self;
     }
   }
 }
 
-PyObject * matrix_sub(PyObject *self, PyObject *other) 
+PyObject * matrix_sub(PyObject *self, PyObject *other)
 {
   return matrix_sub_generic(self, other, 0);
 }
@@ -1513,10 +1431,10 @@ static PyObject * matrix_isub(PyObject *self,PyObject *other)
   return matrix_sub_generic(self, other, 1);
 }
 
-static PyObject * 
-matrix_mul_generic(PyObject *self, PyObject *other, int inplace) 
+static PyObject *
+matrix_mul_generic(PyObject *self, PyObject *other, int inplace)
 {
-  if (!(Matrix_Check(self) || PY_NUMBER(self)) || 
+  if (!(Matrix_Check(self) || PY_NUMBER(self)) ||
       !(Matrix_Check(other) || PY_NUMBER(other))) {
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
@@ -1524,21 +1442,21 @@ matrix_mul_generic(PyObject *self, PyObject *other, int inplace)
 
   int id_self = get_id(self, (Matrix_Check(self) ? 0 : 1));
   int id_other = get_id(other, (Matrix_Check(other) ? 0 : 1));
-  int id = MAX(id_self,id_other);    
+  int id = MAX(id_self,id_other);
 
-  if (inplace && (id != id_self || (MAT_LGT(self)==1 && 
-	      (Matrix_Check(other) && MAT_LGT(other)!=1)) ||
-	  (MAT_LGT(self)>1 && (Matrix_Check(other) && MAT_LGT(other)>1))) )
+  if (inplace && (id != id_self || (MAT_LGT(self)==1 &&
+      (Matrix_Check(other) && MAT_LGT(other)!=1)) ||
+      (MAT_LGT(self)>1 && (Matrix_Check(other) && MAT_LGT(other)>1))) )
     PY_ERR_TYPE("invalid inplace operation");
 
   /* first operand is a scalar */
-  if (PY_NUMBER(self) || (Matrix_Check(self) && MAT_LGT(self)==1)) 
-  {          
+  if (PY_NUMBER(self) || (Matrix_Check(self) && MAT_LGT(self)==1))
+    {
     number n;
     if (!inplace) {
       convert_num[id](&n,self,(Matrix_Check(self) ? 0 : 1),0);
-    
-      matrix *ret = Matrix_NewFromMatrix((matrix *)other, id);      
+
+      matrix *ret = Matrix_NewFromMatrix((matrix *)other, id);
       if (!ret) return PyErr_NoMemory();
 
       int lgt = MAT_LGT(ret), int1 = 1;
@@ -1553,17 +1471,17 @@ matrix_mul_generic(PyObject *self, PyObject *other, int inplace)
 
       Py_INCREF(self);
       return self;
-    }    
-  }
+    }
+    }
   /* second operand is a scalar */
-  else if (PY_NUMBER(other) || (Matrix_Check(other) && 
-	  MAT_LGT(other)==1))       
-  {
+  else if (PY_NUMBER(other) || (Matrix_Check(other) &&
+      MAT_LGT(other)==1))
+    {
     number n;
     convert_num[id](&n,other,(Matrix_Check(other) ? 0 : 1),0);
-    
-    if (!inplace) {      
-      matrix *ret = Matrix_NewFromMatrix((matrix *)self, id); 
+
+    if (!inplace) {
+      matrix *ret = Matrix_NewFromMatrix((matrix *)self, id);
       if (!ret) return PyErr_NoMemory();
 
       int lgt = MAT_LGT(self), int1 = 1;
@@ -1576,14 +1494,14 @@ matrix_mul_generic(PyObject *self, PyObject *other, int inplace)
 
       Py_INCREF(self);
       return self;
-    }    
-  }
-  else { /* multiplying two matrices */       
-    if (MAT_NCOLS(self) != MAT_NROWS(other)) 
+    }
+    }
+  else { /* multiplying two matrices */
+    if (MAT_NCOLS(self) != MAT_NROWS(other))
       PY_ERR_TYPE("incompatible dimensions");
-    
+
     int m = MAT_NROWS(self), n = MAT_NCOLS(other), k = MAT_NCOLS(self);
-    
+
     int ldA = MAX(1,MAT_NROWS(self));
     int ldB = MAX(1,MAT_NROWS(other));
     int ldC = MAX(1,MAT_NROWS(self));
@@ -1593,28 +1511,28 @@ matrix_mul_generic(PyObject *self, PyObject *other, int inplace)
     if (!self_coerce) return PyErr_NoMemory();
 
     void *other_coerce = convert_mtx_alloc((matrix *)other, id);
-    if (!other_coerce) { 
+    if (!other_coerce) {
       if (MAT_ID(self) != id) { free(self_coerce); }
-      return PyErr_NoMemory(); 
+      return PyErr_NoMemory();
     }
 
     matrix *c = Matrix_New(m, n, id);
     if (!c) {
       if (MAT_ID(self) != id)  { free(self_coerce); }
       if (MAT_ID(other) != id) { free(other_coerce); }
-      return PyErr_NoMemory(); 
+      return PyErr_NoMemory();
     }
-      
-    gemm[id](&transA, &transB, &m, &n, &k, &One[id], self_coerce, 
-	&ldA, other_coerce, &ldB, &Zero[id], MAT_BUF(c), &ldC);
+
+    gemm[id](&transA, &transB, &m, &n, &k, &One[id], self_coerce,
+        &ldA, other_coerce, &ldB, &Zero[id], MAT_BUF(c), &ldC);
 
     if (MAT_ID(self) != id)  { free(self_coerce); }
-    if (MAT_ID(other) != id) { free(other_coerce); }      
+    if (MAT_ID(other) != id) { free(other_coerce); }
     return (PyObject *)c;
   }
 }
 
-static PyObject * matrix_mul(PyObject *self, PyObject *other) 
+static PyObject * matrix_mul(PyObject *self, PyObject *other)
 {
   return matrix_mul_generic(self, other, 0);
 }
@@ -1624,8 +1542,8 @@ static PyObject * matrix_imul(PyObject *self,PyObject *other)
   return matrix_mul_generic(self, other, 1);
 }
 
-static PyObject * 
-matrix_div_generic(PyObject *self, PyObject *other, int inplace) 
+static PyObject *
+matrix_div_generic(PyObject *self, PyObject *other, int inplace)
 {
   if (!((Matrix_Check(other) && MAT_LGT(other)==1) || PY_NUMBER(other))) {
     Py_INCREF(Py_NotImplemented);
@@ -1634,13 +1552,13 @@ matrix_div_generic(PyObject *self, PyObject *other, int inplace)
 
   int id_self = get_id(self, (Matrix_Check(self) ? 0 : 1));
   int id_other = get_id(other, (Matrix_Check(other) ? 0 : 1));
-  int id = MAX(id_self,id_other);    
+  int id = MAX(id_self,id_other);
 
   number n;
   convert_num[id](&n,other,(Matrix_Check(other) ? 0 : 1),0);
-    
-  if (!inplace) {      
-    matrix *ret = Matrix_NewFromMatrix((matrix *)self, id); 
+
+  if (!inplace) {
+    matrix *ret = Matrix_NewFromMatrix((matrix *)self, id);
     if (!ret) return PyErr_NoMemory();
 
     int lgt = MAT_LGT(ret);
@@ -1649,16 +1567,16 @@ matrix_div_generic(PyObject *self, PyObject *other, int inplace)
   }
   else {
     if (id != id_self) PY_ERR_TYPE("invalid inplace operation");
-  
-    if (div_array[id](MAT_BUF(self), n, MAT_LGT(self)))  
-      return NULL; 
-    
+
+    if (div_array[id](MAT_BUF(self), n, MAT_LGT(self)))
+      return NULL;
+
     Py_INCREF(self);
     return self;
-  }    
+  }
 }
 
-static PyObject * matrix_div(PyObject *self, PyObject *other) 
+static PyObject * matrix_div(PyObject *self, PyObject *other)
 {
   return matrix_div_generic(self, other, 0);
 }
@@ -1669,7 +1587,7 @@ static PyObject * matrix_idiv(PyObject *self,PyObject *other)
 }
 
 static PyObject *
-matrix_rem_generic(PyObject *self, PyObject *other, int inplace) 
+matrix_rem_generic(PyObject *self, PyObject *other, int inplace)
 {
   if (!((Matrix_Check(other) && MAT_LGT(other)==1) || PY_NUMBER(other))) {
     Py_INCREF(Py_NotImplemented);
@@ -1678,17 +1596,17 @@ matrix_rem_generic(PyObject *self, PyObject *other, int inplace)
 
   int id_self = get_id(self, (Matrix_Check(self) ? 0 : 1));
   int id_other = get_id(other, (Matrix_Check(other) ? 0 : 1));
-  int id = MAX(id_self,id_other);    
+  int id = MAX(id_self,id_other);
+
+  if (id == COMPLEX) PY_ERR(PyExc_NotImplementedError, "complex modulo");
 
-  if (id == COMPLEX) PY_ERR(PyExc_NotImplementedError, "complex modulo");  
-  
   number n;
   convert_num[id](&n,other,(Matrix_Check(other) ? 0 : 1),0);
-  
-  if (!inplace) {      
-    matrix *ret = Matrix_NewFromMatrix((matrix *)self, id); 
+
+  if (!inplace) {
+    matrix *ret = Matrix_NewFromMatrix((matrix *)self, id);
     if (!ret) return PyErr_NoMemory();
-    
+
     int lgt = MAT_LGT(ret);
     if (mtx_rem[id](ret->buffer, n, lgt)) { Py_DECREF(ret); return NULL; }
     return (PyObject *)ret;
@@ -1696,14 +1614,14 @@ matrix_rem_generic(PyObject *self, PyObject *other, int inplace)
   else {
     void *ptr = convert_mtx_alloc((matrix *)self, id);
     if (!ptr) return PyErr_NoMemory();
-    
+
     int lgt = MAT_LGT(self);
     if (mtx_rem[id](ptr,n,lgt)) { free(ptr); return NULL; }
-    
+
     free_convert_mtx_alloc(self, ptr, id);
     Py_INCREF(self);
     return self;
-  }      
+  }
 }
 
 static PyObject * matrix_rem(PyObject *self, PyObject *other)
@@ -1720,10 +1638,10 @@ static PyObject * matrix_neg(matrix *self)
 {
   matrix *x = Matrix_NewFromMatrix(self,self->id);
   if (!x) return PyErr_NoMemory();
-  
+
   int n = MAT_LGT(x), int1 = 1;
   scal[x->id](&n, &MinusOne[x->id], x->buffer, &int1);
-  
+
   return (PyObject *)x;
 }
 
@@ -1731,12 +1649,12 @@ static PyObject * matrix_pos(matrix *self)
 {
   matrix *x = Matrix_NewFromMatrix(self, self->id);
   if (!x) return PyErr_NoMemory();
-  
+
   return (PyObject *)x;
 }
 
 static PyObject * matrix_abs(matrix *self)
-{ 
+{
   matrix *ret = Matrix_New(self->nrows, self->ncols,
       (self->id == COMPLEX ? DOUBLE : self->id));
 
@@ -1746,36 +1664,36 @@ static PyObject * matrix_abs(matrix *self)
   return (PyObject *)ret;
 }
 
-static PyObject * matrix_pow(PyObject *self, PyObject *other) 
+static PyObject * matrix_pow(PyObject *self, PyObject *other)
 {
   if (!PY_NUMBER(other)) PY_ERR_TYPE("exponent must be a number");
-  
+
   number val;
   int id = MAX(DOUBLE, MAX(MAT_ID(self), get_id(other, 1)));
-  convert_num[id](&val, other, 1, 0); 
+  convert_num[id](&val, other, 1, 0);
   matrix *Y = Matrix_NewFromMatrix((matrix *)self, id);
   if (!Y) return PyErr_NoMemory();
 
   int i;
   for (i=0; i<MAT_LGT(Y); i++) {
     if (id == DOUBLE) {
-      if ((MAT_BUFD(Y)[i] == 0.0 && val.d < 0.0) || 
-	  (MAT_BUFD(Y)[i] < 0.0 && val.d < 1.0 && val.d > 0.0)) {
-	Py_DECREF(Y);
-	PY_ERR(PyExc_ValueError, "domain error");
+      if ((MAT_BUFD(Y)[i] == 0.0 && val.d < 0.0) ||
+          (MAT_BUFD(Y)[i] < 0.0 && val.d < 1.0 && val.d > 0.0)) {
+        Py_DECREF(Y);
+        PY_ERR(PyExc_ValueError, "domain error");
       }
 
 
       MAT_BUFD(Y)[i] = pow(MAT_BUFD(Y)[i], val.d);
     } else {
       if (MAT_BUFZ(Y)[i] == 0.0 && (cimag(val.z) != 0.0 || creal(val.z)<0.0)) {
-	Py_DECREF(Y);
-	PY_ERR(PyExc_ValueError, "domain error");
+        Py_DECREF(Y);
+        PY_ERR(PyExc_ValueError, "domain error");
       }
       MAT_BUFZ(Y)[i] = cpow(MAT_BUFZ(Y)[i], val.z);
-    }    
+    }
   }
-  
+
   return (PyObject *)Y;
 }
 
@@ -1784,52 +1702,52 @@ static int matrix_nonzero(matrix *self)
   int i, res = 0;
   for (i=0; i<MAT_LGT(self); i++) {
     if ((MAT_ID(self) == INT) && (MAT_BUFI(self)[i] != 0)) res = 1;
-    else if ((MAT_ID(self) == DOUBLE) && (MAT_BUFD(self)[i] != 0)) res = 1;    
+    else if ((MAT_ID(self) == DOUBLE) && (MAT_BUFD(self)[i] != 0)) res = 1;
     else if ((MAT_ID(self) == COMPLEX) && (MAT_BUFZ(self)[i] != 0)) res = 1;
   }
-  
+
   return res;
 }
 
 static PyNumberMethods matrix_as_number = {
-	(binaryfunc)matrix_add,	/*nb_add*/
-	(binaryfunc)matrix_sub,	/*nb_subtract*/
-	(binaryfunc)matrix_mul,	/*nb_multiply*/
-	(binaryfunc)matrix_div, /*nb_divide*/
-	(binaryfunc)matrix_rem, /*nb_remainder*/
-	0,	                /*nb_divmod*/
-	(ternaryfunc)matrix_pow, /*nb_power*/
-	(unaryfunc)matrix_neg,	/*nb_negative*/
-	(unaryfunc)matrix_pos,	/*nb_positive*/
-	(unaryfunc)matrix_abs,	/*nb_absolute*/
-	(inquiry)matrix_nonzero,/*nb_nonzero*/
-	0,	                /*nb_invert*/
-	0,	                /*nb_lshift*/
-	0,	                /*nb_rshift*/
-	0,	                /*nb_and*/
-	0,	                /*nb_xor*/
-	0,	                /*nb_or*/
-	0,		        /*nb_coerce*/
-	0,	                /*nb_int*/
-	0,	                /*nb_long*/
-	0,                      /*nb_float*/
-	0,	                /*nb_oct*/
-	0, 	                /*nb_hex*/
-	(binaryfunc)matrix_iadd,/*nb_inplace_add*/
-	(binaryfunc)matrix_isub,/*nb_inplace_subtract*/
-	(binaryfunc)matrix_imul,/*nb_inplace_multiply*/
-	(binaryfunc)matrix_idiv,/*nb_inplace_divide*/
-	(binaryfunc)matrix_irem,/*nb_inplace_remainder*/
-	0,			/*nb_inplace_power*/
-	0,			/*nb_inplace_lshift*/
-	0,			/*nb_inplace_rshift*/
-	0,			/*nb_inplace_and*/
-	0,			/*nb_inplace_xor*/
-	0,			/*nb_inplace_or*/
-	0,	                /*nb_floor_divide*/
-	0,	                /*nb_true_divide*/
-	0,			/*nb_inplace_floor_divide*/
-	0,			/*nb_inplace_true_divide*/
+    (binaryfunc)matrix_add,	/*nb_add*/
+    (binaryfunc)matrix_sub,	/*nb_subtract*/
+    (binaryfunc)matrix_mul,	/*nb_multiply*/
+    (binaryfunc)matrix_div, /*nb_divide*/
+    (binaryfunc)matrix_rem, /*nb_remainder*/
+    0,	                /*nb_divmod*/
+    (ternaryfunc)matrix_pow, /*nb_power*/
+    (unaryfunc)matrix_neg,	/*nb_negative*/
+    (unaryfunc)matrix_pos,	/*nb_positive*/
+    (unaryfunc)matrix_abs,	/*nb_absolute*/
+    (inquiry)matrix_nonzero,/*nb_nonzero*/
+    0,	                /*nb_invert*/
+    0,	                /*nb_lshift*/
+    0,	                /*nb_rshift*/
+    0,	                /*nb_and*/
+    0,	                /*nb_xor*/
+    0,	                /*nb_or*/
+    0,		        /*nb_coerce*/
+    0,	                /*nb_int*/
+    0,	                /*nb_long*/
+    0,                      /*nb_float*/
+    0,	                /*nb_oct*/
+    0, 	                /*nb_hex*/
+    (binaryfunc)matrix_iadd,/*nb_inplace_add*/
+    (binaryfunc)matrix_isub,/*nb_inplace_subtract*/
+    (binaryfunc)matrix_imul,/*nb_inplace_multiply*/
+    (binaryfunc)matrix_idiv,/*nb_inplace_divide*/
+    (binaryfunc)matrix_irem,/*nb_inplace_remainder*/
+    0,			/*nb_inplace_power*/
+    0,			/*nb_inplace_lshift*/
+    0,			/*nb_inplace_rshift*/
+    0,			/*nb_inplace_and*/
+    0,			/*nb_inplace_xor*/
+    0,			/*nb_inplace_or*/
+    0,	                /*nb_floor_divide*/
+    0,	                /*nb_true_divide*/
+    0,			/*nb_inplace_floor_divide*/
+    0,			/*nb_inplace_true_divide*/
 };
 
 
@@ -1838,7 +1756,7 @@ static PyNumberMethods matrix_as_number = {
 typedef struct {
   PyObject_HEAD
   long index;
-  matrix *mObj;   
+  matrix *mObj;
 } matrixiter;
 
 static PyTypeObject matrixiter_tp;
@@ -1849,7 +1767,7 @@ static PyObject *
 matrix_iter(matrix *obj)
 {
   matrixiter *it;
-  
+
   if (!Matrix_Check(obj)) {
     PyErr_BadInternalCall();
     return NULL;
@@ -1892,40 +1810,40 @@ matrixiter_next(matrixiter *it)
   assert(MatrixIter_Check(it));
   if (it->index >= MAT_LGT(it->mObj))
     return NULL;
-  
+
   return num2PyObject[it->mObj->id](it->mObj->buffer, it->index++);
 }
 
 static PyTypeObject matrixiter_tp = {
-        PyObject_HEAD_INIT(NULL)
-	0,					/* ob_size */
-	"matrixiter",			        /* tp_name */
-	sizeof(matrixiter),      		/* tp_basicsize */
-	0,					/* tp_itemsize */
-	(destructor)matrixiter_dealloc,		/* tp_dealloc */
-	0,					/* tp_print */
-	0,					/* tp_getattr */
-	0,					/* tp_setattr */
-	0,					/* tp_compare */
-	0,					/* tp_repr */
-	0,					/* tp_as_number */
-	0,					/* tp_as_sequence */
-	0,					/* tp_as_mapping */
-	0,					/* tp_hash */
-	0,					/* tp_call */
-	0,					/* tp_str */
-	0,                      		/* tp_getattro */
-	0,					/* tp_setattro */
-	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
-	0,					/* tp_doc */
-	(traverseproc)matrixiter_traverse,	/* tp_traverse */
-	0,					/* tp_clear */
-	0,					/* tp_richcompare */
-	0,					/* tp_weaklistoffset */
-	0,                  			/* tp_iter */
-	(iternextfunc)matrixiter_next,		/* tp_iternext */
-	0,					/* tp_methods */
+    PyObject_HEAD_INIT(NULL)
+    0,					/* ob_size */
+    "matrixiter",			        /* tp_name */
+    sizeof(matrixiter),      		/* tp_basicsize */
+    0,					/* tp_itemsize */
+    (destructor)matrixiter_dealloc,		/* tp_dealloc */
+    0,					/* tp_print */
+    0,					/* tp_getattr */
+    0,					/* tp_setattr */
+    0,					/* tp_compare */
+    0,					/* tp_repr */
+    0,					/* tp_as_number */
+    0,					/* tp_as_sequence */
+    0,					/* tp_as_mapping */
+    0,					/* tp_hash */
+    0,					/* tp_call */
+    0,					/* tp_str */
+    0,                      		/* tp_getattro */
+    0,					/* tp_setattro */
+    0,					/* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+    0,					/* tp_doc */
+    (traverseproc)matrixiter_traverse,	/* tp_traverse */
+    0,					/* tp_clear */
+    0,					/* tp_richcompare */
+    0,					/* tp_weaklistoffset */
+    0,                  			/* tp_iter */
+    (iternextfunc)matrixiter_next,		/* tp_iternext */
+    0,					/* tp_methods */
 };
 
 
@@ -1940,45 +1858,45 @@ PyObject * matrix_log(matrix *self, PyObject *args, PyObject *kwrds)
     double f = PyFloat_AsDouble(A);
     if (f>0.0)
       return Py_BuildValue("d",log(f));
-    else 
+    else
       PY_ERR(PyExc_ValueError, "domain error");
   }
   else if (PyComplex_Check(A)) {
     number n;
     convert_num[COMPLEX](&n, A, 1, 0);
-    
+
     if (n.z == 0) PY_ERR(PyExc_ValueError, "domain error");
 
     n.z = clog(n.z);
-    return num2PyObject[COMPLEX](&n, 0);    
+    return num2PyObject[COMPLEX](&n, 0);
   }
-    
+
   else if (Matrix_Check(A)  && (MAT_ID(A) == INT || MAT_ID(A) == DOUBLE)) {
-    if (MAT_LGT(A) == 0) 
+    if (MAT_LGT(A) == 0)
       return (PyObject *)Matrix_New(MAT_NROWS(A),MAT_NCOLS(A),DOUBLE);
 
     double val = (MAT_ID(A) == INT ? MAT_BUFI(A)[0] : MAT_BUFD(A)[0]);
 
-    int i;      
+    int i;
     for (i=1; i<MAT_LGT(A); i++) {
       if (MAT_ID(A) == INT)
-	val = MIN(val,(MAT_BUFI(A)[i]));
+        val = MIN(val,(MAT_BUFI(A)[i]));
       else
-	val = MIN(val,(MAT_BUFD(A)[i]));
+        val = MIN(val,(MAT_BUFD(A)[i]));
     }
 
-    if (val > 0.0) {	
+    if (val > 0.0) {
       matrix *ret = Matrix_New(MAT_NROWS(A), MAT_NCOLS(A), DOUBLE);
       if (!ret) return PyErr_NoMemory();
-      
+
       for (i=0; i<MAT_LGT(A); i++)
-	MAT_BUFD(ret)[i] = log((MAT_ID(A)== INT ? 
-		MAT_BUFI(A)[i] : MAT_BUFD(A)[i]));
+        MAT_BUFD(ret)[i] = log((MAT_ID(A)== INT ?
+            MAT_BUFI(A)[i] : MAT_BUFD(A)[i]));
 
       return (PyObject *)ret;
-    } 
+    }
     else PY_ERR(PyExc_ValueError, "domain error");
-      
+
   }
   else if (Matrix_Check(A) && MAT_ID(A) == COMPLEX) {
     matrix *ret = Matrix_New(MAT_NROWS(A), MAT_NCOLS(A), COMPLEX);
@@ -1987,10 +1905,10 @@ PyObject * matrix_log(matrix *self, PyObject *args, PyObject *kwrds)
     int i;
     for (i=0; i<MAT_LGT(A); i++) {
       if (MAT_BUFZ(A)[i] == 0) {
-	Py_DECREF(ret);
-	PY_ERR(PyExc_ValueError, "domain error");
+        Py_DECREF(ret);
+        PY_ERR(PyExc_ValueError, "domain error");
       }
-      MAT_BUFZ(ret)[i] = clog(MAT_BUFZ(A)[i]);    
+      MAT_BUFZ(ret)[i] = clog(MAT_BUFZ(A)[i]);
     }
     return (PyObject *)ret;
   }
@@ -2003,29 +1921,29 @@ PyObject * matrix_exp(matrix *self, PyObject *args, PyObject *kwrds)
 
   if (!PyArg_ParseTuple(args, "O", &A)) return NULL;
 
-  if (PyInt_Check(A) || PyFloat_Check(A)) 
+  if (PyInt_Check(A) || PyFloat_Check(A))
     return Py_BuildValue("d",exp(PyFloat_AsDouble(A)));
 
   else if (PyComplex_Check(A)) {
     number n;
     convert_num[COMPLEX](&n, A, 1, 0);
     n.z = cexp(n.z);
-    return num2PyObject[COMPLEX](&n, 0);    
+    return num2PyObject[COMPLEX](&n, 0);
   }
-    
+
   else if (Matrix_Check(A)) {
     matrix *ret = Matrix_New(MAT_NROWS(A),MAT_NCOLS(A),
-	(MAT_ID(A) == COMPLEX ? COMPLEX : DOUBLE));
+        (MAT_ID(A) == COMPLEX ? COMPLEX : DOUBLE));
     if (!ret) return PyErr_NoMemory();
-      
+
     int i;
-    if (MAT_ID(ret) == DOUBLE) 
+    if (MAT_ID(ret) == DOUBLE)
       for (i=0; i<MAT_LGT(ret); i++)
-	MAT_BUFD(ret)[i] = exp(MAT_ID(A) == DOUBLE ? MAT_BUFD(A)[i] :
-	    MAT_BUFI(A)[i]);
-    else 
+        MAT_BUFD(ret)[i] = exp(MAT_ID(A) == DOUBLE ? MAT_BUFD(A)[i] :
+        MAT_BUFI(A)[i]);
+    else
       for (i=0; i<MAT_LGT(ret); i++)
-	MAT_BUFZ(ret)[i] = cexp(MAT_BUFZ(A)[i]);
+        MAT_BUFZ(ret)[i] = cexp(MAT_BUFZ(A)[i]);
 
     return (PyObject *)ret;
   }
@@ -2048,33 +1966,33 @@ PyObject * matrix_sqrt(matrix *self, PyObject *args, PyObject *kwrds)
     number n;
     convert_num[COMPLEX](&n, A, 1, 0);
     n.z = csqrt(n.z);
-    return num2PyObject[COMPLEX](&n, 0);    
-  }  
+    return num2PyObject[COMPLEX](&n, 0);
+  }
   else if (Matrix_Check(A) && (MAT_ID(A) == INT || MAT_ID(A) == DOUBLE)) {
-    if (MAT_LGT(A) == 0) 
+    if (MAT_LGT(A) == 0)
       return (PyObject *)Matrix_New(MAT_NROWS(A),MAT_NCOLS(A),DOUBLE);
 
     double val = (MAT_ID(A) == INT ? MAT_BUFI(A)[0] : MAT_BUFD(A)[0]);
 
-    int i;      
+    int i;
     for (i=1; i<MAT_LGT(A); i++) {
       if (MAT_ID(A) == INT)
-	val = MIN(val,(MAT_BUFI(A)[i]));
+        val = MIN(val,(MAT_BUFI(A)[i]));
       else
-	val = MIN(val,(MAT_BUFD(A)[i]));
+        val = MIN(val,(MAT_BUFD(A)[i]));
     }
 
-    if (val >= 0.0) {	
+    if (val >= 0.0) {
       matrix *ret = Matrix_New(MAT_NROWS(A), MAT_NCOLS(A), DOUBLE);
       if (!ret) return PyErr_NoMemory();
-      
+
       for (i=0; i<MAT_LGT(A); i++)
-	MAT_BUFD(ret)[i] = sqrt((MAT_ID(A)== INT ? 
-		MAT_BUFI(A)[i] : MAT_BUFD(A)[i]));
+        MAT_BUFD(ret)[i] = sqrt((MAT_ID(A)== INT ?
+            MAT_BUFI(A)[i] : MAT_BUFD(A)[i]));
 
       return (PyObject *)ret;
-      
-    } 
+
+    }
     else PY_ERR(PyExc_ValueError, "domain error");
   }
   else if (Matrix_Check(A) && MAT_ID(A) == COMPLEX) {
@@ -2082,8 +2000,8 @@ PyObject * matrix_sqrt(matrix *self, PyObject *args, PyObject *kwrds)
     if (!ret) return PyErr_NoMemory();
 
     int i;
-    for (i=0; i<MAT_LGT(A); i++) 
-      MAT_BUFZ(ret)[i] = csqrt(MAT_BUFZ(A)[i]);    
+    for (i=0; i<MAT_LGT(A); i++)
+      MAT_BUFZ(ret)[i] = csqrt(MAT_BUFZ(A)[i]);
 
     return (PyObject *)ret;
   }
@@ -2096,29 +2014,29 @@ PyObject * matrix_cos(matrix *self, PyObject *args, PyObject *kwrds)
 
   if (!PyArg_ParseTuple(args, "O", &A)) return NULL;
 
-  if (PyInt_Check(A) || PyFloat_Check(A)) 
+  if (PyInt_Check(A) || PyFloat_Check(A))
     return Py_BuildValue("d",cos(PyFloat_AsDouble(A)));
 
   else if (PyComplex_Check(A)) {
     number n;
     convert_num[COMPLEX](&n, A, 1, 0);
     n.z = ccos(n.z);
-    return num2PyObject[COMPLEX](&n, 0);    
+    return num2PyObject[COMPLEX](&n, 0);
   }
-    
+
   else if (Matrix_Check(A)) {
     matrix *ret = Matrix_New(MAT_NROWS(A),MAT_NCOLS(A),
-	(MAT_ID(A) == COMPLEX ? COMPLEX : DOUBLE));
+        (MAT_ID(A) == COMPLEX ? COMPLEX : DOUBLE));
     if (!ret) return PyErr_NoMemory();
-      
+
     int_t i;
-    if (MAT_ID(ret) == DOUBLE) 
+    if (MAT_ID(ret) == DOUBLE)
       for (i=0; i<MAT_LGT(ret); i++)
-	MAT_BUFD(ret)[i] = cos(MAT_ID(A) == DOUBLE ? MAT_BUFD(A)[i] :
-	    MAT_BUFI(A)[i]);
-    else 
+        MAT_BUFD(ret)[i] = cos(MAT_ID(A) == DOUBLE ? MAT_BUFD(A)[i] :
+        MAT_BUFI(A)[i]);
+    else
       for (i=0; i<MAT_LGT(ret); i++)
-	MAT_BUFZ(ret)[i] = ccos(MAT_BUFZ(A)[i]);
+        MAT_BUFZ(ret)[i] = ccos(MAT_BUFZ(A)[i]);
 
     return (PyObject *)ret;
   }
@@ -2131,29 +2049,29 @@ PyObject * matrix_sin(matrix *self, PyObject *args, PyObject *kwrds)
 
   if (!PyArg_ParseTuple(args, "O", &A)) return NULL;
 
-  if (PyInt_Check(A) || PyFloat_Check(A)) 
+  if (PyInt_Check(A) || PyFloat_Check(A))
     return Py_BuildValue("d",sin(PyFloat_AsDouble(A)));
 
   else if (PyComplex_Check(A)) {
     number n;
     convert_num[COMPLEX](&n, A, 1, 0);
     n.z = csin(n.z);
-    return num2PyObject[COMPLEX](&n, 0);    
+    return num2PyObject[COMPLEX](&n, 0);
   }
-    
+
   else if (Matrix_Check(A)) {
     matrix *ret = Matrix_New(MAT_NROWS(A),MAT_NCOLS(A),
-	(MAT_ID(A) == COMPLEX ? COMPLEX : DOUBLE));
+        (MAT_ID(A) == COMPLEX ? COMPLEX : DOUBLE));
     if (!ret) return PyErr_NoMemory();
-      
+
     int_t i;
-    if (MAT_ID(ret) == DOUBLE) 
+    if (MAT_ID(ret) == DOUBLE)
       for (i=0; i<MAT_LGT(ret); i++)
-	MAT_BUFD(ret)[i] = sin(MAT_ID(A) == DOUBLE ? MAT_BUFD(A)[i] :
-	    MAT_BUFI(A)[i]);
-    else 
+        MAT_BUFD(ret)[i] = sin(MAT_ID(A) == DOUBLE ? MAT_BUFD(A)[i] :
+        MAT_BUFI(A)[i]);
+    else
       for (i=0; i<MAT_LGT(ret); i++)
-	MAT_BUFZ(ret)[i] = csin(MAT_BUFZ(A)[i]);
+        MAT_BUFZ(ret)[i] = csin(MAT_BUFZ(A)[i]);
 
     return (PyObject *)ret;
   }
diff --git a/src/C/dsdp.c b/src/C/dsdp.c
index c51c542..6201b00 100644
--- a/src/C/dsdp.c
+++ b/src/C/dsdp.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -35,7 +35,7 @@ PyDoc_STRVAR(dsdp__doc__,"Interface to DSDP version 5.8.\n\n"
 
 static  PyObject *dsdp_module;
 
-static char doc_dsdp[] = 
+static char doc_dsdp[] =
     "Solves a semidefinite program using DSDP.\n\n"
     "(status, x, r, zl, zs) = sdp(c, Gl=None, hl=None, Gs=None, hs=None"
     ",\n"
@@ -56,7 +56,7 @@ static char doc_dsdp[] =
     "entries of y stored columnwise.   mat(y) is the inverse\n"
     "operation.\n\n"
     "ARGUMENTS\n"
-    "c         n by 1 dense 'd' matrix\n\n" 
+    "c         n by 1 dense 'd' matrix\n\n"
     "Gl        ml by n dense or sparse 'd' matrixi.  The default\n"
     "          value is a matrix with zero rows.\n\n"
     "hl        ml by 1 dense 'd' matrix.  The default value is a\n"
@@ -90,19 +90,19 @@ static char doc_dsdp[] =
 typedef struct {     /* symmetric matrix X in DSDP packed storage */
     int n;           /* order of X */
     char issparse;
-    double *val;     /* lower triangular nonzeros of X.  Stored in row 
+    double *val;     /* lower triangular nonzeros of X.  Stored in row
                       * major order as an n*(n+1)/2-array if X is dense,
                       * and in arbitrary order if X is sparse.*/
-    int *ind;        /* NULL if X is dense; otherwise, the indices of 
+    int *ind;        /* NULL if X is dense; otherwise, the indices of
                       *	the elements of val in the n*(n+1)/2 array of
-                      *	the lower triangular entries of X stored 
+                      *	the lower triangular entries of X stored
                       *	rowwise. */
     int nnz;         /* length of val */
 } dsdp_matrix;
 
 extern void dcopy_(int *n, double *x, int *incx, double *y, int *incy);
 
-static PyObject* solvesdp(PyObject *self, PyObject *args, 
+static PyObject* solvesdp(PyObject *self, PyObject *args,
     PyObject *kwrds)
 {
     matrix *c, *hl=NULL, *hk, *x=NULL, *zl=NULL, *zsk=NULL;
@@ -111,20 +111,20 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
     int i, j, k, n, ml, l, mk, nnz, *lp_colptr=NULL, *lp_rowind=NULL,
       incx, incy, lngth, maxm;
     int_t pos=0;
-    double *lp_values=NULL, *zlvals=NULL, *zk=NULL, r, beta=-1.0, 
+    double *lp_values=NULL, *zlvals=NULL, *zk=NULL, r, beta=-1.0,
         gamma=-1.0, tol;
     dsdp_matrix **lmis=NULL;
     div_t qr;
     DSDP sdp;
-    LPCone lpcone; 
-    SDPCone sdpcone; 
+    LPCone lpcone;
+    SDPCone sdpcone;
     DSDPTerminationReason info;
     DSDPSolutionType status;
     char *keystr, err_str[100];
-    char *kwlist[] = {"c", "Gl", "hl", "Gs", "hs", "gamma", "beta", 
+    char *kwlist[] = {"c", "Gl", "hl", "Gs", "hs", "gamma", "beta",
         NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OOOOdd", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OOOOdd", kwlist,
         &c, &Gl, &hl, &Gs, &hs, &gamma, &beta)) return NULL;
 
 
@@ -133,11 +133,11 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
         PY_ERR_TYPE("c must be a dense 'd' matrix with one column");
     n = MAT_NROWS(c);
 
-    if (Gl && ((!Matrix_Check(Gl) && !SpMatrix_Check(Gl)) || 
+    if (Gl && ((!Matrix_Check(Gl) && !SpMatrix_Check(Gl)) ||
         X_NCOLS(Gl) != n || X_ID(Gl) != DOUBLE))
         PY_ERR_TYPE("invalid type or dimensions for Gl");
     ml = Gl ? X_NROWS(Gl) : 0;
-    if ((!hl && ml) || (hl && (!Matrix_Check(hl) || MAT_NCOLS(hl) != 1 
+    if ((!hl && ml) || (hl && (!Matrix_Check(hl) || MAT_NCOLS(hl) != 1
         || MAT_NROWS(hl) != ml || MAT_ID(hl) != DOUBLE)))
         PY_ERR_TYPE("invalid type or dimensions for hl");
 
@@ -147,9 +147,9 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
     if ((!hs && l) || (hs && PyList_Size(hs) != l))
         PY_ERR_TYPE("Gs and hs must be lists of equal length");
     for (maxm=0, k=0; k<l; k++) {
-        Gk = PyList_GetItem(Gs, k); 
-        hk = (matrix *) PyList_GetItem(hs, k); 
-        if ((!Matrix_Check(Gk) && !SpMatrix_Check(Gk)) || 
+        Gk = PyList_GetItem(Gs, k);
+        hk = (matrix *) PyList_GetItem(hs, k);
+        if ((!Matrix_Check(Gk) && !SpMatrix_Check(Gk)) ||
             X_ID(Gk) != DOUBLE)
             PY_ERR_TYPE("Gs must be a list of 'd' matrices with n "
                 "columns");
@@ -162,8 +162,8 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
         maxm = MAX(mk, maxm);
     }
 
-    if (DSDPCreate(n, &sdp) || DSDPCreateLPCone(sdp, &lpcone) || 
-        DSDPCreateSDPCone(sdp, l, &sdpcone)){ 
+    if (DSDPCreate(n, &sdp) || DSDPCreateLPCone(sdp, &lpcone) ||
+        DSDPCreateSDPCone(sdp, l, &sdpcone)){
         t = PyErr_NoMemory();
         goto done;
     }
@@ -186,11 +186,11 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
 		    Py_DECREF(param);
 		    goto done;
 		}
-		else 
-		    DSDPSetStandardMonitor(sdp, PyInt_AsLong(value)); 
+		else
+		    DSDPSetStandardMonitor(sdp, PyInt_AsLong(value));
 	    }
 	    if (!strcmp(keystr, "DSDP_MaxIts")){
-		if (!PyInt_Check(value) || 
+		if (!PyInt_Check(value) ||
                     (k = PyInt_AsLong(value)) < 0) {
                     sprintf(err_str, "invalid value for nonnegative "
                         "integer DSDP parameter: DSDP_MaxIts");
@@ -199,11 +199,11 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
 		    Py_DECREF(param);
 		    goto done;
 		}
-		else 
-		    DSDPSetMaxIts(sdp, k); 
+		else
+		    DSDPSetMaxIts(sdp, k);
             }
 	    if (!strcmp(keystr, "DSDP_GapTolerance")){
-		if ((!PyFloat_Check(value) && !PyInt_Check(value)) || 
+		if ((!PyFloat_Check(value) && !PyInt_Check(value)) ||
                     (tol = PyFloat_AsDouble(value)) <= 0.0) {
                     sprintf(err_str, "invalid value for float "
                         "DSDP parameter: DSDP_GapTolerance");
@@ -212,14 +212,14 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
 		    Py_DECREF(param);
 		    goto done;
 		}
-		else 
-		    DSDPSetGapTolerance(sdp, tol); 
+		else
+		    DSDPSetGapTolerance(sdp, tol);
            }
         }
     Py_DECREF(param);
 
-    if (gamma > 0) DSDPSetPenaltyParameter(sdp, gamma); 
-    if (beta > 0) DSDPSetYBounds(sdp, -beta, beta); 
+    if (gamma > 0) DSDPSetPenaltyParameter(sdp, gamma);
+    if (beta > 0) DSDPSetYBounds(sdp, -beta, beta);
 
     /* cost function */
     for (k=0; k<n; k++) DSDPSetDualObjective(sdp, k+1, -MAT_BUFD(c)[k]);
@@ -260,7 +260,7 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
     }
     /* LPConeView(lpcone); */
 
-    /* linear matrix inequalities: store mat(hs[k]), mat(Gs[k][:,i]) 
+    /* linear matrix inequalities: store mat(hs[k]), mat(Gs[k][:,i])
      * as an lx(n+1) array of dsdp matrices. */
     if (!(lmis = (dsdp_matrix **) calloc(l, sizeof(dsdp_matrix *)))){
         t = PyErr_NoMemory();
@@ -268,19 +268,19 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
     }
     for (k=0; k<l; k++) lmis[k] = NULL;
     for (k=0; k<l; k++){
-        Gk = PyList_GetItem(Gs, k); 
-        hk = (matrix *) PyList_GetItem(hs, k); 
-        if (!(lmis[k] = (dsdp_matrix *) calloc(n+1, 
-            sizeof(dsdp_matrix)))){ 
+        Gk = PyList_GetItem(Gs, k);
+        hk = (matrix *) PyList_GetItem(hs, k);
+        if (!(lmis[k] = (dsdp_matrix *) calloc(n+1,
+            sizeof(dsdp_matrix)))){
             t = PyErr_NoMemory();
             goto done;
         }
 
 	/* lmis[k][0] is hs[k] as a dsdp matrix */
-        mk = MAT_NROWS(hk); 
+        mk = MAT_NROWS(hk);
         lmis[k][0].n = mk;
         lmis[k][0].issparse = 0;
-        if (!(lmis[k][0].val = (double *) calloc(mk*(mk+1)/2, 
+        if (!(lmis[k][0].val = (double *) calloc(mk*(mk+1)/2,
             sizeof(double)))){
             t = PyErr_NoMemory();
             goto done;
@@ -289,8 +289,8 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
         lmis[k][0].nnz = mk*(mk+1)/2;
         for (j=0; j<mk; j++){
 	    lngth = j+1;  incx = mk;  incy = 1;
-            dcopy_(&lngth, MAT_BUFD(hk)+j, &incx, 
-                lmis[k][0].val+j*(j+1)/2, &incy); 
+            dcopy_(&lngth, MAT_BUFD(hk)+j, &incx,
+                lmis[k][0].val+j*(j+1)/2, &incy);
         }
 
         /* lmis[k][i+1] is mat(Gs[k][i]) as a dsdp matrix */
@@ -298,7 +298,7 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
             lmis[k][i+1].n = mk;
             if (Matrix_Check(Gk)){
                 lmis[k][i+1].issparse = 0;
-                if (!(lmis[k][i+1].val = (double *) calloc(mk*(mk+1)/2, 
+                if (!(lmis[k][i+1].val = (double *) calloc(mk*(mk+1)/2,
                     sizeof(double)))){
                     t = PyErr_NoMemory();
                     goto done;
@@ -307,38 +307,38 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
                 lmis[k][i+1].nnz = mk*(mk+1)/2;
                 for (j=0; j<mk; j++){
                     lngth = j+1;  incx = mk;  incy = 1;
-                    dcopy_(&lngth, MAT_BUFD(Gk)+i*mk*mk+j, &incx, 
+                    dcopy_(&lngth, MAT_BUFD(Gk)+i*mk*mk+j, &incx,
                         lmis[k][i+1].val+j*(j+1)/2, &incy);
                 }
             } else {
                 lmis[k][i+1].issparse = 1;
-                /* nnz is number of lower triangular nonzeros in 
+                /* nnz is number of lower triangular nonzeros in
                  * Gk[:,i] */
                 for (nnz=0, j=SP_COL(Gk)[i]; j<SP_COL(Gk)[i+1]; j++){
-                    qr = div(SP_ROW(Gk)[j], mk); 
+                    qr = div(SP_ROW(Gk)[j], mk);
                     if (qr.quot <= qr.rem) nnz++;
                 }
                 lmis[k][i+1].nnz = nnz;
-                if (!(lmis[k][i+1].val = (double *) calloc(nnz, 
-                    sizeof(double))) || !(lmis[k][i+1].ind = (int *) 
+                if (!(lmis[k][i+1].val = (double *) calloc(nnz,
+                    sizeof(double))) || !(lmis[k][i+1].ind = (int *)
                     calloc(nnz, sizeof(int)))){
                     t = PyErr_NoMemory();
                     goto done;
                 }
-                /* lmis[k][i+1].val, lmis[k][i+1].ind are the lower 
+                /* lmis[k][i+1].val, lmis[k][i+1].ind are the lower
                  * triangular nonzeros/indices of Gk[:,i].  The indices
-		 * refer to the postions in the lower triangular part 
+		 * refer to the postions in the lower triangular part
 		 * stored in row major order as an mk*(mk+1)/2 array. */
                 for (nnz=0, j=SP_COL(Gk)[i]; j<SP_COL(Gk)[i+1]; j++){
-                    qr = div(SP_ROW(Gk)[j], mk); 
+                    qr = div(SP_ROW(Gk)[j], mk);
                     if (qr.quot <= qr.rem){
                         lmis[k][i+1].val[nnz] = SP_VALD(Gk)[j];
-                        lmis[k][i+1].ind[nnz] = qr.rem*(qr.rem+1)/2 + 
-                            qr.quot; 
+                        lmis[k][i+1].ind[nnz] = qr.rem*(qr.rem+1)/2 +
+                            qr.quot;
                         nnz++;
-                    } 
+                    }
                 }
-            } 
+            }
         }
     }
     for (k=0; k<l; k++) for(i=0; i<n+1; i++){
@@ -347,7 +347,7 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
                 lmis[k][i].ind, lmis[k][i].val, lmis[k][i].nnz);
         }
         else {
-            SDPConeSetADenseVecMat(sdpcone, k, i, lmis[k][i].n, 1.0, 
+            SDPConeSetADenseVecMat(sdpcone, k, i, lmis[k][i].n, 1.0,
                 lmis[k][i].val, lmis[k][i].nnz);
         }
         /* SDPConeViewDataMatrix(sdpcone, k, i);  */
@@ -360,18 +360,18 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
 	goto done;
     }
     DSDPStopReason(sdp, &info);
-    if (info != DSDP_CONVERGED && info != DSDP_SMALL_STEPS && 
-        info != DSDP_INDEFINITE_SCHUR_MATRIX && info != DSDP_MAX_IT 
+    if (info != DSDP_CONVERGED && info != DSDP_SMALL_STEPS &&
+        info != DSDP_INDEFINITE_SCHUR_MATRIX && info != DSDP_MAX_IT
         && info != DSDP_NUMERICAL_ERROR && info != DSDP_UPPERBOUND ){
         PyErr_SetObject(PyExc_ArithmeticError, Py_BuildValue("i",info));
         t = NULL;
         goto done;
     }
 
-    if (!(zs = PyList_New(l)) || !(x = (matrix *) Matrix_New(n, 1, 
-        DOUBLE)) || !(zl = (matrix *) Matrix_New(ml, 1, DOUBLE)) || 
-        !(zk = (double *) calloc(maxm*(maxm+1)/2, sizeof(double))) || 
-        !(t = PyTuple_New(5))) { 
+    if (!(zs = PyList_New(l)) || !(x = (matrix *) Matrix_New(n, 1,
+        DOUBLE)) || !(zl = (matrix *) Matrix_New(ml, 1, DOUBLE)) ||
+        !(zk = (double *) calloc(maxm*(maxm+1)/2, sizeof(double))) ||
+        !(t = PyTuple_New(5))) {
         Py_XDECREF(x);  Py_XDECREF(zl);  Py_XDECREF(zs);  Py_XDECREF(t);
         t = PyErr_NoMemory();
         goto done;
@@ -381,24 +381,24 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
     if (info == DSDP_CONVERGED) {
         switch (status){
             case DSDP_PDFEASIBLE:
-                PyTuple_SET_ITEM(t, 0, (PyObject *) 
+                PyTuple_SET_ITEM(t, 0, (PyObject *)
                     PyString_FromString("DSDP_PDFEASIBLE"));
 	        break;
             case DSDP_UNBOUNDED:
-                PyTuple_SET_ITEM(t, 0, (PyObject *) 
+                PyTuple_SET_ITEM(t, 0, (PyObject *)
                     PyString_FromString("DSDP_UNBOUNDED"));
 	        break;
             case DSDP_INFEASIBLE:
-                PyTuple_SET_ITEM(t, 0, (PyObject *) 
+                PyTuple_SET_ITEM(t, 0, (PyObject *)
                     PyString_FromString("DSDP_INFEASIBLE"));
 	        break;
             case DSDP_PDUNKNOWN:
-                PyTuple_SET_ITEM(t, 0, (PyObject *) 
+                PyTuple_SET_ITEM(t, 0, (PyObject *)
                     PyString_FromString("DSDP_UNKNOWN"));
 	        break;
         }
     } else {
-        PyTuple_SET_ITEM(t, 0, (PyObject *) 
+        PyTuple_SET_ITEM(t, 0, (PyObject *)
         PyString_FromString("DSDP_UNKNOWN"));
     }
 
@@ -414,10 +414,10 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
     PyTuple_SET_ITEM(t, 3, (PyObject *) zl);
 
     for (k=0; k<l; k++){
-        hk = (matrix *) PyList_GetItem(hs, k); 
-        mk = MAT_NROWS(hk); 
+        hk = (matrix *) PyList_GetItem(hs, k);
+        mk = MAT_NROWS(hk);
         if (!(zsk = (matrix *) Matrix_New(mk, mk, DOUBLE))){
-            Py_XDECREF(x);  Py_XDECREF(zl);  Py_XDECREF(zs);  
+            Py_XDECREF(x);  Py_XDECREF(zl);  Py_XDECREF(zs);
             Py_XDECREF(t);
             t = PyErr_NoMemory();
             goto done;
@@ -433,14 +433,14 @@ static PyObject* solvesdp(PyObject *self, PyObject *args,
 
     done:
         free(lp_colptr);  free(lp_rowind);  free(lp_values);  free(zk);
-        DSDPDestroy(sdp);  
-        if (lmis) for (k=0; k<l; k++){ 
-            if (lmis[k]) for (i=0; i<n+1; i++){ 
-                if (lmis[k][i].issparse) free(lmis[k][i].ind); 
-                free(lmis[k][i].val); 
-            } 
-        } 
-        free(lmis); 
+        DSDPDestroy(sdp);
+        if (lmis) for (k=0; k<l; k++){
+            if (lmis[k]) for (i=0; i<n+1; i++){
+                if (lmis[k][i].issparse) free(lmis[k][i].ind);
+                free(lmis[k][i].val);
+            }
+        }
+        free(lmis);
         return t;
 }
 
@@ -451,7 +451,7 @@ static PyMethodDef dsdp_functions[] = {
 
 PyMODINIT_FUNC initdsdp(void)
 {
-    dsdp_module = Py_InitModule3("cvxopt.dsdp", dsdp_functions, 
+    dsdp_module = Py_InitModule3("cvxopt.dsdp", dsdp_functions,
         dsdp__doc__);
     PyModule_AddObject(dsdp_module, "options", PyDict_New());
     if (import_cvxopt() < 0) return;
diff --git a/src/C/fftw.c b/src/C/fftw.c
index c7b1bc3..b966651 100644
--- a/src/C/fftw.c
+++ b/src/C/fftw.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,9 +26,9 @@ PyDoc_STRVAR(fftw__doc__,
 
 extern void zscal_(int *n, complex *alpha, complex *x, int *incx);
 extern void dscal_(int *n, double *alpha, double *x, int *incx);
-        
-static char doc_dft[] = 
-    "DFT of a matrix,  X := dft(X)\n\n" 
+
+static char doc_dft[] =
+    "DFT of a matrix,  X := dft(X)\n\n"
     "PURPOSE\n"
     "Computes the DFT of a dense matrix X column by column.\n\n"
     "ARGUMENTS\n"
@@ -39,30 +39,30 @@ static PyObject *dft(PyObject *self, PyObject *args, PyObject *kwrds)
   matrix *X;
   char *kwlist[] = {"X", NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O", kwlist, &X)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O", kwlist, &X))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == COMPLEX))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == COMPLEX))
     PY_ERR(PyExc_ValueError, "X must be a dense matrix with type 'z'");
 
-  int m = X->nrows, n = X->ncols; 
+  int m = X->nrows, n = X->ncols;
   if (m == 0) return Py_BuildValue("");
 
-  fftw_plan p = fftw_plan_many_dft(1, &m, n, 
+  fftw_plan p = fftw_plan_many_dft(1, &m, n,
       X->buffer, &m, 1, m,
       X->buffer, &m, 1, m,
       FFTW_FORWARD, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  fftw_destroy_plan(p);  
+  fftw_destroy_plan(p);
   return Py_BuildValue("");
 }
 
-static char doc_dftn[] = 
+static char doc_dftn[] =
     "N-dimensional DFT of a matrix.\n"
-    "X := dftn(X, dims)\n\n" 
+    "X := dftn(X, dims)\n\n"
     "PURPOSE\n"
     "Computes the DFT of an N-dimensional array represented by a dense\n"
     "matrix X. The shape of the matrix X does not matter, but the data\n"
@@ -81,12 +81,12 @@ static PyObject *dftn(PyObject *self, PyObject *args, PyObject *kwrds)
   int *dimarr;
   int free_dims = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|O:dftn", kwlist, &X, &dims)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|O:dftn", kwlist, &X, &dims))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == COMPLEX))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == COMPLEX))
     PY_ERR_TYPE("X must be a dense matrix with type 'z'");
-   
+
   if (!dims) {
     dims = PyTuple_New(2);
     if (!dims) return PyErr_NoMemory();
@@ -101,7 +101,7 @@ static PyObject *dftn(PyObject *self, PyObject *args, PyObject *kwrds)
     PY_ERR_TYPE("invalid dimension tuple");
   }
 
-  int len = PySequence_Size(dims);  
+  int len = PySequence_Size(dims);
   PyObject *seq = PySequence_Fast(dims, "list is not iterable");
 
   if (!(dimarr = malloc(len*sizeof(int)))) {
@@ -113,21 +113,21 @@ static PyObject *dftn(PyObject *self, PyObject *args, PyObject *kwrds)
   int i, proddim = 1;
   for (i=0; i<len; i++) {
     PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
     if (!PyInt_Check(item)) {
       if (free_dims) { Py_DECREF(dims); }
       Py_DECREF(seq);
-      free(dimarr); 
+      free(dimarr);
       PY_ERR_TYPE("non-integer in dimension tuple");
     }
-    
+
     dimarr[len-i-1] = PyInt_AS_LONG(item);
     if (dimarr[len-i-1] < 0) {
       if (free_dims) { Py_DECREF(dims); }
       Py_DECREF(seq);
-      free(dimarr); 
+      free(dimarr);
       PY_ERR(PyExc_ValueError, "negative dimension");
-    }        
+    }
     proddim *= dimarr[len-i-1];
   }
 
@@ -136,12 +136,12 @@ static PyObject *dftn(PyObject *self, PyObject *args, PyObject *kwrds)
   Py_DECREF(seq);
 
   if (proddim != MAT_LGT(X)) {
-    free(dimarr); 
+    free(dimarr);
     PY_ERR_TYPE("length of X does not match dimensions");
   }
-    
+
   if (proddim == 0) {
-    free(dimarr); 
+    free(dimarr);
     return Py_BuildValue("");
   }
 
@@ -149,15 +149,15 @@ static PyObject *dftn(PyObject *self, PyObject *args, PyObject *kwrds)
       X->buffer, X->buffer, FFTW_FORWARD, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  fftw_destroy_plan(p);  
-  free(dimarr); 
+  fftw_destroy_plan(p);
+  free(dimarr);
   return Py_BuildValue("");
 }
 
-static char doc_idft[] = 
-    "IDFT of a matrix,  X := idft(X)\n\n" 
+static char doc_idft[] =
+    "IDFT of a matrix,  X := idft(X)\n\n"
     "PURPOSE\n"
     "Computes the inverse DFT of a dense matrix X column by column.\n\n"
     "ARGUMENTS\n"
@@ -168,36 +168,36 @@ static PyObject *idft(PyObject *self, PyObject *args, PyObject *kwrds)
   matrix *X;
   char *kwlist[] = {"X", NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O", kwlist, &X)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O", kwlist, &X))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == COMPLEX))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == COMPLEX))
     PY_ERR(PyExc_ValueError, "X must be a dense matrix with type 'z'");
 
-  int m = X->nrows, n = X->ncols; 
+  int m = X->nrows, n = X->ncols;
   if (m == 0) return Py_BuildValue("");
 
-  fftw_plan p = fftw_plan_many_dft(1, &m, n, 
+  fftw_plan p = fftw_plan_many_dft(1, &m, n,
       X->buffer, &m, 1, m,
       X->buffer, &m, 1, m,
       FFTW_BACKWARD, FFTW_ESTIMATE);
-  
+
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p); 
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  
+
   number a;
   a.z = 1.0/m;
   int mn = m*n, ix = 1;
   zscal_(&mn, &a.z, MAT_BUFZ(X), &ix);
-  
+
   fftw_destroy_plan(p);
-  return Py_BuildValue("");  
+  return Py_BuildValue("");
 }
 
-static char doc_idftn[] = 
+static char doc_idftn[] =
     "Inverse N-dimensional DFT of a matrix.\n"
-    "X := idftn(X, dims)\n\n" 
+    "X := idftn(X, dims)\n\n"
     "PURPOSE\n"
     "Computes the IDFT of an N-dimensional array represented by a dense\n"
     "matrix X. The shape of the matrix X does not matter, but the data\n"
@@ -216,11 +216,11 @@ static PyObject *idftn(PyObject *self, PyObject *args, PyObject *kwrds)
   int *dimarr;
   int free_dims = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|O:idftn", 
-	  kwlist, &X, &dims)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|O:idftn",
+	  kwlist, &X, &dims))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == COMPLEX))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == COMPLEX))
     PY_ERR_TYPE("X must be a dense matrix with type 'z'");
 
   if (!dims) {
@@ -232,10 +232,10 @@ static PyObject *idftn(PyObject *self, PyObject *args, PyObject *kwrds)
     free_dims = 1;
   }
 
-  if (!PyTuple_Check(dims)) 
+  if (!PyTuple_Check(dims))
     PY_ERR_TYPE("invalid dimension tuple");
 
-  int len = PySequence_Size(dims);  
+  int len = PySequence_Size(dims);
   PyObject *seq = PySequence_Fast(dims, "list is not iterable");
 
   if (!(dimarr = malloc(len*sizeof(int)))) {
@@ -247,21 +247,21 @@ static PyObject *idftn(PyObject *self, PyObject *args, PyObject *kwrds)
   int i, proddim = 1;
   for (i=0; i<len; i++) {
     PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
     if (!PyInt_Check(item)) {
       if (free_dims) { Py_DECREF(dims); }
       Py_DECREF(seq);
-      free(dimarr); 
+      free(dimarr);
       PY_ERR_TYPE("non-integer in dimension tuple");
     }
-    
+
     dimarr[len-i-1] = PyInt_AS_LONG(item);
     if (dimarr[len-i-1] < 0) {
       if (free_dims) { Py_DECREF(dims); }
       Py_DECREF(seq);
-      free(dimarr); 
+      free(dimarr);
       PY_ERR(PyExc_ValueError, "negative dimension");
-    }        
+    }
     proddim *= dimarr[len-i-1];
   }
 
@@ -270,12 +270,12 @@ static PyObject *idftn(PyObject *self, PyObject *args, PyObject *kwrds)
   if (free_dims) { Py_DECREF(dims); }
 
   if (proddim != MAT_LGT(X)) {
-    free(dimarr); 
+    free(dimarr);
     PY_ERR_TYPE("length of X does not match dimensions");
   }
-    
+
   if (proddim == 0) {
-    free(dimarr); 
+    free(dimarr);
     return Py_BuildValue("");
   }
 
@@ -289,16 +289,16 @@ static PyObject *idftn(PyObject *self, PyObject *args, PyObject *kwrds)
       X->buffer, X->buffer, FFTW_BACKWARD, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  fftw_destroy_plan(p);  
-  free(dimarr); 
+  fftw_destroy_plan(p);
+  free(dimarr);
   return Py_BuildValue("");
 }
 
-static char doc_dct[] = 
+static char doc_dct[] =
     "DCT of a matrix.\n"
-    "X := dct(X, type=2)\n\n" 
+    "X := dct(X, type=2)\n\n"
     "PURPOSE\n"
     "Computes the DCT of a dense matrix X column by column.\n\n"
     "ARGUMENTS\n"
@@ -312,19 +312,19 @@ static PyObject *dct(PyObject *self, PyObject *args, PyObject *kwrds)
   int type = 2;
   char *kwlist[] = {"X", "type", NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|i", kwlist, &X, &type)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|i", kwlist, &X, &type))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))
     PY_ERR(PyExc_ValueError, "X must be a dense matrix with type 'd'");
-   
+
   int m = X->nrows, n = X->ncols;
   if (m == 0) return Py_BuildValue("");
 
   fftw_r2r_kind kind;
   switch(type) {
-  case 1: 
-    kind = FFTW_REDFT00; 
+  case 1:
+    kind = FFTW_REDFT00;
     if (m <= 1) PY_ERR(PyExc_ValueError, "m must be greater than 1 for DCT-I");
     break;
   case 2: kind = FFTW_REDFT10; break;
@@ -332,21 +332,21 @@ static PyObject *dct(PyObject *self, PyObject *args, PyObject *kwrds)
   case 4: kind = FFTW_REDFT11; break;
   default: PY_ERR(PyExc_ValueError, "type must be between 1 and 4");
   }
-  fftw_plan p = fftw_plan_many_r2r(1, &m, n, 
+  fftw_plan p = fftw_plan_many_r2r(1, &m, n,
       X->buffer, &m, 1, m,
       X->buffer, &m, 1, m,
       &kind, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  fftw_destroy_plan(p);  
+  fftw_destroy_plan(p);
   return Py_BuildValue("");
 }
 
-static char doc_dctn[] = 
+static char doc_dctn[] =
     "N-dimensional DCT of a matrix.\n"
-    "X := dctn(X, dims, type=2)\n\n" 
+    "X := dctn(X, dims, type=2)\n\n"
     "PURPOSE\n"
     "Computes the DCT of an N-dimensional array represented by a dense\n"
     "matrix X. The shape of the matrix X does not matter, but the data\n"
@@ -368,11 +368,11 @@ static PyObject *dctn(PyObject *self, PyObject *args, PyObject *kwrds)
   fftw_r2r_kind *kindarr;
   int free_dims = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OO:dctn", kwlist, 
-	  &X, &dims, &type)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OO:dctn", kwlist,
+	  &X, &dims, &type))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))
     PY_ERR_TYPE("X must be a dense matrix with type 'd'");
 
   if (!dims) {
@@ -383,8 +383,8 @@ static PyObject *dctn(PyObject *self, PyObject *args, PyObject *kwrds)
     PyTuple_SET_ITEM(dims, 1, PyInt_FromLong(MAT_NROWS(X)));
     free_dims = 1;
   }
-   
-  if (!PyTuple_Check(dims)) 
+
+  if (!PyTuple_Check(dims))
     PY_ERR_TYPE("invalid dimension tuple");
 
   if (type && !PyTuple_Check(type)) {
@@ -416,21 +416,21 @@ static PyObject *dctn(PyObject *self, PyObject *args, PyObject *kwrds)
   int i, proddim = 1;
   for (i=0; i<len; i++) {
     PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
     if (!PyInt_Check(item)) {
       if (free_dims) { Py_DECREF(dims); }
       Py_DECREF(seq);
       free(dimarr); free(kindarr);
       PY_ERR_TYPE("non-integer in dimension tuple");
     }
-    
+
     dimarr[len-i-1] = PyInt_AS_LONG(item);
     if (dimarr[len-i-1] < 0) {
       if (free_dims) { Py_DECREF(dims); }
       Py_DECREF(seq);
       free(dimarr); free(kindarr);
       PY_ERR(PyExc_ValueError, "negative dimension");
-    }        
+    }
     proddim *= dimarr[len-i-1];
   }
 
@@ -441,7 +441,7 @@ static PyObject *dctn(PyObject *self, PyObject *args, PyObject *kwrds)
     free(dimarr); free(kindarr);
     PY_ERR_TYPE("length of X does not match dimensions");
   }
-    
+
   if (proddim == 0) {
     Py_DECREF(seq);
     free(dimarr); free(kindarr);
@@ -449,41 +449,41 @@ static PyObject *dctn(PyObject *self, PyObject *args, PyObject *kwrds)
   }
 
   Py_DECREF(seq);
-  
+
   if (type == NULL) {
     for (i=0; i<len; i++)
       kindarr[i] = FFTW_REDFT10;
   } else {
-    
+
     seq = PySequence_Fast(type, "list is not iterable");
 
     for (i=0; i<len; i++) {
       PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
       if (!PyInt_Check(item)) {
 	Py_DECREF(seq);
 	free(dimarr); free(kindarr);
 	PY_ERR_TYPE("non-integer in type tuple");
       }
-      
+
       switch(PyInt_AS_LONG(item)) {
-      case 1: 
-	kindarr[len-i-1] = FFTW_REDFT00; 
+      case 1:
+	kindarr[len-i-1] = FFTW_REDFT00;
 	if (dimarr[len-i-1] <= 1) {
 	  Py_DECREF(seq);
 	  free(dimarr); free(kindarr);
-	  PY_ERR(PyExc_ValueError, 
+	  PY_ERR(PyExc_ValueError,
 	      "dimension must be greater than 1 for DCT-I");
 	}
 	break;
       case 2: kindarr[len-i-1] = FFTW_REDFT10; break;
       case 3: kindarr[len-i-1] = FFTW_REDFT01; break;
       case 4: kindarr[len-i-1] = FFTW_REDFT11; break;
-      default: 
+      default:
 	Py_DECREF(seq);
 	free(dimarr); free(kindarr);
 	PY_ERR(PyExc_ValueError, "type must be between 1 and 4");
-      }      
+      }
     }
 
     Py_DECREF(seq);
@@ -493,16 +493,16 @@ static PyObject *dctn(PyObject *self, PyObject *args, PyObject *kwrds)
       X->buffer, X->buffer, kindarr, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  fftw_destroy_plan(p);  
+  fftw_destroy_plan(p);
   free(dimarr); free(kindarr);
   return Py_BuildValue("");
 }
 
-static char doc_idct[] = 
+static char doc_idct[] =
     "Inverse DCT of a matrix.\n"
-    "X := idct(X, type=2)\n\n" 
+    "X := idct(X, type=2)\n\n"
     "PURPOSE\n"
     "Computes the IDCT of a dense matrix X column by column.\n\n"
     "ARGUMENTS\n"
@@ -516,18 +516,18 @@ static PyObject *idct(PyObject *self, PyObject *args, PyObject *kwrds)
   int type = 2;
   char *kwlist[] = {"X", "type", NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|i", kwlist, &X, &type)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|i", kwlist, &X, &type))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))
     PY_ERR(PyExc_ValueError, "X must be a dense matrix with type 'd'");
-   
+
   int m = X->nrows, n = X->ncols;
   if (m == 0) return Py_BuildValue("");
 
   fftw_r2r_kind kind;
   switch(type) {
-  case 1: kind = FFTW_REDFT00; 
+  case 1: kind = FFTW_REDFT00;
     if (m <= 1) PY_ERR(PyExc_ValueError, "m must be greater than 1 for DCT-I");
     break;
   case 2: kind = FFTW_REDFT01; break;
@@ -535,26 +535,26 @@ static PyObject *idct(PyObject *self, PyObject *args, PyObject *kwrds)
   case 4: kind = FFTW_REDFT11; break;
   default: PY_ERR(PyExc_ValueError, "type must be between 1 and 4");
   }
-  fftw_plan p = fftw_plan_many_r2r(1, &m, n, 
+  fftw_plan p = fftw_plan_many_r2r(1, &m, n,
       X->buffer, &m, 1, m,
       X->buffer, &m, 1, m,
       &kind, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  
+
   double a = 1.0/(type == 1 ? MAX(1,2*(m-1)) : 2*m);
   int mn = m*n, ix = 1;
   dscal_(&mn, &a, MAT_BUFD(X), &ix);
 
-  fftw_destroy_plan(p);  
+  fftw_destroy_plan(p);
   return Py_BuildValue("");
 }
 
-static char doc_idctn[] = 
+static char doc_idctn[] =
     "Inverse N-dimensional DCT of a matrix.\n"
-    "X := idctn(X, dims, type=2)\n\n" 
+    "X := idctn(X, dims, type=2)\n\n"
     "PURPOSE\n"
     "Computes the IDCT of an N-dimensional array represented by a dense\n"
     "matrix X. The shape of the matrix X does not matter, but the data\n"
@@ -576,11 +576,11 @@ static PyObject *idctn(PyObject *self, PyObject *args, PyObject *kwrds)
   fftw_r2r_kind *kindarr;
   int free_dims = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OO:idctn", kwlist, 
-	  &X, &dims, &type)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OO:idctn", kwlist,
+	  &X, &dims, &type))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))
     PY_ERR_TYPE("X must be a dense matrix with type 'd'");
 
   if (!dims) {
@@ -591,8 +591,8 @@ static PyObject *idctn(PyObject *self, PyObject *args, PyObject *kwrds)
     PyTuple_SET_ITEM(dims, 1, PyInt_FromLong(MAT_NROWS(X)));
     free_dims = 1;
   }
-   
-  if (!PyTuple_Check(dims)) 
+
+  if (!PyTuple_Check(dims))
     PY_ERR_TYPE("invalid dimension tuple");
 
   if (type && !PyTuple_Check(type)) {
@@ -624,21 +624,21 @@ static PyObject *idctn(PyObject *self, PyObject *args, PyObject *kwrds)
   int i, proddim = 1;
   for (i=0; i<len; i++) {
     PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
     if (!PyInt_Check(item)) {
       if (free_dims) { Py_DECREF(dims); }
       Py_DECREF(seq);
       free(dimarr); free(kindarr);
       PY_ERR_TYPE("non-integer in dimension tuple");
     }
-    
+
     dimarr[len-i-1] = PyInt_AS_LONG(item);
     if (dimarr[len-i-1] < 0) {
       if (free_dims) { Py_DECREF(dims); }
       Py_DECREF(seq);
       free(dimarr); free(kindarr);
       PY_ERR(PyExc_ValueError, "negative dimension");
-    }        
+    }
     proddim *= dimarr[len-i-1];
   }
 
@@ -650,42 +650,42 @@ static PyObject *idctn(PyObject *self, PyObject *args, PyObject *kwrds)
     free(dimarr); free(kindarr);
     PY_ERR_TYPE("length of X does not match dimensions");
   }
-    
+
   if (proddim == 0) {
     free(dimarr); free(kindarr);
     return Py_BuildValue("");
   }
-    
+
   if (type == NULL) {
     for (i=0; i<len; i++)
       kindarr[i] = FFTW_REDFT01;
   } else {
-    
+
     seq = PySequence_Fast(type, "list is not iterable");
 
     for (i=0; i<len; i++) {
       PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-      
+
       if (!PyInt_Check(item)) {
 	Py_DECREF(seq);
 	free(dimarr); free(kindarr);
 	PY_ERR_TYPE("non-integer in type tuple");
       }
-      
+
       switch(PyInt_AS_LONG(item)) {
-      case 1: 
-	kindarr[len-i-1] = FFTW_REDFT00; 
+      case 1:
+	kindarr[len-i-1] = FFTW_REDFT00;
 	if (dimarr[len-i-1] <= 1) {
 	  Py_DECREF(seq);
 	  free(dimarr); free(kindarr);
-	  PY_ERR(PyExc_ValueError, 
+	  PY_ERR(PyExc_ValueError,
 	      "dimension must be greater than 1 for DCT-I");
 	}
 	break;
       case 2: kindarr[len-i-1] = FFTW_REDFT01; break;
       case 3: kindarr[len-i-1] = FFTW_REDFT10; break;
       case 4: kindarr[len-i-1] = FFTW_REDFT11; break;
-      default: 
+      default:
 	Py_DECREF(seq);
 	free(dimarr); free(kindarr);
 	PY_ERR(PyExc_ValueError, "type must be between 1 and 4");
@@ -701,21 +701,21 @@ static PyObject *idctn(PyObject *self, PyObject *args, PyObject *kwrds)
 
   int ix = 1;
   dscal_(&proddim, &a, MAT_BUFD(X), &ix);
-  
+
   fftw_plan p = fftw_plan_r2r(len, dimarr,
       X->buffer, X->buffer, kindarr, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  fftw_destroy_plan(p);  
+  fftw_destroy_plan(p);
   free(dimarr); free(kindarr);
   return Py_BuildValue("");
 }
 
-static char doc_dst[] = 
+static char doc_dst[] =
     "DST of a matrix.\n"
-    "X := dst(X, type=1)\n\n" 
+    "X := dst(X, type=1)\n\n"
     "PURPOSE\n"
     "Computes the DST of a dense matrix X column by column.\n\n"
     "ARGUMENTS\n"
@@ -729,12 +729,12 @@ static PyObject *dst(PyObject *self, PyObject *args, PyObject *kwrds)
   int type = 1;
   char *kwlist[] = {"X", "type", NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|i", kwlist, &X, &type)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|i", kwlist, &X, &type))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))
     PY_ERR(PyExc_ValueError, "X must be a dense matrix with type 'd'");
-   
+
   int m = X->nrows, n = X->ncols;
   if (m == 0) return Py_BuildValue("");
 
@@ -746,21 +746,21 @@ static PyObject *dst(PyObject *self, PyObject *args, PyObject *kwrds)
   case 4: kind = FFTW_RODFT11; break;
   default: PY_ERR(PyExc_ValueError, "type must be between 1 and 4");
   }
-  fftw_plan p = fftw_plan_many_r2r(1, &m, n, 
+  fftw_plan p = fftw_plan_many_r2r(1, &m, n,
       X->buffer, &m, 1, m,
       X->buffer, &m, 1, m,
       &kind, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  fftw_destroy_plan(p);  
+  fftw_destroy_plan(p);
   return Py_BuildValue("");
 }
 
-static char doc_dstn[] = 
+static char doc_dstn[] =
     "N-dimensional DST of a matrix.\n"
-    "X := dstn(X, dims, type=1)\n\n" 
+    "X := dstn(X, dims, type=1)\n\n"
     "PURPOSE\n"
     "Computes the DST of an N-dimensional array represented by a dense\n"
     "matrix X. The shape of the matrix X does not matter, but the data\n"
@@ -782,11 +782,11 @@ static PyObject *dstn(PyObject *self, PyObject *args, PyObject *kwrds)
   fftw_r2r_kind *kindarr;
   int free_dims = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OO:dctn", kwlist, 
-	  &X, &dims, &type)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OO:dctn", kwlist,
+	  &X, &dims, &type))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))
     PY_ERR_TYPE("X must be a dense matrix with type 'd'");
 
   if (!dims) {
@@ -797,8 +797,8 @@ static PyObject *dstn(PyObject *self, PyObject *args, PyObject *kwrds)
     PyTuple_SET_ITEM(dims, 1, PyInt_FromLong(MAT_NROWS(X)));
     free_dims = 1;
   }
-   
-  if (!PyTuple_Check(dims)) 
+
+  if (!PyTuple_Check(dims))
     PY_ERR_TYPE("invalid dimension tuple");
 
   if (type && !PyTuple_Check(type))
@@ -826,19 +826,19 @@ static PyObject *dstn(PyObject *self, PyObject *args, PyObject *kwrds)
   int i, proddim = 1;
   for (i=0; i<len; i++) {
     PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
     if (!PyInt_Check(item)) {
       if (free_dims) { Py_DECREF(dims); }
       free(dimarr); free(kindarr);
       PY_ERR_TYPE("non-integer in dimension tuple");
     }
-    
+
     dimarr[len-i-1] = PyInt_AS_LONG(item);
     if (dimarr[len-i-1] < 0) {
       if (free_dims) { Py_DECREF(dims); }
       free(dimarr); free(kindarr);
       PY_ERR(PyExc_ValueError, "negative dimension");
-    }        
+    }
     proddim *= dimarr[len-i-1];
   }
 
@@ -848,7 +848,7 @@ static PyObject *dstn(PyObject *self, PyObject *args, PyObject *kwrds)
     free(dimarr); free(kindarr);
     PY_ERR_TYPE("length of X does not match dimensions");
   }
-    
+
   if (proddim == 0) {
     free(dimarr); free(kindarr);
     return Py_BuildValue("");
@@ -858,23 +858,23 @@ static PyObject *dstn(PyObject *self, PyObject *args, PyObject *kwrds)
     for (i=0; i<len; i++)
       kindarr[i] = FFTW_RODFT00;
   } else {
-    
+
     seq = PySequence_Fast(type, "list is not iterable");
 
     for (i=0; i<len; i++) {
       PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
       if (!PyInt_Check(item)) {
 	free(dimarr); free(kindarr);
 	PY_ERR_TYPE("non-integer in type tuple");
       }
-      
+
       switch(PyInt_AS_LONG(item)) {
       case 1: kindarr[len-i-1] = FFTW_RODFT00; break;
       case 2: kindarr[len-i-1] = FFTW_RODFT10; break;
       case 3: kindarr[len-i-1] = FFTW_RODFT01; break;
       case 4: kindarr[len-i-1] = FFTW_RODFT11; break;
-      default: 
+      default:
 	free(dimarr); free(kindarr);
 	PY_ERR(PyExc_ValueError, "type must be between 1 and 4");
       }
@@ -885,16 +885,16 @@ static PyObject *dstn(PyObject *self, PyObject *args, PyObject *kwrds)
       X->buffer, X->buffer, kindarr, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  fftw_destroy_plan(p);  
+  fftw_destroy_plan(p);
   free(dimarr); free(kindarr);
   return Py_BuildValue("");
 }
 
-static char doc_idst[] = 
+static char doc_idst[] =
     "IDST of a matrix.\n"
-    "X := idst(X, type=1)\n\n" 
+    "X := idst(X, type=1)\n\n"
     "PURPOSE\n"
     "Computes the IDST of a dense matrix X column by column.\n\n"
     "ARGUMENTS\n"
@@ -908,12 +908,12 @@ static PyObject *idst(PyObject *self, PyObject *args, PyObject *kwrds)
   int type = 1;
   char *kwlist[] = {"X", "type", NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|i", kwlist, &X, &type)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|i", kwlist, &X, &type))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))
     PY_ERR(PyExc_ValueError, "X must be a dense matrix with type 'd'");
-   
+
   int m = X->nrows, n = X->ncols;
   if (m == 0) return Py_BuildValue("");
 
@@ -925,26 +925,26 @@ static PyObject *idst(PyObject *self, PyObject *args, PyObject *kwrds)
   case 4: kind = FFTW_RODFT11; break;
   default: PY_ERR(PyExc_ValueError, "type must be between 1 and 4");
   }
-  fftw_plan p = fftw_plan_many_r2r(1, &m, n, 
+  fftw_plan p = fftw_plan_many_r2r(1, &m, n,
       X->buffer, &m, 1, m,
       X->buffer, &m, 1, m,
       &kind, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  
+
   double a = 1.0/(type == 1 ? MAX(1,2*(m+1)) : 2*m);
   int mn = m*n, ix = 1;
   dscal_(&mn, &a, MAT_BUFD(X), &ix);
 
-  fftw_destroy_plan(p);  
+  fftw_destroy_plan(p);
   return Py_BuildValue("");
 }
 
-static char doc_idstn[] = 
+static char doc_idstn[] =
     "Inverse N-dimensional DST of a matrix.\n"
-    "X := idstn(X, dims, type=1)\n\n" 
+    "X := idstn(X, dims, type=1)\n\n"
     "PURPOSE\n"
     "Computes the IDST of an N-dimensional array represented by a dense\n"
     "matrix X. The shape of the matrix X does not matter, but the data\n"
@@ -966,11 +966,11 @@ static PyObject *idstn(PyObject *self, PyObject *args, PyObject *kwrds)
   fftw_r2r_kind *kindarr;
   int free_dims = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OO:dctn", kwlist, 
-	  &X, &dims, &type)) 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OO:dctn", kwlist,
+	  &X, &dims, &type))
     return NULL;
 
-  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))     
+  if (!(Matrix_Check(X) && MAT_ID(X) == DOUBLE))
     PY_ERR_TYPE("X must be a dense matrix with type 'd'");
 
   if (!dims) {
@@ -981,8 +981,8 @@ static PyObject *idstn(PyObject *self, PyObject *args, PyObject *kwrds)
     PyTuple_SET_ITEM(dims, 1, PyInt_FromLong(MAT_NROWS(X)));
     free_dims = 1;
   }
-   
-  if (!PyTuple_Check(dims)) 
+
+  if (!PyTuple_Check(dims))
     PY_ERR_TYPE("invalid dimension tuple");
 
   if (type && !PyTuple_Check(type)) {
@@ -1012,19 +1012,19 @@ static PyObject *idstn(PyObject *self, PyObject *args, PyObject *kwrds)
   int i, proddim = 1;
   for (i=0; i<len; i++) {
     PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
     if (!PyInt_Check(item)) {
       if (free_dims) { Py_DECREF(dims); }
       free(dimarr); free(kindarr);
       PY_ERR_TYPE("non-integer in dimension tuple");
     }
-    
+
     dimarr[len-i-1] = PyInt_AS_LONG(item);
     if (dimarr[len-i-1] < 0) {
       if (free_dims) { Py_DECREF(dims); }
       free(dimarr); free(kindarr);
       PY_ERR(PyExc_ValueError, "negative dimension");
-    }        
+    }
     proddim *= dimarr[len-i-1];
   }
 
@@ -1034,33 +1034,33 @@ static PyObject *idstn(PyObject *self, PyObject *args, PyObject *kwrds)
     free(dimarr); free(kindarr);
     PY_ERR_TYPE("length of X does not match dimensions");
   }
-    
+
   if (proddim == 0) {
     free(dimarr); free(kindarr);
     return Py_BuildValue("");
   }
-    
+
   if (type == NULL) {
     for (i=0; i<len; i++)
       kindarr[i] = FFTW_RODFT00;
   } else {
-    
+
     seq = PySequence_Fast(type, "list is not iterable");
 
     for (i=0; i<len; i++) {
       PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
-	
+
       if (!PyInt_Check(item)) {
 	free(dimarr); free(kindarr);
 	PY_ERR_TYPE("non-integer in type tuple");
       }
-    
+
       switch(PyInt_AS_LONG(item)) {
       case 1: kindarr[len-i-1] = FFTW_RODFT00; break;
       case 2: kindarr[len-i-1] = FFTW_RODFT10; break;
       case 3: kindarr[len-i-1] = FFTW_RODFT01; break;
       case 4: kindarr[len-i-1] = FFTW_RODFT11; break;
-      default: 
+      default:
 	free(dimarr); free(kindarr);
 	PY_ERR(PyExc_ValueError, "type must be between 1 and 4");
       }
@@ -1073,14 +1073,14 @@ static PyObject *idstn(PyObject *self, PyObject *args, PyObject *kwrds)
 
   int ix = 1;
   dscal_(&proddim, &a, MAT_BUFD(X), &ix);
-  
+
   fftw_plan p = fftw_plan_r2r(len, dimarr,
       X->buffer, X->buffer, kindarr, FFTW_ESTIMATE);
 
   Py_BEGIN_ALLOW_THREADS
-  fftw_execute(p);   
+  fftw_execute(p);
   Py_END_ALLOW_THREADS
-  fftw_destroy_plan(p);  
+  fftw_destroy_plan(p);
   free(dimarr); free(kindarr);
   return Py_BuildValue("");
 }
diff --git a/src/C/glpk.c b/src/C/glpk.c
index cae0623..8243f23 100644
--- a/src/C/glpk.c
+++ b/src/C/glpk.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2007 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@
 #include "glpk.h"
 
 PyDoc_STRVAR(glpk__doc__,
-    "Interface to the simplex algorithm in GLPK.\n\n" 
+    "Interface to the simplex algorithm in GLPK.\n\n"
     "The GLPK control parameters have the default values listed in \n"
     "the GLPK documentation, except for 'LPX_K_PRESOL', which is set\n"
     "to 1 and cannot be modified.  The other parameters can be\n"
@@ -40,7 +40,7 @@ typedef struct {
     char  type;
 }   param_tuple;
 
-static const param_tuple GLPK_PARAM_LIST[] = { 
+static const param_tuple GLPK_PARAM_LIST[] = {
     {"LPX_K_MSGLEV", 300, 'i'},
     {"LPX_K_SCALE",  301, 'i'},
     {"LPX_K_DUAL",   302, 'i'},
@@ -72,22 +72,22 @@ static const param_tuple GLPK_PARAM_LIST[] = {
 }; /* 28 paramaters */
 
 
-static int get_param_idx(char *str, int *idx, char *type) 
+static int get_param_idx(char *str, int *idx, char *type)
 {
     int i;
 
     for (i=0; i<28; i++) {
         if (!strcmp(GLPK_PARAM_LIST[i].name, str)) {
-            *idx =  GLPK_PARAM_LIST[i].idx; 
-            *type = GLPK_PARAM_LIST[i].type; 
+            *idx =  GLPK_PARAM_LIST[i].idx;
+            *type = GLPK_PARAM_LIST[i].type;
             return 1;
         }
     }
-    return 0;  
+    return 0;
 }
 
 
-static char doc_simplex[] = 
+static char doc_simplex[] =
     "Solves a linear program using GLPK.\n\n"
     "(status, x, z, y) = lp(c, G, h, A, b)\n"
     "(status, x, z) = lp(c, G, h)\n\n"
@@ -103,7 +103,7 @@ static char doc_simplex[] =
     "    subject to  G*x <= h        subject to  G'*z + c = 0\n"
     "                                            z >= 0.\n\n"
     "ARGUMENTS\n"
-    "c            nx1 dense 'd' matrix with n>=1\n\n" 
+    "c            nx1 dense 'd' matrix with n>=1\n\n"
     "G            mxn dense or sparse 'd' matrix with m>=1\n\n"
     "h            mx1 dense 'd' matrix\n\n"
     "A            pxn dense or sparse 'd' matrix with p>=0\n\n"
@@ -116,14 +116,14 @@ static char doc_simplex[] =
     "             None otherwise";
 
 
-static PyObject *simplex(PyObject *self, PyObject *args, 
+static PyObject *simplex(PyObject *self, PyObject *args,
     PyObject *kwrds)
 {
     matrix *c, *h, *b=NULL, *x=NULL, *z=NULL, *y=NULL;
     PyObject *G, *A=NULL, *t=NULL, *param, *key, *value;
     LPX *lp;
     int m, n, p, i, j, k, nnz, nnzmax, *rn=NULL, *cn=NULL, param_id;
-    int_t pos=0;    
+    int_t pos=0;
     double *a=NULL, val;
     char param_type, err_str[100], *keystr;
     char *kwlist[] = {"c", "G", "h", "A", "b", NULL};
@@ -131,15 +131,15 @@ static PyObject *simplex(PyObject *self, PyObject *args,
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|OO", kwlist, &c,
         &G, &h, &A, &b)) return NULL;
 
-    if ((Matrix_Check(G) && MAT_ID(G) != DOUBLE) || 
+    if ((Matrix_Check(G) && MAT_ID(G) != DOUBLE) ||
         (SpMatrix_Check(G) && SP_ID(G) != DOUBLE) ||
         (!Matrix_Check(G) && !SpMatrix_Check(G))){
         PyErr_SetString(PyExc_TypeError, "G must be a 'd' matrix");
         return NULL;
     }
-    if ((m = Matrix_Check(G) ? MAT_NROWS(G) : SP_NROWS(G)) <= 0) 
+    if ((m = Matrix_Check(G) ? MAT_NROWS(G) : SP_NROWS(G)) <= 0)
         err_p_int("m");
-    if ((n = Matrix_Check(G) ? MAT_NCOLS(G) : SP_NCOLS(G)) <= 0) 
+    if ((n = Matrix_Check(G) ? MAT_NCOLS(G) : SP_NCOLS(G)) <= 0)
         err_p_int("n");
 
     if (!Matrix_Check(h) || h->id != DOUBLE) err_dbl_mtrx("h");
@@ -149,7 +149,7 @@ static PyObject *simplex(PyObject *self, PyObject *args,
     }
 
     if (A){
-        if ((Matrix_Check(A) && MAT_ID(A) != DOUBLE) || 
+        if ((Matrix_Check(A) && MAT_ID(A) != DOUBLE) ||
             (SpMatrix_Check(A) && SP_ID(A) != DOUBLE) ||
             (!Matrix_Check(A) && !SpMatrix_Check(A))){
                 PyErr_SetString(PyExc_ValueError, "A must be a dense "
@@ -181,12 +181,12 @@ static PyObject *simplex(PyObject *self, PyObject *args,
         lpx_set_col_bnds(lp, i+1, LPX_FR, 0.0, 0.0);
     }
     for (i=0; i<m; i++)
-        lpx_set_row_bnds(lp, i+1, LPX_UP, 0.0, MAT_BUFD(h)[i]);     
+        lpx_set_row_bnds(lp, i+1, LPX_UP, 0.0, MAT_BUFD(h)[i]);
     for (i=0; i<p; i++)
-        lpx_set_row_bnds(lp, i+m+1, LPX_FX, MAT_BUFD(b)[i], 
-            MAT_BUFD(b)[i]);     
+        lpx_set_row_bnds(lp, i+m+1, LPX_FX, MAT_BUFD(b)[i],
+            MAT_BUFD(b)[i]);
 
-    nnzmax = (SpMatrix_Check(G) ? SP_NNZ(G) : m*n ) + 
+    nnzmax = (SpMatrix_Check(G) ? SP_NNZ(G) : m*n ) +
         ((A && SpMatrix_Check(A)) ? SP_NNZ(A) : p*n);
     a = (double *) calloc(nnzmax+1, sizeof(double));
     rn = (int *) calloc(nnzmax+1, sizeof(int));
@@ -242,19 +242,19 @@ static PyObject *simplex(PyObject *self, PyObject *args,
     if (!(param = PyObject_GetAttrString(glpk_module, "options"))
         || !PyDict_Check(param)){
             lpx_delete_prob(lp);
-            PyErr_SetString(PyExc_AttributeError, 
+            PyErr_SetString(PyExc_AttributeError,
                 "missing glpk.options dictionary");
-            return NULL; 
+            return NULL;
     }
-    
+
     while (PyDict_Next(param, &pos, &key, &value))
-        if ((keystr = PyString_AsString(key)) && get_param_idx(keystr, 
+        if ((keystr = PyString_AsString(key)) && get_param_idx(keystr,
             &param_id, &param_type)){
 	    if (param_type == 'i'){
 	        if (!PyInt_Check(value)){
                     sprintf(err_str, "invalid value for integer "
                         "GLPK parameter: %-.20s", keystr);
-                    PyErr_SetString(PyExc_ValueError, err_str); 
+                    PyErr_SetString(PyExc_ValueError, err_str);
 	            lpx_delete_prob(lp);
 	            Py_DECREF(param);
                     return NULL;
@@ -264,21 +264,21 @@ static PyObject *simplex(PyObject *self, PyObject *args,
                     PyErr_Warn(PyExc_UserWarning, "ignoring value of "
                         "GLPK parameter 'LPX_K_PRESOL'");
                 }
-                else lpx_set_int_parm(lp, param_id, 
+                else lpx_set_int_parm(lp, param_id,
                     PyInt_AS_LONG(value));
-	    } 
-	    else { 
+	    }
+	    else {
 	        if (!PyInt_Check(value) && !PyFloat_Check(value)){
                     sprintf(err_str, "invalid value for floating point "
                         "GLPK parameter: %-.20s", keystr);
-                    PyErr_SetString(PyExc_ValueError, err_str); 
+                    PyErr_SetString(PyExc_ValueError, err_str);
 	            lpx_delete_prob(lp);
 	            Py_DECREF(param);
                     return NULL;
 	        }
-	        lpx_set_real_parm(lp, param_id, 
+	        lpx_set_real_parm(lp, param_id,
                     PyFloat_AsDouble(value));
-	    } 
+	    }
     }
     lpx_set_int_parm(lp, LPX_K_PRESOL, 1);
     Py_DECREF(param);
@@ -299,19 +299,19 @@ static PyObject *simplex(PyObject *self, PyObject *args,
                 return PyErr_NoMemory();
             }
 
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("optimal"));
 
-            for (i=0; i<n; i++) 
+            for (i=0; i<n; i++)
                 MAT_BUFD(x)[i] = lpx_get_col_prim(lp, i+1);
             PyTuple_SET_ITEM(t, 1, (PyObject *) x);
 
-            for (i=0; i<m; i++) 
+            for (i=0; i<m; i++)
                 MAT_BUFD(z)[i] = -lpx_get_row_dual(lp, i+1);
             PyTuple_SET_ITEM(t, 2, (PyObject *) z);
 
             if (A){
-                for (i=0; i<p; i++) 
+                for (i=0; i<p; i++)
                     MAT_BUFD(y)[i] = -lpx_get_row_dual(lp, m+i+1);
                 PyTuple_SET_ITEM(t, 3, (PyObject *) y);
             }
@@ -319,21 +319,21 @@ static PyObject *simplex(PyObject *self, PyObject *args,
             lpx_delete_prob(lp);
             return (PyObject *) t;
 
-        case LPX_E_NOPFS: 
+        case LPX_E_NOPFS:
 
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("primal infeasible"));
             break;
-    
+
         case LPX_E_NODFS:
 
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("dual infeasible"));
             break;
 
         default:
 
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("unknown"));
     }
 
@@ -348,7 +348,7 @@ static PyObject *simplex(PyObject *self, PyObject *args,
 
 
 
-static char doc_integer[] = 
+static char doc_integer[] =
     "Solves a mixed integer linear program using GLPK.\n\n"
     "(status, x) = ilp(c, G, h, A, b, I, B)\n\n"
     "PURPOSE\n"
@@ -359,7 +359,7 @@ static char doc_integer[] =
     "                x[I] are all integer\n"
     "                x[B] are all binary\n\n"
     "ARGUMENTS\n"
-    "c            nx1 dense 'd' matrix with n>=1\n\n" 
+    "c            nx1 dense 'd' matrix with n>=1\n\n"
     "G            mxn dense or sparse 'd' matrix with m>=1\n\n"
     "h            mx1 dense 'd' matrix\n\n"
     "A            pxn dense or sparse 'd' matrix with p>=0\n\n"
@@ -372,7 +372,7 @@ static char doc_integer[] =
     "x            an optimal solution if status is 'optimal';\n"
     "             None otherwise";
 
-static PyObject *integer(PyObject *self, PyObject *args, 
+static PyObject *integer(PyObject *self, PyObject *args,
     PyObject *kwrds)
 {
     matrix *c, *h, *b=NULL, *x=NULL;
@@ -380,7 +380,7 @@ static PyObject *integer(PyObject *self, PyObject *args,
     PyObject *t=NULL, *param, *key, *value;
     LPX *lp;
     int m, n, p, i, j, k, nnz, nnzmax, *rn=NULL, *cn=NULL, param_id;
-    int_t pos=0;    
+    int_t pos=0;
     double *a=NULL, val;
     char param_type, err_str[100], *keystr;
     char *kwlist[] = {"c", "G", "h", "A", "b", "I", "B", NULL};
@@ -388,15 +388,15 @@ static PyObject *integer(PyObject *self, PyObject *args,
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|OOOO", kwlist, &c,
 	    &G, &h, &A, &b, &IntSet, &BinSet)) return NULL;
 
-    if ((Matrix_Check(G) && MAT_ID(G) != DOUBLE) || 
+    if ((Matrix_Check(G) && MAT_ID(G) != DOUBLE) ||
         (SpMatrix_Check(G) && SP_ID(G) != DOUBLE) ||
         (!Matrix_Check(G) && !SpMatrix_Check(G))){
         PyErr_SetString(PyExc_TypeError, "G must be a 'd' matrix");
         return NULL;
     }
-    if ((m = Matrix_Check(G) ? MAT_NROWS(G) : SP_NROWS(G)) <= 0) 
+    if ((m = Matrix_Check(G) ? MAT_NROWS(G) : SP_NROWS(G)) <= 0)
         err_p_int("m");
-    if ((n = Matrix_Check(G) ? MAT_NCOLS(G) : SP_NCOLS(G)) <= 0) 
+    if ((n = Matrix_Check(G) ? MAT_NCOLS(G) : SP_NCOLS(G)) <= 0)
         err_p_int("n");
 
     if (!Matrix_Check(h) || h->id != DOUBLE) err_dbl_mtrx("h");
@@ -406,7 +406,7 @@ static PyObject *integer(PyObject *self, PyObject *args,
     }
 
     if (A){
-        if ((Matrix_Check(A) && MAT_ID(A) != DOUBLE) || 
+        if ((Matrix_Check(A) && MAT_ID(A) != DOUBLE) ||
             (SpMatrix_Check(A) && SP_ID(A) != DOUBLE) ||
             (!Matrix_Check(A) && !SpMatrix_Check(A))){
                 PyErr_SetString(PyExc_ValueError, "A must be a dense "
@@ -429,10 +429,10 @@ static PyObject *integer(PyObject *self, PyObject *args,
         return NULL;
     }
 
-    if ((IntSet) && (!PyAnySet_Check(IntSet))) 
+    if ((IntSet) && (!PyAnySet_Check(IntSet)))
       PY_ERR_TYPE("invalid integer index set");
 
-    if ((BinSet) && (!PyAnySet_Check(BinSet))) 
+    if ((BinSet) && (!PyAnySet_Check(BinSet)))
       PY_ERR_TYPE("invalid binary index set");
 
     lp = lpx_create_prob();
@@ -444,12 +444,12 @@ static PyObject *integer(PyObject *self, PyObject *args,
         lpx_set_col_bnds(lp, i+1, LPX_FR, 0.0, 0.0);
     }
     for (i=0; i<m; i++)
-        lpx_set_row_bnds(lp, i+1, LPX_UP, 0.0, MAT_BUFD(h)[i]);     
+        lpx_set_row_bnds(lp, i+1, LPX_UP, 0.0, MAT_BUFD(h)[i]);
     for (i=0; i<p; i++)
-        lpx_set_row_bnds(lp, i+m+1, LPX_FX, MAT_BUFD(b)[i], 
-            MAT_BUFD(b)[i]);     
+        lpx_set_row_bnds(lp, i+m+1, LPX_FX, MAT_BUFD(b)[i],
+            MAT_BUFD(b)[i]);
 
-    nnzmax = (SpMatrix_Check(G) ? SP_NNZ(G) : m*n ) + 
+    nnzmax = (SpMatrix_Check(G) ? SP_NNZ(G) : m*n ) +
         ((A && SpMatrix_Check(A)) ? SP_NNZ(A) : p*n);
     a = (double *) calloc(nnzmax+1, sizeof(double));
     rn = (int *) calloc(nnzmax+1, sizeof(int));
@@ -501,23 +501,23 @@ static PyObject *integer(PyObject *self, PyObject *args,
         lpx_delete_prob(lp);
         return PyErr_NoMemory();
     }
-    
+
     if (!(param = PyObject_GetAttrString(glpk_module, "options"))
         || !PyDict_Check(param)){
             lpx_delete_prob(lp);
-            PyErr_SetString(PyExc_AttributeError, 
+            PyErr_SetString(PyExc_AttributeError,
                 "missing glpk.options dictionary");
-            return NULL; 
+            return NULL;
     }
-    
+
     while (PyDict_Next(param, &pos, &key, &value))
-        if ((keystr = PyString_AsString(key)) && get_param_idx(keystr, 
+        if ((keystr = PyString_AsString(key)) && get_param_idx(keystr,
             &param_id, &param_type)){
 	    if (param_type == 'i'){
 	        if (!PyInt_Check(value)){
                     sprintf(err_str, "invalid value for integer "
                         "GLPK parameter: %-.20s", keystr);
-                    PyErr_SetString(PyExc_ValueError, err_str); 
+                    PyErr_SetString(PyExc_ValueError, err_str);
 	            lpx_delete_prob(lp);
 	            Py_DECREF(param);
                     return NULL;
@@ -527,30 +527,30 @@ static PyObject *integer(PyObject *self, PyObject *args,
                     PyErr_Warn(PyExc_UserWarning, "ignoring value of "
                         "GLPK parameter 'LPX_K_PRESOL'");
                 }
-                else lpx_set_int_parm(lp, param_id, 
+                else lpx_set_int_parm(lp, param_id,
                     PyInt_AS_LONG(value));
-	    } 
-	    else { 
+	    }
+	    else {
 	        if (!PyInt_Check(value) && !PyFloat_Check(value)){
                     sprintf(err_str, "invalid value for floating point "
                         "GLPK parameter: %-.20s", keystr);
-                    PyErr_SetString(PyExc_ValueError, err_str); 
+                    PyErr_SetString(PyExc_ValueError, err_str);
 	            lpx_delete_prob(lp);
 	            Py_DECREF(param);
                     return NULL;
 	        }
-	        lpx_set_real_parm(lp, param_id, 
+	        lpx_set_real_parm(lp, param_id,
                     PyFloat_AsDouble(value));
-	    } 
+	    }
     }
     lpx_set_int_parm(lp, LPX_K_PRESOL, 1);
     Py_DECREF(param);
 
     if (IntSet) {
       PyObject *iter = PySequence_Fast(IntSet, "Critical error: not sequence");
-    
+
       for (i=0; i<PySet_GET_SIZE(IntSet); i++) {
-	
+
 	PyObject *tmp = PySequence_Fast_GET_ITEM(iter, i);
 	if (!PyInt_Check(tmp)) {
 	  lpx_delete_prob(lp);
@@ -565,15 +565,15 @@ static PyObject *integer(PyObject *self, PyObject *args,
 	}
 	glp_set_col_kind(lp, k+1, GLP_IV);
       }
-      
+
       Py_DECREF(iter);
     }
 
     if (BinSet) {
       PyObject *iter = PySequence_Fast(BinSet, "Critical error: not sequence");
-    
+
       for (i=0; i<PySet_GET_SIZE(BinSet); i++) {
-	
+
 	PyObject *tmp = PySequence_Fast_GET_ITEM(iter, i);
 	if (!PyInt_Check(tmp)) {
 	  lpx_delete_prob(lp);
@@ -592,60 +592,60 @@ static PyObject *integer(PyObject *self, PyObject *args,
       Py_DECREF(iter);
 
     }
-    
+
 
 
     switch (lpx_intopt(lp)){
 
         case LPX_E_OK:
-	  
+
             x = (matrix *) Matrix_New(n,1,DOUBLE);
             if (!x) {
                 Py_XDECREF(t);
                 lpx_delete_prob(lp);
                 return PyErr_NoMemory();
             }
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("optimal"));
-	    
-            for (i=0; i<n; i++) 
+
+            for (i=0; i<n; i++)
                 MAT_BUFD(x)[i] = lpx_mip_col_val(lp, i+1);
             PyTuple_SET_ITEM(t, 1, (PyObject *) x);
-	    
+
             lpx_delete_prob(lp);
             return (PyObject *) t;
-	    
+
         case LPX_E_FAULT:
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("invalid MIP formulation"));
 
 	case LPX_E_NOPFS:
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("primal infeasible"));
 
 	case LPX_E_NODFS:
 
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("dual infeasible"));
 
         case LPX_E_ITLIM:
 
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("maxiters exceeded"));
-	
+
         case LPX_E_TMLIM:
 
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("time limit exceeded"));
 
 	case LPX_E_SING:
 
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("singular or ill-conditioned basis"));
-	  
+
         default:
 
-            PyTuple_SET_ITEM(t, 0, (PyObject *) 
+            PyTuple_SET_ITEM(t, 0, (PyObject *)
                 PyString_FromString("unknown"));
     }
 
@@ -657,9 +657,9 @@ static PyObject *integer(PyObject *self, PyObject *args,
 
 
 static PyMethodDef glpk_functions[] = {
-    {"lp", (PyCFunction) simplex, METH_VARARGS|METH_KEYWORDS, 
+    {"lp", (PyCFunction) simplex, METH_VARARGS|METH_KEYWORDS,
         doc_simplex},
-    {"ilp", (PyCFunction) integer, METH_VARARGS|METH_KEYWORDS, 
+    {"ilp", (PyCFunction) integer, METH_VARARGS|METH_KEYWORDS,
         doc_integer},
     {NULL}  /* Sentinel */
 };
@@ -667,7 +667,7 @@ static PyMethodDef glpk_functions[] = {
 
 PyMODINIT_FUNC initglpk(void)
 {
-    glpk_module = Py_InitModule3("cvxopt.glpk", glpk_functions, 
+    glpk_module = Py_InitModule3("cvxopt.glpk", glpk_functions,
         glpk__doc__);
 
     PyModule_AddObject(glpk_module, "options", PyDict_New());
diff --git a/src/C/gsl.c b/src/C/gsl.c
index d15a0e2..68e1ebc 100644
--- a/src/C/gsl.c
+++ b/src/C/gsl.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,13 +32,13 @@ PyDoc_STRVAR(gsl__doc__,"Random Module.");
 
 static unsigned long seed = 0;
 static const gsl_rng_type *rng_type;
-static gsl_rng *rng; 
+static gsl_rng *rng;
 
 static char doc_getseed[] =
   "Returns the seed value for the random number generator.\n\n"
   "getseed()";
 
-static PyObject * getseed(PyObject *self) 
+static PyObject * getseed(PyObject *self)
 {
   return Py_BuildValue("l",seed);
 }
@@ -50,18 +50,18 @@ static char doc_setseed[] =
   "value     integer seed. If the value is 0, then the system clock\n"
   "          measured in seconds is used instead";
 
-static PyObject * setseed(PyObject *self, PyObject *args) 
+static PyObject * setseed(PyObject *self, PyObject *args)
 {
   unsigned long seed_ = 0;
   time_t seconds;
-  
+
   if (!PyArg_ParseTuple(args, "|l", &seed_))
     return NULL;
 
   if (!seed_) {
     time(&seconds);
     seed = (unsigned long)seconds;
-  } 
+  }
   else seed = seed_;
 
   return Py_BuildValue("");
@@ -81,14 +81,14 @@ static char doc_normal[] =
   "mean      approximate mean of the distribution\n\n"
   "std       standard deviation of the distribution";
 static PyObject *
-normal(PyObject *self, PyObject *args, PyObject *kwrds) 
+normal(PyObject *self, PyObject *args, PyObject *kwrds)
 {
   matrix *obj;
   int i, nrows, ncols = 1;
   double m = 0, s = 1;
   char *kwlist[] = {"nrows", "ncols", "mean", "std",  NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "i|idd", kwlist, 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "i|idd", kwlist,
 	  &nrows, &ncols, &m, &s)) return NULL;
 
   if (s < 0.0) PY_ERR(PyExc_ValueError, "std must be non-negative");
@@ -105,8 +105,8 @@ normal(PyObject *self, PyObject *args, PyObject *kwrds)
   rng_type = gsl_rng_default;
   rng = gsl_rng_alloc (rng_type);
   gsl_rng_set(rng, seed);
-     
-  for (i = 0; i < nrows*ncols; i++) 
+
+  for (i = 0; i < nrows*ncols; i++)
     MAT_BUFD(obj)[i] = gsl_ran_gaussian (rng, s) + m;
 
   seed = gsl_rng_get (rng);
@@ -129,7 +129,7 @@ static char doc_uniform[] =
   "b         upper bound";
 
 static PyObject *
-uniform(PyObject *self, PyObject *args, PyObject *kwrds) 
+uniform(PyObject *self, PyObject *args, PyObject *kwrds)
 {
   matrix *obj;
   int i, nrows, ncols = 1;
@@ -137,14 +137,14 @@ uniform(PyObject *self, PyObject *args, PyObject *kwrds)
 
   char *kwlist[] = {"nrows", "ncols", "a", "b", NULL};
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "i|idd", kwlist, 
+  if (!PyArg_ParseTupleAndKeywords(args, kwrds, "i|idd", kwlist,
 	  &nrows, &ncols, &a, &b)) return NULL;
-  
+
   if (a>b) PY_ERR(PyExc_ValueError, "a must be less than b");
 
-  if ((nrows<0) || (ncols<0)) 
+  if ((nrows<0) || (ncols<0))
     PY_ERR_TYPE("dimensions must be non-negative");
-  
+
   if (!(obj = (matrix *)Matrix_New(nrows, ncols, DOUBLE)))
     return PyErr_NoMemory();
 
@@ -152,21 +152,21 @@ uniform(PyObject *self, PyObject *args, PyObject *kwrds)
   rng_type = gsl_rng_default;
   rng = gsl_rng_alloc (rng_type);
   gsl_rng_set(rng, seed);
- 
+
   for (i= 0; i < nrows*ncols; i++)
     MAT_BUFD(obj)[i] = gsl_ran_flat (rng, a, b);
 
   seed = gsl_rng_get (rng);
   gsl_rng_free(rng);
-  
+
   return (PyObject *)obj;
 }
 
 static PyMethodDef gsl_functions[] = {
-  {"getseed", (PyCFunction)getseed, METH_VARARGS|METH_KEYWORDS, doc_getseed},  
-  {"setseed", (PyCFunction)setseed, METH_VARARGS|METH_KEYWORDS, doc_setseed},  
-  {"normal", (PyCFunction)normal, METH_VARARGS|METH_KEYWORDS, doc_normal},  
-  {"uniform", (PyCFunction)uniform, METH_VARARGS|METH_KEYWORDS, doc_uniform},  
+  {"getseed", (PyCFunction)getseed, METH_VARARGS|METH_KEYWORDS, doc_getseed},
+  {"setseed", (PyCFunction)setseed, METH_VARARGS|METH_KEYWORDS, doc_setseed},
+  {"normal", (PyCFunction)normal, METH_VARARGS|METH_KEYWORDS, doc_normal},
+  {"uniform", (PyCFunction)uniform, METH_VARARGS|METH_KEYWORDS, doc_uniform},
   {NULL}  /* Sentinel */
 };
 
@@ -176,7 +176,7 @@ initgsl(void)
   PyObject *m;
 
   m = Py_InitModule3("cvxopt.gsl", gsl_functions, gsl__doc__);
-  
+
   if (import_cvxopt() < 0)
     return;
 }
diff --git a/src/C/lapack.c b/src/C/lapack.c
index bac7f24..2333537 100644
--- a/src/C/lapack.c
+++ b/src/C/lapack.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,69 +26,73 @@
     return NULL;}
 
 PyDoc_STRVAR(lapack__doc__, "Interface to the LAPACK library.\n\n"
-    "Double-precision real and complex LAPACK routines for solving\n"
-    "sets of linear equations, linear least-squares and least-norm\n"
-    "problems, symmetric and Hermitian eigenvalue problems, singular \n"
-    "value decomposition, and Schur factorization.\n\n"
-    "For more details, see the LAPACK Users' Guide at \n"
-    "www.netlib.org/lapack/lug/lapack_lug.html.\n\n"
-    "Double and complex matrices and vectors are stored in CVXOPT \n"
-    "matrices using the conventional BLAS storage schemes, with the\n"
-    "CVXOPT matrix buffers interpreted as one-dimensional arrays.\n"
-    "For each matrix argument X, an additional integer argument offsetX\n"
-    "specifies the start of the array, i.e., the pointer \n"
-    "X->buffer + offsetX is passed to the LAPACK function.  The other\n"
-    "arguments (dimensions and options) have the same meaning as in\n"
-    "the LAPACK definition.  Default values of the dimension arguments\n"
-    "are derived from the CVXOPT matrix sizes.\n"
-    "If a routine from the LAPACK library returns with a positive \n"
-    "'info' value, an ArithmeticError is raised.  If it returns with \n"
-    "a negative 'info' value, a ValueError is raised.  In both cases\n"
-    "the value of 'info' is returned as an argument to the exception.");
+"Double-precision real and complex LAPACK routines for solving sets of\n"
+"linear equations, linear least-squares and least-norm problems,\n"
+"symmetric and Hermitian eigenvalue problems, singular value \n"
+"decomposition, and Schur factorization.\n\n"
+"For more details, see the LAPACK Users' Guide at \n"
+"www.netlib.org/lapack/lug/lapack_lug.html.\n\n"
+"Double and complex matrices and vectors are stored in CVXOPT matrices\n"
+"using the conventional BLAS storage schemes, with the CVXOPT matrix\n"
+"buffers interpreted as one-dimensional arrays.  For each matrix \n"
+"argument X, an additional integer argument offsetX specifies the start\n"
+"of the array, i.e., the pointer X->buffer + offsetX is passed to the\n"
+"LAPACK function.  The other arguments (dimensions and options) have the\n"
+"same meaning as in the LAPACK definition.  Default values of the\n"
+"dimension arguments are derived from the CVXOPT matrix sizes.\n\n"
+"If a routine from the LAPACK library returns with a positive 'info'\n"
+"value, an ArithmeticError is raised.  If it returns with a negative\n"
+"'info' value, a ValueError is raised.  In both cases the value of \n"
+"'info' is returned as an argument to the exception.");
 
 
 /* LAPACK prototypes */
-extern int ilaenv_(int  *ispec, char **name, char **opts, int *n1, 
+extern int ilaenv_(int  *ispec, char **name, char **opts, int *n1,
     int *n2, int *n3, int *n4);
 
-extern void dgetrf_(int *m, int *n, double *A, int *lda, int *ipiv, 
+extern void dlacpy_(char *uplo, int *m, int *n, double *A, int *lda,
+    double *B, int *ldb);
+extern void zlacpy_(char *uplo, int *m, int *n, complex *A, int *lda,
+    complex *B, int *ldb);
+
+extern void dgetrf_(int *m, int *n, double *A, int *lda, int *ipiv,
     int *info);
-extern void zgetrf_(int *m, int *n, complex *A, int *lda, int *ipiv, 
+extern void zgetrf_(int *m, int *n, complex *A, int *lda, int *ipiv,
     int *info);
 extern void dgetrs_(char *trans, int *n, int *nrhs, double *A, int *lda,
     int *ipiv, double *B, int *ldb, int *info);
-extern void zgetrs_(char *trans, int *n, int *nrhs, complex *A, int *lda, 
+extern void zgetrs_(char *trans, int *n, int *nrhs, complex *A, int *lda,
     int *ipiv, complex *B, int *ldb, int *info);
-extern void dgetri_(int *n, double *A, int *lda, int *ipiv, double *work, 
+extern void dgetri_(int *n, double *A, int *lda, int *ipiv, double *work,
     int *lwork, int *info);
 extern void zgetri_(int *n, complex *A, int *lda, int *ipiv, complex *work,
     int *lwork, int *info);
-extern void dgesv_(int *n, int *nrhs, double *A, int *lda, int *ipiv, 
+extern void dgesv_(int *n, int *nrhs, double *A, int *lda, int *ipiv,
     double *B, int *ldb, int *info);
-extern void zgesv_(int *n, int *nrhs, complex *A, int *lda, int *ipiv, 
+extern void zgesv_(int *n, int *nrhs, complex *A, int *lda, int *ipiv,
     complex *B, int *ldb, int *info);
 
-extern void dgbtrf_(int *m, int *n, int *kl, int *ku, double *AB, 
+extern void dgbtrf_(int *m, int *n, int *kl, int *ku, double *AB,
     int *ldab, int *ipiv, int *info);
-extern void zgbtrf_(int *m, int *n, int *kl, int *ku, complex *AB, 
+extern void zgbtrf_(int *m, int *n, int *kl, int *ku, complex *AB,
     int *ldab, int *ipiv, int *info);
 extern void dgbtrs_(char *trans, int *n, int *kl, int *ku, int *nrhs,
     double *AB, int *ldab, int *ipiv, double *B, int *ldB, int *info);
 extern void zgbtrs_(char *trans, int *n, int *kl, int *ku, int *nrhs,
     complex *AB, int *ldab, int *ipiv, complex *B, int *ldB, int *info);
-extern void dgbsv_(int *n, int *kl, int *ku, int *nrhs, double *ab, 
+extern void dgbsv_(int *n, int *kl, int *ku, int *nrhs, double *ab,
     int *ldab, int *ipiv, double *b, int *ldb, int *info);
-extern void zgbsv_(int *n, int *kl, int *ku, int *nrhs, complex *ab, 
+extern void zgbsv_(int *n, int *kl, int *ku, int *nrhs, complex *ab,
     int *ldab, int *ipiv, complex *b, int *ldb, int *info);
 
-extern void dgttrf_(int *n, double *dl, double *d, double *du, 
+extern void dgttrf_(int *n, double *dl, double *d, double *du,
     double *du2, int *ipiv, int *info);
-extern void zgttrf_(int *n, complex *dl, complex *d, complex *du, 
+extern void zgttrf_(int *n, complex *dl, complex *d, complex *du,
     complex *du2, int *ipiv, int *info);
 extern void dgttrs_(char *trans, int *n, int *nrhs, double *dl, double *d,
     double *du, double *du2, int *ipiv, double *B, int *ldB, int *info);
-extern void zgttrs_(char *trans, int *n, int *nrhs, complex *dl, 
-    complex *d, complex *du, complex *du2, int *ipiv, complex *B, 
+extern void zgttrs_(char *trans, int *n, int *nrhs, complex *dl,
+    complex *d, complex *du, complex *du2, int *ipiv, complex *B,
     int *ldB, int *info);
 extern void dgtsv_(int *n, int *nrhs, double *dl, double *d, double *du,
     double *B, int *ldB, int *info);
@@ -97,15 +101,15 @@ extern void zgtsv_(int *n, int *nrhs, complex *dl, complex *d, complex *du,
 
 extern void dpotrf_(char *uplo, int *n, double *A, int *lda, int *info);
 extern void zpotrf_(char *uplo, int *n, complex *A, int *lda, int *info);
-extern void dpotrs_(char *uplo, int *n, int *nrhs, double *A, int *lda, 
+extern void dpotrs_(char *uplo, int *n, int *nrhs, double *A, int *lda,
     double *B, int *ldb, int *info);
-extern void zpotrs_(char *uplo, int *n, int *nrhs, complex *A, int *lda, 
+extern void zpotrs_(char *uplo, int *n, int *nrhs, complex *A, int *lda,
     complex *B, int *ldb, int *info);
 extern void dpotri_(char *uplo, int *n, double *A, int *lda, int *info);
 extern void zpotri_(char *uplo, int *n, complex *A, int *lda, int *info);
-extern void dposv_(char *uplo, int *n, int *nrhs, double *A, int *lda, 
+extern void dposv_(char *uplo, int *n, int *nrhs, double *A, int *lda,
     double *B, int *ldb, int *info);
-extern void zposv_(char *uplo, int *n, int *nrhs, complex *A, int *lda, 
+extern void zposv_(char *uplo, int *n, int *nrhs, complex *A, int *lda,
     complex *B, int *ldb, int *info);
 
 extern void dpbtrf_(char *uplo, int *n, int *kd, double *AB, int *ldab,
@@ -125,24 +129,24 @@ extern void dpttrf_(int *n, double *d, double *e, int *info);
 extern void zpttrf_(int *n, double *d, complex *e, int *info);
 extern void dpttrs_(int *n, int *nrhs, double *d, double *e, double *B,
     int *ldB, int *info);
-extern void zpttrs_(char *uplo, int *n, int *nrhs, double *d, complex *e, 
+extern void zpttrs_(char *uplo, int *n, int *nrhs, double *d, complex *e,
     complex *B, int *ldB, int *info);
 extern void dptsv_(int *n, int *nrhs, double *d, double *e, double *B,
     int *ldB, int *info);
 extern void zptsv_(int *n, int *nrhs, double *d, complex *e, complex *B,
     int *ldB, int *info);
 
-extern void dsytrf_(char *uplo, int *n, double *A, int *lda, int *ipiv, 
+extern void dsytrf_(char *uplo, int *n, double *A, int *lda, int *ipiv,
     double *work, int *lwork, int *info);
-extern void zsytrf_(char *uplo, int *n, complex *A, int *lda, int *ipiv, 
+extern void zsytrf_(char *uplo, int *n, complex *A, int *lda, int *ipiv,
     complex *work, int *lwork, int *info);
 extern void zhetrf_(char *uplo, int *n, complex *A, int *lda, int *ipiv,
     complex *work, int *lwork, int *info);
-extern void dsytrs_(char *uplo, int *n, int *nrhs, double *A, int *lda, 
+extern void dsytrs_(char *uplo, int *n, int *nrhs, double *A, int *lda,
     int *ipiv, double *B, int *ldb, int *info);
-extern void zsytrs_(char *uplo, int *n, int *nrhs, complex *A, int *lda, 
+extern void zsytrs_(char *uplo, int *n, int *nrhs, complex *A, int *lda,
     int *ipiv, complex *B, int *ldb, int *info);
-extern void zhetrs_(char *uplo, int *n, int *nrhs, complex *A, int *lda, 
+extern void zhetrs_(char *uplo, int *n, int *nrhs, complex *A, int *lda,
     int *ipiv, complex *B, int *ldb, int *info);
 extern void dsytri_(char *uplo, int *n, double *A, int *lda, int *ipiv,
     double *work, int *info);
@@ -150,82 +154,106 @@ extern void zsytri_(char *uplo, int *n, complex *A, int *lda, int *ipiv,
     complex *work, int *info);
 extern void zhetri_(char *uplo, int *n, complex *A, int *lda, int *ipiv,
     complex *work, int *info);
-extern void dsysv_(char *uplo, int *n, int *nrhs, double *A, int *lda, 
+extern void dsysv_(char *uplo, int *n, int *nrhs, double *A, int *lda,
     int *ipiv, double *B, int *ldb, double *work, int *lwork,
     int *info);
-extern void zsysv_(char *uplo, int *n, int *nrhs, complex *A, int *lda, 
+extern void zsysv_(char *uplo, int *n, int *nrhs, complex *A, int *lda,
     int *ipiv, complex *B, int *ldb, complex *work, int *lwork, int *info);
-extern void zhesv_(char *uplo, int *n, int *nrhs, complex *A, int *lda, 
+extern void zhesv_(char *uplo, int *n, int *nrhs, complex *A, int *lda,
     int *ipiv, complex *B, int *ldb, complex *work, int *lwork, int *info);
 
 extern void dtrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs,
     double  *a, int *lda, double *b, int *ldb, int *info);
 extern void ztrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs,
     complex  *a, int *lda, complex *b, int *ldb, int *info);
-extern void dtrtri_(char *uplo, char *diag, int *n, double  *a, int *lda, 
+extern void dtrtri_(char *uplo, char *diag, int *n, double  *a, int *lda,
     int *info);
-extern void ztrtri_(char *uplo, char *diag, int *n, complex  *a, int *lda, 
+extern void ztrtri_(char *uplo, char *diag, int *n, complex  *a, int *lda,
     int *info);
 extern void dtbtrs_(char *uplo, char *trans, char *diag, int *n, int *kd,
     int *nrhs, double *ab, int *ldab, double *b, int *ldb, int *info);
 extern void ztbtrs_(char *uplo, char *trans, char *diag, int *n, int *kd,
     int *nrhs, complex *ab, int *ldab, complex *b, int *ldb, int *info);
 
-extern void dgels_(char *trans, int *m, int *n, int *nrhs, double *a, 
+extern void dgels_(char *trans, int *m, int *n, int *nrhs, double *a,
     int *lda, double *b, int *ldb, double *work, int *lwork, int *info);
-extern void zgels_(char *trans, int *m, int *n, int *nrhs, complex *a, 
+extern void zgels_(char *trans, int *m, int *n, int *nrhs, complex *a,
     int *lda, complex *b, int *ldb, complex *work, int *lwork, int *info);
 extern void dgeqrf_(int *m, int *n, double *a, int *lda, double *tau,
-    double *work, int *lwork, int *info);         
+    double *work, int *lwork, int *info);
 extern void zgeqrf_(int *m, int *n, complex *a, int *lda, complex *tau,
-    complex *work, int *lwork, int *info);         
+    complex *work, int *lwork, int *info);
 extern void dormqr_(char *side, char *trans, int *m, int *n, int *k,
     double *a, int *lda, double *tau, double *c, int *ldc, double *work,
     int *lwork, int *info);
 extern void zunmqr_(char *side, char *trans, int *m, int *n, int *k,
-    complex *a, int *lda, complex *tau, complex *c, int *ldc, 
+    complex *a, int *lda, complex *tau, complex *c, int *ldc,
+    complex *work, int *lwork, int *info);
+extern void dorgqr_(int *m, int *n, int *k, double *A, int *lda,
+    double *tau, double *work, int *lwork, int *info);
+extern void zungqr_(int *m, int *n, int *k, complex *A, int *lda,
+    complex *tau, complex *work, int *lwork, int *info);
+extern void dorglq_(int *m, int *n, int *k, double *A, int *lda,
+    double *tau, double *work, int *lwork, int *info);
+extern void zunglq_(int *m, int *n, int *k, complex *A, int *lda,
+    complex *tau, complex *work, int *lwork, int *info);
+
+extern void dgelqf_(int *m, int *n, double *a, int *lda, double *tau,
+    double *work, int *lwork, int *info);
+extern void zgelqf_(int *m, int *n, complex *a, int *lda, complex *tau,
+    complex *work, int *lwork, int *info);
+extern void dormlq_(char *side, char *trans, int *m, int *n, int *k,
+    double *a, int *lda, double *tau, double *c, int *ldc, double *work,
+    int *lwork, int *info);
+extern void zunmlq_(char *side, char *trans, int *m, int *n, int *k,
+    complex *a, int *lda, complex *tau, complex *c, int *ldc,
     complex *work, int *lwork, int *info);
 
-extern void dsyev_(char *jobz, char *uplo, int *n, double *A, int *lda, 
+extern void dgeqp3_(int *m, int *n, double *a, int *lda, int *jpvt,
+    double *tau, double *work, int *lwork, int *info);
+extern void zgeqp3_(int *m, int *n, complex *a, int *lda, int *jpvt,
+    complex *tau, complex *work, int *lwork, double *rwork, int *info);
+
+extern void dsyev_(char *jobz, char *uplo, int *n, double *A, int *lda,
     double *W, double *work, int *lwork, int *info);
 extern void zheev_(char *jobz, char *uplo, int *n, complex *A, int *lda,
     double *W, complex *work, int *lwork, double *rwork, int *info);
 extern void dsyevx_(char *jobz, char *range, char *uplo, int *n, double *A,
-    int *lda, double *vl, double *vu, int *il, int *iu, double *abstol, 
-    int *m, double *W, double *Z, int *ldz, double *work, int *lwork, 
+    int *lda, double *vl, double *vu, int *il, int *iu, double *abstol,
+    int *m, double *W, double *Z, int *ldz, double *work, int *lwork,
     int *iwork, int *ifail, int *info);
-extern void zheevx_(char *jobz, char *range, char *uplo, int *n, 
-    complex *A, int *lda, double *vl, double *vu, int *il, int *iu, 
+extern void zheevx_(char *jobz, char *range, char *uplo, int *n,
+    complex *A, int *lda, double *vl, double *vu, int *il, int *iu,
     double *abstol, int *m, double *W, complex *Z, int *ldz, complex *work,
     int *lwork, double *rwork, int *iwork, int *ifail, int *info);
-extern void dsyevd_(char *jobz, char *uplo, int *n, double *A, int *ldA, 
-    double *W, double *work, int *lwork, int *iwork, int *liwork, 
-    int *info); 
-extern void zheevd_(char *jobz, char *uplo, int *n, complex *A, int *ldA, 
-    double *W, complex *work, int *lwork, double *rwork, int *lrwork, 
-    int *iwork, int *liwork, int *info); 
+extern void dsyevd_(char *jobz, char *uplo, int *n, double *A, int *ldA,
+    double *W, double *work, int *lwork, int *iwork, int *liwork,
+    int *info);
+extern void zheevd_(char *jobz, char *uplo, int *n, complex *A, int *ldA,
+    double *W, complex *work, int *lwork, double *rwork, int *lrwork,
+    int *iwork, int *liwork, int *info);
 extern void dsyevr_(char *jobz, char *range, char *uplo, int *n, double *A,
-    int *ldA, double *vl, double *vu, int *il, int *iu, double *abstol, 
-    int *m, double *W, double *Z, int *ldZ, int *isuppz, double *work, 
-    int *lwork, int *iwork, int *liwork, int *info); 
-extern void zheevr_(char *jobz, char *range, char *uplo, int *n, 
-    complex *A, int *ldA, double *vl, double *vu, int *il, int *iu, 
-    double *abstol, int *m, double *W, complex *Z, int *ldZ, int *isuppz, 
-    complex *work, int *lwork, double *rwork, int *lrwork, int *iwork, 
-    int *liwork, int *info); 
-
-extern void dsygv_(int *itype, char *jobz, char *uplo, int *n, double *A, 
-    int *lda, double *B, int *ldb, double *W, double *work, int *lwork, 
+    int *ldA, double *vl, double *vu, int *il, int *iu, double *abstol,
+    int *m, double *W, double *Z, int *ldZ, int *isuppz, double *work,
+    int *lwork, int *iwork, int *liwork, int *info);
+extern void zheevr_(char *jobz, char *range, char *uplo, int *n,
+    complex *A, int *ldA, double *vl, double *vu, int *il, int *iu,
+    double *abstol, int *m, double *W, complex *Z, int *ldZ, int *isuppz,
+    complex *work, int *lwork, double *rwork, int *lrwork, int *iwork,
+    int *liwork, int *info);
+
+extern void dsygv_(int *itype, char *jobz, char *uplo, int *n, double *A,
+    int *lda, double *B, int *ldb, double *W, double *work, int *lwork,
     int *info);
-extern void zhegv_(int *itype, char *jobz, char *uplo, int *n, complex *A, 
-    int *lda, complex *B, int *ldb, double *W, complex *work, int *lwork, 
+extern void zhegv_(int *itype, char *jobz, char *uplo, int *n, complex *A,
+    int *lda, complex *B, int *ldb, double *W, complex *work, int *lwork,
     double *rwork, int *info);
 
 extern void dgesvd_(char *jobu, char *jobvt, int *m, int *n, double *A,
     int *ldA, double *S, double *U, int *ldU, double *Vt, int *ldVt,
     double *work, int *lwork, int *info);
 extern void dgesdd_(char *jobz, int *m, int *n, double *A, int *ldA,
-    double *S, double *U, int *ldU, double *Vt, int *ldVt, double *work, 
+    double *S, double *U, int *ldU, double *Vt, int *ldVt, double *work,
     int *lwork, int *iwork, int *info);
 extern void zgesvd_(char *jobu, char *jobvt, int *m, int *n, complex *A,
     int *ldA, double *S, complex *U, int *ldU, complex *Vt, int *ldVt,
@@ -234,25 +262,25 @@ extern void zgesdd_(char *jobz, int *m, int *n, complex *A, int *ldA,
     double *S, complex *U, int *ldU, complex *Vt, int *ldVt, complex *work,
     int *lwork, double *rwork, int *iwork, int *info);
 
-extern void dgees_(char *jobvs, char *sort, void *select, int *n, 
-    double *A, int *ldA, int *sdim, double *wr, double *wi, double *vs, 
+extern void dgees_(char *jobvs, char *sort, void *select, int *n,
+    double *A, int *ldA, int *sdim, double *wr, double *wi, double *vs,
     int *ldvs, double *work, int *lwork, int *bwork, int *info);
-extern void zgees_(char *jobvs, char *sort, void *select, int *n, 
+extern void zgees_(char *jobvs, char *sort, void *select, int *n,
     complex *A, int *ldA, int *sdim, complex *w, complex *vs, int *ldvs,
     complex *work, int *lwork, complex *rwork, int *bwork, int *info);
-extern void dgges_(char *jobvsl, char *jobvsr, char *sort, void *delctg, 
-    int *n, double *A, int *ldA, double *B, int *ldB, int *sdim, 
+extern void dgges_(char *jobvsl, char *jobvsr, char *sort, void *delctg,
+    int *n, double *A, int *ldA, double *B, int *ldB, int *sdim,
     double *alphar, double *alphai, double *beta, double *vsl, int *ldvsl,
-    double *vsr, int *ldvsr, double *work, int *lwork, int *bwork, 
+    double *vsr, int *ldvsr, double *work, int *lwork, int *bwork,
     int *info);
-extern void zgges_(char *jobvsl, char *jobvsr, char *sort, void *delctg, 
-    int *n, complex *A, int *ldA, complex *B, int *ldB, int *sdim, 
+extern void zgges_(char *jobvsl, char *jobvsr, char *sort, void *delctg,
+    int *n, complex *A, int *ldA, complex *B, int *ldB, int *sdim,
     complex *alpha, complex *beta, complex *vsl, int *ldvsl, complex *vsr,
-    int *ldvsr, complex *work, int *lwork, double *rwork, int *bwork, 
+    int *ldvsr, complex *work, int *lwork, double *rwork, int *bwork,
     int *info);
 
 
-static char doc_getrf[] = 
+static char doc_getrf[] =
     "LU factorization of a general real or complex m by n matrix.\n\n"
     "getrf(A, ipiv, m=A.size[0], n=A.size[1], ldA=max(1,A.size[0]),\n"
     "      offsetA=0)\n\n"
@@ -271,15 +299,15 @@ static char doc_getrf[] =
     "          used.\n\n"
     "ldA       positive integer.  ldA >= max(1,m).  If zero, the default\n"
     "          value is used.\n\n"
-    "offsetA   nonnegative integer"; 
+    "offsetA   nonnegative integer";
 
 static PyObject* getrf(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *ipiv; 
-    int m=-1, n=-1, ldA=0, oA=0, info; 
+    matrix *A, *ipiv;
+    int m=-1, n=-1, ldA=0, oA=0, info;
     char *kwlist[] = {"A", "ipiv", "m", "n", "ldA", "offsetA", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiii", kwlist,
         &A, &ipiv, &m, &n, &ldA, &oA)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -293,44 +321,44 @@ static PyObject* getrf(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oA + (n-1)*ldA + m > len(A)) err_buf_len("A");
     if (len(ipiv) < MIN(n,m)) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(MIN(m,n)*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory(); 
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(MIN(m,n)*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(A)) {
-        case DOUBLE: 
-            Py_BEGIN_ALLOW_THREADS	    
+        case DOUBLE:
+            Py_BEGIN_ALLOW_THREADS
             dgetrf_(&m, &n, MAT_BUFD(A)+oA, &ldA, ipiv_ptr, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zgetrf_(&m, &n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
             free(ipiv_ptr);
 #endif
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
+#if (SIZEOF_INT < SIZEOF_LONG)
     int i;  for (i=0; i<MIN(m,n); i++) MAT_BUFI(ipiv)[i] = ipiv_ptr[i];
-    free(ipiv_ptr); 
-#endif 
+    free(ipiv_ptr);
+#endif
 
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_getrs[] = 
+static char doc_getrs[] =
     "Solves a general real or complex set of linear equations,\n"
     "given the LU factorization computed by getrf() or gesv().\n\n"
     "getrs(A, ipiv, B, trans='N', n=A.size[0], nrhs=B.size[1],\n"
@@ -342,7 +370,7 @@ static char doc_getrs[] =
     "If trans is 'C', solves A^H*X = B.\n"
     "On entry, A and ipiv contain the LU factorization of an n by n\n"
     "matrix A as computed by getrf() or gesv().  On exit B is replaced\n"
-    "by the solution X.\n\n"  
+    "by the solution X.\n\n"
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix\n\n"
     "ipiv      'i' matrix\n\n"
@@ -361,14 +389,14 @@ static char doc_getrs[] =
 
 static PyObject* getrs(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B, *ipiv; 
-    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info; 
+    matrix *A, *B, *ipiv;
+    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info;
     char trans='N';
-    char *kwlist[] = {"A", "ipiv", "B", "trans", "n", "nrhs", "ldA", 
+    char *kwlist[] = {"A", "ipiv", "B", "trans", "n", "nrhs", "ldA",
         "ldB", "offsetA", "offsetB", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ciiiiii", kwlist,
-        &A, &ipiv, &B, &trans, &n, &nrhs, &ldA, &ldB, &oA, &oB)) 
+        &A, &ipiv, &B, &trans, &n, &nrhs, &ldA, &ldB, &oA, &oB))
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -396,52 +424,52 @@ static PyObject* getrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
     if (len(ipiv) < n) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(n*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory();	
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(n*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
     int i;  for (i=0; i<n; i++) ipiv_ptr[i] = MAT_BUFI(ipiv)[i];
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(A)){
         case DOUBLE:
             if (trans == 'C') trans = 'T';
-            Py_BEGIN_ALLOW_THREADS	    
-            dgetrs_(&trans, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            dgetrs_(&trans, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, ipiv_ptr,
                 MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            zgetrs_(&trans, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            zgetrs_(&trans, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr,
                 MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
-    
+
 	default:
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
             free(ipiv_ptr);
 #endif
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
-    free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+    free(ipiv_ptr);
+#endif
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_getri[] = 
+static char doc_getri[] =
     "Inverse of a real or complex matrix.\n\n"
     "getri(A, ipiv, n=A.size[0], ldA = max(1,A.size[0]), offsetA=0)\n\n"
     "PURPOSE\n"
     "Computes the inverse of real or complex matrix of order n.  On\n"
     "entry, A and ipiv contain the LU factorization, as returned by\n"
-    "gesv() or getrf().  On exit A is replaced by the inverse.\n\n" 
+    "gesv() or getrf().  On exit A is replaced by the inverse.\n\n"
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix\n\n"
     "ipiv      'i' matrix\n\n"
@@ -453,9 +481,9 @@ static char doc_getri[] =
 
 static PyObject* getri(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *ipiv; 
-    int n=-1, ldA=0, oA=0, info, lwork; 
-    void *work; 
+    matrix *A, *ipiv;
+    int n=-1, ldA=0, oA=0, info, lwork;
+    void *work;
     number wl;
     char *kwlist[] = {"A", "ipiv", "n", "ldA", "offsetA", NULL};
 
@@ -482,16 +510,16 @@ static PyObject* getri(PyObject *self, PyObject *args, PyObject *kwrds)
     int *ipiv_ptr = malloc(n*sizeof(int));
     if (!ipiv_ptr) return PyErr_NoMemory();
     int i;  for (i=0; i<n; i++) ipiv_ptr[i] = MAT_BUFI(ipiv)[i];
-#else 
+#else
     int *ipiv_ptr = MAT_BUFI(ipiv);
 #endif
 
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dgetri_(&n, NULL, &ldA, NULL, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = (void *) calloc(lwork, sizeof(double)))) {
 #if (SIZEOF_INT < SIZEOF_LONG)
@@ -499,18 +527,18 @@ static PyObject* getri(PyObject *self, PyObject *args, PyObject *kwrds)
 #endif
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dgetri_(&n, MAT_BUFD(A)+oA, &ldA, ipiv_ptr, (double *) work,
                 &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
             break;
 
         case COMPLEX:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zgetri_(&n, NULL, &ldA, NULL, &wl.z, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
             if (!(work = (void *) calloc(lwork, sizeof(complex)))){
 #if (SIZEOF_INT < SIZEOF_LONG)
@@ -518,29 +546,29 @@ static PyObject* getri(PyObject *self, PyObject *args, PyObject *kwrds)
 #endif
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            zgetri_(&n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            zgetri_(&n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr,
                 (complex *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
             break;
 
         default:
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
             free(ipiv_ptr);
 #endif
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
-    free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+    free(ipiv_ptr);
+#endif
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_gesv[] = 
+static char doc_gesv[] =
     "Solves a general real or complex set of linear equations.\n\n"
     "dgesv(A, B, ipiv=None, n=A.size[0], nrhs=B.size[1], \n"
     "      ldA=max(1,A.size[0]), ldB=max(1,B.size[0]), offsetA=0, \n"
@@ -564,27 +592,27 @@ static char doc_gesv[] =
     "          value is used.\n\n"
     "ldB       positive integer.  ldB >= max(1,n).  If zero, the default\n"
     "          value is used.\n\n"
-    "offsetA   nonnegative integer\n\n" 
+    "offsetA   nonnegative integer\n\n"
     "offsetA   nonnegative integer";
 
 static PyObject* gesv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B, *ipiv=NULL; 
-    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info, k; 
+    matrix *A, *B, *ipiv=NULL;
+    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info, k;
     void *Ac=NULL;
     int *ipivc=NULL;
-    static char *kwlist[] = {"A", "B", "ipiv", "n", "nrhs", "ldA", 
+    static char *kwlist[] = {"A", "B", "ipiv", "n", "nrhs", "ldA",
         "ldB", "offsetA", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Oiiiiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Oiiiiii", kwlist,
         &A, &B, &ipiv, &n, &nrhs, &ldA, &ldB, &oA, &oB)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(B)) err_mtrx("B");
     if (MAT_ID(A) != MAT_ID(B)) err_conflicting_ids;
-    if (ipiv && (!Matrix_Check(ipiv) || ipiv->id != INT)) 
+    if (ipiv && (!Matrix_Check(ipiv) || ipiv->id != INT))
         err_int_mtrx("ipiv");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -604,83 +632,83 @@ static PyObject* gesv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ipiv && len(ipiv) < n) err_buf_len("ipiv");
 
     if (ipiv) {
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
         if (!(ipivc = (int *) calloc(n, sizeof(int))))
-            return PyErr_NoMemory();	
-#else 
-        ipivc = MAT_BUFI(ipiv);		
-#endif						    
+            return PyErr_NoMemory();
+#else
+        ipivc = MAT_BUFI(ipiv);
+#endif
     }
     else if (!(ipivc = (int *) calloc(n, sizeof(int))))
         return PyErr_NoMemory();
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            if (ipiv) 
-                Py_BEGIN_ALLOW_THREADS	    
+            if (ipiv)
+                Py_BEGIN_ALLOW_THREADS
                 dgesv_(&n, &nrhs, MAT_BUFD(A)+oA, &ldA, ipivc,
                     MAT_BUFD(B)+oB, &ldB, &info);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             else {
                 if (!(Ac = (void *) calloc(n*n, sizeof(double)))){
-                    free(ipivc);  
+                    free(ipivc);
                     return PyErr_NoMemory();
                 }
-                for (k=0; k<n; k++) memcpy((double *) Ac + k*n, 
+                for (k=0; k<n; k++) memcpy((double *) Ac + k*n,
                     MAT_BUFD(A)+oA+k*ldA, n*sizeof(double));
-                Py_BEGIN_ALLOW_THREADS	    
-                dgesv_(&n, &nrhs, (double *) Ac, &n, ipivc, 
+                Py_BEGIN_ALLOW_THREADS
+                dgesv_(&n, &nrhs, (double *) Ac, &n, ipivc,
                     MAT_BUFD(B)+oB, &ldB, &info);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
                 free(Ac);
             }
             break;
 
         case COMPLEX:
-            if (ipiv) 
-                Py_BEGIN_ALLOW_THREADS	    
+            if (ipiv)
+                Py_BEGIN_ALLOW_THREADS
                 zgesv_(&n, &nrhs, MAT_BUFZ(A)+oA, &ldA, ipivc,
                     MAT_BUFZ(B)+oB, &ldB, &info);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             else {
                 if (!(Ac = (void *) calloc(n*n, sizeof(complex)))){
-                    free(ipivc);  
+                    free(ipivc);
                     return PyErr_NoMemory();
                 }
-                for (k=0; k<n; k++) memcpy((complex *) Ac + k*n, 
+                for (k=0; k<n; k++) memcpy((complex *) Ac + k*n,
                     MAT_BUFZ(A)+oA+k*ldA, n*sizeof(complex));
-                Py_BEGIN_ALLOW_THREADS	    
-                zgesv_(&n, &nrhs, (complex *) Ac, &n, ipivc, 
+                Py_BEGIN_ALLOW_THREADS
+                zgesv_(&n, &nrhs, (complex *) Ac, &n, ipivc,
                     MAT_BUFZ(B)+oB, &ldB, &info);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
                 free(Ac);
             }
             break;
 
         default:
             if (ipiv){
-#if (SIZEOF_INT < SIZEOF_LONG) 
-                free(ipivc); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+                free(ipivc);
+#endif
             }
             else free(ipivc);
             err_invalid_id;
     }
 
     if (ipiv){
-#if (SIZEOF_INT < SIZEOF_LONG) 
+#if (SIZEOF_INT < SIZEOF_LONG)
         for (k=0; k<n; k++) MAT_BUFI(ipiv)[k] = ipivc[k];
-        free(ipivc); 
-#endif 
+        free(ipivc);
+#endif
     }
     else free(ipivc);
-    
+
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_gbtrf[] = 
+static char doc_gbtrf[] =
     "LU factorization of a real or complex m by n band matrix.\n\n"
     "gbtrf(A, m, kl, ipiv, n=A.size[1], ku=A.size[0]-2*kl-1,\n"
     "      ldA=max(1,A.size[0]), offsetA=0)\n\n"
@@ -693,7 +721,7 @@ static char doc_gbtrf[] =
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix\n\n"
     "m         nonnegative integer\n\n"
-    "kl        nonnegative integer.\n\n"  
+    "kl        nonnegative integer.\n\n"
     "ipiv      'i' matrix of length at least min(m,n)\n\n"
     "n         nonnegative integer.  If negative, the default value is\n"
     "          used.\n\n"
@@ -701,16 +729,16 @@ static char doc_gbtrf[] =
     "          used.\n\n"
     "ldA       positive integer.  ldA >= 2*kl+ku+1.  If zero, the\n"
     "          default value is used.\n\n"
-    "offsetA   nonnegative integer"; 
+    "offsetA   nonnegative integer";
 
 static PyObject* gbtrf(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *ipiv; 
-    int m, kl, n=-1, ku=-1, ldA=0, oA=0, info; 
-    char *kwlist[] = {"A", "m", "kl", "ipiv", "n", "ku", "ldA", "offsetA", 
+    matrix *A, *ipiv;
+    int m, kl, n=-1, ku=-1, ldA=0, oA=0, info;
+    char *kwlist[] = {"A", "m", "kl", "ipiv", "n", "ku", "ldA", "offsetA",
         NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OiiO|iiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OiiO|iiii", kwlist,
         &A, &m, &kl, &ipiv, &n, &ku, &ldA, &oA)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -727,48 +755,48 @@ static PyObject* gbtrf(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(ipiv) || ipiv ->id != INT) err_int_mtrx("ipiv");
     if (len(ipiv) < MIN(n,m)) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(MIN(m,n)*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory(); 
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(MIN(m,n)*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(A)) {
-        case DOUBLE: 
-            Py_BEGIN_ALLOW_THREADS	    
-            dgbtrf_(&m, &n, &kl, &ku, MAT_BUFD(A)+oA, &ldA, ipiv_ptr, 
+        case DOUBLE:
+            Py_BEGIN_ALLOW_THREADS
+            dgbtrf_(&m, &n, &kl, &ku, MAT_BUFD(A)+oA, &ldA, ipiv_ptr,
                 &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            zgbtrf_(&m, &n, &kl, &ku, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            zgbtrf_(&m, &n, &kl, &ku, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr,
                 &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
             free(ipiv_ptr);
 #endif
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
+#if (SIZEOF_INT < SIZEOF_LONG)
     int i;  for (i=0; i<MIN(m,n); i++) MAT_BUFI(ipiv)[i] = ipiv_ptr[i];
-    free(ipiv_ptr); 
-#endif 
+    free(ipiv_ptr);
+#endif
 
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_gbtrs[] = 
+static char doc_gbtrs[] =
     "Solves a real or complex set of linear equations with a banded\n"
-    "coefficient matrix, given the LU factorization computed by gbtrf()\n" 
+    "coefficient matrix, given the LU factorization computed by gbtrf()\n"
     "or gbsv().\n\n"
     "gbtrs(A, kl, ipiv, B, trans='N', n=A.size[1], ku=A.size[0]-2*kl-1,\n"
     "      nrhs=B.size[1], ldA=max(1,AB.size[0]), ldB=max(1,B.size[0]),\n"
@@ -779,7 +807,7 @@ static char doc_gbtrs[] =
     "If trans is 'C', solves A^H*X = B.\n"
     "On entry, A and ipiv contain the LU factorization of an n by n\n"
     "band matrix A as computed by getrf() or gbsv().  On exit B is\n"
-    "replaced by the solution X.\n\n"  
+    "replaced by the solution X.\n\n"
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix\n\n"
     "kl        nonnegative integer\n\n"
@@ -801,14 +829,14 @@ static char doc_gbtrs[] =
 
 static PyObject* gbtrs(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B, *ipiv; 
-    int kl, n=-1, ku=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info; 
+    matrix *A, *B, *ipiv;
+    int kl, n=-1, ku=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info;
     char trans='N';
     char *kwlist[] = {"A", "kl", "ipiv", "B", "trans", "n", "ku", "nrhs",
         "ldA", "ldB", "offsetA", "offsetB", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OiOO|ciiiiiii", kwlist,
-        &A, &kl, &ipiv, &B, &trans, &n, &ku, &nrhs, &ldA, &ldB, &oA, 
+        &A, &kl, &ipiv, &B, &trans, &n, &ku, &nrhs, &ldA, &ldB, &oA,
         &oB)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -833,46 +861,46 @@ static PyObject* gbtrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
     if (len(ipiv) < n) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(n*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory();	
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(n*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
     int i;  for (i=0; i<n; i++) ipiv_ptr[i] = MAT_BUFI(ipiv)[i];
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(A)){
         case DOUBLE:
             if (trans == 'C') trans = 'T';
-            Py_BEGIN_ALLOW_THREADS	    
-            dgbtrs_(&trans, &n, &kl, &ku, &nrhs, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dgbtrs_(&trans, &n, &kl, &ku, &nrhs, MAT_BUFD(A)+oA, &ldA,
                 ipiv_ptr, MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            zgbtrs_(&trans, &n, &kl, &ku, &nrhs, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            zgbtrs_(&trans, &n, &kl, &ku, &nrhs, MAT_BUFZ(A)+oA, &ldA,
                 ipiv_ptr, MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
-    
+
 	default:
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
             free(ipiv_ptr);
 #endif
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
-    free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+    free(ipiv_ptr);
+#endif
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_gbsv[] = 
+static char doc_gbsv[] =
     "Solves a real or complex set of linear equations with a banded\n"
     "coefficient matrix.\n\n"
     "gbsv(A, kl, B, ipiv=None, ku=None, n=A.size[1], nrhs=B.size[1],\n"
@@ -905,27 +933,27 @@ static char doc_gbsv[] =
     "          default value is used.\n\n"
     "ldB       positive integer.  ldB >= max(1,n).  If zero, the default\n"
     "          default value is used.\n\n"
-    "offsetA   nonnegative integer\n\n" 
+    "offsetA   nonnegative integer\n\n"
     "offsetB   nonnegative integer";
 
 
 static PyObject* gbsv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B, *ipiv=NULL; 
+    matrix *A, *B, *ipiv=NULL;
     void *Ac;
-    int kl, ku=-1, n=-1, nrhs=-1, ldA=0, oA=0, ldB=0, oB=0, info, k; 
+    int kl, ku=-1, n=-1, nrhs=-1, ldA=0, oA=0, ldB=0, oB=0, info, k;
     int *ipivc=NULL;
-    static char *kwlist[] = {"A", "kl", "B", "ipiv", "ku", "n", "nrhs",  
+    static char *kwlist[] = {"A", "kl", "B", "ipiv", "ku", "n", "nrhs",
         "ldA", "ldB", "oA", "oB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OiO|Oiiiiiii", kwlist, 
-        &A, &kl, &B, &ipiv, &ku, &n, &nrhs, &ldA, &ldB, &oA, &oB)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OiO|Oiiiiiii", kwlist,
+        &A, &kl, &B, &ipiv, &ku, &n, &nrhs, &ldA, &ldB, &oA, &oB))
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(B)) err_mtrx("B");
     if (MAT_ID(A) != MAT_ID(B)) err_conflicting_ids;
-    if (ipiv && (!Matrix_Check(ipiv) || ipiv->id != INT)) 
+    if (ipiv && (!Matrix_Check(ipiv) || ipiv->id != INT))
         err_int_mtrx("ipiv");
     if (n < 0) n = A->ncols;
     if (nrhs < 0) nrhs = B->ncols;
@@ -937,99 +965,99 @@ static PyObject* gbsv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldA < ( ipiv ? 2*kl+ku+1 : kl+ku+1)) err_ld("ldA");
     if (ldB == 0) ldB = MAX(1,B->nrows);
     if (ldB < MAX(1,n)) err_ld("ldB");
-    if (oA < 0) err_nn_int("offsetA");  
-    if (oA + (n-1)*ldA + (ipiv ? 2*kl+ku+1 : kl+ku+1) > len(A)) 
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + (n-1)*ldA + (ipiv ? 2*kl+ku+1 : kl+ku+1) > len(A))
         err_buf_len("A");
     if (oB < 0) err_nn_int("offsetB");
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
     if (ipiv && len(ipiv) < n) err_buf_len("ipiv");
 
     if (ipiv) {
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
         if (!(ipivc = (int *) calloc(n, sizeof(int))))
-            return PyErr_NoMemory();	
-#else 
-        ipivc = MAT_BUFI(ipiv);		
-#endif						    
+            return PyErr_NoMemory();
+#else
+        ipivc = MAT_BUFI(ipiv);
+#endif
     }
     else if (!(ipivc = (int *) calloc(n, sizeof(int))))
         return PyErr_NoMemory();
 
     switch (MAT_ID(A)) {
         case DOUBLE:
-            if (ipiv) 
-                Py_BEGIN_ALLOW_THREADS	    
+            if (ipiv)
+                Py_BEGIN_ALLOW_THREADS
                 dgbsv_(&n, &kl, &ku, &nrhs, MAT_BUFD(A)+oA, &ldA, ipivc,
                     MAT_BUFD(B)+oB, &ldB, &info);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             else {
-                if (!(Ac = (void *) calloc((2*kl+ku+1)*n, 
+                if (!(Ac = (void *) calloc((2*kl+ku+1)*n,
                     sizeof(double)))){
-                    free(ipivc); 
+                    free(ipivc);
                     return PyErr_NoMemory();
                 }
-                for (k=0; k<n; k++) 
-                    memcpy((double *) Ac + kl + k*(2*kl+ku+1),  
-                        MAT_BUFD(A) + oA + k*ldA, 
-                        (kl+ku+1)*sizeof(double)); 
+                for (k=0; k<n; k++)
+                    memcpy((double *) Ac + kl + k*(2*kl+ku+1),
+                        MAT_BUFD(A) + oA + k*ldA,
+                        (kl+ku+1)*sizeof(double));
                 ldA = 2*kl+ku+1;
-                Py_BEGIN_ALLOW_THREADS	    
+                Py_BEGIN_ALLOW_THREADS
                 dgbsv_(&n, &kl, &ku, &nrhs, (double *) Ac, &ldA, ipivc,
                     MAT_BUFD(B)+oB, &ldB, &info);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
                 free(Ac);
             }
             break;
-    
+
         case COMPLEX:
-            if (ipiv) 
-                Py_BEGIN_ALLOW_THREADS	    
+            if (ipiv)
+                Py_BEGIN_ALLOW_THREADS
                 zgbsv_(&n, &kl, &ku, &nrhs, MAT_BUFZ(A)+oA, &ldA, ipivc,
                     MAT_BUFZ(B)+oB, &ldB, &info);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
             else {
-                if (!(Ac = (void *) calloc((2*kl+ku+1)*n, 
+                if (!(Ac = (void *) calloc((2*kl+ku+1)*n,
                     sizeof(complex)))){
                     free(ipivc);
                     return PyErr_NoMemory();
                 }
-                for (k=0; k<n; k++) 
-                    memcpy((complex *) Ac + kl + k*(2*kl+ku+1),  
-                        MAT_BUFZ(A) + oA + k*ldA, 
-                        (kl+ku+1)*sizeof(complex)); 
+                for (k=0; k<n; k++)
+                    memcpy((complex *) Ac + kl + k*(2*kl+ku+1),
+                        MAT_BUFZ(A) + oA + k*ldA,
+                        (kl+ku+1)*sizeof(complex));
                 ldA = 2*kl+ku+1;
-                Py_BEGIN_ALLOW_THREADS	    
+                Py_BEGIN_ALLOW_THREADS
                 zgbsv_(&n, &kl, &ku, &nrhs, (complex *) Ac, &ldA, ipivc,
                     MAT_BUFZ(B)+oB, &ldB, &info);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
                 free(Ac);
             }
             break;
 
         default:
             if (ipiv){
-#if (SIZEOF_INT < SIZEOF_LONG) 
-                free(ipivc); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+                free(ipivc);
+#endif
             }
             else free(ipivc);
             err_invalid_id;
     }
 
     if (ipiv){
-#if (SIZEOF_INT < SIZEOF_LONG) 
+#if (SIZEOF_INT < SIZEOF_LONG)
         for (k=0; k<n; k++) MAT_BUFI(ipiv)[k] = ipivc[k];
-        free(ipivc); 
-#endif 
+        free(ipivc);
+#endif
     }
     else free(ipivc);
-    
+
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_gttrf[] = 
+static char doc_gttrf[] =
     "LU factorization of a real or complex tridiagonal matrix.\n\n"
     "gttrf(dl, d, du, du2, ipiv, n=len(d)-offsetd, offsetdl=0, offsetd=0,"
     "\n"
@@ -1048,26 +1076,26 @@ static char doc_gttrf[] =
     "ipiv      'i' matrix of length at least n\n\n"
     "n         nonnegative integer.  If negative, the default value is\n"
     "          used.\n\n"
-    "offsetdl  nonnegative integer\n\n" 
-    "offsetd   nonnegative integer\n\n" 
-    "offsetdu  nonnegative integer"; 
+    "offsetdl  nonnegative integer\n\n"
+    "offsetd   nonnegative integer\n\n"
+    "offsetdu  nonnegative integer";
 
 static PyObject* gttrf(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *dl, *d, *du, *du2, *ipiv; 
-    int n=-1, odl=0, od=0, odu=0, info; 
-    static char *kwlist[] = {"dl", "d", "du", "du2", "ipiv", "n", 
+    matrix *dl, *d, *du, *du2, *ipiv;
+    int n=-1, odl=0, od=0, odu=0, info;
+    static char *kwlist[] = {"dl", "d", "du", "du2", "ipiv", "n",
         "offsetdl", "offsetd", "offsetdu", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOOOO|iiii", kwlist, 
-        &dl, &d, &du, &du2, &ipiv, &n, &odl, &od, &odu)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOOOO|iiii", kwlist,
+        &dl, &d, &du, &du2, &ipiv, &n, &odl, &od, &odu))
         return NULL;
 
     if (!Matrix_Check(dl)) err_mtrx("dl");
     if (!Matrix_Check(d)) err_mtrx("d");
     if (!Matrix_Check(du)) err_mtrx("du");
     if (!Matrix_Check(du2)) err_mtrx("du");
-    if ((MAT_ID(dl) != MAT_ID(d)) || (MAT_ID(dl) != MAT_ID(du)) || 
+    if ((MAT_ID(dl) != MAT_ID(d)) || (MAT_ID(dl) != MAT_ID(du)) ||
         (MAT_ID(dl) != MAT_ID(du2))) err_conflicting_ids;
     if (!Matrix_Check(ipiv) || ipiv->id != INT) err_int_mtrx("ipiv");
     if (od < 0) err_nn_int("offsetd");
@@ -1083,46 +1111,46 @@ static PyObject* gttrf(PyObject *self, PyObject *args, PyObject *kwrds)
     if (len(ipiv) < n) err_buf_len("ipiv");
     if (n > len(ipiv)) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(n*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory(); 
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(n*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(dl)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dgttrf_(&n, MAT_BUFD(dl)+odl, MAT_BUFD(d)+od, MAT_BUFD(du)+odu,
                 MAT_BUFD(du2), ipiv_ptr, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zgttrf_(&n, MAT_BUFZ(dl)+odl, MAT_BUFZ(d)+od, MAT_BUFZ(du)+odu,
                 MAT_BUFZ(du2), ipiv_ptr, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
             free(ipiv_ptr);
 #endif
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
+#if (SIZEOF_INT < SIZEOF_LONG)
     int i;  for (i=0; i<n; i++) MAT_BUFI(ipiv)[i] = ipiv_ptr[i];
-    free(ipiv_ptr); 
-#endif 
+    free(ipiv_ptr);
+#endif
 
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_gttrs[] = 
+static char doc_gttrs[] =
     "Solves a real or complex tridiagonal set of linear equations, \n"
     "given the LU factorization computed by gttrf().\n\n"
     "gttrs(dl, d, du, du2, ipiv, B, trans='N', n=len(d)-offsetd,\n"
@@ -1149,22 +1177,22 @@ static char doc_gttrs[] =
     "          used.\n\n"
     "ldB       positive integer.  ldB >= max(1,n).  If zero, the default\n"
     "          value is used.\n\n"
-    "offsetdl  nonnegative integer\n\n" 
-    "offsetd   nonnegative integer\n\n" 
-    "offsetdu  nonnegative integer\n\n" 
-    "offsetB   nonnegative integer"; 
+    "offsetdl  nonnegative integer\n\n"
+    "offsetd   nonnegative integer\n\n"
+    "offsetdu  nonnegative integer\n\n"
+    "offsetB   nonnegative integer";
 
 static PyObject* gttrs(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *dl, *d, *du, *du2, *ipiv, *B; 
+    matrix *dl, *d, *du, *du2, *ipiv, *B;
     char trans='N';
-    int n=-1, nrhs=-1, ldB=0, odl=0, od=0, odu=0, oB=0, info; 
+    int n=-1, nrhs=-1, ldB=0, odl=0, od=0, odu=0, oB=0, info;
     static char *kwlist[] = {"dl", "d", "du", "du2", "ipiv", "B", "trans",
         "n", "nrhs", "ldB", "offsetdl", "offsetd", "offsetdu", "offsetB",
         NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOOOOO|ciiiiiii", 
-        kwlist, &dl, &d, &du, &du2, &ipiv, &B, &trans, &n, &nrhs, &ldB, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOOOOO|ciiiiiii",
+        kwlist, &dl, &d, &du, &du2, &ipiv, &B, &trans, &n, &nrhs, &ldB,
         &odl, &od, &odu, &oB)) return NULL;
 
     if (!Matrix_Check(dl)) err_mtrx("dl");
@@ -1172,8 +1200,8 @@ static PyObject* gttrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(du)) err_mtrx("du");
     if (!Matrix_Check(du2)) err_mtrx("du");
     if (!Matrix_Check(B)) err_mtrx("B");
-    if ((MAT_ID(dl) != MAT_ID(d)) || (MAT_ID(dl) != MAT_ID(du)) || 
-        (MAT_ID(dl) != MAT_ID(du2)) || (MAT_ID(dl) != MAT_ID(B))) 
+    if ((MAT_ID(dl) != MAT_ID(d)) || (MAT_ID(dl) != MAT_ID(du)) ||
+        (MAT_ID(dl) != MAT_ID(du2)) || (MAT_ID(dl) != MAT_ID(B)))
         err_conflicting_ids;
     if (!Matrix_Check(ipiv) || ipiv->id != INT) err_int_mtrx("ipiv");
     if (trans != 'N' && trans != 'T' && trans != 'C')
@@ -1195,48 +1223,48 @@ static PyObject* gttrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
     if (n > len(ipiv)) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(n*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory(); 
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(n*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
     int i;  for (i=0; i<n; i++) ipiv_ptr[i] = MAT_BUFI(ipiv)[i];
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(dl)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dgttrs_(&trans, &n, &nrhs, MAT_BUFD(dl)+odl, MAT_BUFD(d)+od,
-                MAT_BUFD(du)+odu, MAT_BUFD(du2), ipiv_ptr, 
+                MAT_BUFD(du)+odu, MAT_BUFD(du2), ipiv_ptr,
                 MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zgttrs_(&trans, &n, &nrhs, MAT_BUFZ(dl)+odl, MAT_BUFZ(d)+od,
-                MAT_BUFZ(du)+odu, MAT_BUFZ(du2), ipiv_ptr, 
+                MAT_BUFZ(du)+odu, MAT_BUFZ(du2), ipiv_ptr,
                 MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
             free(ipiv_ptr);
 #endif
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
-    free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+    free(ipiv_ptr);
+#endif
 
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_gtsv[] = 
+static char doc_gtsv[] =
     "Solves a real or complex set of linear equations with a tridiagonal\n"
     "coefficient matrix.\n\n"
     "gtsv(dl, d, du, B, n=len(d)-offsetd, nrhs=B.size[1], \n"
@@ -1259,28 +1287,28 @@ static char doc_gtsv[] =
     "          used.\n\n"
     "ldB       positive integer.  ldB >= max(1,n).  If zero, the default\n"
     "          value is used.\n\n"
-    "offsetdl  nonnegative integer\n\n" 
-    "offsetd   nonnegative integer\n\n" 
-    "offsetdu  nonnegative integer\n\n" 
+    "offsetdl  nonnegative integer\n\n"
+    "offsetd   nonnegative integer\n\n"
+    "offsetdu  nonnegative integer\n\n"
     "offsetB   nonnegative integer";
 
 static PyObject* gtsv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *dl, *d, *du, *B; 
-    int n=-1, nrhs=-1, ldB=0, odl=0, od=0, odu=0, oB=0, info; 
-    static char *kwlist[] = {"dl", "d", "du", "B", "n", "nrhs", "ldB", 
+    matrix *dl, *d, *du, *B;
+    int n=-1, nrhs=-1, ldB=0, odl=0, od=0, odu=0, oB=0, info;
+    static char *kwlist[] = {"dl", "d", "du", "B", "n", "nrhs", "ldB",
         "offsetdl", "offsetd", "offsetdu", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOOO|iiiiiii", kwlist, 
-        &dl, &d, &du, &B, &n, &nrhs, &ldB, &odl, &od, &odu, &oB)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOOO|iiiiiii", kwlist,
+        &dl, &d, &du, &B, &n, &nrhs, &ldB, &odl, &od, &odu, &oB))
         return NULL;
 
     if (!Matrix_Check(dl)) err_mtrx("dl");
     if (!Matrix_Check(d)) err_mtrx("d");
     if (!Matrix_Check(du)) err_mtrx("du");
     if (!Matrix_Check(B)) err_mtrx("B");
-    if ((MAT_ID(dl) != MAT_ID(B)) || (MAT_ID(dl) != MAT_ID(d)) || 
-        (MAT_ID(dl) != MAT_ID(du)) || (MAT_ID(dl) != MAT_ID(B))) 
+    if ((MAT_ID(dl) != MAT_ID(B)) || (MAT_ID(dl) != MAT_ID(d)) ||
+        (MAT_ID(dl) != MAT_ID(du)) || (MAT_ID(dl) != MAT_ID(B)))
         err_conflicting_ids;
     if (od < 0) err_nn_int("offsetd");
     if (n < 0) n = len(d) - od;
@@ -1299,17 +1327,17 @@ static PyObject* gtsv(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(dl)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dgtsv_(&n, &nrhs, MAT_BUFD(dl)+odl, MAT_BUFD(d)+od,
                 MAT_BUFD(du)+odu, MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zgtsv_(&n, &nrhs, MAT_BUFZ(dl)+odl, MAT_BUFZ(d)+od,
                 MAT_BUFZ(du)+odu, MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1321,7 +1349,7 @@ static PyObject* gtsv(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_potrf[] = 
+static char doc_potrf[] =
     "Cholesky factorization of a real symmetric or complex Hermitian\n"
     "positive definite matrix.\n\n"
     "potrf(A, uplo='L', n=A.size[0], ldA = max(1,A.size[0]), offsetA=0)"
@@ -1343,8 +1371,8 @@ static char doc_potrf[] =
 
 static PyObject* potrf(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A; 
-    int n=-1, ldA=0, oA=0, info; 
+    matrix *A;
+    int n=-1, ldA=0, oA=0, info;
     char uplo='L';
     char *kwlist[] = {"A", "uplo", "n", "ldA", "offsetA", NULL};
 
@@ -1353,7 +1381,7 @@ static PyObject* potrf(PyObject *self, PyObject *args, PyObject *kwrds)
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A is not square");
@@ -1364,20 +1392,20 @@ static PyObject* potrf(PyObject *self, PyObject *args, PyObject *kwrds)
     if (n == 0) return Py_BuildValue("");
     if (ldA == 0) ldA = MAX(1, A->nrows);
     if (ldA < MAX(1,n)) err_ld("ldA");
-    if (oA < 0) err_nn_int("offsetA"); 
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dpotrf_(&uplo, &n, MAT_BUFD(A)+oA, &ldA, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
 	    break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zpotrf_(&uplo, &n, MAT_BUFZ(A)+oA, &ldA, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
 	    break;
 
 	default:
@@ -1388,7 +1416,7 @@ static PyObject* potrf(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_potrs[] = 
+static char doc_potrs[] =
     "Solves a real symmetric or complex Hermitian positive definite set\n"
     "of linear equations, given the Cholesky factorization computed by\n"
     "potrf() or posv().\n\n"
@@ -1417,13 +1445,13 @@ static char doc_potrs[] =
 
 static PyObject* potrs(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B; 
-    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info; 
+    matrix *A, *B;
+    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info;
     char uplo='L';
-    char *kwlist[] = {"A", "B", "uplo", "n", "nrhs", "ldA", "ldB", 
+    char *kwlist[] = {"A", "B", "uplo", "n", "nrhs", "ldA", "ldB",
         "offsetA", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiii", kwlist,
         &A, &B, &uplo, &n, &nrhs, &ldA, &ldB, &oA, &oB))
         return NULL;
 
@@ -1445,17 +1473,17 @@ static PyObject* potrs(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dpotrs_(&uplo, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, MAT_BUFD(B)+oB,
                 &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zpotrs_(&uplo, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, MAT_BUFZ(B)+oB,
                 &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
 	    break;
 
         default:
@@ -1466,8 +1494,8 @@ static PyObject* potrs(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_potri[] = 
-    "Inverse of a real symmetric or complex Hermitian positive definite\n" 
+static char doc_potri[] =
+    "Inverse of a real symmetric or complex Hermitian positive definite\n"
     "matrix.\n\n"
     "potri(A, uplo='L', n=A.size[0], ldA=max(1,A.size[0]), offsetA=0)\n\n"
     "PURPOSE\n"
@@ -1486,12 +1514,12 @@ static char doc_potri[] =
 
 static PyObject* potri(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A; 
-    int n=-1, ldA=0, oA=0, info; 
+    matrix *A;
+    int n=-1, ldA=0, oA=0, info;
     char uplo='L';
     char *kwlist[] = {"A", "uplo", "n", "ldA", "offsetA", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|ciii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|ciii", kwlist,
         &A, &uplo, &n, &ldA, &oA)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -1505,15 +1533,15 @@ static PyObject* potri(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dpotri_(&uplo, &n, MAT_BUFD(A)+oA, &ldA, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zpotri_(&uplo, &n, MAT_BUFZ(A)+oA, &ldA, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1524,7 +1552,7 @@ static PyObject* potri(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_posv[] = 
+static char doc_posv[] =
     "Solves a real symmetric or complex Hermitian positive definite set\n"
     "of linear equations.\n\n"
     "posv(A, B, uplo='L', n=A.size[0], nrhs=B.size[1], \n"
@@ -1553,13 +1581,13 @@ static char doc_posv[] =
 
 static PyObject* posv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B; 
-    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info; 
+    matrix *A, *B;
+    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info;
     char uplo='L';
-    char *kwlist[] = {"A", "B", "uplo", "n", "nrhs", "ldA", "ldB", 
+    char *kwlist[] = {"A", "B", "uplo", "n", "nrhs", "ldA", "ldB",
         "offsetA", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiii", kwlist,
         &A, &B, &uplo, &n, &nrhs, &ldA, &ldB, &oA, &oB))
         return NULL;
 
@@ -1576,22 +1604,22 @@ static PyObject* posv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldB < MAX(1, n)) err_ld("ldB");
     if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
-    if (oB < 0) err_nn_int("offsetB");  
+    if (oB < 0) err_nn_int("offsetB");
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dposv_(&uplo, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, MAT_BUFD(B)+oB,
                 &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zposv_(&uplo, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, MAT_BUFZ(B)+oB,
                 &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1602,7 +1630,7 @@ static PyObject* posv(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_pbtrf[] = 
+static char doc_pbtrf[] =
     "Cholesky factorization of a real symmetric or complex Hermitian\n"
     "positive definite band matrix.\n\n"
     "pbtrf(A, uplo='L', n=A.size[1], kd=A.size[0]-1, ldA=max(1,A.size[0]),"
@@ -1627,8 +1655,8 @@ static char doc_pbtrf[] =
 
 static PyObject* pbtrf(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A; 
-    int n=-1, kd=-1, ldA=0, oA=0, info; 
+    matrix *A;
+    int n=-1, kd=-1, ldA=0, oA=0, info;
     char uplo='L';
     char *kwlist[] = {"A", "uplo", "n", "kd", "ldA", "offsetA", NULL};
 
@@ -1644,20 +1672,20 @@ static PyObject* pbtrf(PyObject *self, PyObject *args, PyObject *kwrds)
     if (kd < 0) err_nn_int("kd");
     if (ldA == 0) ldA = MAX(1, A->nrows);
     if (ldA < kd+1) err_ld("ldA");
-    if (oA < 0) err_nn_int("offsetA"); 
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + kd + 1 > len(A)) err_buf_len("A");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dpbtrf_(&uplo, &n, &kd, MAT_BUFD(A)+oA, &ldA, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zpbtrf_(&uplo, &n, &kd, MAT_BUFZ(A)+oA, &ldA, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1668,7 +1696,7 @@ static PyObject* pbtrf(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_pbtrs[] = 
+static char doc_pbtrs[] =
     "Solves a real symmetric or complex Hermitian positive definite set\n"
     "of linear equations with a banded coefficient matrix, given the\n"
     "Cholesky factorization computed by pbtrf() or pbsv().\n\n"
@@ -1700,13 +1728,13 @@ static char doc_pbtrs[] =
 
 static PyObject* pbtrs(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B; 
-    int n=-1, kd=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info; 
+    matrix *A, *B;
+    int n=-1, kd=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info;
     char uplo='L';
     char *kwlist[] = {"A", "B", "uplo", "n", "kd", "nrhs", "ldA", "ldB",
         "offsetA", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiiii", kwlist,
         &A, &B, &uplo, &n, &kd, &nrhs, &ldA, &ldB, &oA, oB))
         return NULL;
 
@@ -1723,24 +1751,24 @@ static PyObject* pbtrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldA < kd+1) err_ld("ldA");
     if (ldB == 0) ldB = MAX(1,B->nrows);
     if (ldB < MAX(1,n)) err_ld("ldB");
-    if (oA < 0) err_nn_int("offsetA"); 
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + kd + 1 > len(A)) err_buf_len("A");
     if (oB < 0) err_nn_int("offsetB");
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dpbtrs_(&uplo, &n, &kd, &nrhs, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dpbtrs_(&uplo, &n, &kd, &nrhs, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            zpbtrs_(&uplo, &n, &kd, &nrhs, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            zpbtrs_(&uplo, &n, &kd, &nrhs, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1751,7 +1779,7 @@ static PyObject* pbtrs(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_pbsv[] = 
+static char doc_pbsv[] =
     "Solves a real symmetric or complex Hermitian positive definite set\n"
     "of linear equations with a banded coefficient matrix.\n\n"
     "pbsv(A, B, uplo='L', n=A.size[1], kd=A.size[0]-1, nrhs=B.size[1],\n"
@@ -1784,13 +1812,13 @@ static char doc_pbsv[] =
 
 static PyObject* pbsv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B; 
-    int n=-1, kd=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info; 
+    matrix *A, *B;
+    int n=-1, kd=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info;
     char uplo='L';
     char *kwlist[] = {"A", "B", "uplo", "n", "kd", "nrhs", "ldA", "ldB",
         "offsetA", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiiii", kwlist,
         &A, &B, &uplo, &n, &kd, &nrhs, &ldA, &ldB, &oA, oB))
         return NULL;
 
@@ -1807,24 +1835,24 @@ static PyObject* pbsv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldA < kd+1) err_ld("ldA");
     if (ldB == 0) ldB = MAX(1,B->nrows);
     if (ldB < MAX(1,n)) err_ld("ldB");
-    if (oA < 0) err_nn_int("offsetA"); 
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + kd + 1 > len(A)) err_buf_len("A");
     if (oB < 0) err_nn_int("offsetB");
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dpbsv_(&uplo, &n, &kd, &nrhs, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dpbsv_(&uplo, &n, &kd, &nrhs, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            zpbsv_(&uplo, &n, &kd, &nrhs, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            zpbsv_(&uplo, &n, &kd, &nrhs, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1835,7 +1863,7 @@ static PyObject* pbsv(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_pttrf[] = 
+static char doc_pttrf[] =
     "Cholesky factorization of a real symmetric or complex Hermitian\n"
     "positive definite tridiagonal matrix.\n\n"
     "pttrf(d, e, n=len(d)-offsetd, offsetd=0, offsete=0)\n\n"
@@ -1850,16 +1878,16 @@ static char doc_pttrf[] =
     "e         'd' or 'z' matrix.\n\n"
     "n         nonnegative integer.  If negative, the default value is\n"
     "          used.\n\n"
-    "offsetd   nonnegative integer\n\n" 
+    "offsetd   nonnegative integer\n\n"
     "offsete   nonnegative integer";
 
 static PyObject* pttrf(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *d, *e; 
-    int n=-1, od=0, oe=0, info; 
+    matrix *d, *e;
+    int n=-1, od=0, oe=0, info;
     static char *kwlist[] = {"d", "e", "n", "offsetd", "offsete", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iii", kwlist, &d, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iii", kwlist, &d,
         &e, &n, &od, &oe)) return NULL;
 
     if (!Matrix_Check(d)) err_mtrx("d");
@@ -1875,15 +1903,15 @@ static PyObject* pttrf(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(e)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dpttrf_(&n, MAT_BUFD(d)+od, MAT_BUFD(e)+oe, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zpttrf_(&n, MAT_BUFD(d)+od, MAT_BUFZ(e)+oe, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1895,7 +1923,7 @@ static PyObject* pttrf(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_pttrs[] = 
+static char doc_pttrs[] =
     "Solves a real symmetric or complex Hermitian positive definite set\n"
     "of linear equations with a tridiagonal coefficient matrix, given \n"
     "the factorization computed by pttrf().\n\n"
@@ -1921,19 +1949,19 @@ static char doc_pttrs[] =
     "          used.\n\n"
     "ldB       positive integer.  ldB >= max(1,n).  If zero, the default\n"
     "          value is used.\n\n"
-    "offsetd   nonnegative integer\n\n" 
-    "offsete   nonnegative integer\n\n" 
+    "offsetd   nonnegative integer\n\n"
+    "offsete   nonnegative integer\n\n"
     "offsetB   nonnegative integer";
 
 static PyObject* pttrs(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *d, *e, *B; 
+    matrix *d, *e, *B;
     char uplo='L';
-    int n=-1, nrhs=-1, ldB=0, od=0, oe=0, oB=0, info; 
-    static char *kwlist[] = {"d", "e", "B", "uplo", "n", "nrhs", "ldB", 
+    int n=-1, nrhs=-1, ldB=0, od=0, oe=0, oB=0, info;
+    static char *kwlist[] = {"d", "e", "B", "uplo", "n", "nrhs", "ldB",
         "offsetd", "offsete", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ciiiiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ciiiiii", kwlist,
         &d, &e, &B, &uplo, &n, &nrhs, &ldB, &od, &oe, &oB)) return NULL;
 
     if (!Matrix_Check(d)) err_mtrx("d");
@@ -1957,17 +1985,17 @@ static PyObject* pttrs(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(e)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dpttrs_(&n, &nrhs, MAT_BUFD(d)+od, MAT_BUFD(e)+oe, 
+            Py_BEGIN_ALLOW_THREADS
+            dpttrs_(&n, &nrhs, MAT_BUFD(d)+od, MAT_BUFD(e)+oe,
                 MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            zpttrs_(&uplo, &n, &nrhs, MAT_BUFD(d)+od, MAT_BUFZ(e)+oe, 
+            Py_BEGIN_ALLOW_THREADS
+            zpttrs_(&uplo, &n, &nrhs, MAT_BUFD(d)+od, MAT_BUFZ(e)+oe,
                 MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -1979,7 +2007,7 @@ static PyObject* pttrs(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_ptsv[] = 
+static char doc_ptsv[] =
     "Solves a real symmetric or complex Hermitian positive definite set\n"
     "of linear equations with a tridiagonal coefficient matrix.\n\n"
     "ptsv(d, e, B, n=len(d)-offsetd, nrhs=B.size[1], ldB=max(1,B.size[0],"
@@ -2001,18 +2029,18 @@ static char doc_ptsv[] =
     "          used.\n\n"
     "ldB       positive integer.  ldB >= max(1,n).  If zero, the default\n"
     "          value is used.\n\n"
-    "offsetd   nonnegative integer\n\n" 
-    "offsete   nonnegative integer\n\n" 
+    "offsetd   nonnegative integer\n\n"
+    "offsete   nonnegative integer\n\n"
     "offsetB   nonnegative integer";
 
 static PyObject* ptsv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *d, *e, *B; 
-    int n=-1, nrhs=-1, ldB=0, od=0, oe=0, oB=0, info; 
-    static char *kwlist[] = {"d", "e", "B", "n", "nrhs", "ldB", "offsetd", 
+    matrix *d, *e, *B;
+    int n=-1, nrhs=-1, ldB=0, od=0, oe=0, oB=0, info;
+    static char *kwlist[] = {"d", "e", "B", "n", "nrhs", "ldB", "offsetd",
         "offsete", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|iiiiii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|iiiiii", kwlist,
         &d, &e, &B, &n, &nrhs, &ldB, &od, &oe, &oB)) return NULL;
 
     if (!Matrix_Check(d)) err_mtrx("d");
@@ -2035,17 +2063,17 @@ static PyObject* ptsv(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(e)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dptsv_(&n, &nrhs, MAT_BUFD(d)+od, MAT_BUFD(e)+oe, 
+            Py_BEGIN_ALLOW_THREADS
+            dptsv_(&n, &nrhs, MAT_BUFD(d)+od, MAT_BUFD(e)+oe,
                 MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            zptsv_(&n, &nrhs, MAT_BUFD(d)+od, MAT_BUFZ(e)+oe, 
+            Py_BEGIN_ALLOW_THREADS
+            zptsv_(&n, &nrhs, MAT_BUFD(d)+od, MAT_BUFZ(e)+oe,
                 MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -2057,7 +2085,7 @@ static PyObject* ptsv(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_sytrf[] = 
+static char doc_sytrf[] =
     "LDL^T factorization of a real or complex symmetric matrix.\n\n"
     "sytrf(A, ipiv, uplo='L', n=A.size[0], ldA=max(1,A.size[0]))\n\n"
     "PURPOSE\n"
@@ -2066,7 +2094,7 @@ static char doc_sytrf[] =
     "factorization.\n\n"
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix\n\n"
-    "ipiv      'i' matrix of length at least n\n\n" 
+    "ipiv      'i' matrix of length at least n\n\n"
     "uplo      'L' or 'U'\n\n"
     "n         nonnegative integer.  If negative, the default value is\n"
     "          used.\n\n"
@@ -2076,20 +2104,20 @@ static char doc_sytrf[] =
 
 static PyObject* sytrf(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *ipiv; 
-    void *work; 
+    matrix *A, *ipiv;
+    void *work;
     number wl;
     int n=-1, ldA=0, oA=0, info, lwork;
     char uplo='L';
     char *kwlist[] = {"A", "ipiv", "uplo", "n", "ldA", "offsetA", NULL};
-    
+
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciii", kwlist,
         &A, &ipiv, &uplo, &n, &ldA, &oA)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(ipiv) || ipiv->id != INT) err_int_mtrx("ipiv");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -2099,73 +2127,73 @@ static PyObject* sytrf(PyObject *self, PyObject *args, PyObject *kwrds)
     if (n == 0) return Py_BuildValue("");
     if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1,n)) err_ld("ldA");
-    if (oA < 0) err_nn_int("offsetA");  
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
     if (len(ipiv) < n) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(n*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory();			
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(n*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsytrf_(&uplo, &n, NULL, &ldA, NULL, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = (void *) calloc(lwork, sizeof(double)))){
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
                 free(ipiv_ptr);
-#endif						
+#endif
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            dsytrf_(&uplo, &n, MAT_BUFD(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            dsytrf_(&uplo, &n, MAT_BUFD(A)+oA, &ldA, ipiv_ptr,
                 (double *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   
+            Py_END_ALLOW_THREADS
+            free(work);
             break;
 
         case COMPLEX:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zsytrf_(&uplo, &n, NULL, &ldA, NULL, &wl.z, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
             if (!(work = (void *) calloc(lwork, sizeof(complex)))){
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
                 free(ipiv_ptr);
-#endif						
+#endif
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            zsytrf_(&uplo, &n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            zsytrf_(&uplo, &n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr,
                 (complex *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   
+            Py_END_ALLOW_THREADS
+            free(work);
             break;
 
         default:
-#if (SIZEOF_INT < SIZEOF_LONG) 
-            free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+            free(ipiv_ptr);
+#endif
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
+#if (SIZEOF_INT < SIZEOF_LONG)
     int i;  for (i=0; i<n; i++)  MAT_BUFI(ipiv)[i] = ipiv_ptr[i];
-    free(ipiv_ptr); 
-#endif 
+    free(ipiv_ptr);
+#endif
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_hetrf[] = 
+static char doc_hetrf[] =
     "LDL^H factorization of a real symmetric or complex Hermitian matrix."
     "\n\n"
     "hetrf(A, ipiv, uplo='L', n=A.size[0], ldA=max(1,A.size[0]))\n\n"
@@ -2175,7 +2203,7 @@ static char doc_hetrf[] =
     "details of the factorization.\n\n"
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix\n\n"
-    "ipiv      'i' matrix of length at least n\n\n" 
+    "ipiv      'i' matrix of length at least n\n\n"
     "uplo      'L' or 'U'\n\n"
     "n         nonnegative integer.  If negative, the default value is\n"
     "          used.\n\n"
@@ -2185,20 +2213,20 @@ static char doc_hetrf[] =
 
 static PyObject* hetrf(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *ipiv; 
-    void *work; 
+    matrix *A, *ipiv;
+    void *work;
     number wl;
     int n=-1, ldA=0, oA=0, info, lwork;
     char uplo='L';
     char *kwlist[] = {"A", "ipiv", "uplo", "n", "ldA", "offsetA", NULL};
-    
+
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciii", kwlist,
         &A, &ipiv, &uplo, &n, &ldA, &oA)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(ipiv) || ipiv->id != INT) err_int_mtrx("ipiv");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -2208,73 +2236,73 @@ static PyObject* hetrf(PyObject *self, PyObject *args, PyObject *kwrds)
     if (n == 0) return Py_BuildValue("");
     if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1,n)) err_ld("ldA");
-    if (oA < 0) err_nn_int("offsetA");  
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
     if (len(ipiv) < n) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(n*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory();			
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(n*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsytrf_(&uplo, &n, NULL, &ldA, NULL, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = (void *) calloc(lwork, sizeof(double)))){
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
                 free(ipiv_ptr);
-#endif						
+#endif
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            dsytrf_(&uplo, &n, MAT_BUFD(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            dsytrf_(&uplo, &n, MAT_BUFD(A)+oA, &ldA, ipiv_ptr,
                 (double *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   
+            Py_END_ALLOW_THREADS
+            free(work);
             break;
 
         case COMPLEX:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zhetrf_(&uplo, &n, NULL, &ldA, NULL, &wl.z, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
             if (!(work = (void *) calloc(lwork, sizeof(complex)))){
-#if (SIZEOF_INT < SIZEOF_LONG)			
+#if (SIZEOF_INT < SIZEOF_LONG)
                 free(ipiv_ptr);
-#endif						
+#endif
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            zhetrf_(&uplo, &n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            zhetrf_(&uplo, &n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr,
                 (complex *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   
+            Py_END_ALLOW_THREADS
+            free(work);
             break;
 
         default:
-#if (SIZEOF_INT < SIZEOF_LONG) 
-            free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+            free(ipiv_ptr);
+#endif
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
+#if (SIZEOF_INT < SIZEOF_LONG)
     int i;  for (i=0; i<n; i++)  MAT_BUFI(ipiv)[i] = ipiv_ptr[i];
-    free(ipiv_ptr); 
-#endif 
+    free(ipiv_ptr);
+#endif
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_sytrs[] = 
+static char doc_sytrs[] =
     "Solves a real or complex symmetric set of linear equations,\n"
     "given the LDL^T factorization computed by sytrf() or sysv().\n\n"
     "sytrs(A, ipiv, B, uplo='L', n=A.size[0], nrhs=B.size[1],\n"
@@ -2303,14 +2331,14 @@ static char doc_sytrs[] =
 
 static PyObject* sytrs(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B, *ipiv; 
-    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info; 
+    matrix *A, *B, *ipiv;
+    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info;
     char uplo='L';
     char *kwlist[] = {"A", "ipiv", "B", "uplo", "n", "nrhs", "ldA", "ldB",
         "offsetA", "offsetB", NULL};
-    
+
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ciiiiii", kwlist,
-        &A, &ipiv, &B, &uplo, &n, &nrhs, &ldA, &ldB, &oA, &oB)) 
+        &A, &ipiv, &B, &uplo, &n, &nrhs, &ldA, &ldB, &oA, &oB))
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -2318,14 +2346,14 @@ static PyObject* sytrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(B)) err_mtrx("B");
     if (MAT_ID(A) != MAT_ID(B)) err_conflicting_ids;
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
             return NULL;
         }
     }
-    if (nrhs < 0) nrhs = B->ncols; 
+    if (nrhs < 0) nrhs = B->ncols;
     if (n == 0 || nrhs == 0) return Py_BuildValue("");
     if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1,n)) err_ld("ldA");
@@ -2337,47 +2365,47 @@ static PyObject* sytrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
     if (len(ipiv) < n) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(n*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory();			
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(n*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
     int i;  for (i=0; i<n; i++) ipiv_ptr[i] = MAT_BUFI(ipiv)[i];
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dsytrs_(&uplo, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            dsytrs_(&uplo, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, ipiv_ptr,
                 MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
 	case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            zsytrs_(&uplo, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            zsytrs_(&uplo, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr,
                 MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
 	default:
-#if (SIZEOF_INT < SIZEOF_LONG) 
-            free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+            free(ipiv_ptr);
+#endif
 	    err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
-    free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+    free(ipiv_ptr);
+#endif
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_hetrs[] = 
+static char doc_hetrs[] =
     "Solves a real symmetric or complex Hermitian set of linear\n"
-    "equations, given the LDL^H factorization computed by hetrf() or " 
+    "equations, given the LDL^H factorization computed by hetrf() or "
     "hesv().\n\n"
     "hetrs(A, ipiv, B, uplo='L', n=A.size[0], nrhs=B.size[1],\n"
     "      ldA=max(1,A.size[0]), ldB=max(1,B.size[0]), offsetA=0,\n"
@@ -2405,14 +2433,14 @@ static char doc_hetrs[] =
 
 static PyObject* hetrs(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B, *ipiv; 
-    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info; 
+    matrix *A, *B, *ipiv;
+    int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info;
     char uplo='L';
-    char *kwlist[] = {"A", "ipiv", "B", "uplo", "n", "nrhs", "ldA", "ldB", 
+    char *kwlist[] = {"A", "ipiv", "B", "uplo", "n", "nrhs", "ldA", "ldB",
         "offsetA", "offsetB", NULL};
-    
+
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ciiiiii", kwlist,
-        &A, &ipiv, &B, &uplo, &n, &nrhs, &ldA, &ldB, &oA, &oB)) 
+        &A, &ipiv, &B, &uplo, &n, &nrhs, &ldA, &ldB, &oA, &oB))
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -2420,14 +2448,14 @@ static PyObject* hetrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(B)) err_mtrx("B");
     if (MAT_ID(A) != MAT_ID(B)) err_conflicting_ids;
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
             return NULL;
         }
     }
-    if (nrhs < 0) nrhs = B->ncols; 
+    if (nrhs < 0) nrhs = B->ncols;
     if (n == 0 || nrhs == 0) return Py_BuildValue("");
     if (ldA == 0) ldA = MAX(1,A->nrows);
     if (ldA < MAX(1,n)) err_ld("ldA");
@@ -2439,45 +2467,45 @@ static PyObject* hetrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
     if (len(ipiv) < n) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(n*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory();			
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(n*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
     int i;  for (i=0; i<n; i++) ipiv_ptr[i] = MAT_BUFI(ipiv)[i];
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
-            dsytrs_(&uplo, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dsytrs_(&uplo, &n, &nrhs, MAT_BUFD(A)+oA, &ldA,
                 ipiv_ptr, MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
 	case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            zhetrs_(&uplo, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            zhetrs_(&uplo, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA,
                 ipiv_ptr, MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
 	default:
-#if (SIZEOF_INT < SIZEOF_LONG) 
-            free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+            free(ipiv_ptr);
+#endif
 	    err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
-    free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+    free(ipiv_ptr);
+#endif
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_sytri[] = 
+static char doc_sytri[] =
     "Inverse of a real or complex symmetric matrix.\n\n"
     "sytri(A, ipiv, uplo='L', n=A.size[0], ldA=max(1,A.size[0]),\n"
     "      offsetA=0)\n\n"
@@ -2498,20 +2526,20 @@ static char doc_sytri[] =
 
 static PyObject* sytri(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *ipiv; 
-    int n=-1, ldA=0, oA=0, info; 
+    matrix *A, *ipiv;
+    int n=-1, ldA=0, oA=0, info;
     char uplo='L';
-    void *work; 
+    void *work;
     char *kwlist[] = {"A", "ipiv", "uplo", "n", "ldA", "offsetA", NULL};
-    
+
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciii", kwlist,
-        &A, &ipiv, &uplo, &n, &ldA, &oA)) 
+        &A, &ipiv, &uplo, &n, &ldA, &oA))
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(ipiv) || ipiv->id != INT) err_int_mtrx("ipiv");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -2525,13 +2553,13 @@ static PyObject* sytri(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
     if (len(ipiv) < n) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(n*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory();			
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(n*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
     int i;  for (i=0; i<n; i++) ipiv_ptr[i] = MAT_BUFI(ipiv)[i];
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(A)){
         case DOUBLE:
@@ -2541,10 +2569,10 @@ static PyObject* sytri(PyObject *self, PyObject *args, PyObject *kwrds)
 #endif
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            dsytri_(&uplo, &n, MAT_BUFD(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            dsytri_(&uplo, &n, MAT_BUFD(A)+oA, &ldA, ipiv_ptr,
                 (double *) work, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
             break;
 
@@ -2555,10 +2583,10 @@ static PyObject* sytri(PyObject *self, PyObject *args, PyObject *kwrds)
 #endif
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            zsytri_(&uplo, &n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            zsytri_(&uplo, &n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr,
                 (complex *) work, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
             break;
 
@@ -2569,15 +2597,15 @@ static PyObject* sytri(PyObject *self, PyObject *args, PyObject *kwrds)
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
-    free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+    free(ipiv_ptr);
+#endif
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_hetri[] = 
+static char doc_hetri[] =
     "Inverse of a real symmetric or complex Hermitian matrix.\n\n"
     "hetri(A, ipiv, uplo='L', n=A.size[0], ldA=max(1,A.size[0]),\n"
     "      offsetA=0)\n\n"
@@ -2598,20 +2626,20 @@ static char doc_hetri[] =
 
 static PyObject* hetri(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *ipiv; 
-    int n=-1, ldA=0, oA=0, info; 
+    matrix *A, *ipiv;
+    int n=-1, ldA=0, oA=0, info;
     char uplo='L';
-    void *work; 
+    void *work;
     char *kwlist[] = {"A", "ipiv", "uplo", "n", "ldA", "offsetA", NULL};
-    
+
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciii", kwlist,
-        &A, &ipiv, &uplo, &n, &ldA, &oA)) 
+        &A, &ipiv, &uplo, &n, &ldA, &oA))
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(ipiv) || ipiv->id != INT) err_int_mtrx("ipiv");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -2625,13 +2653,13 @@ static PyObject* hetri(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
     if (len(ipiv) < n) err_buf_len("ipiv");
 
-#if (SIZEOF_INT < SIZEOF_LONG)			
-    int *ipiv_ptr = malloc(n*sizeof(int));	
-    if (!ipiv_ptr) return PyErr_NoMemory();			
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *ipiv_ptr = malloc(n*sizeof(int));
+    if (!ipiv_ptr) return PyErr_NoMemory();
     int i;  for (i=0; i<n; i++) ipiv_ptr[i] = MAT_BUFI(ipiv)[i];
-#else 
-    int *ipiv_ptr = MAT_BUFI(ipiv);		
-#endif						
+#else
+    int *ipiv_ptr = MAT_BUFI(ipiv);
+#endif
 
     switch (MAT_ID(A)){
         case DOUBLE:
@@ -2641,10 +2669,10 @@ static PyObject* hetri(PyObject *self, PyObject *args, PyObject *kwrds)
 #endif
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            dsytri_(&uplo, &n, MAT_BUFD(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            dsytri_(&uplo, &n, MAT_BUFD(A)+oA, &ldA, ipiv_ptr,
                 (double *) work, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
             break;
 
@@ -2655,10 +2683,10 @@ static PyObject* hetri(PyObject *self, PyObject *args, PyObject *kwrds)
 #endif
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            zhetri_(&uplo, &n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr, 
+            Py_BEGIN_ALLOW_THREADS
+            zhetri_(&uplo, &n, MAT_BUFZ(A)+oA, &ldA, ipiv_ptr,
                 (complex *) work, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
             break;
 
@@ -2669,15 +2697,15 @@ static PyObject* hetri(PyObject *self, PyObject *args, PyObject *kwrds)
             err_invalid_id;
     }
 
-#if (SIZEOF_INT < SIZEOF_LONG) 
-    free(ipiv_ptr); 
-#endif 
+#if (SIZEOF_INT < SIZEOF_LONG)
+    free(ipiv_ptr);
+#endif
     if (info) err_lapack
     else return Py_BuildValue("");
 }
 
 
-static char doc_sysv[] = 
+static char doc_sysv[] =
     "Solves a real or complex symmetric set of linear equations.\n\n"
     "sysv(A, B, ipiv=None, uplo='L', n=A.size[0], nrhs=B.size[1],\n"
     "     ldA = max(1,A.size[0]), ldB = max(1,B.size[0]),\n"
@@ -2691,7 +2719,7 @@ static char doc_sysv[] =
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix\n\n"
     "B         'd' or 'z' matrix.  Must have the same type as A.\n\n"
-    "ipiv      'i' matrix of length at least n\n\n" 
+    "ipiv      'i' matrix of length at least n\n\n"
     "uplo      'L' or 'U'\n\n"
     "n         nonnegative integer.  If negative, the default value is\n"
     "          used.\n\n"
@@ -2706,13 +2734,13 @@ static char doc_sysv[] =
 
 static PyObject* sysv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B, *ipiv=NULL; 
+    matrix *A, *B, *ipiv=NULL;
     int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info, lwork, k,
-        *ipivc=NULL; 
+        *ipivc=NULL;
     void *work=NULL, *Ac=NULL;
     number wl;
     char uplo='L';
-    char *kwlist[] = {"A", "B", "ipiv", "uplo", "n", "nrhs", "ldA", 
+    char *kwlist[] = {"A", "B", "ipiv", "uplo", "n", "nrhs", "ldA",
         "ldB", "offsetA", "offsetB", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Ociiiiii", kwlist,
@@ -2722,10 +2750,10 @@ static PyObject* sysv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(B)) err_mtrx("B");
     if (MAT_ID(A) != MAT_ID(B)) err_conflicting_ids;
-    if (ipiv && (!Matrix_Check(ipiv) || ipiv->id != INT)) 
+    if (ipiv && (!Matrix_Check(ipiv) || ipiv->id != INT))
         err_int_mtrx("ipiv");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -2747,31 +2775,31 @@ static PyObject* sysv(PyObject *self, PyObject *args, PyObject *kwrds)
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsytrf_(&uplo, &n, NULL, &ldA, NULL, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = (void *) calloc(lwork, sizeof(double))))
                 return PyErr_NoMemory();
             if (ipiv) {
-#if (SIZEOF_INT < SIZEOF_LONG)			
-                if (!(ipivc = (int *) calloc(n, sizeof(int)))){	
-                    free(work); 
+#if (SIZEOF_INT < SIZEOF_LONG)
+                if (!(ipivc = (int *) calloc(n, sizeof(int)))){
+                    free(work);
                     return PyErr_NoMemory();
                 }
                 for (k=0; k<n; k++) ipivc[k] = MAT_BUFI(ipiv)[k];
-#else 
-                ipivc = MAT_BUFI(ipiv);		
-#endif						
-                Py_BEGIN_ALLOW_THREADS	    
-                dsysv_(&uplo, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, ipivc, 
-                    MAT_BUFD(B)+oB, &ldB, (double *) work, &lwork, 
+#else
+                ipivc = MAT_BUFI(ipiv);
+#endif
+                Py_BEGIN_ALLOW_THREADS
+                dsysv_(&uplo, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, ipivc,
+                    MAT_BUFD(B)+oB, &ldB, (double *) work, &lwork,
                     &info);
-                Py_END_ALLOW_THREADS	    
-#if (SIZEOF_INT < SIZEOF_LONG) 
+                Py_END_ALLOW_THREADS
+#if (SIZEOF_INT < SIZEOF_LONG)
 		for (k=0; k<n; k++) MAT_BUFI(ipiv)[k] = ipivc[k];
-                free(ipivc); 
-#endif 
+                free(ipivc);
+#endif
 	    }
             else {
                 ipivc = (int *) calloc(n, sizeof(int));
@@ -2780,44 +2808,44 @@ static PyObject* sysv(PyObject *self, PyObject *args, PyObject *kwrds)
                     free(work);  free(ipivc);  free(Ac);
                     return PyErr_NoMemory();
                 }
-                for (k=0; k<n; k++) 
-                    memcpy((double *) Ac + k*n, MAT_BUFD(A) + oA + k*ldA, 
+                for (k=0; k<n; k++)
+                    memcpy((double *) Ac + k*n, MAT_BUFD(A) + oA + k*ldA,
                         n*sizeof(double));
-                Py_BEGIN_ALLOW_THREADS	    
-                dsysv_(&uplo, &n, &nrhs, (double *) Ac, &n, ipivc, 
+                Py_BEGIN_ALLOW_THREADS
+                dsysv_(&uplo, &n, &nrhs, (double *) Ac, &n, ipivc,
                     MAT_BUFD(B)+oB, &ldB, work, &lwork, &info);
-                Py_END_ALLOW_THREADS	    
+                Py_END_ALLOW_THREADS
                 free(ipivc); free(Ac);
             }
-            free(work);   
+            free(work);
             break;
 
         case COMPLEX:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zsytrf_(&uplo, &n, NULL, &ldA, NULL, &wl.z, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
             if (!(work = (void *) calloc(lwork, sizeof(complex))))
                 return PyErr_NoMemory();
             if (ipiv) {
-#if (SIZEOF_INT < SIZEOF_LONG)			
-                if (!(ipivc = (int *) calloc(n, sizeof(int)))){	
+#if (SIZEOF_INT < SIZEOF_LONG)
+                if (!(ipivc = (int *) calloc(n, sizeof(int)))){
                     free(work);
-                    return PyErr_NoMemory();			
+                    return PyErr_NoMemory();
                 }
                 for (k=0; k<n; k++) ipivc[k] = MAT_BUFI(ipiv)[k];
-#else 
-                ipivc = MAT_BUFI(ipiv);		
+#else
+                ipivc = MAT_BUFI(ipiv);
 #endif
-                Py_BEGIN_ALLOW_THREADS	    
-                zsysv_(&uplo, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, ipivc, 
+                Py_BEGIN_ALLOW_THREADS
+                zsysv_(&uplo, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, ipivc,
                     MAT_BUFZ(B)+oB, &ldB, (complex *) work, &lwork, &info);
-                Py_END_ALLOW_THREADS	    
-#if (SIZEOF_INT < SIZEOF_LONG) 
+                Py_END_ALLOW_THREADS
+#if (SIZEOF_INT < SIZEOF_LONG)
                 for (k=0; k<n; k++) MAT_BUFI(ipiv)[k] = ipivc[k];
-                free(ipivc); 
-#endif 
+                free(ipivc);
+#endif
             }
             else {
                 ipivc = (int *) calloc(n, sizeof(int));
@@ -2826,16 +2854,16 @@ static PyObject* sysv(PyObject *self, PyObject *args, PyObject *kwrds)
                     free(work);  free(ipivc);  free(Ac);
                     return PyErr_NoMemory();
                 }
-                for (k=0; k<n; k++) 
-                    memcpy((complex *) Ac + k*n, MAT_BUFZ(A) + oA + k*ldA, 
+                for (k=0; k<n; k++)
+                    memcpy((complex *) Ac + k*n, MAT_BUFZ(A) + oA + k*ldA,
                         n*sizeof(complex));
-                Py_BEGIN_ALLOW_THREADS	    
-                zsysv_(&uplo, &n, &nrhs, (complex *) Ac, &n, ipivc, 
+                Py_BEGIN_ALLOW_THREADS
+                zsysv_(&uplo, &n, &nrhs, (complex *) Ac, &n, ipivc,
                     MAT_BUFZ(B)+oB, &ldB, work, &lwork, &info);
-                Py_END_ALLOW_THREADS	    
-                free(ipivc);  free(Ac);    
+                Py_END_ALLOW_THREADS
+                free(ipivc);  free(Ac);
             }
-            free(work);   
+            free(work);
             break;
 
         default:
@@ -2847,7 +2875,7 @@ static PyObject* sysv(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_hesv[] = 
+static char doc_hesv[] =
     "Solves a real symmetric or complex Hermitian set of linear\n"
     "equations.\n\n"
     "herv(A, B, ipiv=None, uplo='L', n=A.size[0], nrhs=B.size[1],\n"
@@ -2862,7 +2890,7 @@ static char doc_hesv[] =
     "ARGUMENTS\n"
     "A         'd' or 'z' matrix\n\n"
     "B         'd' or 'z' matrix.  Must have the same type as A.\n\n"
-    "ipiv      'i' matrix of length at least n\n\n" 
+    "ipiv      'i' matrix of length at least n\n\n"
     "uplo      'U' or 'L'\n\n"
     "n         nonnegative integer.  If negative, the default value is\n"
     "          used.\n\n"
@@ -2877,13 +2905,13 @@ static char doc_hesv[] =
 
 static PyObject* hesv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B, *ipiv=NULL; 
+    matrix *A, *B, *ipiv=NULL;
     int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info, lwork, k,
-        *ipivc=NULL; 
+        *ipivc=NULL;
     void *work=NULL, *Ac=NULL;
     number wl;
     char uplo='L';
-    char *kwlist[] = {"A", "B", "ipiv", "uplo", "n", "nrhs", "ldA", "ldB", 
+    char *kwlist[] = {"A", "B", "ipiv", "uplo", "n", "nrhs", "ldA", "ldB",
         "offsetA", "offsetB", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Ociiiiii", kwlist,
@@ -2893,10 +2921,10 @@ static PyObject* hesv(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(B)) err_mtrx("B");
     if (MAT_ID(A) != MAT_ID(B)) err_conflicting_ids;
-    if (ipiv && (!Matrix_Check(ipiv) || ipiv->id != INT)) 
+    if (ipiv && (!Matrix_Check(ipiv) || ipiv->id != INT))
         err_int_mtrx("ipiv");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -2918,31 +2946,31 @@ static PyObject* hesv(PyObject *self, PyObject *args, PyObject *kwrds)
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsytrf_(&uplo, &n, NULL, &ldA, NULL, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = (void *) calloc(lwork, sizeof(double))))
                 return PyErr_NoMemory();
             if (ipiv) {
-#if (SIZEOF_INT < SIZEOF_LONG)			
-                if (!(ipivc = (int *) calloc(n,sizeof(int)))){	
-                    free(work);  
-                    return PyErr_NoMemory();			
+#if (SIZEOF_INT < SIZEOF_LONG)
+                if (!(ipivc = (int *) calloc(n,sizeof(int)))){
+                    free(work);
+                    return PyErr_NoMemory();
                 }
                 int i; for (i=0; i<n; i++) ipivc[i] = MAT_BUFI(ipiv)[i];
-#else 
-                ipivc = MAT_BUFI(ipiv);		
+#else
+                ipivc = MAT_BUFI(ipiv);
 #endif
-                Py_BEGIN_ALLOW_THREADS	    
-                dsysv_(&uplo, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, ipivc, 
-                    MAT_BUFD(B)+oB, &ldB, (double *) work, &lwork, 
+                Py_BEGIN_ALLOW_THREADS
+                dsysv_(&uplo, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, ipivc,
+                    MAT_BUFD(B)+oB, &ldB, (double *) work, &lwork,
                     &info);
-                Py_END_ALLOW_THREADS	    
-#if (SIZEOF_INT < SIZEOF_LONG) 
+                Py_END_ALLOW_THREADS
+#if (SIZEOF_INT < SIZEOF_LONG)
                 for (i=0; i<n; i++) MAT_BUFI(ipiv)[i] = ipivc[i];
-                free(ipivc); 
-#endif 
+                free(ipivc);
+#endif
             }
             else {
                 ipivc = (int *) calloc(n, sizeof(int));
@@ -2951,16 +2979,16 @@ static PyObject* hesv(PyObject *self, PyObject *args, PyObject *kwrds)
                     free(work);  free(ipivc);  free(Ac);
                     return PyErr_NoMemory();
                 }
-                for (k=0; k<n; k++) 
-                    memcpy((double *) Ac + k*n, MAT_BUFD(A) + oA + k*ldA, 
+                for (k=0; k<n; k++)
+                    memcpy((double *) Ac + k*n, MAT_BUFD(A) + oA + k*ldA,
                         n*sizeof(double));
-                Py_BEGIN_ALLOW_THREADS	    
-                dsysv_(&uplo, &n, &nrhs, (double *) Ac, &n, ipivc, 
+                Py_BEGIN_ALLOW_THREADS
+                dsysv_(&uplo, &n, &nrhs, (double *) Ac, &n, ipivc,
                     MAT_BUFD(B)+oB, &ldB, work, &lwork, &info);
-                Py_END_ALLOW_THREADS	    
-                free(ipivc);  free(Ac); 
+                Py_END_ALLOW_THREADS
+                free(ipivc);  free(Ac);
             }
-            free(work);   
+            free(work);
             break;
 
         case COMPLEX:
@@ -2970,23 +2998,23 @@ static PyObject* hesv(PyObject *self, PyObject *args, PyObject *kwrds)
             if (!(work = (void *) calloc(lwork, sizeof(complex))))
                 return PyErr_NoMemory();
             if (ipiv) {
-#if (SIZEOF_INT < SIZEOF_LONG)			
-                if (!(ipivc = (int *) calloc(n,sizeof(int)))){ 	
+#if (SIZEOF_INT < SIZEOF_LONG)
+                if (!(ipivc = (int *) calloc(n,sizeof(int)))){
                     free(work);
-                    return PyErr_NoMemory();			
+                    return PyErr_NoMemory();
                 }
                 for (k=0; k<n; k++) ipivc[k] = MAT_BUFI(ipiv)[k];
-#else 
-                ipivc = MAT_BUFI(ipiv);		
+#else
+                ipivc = MAT_BUFI(ipiv);
 #endif
-                Py_BEGIN_ALLOW_THREADS	    
-                zhesv_(&uplo, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, ipivc, 
+                Py_BEGIN_ALLOW_THREADS
+                zhesv_(&uplo, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, ipivc,
                     MAT_BUFZ(B)+oB, &ldB, (complex *) work, &lwork, &info);
-                Py_END_ALLOW_THREADS	    
-#if (SIZEOF_INT < SIZEOF_LONG) 
+                Py_END_ALLOW_THREADS
+#if (SIZEOF_INT < SIZEOF_LONG)
                 for (k=0; k<n; k++) MAT_BUFI(ipiv)[k] = ipivc[k];
-                free(ipivc); 
-#endif 
+                free(ipivc);
+#endif
             }
             else {
                 ipivc = (int *) calloc(n, sizeof(int));
@@ -2995,16 +3023,16 @@ static PyObject* hesv(PyObject *self, PyObject *args, PyObject *kwrds)
                     free(work);  free(ipivc);  free(Ac);
                     return PyErr_NoMemory();
                 }
-                for (k=0; k<n; k++) 
-                    memcpy((complex *) Ac + k*n, MAT_BUFZ(A) + oA + k*ldA, 
+                for (k=0; k<n; k++)
+                    memcpy((complex *) Ac + k*n, MAT_BUFZ(A) + oA + k*ldA,
                         n*sizeof(complex));
-                Py_BEGIN_ALLOW_THREADS	    
-                zhesv_(&uplo, &n, &nrhs, (complex *) Ac, &n, ipivc, 
+                Py_BEGIN_ALLOW_THREADS
+                zhesv_(&uplo, &n, &nrhs, (complex *) Ac, &n, ipivc,
                     MAT_BUFZ(B)+oB, &ldB, work, &lwork, &info);
-                Py_END_ALLOW_THREADS	    
-                free(ipivc);  free(Ac); 
+                Py_END_ALLOW_THREADS
+                free(ipivc);  free(Ac);
             }
-            free(work);   
+            free(work);
             break;
 
         default:
@@ -3022,7 +3050,7 @@ static char doc_trtrs[] =
     "trtrs(A, B, uplo='L', trans='N', diag='N', n=A.size[0],\n"
     "      nrhs=B.size[1], ldA=max(1,A.size[0]), ldB=max(1,B.size[0]),\n"
     "      offsetA=0, offsetB=0)\n\n"
-    "PURPOSE\n"   
+    "PURPOSE\n"
     "If trans is 'N', solves A*X = B.\n"
     "If trans is 'T', solves A^T*X = B.\n"
     "If trans is 'C', solves A^H*X = B.\n"
@@ -3038,7 +3066,7 @@ static char doc_trtrs[] =
     "nrhs      nonnegative integer.  If negative, the default value is\n"
     "          used.\n\n"
     "ldA       positive integer.  ldA >= max(1,n).  If zero, the default\n"
-    "          value is used.\n\n" 
+    "          value is used.\n\n"
     "ldB       positive integer.  ldB >= max(1,n).  If zero, the default\n"
     "          value is used.\n\n"
     "offsetA   nonnegative integer\n\n"
@@ -3049,11 +3077,11 @@ static PyObject* trtrs(PyObject *self, PyObject *args, PyObject *kwrds)
     matrix *A, *B;
     int n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info;
     char uplo='L', trans='N', diag='N';
-    char *kwlist[] = {"A", "B", "uplo", "trans", "diag", "n", "nrhs", 
+    char *kwlist[] = {"A", "B", "uplo", "trans", "diag", "n", "nrhs",
         "ldA", "ldB", "offsetA", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiiii", kwlist, 
-        &A, &B, &uplo, &trans, &diag, &n, &nrhs, &ldA, &ldB, &oA, &oB)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiiii", kwlist,
+        &A, &B, &uplo, &trans, &diag, &n, &nrhs, &ldA, &ldB, &oA, &oB))
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -3061,9 +3089,9 @@ static PyObject* trtrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (MAT_ID(A) != MAT_ID(B)) err_conflicting_ids;
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (diag != 'N' && diag != 'U') err_char("diag", "'N', 'U'");
-    if (trans != 'N' && trans != 'T' && trans != 'C') 
+    if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N', 'T', 'C'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (A->nrows != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -3078,23 +3106,23 @@ static PyObject* trtrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldB < MAX(1,n)) err_ld("ldB");
     if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
-    if (oB < 0) err_nn_int("offsetB"); 
+    if (oB < 0) err_nn_int("offsetB");
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
 
     switch (MAT_ID(A)){
         case DOUBLE:
             if (trans == 'C') trans = 'T';
-            Py_BEGIN_ALLOW_THREADS	    
-            dtrtrs_(&uplo, &trans, &diag, &n, &nrhs, MAT_BUFD(A)+oA, 
+            Py_BEGIN_ALLOW_THREADS
+            dtrtrs_(&uplo, &trans, &diag, &n, &nrhs, MAT_BUFD(A)+oA,
                 &ldA, MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            ztrtrs_(&uplo, &trans, &diag, &n, &nrhs, MAT_BUFZ(A)+oA, 
+            Py_BEGIN_ALLOW_THREADS
+            ztrtrs_(&uplo, &trans, &diag, &n, &nrhs, MAT_BUFZ(A)+oA,
                 &ldA, MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -3108,9 +3136,9 @@ static PyObject* trtrs(PyObject *self, PyObject *args, PyObject *kwrds)
 
 static char doc_trtri[] =
     "Inverse of a triangular matrix.\n\n"
-    "trtri(A, uplo='L', diag='N', n=A.size[0], ldA=max(1,A.size[0]),\n" 
+    "trtri(A, uplo='L', diag='N', n=A.size[0], ldA=max(1,A.size[0]),\n"
     "      offsetA=0)\n\n"
-    "PURPOSE\n"   
+    "PURPOSE\n"
     "Computes the inverse of a triangular matrix of order n.\n"
     "On exit, A is replaced with its inverse.\n\n"
     "ARGUMENTS\n"
@@ -3120,7 +3148,7 @@ static char doc_trtri[] =
     "n         nonnegative integer.  If negative, the default value is\n"
     "          used.\n\n"
     "ldA       positive integer.  ldA >= max(1,n).  If zero, the default\n"
-    "          value is used.\n\n" 
+    "          value is used.\n\n"
     "offsetA   nonnegative integer";
 
 static PyObject* trtri(PyObject *self, PyObject *args, PyObject *kwrds)
@@ -3130,13 +3158,13 @@ static PyObject* trtri(PyObject *self, PyObject *args, PyObject *kwrds)
     char uplo='L', diag='N';
     char *kwlist[] = {"A", "uplo", "diag", "n", "ldA", "offsetA", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|cciii", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|cciii", kwlist,
         &A, &uplo, &diag, &n, &ldA, &oA)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (diag != 'N' && diag != 'U') err_char("diag", "'N', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (A->nrows != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -3151,15 +3179,15 @@ static PyObject* trtri(PyObject *self, PyObject *args, PyObject *kwrds)
 
     switch (MAT_ID(A)){
         case DOUBLE:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dtrtri_(&uplo, &diag, &n, MAT_BUFD(A)+oA, &ldA, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             ztrtri_(&uplo, &diag, &n, MAT_BUFZ(A)+oA, &ldA, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -3177,7 +3205,7 @@ static char doc_tbtrs[] =
     "tbtrs(A, B, uplo='L', trans='N', diag='N', n=A.size[1], \n"
     "      kd=A.size[0]-1, nrhs=B.size[1], ldA=max(1,A.size[0]),\n"
     "      ldB=max(1,B.size[0]), offsetA=0, offsetB=0)\n\n"
-    "PURPOSE\n"   
+    "PURPOSE\n"
     "If trans is 'N', solves A*X = B.\n"
     "If trans is 'T', solves A^T*X = B.\n"
     "If trans is 'C', solves A^H*X = B.\n"
@@ -3196,7 +3224,7 @@ static char doc_tbtrs[] =
     "nrhs      nonnegative integer.  If negative, the default value is\n"
     "          used.\n\n"
     "ldA       positive integer.  ldA >= kd+1.  If zero, the default\n"
-    "          value is used.\n\n" 
+    "          value is used.\n\n"
     "ldB       positive integer.  ldB >= max(1,n).  If zero, the default\n"
     "          value is used.\n\n"
     "offsetA   nonnegative integer\n\n"
@@ -3210,9 +3238,9 @@ static PyObject* tbtrs(PyObject *self, PyObject *args, PyObject *kwrds)
     char *kwlist[] = {"A", "B", "uplo", "trans", "diag", "n", "kd", "nrhs",
         "ldA", "ldB", "offsetA", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiiiii", kwlist, 
-        &A, &B, &uplo, &trans, &diag, &n, &kd, &nrhs, &ldA, &ldB, &oA, 
-        &oB)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccciiiiiii", kwlist,
+        &A, &B, &uplo, &trans, &diag, &n, &kd, &nrhs, &ldA, &ldB, &oA,
+        &oB))
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -3220,7 +3248,7 @@ static PyObject* tbtrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (MAT_ID(A) != MAT_ID(B)) err_conflicting_ids;
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
     if (diag != 'N' && diag != 'U') err_char("diag", "'N', 'U'");
-    if (trans != 'N' && trans != 'T' && trans != 'C') 
+    if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N', 'T', 'C'");
     if (n < 0) n = A->ncols;
     if (kd < 0) kd = A->nrows - 1;
@@ -3233,23 +3261,23 @@ static PyObject* tbtrs(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldB < MAX(1,n)) err_ld("ldB");
     if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + kd + 1 > len(A)) err_buf_len("A");
-    if (oB < 0) err_nn_int("offsetB"); 
+    if (oB < 0) err_nn_int("offsetB");
     if (oB + (nrhs-1)*ldB + n > len(B)) err_buf_len("B");
 
     switch (MAT_ID(A)){
         case DOUBLE:
             if (trans == 'C') trans = 'T';
-            Py_BEGIN_ALLOW_THREADS	    
-            dtbtrs_(&uplo, &trans, &diag, &n, &kd, &nrhs, MAT_BUFD(A)+oA, 
+            Py_BEGIN_ALLOW_THREADS
+            dtbtrs_(&uplo, &trans, &diag, &n, &kd, &nrhs, MAT_BUFD(A)+oA,
                 &ldA, MAT_BUFD(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         case COMPLEX:
-            Py_BEGIN_ALLOW_THREADS	    
-            ztbtrs_(&uplo, &trans, &diag, &n, &kd, &nrhs, MAT_BUFZ(A)+oA, 
+            Py_BEGIN_ALLOW_THREADS
+            ztbtrs_(&uplo, &trans, &diag, &n, &kd, &nrhs, MAT_BUFZ(A)+oA,
                 &ldA, MAT_BUFZ(B)+oB, &ldB, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             break;
 
         default:
@@ -3261,16 +3289,16 @@ static PyObject* tbtrs(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_gels[] = 
+static char doc_gels[] =
     "Solves least-squares and least-norm problems with full rank\n"
     "matrices.\n\n"
     "gels(A, B, trans='N', m=A.size[0], n=A.size[1], nrhs=B.size[1],\n"
     "     ldA=max(1,A.size[0]), ldB=max(1,B.size[0]), offsetA=0,\n"
     "     offsetB=0)\n\n"
-    "PURPOSE\n" 
+    "PURPOSE\n"
     "1. If trans is 'N' and A and B are real/complex:\n"
-    "- if m >= n: minimizes ||A*X - B||_F.\n" 
-    "- if m < n: minimizes ||X||_F subject to A*X = B.\n\n" 
+    "- if m >= n: minimizes ||A*X - B||_F.\n"
+    "- if m < n: minimizes ||X||_F subject to A*X = B.\n\n"
     "2. If trans is 'N' or 'C' and A and B are real:\n"
     "- if m >= n: minimizes ||X||_F subject to A^T*X = B.\n"
     "- if m < n: minimizes ||X||_F subject to A^T*X = B.\n\n"
@@ -3298,16 +3326,16 @@ static char doc_gels[] =
 
 static PyObject* gels(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B; 
-    int m=-1, n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info, lwork; 
-    void *work; 
+    matrix *A, *B;
+    int m=-1, n=-1, nrhs=-1, ldA=0, ldB=0, oA=0, oB=0, info, lwork;
+    void *work;
     number wl;
     char trans='N';
     char *kwlist[] = {"A", "B", "trans", "m", "n", "nrhs", "ldA", "ldB",
         "offsetA", "offsetB", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiiii", 
-        kwlist, &A, &B, &trans, &m, &n, &nrhs, &ldA, &ldB, &oA, &oB)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiiii",
+        kwlist, &A, &B, &trans, &m, &n, &nrhs, &ldA, &ldB, &oA, &oB))
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -3320,47 +3348,47 @@ static PyObject* gels(PyObject *self, PyObject *args, PyObject *kwrds)
     if (nrhs < 0) nrhs = B->ncols;
     if (m == 0 || n == 0 || nrhs == 0) return Py_BuildValue("");
     if (ldA == 0) ldA = MAX(1,A->nrows);
-    if (ldA < MAX(1,m)) err_ld("ldA"); 
+    if (ldA < MAX(1,m)) err_ld("ldA");
     if (ldB == 0) ldB = MAX(1,B->nrows);
     if (ldB < MAX(MAX(1,n),m)) err_ld("ldB");
-    if (oA < 0) err_nn_int("offsetA");  
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + m > len(A)) err_buf_len("A");
     if (oB < 0) err_nn_int("offsetB");
-    if (oB + (nrhs-1)*ldB + ((trans == 'N') ? m : n) > len(B))
+    if (oB + (nrhs-1)*ldB + ((trans == 'N') ? n : m) > len(B))
         err_buf_len("B");
 
     switch (MAT_ID(A)){
         case DOUBLE:
             if (trans == 'C') trans = 'T';
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dgels_(&trans, &m, &n, &nrhs, NULL, &ldA, NULL, &ldB, &wl.d,
                 &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = (void *) calloc(lwork, sizeof(double))))
                 return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-            dgels_(&trans, &m, &n, &nrhs, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dgels_(&trans, &m, &n, &nrhs, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(B)+oB, &ldB, (double *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
 	    break;
 
         case COMPLEX:
             if (trans == 'T') err_char("trans", "'N', 'C'");
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zgels_(&trans, &m, &n, &nrhs, NULL, &ldA, NULL, &ldB, &wl.z,
                 &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
             if (!(work = (void *) calloc(lwork, sizeof(complex))))
                 return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-            zgels_(&trans, &m, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            zgels_(&trans, &m, &n, &nrhs, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFZ(B)+oB, &ldB, (complex *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
 	    break;
 
@@ -3373,14 +3401,14 @@ static PyObject* gels(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_geqrf[] = 
+static char doc_geqrf[] =
     "QR factorization.\n\n"
     "geqrf(A, tau, m=A.size[0], n=A.size[1], ldA=max(1,A.size[0]),\n"
     "      offsetA=0)\n\n"
-    "PURPOSE\n" 
-    "QR factorization of an m by n real or complex matrix A:\n"
-    "A = Q*R = [Q1 Q2] * [R1; 0] if m >= n\n" 
-    "A = Q*R = Q * [R1 R2] if m <= n,\n"
+    "PURPOSE\n"
+    "QR factorization of an m by n real or complex matrix A:\n\n"
+    "A = Q*R = [Q1 Q2] * [R1; 0] if m >= n\n"
+    "A = Q*R = Q * [R1 R2] if m <= n,\n\n"
     "where Q is m by m and orthogonal/unitary and R is m by n with R1\n"
     "upper triangular.  On exit, R is stored in the upper triangular\n"
     "part of A.  Q is stored as a product of k=min(m,n) elementary\n"
@@ -3399,14 +3427,14 @@ static char doc_geqrf[] =
 
 static PyObject* geqrf(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *tau; 
-    int m=-1, n=-1, ldA=0, oA=0, info, lwork; 
-    void *work; 
+    matrix *A, *tau;
+    int m=-1, n=-1, ldA=0, oA=0, info, lwork;
+    void *work;
     number wl;
     char *kwlist[] = {"A", "tau", "m", "n", "ldA", "offsetA", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiii", kwlist, 
-        &A, &tau, &m, &n, &ldA, &oA)) 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiii", kwlist,
+        &A, &tau, &m, &n, &ldA, &oA))
         return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -3416,39 +3444,39 @@ static PyObject* geqrf(PyObject *self, PyObject *args, PyObject *kwrds)
     if (n < 0) n = A->ncols;
     if (m == 0 || n == 0) return Py_BuildValue("");
     if (ldA == 0) ldA = MAX(1,A->nrows);
-    if (ldA < MAX(1,m)) err_ld("ldA"); 
-    if (oA < 0) err_nn_int("offsetA");  
+    if (ldA < MAX(1,m)) err_ld("ldA");
+    if (oA < 0) err_nn_int("offsetA");
     if (oA + (n-1)*ldA + m > len(A)) err_buf_len("A");
     if (len(tau) < MIN(m,n)) err_buf_len("tau");
 
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dgeqrf_(&m, &n, NULL, &ldA, NULL, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = (void *) calloc(lwork, sizeof(double))))
                 return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-            dgeqrf_(&m, &n, MAT_BUFD(A)+oA, &ldA, MAT_BUFD(tau), 
+            Py_BEGIN_ALLOW_THREADS
+            dgeqrf_(&m, &n, MAT_BUFD(A)+oA, &ldA, MAT_BUFD(tau),
                 (double *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
 	    break;
 
         case COMPLEX:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zgeqrf_(&m, &n, NULL, &ldA, NULL, &wl.z, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
             if (!(work = (void *) calloc(lwork, sizeof(complex))))
                 return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-            zgeqrf_(&m, &n, MAT_BUFZ(A)+oA, &ldA, MAT_BUFZ(tau), 
+            Py_BEGIN_ALLOW_THREADS
+            zgeqrf_(&m, &n, MAT_BUFZ(A)+oA, &ldA, MAT_BUFZ(tau),
                 (complex *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
 	    break;
 
@@ -3461,12 +3489,12 @@ static PyObject* geqrf(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_ormqr[] = 
+static char doc_ormqr[] =
     "Product with a real orthogonal matrix.\n\n"
     "ormqr(A, tau, C, side='L', trans='N', m=C.size[0], n=C.size[1],\n"
-    "      k=min(A.size), ldA=max(1,A.size[0]), ldC=max(1,C.size[0]),\n"
+    "      k=len(tau), ldA=max(1,A.size[0]), ldC=max(1,C.size[0]),\n"
     "      offsetA=0, offsetC=0)\n\n"
-    "PURPOSE\n" 
+    "PURPOSE\n"
     "Computes\n"
     "C := Q*C   if side = 'L' and trans = 'N'.\n"
     "C := Q^T*C if side = 'L' and trans = 'T'.\n"
@@ -3484,7 +3512,8 @@ static char doc_ormqr[] =
     "trans     'N' or 'T'\n\n"
     "m         integer.  If negative, the default value is used.\n\n"
     "n         integer.  If negative, the default value is used.\n\n"
-    "k         integer.  If negative, the default value is used.\n\n"
+    "k         integer.  k <= m if side = 'R' and k <= n if side = 'L'.\n"
+    "          If negative, the default value is used.\n\n"
     "ldA       nonnegative integer.  ldA >= max(1,m) if side = 'L'\n"
     "          and ldA >= max(1,n) if side = 'R'.  If zero, the\n"
     "          default value is used.\n\n"
@@ -3495,37 +3524,36 @@ static char doc_ormqr[] =
 
 static PyObject* ormqr(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *tau, *C; 
-    int m=-1, n=-1, k=-1, ldA=0, ldC=0, oA=0, oC=0, info, lwork; 
-    void *work; 
+    matrix *A, *tau, *C;
+    int m=-1, n=-1, k=-1, ldA=0, ldC=0, oA=0, oC=0, info, lwork;
+    void *work;
     number wl;
     char side='L', trans='N';
-    char *kwlist[] = {"A", "tau", "C", "side", "trans", "m", "n", "k", 
+    char *kwlist[] = {"A", "tau", "C", "side", "trans", "m", "n", "k",
         "ldA", "ldC", "offsetA", "offsetC", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cciiiiiii", 
-        kwlist, &A, &tau, &C, &side, &trans, &m, &n, &k, &ldA, &ldC, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cciiiiiii",
+        kwlist, &A, &tau, &C, &side, &trans, &m, &n, &k, &ldA, &ldC,
         &oA, &oC)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(tau)) err_mtrx("tau");
     if (!Matrix_Check(C)) err_mtrx("C");
-    if (MAT_ID(A) != MAT_ID(tau) || MAT_ID(A) != MAT_ID(C)) 
+    if (MAT_ID(A) != MAT_ID(tau) || MAT_ID(A) != MAT_ID(C))
         err_conflicting_ids;
     if (side != 'L' && side != 'R') err_char("side", "'L', 'R'");
     if (trans != 'N' && trans != 'T') err_char("trans", "'N', 'T'");
     if (m < 0) m = C->nrows;
     if (n < 0) n = C->ncols;
-    if (k < 0) k = MIN(A->nrows, A->ncols);
+    if (k < 0) k = len(tau);
     if (m == 0 || n == 0 || k == 0) return Py_BuildValue("");
     if (k > ((side == 'L') ? m : n)) err_ld("k");
     if (ldA == 0) ldA = MAX(1,A->nrows);
-    if (ldA < ((side == 'L') ? MAX(1,m) : MAX(1,n))) err_ld("ldA"); 
+    if (ldA < ((side == 'L') ? MAX(1,m) : MAX(1,n))) err_ld("ldA");
     if (ldC == 0) ldC = MAX(1,C->nrows);
     if (ldC < MAX(1,m)) err_ld("ldC");
-    if (oA < 0) err_nn_int("offsetA");  
-    if (oA + (k-1)*ldA + ((side == 'L' ) ? m : n) > len(A)) 
-        err_buf_len("A");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + k*ldA  > len(A)) err_buf_len("A");
     if (oC < 0) err_nn_int("offsetC");
     if (oC + (n-1)*ldC + m > len(C)) err_buf_len("C");
     if (len(tau) < k) err_buf_len("tau");
@@ -3533,18 +3561,18 @@ static PyObject* ormqr(PyObject *self, PyObject *args, PyObject *kwrds)
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dormqr_(&side, &trans, &m, &n, &k, NULL, &ldA, NULL, NULL,
                 &ldC, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = (void *) calloc(lwork, sizeof(double))))
                 return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-            dormqr_(&side, &trans, &m, &n, &k, MAT_BUFD(A)+oA, &ldA, 
-                MAT_BUFD(tau), MAT_BUFD(C)+oC, &ldC, (double *) work, 
+            Py_BEGIN_ALLOW_THREADS
+            dormqr_(&side, &trans, &m, &n, &k, MAT_BUFD(A)+oA, &ldA,
+                MAT_BUFD(tau), MAT_BUFD(C)+oC, &ldC, (double *) work,
                 &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
 	    break;
 
@@ -3557,12 +3585,12 @@ static PyObject* ormqr(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_unmqr[] = 
+static char doc_unmqr[] =
     "Product with a real or complex orthogonal matrix.\n\n"
-    "ormqr(A, tau, C, side='L', trans='N', m=C.size[0], n=C.size[1],\n"
-    "      k=min(A.size), ldA=max(1,A.size[0]), ldC=max(1,C.size[0]),\n"
+    "unmqr(A, tau, C, side='L', trans='N', m=C.size[0], n=C.size[1],\n"
+    "      k=len(tau), ldA=max(1,A.size[0]), ldC=max(1,C.size[0]),\n"
     "      offsetA=0, offsetC=0)\n\n"
-    "PURPOSE\n" 
+    "PURPOSE\n"
     "Computes\n"
     "C := Q*C   if side = 'L' and trans = 'N'.\n"
     "C := Q^T*C if side = 'L' and trans = 'T'.\n"
@@ -3580,10 +3608,11 @@ static char doc_unmqr[] =
     "          same type as A.\n\n"
     "C         'd' or 'z' matrix.  Must have the same type as A.\n\n"
     "side      'L' or 'R'\n\n"
-    "trans     'N', 'T' or 'C'n\n"
+    "trans     'N', 'T', or 'C'n\n"
     "m         integer.  If negative, the default value is used.\n\n"
     "n         integer.  If negative, the default value is used.\n\n"
-    "k         integer.  If negative, the default value is used.\n\n"
+    "k         integer.  k <= m if side = 'R' and k <= n if side = 'L'.\n"
+    "          If negative, the default value is used.\n\n"
     "ldA       nonnegative integer.  ldA >= max(1,m) if side = 'L'\n"
     "          and ldA >= max(1,n) if side = 'R'.  If zero, the\n"
     "          default value is used.\n\n"
@@ -3592,27 +3621,488 @@ static char doc_unmqr[] =
     "offsetA   nonnegative integer\n\n"
     "offsetB   nonnegative integer";
 
-static PyObject* unmqr(PyObject *self, PyObject *args, PyObject *kwrds)
+static PyObject* unmqr(PyObject *self, PyObject *args, PyObject *kwrds)
+{
+    matrix *A, *tau, *C;
+    int m=-1, n=-1, k=-1, ldA=0, ldC=0, oA=0, oC=0, info, lwork;
+    void *work;
+    number wl;
+    char side='L', trans='N';
+    char *kwlist[] = {"A", "tau", "C", "side", "trans", "m", "n", "k",
+        "ldA", "ldC", "offsetA", "offsetC", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cciiiiiii",
+        kwlist, &A, &tau, &C, &side, &trans, &m, &n, &k, &ldA, &ldC,
+        &oA, &oC)) return NULL;
+
+    if (!Matrix_Check(A)) err_mtrx("A");
+    if (!Matrix_Check(tau)) err_mtrx("tau");
+    if (!Matrix_Check(C)) err_mtrx("C");
+    if (MAT_ID(A) != MAT_ID(tau) || MAT_ID(A) != MAT_ID(C))
+        err_conflicting_ids;
+    if (side != 'L' && side != 'R') err_char("side", "'L', 'R'");
+    if (trans != 'N' && trans != 'T' && trans != 'C')
+        err_char("trans", "'N', 'T', 'C'");
+    if (m < 0) m = C->nrows;
+    if (n < 0) n = C->ncols;
+    if (k < 0) k = len(tau);
+    if (m == 0 || n == 0 || k == 0) return Py_BuildValue("");
+    if (k > ((side == 'L') ? m : n)) err_ld("k");
+    if (ldA == 0) ldA = MAX(1,A->nrows);
+    if (ldA < ((side == 'L') ? MAX(1,m) : MAX(1,n))) err_ld("ldA");
+    if (ldC == 0) ldC = MAX(1,C->nrows);
+    if (ldC < MAX(1,m)) err_ld("ldC");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + k*ldA > len(A)) err_buf_len("A");
+    if (oC < 0) err_nn_int("offsetC");
+    if (oC + (n-1)*ldC + m > len(C)) err_buf_len("C");
+    if (len(tau) < k) err_buf_len("tau");
+
+    switch (MAT_ID(A)){
+        case DOUBLE:
+            if (trans == 'C') trans = 'T';
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            dormqr_(&side, &trans, &m, &n, &k, NULL, &ldA, NULL, NULL,
+                &ldC, &wl.d, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) wl.d;
+            if (!(work = (void *) calloc(lwork, sizeof(double))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            dormqr_(&side, &trans, &m, &n, &k, MAT_BUFD(A)+oA, &ldA,
+                MAT_BUFD(tau), MAT_BUFD(C)+oC, &ldC, (double *) work,
+                &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        case COMPLEX:
+            if (trans == 'T') err_char("trans", "'N', 'C'");
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            zunmqr_(&side, &trans, &m, &n, &k, NULL, &ldA, NULL, NULL,
+                &ldC, &wl.z, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) creal(wl.z);
+            if (!(work = (void *) calloc(lwork, sizeof(complex))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            zunmqr_(&side, &trans, &m, &n, &k, MAT_BUFZ(A)+oA, &ldA,
+                MAT_BUFZ(tau), MAT_BUFZ(C)+oC, &ldC, (complex *) work,
+                &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        default:
+	    err_invalid_id;
+    }
+
+    if (info) err_lapack
+    else return Py_BuildValue("");
+}
+
+
+static char doc_orgqr[] =
+    "Generate the orthogonal matrix in a QR factorization.\n\n"
+    "ormqr(A, tau, m=A.size[0], n=min(A.size), k=len(tau), \n"
+    "      ldA=max(1,A.size[0]), offsetA=0)\n\n"
+    "PURPOSE\n"
+    "On entry, A and tau contain an m by m orthogonal matrix Q.\n"
+    "Q is defined as a product of k elementary reflectors, stored in the\n"
+    "first k columns of A and in tau, as computed by geqrf().  On exit,\n"
+    "the first n columns of Q are stored in the leading columns of A.\n\n"
+    "ARGUMENTS\n"
+    "A         'd' matrix\n\n"
+    "tau       'd' matrix of length at least k\n\n"
+    "m         integer.  If negative, the default value is used.\n\n"
+    "n         integer.  n <= m.  If negative, the default value is used."
+    "\n\n"
+    "k         integer.  k <= n.  If negative, the default value is \n"
+    "          used.\n\n"
+    "ldA       nonnegative integer.  ldA >= max(1,m).  If zero, the\n"
+    "          default value is used.\n\n"
+    "offsetA   nonnegative integer";
+
+static PyObject* orgqr(PyObject *self, PyObject *args, PyObject *kwrds)
+{
+    matrix *A, *tau;
+    int m=-1, n=-1, k=-1, ldA=0, oA=0, info, lwork;
+    void *work;
+    number wl;
+    char *kwlist[] = {"A", "tau", "m", "n", "k", "ldA", "offsetA", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii", kwlist, &A,
+        &tau, &m, &n, &k, &ldA, &oA)) return NULL;
+
+    if (!Matrix_Check(A)) err_mtrx("A");
+    if (!Matrix_Check(tau)) err_mtrx("tau");
+    if (MAT_ID(A) != MAT_ID(tau)) err_conflicting_ids;
+    if (m < 0) m = A->nrows;
+    if (n < 0) n = MIN(A->nrows, A->ncols);
+    if (n > m) err_ld("n");
+    if (k < 0) k = len(tau);
+    if (k > n) err_ld("k");
+    if (m == 0 || n == 0) return Py_BuildValue("");
+    if (ldA == 0) ldA = MAX(1, A->nrows);
+    if (ldA <  MAX(1, m)) err_ld("ldA");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + n*ldA  > len(A)) err_buf_len("A");
+    if (len(tau) < k) err_buf_len("tau");
+
+    switch (MAT_ID(A)){
+        case DOUBLE:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            dorgqr_(&m, &n, &k, NULL, &ldA, NULL, &wl.d, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) wl.d;
+            if (!(work = (void *) calloc(lwork, sizeof(double))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            dorgqr_(&m, &n, &k, MAT_BUFD(A) + oA, &ldA, MAT_BUFD(tau),
+                (double *) work, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        default:
+	    err_invalid_id;
+    }
+
+    if (info) err_lapack
+    else return Py_BuildValue("");
+}
+
+
+static char doc_ungqr[] =
+    "Generate the orthogonal or unitary matrix in a QR factorization.\n\n"
+    "ungqr(A, tau, m=A.size[0], n=min(A.size), k=len(tau), \n"
+    "      ldA=max(1,A.size[0]), offsetA=0)\n\n"
+    "PURPOSE\n"
+    "On entry, A and tau contain an m by m orthogonal/unitary matrix Q.\n"
+    "Q is defined as a product of k elementary reflectors, stored in the\n"
+    "first k columns of A and in tau, as computed by geqrf().  On exit,\n"
+    "the first n columns of Q are stored in the leading columns of A.\n\n"
+    "ARGUMENTS\n"
+    "A         'd' or 'z' matrix\n\n"
+    "tau       'd' or 'z' matrix of length at least k.  Must have the\n"
+    "          same type as A.\n\n"
+    "m         integer.  If negative, the default value is used.\n\n"
+    "n         integer.  n <= m.  If negative, the default value is used."
+    "\n\n"
+    "k         integer.  k <= n.  If negative, the default value is \n"
+    "          used.\n\n"
+    "ldA       nonnegative integer.  ldA >= max(1,m).  If zero, the\n"
+    "          default value is used.\n\n"
+    "offsetA   nonnegative integer";
+
+static PyObject* ungqr(PyObject *self, PyObject *args, PyObject *kwrds)
+{
+    matrix *A, *tau;
+    int m=-1, n=-1, k=-1, ldA=0, oA=0, info, lwork;
+    void *work;
+    number wl;
+    char *kwlist[] = {"A", "tau", "m", "n", "k", "ldA", "offsetA", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii",
+        kwlist, &A, &tau, &m, &n, &k, &ldA, &oA)) return NULL;
+
+    if (!Matrix_Check(A)) err_mtrx("A");
+    if (!Matrix_Check(tau)) err_mtrx("tau");
+    if (MAT_ID(A) != MAT_ID(tau)) err_conflicting_ids;
+    if (m < 0) m = A->nrows;
+    if (n < 0) n = MIN(A->nrows, A->ncols);
+    if (n > m) err_ld("n");
+    if (k < 0) k = len(tau);
+    if (k > n) err_ld("k");
+    if (m == 0 || n == 0) return Py_BuildValue("");
+    if (ldA == 0) ldA = MAX(1, A->nrows);
+    if (ldA <  MAX(1, m)) err_ld("ldA");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + n*ldA  > len(A)) err_buf_len("A");
+    if (len(tau) < k) err_buf_len("tau");
+
+    switch (MAT_ID(A)){
+        case DOUBLE:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            dorgqr_(&m, &n, &k, NULL, &ldA, NULL, &wl.d, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) wl.d;
+            if (!(work = (void *) calloc(lwork, sizeof(double))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            dorgqr_(&m, &n, &k, MAT_BUFD(A) + oA, &ldA, MAT_BUFD(tau),
+                (double *) work, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        case COMPLEX:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            zungqr_(&m, &n, &k, NULL, &ldA, NULL, &wl.z, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) creal(wl.z);
+            if (!(work = (void *) calloc(lwork, sizeof(complex))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            zungqr_(&m, &n, &k, MAT_BUFZ(A) + oA, &ldA, MAT_BUFZ(tau),
+                (complex *) work, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        default:
+	    err_invalid_id;
+    }
+
+    if (info) err_lapack
+    else return Py_BuildValue("");
+}
+
+
+static char doc_gelqf[] =
+    "LQ factorization.\n\n"
+    "gelqf(A, tau, m=A.size[0], n=A.size[1], ldA=max(1,A.size[0]),\n"
+    "      offsetA=0)\n\n"
+    "PURPOSE\n"
+    "LQ factorization of an m by n real or complex matrix A:\n\n"
+    "A = L*Q = [L1; 0] * [Q1; Q2] if m <= n\n"
+    "A = L*Q = [L1; L2] * Q if m >= n,\n\n"
+    "where Q is n by n and orthogonal/unitary and L is m by n with L1\n"
+    "lower triangular.  On exit, L is stored in the lower triangular\n"
+    "part of A.  Q is stored as a product of k=min(m,n) elementary\n"
+    "reflectors.  The parameters of the reflectors are stored in the\n"
+    "first k entries of tau and in the upper  triangular part of the\n"
+    "first k rows of A.\n\n"
+    "ARGUMENTS\n"
+    "A         'd' or 'z' matrix\n\n"
+    "tau       'd' or 'z' matrix of length at least min(m,n).  Must\n"
+    "          have the same type as A.\n\n"
+    "m         integer.  If negative, the default value is used.\n\n"
+    "n         integer.  If negative, the default value is used.\n\n"
+    "ldA       nonnegative integer.  ldA >= max(1,m).  If zero, the\n"
+    "          default value is used.\n\n"
+    "offsetA   nonnegative integer";
+
+static PyObject* gelqf(PyObject *self, PyObject *args, PyObject *kwrds)
+{
+    matrix *A, *tau;
+    int m=-1, n=-1, ldA=0, oA=0, info, lwork;
+    void *work;
+    number wl;
+    char *kwlist[] = {"A", "tau", "m", "n", "ldA", "offsetA", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiii", kwlist,
+        &A, &tau, &m, &n, &ldA, &oA))
+        return NULL;
+
+    if (!Matrix_Check(A)) err_mtrx("A");
+    if (!Matrix_Check(tau)) err_mtrx("tau");
+    if (MAT_ID(A) != MAT_ID(tau)) err_conflicting_ids;
+    if (m < 0) m = A->nrows;
+    if (n < 0) n = A->ncols;
+    if (m == 0 || n == 0) return Py_BuildValue("");
+    if (ldA == 0) ldA = MAX(1,A->nrows);
+    if (ldA < MAX(1,m)) err_ld("ldA");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + (n-1)*ldA + m > len(A)) err_buf_len("A");
+    if (len(tau) < MIN(m,n)) err_buf_len("tau");
+
+    switch (MAT_ID(A)){
+        case DOUBLE:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            dgelqf_(&m, &n, NULL, &ldA, NULL, &wl.d, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) wl.d;
+            if (!(work = (void *) calloc(lwork, sizeof(double))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            dgelqf_(&m, &n, MAT_BUFD(A)+oA, &ldA, MAT_BUFD(tau),
+                (double *) work, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        case COMPLEX:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            zgelqf_(&m, &n, NULL, &ldA, NULL, &wl.z, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) creal(wl.z);
+            if (!(work = (void *) calloc(lwork, sizeof(complex))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            zgelqf_(&m, &n, MAT_BUFZ(A)+oA, &ldA, MAT_BUFZ(tau),
+                (complex *) work, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        default:
+	    err_invalid_id;
+    }
+
+    if (info) err_lapack
+    else return Py_BuildValue("");
+}
+
+
+static char doc_ormlq[] =
+    "Product with a real orthogonal matrix.\n\n"
+    "ormlq(A, tau, C, side='L', trans='N', m=C.size[0], n=C.size[1],\n"
+    "      k=min(A.size), ldA=max(1,A.size[0]), ldC=max(1,C.size[0]),\n"
+    "      offsetA=0, offsetC=0)\n\n"
+    "PURPOSE\n"
+    "Computes\n"
+    "C := Q*C   if side = 'L' and trans = 'N'.\n"
+    "C := Q^T*C if side = 'L' and trans = 'T'.\n"
+    "C := C*Q   if side = 'R' and trans = 'N'.\n"
+    "C := C*Q^T if side = 'R' and trans = 'T'.\n"
+    "C is m by n and Q is a square orthogonal matrix computed by gelqf."
+    "\n"
+    "Q is defined as a product of k elementary reflectors, stored as\n"
+    "the first k rows of A and the first k entries of tau.\n\n"
+    "ARGUMENTS\n"
+    "A         'd' matrix\n\n"
+    "tau       'd' matrix of length at least k\n\n"
+    "C         'd' matrix\n\n"
+    "side      'L' or 'R'\n\n"
+    "trans     'N' or 'T'\n\n"
+    "m         integer.  If negative, the default value is used.\n\n"
+    "n         integer.  If negative, the default value is used.\n\n"
+    "k         integer.  k <= m if side = 'L' and k <= n if side = 'R'.\n"
+    "          If negative, the default value is used.\n\n"
+    "ldA       nonnegative integer.  ldA >= max(1,k).  If zero, the\n"
+    "          default value is used.\n\n"
+    "ldC       nonnegative integer.  ldC >= max(1,m).  If zero, the\n"
+    "          default value is used.\n\n"
+    "offsetA   nonnegative integer\n\n"
+    "offsetB   nonnegative integer";
+
+static PyObject* ormlq(PyObject *self, PyObject *args, PyObject *kwrds)
+{
+    matrix *A, *tau, *C;
+    int m=-1, n=-1, k=-1, ldA=0, ldC=0, oA=0, oC=0, info, lwork;
+    void *work;
+    number wl;
+    char side='L', trans='N';
+    char *kwlist[] = {"A", "tau", "C", "side", "trans", "m", "n", "k",
+        "ldA", "ldC", "offsetA", "offsetC", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cciiiiiii",
+        kwlist, &A, &tau, &C, &side, &trans, &m, &n, &k, &ldA, &ldC,
+        &oA, &oC)) return NULL;
+
+    if (!Matrix_Check(A)) err_mtrx("A");
+    if (!Matrix_Check(tau)) err_mtrx("tau");
+    if (!Matrix_Check(C)) err_mtrx("C");
+    if (MAT_ID(A) != MAT_ID(tau) || MAT_ID(A) != MAT_ID(C))
+        err_conflicting_ids;
+    if (side != 'L' && side != 'R') err_char("side", "'L', 'R'");
+    if (trans != 'N' && trans != 'T') err_char("trans", "'N', 'T'");
+    if (m < 0) m = C->nrows;
+    if (n < 0) n = C->ncols;
+    if (k < 0) k = MIN(A->nrows, A->ncols);
+    if (m == 0 || n == 0 || k == 0) return Py_BuildValue("");
+    if (k > ((side == 'L') ? m : n)) err_ld("k");
+    if (ldA == 0) ldA = MAX(1,A->nrows);
+    if (ldA < MAX(1,k)) err_ld("ldA");
+    if (ldC == 0) ldC = MAX(1,C->nrows);
+    if (ldC < MAX(1,m)) err_ld("ldC");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + ldA * ((side == 'L') ? m : n) > len(A)) err_buf_len("A");
+    if (oC < 0) err_nn_int("offsetC");
+    if (oC + (n-1)*ldC + m > len(C)) err_buf_len("C");
+    if (len(tau) < k) err_buf_len("tau");
+
+    switch (MAT_ID(A)){
+        case DOUBLE:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            dormlq_(&side, &trans, &m, &n, &k, NULL, &ldA, NULL, NULL,
+                &ldC, &wl.d, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) wl.d;
+            if (!(work = (void *) calloc(lwork, sizeof(double))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            dormlq_(&side, &trans, &m, &n, &k, MAT_BUFD(A)+oA, &ldA,
+                MAT_BUFD(tau), MAT_BUFD(C)+oC, &ldC, (double *) work,
+                &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        default:
+	    err_invalid_id;
+    }
+
+    if (info) err_lapack
+    else return Py_BuildValue("");
+}
+
+
+static char doc_unmlq[] =
+    "Product with a real or complex orthogonal matrix.\n\n"
+    "unmlq(A, tau, C, side='L', trans='N', m=C.size[0], n=C.size[1],\n"
+    "      k=min(A.size), ldA=max(1,A.size[0]), ldC=max(1,C.size[0]),\n"
+    "      offsetA=0, offsetC=0)\n\n"
+    "PURPOSE\n"
+    "Computes\n"
+    "C := Q*C   if side = 'L' and trans = 'N'.\n"
+    "C := Q^T*C if side = 'L' and trans = 'T'.\n"
+    "C := Q^H*C if side = 'L' and trans = 'C'.\n"
+    "C := C*Q   if side = 'R' and trans = 'N'.\n"
+    "C := C*Q^T if side = 'R' and trans = 'T'.\n"
+    "C := C*Q^H if side = 'R' and trans = 'C'.\n"
+    "C is m by n and Q is a square orthogonal/unitary matrix computed\n"
+    "by gelqf.  Q is defined as a product of k elementary reflectors,\n"
+    "stored as the first k rows of A and the first k entries of tau."
+    "\n\n"
+    "ARGUMENTS\n"
+    "A         'd' or 'z' matrix\n\n"
+    "tau       'd' or 'z' matrix of length at least k.  Must have the\n"
+    "          same type as A.\n\n"
+    "C         'd' or 'z' matrix.  Must have the same type as A.\n\n"
+    "side      'L' or 'R'\n\n"
+    "trans     'N', 'T', or 'C'n\n"
+    "m         integer.  If negative, the default value is used.\n\n"
+    "n         integer.  If negative, the default value is used.\n\n"
+    "k         integer.  k <= m if side = 'R' and k <= n if side = 'L'.\n"
+    "          If negative, the default value is used.\n\n"
+    "ldA       nonnegative integer.  ldA >= max(1,k).  If zero, the\n"
+    "          default value is used.\n\n"
+    "ldC       nonnegative integer.  ldC >= max(1,m).  If zero, the\n"
+    "          default value is used.\n\n"
+    "offsetA   nonnegative integer\n\n"
+    "offsetB   nonnegative integer";
+
+static PyObject* unmlq(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *tau, *C; 
-    int m=-1, n=-1, k=-1, ldA=0, ldC=0, oA=0, oC=0, info, lwork; 
-    void *work; 
+    matrix *A, *tau, *C;
+    int m=-1, n=-1, k=-1, ldA=0, ldC=0, oA=0, oC=0, info, lwork;
+    void *work;
     number wl;
     char side='L', trans='N';
-    char *kwlist[] = {"A", "tau", "C", "side", "trans", "m", "n", "k", 
+    char *kwlist[] = {"A", "tau", "C", "side", "trans", "m", "n", "k",
         "ldA", "ldC", "offsetA", "offsetC", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cciiiiiii", 
-        kwlist, &A, &tau, &C, &side, &trans, &m, &n, &k, &ldA, &ldC, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|cciiiiiii",
+        kwlist, &A, &tau, &C, &side, &trans, &m, &n, &k, &ldA, &ldC,
         &oA, &oC)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(tau)) err_mtrx("tau");
     if (!Matrix_Check(C)) err_mtrx("C");
-    if (MAT_ID(A) != MAT_ID(tau) || MAT_ID(A) != MAT_ID(C)) 
+    if (MAT_ID(A) != MAT_ID(tau) || MAT_ID(A) != MAT_ID(C))
         err_conflicting_ids;
     if (side != 'L' && side != 'R') err_char("side", "'L', 'R'");
-    if (trans != 'N' && trans != 'T' && trans != 'C') 
+    if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N', 'T', 'C'");
     if (m < 0) m = C->nrows;
     if (n < 0) n = C->ncols;
@@ -3620,12 +4110,11 @@ static PyObject* unmqr(PyObject *self, PyObject *args, PyObject *kwrds)
     if (m == 0 || n == 0 || k == 0) return Py_BuildValue("");
     if (k > ((side == 'L') ? m : n)) err_ld("k");
     if (ldA == 0) ldA = MAX(1,A->nrows);
-    if (ldA < ((side == 'L') ? MAX(1,m) : MAX(1,n))) err_ld("ldA"); 
+    if (ldA < MAX(1,k)) err_ld("ldA");
     if (ldC == 0) ldC = MAX(1,C->nrows);
     if (ldC < MAX(1,m)) err_ld("ldC");
-    if (oA < 0) err_nn_int("offsetA");  
-    if (oA + (k-1)*ldA + ((side == 'L' ) ? m : n) > len(A)) 
-        err_buf_len("A");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + ldA * ((side == 'L') ? m : n) > len(A)) err_buf_len("A");
     if (oC < 0) err_nn_int("offsetC");
     if (oC + (n-1)*ldC + m > len(C)) err_buf_len("C");
     if (len(tau) < k) err_buf_len("tau");
@@ -3634,36 +4123,196 @@ static PyObject* unmqr(PyObject *self, PyObject *args, PyObject *kwrds)
         case DOUBLE:
             if (trans == 'C') trans = 'T';
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
-            dormqr_(&side, &trans, &m, &n, &k, NULL, &ldA, NULL, NULL,
+            Py_BEGIN_ALLOW_THREADS
+            dormlq_(&side, &trans, &m, &n, &k, NULL, &ldA, NULL, NULL,
                 &ldC, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = (void *) calloc(lwork, sizeof(double))))
                 return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-            dormqr_(&side, &trans, &m, &n, &k, MAT_BUFD(A)+oA, &ldA, 
-                MAT_BUFD(tau), MAT_BUFD(C)+oC, &ldC, (double *) work, 
+            Py_BEGIN_ALLOW_THREADS
+            dormlq_(&side, &trans, &m, &n, &k, MAT_BUFD(A)+oA, &ldA,
+                MAT_BUFD(tau), MAT_BUFD(C)+oC, &ldC, (double *) work,
                 &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);
 	    break;
 
         case COMPLEX:
             if (trans == 'T') err_char("trans", "'N', 'C'");
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
-            zunmqr_(&side, &trans, &m, &n, &k, NULL, &ldA, NULL, NULL,
+            Py_BEGIN_ALLOW_THREADS
+            zunmlq_(&side, &trans, &m, &n, &k, NULL, &ldA, NULL, NULL,
                 &ldC, &wl.z, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
             if (!(work = (void *) calloc(lwork, sizeof(complex))))
                 return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-            zunmqr_(&side, &trans, &m, &n, &k, MAT_BUFZ(A)+oA, &ldA, 
-                MAT_BUFZ(tau), MAT_BUFZ(C)+oC, &ldC, (complex *) work, 
+            Py_BEGIN_ALLOW_THREADS
+            zunmlq_(&side, &trans, &m, &n, &k, MAT_BUFZ(A)+oA, &ldA,
+                MAT_BUFZ(tau), MAT_BUFZ(C)+oC, &ldC, (complex *) work,
                 &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        default:
+	    err_invalid_id;
+    }
+
+    if (info) err_lapack
+    else return Py_BuildValue("");
+}
+
+
+static char doc_orglq[] =
+    "Generate the orthogonal matrix in an LQ factorization.\n\n"
+    "orglq(A, tau, m=min(A.size), n=A.size[1], k=len(tau), \n"
+    "      ldA=max(1,A.size[0]), offsetA=0)\n\n"
+    "PURPOSE\n"
+    "On entry, A and tau contain an n by n orthogonal matrix Q.\n"
+    "Q is defined as a product of k elementary reflectors, stored in the\n"
+    "first k rows of A and in tau, as computed by gelqf().  On exit,\n"
+    "the first m rows of Q are stored in the leading rows of A.\n\n"
+    "ARGUMENTS\n"
+    "A         'd' matrix\n\n"
+    "tau       'd' matrix of length at least k\n\n"
+    "m         integer.  If negative, the default value is used.\n\n"
+    "n         integer.  n >= m.  If negative, the default value is used."
+    "\n\n"
+    "k         integer.  k <= m.  If negative, the default value is \n"
+    "          used.\n\n"
+    "ldA       nonnegative integer.  ldA >= max(1,m).  If zero, the\n"
+    "          default value is used.\n\n"
+    "offsetA   nonnegative integer";
+
+static PyObject* orglq(PyObject *self, PyObject *args, PyObject *kwrds)
+{
+    matrix *A, *tau;
+    int m=-1, n=-1, k=-1, ldA=0, oA=0, info, lwork;
+    void *work;
+    number wl;
+    char *kwlist[] = {"A", "tau", "m", "n", "k", "ldA", "offsetA", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii", kwlist, &A,
+        &tau, &m, &n, &k, &ldA, &oA)) return NULL;
+
+    if (!Matrix_Check(A)) err_mtrx("A");
+    if (!Matrix_Check(tau)) err_mtrx("tau");
+    if (MAT_ID(A) != MAT_ID(tau)) err_conflicting_ids;
+    if (m < 0) m = MIN(A->nrows, A->ncols);
+    if (n < 0) n = A->ncols;
+    if (m > n) err_ld("n");
+    if (k < 0) k = len(tau);
+    if (k > m) err_ld("k");
+    if (m == 0 || n == 0) return Py_BuildValue("");
+    if (ldA == 0) ldA = MAX(1, A->nrows);
+    if (ldA <  MAX(1, m)) err_ld("ldA");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + n*ldA  > len(A)) err_buf_len("A");
+    if (len(tau) < k) err_buf_len("tau");
+
+    switch (MAT_ID(A)){
+        case DOUBLE:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            dorglq_(&m, &n, &k, NULL, &ldA, NULL, &wl.d, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) wl.d;
+            if (!(work = (void *) calloc(lwork, sizeof(double))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            dorglq_(&m, &n, &k, MAT_BUFD(A) + oA, &ldA, MAT_BUFD(tau),
+                (double *) work, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        default:
+	    err_invalid_id;
+    }
+
+    if (info) err_lapack
+    else return Py_BuildValue("");
+}
+
+
+static char doc_unglq[] =
+    "Generate the orthogonal or unitary matrix in an LQ factorization.\n\n"
+    "unglq(A, tau, m=min(A.size), n=A.size[1], k=len(tau), \n"
+    "      ldA=max(1,A.size[0]), offsetA=0)\n\n"
+    "PURPOSE\n"
+    "On entry, A and tau contain an n by n orthogonal/unitary matrix Q.\n"
+    "Q is defined as a product of k elementary reflectors, stored in the\n"
+    "first k rows of A and in tau, as computed by gelqf().  On exit,\n"
+    "the first m rows of Q are stored in the leading rows of A.\n\n"
+    "ARGUMENTS\n"
+    "A         'd' or 'z' matrix\n\n"
+    "tau       'd' or 'z' matrix of length at least k.  Must have the\n"
+    "          same type as A.\n\n"
+    "m         integer.  If negative, the default value is used.\n\n"
+    "n         integer.  n >= m.  If negative, the default value is used."
+    "\n\n"
+    "k         integer.  k <= m.  If negative, the default value is \n"
+    "          used.\n\n"
+    "ldA       nonnegative integer.  ldA >= max(1,m).  If zero, the\n"
+    "          default value is used.\n\n"
+    "offsetA   nonnegative integer";
+
+static PyObject* unglq(PyObject *self, PyObject *args, PyObject *kwrds)
+{
+    matrix *A, *tau;
+    int m=-1, n=-1, k=-1, ldA=0, oA=0, info, lwork;
+    void *work;
+    number wl;
+    char *kwlist[] = {"A", "tau", "m", "n", "k", "ldA", "offsetA", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iiiii",
+        kwlist, &A, &tau, &m, &n, &k, &ldA, &oA)) return NULL;
+
+    if (!Matrix_Check(A)) err_mtrx("A");
+    if (!Matrix_Check(tau)) err_mtrx("tau");
+    if (MAT_ID(A) != MAT_ID(tau)) err_conflicting_ids;
+    if (m < 0) m = MIN(A->nrows, A->ncols);
+    if (n < 0) n = A->ncols;
+    if (m > n) err_ld("n");
+    if (k < 0) k = len(tau);
+    if (k > m) err_ld("k");
+    if (m == 0 || n == 0) return Py_BuildValue("");
+    if (ldA == 0) ldA = MAX(1, A->nrows);
+    if (ldA <  MAX(1, m)) err_ld("ldA");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + n*ldA  > len(A)) err_buf_len("A");
+    if (len(tau) < k) err_buf_len("tau");
+
+    switch (MAT_ID(A)){
+        case DOUBLE:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            dorglq_(&m, &n, &k, NULL, &ldA, NULL, &wl.d, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) wl.d;
+            if (!(work = (void *) calloc(lwork, sizeof(double))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            dorglq_(&m, &n, &k, MAT_BUFD(A) + oA, &ldA, MAT_BUFD(tau),
+                (double *) work, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        case COMPLEX:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            zunglq_(&m, &n, &k, NULL, &ldA, NULL, &wl.z, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) creal(wl.z);
+            if (!(work = (void *) calloc(lwork, sizeof(complex))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            zunglq_(&m, &n, &k, MAT_BUFZ(A) + oA, &ldA, MAT_BUFZ(tau),
+                (complex *) work, &lwork, &info);
+            Py_END_ALLOW_THREADS
             free(work);
 	    break;
 
@@ -3675,7 +4324,126 @@ static PyObject* unmqr(PyObject *self, PyObject *args, PyObject *kwrds)
     else return Py_BuildValue("");
 }
 
-static char doc_syev[] = 
+
+static char doc_geqp3[] =
+    "QR factorization with column pivoting.\n\n"
+    "geqp3(A, jpvt, tau, m=A.size[0], n=A.size[1], ldA=max(1,A.size[0]),\n"
+    "      offsetA=0)\n\n"
+    "PURPOSE\n"
+    "QR factorization with column pivoting of an m by n real or complex\n"
+    "matrix A:\n\n"
+    "A*P = Q*R = [Q1 Q2] * [R1; 0] if m >= n\n"
+    "A*P = Q*R = Q * [R1 R2] if m <= n,\n\n"
+    "where P is a permutation matrix, Q is m by m and orthogonal/unitary\n"
+    "and R is m by n with R1 upper triangular.  On exit, R is stored in\n"
+    "the upper triangular part of A.  Q is stored as a product of\n"
+    "k=min(m,n) elementary reflectors.  The parameters of the\n"
+    "reflectors are stored in the first k entries of tau and in the\n"
+    "lower triangular part of the first k columns of A.  On entry, if\n"
+    "jpvt[j] is nonzero, the jth column of A is permuted to the front of\n"
+    "A*P.  If jpvt[j] is zero, the jth column is a free column.  On exit\n"
+    "A*P = A[:, jpvt - 1].\n\n"
+    "ARGUMENTS\n"
+    "A         'd' or 'z' matrix\n\n"
+    "jpvt      'i' matrix of length n\n\n"
+    "tau       'd' or 'z' matrix of length min(m,n).  Must have the same\n"
+    "          type as A.\n\n"
+    "m         integer.  If negative, the default value is used.\n\n"
+    "n         integer.  If negative, the default value is used.\n\n"
+    "ldA       nonnegative integer.  ldA >= max(1,m).  If zero, the\n"
+    "          default value is used.\n\n"
+    "offsetA   nonnegative integer";
+
+static PyObject* geqp3(PyObject *self, PyObject *args, PyObject *kwrds)
+{
+    matrix *A, *tau, *jpvt;
+    int m=-1, n=-1, ldA=0, oA=0, info, lwork;
+    double *rwork = NULL;
+    void *work = NULL;
+    number wl;
+    char *kwlist[] = {"A", "jpvt", "tau", "m", "n", "ldA", "offsetA",
+        NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|iiii", kwlist,
+        &A, &jpvt, &tau, &m, &n, &ldA, &oA))
+        return NULL;
+
+    if (!Matrix_Check(A)) err_mtrx("A");
+    if (!Matrix_Check(jpvt) || jpvt ->id != INT) err_int_mtrx("jpvt");
+    if (!Matrix_Check(tau)) err_mtrx("tau");
+    if (MAT_ID(A) != MAT_ID(tau)) err_conflicting_ids;
+    if (m < 0) m = A->nrows;
+    if (n < 0) n = A->ncols;
+    if (m == 0 || n == 0) return Py_BuildValue("");
+    if (ldA == 0) ldA = MAX(1, A->nrows);
+    if (ldA < MAX(1,m)) err_ld("ldA");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + (n-1)*ldA + m > len(A)) err_buf_len("A");
+    if (len(jpvt) < n) err_buf_len("jpvt");
+    if (len(tau) < MIN(m,n)) err_buf_len("tau");
+
+    int i;
+#if (SIZEOF_INT < SIZEOF_LONG)
+    int *jpvt_ptr = malloc(n*sizeof(int));
+    if (!jpvt_ptr) return PyErr_NoMemory();
+    for (i=0; i<n; i++) jpvt_ptr[i] = MAT_BUFI(jpvt)[i];
+#else
+    int *jpvt_ptr = MAT_BUFI(jpvt);
+#endif
+
+    switch (MAT_ID(A)){
+        case DOUBLE:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            dgeqp3_(&m, &n, NULL, &ldA, NULL, NULL, &wl.d, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) wl.d;
+            if (!(work = (void *) calloc(lwork, sizeof(double))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            dgeqp3_(&m, &n, MAT_BUFD(A)+oA, &ldA, jpvt_ptr, MAT_BUFD(tau),
+                (double *) work, &lwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+	    break;
+
+        case COMPLEX:
+            lwork = -1;
+            Py_BEGIN_ALLOW_THREADS
+            zgeqp3_(&m, &n, NULL, &ldA, NULL, NULL, &wl.z, &lwork, NULL,
+                &info);
+            Py_END_ALLOW_THREADS
+            lwork = (int) creal(wl.z);
+            if (!(work = (void *) calloc(lwork, sizeof(complex))) ||
+                !(rwork = (double *) calloc(2*n, sizeof(double))))
+                return PyErr_NoMemory();
+            Py_BEGIN_ALLOW_THREADS
+            zgeqp3_(&m, &n, MAT_BUFZ(A)+oA, &ldA, jpvt_ptr, MAT_BUFZ(tau),
+                (complex *) work, &lwork, rwork, &info);
+            Py_END_ALLOW_THREADS
+            free(work);
+            free(rwork);
+	    break;
+
+        default:
+#if (SIZEOF_INT < SIZEOF_LONG)
+            free(jpvt_ptr);
+#endif
+            err_invalid_id;
+    }
+
+#if (SIZEOF_INT < SIZEOF_LONG)
+    for (i=0; i<n; i++) MAT_BUFI(jpvt)[i] = jpvt_ptr[i];
+    free(jpvt_ptr);
+#endif
+
+    if (info) err_lapack
+    else return Py_BuildValue("");
+}
+
+
+
+static char doc_syev[] =
     "Eigenvalue decomposition of a real symmetric matrix.\n\n"
     "syev(A, W, jobz='N', uplo='L', n=A.size[0], "
     "ldA = max(1,A.size[0]),\n"
@@ -3699,12 +4467,12 @@ static char doc_syev[] =
 
 static PyObject* syev(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *W; 
-    int n=-1, ldA=0, oA=0, oW=0, info, lwork; 
-    double *work; 
-    number wl; 
+    matrix *A, *W;
+    int n=-1, ldA=0, oA=0, oW=0, info, lwork;
+    double *work;
+    number wl;
     char uplo='L', jobz='N';
-    char *kwlist[] = {"A", "W", "jobz", "uplo", "n", "ldA", "offsetA", 
+    char *kwlist[] = {"A", "W", "jobz", "uplo", "n", "ldA", "offsetA",
         "offsetW", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cciiii", kwlist,
@@ -3714,7 +4482,7 @@ static PyObject* syev(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(W) || MAT_ID(W) != DOUBLE) err_dbl_mtrx("W");
     if (jobz != 'N' && jobz != 'V') err_char("jobz", "'N', 'V'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -3732,18 +4500,18 @@ static PyObject* syev(PyObject *self, PyObject *args, PyObject *kwrds)
     switch (MAT_ID(A)){
 	case DOUBLE:
 	    lwork=-1;
-            Py_BEGIN_ALLOW_THREADS	    
-	    dsyev_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl.d, &lwork, 
+            Py_BEGIN_ALLOW_THREADS
+	    dsyev_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl.d, &lwork,
                 &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
 	    lwork = (int) wl.d;
 	    if (!(work = calloc(lwork, sizeof(double))))
 		return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-	    dsyev_(&jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+	    dsyev_(&jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(W)+oW, work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
-	    free(work);   
+            Py_END_ALLOW_THREADS
+	    free(work);
 	    break;
 
         default:
@@ -3755,7 +4523,7 @@ static PyObject* syev(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_heev[] = 
+static char doc_heev[] =
     "Eigenvalue decomposition of a real symmetric or complex Hermitian"
     "\nmatrix.\n\n"
     "heev(A, W, jobz='N', uplo='L', n=A.size[0], "
@@ -3780,13 +4548,13 @@ static char doc_heev[] =
 
 static PyObject* heev(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *W; 
-    int n=-1, ldA=0, oA=0, oW=0, info, lwork; 
+    matrix *A, *W;
+    int n=-1, ldA=0, oA=0, oW=0, info, lwork;
     double *rwork=NULL;
-    void *work=NULL; 
-    number wl; 
+    void *work=NULL;
+    number wl;
     char uplo='L', jobz='N';
-    char *kwlist[] = {"A", "W", "jobz", "uplo", "n", "ldA", "offsetA", 
+    char *kwlist[] = {"A", "W", "jobz", "uplo", "n", "ldA", "offsetA",
         "offsetW", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cciiii", kwlist,
@@ -3796,7 +4564,7 @@ static PyObject* heev(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(W) || MAT_ID(W) != DOUBLE) err_dbl_mtrx("W");
     if (jobz != 'N' && jobz != 'V') err_char("jobz", "'N', 'V'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -3813,26 +4581,26 @@ static PyObject* heev(PyObject *self, PyObject *args, PyObject *kwrds)
     switch (MAT_ID(A)){
 	case DOUBLE:
 	    lwork=-1;
-            Py_BEGIN_ALLOW_THREADS	    
-	    dsyev_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl.d, &lwork, 
+            Py_BEGIN_ALLOW_THREADS
+	    dsyev_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl.d, &lwork,
                 &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
 	    lwork = (int) wl.d;
 	    if (!(work = (void *) calloc(lwork, sizeof(double))))
 		return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-	    dsyev_(&jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+	    dsyev_(&jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(W)+oW, (double *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
-	    free(work);   
+            Py_END_ALLOW_THREADS
+	    free(work);
 	    break;
 
         case COMPLEX:
 	    lwork=-1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
 	    zheev_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl.z, &lwork,
                 NULL, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
 	    lwork = (int) creal(wl.z);
 	    work = (void *) calloc(lwork, sizeof(complex));
 	    rwork = (double *) calloc(3*n-2, sizeof(double));
@@ -3840,11 +4608,11 @@ static PyObject* heev(PyObject *self, PyObject *args, PyObject *kwrds)
 		free(work);  free(rwork);
 		return PyErr_NoMemory();
 	    }
-            Py_BEGIN_ALLOW_THREADS	    
-	    zheev_(&jobz, &uplo, &n, MAT_BUFZ(A)+oA, &ldA, 
-		MAT_BUFD(W)+oW,  (complex *) work, &lwork, rwork, 
+            Py_BEGIN_ALLOW_THREADS
+	    zheev_(&jobz, &uplo, &n, MAT_BUFZ(A)+oA, &ldA,
+		MAT_BUFD(W)+oW,  (complex *) work, &lwork, rwork,
 		&info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
 	    free(work);  free(rwork);
 	    break;
 
@@ -3857,7 +4625,7 @@ static PyObject* heev(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_syevx[] = 
+static char doc_syevx[] =
     "Computes selected eigenvalues and eigenvectors of a real symmetric"
     "\nmatrix (expert driver).\n\n"
     "m = syevx(A, W, jobz='N', range='A', uplo='L', vl=0.0, vu=0.0, \n"
@@ -3873,10 +4641,10 @@ static char doc_syevx[] =
     "If range is 'I', all eigenvalues il through iu are computed\n"
     "(sorted in ascending order with 1 <= il <= iu <= n).\n"
     "If jobz is 'N', only the eigenvalues are returned in W.\n"
-    "If jobz is 'V', the eigenvectors are also returned in Z.\n"  
+    "If jobz is 'V', the eigenvectors are also returned in Z.\n"
     "On exit, the content of A is destroyed.\n\n"
     "ARGUMENTS\n"
-    "A         'd' matrix\n\n"  
+    "A         'd' matrix\n\n"
     "W         'd' matrix of length at least n.  On exit, contains\n"
     "          the computed eigenvalues in ascending order.\n\n"
     "jobz      'N' or 'V'\n\n"
@@ -3905,14 +4673,14 @@ static char doc_syevx[] =
 
 static PyObject* syevx(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *W, *Z=NULL; 
+    matrix *A, *W, *Z=NULL;
     int n=-1, ldA=0, ldZ=0, il=1, iu=1, oA=0, oW=0, oZ=0, info, lwork,
-        *iwork, m, *ifail=NULL; 
-    double *work, vl=0.0, vu=0.0, abstol=0.0; 
+        *iwork, m, *ifail=NULL;
+    double *work, vl=0.0, vu=0.0, abstol=0.0;
     double wl;
     char uplo='L', jobz='N', range='A';
-    char *kwlist[] = {"A", "W", "jobz", "range", "uplo", "vl", "vu", 
-	"il", "iu", "Z", "n", "ldA", "ldZ", "abstol", "offsetA", 
+    char *kwlist[] = {"A", "W", "jobz", "range", "uplo", "vl", "vu",
+	"il", "iu", "Z", "n", "ldA", "ldZ", "abstol", "offsetA",
         "offsetW", "offsetZ", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cccddiiOiiidiii",
@@ -3922,10 +4690,10 @@ static PyObject* syevx(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(W) || MAT_ID(W) != DOUBLE) err_dbl_mtrx("W");
     if (jobz != 'N' && jobz != 'V') err_char("jobz", "'N', 'V'");
-    if (range != 'A' && range != 'V' && range != 'I') 
+    if (range != 'A' && range != 'V' && range != 'I')
 	err_char("range", "'A', 'V', 'I'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -3949,13 +4717,13 @@ static PyObject* syevx(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oW < 0) err_nn_int("offsetW");
     if (oW + n > len(W)) err_buf_len("W");
     if (jobz == 'V'){
-        if (!Z || !Matrix_Check(Z) || MAT_ID(Z) != DOUBLE) 
+        if (!Z || !Matrix_Check(Z) || MAT_ID(Z) != DOUBLE)
             err_dbl_mtrx("Z");
         if (ldZ == 0) ldZ = MAX(1,Z->nrows);
         if (ldZ < MAX(1,n)) err_ld("ldZ");
         if (oZ < 0) err_nn_int("offsetZ");
-        if (oZ + ((range == 'I') ? iu-il : n-1)*ldZ + n > len(Z)) 
-	    err_buf_len("Z"); 
+        if (oZ + ((range == 'I') ? iu-il : n-1)*ldZ + n > len(Z))
+	    err_buf_len("Z");
     } else {
         if (ldZ == 0) ldZ = 1;
         if (ldZ < 1) err_ld("ldZ");
@@ -3964,11 +4732,11 @@ static PyObject* syevx(PyObject *self, PyObject *args, PyObject *kwrds)
     switch (MAT_ID(A)){
         case DOUBLE:
 	    lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
 	    dsyevx_(&jobz, &range, &uplo, &n, NULL, &ldA, &vl, &vu, &il,
                 &iu, &abstol, &m, NULL, NULL, &ldZ, &wl, &lwork, NULL,
 	       	NULL, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
 	    lwork = (int) wl;
 	    work = (double *) calloc(lwork, sizeof(double));
 	    iwork = (int *) calloc(5*n, sizeof(int));
@@ -3977,13 +4745,13 @@ static PyObject* syevx(PyObject *self, PyObject *args, PyObject *kwrds)
 		free(work); free(iwork); free(ifail);
 	        return PyErr_NoMemory();
 	    }
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
 	    dsyevx_(&jobz, &range, &uplo, &n, MAT_BUFD(A)+oA, &ldA, &vl,
-                &vu, &il, &iu, &abstol, &m, MAT_BUFD(W)+oW, 
-		(jobz == 'V') ? MAT_BUFD(Z)+oZ : NULL,  &ldZ, work, 
+                &vu, &il, &iu, &abstol, &m, MAT_BUFD(W)+oW,
+		(jobz == 'V') ? MAT_BUFD(Z)+oZ : NULL,  &ldZ, work,
 		&lwork, iwork, ifail, &info);
-            Py_END_ALLOW_THREADS	    
-	    free(work);   free(iwork);   free(ifail);   
+            Py_END_ALLOW_THREADS
+	    free(work);   free(iwork);   free(ifail);
             break;
 
         default:
@@ -3995,7 +4763,7 @@ static PyObject* syevx(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_heevx[] = 
+static char doc_heevx[] =
     "Computes selected eigenvalues and eigenvectors of a real symmetric"
     "\nor complex Hermitian matrix (expert driver).\n\n"
     "m = syevx(A, W, jobz='N', range='A', uplo='L', vl=0.0, vu=0.0, \n"
@@ -4011,10 +4779,10 @@ static char doc_heevx[] =
     "If range is 'I', all eigenvalues il through iu are computed\n"
     "(sorted in ascending order with 1 <= il <= iu <= n).\n"
     "If jobz is 'N', only the eigenvalues are returned in W.\n"
-    "If jobz is 'V', the eigenvectors are also returned in Z.\n"  
+    "If jobz is 'V', the eigenvectors are also returned in Z.\n"
     "On exit, the content of A is destroyed.\n\n"
     "ARGUMENTS\n"
-    "A         'd' or 'z' matrix\n\n"  
+    "A         'd' or 'z' matrix\n\n"
     "W         'd' matrix of length at least n.  On exit, contains\n"
     "          the computed eigenvalues in ascending order.\n\n"
     "jobz      'N' or 'V'\n\n"
@@ -4044,28 +4812,28 @@ static char doc_heevx[] =
 
 static PyObject* heevx(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *W, *Z=NULL; 
+    matrix *A, *W, *Z=NULL;
     int n=-1, ldA=0, ldZ=0, il=1, iu=1, oA=0, oW=0, oZ=0, info, lwork,
-        *iwork, m, *ifail=NULL; 
-    double vl=0.0, vu=0.0, abstol=0.0, *rwork; 
+        *iwork, m, *ifail=NULL;
+    double vl=0.0, vu=0.0, abstol=0.0, *rwork;
     number wl;
     void *work;
     char uplo='L', jobz='N', range='A';
     char *kwlist[] = {"A", "W", "jobz", "range", "uplo", "vl", "vu",
-	"il", "iu", "Z", "n", "ldA", "ldZ", "abstol", "offsetA", 
+	"il", "iu", "Z", "n", "ldA", "ldZ", "abstol", "offsetA",
         "offsetW", "offsetZ", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cccddiiOiiidiii",
-        kwlist, &A, &W, &jobz, &range, &uplo, &vl, &vu, &il, &iu, &Z, 
+        kwlist, &A, &W, &jobz, &range, &uplo, &vl, &vu, &il, &iu, &Z,
 	&n, &ldA, &ldZ, &abstol, &oA, &oW, &oZ)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(W) || MAT_ID(W) != DOUBLE) err_dbl_mtrx("W");
     if (jobz != 'N' && jobz != 'V') err_char("jobz", "'N', 'V'");
-    if (range != 'A' && range != 'V' && range != 'I') 
+    if (range != 'A' && range != 'V' && range != 'I')
 	err_char("range", "'A', 'V', 'I'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -4090,12 +4858,12 @@ static PyObject* heevx(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oW + n > len(W)) err_buf_len("W");
     if (jobz == 'V'){
         if (!Z || !Matrix_Check(Z)) err_mtrx("Z");
-	if (MAT_ID(Z) != MAT_ID(A)) err_conflicting_ids; 
+	if (MAT_ID(Z) != MAT_ID(A)) err_conflicting_ids;
         if (ldZ == 0) ldZ = MAX(1,Z->nrows);
         if (ldZ < MAX(1,n)) err_ld("ldZ");
         if (oZ < 0) err_nn_int("offsetZ");
-        if (oZ + ((range == 'I') ? iu-il : n-1)*ldZ + n > len(Z)) 
-	    err_buf_len("Z"); 
+        if (oZ + ((range == 'I') ? iu-il : n-1)*ldZ + n > len(Z))
+	    err_buf_len("Z");
     } else {
         if (ldZ == 0) ldZ = 1;
         if (ldZ < 1) err_ld("ldZ");
@@ -4104,11 +4872,11 @@ static PyObject* heevx(PyObject *self, PyObject *args, PyObject *kwrds)
     switch (MAT_ID(A)){
         case DOUBLE:
 	    lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
 	    dsyevx_(&jobz, &range, &uplo, &n, NULL, &ldA, &vl, &vu, &il,
                 &iu, &abstol, &m, NULL, NULL, &ldZ, &wl.d, &lwork, NULL,
 	       	NULL, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
 	    lwork = (int) wl.d;
 	    work = (void *) calloc(lwork, sizeof(double));
 	    iwork = (int *) calloc(5*n, sizeof(int));
@@ -4117,22 +4885,22 @@ static PyObject* heevx(PyObject *self, PyObject *args, PyObject *kwrds)
 		free(work); free(iwork); free(ifail);
 	        return PyErr_NoMemory();
 	    }
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
 	    dsyevx_(&jobz, &range, &uplo, &n, MAT_BUFD(A)+oA, &ldA, &vl,
-                &vu, &il, &iu, &abstol, &m, MAT_BUFD(W)+oW, 
-		(jobz == 'V') ? MAT_BUFD(Z)+oZ : NULL,  &ldZ, 
+                &vu, &il, &iu, &abstol, &m, MAT_BUFD(W)+oW,
+		(jobz == 'V') ? MAT_BUFD(Z)+oZ : NULL,  &ldZ,
 		(double *) work, &lwork, iwork, ifail, &info);
-            Py_END_ALLOW_THREADS	    
-	    free(work);  free(iwork);  free(ifail);   
+            Py_END_ALLOW_THREADS
+	    free(work);  free(iwork);  free(ifail);
             break;
 
 	case COMPLEX:
 	    lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
 	    zheevx_(&jobz, &range, &uplo, &n, NULL, &ldA, &vl, &vu, &il,
                 &iu, &abstol, &m, NULL, NULL, &ldZ, &wl.z, &lwork, NULL,
 	       	NULL, NULL, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
 	    lwork = (int) creal(wl.z);
 	    work = (void *) calloc(lwork, sizeof(complex));
 	    rwork = (double *) calloc(7*n, sizeof(double));
@@ -4142,13 +4910,13 @@ static PyObject* heevx(PyObject *self, PyObject *args, PyObject *kwrds)
 		free(work); free(rwork); free(iwork); free(ifail);
 	        return PyErr_NoMemory();
 	    }
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
 	    zheevx_(&jobz, &range, &uplo, &n, MAT_BUFZ(A)+oA, &ldA, &vl,
-                &vu, &il, &iu, &abstol, &m, MAT_BUFD(W)+oW, 
-		(jobz == 'V') ? MAT_BUFZ(Z)+oZ : NULL,  &ldZ, 
+                &vu, &il, &iu, &abstol, &m, MAT_BUFD(W)+oW,
+		(jobz == 'V') ? MAT_BUFZ(Z)+oZ : NULL,  &ldZ,
 		(complex *) work, &lwork, rwork, iwork, ifail, &info);
-            Py_END_ALLOW_THREADS	    
-	    free(work);  free(rwork);  free(iwork);  free(ifail);   
+            Py_END_ALLOW_THREADS
+	    free(work);  free(rwork);  free(iwork);  free(ifail);
             break;
 
         default:
@@ -4160,7 +4928,7 @@ static PyObject* heevx(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_syevd[] = 
+static char doc_syevd[] =
     "Eigenvalue decomposition of a real symmetric matrix\n"
     "(divide-and-conquer driver).\n\n"
     "syevd(A, W, jobz='N', uplo='L', n=A.size[0], "
@@ -4186,11 +4954,11 @@ static char doc_syevd[] =
 
 static PyObject* syevd(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *W; 
-    int n=-1, ldA=0, oA=0, oW=0, info, lwork, liwork, *iwork, iwl; 
-    double *work=NULL, wl; 
+    matrix *A, *W;
+    int n=-1, ldA=0, oA=0, oW=0, info, lwork, liwork, *iwork, iwl;
+    double *work=NULL, wl;
     char uplo='L', jobz='N';
-    char *kwlist[] = {"A", "W", "jobz", "uplo", "n", "ldA", "offsetA", 
+    char *kwlist[] = {"A", "W", "jobz", "uplo", "n", "ldA", "offsetA",
         "offsetW", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cciiii", kwlist,
@@ -4200,7 +4968,7 @@ static PyObject* syevd(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(W) || W->id != DOUBLE) err_dbl_mtrx("W");
     if (jobz != 'N' && jobz != 'V') err_char("jobz", "'N', 'V'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -4219,10 +4987,10 @@ static PyObject* syevd(PyObject *self, PyObject *args, PyObject *kwrds)
         case DOUBLE:
             lwork = -1;
             liwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
-            dsyevd_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl, &lwork, 
+            Py_BEGIN_ALLOW_THREADS
+            dsyevd_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl, &lwork,
                 &iwl, &liwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl;
             liwork = iwl;
             work = (double *) calloc(lwork, sizeof(double));
@@ -4231,10 +4999,10 @@ static PyObject* syevd(PyObject *self, PyObject *args, PyObject *kwrds)
                 free(work);  free(iwork);
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-	    dsyevd_(&jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+	    dsyevd_(&jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(W)+oW, work, &lwork, iwork, &liwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);  free(iwork);
             break;
 
@@ -4247,7 +5015,7 @@ static PyObject* syevd(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_heevd[] = 
+static char doc_heevd[] =
     "Eigenvalue decomposition of a real symmetric or complex Hermitian"
     "\nmatrix (divide-and-conquer driver).\n\n"
     "heevd(A, W, jobz='N', uplo='L', n=A.size[0], "
@@ -4273,14 +5041,14 @@ static char doc_heevd[] =
 
 static PyObject* heevd(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *W; 
-    int n=-1, ldA=0, oA=0, oW=0, info, lwork, liwork, *iwork, iwl, 
-	lrwork; 
+    matrix *A, *W;
+    int n=-1, ldA=0, oA=0, oW=0, info, lwork, liwork, *iwork, iwl,
+	lrwork;
     double *rwork, rwl;
     number wl;
     void *work;
     char uplo='L', jobz='N';
-    char *kwlist[] = {"A", "W", "jobz", "uplo", "n", "ldA", "offsetA", 
+    char *kwlist[] = {"A", "W", "jobz", "uplo", "n", "ldA", "offsetA",
         "offsetW", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cciiii", kwlist,
@@ -4290,7 +5058,7 @@ static PyObject* heevd(PyObject *self, PyObject *args, PyObject *kwrds)
     if (!Matrix_Check(W) || W->id != DOUBLE) err_dbl_mtrx("W");
     if (jobz != 'N' && jobz != 'V') err_char("jobz", "'N', 'V'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -4309,10 +5077,10 @@ static PyObject* heevd(PyObject *self, PyObject *args, PyObject *kwrds)
         case DOUBLE:
             lwork = -1;
             liwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
-            dsyevd_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl.d, &lwork, 
+            Py_BEGIN_ALLOW_THREADS
+            dsyevd_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl.d, &lwork,
                 &iwl, &liwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             liwork = iwl;
             work = (void *) calloc(lwork, sizeof(double));
@@ -4321,11 +5089,11 @@ static PyObject* heevd(PyObject *self, PyObject *args, PyObject *kwrds)
                 free(work);  free(iwork);
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            dsyevd_(&jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            dsyevd_(&jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA,
                 MAT_BUFD(W)+oW, (double *) work, &lwork, iwork, &liwork,
                 &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);   free(iwork);
             break;
 
@@ -4333,10 +5101,10 @@ static PyObject* heevd(PyObject *self, PyObject *args, PyObject *kwrds)
             lwork = -1;
             liwork = -1;
             lrwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
-            zheevd_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl.z, &lwork, 
+            Py_BEGIN_ALLOW_THREADS
+            zheevd_(&jobz, &uplo, &n, NULL, &ldA, NULL, &wl.z, &lwork,
                 &rwl, &lrwork, &iwl, &liwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             lrwork = (int) rwl;
             liwork = iwl;
@@ -4347,11 +5115,11 @@ static PyObject* heevd(PyObject *self, PyObject *args, PyObject *kwrds)
                 free(work);  free(rwork);  free(iwork);
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            zheevd_(&jobz, &uplo, &n, MAT_BUFZ(A)+oA, &ldA, 
+            Py_BEGIN_ALLOW_THREADS
+            zheevd_(&jobz, &uplo, &n, MAT_BUFZ(A)+oA, &ldA,
                 MAT_BUFD(W)+oW, (complex *) work, &lwork, rwork,
                 &lrwork, iwork, &liwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);  free(rwork);  free(iwork);
             break;
 
@@ -4364,14 +5132,14 @@ static PyObject* heevd(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_syevr[] = 
+static char doc_syevr[] =
     "Computes selected eigenvalues and eigenvectors of a real symmetric"
     "\n"
     "matrix (RRR driver).\n\n"
     "m = syevr(A, W, jobz='N', range='A', uplo='L', vl=0.0, vu=0.0, \n"
     "          il=1, iu=1, Z=None, n=A.size[0], ldA=max(1,A.size[0]),\n"
     "          ldZ=None, abstol=0.0, offsetA=0, offsetW=0, offsetZ=0)\n"
-    "\n" 
+    "\n"
     "PURPOSE\n"
     "Computes selected eigenvalues/vectors of a real symmetric n by n\n"
     "matrix A.\n"
@@ -4381,11 +5149,11 @@ static char doc_syevr[] =
     "If range is 'I', all eigenvalues il through iu are computed\n"
     "(sorted in ascending order with 1 <= il <= iu <= n).\n"
     "If jobz is 'N', only the eigenvalues are returned in W.\n"
-    "If jobz is 'V', the eigenvectors are also returned in Z.\n"  
+    "If jobz is 'V', the eigenvectors are also returned in Z.\n"
     "On exit, the content of A is destroyed.\n"
     "syevr is usually the fastest of the four eigenvalue routines.\n\n"
     "ARGUMENTS\n"
-    "A         'd' matrix\n\n"  
+    "A         'd' matrix\n\n"
     "W         'd' matrix of length at least n.  On exit, contains\n"
     "          the computed eigenvalues in ascending order.\n\n"
     "jobz      'N' or 'V'\n\n"
@@ -4415,26 +5183,26 @@ static char doc_syevr[] =
 
 static PyObject* syevr(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *W, *Z=NULL; 
+    matrix *A, *W, *Z=NULL;
     int n=-1, ldA=0, ldZ=0, il=1, iu=1, oA=0, oW=0, oZ=0, info, lwork,
-        *iwork=NULL, liwork, m, *isuppz=NULL, iwl; 
-    double *work=NULL, vl=0.0, vu=0.0, abstol=0.0, wl; 
+        *iwork=NULL, liwork, m, *isuppz=NULL, iwl;
+    double *work=NULL, vl=0.0, vu=0.0, abstol=0.0, wl;
     char uplo='L', jobz='N', range='A';
     char *kwlist[] = {"A", "W", "jobz", "range", "uplo", "vl", "vu",
-	"il", "iu", "Z", "n", "ldA", "ldZ", "abstol", "offsetA", 
+	"il", "iu", "Z", "n", "ldA", "ldZ", "abstol", "offsetA",
         "offsetW", "offsetZ", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cccddiiOiiidiii",
         kwlist, &A, &W, &jobz, &range, &uplo, &vl, &vu, &il, &iu, &Z,
 	&n, &ldA, &ldZ, &abstol, &oA, &oW, &oZ)) return NULL;
 
-    if (!Matrix_Check(A)) err_mtrx("A"); 
+    if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(W) || MAT_ID(W) != DOUBLE) err_dbl_mtrx("W");
     if (jobz != 'N' && jobz != 'V') err_char("jobz", "'N', 'V'");
-    if (range != 'A' && range != 'V' && range != 'I') 
+    if (range != 'A' && range != 'V' && range != 'I')
 	err_char("range", "'A', 'V', 'I'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -4454,7 +5222,7 @@ static PyObject* syevr(PyObject *self, PyObject *args, PyObject *kwrds)
         return NULL;
     }
     if (jobz == 'V'){
-        if (!Z || !Matrix_Check(Z) || MAT_ID(Z) != DOUBLE) 
+        if (!Z || !Matrix_Check(Z) || MAT_ID(Z) != DOUBLE)
             err_dbl_mtrx("Z");
         if (ldZ == 0) ldZ = MAX(1,Z->nrows);
         if (ldZ < MAX(1,n)) err_ld("ldZ");
@@ -4468,38 +5236,38 @@ static PyObject* syevr(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oW + n > len(W)) err_buf_len("W");
     if (jobz == 'V'){
         if (oZ < 0) err_nn_int("offsetZ");
-        if (oZ + ((range == 'I') ? iu-il : n-1)*ldZ + n > len(Z)) 
-	    err_buf_len("Z"); 
+        if (oZ + ((range == 'I') ? iu-il : n-1)*ldZ + n > len(Z))
+	    err_buf_len("Z");
     }
 
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
             liwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsyevr_(&jobz, &range, &uplo, &n, NULL, &ldA, &vl, &vu, &il,
-                &iu, &abstol, &m, NULL, NULL, &ldZ, NULL, &wl, &lwork, 
+                &iu, &abstol, &m, NULL, NULL, &ldZ, NULL, &wl, &lwork,
                 &iwl, &liwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl;
             liwork = iwl;
             work = (void *) calloc(lwork, sizeof(double));
             iwork = (int *) calloc(liwork, sizeof(int));
-            if (jobz == 'V') 
-                isuppz = (int *) calloc(2*MAX(1, (range == 'I') ? 
+            if (jobz == 'V')
+                isuppz = (int *) calloc(2*MAX(1, (range == 'I') ?
                    iu-il+1 : n), sizeof(int));
             if (!work  || !iwork || (jobz == 'V' && !isuppz)){
                 free(work);  free(iwork);  free(isuppz);
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsyevr_(&jobz, &range, &uplo, &n, MAT_BUFD(A)+oA, &ldA, &vl,
                 &vu, &il, &iu, &abstol, &m, MAT_BUFD(W)+oW,
-                (jobz == 'V') ? MAT_BUFD(Z)+oZ : NULL,  &ldZ, 
-                (jobz == 'V') ? isuppz : NULL, work, &lwork, iwork, 
+                (jobz == 'V') ? MAT_BUFD(Z)+oZ : NULL,  &ldZ,
+                (jobz == 'V') ? isuppz : NULL, work, &lwork, iwork,
                 &liwork, &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   free(iwork);   free(isuppz);   
+            Py_END_ALLOW_THREADS
+            free(work);   free(iwork);   free(isuppz);
             break;
 
         default:
@@ -4511,7 +5279,7 @@ static PyObject* syevr(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_heevr[] = 
+static char doc_heevr[] =
     "Computes selected eigenvalues and eigenvectors of a real symmetric"
     "\nor complex Hermitian matrix (RRR driver).\n\n"
     "m = syevr(A, W, jobz='N', range='A', uplo='L', vl=0.0, vu=0.0, \n"
@@ -4527,11 +5295,11 @@ static char doc_heevr[] =
     "If range is 'I', all eigenvalues il through iu are computed\n"
     "(sorted in ascending order with 1 <= il <= iu <= n).\n"
     "If jobz is 'N', only the eigenvalues are returned in W.\n"
-    "If jobz is 'V', the eigenvectors are also returned in Z.\n"  
+    "If jobz is 'V', the eigenvectors are also returned in Z.\n"
     "On exit, the content of A is destroyed.\n"
     "syevr is usually the fastest of the four eigenvalue routines.\n\n"
     "ARGUMENTS\n"
-    "A         'd' or 'z' matrix\n\n"  
+    "A         'd' or 'z' matrix\n\n"
     "W         'd' matrix of length at least n.  On exit, contains\n"
     "          the computed eigenvalues in ascending order.\n\n"
     "jobz      'N' or 'V'\n\n"
@@ -4561,28 +5329,28 @@ static char doc_heevr[] =
 
 static PyObject* heevr(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *W, *Z=NULL; 
-    int n=-1, ldA=0, ldZ=0, il=1, iu=1, oA=0, oW=0, oZ=0, info, 
-        lwork, *iwork, liwork, lrwork, m, *isuppz=NULL, iwl; 
-    double vl=0.0, vu=0.0, abstol=0.0, *rwork, rwl; 
+    matrix *A, *W, *Z=NULL;
+    int n=-1, ldA=0, ldZ=0, il=1, iu=1, oA=0, oW=0, oZ=0, info,
+        lwork, *iwork, liwork, lrwork, m, *isuppz=NULL, iwl;
+    double vl=0.0, vu=0.0, abstol=0.0, *rwork, rwl;
     void *work;
     number wl;
     char uplo='L', jobz='N', range='A';
     char *kwlist[] = {"A", "W", "jobz", "range", "uplo", "vl", "vu",
-	"il", "iu", "Z", "n", "ldA", "ldZ", "abstol", "offsetA", 
+	"il", "iu", "Z", "n", "ldA", "ldZ", "abstol", "offsetA",
         "offsetW", "offsetZ", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cccddiiOiiidiii",
         kwlist, &A, &W, &jobz, &range, &uplo, &vl, &vu, &il, &iu, &Z,
 	&n, &ldA, &ldZ, &abstol, &oA, &oW, &oZ)) return NULL;
 
-    if (!Matrix_Check(A)) err_mtrx("A"); 
+    if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(W) || MAT_ID(W) != DOUBLE) err_dbl_mtrx("W");
     if (jobz != 'N' && jobz != 'V') err_char("jobz", "'N', 'V'");
-    if (range != 'A' && range != 'V' && range != 'I') 
+    if (range != 'A' && range != 'V' && range != 'I')
 	err_char("range", "'A', 'V', 'I'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -4603,7 +5371,7 @@ static PyObject* heevr(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (jobz == 'V'){
         if (!Z || !Matrix_Check(Z)) err_mtrx("Z");
-	if (MAT_ID(Z) != MAT_ID(A)) err_conflicting_ids; 
+	if (MAT_ID(Z) != MAT_ID(A)) err_conflicting_ids;
         if (ldZ == 0) ldZ = MAX(1,Z->nrows);
         if (ldZ < MAX(1,n)) err_ld("ldZ");
     } else {
@@ -4616,70 +5384,70 @@ static PyObject* heevr(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oW + n > len(W)) err_buf_len("W");
     if (jobz == 'V'){
         if (oZ < 0) err_nn_int("offsetZ");
-        if (oZ + ((range == 'I') ? iu-il : n-1)*ldZ + n > len(Z)) 
-	    err_buf_len("Z"); 
+        if (oZ + ((range == 'I') ? iu-il : n-1)*ldZ + n > len(Z))
+	    err_buf_len("Z");
     }
 
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
             liwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsyevr_(&jobz, &range, &uplo, &n, NULL, &ldA, &vl, &vu, &il,
                 &iu, &abstol, &m, NULL, NULL, &ldZ, NULL, &wl.d, &lwork,
                 &iwl, &liwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             liwork = iwl;
             work = (void *) calloc(lwork, sizeof(double));
             iwork = (int *) calloc(liwork, sizeof(int));
-            if (jobz == 'V') 
-                isuppz = (int *) calloc(2*MAX(1, (range == 'I') ? 
+            if (jobz == 'V')
+                isuppz = (int *) calloc(2*MAX(1, (range == 'I') ?
                    iu-il+1 : n), sizeof(int));
             if (!work  || !iwork || (jobz == 'V' && !isuppz)){
                 free(work);  free(iwork);  free(isuppz);
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsyevr_(&jobz, &range, &uplo, &n, MAT_BUFD(A)+oA, &ldA, &vl,
                 &vu, &il, &iu, &abstol, &m, MAT_BUFD(W)+oW,
-                (jobz == 'V') ? MAT_BUFD(Z)+oZ : NULL,  &ldZ, 
+                (jobz == 'V') ? MAT_BUFD(Z)+oZ : NULL,  &ldZ,
                 (jobz == 'V') ? isuppz : NULL, (double *) work, &lwork,
 	       	iwork, &liwork, &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   free(iwork);   free(isuppz);   
+            Py_END_ALLOW_THREADS
+            free(work);   free(iwork);   free(isuppz);
             break;
 
 	case COMPLEX:
             lwork = -1;
             liwork = -1;
 	    lrwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zheevr_(&jobz, &range, &uplo, &n, NULL, &ldA, &vl, &vu, &il,
                 &iu, &abstol, &m, NULL, NULL, &ldZ, NULL, &wl.z, &lwork,
                 &rwl, &lrwork, &iwl, &liwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
 	    lrwork = (int) rwl;
             liwork = iwl;
             work = (void *) calloc(lwork, sizeof(complex));
             rwork = (double *) calloc(lrwork, sizeof(double));
             iwork = (int *) calloc(liwork, sizeof(int));
-            if (jobz == 'V') 
-                isuppz = (int *) calloc(2*MAX(1, (range == 'I') ? 
+            if (jobz == 'V')
+                isuppz = (int *) calloc(2*MAX(1, (range == 'I') ?
                    iu-il+1 : n), sizeof(int));
             if (!work  || !rwork || !iwork || (jobz == 'V' && !isuppz)){
                 free(work);  free(rwork);  free(iwork);  free(isuppz);
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zheevr_(&jobz, &range, &uplo, &n, MAT_BUFZ(A)+oA, &ldA, &vl,
                 &vu, &il, &iu, &abstol, &m, MAT_BUFD(W)+oW,
-                (jobz == 'V') ? MAT_BUFZ(Z)+oZ : NULL,  &ldZ, 
+                (jobz == 'V') ? MAT_BUFZ(Z)+oZ : NULL,  &ldZ,
                 (jobz == 'V') ? isuppz : NULL, (complex *) work, &lwork,
 	       	rwork, &lrwork, iwork, &liwork, &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   free(rwork); free(iwork);   free(isuppz);   
+            Py_END_ALLOW_THREADS
+            free(work);   free(rwork); free(iwork);   free(isuppz);
             break;
 
         default:
@@ -4691,9 +5459,9 @@ static PyObject* heevr(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_sygv[] = 
+static char doc_sygv[] =
     "Generalized symmetric-definite eigenvalue decomposition with real"
-    "\n" 
+    "\n"
     "matrices.\n\n"
     "sygv(A, B, W, itype=1, jobz='N', uplo='L', n=A.size[0], \n"
     "     ldA = max(1,A.size[0]), ldB = max(1,B.size[0]), offsetA=0, \n"
@@ -4731,16 +5499,16 @@ static char doc_sygv[] =
 
 static PyObject* sygv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B, *W; 
-    int n=-1, itype=1, ldA=0, ldB=0, oA=0, oB=0, oW=0, info, lwork; 
-    double *work; 
-    number wl; 
+    matrix *A, *B, *W;
+    int n=-1, itype=1, ldA=0, ldB=0, oA=0, oB=0, oW=0, info, lwork;
+    double *work;
+    number wl;
     char uplo='L', jobz='N';
-    char *kwlist[] = {"A", "B", "W", "itype", "jobz", "uplo", "n", 
+    char *kwlist[] = {"A", "B", "W", "itype", "jobz", "uplo", "n",
         "ldA", "ldB", "offsetA", "offsetB", "offsetW", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|icciiiiii", 
-        kwlist, &A, &B, &W, &itype, &jobz, &uplo, &n, &ldA, &ldB, &oA, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|icciiiiii",
+        kwlist, &A, &B, &W, &itype, &jobz, &uplo, &n, &ldA, &ldB, &oA,
         &oB, &oW)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -4750,7 +5518,7 @@ static PyObject* sygv(PyObject *self, PyObject *args, PyObject *kwrds)
         err_char("itype", "1, 2, 3");
     if (jobz != 'N' && jobz != 'V') err_char("jobz", "'N', 'V'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -4777,19 +5545,19 @@ static PyObject* sygv(PyObject *self, PyObject *args, PyObject *kwrds)
     switch (MAT_ID(A)){
 	case DOUBLE:
             lwork=-1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsygv_(&itype, &jobz, &uplo, &n, NULL, &ldA, NULL, &ldB,
                 NULL, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = calloc(lwork, sizeof(double))))
                 return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-            dsygv_(&itype, &jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA, 
-                MAT_BUFD(B)+oB, &ldB, MAT_BUFD(W)+oW, work, &lwork, 
+            Py_BEGIN_ALLOW_THREADS
+            dsygv_(&itype, &jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA,
+                MAT_BUFD(B)+oB, &ldB, MAT_BUFD(W)+oW, work, &lwork,
                 &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   
+            Py_END_ALLOW_THREADS
+            free(work);
             break;
 
         default:
@@ -4801,7 +5569,7 @@ static PyObject* sygv(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_hegv[] = 
+static char doc_hegv[] =
     "Generalized symmetric-definite eigenvalue decomposition with\n"
     "real or complex matrices.\n\n"
     "hegv(A, B, W, itype=1, jobz='N', uplo='L', n=A.size[0], \n"
@@ -4840,19 +5608,19 @@ static char doc_hegv[] =
 
 static PyObject* hegv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *B, *W; 
-    int n=-1, itype=1, ldA=0, ldB=0, oA=0, oB=0, oW=0, info, lwork; 
+    matrix *A, *B, *W;
+    int n=-1, itype=1, ldA=0, ldB=0, oA=0, oB=0, oW=0, info, lwork;
     double *rwork=NULL;
-    void *work=NULL; 
-    number wl; 
+    void *work=NULL;
+    number wl;
     char uplo='L', jobz='N';
-    char *kwlist[] = {"A", "B", "W", "itype", "jobz", "uplo", "n", 
+    char *kwlist[] = {"A", "B", "W", "itype", "jobz", "uplo", "n",
         "ldA", "offsetA", "offsetB", "offsetW", NULL};
     int ispec=1, n2=-1, n3=-1, n4=-1;
     char *name = "zhetrd", *uplol = "L", *uplou = "U";
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|icciiiii", 
-        kwlist, &A, &B, &W, &itype, &jobz, &uplo, &n, &ldA, &ldB, &oA, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|icciiiii",
+        kwlist, &A, &B, &W, &itype, &jobz, &uplo, &n, &ldA, &ldB, &oA,
         &oB, &oW)) return NULL;
 
     if (!Matrix_Check(A)) err_mtrx("A");
@@ -4862,7 +5630,7 @@ static PyObject* hegv(PyObject *self, PyObject *args, PyObject *kwrds)
         err_char("itype", "1, 2, 3");
     if (jobz != 'N' && jobz != 'V') err_char("jobz", "'N', 'V'");
     if (uplo != 'L' && uplo != 'U') err_char("uplo", "'L', 'U'");
-    if (n < 0){ 
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -4889,46 +5657,46 @@ static PyObject* hegv(PyObject *self, PyObject *args, PyObject *kwrds)
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork=-1;
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dsygv_(&itype, &jobz, &uplo, &n, NULL, &ldA, NULL, &ldB,
                 NULL, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = calloc(lwork, sizeof(double))))
                 return PyErr_NoMemory();
-            Py_BEGIN_ALLOW_THREADS	    
-            dsygv_(&itype, &jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA, 
-                MAT_BUFD(B)+oB, &ldB, MAT_BUFD(W)+oW, work, &lwork, 
+            Py_BEGIN_ALLOW_THREADS
+            dsygv_(&itype, &jobz, &uplo, &n, MAT_BUFD(A)+oA, &ldA,
+                MAT_BUFD(B)+oB, &ldB, MAT_BUFD(W)+oW, work, &lwork,
                 &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   
+            Py_END_ALLOW_THREADS
+            free(work);
             break;
 
         case COMPLEX:
-#if 0       
+#if 0
             /* zhegv does not handle lwork=-1 correctly */
             lwork=-1;
-            Py_BEGIN_ALLOW_THREADS	    
-            zhegv_(&itype, &jobz, &uplo, &n, NULL, &n, NULL, &n, NULL, 
+            Py_BEGIN_ALLOW_THREADS
+            zhegv_(&itype, &jobz, &uplo, &n, NULL, &n, NULL, &n, NULL,
                 &wl.z, &lwork, NULL, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
 #endif
             /* replaces call to zhegv with lwork=-1 */
-            lwork = n * (1 + ilaenv_(&ispec, &name, (uplo == 'L') ?  
+            lwork = n * (1 + ilaenv_(&ispec, &name, (uplo == 'L') ?
                 &uplol : &uplou, &n, &n2, &n3, &n4));
-	    
+
             work = (void *) calloc(lwork, sizeof(complex));
             rwork = (double *) calloc(3*n-2, sizeof(double));
             if (!work || !rwork){
                 free(work);  free(rwork);
                 return PyErr_NoMemory();
-            }	
-            Py_BEGIN_ALLOW_THREADS	    
-            zhegv_(&itype, &jobz, &uplo, &n, MAT_BUFZ(A)+oA, &ldA, 
-                MAT_BUFZ(B)+oB, &ldB, MAT_BUFD(W)+oW, (complex *) work, 
+            }
+            Py_BEGIN_ALLOW_THREADS
+            zhegv_(&itype, &jobz, &uplo, &n, MAT_BUFZ(A)+oA, &ldA,
+                MAT_BUFZ(B)+oB, &ldB, MAT_BUFD(W)+oW, (complex *) work,
                 &lwork, rwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);  free(rwork);
             break;
 
@@ -4941,7 +5709,7 @@ static PyObject* hegv(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_gesvd[] = 
+static char doc_gesvd[] =
     "Singular value decomposition of a real or complex matrix.\n\n"
     "gesvd(A, S, jobu='N', jobvt='N', U=None, Vt=None, m=A.size[0],\n"
     "      n=A.size[1], ldA=max(1,A.size[0]), ldU=None, ldVt=None,\n"
@@ -4971,7 +5739,7 @@ static char doc_gesvd[] =
     "vectors are returned in Vt or A.\n\n"
     "On exit (in all cases), the contents of A are destroyed.\n\n"
     "ARGUMENTS\n"
-    "A         'd' or 'z' matrix\n\n"  
+    "A         'd' or 'z' matrix\n\n"
     "S         'd' matrix of length at least min(m,n).  On exit, \n"
     "          contains the computed singular values in descending\n"
     "          order.\n\n"
@@ -5004,7 +5772,7 @@ static char doc_gesvd[] =
     "          ldVt >= max(1,n) if jobvt is 'A'.  \n"
     "          ldVt >= max(1,min(m,n)) if ldVt is 'S'.\n"
     "          The default value is max(1,Vt.size[0]) if jobvt is 'A'\n"
-    "          or 'S', and 1 otherwise.\n" 
+    "          or 'S', and 1 otherwise.\n"
     "          If zero, the default value is used.\n\n"
     "offsetA   nonnegative integer\n\n"
     "offsetS   nonnegative integer\n\n"
@@ -5013,26 +5781,26 @@ static char doc_gesvd[] =
 
 static PyObject* gesvd(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *S, *U=NULL, *Vt=NULL; 
+    matrix *A, *S, *U=NULL, *Vt=NULL;
     int m=-1, n=-1, ldA=0, ldU=0, ldVt=0, oA=0, oS=0, oU=0, oVt=0, info,
-       	lwork; 
-    double *rwork=NULL; 
+       	lwork;
+    double *rwork=NULL;
     void *work=NULL;
     number wl;
-    char jobu='N', jobvt='N'; 
-    char *kwlist[] = {"A", "S", "jobu", "jobvt", "U", "Vt", "m", "n", 
-	"ldA", "ldU", "ldVt", "offsetA", "offsetS", "offsetU", 
+    char jobu='N', jobvt='N';
+    char *kwlist[] = {"A", "S", "jobu", "jobvt", "U", "Vt", "m", "n",
+	"ldA", "ldU", "ldVt", "offsetA", "offsetS", "offsetU",
         "offsetVt", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ccOOiiiiiiiii",
-        kwlist, &A, &S, &jobu, &jobvt, &U, &Vt, &m, &n, &ldA, &ldU, 
+        kwlist, &A, &S, &jobu, &jobvt, &U, &Vt, &m, &n, &ldA, &ldU,
         &ldVt, &oA, &oS, &oU, &oVt)) return NULL;
 
-    if (!Matrix_Check(A)) err_mtrx("A"); 
+    if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(S) || MAT_ID(S) != DOUBLE) err_dbl_mtrx("S");
-    if (jobu != 'N' && jobu != 'A' && jobu != 'O' && jobu != 'S') 
+    if (jobu != 'N' && jobu != 'A' && jobu != 'O' && jobu != 'S')
         err_char("jobu", "'N', 'A', 'S', 'O'");
-    if (jobvt != 'N' && jobvt != 'A' && jobvt != 'O' && jobvt != 'S') 
+    if (jobvt != 'N' && jobvt != 'A' && jobvt != 'O' && jobvt != 'S')
         err_char("jobvt", "'N', 'A', 'S', 'O'");
     if (jobu == 'O' && jobvt == 'O') {
         PyErr_SetString(PyExc_ValueError, "'jobu' and 'jobvt' cannot "
@@ -5046,7 +5814,7 @@ static PyObject* gesvd(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldA < MAX(1,m)) err_ld("ldA");
     if (jobu == 'A' || jobu == 'S'){
         if (!U || !Matrix_Check(U)) err_mtrx("U");
-        if (MAT_ID(U) != MAT_ID(A)) err_conflicting_ids; 
+        if (MAT_ID(U) != MAT_ID(A)) err_conflicting_ids;
         if (ldU == 0) ldU = MAX(1,U->nrows);
         if (ldU < MAX(1,m)) err_ld("ldU");
     } else {
@@ -5055,9 +5823,9 @@ static PyObject* gesvd(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (jobvt == 'A' || jobvt == 'S'){
         if (!Vt || !Matrix_Check(Vt)) err_mtrx("Vt");
-	if (MAT_ID(Vt) != MAT_ID(A)) err_conflicting_ids; 
+	if (MAT_ID(Vt) != MAT_ID(A)) err_conflicting_ids;
         if (ldVt == 0) ldVt = MAX(1,Vt->nrows);
-        if (ldVt < ((jobvt == 'A') ?  MAX(1,n) : MAX(1,MIN(m,n)))) 
+        if (ldVt < ((jobvt == 'A') ?  MAX(1,n) : MAX(1,MIN(m,n))))
             err_ld("ldVt");
     } else {
         if (ldVt == 0) ldVt = 1;
@@ -5069,58 +5837,58 @@ static PyObject* gesvd(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oS + MIN(m,n) > len(S)) err_buf_len("S");
     if (jobu == 'A' || jobu == 'S'){
         if (oU < 0) err_nn_int("offsetU");
-        if (oU + ((jobu == 'A') ? m-1 : MIN(m,n)-1)*ldU + m > len(U)) 
-            err_buf_len("U"); 
+        if (oU + ((jobu == 'A') ? m-1 : MIN(m,n)-1)*ldU + m > len(U))
+            err_buf_len("U");
     }
     if (jobvt == 'A' || jobvt == 'S'){
         if (oVt < 0) err_nn_int("offsetVt");
-        if (oVt + (n-1)*ldVt + ((jobvt == 'A') ? n : MIN(m,n)) > 
-            len(Vt)) err_buf_len("Vt"); 
+        if (oVt + (n-1)*ldVt + ((jobvt == 'A') ? n : MIN(m,n)) >
+            len(Vt)) err_buf_len("Vt");
     }
 
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
-             Py_BEGIN_ALLOW_THREADS	    
-            dgesvd_(&jobu, &jobvt, &m, &n, NULL, &ldA, NULL, NULL, 
+             Py_BEGIN_ALLOW_THREADS
+            dgesvd_(&jobu, &jobvt, &m, &n, NULL, &ldA, NULL, NULL,
                 &ldU, NULL, &ldVt, &wl.d, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             if (!(work = (void *) calloc(lwork, sizeof(double)))){
-                free(work);  
+                free(work);
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            dgesvd_(&jobu, &jobvt, &m, &n, MAT_BUFD(A)+oA, &ldA, 
-                MAT_BUFD(S)+oS,  (jobu == 'A' || jobu == 'S') ? 
-		MAT_BUFD(U)+oU : NULL, &ldU, (jobvt == 'A' || 
-                jobvt == 'S') ?  MAT_BUFD(Vt)+oVt : NULL, &ldVt, 
+            Py_BEGIN_ALLOW_THREADS
+            dgesvd_(&jobu, &jobvt, &m, &n, MAT_BUFD(A)+oA, &ldA,
+                MAT_BUFD(S)+oS,  (jobu == 'A' || jobu == 'S') ?
+		MAT_BUFD(U)+oU : NULL, &ldU, (jobvt == 'A' ||
+                jobvt == 'S') ?  MAT_BUFD(Vt)+oVt : NULL, &ldVt,
 		(double *) work, &lwork, &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   
+            Py_END_ALLOW_THREADS
+            free(work);
             break;
 
 	case COMPLEX:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
-            zgesvd_(&jobu, &jobvt, &m, &n, NULL, &ldA, NULL, NULL, 
+            Py_BEGIN_ALLOW_THREADS
+            zgesvd_(&jobu, &jobvt, &m, &n, NULL, &ldA, NULL, NULL,
                 &ldU, NULL, &ldVt, &wl.z, &lwork, NULL, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
             work = (void *) calloc(lwork, sizeof(complex));
             rwork = (double *) calloc(5*MIN(m,n), sizeof(double));
-	    if (!work || !rwork){ 
+	    if (!work || !rwork){
                 free(work);  free(rwork);
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
-            zgesvd_(&jobu, &jobvt, &m, &n, MAT_BUFZ(A)+oA, &ldA, 
-                MAT_BUFD(S)+oS, (jobu == 'A' || jobu == 'S') ? 
-                MAT_BUFZ(U)+oU : NULL,  &ldU, (jobvt == 'A' || 
-                jobvt == 'S') ? MAT_BUFZ(Vt)+oVt : NULL, &ldVt, 
+            Py_BEGIN_ALLOW_THREADS
+            zgesvd_(&jobu, &jobvt, &m, &n, MAT_BUFZ(A)+oA, &ldA,
+                MAT_BUFD(S)+oS, (jobu == 'A' || jobu == 'S') ?
+                MAT_BUFZ(U)+oU : NULL,  &ldU, (jobvt == 'A' ||
+                jobvt == 'S') ? MAT_BUFZ(Vt)+oVt : NULL, &ldVt,
                 (complex *) work, &lwork, rwork, &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);   free(rwork); 
+            Py_END_ALLOW_THREADS
+            free(work);   free(rwork);
             break;
 
         default:
@@ -5132,7 +5900,7 @@ static PyObject* gesvd(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_gesdd[] = 
+static char doc_gesdd[] =
     "Singular value decomposition of a real or complex matrix\n"
     "(divide-and-conquer driver).\n\n"
     "gesdd(A, S, jobz='N', U=None, V=None, m=A.size[0], n=A.size[1], \n"
@@ -5157,7 +5925,7 @@ static char doc_gesdd[] =
     "vectors are returned in Vt or A.\n\n"
     "On exit (in all cases), the contents of A are destroyed.\n\n"
     "ARGUMENTS\n"
-    "A         'd' or 'z' matrix\n\n"  
+    "A         'd' or 'z' matrix\n\n"
     "S         'd' matrix of length at least min(m,n).  On exit, \n"
     "          contains the computed singular values in descending\n"
     "          order.\n\n"
@@ -5192,7 +5960,7 @@ static char doc_gesdd[] =
     "          m>=n.  \n"
     "          ldVt >= max(1,min(m,n)) if ldVt is 'S'.\n"
     "          The default value is max(1,Vt.size[0]) if jobvt is 'A'\n"
-    "          or 'S' or jobvt is 'O' and m>=n, and 1 otherwise.\n" 
+    "          or 'S' or jobvt is 'O' and m>=n, and 1 otherwise.\n"
     "          If zero, the default value is used.\n\n"
     "offsetA   nonnegative integer\n\n"
     "offsetS   nonnegative integer\n\n"
@@ -5201,24 +5969,24 @@ static char doc_gesdd[] =
 
 static PyObject* gesdd(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *A, *S, *U=NULL, *Vt=NULL; 
+    matrix *A, *S, *U=NULL, *Vt=NULL;
     int m=-1, n=-1, ldA=0, ldU=0, ldVt=0, oA=0, oS=0, oU=0, oVt=0, info,
-       	*iwork=NULL, lwork; 
-    double *rwork=NULL; 
+       	*iwork=NULL, lwork;
+    double *rwork=NULL;
     void *work=NULL;
     number wl;
     char jobz='N';
-    char *kwlist[] = {"A", "S", "jobz", "U", "Vt", "m", "n", "ldA", 
-	"ldU", "ldVt", "offsetA", "offsetS", "offsetU", "offsetVt", 
+    char *kwlist[] = {"A", "S", "jobz", "U", "Vt", "m", "n", "ldA",
+	"ldU", "ldVt", "offsetA", "offsetS", "offsetU", "offsetVt",
         NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cOOiiiiiiiii",
         kwlist, &A, &S, &jobz, &U, &Vt, &m, &n, &ldA, &ldU, &ldVt, &oA,
        	&oS, &oU, &oVt)) return NULL;
 
-    if (!Matrix_Check(A)) err_mtrx("A"); 
+    if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(S) || MAT_ID(S) != DOUBLE) err_dbl_mtrx("S");
-    if (jobz != 'A' && jobz != 'S' && jobz != 'O' && jobz != 'N') 
+    if (jobz != 'A' && jobz != 'S' && jobz != 'O' && jobz != 'N')
         err_char("jobz", "'A', 'S', 'O', 'N'");
     if (m < 0) m = A->nrows;
     if (n < 0) n = A->ncols;
@@ -5227,7 +5995,7 @@ static PyObject* gesdd(PyObject *self, PyObject *args, PyObject *kwrds)
     if (ldA < MAX(1,m)) err_ld("ldA");
     if (jobz == 'A' || jobz == 'S' || (jobz == 'O' && m<n)){
         if (!U || !Matrix_Check(U)) err_mtrx("U");
-        if (MAT_ID(U) != MAT_ID(A)) err_conflicting_ids; 
+        if (MAT_ID(U) != MAT_ID(A)) err_conflicting_ids;
         if (ldU == 0) ldU = MAX(1,U->nrows);
         if (ldU < MAX(1,m)) err_ld("ldU");
     } else {
@@ -5236,9 +6004,9 @@ static PyObject* gesdd(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     if (jobz == 'A' || jobz == 'S' || (jobz == 'O' && m>=n)){
         if (!Vt || !Matrix_Check(Vt)) err_mtrx("Vt");
-	if (MAT_ID(Vt) != MAT_ID(A)) err_conflicting_ids; 
+	if (MAT_ID(Vt) != MAT_ID(A)) err_conflicting_ids;
         if (ldVt == 0) ldVt = MAX(1,Vt->nrows);
-        if (ldVt < ((jobz == 'A' || jobz == 'O') ?  MAX(1,n) : 
+        if (ldVt < ((jobz == 'A' || jobz == 'O') ?  MAX(1,n) :
             MAX(1,MIN(m,n)))) err_ld("ldVt");
     } else {
         if (ldVt == 0) ldVt = 1;
@@ -5250,23 +6018,23 @@ static PyObject* gesdd(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oS + MIN(m,n) > len(S)) err_buf_len("S");
     if (jobz == 'A' || jobz == 'S' || (jobz == 'O' && m<n)){
         if (oU < 0) err_nn_int("offsetU");
-        if (oU + ((jobz == 'A' || jobz == 'O') ? m-1 : MIN(m,n)-1)*ldU 
-            + m > len(U)) 
-	    err_buf_len("U"); 
+        if (oU + ((jobz == 'A' || jobz == 'O') ? m-1 : MIN(m,n)-1)*ldU
+            + m > len(U))
+	    err_buf_len("U");
     }
     if (jobz == 'A' || jobz == 'S' || (jobz == 'O' && m>=n)){
         if (oVt < 0) err_nn_int("offsetVt");
-        if (oVt + (n-1)*ldVt + ((jobz == 'A' || jobz == 'O') ? n : 
-            MIN(m,n)) > len(Vt)) err_buf_len("Vt"); 
+        if (oVt + (n-1)*ldVt + ((jobz == 'A' || jobz == 'O') ? n :
+            MIN(m,n)) > len(Vt)) err_buf_len("Vt");
     }
 
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
-            dgesdd_(&jobz, &m, &n, NULL, &ldA, NULL, NULL, &ldU, NULL, 
+            Py_BEGIN_ALLOW_THREADS
+            dgesdd_(&jobz, &m, &n, NULL, &ldA, NULL, NULL, &ldU, NULL,
                 &ldVt, &wl.d, &lwork, NULL, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) wl.d;
             work = (void *) calloc(lwork, sizeof(double));
             iwork = (int *) calloc(8*MIN(m,n), sizeof(int));
@@ -5274,41 +6042,41 @@ static PyObject* gesdd(PyObject *self, PyObject *args, PyObject *kwrds)
                 free(work);  free(iwork);
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             dgesdd_(&jobz, &m, &n, MAT_BUFD(A)+oA, &ldA, MAT_BUFD(S)+oS,
                 (jobz == 'A' || jobz == 'S' || (jobz == 'O' && m<n)) ?
-                MAT_BUFD(U)+oU : NULL, &ldU, (jobz == 'A' || 
-                jobz == 'S' || (jobz == 'O'  && m>=n)) ? 
+                MAT_BUFD(U)+oU : NULL, &ldU, (jobz == 'A' ||
+                jobz == 'S' || (jobz == 'O'  && m>=n)) ?
                 MAT_BUFD(Vt)+oVt : NULL, &ldVt, (double *) work, &lwork,
                 iwork, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             free(work);   free(iwork);
             break;
 
 	case COMPLEX:
             lwork = -1;
-            Py_BEGIN_ALLOW_THREADS	    
-            zgesdd_(&jobz, &m, &n, NULL, &ldA, NULL, NULL, &ldU, NULL, 
+            Py_BEGIN_ALLOW_THREADS
+            zgesdd_(&jobz, &m, &n, NULL, &ldA, NULL, NULL, &ldU, NULL,
                 &ldVt, &wl.z, &lwork, NULL, NULL, &info);
-            Py_END_ALLOW_THREADS	    
+            Py_END_ALLOW_THREADS
             lwork = (int) creal(wl.z);
             work = (void *) calloc(lwork, sizeof(complex));
             iwork = (int *) calloc(8*MIN(m,n), sizeof(int));
             rwork = (double *) calloc( (jobz == 'N') ? 7*MIN(m,n) :
                 5*MIN(m,n)*(MIN(m,n)+1), sizeof(double));
-	    if (!work || !iwork || !rwork){ 
+	    if (!work || !iwork || !rwork){
                 free(work);  free(iwork); free(rwork);
                 return PyErr_NoMemory();
             }
-            Py_BEGIN_ALLOW_THREADS	    
+            Py_BEGIN_ALLOW_THREADS
             zgesdd_(&jobz, &m, &n, MAT_BUFZ(A)+oA, &ldA, MAT_BUFD(S)+oS,
-                (jobz == 'A' || jobz == 'S' || (jobz == 'O' && m<n)) ? 
-		MAT_BUFZ(U)+oU : NULL,  &ldU, (jobz == 'A' || 
-                jobz == 'S' || (jobz == 'O' && m>=n)) ? 
-                MAT_BUFZ(Vt)+oVt : NULL, &ldVt, (complex *) work, 
+                (jobz == 'A' || jobz == 'S' || (jobz == 'O' && m<n)) ?
+		MAT_BUFZ(U)+oU : NULL,  &ldU, (jobz == 'A' ||
+                jobz == 'S' || (jobz == 'O' && m>=n)) ?
+                MAT_BUFZ(Vt)+oVt : NULL, &ldVt, (complex *) work,
                 &lwork, rwork, iwork, &info);
-            Py_END_ALLOW_THREADS	    
-            free(work);  free(iwork); free(rwork); 
+            Py_END_ALLOW_THREADS
+            free(work);  free(iwork); free(rwork);
             break;
 
         default:
@@ -5320,9 +6088,9 @@ static PyObject* gesdd(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_gees[] = 
+static char doc_gees[] =
     "Schur factorization of a real of complex matrix.\n\n"
-    "sdim = gees(A, w=None, V=None, select=None, n=A.size[0],\n" 
+    "sdim = gees(A, w=None, V=None, select=None, n=A.size[0],\n"
     "            ldA=max(1,A.size[0]), ldV=max(1,Vs.size[0]), offsetA=0,\n"
     "            offsetw=0, offsetV=0)\n\n"
     "PURPOSE\n"
@@ -5341,8 +6109,8 @@ static char doc_gees[] =
     "If select is provided, gees() returns the number of eigenvalues \n"
     "that satisfy the selection criterion.   Otherwise, it returns 0.\n\n"
     "ARGUMENTS\n"
-    "A         'd' or 'z' matrix\n\n"  
-    "w         'z' matrix of length at least n\n\n"  
+    "A         'd' or 'z' matrix\n\n"
+    "w         'z' matrix of length at least n\n\n"
     "V         'd' or 'z' matrix.  Must have the same type as A.\n\n"
     "select    Python function that takes a complex number as argument\n"
     "          and returns True or False.\n\n"
@@ -5372,8 +6140,8 @@ extern int fselect_c(complex *w)
         return -1;
     }
     if PyInt_Check(result)
-        a = (int) PyInt_AsLong(result);  
-    else 
+        a = (int) PyInt_AsLong(result);
+    else
         PyErr_SetString(PyExc_TypeError, "select() must return an integer "
             "argument");
     Py_XDECREF(wpy);  Py_XDECREF(result);
@@ -5391,8 +6159,8 @@ extern int fselect_r(double *wr, double *wi)
         return -1;
     }
     if PyInt_Check(result)
-        a = (int) PyInt_AsLong(result);  
-    else 
+        a = (int) PyInt_AsLong(result);
+    else
         PyErr_SetString(PyExc_TypeError, "select() must return an integer "
            "argument");
     Py_XDECREF(wpy);  Py_XDECREF(result);
@@ -5402,22 +6170,22 @@ extern int fselect_r(double *wr, double *wi)
 static PyObject* gees(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     PyObject *F=NULL;
-    matrix *A, *W=NULL, *Vs=NULL; 
+    matrix *A, *W=NULL, *Vs=NULL;
     int n=-1, ldA=0, ldVs=0, oA=0, oVs=0, oW=0, info, lwork, sdim, k,
-        *bwork=NULL; 
+        *bwork=NULL;
     double *wr=NULL, *wi=NULL, *rwork=NULL;
     complex *w=NULL;
     void *work=NULL;
     number wl;
-    char *kwlist[] = {"A", "w", "V", "select", "n", "ldA", "ldV", 
+    char *kwlist[] = {"A", "w", "V", "select", "n", "ldA", "ldV",
         "offsetA", "offsetw", "offsetV", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OOOiiiiii",
-        kwlist, &A, &W, &Vs, &F, &n, &ldA, &ldVs, &oA, &oW, &oVs)) 
+        kwlist, &A, &W, &Vs, &F, &n, &ldA, &ldVs, &oA, &oW, &oVs))
         return NULL;
 
-    if (!Matrix_Check(A)) err_mtrx("A"); 
-    if (n < 0){ 
+    if (!Matrix_Check(A)) err_mtrx("A");
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -5430,33 +6198,33 @@ static PyObject* gees(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oA + (n-1)*ldA + n > len(A)) err_buf_len("A");
 
     if (W){
-        if (!Matrix_Check(W) || MAT_ID(W) != COMPLEX) 
-            PY_ERR_TYPE("W must be a matrix with typecode 'z'") 
+        if (!Matrix_Check(W) || MAT_ID(W) != COMPLEX)
+            PY_ERR_TYPE("W must be a matrix with typecode 'z'")
         if (oW < 0) err_nn_int("offsetW");
         if (oW + n > len(W)) err_buf_len("W");
     }
 
     if (Vs){
         if (!Matrix_Check(Vs)) err_mtrx("Vs");
-        if (MAT_ID(Vs) != MAT_ID(A)) err_conflicting_ids; 
+        if (MAT_ID(Vs) != MAT_ID(A)) err_conflicting_ids;
         if (ldVs == 0) ldVs = MAX(1, Vs->nrows);
         if (ldVs < MAX(1,n)) err_ld("ldVs");
         if (oVs < 0) err_nn_int("offsetVs");
-        if (oVs + (n-1)*ldVs + n > len(Vs)) err_buf_len("Vs"); 
+        if (oVs + (n-1)*ldVs + n > len(Vs)) err_buf_len("Vs");
     } else {
         if (ldVs == 0) ldVs = 1;
         if (ldVs < 1) err_ld("ldVs");
     }
 
-    if (F && !PyFunction_Check(F)) 
-        PY_ERR_TYPE("select must be a Python function") 
+    if (F && !PyFunction_Check(F))
+        PY_ERR_TYPE("select must be a Python function")
 
 
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
-            dgees_(Vs ? "V" : "N", F ? "S" : "N", NULL, &n, NULL, &ldA, 
-                &sdim, NULL, NULL, NULL, &ldVs, &wl.d, &lwork, NULL, 
+            dgees_(Vs ? "V" : "N", F ? "S" : "N", NULL, &n, NULL, &ldA,
+                &sdim, NULL, NULL, NULL, &ldVs, &wl.d, &lwork, NULL,
                 &info);
             lwork = (int) wl.d;
             work = (void *) calloc(lwork, sizeof(double));
@@ -5468,9 +6236,9 @@ static PyObject* gees(PyObject *self, PyObject *args, PyObject *kwrds)
                 return PyErr_NoMemory();
             }
             py_select_r = F;
-            dgees_(Vs ? "V": "N", F ? "S" : "N", F ? &fselect_r : NULL, 
-                &n, MAT_BUFD(A) + oA, &ldA, &sdim, wr, wi, 
-                Vs ? MAT_BUFD(Vs) + oVs : NULL, &ldVs, (double *) work, 
+            dgees_(Vs ? "V": "N", F ? "S" : "N", F ? &fselect_r : NULL,
+                &n, MAT_BUFD(A) + oA, &ldA, &sdim, wr, wi,
+                Vs ? MAT_BUFD(Vs) + oVs : NULL, &ldVs, (double *) work,
                 &lwork, bwork, &info);
             if (W) for (k=0; k<n; k++)
                 MAT_BUFZ(W)[oW + k] = wr[k] + I * wi[k];
@@ -5479,22 +6247,22 @@ static PyObject* gees(PyObject *self, PyObject *args, PyObject *kwrds)
 
 	case COMPLEX:
             lwork = -1;
-            zgees_(Vs ? "V" : "N", F ? "S": "N", NULL, &n, NULL, &ldA, 
-                &sdim, NULL, NULL, &ldVs, &wl.z, &lwork, NULL, NULL, 
+            zgees_(Vs ? "V" : "N", F ? "S": "N", NULL, &n, NULL, &ldA,
+                &sdim, NULL, NULL, &ldVs, &wl.z, &lwork, NULL, NULL,
                 &info);
             lwork = (int) creal(wl.z);
             work = (void *) calloc(lwork, sizeof(complex));
             rwork = (double *) calloc(n, sizeof(complex));
             if (F) bwork = (int *) calloc(n, sizeof(int));
             if (!W) w = (complex *) calloc(n, sizeof(complex));
-	    if (!work || !rwork || (F && !bwork) || (!W && !w) ){ 
-                free(work);  free(rwork); free(bwork);  free(w); 
+	    if (!work || !rwork || (F && !bwork) || (!W && !w) ){
+                free(work);  free(rwork); free(bwork);  free(w);
                 return PyErr_NoMemory();
             }
             py_select_c = F;
-            zgees_(Vs ? "V": "N", F ? "S" : "N", F ? &fselect_c : NULL, 
-                &n, MAT_BUFZ(A) + oA, &ldA, &sdim, 
-                W ? MAT_BUFZ(W) + oW : w, Vs ? MAT_BUFZ(Vs) + oVs : NULL, 
+            zgees_(Vs ? "V": "N", F ? "S" : "N", F ? &fselect_c : NULL,
+                &n, MAT_BUFZ(A) + oA, &ldA, &sdim,
+                W ? MAT_BUFZ(W) + oW : w, Vs ? MAT_BUFZ(Vs) + oVs : NULL,
                 &ldVs, (complex *) work, &lwork, (complex *) rwork,  bwork,
                  &info);
             free(work);  free(rwork); free(bwork);  free(w);
@@ -5511,7 +6279,7 @@ static PyObject* gees(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_gges[] = 
+static char doc_gges[] =
     "Generalized Schur factorization of real or complex matrices.\n\n"
     "sdim = gges(A, B, a=None, b=None, Vl=None, Vr=None, select=None,\n"
     "            n=A.size[0], ldA=max(1,A.size[0]),\n"
@@ -5532,17 +6300,17 @@ static char doc_gges[] =
     "provided then the right Schur vectors are computed and returned \n"
     "in Vr.  The argument select can be used to obtain an ordered Schur\n"
     "factorization.  It must be a Python function that can be called as\n"
-    "f(u,v) with u complex, and v real, and returns 0 or 1.  The \n" 
+    "f(u,v) with u complex, and v real, and returns 0 or 1.  The \n"
     "eigenvalues u/v for which f(u, v) is 1 will be placed first on the\n"
     "diagonal of S and T.  For the real case, eigenvalues u/v for which\n"
     "f(u, v) or f(conj(u), v) is 1, are placed first.  If select is \n"
     "provided, gges() returns the number of eigenvalues that satisfy the\n"
-    "selection criterion.  Otherwise, it returns 0.\n\n"  
+    "selection criterion.  Otherwise, it returns 0.\n\n"
     "ARGUMENTS\n"
-    "A         'd' or 'z' matrix\n\n"  
-    "B         'd' or 'z' matrix.  Must have the same type as A.\n\n"  
-    "a         'z' matrix of length at least n\n\n"  
-    "b         'd' matrix of length at least n\n\n"  
+    "A         'd' or 'z' matrix\n\n"
+    "B         'd' or 'z' matrix.  Must have the same type as A.\n\n"
+    "a         'z' matrix of length at least n\n\n"
+    "b         'd' matrix of length at least n\n\n"
     "Vl        'd' or 'z' matrix.  Must have the same type as A.\n\n"
     "Vr        'd' or 'z' matrix.  Must have the same type as A.\n\n"
     "select    Python function that takes a complex and a real number \n"
@@ -5579,12 +6347,12 @@ extern int fselect_gc(complex *w, double *v)
    vpy = PyFloat_FromDouble(*v);
    if (!(result = PyObject_CallFunctionObjArgs(py_select_gc, wpy, vpy,
        NULL))) {
-       Py_XDECREF(wpy); Py_XDECREF(vpy); 
+       Py_XDECREF(wpy); Py_XDECREF(vpy);
        return -1;
    }
    if PyInt_Check(result)
-       a = (int) PyInt_AsLong(result);  
-   else 
+       a = (int) PyInt_AsLong(result);
+   else
        PyErr_SetString(PyExc_TypeError, "select() must return an integer "
            "argument");
    Py_XDECREF(wpy);  Py_XDECREF(vpy);  Py_XDECREF(result);
@@ -5598,14 +6366,14 @@ extern int fselect_gr(double *wr, double *wi, double *v)
 
    wpy = PyComplex_FromDoubles(*wr, *wi);
    vpy = PyFloat_FromDouble(*v);
-   if (!(result = PyObject_CallFunctionObjArgs(py_select_gr, wpy, vpy, 
+   if (!(result = PyObject_CallFunctionObjArgs(py_select_gr, wpy, vpy,
        NULL))) {
        Py_XDECREF(wpy); Py_XDECREF(vpy);
        return -1;
    }
    if PyInt_Check(result)
-       a = (int) PyInt_AsLong(result);  
-   else 
+       a = (int) PyInt_AsLong(result);
+   else
        PyErr_SetString(PyExc_TypeError, "select() must return an integer "
            "argument");
    Py_XDECREF(wpy);  Py_XDECREF(vpy);  Py_XDECREF(result);
@@ -5615,26 +6383,26 @@ extern int fselect_gr(double *wr, double *wi, double *v)
 static PyObject* gges(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     PyObject *F=NULL;
-    matrix *A, *B, *a=NULL, *b=NULL, *Vsl=NULL, *Vsr=NULL; 
-    int n=-1, ldA=0, ldB=0, ldVsl=0, ldVsr=0, oA=0, oB=0, oa=0, ob=0, 
-        oVsl=0, oVsr=0, info, lwork, sdim, k, *bwork=NULL; 
+    matrix *A, *B, *a=NULL, *b=NULL, *Vsl=NULL, *Vsr=NULL;
+    int n=-1, ldA=0, ldB=0, ldVsl=0, ldVsr=0, oA=0, oB=0, oa=0, ob=0,
+        oVsl=0, oVsr=0, info, lwork, sdim, k, *bwork=NULL;
     double *ar=NULL, *ai=NULL, *rwork=NULL;
-    complex *ac=NULL; 
+    complex *ac=NULL;
     void *work=NULL, *bc=NULL;
     number wl;
 
-    char *kwlist[] = {"A", "B", "a", "b", "Vl", "Vr", "select", "n", 
-        "ldA", "ldB", "ldVl", "ldVr", "offsetA", "offsetB", "offseta", 
+    char *kwlist[] = {"A", "B", "a", "b", "Vl", "Vr", "select", "n",
+        "ldA", "ldB", "ldVl", "ldVr", "offsetA", "offsetB", "offseta",
         "offsetb", "offsetVl", "offsetVr", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|OOOOOiiiiiiiiiii",
-        kwlist, &A, &B, &a, &b, &Vsl, &Vsr, &F, &n, &ldA, &ldB, &ldVsl, 
+        kwlist, &A, &B, &a, &b, &Vsl, &Vsr, &F, &n, &ldA, &ldB, &ldVsl,
         &ldVsr, &oA, &oB, &oa, &ob, &oVsl, &oVsr)) return NULL;
 
-    if (!Matrix_Check(A)) err_mtrx("A"); 
+    if (!Matrix_Check(A)) err_mtrx("A");
     if (!Matrix_Check(B)) err_mtrx("B");
-    if (MAT_ID(B) != MAT_ID(A)) err_conflicting_ids; 
-    if (n < 0){ 
+    if (MAT_ID(B) != MAT_ID(A)) err_conflicting_ids;
+    if (n < 0){
         n = A->nrows;
         if (n != A->ncols){
             PyErr_SetString(PyExc_TypeError, "A must be square");
@@ -5656,8 +6424,8 @@ static PyObject* gges(PyObject *self, PyObject *args, PyObject *kwrds)
     if (oB + (n-1)*ldB + n > len(B)) err_buf_len("B");
 
     if (a){
-        if (!Matrix_Check(a) || MAT_ID(a) != COMPLEX) 
-            PY_ERR_TYPE("a must be a matrix with typecode 'z'") 
+        if (!Matrix_Check(a) || MAT_ID(a) != COMPLEX)
+            PY_ERR_TYPE("a must be a matrix with typecode 'z'")
         if (oa < 0) err_nn_int("offseta");
         if (oa + n > len(a)) err_buf_len("a");
         if (!b){
@@ -5667,8 +6435,8 @@ static PyObject* gges(PyObject *self, PyObject *args, PyObject *kwrds)
         }
     }
     if (b){
-        if (!Matrix_Check(b) || MAT_ID(b) != DOUBLE) 
-            PY_ERR_TYPE("b must be a matrix with typecode 'd'") 
+        if (!Matrix_Check(b) || MAT_ID(b) != DOUBLE)
+            PY_ERR_TYPE("b must be a matrix with typecode 'd'")
         if (ob < 0) err_nn_int("offsetb");
         if (ob + n > len(b)) err_buf_len("b");
         if (!a){
@@ -5680,11 +6448,11 @@ static PyObject* gges(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (Vsl){
         if (!Matrix_Check(Vsl)) err_mtrx("Vsl");
-        if (MAT_ID(Vsl) != MAT_ID(A)) err_conflicting_ids; 
+        if (MAT_ID(Vsl) != MAT_ID(A)) err_conflicting_ids;
         if (ldVsl == 0) ldVsl = MAX(1, Vsl->nrows);
         if (ldVsl < MAX(1,n)) err_ld("ldVsl");
         if (oVsl < 0) err_nn_int("offsetVsl");
-        if (oVsl + (n-1)*ldVsl + n > len(Vsl)) err_buf_len("Vsl"); 
+        if (oVsl + (n-1)*ldVsl + n > len(Vsl)) err_buf_len("Vsl");
     } else {
         if (ldVsl == 0) ldVsl = 1;
         if (ldVsl < 1) err_ld("ldVsl");
@@ -5692,25 +6460,25 @@ static PyObject* gges(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (Vsr){
         if (!Matrix_Check(Vsr)) err_mtrx("Vsr");
-        if (MAT_ID(Vsr) != MAT_ID(A)) err_conflicting_ids; 
+        if (MAT_ID(Vsr) != MAT_ID(A)) err_conflicting_ids;
         if (ldVsr == 0) ldVsr = MAX(1, Vsr->nrows);
         if (ldVsr < MAX(1,n)) err_ld("ldVsr");
         if (oVsr < 0) err_nn_int("offsetVsr");
-        if (oVsr + (n-1)*ldVsr + n > len(Vsr)) err_buf_len("Vsr"); 
+        if (oVsr + (n-1)*ldVsr + n > len(Vsr)) err_buf_len("Vsr");
     } else {
         if (ldVsr == 0) ldVsr = 1;
         if (ldVsr < 1) err_ld("ldVsr");
     }
 
-    if (F && !PyFunction_Check(F)) 
-        PY_ERR_TYPE("select must be a Python function") 
+    if (F && !PyFunction_Check(F))
+        PY_ERR_TYPE("select must be a Python function")
 
     switch (MAT_ID(A)){
         case DOUBLE:
             lwork = -1;
             dgges_(Vsl ? "V" : "N", Vsr ? "V" : "N", F ? "S" : "N", NULL,
                 &n, NULL, &ldA, NULL, &ldB, &sdim, NULL, NULL, NULL, NULL,
-                &ldVsl, NULL, &ldVsr, &wl.d, &lwork, NULL, &info); 
+                &ldVsl, NULL, &ldVsr, &wl.d, &lwork, NULL, &info);
             lwork = (int) wl.d;
             work = (void *) calloc(lwork, sizeof(double));
             ar = (double *) calloc(n, sizeof(double));
@@ -5722,12 +6490,12 @@ static PyObject* gges(PyObject *self, PyObject *args, PyObject *kwrds)
                 return PyErr_NoMemory();
             }
             py_select_gr = F;
-            dgges_(Vsl ? "V" : "N", Vsr ? "V" : "N", F ? "S" : "N", 
-                F ? &fselect_gr : NULL, &n, MAT_BUFD(A) + oA, &ldA, 
-                MAT_BUFD(B) + oB, &ldB, &sdim, ar, ai, 
-                b ? MAT_BUFD(b) + ob : (double *) bc, 
-                Vsl ? MAT_BUFD(Vsl) + oVsl : NULL, &ldVsl, 
-                Vsr ? MAT_BUFD(Vsr) + oVsr : NULL, &ldVsr, 
+            dgges_(Vsl ? "V" : "N", Vsr ? "V" : "N", F ? "S" : "N",
+                F ? &fselect_gr : NULL, &n, MAT_BUFD(A) + oA, &ldA,
+                MAT_BUFD(B) + oB, &ldB, &sdim, ar, ai,
+                b ? MAT_BUFD(b) + ob : (double *) bc,
+                Vsl ? MAT_BUFD(Vsl) + oVsl : NULL, &ldVsl,
+                Vsr ? MAT_BUFD(Vsr) + oVsr : NULL, &ldVsr,
                 (double *) work, &lwork, bwork, &info);
             if (a) for (k=0; k<n; k++)
                 MAT_BUFZ(a)[oa + k] = ar[k] + I * ai[k];
@@ -5737,7 +6505,7 @@ static PyObject* gges(PyObject *self, PyObject *args, PyObject *kwrds)
 	case COMPLEX:
             lwork = -1;
             zgges_(Vsl ? "V" : "N", Vsr ? "V" : "N", F ? "S" : "N", NULL,
-                &n, NULL, &ldA, NULL, &ldB, &sdim, NULL, NULL, NULL, 
+                &n, NULL, &ldA, NULL, &ldB, &sdim, NULL, NULL, NULL,
                 &ldVsl, NULL, &ldVsr, &wl.z, &lwork, NULL, NULL, &info);
             lwork = (int) creal(wl.z);
             work = (void *) calloc(lwork, sizeof(complex));
@@ -5750,11 +6518,11 @@ static PyObject* gges(PyObject *self, PyObject *args, PyObject *kwrds)
                 return PyErr_NoMemory();
             }
             py_select_gc = F;
-            zgges_(Vsl ? "V": "N", Vsr ? "V" : "N", F ? "S" : "N", 
-                F ? &fselect_gc : NULL, &n, MAT_BUFZ(A) + oA, &ldA, 
-                MAT_BUFZ(B) + oB, &ldB, &sdim, a ? MAT_BUFZ(a) + oa : ac, 
+            zgges_(Vsl ? "V": "N", Vsr ? "V" : "N", F ? "S" : "N",
+                F ? &fselect_gc : NULL, &n, MAT_BUFZ(A) + oA, &ldA,
+                MAT_BUFZ(B) + oB, &ldB, &sdim, a ? MAT_BUFZ(a) + oa : ac,
                 (complex *) bc, Vsl ? MAT_BUFZ(Vsl) + oVsl : NULL, &ldVsl,
-                Vsr ? MAT_BUFZ(Vsr) + oVsr : NULL, &ldVsr, 
+                Vsr ? MAT_BUFZ(Vsr) + oVsr : NULL, &ldVsr,
                 (complex *) work, &lwork, rwork,  bwork, &info);
             if (b) for (k=0; k<n; k++)
                 MAT_BUFD(b)[ob + k] = (double) creal(((complex *) bc)[k]);
@@ -5772,6 +6540,77 @@ static PyObject* gges(PyObject *self, PyObject *args, PyObject *kwrds)
     else return Py_BuildValue("i", F ? sdim : 0);
 }
 
+
+static char doc_lacpy[] =
+"Copy all or part of a matrix.\n\n"
+"lacpy(A, B, uplo='N', m=A.size[0], n=A.size[1], ldA=max(1,A.size[0]),\n"
+"      ldB=max(1,B.size[0]), offsetA=0, offsetB=0)\n\n"
+"PURPOSE\n"
+"Copy the m x n matrix A to B.  If uplo is 'U', the upper trapezoidal\n"
+"part of A is copied.  If uplo is 'L', the lower trapezoidal part is\n"
+"copied.  if uplo is 'N', the entire matrix is copied.\n\n"
+"ARGUMENTS\n"
+"A         'd' or 'z' matrix\n\n"
+"B         'd' or 'z' matrix.  Must have the same type as A.\n\n"
+"uplo      'N', 'L' or 'U'\n\n"
+"m         nonnegative integer.  If negative, the default value is used.\n"
+"\n"
+"n         nonnegative integer.  If negative, the default value is used.\n"
+"\n"
+"ldA       positive integer.  ldA >= max(1,m).  If zero, the default\n"
+"          value is used.\n\n"
+"ldB       positive integer.  ldB >= max(1,m).  If zero, the default\n"
+"          value is used.\n\n"
+"offsetA   nonnegative integer\n\n"
+"offsetB   nonnegative integer";
+
+static PyObject* lacpy(PyObject *self, PyObject *args, PyObject *kwrds)
+{
+    matrix *A, *B;
+    int m = -1, n = -1, ldA = 0, ldB = 0, oA = 0, oB = 0;
+    char uplo = 'N';
+    char *kwlist[] = {"A", "B", "uplo", "m", "n", "ldA", "ldB", "offsetA",
+        "offsetB", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciiiiii", kwlist,
+        &A, &B, &uplo, &m, &n, &ldA, &ldB, &oA, &oB))
+        return NULL;
+
+    if (!Matrix_Check(A)) err_mtrx("A");
+    if (!Matrix_Check(B)) err_mtrx("B");
+    if (MAT_ID(A) != MAT_ID(B)) err_conflicting_ids;
+    if (uplo != 'N' && uplo != 'L' && uplo != 'U')
+        err_char("trans", "'N', 'L', 'U'");
+    if (m < 0) m = A->nrows;
+    if (n < 0) n = A->ncols;
+    if (ldA == 0) ldA = MAX(1, A->nrows);
+    if (ldA < MAX(1, m)) err_ld("ldA");
+    if (ldB == 0) ldB = MAX(1, B->nrows);
+    if (ldB < MAX(1, m)) err_ld("ldB");
+    if (oA < 0) err_nn_int("offsetA");
+    if (oA + (n-1)*ldA + m > len(A)) err_buf_len("A");
+    if (oB < 0) err_nn_int("offsetB");
+    if (oB + (n-1)*ldB + m > len(B)) err_buf_len("B");
+
+    switch (MAT_ID(A)){
+        case DOUBLE:
+            dlacpy_(&uplo, &m, &n, MAT_BUFD(A)+oA, &ldA, MAT_BUFD(B)+oB,
+                &ldB);
+            break;
+
+        case COMPLEX:
+            zlacpy_(&uplo, &m, &n, MAT_BUFZ(A)+oA, &ldA, MAT_BUFZ(B)+oB,
+                &ldB);
+            break;
+
+	default:
+            err_invalid_id;
+    }
+
+    return Py_BuildValue("");
+}
+
+
 static PyMethodDef lapack_functions[] = {
 {"getrf", (PyCFunction) getrf, METH_VARARGS|METH_KEYWORDS, doc_getrf},
 {"getrs", (PyCFunction) getrs, METH_VARARGS|METH_KEYWORDS, doc_getrs},
@@ -5808,6 +6647,13 @@ static PyMethodDef lapack_functions[] = {
 {"geqrf", (PyCFunction) geqrf, METH_VARARGS|METH_KEYWORDS, doc_geqrf},
 {"ormqr", (PyCFunction) ormqr, METH_VARARGS|METH_KEYWORDS, doc_ormqr},
 {"unmqr", (PyCFunction) unmqr, METH_VARARGS|METH_KEYWORDS, doc_unmqr},
+{"orgqr", (PyCFunction) orgqr, METH_VARARGS|METH_KEYWORDS, doc_orgqr},
+{"ungqr", (PyCFunction) ungqr, METH_VARARGS|METH_KEYWORDS, doc_ungqr},
+{"gelqf", (PyCFunction) gelqf, METH_VARARGS|METH_KEYWORDS, doc_gelqf},
+{"ormlq", (PyCFunction) ormlq, METH_VARARGS|METH_KEYWORDS, doc_ormlq},
+{"unmlq", (PyCFunction) unmlq, METH_VARARGS|METH_KEYWORDS, doc_unmlq},
+{"orglq", (PyCFunction) orglq, METH_VARARGS|METH_KEYWORDS, doc_orglq},
+{"unglq", (PyCFunction) unglq, METH_VARARGS|METH_KEYWORDS, doc_unglq},
 {"syev",  (PyCFunction) syev,  METH_VARARGS|METH_KEYWORDS, doc_syev},
 {"heev",  (PyCFunction) heev,  METH_VARARGS|METH_KEYWORDS, doc_heev},
 {"syevx", (PyCFunction) syevx, METH_VARARGS|METH_KEYWORDS, doc_syevx},
@@ -5822,6 +6668,8 @@ static PyMethodDef lapack_functions[] = {
 {"gesdd", (PyCFunction) gesdd, METH_VARARGS|METH_KEYWORDS, doc_gesdd},
 {"gees", (PyCFunction) gees, METH_VARARGS|METH_KEYWORDS, doc_gees},
 {"gges", (PyCFunction) gges, METH_VARARGS|METH_KEYWORDS, doc_gges},
+{"lacpy", (PyCFunction) lacpy, METH_VARARGS|METH_KEYWORDS, doc_lacpy},
+{"geqp3", (PyCFunction) geqp3, METH_VARARGS|METH_KEYWORDS, doc_geqp3},
 {NULL}  /* Sentinel */
 };
 
diff --git a/src/C/misc.h b/src/C/misc.h
index ffefba2..de57b33 100644
--- a/src/C/misc.h
+++ b/src/C/misc.h
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -42,9 +42,9 @@ typedef union {
 #define OUT_RNG(i, dim) (i < -dim || i >= dim)
 
 
-#define VALID_TC_MAT(t) (t=='i' || t=='d' || t=='z') 
-#define VALID_TC_SP(t)  (t=='d' || t=='z') 
-#define TC2ID(c) (c=='i' ? 0 : (c=='d' ? 1 : 2)) 
+#define VALID_TC_MAT(t) (t=='i' || t=='d' || t=='z')
+#define VALID_TC_SP(t)  (t=='d' || t=='z')
+#define TC2ID(c) (c=='i' ? 0 : (c=='d' ? 1 : 2))
 
 #define X_ID(O)    (Matrix_Check(O) ? MAT_ID(O)    : SP_ID(O))
 #define X_NROWS(O) (Matrix_Check(O) ? MAT_NROWS(O) : SP_NROWS(O))
@@ -58,7 +58,7 @@ typedef union {
 
 #define len(x) (Matrix_Check(x) ? MAT_LGT(x) : SP_LGT(x))
 
-#define err_mtrx(s) PY_ERR_TYPE(s " must be a matrix") 
+#define err_mtrx(s) PY_ERR_TYPE(s " must be a matrix")
 
 #define err_bool(s) PY_ERR_TYPE(s " must be True or False")
 
@@ -68,9 +68,9 @@ typedef union {
 #define err_invalid_id {PY_ERR_TYPE( \
 	"matrix arguments must have type 'd' or 'z'") }
 
-#define err_nz_int(s) PY_ERR_TYPE(s " must be a nonzero integer") 
+#define err_nz_int(s) PY_ERR_TYPE(s " must be a nonzero integer")
 
-#define err_nn_int(s) PY_ERR_TYPE(s " must be a nonnegative integer") 
+#define err_nn_int(s) PY_ERR_TYPE(s " must be a nonnegative integer")
 
 #define err_buf_len(s) PY_ERR_TYPE("length of " s " is too small")
 
@@ -91,7 +91,7 @@ typedef union {
 #define err_dbl_mtrx(s) { \
     PY_ERR_TYPE(s " must be a matrix with typecode 'd'") }
 
-#define err_CO(s) PY_ERR_TYPE(s " is not a CObject") 
+#define err_CO(s) PY_ERR_TYPE(s " is not a CObject")
 
 
 #define err_msk_noparam "missing options dictionary"
diff --git a/src/C/misc_solvers.c b/src/C/misc_solvers.c
index 588e97d..05a09d0 100644
--- a/src/C/misc_solvers.c
+++ b/src/C/misc_solvers.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,34 +30,34 @@ extern void dcopy_(int *n, double *x, int *incx, double *y, int *incy);
 extern double dnrm2_(int *n, double *x, int *incx);
 extern double ddot_(int *n, double *x, int *incx, double *y, int *incy);
 extern void dscal_(int *n, double *alpha, double *x, int *incx);
-extern void daxpy_(int *n, double *alpha, double *x, int *incx, double *y, 
+extern void daxpy_(int *n, double *alpha, double *x, int *incx, double *y,
     int *incy);
-extern void dtbmv_(char *uplo, char *trans, char *diag, int *n, int *k,  
+extern void dtbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
     double *A, int *lda, double *x, int *incx);
-extern void dtbsv_(char *uplo, char *trans, char *diag, int *n, int *k, 
+extern void dtbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
     double *A, int *lda, double *x, int *incx);
-extern void dgemv_(char* trans, int *m, int *n, double *alpha, double *A, 
+extern void dgemv_(char* trans, int *m, int *n, double *alpha, double *A,
     int *lda, double *x, int *incx, double *beta, double *y, int *incy);
-extern void dger_(int *m, int *n, double *alpha, double *x, int *incx, 
+extern void dger_(int *m, int *n, double *alpha, double *x, int *incx,
     double *y, int *incy, double *A, int *lda);
-extern void dtrmm_(char *side, char *uplo, char *transa, char *diag, 
-    int *m, int *n, double *alpha, double *A, int *lda, double *B, 
+extern void dtrmm_(char *side, char *uplo, char *transa, char *diag,
+    int *m, int *n, double *alpha, double *A, int *lda, double *B,
     int *ldb);
 extern void dsyr2k_(char *uplo, char *trans, int *n, int *k, double *alpha,
-    double *A, int *lda, double *B, int *ldb, double *beta, double *C, 
+    double *A, int *lda, double *B, int *ldb, double *beta, double *C,
     int *ldc);
-extern void dlacpy_(char *uplo, int *m, int *n, double *A, int *lda, 
+extern void dlacpy_(char *uplo, int *m, int *n, double *A, int *lda,
     double *B, int *ldb);
 extern void dsyevr_(char *jobz, char *range, char *uplo, int *n, double *A,
-    int *ldA, double *vl, double *vu, int *il, int *iu, double *abstol, 
-    int *m, double *W, double *Z, int *ldZ, int *isuppz, double *work, 
-    int *lwork, int *iwork, int *liwork, int *info); 
-extern void dsyevd_(char *jobz, char *uplo, int *n, double *A, int *ldA, 
-    double *W, double *work, int *lwork, int *iwork, int *liwork, 
-    int *info); 
+    int *ldA, double *vl, double *vu, int *il, int *iu, double *abstol,
+    int *m, double *W, double *Z, int *ldZ, int *isuppz, double *work,
+    int *lwork, int *iwork, int *liwork, int *info);
+extern void dsyevd_(char *jobz, char *uplo, int *n, double *A, int *ldA,
+    double *W, double *work, int *lwork, int *iwork, int *liwork,
+    int *info);
 
 
-static char doc_scale[] = 
+static char doc_scale[] =
     "Applies Nesterov-Todd scaling or its inverse.\n\n"
     "scale(x, W, trans = 'N', inverse = 'N')\n\n"
     "Computes\n\n"
@@ -82,7 +82,7 @@ static char doc_scale[] =
 
 static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *d, *vk, *rk; 
+    matrix *x, *d, *vk, *rk;
     PyObject *W, *v, *beta, *r, *betak;
     char trans = 'N', inverse = 'N';
     int m, n, ind = 0, int0 = 0, int1 = 1, i, k, inc, len, ld, maxn, N;
@@ -90,27 +90,27 @@ static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
         *wrk;
     char *kwlist[] = {"x", "W", "trans", "inverse", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cc", kwlist, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|cc", kwlist,
         &x, &W, &trans, &inverse)) return NULL;
 
 
-    /* 
-     * Scaling for nonlinear component xk is xk := dnl .* xk; inverse is 
+    /*
+     * Scaling for nonlinear component xk is xk := dnl .* xk; inverse is
      * xk ./ dnl = dnli .* xk, where dnl = W['dnl'], dnli = W['dnli'].
      */
 
     if ((d = (inverse == 'N') ? (matrix *) PyDict_GetItemString(W, "dnl") :
-        (matrix *) PyDict_GetItemString(W, "dnli"))){ 
+        (matrix *) PyDict_GetItemString(W, "dnli"))){
         m = len(d);
         for (i = 0; i < x->ncols; i++)
-            dtbmv_("L", "N", "N", &m, &int0, MAT_BUFD(d), &int1, 
-                MAT_BUFD(x) + i*x->nrows, &int1); 
+            dtbmv_("L", "N", "N", &m, &int0, MAT_BUFD(d), &int1,
+                MAT_BUFD(x) + i*x->nrows, &int1);
         ind += m;
     }
 
 
     /*
-     * Scaling for 'l' component xk is xk := d .* xk; inverse scaling is 
+     * Scaling for 'l' component xk is xk := d .* xk; inverse scaling is
      * xk ./ d = di .* xk, where d = W['d'], di = W['di'].
      */
 
@@ -121,8 +121,8 @@ static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     m = len(d);
     for (i = 0; i < x->ncols; i++)
-        dtbmv_("L", "N", "N", &m, &int0, MAT_BUFD(d), &int1, MAT_BUFD(x) 
-            + i*x->nrows + ind, &int1); 
+        dtbmv_("L", "N", "N", &m, &int0, MAT_BUFD(d), &int1, MAT_BUFD(x)
+            + i*x->nrows + ind, &int1);
     ind += m;
 
 
@@ -131,7 +131,7 @@ static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
      *
      *     xk := beta * (2*v*v' - J) * xk
      *         = beta * (2*v*(xk'*v)' - J*xk)
-     * 
+     *
      * where beta = W['beta'][k], v = W['v'][k], J = [1, 0; 0, -I].
      *
      * Inverse scaling is
@@ -140,10 +140,10 @@ static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
      *        = 1/beta * (-J) * (2*v*((-J*xk)'*v)' + xk).
      */
 
-    v = PyDict_GetItemString(W, "v"); 
+    v = PyDict_GetItemString(W, "v");
     beta = PyDict_GetItemString(W, "beta");
     N = (int) PyList_Size(v);
-    if (!(wrk = (double *) calloc(x->ncols, sizeof(double)))) 
+    if (!(wrk = (double *) calloc(x->ncols, sizeof(double))))
         return PyErr_NoMemory();
     for (k = 0; k < N; k++){
         vk = (matrix *) PyList_GetItem(v, (Py_ssize_t) k);
@@ -151,10 +151,10 @@ static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
         if (inverse == 'I')
             dscal_(&(x->ncols), &dblm1, MAT_BUFD(x) + ind, &(x->nrows));
         ld = MAX(x->nrows, 1);
-        dgemv_("T", &m, &(x->ncols), &dbl1, MAT_BUFD(x) + ind, &ld, 
+        dgemv_("T", &m, &(x->ncols), &dbl1, MAT_BUFD(x) + ind, &ld,
             MAT_BUFD(vk), &int1, &dbl0, wrk, &int1);
         dscal_(&(x->ncols), &dblm1, MAT_BUFD(x) + ind, &(x->nrows));
-        dger_(&m, &(x->ncols), &dbl2, MAT_BUFD(vk), &int1, wrk, &int1, 
+        dger_(&m, &(x->ncols), &dbl2, MAT_BUFD(vk), &int1, wrk, &int1,
             MAT_BUFD(x) + ind, &ld);
         if (inverse == 'I')
             dscal_(&(x->ncols), &dblm1, MAT_BUFD(x) + ind, &(x->nrows));
@@ -162,9 +162,9 @@ static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
         betak = PyList_GetItem(beta, (Py_ssize_t) k);
         b = PyFloat_AS_DOUBLE(betak);
         if (inverse == 'I') b = 1.0 / b;
-        for (i = 0; i < x->ncols; i++) 
+        for (i = 0; i < x->ncols; i++)
             dscal_(&m, &b, MAT_BUFD(x) + ind + i*x->nrows, &int1);
-        ind += m; 
+        ind += m;
     }
     free(wrk);
 
@@ -174,9 +174,9 @@ static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
      *
      *     xk := vec( r' * mat(xk) * r )  if trans = 'N'
      *     xk := vec( r * mat(xk) * r' )  if trans = 'T'.
-     * 
+     *
      * r is kth element of W['r'].
-     * 
+     *
      * Inverse scaling is
      *
      *     xk := vec( rti * mat(xk) * rti' )  if trans = 'N'
@@ -185,14 +185,14 @@ static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
      * rti is kth element of W['rti'].
      */
 
-    r = (inverse == 'N') ? PyDict_GetItemString(W, "r") : 
+    r = (inverse == 'N') ? PyDict_GetItemString(W, "r") :
         PyDict_GetItemString(W, "rti");
     N = (int) PyList_Size(r);
     for (k = 0, maxn = 0; k < N; k++){
         rk = (matrix *) PyList_GetItem(r, (Py_ssize_t) k);
         maxn = MAX(maxn, rk->nrows);
     }
-    if (!(wrk = (double *) calloc(maxn*maxn, sizeof(double)))) 
+    if (!(wrk = (double *) calloc(maxn*maxn, sizeof(double))))
         return PyErr_NoMemory();
     for (k = 0; k < N; k++){
         rk = (matrix *) PyList_GetItem(r, (Py_ssize_t) k);
@@ -203,23 +203,23 @@ static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
             inc = n + 1;
             dscal_(&n, &dbl5, MAT_BUFD(x) + ind + i*x->nrows, &inc);
 
-            /* wrk = r*tril(x) if inverse is 'N' and trans is 'T' or 
+            /* wrk = r*tril(x) if inverse is 'N' and trans is 'T' or
              *                 inverse is 'I' and trans is 'N'
              * wrk = tril(x)*r otherwise. */
             len = n*n;
             dcopy_(&len, MAT_BUFD(rk), &int1, wrk, &int1);
             ld = MAX(1, n);
-            dtrmm_( (( inverse == 'N' && trans == 'T') || ( inverse == 'I' 
-                && trans == 'N')) ? "R" : "L", "L", "N", "N", &n, &n, 
+            dtrmm_( (( inverse == 'N' && trans == 'T') || ( inverse == 'I'
+                && trans == 'N')) ? "R" : "L", "L", "N", "N", &n, &n,
                 &dbl1, MAT_BUFD(x) + ind + i*x->nrows, &ld, wrk, &ld);
 
-            /* x := (r*wrk' + wrk*r') if inverse is 'N' and trans is 'T' 
-             *                        or inverse is 'I' and trans is 'N' 
-             * x := (r'*wrk + wrk'*r) otherwise. */                       
-            dsyr2k_("L", ((inverse == 'N' && trans == 'T') || 
-                (inverse == 'I' && trans == 'N')) ? "N" : "T", &n, &n, 
-                &dbl1, MAT_BUFD(rk), &ld, wrk, &ld, &dbl0, MAT_BUFD(x) + 
-                ind + i*x->nrows, &ld);            
+            /* x := (r*wrk' + wrk*r') if inverse is 'N' and trans is 'T'
+             *                        or inverse is 'I' and trans is 'N'
+             * x := (r'*wrk + wrk'*r) otherwise. */
+            dsyr2k_("L", ((inverse == 'N' && trans == 'T') ||
+                (inverse == 'I' && trans == 'N')) ? "N" : "T", &n, &n,
+                &dbl1, MAT_BUFD(rk), &ld, wrk, &ld, &dbl0, MAT_BUFD(x) +
+                ind + i*x->nrows, &ld);
         }
         ind += n*n;
     }
@@ -229,19 +229,19 @@ static PyObject* scale(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_scale2[] = 
+static char doc_scale2[] =
     "Multiplication with square root of the Hessian.\n\n"
     "scale2(lmbda, x, dims, mnl = 0, inverse = 'N')\n\n"
     "Computes\n\n"
     "Evaluates\n\n"
-    "    x := H(lambda^{1/2}) * x   (inverse is 'N')\n" 
+    "    x := H(lambda^{1/2}) * x   (inverse is 'N')\n"
     "    x := H(lambda^{-1/2}) * x  (inverse is 'I').\n\n"
     "H is the Hessian of the logarithmic barrier.";
 
 static PyObject* scale2(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *lmbda, *x;
-    PyObject *dims, *O, *Ok; 
+    PyObject *dims, *O, *Ok;
     char inverse = 'N';
     double a, lx, x0, b, *c = NULL, *sql = NULL;
     int m = 0, mk, i, j, len, int0 = 0, int1 = 1, maxn = 0, ind2;
@@ -251,37 +251,37 @@ static PyObject* scale2(PyObject *self, PyObject *args, PyObject *kwrds)
         &x, &dims, &m, &inverse)) return NULL;
 
 
-    /* 
-     * For nonlinear and 'l' blocks: 
-     * 
-     *     xk := xk ./ l  (invers is 'N') 
-     *     xk := xk .* l  (invers is 'I') 
+    /*
+     * For nonlinear and 'l' blocks:
+     *
+     *     xk := xk ./ l  (invers is 'N')
+     *     xk := xk .* l  (invers is 'I')
      *
      * where l is the first mnl + dims['l'] components of lmbda.
      */
 
     O = PyDict_GetItemString(dims, "l");
     m += (int) PyInt_AsLong(O);
-    if (inverse == 'N') 
-        dtbsv_("L", "N", "N", &m, &int0, MAT_BUFD(lmbda), &int1, 
-             MAT_BUFD(x), &int1); 
+    if (inverse == 'N')
+        dtbsv_("L", "N", "N", &m, &int0, MAT_BUFD(lmbda), &int1,
+             MAT_BUFD(x), &int1);
     else
-        dtbmv_("L", "N", "N", &m, &int0, MAT_BUFD(lmbda), &int1, 
-             MAT_BUFD(x), &int1); 
+        dtbmv_("L", "N", "N", &m, &int0, MAT_BUFD(lmbda), &int1,
+             MAT_BUFD(x), &int1);
 
 
     /*
-     * For 'q' blocks, if inverse is 'N', 
-     *    
-     *     xk := 1/a * [ l'*J*xk;  
+     * For 'q' blocks, if inverse is 'N',
+     *
+     *     xk := 1/a * [ l'*J*xk;
      *         xk[1:] - (xk[0] + l'*J*xk) / (l[0] + 1) * l[1:] ].
-     *     
-     *  If inverse is 'I', 
-     *    
-     *     xk := a * [ l'*xk; 
+     *
+     *  If inverse is 'I',
+     *
+     *     xk := a * [ l'*xk;
      *         xk[1:] + (xk[0] + l'*xk) / (l[0] + 1) * l[1:] ].
-     *    
-     * a = sqrt(lambda_k' * J * lambda_k), l = lambda_k / a. 
+     *
+     * a = sqrt(lambda_k' * J * lambda_k), l = lambda_k / a.
      */
 
     O = PyDict_GetItemString(dims, "q");
@@ -292,17 +292,17 @@ static PyObject* scale2(PyObject *self, PyObject *args, PyObject *kwrds)
         a = dnrm2_(&len, MAT_BUFD(lmbda) + m + 1, &int1);
         a = sqrt(MAT_BUFD(lmbda)[m] + a) * sqrt(MAT_BUFD(lmbda)[m] - a);
         if (inverse == 'N')
-            lx = ( MAT_BUFD(lmbda)[m] * MAT_BUFD(x)[m] - 
+            lx = ( MAT_BUFD(lmbda)[m] * MAT_BUFD(x)[m] -
                 ddot_(&len, MAT_BUFD(lmbda) + m + 1, &int1, MAT_BUFD(x) + m
                     + 1, &int1) ) / a;
-        else 
-            lx = ddot_(&mk, MAT_BUFD(lmbda) + m, &int1, MAT_BUFD(x) + m, 
+        else
+            lx = ddot_(&mk, MAT_BUFD(lmbda) + m, &int1, MAT_BUFD(x) + m,
                 &int1) / a;
         x0 = MAT_BUFD(x)[m];
         MAT_BUFD(x)[m] = lx;
         b = (x0 + lx) / (MAT_BUFD(lmbda)[m]/a + 1.0) / a;
         if (inverse == 'N')  b *= -1.0;
-        daxpy_(&len, &b, MAT_BUFD(lmbda) + m + 1, &int1, 
+        daxpy_(&len, &b, MAT_BUFD(lmbda) + m + 1, &int1,
             MAT_BUFD(x) + m + 1, &int1);
         if (inverse == 'N')  a = 1.0 / a;
         dscal_(&mk, &a, MAT_BUFD(x) + m, &int1);
@@ -312,15 +312,15 @@ static PyObject* scale2(PyObject *self, PyObject *args, PyObject *kwrds)
 
     /*
      *  For the 's' blocks, if inverse is 'N',
-     * 
+     *
      *      xk := vec( diag(l)^{-1/2} * mat(xk) * diag(k)^{-1/2}).
-     * 
+     *
      *  If inverse is 'I',
-     * 
+     *
      *     xk := vec( diag(l)^{1/2} * mat(xk) * diag(k)^{1/2}).
-     * 
+     *
      * where l is kth block of lambda.
-     * 
+     *
      * We scale upper and lower triangular part of mat(xk) because the
      * inverse operation will be applied to nonsymmetric matrices.
      */
@@ -346,11 +346,11 @@ static PyObject* scale2(PyObject *self, PyObject *args, PyObject *kwrds)
             b = sqrt(MAT_BUFD(lmbda)[ind2 + j]);
             dscal_(&mk, &b, c, &int1);
             if (inverse == 'N')
-                dtbsv_("L", "N", "N", &mk, &int0, c, &int1, MAT_BUFD(x) + 
-                    m + j*mk, &int1); 
+                dtbsv_("L", "N", "N", &mk, &int0, c, &int1, MAT_BUFD(x) +
+                    m + j*mk, &int1);
             else
-                dtbmv_("L", "N", "N", &mk, &int0, c, &int1, MAT_BUFD(x) + 
-                    m + j*mk, &int1); 
+                dtbmv_("L", "N", "N", &mk, &int0, c, &int1, MAT_BUFD(x) +
+                    m + j*mk, &int1);
         }
         m += mk*mk;
         ind2 += mk;
@@ -361,23 +361,23 @@ static PyObject* scale2(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_pack[] = 
+static char doc_pack[] =
     "Copy x to y using packed storage.\n\n"
     "pack(x, y, dims, mnl = 0, offsetx = 0, offsety = 0)\n\n"
-    "The vector x is an element of S, with the 's' components stored in\n" 
+    "The vector x is an element of S, with the 's' components stored in\n"
     "unpacked storage.  On return, x is copied to y with the 's' \n"
     "components stored in packed storage and the off-diagonal entries \n"
     "scaled by sqrt(2).";
 
 static PyObject* pack(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *y; 
+    matrix *x, *y;
     PyObject *O, *Ok, *dims;
     double a;
     int i, k, nlq = 0, ox = 0, oy = 0, np, iu, ip, int1 = 1, len, n;
     char *kwlist[] = {"x", "y", "dims", "mnl", "offsetx", "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|iii", kwlist, &x, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|iii", kwlist, &x,
         &y, &dims, &nlq, &ox, &oy)) return NULL;
 
     O = PyDict_GetItemString(dims, "l");
@@ -391,19 +391,19 @@ static PyObject* pack(PyObject *self, PyObject *args, PyObject *kwrds)
     dcopy_(&nlq, MAT_BUFD(x) + ox, &int1, MAT_BUFD(y) + oy, &int1);
 
     O = PyDict_GetItemString(dims, "s");
-    for (i = 0, np = 0, iu = ox + nlq, ip = oy + nlq; i < (int) 
+    for (i = 0, np = 0, iu = ox + nlq, ip = oy + nlq; i < (int)
         PyList_Size(O); i++){
         Ok = PyList_GetItem(O, (Py_ssize_t) i);
         n = (int) PyInt_AsLong(Ok);
         for (k = 0; k < n; k++){
             len = n-k;
-            dcopy_(&len, MAT_BUFD(x) + iu + k*(n+1), &int1,  MAT_BUFD(y) + 
+            dcopy_(&len, MAT_BUFD(x) + iu + k*(n+1), &int1,  MAT_BUFD(y) +
                 ip, &int1);
             MAT_BUFD(y)[ip] /= sqrt(2.0);
             ip += len;
         }
         np += n*(n+1)/2;
-        iu += n*n;        
+        iu += n*n;
     }
 
     a = sqrt(2.0);
@@ -413,23 +413,23 @@ static PyObject* pack(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_pack2[] = 
+static char doc_pack2[] =
     "In-place version of pack().\n\n"
     "pack2(x, y, dims, mnl = 0)\n\n"
     "In-place version of pack(), which also accepts matrix arguments x.\n"
     "The columns of x are elements of S, with the 's' components stored\n"
-    "in unpacked storage.  On return, the 's' components are stored in\n" 
+    "in unpacked storage.  On return, the 's' components are stored in\n"
     "packed storage and the off-diagonal entries are scaled by sqrt(2).";
 
 static PyObject* pack2(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x; 
+    matrix *x;
     PyObject *O, *Ok, *dims;
     double a = sqrt(2.0), *wrk;
     int i, j, k, nlq = 0, iu, ip, len, n, maxn;
     char *kwlist[] = {"x", "dims", "mnl", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|i", kwlist, &x, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|i", kwlist, &x,
         &dims, &nlq)) return NULL;
 
     O = PyDict_GetItemString(dims, "l");
@@ -459,11 +459,11 @@ static PyObject* pack2(PyObject *self, PyObject *args, PyObject *kwrds)
                 &(x->nrows), wrk, &maxn);
             for (j = 1; j < len; j++)
                 dscal_(&(x->ncols), &a, wrk + j, &maxn);
-            dlacpy_(" ", &len, &(x->ncols), wrk, &maxn, MAT_BUFD(x) + ip, 
+            dlacpy_(" ", &len, &(x->ncols), wrk, &maxn, MAT_BUFD(x) + ip,
                 &(x->nrows));
             ip += len;
         }
-        iu += n*n;        
+        iu += n*n;
     }
 
     free(wrk);
@@ -471,23 +471,23 @@ static PyObject* pack2(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_unpack[] = 
+static char doc_unpack[] =
     "Unpacks x into y.\n\n"
     "unpack(x, y, dims, mnl = 0, offsetx = 0, offsety = 0)\n\n"
-    "The vector x is an element of S, with the 's' components stored in\n" 
+    "The vector x is an element of S, with the 's' components stored in\n"
     "unpacked storage and off-diagonal entries scaled by sqrt(2).\n"
-    "On return, x is copied to y with the 's' components stored in\n" 
+    "On return, x is copied to y with the 's' components stored in\n"
     "unpacked storage.";
 
 static PyObject* unpack(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *y; 
+    matrix *x, *y;
     PyObject *O, *Ok, *dims;
-    double a = 1.0 / sqrt(2.0); 
+    double a = 1.0 / sqrt(2.0);
     int m = 0, ox = 0, oy = 0, int1 = 1, iu, ip, len, i, k, n;
     char *kwlist[] = {"x", "y", "dims", "mnl", "offsetx", "offsety", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|iii", kwlist, &x, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|iii", kwlist, &x,
         &y, &dims, &m, &ox, &oy)) return NULL;
 
     O = PyDict_GetItemString(dims, "l");
@@ -506,20 +506,20 @@ static PyObject* unpack(PyObject *self, PyObject *args, PyObject *kwrds)
         n = (int) PyInt_AsLong(Ok);
         for (k = 0; k < n; k++){
             len = n-k;
-            dcopy_(&len, MAT_BUFD(x) + ip, &int1, MAT_BUFD(y) + iu + 
-                k*(n+1), &int1);  
+            dcopy_(&len, MAT_BUFD(x) + ip, &int1, MAT_BUFD(y) + iu +
+                k*(n+1), &int1);
             ip += len;
             len -= 1;
             dscal_(&len, &a, MAT_BUFD(y) + iu + k*(n+1) + 1, &int1);
         }
-        iu += n*n;        
+        iu += n*n;
     }
 
     return Py_BuildValue("");
 }
 
 
-static char doc_symm[] = 
+static char doc_symm[] =
     "Converts lower triangular matrix to symmetric.\n\n"
     "symm(x, n, offset = 0)\n\n"
     "Fills in the upper triangular part of the symmetric matrix stored\n"
@@ -527,7 +527,7 @@ static char doc_symm[] =
 
 static PyObject* symm(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x; 
+    matrix *x;
     int n, ox = 0, k, len, int1 = 1;
     char *kwlist[] = {"x", "n", "offset", NULL};
 
@@ -536,14 +536,14 @@ static PyObject* symm(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (n > 1) for (k = 0; k < n; k++){
         len = n-k-1;
-        dcopy_(&len, MAT_BUFD(x) + ox + k*(n+1) + 1, &int1, MAT_BUFD(x) +  
+        dcopy_(&len, MAT_BUFD(x) + ox + k*(n+1) + 1, &int1, MAT_BUFD(x) +
             ox + (k+1)*(n+1)-1, &n);
     }
     return Py_BuildValue("");
 }
 
 
-static char doc_sprod[] = 
+static char doc_sprod[] =
     "The product x := (y o x).\n\n"
     "sprod(x, y, dims, mnl = 0, diag = 'N')\n\n"
     "If diag is 'D', the 's' part of y is diagonal and only the diagonal\n"
@@ -551,37 +551,37 @@ static char doc_sprod[] =
 
 static PyObject* sprod(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *y; 
+    matrix *x, *y;
     PyObject *dims, *O, *Ok;
     int i, j, k, mk, len, maxn, ind = 0, ind2, int0 = 0, int1 = 1, ld;
     double a, *A = NULL, dbl2 = 0.5, dbl0 = 0.0;
-    char diag = 'N'; 
+    char diag = 'N';
     char *kwlist[] = {"x", "y", "dims", "mnl", "diag", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ic", kwlist, &x, &y,
         &dims, &ind, &diag)) return NULL;
 
 
-    /* 
-     * For nonlinear and 'l' blocks: 
-     * 
-     *     yk o xk = yk .* xk 
+    /*
+     * For nonlinear and 'l' blocks:
+     *
+     *     yk o xk = yk .* xk
      */
 
     O = PyDict_GetItemString(dims, "l");
     ind += (int) PyInt_AsLong(O);
-    dtbmv_("L", "N", "N", &ind, &int0, MAT_BUFD(y), &int1, MAT_BUFD(x), 
-        &int1); 
+    dtbmv_("L", "N", "N", &ind, &int0, MAT_BUFD(y), &int1, MAT_BUFD(x),
+        &int1);
 
 
     /*
-     * For 'q' blocks: 
-     *    
+     * For 'q' blocks:
+     *
      *                [ l0   l1'  ]
      *     yk o xk =  [           ] * xk
      *                [ l1   l0*I ]
      *
-     * where yk = (l0, l1).     
+     * where yk = (l0, l1).
      */
 
     O = PyDict_GetItemString(dims, "q");
@@ -591,7 +591,7 @@ static PyObject* sprod(PyObject *self, PyObject *args, PyObject *kwrds)
         a = ddot_(&mk, MAT_BUFD(y) + ind, &int1, MAT_BUFD(x) + ind, &int1);
         len = mk - 1;
         dscal_(&len, MAT_BUFD(y) + ind, MAT_BUFD(x) + ind + 1, &int1);
-        daxpy_(&len, MAT_BUFD(x) + ind, MAT_BUFD(y) + ind + 1, &int1, 
+        daxpy_(&len, MAT_BUFD(x) + ind, MAT_BUFD(y) + ind + 1, &int1,
             MAT_BUFD(x) + ind + 1, &int1);
         MAT_BUFD(x)[ind] = a;
         ind += mk;
@@ -602,7 +602,7 @@ static PyObject* sprod(PyObject *self, PyObject *args, PyObject *kwrds)
      * For the 's' blocks:
      *
      *    yk o sk = .5 * ( Yk * mat(xk) + mat(xk) * Yk )
-     * 
+     *
      * where Yk = mat(yk) if diag is 'N' and Yk = diag(yk) if diag is 'D'.
      */
 
@@ -622,9 +622,9 @@ static PyObject* sprod(PyObject *self, PyObject *args, PyObject *kwrds)
 
             if (mk > 1) for (k = 0; k < mk; k++){
                 len = mk - k - 1;
-                dcopy_(&len, A + k*(mk+1) + 1, &int1, A + (k+1)*(mk+1)-1, 
+                dcopy_(&len, A + k*(mk+1) + 1, &int1, A + (k+1)*(mk+1)-1,
                     &mk);
-                dcopy_(&len, MAT_BUFD(y) + ind + k*(mk+1) + 1, &int1, 
+                dcopy_(&len, MAT_BUFD(y) + ind + k*(mk+1) + 1, &int1,
                     MAT_BUFD(y) + ind + (k+1)*(mk+1)-1, &mk);
             }
 
@@ -634,9 +634,9 @@ static PyObject* sprod(PyObject *self, PyObject *args, PyObject *kwrds)
         }
     }
     else {
-        if (!(A = (double *) calloc(maxn, sizeof(double)))) 
+        if (!(A = (double *) calloc(maxn, sizeof(double))))
             return PyErr_NoMemory();
-        for (i = 0, ind2 = ind; i < (int) PyList_Size(O); ind += mk*mk, 
+        for (i = 0, ind2 = ind; i < (int) PyList_Size(O); ind += mk*mk,
             ind2 += mk, i++){
             Ok = PyList_GetItem(O, (Py_ssize_t) i);
             mk = (int) PyInt_AsLong(Ok);
@@ -645,7 +645,7 @@ static PyObject* sprod(PyObject *self, PyObject *args, PyObject *kwrds)
                 dcopy_(&len, MAT_BUFD(y) + ind2 + k, &int1, A, &int1);
                 for (j = 0; j < len; j++) A[j] += MAT_BUFD(y)[ind2 + k];
                 dscal_(&len, &dbl2, A, &int1);
-                dtbmv_("L", "N", "N", &len, &int0, A, &int1, MAT_BUFD(x) + 
+                dtbmv_("L", "N", "N", &len, &int0, A, &int1, MAT_BUFD(x) +
                     ind + k * (mk+1), &int1);
             }
         }
@@ -656,14 +656,14 @@ static PyObject* sprod(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_sinv[] =  
+static char doc_sinv[] =
     "The inverse of the product x := (y o x) when the 's' components of \n"
     "y are diagonal.\n\n"
     "sinv(x, y, dims, mnl = 0)";
 
 static PyObject* sinv(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *y; 
+    matrix *x, *y;
     PyObject *dims, *O, *Ok;
     int i, j, k, mk, len, maxn, ind = 0, ind2, int0 = 0, int1 = 1;
     double a, c, d, alpha, *A = NULL, dbl2 = 0.5;
@@ -673,26 +673,26 @@ static PyObject* sinv(PyObject *self, PyObject *args, PyObject *kwrds)
         &dims, &ind)) return NULL;
 
 
-    /* 
-     * For nonlinear and 'l' blocks: 
-     * 
-     *     yk o\ xk = yk .\ xk 
+    /*
+     * For nonlinear and 'l' blocks:
+     *
+     *     yk o\ xk = yk .\ xk
      */
 
     O = PyDict_GetItemString(dims, "l");
     ind += (int) PyInt_AsLong(O);
-    dtbsv_("L", "N", "N", &ind, &int0, MAT_BUFD(y), &int1, MAT_BUFD(x), 
-        &int1); 
+    dtbsv_("L", "N", "N", &ind, &int0, MAT_BUFD(y), &int1, MAT_BUFD(x),
+        &int1);
 
 
     /*
-     * For 'q' blocks: 
-     *    
+     * For 'q' blocks:
+     *
      *                        [  l0   -l1'               ]
      *     yk o\ xk = 1/a^2 * [                          ] * xk
      *                        [ -l1    (a*I + l1*l1')/l0 ]
      *
-     * where yk = (l0, l1) and a = l0^2 - l1'*l1.     
+     * where yk = (l0, l1) and a = l0^2 - l1'*l1.
      */
 
     O = PyDict_GetItemString(dims, "q");
@@ -703,13 +703,13 @@ static PyObject* sinv(PyObject *self, PyObject *args, PyObject *kwrds)
         a = dnrm2_(&len, MAT_BUFD(y) + ind + 1, &int1);
         a = (MAT_BUFD(y)[ind] + a) * (MAT_BUFD(y)[ind] - a);
         c = MAT_BUFD(x)[ind];
-        d = ddot_(&len, MAT_BUFD(x) + ind + 1, &int1, 
+        d = ddot_(&len, MAT_BUFD(x) + ind + 1, &int1,
             MAT_BUFD(y) + ind + 1, &int1);
         MAT_BUFD(x)[ind] = c * MAT_BUFD(y)[ind] - d;
-        alpha = a / MAT_BUFD(y)[ind]; 
+        alpha = a / MAT_BUFD(y)[ind];
         dscal_(&len, &alpha, MAT_BUFD(x) + ind + 1, &int1);
-        alpha = d / MAT_BUFD(y)[ind] - c; 
-        daxpy_(&len, &alpha, MAT_BUFD(y) + ind + 1, &int1, MAT_BUFD(x) + 
+        alpha = d / MAT_BUFD(y)[ind] - c;
+        daxpy_(&len, &alpha, MAT_BUFD(y) + ind + 1, &int1, MAT_BUFD(x) +
             ind + 1, &int1);
         alpha = 1.0 / a;
         dscal_(&mk, &alpha, MAT_BUFD(x) + ind, &int1);
@@ -721,7 +721,7 @@ static PyObject* sinv(PyObject *self, PyObject *args, PyObject *kwrds)
      * For the 's' blocks:
      *
      *    yk o\ sk = xk ./ gamma
-     * 
+     *
      * where  gammaij = .5 * (yk_i + yk_j).
      */
 
@@ -730,9 +730,9 @@ static PyObject* sinv(PyObject *self, PyObject *args, PyObject *kwrds)
         Ok = PyList_GetItem(O, (Py_ssize_t) i);
         maxn = MAX(maxn, (int) PyInt_AsLong(Ok));
     }
-    if (!(A = (double *) calloc(maxn, sizeof(double)))) 
+    if (!(A = (double *) calloc(maxn, sizeof(double))))
         return PyErr_NoMemory();
-    for (i = 0, ind2 = ind; i < (int) PyList_Size(O); ind += mk*mk, 
+    for (i = 0, ind2 = ind; i < (int) PyList_Size(O); ind += mk*mk,
         ind2 += mk, i++){
         Ok = PyList_GetItem(O, (Py_ssize_t) i);
         mk = (int) PyInt_AsLong(Ok);
@@ -741,7 +741,7 @@ static PyObject* sinv(PyObject *self, PyObject *args, PyObject *kwrds)
             dcopy_(&len, MAT_BUFD(y) + ind2 + k, &int1, A, &int1);
             for (j = 0; j < len; j++) A[j] += MAT_BUFD(y)[ind2 + k];
             dscal_(&len, &dbl2, A, &int1);
-            dtbsv_("L", "N", "N", &len, &int0, A, &int1, MAT_BUFD(x) + ind 
+            dtbsv_("L", "N", "N", &len, &int0, A, &int1, MAT_BUFD(x) + ind
                 + k * (mk+1), &int1);
         }
     }
@@ -752,7 +752,7 @@ static PyObject* sinv(PyObject *self, PyObject *args, PyObject *kwrds)
 
 
 
-static char doc_trisc[] = 
+static char doc_trisc[] =
     "Sets the upper triangular part of the 's' components of x equal to\n"
     "zero and scales the strictly lower triangular part\n\n"
     "trisc(x, dims, offset = 0)";
@@ -760,12 +760,12 @@ static char doc_trisc[] =
 static PyObject* trisc(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *x;
-    double dbl0 = 0.0, dbl2 = 2.0; 
-    int ox = 0, i, k, nk, len, int1 = 1; 
+    double dbl0 = 0.0, dbl2 = 2.0;
+    int ox = 0, i, k, nk, len, int1 = 1;
     PyObject *dims, *O, *Ok;
     char *kwlist[] = {"x", "dims", "offset", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|i", kwlist, &x, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|i", kwlist, &x,
         &dims, &ox)) return NULL;
 
     O = PyDict_GetItemString(dims, "l");
@@ -793,7 +793,7 @@ static PyObject* trisc(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_triusc[] = 
+static char doc_triusc[] =
     "Scales the strictly lower triangular part of the 's' components of\n"
     "x by 0.5.\n\n"
     "triusc(x, dims, offset = 0)";
@@ -801,12 +801,12 @@ static char doc_triusc[] =
 static PyObject* triusc(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *x;
-    double dbl5 = 0.5; 
-    int ox = 0, i, k, nk, len, int1 = 1; 
+    double dbl5 = 0.5;
+    int ox = 0, i, k, nk, len, int1 = 1;
     PyObject *dims, *O, *Ok;
     char *kwlist[] = {"x", "dims", "offset", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|i", kwlist, &x, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|i", kwlist, &x,
         &dims, &ox)) return NULL;
 
     O = PyDict_GetItemString(dims, "l");
@@ -833,14 +833,14 @@ static PyObject* triusc(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_sdot[] = 
+static char doc_sdot[] =
     "Inner product of two vectors in S.\n\n"
     "sdot(x, y, dims, mnl= 0)";
-   
+
 static PyObject* sdot(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     matrix *x, *y;
-    int m = 0, int1 = 1, i, k, nk, inc, len; 
+    int m = 0, int1 = 1, i, k, nk, inc, len;
     double a;
     PyObject *dims, *O, *Ok;
     char *kwlist[] = {"x", "y", "dims", "mnl", NULL};
@@ -866,7 +866,7 @@ static PyObject* sdot(PyObject *self, PyObject *args, PyObject *kwrds)
         a += ddot_(&nk, MAT_BUFD(x) + m, &inc, MAT_BUFD(y) + m, &inc);
         for (i = 1; i < nk; i++){
             len = nk - i;
-            a += 2.0 * ddot_(&len, MAT_BUFD(x) + m + i, &inc, 
+            a += 2.0 * ddot_(&len, MAT_BUFD(x) + m + i, &inc,
                 MAT_BUFD(y) + m + i, &inc);
         }
         m += nk*nk;
@@ -876,27 +876,27 @@ static PyObject* sdot(PyObject *self, PyObject *args, PyObject *kwrds)
 }
 
 
-static char doc_max_step[] = 
+static char doc_max_step[] =
     "Returns min {t | x + t*e >= 0}\n\n."
     "max_step(x, dims, mnl = 0, sigma = None)\n\n"
     "e is defined as follows\n\n"
     "- For the nonlinear and 'l' blocks: e is the vector of ones.\n"
     "- For the 'q' blocks: e is the first unit vector.\n"
     "- For the 's' blocks: e is the identity matrix.\n\n"
-    "When called with the argument sigma, also returns the eigenvalues\n" 
+    "When called with the argument sigma, also returns the eigenvalues\n"
     "(in sigma) and the eigenvectors (in x) of the 's' components of x.\n";
-   
+
 static PyObject* max_step(PyObject *self, PyObject *args, PyObject *kwrds)
 {
-    matrix *x, *sigma = NULL; 
+    matrix *x, *sigma = NULL;
     PyObject *dims, *O, *Ok;
     int i, mk, len, maxn, ind = 0, ind2, int1 = 1, ld, Ns = 0, info, lwork,
         *iwork = NULL, liwork, iwl, m;
-    double t = -FLT_MAX, dbl0 = 0.0, *work = NULL, wl, *Q = NULL, 
+    double t = -FLT_MAX, dbl0 = 0.0, *work = NULL, wl, *Q = NULL,
         *w = NULL;
     char *kwlist[] = {"x", "dims", "mnl", "sigma", NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iO", kwlist, &x, 
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|iO", kwlist, &x,
         &dims, &ind, &sigma)) return NULL;
 
     O = PyDict_GetItemString(dims, "l");
@@ -908,7 +908,7 @@ static PyObject* max_step(PyObject *self, PyObject *args, PyObject *kwrds)
         Ok = PyList_GetItem(O, (Py_ssize_t) i);
         mk = (int) PyInt_AsLong(Ok);
         len = mk - 1;
-        t = MAX(t, dnrm2_(&len, MAT_BUFD(x) + ind + 1, &int1) - 
+        t = MAX(t, dnrm2_(&len, MAT_BUFD(x) + ind + 1, &int1) -
             MAT_BUFD(x)[ind]);
         ind += mk;
     }
@@ -925,13 +925,13 @@ static PyObject* max_step(PyObject *self, PyObject *args, PyObject *kwrds)
     liwork = -1;
     ld = MAX(1, maxn);
     if (sigma){
-        dsyevd_("V", "L", &maxn, NULL, &ld, NULL, &wl, &lwork, &iwl, 
+        dsyevd_("V", "L", &maxn, NULL, &ld, NULL, &wl, &lwork, &iwl,
             &liwork, &info);
     }
     else {
-        if (!(Q = (double *) calloc(maxn * maxn, sizeof(double))) || 
+        if (!(Q = (double *) calloc(maxn * maxn, sizeof(double))) ||
             !(w = (double *) calloc(maxn, sizeof(double)))){
-            free(Q); free(w); 
+            free(Q); free(w);
             return PyErr_NoMemory();
         }
         dsyevr_("N", "I", "L", &maxn, NULL, &ld, &dbl0, &dbl0, &int1,
@@ -940,7 +940,7 @@ static PyObject* max_step(PyObject *self, PyObject *args, PyObject *kwrds)
     }
     lwork = (int) wl;
     liwork = iwl;
-    if (!(work = (double *) calloc(lwork, sizeof(double))) || 
+    if (!(work = (double *) calloc(lwork, sizeof(double))) ||
         (!(iwork = (int *) calloc(liwork, sizeof(int))))){
         free(Q);  free(w);  free(work); free(iwork);
         return PyErr_NoMemory();
@@ -950,8 +950,8 @@ static PyObject* max_step(PyObject *self, PyObject *args, PyObject *kwrds)
         mk = (int) PyInt_AsLong(Ok);
         if (mk){
             if (sigma){
-                dsyevd_("V", "L", &mk, MAT_BUFD(x) + ind, &mk, 
-                    MAT_BUFD(sigma) + ind2, work, &lwork, iwork, &liwork, 
+                dsyevd_("V", "L", &mk, MAT_BUFD(x) + ind, &mk,
+                    MAT_BUFD(sigma) + ind2, work, &lwork, iwork, &liwork,
                     &info);
                 t = MAX(t, -MAT_BUFD(sigma)[ind2]);
             }
@@ -959,7 +959,7 @@ static PyObject* max_step(PyObject *self, PyObject *args, PyObject *kwrds)
                 len = mk*mk;
                 dcopy_(&len, MAT_BUFD(x) + ind, &int1, Q, &int1);
                 ld = MAX(1, mk);
-                dsyevr_("N", "I", "L", &mk, Q, &mk, &dbl0, &dbl0, &int1, 
+                dsyevr_("N", "I", "L", &mk, Q, &mk, &dbl0, &dbl0, &int1,
                     &int1, &dbl0, &m, w, NULL, &int1, NULL, work, &lwork,
                     iwork, &liwork, &info);
                 t = MAX(t, -w[0]);
@@ -975,20 +975,20 @@ static PyObject* max_step(PyObject *self, PyObject *args, PyObject *kwrds)
 
 static PyMethodDef misc_solvers__functions[] = {
     {"scale", (PyCFunction) scale, METH_VARARGS|METH_KEYWORDS, doc_scale},
-    {"scale2", (PyCFunction) scale2, METH_VARARGS|METH_KEYWORDS, 
+    {"scale2", (PyCFunction) scale2, METH_VARARGS|METH_KEYWORDS,
         doc_scale2},
     {"pack", (PyCFunction) pack, METH_VARARGS|METH_KEYWORDS, doc_pack},
     {"pack2", (PyCFunction) pack2, METH_VARARGS|METH_KEYWORDS, doc_pack2},
-    {"unpack", (PyCFunction) unpack, METH_VARARGS|METH_KEYWORDS, 
+    {"unpack", (PyCFunction) unpack, METH_VARARGS|METH_KEYWORDS,
         doc_unpack},
     {"symm", (PyCFunction) symm, METH_VARARGS|METH_KEYWORDS, doc_symm},
     {"trisc", (PyCFunction) trisc, METH_VARARGS|METH_KEYWORDS, doc_trisc},
-    {"triusc", (PyCFunction) triusc, METH_VARARGS|METH_KEYWORDS, 
+    {"triusc", (PyCFunction) triusc, METH_VARARGS|METH_KEYWORDS,
         doc_triusc},
     {"sdot", (PyCFunction) sdot, METH_VARARGS|METH_KEYWORDS, doc_sdot},
     {"sprod", (PyCFunction) sprod, METH_VARARGS|METH_KEYWORDS, doc_sprod},
     {"sinv", (PyCFunction) sinv, METH_VARARGS|METH_KEYWORDS, doc_sinv},
-    {"max_step", (PyCFunction) max_step, METH_VARARGS|METH_KEYWORDS, 
+    {"max_step", (PyCFunction) max_step, METH_VARARGS|METH_KEYWORDS,
         doc_max_step},
     {NULL}  /* Sentinel */
 };
@@ -997,7 +997,7 @@ PyMODINIT_FUNC initmisc_solvers(void)
 {
   PyObject *m;
 
-  m = Py_InitModule3("cvxopt.misc_solvers", misc_solvers__functions, 
+  m = Py_InitModule3("cvxopt.misc_solvers", misc_solvers__functions,
       misc_solvers__doc__);
 
   if (import_cvxopt() < 0) return;
diff --git a/src/C/sparse.c b/src/C/sparse.c
index a1f8331..a2062b2 100644
--- a/src/C/sparse.c
+++ b/src/C/sparse.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
 
 #include "Python.h"
 #include "cvxopt.h"
-#include "misc.h" 
+#include "misc.h"
 
 #include <complexobject.h>
 
@@ -36,50 +36,50 @@ extern int (*convert_num[])(void *, void *, int, int_t) ;
 extern PyObject * (*num2PyObject[])(void *, int) ;
 extern void (*scal[])(int *, number *, void *, int *) ;
 extern void (*axpy[])(int *, void *, void *, int *, void *, int *) ;
-extern void (*gemm[])(char *, char *, int *, int *, int *, void *, 
+extern void (*gemm[])(char *, char *, int *, int *, int *, void *,
     void *, int *, void *, int *, void *, void *, int *) ;
 extern int (*div_array[])(void *, number, int) ;
 extern int get_id(void *, int ) ;
 
 extern PyTypeObject matrix_tp ;
 extern matrix * Matrix_NewFromMatrix(matrix *, int) ;
-extern matrix * Matrix_NewFromSequence(PyObject *, int) ; 
+extern matrix * Matrix_NewFromSequence(PyObject *, int) ;
 extern matrix * Matrix_NewFromArrayStruct(PyObject *, int, int_t *) ;
-extern matrix * Matrix_NewFromNumber(int , int , int , void *, int ) ;
-extern matrix * create_indexlist(int, PyObject *) ; 
-extern matrix * Matrix_New(int, int, int) ;
-extern matrix * dense(spmatrix *) ;  
-extern PyObject * matrix_add(PyObject *, PyObject *) ; 
-extern PyObject * matrix_sub(PyObject *, PyObject *) ; 
+extern matrix * Matrix_NewFromNumber(int_t , int_t , int_t , void *, int ) ;
+extern matrix * create_indexlist(int, PyObject *) ;
+extern matrix * Matrix_New(int_t, int_t, int) ;
+extern matrix * dense(spmatrix *) ;
+extern PyObject * matrix_add(PyObject *, PyObject *) ;
+extern PyObject * matrix_sub(PyObject *, PyObject *) ;
 extern void * convert_mtx_alloc(matrix *, int) ;
 
 PyTypeObject spmatrix_tp ;
-spmatrix * SpMatrix_New(int, int, int, int ) ;
+spmatrix * SpMatrix_New(int_t, int_t, int_t, int ) ;
 
 extern void (*scal[])(int *, number *, void *, int *) ;
-extern void (*gemm[])(char *, char *, int *, int *, int *, void *, void *, 
+extern void (*gemm[])(char *, char *, int *, int *, int *, void *, void *,
     int *, void *, int *, void *, void *, int *) ;
 extern void (*syrk[])(char *, char *, int *, int *, void *, void *,
     int *, void *, void *, int *) ;
 
 static int sp_daxpy(number, void *, void *, int, int, int, void **) ;
 static int sp_zaxpy(number, void *, void *, int, int, int, void **) ;
-int (*sp_axpy[])(number, void *, void *, int, int, int, void **) 
-  = { NULL, sp_daxpy, sp_zaxpy };
-
-static int sp_dgemm(char, char, number, void *, void *, number, void *, 
-    int, int, int, int, void **, int, int, int) ; 
-static int sp_zgemm(char, char, number, void *, void *, number, void *, 
-    int, int, int, int, void **, int, int, int) ; 
-int (*sp_gemm[])(char, char, number, void *, void *, number, void *, 
-    int, int, int, int, void **, int, int, int) 
-  = { NULL, sp_dgemm, sp_zgemm };
-
-static int sp_dgemv(char, int, int, number, void *, int, 
+int (*sp_axpy[])(number, void *, void *, int, int, int, void **)
+= { NULL, sp_daxpy, sp_zaxpy };
+
+static int sp_dgemm(char, char, number, void *, void *, number, void *,
+    int, int, int, int, void **, int, int, int) ;
+static int sp_zgemm(char, char, number, void *, void *, number, void *,
+    int, int, int, int, void **, int, int, int) ;
+int (*sp_gemm[])(char, char, number, void *, void *, number, void *,
+    int, int, int, int, void **, int, int, int)
+    = { NULL, sp_dgemm, sp_zgemm };
+
+static int sp_dgemv(char, int, int, number, void *, int,
     void *, int, number, void *, int) ;
-static int sp_zgemv(char, int, int, number, void *, int, 
+static int sp_zgemv(char, int, int, number, void *, int,
     void *, int, number, void *, int) ;
-int (*sp_gemv[])(char, int, int, number, void *, int, void *, int,  
+int (*sp_gemv[])(char, int, int, number, void *, int, void *, int,
     number, void *, int) = { NULL, sp_dgemv, sp_zgemv } ;
 
 static int sp_dsymv(char, int, number, ccs *, int, void *, int,
@@ -89,9 +89,9 @@ static int sp_zsymv(char, int, number, ccs *, int, void *, int,
 int (*sp_symv[])(char, int, number, ccs *, int, void *, int,
     number, void *, int) = { NULL, sp_dsymv, sp_zsymv } ;
 
-static int sp_dsyrk(char, char, number, void *, number, 
+static int sp_dsyrk(char, char, number, void *, number,
     void *, int, int, int, int, void **) ;
-int (*sp_syrk[])(char, char, number, void *, number, 
+int (*sp_syrk[])(char, char, number, void *, number,
     void *, int, int, int, int, void **) = { NULL, sp_dsyrk, NULL };
 
 typedef struct {
@@ -99,7 +99,7 @@ typedef struct {
 } int_list;
 
 static int comp_int(const void *x, const void *y) {
-  if (((int_list *)x)->key == ((int_list *)y)->key) 
+  if (((int_list *)x)->key == ((int_list *)y)->key)
     return 0;
   else
     return (((int_list *)x)->key > ((int_list *)y)->key ? 1 : -1);
@@ -110,7 +110,7 @@ typedef struct {
 } double_list;
 
 static int comp_double(const void *x, const void *y) {
-  if (((double_list *)x)->key == ((double_list *)y)->key) 
+  if (((double_list *)x)->key == ((double_list *)y)->key)
     return 0;
   else
     return (((double_list *)x)->key > ((double_list *)y)->key ? 1 : -1);
@@ -121,19 +121,19 @@ typedef struct {
 } complex_list;
 
 static int comp_complex(const void *x, const void *y) {
-  if (((complex_list *)x)->key == ((complex_list *)y)->key) 
+  if (((complex_list *)x)->key == ((complex_list *)y)->key)
     return 0;
   else
     return (((complex_list *)x)->key > ((complex_list *)y)->key ? 1 : -1);
 }
 
 #define spmatrix_getitem_i(O,i,v) \
-  spmatrix_getitem_ij(O,i%SP_NROWS(O),i/SP_NROWS(O),v)
+    spmatrix_getitem_ij(O,i%SP_NROWS(O),i/SP_NROWS(O),v)
 #define spmatrix_setitem_i(O,i,v) \
-  spmatrix_setitem_ij(O,i%SP_NROWS(O),i/SP_NROWS(O),v)
+    spmatrix_setitem_ij(O,i%SP_NROWS(O),i/SP_NROWS(O),v)
 
 #define free_lists_exit(argI,argJ,I,J,ret) { \
-   if (argI && !Matrix_Check(argI)) { Py_XDECREF(I); } \
+    if (argI && !Matrix_Check(argI)) { Py_XDECREF(I); } \
     if (argJ && !Matrix_Check(argJ)) { Py_XDECREF(J); } \
     return ret; }
 
@@ -141,12 +141,12 @@ static int comp_complex(const void *x, const void *y) {
     while (((ccs *)O)->colptr[j+1] == k+1) j++;	\
     k++; }
 
-int 
+int
 convert_array(void *dest, void *src, int dest_id, int src_id, int n) {
 
-  if (dest_id != MAX(dest_id,src_id)) 
+  if (dest_id != MAX(dest_id,src_id))
     return -1;
-  
+
   int i;
   if (dest_id == src_id)
     memcpy(dest, src, n*E_SIZE[dest_id]);
@@ -156,17 +156,17 @@ convert_array(void *dest, void *src, int dest_id, int src_id, int n) {
   } else {
     if (src_id == INT) {
       for (i=0; i<n; i++)
-	((complex *)dest)[i] = ((int *)src)[i];
+        ((complex *)dest)[i] = ((int *)src)[i];
     } else {
       for (i=0; i<n; i++)
-	((complex *)dest)[i] = ((double *)src)[i];
+        ((complex *)dest)[i] = ((double *)src)[i];
     }
   }
   return 0;
 }
 
-ccs * alloc_ccs(int_t nrows, int_t ncols, int nnz, int id) 
-{  
+ccs * alloc_ccs(int_t nrows, int_t ncols, int nnz, int id)
+{
   ccs *obj = malloc(sizeof(ccs));
   if (!obj) return NULL;
 
@@ -175,15 +175,15 @@ ccs * alloc_ccs(int_t nrows, int_t ncols, int nnz, int id)
   obj->id = id;
 
   obj->values = malloc(E_SIZE[id]*nnz);
-  obj->colptr = calloc(ncols+1,sizeof(int_t));    
-  obj->rowind = malloc(sizeof(int_t)*nnz);  
+  obj->colptr = calloc(ncols+1,sizeof(int_t));
+  obj->rowind = malloc(sizeof(int_t)*nnz);
 
   if (!obj->values || !obj->colptr || !obj->rowind) {
     free(obj->values); free(obj->colptr); free(obj->rowind); free(obj);
     return NULL;
-  } 
-  
-  return obj;  
+  }
+
+  return obj;
 }
 
 void free_ccs(ccs *obj) {
@@ -201,26 +201,26 @@ realloc_ccs(ccs *obj, int nnz) {
 
   if ((rowind = realloc(obj->rowind, nnz*sizeof(int_t))))
     obj->rowind = rowind;
-  else  
+  else
     return 0;
 
   if ((values = realloc(obj->values, nnz*E_SIZE[obj->id])))
     obj->values = values;
-  else 
+  else
+
     return 0;
-  
   return 1;
 }
 
 static ccs * convert_ccs(ccs *src, int id) {
-  
+
   if (src->id == id) return src;
 
   if (id != MAX(id,src->id)) PY_ERR_TYPE("incompatible matrix types");
-    
+
   ccs *ret = alloc_ccs(src->nrows,src->ncols,CCS_NNZ(src),id);
   if (!ret) return (ccs *)PyErr_NoMemory();
-  
+
   convert_array(ret->values, src->values, id, src->id, CCS_NNZ(src));
   memcpy(ret->rowind, src->rowind, CCS_NNZ(src)*sizeof(int_t));
   memcpy(ret->colptr, src->colptr, (src->ncols+1)*sizeof(int_t));
@@ -233,15 +233,15 @@ spmatrix *SpMatrix_NewFromMatrix(matrix *src, int id)
   int nnz = 0, i, j;
 
   if (id < MAT_ID(src)) PY_ERR_TYPE("illegal type conversion");
-  
+
   for (j=0; j<MAT_NCOLS(src); j++) {
     for (i=0; i<MAT_NROWS(src); i++) {
 
       number *a = MAT_BUF(src) + (i+j*MAT_NROWS(src))*E_SIZE[MAT_ID(src)];
       if (((MAT_ID(src) == INT) && (a->i != Zero[INT].i)) ||
-	  ((MAT_ID(src) == DOUBLE) && (a->d != Zero[DOUBLE].d)) ||
-	  ((MAT_ID(src) == COMPLEX) && (a->z != Zero[COMPLEX].z))) 
-	nnz++;
+          ((MAT_ID(src) == DOUBLE) && (a->d != Zero[DOUBLE].d)) ||
+          ((MAT_ID(src) == COMPLEX) && (a->z != Zero[COMPLEX].z)))
+        nnz++;
     }
   }
 
@@ -255,18 +255,18 @@ spmatrix *SpMatrix_NewFromMatrix(matrix *src, int id)
       number a;
       convert_num[id](&a, src, 0, i+j*MAT_NROWS(src));
       if (((id == INT) && (a.i != Zero[INT].i)) ||
-	  ((id == DOUBLE) && (a.d != Zero[DOUBLE].d)) ||
-	  ((id == COMPLEX) && (a.z != Zero[COMPLEX].z))) {
-	write_num[id](SP_VAL(A), cnt, &a, 0); 
-	SP_ROW(A)[cnt++] = i;
-	SP_COL(A)[j+1]++;
+          ((id == DOUBLE) && (a.d != Zero[DOUBLE].d)) ||
+          ((id == COMPLEX) && (a.z != Zero[COMPLEX].z))) {
+        write_num[id](SP_VAL(A), cnt, &a, 0);
+        SP_ROW(A)[cnt++] = i;
+        SP_COL(A)[j+1]++;
       }
     }
   }
 
   for (i=0; i<SP_NCOLS(A); i++)
     SP_COL(A)[i+1] += SP_COL(A)[i];
-  
+
   return A;
 }
 
@@ -274,161 +274,161 @@ spmatrix * sparse_concat(PyObject *L, int id_arg)
 {
   int m=0, n=0, mk=0, nk=0, i=0, j, id=0, nnz=0;
   PyObject *col;
-  
-  int single_col = (PyList_GET_SIZE(L) > 0 && 
+
+  int single_col = (PyList_GET_SIZE(L) > 0 &&
       !PyList_Check(PyList_GET_ITEM(L, 0)));
 
   for (j=0; j<(single_col ? 1 : PyList_GET_SIZE(L)); j++) {
 
     col = (single_col ? L : PyList_GET_ITEM(L, j));
-    if (!PyList_Check(col))  
+    if (!PyList_Check(col))
       PY_ERR_TYPE("L must be a list of lists with matrices");
-    
+
     mk = 0;
     for (i=0; i<PyList_GET_SIZE(col); i++) {
       PyObject *Lij = PyList_GET_ITEM(col, i);
-      if (!Matrix_Check(Lij) && !SpMatrix_Check(Lij) && !PY_NUMBER(Lij)) 
-	PY_ERR_TYPE("invalid type in list");
+      if (!Matrix_Check(Lij) && !SpMatrix_Check(Lij) && !PY_NUMBER(Lij))
+        PY_ERR_TYPE("invalid type in list");
 
       int blk_nrows, blk_ncols;
       if (Matrix_Check(Lij) || SpMatrix_Check(Lij)) {
-	blk_nrows = X_NROWS(Lij); blk_ncols = X_NCOLS(Lij);
-	id = MAX(id, X_ID(Lij));
+        blk_nrows = X_NROWS(Lij); blk_ncols = X_NCOLS(Lij);
+        id = MAX(id, X_ID(Lij));
       } else {
-	blk_nrows = 1; blk_ncols = 1;
-	id = MAX(id, get_id(Lij,1));
+        blk_nrows = 1; blk_ncols = 1;
+        id = MAX(id, get_id(Lij,1));
       }
 
       if (Matrix_Check(Lij)) {
-	
-	int ik, jk;
-	for (jk=0; jk<MAT_NCOLS(Lij); jk++) {
-	  for (ik=0; ik<MAT_NROWS(Lij); ik++) {
-	
-	    number *a = MAT_BUF(Lij) + 
-	      (ik+jk*MAT_NROWS(Lij))*E_SIZE[MAT_ID(Lij)];
-
-	    if (((MAT_ID(Lij) == INT) && (a->i != Zero[INT].i)) ||
-		((MAT_ID(Lij) == DOUBLE) && (a->d != Zero[DOUBLE].d)) ||
-		((MAT_ID(Lij) == COMPLEX) && (a->z != Zero[COMPLEX].z))) 
-	      nnz++;
-	  }
-	}
+
+        int ik, jk;
+        for (jk=0; jk<MAT_NCOLS(Lij); jk++) {
+          for (ik=0; ik<MAT_NROWS(Lij); ik++) {
+
+            number *a = MAT_BUF(Lij) +
+                (ik+jk*MAT_NROWS(Lij))*E_SIZE[MAT_ID(Lij)];
+
+            if (((MAT_ID(Lij) == INT) && (a->i != Zero[INT].i)) ||
+                ((MAT_ID(Lij) == DOUBLE) && (a->d != Zero[DOUBLE].d)) ||
+                ((MAT_ID(Lij) == COMPLEX) && (a->z != Zero[COMPLEX].z)))
+              nnz++;
+          }
+        }
       } else if (SpMatrix_Check(Lij)) {
-	int ik, jk;
-	for (jk=0; jk<SP_NCOLS(Lij); jk++) {
-	  
-	  for (ik=SP_COL(Lij)[jk]; ik<SP_COL(Lij)[jk+1]; ik++) {
-	    if (((SP_ID(Lij) == DOUBLE) && (SP_VALD(Lij)[ik] != 0.0)) ||
-		((SP_ID(Lij) == COMPLEX) && (SP_VALZ(Lij)[ik] != 0.0)))
-	      nnz++;
-	  }
-	}	
+        int ik, jk;
+        for (jk=0; jk<SP_NCOLS(Lij); jk++) {
+
+          for (ik=SP_COL(Lij)[jk]; ik<SP_COL(Lij)[jk+1]; ik++) {
+            if (((SP_ID(Lij) == DOUBLE) && (SP_VALD(Lij)[ik] != 0.0)) ||
+                ((SP_ID(Lij) == COMPLEX) && (SP_VALZ(Lij)[ik] != 0.0)))
+              nnz++;
+          }
+        }
       }
       else nnz += 1;
-	
+
       if (i==0) {
-	nk = blk_ncols; n += nk;
-	mk = blk_nrows; 
+        nk = blk_ncols; n += nk;
+        mk = blk_nrows;
       } else {
-	if (blk_ncols != nk) 
-	  PY_ERR_TYPE("incompatible dimensions of subblocks");
-	mk += blk_nrows;
+        if (blk_ncols != nk)
+          PY_ERR_TYPE("incompatible dimensions of subblocks");
+        mk += blk_nrows;
       }
     }
-    if (j==0) 
+    if (j==0)
       m = mk;
-    else if (m != mk) PY_ERR_TYPE("incompatible dimensions of subblocks");   
+    else if (m != mk) PY_ERR_TYPE("incompatible dimensions of subblocks");
   }
 
   if ((id_arg >= 0) && (id_arg < id))
     PY_ERR_TYPE("illegal type conversion");
 
-  id = MAX(DOUBLE, MAX(id, id_arg));    
+  id = MAX(DOUBLE, MAX(id, id_arg));
   spmatrix *A = SpMatrix_New(m, n, nnz, id);
   if (!A) return (spmatrix *)PyErr_NoMemory();
-  
+
   int ik = 0, jk, cnt = 0;
   nk = 0;
   for (j=0; j<(single_col ? 1 : PyList_GET_SIZE(L)); j++) {
     col = (single_col ? L : PyList_GET_ITEM(L, j));
-      
+
     if (PyList_GET_SIZE(col) > 0) {
-	
-      int tmp = (PY_NUMBER(PyList_GET_ITEM(col, 0)) ? 1 :  
-	  X_NCOLS(PyList_GET_ITEM(col, 0)));
+
+      int tmp = (PY_NUMBER(PyList_GET_ITEM(col, 0)) ? 1 :
+      X_NCOLS(PyList_GET_ITEM(col, 0)));
 
       for (jk=0; jk<tmp; jk++) {
-	  
-	mk = 0;
-	int blk_nrows = 0, blk_ncols = 0;
-	for (i=0; i<PyList_GET_SIZE(col); i++) {
-	  
-	  PyObject *Lij = PyList_GET_ITEM(col, i);
-	  
-	  if (Matrix_Check(Lij) || SpMatrix_Check(Lij)) {
-	    blk_nrows = X_NROWS(Lij); blk_ncols = X_NCOLS(Lij);
-	  } else {
-	    blk_nrows = 1; blk_ncols = 1;
-	  }
-
-	  if (Matrix_Check(Lij)) {
-	    for (ik=0; ik<MAT_NROWS(Lij); ik++) {
-	      
-	      number a;
-	      convert_num[id](&a, Lij, 0, ik + jk*MAT_NROWS(Lij));
-
-	      if (((id == DOUBLE) && (a.d != Zero[DOUBLE].d)) ||
-		  ((id == COMPLEX) && (a.z != Zero[COMPLEX].z))) {
-
-		write_num[id](SP_VAL(A), cnt, &a, 0); 
-		SP_ROW(A)[cnt++] = mk + ik;
-		SP_COL(A)[nk+1]++;
-	      }
-	    }
-	  } else if SpMatrix_Check(Lij) { 
-	    
-	    int ik;
-	    for (ik=SP_COL(Lij)[jk]; ik<SP_COL(Lij)[jk+1]; ik++) {
-	      if ((SP_ID(Lij) == DOUBLE) && (SP_VALD(Lij)[ik] != 0.0)) {
-		if (id == DOUBLE) 
-		  SP_VALD(A)[cnt] = SP_VALD(Lij)[ik];
-		else
-		  SP_VALZ(A)[cnt] = SP_VALD(Lij)[ik];
-
-		SP_ROW(A)[cnt++] = mk + SP_ROW(Lij)[ik];
-		SP_COL(A)[nk+1]++;	
-		nnz++;
-	      } 
-	      else if ((SP_ID(Lij) == COMPLEX) && (SP_VALZ(Lij)[ik] != 0.0)) {
-
-		SP_VALZ(A)[cnt] = SP_VALD(Lij)[ik];
-		SP_ROW(A)[cnt++] = mk + SP_ROW(Lij)[ik];
-		SP_COL(A)[nk+1]++;	
-		nnz++;				
-	      }
-	    }
-	  } else {
-
-	    number a;
-	    convert_num[id](&a,	Lij, 1, 0);
-
-	    if (((id == DOUBLE) && (a.d != Zero[DOUBLE].d)) ||
-		((id == COMPLEX) && (a.z != Zero[COMPLEX].z))) {
-
-	      write_num[id](SP_VAL(A), cnt, &a, 0); 
-	      SP_ROW(A)[cnt++] = mk;
-	      SP_COL(A)[nk+1]++;
-	    } 
-	  }
-	  mk += blk_nrows;
-	}
-	nk++;
-      }
-    }
-  }
-
-  for (i=0; i<n; i++) 
+
+        mk = 0;
+        int blk_nrows = 0, blk_ncols = 0;
+        for (i=0; i<PyList_GET_SIZE(col); i++) {
+
+          PyObject *Lij = PyList_GET_ITEM(col, i);
+
+          if (Matrix_Check(Lij) || SpMatrix_Check(Lij)) {
+            blk_nrows = X_NROWS(Lij); blk_ncols = X_NCOLS(Lij);
+          } else {
+            blk_nrows = 1; blk_ncols = 1;
+          }
+
+          if (Matrix_Check(Lij)) {
+            for (ik=0; ik<MAT_NROWS(Lij); ik++) {
+
+              number a;
+              convert_num[id](&a, Lij, 0, ik + jk*MAT_NROWS(Lij));
+
+              if (((id == DOUBLE) && (a.d != Zero[DOUBLE].d)) ||
+                  ((id == COMPLEX) && (a.z != Zero[COMPLEX].z))) {
+
+                write_num[id](SP_VAL(A), cnt, &a, 0);
+                SP_ROW(A)[cnt++] = mk + ik;
+                SP_COL(A)[nk+1]++;
+              }
+            }
+          } else if SpMatrix_Check(Lij) {
+
+            int ik;
+            for (ik=SP_COL(Lij)[jk]; ik<SP_COL(Lij)[jk+1]; ik++) {
+              if ((SP_ID(Lij) == DOUBLE) && (SP_VALD(Lij)[ik] != 0.0)) {
+                if (id == DOUBLE)
+                  SP_VALD(A)[cnt] = SP_VALD(Lij)[ik];
+                else
+                  SP_VALZ(A)[cnt] = SP_VALD(Lij)[ik];
+
+                SP_ROW(A)[cnt++] = mk + SP_ROW(Lij)[ik];
+                SP_COL(A)[nk+1]++;
+                nnz++;
+              }
+              else if ((SP_ID(Lij) == COMPLEX) && (SP_VALZ(Lij)[ik] != 0.0)) {
+
+                SP_VALZ(A)[cnt] = SP_VALD(Lij)[ik];
+                SP_ROW(A)[cnt++] = mk + SP_ROW(Lij)[ik];
+                SP_COL(A)[nk+1]++;
+                nnz++;
+              }
+            }
+          } else {
+
+            number a;
+            convert_num[id](&a,	Lij, 1, 0);
+
+            if (((id == DOUBLE) && (a.d != Zero[DOUBLE].d)) ||
+                ((id == COMPLEX) && (a.z != Zero[COMPLEX].z))) {
+
+              write_num[id](SP_VAL(A), cnt, &a, 0);
+              SP_ROW(A)[cnt++] = mk;
+              SP_COL(A)[nk+1]++;
+            }
+          }
+          mk += blk_nrows;
+        }
+        nk++;
+      }
+    }
+  }
+
+  for (i=0; i<n; i++)
     SP_COL(A)[i+1] += SP_COL(A)[i];
 
   return A;
@@ -442,7 +442,7 @@ static ccs * transpose(ccs *A, int conjugate) {
 
   int_t i, j, *buf = calloc(A->nrows,sizeof(int_t));
   if (!buf) { free_ccs(B); return NULL; }
-  
+
   /* Run through matrix and count number of elms in each row */
   for (i=0; i<A->colptr[A->ncols]; i++) buf[ A->rowind[i] ]++;
 
@@ -451,23 +451,23 @@ static ccs * transpose(ccs *A, int conjugate) {
     B->colptr[i+1] = B->colptr[i] + buf[i];
 
   /* fill in rowind and values */
-  for (i=0; i<A->nrows; i++) buf[i] = 0;        
+  for (i=0; i<A->nrows; i++) buf[i] = 0;
   for (i=0; i<A->ncols; i++) {
     if (A->id == DOUBLE)
       for (j=A->colptr[i]; j<A->colptr[i+1]; j++) {
-	B->rowind[ B->colptr[A->rowind[j]] + buf[A->rowind[j]] ] = i;
-	((double *)B->values)[B->colptr[A->rowind[j]] + buf[A->rowind[j]]++] = 
-	  ((double *)A->values)[j];
+        B->rowind[ B->colptr[A->rowind[j]] + buf[A->rowind[j]] ] = i;
+        ((double *)B->values)[B->colptr[A->rowind[j]] + buf[A->rowind[j]]++] =
+            ((double *)A->values)[j];
       }
-    else 
+    else
       for (j=A->colptr[i]; j<A->colptr[i+1]; j++) {
-	B->rowind[ B->colptr[A->rowind[j]] + buf[A->rowind[j]] ] = i;
-	((complex *)B->values)[B->colptr[A->rowind[j]]+buf[A->rowind[j]]++] = 
-	  (conjugate ? conj(((complex *)A->values)[j]) : 
-	      ((complex *)A->values)[j]);
+        B->rowind[ B->colptr[A->rowind[j]] + buf[A->rowind[j]] ] = i;
+        ((complex *)B->values)[B->colptr[A->rowind[j]]+buf[A->rowind[j]]++] =
+            (conjugate ? conj(((complex *)A->values)[j]) :
+              ((complex *)A->values)[j]);
       }
   }
-  free(buf);    
+  free(buf);
   return B;
 }
 
@@ -490,9 +490,9 @@ static int sort_ccs(ccs *A) {
   return 0;
 }
 
-/* 
+/*
    Sparse accumulator (spa) - dense representation of a sparse vector
-*/
+ */
 typedef struct {
   void *val;
   char *nz;
@@ -500,10 +500,10 @@ typedef struct {
   int nnz, n, id;
 } spa;
 
-static spa * alloc_spa(int n, int id) {
-  
+static spa * alloc_spa(int_t n, int id) {
+
   spa *s = malloc(sizeof(spa));
-  
+
   if (s) {
     s->val = malloc( E_SIZE[id]*n );
     s->nz  = malloc( n*sizeof(char) );
@@ -518,7 +518,7 @@ static spa * alloc_spa(int n, int id) {
     return NULL;
   }
 
-  int i;
+  int_t i;
   for (i=0; i<n; i++) s->nz[i] = 0;
 
   return s;
@@ -531,10 +531,10 @@ static void free_spa(spa *s) {
 }
 
 static void init_spa(spa *s, ccs *X, int col) {
-  int i;
-  for (i=0; i<s->nnz; i++) 
+  int_t i;
+  for (i=0; i<s->nnz; i++)
     s->nz[s->idx[i]] = 0;
-  
+
   s->nnz = 0;
 
   if (X && X->id == DOUBLE) {
@@ -552,25 +552,25 @@ static void init_spa(spa *s, ccs *X, int col) {
   }
 }
 
-static inline void 
+static inline void
 spa_daxpy_partial (double a, ccs *X, int col, spa *y) {
   int i;
 
   for (i=X->colptr[col]; i<X->colptr[col+1]; i++) {
     if (y->nz[X->rowind[i]]) {
       ((double *)y->val)[X->rowind[i]] += a*((double *)X->values)[i];
-    }	
+    }
   }
 }
 
-static inline void 
+static inline void
 spa_zaxpy_partial (complex a, ccs *X, int col, spa *y) {
   int i;
 
   for (i=X->colptr[col]; i<X->colptr[col+1]; i++) {
     if (y->nz[X->rowind[i]]) {
       ((complex *)y->val)[X->rowind[i]] += a*((complex *)X->values)[i];
-    }	
+    }
   }
 }
 
@@ -587,83 +587,83 @@ static inline void spa_daxpy (double a, ccs *X, int col, spa *y) {
       y->idx[y->nnz++] = X->rowind[i];
     }
   }
-} 
+}
 
-static inline void spa_zaxpy (complex a, ccs *X, char conjx, int col, spa *y) 
+static inline void spa_zaxpy (complex a, ccs *X, char conjx, int col, spa *y)
 {
   int i;
 
   for (i=X->colptr[col]; i<X->colptr[col+1]; i++) {
     if (y->nz[X->rowind[i]]) {
-      ((complex *)y->val)[X->rowind[i]] += 
-	a*CONJ(conjx,((complex *)X->values)[i]);
+      ((complex *)y->val)[X->rowind[i]] +=
+          a*CONJ(conjx,((complex *)X->values)[i]);
     }
     else {
-      ((complex *)y->val)[X->rowind[i]] = 
-	a*CONJ(conjx,((complex *)X->values)[i]);
+      ((complex *)y->val)[X->rowind[i]] =
+          a*CONJ(conjx,((complex *)X->values)[i]);
       y->nz[X->rowind[i]] = 1;
       y->idx[y->nnz++] = X->rowind[i];
     }
   }
-} 
+}
 
-static inline void 
+static inline void
 spa_daxpy_uplo (double a, ccs *X, int col, spa *y, int j, char uplo) {
   int i;
 
   for (i=X->colptr[col]; i<X->colptr[col+1]; i++) {
     if ((uplo == 'U' && X->rowind[i] <= j) ||
-	(uplo == 'L' && X->rowind[i] >= j)) {
+        (uplo == 'L' && X->rowind[i] >= j)) {
       if (y->nz[X->rowind[i]]) {
-	((double *)y->val)[X->rowind[i]] += a*((double *)X->values)[i];
+        ((double *)y->val)[X->rowind[i]] += a*((double *)X->values)[i];
       }
       else {
-	((double *)y->val)[X->rowind[i]] = a*((double *)X->values)[i];
-	y->nz[X->rowind[i]] = 1;
-	y->idx[y->nnz++] = X->rowind[i];
+        ((double *)y->val)[X->rowind[i]] = a*((double *)X->values)[i];
+        y->nz[X->rowind[i]] = 1;
+        y->idx[y->nnz++] = X->rowind[i];
       }
     }
   }
-} 
+}
 
-static inline void 
+static inline void
 spa_zaxpy_uplo (complex a, ccs *X, int col, spa *y, int j, char uplo) {
   int i;
 
   for (i=X->colptr[col]; i<X->colptr[col+1]; i++) {
     if ((uplo == 'U' && X->rowind[i] <= j) ||
-	(uplo == 'L' && X->rowind[i] >= j)) {
+        (uplo == 'L' && X->rowind[i] >= j)) {
       if (y->nz[X->rowind[i]]) {
-	((complex *)y->val)[X->rowind[i]] += a*((complex *)X->values)[i];
+        ((complex *)y->val)[X->rowind[i]] += a*((complex *)X->values)[i];
       }
       else {
-	((complex *)y->val)[X->rowind[i]] = a*((complex *)X->values)[i];
-	y->nz[X->rowind[i]] = 1;
-	y->idx[y->nnz++] = X->rowind[i];
+        ((complex *)y->val)[X->rowind[i]] = a*((complex *)X->values)[i];
+        y->nz[X->rowind[i]] = 1;
+        y->idx[y->nnz++] = X->rowind[i];
       }
     }
   }
-} 
+}
 
 static inline void spa_symb_axpy (ccs *X, int col, spa *y) {
   int i;
-  for (i=X->colptr[col]; i<X->colptr[col+1]; i++) 
+  for (i=X->colptr[col]; i<X->colptr[col+1]; i++)
     if (!y->nz[X->rowind[i]]) {
       y->nz[X->rowind[i]] = 1;
       y->idx[y->nnz++] = X->rowind[i];
     }
 }
 
-static inline void 
+static inline void
 spa_symb_axpy_uplo (ccs *X, int col, spa *y, int j, char uplo) {
   int i;
   for (i=X->colptr[col]; i<X->colptr[col+1]; i++)
     if ((uplo == 'U' && X->rowind[i] <= j) ||
-	(uplo == 'L' && X->rowind[i] >= j)) {
-         
+        (uplo == 'L' && X->rowind[i] >= j)) {
+
       if (!y->nz[X->rowind[i]]) {
-	y->nz[X->rowind[i]] = 1;
-	y->idx[y->nnz++] = X->rowind[i];
+        y->nz[X->rowind[i]] = 1;
+        y->idx[y->nnz++] = X->rowind[i];
       }
     }
 }
@@ -671,21 +671,21 @@ spa_symb_axpy_uplo (ccs *X, int col, spa *y, int j, char uplo) {
 static inline double spa_ddot (ccs *X, int col, spa *y) {
   int i;
   double a = 0;
-  for (i=X->colptr[col]; i<X->colptr[col+1]; i++) 
+  for (i=X->colptr[col]; i<X->colptr[col+1]; i++)
     if (y->nz[X->rowind[i]])
       a += ((double *)X->values)[i]*((double *)y->val)[X->rowind[i]];
 
   return a;
 }
 
-static inline 
+static inline
 complex spa_zdot (ccs *X, int col, spa *y, char conjx, char conjy) {
   int i;
   complex a = 0;
-  for (i=X->colptr[col]; i<X->colptr[col+1]; i++) 
+  for (i=X->colptr[col]; i<X->colptr[col+1]; i++)
     if (y->nz[X->rowind[i]])
       a += CONJ(conjx, ((complex *)X->values)[i])*
-	CONJ(conjy,((complex *)y->val)[X->rowind[i]]);
+      CONJ(conjy,((complex *)y->val)[X->rowind[i]]);
 
   return a;
 }
@@ -699,134 +699,87 @@ static void spa2compressed(spa *s, ccs *A, int col) {
       A->rowind[i] = s->idx[k];
       ((double *)A->values)[i] = ((double *)s->val)[s->idx[k++]];
     }
-    break;
+  break;
   case COMPLEX:
     for (i=A->colptr[col]; i<A->colptr[col+1]; i++) {
       A->rowind[i] = s->idx[k];
       ((complex *)A->values)[i] = ((complex *)s->val)[s->idx[k++]];
     }
     break;
-  }   
+  }
 }
 
-static int sp_daxpy(number a, void *x, void *y, int sp_x, int sp_y, 
+static int sp_daxpy(number a, void *x, void *y, int sp_x, int sp_y,
     int partial, void **z)
-{   
+{
   int j, k;
   if (sp_x && !sp_y) {
 
     ccs *X = x;
     double *Y = y;
-    
+
     for (j=0; j<X->ncols; j++) {
-      for (k=X->colptr[j]; k<X->colptr[j+1]; k++) 	
-	Y[X->rowind[k] + j*X->nrows] += a.d*(((double *)X->values)[k]);	      
-    }
-  }
-  else if (sp_x && sp_y && partial) 
-  {
-    ccs *X = x, *Y = y;    
-    int kX = 0, jX = 0, nnzX = X->colptr[X->ncols], kY, jY;
-    
-    for (jY=0; jY<Y->ncols; jY++) {    
-      for (kY=Y->colptr[jY]; kY<Y->colptr[jY+1]; kY++) {
-	
-	while ((kX < nnzX) && ((jX<jY) || 
-		(jX==jY && X->rowind[kX] < Y->rowind[kY]))) {
-	  while (X->colptr[jX+1] == kX+1) jX++;
-	  kX++;
-	}
-	
-	if ((jX == jY) && (X->rowind[kX] == Y->rowind[kY]) )
-	  ((double *)Y->values)[kY] = a.d*((double *)X->values)[kX] +
-	    ((double *)Y->values)[kY];
-	else 
-	  ((double *)Y->values)[kY] = ((double *)Y->values)[kY];
-      }
-    }
-  } 
+      for (k=X->colptr[j]; k<X->colptr[j+1]; k++)
+        Y[X->rowind[k] + j*X->nrows] += a.d*(((double *)X->values)[k]);
+    }
+  }
+  else if (sp_x && sp_y && partial) {
+
+    ccs *X = x, *Y = y;
+    spa *s = alloc_spa(X->nrows, DOUBLE);
+
+    int n = X->ncols;
+
+    for (j=0; j<n; j++) {
+
+      init_spa(s, Y, j);
+      spa_daxpy_partial(a.d, X, j, s);
+      spa2compressed(s, Y, j);
+
+    }
+    free_spa(s);
+
+  }
   else if (sp_x && sp_y && !partial) {
 
-    ccs *X = x, *Y = y;    
-    int kX = 0, jX = 0, nnzX = X->colptr[X->ncols];
-    int kY = 0, jY = 0;
-    int nnzZ = 0;
-
-    while (nnzX && !(X->colptr[jX+1])) jX++;
-
-    for (jY=0; jY<Y->ncols; jY++) {    
-      for (kY=Y->colptr[jY]; kY<Y->colptr[jY+1]; kY++) {
-	
-	while ((kX < nnzX) && ((jX<jY) || 
-		(jX==jY && X->rowind[kX] < Y->rowind[kY]))) {
-	  while (X->colptr[jX+1] == kX+1) jX++;
-	  kX++; nnzZ++;
-	}
-
-	if (jX==jY && X->rowind[kX] == Y->rowind[kY]) {
-	  while (X->colptr[jX+1] == kX+1) jX++;
-	  kX++;
-	} 
-	nnzZ++;	
-      }
-    }
-
-    nnzZ += (nnzX - kX);    
-
-    ccs *Z;
-    if (!(Z = alloc_ccs(Y->nrows, Y->ncols, nnzZ, Y->id))) return -1;
-
-    kX = 0; jX = 0; kY = 0; jY = 0, nnzZ = 0;
-    while (nnzX && !(X->colptr[jX+1])) jX++;
-
-    for (jY=0; jY<Y->ncols; jY++) {    
-      for (kY=Y->colptr[jY]; kY<Y->colptr[jY+1]; kY++) {
-	
-	while ((kX < nnzX) && ((jX<jY) || 
-		(jX==jY && X->rowind[kX] < Y->rowind[kY]))) {
-	  Z->colptr[jX+1]++;
-	  Z->rowind[nnzZ] = X->rowind[kX];
-	  ((double *)Z->values)[nnzZ++] = a.d*((double *)X->values)[kX];
-
-	  while (X->colptr[jX+1] == kX+1) jX++;
-	  kX++;
-	}
-	
-	Z->colptr[jY+1]++;
-	Z->rowind[nnzZ] = Y->rowind[kY];
-	if (jX==jY && X->rowind[kX] == Y->rowind[kY]) {
-	  ((double *)Z->values)[nnzZ++] = a.d*((double *)X->values)[kX] +
-	    ((double *)Y->values)[kY];
-	  while (X->colptr[jX+1] == kX+1) jX++;
-	  kX++;
-	} 
-	else ((double *)Z->values)[nnzZ++] = ((double *)Y->values)[kY];
-      }
-    }
-    
-    while (kX < nnzX) {
-      Z->colptr[jX+1]++;
-      Z->rowind[nnzZ] = X->rowind[kX];
-      ((double *)Z->values)[nnzZ++] = a.d*((double *)X->values)[kX];
-      
-      while (X->colptr[jX+1] == kX+1) jX++;
-      kX++;      
-    }
-    
-    int i;
-    for (i=0; i<Z->ncols; i++) Z->colptr[i+1] += Z->colptr[i];
-    
-    *z = Z;
-  }    
-  else if (!sp_x && sp_y && partial)
-  { 
+    ccs *X = x, *Y = y;
+    spa *s = alloc_spa(X->nrows, DOUBLE);
+
+    int m = X->nrows, n = X->ncols;
+    ccs *Z = alloc_ccs(m, n, X->colptr[n]+Y->colptr[n], DOUBLE);
+    if (!Z) return -1;
+
+    for (j=0; j<n; j++) {
+
+      init_spa(s, Y, j);
+      spa_daxpy(a.d, X, j, s);
+      Z->colptr[j+1] = Z->colptr[j] + s->nnz;
+      spa2compressed(s, Z, j);
+
+    }
+    free_spa(s);
+
+    Z->rowind = realloc(Z->rowind, Z->colptr[n]*sizeof(int_t));
+    Z->values = realloc(Z->values, Z->colptr[n]*sizeof(double));
+
+    ccs *Zt = transpose(Z, 0);
+    free_ccs(Z);
+    if (!Zt) return -1;
+
+    *z = transpose(Zt, 0);
+    free_ccs(Zt);
+    if (!(*z)) return -1;
+
+  }
+  else if (!sp_x && sp_y && partial) {
+
     double *X = x;
     ccs *Y = y;
     int kY, jY;
-    
-    for (jY=0; jY<Y->ncols; jY++) {      
-      for (kY=Y->colptr[jY]; kY<Y->colptr[jY+1]; kY++) 
-	((double *)Y->values)[kY] += a.d*X[jY*Y->nrows + Y->rowind[kY]];      
+
+    for (jY=0; jY<Y->ncols; jY++) {
+      for (kY=Y->colptr[jY]; kY<Y->colptr[jY+1]; kY++)
+        ((double *)Y->values)[kY] += a.d*X[jY*Y->nrows + Y->rowind[kY]];
     }
   }
   else { // if (!sp_x && !sp_y) {
@@ -834,11 +787,11 @@ static int sp_daxpy(number a, void *x, void *y, int sp_x, int sp_y,
     double *X = x;
     ccs *Y = y;
 
-    int mn = Y->nrows*Y->ncols; 
+    int mn = Y->nrows*Y->ncols;
     ccs *Z = alloc_ccs(Y->nrows, Y->ncols, mn, Y->id);
     if (!Z) return -1;
 
-    memcpy(Z->values, X, sizeof(double)*mn); 
+    memcpy(Z->values, X, sizeof(double)*mn);
     scal[Y->id](&mn, &a, Z->values, (int *)&One[INT]);
 
     int j, k;
@@ -846,148 +799,100 @@ static int sp_daxpy(number a, void *x, void *y, int sp_x, int sp_y,
 
       Z->colptr[j+1] = Z->colptr[j] + Y->nrows;
 
-      for (k=0; k<Y->nrows; k++) 
-	Z->rowind[j*Y->nrows+k] = k;
+      for (k=0; k<Y->nrows; k++)
+        Z->rowind[j*Y->nrows+k] = k;
 
       for (k=Y->colptr[j]; k<Y->colptr[j+1]; k++)
-	((double *)Z->values)[j*Y->nrows + Y->rowind[k]] += 
-	  ((double *)Y->values)[k];
-    }    
+        ((double *)Z->values)[j*Y->nrows + Y->rowind[k]] +=
+            ((double *)Y->values)[k];
+    }
     *z = Z;
   }
   return 0;
 }
 
-static int sp_zaxpy(number a, void *x, void *y, int sp_x, int sp_y, 
+static int sp_zaxpy(number a, void *x, void *y, int sp_x, int sp_y,
     int partial, void **z)
-{   
+{
   int j, k;
   if (sp_x && !sp_y) {
 
     ccs *X = x;
     complex *Y = y;
-    
+
     for (j=0; j<X->ncols; j++) {
-      for (k=X->colptr[j]; k<X->colptr[j+1]; k++) 	
-	Y[X->rowind[k] + j*X->nrows] += a.z*(((complex *)X->values)[k]);      
-    }
-  }
-  else if (sp_x && sp_y && partial) 
-  {
-    ccs *X = x, *Y = y;    
-    int kX = 0, jX = 0, nnzX = X->colptr[X->ncols], kY, jY;
-    
-    for (jY=0; jY<Y->ncols; jY++) {    
-      for (kY=Y->colptr[jY]; kY<Y->colptr[jY+1]; kY++) {
-	
-	while ((kX < nnzX) && ((jX<jY) || 
-		(jX==jY && X->rowind[kX] < Y->rowind[kY]))) {
-	  while (X->colptr[jX+1] == kX+1) jX++;
-	  kX++;
-	}
-	
-	if ((jX == jY) && (X->rowind[kX] == Y->rowind[kY]) )
-	  ((complex *)Y->values)[kY] = a.z*((complex *)X->values)[kX] +
-	    ((complex *)Y->values)[kY];
-	else 
-	  ((complex *)Y->values)[kY] = ((complex *)Y->values)[kY];
-      }
-    }
-  } 
+      for (k=X->colptr[j]; k<X->colptr[j+1]; k++)
+        Y[X->rowind[k] + j*X->nrows] += a.z*(((complex *)X->values)[k]);
+    }
+  }
+  else if (sp_x && sp_y && partial) {
+
+    ccs *X = x, *Y = y;
+    spa *s = alloc_spa(X->nrows, COMPLEX);
+
+    int n = X->ncols;
+
+    for (j=0; j<n; j++) {
+
+      init_spa(s, Y, j);
+      spa_zaxpy_partial(a.z, X, j, s);
+      spa2compressed(s, Y, j);
+
+    }
+    free_spa(s);
+  }
   else if (sp_x && sp_y && !partial) {
 
-    ccs *X = x, *Y = y;    
-    int kX = 0, jX = 0, nnzX = X->colptr[X->ncols];
-    int kY = 0, jY = 0;
-    int nnzZ = 0;
-
-    while (nnzX && !(X->colptr[jX+1])) jX++;
-
-    for (jY=0; jY<Y->ncols; jY++) {    
-      for (kY=Y->colptr[jY]; kY<Y->colptr[jY+1]; kY++) {
-	
-	while ((kX < nnzX) && ((jX<jY) || 
-		(jX==jY && X->rowind[kX] < Y->rowind[kY]))) {
-	  while (X->colptr[jX+1] == kX+1) jX++;
-	  kX++; nnzZ++;
-	}
-
-	if (jX==jY && X->rowind[kX] == Y->rowind[kY]) {
-	  while (X->colptr[jX+1] == kX+1) jX++;
-	  kX++;
-	} 
-	nnzZ++;	
-      }
-    }
-
-    nnzZ += (nnzX - kX);    
-
-    ccs *Z;
-    if (!(Z = alloc_ccs(Y->nrows, Y->ncols, nnzZ, Y->id))) return -1;
-
-    kX = 0; jX = 0; kY = 0; jY = 0, nnzZ = 0;
-    while (nnzX && !(X->colptr[jX+1])) jX++;
-
-    for (jY=0; jY<Y->ncols; jY++) {    
-      for (kY=Y->colptr[jY]; kY<Y->colptr[jY+1]; kY++) {
-	
-	while ((kX < nnzX) && ((jX<jY) || 
-		(jX==jY && X->rowind[kX] < Y->rowind[kY]))) {
-	  Z->colptr[jX+1]++;
-	  Z->rowind[nnzZ] = X->rowind[kX];
-	  ((complex *)Z->values)[nnzZ++] = a.z*((complex *)X->values)[kX];
-
-	  while (X->colptr[jX+1] == kX+1) jX++;
-	  kX++;
-	}
-	
-	Z->colptr[jY+1]++;
-	Z->rowind[nnzZ] = Y->rowind[kY];
-	if (jX==jY && X->rowind[kX] == Y->rowind[kY]) {
-	  ((complex *)Z->values)[nnzZ++] = a.z*((complex *)X->values)[kX] +
-	    ((complex *)Y->values)[kY];
-	  while (X->colptr[jX+1] == kX+1) jX++;
-	  kX++;
-	} 
-	else ((complex *)Z->values)[nnzZ++] = ((complex *)Y->values)[kY];		  
-      }
-    }
-    
-    while (kX < nnzX) {
-      Z->colptr[jX+1]++;
-      Z->rowind[nnzZ] = X->rowind[kX];
-      ((complex *)Z->values)[nnzZ++] = a.z*((complex *)X->values)[kX];
-      
-      while (X->colptr[jX+1] == kX+1) jX++;
-      kX++;      
-    }
-    
-    int i;
-    for (i=0; i<Z->ncols; i++) Z->colptr[i+1] += Z->colptr[i];
-    
-    *z = Z;
-  }    
+    ccs *X = x, *Y = y;
+    spa *s = alloc_spa(X->nrows, COMPLEX);
+
+    int m = X->nrows, n = X->ncols;
+    ccs *Z = alloc_ccs(m, n, X->colptr[n]+Y->colptr[n], COMPLEX);
+    if (!Z) return -1;
+
+    for (j=0; j<n; j++) {
+
+      init_spa(s, Y, j);
+      spa_zaxpy(a.z, X, 'N', j, s);
+      Z->colptr[j+1] = Z->colptr[j] + s->nnz;
+      spa2compressed(s, Z, j);
+
+    }
+    free_spa(s);
+
+    Z->rowind = realloc(Z->rowind, Z->colptr[n]*sizeof(int_t));
+    Z->values = realloc(Z->values, Z->colptr[n]*sizeof(complex));
+
+    ccs *Zt = transpose(Z, 0);
+    free_ccs(Z);
+    if (!Zt) return -1;
+
+    *z = transpose(Zt, 0);
+    free_ccs(Zt);
+    if (!(*z)) return -1;
+
+  }
   else if (!sp_x && sp_y && partial)
-  { 
+    {
     complex *X = x;
     ccs *Y = y;
     int kY, jY;
-    
-    for (jY=0; jY<Y->ncols; jY++) {      
-      for (kY=Y->colptr[jY]; kY<Y->colptr[jY+1]; kY++) 
-	((complex *)Y->values)[kY] += a.z*X[jY*Y->nrows + Y->rowind[kY]];      
+
+    for (jY=0; jY<Y->ncols; jY++) {
+      for (kY=Y->colptr[jY]; kY<Y->colptr[jY+1]; kY++)
+        ((complex *)Y->values)[kY] += a.z*X[jY*Y->nrows + Y->rowind[kY]];
+    }
     }
-  }
   else { // if (!p_x && !sp_y) {
 
     complex *X = x;
     ccs *Y = y;
 
-    int mn = Y->nrows*Y->ncols; 
+    int mn = Y->nrows*Y->ncols;
     ccs *Z = alloc_ccs(Y->nrows, Y->ncols, mn, Y->id);
     if (!Z) return -1;
 
-    memcpy(Z->values, X, sizeof(complex)*mn); 
+    memcpy(Z->values, X, sizeof(complex)*mn);
     scal[Y->id](&mn, &a, Z->values, (int *)&One[INT]);
 
     int j, k;
@@ -995,19 +900,19 @@ static int sp_zaxpy(number a, void *x, void *y, int sp_x, int sp_y,
 
       Z->colptr[j+1] = Z->colptr[j] + Y->nrows;
 
-      for (k=0; k<Y->nrows; k++) 
-	Z->rowind[j*Y->nrows+k] = k;
+      for (k=0; k<Y->nrows; k++)
+        Z->rowind[j*Y->nrows+k] = k;
 
       for (k=Y->colptr[j]; k<Y->colptr[j+1]; k++)
-	((complex *)Z->values)[j*Y->nrows + Y->rowind[k]] += 
-	  ((complex *)Y->values)[k];
-    }    
+        ((complex *)Z->values)[j*Y->nrows + Y->rowind[k]] +=
+            ((complex *)Y->values)[k];
+    }
     *z = Z;
   }
   return 0;
 }
 
-static int sp_dgemv(char tA, int m, int n, number alpha, void *a, int oA, 
+static int sp_dgemv(char tA, int m, int n, number alpha, void *a, int oA,
     void *x, int ix, number beta, void *y, int iy)
 {
   ccs *A = a;
@@ -1019,28 +924,28 @@ static int sp_dgemv(char tA, int m, int n, number alpha, void *a, int oA,
   int i, j, k, oi = oA % A->nrows, oj = oA / A->nrows;
 
   if (tA == 'N') {
-    for (j=oj; j<n+oj; j++) {  
-      for (k=A->colptr[j]; k<A->colptr[j+1]; k++) 
-	if ((A->rowind[k] >= oi) && (A->rowind[k] < oi+m))
-	  Y[iy*(A->rowind[k]-oi + (iy > 0 ? 0 : 1 - m))] +=
-	    alpha.d*((double *)A->values)[k]*
-	    X[ix*(j-oj + (ix > 0 ? 0 : 1 - n))];      
-      
-    }
-  } else {   
+    for (j=oj; j<n+oj; j++) {
+      for (k=A->colptr[j]; k<A->colptr[j+1]; k++)
+        if ((A->rowind[k] >= oi) && (A->rowind[k] < oi+m))
+          Y[iy*(A->rowind[k]-oi + (iy > 0 ? 0 : 1 - m))] +=
+              alpha.d*((double *)A->values)[k]*
+              X[ix*(j-oj + (ix > 0 ? 0 : 1 - n))];
+
+    }
+  } else {
     for (i=oj; i<oj+n; i++) {
       for (k=A->colptr[i]; k<A->colptr[i+1]; k++) {
-	if ((A->rowind[k] >= oi) && (A->rowind[k] < oi+m))
-	  Y[iy*(i-oj + (iy > 0 ? 0 : 1 - n))] += alpha.d*
-	    ((double *)A->values)[k]*
-	    X[ix*(A->rowind[k]-oi + (ix > 0 ? 0 : 1 - m))];	  
+        if ((A->rowind[k] >= oi) && (A->rowind[k] < oi+m))
+          Y[iy*(i-oj + (iy > 0 ? 0 : 1 - n))] += alpha.d*
+          ((double *)A->values)[k]*
+          X[ix*(A->rowind[k]-oi + (ix > 0 ? 0 : 1 - m))];
       }
-    }    
+    }
   }
   return 0;
 }
 
-static int sp_zgemv(char tA, int m, int n, number alpha, void *a, int oA, 
+static int sp_zgemv(char tA, int m, int n, number alpha, void *a, int oA,
     void *x, int ix, number beta, void *y, int iy)
 {
   ccs *A = a;
@@ -1052,22 +957,22 @@ static int sp_zgemv(char tA, int m, int n, number alpha, void *a, int oA,
   int i, j, k, oi = oA % A->nrows, oj = oA / A->nrows;
 
   if (tA == 'N') {
-    for (j=oj; j<n+oj; j++) {  
-      for (k=A->colptr[j]; k<A->colptr[j+1]; k++) 
-	if ((A->rowind[k] >= oi) && (A->rowind[k] < oi+m))
-	  Y[iy*(A->rowind[k]-oi + (iy > 0 ? 0 : 1 - m))] +=
-	    alpha.z*((complex *)A->values)[k]*
-	    X[ix*(j-oj + (ix > 0 ? 0 : 1 - n))];      
-    }
-  } else {   
+    for (j=oj; j<n+oj; j++) {
+      for (k=A->colptr[j]; k<A->colptr[j+1]; k++)
+        if ((A->rowind[k] >= oi) && (A->rowind[k] < oi+m))
+          Y[iy*(A->rowind[k]-oi + (iy > 0 ? 0 : 1 - m))] +=
+              alpha.z*((complex *)A->values)[k]*
+              X[ix*(j-oj + (ix > 0 ? 0 : 1 - n))];
+    }
+  } else {
     for (i=oj; i<oj+n; i++) {
       for (k=A->colptr[i]; k<A->colptr[i+1]; k++) {
-	if ((A->rowind[k] >= oi) && (A->rowind[k] < oi+m))
-	  Y[iy*(i-oj + (iy > 0 ? 0 : 1 - n))] += alpha.z*
-	    CONJ(tA, ((complex *)A->values)[k])*
-	    X[ix*(A->rowind[k]-oi + (ix > 0 ? 0 : 1 - m))];  
+        if ((A->rowind[k] >= oi) && (A->rowind[k] < oi+m))
+          Y[iy*(i-oj + (iy > 0 ? 0 : 1 - n))] += alpha.z*
+          CONJ(tA, ((complex *)A->values)[k])*
+          X[ix*(A->rowind[k]-oi + (ix > 0 ? 0 : 1 - m))];
       }
-    }    
+    }
   }
   return 0;
 }
@@ -1076,36 +981,36 @@ static int sp_zgemv(char tA, int m, int n, number alpha, void *a, int oA,
 int sp_dsymv(char uplo, int n, number alpha, ccs *A, int oA, void *x, int ix,
     number beta, void *y, int iy)
 {
-  double *X = x, *Y = y; 
+  double *X = x, *Y = y;
   scal[A->id](&n, &beta, y, &iy);
 
   if (!n) return 0;
   int i, j, k, oi = oA % A->nrows, oj = oA / A->nrows;
-  for (j=0; j<n; j++) {  
-    
+  for (j=0; j<n; j++) {
+
     for (k = A->colptr[j+oj]; k < A->colptr[j+oj+1]; k++) {
-      i = A->rowind[k] - oi; 
+      i = A->rowind[k] - oi;
 
       if ((i >= 0) && (i < n)) {
-	if ((uplo == 'U') && (i > j)) 
-	  break;
-	if ((uplo == 'U') && (i <= j)) {
-	  Y[iy*(i + (iy > 0 ? 0 : 1 - n))] += alpha.d*((double *)A->values)[k]*
-	    X[ix*(j + (ix > 0 ? 0 : 1-n))];
-	  if (i != j)
-	    Y[iy*(j + (iy > 0 ? 0 : 1-n))] += alpha.d*((double *)A->values)[k]*
-	      X[ix*(i + (ix > 0 ? 0 : 1-n))];
-	}
-	else if ((uplo == 'L') && (i >= j)) {
-	  Y[iy*(i + (iy > 0 ? 0 : 1-n))] += alpha.d*((double *)A->values)[k]*
-	    X[ix*(j + (ix > 0 ? 0 : 1-n))];
-	  if (i != j)
-	    Y[iy*(j + (iy > 0 ? 0 : 1-n))] += alpha.d*((double *)A->values)[k]*
-	      X[ix*(i + (ix > 0 ? 0 : 1-n))];
-	} 
-      }
-    }
-  }    
+        if ((uplo == 'U') && (i > j))
+          break;
+        if ((uplo == 'U') && (i <= j)) {
+          Y[iy*(i + (iy > 0 ? 0 : 1 - n))] += alpha.d*((double *)A->values)[k]*
+              X[ix*(j + (ix > 0 ? 0 : 1-n))];
+          if (i != j)
+            Y[iy*(j + (iy > 0 ? 0 : 1-n))] += alpha.d*((double *)A->values)[k]*
+            X[ix*(i + (ix > 0 ? 0 : 1-n))];
+        }
+        else if ((uplo == 'L') && (i >= j)) {
+          Y[iy*(i + (iy > 0 ? 0 : 1-n))] += alpha.d*((double *)A->values)[k]*
+              X[ix*(j + (ix > 0 ? 0 : 1-n))];
+          if (i != j)
+            Y[iy*(j + (iy > 0 ? 0 : 1-n))] += alpha.d*((double *)A->values)[k]*
+            X[ix*(i + (ix > 0 ? 0 : 1-n))];
+        }
+      }
+    }
+  }
   return 0;
 }
 
@@ -1117,35 +1022,35 @@ int sp_zsymv(char uplo, int n, number alpha, ccs *A, int oA, void *x, int ix,
 
   if (!n) return 0;
   int i, j, k, oi = oA % A->nrows, oj = oA / A->nrows;
-  for (j=0; j<n; j++) {  
+  for (j=0; j<n; j++) {
 
     for (k = A->colptr[j+oj]; k < A->colptr[j+oj+1]; k++) {
-      i = A->rowind[k] - oi; 
-
-      if ((i >= 0) && (i < n)) {      
-	if ((uplo == 'U') && (i > j)) 
-	  break;
-	if ((uplo == 'U') && (i <= j)) {
-	  Y[iy*(i + (iy > 0 ? 0 : 1-n))] += alpha.z*((complex *)A->values)[k]*
-	    X[ix*(j + (ix > 0 ? 0 : 1-n))];
-	  if (i != j)
-	    Y[iy*(j+(iy>0 ? 0 : 1-n))] += alpha.z*((complex *)A->values)[k]*
-	      X[ix*(i + (ix > 0 ? 0 : 1-n))];
-	}
-	else if ((uplo == 'L') && (i >= j)) {
-	  Y[iy*(i + (iy > 0 ? 0 : 1-n))] += alpha.z*((complex *)A->values)[k]*
-	    X[ix*(j + (ix > 0 ? 0 : 1-n))];
-	  if (i != j)
-	    Y[iy*(j+(iy > 0 ? 0 : 1-n))] += alpha.z*((complex *)A->values)[k]*
-	      X[ix*(i + (ix > 0 ? 0 : 1-n))];
-	}       
-      }
-    }
-  }    
+      i = A->rowind[k] - oi;
+
+      if ((i >= 0) && (i < n)) {
+        if ((uplo == 'U') && (i > j))
+          break;
+        if ((uplo == 'U') && (i <= j)) {
+          Y[iy*(i + (iy > 0 ? 0 : 1-n))] += alpha.z*((complex *)A->values)[k]*
+              X[ix*(j + (ix > 0 ? 0 : 1-n))];
+          if (i != j)
+            Y[iy*(j+(iy>0 ? 0 : 1-n))] += alpha.z*((complex *)A->values)[k]*
+            X[ix*(i + (ix > 0 ? 0 : 1-n))];
+        }
+        else if ((uplo == 'L') && (i >= j)) {
+          Y[iy*(i + (iy > 0 ? 0 : 1-n))] += alpha.z*((complex *)A->values)[k]*
+              X[ix*(j + (ix > 0 ? 0 : 1-n))];
+          if (i != j)
+            Y[iy*(j+(iy > 0 ? 0 : 1-n))] += alpha.z*((complex *)A->values)[k]*
+            X[ix*(i + (ix > 0 ? 0 : 1-n))];
+        }
+      }
+    }
+  }
   return 0;
 }
 
-static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b, 
+static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
     number beta, void *c, int sp_a, int sp_b, int sp_c, int partial, void **z,
     int m, int n, int k)
 {
@@ -1163,13 +1068,13 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
       return -1;
     }
 
-    for (j=0; j<n; j++) {   
+    for (j=0; j<n; j++) {
       for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
-	init_spa(s, A, C->rowind[l]);
-	((double *)C->values)[l] = alpha.d*spa_ddot (B, j, s) +
-	  beta.d*((double *)C->values)[l];	  
+        init_spa(s, A, C->rowind[l]);
+        ((double *)C->values)[l] = alpha.d*spa_ddot (B, j, s) +
+            beta.d*((double *)C->values)[l];
       }
-    }    
+    }
     free_spa(s);
     if (A != a) free_ccs(A);
     if (B != b) free_ccs(B);
@@ -1180,7 +1085,7 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
     ccs *A = (tA == 'N' ? a : transpose(a, 0));
     ccs *B = (tB == 'N' ? b : transpose(b, 0));
     ccs *C = c;
-    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));    
+    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));
 
     spa *s = alloc_spa(A->nrows, A->id);
     if (!s || !colptr_new) {
@@ -1194,19 +1099,19 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
     for (j=0; j<n; j++) {
       init_spa(s, NULL, 0);
       if (beta.d != 0.0)
-      	spa_symb_axpy (C, j, s);
-      
-      for (l=B->colptr[j]; l<B->colptr[j+1]; l++) 
-	spa_symb_axpy (A, B->rowind[l], s);
+        spa_symb_axpy (C, j, s);
+
+      for (l=B->colptr[j]; l<B->colptr[j+1]; l++)
+        spa_symb_axpy (A, B->rowind[l], s);
 
       colptr_new[j+1] = colptr_new[j] + s->nnz;
-    }   
-    
-    int nnz = colptr_new[n]; 
+    }
+
+    int nnz = colptr_new[n];
     ccs *Z = alloc_ccs(m, n, MAX(nnz,CCS_NNZ(C)), C->id);
     if (!Z) {
-      if (A != a) free_ccs(A); 
-      if (B != b) free_ccs(B); 
+      if (A != a) free_ccs(A);
+      if (B != b) free_ccs(B);
       free(colptr_new); free_spa(s);
       return -1;
     }
@@ -1215,19 +1120,19 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
     for (j=0; j<n; j++) {
       init_spa(s, NULL, 0);
       if (beta.d != 0.0)
-      	spa_daxpy (beta.d, C, j, s);
-      
-      for (l=B->colptr[j]; l<B->colptr[j+1]; l++) 	
-	spa_daxpy (((double *)B->values)[l], A, B->rowind[l], s);
+        spa_daxpy (beta.d, C, j, s);
+
+      for (l=B->colptr[j]; l<B->colptr[j+1]; l++)
+        spa_daxpy (alpha.d*((double *)B->values)[l], A, B->rowind[l], s);
 
       spa2compressed(s, Z, j);
-    }   
-    
+    }
+
     free_spa(s);
 
     if (A != a) free_ccs(A);
     if (B != b) free_ccs(B);
-    
+
     if (sort_ccs(Z)) {
       free_ccs(Z); return -1;
     }
@@ -1246,79 +1151,79 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
       return -1;
     }
 
-    int mn = m*n; 
+    int mn = m*n;
     scal[A->id](&mn, &beta, C, (int *)&One[INT]);
 
-    int j, l;    
+    int j, l;
     for (j=0; j<n; j++) {
       init_spa(s, NULL, 0);
-      
-      for (l=B->colptr[j]; l<B->colptr[j+1]; l++) 	
-	spa_daxpy (((double *)B->values)[l], A, B->rowind[l], s);
 
-      for (l=0; l<s->nnz; l++) 
-	C[j*A->nrows + s->idx[l]] += alpha.d*((double *)s->val)[s->idx[l]];
-    }   
+      for (l=B->colptr[j]; l<B->colptr[j+1]; l++)
+        spa_daxpy (((double *)B->values)[l], A, B->rowind[l], s);
+
+      for (l=0; l<s->nnz; l++)
+        C[j*A->nrows + s->idx[l]] += alpha.d*((double *)s->val)[s->idx[l]];
+    }
     free_spa(s);
-    
+
     if (A != a) free_ccs(A);
     if (B != b) free_ccs(B);
   }
 
   else if (!sp_a && sp_b && !sp_c) {
-   
-    double *A = a, *C = c;    
+
+    double *A = a, *C = c;
     ccs *B = (tB == 'N' ? b : transpose(b, 0));
 
     int j, l, mn_ = m*n;
     scal[DOUBLE](&mn_, &beta, C, (int *)&One[INT]);
- 
+
     for (j=0; j<n; j++) {
-      for (l=B->colptr[j]; l<B->colptr[j+1]; l++) {	
-	double a_ = alpha.d*((double *)B->values)[l];	
-	axpy[DOUBLE](&m, &a_, A + (tA=='N' ? B->rowind[l]*m : B->rowind[l]), 
-	    (tA=='N' ? (int *)&One[INT] : &k), C + j*m, (int *)&One[INT]);
+      for (l=B->colptr[j]; l<B->colptr[j+1]; l++) {
+        double a_ = alpha.d*((double *)B->values)[l];
+        axpy[DOUBLE](&m, &a_, A + (tA=='N' ? B->rowind[l]*m : B->rowind[l]),
+            (tA=='N' ? (int *)&One[INT] : &k), C + j*m, (int *)&One[INT]);
       }
-    }    
+    }
     if (B != b) free_ccs(B);
   }
 
   else if (sp_a && !sp_b && !sp_c) {
 
     ccs *A = (tA == 'N' ? a : transpose(a, 0));
-    double *B = b, *C = c;    
+    double *B = b, *C = c;
 
     int j, l, mn_ = m*n, ib = (tB == 'N' ? k : 1);
     scal[DOUBLE](&mn_, &beta, C, (int *)&One[INT]);
-    
+
     for (j=0; j<A->ncols; j++) {
       for (l=A->colptr[j]; l<A->colptr[j+1]; l++) {
 
-	double a_ = alpha.d*((double *)A->values)[l];	
-	axpy[DOUBLE](&n, &a_, B + (tB == 'N' ? j : j*n), &ib, 
-	    C + A->rowind[l], &m);
+        double a_ = alpha.d*((double *)A->values)[l];
+        axpy[DOUBLE](&n, &a_, B + (tB == 'N' ? j : j*n), &ib,
+            C + A->rowind[l], &m);
       }
     }
     if (A != a) free_ccs(A);
   }
-  
+
   else if (!sp_a && sp_b && sp_c && partial) {
 
     double *A = a, val;
     ccs *B = (tB == 'N' ? b : transpose(b, 0)), *C = c;
     int j, l, o;
 
-    for (j=0; j<n; j++) {    
+    for (j=0; j<n; j++) {
       for (o=C->colptr[j]; o<C->colptr[j+1]; o++) {
 
-	val = 0;
-	for (l=B->colptr[j]; l < B->colptr[j+1]; l++)
-	  val += A[tA == 'N' ? C->rowind[o] + B->rowind[l]*m : 
-		   B->rowind[l] + C->rowind[o]*B->nrows]*
-	    ((double *)B->values)[l];
-	
-	((double *)C->values)[o] = alpha.d*val + 
-	  beta.d*((double *)C->values)[o];
+        val = 0;
+        for (l=B->colptr[j]; l < B->colptr[j+1]; l++)
+          val += A[tA == 'N' ? C->rowind[o] + B->rowind[l]*m :
+          B->rowind[l] + C->rowind[o]*B->nrows]*
+          ((double *)B->values)[l];
+
+        ((double *)C->values)[o] = alpha.d*val +
+            beta.d*((double *)C->values)[o];
       }
     }
     if (B != b) free_ccs(B);
@@ -1327,8 +1232,8 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
 
     double *A = a;
     ccs *B = (tB == 'N' ? b : transpose(b,0)), *C = c;
-    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));    
-    
+    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));
+
     if (!colptr_new) {
       if (B != b) free_ccs(B);
       free(colptr_new);
@@ -1336,14 +1241,14 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
     }
 
     int j, l;
-    for (j=0; j<n; j++) 
-      colptr_new[j+1] = colptr_new[j] + 
-	MAX(((B->colptr[j+1]-B->colptr[j])>0)*m, C->colptr[j+1]-C->colptr[j]);
+    for (j=0; j<n; j++)
+      colptr_new[j+1] = colptr_new[j] +
+      MAX(((B->colptr[j+1]-B->colptr[j])>0)*m, C->colptr[j+1]-C->colptr[j]);
 
-    int nnz = colptr_new[n]; 
+    int nnz = colptr_new[n];
     ccs *Z = alloc_ccs(m, n, nnz, C->id);
     if (!Z) {
-      if (B != b) free_ccs(B); 
+      if (B != b) free_ccs(B);
       free(colptr_new);
       return -1;
     }
@@ -1351,36 +1256,36 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
     for (l=0; l<nnz; l++) ((double *)Z->values)[l] = 0;
 
     for (j=0; j<C->ncols; j++) {
-      
+
       if (B->colptr[j+1]-B->colptr[j])
-	for (l=0; l<m; l++)
-	  Z->rowind[Z->colptr[j]+l] = l;
+        for (l=0; l<m; l++)
+          Z->rowind[Z->colptr[j]+l] = l;
 
       for (k=B->colptr[j]; k<B->colptr[j+1]; k++) {
-	
-	double a_ = alpha.d*((double *)B->values)[k];
-	axpy[DOUBLE](&m, &a_, A + 
-	    (tA=='N' ? B->rowind[k]*m : B->rowind[k]), 
-	    (tA=='N' ? (int *)&One[INT] : &k), 
-	    (double *)Z->values + Z->colptr[j], (int *)&One[INT]);
-      }
-      
+
+        double a_ = alpha.d*((double *)B->values)[k];
+        axpy[DOUBLE](&m, &a_, A +
+            (tA=='N' ? B->rowind[k]*m : B->rowind[k]),
+            (tA=='N' ? (int *)&One[INT] : &k),
+            (double *)Z->values + Z->colptr[j], (int *)&One[INT]);
+      }
+
       if (beta.d != 0.0) {
-	if (Z->colptr[j+1]-Z->colptr[j] == m) {
-	  for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
-	    ((double *)Z->values)[Z->colptr[j]+C->rowind[l]] +=
-	      beta.d*((double *)C->values)[l];
-	  }	
-	}
-	else {
-	  for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
-	    ((double *)Z->values)[Z->colptr[j]+l-C->colptr[j]] =
-	      beta.d*((double *)C->values)[l];
-	    Z->rowind[Z->colptr[j]+l-C->colptr[j]] = C->rowind[l];
-	  }
-	}
-      }
-    }       
+        if (Z->colptr[j+1]-Z->colptr[j] == m) {
+          for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
+            ((double *)Z->values)[Z->colptr[j]+C->rowind[l]] +=
+                beta.d*((double *)C->values)[l];
+          }
+        }
+        else {
+          for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
+            ((double *)Z->values)[Z->colptr[j]+l-C->colptr[j]] =
+                beta.d*((double *)C->values)[l];
+            Z->rowind[Z->colptr[j]+l-C->colptr[j]] = C->rowind[l];
+          }
+        }
+      }
+    }
     if (B != b) free_ccs(B);
     *z = Z;
   }
@@ -1389,18 +1294,18 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
     ccs *A = (tA == 'N' ? transpose(a,0) : a), *C = c;
     double *B = b, val;
 
-    int j, l, o;   
-    for (j=0; j<n; j++) {      
+    int j, l, o;
+    for (j=0; j<n; j++) {
       for (o=C->colptr[j]; o<C->colptr[j+1]; o++) {
-	
-	val = 0;
-	for (l=A->colptr[C->rowind[o]]; l < A->colptr[C->rowind[o]+1]; l++)
-	  val += ((double *)A->values)[l]*
-	    B[tB == 'N' ? j*A->nrows + A->rowind[l] : 
-		A->rowind[l]*C->ncols + j];
-	
-	((double *)C->values)[o] = alpha.d*val + 
-	  beta.d*((double *)C->values)[o];	
+
+        val = 0;
+        for (l=A->colptr[C->rowind[o]]; l < A->colptr[C->rowind[o]+1]; l++)
+          val += ((double *)A->values)[l]*
+          B[tB == 'N' ? j*A->nrows + A->rowind[l] :
+          A->rowind[l]*C->ncols + j];
+
+        ((double *)C->values)[o] = alpha.d*val +
+            beta.d*((double *)C->values)[o];
       }
     }
     if (A != a) free_ccs(A);
@@ -1409,30 +1314,30 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
 
     ccs *A = (tA == 'N' ? a : transpose(a,0)), *C = c;
     double *B = b;
-    
+
     spa *s = alloc_spa(A->nrows, A->id);
-    int_t *colptr_new = calloc(n+1,sizeof(int_t));    
+    int_t *colptr_new = calloc(n+1,sizeof(int_t));
     if (!s || !colptr_new) {
       free(s); free(colptr_new);
       if (A != a) free_ccs(A);
       return -1;
     }
-        
-    int j, l;    
+
+    int j, l;
     for (j=0; j<n; j++) {
       init_spa(s, NULL, 0);
-      
-      for (l=0; l<A->ncols; l++) 
-	spa_symb_axpy(A, l, s);
-      
+
+      for (l=0; l<A->ncols; l++)
+        spa_symb_axpy(A, l, s);
+
       if (beta.d != 0.0) spa_symb_axpy(C, j, s);
       colptr_new[j+1] = colptr_new[j] + s->nnz;
-    } 
+    }
 
-    int nnz = colptr_new[n]; 
+    int nnz = colptr_new[n];
     ccs *Z = alloc_ccs(m, n, nnz, C->id);
     if (!Z) {
-      if (A != a) free_ccs(A); 
+      if (A != a) free_ccs(A);
       free_spa(s); free(colptr_new);
       return -1;
     }
@@ -1440,41 +1345,41 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
 
     for (j=0; j<n; j++) {
       init_spa(s, NULL, 0);
-      
+
       for (l=0; l<k; l++) {
-	spa_daxpy(alpha.d*B[tB == 'N' ? l + j*k : j + l*n], A, l, s);
+        spa_daxpy(alpha.d*B[tB == 'N' ? l + j*k : j + l*n], A, l, s);
       }
-      
+
       if (beta.d != 0.0) spa_daxpy(beta.d, C, j, s);
       spa2compressed(s, Z, j);
-    }     
+    }
     free_spa(s);
-    if (A != a) free_ccs(A);    
+    if (A != a) free_ccs(A);
     if (sort_ccs(Z)) {
       free_ccs(Z); return -1;
-    }    
+    }
     *z = Z;
   }
   else if (!sp_a && !sp_b && sp_c && partial) {
     ccs *C = c;
     double *A = a, *B = b, val;
 
-    int j, l, o;   
-    for (j=0; j<C->ncols; j++) {      
+    int j, l, o;
+    for (j=0; j<C->ncols; j++) {
       for (o=C->colptr[j]; o<C->colptr[j+1]; o++) {
-	
-	val = 0;
-	for (l=0; l<k; l++)
-	  val += A[tA == 'N' ? m*l + C->rowind[o] : l + C->rowind[o]*k]*
-	      B[tB == 'N' ? j*k + l : l*n + j];
-		
-	((double *)C->values)[o] = alpha.d*val + 
-	  beta.d*((double *)C->values)[o];	
+
+        val = 0;
+        for (l=0; l<k; l++)
+          val += A[tA == 'N' ? m*l + C->rowind[o] : l + C->rowind[o]*k]*
+          B[tB == 'N' ? j*k + l : l*n + j];
+
+        ((double *)C->values)[o] = alpha.d*val +
+            beta.d*((double *)C->values)[o];
       }
     }
   }
   else if (!sp_a && !sp_b && sp_c && !partial) {
-    
+
     double *A = a, *B = b;
     ccs *C = c;
 
@@ -1488,22 +1393,22 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
     int ldB = MAX(1, (tB == 'N' ? k : n));
     int ldC = MAX(1, m);
 
-    gemm[DOUBLE](&tA, &tB, &m, &n, &k, &alpha, A, &ldA, 
-	B, &ldB, &Zero[DOUBLE], Z->values, &ldC);
+    gemm[DOUBLE](&tA, &tB, &m, &n, &k, &alpha, A, &ldA,
+        B, &ldB, &Zero[DOUBLE], Z->values, &ldC);
 
     for (j=0; j<n; j++) {
-      for (l=0; l<m; l++) 
-	Z->rowind[j*m + l] = l;	
-      
+      for (l=0; l<m; l++)
+        Z->rowind[j*m + l] = l;
+
       Z->colptr[j+1] = Z->colptr[j] + m;
     }
-    
+
     if (beta.d != 0.0) {
       for (j=0; j<n; j++) {
-	for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
-	  ((double *)Z->values)[j*m + C->rowind[l]] += 
-	    beta.d*((double *)C->values)[l];
-	}
+        for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
+          ((double *)Z->values)[j*m + C->rowind[l]] +=
+              beta.d*((double *)C->values)[l];
+        }
       }
     }
     *z = Z;
@@ -1511,7 +1416,7 @@ static int sp_dgemm(char tA, char tB, number alpha, void *a, void *b,
   return 0;
 }
 
-static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b, 
+static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
     number beta, void *c, int sp_a, int sp_b, int sp_c, int partial, void **z,
     int m, int n, int k)
 {
@@ -1529,13 +1434,13 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
       return -1;
     }
 
-    for (j=0; j<n; j++) {   
+    for (j=0; j<n; j++) {
       for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
-	init_spa(s, A, C->rowind[l]);
-	((complex *)C->values)[l] = alpha.z*spa_zdot(B, j, s, tB, tA) +
-	  beta.z*((complex *)C->values)[l];	
+        init_spa(s, A, C->rowind[l]);
+        ((complex *)C->values)[l] = alpha.z*spa_zdot(B, j, s, tB, tA) +
+            beta.z*((complex *)C->values)[l];
       }
-    }    
+    }
     free_spa(s);
     if (A != a) free_ccs(A);
     if (B != b) free_ccs(B);
@@ -1546,7 +1451,7 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
     ccs *A = (tA == 'N' ? a : transpose(a, 0));
     ccs *B = (tB == 'N' ? b : transpose(b, 0));
     ccs *C = c;
-    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));    
+    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));
 
     spa *s = alloc_spa(A->nrows, A->id);
     if (!s || !colptr_new) {
@@ -1560,19 +1465,19 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
     for (j=0; j<n; j++) {
       init_spa(s, NULL, 0);
       if (beta.z != 0.0)
-      	spa_symb_axpy (C, j, s);
-      
-      for (l=B->colptr[j]; l<B->colptr[j+1]; l++) 
-	spa_symb_axpy (A, B->rowind[l], s);
+        spa_symb_axpy (C, j, s);
+
+      for (l=B->colptr[j]; l<B->colptr[j+1]; l++)
+        spa_symb_axpy (A, B->rowind[l], s);
 
       colptr_new[j+1] = colptr_new[j] + s->nnz;
-    }   
-    
-    int nnz = colptr_new[n]; 
+    }
+
+    int nnz = colptr_new[n];
     ccs *Z = alloc_ccs(m, n, nnz, A->id);
     if (!Z) {
-      if (A != a) free_ccs(A); 
-      if (B != b) free_ccs(B); 
+      if (A != a) free_ccs(A);
+      if (B != b) free_ccs(B);
       free(colptr_new); free_spa(s);
       return -1;
     }
@@ -1581,19 +1486,19 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
     for (j=0; j<n; j++) {
       init_spa(s, NULL, 0);
       if (beta.z != 0.0)
-      	spa_zaxpy (beta.z, C, 'N', j, s);
-      
-      for (l=B->colptr[j]; l<B->colptr[j+1]; l++) 	
-	spa_zaxpy(CONJ(tB, ((complex *)B->values)[l]), A, tA, B->rowind[l], s);
+        spa_zaxpy (beta.z, C, 'N', j, s);
+
+      for (l=B->colptr[j]; l<B->colptr[j+1]; l++)
+        spa_zaxpy(alpha.z*CONJ(tB, ((complex *)B->values)[l]), A, tA, B->rowind[l], s);
 
       spa2compressed(s, Z, j);
-    }   
-    
+    }
+
     free_spa(s);
 
     if (A != a) free_ccs(A);
     if (B != b) free_ccs(B);
-    
+
     if (sort_ccs(Z)) {
       free_ccs(Z); return -1;
     }
@@ -1612,81 +1517,81 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
       return -1;
     }
 
-    int mn = m*n; 
+    int mn = m*n;
     scal[A->id](&mn, &beta, C, (int *)&One[COMPLEX]);
 
-    int j, l;    
+    int j, l;
     for (j=0; j<n; j++) {
       init_spa(s, NULL, 0);
-      
-      for (l=B->colptr[j]; l<B->colptr[j+1]; l++) 	
-	spa_zaxpy (CONJ(tB,((complex *)B->values)[l]), A, tA, B->rowind[l], s);
 
-      for (l=0; l<s->nnz; l++) 
-	C[j*A->nrows + s->idx[l]] += alpha.z*((complex *)s->val)[s->idx[l]];
-    }   
+      for (l=B->colptr[j]; l<B->colptr[j+1]; l++)
+        spa_zaxpy (CONJ(tB,((complex *)B->values)[l]), A, tA, B->rowind[l], s);
+
+      for (l=0; l<s->nnz; l++)
+        C[j*A->nrows + s->idx[l]] += alpha.z*((complex *)s->val)[s->idx[l]];
+    }
     free_spa(s);
-    
+
     if (A != a) free_ccs(A);
     if (B != b) free_ccs(B);
   }
 
   else if (!sp_a && sp_b && !sp_c) {
 
-    complex *A = a, *C = c;    
+    complex *A = a, *C = c;
     ccs *B = (tB == 'N' ? b : transpose(b, 0));
 
     int i, j, l, mn_ = m*n;
     scal[COMPLEX](&mn_, &beta, C, (int *)&One[COMPLEX]);
-    
+
     for (j=0; j<n; j++) {
       for (l=B->colptr[j]; l<B->colptr[j+1]; l++) {
-	
-	for (i=0; i<m; i++)
-	  C[i+j*m] += alpha.z*CONJ(tA,A[tA=='N' ? i+B->rowind[l]*m : 
-		  B->rowind[l]+i*k])*
-	    CONJ(tB,((complex *)B->values)[l]);
+
+        for (i=0; i<m; i++)
+          C[i+j*m] += alpha.z*CONJ(tA,A[tA=='N' ? i+B->rowind[l]*m :
+          B->rowind[l]+i*k])*
+          CONJ(tB,((complex *)B->values)[l]);
       }
-    }    
+    }
     if (B != b) free_ccs(B);
   }
 
   else if (sp_a && !sp_b && !sp_c) {
 
     ccs *A = (tA == 'N' ? a : transpose(a, 0));
-    complex *B = b, *C = c;    
+    complex *B = b, *C = c;
 
     int i, j, l, mn_ = m*n;
     scal[COMPLEX](&mn_, &beta, C, (int *)&One[INT]);
-    
+
     for (j=0; j<A->ncols; j++) {
       for (l=A->colptr[j]; l<A->colptr[j+1]; l++) {
-	
-	for (i=0; i<n; i++)
-	  C[A->rowind[l]+i*m] += alpha.z*CONJ(tA,((complex *)A->values)[l])*
-	    CONJ(tB,B[tB=='N' ? j+i*k : i+j*n]);
+
+        for (i=0; i<n; i++)
+          C[A->rowind[l]+i*m] += alpha.z*CONJ(tA,((complex *)A->values)[l])*
+          CONJ(tB,B[tB=='N' ? j+i*k : i+j*n]);
       }
     }
     if (A != a) free_ccs(A);
   }
-  
+
   else if (!sp_a && sp_b && sp_c && partial) {
 
     complex *A = a, val;
     ccs *B = (tB == 'N' ? b : transpose(b, 0)), *C = c;
     int j, l, o;
 
-    for (j=0; j<n; j++) {    
+    for (j=0; j<n; j++) {
       for (o=C->colptr[j]; o<C->colptr[j+1]; o++) {
 
-	val = 0;
-	for (l=B->colptr[j]; l < B->colptr[j+1]; l++)
-	  val += CONJ(tA,A[tA == 'N' ? C->rowind[o] + B->rowind[l]*m : 
-		  B->rowind[l] + C->rowind[o]*B->nrows])*
-	    CONJ(tB,((complex *)B->values)[l]);
-	
-	((complex *)C->values)[o] = alpha.z*val + 
-	  beta.z*((complex *)C->values)[o];
+        val = 0;
+        for (l=B->colptr[j]; l < B->colptr[j+1]; l++)
+          val += CONJ(tA,A[tA == 'N' ? C->rowind[o] + B->rowind[l]*m :
+          B->rowind[l] + C->rowind[o]*B->nrows])*
+          CONJ(tB,((complex *)B->values)[l]);
+
+        ((complex *)C->values)[o] = alpha.z*val +
+            beta.z*((complex *)C->values)[o];
       }
     }
     if (B != b) free_ccs(B);
@@ -1695,8 +1600,8 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
 
     complex *A = a;
     ccs *B = (tB == 'N' ? b : transpose(b,0)), *C = c;
-    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));    
-    
+    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));
+
     if (!colptr_new) {
       if (B != b) free_ccs(B);
       free(colptr_new);
@@ -1704,14 +1609,14 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
     }
 
     int i, j, l;
-    for (j=0; j<n; j++) 
-      colptr_new[j+1] = colptr_new[j] + 
-	MAX(((B->colptr[j+1]-B->colptr[j])>0)*m, C->colptr[j+1]-C->colptr[j]);
+    for (j=0; j<n; j++)
+      colptr_new[j+1] = colptr_new[j] +
+      MAX(((B->colptr[j+1]-B->colptr[j])>0)*m, C->colptr[j+1]-C->colptr[j]);
 
-    int nnz = colptr_new[n]; 
+    int nnz = colptr_new[n];
     ccs *Z = alloc_ccs(m, n, nnz, C->id);
     if (!Z) {
-      if (B != b) free_ccs(B); 
+      if (B != b) free_ccs(B);
       free(colptr_new);
       return -1;
     }
@@ -1719,37 +1624,37 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
     for (l=0; l<nnz; l++) ((complex *)Z->values)[l] = 0;
 
     for (j=0; j<C->ncols; j++) {
-      
+
       if (B->colptr[j+1]-B->colptr[j])
-	for (l=0; l<m; l++)
-	  Z->rowind[Z->colptr[j]+l] = l;
+        for (l=0; l<m; l++)
+          Z->rowind[Z->colptr[j]+l] = l;
 
       for (l=B->colptr[j]; l<B->colptr[j+1]; l++) {
-	
-	for (i=0; i<m; i++) {
-	  ((complex*)Z->values)[Z->colptr[j]+i] += alpha.z*
-	    CONJ(tA,A[tA=='N' ? B->rowind[l]*m+i : B->rowind[l]+i*k])*
-	    CONJ(tB,((complex *)B->values)[l]);
 
-	}
+        for (i=0; i<m; i++) {
+          ((complex*)Z->values)[Z->colptr[j]+i] += alpha.z*
+              CONJ(tA,A[tA=='N' ? B->rowind[l]*m+i : B->rowind[l]+i*k])*
+              CONJ(tB,((complex *)B->values)[l]);
+
+        }
       }
-      
+
       if (beta.z != 0.0) {
-	if (Z->colptr[j+1]-Z->colptr[j] == m) {
-	  for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
-	    ((complex *)Z->values)[Z->colptr[j]+C->rowind[l]] +=
-	      beta.z*((complex *)C->values)[l];
-	  }	
-	}
-	else {
-	  for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
-	    ((complex *)Z->values)[Z->colptr[j]+l-C->colptr[j]] =
-	      beta.z*((complex *)C->values)[l];
-	    Z->rowind[Z->colptr[j]+l-C->colptr[j]] = C->rowind[l];
-	  }
-	}
-      }
-    }       
+        if (Z->colptr[j+1]-Z->colptr[j] == m) {
+          for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
+            ((complex *)Z->values)[Z->colptr[j]+C->rowind[l]] +=
+                beta.z*((complex *)C->values)[l];
+          }
+        }
+        else {
+          for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
+            ((complex *)Z->values)[Z->colptr[j]+l-C->colptr[j]] =
+                beta.z*((complex *)C->values)[l];
+            Z->rowind[Z->colptr[j]+l-C->colptr[j]] = C->rowind[l];
+          }
+        }
+      }
+    }
     if (B != b) free_ccs(B);
     *z = Z;
   }
@@ -1758,18 +1663,18 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
     ccs *A = (tA == 'N' ? transpose(a,0) : a), *C = c;
     complex *B = b, val;
 
-    int j, l, o;   
-    for (j=0; j<n; j++) {      
+    int j, l, o;
+    for (j=0; j<n; j++) {
       for (o=C->colptr[j]; o<C->colptr[j+1]; o++) {
-	
-	val = 0;
-	for (l=A->colptr[C->rowind[o]]; l < A->colptr[C->rowind[o]+1]; l++)
-	  val += CONJ(tA, ((complex *)A->values)[l])*
-	    CONJ(tB, B[tB == 'N' ? j*A->nrows + A->rowind[l] : 
-		    A->rowind[l]*C->ncols + j]);
-	
-	((complex *)C->values)[o] = alpha.z*val + 
-	  beta.z*((complex *)C->values)[o];	
+
+        val = 0;
+        for (l=A->colptr[C->rowind[o]]; l < A->colptr[C->rowind[o]+1]; l++)
+          val += CONJ(tA, ((complex *)A->values)[l])*
+          CONJ(tB, B[tB == 'N' ? j*A->nrows + A->rowind[l] :
+          A->rowind[l]*C->ncols + j]);
+
+        ((complex *)C->values)[o] = alpha.z*val +
+            beta.z*((complex *)C->values)[o];
       }
     }
     if (A != a) free_ccs(A);
@@ -1778,30 +1683,30 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
 
     ccs *A = (tA == 'N' ? a : transpose(a,0)), *C = c;
     complex *B = b;
-    
+
     spa *s = alloc_spa(A->nrows, A->id);
-    int_t *colptr_new = calloc(n+1,sizeof(int_t));    
+    int_t *colptr_new = calloc(n+1,sizeof(int_t));
     if (!s || !colptr_new) {
       free(s); free(colptr_new);
       if (A != a) free_ccs(A);
       return -1;
     }
-        
-    int j, l;    
+
+    int j, l;
     for (j=0; j<n; j++) {
       init_spa(s, NULL, 0);
-      
-      for (l=0; l<A->ncols; l++) 
-	spa_symb_axpy(A, l, s);
-      
+
+      for (l=0; l<A->ncols; l++)
+        spa_symb_axpy(A, l, s);
+
       if (beta.z != 0.0) spa_symb_axpy(C, j, s);
       colptr_new[j+1] = colptr_new[j] + s->nnz;
-    } 
+    }
 
-    int nnz = colptr_new[n]; 
+    int nnz = colptr_new[n];
     ccs *Z = alloc_ccs(m, n, nnz, C->id);
     if (!Z) {
-      if (A != a) free_ccs(A); 
+      if (A != a) free_ccs(A);
       free_spa(s); free(colptr_new);
       return -1;
     }
@@ -1809,42 +1714,42 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
 
     for (j=0; j<n; j++) {
       init_spa(s, NULL, 0);
-      
+
       for (l=0; l<k; l++) {
-	spa_zaxpy(alpha.z*CONJ(tB, B[tB == 'N' ? l + j*k : j + l*n]), 
-	    A, tA, l, s);
+        spa_zaxpy(alpha.z*CONJ(tB, B[tB == 'N' ? l + j*k : j + l*n]),
+            A, tA, l, s);
       }
-      
+
       if (beta.z != 0.0) spa_zaxpy(beta.z, C, 'N', j, s);
       spa2compressed(s, Z, j);
-    }     
+    }
     free_spa(s);
-    if (A != a) free_ccs(A);    
+    if (A != a) free_ccs(A);
     if (sort_ccs(Z)) {
       free_ccs(Z); return -1;
-    }    
+    }
     *z = Z;
   }
   else if (!sp_a && !sp_b && sp_c && partial) {
     ccs *C = c;
     complex *A = a, *B = b, val;
 
-    int j, l, o;   
-    for (j=0; j<C->ncols; j++) {      
+    int j, l, o;
+    for (j=0; j<C->ncols; j++) {
       for (o=C->colptr[j]; o<C->colptr[j+1]; o++) {
-	
-	val = 0;
-	for (l=0; l<k; l++)
-	  val += CONJ(tA, A[tA=='N' ? m*l+C->rowind[o] : l+C->rowind[o]*k])*
-	    CONJ(tB, B[tB == 'N' ? j*k + l : l*n + j]);
-		
-	((complex *)C->values)[o] = alpha.z*val + 
-	  beta.z*((complex *)C->values)[o];	
+
+        val = 0;
+        for (l=0; l<k; l++)
+          val += CONJ(tA, A[tA=='N' ? m*l+C->rowind[o] : l+C->rowind[o]*k])*
+          CONJ(tB, B[tB == 'N' ? j*k + l : l*n + j]);
+
+        ((complex *)C->values)[o] = alpha.z*val +
+            beta.z*((complex *)C->values)[o];
       }
     }
   }
   else if (!sp_a && !sp_b && sp_c && !partial) {
-    
+
     complex *A = a, *B = b;
     ccs *C = c;
 
@@ -1858,22 +1763,22 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
     int ldB = MAX(1, (tB == 'N' ? k : n));
     int ldC = MAX(1, m);
 
-    gemm[COMPLEX](&tA, &tB, &m, &n, &k, &alpha, A, &ldA, 
-	B, &ldB, &Zero[COMPLEX], Z->values, &ldC);
+    gemm[COMPLEX](&tA, &tB, &m, &n, &k, &alpha, A, &ldA,
+        B, &ldB, &Zero[COMPLEX], Z->values, &ldC);
 
     for (j=0; j<n; j++) {
-      for (l=0; l<m; l++) 
-	Z->rowind[j*m + l] = l;	
-      
+      for (l=0; l<m; l++)
+        Z->rowind[j*m + l] = l;
+
       Z->colptr[j+1] = Z->colptr[j] + m;
     }
-    
+
     if (beta.z != 0.0) {
       for (j=0; j<n; j++) {
-	for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
-	  ((complex *)Z->values)[j*m + C->rowind[l]] += 
-	    beta.z*((complex *)C->values)[l];
-	}
+        for (l=C->colptr[j]; l<C->colptr[j+1]; l++) {
+          ((complex *)Z->values)[j*m + C->rowind[l]] +=
+              beta.z*((complex *)C->values)[l];
+        }
       }
     }
     *z = Z;
@@ -1881,11 +1786,11 @@ static int sp_zgemm(char tA, char tB, number alpha, void *a, void *b,
   return 0;
 }
 
-static int sp_dsyrk(char uplo, char trans, number alpha, void *a, 
+static int sp_dsyrk(char uplo, char trans, number alpha, void *a,
     number beta, void *c, int sp_a, int sp_c, int partial, int k, void **z)
 {
   if (sp_a && sp_c && partial) {
-    
+
     ccs *A = (trans == 'N' ?  transpose(a, 0) : a), *C = c;
     spa *s = alloc_spa(A->nrows, C->id);
     if (!A || !s) {
@@ -1896,12 +1801,12 @@ static int sp_dsyrk(char uplo, char trans, number alpha, void *a,
     int j, k;
     for (j=0; j<C->ncols; j++) {
       for (k=C->colptr[j]; k<C->colptr[j+1]; k++) {
-	if ((uplo == 'L' && C->rowind[k] >= j) ||
-	    (uplo == 'U' && C->rowind[k] <= j)) {
-	  init_spa(s, A, C->rowind[k]);
-	  ((double *)C->values)[k] = alpha.d*spa_ddot(A, j, s) +
-	    beta.d*((double *)C->values)[k];
-	}
+        if ((uplo == 'L' && C->rowind[k] >= j) ||
+            (uplo == 'U' && C->rowind[k] <= j)) {
+          init_spa(s, A, C->rowind[k]);
+          ((double *)C->values)[k] = alpha.d*spa_ddot(A, j, s) +
+              beta.d*((double *)C->values)[k];
+        }
       }
     }
     free_spa(s);
@@ -1913,7 +1818,7 @@ static int sp_dsyrk(char uplo, char trans, number alpha, void *a,
     ccs *B = (trans == 'N' ? transpose(a, 0) : a);
     ccs *C = c;
     spa *s = alloc_spa(C->nrows, C->id);
-    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));    
+    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));
 
     if (!A || !B || !s || !colptr_new) {
       if (A != a) free_ccs(A);
@@ -1921,20 +1826,20 @@ static int sp_dsyrk(char uplo, char trans, number alpha, void *a,
       free_spa(s); free(colptr_new);
       return -1;
     }
-    
-    int j, k; 
+
+    int j, k;
     for (j=0; j<B->ncols; j++) {
       init_spa(s, NULL, 0);
       if (beta.d != 0.0)
-	spa_symb_axpy_uplo(C, j, s, j, uplo);      
-      
-      for (k=B->colptr[j]; k<B->colptr[j+1]; k++) 
-	spa_symb_axpy_uplo(A, B->rowind[k], s, j, uplo);      
-      
-      colptr_new[j+1] = colptr_new[j] + s->nnz;      
+        spa_symb_axpy_uplo(C, j, s, j, uplo);
+
+      for (k=B->colptr[j]; k<B->colptr[j+1]; k++)
+        spa_symb_axpy_uplo(A, B->rowind[k], s, j, uplo);
+
+      colptr_new[j+1] = colptr_new[j] + s->nnz;
     }
 
-    int nnz = colptr_new[C->ncols];     
+    int nnz = colptr_new[C->ncols];
     ccs *Z = alloc_ccs(C->nrows, C->ncols, nnz, C->id);
     if (!Z) {
       if (A != a) free_ccs(A);
@@ -1943,16 +1848,16 @@ static int sp_dsyrk(char uplo, char trans, number alpha, void *a,
       return -1;
     }
     free(Z->colptr); Z->colptr = colptr_new;
-    
+
     for (j=0; j<B->ncols; j++) {
-      init_spa(s, NULL, 0); 
-      if (beta.d != 0.0) 
-	spa_daxpy_uplo(beta.d, C, j, s, j, uplo); 
-      
+      init_spa(s, NULL, 0);
+      if (beta.d != 0.0)
+        spa_daxpy_uplo(beta.d, C, j, s, j, uplo);
+
       for (k=B->colptr[j]; k<B->colptr[j+1]; k++) {
-	spa_daxpy_uplo(alpha.d*((double *)B->values)[k], A, B->rowind[k], 
-	    s, j, uplo);      
-      }      
+        spa_daxpy_uplo(alpha.d*((double *)B->values)[k], A, B->rowind[k],
+            s, j, uplo);
+      }
       spa2compressed(s, Z, j);
     }
 
@@ -1963,7 +1868,7 @@ static int sp_dsyrk(char uplo, char trans, number alpha, void *a,
     if (sort_ccs(Z)) {
       free_ccs(Z); return -1;
     }
-    *z = Z;     
+    *z = Z;
   }
   else if (sp_a && !sp_c) {
 
@@ -1976,35 +1881,35 @@ static int sp_dsyrk(char uplo, char trans, number alpha, void *a,
     if (!A || !B || !s) {
       if (A != a) free_ccs(A);
       if (B != a) free_ccs(B);
-      free_spa(s); 
+      free_spa(s);
       return -1;
     }
 
-    int j, k; 
+    int j, k;
     for (j=0; j<B->ncols; j++) {
-      init_spa(s, NULL, 0); 
-      
+      init_spa(s, NULL, 0);
+
       for (k=B->colptr[j]; k<B->colptr[j+1]; k++) {
-	spa_daxpy_uplo(alpha.d*((double *)B->values)[k], A, B->rowind[k], 
-	    s, j, uplo);      
-      }      
+        spa_daxpy_uplo(alpha.d*((double *)B->values)[k], A, B->rowind[k],
+            s, j, uplo);
+      }
 
       if (uplo == 'U') {
-	int m = j+1;
-	scal[DOUBLE](&m, &beta, C + j*n, (int *)&One[INT]);
+        int m = j+1;
+        scal[DOUBLE](&m, &beta, C + j*n, (int *)&One[INT]);
 
-	for (k=0; k<s->nnz; k++) {
-	  if (s->idx[k] <= j) 
-	    C[j*n + s->idx[k]] += alpha.d*((double *)s->val)[s->idx[k]];
-	}
+        for (k=0; k<s->nnz; k++) {
+          if (s->idx[k] <= j)
+            C[j*n + s->idx[k]] += alpha.d*((double *)s->val)[s->idx[k]];
+        }
       } else {
-	int m = n-j;
-	scal[DOUBLE](&m, &beta, C + j*(n+1), (int *)&One[INT]);
-	
-	for (k=0; k<s->nnz; k++) {
-	  if (s->idx[k] >= j) 
-	    C[j*n + s->idx[k]] += alpha.d*((double *)s->val)[s->idx[k]];
-	}
+        int m = n-j;
+        scal[DOUBLE](&m, &beta, C + j*(n+1), (int *)&One[INT]);
+
+        for (k=0; k<s->nnz; k++) {
+          if (s->idx[k] >= j)
+            C[j*n + s->idx[k]] += alpha.d*((double *)s->val)[s->idx[k]];
+        }
       }
     }
     if (A != a) free_ccs(A);
@@ -2015,20 +1920,20 @@ static int sp_dsyrk(char uplo, char trans, number alpha, void *a,
 
     ccs *C = c;
     double *A = a;
-    
+
     int j, i, l, n=C->nrows;
     for (j=0; j<n; j++) {
       for (i=C->colptr[j]; i<C->colptr[j+1]; i++) {
-	if ((uplo == 'L' && C->rowind[i] >= j) ||
-	    (uplo == 'U' && C->rowind[i] <= j)) {
-	  
-	  ((double *)C->values)[i] *= beta.d;
+        if ((uplo == 'L' && C->rowind[i] >= j) ||
+            (uplo == 'U' && C->rowind[i] <= j)) {
+
+          ((double *)C->values)[i] *= beta.d;
 
-	  for (l=0; l<k; l++) 
-	    ((double *)C->values)[i] += 
-	      alpha.d*A[trans == 'N' ? C->rowind[i]+l*n : l+C->rowind[i]*k]*
-	      A[trans == 'N' ? j+l*n : l+j*k];
-	}
+          for (l=0; l<k; l++)
+            ((double *)C->values)[i] +=
+                alpha.d*A[trans == 'N' ? C->rowind[i]+l*n : l+C->rowind[i]*k]*
+                A[trans == 'N' ? j+l*n : l+j*k];
+        }
       }
     }
   }
@@ -2036,59 +1941,59 @@ static int sp_dsyrk(char uplo, char trans, number alpha, void *a,
 
     ccs *C = c;
     double *A = a, *C_ = malloc( C->nrows*C->nrows*sizeof(double) );
-    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));    
-    
+    int_t *colptr_new = calloc(C->ncols+1,sizeof(int_t));
+
     if (!C_ || !colptr_new) {
       free(C_); free(colptr_new); return -1;
     }
     int j, i, n=C->nrows;
-    for (j=0; j<n; j++) 
+    for (j=0; j<n; j++)
       colptr_new[j+1] = colptr_new[j] + (uplo == 'U' ? j+1 : n-j);
 
-    int nnz = colptr_new[n];     
+    int nnz = colptr_new[n];
     ccs *Z = alloc_ccs(n, n, nnz, C->id);
     if (!Z) {
       free(C_); free(colptr_new);
       return -1;
     }
     free(Z->colptr); Z->colptr = colptr_new;
-    
-    syrk[DOUBLE](&uplo, &trans, &n, &k, &alpha, A, 
-	(trans == 'N' ? &n : &k), &Zero[DOUBLE], C_, &n);
+
+    syrk[DOUBLE](&uplo, &trans, &n, &k, &alpha, A,
+        (trans == 'N' ? &n : &k), &Zero[DOUBLE], C_, &n);
 
     for (j=0; j<n; j++) {
       for (i=Z->colptr[j]; i<Z->colptr[j+1]; i++) {
-	if (uplo == 'U') {
-	  ((double *)Z->values)[i] = C_[j*n + i-Z->colptr[j]];
-	  Z->rowind[i] = i-Z->colptr[j];
-	} else {
-	  ((double *)Z->values)[i] = C_[j*(n+1) + i-Z->colptr[j]];
-	  Z->rowind[i] = j+i-Z->colptr[j];
-	}
-      }
-      
+        if (uplo == 'U') {
+          ((double *)Z->values)[i] = C_[j*n + i-Z->colptr[j]];
+          Z->rowind[i] = i-Z->colptr[j];
+        } else {
+          ((double *)Z->values)[i] = C_[j*(n+1) + i-Z->colptr[j]];
+          Z->rowind[i] = j+i-Z->colptr[j];
+        }
+      }
+
       for (i=C->colptr[j]; i<C->colptr[j+1]; i++) {
-	if (uplo == 'U' && C->rowind[i] <= j) 
-	  ((double *)Z->values)[Z->colptr[j]+C->rowind[i]] +=
-	    beta.d*((double *)C->values)[i];
-	else if (uplo == 'L' && C->rowind[i] >= j) 
-	  ((double *)Z->values)[Z->colptr[j]+C->rowind[i]-j] +=
-	    beta.d*((double *)C->values)[i];
-      }      
+        if (uplo == 'U' && C->rowind[i] <= j)
+          ((double *)Z->values)[Z->colptr[j]+C->rowind[i]] +=
+              beta.d*((double *)C->values)[i];
+        else if (uplo == 'L' && C->rowind[i] >= j)
+          ((double *)Z->values)[Z->colptr[j]+C->rowind[i]-j] +=
+              beta.d*((double *)C->values)[i];
+      }
     }
     free(C_);
-    *z = Z;    
+    *z = Z;
   }
 
   return 0;
 }
 
-/* No error checking: Il and Jl must be valid indexlist, 
+/* No error checking: Il and Jl must be valid indexlist,
    and Il,Jl,V must be of same length (V can also be NULL) */
-static spmatrix * 
+static spmatrix *
 triplet2dccs(matrix *Il, matrix *Jl, matrix *V,
-    int_t nrows, int_t ncols)     
-{    
+    int_t nrows, int_t ncols)
+    {
   spmatrix *ret = SpMatrix_New(nrows,ncols, MAT_LGT(Il), DOUBLE);
   double_list *dlist = malloc(MAT_LGT(Jl)*sizeof(double_list));
   int_t *colcnt = calloc(ncols,sizeof(int_t));
@@ -2096,11 +2001,11 @@ triplet2dccs(matrix *Il, matrix *Jl, matrix *V,
   if (!ret || !dlist || !colcnt) {
     Py_XDECREF(ret); free(dlist); free(colcnt);
     return (spmatrix *)PyErr_NoMemory();
-  }  
+  }
 
   /* build colptr */
   int_t i,j,k,l;
-  for (j=0; j<ncols+1; j++) SP_COL(ret)[j] = 0;  
+  for (j=0; j<ncols+1; j++) SP_COL(ret)[j] = 0;
   for (j=0; j<MAT_LGT(Jl); j++) {
     SP_COL(ret)[1+MAT_BUFI(Jl)[j]]++;
     dlist[j].key = -1;
@@ -2111,52 +2016,52 @@ triplet2dccs(matrix *Il, matrix *Jl, matrix *V,
   /* build rowind and values */
   for (k=0; k<MAT_LGT(Il); k++) {
     i = MAT_BUFI(Il)[k], j = MAT_BUFI(Jl)[k];
-   
-    for (l=SP_COL(ret)[j]; l<SP_COL(ret)[j+1]; l++) 
+
+    for (l=SP_COL(ret)[j]; l<SP_COL(ret)[j+1]; l++)
       if (dlist[l].key == i) {
 
-	number n;
-	if (V) { 
-	  convert_num[DOUBLE](&n, V, 0, k); 
-	  dlist[l].value += n.d; 
-	}
+        number n;
+        if (V) {
+          convert_num[DOUBLE](&n, V, 0, k);
+          dlist[l].value += n.d;
+        }
 
-	goto skip;
+        goto skip;
       }
-    
-    if (V) 
-      convert_num[DOUBLE](&dlist[SP_COL(ret)[j]+colcnt[j]].value, V, 0, k);    
-      
+
+    if (V)
+      convert_num[DOUBLE](&dlist[SP_COL(ret)[j]+colcnt[j]].value, V, 0, k);
+
     dlist[SP_COL(ret)[j] + colcnt[j]++].key = i;
 
-  skip:
+    skip:
     ;
   }
 
-  for (j=0; j<ncols; j++) 
+  for (j=0; j<ncols; j++)
     qsort(&dlist[SP_COL(ret)[j]],colcnt[j],sizeof(double_list),&comp_double);
 
   int_t cnt = 0;
   for (j=0; j<ncols; j++) {
     for (i=0; i<colcnt[j]; i++) {
-      
+
       SP_ROW(ret)[cnt] = dlist[i + SP_COL(ret)[j]].key;
       SP_VALD(ret)[cnt++] = dlist[i + SP_COL(ret)[j]].value;
-      
+
     }
   }
 
-  for (j=0; j<ncols; j++) 
+  for (j=0; j<ncols; j++)
     SP_COL(ret)[j+1] = colcnt[j] + SP_COL(ret)[j];
-  
-  free(dlist); free(colcnt);   
+
+  free(dlist); free(colcnt);
   return ret;
-}
+    }
 
-static spmatrix * 
+static spmatrix *
 triplet2zccs(matrix *Il, matrix *Jl, matrix *V,
-    int_t nrows, int_t ncols)     
-{    
+    int_t nrows, int_t ncols)
+    {
   spmatrix *ret = SpMatrix_New(nrows,ncols, MAT_LGT(Il), COMPLEX);
   complex_list *zlist = malloc(MAT_LGT(Jl)*sizeof(complex_list));
   int_t *colcnt = calloc(ncols,sizeof(int_t));
@@ -2164,11 +2069,11 @@ triplet2zccs(matrix *Il, matrix *Jl, matrix *V,
   if (!ret || !zlist || !colcnt) {
     Py_XDECREF(ret); free(zlist); free(colcnt);
     return (spmatrix *)PyErr_NoMemory();
-  }  
+  }
 
   /* build colptr */
   int_t i,j,k,l;
-  for (j=0; j<ncols+1; j++) SP_COL(ret)[j] = 0;  
+  for (j=0; j<ncols+1; j++) SP_COL(ret)[j] = 0;
   for (j=0; j<MAT_LGT(Jl); j++) {
     SP_COL(ret)[1+MAT_BUFI(Jl)[j]]++;
     zlist[j].key = -1;
@@ -2179,104 +2084,104 @@ triplet2zccs(matrix *Il, matrix *Jl, matrix *V,
   /* build rowind and values */
   for (k=0; k<MAT_LGT(Il); k++) {
     i = MAT_BUFI(Il)[k], j = MAT_BUFI(Jl)[k];
-   
-    for (l=SP_COL(ret)[j]; l<SP_COL(ret)[j+1]; l++) 
+
+    for (l=SP_COL(ret)[j]; l<SP_COL(ret)[j+1]; l++)
       if (zlist[l].key == i) {
 
-	number n;
-	if (V) { 
-	  convert_num[COMPLEX](&n, V, 0, k); 
-	  zlist[l].value += n.z; 
-	}
+        number n;
+        if (V) {
+          convert_num[COMPLEX](&n, V, 0, k);
+          zlist[l].value += n.z;
+        }
 
-	goto skip;
+        goto skip;
       }
-    
-    if (V) 
+
+    if (V)
       convert_num[COMPLEX](&zlist[SP_COL(ret)[j]+colcnt[j]].value, V, 0, k);
 
     zlist[SP_COL(ret)[j] + colcnt[j]++].key = i;
 
-  skip:
+    skip:
     ;
   }
 
-  for (j=0; j<ncols; j++) 
+  for (j=0; j<ncols; j++)
     qsort(&zlist[SP_COL(ret)[j]],colcnt[j],sizeof(complex_list),&comp_complex);
 
   int_t cnt = 0;
   for (j=0; j<ncols; j++) {
     for (i=0; i<colcnt[j]; i++) {
-      
+
       SP_ROW(ret)[cnt] = zlist[i + SP_COL(ret)[j]].key;
       SP_VALZ(ret)[cnt++] = zlist[i + SP_COL(ret)[j]].value;
-      
+
     }
   }
 
-  for (j=0; j<ncols; j++) 
+  for (j=0; j<ncols; j++)
     SP_COL(ret)[j+1] = colcnt[j] + SP_COL(ret)[j];
-  
-  free(zlist); free(colcnt);   
+
+  free(zlist); free(colcnt);
   return ret;
-}
+    }
 
 /*
   SpMatrix_New. In API.
 
   Returns an uninitialized spmatrix object.
-  
-  Arguments:  
-  mrows,nrows  : Dimension of spmatrix. 
+
+  Arguments:
+  mrows,nrows  : Dimension of spmatrix.
   nnz          : Number of nonzero elements.
   id           : DOUBLE/COMPLEX
-*/
+ */
 spmatrix *
-SpMatrix_New(int nrows, int ncols, int nnz, int id) 
-{  
-  spmatrix *ret;  
+SpMatrix_New(int_t nrows, int_t ncols, int_t nnz, int id)
+{
+  spmatrix *ret;
   if (!(ret = (spmatrix *)spmatrix_tp.tp_alloc(&spmatrix_tp, 0)))
     return (spmatrix *)PyErr_NoMemory();
 
   ret->obj = alloc_ccs(nrows, ncols, nnz, id);
   if (!ret->obj) { Py_DECREF(ret); return (spmatrix *)PyErr_NoMemory(); }
-    
-  return ret;  
- }
 
-static spmatrix * SpMatrix_NewFromCCS(ccs *x) 
-{    
-  spmatrix *ret;  
+  return ret;
+}
+
+static spmatrix * SpMatrix_NewFromCCS(ccs *x)
+{
+  spmatrix *ret;
   if (!(ret = (spmatrix *)spmatrix_tp.tp_alloc(&spmatrix_tp, 0)))
     return (spmatrix *)PyErr_NoMemory();
 
   ret->obj = x;
-  return ret;  
+  return ret;
 }
 
 /*
   SpMatrix_NewFromSpMatrix. In API.
-  
+
   Returns a copy of an spmatrix object.
-  
-  Arguments:  
-  A            : spmatrix object 
+
+  Arguments:
+  A            : spmatrix object
   id           : DOUBLE/COMPLEX
-*/
-spmatrix * SpMatrix_NewFromSpMatrix(spmatrix *A, int id) 
-{  
+ */
+spmatrix * SpMatrix_NewFromSpMatrix(spmatrix *A, int id)
+{
   if ((id == DOUBLE) && (SP_ID(A) == COMPLEX))
     PY_ERR_TYPE("cannot convert complex to double");
-  
+
   spmatrix *ret = SpMatrix_New
-    (SP_NROWS(A), SP_NCOLS(A), SP_NNZ(A), id);
-  
+      (SP_NROWS(A), SP_NCOLS(A), SP_NNZ(A), id);
+
   if (!ret) return (spmatrix *)PyErr_NoMemory();
-  
-  convert_array(SP_VAL(ret), SP_VAL(A), id, SP_ID(A), SP_NNZ(A)); 
+
+  convert_array(SP_VAL(ret), SP_VAL(A), id, SP_ID(A), SP_NNZ(A));
   memcpy(SP_COL(ret), SP_COL(A), (SP_NCOLS(A)+1)*sizeof(int_t));
   memcpy(SP_ROW(ret), SP_ROW(A), SP_NNZ(A)*sizeof(int_t));
-  
+
   return ret;
 }
 
@@ -2284,31 +2189,31 @@ spmatrix * SpMatrix_NewFromSpMatrix(spmatrix *A, int id)
   SpMatrix_NewFromIJV.
 
   Returns a spmatrix object from a triplet description.
-  
-  Arguments:  
+
+  Arguments:
   Il,Jl,V : (INT,INT,DOUBLE/COMPLEX) triplet description
   m,n     : Dimension of spmatrix. If either m==0 or n==0, then
             the dimension is taken as MAX(I) x MAX(Jl).
   id      : DOUBLE, COMPLEX
-*/
-spmatrix * SpMatrix_NewFromIJV(matrix *Il, matrix *Jl, matrix *V, 
+ */
+spmatrix * SpMatrix_NewFromIJV(matrix *Il, matrix *Jl, matrix *V,
     int_t m, int_t n, int id)
-{   
+    {
 
   if (MAT_ID(Il) != INT || MAT_ID(Jl) != INT)
     PY_ERR_TYPE("index sets I and J must be integer");
-  
+
   if (MAT_LGT(Il) != MAT_LGT(Jl))
     PY_ERR_TYPE("index sets I and J must be of same length");
 
   if (V && !Matrix_Check(V)) PY_ERR_TYPE("invalid V argument");
 
-  if (V && Matrix_Check(V) && (MAX(id,MAT_ID(V)) != id)) 
+  if (V && Matrix_Check(V) && (MAX(id,MAT_ID(V)) != id))
     PY_ERR_TYPE("matrix V has invalid type");
-  
+
   if (V && (MAT_LGT(V) != MAT_LGT(Il)))
     PY_ERR_TYPE("I, J and V must have same length");
-  
+
   if (!Il || !Jl) return SpMatrix_New(0,0,0,id);
 
   int_t k, Imax=-1, Jmax=-1;
@@ -2316,19 +2221,19 @@ spmatrix * SpMatrix_NewFromIJV(matrix *Il, matrix *Jl, matrix *V,
     if (MAT_BUFI(Il)[k]>Imax) Imax = MAT_BUFI(Il)[k];
     if (MAT_BUFI(Jl)[k]>Jmax) Jmax = MAT_BUFI(Jl)[k];
   }
-  
+
   if ((m<0) || (n<0)) { m = MAX(Imax+1,m); n = MAX(Jmax+1,n);}
-  
+
   if (m < Imax+1 || n < Jmax+1) PY_ERR_TYPE("dimension too small");
 
-  for (k=0; k<MAT_LGT(Il); k++) 
-    if ((MAT_BUFI(Il)[k] < 0) || (MAT_BUFI(Il)[k] >= m) || 
-	(MAT_BUFI(Jl)[k] < 0) || (MAT_BUFI(Jl)[k] >= n) ) 
-      PY_ERR_TYPE("index out of range");      
-  
-  return (id == DOUBLE ? triplet2dccs(Il,Jl,V,m,n) : 
-      triplet2zccs(Il,Jl,V,m,n));  
-}
+  for (k=0; k<MAT_LGT(Il); k++)
+    if ((MAT_BUFI(Il)[k] < 0) || (MAT_BUFI(Il)[k] >= m) ||
+        (MAT_BUFI(Jl)[k] < 0) || (MAT_BUFI(Jl)[k] >= n) )
+      PY_ERR_TYPE("index out of range");
+
+  return (id == DOUBLE ? triplet2dccs(Il,Jl,V,m,n) :
+    triplet2zccs(Il,Jl,V,m,n));
+    }
 
 static void spmatrix_dealloc(spmatrix* self)
 {
@@ -2348,27 +2253,27 @@ spmatrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
   char tc = 0;
 
   static char *kwlist[] = { "V", "I", "J", "size","tc", NULL};
-  
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|Oc:spmatrix", kwlist, 
-	  &V, &Il, &Jl, &size, &tc))
+
+  if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|Oc:spmatrix", kwlist,
+      &V, &Il, &Jl, &size, &tc))
     return NULL;
-  
+
   if (!(PySequence_Check((PyObject *)V) || Matrix_Check(V) || PY_NUMBER(V))) {
     PY_ERR_TYPE("V must be either a sequence type, a matrix, or a number");
   }
 
-  if (size && !PyArg_ParseTuple(size, "ll", &nrows, &ncols)) 
+  if (size && !PyArg_ParseTuple(size, "ll", &nrows, &ncols))
     PY_ERR_TYPE("invalid dimension tuple");
-  
-  if (size && (nrows < 0 || ncols < 0)) 
+
+  if (size && (nrows < 0 || ncols < 0))
     PY_ERR_TYPE("dimensions must be non-negative");
 
-  if (tc && !(VALID_TC_SP(tc))) PY_ERR_TYPE("tc must be 'd' or 'z'");  
+  if (tc && !(VALID_TC_SP(tc))) PY_ERR_TYPE("tc must be 'd' or 'z'");
   int id = (tc ? TC2ID(tc) : -1);
 
   int_t ndim = 0;
   /* convert lists to matrices */
-  if (Matrix_Check(Il)) 
+  if (Matrix_Check(Il))
     Py_INCREF(Il);
   else if (PyObject_HasAttrString((PyObject *)Il,"__array_struct__")) {
     if (!(Il = Matrix_NewFromArrayStruct((PyObject *)Il, INT, &ndim)))
@@ -2377,20 +2282,20 @@ spmatrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
   else if (PySequence_Check((PyObject *)Il)) {
     if (!(Il = Matrix_NewFromSequence((PyObject *)Il, INT)))
       return NULL;
-  } 
+  }
   else PY_ERR_TYPE("invalid type for I");
 
-  if (Matrix_Check(Jl)) 
+  if (Matrix_Check(Jl))
     Py_INCREF(Jl);
   else if (PyObject_HasAttrString((PyObject *)Jl,"__array_struct__")) {
     if (!(Jl = Matrix_NewFromArrayStruct((PyObject *)Jl, INT, &ndim))) {
-      Py_DECREF(Il); 
+      Py_DECREF(Il);
       return NULL;
     }
   }
-  else if (PySequence_Check((PyObject *)Jl)) {    
+  else if (PySequence_Check((PyObject *)Jl)) {
     if (!(Jl = Matrix_NewFromSequence((PyObject *)Jl, INT))) {
-      Py_DECREF(Il); 
+      Py_DECREF(Il);
       return NULL;
     }
   }
@@ -2399,32 +2304,32 @@ spmatrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PY_ERR_TYPE("invalid type for J");
   }
 
-  if (Matrix_Check(V)) 
+  if (Matrix_Check(V))
     Py_INCREF(V);
   else if (PyObject_HasAttrString((PyObject *)V,"__array_struct__")) {
     int_t ndim = 0;
     if (!(V = Matrix_NewFromArrayStruct((PyObject *)V, id, &ndim))) {
-      Py_DECREF(Il); 
-      Py_DECREF(Jl); 
+      Py_DECREF(Il);
+      Py_DECREF(Jl);
       return NULL;
     }
   }
-  else if (PySequence_Check((PyObject *)V)) 
-  {  
+  else if (PySequence_Check((PyObject *)V))
+    {
     if (!(V = Matrix_NewFromSequence((PyObject *)V, id))) {
-      Py_DECREF(Il); 
-      Py_DECREF(Jl); 
+      Py_DECREF(Il);
+      Py_DECREF(Jl);
       return NULL;
     }
-  }
-  else if (PY_NUMBER(V)) 
-  {
+    }
+  else if (PY_NUMBER(V))
+    {
     if (!(V = Matrix_NewFromNumber(MAT_LGT(Il), 1, get_id(V, 1), V, 1))) {
-      Py_DECREF(Il); 
-      Py_DECREF(Jl); 
+      Py_DECREF(Il);
+      Py_DECREF(Jl);
       return PyErr_NoMemory();
     }
-  }
+    }
   else {
     Py_DECREF(Il);
     Py_DECREF(Jl);
@@ -2433,22 +2338,22 @@ spmatrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
   id = (id == -1 ? MAX(get_id(V, !Matrix_Check(V)), DOUBLE) : id);
 
-  spmatrix *ret = SpMatrix_NewFromIJV(Il, Jl, V, nrows, ncols, 
+  spmatrix *ret = SpMatrix_NewFromIJV(Il, Jl, V, nrows, ncols,
       id == -1 ? MAX(MAT_ID(V),DOUBLE) : id);
 
-  Py_DECREF(Il); 
-  Py_DECREF(Jl); 
-  Py_DECREF(V); 
+  Py_DECREF(Il);
+  Py_DECREF(Jl);
+  Py_DECREF(V);
 
   return (PyObject *)ret;
-} 
+}
 
 static PyObject *
 spmatrix_str(matrix *self) {
 
   PyObject *cvxopt = PyImport_ImportModule("cvxopt");
   PyObject *str, *ret;
-  
+
   if (!(str = PyObject_GetAttrString(cvxopt, "spmatrix_str"))) {
     Py_DECREF(cvxopt);
     PY_ERR(PyExc_KeyError, "missing 'spmatrix_str' in 'cvxopt'");
@@ -2460,7 +2365,7 @@ spmatrix_str(matrix *self) {
   ret = PyObject_CallFunctionObjArgs(str, (PyObject *)self, NULL);
   Py_DECREF(str);
 
-  return ret;  
+  return ret;
 }
 
 static PyObject *
@@ -2468,7 +2373,7 @@ spmatrix_repr(matrix *self) {
 
   PyObject *cvxopt = PyImport_ImportModule("cvxopt");
   PyObject *repr, *ret;
-  
+
   if (!(repr = PyObject_GetAttrString(cvxopt, "spmatrix_repr"))) {
     Py_DECREF(cvxopt);
     PY_ERR(PyExc_KeyError, "missing 'spmatrix_repr' in 'cvxopt'");
@@ -2480,22 +2385,22 @@ spmatrix_repr(matrix *self) {
   ret = PyObject_CallFunctionObjArgs(repr, (PyObject *)self, NULL);
   Py_DECREF(repr);
 
-  return ret;  
+  return ret;
 }
 
-static PyObject * 
+static PyObject *
 spmatrix_richcompare(PyObject *self, PyObject *other, int op) {
 
-  PY_ERR(PyExc_NotImplementedError, "matrix comparison not implemented");  
+  PY_ERR(PyExc_NotImplementedError, "matrix comparison not implemented");
 }
 
 static PyObject * spmatrix_get_size(spmatrix *self, void *closure)
 {
   PyObject *t = PyTuple_New(2);
-  
+
   PyTuple_SET_ITEM(t, 0, PyInt_FromLong(SP_NROWS(self)));
   PyTuple_SET_ITEM(t, 1, PyInt_FromLong(SP_NCOLS(self)));
-  
+
   return t;
 }
 
@@ -2506,16 +2411,16 @@ static int spmatrix_set_size(spmatrix *self, PyObject *value, void *closure)
   if (!PyTuple_Check(value) || PyTuple_Size(value) != 2)
     PY_ERR_INT(PyExc_TypeError, "can only assign a 2-tuple to size");
 
-  if (!PyInt_Check(PyTuple_GET_ITEM(value, 0)) || 
+  if (!PyInt_Check(PyTuple_GET_ITEM(value, 0)) ||
       !PyInt_Check(PyTuple_GET_ITEM(value, 1)))
     PY_ERR_INT(PyExc_TypeError, "invalid size tuple");
-    
+
   int m = PyInt_AS_LONG(PyTuple_GET_ITEM(value, 0));
   int n = PyInt_AS_LONG(PyTuple_GET_ITEM(value, 1));
 
   if (m<0 || n<0)
     PY_ERR_INT(PyExc_TypeError, "dimensions must be non-negative");
-  
+
   if (m*n != SP_NROWS(self)*SP_NCOLS(self))
     PY_ERR_INT(PyExc_TypeError, "number of elements in matrix cannot change");
 
@@ -2557,25 +2462,25 @@ spmatrix_get_V(spmatrix *self, void *closure)
   return (PyObject *)ret;
 }
 
-static int 
+static int
 spmatrix_set_V(spmatrix *self, PyObject *value, void *closure)
 {
   if (!value) PY_ERR_INT(PyExc_AttributeError, "attribute cannot be deleted");
-  
+
   if (PY_NUMBER(value)) {
     number val;
     if (convert_num[SP_ID(self)](&val, value, 1, 0))
       PY_ERR_INT(PyExc_TypeError, "invalid type in assignment");
-    
+
     int i;
-    for (i=0; i<SP_NNZ(self); i++) 
+    for (i=0; i<SP_NNZ(self); i++)
       write_num[SP_ID(self)](SP_VAL(self),i,&val,0);
 
     return 0;
-  }  
-  else if (Matrix_Check(value) && MAT_ID(value) == SP_ID(self) && 
+  }
+  else if (Matrix_Check(value) && MAT_ID(value) == SP_ID(self) &&
       MAT_LGT(value) == SP_NNZ(self) && MAT_NCOLS(value) == 1) {
-    
+
     memcpy(SP_VAL(self), MAT_BUF(value), MAT_LGT(value)*E_SIZE[SP_ID(self)]);
     return 0;
   } else PY_ERR_INT(PyExc_TypeError, "invalid assignment for V attribute");
@@ -2585,7 +2490,7 @@ static PyObject *spmatrix_get_I(spmatrix *self, void *closure)
 {
   matrix *A = Matrix_New( SP_NNZ(self), 1, INT);
   if (!A) return PyErr_NoMemory();
-  
+
   memcpy(MAT_BUF(A), SP_ROW(self), SP_NNZ(self)*sizeof(int_t));
   return (PyObject *)A;
 }
@@ -2594,12 +2499,12 @@ static PyObject * spmatrix_get_J(spmatrix *self, void *closure)
 {
   matrix *A = Matrix_New( SP_NNZ(self), 1, INT);
   if (!A) return PyErr_NoMemory();
-  
+
   int_t k, j;
   for (k=0; k<SP_NCOLS(self); k++)
     for (j=SP_COL(self)[k]; j<SP_COL(self)[k+1]; j++)
       MAT_BUFI(A)[j] = k;
-  
+
   return (PyObject *)A;
 }
 
@@ -2609,7 +2514,7 @@ static PyObject *spmatrix_get_CCS(spmatrix *self, void *closure)
   matrix *rowind = Matrix_New( SP_NNZ(self), 1, INT);
   matrix *val    = Matrix_New( SP_NNZ(self), 1, SP_ID(self));
   PyObject *ret  = PyTuple_New(3);
-  
+
   if (!colptr || !rowind || !val || !ret) {
     Py_XDECREF(colptr);
     Py_XDECREF(rowind);
@@ -2617,7 +2522,7 @@ static PyObject *spmatrix_get_CCS(spmatrix *self, void *closure)
     Py_XDECREF(ret);
     return PyErr_NoMemory();
   }
-  
+
   memcpy(MAT_BUF(colptr), SP_COL(self), (SP_NCOLS(self)+1)*sizeof(int_t));
   memcpy(MAT_BUF(rowind), SP_ROW(self), SP_NNZ(self)*sizeof(int_t));
   memcpy(MAT_BUF(val),    SP_VAL(self), SP_NNZ(self)*E_SIZE[SP_ID(self)]);
@@ -2641,19 +2546,19 @@ static spmatrix * spmatrix_get_H(spmatrix *self, void *closure)
 
 
 static PyGetSetDef spmatrix_getsets[] = {
-  {"size", (getter) spmatrix_get_size, (setter) spmatrix_set_size, 
-   "matrix dimensions"}, 
-  {"typecode", (getter) spmatrix_get_typecode, NULL, "type character"},
-  {"V", (getter) spmatrix_get_V, (setter) spmatrix_set_V, 
-   "the value list of the matrix in triplet form"},
-  {"I", (getter) spmatrix_get_I, NULL, 
-   "the I (row) list of the matrix in triplet form"},
-  {"J", (getter) spmatrix_get_J, NULL, 
-   "the J (column) list of the matrix in triplet form"},
-  {"T", (getter) spmatrix_get_T, NULL, "transpose"},
-  {"H", (getter) spmatrix_get_H, NULL, "conjugate transpose"},
-  {"CCS", (getter) spmatrix_get_CCS, NULL, "CCS representation"},
-  {NULL}  /* Sentinel */
+    {"size", (getter) spmatrix_get_size, (setter) spmatrix_set_size,
+        "matrix dimensions"},
+        {"typecode", (getter) spmatrix_get_typecode, NULL, "type character"},
+        {"V", (getter) spmatrix_get_V, (setter) spmatrix_set_V,
+            "the value list of the matrix in triplet form"},
+            {"I", (getter) spmatrix_get_I, NULL,
+                "the I (row) list of the matrix in triplet form"},
+                {"J", (getter) spmatrix_get_J, NULL,
+                    "the J (column) list of the matrix in triplet form"},
+                    {"T", (getter) spmatrix_get_T, NULL, "transpose"},
+                    {"H", (getter) spmatrix_get_H, NULL, "conjugate transpose"},
+                    {"CCS", (getter) spmatrix_get_CCS, NULL, "CCS representation"},
+                    {NULL}  /* Sentinel */
 };
 
 static PyObject *
@@ -2667,7 +2572,7 @@ spmatrix_getstate(spmatrix *self)
     Py_XDECREF(Il); Py_XDECREF(Jl); Py_XDECREF(V); Py_XDECREF(size);
     return NULL;
   }
-  
+
   PyTuple_SET_ITEM(size, 0, PyInt_FromLong(SP_NROWS(self)));
   PyTuple_SET_ITEM(size, 1, PyInt_FromLong(SP_NCOLS(self)));
 
@@ -2677,30 +2582,30 @@ spmatrix_getstate(spmatrix *self)
 }
 
 static PyObject * spmatrix_trans(spmatrix *self) {
-  
+
   return (PyObject *)SpMatrix_NewFromCCS(transpose(((spmatrix *)self)->obj,0));
 
 }
 
 static PyObject * spmatrix_ctrans(spmatrix *self) {
-  
+
   return (PyObject *)SpMatrix_NewFromCCS(transpose(((spmatrix *)self)->obj,1));
 
 }
 
 static PyObject * spmatrix_real(spmatrix *self) {
 
-  if (SP_ID(self) != COMPLEX) 
+  if (SP_ID(self) != COMPLEX)
     return (PyObject *)SpMatrix_NewFromSpMatrix(self, SP_ID(self));
-  
-  spmatrix *ret = SpMatrix_New(SP_NROWS(self), SP_NCOLS(self), 
+
+  spmatrix *ret = SpMatrix_New(SP_NROWS(self), SP_NCOLS(self),
       SP_NNZ(self), DOUBLE);
   if (!ret) return PyErr_NoMemory();
 
   int i;
-  for (i=0; i < SP_NNZ(self); i++) 
+  for (i=0; i < SP_NNZ(self); i++)
     SP_VALD(ret)[i] = creal(SP_VALZ(self)[i]);
-  
+
   memcpy(SP_COL(ret), SP_COL(self), (SP_NCOLS(self)+1)*sizeof(int_t));
   memcpy(SP_ROW(ret), SP_ROW(self), SP_NNZ(self)*sizeof(int_t));
   return (PyObject *)ret;
@@ -2708,17 +2613,17 @@ static PyObject * spmatrix_real(spmatrix *self) {
 
 static PyObject * spmatrix_imag(spmatrix *self) {
 
-  if (SP_ID(self) != COMPLEX) 
+  if (SP_ID(self) != COMPLEX)
     return (PyObject *)SpMatrix_NewFromSpMatrix(self, SP_ID(self));
-  
-  spmatrix *ret = SpMatrix_New(SP_NROWS(self), SP_NCOLS(self), 
+
+  spmatrix *ret = SpMatrix_New(SP_NROWS(self), SP_NCOLS(self),
       SP_NNZ(self), DOUBLE);
   if (!ret) return PyErr_NoMemory();
 
   int i;
-  for (i=0; i < SP_NNZ(self); i++) 
+  for (i=0; i < SP_NNZ(self); i++)
     SP_VALD(ret)[i] = cimag(SP_VALZ(self)[i]);
-  
+
   memcpy(SP_COL(ret), SP_COL(self), (SP_NCOLS(self)+1)*sizeof(int_t));
   memcpy(SP_ROW(ret), SP_ROW(self), SP_NNZ(self)*sizeof(int_t));
   return (PyObject *)ret;
@@ -2731,22 +2636,22 @@ spmatrix_reduce(spmatrix* self)
 }
 
 static PyMethodDef spmatrix_methods[] = {
-  {"real", (PyCFunction)spmatrix_real, METH_NOARGS, 
-   "Returns real part of sparse matrix"},
-  {"imag", (PyCFunction)spmatrix_imag, METH_NOARGS, 
-   "Returns imaginary part of sparse matrix"},
-  {"trans", (PyCFunction)spmatrix_trans, METH_NOARGS, 
-   "Returns the matrix transpose"},
-  {"ctrans", (PyCFunction)spmatrix_ctrans, METH_NOARGS, 
-   "Returns the matrix conjugate transpose"},
-  {"__reduce__", (PyCFunction)spmatrix_reduce, METH_NOARGS,
-   "__reduce__() -> (cls, state)"},
-  {NULL}  /* Sentinel */
+    {"real", (PyCFunction)spmatrix_real, METH_NOARGS,
+        "Returns real part of sparse matrix"},
+        {"imag", (PyCFunction)spmatrix_imag, METH_NOARGS,
+            "Returns imaginary part of sparse matrix"},
+            {"trans", (PyCFunction)spmatrix_trans, METH_NOARGS,
+                "Returns the matrix transpose"},
+                {"ctrans", (PyCFunction)spmatrix_ctrans, METH_NOARGS,
+                    "Returns the matrix conjugate transpose"},
+                    {"__reduce__", (PyCFunction)spmatrix_reduce, METH_NOARGS,
+                        "__reduce__() -> (cls, state)"},
+                        {NULL}  /* Sentinel */
 };
 
 
-static int 
-bsearch_int(int_t *lower, int_t *upper, int_t key, int_t *k) {  
+static int
+bsearch_int(int_t *lower, int_t *upper, int_t key, int_t *k) {
 
   if (lower>upper) { *k = 0; return 0; }
 
@@ -2754,7 +2659,7 @@ bsearch_int(int_t *lower, int_t *upper, int_t key, int_t *k) {
 
   while (upper - lower > 1) {
     mid = lower+((upper-lower)>>1);
-    if (*mid > key) 
+    if (*mid > key)
       upper = mid;
     else if (*mid < key)
       lower = mid;
@@ -2763,19 +2668,19 @@ bsearch_int(int_t *lower, int_t *upper, int_t key, int_t *k) {
       return 1;
     }
   }
-  
+
   if (*upper == key) {
     *k = upper - start; return 1;
   }
   else if (*lower == key) {
     *k = lower - start; return 1;
-  } 
+  }
   else {
-    if (*lower > key) 
+    if (*lower > key)
       *k = lower - start;
     else if (*upper < key)
       *k = upper - start + 1;
-    else 
+    else
       *k = upper - start;
     return 0;
   }
@@ -2783,10 +2688,10 @@ bsearch_int(int_t *lower, int_t *upper, int_t key, int_t *k) {
 
 int spmatrix_getitem_ij(spmatrix *A, int_t i, int_t j, number *value)
 {
-  int_t k;  
-  
+  int_t k;
+
   if (SP_NNZ(A) && bsearch_int(&(SP_ROW(A)[SP_COL(A)[j]]),&
-	  (SP_ROW(A)[SP_COL(A)[j+1]-1]), i, &k)) {
+      (SP_ROW(A)[SP_COL(A)[j+1]-1]), i, &k)) {
 
     write_num[SP_ID(A)](value, 0, SP_VAL(A), SP_COL(A)[j]+k);
     return 1;
@@ -2801,10 +2706,10 @@ int spmatrix_getitem_ij(spmatrix *A, int_t i, int_t j, number *value)
 static void
 spmatrix_setitem_ij(spmatrix *A, int_t i, int_t j, number *value) {
 
-  int_t k,l;  
-  
+  int_t k, l;
+
   if (bsearch_int(&(SP_ROW(A)[SP_COL(A)[j]]),
-	  &(SP_ROW(A)[SP_COL(A)[j+1]-1]),i, &k)) {
+      &(SP_ROW(A)[SP_COL(A)[j+1]-1]),i, &k)) {
 
     write_num[SP_ID(A)](SP_VAL(A), SP_COL(A)[j] + k, value, 0);
     return;
@@ -2812,14 +2717,14 @@ spmatrix_setitem_ij(spmatrix *A, int_t i, int_t j, number *value) {
   k += SP_COL(A)[j];
 
   for (l=j+1; l<SP_NCOLS(A)+1; l++) SP_COL(A)[l]++;
-    
+
   /* split rowind and value lists at position 'k' and insert element */
   for (l=SP_NNZ(A)-1; l>k; l--) {
-    SP_ROW(A)[l] = SP_ROW(A)[l-1]; 
-      write_num[SP_ID(A)](SP_VAL(A),l,SP_VAL(A),l-1);
+    SP_ROW(A)[l] = SP_ROW(A)[l-1];
+    write_num[SP_ID(A)](SP_VAL(A),l,SP_VAL(A),l-1);
   }
-  
-  SP_ROW(A)[k] = i;   
+
+  SP_ROW(A)[k] = i;
   write_num[SP_ID(A)](SP_VAL(A), k, value, 0);
 }
 
@@ -2832,56 +2737,56 @@ spmatrix_length(spmatrix *self)
 static PyObject*
 spmatrix_subscr(spmatrix* self, PyObject* args)
 {
-  int_t i = 0, j = 0;
+  int_t i = 0, j = 0, k;
   number val;
   matrix *Il = NULL, *Jl = NULL;
-  
+
   /* single integer */
   if (PyInt_Check(args)) {
     i = PyInt_AS_LONG(args);
-    if ( i<-SP_LGT(self) || i >= SP_LGT(self) ) 
+    if ( i<-SP_LGT(self) || i >= SP_LGT(self) )
       PY_ERR(PyExc_IndexError, "index out of range");
-    
+
     spmatrix_getitem_i(self, CWRAP(i,SP_LGT(self)), &val);
-    
+
     return num2PyObject[SP_ID(self)](&val, 0);
   }
 
   else if (PyList_Check(args) || Matrix_Check(args) || PySlice_Check(args)) {
-    
+
     if (!(Il = create_indexlist(SP_LGT(self), args))) return NULL;
 
-    int_t i, idx, lgt = MAT_LGT(Il), nnz = 0, k = 0;        
+    int_t i, idx, lgt = MAT_LGT(Il), nnz = 0, k = 0;
     /* count # elements in index list */
     for (i=0; i<lgt; i++) {
       idx = MAT_BUFI(Il)[i];
       if (idx < -SP_LGT(self) || idx >= SP_LGT(self)) {
-	Py_DECREF(Il);
-	PY_ERR(PyExc_IndexError, "index out of range");
+        Py_DECREF(Il);
+        PY_ERR(PyExc_IndexError, "index out of range");
       }
       nnz += spmatrix_getitem_i(self, CWRAP(idx,SP_LGT(self)), &val);
     }
 
     spmatrix *B = SpMatrix_New(lgt,1,nnz,SP_ID(self));
     if (!B) { Py_DECREF(Il); return PyErr_NoMemory(); }
-    
+
     SP_COL(B)[1] = nnz;
     /* fill up rowind and values */
     for (i=0; i<lgt; i++) {
       idx = MAT_BUFI(Il)[i];
       if (spmatrix_getitem_i(self, CWRAP(idx,SP_LGT(self)), &val)) {
-	SP_ROW(B)[k] = i; 
-	write_num[SP_ID(B)](SP_VAL(B), k++, &val, 0);
-      }	
-    }    
+        SP_ROW(B)[k] = i;
+        write_num[SP_ID(B)](SP_VAL(B), k++, &val, 0);
+      }
+    }
     free_lists_exit(args,(PyObject *)NULL,Il,(PyObject *)NULL,(PyObject *)B);
   }
-  
+
   /* remainding cases are different two argument indexing */
   PyObject *argI = NULL, *argJ = NULL;
-  if (!PyArg_ParseTuple(args, "OO", &argI, &argJ)) 
+  if (!PyArg_ParseTuple(args, "OO", &argI, &argJ))
     PY_ERR(PyExc_TypeError, "invalid index sets I or J");
-  
+
   /* two integers, subscript form, handle separately */
   if (PyInt_Check(argI) && PyInt_Check(argJ)) {
     i = PyInt_AS_LONG(argI); j = PyInt_AS_LONG(argJ);
@@ -2889,18 +2794,170 @@ spmatrix_subscr(spmatrix* self, PyObject* args)
       PY_ERR(PyExc_IndexError, "index out of range");
 
     spmatrix_getitem_ij(self,CWRAP(i,SP_NROWS(self)),
-	CWRAP(j,SP_NCOLS(self)), &val);
+        CWRAP(j,SP_NCOLS(self)), &val);
 
     return num2PyObject[SP_ID(self)](&val,0);
   }
 
+  if (PySlice_Check(argI)) {
+    int_t rowstart, rowstop, rowstep, rowlgt, rowcnt;
+
+    if (PySlice_GetIndicesEx((PySliceObject*)argI, SP_NROWS(self),
+        &rowstart, &rowstop, &rowstep, &rowlgt) < 0) return NULL;
+
+    int_t colstart, colstop, colstep, collgt, colcnt;
+    if (PySlice_Check(argJ))
+      {
+      if (PySlice_GetIndicesEx((PySliceObject*)argJ, SP_NCOLS(self),
+          &colstart, &colstop, &colstep, &collgt) < 0)
+        return NULL;
+      }
+    else if (PyInt_Check(argJ))
+      {
+      j = PyInt_AS_LONG(argJ);
+      if ( OUT_RNG(j, SP_NCOLS(self)) )
+        PY_ERR(PyExc_IndexError, "index out of range");
+      colstart = 	CWRAP(j,SP_NCOLS(self)); colstop = colstart; collgt = 1; colstep = 1;
+      }
+    else if (PyList_Check(argJ) || Matrix_Check(argJ)) {
+      if (!(Jl = create_indexlist(SP_NCOLS(self), argJ)))
+        return NULL;
+
+      colstart = 0; colstop = MAT_LGT(Jl)-1; collgt = MAT_LGT(Jl); colstep = 1;
+    }
+
+    int_t *colptr = calloc(collgt+1, sizeof(int_t));
+    if (!colptr) {
+      if (Jl && !Matrix_Check(argJ)) { Py_DECREF(Jl); }
+      return PyErr_NoMemory();
+    }
+
+    for (colcnt=0; colcnt<collgt; colcnt++) {
+      j = (Jl ? MAT_BUFI(Jl)[colcnt] : colstart + colcnt*colstep);
+
+      if (rowstart == 0 && rowstop == SP_NROWS(self) && rowstep == 1) {
+        /* copy entire column */
+        colptr[colcnt+1] = colptr[colcnt] + SP_COL(self)[j+1] - SP_COL(self)[j];
+      } else {
+        colptr[colcnt+1] += colptr[colcnt];
+        rowcnt = 0;
+        if (rowstep > 0) {
+          for (k=SP_COL(self)[j]; k<SP_COL(self)[j+1]; k++) {
+
+            while (rowstart + rowcnt*rowstep < SP_ROW(self)[k] && rowcnt < rowlgt)
+              rowcnt++;
+
+            if (rowcnt == rowlgt) break;
+
+            if (rowstart + rowcnt*rowstep == SP_ROW(self)[k]) {
+              colptr[colcnt+1]++;
+              rowcnt++;
+            }
+          }
+        } else {
+          for (k=SP_COL(self)[j+1]-1; k>=SP_COL(self)[j]; k--) {
+
+            while (rowstart + rowcnt*rowstep > SP_ROW(self)[k] && rowcnt < rowlgt)
+              rowcnt++;
+
+            if (rowcnt == rowlgt) break;
+
+            if (rowstart + rowcnt*rowstep == SP_ROW(self)[k]) {
+              colptr[colcnt+1]++;
+              rowcnt++;
+            }
+          }
+        }
+      }
+    }
+
+    ccs *A;
+    if (!(A = alloc_ccs(rowlgt, collgt, colptr[collgt], SP_ID(self)))) {
+      free(colptr);
+      if (Jl && !Matrix_Check(argJ)) { Py_DECREF(Jl); }
+      return PyErr_NoMemory();
+    }
+
+    free(A->colptr);
+    A->colptr = colptr;
+
+    for (colcnt=0; colcnt<collgt; colcnt++) {
+      j = (Jl ? MAT_BUFI(Jl)[colcnt] : colstart + colcnt*colstep);
+
+      if (rowstart == 0 && rowstop == SP_NROWS(self) && rowstep == 1) {
+        /* copy entire column */
+        rowcnt = 0;
+        for (k = SP_COL(self)[j]; k < SP_COL(self)[j+1]; k++) {
+          A->rowind[A->colptr[colcnt] + rowcnt] = SP_ROW(self)[k];
+          if (SP_ID(self) == DOUBLE)
+            ((double *)A->values)[colptr[colcnt] + rowcnt] = SP_VALD(self)[k];
+          else
+            ((complex *)A->values)[colptr[colcnt] + rowcnt] = SP_VALZ(self)[k];
+
+          rowcnt++;
+        }
+
+      } else {
+
+        rowcnt = 0; i = 0;
+        if (rowstep > 0) {
+          for (k=SP_COL(self)[j]; k<SP_COL(self)[j+1]; k++) {
+
+            while (rowstart + rowcnt*rowstep < SP_ROW(self)[k] && rowcnt < rowlgt)
+              rowcnt++;
+
+            if (rowcnt == rowlgt) break;
+
+            if (rowstart + rowcnt*rowstep == SP_ROW(self)[k]) {
+
+              A->rowind[colptr[colcnt] + i] = rowcnt;
+              if (SP_ID(self) == DOUBLE)
+                ((double *)A->values)[colptr[colcnt] + i] = SP_VALD(self)[k];
+              else
+                ((complex *)A->values)[colptr[colcnt] + i] = SP_VALZ(self)[k];
+
+              rowcnt++;
+              i++;
+            }
+          }
+        } else {
+          for (k=SP_COL(self)[j+1]-1; k>=SP_COL(self)[j]; k--) {
+
+            while (rowstart + rowcnt*rowstep > SP_ROW(self)[k] && rowcnt < rowlgt)
+              rowcnt++;
+
+            if (rowcnt == rowlgt) break;
+
+            if (rowstart + rowcnt*rowstep == SP_ROW(self)[k]) {
+
+              A->rowind[colptr[colcnt] + i] = rowcnt;
+              if (SP_ID(self) == DOUBLE)
+                ((double *)A->values)[colptr[colcnt] + i] = SP_VALD(self)[k];
+              else
+                ((complex *)A->values)[colptr[colcnt] + i] = SP_VALZ(self)[k];
+
+              rowcnt++;
+              i++;
+            }
+          }
+        }
+      }
+    }
+
+    if (Jl && !Matrix_Check(argJ)) { Py_DECREF(Jl); }
+
+    spmatrix *B = SpMatrix_New(A->nrows, A->ncols, 0, A->id);
+    free_ccs(B->obj);
+    B->obj = A;
+    return (PyObject *)B;
+  }
+
   if (!(Il = create_indexlist(SP_NROWS(self), argI)) ||
       !(Jl = create_indexlist(SP_NCOLS(self), argJ))) {
-    PyErr_SetNone(PyExc_MemoryError);
     free_lists_exit(argI, argJ, Il, Jl, NULL);
   }
 
-  int lgt_row = MAT_LGT(Il), lgt_col = MAT_LGT(Jl), k, nnz = 0;
+  int lgt_row = MAT_LGT(Il), lgt_col = MAT_LGT(Jl), nnz = 0;
   ccs *A = self->obj;
   spa *s = alloc_spa(A->nrows, A->id);
   if (!s) {
@@ -2908,38 +2965,39 @@ spmatrix_subscr(spmatrix* self, PyObject* args)
     free_lists_exit(argI, argJ, Il, Jl, NULL);
   }
 
-  for (j=0; j<lgt_col; j++) {    
+  for (j=0; j<lgt_col; j++) {
     init_spa(s, A, CWRAP(MAT_BUFI(Jl)[j], SP_NCOLS(self)));
 
-    for (k=0; k<lgt_row; k++) 
+    for (k=0; k<lgt_row; k++)
       nnz += s->nz[CWRAP(MAT_BUFI(Il)[k], SP_NROWS(self))];
   }
+
   spmatrix *B = SpMatrix_New(lgt_row, lgt_col,nnz,A->id);
   if (!B) {
     free_spa(s);
     PyErr_SetNone(PyExc_MemoryError);
     free_lists_exit(argI, argJ, Il, Jl, NULL);
   }
-  
+
   nnz = 0;
-  for (j=0; j<lgt_col; j++) {    
+  for (j=0; j<lgt_col; j++) {
     init_spa(s, A, CWRAP(MAT_BUFI(Jl)[j],SP_NCOLS(self)));
 
     for (k=0; k<lgt_row; k++) {
       if (s->nz[ CWRAP(MAT_BUFI(Il)[k], SP_NROWS(self))]) {
-	if (A->id == DOUBLE) 
-	  SP_VALD(B)[nnz]   = ((double *)s->val)
-	    [CWRAP(MAT_BUFI(Il)[k],SP_NROWS(self))];
-	else
-	  SP_VALZ(B)[nnz]   = ((complex *)s->val)
-	    [CWRAP(MAT_BUFI(Il)[k],SP_NROWS(self))];
-	SP_ROW(B) [nnz++] = k;
-	SP_COL(B)[j+1]++;
+        if (A->id == DOUBLE)
+          SP_VALD(B)[nnz]   = ((double *)s->val)
+          [CWRAP(MAT_BUFI(Il)[k],SP_NROWS(self))];
+        else
+          SP_VALZ(B)[nnz]   = ((complex *)s->val)
+          [CWRAP(MAT_BUFI(Il)[k],SP_NROWS(self))];
+        SP_ROW(B) [nnz++] = k;
+        SP_COL(B)[j+1]++;
       }
     }
     SP_COL(B)[j+1] += SP_COL(B)[j];
   }
-  free_spa(s);  
+  free_spa(s);
   free_lists_exit(argI, argJ, Il, Jl, (PyObject *)B);
 }
 
@@ -2952,24 +3010,24 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
   number val, tempval;
   matrix *Il = NULL, *Jl = NULL;
 
-  if (!value) PY_ERR_INT(PyExc_NotImplementedError, 
+  if (!value) PY_ERR_INT(PyExc_NotImplementedError,
       "cannot delete matrix entries");
 
   if (!(PY_NUMBER(value) || Matrix_Check(value) || SpMatrix_Check(value))) {
-    if (PyObject_HasAttrString(value,"__array_struct__")) 
-      value = (PyObject *)Matrix_NewFromArrayStruct(value, -1, 
-	  &arraystruct_nd);
-    else 
+    if (PyObject_HasAttrString(value,"__array_struct__"))
+      value = (PyObject *)Matrix_NewFromArrayStruct(value, -1,
+          &arraystruct_nd);
+    else
       value = (PyObject *)Matrix_NewFromSequence(value, SP_ID(self));
 
     if (!value)
-      PY_ERR_INT(PyExc_NotImplementedError, "invalid type in assignment");    
+      PY_ERR_INT(PyExc_NotImplementedError, "invalid type in assignment");
 
     decref_val = 1;
   }
-  
+
   int val_id = get_id(value, (PY_NUMBER(value) ? 1 : 0));
-  if (val_id > id) 
+  if (val_id > id)
     PY_ERR_INT(PyExc_TypeError, "invalid type in assignment");
 
   /* assignment value is matrix or number ? */
@@ -2977,39 +3035,39 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
     if (convert_num[id](&val, value, 1, 0))
       PY_ERR_INT(PyExc_TypeError, "invalid argument type");
     itype = 'n';
-  } 
-  else if (Matrix_Check(value) && MAT_LGT(value)==1) { 
+  }
+  else if (Matrix_Check(value) && MAT_LGT(value)==1) {
     convert_num[id](&val, value, 0, 0);
     itype = 'n';
   }
-  else if (Matrix_Check(value)) 
+  else if (Matrix_Check(value))
     itype = 'd';
-  else 
+  else
     itype = 's';
 
   /* single integer */
   if (PyInt_Check(args)) {
-    if (itype != 'n') 
+    if (itype != 'n')
       PY_ERR_INT(PyExc_IndexError, "incompatible sizes in assignment");
 
     i = PyInt_AsLong(args);
-    if ( i<-SP_LGT(self) || i >= SP_LGT(self) ) 
+    if ( i<-SP_LGT(self) || i >= SP_LGT(self) )
       PY_ERR_INT(PyExc_IndexError, "index out of range");
 
     i = CWRAP(i,SP_LGT(self));
 
-    if (spmatrix_getitem_i(self, i, &tempval)) 
+    if (spmatrix_getitem_i(self, i, &tempval))
       spmatrix_setitem_i(self, i, &val);
     else {
-      if (!realloc_ccs(self->obj, SP_NNZ(self)+1)) 
-	PY_ERR_INT(PyExc_MemoryError, "Cannot reallocate sparse matrix");
-      spmatrix_setitem_i(self, i, &val); 
+      if (!realloc_ccs(self->obj, SP_NNZ(self)+1))
+        PY_ERR_INT(PyExc_MemoryError, "Cannot reallocate sparse matrix");
+      spmatrix_setitem_i(self, i, &val);
     }
     return 0;
   }
 
   /* integer matrix list */
-  if (PyList_Check(args) || Matrix_Check(args) || PySlice_Check(args)) {    
+  if (PyList_Check(args) || Matrix_Check(args) || PySlice_Check(args)) {
 
     if (!(Il = create_indexlist(SP_LGT(self), args))) {
       if (decref_val) { Py_DECREF(value); }
@@ -3017,12 +3075,12 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
     }
 
     int_t i, lgtI = MAT_LGT(Il);
-    int_t nnz = SP_NNZ(self)+MAT_LGT(Il);    
-    
-    if (((itype == 'd') && 
-	    ((lgtI != MAT_LGT(value) || MAT_NCOLS(value) != 1))) ||
-	(((itype == 's') && 
-	    ((lgtI != SP_LGT(value)) || SP_NCOLS(value) != 1)))) {
+    int_t nnz = SP_NNZ(self)+MAT_LGT(Il);
+
+    if (((itype == 'd') &&
+        ((lgtI != MAT_LGT(value) || MAT_NCOLS(value) != 1))) ||
+        (((itype == 's') &&
+            ((lgtI != SP_LGT(value)) || SP_NCOLS(value) != 1)))) {
       if (!Matrix_Check(args)) { Py_DECREF(Il); }
       if (decref_val) { Py_DECREF(value); }
       PY_ERR_INT(PyExc_TypeError, "incompatible sizes in assignment");
@@ -3036,187 +3094,187 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
       void *val_merge = malloc(nnz*E_SIZE[id]);
       int_list *ilist = malloc(lgtI*sizeof(int_list));
       if (!col_merge || !row_merge || !val_merge || !ilist) {
-	if (!Matrix_Check(args)) { Py_DECREF(Il); }
-	free(col_merge); free(row_merge); free(val_merge); free(ilist);
-	if (decref_val) { Py_DECREF(value); }
-	PY_ERR_INT(PyExc_MemoryError, "insufficient memory");
+        if (!Matrix_Check(args)) { Py_DECREF(Il); }
+        free(col_merge); free(row_merge); free(val_merge); free(ilist);
+        if (decref_val) { Py_DECREF(value); }
+        PY_ERR_INT(PyExc_MemoryError, "insufficient memory");
       }
-      
+
       for (i=0; i<lgtI; i++) {
-	ilist[i].key = CWRAP(MAT_BUFI(Il)[i],SP_NROWS(self)*SP_NCOLS(self));
-	ilist[i].value = i;
+        ilist[i].key = CWRAP(MAT_BUFI(Il)[i],SP_NROWS(self)*SP_NCOLS(self));
+        ilist[i].value = i;
       }
-      qsort(ilist, lgtI, sizeof(int_list), comp_int);      
+      qsort(ilist, lgtI, sizeof(int_list), comp_int);
 
       /* merge lists */
       int_t rhs_cnt = 0, tot_cnt = 0;
       int_t rhs_j = ilist[rhs_cnt].key / SP_NROWS(self);
       int_t rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
       for (j=0; j<SP_NCOLS(self); j++) {
-	for (i=SP_COL(self)[j]; i<SP_COL(self)[j+1]; i++) {
-	  while (rhs_cnt<lgtI && rhs_j == j && rhs_i < SP_ROW(self)[i]) {
-	    if (rhs_cnt == 0 || (rhs_cnt>0 && 
-		    ilist[rhs_cnt].key != ilist[rhs_cnt-1].key)) {
-	      row_merge[tot_cnt] = rhs_i;
-	      if (itype == 'n')
-		write_num[id](val_merge, tot_cnt++, &val, 0);
-	      else
-		convert_num[id](val_merge + E_SIZE[id]*tot_cnt++, 
-		    value, 0, ilist[rhs_cnt].value);
-
-	      col_merge[j+1]++;
-	    }	    
-	    if (rhs_cnt++ < lgtI-1) {
-	      rhs_j = ilist[rhs_cnt].key / SP_NROWS(self); 
-	      rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
-	    }
-	  }
-	  if (rhs_cnt<lgtI && rhs_i == SP_ROW(self)[i] && rhs_j == j) {
-	    if (rhs_cnt == 0 || 
-		(rhs_cnt>0 && ilist[rhs_cnt].key != ilist[rhs_cnt-1].key)) {
-	      row_merge[tot_cnt] = rhs_i;
-	      if (itype == 'n')
-		write_num[id](val_merge, tot_cnt++, &val, 0);
-	      else
-		convert_num[id](val_merge + E_SIZE[id]*tot_cnt++, 
-		    value, 0, ilist[rhs_cnt].value);
-	      col_merge[j+1]++;
-	    }	    
-	    if (rhs_cnt++ < lgtI-1) {
-	      rhs_j = ilist[rhs_cnt].key / SP_NROWS(self); 
-	      rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
-	    }
-	  }
-	  else {
-	    row_merge[tot_cnt] = SP_ROW(self)[i];
-	    write_num[id](val_merge, tot_cnt++, SP_VAL(self), i);
-	    col_merge[j+1]++;
-	  }
-	}
-	while (rhs_cnt<lgtI && rhs_j == j) {	  
-	  if (rhs_cnt == 0 || 
-	      (rhs_cnt>0 && ilist[rhs_cnt].key != ilist[rhs_cnt-1].key)) {
-	    row_merge[tot_cnt] = rhs_i;
-	    if (itype == 'n')
-	      write_num[id](val_merge, tot_cnt++, &val, 0);
-	    else
-	      convert_num[id](val_merge + E_SIZE[id]*tot_cnt++, 
-		  value, 0, ilist[rhs_cnt].value);
-	    col_merge[j+1]++;
-	  }	    
-	  if (rhs_cnt++ < lgtI-1) {
-	    rhs_j = ilist[rhs_cnt].key / SP_NROWS(self); 
-	    rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
-	  }
-	}
-      }
-
-      for (i=0; i<SP_NCOLS(self); i++) 
-	col_merge[i+1] += col_merge[i];      
+        for (i=SP_COL(self)[j]; i<SP_COL(self)[j+1]; i++) {
+          while (rhs_cnt<lgtI && rhs_j == j && rhs_i < SP_ROW(self)[i]) {
+            if (rhs_cnt == 0 || (rhs_cnt>0 &&
+                ilist[rhs_cnt].key != ilist[rhs_cnt-1].key)) {
+              row_merge[tot_cnt] = rhs_i;
+              if (itype == 'n')
+                write_num[id](val_merge, tot_cnt++, &val, 0);
+              else
+                convert_num[id](val_merge + E_SIZE[id]*tot_cnt++,
+                    value, 0, ilist[rhs_cnt].value);
+
+              col_merge[j+1]++;
+            }
+            if (rhs_cnt++ < lgtI-1) {
+              rhs_j = ilist[rhs_cnt].key / SP_NROWS(self);
+              rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
+            }
+          }
+          if (rhs_cnt<lgtI && rhs_i == SP_ROW(self)[i] && rhs_j == j) {
+            if (rhs_cnt == 0 ||
+                (rhs_cnt>0 && ilist[rhs_cnt].key != ilist[rhs_cnt-1].key)) {
+              row_merge[tot_cnt] = rhs_i;
+              if (itype == 'n')
+                write_num[id](val_merge, tot_cnt++, &val, 0);
+              else
+                convert_num[id](val_merge + E_SIZE[id]*tot_cnt++,
+                    value, 0, ilist[rhs_cnt].value);
+              col_merge[j+1]++;
+            }
+            if (rhs_cnt++ < lgtI-1) {
+              rhs_j = ilist[rhs_cnt].key / SP_NROWS(self);
+              rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
+            }
+          }
+          else {
+            row_merge[tot_cnt] = SP_ROW(self)[i];
+            write_num[id](val_merge, tot_cnt++, SP_VAL(self), i);
+            col_merge[j+1]++;
+          }
+        }
+        while (rhs_cnt<lgtI && rhs_j == j) {
+          if (rhs_cnt == 0 ||
+              (rhs_cnt>0 && ilist[rhs_cnt].key != ilist[rhs_cnt-1].key)) {
+            row_merge[tot_cnt] = rhs_i;
+            if (itype == 'n')
+              write_num[id](val_merge, tot_cnt++, &val, 0);
+            else
+              convert_num[id](val_merge + E_SIZE[id]*tot_cnt++,
+                  value, 0, ilist[rhs_cnt].value);
+            col_merge[j+1]++;
+          }
+          if (rhs_cnt++ < lgtI-1) {
+            rhs_j = ilist[rhs_cnt].key / SP_NROWS(self);
+            rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
+          }
+        }
+      }
+
+      for (i=0; i<SP_NCOLS(self); i++)
+        col_merge[i+1] += col_merge[i];
 
       free(SP_COL(self)); SP_COL(self) = col_merge;
       free(SP_ROW(self)); SP_ROW(self) = row_merge;
-      free(SP_VAL(self)); SP_VAL(self) = val_merge;      
-      free(ilist); 
+      free(SP_VAL(self)); SP_VAL(self) = val_merge;
+      free(ilist);
 
-      //realloc_ccs(self->obj, SP_NNZ(self)); 
+      //realloc_ccs(self->obj, SP_NNZ(self));
     }
     /* ass. argument is a sparse matrix */
-    else 
-    {    
+    else
+      {
       int_list *ilist = malloc(lgtI*sizeof(int_list));
       int_t *col_merge = calloc(SP_NCOLS(self)+1,sizeof(int_t));
       int_t *row_merge = malloc(nnz*sizeof(int_t));
       void *val_merge = malloc(nnz*E_SIZE[id]);
       if (!ilist || !col_merge || !row_merge || !val_merge) {
-	free(ilist); free(col_merge); free(row_merge); free(val_merge);
-	if (!Matrix_Check(args)) { Py_DECREF(Il); }
-	if (decref_val) { Py_DECREF(value); }
-	PY_ERR_INT(PyExc_MemoryError, "insufficient memory");
-      }      
-     
+        free(ilist); free(col_merge); free(row_merge); free(val_merge);
+        if (!Matrix_Check(args)) { Py_DECREF(Il); }
+        if (decref_val) { Py_DECREF(value); }
+        PY_ERR_INT(PyExc_MemoryError, "insufficient memory");
+      }
+
       for (i=0; i<lgtI; i++) {
-	ilist[i].key = CWRAP(MAT_BUFI(Il)[i],SP_NROWS(self)*SP_NCOLS(self));
-	ilist[i].value = -1;
+        ilist[i].key = CWRAP(MAT_BUFI(Il)[i],SP_NROWS(self)*SP_NCOLS(self));
+        ilist[i].value = -1;
       }
 
-      for (i=0; i<SP_NNZ(value); i++) 
-	ilist[SP_ROW(value)[i]].value = i;
+      for (i=0; i<SP_NNZ(value); i++)
+        ilist[SP_ROW(value)[i]].value = i;
 
       qsort(ilist, lgtI, sizeof(int_list), comp_int);
-              
+
       /* merge lists */
       int_t rhs_cnt = 0, tot_cnt = 0;
       int_t rhs_j = ilist[rhs_cnt].key / SP_NROWS(self);
       int_t rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
       for (j=0; j<SP_NCOLS(self); j++) {
-	for (i=SP_COL(self)[j]; i<SP_COL(self)[j+1]; i++) {
-
-	  while (rhs_cnt<lgtI && rhs_j == j && rhs_i < SP_ROW(self)[i]) {
-	    if (ilist[rhs_cnt].value >= 0 && 
-		(rhs_cnt==0 || (rhs_cnt>0 && ilist[rhs_cnt].key != 
-		    ilist[rhs_cnt-1].key))) {
-	      row_merge[tot_cnt] = rhs_i;
-	      convert_array(val_merge + E_SIZE[id]*tot_cnt++,  
-		  SP_VAL(value) + E_SIZE[val_id]*ilist[rhs_cnt].value, 
-		  id, val_id, 1);
-	      col_merge[j+1]++;
-	    }	    
-	    if (rhs_cnt++ < lgtI-1) {
-	      rhs_j = ilist[rhs_cnt].key / SP_NROWS(self); 
-	      rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
-	    }
-	  }
-
-	  if (rhs_cnt<lgtI && rhs_i == SP_ROW(self)[i] && rhs_j == j) {
-	    if (ilist[rhs_cnt].value >= 0 && (rhs_cnt==0 || 
-		    (rhs_cnt>0 && ilist[rhs_cnt].key != 
-			ilist[rhs_cnt-1].key))) {
-	      row_merge[tot_cnt] = rhs_i;
-	      convert_array(val_merge + E_SIZE[id]*tot_cnt++,  
-		  SP_VAL(value) + E_SIZE[val_id]*ilist[rhs_cnt].value, 
-		  id, val_id, 1);
-	      col_merge[j+1]++;
-	    }	    
-	    if (rhs_cnt++ < lgtI-1) {
-	      rhs_j = ilist[rhs_cnt].key / SP_NROWS(self); 
-	      rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
-	    }
-	  }
-	  else {
-	    row_merge[tot_cnt] = SP_ROW(self)[i];
-	    convert_array(val_merge + E_SIZE[id]*tot_cnt++,  
-		SP_VAL(self) + E_SIZE[id]*i, id, id, 1);
-	    col_merge[j+1]++;
-	  }
-	}
-	while (rhs_cnt<lgtI && rhs_j == j) {	  
-	  if (ilist[rhs_cnt].value >= 0 && (rhs_cnt==0 || (rhs_cnt>0 && 
-		      ilist[rhs_cnt].key != ilist[rhs_cnt-1].key))) {
-	    row_merge[tot_cnt] = rhs_i;
-	    convert_array(val_merge + E_SIZE[id]*tot_cnt++,  
-		SP_VAL(value) + E_SIZE[val_id]*ilist[rhs_cnt].value, 
-		id, val_id, 1);
-	    col_merge[j+1]++;
-	  }	    
-	  if (rhs_cnt++ < lgtI-1) {
-	    rhs_j = ilist[rhs_cnt].key / SP_NROWS(self); 
-	    rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
-	  }
-	}
-      }
-      
-      for (i=0; i<SP_NCOLS(self); i++) 
-	col_merge[i+1] += col_merge[i];      
+        for (i=SP_COL(self)[j]; i<SP_COL(self)[j+1]; i++) {
+
+          while (rhs_cnt<lgtI && rhs_j == j && rhs_i < SP_ROW(self)[i]) {
+            if (ilist[rhs_cnt].value >= 0 &&
+                (rhs_cnt==0 || (rhs_cnt>0 && ilist[rhs_cnt].key !=
+                    ilist[rhs_cnt-1].key))) {
+              row_merge[tot_cnt] = rhs_i;
+              convert_array(val_merge + E_SIZE[id]*tot_cnt++,
+                  SP_VAL(value) + E_SIZE[val_id]*ilist[rhs_cnt].value,
+                  id, val_id, 1);
+              col_merge[j+1]++;
+            }
+            if (rhs_cnt++ < lgtI-1) {
+              rhs_j = ilist[rhs_cnt].key / SP_NROWS(self);
+              rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
+            }
+          }
+
+          if (rhs_cnt<lgtI && rhs_i == SP_ROW(self)[i] && rhs_j == j) {
+            if (ilist[rhs_cnt].value >= 0 && (rhs_cnt==0 ||
+                (rhs_cnt>0 && ilist[rhs_cnt].key !=
+                    ilist[rhs_cnt-1].key))) {
+              row_merge[tot_cnt] = rhs_i;
+              convert_array(val_merge + E_SIZE[id]*tot_cnt++,
+                  SP_VAL(value) + E_SIZE[val_id]*ilist[rhs_cnt].value,
+                  id, val_id, 1);
+              col_merge[j+1]++;
+            }
+            if (rhs_cnt++ < lgtI-1) {
+              rhs_j = ilist[rhs_cnt].key / SP_NROWS(self);
+              rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
+            }
+          }
+          else {
+            row_merge[tot_cnt] = SP_ROW(self)[i];
+            convert_array(val_merge + E_SIZE[id]*tot_cnt++,
+                SP_VAL(self) + E_SIZE[id]*i, id, id, 1);
+            col_merge[j+1]++;
+          }
+        }
+        while (rhs_cnt<lgtI && rhs_j == j) {
+          if (ilist[rhs_cnt].value >= 0 && (rhs_cnt==0 || (rhs_cnt>0 &&
+              ilist[rhs_cnt].key != ilist[rhs_cnt-1].key))) {
+            row_merge[tot_cnt] = rhs_i;
+            convert_array(val_merge + E_SIZE[id]*tot_cnt++,
+                SP_VAL(value) + E_SIZE[val_id]*ilist[rhs_cnt].value,
+                id, val_id, 1);
+            col_merge[j+1]++;
+          }
+          if (rhs_cnt++ < lgtI-1) {
+            rhs_j = ilist[rhs_cnt].key / SP_NROWS(self);
+            rhs_i = ilist[rhs_cnt].key % SP_NROWS(self);
+          }
+        }
+      }
+
+      for (i=0; i<SP_NCOLS(self); i++)
+        col_merge[i+1] += col_merge[i];
 
       free(SP_COL(self)); SP_COL(self) = col_merge;
       free(SP_ROW(self)); SP_ROW(self) = row_merge;
-      free(SP_VAL(self)); SP_VAL(self) = val_merge;      
-      free(ilist); 
+      free(SP_VAL(self)); SP_VAL(self) = val_merge;
+      free(ilist);
 
       //realloc_ccs(self->obj, SP_NNZ(self));
-    }
-    
+      }
+
     if (!Matrix_Check(args)) { Py_DECREF(Il); }
     if (decref_val) { Py_DECREF(value); }
 
@@ -3226,7 +3284,7 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
   /* remainding cases are different two argument indexing */
 
   PyObject *argI = NULL, *argJ = NULL;
-  if (!PyArg_ParseTuple(args, "OO", &argI, &argJ)) 
+  if (!PyArg_ParseTuple(args, "OO", &argI, &argJ))
     PY_ERR_INT(PyExc_TypeError, "invalid index arguments");
 
   /* two integers, subscript form, handle separately */
@@ -3234,40 +3292,41 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
 
     if (itype != 'n')
       PY_ERR_INT(PyExc_TypeError, "argument has wrong size");
-    
+
     i = PyInt_AS_LONG(argI); j = PyInt_AS_LONG(argJ);
     if ( OUT_RNG(i, SP_NROWS(self)) || OUT_RNG(j, SP_NCOLS(self)) )
       PY_ERR_INT(PyExc_IndexError, "index out of range");
 
-    i = CWRAP(i,SP_NROWS(self)); j = CWRAP(j,SP_NCOLS(self)); 
+    i = CWRAP(i,SP_NROWS(self)); j = CWRAP(j,SP_NCOLS(self));
     if (spmatrix_getitem_ij(self, i, j, &tempval))
       spmatrix_setitem_ij(self, i, j, &val);
     else {
-      if (!realloc_ccs(self->obj, SP_NNZ(self)+1)) 
-	PY_ERR_INT(PyExc_MemoryError, "insufficient memory");
-      
+      if (!realloc_ccs(self->obj, SP_NNZ(self)+1))
+        PY_ERR_INT(PyExc_MemoryError, "insufficient memory");
+
       spmatrix_setitem_ij(self, i, j, &val);
     }
+
     return 0;
   }
-  
+
   if (!(Il = create_indexlist(SP_NROWS(self), argI)) ||
       !(Jl = create_indexlist(SP_NCOLS(self), argJ))) {
-    PyErr_SetNone(PyExc_MemoryError); 
+    PyErr_SetNone(PyExc_MemoryError);
     free_lists_exit(argI,argJ,Il,Jl,-1);
   }
 
-  if (decref_val && arraystruct_nd < 2 && 
+  if (decref_val && arraystruct_nd < 2 &&
       MAT_LGT(value) == MAT_LGT(Il)*MAT_LGT(Jl)) {
     MAT_NROWS(value) = MAT_LGT(Il); MAT_NCOLS(value) = MAT_LGT(Jl);
   }
 
   int_t lgtI = MAT_LGT(Il), lgtJ = MAT_LGT(Jl);
-  
+
   if ((itype == 'd' && (lgtI != MAT_NROWS(value) ||
-	      lgtJ != MAT_NCOLS(value))) ||
+      lgtJ != MAT_NCOLS(value))) ||
       (itype == 's' && (lgtI != SP_NROWS(value) ||
-	  lgtJ != SP_NCOLS(value)))) {
+          lgtJ != SP_NCOLS(value)))) {
     if (!Matrix_Check(argI)) { Py_DECREF(Il); }
     if (!Matrix_Check(argJ)) { Py_DECREF(Jl); }
     if (decref_val) { Py_DECREF(value); }
@@ -3277,22 +3336,22 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
   /* ass. argument is dense matrix or number */
   if  ((itype == 'd' || itype == 'n') && lgtI*lgtJ> 0) {
 
-    int_t nnz = SP_NNZ(self)+lgtI*lgtJ;    
-      
+    int_t nnz = SP_NNZ(self)+lgtI*lgtJ;
+
     int_t *col_merge = calloc(SP_NCOLS(self)+1,sizeof(int_t));
     int_t *row_merge = malloc(nnz*sizeof(int_t));
-    void *val_merge  = malloc(nnz*E_SIZE[id]);     
+    void *val_merge  = malloc(nnz*E_SIZE[id]);
     int_list *Is = malloc(lgtI*sizeof(int_list));
     int_list *Js = malloc(lgtJ*sizeof(int_list));
     if (!Is || !Js || !col_merge || !row_merge || !val_merge) {
       if (!Matrix_Check(argI)) { Py_DECREF(Il); }
       if (!Matrix_Check(argJ)) { Py_DECREF(Jl); }
-      free(Is); free(Js); 
+      free(Is); free(Js);
       free(col_merge); free(row_merge); free(val_merge);
       if (decref_val) { Py_DECREF(value); }
       PY_ERR_INT(PyExc_MemoryError, "insufficient memory");
     }
-     
+
     for (i=0; i<lgtI; i++) {
       Is[i].key = CWRAP(MAT_BUFI(Il)[i],SP_NROWS(self));
       Is[i].value = i;
@@ -3304,92 +3363,92 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
       Js[i].value = i;
     }
     qsort(Js, lgtJ, sizeof(int_list), comp_int);
-    
+
     int_t rhs_cnti, rhs_cntj = 0, tot_cnt = 0;
-    int_t rhs_i, rhs_j = Js[0].key; 
+    int_t rhs_i, rhs_j = Js[0].key;
     for (j=0; j<SP_NCOLS(self); j++) {
 
       if (rhs_j < j && rhs_cntj++ < lgtJ-1) {
-	rhs_j = Js[rhs_cntj].key;	
+        rhs_j = Js[rhs_cntj].key;
       }
 
       rhs_cnti = 0; rhs_i = Is[0].key;
       for (i=SP_COL(self)[j]; i<SP_COL(self)[j+1]; i++) {
-	
-	while (rhs_cnti<lgtI && rhs_j == j && rhs_i < SP_ROW(self)[i]) {
-	  if (rhs_cnti == 0 || (rhs_cnti>0 && 
-		  Is[rhs_cnti].key != Is[rhs_cnti-1].key)) {
-	    row_merge[tot_cnt] = rhs_i;
-
-	    if (itype == 'n')
-	      write_num[id](val_merge, tot_cnt++, &val, 0);
-	    else
-	      convert_num[id](val_merge + E_SIZE[id]*tot_cnt++, 
-		  value, 0, Is[rhs_cnti].value + lgtI*Js[rhs_cntj].value);
-	    col_merge[j+1]++;
-	  }	    
-	  if (rhs_cnti++ < lgtI-1) 
-	    rhs_i = Is[rhs_cnti].key;	  
-	}
-	
-	if (rhs_cnti<lgtI && rhs_i == SP_ROW(self)[i] && rhs_j == j) {
-	  if (rhs_cnti == 0 || (rhs_cnti>0 && 
-		  Is[rhs_cnti].key != Is[rhs_cnti-1].key)) {
-	    row_merge[tot_cnt] = rhs_i;
-
-	    if (itype == 'n')
-	      write_num[id](val_merge, tot_cnt++, &val, 0);
-	    else
-	      convert_num[id](val_merge + E_SIZE[id]*tot_cnt++, 
-		  value, 0, Is[rhs_cnti].value + lgtI*Js[rhs_cntj].value);
-
-	    col_merge[j+1]++;
-	  }	    
-	  if (rhs_cnti++ < lgtI-1) 
-	    rhs_i = Is[rhs_cnti].key;	  
-	}
-	else {
-	  row_merge[tot_cnt] = SP_ROW(self)[i];
-	  convert_array(val_merge + E_SIZE[id]*tot_cnt++,  
-	      SP_VAL(self) + E_SIZE[id]*i, id, id, 1);
-	  col_merge[j+1]++;
-	}
-      }
-      while (rhs_cnti<lgtI && rhs_j == j) {	  
-	if (rhs_cnti == 0 || (rhs_cnti>0 && 
-		Is[rhs_cnti].key != Is[rhs_cnti-1].key)) {
-	  
-	  row_merge[tot_cnt] = rhs_i;
-
-	  if (itype == 'n')
-	    write_num[id](val_merge, tot_cnt++, &val, 0);
-	  else
-	    convert_num[id](val_merge + E_SIZE[id]*tot_cnt++, 
-		value, 0, Is[rhs_cnti].value + lgtI*Js[rhs_cntj].value);
-	  
-	  col_merge[j+1]++;
-	}	    
-	if (rhs_cnti++ < lgtI-1) 
-	  rhs_i = Is[rhs_cnti].key;	  
-      }
-    }
-    
-    for (i=0; i<SP_NCOLS(self); i++) 
-      col_merge[i+1] += col_merge[i];      
+
+        while (rhs_cnti<lgtI && rhs_j == j && rhs_i < SP_ROW(self)[i]) {
+          if (rhs_cnti == 0 || (rhs_cnti>0 &&
+              Is[rhs_cnti].key != Is[rhs_cnti-1].key)) {
+            row_merge[tot_cnt] = rhs_i;
+
+            if (itype == 'n')
+              write_num[id](val_merge, tot_cnt++, &val, 0);
+            else
+              convert_num[id](val_merge + E_SIZE[id]*tot_cnt++,
+                  value, 0, Is[rhs_cnti].value + lgtI*Js[rhs_cntj].value);
+            col_merge[j+1]++;
+          }
+          if (rhs_cnti++ < lgtI-1)
+            rhs_i = Is[rhs_cnti].key;
+        }
+
+        if (rhs_cnti<lgtI && rhs_i == SP_ROW(self)[i] && rhs_j == j) {
+          if (rhs_cnti == 0 || (rhs_cnti>0 &&
+              Is[rhs_cnti].key != Is[rhs_cnti-1].key)) {
+            row_merge[tot_cnt] = rhs_i;
+
+            if (itype == 'n')
+              write_num[id](val_merge, tot_cnt++, &val, 0);
+            else
+              convert_num[id](val_merge + E_SIZE[id]*tot_cnt++,
+                  value, 0, Is[rhs_cnti].value + lgtI*Js[rhs_cntj].value);
+
+            col_merge[j+1]++;
+          }
+          if (rhs_cnti++ < lgtI-1)
+            rhs_i = Is[rhs_cnti].key;
+        }
+        else {
+          row_merge[tot_cnt] = SP_ROW(self)[i];
+          convert_array(val_merge + E_SIZE[id]*tot_cnt++,
+              SP_VAL(self) + E_SIZE[id]*i, id, id, 1);
+          col_merge[j+1]++;
+        }
+      }
+      while (rhs_cnti<lgtI && rhs_j == j) {
+        if (rhs_cnti == 0 || (rhs_cnti>0 &&
+            Is[rhs_cnti].key != Is[rhs_cnti-1].key)) {
+
+          row_merge[tot_cnt] = rhs_i;
+
+          if (itype == 'n')
+            write_num[id](val_merge, tot_cnt++, &val, 0);
+          else
+            convert_num[id](val_merge + E_SIZE[id]*tot_cnt++,
+                value, 0, Is[rhs_cnti].value + lgtI*Js[rhs_cntj].value);
+
+          col_merge[j+1]++;
+        }
+        if (rhs_cnti++ < lgtI-1)
+          rhs_i = Is[rhs_cnti].key;
+      }
+    }
+
+    for (i=0; i<SP_NCOLS(self); i++)
+      col_merge[i+1] += col_merge[i];
 
     free(SP_COL(self)); SP_COL(self) = col_merge;
     free(SP_ROW(self)); SP_ROW(self) = row_merge;
-    free(SP_VAL(self)); SP_VAL(self) = val_merge;      
-    free(Is); free(Js); 
+    free(SP_VAL(self)); SP_VAL(self) = val_merge;
+    free(Is); free(Js);
 
-    //realloc_ccs(self->obj, SP_NNZ(self));    
+    //realloc_ccs(self->obj, SP_NNZ(self));
 
   }
   /* ass. argument is a sparse matrix */
   else if (itype == 's' && lgtI*lgtJ > 0) {
 
-    int_t nnz = SP_NNZ(self)+SP_NNZ(value);    
-    
+    int_t nnz = SP_NNZ(self)+SP_NNZ(value);
+
     int_t *col_merge = calloc((SP_NCOLS(self)+1),sizeof(int_t));
     int_t *row_merge = malloc(nnz*sizeof(int_t));
     void *val_merge  = malloc(nnz*E_SIZE[id]);
@@ -3398,12 +3457,12 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
     if (!Is || !Js || !col_merge || !row_merge || !val_merge) {
       if (!Matrix_Check(argI)) { Py_DECREF(Il); }
       if (!Matrix_Check(argJ)) { Py_DECREF(Jl); }
-      free(Is); free(Js); 
+      free(Is); free(Js);
       free(col_merge); free(row_merge); free(val_merge);
       if (decref_val) { Py_DECREF(value); }
       PY_ERR_INT(PyExc_MemoryError,"insufficient memory");
     }
-     
+
     for (i=0; i<lgtJ; i++) {
       Js[i].key = CWRAP(MAT_BUFI(Jl)[i],SP_NCOLS(self));
       Js[i].value = i;
@@ -3411,88 +3470,88 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
     qsort(Js, lgtJ, sizeof(int_list), comp_int);
 
     int_t rhs_cnti, rhs_cntj = -1, tot_cnt = 0, rhs_offs_rptr = 0;
-    int_t rhs_i, rhs_j = -1;     
+    int_t rhs_i, rhs_j = -1;
     for (j=0; j<SP_NCOLS(self); j++) {
 
-      if (rhs_j < j && rhs_cntj++ < lgtJ-1) {	
-	rhs_j = Js[rhs_cntj].key;
-	rhs_offs_rptr = SP_COL(value)[Js[rhs_cntj].value];
+      if (rhs_j < j && rhs_cntj++ < lgtJ-1) {
+        rhs_j = Js[rhs_cntj].key;
+        rhs_offs_rptr = SP_COL(value)[Js[rhs_cntj].value];
+
+        for (i=0; i<lgtI; i++) {
+          Is[i].key = CWRAP(MAT_BUFI(Il)[i],SP_NROWS(self));
+          Is[i].value = -1;
+        }
 
-	for (i=0; i<lgtI; i++) {
-	  Is[i].key = CWRAP(MAT_BUFI(Il)[i],SP_NROWS(self));
-	  Is[i].value = -1;
-	}
+        for (i=rhs_offs_rptr; i<SP_COL(value)[Js[rhs_cntj].value+1]; i++)
+          Is[SP_ROW(value)[i]].value = i-rhs_offs_rptr;
 
-	for (i=rhs_offs_rptr; i<SP_COL(value)[Js[rhs_cntj].value+1]; i++) 
-	  Is[SP_ROW(value)[i]].value = i-rhs_offs_rptr;
-	
-	qsort(Is, lgtI, sizeof(int_list), comp_int);
+        qsort(Is, lgtI, sizeof(int_list), comp_int);
       }
-      
+
       rhs_cnti = 0; rhs_i = Is[0].key;
       for (i=SP_COL(self)[j]; i<SP_COL(self)[j+1]; i++) {
-	
-	while (rhs_cnti<lgtI && rhs_j == j && rhs_i < SP_ROW(self)[i]) {
-	  if (Is[rhs_cnti].value >= 0 && (rhs_cnti==0 || 
-		  (rhs_cnti>0 && Is[rhs_cnti].key != Is[rhs_cnti-1].key))) {
-	    row_merge[tot_cnt] = rhs_i;
-
-	    convert_array(val_merge + E_SIZE[id]*tot_cnt++,  
-		SP_VAL(value) + E_SIZE[val_id]*
-		(Is[rhs_cnti].value+rhs_offs_rptr), id, val_id, 1);
-
-	    col_merge[j+1]++;
-	  }	    
-	  if (rhs_cnti++ < lgtI-1) 
-	    rhs_i = Is[rhs_cnti].key;	  
-	}
-	if (rhs_cnti<lgtI && rhs_i == SP_ROW(self)[i] && rhs_j == j) {
-	  if (Is[rhs_cnti].value >= 0 && (rhs_cnti==0 || 
-		  (rhs_cnti>0 && Is[rhs_cnti].key != Is[rhs_cnti-1].key))) {
-	    row_merge[tot_cnt] = rhs_i;
-
-	    convert_array(val_merge + E_SIZE[id]*tot_cnt++,  
-		SP_VAL(value) + E_SIZE[val_id]*
-		(Is[rhs_cnti].value+rhs_offs_rptr), id, val_id, 1);
-
-	    col_merge[j+1]++;
-	  }	    
-	  if (rhs_cnti++ < lgtI-1) 
-	    rhs_i = Is[rhs_cnti].key;	  
-	}
-	else {
-	  row_merge[tot_cnt] = SP_ROW(self)[i];
-	  convert_array(val_merge + E_SIZE[id]*tot_cnt++,  
-	      SP_VAL(self) + E_SIZE[id]*i, id, id, 1);
-	  col_merge[j+1]++;
-	}
-      }
-      while (rhs_cnti<lgtI && rhs_j == j) {	  
-	if (Is[rhs_cnti].value >= 0 && (rhs_cnti == 0 || (rhs_cnti>0 && 
-		    Is[rhs_cnti].key != Is[rhs_cnti-1].key))) {
-	  
-	  row_merge[tot_cnt] = rhs_i;
-
-	  convert_array(val_merge + E_SIZE[id]*tot_cnt++,  
-	      SP_VAL(value) + E_SIZE[val_id]*
-	      (Is[rhs_cnti].value+rhs_offs_rptr), id, val_id, 1);
-
-	  col_merge[j+1]++;
-	}	    
-	if (rhs_cnti++ < lgtI-1) 
-	  rhs_i = Is[rhs_cnti].key;	  
-      }    
-    }
-    
-    for (i=0; i<SP_NCOLS(self); i++) 
-      col_merge[i+1] += col_merge[i];      
+
+        while (rhs_cnti<lgtI && rhs_j == j && rhs_i < SP_ROW(self)[i]) {
+          if (Is[rhs_cnti].value >= 0 && (rhs_cnti==0 ||
+              (rhs_cnti>0 && Is[rhs_cnti].key != Is[rhs_cnti-1].key))) {
+            row_merge[tot_cnt] = rhs_i;
+
+            convert_array(val_merge + E_SIZE[id]*tot_cnt++,
+                SP_VAL(value) + E_SIZE[val_id]*
+                (Is[rhs_cnti].value+rhs_offs_rptr), id, val_id, 1);
+
+            col_merge[j+1]++;
+          }
+          if (rhs_cnti++ < lgtI-1)
+            rhs_i = Is[rhs_cnti].key;
+        }
+        if (rhs_cnti<lgtI && rhs_i == SP_ROW(self)[i] && rhs_j == j) {
+          if (Is[rhs_cnti].value >= 0 && (rhs_cnti==0 ||
+              (rhs_cnti>0 && Is[rhs_cnti].key != Is[rhs_cnti-1].key))) {
+            row_merge[tot_cnt] = rhs_i;
+
+            convert_array(val_merge + E_SIZE[id]*tot_cnt++,
+                SP_VAL(value) + E_SIZE[val_id]*
+                (Is[rhs_cnti].value+rhs_offs_rptr), id, val_id, 1);
+
+            col_merge[j+1]++;
+          }
+          if (rhs_cnti++ < lgtI-1)
+            rhs_i = Is[rhs_cnti].key;
+        }
+        else {
+          row_merge[tot_cnt] = SP_ROW(self)[i];
+          convert_array(val_merge + E_SIZE[id]*tot_cnt++,
+              SP_VAL(self) + E_SIZE[id]*i, id, id, 1);
+          col_merge[j+1]++;
+        }
+      }
+      while (rhs_cnti<lgtI && rhs_j == j) {
+        if (Is[rhs_cnti].value >= 0 && (rhs_cnti == 0 || (rhs_cnti>0 &&
+            Is[rhs_cnti].key != Is[rhs_cnti-1].key))) {
+
+          row_merge[tot_cnt] = rhs_i;
+
+          convert_array(val_merge + E_SIZE[id]*tot_cnt++,
+              SP_VAL(value) + E_SIZE[val_id]*
+              (Is[rhs_cnti].value+rhs_offs_rptr), id, val_id, 1);
+
+          col_merge[j+1]++;
+        }
+        if (rhs_cnti++ < lgtI-1)
+          rhs_i = Is[rhs_cnti].key;
+      }
+    }
+
+    for (i=0; i<SP_NCOLS(self); i++)
+      col_merge[i+1] += col_merge[i];
 
     free(SP_COL(self)); SP_COL(self) = col_merge;
     free(SP_ROW(self)); SP_ROW(self) = row_merge;
-    free(SP_VAL(self)); SP_VAL(self) = val_merge;      
-    free(Is); free(Js); 
+    free(SP_VAL(self)); SP_VAL(self) = val_merge;
+    free(Is); free(Js);
 
-    //realloc_ccs(self->obj, SP_NNZ(self));    
+    //realloc_ccs(self->obj, SP_NNZ(self));
   }
 
   if (!Matrix_Check(argI)) { Py_DECREF(Il); }
@@ -3500,43 +3559,43 @@ spmatrix_ass_subscr(spmatrix* self, PyObject* args, PyObject* value)
   if (decref_val) { Py_DECREF(value); }
 
   return 0;
-  
+
 }
 
 static PyMappingMethods spmatrix_as_mapping = {
-  (lenfunc)spmatrix_length,
-  (binaryfunc)spmatrix_subscr,
-  (objobjargproc)spmatrix_ass_subscr
+    (lenfunc)spmatrix_length,
+    (binaryfunc)spmatrix_subscr,
+    (objobjargproc)spmatrix_ass_subscr
 };
 
 
 static PyObject * spmatrix_neg(spmatrix *self)
-{  
+{
   spmatrix *x = SpMatrix_NewFromSpMatrix(self,SP_ID(self));
   if (!x) return PyErr_NoMemory();
 
   int n=SP_NNZ(x);
   scal[SP_ID(self)](&n, &MinusOne[SP_ID(self)], SP_VAL(x), (int *)&One[INT]);
-  
+
   return (PyObject *)x;
 }
 
 static PyObject * spmatrix_pos(spmatrix *self)
-{  
+{
   spmatrix *x = SpMatrix_NewFromSpMatrix(self,SP_ID(self));
   if (!x) return PyErr_NoMemory();
-  
+
   return (PyObject *)x;
 }
 
 static PyObject * spmatrix_abs(spmatrix *self)
 {
-  spmatrix *x = SpMatrix_New(SP_NROWS(self), SP_NCOLS(self), 
+  spmatrix *x = SpMatrix_New(SP_NROWS(self), SP_NCOLS(self),
       SP_NNZ(self), DOUBLE);
   if (!x) return PyErr_NoMemory();
 
   int_t i;
-  
+
   if (SP_ID(self) == DOUBLE)
     for (i=0; i<SP_NNZ(self); i++) SP_VALD(x)[i] = fabs(SP_VALD(self)[i]);
   else
@@ -3548,47 +3607,47 @@ static PyObject * spmatrix_abs(spmatrix *self)
   return (PyObject *)x;
 }
 
-static PyObject * 
+static PyObject *
 spmatrix_add_helper(PyObject *self, PyObject *other, int add)
-{  
-  if (!SpMatrix_Check(self)  || 
+{
+  if (!SpMatrix_Check(self)  ||
       !(Matrix_Check(other) || SpMatrix_Check(other)))
-  {
+    {
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
-  }
+    }
 
   if ((X_NROWS(self) != X_NROWS(other)) || (X_NCOLS(self) != X_NCOLS(other)))
     PY_ERR_TYPE("incompatible dimensions");
 
-  int id = MAX(SP_ID(self),X_ID(other));    
+  int id = MAX(SP_ID(self),X_ID(other));
 
   ccs *x, *z = NULL;
   void *y;
 
-  if (!(x = convert_ccs(((spmatrix *)self)->obj, id))) 
+  if (!(x = convert_ccs(((spmatrix *)self)->obj, id)))
     return NULL;
 
   if (!(y = (Matrix_Check(other) ?
-	      (void *)Matrix_NewFromMatrix((matrix *)other, id) : 
-	      (void *)convert_ccs(((spmatrix *)other)->obj, id)))) {
+      (void *)Matrix_NewFromMatrix((matrix *)other, id) :
+        (void *)convert_ccs(((spmatrix *)other)->obj, id)))) {
     if (x->id != id) free_ccs(x);
     return NULL;
   }
-      
-  if (sp_axpy[id]((add ? One[id] : MinusOne[id]), x,  
-	  (Matrix_Check(other) ? MAT_BUF(y) : y),  
-	  1, SpMatrix_Check(other), 0, (void *)&z)) 
-  {
+
+  if (sp_axpy[id]((add ? One[id] : MinusOne[id]), x,
+      (Matrix_Check(other) ? MAT_BUF(y) : y),
+      1, SpMatrix_Check(other), 0, (void *)&z))
+    {
     if (x->id != id) free_ccs(x);
-    if (Matrix_Check(other)) 
+    if (Matrix_Check(other))
       Py_DECREF((PyObject *)y);
     else
       if (((ccs *)y)->id != id) free_ccs(y);
-    
-    return PyErr_NoMemory(); 
-  }
-  
+
+    return PyErr_NoMemory();
+    }
+
   if (x->id != id) free_ccs(x);
   if (SpMatrix_Check(other)) {
     if (((ccs *)y)->id != id) free_ccs(y);
@@ -3597,66 +3656,66 @@ spmatrix_add_helper(PyObject *self, PyObject *other, int add)
     free_ccs(ret->obj);
     ret->obj = z;
     return (PyObject *)ret;
-  } 
+  }
   else return (PyObject *)y;
 }
 
-static PyObject * 
-spmatrix_add(PyObject *self, PyObject *other) 
+static PyObject *
+spmatrix_add(PyObject *self, PyObject *other)
 {
   if (!SpMatrix_Check(self) && SpMatrix_Check(other)) {
     void *ptr = other; other = self; self = ptr;
   }
-  
+
   PyObject *ret, *tmp;
-  if (PY_NUMBER(other) || (Matrix_Check(other) && MAT_LGT(other)==1)) 
+  if (PY_NUMBER(other) || (Matrix_Check(other) && MAT_LGT(other)==1))
     if ((tmp = (PyObject *)dense((spmatrix *)self))) {
       ret = matrix_add(tmp, other);
       Py_DECREF(tmp);
       return ret;
-    } 
+    }
     else return NULL;
-  
+
   else return spmatrix_add_helper(self, other, 1);
 }
 
 
-static PyObject * 
+static PyObject *
 spmatrix_iadd(PyObject *self, PyObject *other)
-{  
+{
   if (!SpMatrix_Check(other))
     PY_ERR_TYPE("invalid inplace operation");
-  
+
   int id = SP_ID(self);
   if (SP_ID(other) > id)
     PY_ERR_TYPE("incompatible types for inplace operation");
 
   if ((SP_NROWS(self) != SP_NROWS(other)) ||
-      (SP_NCOLS(self) != SP_NCOLS(other))) 
+      (SP_NCOLS(self) != SP_NCOLS(other)))
     PY_ERR_TYPE("incompatible dimensions");
 
   ccs *x = ((spmatrix *)self)->obj, *y;
   void *z;
-  
-  if (!(y = convert_ccs(((spmatrix *)other)->obj, id))) 
+
+  if (!(y = convert_ccs(((spmatrix *)other)->obj, id)))
     return NULL;
-  
+
   if (sp_axpy[id](One[id], x, y, 1, 1, 0, &z))
-  {
-    if (y->id != id) free_ccs(y);      
-    return PyErr_NoMemory(); 
-  }
-  
+    {
+    if (y->id != id) free_ccs(y);
+    return PyErr_NoMemory();
+    }
+
   free_ccs(x); ((spmatrix *)self)->obj = z;
-  if (y->id != id) free_ccs(y);      
+  if (y->id != id) free_ccs(y);
 
   Py_INCREF(self);
   return self;
 }
 
 
-static PyObject * 
-spmatrix_sub(PyObject *self, PyObject *other) 
+static PyObject *
+spmatrix_sub(PyObject *self, PyObject *other)
 {
   PyObject *ret, *tmp;
   if (PY_NUMBER(self) || (Matrix_Check(self) && MAT_LGT(self)==1)) {
@@ -3664,144 +3723,145 @@ spmatrix_sub(PyObject *self, PyObject *other)
       ret = matrix_sub(self, tmp);
       Py_DECREF(tmp);
       return ret;
-    } 
+    }
     else return NULL;
-  }     
+  }
   else if (PY_NUMBER(other) || (Matrix_Check(other) && MAT_LGT(other)==1)) {
     if ((tmp = (PyObject *)dense((spmatrix *)self))) {
       ret = matrix_sub(tmp, other);
       Py_DECREF(tmp);
       return ret;
-    } 
+    }
     else return NULL;
   }
   else if (!SpMatrix_Check(self) && SpMatrix_Check(other))
-  {
+    {
     return spmatrix_add_helper(other, self, 0);
-  }
+    }
   else if (SpMatrix_Check(self) && !SpMatrix_Check(other)) {
     if ((ret = spmatrix_add_helper(self, other, 0))) {
-      int n = MAT_LGT(other), id = MAT_ID(ret); 
+      int n = MAT_LGT(other), id = MAT_ID(ret);
       scal[id](&n, &MinusOne[id], MAT_BUF(ret), (int *)&One[INT]);
       return ret;
     }
-    else return NULL;    
+    else return NULL;
   }
   else return spmatrix_add_helper(other, self, 0);
 }
 
-static PyObject * 
+static PyObject *
 spmatrix_isub(PyObject *self, PyObject *other)
-{  
+{
   if (!SpMatrix_Check(other))
     PY_ERR_TYPE("invalid inplace operation");
-  
+
   int id = SP_ID(self);
-  
+
   if (SP_ID(other) > id)
     PY_ERR_TYPE("incompatible types for inplace operation");
 
   if ((SP_NROWS(self) != SP_NROWS(other)) ||
       (SP_NCOLS(self) != SP_NCOLS(other)))
     PY_ERR_TYPE("incompatible dimensions");
-  
+
   ccs *x = ((spmatrix *)self)->obj, *y;
   void *z;
-  
-  if (!(y = convert_ccs(((spmatrix *)other)->obj, id))) 
+
+  if (!(y = convert_ccs(((spmatrix *)other)->obj, id)))
     return NULL;
-  
+
   if (sp_axpy[id](MinusOne[id], y, x, 1, 1, 0, &z))
-  {
-    if (y->id != id) free_ccs(y);      
-    return PyErr_NoMemory(); 
-  }
-  
+    {
+    if (y->id != id) free_ccs(y);
+    return PyErr_NoMemory();
+    }
+
   free_ccs(x); ((spmatrix *)self)->obj = z;
-  if (y->id != id) free_ccs(y);      
+  if (y->id != id) free_ccs(y);
 
   Py_INCREF(self);
   return self;
 }
 
-static PyObject * 
-spmatrix_mul(PyObject *self, PyObject *other) 
+static PyObject *
+spmatrix_mul(PyObject *self, PyObject *other)
 {
-  if (!(SpMatrix_Check(self) || Matrix_Check(self) || PY_NUMBER(self)) || 
+  if (!(SpMatrix_Check(self) || Matrix_Check(self) || PY_NUMBER(self)) ||
       !(SpMatrix_Check(other) || Matrix_Check(other) || PY_NUMBER(other)))
-  {
+    {
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
-  }
-  
+    }
+
   int id = MAX(get_id(self, PY_NUMBER(self)),get_id(other, PY_NUMBER(other)));
   if (PY_NUMBER(self) || (Matrix_Check(self) && MAT_LGT(self) == 1 &&
-	  !(SpMatrix_Check(other) && SP_NCOLS(other) == 1)) || 
+      !(SpMatrix_Check(other) && SP_NCOLS(other) == 1)) ||
       PY_NUMBER(other) || (Matrix_Check(other) && MAT_LGT(other) == 1 &&
-	  !(SpMatrix_Check(self) && SP_NROWS(self) == 1)) )
-  {
-    
+          !(SpMatrix_Check(self) && SP_NROWS(self) == 1)) )
+    {
+
     spmatrix *ret = SpMatrix_NewFromSpMatrix((spmatrix *)
-	(SpMatrix_Check(self) ? self : other), id);
+        (SpMatrix_Check(self) ? self : other), id);
 
     number val;
-    convert_num[id](&val, !SpMatrix_Check(self) ? self : other, 
-	PY_NUMBER(other) || PY_NUMBER(self), 0);
+    convert_num[id](&val, !SpMatrix_Check(self) ? self : other,
+        PY_NUMBER(other) || PY_NUMBER(self), 0);
 
     scal[id]((int *)&SP_NNZ(ret), &val, SP_VAL(ret), (void *)&One[INT]);
     return (PyObject *)ret;
-  }
+    }
 
   else {
     if (X_NCOLS(self) != X_NROWS(other))
       PY_ERR_TYPE("incompatible dimensions");
-    
+
     void *x, *y, *z = NULL;
     int sp_c = SpMatrix_Check(self) && SpMatrix_Check(other);
-    PyObject *C = (sp_c ? 
-	(PyObject *)SpMatrix_New(SP_NROWS(self), SP_NCOLS(other), 0, id) :
-	(PyObject *)Matrix_New(X_NROWS(self), X_NCOLS(other), id));
+    PyObject *C = (sp_c ?
+        (PyObject *)SpMatrix_New(SP_NROWS(self), SP_NCOLS(other), 0, id) :
+          (PyObject *)Matrix_New(X_NROWS(self), X_NCOLS(other), id));
 
-    if (SpMatrix_Check(self)) 
+    if (SpMatrix_Check(self))
       x = convert_ccs(((spmatrix *)self)->obj, id);
     else
       x = convert_mtx_alloc((matrix *)self, id);
-    
-    if (SpMatrix_Check(other)) 
+
+    if (SpMatrix_Check(other))
       y = convert_ccs(((spmatrix *)other)->obj, id);
     else
       y = convert_mtx_alloc((matrix *)other, id);
-      
+
     if (!C || !x || !y) {
       PyErr_SetNone(PyExc_MemoryError);
       Py_XDECREF(C);
       C = NULL;
       goto cleanup;
     }
-    if (sp_gemm[id]('N', 'N', One[id], x, y, Zero[id], 
-	    sp_c ? ((spmatrix *)C)->obj : MAT_BUF(C), 
-	    SpMatrix_Check(self), SpMatrix_Check(other), sp_c, 0, &z,
-	    X_NROWS(self), X_NCOLS(other), X_NROWS(other)))
-    {
+    if (sp_gemm[id]('N', 'N', One[id], x, y, Zero[id],
+        sp_c ? ((spmatrix *)C)->obj : MAT_BUF(C),
+            SpMatrix_Check(self), SpMatrix_Check(other), sp_c, 0, &z,
+            X_NROWS(self), X_NCOLS(other), X_NROWS(other)))
+      {
+      PyErr_SetNone(PyExc_MemoryError);
       Py_DECREF(C); C = NULL;
-    }
+      }
 
-    if (z) { 
+    if (z) {
       free_ccs( ((spmatrix *)C)->obj );
       ((spmatrix *)C)->obj = z;
-    }    
+    }
 
-  cleanup:
+    cleanup:
     if (SpMatrix_Check(self)) {
       if (((ccs *)x)->id != id) free_ccs(x);
-    } 
+    }
     else if (MAT_ID(self) != id) free(x);
-    
+
     if (SpMatrix_Check(other)) {
       if (((ccs *)y)->id != id) free_ccs(y);
-    } 
-    else if (MAT_ID(other) != id) free(y);	
-    
+    }
+    else if (MAT_ID(other) != id) free(y);
+
     return (PyObject *)C;
   }
 }
@@ -3809,53 +3869,53 @@ spmatrix_mul(PyObject *self, PyObject *other)
 static PyObject *
 spmatrix_imul(PyObject *self, PyObject *other)
 {
-  if (!(PY_NUMBER(other) || (Matrix_Check(other) && MAT_LGT(other) == 1))) 
+  if (!(PY_NUMBER(other) || (Matrix_Check(other) && MAT_LGT(other) == 1)))
     PY_ERR_TYPE("invalid operands for sparse multiplication");
 
-  if (SP_ID(self) < get_id(other, PY_NUMBER(other))) 
+  if (SP_ID(self) < get_id(other, PY_NUMBER(other)))
     PY_ERR_TYPE("invalid operands for inplace sparse multiplication");
 
   number val;
   convert_num[SP_ID(self)](&val, other, !Matrix_Check(other), 0);
-  scal[SP_ID(self)]((int *)&SP_NNZ(self), &val, SP_VAL(self), 
+  scal[SP_ID(self)]((int *)&SP_NNZ(self), &val, SP_VAL(self),
       (void *)&One[INT]);
 
   Py_INCREF(self);
   return self;
 }
 
-static PyObject * 
+static PyObject *
 spmatrix_div_generic(spmatrix *A, PyObject *B, int inplace)
 {
-  if (!SpMatrix_Check(A) || !(PY_NUMBER(B) || 
-	  (Matrix_Check(B) && MAT_LGT(B)) == 1))  
+  if (!SpMatrix_Check(A) || !(PY_NUMBER(B) ||
+      (Matrix_Check(B) && MAT_LGT(B)) == 1))
     PY_ERR_TYPE("invalid operands for sparse division");
 
   int idA = get_id(A, 0);
   int idB = get_id(B, (Matrix_Check(B) ? 0 : 1));
-  int id  = MAX(idA,idB);    
+  int id  = MAX(idA,idB);
 
   number n;
   convert_num[id](&n, B, (Matrix_Check(B) ? 0 : 1), 0);
 
-  if (!inplace) {      
+  if (!inplace) {
     PyObject *ret = (PyObject *)SpMatrix_NewFromSpMatrix((spmatrix *)A, id);
     if (!ret) return NULL;
 
-    if (div_array[id](SP_VAL(ret), n, SP_NNZ(ret))) { 
-      Py_DECREF(ret); return NULL; 
+    if (div_array[id](SP_VAL(ret), n, SP_NNZ(ret))) {
+      Py_DECREF(ret); return NULL;
     }
     return ret;
   } else {
     if (id != idA) PY_ERR_TYPE("invalid inplace operation");
 
-    if (div_array[id](SP_VAL(A), n, SP_NNZ(A)))  
-      return NULL; 
+    if (div_array[id](SP_VAL(A), n, SP_NNZ(A)))
+      return NULL;
 
     Py_INCREF(A);
     return (PyObject *)A;
   }
-} 
+}
 
 static PyObject * spmatrix_div(PyObject *self,PyObject *other) {
   return spmatrix_div_generic((spmatrix *)self, other, 0);
@@ -3872,50 +3932,50 @@ static int spmatrix_nonzero(matrix *self)
     if ((SP_ID(self) == DOUBLE) && (SP_VALD(self)[i] != 0.0)) res = 1;
     else if ((SP_ID(self) == COMPLEX) && (SP_VALZ(self)[i] != 0.0)) res = 1;
   }
-  
+
   return res;
 }
 
 
 static PyNumberMethods spmatrix_as_number = {
-        (binaryfunc)spmatrix_add, /*nb_add*/
-	(binaryfunc)spmatrix_sub, /*nb_subtract*/
-	(binaryfunc)spmatrix_mul, /*nb_multiply*/
-	(binaryfunc)spmatrix_div, /*nb_divide*/
-	0,                      /*nb_remainder*/
-	0,	                /*nb_divmod*/
-	0,	                /*nb_power*/
-	(unaryfunc)spmatrix_neg,/*nb_negative*/
-	(unaryfunc)spmatrix_pos,/*nb_positive*/
-	(unaryfunc)spmatrix_abs,/*nb_absolute*/
-	(inquiry)spmatrix_nonzero,/*nb_nonzero*/
-	0,	                /*nb_invert*/
-	0,	                /*nb_lshift*/
-	0,	                /*nb_rshift*/
-	0,	                /*nb_and*/
-	0,	                /*nb_xor*/
-	0,	                /*nb_or*/
-	0,		        /*nb_coerce*/
-	0,	                /*nb_int*/
-	0,	                /*nb_long*/
-	0,	                /*nb_float*/
-	0,	                /*nb_oct*/
-	0, 	                /*nb_hex*/
-	(binaryfunc)spmatrix_iadd,/*nb_inplace_add*/
-	(binaryfunc)spmatrix_isub,/*nb_inplace_subtract*/
-	(binaryfunc)spmatrix_imul,/*nb_inplace_multiply*/
-	(binaryfunc)spmatrix_idiv,/*nb_inplace_divide*/
-	0,                      /*nb_inplace_remainder*/
-	0,			/*nb_inplace_power*/
-	0,			/*nb_inplace_lshift*/
-	0,			/*nb_inplace_rshift*/
-	0,			/*nb_inplace_and*/
-	0,			/*nb_inplace_xor*/
-	0,			/*nb_inplace_or*/
-	0,	                /* nb_floor_divide */
-	0,	                /* nb_true_divide */
-	0,			/* nb_inplace_floor_divide */
-	0,			/* nb_inplace_true_divide */
+    (binaryfunc)spmatrix_add, /*nb_add*/
+    (binaryfunc)spmatrix_sub, /*nb_subtract*/
+    (binaryfunc)spmatrix_mul, /*nb_multiply*/
+    (binaryfunc)spmatrix_div, /*nb_divide*/
+    0,                      /*nb_remainder*/
+    0,	                /*nb_divmod*/
+    0,	                /*nb_power*/
+    (unaryfunc)spmatrix_neg,/*nb_negative*/
+    (unaryfunc)spmatrix_pos,/*nb_positive*/
+    (unaryfunc)spmatrix_abs,/*nb_absolute*/
+    (inquiry)spmatrix_nonzero,/*nb_nonzero*/
+    0,	                /*nb_invert*/
+    0,	                /*nb_lshift*/
+    0,	                /*nb_rshift*/
+    0,	                /*nb_and*/
+    0,	                /*nb_xor*/
+    0,	                /*nb_or*/
+    0,		        /*nb_coerce*/
+    0,	                /*nb_int*/
+    0,	                /*nb_long*/
+    0,	                /*nb_float*/
+    0,	                /*nb_oct*/
+    0, 	                /*nb_hex*/
+    (binaryfunc)spmatrix_iadd,/*nb_inplace_add*/
+    (binaryfunc)spmatrix_isub,/*nb_inplace_subtract*/
+    (binaryfunc)spmatrix_imul,/*nb_inplace_multiply*/
+    (binaryfunc)spmatrix_idiv,/*nb_inplace_divide*/
+    0,                      /*nb_inplace_remainder*/
+    0,			/*nb_inplace_power*/
+    0,			/*nb_inplace_lshift*/
+    0,			/*nb_inplace_rshift*/
+    0,			/*nb_inplace_and*/
+    0,			/*nb_inplace_xor*/
+    0,			/*nb_inplace_or*/
+    0,	                /* nb_floor_divide */
+    0,	                /* nb_true_divide */
+    0,			/* nb_inplace_floor_divide */
+    0,			/* nb_inplace_true_divide */
 };
 
 
@@ -3935,7 +3995,7 @@ static PyObject *
 spmatrix_iter(spmatrix *obj)
 {
   spmatrixiter *it;
-  
+
   if (!SpMatrix_Check(obj)) {
     PyErr_BadInternalCall();
     return NULL;
@@ -3947,7 +4007,7 @@ spmatrix_iter(spmatrix *obj)
   it = PyObject_GC_New(spmatrixiter, &spmatrixiter_tp);
   if (it == NULL)
     return NULL;
- 
+
   Py_INCREF(obj);
   it->index = 0;
   it->mObj = obj;
@@ -3979,82 +4039,82 @@ spmatrixiter_next(spmatrixiter *it)
   assert(SpMatrixIter_Check(it));
   if (it->index >= SP_NNZ(it->mObj))
     return NULL;
-  
+
   return num2PyObject[SP_ID(it->mObj)](SP_VAL(it->mObj), it->index++);
 }
 
 static PyTypeObject spmatrixiter_tp = {
-        PyObject_HEAD_INIT(NULL)
-	0,					/* ob_size */
-	"spmatrixiter", 			/* tp_name */
-	sizeof(spmatrixiter),           	/* tp_basicsize */
-	0,					/* tp_itemsize */
-	(destructor)spmatrixiter_dealloc,	/* tp_dealloc */
-	0,					/* tp_print */
-	0,					/* tp_getattr */
-	0,					/* tp_setattr */
-	0,					/* tp_compare */
-	0,					/* tp_repr */
-	0,					/* tp_as_number */
-	0,					/* tp_as_sequence */
-	0,					/* tp_as_mapping */
-	0,					/* tp_hash */
-	0,					/* tp_call */
-	0,					/* tp_str */
-	0,       		                /* tp_getattro */
-	0, 		                        /* tp_setattro */
-	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
-	0,					/* tp_doc */
-	(traverseproc)spmatrixiter_traverse,	/* tp_traverse */
-	0,					/* tp_clear */
-	0,					/* tp_richcompare */
-	0,					/* tp_weaklistoffset */
-	0,              			/* tp_iter */
-	(iternextfunc)spmatrixiter_next,	/* tp_iternext */
-	0,					/* tp_methods */
+    PyObject_HEAD_INIT(NULL)
+    0,					/* ob_size */
+    "spmatrixiter", 			/* tp_name */
+    sizeof(spmatrixiter),           	/* tp_basicsize */
+    0,					/* tp_itemsize */
+    (destructor)spmatrixiter_dealloc,	/* tp_dealloc */
+    0,					/* tp_print */
+    0,					/* tp_getattr */
+    0,					/* tp_setattr */
+    0,					/* tp_compare */
+    0,					/* tp_repr */
+    0,					/* tp_as_number */
+    0,					/* tp_as_sequence */
+    0,					/* tp_as_mapping */
+    0,					/* tp_hash */
+    0,					/* tp_call */
+    0,					/* tp_str */
+    0,       		                /* tp_getattro */
+    0, 		                        /* tp_setattro */
+    0,					/* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+    0,					/* tp_doc */
+    (traverseproc)spmatrixiter_traverse,	/* tp_traverse */
+    0,					/* tp_clear */
+    0,					/* tp_richcompare */
+    0,					/* tp_weaklistoffset */
+    0,              			/* tp_iter */
+    (iternextfunc)spmatrixiter_next,	/* tp_iternext */
+    0,					/* tp_methods */
 };
 
 
 PyTypeObject spmatrix_tp = {
-	PyObject_HEAD_INIT(NULL)
-	0,
-	"cvxopt.base.spmatrix",
-	sizeof(spmatrix),
-	0,
-	(destructor)spmatrix_dealloc,	        /* tp_dealloc */
-	0,	               	                /* tp_print */
-	0,					/* tp_getattr */
-	0,					/* tp_setattr */
-	0,					/* tp_compare */
-	(reprfunc)spmatrix_repr,                /* tp_repr */
-	&spmatrix_as_number,			/* tp_as_number */
-	0,	                                /* tp_as_sequence */
-	&spmatrix_as_mapping,                   /* tp_as_mapping */
-	0,					/* tp_hash */
-	0,					/* tp_call */
-	(reprfunc)spmatrix_str, 		/* tp_str */
-	0,					/* tp_getattro */
-	0,			                /* tp_setattro */
-	0,			                /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 
-	Py_TPFLAGS_CHECKTYPES,                  /* tp_flags */
-	0,					/* tp_doc */
-	0,					/* tp_traverse */
-	0,					/* tp_clear */
-	(richcmpfunc)spmatrix_richcompare,      /* tp_richcompare */
-	0,					/* tp_weaklistoffset */
-	(getiterfunc)spmatrix_iter,		/* tp_iter */
-	0,	       	                        /* tp_iternext */
-	spmatrix_methods,                       /* tp_methods */
-	0,				        /* tp_members */
-	spmatrix_getsets,      		        /* tp_getset */
-	0,		                        /* tp_base */
-	0,					/* tp_dict */
-	0,	       			        /* tp_descr_get */
-	0,					/* tp_descr_set */
-	0,					/* tp_dictoffset */
-	0,                                      /* tp_init */
-	0,               			/* tp_alloc */
-	spmatrix_new,				/* tp_new */
+    PyObject_HEAD_INIT(NULL)
+    0,
+    "cvxopt.base.spmatrix",
+    sizeof(spmatrix),
+    0,
+    (destructor)spmatrix_dealloc,	        /* tp_dealloc */
+    0,	               	                /* tp_print */
+    0,					/* tp_getattr */
+    0,					/* tp_setattr */
+    0,					/* tp_compare */
+    (reprfunc)spmatrix_repr,                /* tp_repr */
+    &spmatrix_as_number,			/* tp_as_number */
+    0,	                                /* tp_as_sequence */
+    &spmatrix_as_mapping,                   /* tp_as_mapping */
+    0,					/* tp_hash */
+    0,					/* tp_call */
+    (reprfunc)spmatrix_str, 		/* tp_str */
+    0,					/* tp_getattro */
+    0,			                /* tp_setattro */
+    0,			                /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+    Py_TPFLAGS_CHECKTYPES,                  /* tp_flags */
+    0,					/* tp_doc */
+    0,					/* tp_traverse */
+    0,					/* tp_clear */
+    (richcmpfunc)spmatrix_richcompare,      /* tp_richcompare */
+    0,					/* tp_weaklistoffset */
+    (getiterfunc)spmatrix_iter,		/* tp_iter */
+    0,	       	                        /* tp_iternext */
+    spmatrix_methods,                       /* tp_methods */
+    0,				        /* tp_members */
+    spmatrix_getsets,      		        /* tp_getset */
+    0,		                        /* tp_base */
+    0,					/* tp_dict */
+    0,	       			        /* tp_descr_get */
+    0,					/* tp_descr_set */
+    0,					/* tp_dictoffset */
+    0,                                      /* tp_init */
+    0,               			/* tp_alloc */
+    spmatrix_new,				/* tp_new */
 };
diff --git a/src/C/umfpack.c b/src/C/umfpack.c
index 1cd145d..ba2f835 100644
--- a/src/C/umfpack.c
+++ b/src/C/umfpack.c
@@ -1,7 +1,7 @@
 /*
- * Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+ * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.
+ * This file is part of CVXOPT version 1.1.2
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -62,13 +62,13 @@ static void free_umfpack_z_numeric(void *F, void *descr)
 static char doc_linsolve[] =
     "Solves a sparse set of linear equations.\n\n"
     "linsolve(A, B, trans='N', nrhs=B.size[1], ldB=max(1,B.size[0]),\n"
-    "         offsetB=0)\n\n" 
+    "         offsetB=0)\n\n"
     "PURPOSE\n"
     "If trans is 'N', solves A*X = B.\n"
     "If trans is 'T', solves A^T*X = B.\n"
     "If trans is 'C', solves A^H*X = B.\n"
     "A is a sparse n by n matrix, and B is n by nrhs.\n"
-    "On exit B is replaced by the solution.  A is not modified.\n\n" 
+    "On exit B is replaced by the solution.  A is not modified.\n\n"
     "ARGUMENTS\n"
     "A         square sparse matrix\n\n"
     "B         dense matrix of the same type as A, stored following \n"
@@ -79,28 +79,28 @@ static char doc_linsolve[] =
     "          default value is used.\n\n"
     "offsetB   nonnegative integer";
 
-static PyObject* linsolve(PyObject *self, PyObject *args, 
+static PyObject* linsolve(PyObject *self, PyObject *args,
     PyObject *kwrds)
 {
-    spmatrix *A; 
+    spmatrix *A;
     matrix *B;
     char trans='N';
     double info[UMFPACK_INFO];
     int oB=0, n, nrhs=-1, ldB=0, k;
     void *symbolic, *numeric, *x;
-    char *kwlist[] = {"A", "B", "trans", "nrhs", "ldB", "offsetB", 
+    char *kwlist[] = {"A", "B", "trans", "nrhs", "ldB", "offsetB",
         NULL};
-  
-    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciii", kwlist, 
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciii", kwlist,
         &A, &B, &trans, &nrhs, &ldB, &oB)) return NULL;
-  
+
     if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A))
         PY_ERR_TYPE("A must be a square sparse matrix");
     n = SP_NROWS(A);
-    if (!Matrix_Check(B) || MAT_ID(B) != SP_ID(A)) 
+    if (!Matrix_Check(B) || MAT_ID(B) != SP_ID(A))
         PY_ERR_TYPE("B must a dense matrix of the same numeric type "
             "as A");
-  
+
     if (nrhs < 0) nrhs = B->ncols;
     if (n == 0 || nrhs == 0) return Py_BuildValue("i", 0);
     if (ldB == 0) ldB = MAX(1,B->nrows);
@@ -110,18 +110,18 @@ static PyObject* linsolve(PyObject *self, PyObject *args,
 
     if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N', 'T', 'C'");
-  
+
     if (SP_ID(A) == DOUBLE)
         UMFD(symbolic)(n, n, SP_COL(A), SP_ROW(A), SP_VAL(A), &symbolic,
-            NULL, info);    
+            NULL, info);
     else
         UMFZ(symbolic)(n, n, SP_COL(A), SP_ROW(A), SP_VAL(A), NULL,
-            &symbolic, NULL, info);    
-  
+            &symbolic, NULL, info);
+
     if (info[UMFPACK_STATUS] != UMFPACK_OK){
         if (SP_ID(A) == DOUBLE)
             UMFD(free_symbolic)(&symbolic);
-        else 
+        else
             UMFZ(free_symbolic)(&symbolic);
         if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory)
             return PyErr_NoMemory();
@@ -134,11 +134,11 @@ static PyObject* linsolve(PyObject *self, PyObject *args,
     }
 
     if (SP_ID(A) == DOUBLE) {
-        UMFD(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A), symbolic, 
+        UMFD(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A), symbolic,
             &numeric, NULL, info);
         UMFD(free_symbolic)(&symbolic);
     } else {
-        UMFZ(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A), NULL, symbolic, 
+        UMFZ(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A), NULL, symbolic,
             &numeric, NULL, info);
         UMFZ(free_symbolic)(&symbolic);
     }
@@ -149,7 +149,7 @@ static PyObject* linsolve(PyObject *self, PyObject *args,
             UMFZ(free_numeric)(&numeric);
         if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory)
             return PyErr_NoMemory();
-        else { 
+        else {
             if (info[UMFPACK_STATUS] == UMFPACK_WARNING_singular_matrix)
                 PyErr_SetString(PyExc_ArithmeticError, "singular "
                     "matrix");
@@ -161,7 +161,7 @@ static PyObject* linsolve(PyObject *self, PyObject *args,
             return NULL;
         }
     }
-  
+
     if (!(x = malloc(n*E_SIZE[SP_ID(A)]))) {
         if (SP_ID(A) == DOUBLE)
             UMFD(free_numeric)(&numeric);
@@ -171,17 +171,17 @@ static PyObject* linsolve(PyObject *self, PyObject *args,
     }
     for (k=0; k<nrhs; k++){
         if (SP_ID(A) == DOUBLE)
-            UMFD(solve)(trans == 'N' ? UMFPACK_A: UMFPACK_Aat, 
-                SP_COL(A), SP_ROW(A), SP_VAL(A), x, 
+            UMFD(solve)(trans == 'N' ? UMFPACK_A: UMFPACK_Aat,
+                SP_COL(A), SP_ROW(A), SP_VAL(A), x,
                 MAT_BUFD(B) + k*ldB + oB, numeric, NULL, info);
         else
-            UMFZ(solve)(trans == 'N' ? UMFPACK_A: trans == 'C' ? 
-                UMFPACK_At : UMFPACK_Aat, SP_COL(A), SP_ROW(A), 
-                SP_VAL(A), NULL, x, NULL, 
-                (double *)(MAT_BUFZ(B) + k*ldB + oB), NULL, numeric, 
+            UMFZ(solve)(trans == 'N' ? UMFPACK_A: trans == 'C' ?
+                UMFPACK_At : UMFPACK_Aat, SP_COL(A), SP_ROW(A),
+                SP_VAL(A), NULL, x, NULL,
+                (double *)(MAT_BUFZ(B) + k*ldB + oB), NULL, numeric,
                 NULL, info);
-        if (info[UMFPACK_STATUS] == UMFPACK_OK) 
-            memcpy(B->buffer + (k*ldB + oB)*E_SIZE[SP_ID(A)], x, 
+        if (info[UMFPACK_STATUS] == UMFPACK_OK)
+            memcpy(B->buffer + (k*ldB + oB)*E_SIZE[SP_ID(A)], x,
                 n*E_SIZE[SP_ID(A)]);
         else
 	    break;
@@ -191,11 +191,11 @@ static PyObject* linsolve(PyObject *self, PyObject *args,
         UMFD(free_numeric)(&numeric);
     else
         UMFZ(free_numeric)(&numeric);
-  
+
     if (info[UMFPACK_STATUS] != UMFPACK_OK){
         if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory)
             return PyErr_NoMemory();
-        else { 
+        else {
             if (info[UMFPACK_STATUS] == UMFPACK_WARNING_singular_matrix)
                 PyErr_SetString(PyExc_ArithmeticError, "singular "
                     "matrix");
@@ -213,7 +213,7 @@ static PyObject* linsolve(PyObject *self, PyObject *args,
 
 static char doc_symbolic[] =
     "Symbolic LU factorization of a sparse matrix.\n\n"
-    "F = symbolic(A)\n\n" 
+    "F = symbolic(A)\n\n"
     "ARGUMENTS\n"
     "A         sparse matrix with at least one row and at least one\n"
     "          column.  A may be rectangular.\n\n"
@@ -221,39 +221,39 @@ static char doc_symbolic[] =
 
 static PyObject* symbolic(PyObject *self, PyObject *args)
 {
-    spmatrix *A; 
+    spmatrix *A;
     double info[UMFPACK_INFO];
-    void *symbolic; 
-    
+    void *symbolic;
+
     if (!PyArg_ParseTuple(args, "O", &A)) return NULL;
-  
+
     if (!SpMatrix_Check(A)) PY_ERR_TYPE("A must be a sparse matrix");
-    if (SP_NCOLS(A) == 0 || SP_NROWS(A) == 0) { 
+    if (SP_NCOLS(A) == 0 || SP_NROWS(A) == 0) {
         PyErr_SetString(PyExc_ValueError, "A must have at least one "
             "row and column");
         return NULL;
-    } 
+    }
 
     switch (SP_ID(A)){
-        case DOUBLE:  
-            UMFD(symbolic)(SP_NROWS(A), SP_NCOLS(A), SP_COL(A), 
+        case DOUBLE:
+            UMFD(symbolic)(SP_NROWS(A), SP_NCOLS(A), SP_COL(A),
                 SP_ROW(A), SP_VAL(A), &symbolic, NULL, info);
-            if (info[UMFPACK_STATUS] == UMFPACK_OK) 
+            if (info[UMFPACK_STATUS] == UMFPACK_OK)
                 return (PyObject *) PyCObject_FromVoidPtrAndDesc(
-                    (void *) symbolic, "UMFPACK SYM D FACTOR",   
-                    free_umfpack_d_symbolic); 
-            else 
+                    (void *) symbolic, "UMFPACK SYM D FACTOR",
+                    free_umfpack_d_symbolic);
+            else
                 UMFD(free_symbolic)(&symbolic);
             break;
 
         case COMPLEX:
-            UMFZ(symbolic)(SP_NROWS(A), SP_NCOLS(A), SP_COL(A), 
+            UMFZ(symbolic)(SP_NROWS(A), SP_NCOLS(A), SP_COL(A),
                 SP_ROW(A), SP_VAL(A), NULL, &symbolic, NULL, info);
-            if (info[UMFPACK_STATUS] == UMFPACK_OK) 
+            if (info[UMFPACK_STATUS] == UMFPACK_OK)
                 return (PyObject *) PyCObject_FromVoidPtrAndDesc(
-                    (void *) symbolic, "UMFPACK SYM Z FACTOR",  
-                free_umfpack_z_symbolic); 
-            else 
+                    (void *) symbolic, "UMFPACK SYM Z FACTOR",
+                free_umfpack_z_symbolic);
+            else
                 UMFZ(free_symbolic)(&symbolic);
             break;
     }
@@ -273,7 +273,7 @@ static char doc_numeric[] =
     "Numeric LU factorization of a sparse matrix, given a symbolic\n"
     "factorization computed by umfpack.symbolic.  Raises an\n"
     "ArithmeticError if A is singular.\n\n"
-    "Fn = numeric(A, Fs)\n\n" 
+    "Fn = numeric(A, Fs)\n\n"
     "ARGUMENTS\n"
     "A         sparse matrix; may be rectangular\n\n"
     "Fs        symbolic factorization of A, or a matrix with the same\n"
@@ -284,47 +284,47 @@ static char doc_numeric[] =
 static PyObject* numeric(PyObject *self, PyObject *args)
 {
     spmatrix *A;
-    PyObject *Fs; 
+    PyObject *Fs;
     double info[UMFPACK_INFO];
-    void *numeric; 
-  
+    void *numeric;
+
     if (!PyArg_ParseTuple(args, "OO", &A, &Fs)) return NULL;
-  
+
     if (!SpMatrix_Check(A)) PY_ERR_TYPE("A must be a sparse matrix");
     if (!PyCObject_Check(Fs)) err_CO("Fs");
 
-    switch (SP_ID(A)) { 
+    switch (SP_ID(A)) {
 	case DOUBLE:
             TypeCheck_CObject(Fs, "UMFPACK SYM D FACTOR", "Fs is not "
                 "the UMFPACK symbolic factor of a 'd' matrix");
-            UMFD(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A), 
+            UMFD(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A),
 	        (void *) PyCObject_AsVoidPtr(Fs), &numeric, NULL, info);
-            if (info[UMFPACK_STATUS] == UMFPACK_OK) 
+            if (info[UMFPACK_STATUS] == UMFPACK_OK)
                 return (PyObject *) PyCObject_FromVoidPtrAndDesc(
-                    (void *) numeric, "UMFPACK NUM D FACTOR", 
+                    (void *) numeric, "UMFPACK NUM D FACTOR",
                     free_umfpack_d_numeric);
-            else 
+            else
                 UMFD(free_numeric)(&numeric);
 	    break;
 
-        case COMPLEX: 
+        case COMPLEX:
             TypeCheck_CObject(Fs, "UMFPACK SYM Z FACTOR", "Fs is not "
                 "the UMFPACK symbolic factor of a 'z' matrix");
             UMFZ(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A), NULL,
-	         (void *) PyCObject_AsVoidPtr(Fs), &numeric, NULL, 
+	         (void *) PyCObject_AsVoidPtr(Fs), &numeric, NULL,
 		 info);
-            if (info[UMFPACK_STATUS] == UMFPACK_OK) 
+            if (info[UMFPACK_STATUS] == UMFPACK_OK)
                 return (PyObject *) PyCObject_FromVoidPtrAndDesc(
-                    (void *) numeric, "UMFPACK NUM Z FACTOR", 
+                    (void *) numeric, "UMFPACK NUM Z FACTOR",
                     free_umfpack_z_numeric);
-	    else 
+	    else
                  UMFZ(free_numeric)(&numeric);
 	    break;
     }
 
     if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory)
         return PyErr_NoMemory();
-    else { 
+    else {
         if (info[UMFPACK_STATUS] == UMFPACK_WARNING_singular_matrix)
 	    PyErr_SetString(PyExc_ArithmeticError, "singular matrix");
         else {
@@ -340,7 +340,7 @@ static PyObject* numeric(PyObject *self, PyObject *args)
 static char doc_solve[] =
     "Solves a factored set of linear equations.\n\n"
     "solve(A, F, B, trans='N', nrhs=B.size[1], ldB=max(1,B.size[0]),\n"
-    "      offsetB=0)\n\n" 
+    "      offsetB=0)\n\n"
     "PURPOSE\n"
     "If trans is 'N', solves A*X = B.\n"
     "If trans is 'T', solves A^T*X = B.\n"
@@ -363,12 +363,12 @@ static char doc_solve[] =
 static PyObject* solve(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     spmatrix *A;
-    PyObject *F; 
+    PyObject *F;
     matrix *B;
     char trans='N';
     double *x, info[UMFPACK_INFO];
     int oB=0, n, ldB=0, nrhs=-1, k;
-    char *kwlist[] = {"A", "F", "B", "trans", "nrhs", "ldB", "offsetB", 
+    char *kwlist[] = {"A", "F", "B", "trans", "nrhs", "ldB", "offsetB",
         NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|ciii", kwlist,
@@ -388,7 +388,7 @@ static PyObject* solve(PyObject *self, PyObject *args, PyObject *kwrds)
             "UMFPACK numeric factor of a 'z' matrix");
     }
 
-    if (!Matrix_Check(B) || MAT_ID(B) != SP_ID(A)) 
+    if (!Matrix_Check(B) || MAT_ID(B) != SP_ID(A))
         PY_ERR_TYPE("B must a dense matrix of the same numeric type "
             "as A");
     if (nrhs < 0) nrhs = B->ncols;
@@ -400,23 +400,23 @@ static PyObject* solve(PyObject *self, PyObject *args, PyObject *kwrds)
 
     if (trans != 'N' && trans != 'T' && trans != 'C')
         err_char("trans", "'N', 'T', 'C'");
-  
+
     if (!(x = malloc(n*E_SIZE[SP_ID(A)]))) return PyErr_NoMemory();
 
     for (k=0; k<nrhs; k++) {
         if (SP_ID(A) == DOUBLE)
-            UMFD(solve)(trans == 'N' ? UMFPACK_A : UMFPACK_Aat, 
-                SP_COL(A), SP_ROW(A), SP_VAL(A), x, 
-                MAT_BUFD(B) + k*ldB + oB, 
+            UMFD(solve)(trans == 'N' ? UMFPACK_A : UMFPACK_Aat,
+                SP_COL(A), SP_ROW(A), SP_VAL(A), x,
+                MAT_BUFD(B) + k*ldB + oB,
                 (void *) PyCObject_AsVoidPtr(F), NULL, info);
         else
-            UMFZ(solve)(trans == 'N' ? UMFPACK_A : trans == 'C' ? 
-                UMFPACK_At : UMFPACK_Aat, SP_COL(A), SP_ROW(A), 
-                SP_VAL(A), NULL, x, NULL, 
-                (double *)(MAT_BUFZ(B) + k*ldB + oB), NULL,  
+            UMFZ(solve)(trans == 'N' ? UMFPACK_A : trans == 'C' ?
+                UMFPACK_At : UMFPACK_Aat, SP_COL(A), SP_ROW(A),
+                SP_VAL(A), NULL, x, NULL,
+                (double *)(MAT_BUFZ(B) + k*ldB + oB), NULL,
                 (void *) PyCObject_AsVoidPtr(F), NULL, info);
         if (info[UMFPACK_STATUS] == UMFPACK_OK)
-            memcpy(B->buffer + (k*ldB + oB)*E_SIZE[SP_ID(A)], x, 
+            memcpy(B->buffer + (k*ldB + oB)*E_SIZE[SP_ID(A)], x,
                 n*E_SIZE[SP_ID(A)]);
         else
 	    break;
@@ -426,9 +426,9 @@ static PyObject* solve(PyObject *self, PyObject *args, PyObject *kwrds)
     if (info[UMFPACK_STATUS] != UMFPACK_OK){
         if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory)
             return PyErr_NoMemory();
-        else { 
+        else {
             if (info[UMFPACK_STATUS] == UMFPACK_WARNING_singular_matrix)
-                PyErr_SetString(PyExc_ArithmeticError, 
+                PyErr_SetString(PyExc_ArithmeticError,
                     "singular matrix");
             else {
                 snprintf(umfpack_error,20,"%s %i","UMFPACK ERROR",
@@ -438,12 +438,12 @@ static PyObject* solve(PyObject *self, PyObject *args, PyObject *kwrds)
             return NULL;
         }
     }
-  
+
     return Py_BuildValue("");
 }
 
 static PyMethodDef umfpack_functions[] = {
-{"linsolve", (PyCFunction) linsolve, METH_VARARGS|METH_KEYWORDS, 
+{"linsolve", (PyCFunction) linsolve, METH_VARARGS|METH_KEYWORDS,
     doc_linsolve},
 {"symbolic", (PyCFunction) symbolic, METH_VARARGS, doc_symbolic},
 {"numeric", (PyCFunction) numeric, METH_VARARGS, doc_numeric},
@@ -455,7 +455,7 @@ PyMODINIT_FUNC initumfpack(void)
 {
   PyObject *m;
 
-  m = Py_InitModule3("cvxopt.umfpack", umfpack_functions, 
+  m = Py_InitModule3("cvxopt.umfpack", umfpack_functions,
       umfpack__doc__);
 
   if (import_cvxopt() < 0) return;
diff --git a/src/python/__init__.py b/src/python/__init__.py
index 775501d..6aedfaa 100644
--- a/src/python/__init__.py
+++ b/src/python/__init__.py
@@ -11,9 +11,9 @@ library and on the strengths of Python as a high-level programming
 language.
 """ 
 
-# Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+# Copyright 2004-2009 J. Dahl and L. Vandenberghe.
 # 
-# This file is part of CVXOPT version 1.1.
+# This file is part of CVXOPT version 1.1.2
 #
 # CVXOPT is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
diff --git a/src/python/coneprog.py b/src/python/coneprog.py
index 90c7ab4..1416cbb 100644
--- a/src/python/coneprog.py
+++ b/src/python/coneprog.py
@@ -1,10 +1,10 @@
 """
-Solver for linear, second-order cone and semidefinite programming.
+Solver for linear and quadratic cone programs. 
 """
 
-# Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+# Copyright 2004-2009 J. Dahl and L. Vandenberghe.
 # 
-# This file is part of CVXOPT version 1.1.
+# This file is part of CVXOPT version 1.1.2
 #
 # CVXOPT is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -118,18 +118,18 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
         The other arguments are normally not needed.  They make it possible
         to exploit certain types of structure, as described below.
 
-
     Output arguments.
 
         Returns a dictionary with keys 'status', 'x', 's', 'z', 'y',
         'primal objective', 'dual objective', 'gap', 'relative gap',  
         'primal infeasibility', 'dual infeasibility', 'primal slack',
         'dual slack', 'residual as primal infeasibility certificate', 
-        'residual as dual infeasibility certificate'.
+        'residual as dual infeasibility certificate', 'iterations'.
 
         The 'status' field has values 'optimal', 'primal infeasible',
-        'dual infeasible', or 'unknown'.  The values of the other fields
-        depend on the exit status.
+        'dual infeasible', or 'unknown'.  The 'iterations' field is the
+        number of iterations taken.  The values of the other fields depend
+        on the exit status.
 
         Status 'optimal'. 
         - 'x', 's', 'y', 'z' are an approximate solution of the primal and
@@ -166,9 +166,8 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
               e = ( e_0, e_1, ..., e_N, e_{N+1}, ..., e_{M+N} )
 
           is the identity vector in C.  e_0 is an ml-vector of ones, 
-          e_k, k = 1,..., N, is the unit vector (1,0,...,0) of length
-          mq[k], and e_k = vec(I) where I is the identity matrix of order
-          ms[k].
+          e_k, k = 1,..., N, are unit vectors (1,0,...,0) of length mq[k],
+          and e_k = vec(I) where I is the identity matrix of order ms[k].
         - 'dual slack': the smallest dual slack, sup {t | z >= t*e }.
         - 'residual as primal infeasibility certificate': None.
         - 'residual as dual infeasibility certificate': None.
@@ -331,7 +330,7 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
           inverse of the transpose of r_k.
 
         The call f = kktsolver(W) should return a function f that solves 
-        the KKT system by g(x, y, z).  On entry, x, y, z contain the 
+        the KKT system by f(x, y, z).  On entry, x, y, z contain the 
         righthand side bx, by, bz.  On exit, they contain the solution, 
         with uz scaled: the argument z contains W*uz.  In other words,
         on exit, x, y, z are the solution of
@@ -382,6 +381,10 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
           and u is a vector in X.
         - xaxpy(u, v, alpha = 1.0) computes v := alpha*u + v for a scalar 
           alpha and two vectors u and v in X.
+        If this option is used, the argument c must be in the same format
+        as x, the argument G must be a Python function, the argument A 
+        must be a Python function or None, and the argument kktsolver is 
+        required.
 
         If Y is the vector space of primal variables y:
         - ynewcopy(u) creates a new copy of the vector u in Y.
@@ -391,8 +394,8 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
         - yaxpy(u, v, alpha = 1.0) computes v := alpha*u + v for a scalar 
           alpha and two vectors u and v in Y.
         If this option is used, the argument b must be in the same format
-        as y, the argument A must be a Python function, and the argument 
-        kktsolver is required.
+        as y, the argument A must be a Python function or None, and the 
+        argument kktsolver is required.
 
 
     Control parameters.
@@ -411,8 +414,7 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
 
     """
     import math
-    from cvxopt import base, blas, misc
-    from cvxopt.base import matrix, spmatrix
+    from cvxopt import base, blas, misc, matrix, spmatrix
 
     EXPON = 3
     STEP = 0.99
@@ -466,19 +468,19 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
 
     # Argument error checking depends on level of customization.
     customkkt = type(kktsolver) is not str
-    operatorG = type(G) not in (matrix, spmatrix)
-    operatorA = A is not None and type(A) not in (matrix, spmatrix)
-    if (operatorG or operatorA) and not customkkt:
+    matrixG = type(G) in (matrix, spmatrix)
+    matrixA = type(A) in (matrix, spmatrix)
+    if (not matrixG or (not matrixA and A is not None)) and not customkkt:
         raise ValueError, "use of function valued G, A requires a "\
             "user-provided kktsolver"
-    customx = ( xnewcopy != None or xdot != None or xaxpy != None or 
-        xscal != None )
-    if customx and (not operatorG or not operatorA or not customkkt):
+    customx = (xnewcopy != None or xdot != None or xaxpy != None or 
+        xscal != None)
+    if customx and (matrixG or matrixA or not customkkt):
         raise ValueError, "use of non-vector type for x requires "\
             "function valued G, A and user-provided kktsolver"
     customy = (ynewcopy != None or ydot != None or yaxpy != None or 
         yscal != None)
-    if customy and (not operatorA or not customkkt):
+    if customy and (matrixA or not customkkt):
         raise ValueError, "use of non-vector type for y requires "\
             "function valued A and user-provided kktsolver"
 
@@ -525,7 +527,7 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
     inds = [ indq[-1] ]
     for k in dims['s']:  inds = inds + [ inds[-1] + k**2 ] 
 
-    if not operatorG:
+    if matrixG:
         if G.typecode != 'd' or G.size != (cdim, c.size[0]):
             raise TypeError, "'G' must be a 'd' matrix of size (%d, %d)"\
                 %(cdim, c.size[0])
@@ -539,10 +541,11 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
         if customx or customy: 
             def A(x, y, trans = 'N', alpha = 1.0, beta = 0.0):
                 if trans == 'N': pass
-                else: yscal(beta, y)
+                else: xscal(beta, y)
         else: 
             A = spmatrix([], [], [], (0, c.size[0]))
-    if not operatorA:
+            matrixA = True
+    if matrixA:
         if A.typecode != 'd' or A.size[1] != c.size[0]:
             raise TypeError, "'A' must be a 'd' matrix with %d columns "\
                 %c.size[0]
@@ -555,7 +558,7 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
         if b is None: b = matrix(0.0, (0,1))
         if type(b) is not matrix or b.typecode != 'd' or b.size[1] != 1:
             raise TypeError, "'b' must be a 'd' matrix with one column" 
-        if not operatorA and b.size[0] != A.size[0]:
+        if matrixA and b.size[0] != A.size[0]:
             raise TypeError, "'b' must have length %d" %A.size[0]
     else:
         if b is None: 
@@ -587,13 +590,13 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
 
     # res() evaluates residual in 5x5 block KKT system
     #
-    # [ vx   ]    [ 0         ]   [ 0   A'  G'  c ] [ ux        ]
-    # [ vy   ]    [ 0         ]   [-A   0   0   b ] [ uy        ]
-    # [ vz   ] += [ W'*us     ] - [-G   0   0   h ] [ W^{-1}*uz ]
-    # [ vtau ]    [ dg*ukappa ]   [-c' -b' -h'  0 ] [ utau/dg   ]
+    #     [ vx   ]    [ 0         ]   [ 0   A'  G'  c ] [ ux        ]
+    #     [ vy   ]    [ 0         ]   [-A   0   0   b ] [ uy        ]
+    #     [ vz   ] += [ W'*us     ] - [-G   0   0   h ] [ W^{-1}*uz ]
+    #     [ vtau ]    [ dg*ukappa ]   [-c' -b' -h'  0 ] [ utau/dg   ]
     # 
-    # vs := vs + lmbda o (dz + ds) 
-    # vkappa := vkappa + lmbdg * (dtau + dkappa).
+    #           vs += lmbda o (dz + ds) 
+    #       vkappa += lmbdg * (dtau + dkappa).
 
     ws3, wz3 = matrix(0.0, (cdim,1)), matrix(0.0, (cdim,1))
     def res(ux, uy, uz, utau, us, ukappa, vx, vy, vz, vtau, vs, vkappa, W,
@@ -683,14 +686,14 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
 
     if primalstart is None:
 
-	# minimize    || G * x - h ||^2
-	# subject to  A * x = b
-	#
-	# by solving
-	#
-	#     [ 0   A'  G' ]   [ x  ]   [ 0 ]
-	#     [ A   0   0  ] * [ dy ] = [ b ].
-	#     [ G   0  -I  ]   [ -s ]   [ h ]
+        # minimize    || G * x - h ||^2
+        # subject to  A * x = b
+        #
+        # by solving
+        #
+        #     [ 0   A'  G' ]   [ x  ]   [ 0 ]
+        #     [ A   0   0  ] * [ dy ] = [ b ].
+        #     [ G   0  -I  ]   [ -s ]   [ h ]
 
         xscal(0.0, x)
         ycopy(b, dy)  
@@ -738,12 +741,6 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
     if tz >= 0 and dualstart: 
         raise ValueError, "initial z is not positive"
 
-    trz = sum(z[:dims['l']]) + sum(z[indq[:-1]]) + sum([ 
-        sum(z[inds[k] : inds[k+1] : dims['s'][k]+1]) for k in 
-        xrange(len(dims['s'])) ])
-    trs = sum(s[:dims['l']]) + sum(s[indq[:-1]]) + sum([ 
-        sum(s[inds[k] : inds[k+1] : dims['s'][k]+1]) for k in 
-        xrange(len(dims['s'])) ])
     nrms = misc.snrm2(s, dims)
     nrmz = misc.snrm2(z, dims)
 
@@ -806,7 +803,8 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
                 'dual slack': -tz,
                 'dual infeasibility': dres,
                 'residual as primal infeasibility certificate': None,
-                'residual as dual infeasibility certificate': None } 
+                'residual as dual infeasibility certificate': None,
+                'iterations': 0 } 
 
         if ts >= -1e-8 * max(nrms, 1.0):  
             a = 1.0 + ts  
@@ -958,7 +956,8 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
                     'residual as primal infeasibility certificate': 
                         pinfres,
                     'residual as dual infeasibility certificate': 
-                        dinfres}
+                        dinfres,
+                    'iterations': iters}
 
             else:
                 if show_progress:
@@ -974,7 +973,8 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
                     'primal slack': -ts,
                     'dual slack': -tz,
                     'residual as primal infeasibility certificate': None,
-                    'residual as dual infeasibility certificate': None }
+                    'residual as dual infeasibility certificate': None,
+                    'iterations': iters }
 
         elif pinfres is not None and pinfres <= FEASTOL:
             yscal(1.0/(-hz - by), y)
@@ -997,7 +997,8 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
                 'primal slack': None,
                 'dual slack': -tz,
                 'residual as primal infeasibility certificate': pinfres,
-                'residual as dual infeasibility certificate': None }
+                'residual as dual infeasibility certificate': None,
+                'iterations': iters }
 
         elif dinfres is not None and dinfres <= FEASTOL:
             xscal(1.0/(-cx), x)
@@ -1021,7 +1022,8 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
                 'primal slack': -ts,
                 'dual slack': None,
                 'residual as primal infeasibility certificate': None,
-                'residual as dual infeasibility certificate': dinfres }
+                'residual as dual infeasibility certificate': dinfres,
+                'iterations': iters }
 
 
         # Compute initial scaling W:
@@ -1106,7 +1108,8 @@ def conelp(c, G, h, dims = None, A = None, b = None, primalstart = None,
                     'residual as primal infeasibility certificate': 
                         pinfres,
                     'residual as dual infeasibility certificate': 
-                        dinfres }
+                        dinfres, 
+                    'iterations': iters }
 
 
         # f6_no_ir(x, y, z, tau, s, kappa) solves
@@ -1541,15 +1544,17 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
         Returns a dictionary with keys 'status', 'x', 's', 'z', 'y',
         'primal objective', 'dual objective', 'gap', 'relative gap', 
         'primal infeasibility', 'dual infeasibility', 'primal slack',
-        'dual slack'. 
+        'dual slack', 'iterations'. 
+
+        The 'status' field has values 'optimal' or 'unknown'.  'iterations'
+        is the number of iterations taken.
 
-        The 'status' field has values 'optimal' or 'unknown'.  
         If the status is 'optimal', 'x', 's', 'y', 'z' are an approximate 
         solution of the primal and dual optimality conditions   
 
               G*x + s = h,  A*x = b  
               P*x + G'*z + A'*y + q = 0 
-              s >= 0, z >= 0
+              s >= 0,  z >= 0
               s'*z = 0.
 
         If the status is 'unknown', 'x', 'y', 's', 'z' are the last 
@@ -1591,6 +1596,7 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
 
               || P*x + G'*z + A'*y + q || / max(1, ||q||).
 
+
         - 'primal slack': the smallest primal slack, sup {t | s >= t*e }, 
            where 
 
@@ -1600,6 +1606,7 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
           e_k, k = 1,..., N, is the unit vector (1,0,...,0) of length
           mq[k], and e_k = vec(I) where I is the identity matrix of order
           ms[k].
+
         - 'dual slack': the smallest dual slack, sup {t | z >= t*e }.
 
         If the exit status is 'optimal', then the primal and dual
@@ -1725,6 +1732,10 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
           and u is a vector in X.
         - xaxpy(u, v, alpha = 1.0) computes v := alpha*u + v for a scalar 
           alpha and two vectors u and v in X.
+        If this option is used, the argument q must be in the same format
+        as x, the argument P must be a Python function, the arguments A 
+        and G must be Python functions or None, and the argument 
+        kktsolver is required.
 
         If Y is the vector space of primal variables y:
         - ynewcopy(u) creates a new copy of the vector u in Y.
@@ -1733,6 +1744,9 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
           and u is a vector in Y.
         - yaxpy(u, v, alpha = 1.0) computes v := alpha*u + v for a scalar 
           alpha and two vectors u and v in Y.
+        If this option is used, the argument b must be in the same format
+        as y, the argument A must be a Python function or None, and the 
+        argument kktsolver is required.
 
 
     Control parameters.
@@ -1763,6 +1777,7 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
     # Use Mehrotra correction or not.
     try: correction = options['use_correction']
     except KeyError: correction = True
+ 
 
     try: MAXITERS = options['maxiters']
     except KeyError: MAXITERS = 100
@@ -1812,30 +1827,30 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
 
     # Argument error checking depends on level of customization.
     customkkt = type(kktsolver) is not str
-    operatorP = type(P) not in (matrix, spmatrix)
-    operatorG = G is not None and type(G) not in (matrix, spmatrix)
-    operatorA = A is not None and type(A) not in (matrix, spmatrix)
-    if (operatorP or operatorG or operatorA) and not customkkt:
+    matrixP = type(P) in (matrix, spmatrix)
+    matrixG = type(G) in (matrix, spmatrix)
+    matrixA = type(A) in (matrix, spmatrix)
+    if (not matrixP or (not matrixG and G is not None) or 
+        (not matrixA and A is not None)) and not customkkt:
         raise ValueError, "use of function valued P, G, A requires a "\
             "user-provided kktsolver"
     customx = (xnewcopy != None or xdot != None or xaxpy != None or 
         xscal != None) 
-    if customx and (not operatorP or not operatorG or not operatorA or 
-        not customkkt):
+    if customx and (matrixP or matrixG or matrixA or not customkkt):
         raise ValueError, "use of non-vector type for x requires "\
             "function valued P, G, A and user-provided kktsolver"
     customy = (ynewcopy != None or ydot != None or yaxpy != None or 
         yscal != None) 
-    if customy and (not operatorP or not operatorA or not customkkt):
+    if customy and (matrixA or not customkkt):
         raise ValueError, "use of non vector type for y requires "\
-            "function valued P, A and user-provided kktsolver"
+            "function valued A and user-provided kktsolver"
 
 
     if not customx and (type(q) is not matrix or q.typecode != 'd' or
         q.size[1] != 1):
         raise TypeError, "'q' must be a 'd' matrix with one column"
 
-    if not operatorP:
+    if matrixP:
         if P.typecode != 'd' or P.size != (q.size[0], q.size[0]):
             raise TypeError, "'P' must be a 'd' matrix of size (%d, %d)"\
                 %(q.size[0], q.size[0])
@@ -1872,6 +1887,14 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
     if h.size[0] != cdim:
         raise TypeError, "'h' must be a 'd' matrix of size (%d,1)" %cdim
 
+    # Data for kth 'q' constraint are found in rows indq[k]:indq[k+1] of G.
+    indq = [ dims['l'] ]  
+    for k in dims['q']:  indq = indq + [ indq[-1] + k ] 
+
+    # Data for kth 's' constraint are found in rows inds[k]:inds[k+1] of G.
+    inds = [ indq[-1] ]
+    for k in dims['s']:  inds = inds + [ inds[-1] + k**2 ] 
+
     if G is None:
         if customx:
             def G(x, y, trans = 'N', alpha = 1.0, beta = 0.0):
@@ -1879,7 +1902,8 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
                 else: xscal(beta, y)
         else:
             G = spmatrix([], [], [], (0, q.size[0]))
-    if not operatorG:
+            matrixG = True
+    if matrixG:
         if G.typecode != 'd' or G.size != (cdim, q.size[0]):
             raise TypeError, "'G' must be a 'd' matrix of size (%d, %d)"\
                 %(cdim, q.size[0])
@@ -1894,10 +1918,11 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
         if customx or customy:
             def A(x, y, trans = 'N', alpha = 1.0, beta = 0.0):
                 if trans == 'N': pass
-                else: yscal(beta, y)
+                else: xscal(beta, y)
         else:
             A = spmatrix([], [], [], (0, q.size[0]))
-    if not operatorA:
+            matrixA = True
+    if matrixA:
         if A.typecode != 'd' or A.size[1] != q.size[0]:
             raise TypeError, "'A' must be a 'd' matrix with %d columns" \
                 %q.size[0]
@@ -1909,7 +1934,7 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
         if b is None: b = matrix(0.0, (0,1))
         if type(b) is not matrix or b.typecode != 'd' or b.size[1] != 1:
             raise TypeError, "'b' must be a 'd' matrix with one column"
-        if not operatorA and b.size[0] != A.size[0]:
+        if matrixA and b.size[0] != A.size[0]:
             raise TypeError, "'b' must have length %d" %A.size[0]
     if b is None and customy:  
         raise ValueEror, "use of non-vector type for y requires b"
@@ -2026,56 +2051,117 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
             'primal objective': pcost,
             'dual objective': pcost,
             'primal slack': 0.0, 'dual slack': 0.0,
-            'primal infeasibility': pres, 'dual infeasibility': dres} 
+            'primal infeasibility': pres, 'dual infeasibility': dres,
+            'iterations': 0 } 
 
 
-    # Default initial points are x = 0, y = 0, s = e, z = e. 
-
     x, y = xnewcopy(q), ynewcopy(b)  
     s, z = matrix(0.0, (cdim, 1)), matrix(0.0, (cdim, 1))
 
-    if initvals is None: 
-        initvals = {}
-    if 'x' in initvals: 
-        xcopy(initvals['x'], x)
-    else: 
-        xscal(0.0, x)
+    if initvals is None:
+
+        # Factor
+        #
+        #     [ P   A'  G' ] 
+        #     [ A   0   0  ].
+        #     [ G   0  -I  ]
+        
+        W = {}
+        W['d'] = matrix(1.0, (dims['l'], 1)) 
+        W['di'] = matrix(1.0, (dims['l'], 1)) 
+        W['v'] = [ matrix(0.0, (m,1)) for m in dims['q'] ]
+        W['beta'] = len(dims['q']) * [ 1.0 ] 
+        for v in W['v']: v[0] = 1.0
+        W['r'] = [ matrix(0.0, (m,m)) for m in dims['s'] ]
+        W['rti'] = [ matrix(0.0, (m,m)) for m in dims['s'] ]
+        for r in W['r']: r[::r.size[0]+1 ] = 1.0
+        for rti in W['rti']: rti[::rti.size[0]+1 ] = 1.0
+        try: f = kktsolver(W)
+        except ArithmeticError:  
+            raise ValueError, "Rank(A) < p or Rank([P; A; G]) < n"
+
+             
+        # Solve
+        #
+        #     [ P   A'  G' ]   [ x ]   [ -q ]
+        #     [ A   0   0  ] * [ y ] = [  b ].
+        #     [ G   0  -I  ]   [ z ]   [  h ]
+
+        xcopy(q, x)
+        xscal(-1.0, x)
+        ycopy(b, y)  
+        blas.copy(h, z)
+        try: f(x, y, z) 
+        except ArithmeticError:  
+            raise ValueError, "Rank(A) < p or Rank([P; G; A]) < n"
+        blas.copy(z, s)  
+        blas.scal(-1.0, s)  
+
+        nrms = misc.snrm2(s, dims)
+        ts = misc.max_step(s, dims)
+        if ts >= -1e-8 * max(nrms, 1.0):  
+            a = 1.0 + ts  
+            s[:dims['l']] += a
+            s[indq[:-1]] += a
+            ind = dims['l'] + sum(dims['q'])
+            for m in dims['s']:
+                s[ind : ind+m*m : m+1] += a
+                ind += m**2
+
+        nrmz = misc.snrm2(z, dims)
+        tz = misc.max_step(z, dims)
+        if tz >= -1e-8 * max(nrmz, 1.0):
+            a = 1.0 + tz  
+            z[:dims['l']] += a
+            z[indq[:-1]] += a
+            ind = dims['l'] + sum(dims['q'])
+            for m in dims['s']:
+                z[ind : ind+m*m : m+1] += a
+                ind += m**2
+
 
-    if 's' in initvals:
-        blas.copy(initvals['s'], s)
-        # ts = min{ t | s + t*e >= 0 }
-        if misc.max_step(s, dims) >= 0:
-            raise ValueError, "initial s is not positive"
     else: 
-        s[: dims['l']] = 1.0 
-        ind = dims['l']
-        for m in dims['q']:
-            s[ind] = 1.0
-            ind += m
-        for m in dims['s']:
-            s[ind : ind + m*m : m+1] = 1.0
-            ind += m**2
 
-    if 'y' in initvals:
-        ycopy(initvals['y'], y)
-    else:
-        yscal(0.0, y)
+        if 'x' in initvals: 
+            xcopy(initvals['x'], x)
+        else: 
+            xscal(0.0, x)
+
+        if 's' in initvals:
+            blas.copy(initvals['s'], s)
+            # ts = min{ t | s + t*e >= 0 }
+            if misc.max_step(s, dims) >= 0:
+                raise ValueError, "initial s is not positive"
+        else: 
+            s[: dims['l']] = 1.0 
+            ind = dims['l']
+            for m in dims['q']:
+                s[ind] = 1.0
+                ind += m
+            for m in dims['s']:
+                s[ind : ind + m*m : m+1] = 1.0
+                ind += m**2
+
+        if 'y' in initvals:
+            ycopy(initvals['y'], y)
+        else:
+            yscal(0.0, y)
+
+        if 'z' in initvals:
+            blas.copy(initvals['z'], z)
+            # tz = min{ t | z + t*e >= 0 }
+            if misc.max_step(z, dims) >= 0:
+                raise ValueError, "initial z is not positive"
+        else:
+            z[: dims['l']] = 1.0 
+            ind = dims['l']
+            for m in dims['q']:
+                z[ind] = 1.0
+                ind += m
+            for m in dims['s']:
+                z[ind : ind + m*m : m+1] = 1.0
+                ind += m**2
 
-    if 'z' in initvals:
-        blas.copy(initvals['z'], z)
-        # tz = min{ t | z + t*e >= 0 }
-        if misc.max_step(z, dims) >= 0:
-            raise ValueError, "initial z is not positive"
-    else:
-        z[: dims['l']] = 1.0 
-        ind = dims['l']
-        for m in dims['q']:
-            z[ind] = 1.0
-            ind += m
-        for m in dims['s']:
-            z[ind : ind + m*m : m+1] = 1.0
-            ind += m**2
-    
 
     rx, ry, rz = xnewcopy(q), ynewcopy(b), matrix(0.0, (cdim, 1)) 
     dx, dy = xnewcopy(x), ynewcopy(y)   
@@ -2090,6 +2176,7 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
         print "% 10s% 12s% 10s% 8s% 7s" %("pcost", "dcost", "gap", "pres",
             "dres")
 
+
     gap = misc.sdot(s, z, dims) 
 
     for iters in xrange(MAXITERS + 1):
@@ -2159,7 +2246,7 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
                     'primal objective': pcost,  'dual objective': dcost,
                     'primal infeasibility': pres,
                     'dual infeasibility': dres, 'primal slack': -ts,
-                    'dual slack': -tz }
+                    'dual slack': -tz , 'iterations': iters }
                     
 
         # Compute initial scaling W and scaled iterates:  
@@ -2199,7 +2286,7 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
                     'relative gap': relgap, 'primal objective': pcost,  
                     'dual objective': dcost, 'primal infeasibility': pres,
                     'dual infeasibility': dres, 'primal slack': -ts,
-                    'dual slack': -tz }   
+                    'dual slack': -tz, 'iterations': iters }   
 
         # f4_no_ir(x, y, z, s) solves
         # 
@@ -2344,12 +2431,14 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
                         'dual objective': dcost,
                         'primal infeasibility': pres,
                         'dual infeasibility': dres, 'primal slack': -ts,
-                        'dual slack': -tz }
+                        'dual slack': -tz, 'iterations': iters }
+
+            dsdz = misc.sdot(ds, dz, dims)
 
             # Save ds o dz for Mehrotra correction
-            if correction and i == 0:
-                blas.copy(ds, ws3)
-                misc.sprod(ws3, dz, dims)
+            if correction and i == 0:   
+                    blas.copy(ds, ws3)
+                    misc.sprod(ws3, dz, dims)
 
 
             # Maximum steps to boundary.  
@@ -2375,7 +2464,8 @@ def coneqp(P, q, G = None, h = None, dims = None, A = None, b = None,
                 else:
                     step = min(1.0, STEP / t)
             if i == 0: 
-                sigma = (1.0 - step)**EXPON
+                sigma = min(1.0, max(0.0, 
+                    1.0 - step + dsdz/gap * step**2))**EXPON
                 eta = 0.0
 
 
@@ -2519,7 +2609,7 @@ def lp(c, G, h, A = None, b = None, solver = None, primalstart = None,
         'primal objective', 'dual objective', 'gap', 'relative gap',  
         'primal infeasibility', 'dual infeasibility', 'primal slack', 
         'dual slack', 'residual as primal infeasibility certificate', 
-        'residual as dual infeasibility certificate'.
+        'residual as dual infeasibility certificate'. 
 
         The 'status' field has values 'optimal', 'primal infeasible',
         'dual infeasible', or 'unknown'.  The values of the other fields
@@ -4275,8 +4365,14 @@ def qp(P, q, G = None, h = None, A = None, b = None, solver = None,
         else:
             mosek.options = {}
         solsta, x, z, y = mosek.qp(P, q, G, h, A, b)
-        m = G.size[0]
 
+        n = q.size[0]
+        if G is None: G = spmatrix([], [], [], (0,n), 'd')
+        if h is None: h = matrix(0.0, (0,1))
+        if A is None: A = spmatrix([], [], [], (0,n), 'd')
+        if b is None: b = matrix(0.0, (0,1))
+        m = G.size[0]
+    
         resx0 = max(1.0, blas.nrm2(q))
         resy0 = max(1.0, blas.nrm2(b))
         resz0 = max(1.0, blas.nrm2(h))
diff --git a/src/python/cvxprog.py b/src/python/cvxprog.py
index fd50f10..af50805 100644
--- a/src/python/cvxprog.py
+++ b/src/python/cvxprog.py
@@ -6,9 +6,9 @@ for quadratic and geometric programming.  Also includes an interface
 to the quadratic programming solver from MOSEK.
 """
 
-# Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+# Copyright 2004-2009 J. Dahl and L. Vandenberghe.
 # 
-# This file is part of CVXOPT version 1.1.
+# This file is part of CVXOPT version 1.1.2.
 #
 # CVXOPT is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
diff --git a/src/python/info.py b/src/python/info.py
index d08a03f..5885350 100644
--- a/src/python/info.py
+++ b/src/python/info.py
@@ -1,8 +1,8 @@
-version = '1.1'
+version = '1.1.2'
 
 def license(): print(
 """
-CVXOPT version 1.1.  Copyright (c) 2004-2008 J. Dahl and L. Vandenberghe.
+CVXOPT version 1.1.2  Copyright (c) 2004-2009 J. Dahl and L. Vandenberghe.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -21,12 +21,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 The CVXOPT distribution includes source code for part of the SuiteSparse
 suite of sparse matrix algorithms, including:
 
-- AMD Version 2.2.0. Copyright (c) 2007 by Timothy A. Davis, Patrick R. 
+- AMD Version 2.2. Copyright (c) 2007 by Timothy A. Davis, Patrick R. 
   Amestoy, and Iain S. Duff.
-- CHOLMOD Version 1.7.0. Copyright (c) 2005-2007 by University of Florida, 
+- CHOLMOD Version 1.7.1. Copyright (c) 2005-2009 by University of Florida, 
   Timothy A. Davis and W. Hager.
-- COLAMD version 2.7.0. Copyright (c) 1998-2007 by Timothy A. Davis.
-- UMFPACK Version 5.2.0. Copyright (c) 1995-2006 by Timothy A. Davis.
+- COLAMD version 2.7. Copyright (c) 1998-2007 by Timothy A. Davis.
+- UMFPACK Version 5.4.0. Copyright (c) 1994-2009 by Timothy A. Davis.
 
 These packages are licensed under the terms of the GNU General Public 
 License, version 2 or higher (UMFPACK, the Supernodal module of CHOLMOD),
diff --git a/src/python/misc.py b/src/python/misc.py
index 21d33aa..a0fda62 100644
--- a/src/python/misc.py
+++ b/src/python/misc.py
@@ -1,6 +1,6 @@
-# Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+# Copyright 2004-2009 J. Dahl and L. Vandenberghe.
 # 
-# This file is part of CVXOPT version 1.1.
+# This file is part of CVXOPT version 1.1.2.
 #
 # CVXOPT is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -1577,7 +1577,7 @@ def kkt_qr(G, dims, A):
         W^{-T} * G * Q2 = Q3 * R3
     
     (with columns of W^{-T}*G in packed storage), and (2) returns a 
-    function for # solving 
+    function for solving 
     
         [ 0    A'   G'    ]   [ ux ]   [ bx ]
         [ A    0    0     ] * [ uy ] = [ by ].
diff --git a/src/python/modeling.py b/src/python/modeling.py
index 8f3fd11..7089bf0 100644
--- a/src/python/modeling.py
+++ b/src/python/modeling.py
@@ -5,9 +5,9 @@ Routines for specifying and solving convex optimization problems with
 piecewise-linear objective and constraint functions.
 """
 
-# Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+# Copyright 2004-2009 J. Dahl and L. Vandenberghe.
 # 
-# This file is part of CVXOPT version 1.1.
+# This file is part of CVXOPT version 1.1.2
 #
 # CVXOPT is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -2380,7 +2380,7 @@ class op(object):
 
                 for j in xrange(len(fk._flist)):
                     c = fk._flist[j] <= tk
-                    if xrange(len(fk._flist)) > 1:
+                    if len(fk._flist) > 1:
                         c.name = self.name + '[%d](%d)' %(k,j)
                     else:
                         c.name = self.name + '[%d]' %k
diff --git a/src/python/mosek.py b/src/python/mosek.py
index b0b7dab..7574d96 100644
--- a/src/python/mosek.py
+++ b/src/python/mosek.py
@@ -2,9 +2,9 @@
 CVXOPT interface for MOSEK 5.0
 """
 
-# Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+# Copyright 2004-2009 J. Dahl and L. Vandenberghe.
 # 
-# This file is part of CVXOPT version 1.1.
+# This file is part of CVXOPT version 1.1.2
 #
 # CVXOPT is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
diff --git a/src/python/printing.py b/src/python/printing.py
index 6b6008c..f3e7196 100644
--- a/src/python/printing.py
+++ b/src/python/printing.py
@@ -1,6 +1,6 @@
-# Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+# Copyright 2004-2009 J. Dahl and L. Vandenberghe.
 # 
-# This file is part of CVXOPT version 1.1.
+# This file is part of CVXOPT version 1.1.2
 #
 # CVXOPT is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -100,8 +100,8 @@ def spmatrix_str_default(X):
 
     if width*height is 0: return ""
  
-    rlist = range(0,min(m,height))
-    clist = range(0,min(n,width))
+    rlist = xrange(0,min(m,height))
+    clist = xrange(0,min(n,width))
 
     Xr = X[:min(m,height),:min(n,width)]
     Idx = zip(*(Xr.I,Xr.J))
diff --git a/src/python/solvers.py b/src/python/solvers.py
index f1981a2..63d6c40 100644
--- a/src/python/solvers.py
+++ b/src/python/solvers.py
@@ -13,9 +13,9 @@ socp:     solves second-order cone programs.
 options:  dictionary with customizable algorithm parameters.
 """
 
-# Copyright 2004-2008 J. Dahl and L. Vandenberghe.
+# Copyright 2004-2009 J. Dahl and L. Vandenberghe.
 # 
-# This file is part of CVXOPT version 1.1.
+# This file is part of CVXOPT version 1.1.2
 #
 # CVXOPT is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
diff --git a/src/setup.py b/src/setup.py
index d5000b6..c6959bf 100644
--- a/src/setup.py
+++ b/src/setup.py
@@ -1,5 +1,5 @@
 from distutils.core import setup, Extension
-from os import listdir
+from glob import glob
 
 # directory containing libblas and liblapack
 ATLAS_LIB_DIR = '/usr/lib'
@@ -41,7 +41,6 @@ DSDP_LIB_DIR = '/usr/lib'
 # Directory containing dsdp5.h (used only when BUILD_DSDP = 1).
 DSDP_INC_DIR = '/usr/include'
 
-
 extmods = []
 
 # optional modules
@@ -111,8 +110,7 @@ umfpack = Extension('umfpack',
     sources = [ 'C/umfpack.c',
         'C/SuiteSparse/UMFPACK/Source/umfpack_global.c',
         'C/SuiteSparse/UMFPACK/Source/umfpack_tictoc.c' ] +
-        ['C/SuiteSparse_cvxopt_extra/umfpack/' + s for s in
-            listdir('C/SuiteSparse_cvxopt_extra/umfpack')])
+        glob('C/SuiteSparse_cvxopt_extra/umfpack/*'))
 
 # Build for int or long? 
 import sys
@@ -125,28 +123,21 @@ cholmod = Extension('cholmod',
         'C/SuiteSparse/COLAMD', 'C/SuiteSparse/AMD/Include', 
         'C/SuiteSparse/UFconfig', 'C/SuiteSparse/COLAMD/Include' ],
     define_macros = MACROS + [('NPARTITION', '1')],
-    sources = [ 'C/cholmod.c' ] +
+    sources = [ 'C/cholmod.c' ] + 
         ['C/SuiteSparse/AMD/Source/' + s for s in ['amd_global.c',
             'amd_postorder.c', 'amd_post_tree.c', 'amd_2.c']] +
         ['C/SuiteSparse/COLAMD/Source/' + s for s in ['colamd.c',
             'colamd_global.c']] +
-        ['C/SuiteSparse/CHOLMOD/Core/' + s for s in
-            listdir('C/SuiteSparse/CHOLMOD/Core') if s[-2:] == '.c' and
-            s[0] == 'c'] +
-        ['C/SuiteSparse/CHOLMOD/Cholesky/' + s for s in
-            listdir('C/SuiteSparse/CHOLMOD/Cholesky') if s[-2:] == '.c'
-            and s[0] == 'c'] +
+        glob('C/SuiteSparse/CHOLMOD/Core/c*.c') +
+        glob('C/SuiteSparse/CHOLMOD/Cholesky/c*.c') +
         ['C/SuiteSparse/CHOLMOD/Check/cholmod_check.c'] +
-        ['C/SuiteSparse/CHOLMOD/Supernodal/' + s for s in
-            listdir('C/SuiteSparse/CHOLMOD/Supernodal') if 
-            s[-2:] == '.c' and s[0] == 'c'] )
+        glob('C/SuiteSparse/CHOLMOD/Supernodal/c*.c') )
 
 amd = Extension('amd', 
     include_dirs = [ 'C/SuiteSparse/AMD/Include', 
         'C/SuiteSparse/UFconfig' ],
     define_macros = MACROS,
-    sources = [ 'C/amd.c' ] + [ 'C/SuiteSparse/AMD/Source/' + s for s in
-        listdir('C/SuiteSparse/AMD/Source') if s[-2:] == '.c' ])
+    sources = [ 'C/amd.c' ] + glob('C/SuiteSparse/AMD/Source/*.c') )
 
 misc_solvers = Extension('misc_solvers', libraries = ['lapack', 'blas'],
     library_dirs = [ ATLAS_LIB_DIR ],
@@ -157,7 +148,7 @@ extmods += [base, blas, lapack, umfpack, cholmod, amd, misc_solvers]
 
 setup (name = 'cvxopt', 
     description = 'Convex optimization package',
-    version = '1.1', 
+    version = '1.1.2', 
     long_description = '''
 CVXOPT is a free software package for convex optimization based on the 
 Python programming language. It can be used with the interactive Python 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/cvxopt.git



More information about the debian-science-commits mailing list