Hermitian Matrix
Introduction
The Hermitian matrix is a square matrix with complex entries, which is equal to its own conjugate transpose. This matrix has many applications in physics, engineering, and signal processing, particularly in quantum mechanics. This algorithm implements the Hermitian of a given square matrix.
Implementation
(* Hermitian Matrix *)
let hermitian ?(upper = true) x =
let m, n = shape x in
Owl_exception.(check (m = n) (NOT_SQUARE [ m; n ]));
let y = copy x in
let _y = flatten y > Bigarray.array1_of_genarray in
let _conj_op = _owl_conj (kind x) in
let ofs = ref 0 in
let incx, incy =
match upper with
 true > 1, m
 false > m, 1
in
for i = 0 to m  1 do
(* copy and conjugate *)
_conj_op (m  i) ~ofsx:!ofs ~incx ~ofsy:!ofs ~incy y y;
(* set the imaginary part to zero by default. *)
let a = _y.{!ofs} in
_y.{!ofs} < Complex.{ re = a.re; im = 0. };
ofs := !ofs + n + 1
done;
(* return the symmetric matrix *)
y
The function hermitian
implements the Hermitian of a given matrix. It takes an optional argument upper
with a default value true
, which specifies whether the Hermitian matrix should be an upper or lower triangular matrix. If upper
is true, then the upper triangular part of the matrix is computed, and if it is false, then the lower triangular part is computed. The function returns the Hermitian matrix.
Stepbystep Explanation
The hermitian
function works as follows:

It first gets the dimensions of the input matrix
x
using theshape
function and checks if it is a square matrix. If it is not a square matrix, then it raises an exception. 
It then makes a copy of the input matrix
x
and creates a flat vector_y
from the copy using theflatten
function andBigarray.array1_of_genarray
function. 
It defines a new function
_conj_op
that takes an element in_y
and returns its conjugate using theconj
function. It uses this operator to conjugate the matrix elements. 
It initializes the
ofs
variable to 0, which is initially the offset of the vector_y
. 
It defines the
incx
andincy
variables based on theupper
argument. Ifupper
is true, thenincx
is 1, andincy
is equal to the number of rows in the matrix. Ifupper
is false, thenincx
is equal to the number of rows in the matrix, andincy
is 1. 
It then starts a loop from 0 to the number of rows in the matrix minus 1.

In each iteration, it first conjugates the remaining part of the matrix using the
_conj_op
function and sets the imaginary part of the conjugation to zero by default. This step produces the Hermitian of the matrix. 
It then updates the offset
ofs
based on the value ofincx
andincy
. 
After the loop, it returns the Hermitian matrix.
Complexity Analysis
The time complexity of the hermitian
function depends on the size of the input matrix. If the input matrix has dimensions n
by n
, the forloop runs n
times. The inner for
loop does ni
conjugations and each conjugation operation is O(1). Therefore, the time complexity is O(n^3), which is the same as the complexity of matrix multiplication. The space complexity is O(n^2), which is due to the copy of the input matrix, and the flat vector _y
.