\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 \module{cvxopt.base} 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}
