-
Notifications
You must be signed in to change notification settings - Fork 124
Tutorial: Basic Data Types
Array and Matrix are the building block of Owl library. Obviously, matrix is a special case of n-dimensional array, and in fact many functions in Matrix module calls the functions in Ndarray directly.
For both n-dimensional array and matrix, Owl supports: both dense and sparse data structures; both single and double precisions; both real and complex number. Therefore, there are 16 basic data types which we will introduce in this short tutorial.
In the following examples, I suppose you already loaded Owl
library with #require "owl"
, and opened Owl
module with open Owl
in utop
. If you don't have Owl
installed locally, you can still try the examples by pulling a ready-made docker images of the latest Owl
with the following commands.
docker pull ryanrhymes/owl
docker run -t -i ryanrhymes/owl
OK, let's start.
In Owl, Dense
module contains the modules of dense data structures. For example, Dense.Matrix
supports the operations of dense matrices. Similarly, Sparse
module contains the modules of sparse data structures.
Dense.Ndarray (* dense ndarray *)
Dense.Matrix (* dense matrix *)
Sparse.Ndarray (* sparse ndarray *)
Sparse.Matrix (* sparse ndarray *)
With Dense.Ndarray
, you can create a dense n-dimensional array of no more than 16 dimensions. This constraint originates from the underlying Bigarray.Genarray
module. In practice, this constraint makes sense since the space requirement will explode as the dimension increases. If you need anything higher than 16 dimensions, you need to use Sparse.Ndarray
to create a sparse data structure.
After deciding the suitable data structure (either dense or sparse), you can create a ndarray/matrix using creation function in the modules: e.g., empty
, create
, zeros
, ones
... The type of numbers (real or complex) and its precision (single or double) needs to be passed to the creations functions as the parameters.
Herein, we use creation fucntion zeros
as an example. With zeros
function, all the elements in the created data structure will be initialised to zeros.
The following examples are for dense ndarrays.
Dense.Ndarray.zeros float32 [|5;5|];; (* single precision real ndarray *)
Dense.Ndarray.zeros float64 [|5;5|];; (* double precision real ndarray *)
Dense.Ndarray.zeros complex32 [|5;5|];; (* single precision complex ndarray *)
Dense.Ndarray.zeros complex64 [|5;5|];; (* double precision complex ndarray *)
The following examples are for dense matrices.
Dense.Matrix.zeros float32 5 5;; (* single precision real matrix *)
Dense.Matrix.zeros float64 5 5;; (* double precision real matrix *)
Dense.Matrix.zeros complex32 5 5;; (* single precision complex matrix *)
Dense.Matrix.zeros complex64 5 5;; (* double precision complex matrix *)
The following examples are for sparse ndarrays.
Sparse.Ndarray.zeros float32 [|5;5|];; (* single precision real ndarray *)
Sparse.Ndarray.zeros float64 [|5;5|];; (* double precision real ndarray *)
Sparse.Ndarray.zeros complex32 [|5;5|];; (* single precision complex ndarray *)
Sparse.Ndarray.zeros complex64 [|5;5|];; (* double precision complex ndarray *)
The following examples are for sparse matrices.
Sparse.Matrix.zeros float32 5 5;; (* single precision real matrix *)
Sparse.Matrix.zeros float64 5 5;; (* double precision real matrix *)
Sparse.Matrix.zeros complex32 5 5;; (* single precision complex matrix *)
Sparse.Matrix.zeros complex64 5 5;; (* double precision complex matrix *)
Even through you can create four different types of data structure with one module (using different precision and number types), it does not mean you need different functions to process them in Owl. Polymorphism is achieved by pattern matching and GADT.
Herein I use the sum
function in Dense.Matrix
module as an example. sum
function returns the summation of all the elements in a matrix.
let x = Dense.Matrix.eye float32 5 in Dense.Matrix.sum x;;
let x = Dense.Matrix.eye float64 5 in Dense.Matrix.sum x;;
let x = Dense.Matrix.eye complex32 5 in Dense.Matrix.sum x;;
let x = Dense.Matrix.eye complex64 5 in Dense.Matrix.sum x;;
As we can see, no matter what kind of numbers are held in an identity matrix, we always pass it to Dense.Matrix.sum
functions. Similarly, we can do the same thing for other modules (Dense.Ndarray
, Sparse.Matrix
, and etc.) and other functions (add
, mul
, neg
, and etc.).
However, always passing type information into creation function may turn out to be a pain for some people. In reality, we often work with double precision numbers on most platforms nowadays. Therefore, Owl provides some shortcuts to double precision matrices:
-
Dense.Real
is equivalent to double precision realDense.Matrix
; -
Dense.Complex
is equivalent to double precision complexDense.Matrix
; -
Sparse.Real
is equivalent to double precision realSparse.Matrix
; -
Sparse.Complex
is equivalent to double precision complexSparse.Matrix
.
With these shortcut modules, you are no longer required to pass in type information (e.g., in creation functions). Here are some examples as below.
Dense.Real.zeros 5 5;; (* same as Dense.Matrix.zeros Float64 5 5 *)
Dense.Complex.zeros 5 5;; (* same as Dense.Matrix.zeros Complex64 5 5 *)
Sparse.Real.eye 5;; (* same as Sparse.Matrix.eye Float64 5 5 *)
Sparse.Complex.eye 5;; (* same as Sparse.Matrix.eye Complex64 5 5 *)
...
More examples besides creation functions are as follows.
Dense.Real.load "data.mat";; (* same as Dense.Matrix.load "data.mat" *)
Dense.Real.of_arrays 5 5 x;; (* same as Dense.Matrix.of_arrays Float64 5 5 x *)
Dense.Real.linspace 0. 9. 10;; (* same as Dense.Matrix.linspace Float64 0. 9. 10 *)
...
In general, it is recommended to use these shortcut modules to operate matrices unless you really want to control the precision by yourself.
To know more about the functions provided in each module, please read the corresponding interface file.
-
Dense.Ndarray
: owl_dense_ndarray -
Dense.Matrix
: owl_dense_matrix -
Dense.Real
: owl_dense_real -
Dense.Complex
: owl_dense_complex -
Sparse.Ndarray
: owl_sparse_ndarray -
Sparse.Matrix
: owl_sparse_matrix -
Sparse.Real
: owl_sparse_real -
Sparse.Complex
: owl_sparse_complex
Enjoy Owl! Happy hacking!