Module Nla.ZBlop


module ZBlop: sig  end
Complex double precision routines.


Matrices use two-dimensional Bigarray arrays internally. Unfortunately these are not powerful enough to serve as matrices because we cannot access arbitrary, but contiguous, sub-matrices, without a lot of trickery. Psilab got around this by changing the bigarray code. Unfortunately that change never made it into the main OCaml distribution. Rather than attempt to change the Bigarray implementation again I decided to wrap a new matrix type around the existing Bigarray implementation. This has some drawbacks. For one, element-by-element operations on matrix types could be slower than equivalent Bigarray operations, especially when functors prevent the OCaml compiler from inlining the access calls. However, this can be overcome by using the function matrix to efficiently convert native OCaml arrays to matrices, and performing all element by element operations on native OCaml arrays instead.


type t
The type t is either float in modules DBlop and SBlop, or Complex.t in modules ZBlop and CBlop.


type precision_elt
The internal type that is used to represent the elements of the matrix. It is float64_elt in DBlop, float32_elt in SBlop, complex64_elt in ZBlop and complex32_elt in CBlop.


type precision_elt_real
The internal type used for storing arrays of real numbers, like singular values, which are real even for complex matrices. It is float64_elt in modules DBlop and ZBlop, and float32_elt in modules SBlop and CBlop.

val precision : (t, precision_elt) Bigarray.kind
The mechanism for specifying the type of array you want from Bigarray. The usual usage is Array2.create precision fortran_layout m n.
val precision_real : (float, precision_elt_real) Bigarray.kind
Same as above except when you need a real array even inside a complex module.
val machine_epsilon : float
The machine precision. It is approximately 10^{-16} in the DBlop and ZBlop modules, and approximately 10^{-8} in the SBlop and CBlop modules.

The next few functions are generic arithmetic functions which should only be used in non-critical pieces of your code. They are meant to be used inside functors which are meant to work for both the real and complex modules at the same time. Much of my research work is implemented in this fashion and I have not had a problem.

val re : t -> float
re z returns the real part of the (possibly) complex number z.
val im : t -> float
im z returns the imaginary part of the (possibly) complex number z.
val conjugate : t -> t
conjugate z returns the complex conjugate of the (possibly) complex number z.
val zero : t
Either the real or complex zero.
val one : t
Either the real or complex one.
val minus_one : t
Either the real or complex minus one.
val fromInt : int -> t
fromInt n returns either the floating-point version of n or the Complex.t version of n.
val toInt : t -> int
toInt z returns the integer part of the real part of (possibly) complex number z.
val fromFloat : float -> t
Converts a floating point number to floating point number or Complex.t as the case may be.
val randn : unit -> t
randn () returns a random possibly complex number.
val printfn : t -> unit
Prints a possibly complex number to stdout.
val addn : t -> t -> t
Adds two possibly complex numbers.
val subn : t -> t -> t
Subtracts two possibly complex numebrs.
val muln : t -> t -> t
Multiplies two possibly complex numbers.
val mulr : float -> t -> t
mulr r z multiplies the possibly complex number z by the real number r.

With that we are done with generic arithmetic operators. Please note that t is not a union type. In any instance t is either float or Complex.t. For example inside module DBlop the type t always refers to float. Now, on to the matrix stuff.


type matrix
The basic data type. It is a wrapper for Array2.t.


type transformer = matrix -> unit
CamlFloat encourages a style of programming I call storage passing. Such a style is more useful in a pure language like Clean (see CleanFloat). However it continues to have its merits in OCaml. The basic idea is that we frequently need to modify the contents of a matrix. The type transformer encapsulates the most common type of such functions. Furthermore most algorithms can be implemented in a manner in which the destination matrix is the last argument. This enables one to make the code look like the mathematical specification of the algorithm (not the Matlab specification). See the tutorial.


type transform
Usually an object of type transform (not transformer) is a unitary matrix computed by a call to one of the unitary factorization routines: Nla.BLOP.ql' or Nla.BLOP.lq'. It can also be a product of such unitary transforms.


type factor
An object of type factor is usually the triangular part from a QL or LQ factorization. This type alone will save you from most of the bugs encountered when programming on top of Lapack.

val ($@) : Nla.BLOP.matrix -> int * int -> Nla.BLOP.t
a $@ (i,j) returns the (i,j)-th entry of the matrix a.
val (=>) : Nla.BLOP.t -> int * int -> Nla.BLOP.matrix -> unit
The weird syntax (x => (i,j)) a has the effect of making a $@ (i,j) be equal to x. This weird syntax is part of the storage passing style I talked about earler, and its use will become clear soon. Meanwhile, do not use these element-by-element operations in critical for loops. You might take a speed-hit.
val noOfRows : matrix -> int
Returns the number of rows in the matrix.
val noOfCols : matrix -> int
Returns the number of columns in the matrix.
val printMatrixHeight : int Pervasives.ref
Determine the number of rows in a matrix that will be printed by printMatrix.
val printMatrixWidth : int Pervasives.ref
Determines the number of columns of a matrix that will be printed by printMatrix.
val printMatrix : matrix -> unit
Prints a matrix to stdout.
val rawMatrix : int -> int -> matrix
rawMatrix m n creates an m by n matrix whose entries are uninitialized.
val consts : t -> int -> int -> matrix
consts x m n creates an m by n matrix with every entry set to x. See also const.
val const : t -> matrix -> unit
const x a sets every entry of the matrix a to x. See also consts.
val zeros : int -> int -> matrix
zeros m n creates a m by n zero matrix.
val ones : int -> int -> matrix
ones m n creates a m by n matrix of ones.
val randomMatrix : int -> int -> matrix
randomMatrix m n creates a m by n random matrix whose entries (real and imaginary parts) are uniformly distributed between -1.0 and 1.0.
val fun2mat : (int -> int -> t) -> int -> int -> matrix
fun2mat fn m n creates an m by n matrix whose (i,j)-th entry is fn i j. See also fun2mat'.
val fun2mat' : (int -> int -> t) -> matrix -> unit
fun2mat' fn a modifies all the entries of the matrix a such that the (i,j)-th entry becomes fn i j. See also fun2mat.
val eye : int -> int -> matrix
eye m n returns the top-left m by n submatrix of the max m n by max m n identity matrix.
val matrix : t array array -> matrix
Efficiently converts a standard two-dimensional OCaml array into a matrix. Element-by-element operations are better done on regular OCaml arrays.

type range =
| Range of int * int
| All
An intermediate data type for creating sub-matrices. See $.

val ($) : Nla.BLOP.matrix -> Nla.BLOP.range * Nla.BLOP.range -> Nla.BLOP.matrix
val (<->) : int -> int -> Nla.BLOP.range
Equivalent to Matlab's colon operator. a $ (sr <-> lr, sc <-> lc) returns the contiguous submatrix of a that includes rows sr to lr, and columns sc to lc. In Matlab you would have written this as a(sr:lr,sc:lc). If you write instead a $ (All, sc <-> lc) then this would be the submatrix of a that includes all the rows of a, and the columns from sc to lc. In Matlab this would have been a(::,sc:lc). However, there is one big difference from Matlab. a $ (sr <-> lr, sc <-> lc) and a share the same storage! Please be careful. The type system will not keep track of this sharing for you. However, in CleanFloat the uniqueness type attribute will keep track of sharing.
val partition2x1 : int -> int -> matrix -> matrix * matrix
In CamlFloat I strongly discourage you from programming as if you were in Matlab. Rather I strongly encourage you to program as if you were specifying the algorithm in standard mathematical notation. For example, matrix block partitioning is one of the key concepts in matrix analysis. However, in Matlab this can only be achieved by specifying multiple sub-matrices, all of which will be copied out. However, in CamlFloat the call partition2x1 m1 m2 a will return the tuple (a1, a2), where, in Matlab notation, a1 is equal to a(1:m1,::) and a2 is equal to a(m1+1:m1+m2,::). Note the index arithmetic that you must perform correctly in Matlab. Furthermore, note that in CamlFloat a1 and a2 share their storage with a, unlike Matlab.
val partition1x2 : int -> int -> matrix -> matrix * matrix
partition1x2 n1 n2 a returns the tuple (a1,a2) obtained by column partitioning a, with first block column a1 having the first n1 columns, and the second block column a2 having the last n2 columns. Note that a1 and a2 share storage with a.
val partition2x2 : int ->
int ->
int ->
int ->
matrix ->
matrix * matrix * matrix * matrix
partition2x2 n1 n2 m1 m2 a returns the tuple (a11, a12, a21, a22) obtained by block partitioning a into a 2 by 2 matrix, with n1 columns in the first column partition and m1 rows in the first row partition. I usually format the call as follows
 partition2x2 n1 n2
           m1
           m2     a
    
so that it looks more like the mathematical notation.
val partition1x3 : int ->
int ->
int -> matrix -> matrix * matrix * matrix
partition1x3 n1 n2 n3 a returns (a1,a2,a3) obtained by doing a 1 by 3 block column partition of a.
val partition3x1 : int ->
int ->
int -> matrix -> matrix * matrix * matrix
partition3x1 m1 m2 m3 a returns (a1,a2,a3) obtained by doing a 3 by 1 block row partition of a.
val partition3x3 : int ->
int ->
int ->
int ->
int ->
int ->
matrix ->
matrix * matrix * matrix * matrix *
matrix * matrix * matrix * matrix *
matrix
partition3x3 n1 n2 n3 m1 m2 m3 a returns (a11,a12,a13,a21,a22,a23,a31,a32,a33) obtained by doing a 3 by 3 block partitioning of a. I usually format the call as
 partition3x3 n1 n2 n3
           m1
           m2
           m3        a
    
so that it looks more like the mathematical notation.

Sometimes we cannot predict the order of the block partitions. To aid in this situation we have the following functions.

val partitionInfx1 : int list -> matrix -> matrix list
partitionInfx1 ms a returns a list of block row partitions of a, where the number of rows in the i-th partition is determined by the number in the i-th position in the list ms.
val partition1xInf : int list -> matrix -> matrix list
partition1xInf ns a returns a list of block column partitions of a, where the number of columns in the j-th partition is determined by the number in the j-th position in the list ns.
val partitionNx1 : int array -> matrix -> matrix array
partitionNx1 ms a is identical to partitionInfx1 ms a, except tha ms must be an array now.
val partition1xN : int array -> matrix -> matrix array
partition1xN ns a is identical to partition1xInf ns a, except that ns must be an array now.

We now present a set of functions that are most useful in the storage-passing style of programming.

val ooo : matrix -> unit
The function ooo is a nop. Very useful for subsequent functions.
val matrix2x1 : int ->
transformer ->
int -> transformer -> matrix -> unit
matrix2x1 m1 a1 m2 a2 a modifies the entries of the matrix a, by applying the function (transformer) a1 to a $ (1<-> m1, All) and the transformer a2 to a $ (m1+1 <-> m1+m1, All). I usually format the call as
matrix2x1 m1 a1
          m2 a2 a
   
so that it looks more like the mathematical notation. If you use a higher-order style of programming you can even drop the last argument, the destination matrix a, from the call, and make it look even more like the mathematical notation. See the tutorial for a good example of this style. Again observe how this call saves you from index gymnastics.
val matrix3x1 : int ->
transformer ->
int ->
transformer ->
int -> transformer -> matrix -> unit
matrix3x1 m1 a1 m2 a2 m3 a3 a modifies the entries of a by first applying the transformer a1 to the first block row of the 3 by 1 block row partitioning of a, then applying the transformer a2 to the second block row partition of a, and so on. I usually format the call a bit more suggestively as
 matrix3x1 m1 a1
           m2 a2
           m3 a3 a
    
so that it looks more like the mathematical notation.
val matrix1x2 : int ->
int ->
transformer -> transformer -> matrix -> unit
matrix1x2 n1 n2 a1 a2 a modifies the entries of a by applying the two transformers a1 and a2 to the two block column partitions of a. Please observe that matrix1x2 has a very different type from matrix2x1. This is so that I can format the call as
 matrix1x2 n1 n2
           a1 a2 a
    
so that it looks more like the mathematical notation.
val matrix1x3 : int ->
int ->
int ->
transformer ->
transformer -> transformer -> matrix -> unit
matrix1x3 n1 n2 n3 a1 a2 a3 a modifies the entries of the matrix a by applying the transformers a1, a2 and a3 to the corresponding block column partitions of a. Note that matrix1x3 has a different type from matrix3x1. This is so that I can format the call as
 matrix1x3 n1 n2 n3
           a1 a2 a3 a
    
so that it looks more like the mathematical notation.
val matrix2x2 : int ->
int ->
int ->
transformer ->
transformer ->
int ->
transformer -> transformer -> matrix -> unit
matrix2x2 n1 n2 m1 a11 a12 m2 a21 a22 a modifies the entries of the matrix a by applying the transformers a11, a12, a21 and a22 to the corresponding sub-matrices of a obtained by a block 2 by 2 partitioning. I usually format the call as
 matrix2x2 n1  n2
        m1 a11 a12
        m2 a21 a22 a
    
so that it looks more like the mathematical notation.
val matrix2x3 : int ->
int ->
int ->
int ->
transformer ->
transformer ->
transformer ->
int ->
transformer ->
transformer -> transformer -> matrix -> unit
matrix2x3 n1 n2 n3 m1 a11 a12 a13 m2 a21 a22 a23 a modifies the entries of the matrix a by applying the transformers a11, a12, a13, a21, a22 and a23 to the corresponding sub-matrices of a obtained by a block 2 by 3 partitioning. I usually format the call as
 matrix2x3 n1  n2  n3
        m1 a11 a12 a13
        m2 a21 a22 a23 a
    
so that it looks more like the mathematical notation.
val matrix4x2 : int ->
int ->
int ->
transformer ->
transformer ->
int ->
transformer ->
transformer ->
int ->
transformer ->
transformer ->
int ->
transformer -> transformer -> matrix -> unit
matrix4x2 n1 n2 m1 a11 a12 m2 a21 a22 m3 a31 a32 m4 a41 a42 a modifies the entries of the matrix a by applying the transformers aij to the corresponding sub-matrices of a obtained by a block 4 by 2 partitioning. I usually format the call as
 matrix4x2 n1  n2
        m1 a11 a12
        m2 a21 a22
        m3 a31 a32
        m4 a41 a42 a
    
so that it looks more like the mathematical notation.
val matrixInfx1 : int list -> transformer list -> matrix -> unit
matrixInfx1 ms ais a applies the transformers in the list ais to the corresponding row partitions of a as determined by the block sizes in the list ms.
val copy : matrix -> matrix
Since the $ operator produces sub-matrices that share storage with the parent matrix, we need a way to make copies of matrices. copy a produces a copy of the matrix a such that they do not share storage.
val iD : matrix -> matrix -> unit
iD a b replaces the contents of the matrix b with that of a.
val ($=>) : Nla.BLOP.matrix -> Nla.BLOP.range * Nla.BLOP.range -> Nla.BLOP.matrix -> unit
(a $=> (sr<->lr,sc<->lc)) b will replace the contents of b $ (sr<->lc,sc<->lc) with that of a.
val (<-|) : Nla.BLOP.matrix -> Nla.BLOP.transformer -> unit
People who do not like to write the destination storage on the right-hand side, need this operator <-|. Therefore instead of iD a b you can say b <-| (iD a). This is not needed, however, if you use the matrixXxY functions.
val (<-$) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
People who do not like to write (a $=> (sr<->lr,All)) b can now write (b $ (sr<->lr,All)) <-$ a instead. In other words, if you don't like my notation, define your own! After all this is OCaml.

We will now specify the basic matrix arithmetic operators. You will find the Matlab equivalents here. However it is probably more important to realize that you can find the BLAS3 equivalents here too. I have tried to wrap the BLAS3 calls to facilitate the storage-passing style. That is the destination matrix is always the last argument, so by currying these operators you can embed them inside matrix2x2 for example. Some of the operator notation might take some getting used to. I find them logical and convenient. If you disagree just define your own notation.

val (|+|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |+| b) c will replace the contents of c with that of a + b.
val (|-|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |-| b) c will replace the contents of c with that of a - b.
val (|++|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
a |++| b will replace the contents of b with that of a + b.
val (|--|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
a |--| b will replace the contents of b with that of b - a.
val (+$) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix
a +$ b returns a new matrix whose entries are those of a + b.
val (-$) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix
a -$ b returns a new matrix whose entries are those of a - b.
val transp : matrix -> matrix
transp a returns a new matrix formed by conjugate-transposing a.
val transp' : matrix -> matrix -> unit
transp' a b replaces the contents of b with the conjugate-transpose of a.
val conjg' : matrix -> unit
conjg' a replaces the entries of a by their conjugates.
val (|*|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |*| b) c will replace the contents of c with that of a * b.
val (|*~|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |*~| b) c will replace the contents of c with that of a *$ transp b. Note that we use ~ to denote transposition and that it is attached to the operator rather than the argument.
val (|~*|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |~*| b) c will replace the contents of c with that of transp a *$ b. Note that we use ~ to denote transposition and that it is attached to the operator rather than the argument. Also note that the position of ~ tells you to which argument the transpose is attached.
val (*$) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix
a *$ b will create a new matrix with the contents of a * b.
val (*~$) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix
a *~$ b will create a new matrix with the contents of transp a *$ b.
val (*$~) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix
a *$~ b will create a new matrix with the contents of a *$ transp b.
val (|*++|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |*++| b) c will replace the contents of c with that of c + a * b.
val (|*--|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |*--| b) c will replace the contents of c with that of c - a * b.
val (|*~++|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |*~++| b) c will replace the contents of c with that of c + a * transp b.
val (|*~--|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |*~--| b) c will replace the contents of c with that of a * b.
val (|~*++|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |~*++| b) c will replace the contents of c with that of c + transp a * b.
val (|~*--|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
(a |~*--| b) c will replace the contents of c with that of c - transp a * b.
val norm1 : matrix -> float
norm1 a returns the 1-norm of a.
val normInf : matrix -> float
normInf a returns the infinity-norm of a.
val normF : matrix -> float
normF a returns the Frobenius-norm of a.
val normMax : matrix -> float
normMax a returns the largest entry of a in magnitude.

We now move on to the Lapack routines. Currently this mainly includes interfaces to the orthogonal factorization and (non-square) linear system solver routines. As need arises more can be added. Let me know.

val lq' : matrix -> factor * transform
lq' a computes the LQ factorization of a. Note that a is destroyed and its internal storage re-used for the returned l and q. Any extant sub-matrices of a will be rendered useless. You have been warned.
val ql' : matrix -> transform * factor
ql' a computes the QL factorization of a. The contents of a are destroyed and its storage is used to hold a and l.
val copyL : factor -> matrix
Given an L factor l computed from ql' or lq', copyL l returns a lower-triangular (or lower-trapezoidal) matrix that is equivalent to l. Many bugs in the usage of Lapack can be traced to this one operation.
val iDL : factor -> matrix -> unit
Given an l factor computed using ql' or lq', iDL l a copies the lower-trianglar (or lower-trapezoidal) part of l into a.
val (@*) : Nla.BLOP.transform -> Nla.BLOP.matrix -> unit
q @* a applies a transform q to the matrix a changing its contents.
val (@~*) : Nla.BLOP.transform -> Nla.BLOP.matrix -> unit
q @~* a applies the conjugate-transpose of the transform q to the matrix a, changing its contents. Note again that the transpose symbol ~ is attached to the operator rather than the argument. In any operation involving transforms the transpose symbol is always attached to the transform, not the matrix argument. This is not a short-coming.
val (*@) : Nla.BLOP.matrix -> Nla.BLOP.transform -> unit
a *@ q applies the transform q to the matrix a from the right, changing its contents.
val (*~@) : Nla.BLOP.matrix -> Nla.BLOP.transform -> unit
a *~@ q applies the conjugate-transpose of the transform q to the matrix a from the right, changing its contents.
val subs' : factor -> matrix -> unit
subs' l b replaces the contents of the matrix b by l-1b. It assumes that l is a square lower-triangular matrix. That is, if l is lower-trapezoidal you will get a run-time error.
val subsT' : factor -> matrix -> unit
subsT' l b replaces the contents of the matrix b with that of (transpose l)-1b. It assumes that l is a square lower-triangular factor. Otherwise you will get a run-tim error.
val (|/|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
a |/| b replaces the contents of the matrix b by the contents of the minimum-norm least-squares solution of the system of linear equations ax = b. In the process the contents of the matrix a are also destroyed. If a is a fat m by n (m < n) matrix, then the matrix b must have n rows, and initially the actual contents of the right-hand side must lie in the first m rows. On the other hand, if a is a skinny m by n (m > n) matrix, then the least-squares solution will be found in the first n rows of b after the call returns.
val (|~/|) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> unit
The same semantics and restrictions as |/|, except that the system being solved now is (transp a)x=b.
val (/$) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix
a /$ b returns a new matrix obtained by applying the pseudo-inverse of a to b.
val (/~$) : Nla.BLOP.matrix -> Nla.BLOP.matrix -> Nla.BLOP.matrix
a /~$ b returns a new matrix obtained by applying the pseudo-inverse of the conjugate-transpose of a to b.
val scale' : t -> matrix -> unit
scale' x a multiplies every entry of a in place by x.
val rowScale' : (t, precision_elt, Bigarray.fortran_layout)
Bigarray.Array1.t -> matrix -> unit
rowScale' x a scales every row of a in place by the corresponding entry in x.
val colScale' : matrix ->
(t, precision_elt, Bigarray.fortran_layout)
Bigarray.Array1.t -> unit
colScale' a x scales every column of a in place by the corresponding entry in x.
val scale_real' : float -> matrix -> unit
Same as scale' except that first argument must be a real number.
val rowScale_real' : (float, precision_elt_real, Bigarray.fortran_layout)
Bigarray.Array1.t -> matrix -> unit
Same as rowScale' except that the first argument must be a real array. Useful for SVDs of complex matrices.
val colScale_real' : matrix ->
(float, precision_elt_real, Bigarray.fortran_layout)
Bigarray.Array1.t -> unit
Same as colScale' except that the second argument must be a real array. Useful for SVDs of complex matrices.
val svd' : matrix ->
matrix *
(float, precision_elt_real, Bigarray.fortran_layout)
Bigarray.Array1.t * matrix
svd' a returns the economy SVD of a, destroying its contents in the process.
val svdL' : matrix ->
matrix *
(float, precision_elt_real, Bigarray.fortran_layout)
Bigarray.Array1.t
svdL' a is identical svd' a except that the right singular vectors are not calculated.
val svdR' : matrix ->
(float, precision_elt_real, Bigarray.fortran_layout)
Bigarray.Array1.t * matrix
svdR' a is identical to svd' a except that the left singular vectors are not calculated.
val singValues' : matrix ->
(float, precision_elt_real, Bigarray.fortran_layout)
Bigarray.Array1.t
singValues' a is identical to svd' a except that the none of the singular vectors are computed.
val cond : matrix -> float
cond a returns the 2-norm condition number of the matrix a.