Home

Awesome

Lacaml - Linear Algebra for OCaml

Overview

Lacaml is an OCaml library that interfaces with two popular FORTRAN libraries, enabling developers to create high-performance numerical applications requiring linear algebra. Ideal for researchers, engineers, and developers working on scientific computing and data analysis.

Features

Usage

To use Lacaml, open the appropriate module for the desired precision and number type:

open Lacaml.S  (* Single-precision real numbers *)
open Lacaml.D  (* Double-precision real numbers *)
open Lacaml.C  (* Single-precision complex numbers *)
open Lacaml.Z  (* Double-precision complex numbers *)

Link the lacaml library with your application. If not using findlib, also link the bigarray library.

The Lacaml.? modules offer the BLAS/LAPACK interface, with Vec and Mat submodules for vector and matrix operations.

Functions use optional arguments with defaults. For example:

let rank = gelss in_mat out_mat in
(* `gelss` solves linear least squares problems *)
...

To optimize, create work arrays outside loops:

let work = gelss_min_work ~m ~n ~nrhs in
for i = 1 to 1000 do
  let rank = gelss in_mat ~work out_mat in
  ...
done

Access submatrices by specifying parameters like ar and ac for row and column offsets, and m and n for the submatrix dimensions.

Printing

To print large matrices in the OCaml toplevel, you can use Lacaml's printing functions. Here's an example with a large random matrix:

# #require "lacaml";;
# open Lacaml.D;;
# let mat = Mat.random 100 200;;
val mat : Lacaml.D.mat =
              C1        C2        C3          C198       C199      C200
    R1 -0.314362 -0.530711  0.309887 ...  0.519965  -0.230156 0.0479154
    R2  0.835658  0.581404  0.161607 ... -0.749358  -0.630019 -0.858998
    R3 -0.403421  0.458116 -0.497516 ...  0.210811   0.422094  0.589661
             ...       ...       ... ...       ...        ...       ...
   R98 -0.352474  0.878897  0.357842 ...  0.150786   -0.74011  0.353253
   R99  0.104805  0.984924 -0.319127 ... -0.143679  -0.858269  0.859059
  R100  0.419968  0.333358  0.237761 ... -0.483535 -0.0224016  0.513944

The output displays the corners of the matrix, with ellipses (...) for omitted parts. To reduce context further, use Lacaml.Io.Toplevel.lsc to specify the number of rows and columns to display:

# lsc 2;;
- : unit = ()
# mat;;
- : Lacaml.D.mat =
            C1        C2           C199      C200
  R1 -0.314362 -0.530711 ...  -0.230156 0.0479154
  R2  0.835658  0.581404 ...  -0.630019 -0.858998
           ...       ... ...        ...       ...
 R99  0.104805  0.984924 ...  -0.858269  0.859059
R100  0.419968  0.333358 ... -0.0224016  0.513944

For custom output, use the Format module with Lacaml's printing functions. Here's an example with labels and custom settings:

open Lacaml.D
open Lacaml.Io

let () =
  let rows, cols = (200, 100) in
  let a = Mat.random rows cols in
  Format.printf "@[<2>This is an indented random matrix:@\n@\n%a@]@."
    (Lacaml.Io.pp_lfmat
       ~row_labels:(Array.init rows (fun i -> Printf.sprintf "Row %d" (i + 1)))
       ~col_labels:(Array.init cols (fun i -> Printf.sprintf "Col %d" (i + 1)))
       ~vertical_context:(Some (Context.create 2))
       ~horizontal_context:(Some (Context.create 3))
       ~ellipsis:"*" ~print_right:false ~print_foot:false ())
    a

This code might produce:

This is an indented random matrix:

              Col 1     Col 2       Col 3      Col 98    Col 99   Col 100
    Row 1  0.852078 -0.316723    0.195646 *  0.513697  0.656419  0.545189
    Row 2 -0.606197  0.411059    0.158064 * -0.368989    0.2174    0.9001
                  *         *           * *         *         *         *
  Row 199 -0.684374 -0.939027 0.000699582 *  0.117598 -0.285587 -0.654935
  Row 200  0.929341 -0.823264    0.895798 *  0.198334  0.725029 -0.621723

Lacaml provides options for customizing output, such as padding, number formats, and precision.

Error Handling

Lacaml extensively checks arguments to ensure consistency with BLAS/LAPACK but does not verify the contents of vectors and matrices. Checking for NaNs, infinities, or subnormal numbers in every matrix on each call is computationally expensive. Furthermore, some functions require matrices with specific properties, like positive-definiteness, which are costly to verify.

BLAS/LAPACK may inconsistently handle degenerate shapes, such as empty matrices or zero-sized operations. Detecting all corner cases and providing workarounds is challenging.

Users should ensure that data passed to Lacaml functions is valid and avoid using values with degenerate dimensions. User code should raise exceptions for suspicious values or explicitly handle unusual cases.

Supplementary Resources

API Documentation

The Lacaml API documentation is available both in the interface file and online.

BLAS/LAPACK Man Pages

Unix systems typically include man pages for BLAS/LAPACK. For example, to learn about factorizing a positive-definite, complex, single-precision matrix, use:

man cpotrf

In Lacaml, this corresponds to Lacaml.C.potrf. Further naming conventions and documentation are available on the BLAS/LAPACK websites.

Examples

The examples directory contains demonstrations for linear algebra problems using Lacaml.

Performance Optimization

For optimal performance, install a BLAS variant optimized for your system. Processor vendors, such as Intel, offer highly optimized implementations. Apple includes vecLib in its Accelerate framework.

ATLAS is another efficient BLAS substitute, tailored to the architecture it compiles on. Linux users can find binary packages from their distribution vendors, but recompilation may be necessary for optimal performance.

OpenBLAS is another alternative.

To use a non-standard library or location, set these environment variables:

For CPU-specific optimization, use -march=native. In cloud environments, be cautious as VM changes might affect the CPU. The -ffast-math option can improve performance by allowing aggressive optimizations, but it may alter standard floating-point behavior, potentially affecting numerical accuracy and compliance with IEEE standards. Use with caution in applications requiring precise numerical results. Generally, -O3 enhances performance, and Lacaml should perform well with these settings, potentially utilizing SIMD instructions.

Contact Information and Contributing

Report bugs, request features, or contribute via the GitHub issue tracker.

For the latest information, visit: https://mmottl.github.io/lacaml