# QDLDL
A free LDL factorisation routine for quasi-definite linear systems: `Ax=b`

[![Build Status](https://travis-ci.org/oxfordcontrol/qdldl.svg?branch=master)](https://travis-ci.org/oxfordcontrol/qdldl)
[![Build status](https://ci.appveyor.com/api/projects/status/ns4br7v6y3i5stai/branch/master?svg=true)](https://ci.appveyor.com/project/bstellato/qdldl-8q1mv/branch/master)
[![Coverage Status](https://coveralls.io/repos/github/oxfordcontrol/qdldl/badge.svg)](https://coveralls.io/github/oxfordcontrol/qdldl)


## Getting started
To start using QDLDL, first clone the repository

```bash
git clone https://github.com/oxfordcontrol/qdldl.git
```

### Build

To build QDLDL, you need to install [cmake](https://cmake.org/) and run

```bash
mkdir build
cd build
cmake ..
cmake --build .
```

This will generate an `out/` folder with contents:

- `qdldl_example`: a **code example** from [`examples/c/example.c`](./examples/c/example.c)
- `libqdldl`: a static and a dynamic versions of the library.

You can include an addition option `-DUNITTESTS=ON` when calling `cmake`, which will result in an additional executable `qdldl_tester` being built in the `out/` folder to test QDLDL on a variety of problems, including those with rank deficient or otherwise ill-formatted inputs.

**N.B.** All files will have file extensions appropriate to your operating system.


### Install/Uninstall

To install (uninstall) the libraries and headers you can simply run `make install` (`make uninstall`) after running the `cmake` command above.


## Calling QDLDL

### Main API

The QDLDL API consists of 5 functions documented in [`include/qdldl.h`](./include/qdldl.h).
For more details and a working example see [`examples/c/example.c`](./examples/c/example.c).

**N.B.** There is **no memory allocation** performed in these routines. The user is assumed to have the working vectors already allocated.

Here is a brief summary.

* `QDLDL_etree`: compute the elimination tree for the quasidefinite matrix factorization `A = LDL'`
* `QDLDL_factor`: return the factors `L`, `D` and `Dinv = 1./D`
* `QDLDL_solve`: solves the linear system `LDL'x = b`
* `QDLDL_Lsolve`: solves `Lx = b`
* `QDLDL_Ltsolve`: solves `L'x = b`

In the above function calls the matrices `A` and `L` are stored in compressed sparse column (CSC) format.   The matrix `A` is assumed to be symmetric and only the upper triangular portion of A should be passed to the API.   The factor `L` is lower triangular with implicit ones on the diagonal (i.e. the diagonal of L is not stored as part of the CSC formatted data.)

The matrices `D` and `Dinv` are both diagonal matrices, with the diagonal values stored in an array.

The matrix input `A` should be quasidefinite.   The API provides some (non-comprehensive) error checking to protect against non-quasidefinite or non-upper triangular inputs.

### Custom types for integer, floats and booleans
QDLDL uses its own internal types for integers, floats and booleans (`QDLDL_int, QDLDL_float, QDLDL_bool`. They can be specified using the cmake options:

- `DFLOAT` (default false): uses float numbers instead of doubles
- `DLONG` (default true): uses long integers for indexing (for large matrices)

The `QDLDL_bool` is internally defined as `unsigned char`.


## Linking QDLDL

### Basic Example
A basic example appears in [`examples/c/example.c`](./examples/c/example.c) and is compiled using cmake and the `CMakeLists.txt` file in the root folder.


### Including in a cmake project

You can include QDLDL in a cmake project `foo` by adding the subdirectory as
```
# Add project
add_subdirectory(qdldl)
```

QDLDL can be linked using a static or dynamic linker
```
# Link static library
target_link_libraries (foo qdldlstatic)

# Link shared library
target_link_libraries (foo qdldl)
```
for dynamic linking the shared library should be available in your path.

There is also the option to include QDLDL as an object library in your project.
The current `CMakeLists.txt` file creates an object library called `qdldlobject`.
This can be added to your project by adding it after your sources.
For example, when creating a library `foo` you can add

```
add_library(foo foo.c foo.h $<TARGET_OBJECTS:qdldlobject>)
```
for more details see the [cmake documentation](https://cmake.org/cmake/help/latest/command/add_library.html#object-libraries).


## The algorithm

The algorithm is an independent implementation of the elimination tree and factorisation procedures outlined in

> T. A Davis. [Algorithm 849: a concise sparse cholesky factorization package](https://dl.acm.org/citation.cfm?id=1114277). ACM Trans. Math. Softw., 31(4):587–591, 2005.


## Credits

- [Paul Goulart](http://users.ox.ac.uk/~engs1373/): main development
- [Bartolomeo Stellato](https://stellato.io/): code refactoring and testing
- [Goran Banjac](http://control.ee.ethz.ch/~gbanjac/)
