(* gsl-ocaml - OCaml interface to GSL                       *)
(* Copyright (©) 2002-2012 - Olivier Andrieu                *)
(* Distributed under the terms of the GPL version 3         *)


let () = Error.init ()

type order = Blas.order =
  | RowMajor
  | ColMajor

type transpose = Blas.transpose =
  | NoTrans
  | Trans
  | ConjTrans

type uplo = Blas.uplo =
  | Upper
  | Lower

type diag = Blas.diag =
  | NonUnit
  | Unit

type side = Blas.side =
  | Left
  | Right


open Vectmat


(* LEVEL 1 *)
external dot : [< vec] -> [< vec] -> float = "ml_gsl_blas_ddot"
external nrm2 : [< vec] -> float = "ml_gsl_blas_dnrm2"
external asum : [< vec] -> float = "ml_gsl_blas_dasum"
external iamax : [< vec] -> int = "ml_gsl_blas_idamax"
external swap : [< vec] -> [< vec] -> unit = "ml_gsl_blas_dswap"
external copy : [< vec] -> [< vec] -> unit = "ml_gsl_blas_dcopy"
external axpy : float -> [< vec] -> [< vec] -> unit = "ml_gsl_blas_daxpy"
external rot : [< vec] -> [< vec] -> float -> float -> unit = "ml_gsl_blas_drot"
external scal : float -> [< vec] -> unit = "ml_gsl_blas_dscal"


(* LEVEL 2 *)
external gemv : transpose -> alpha:float -> a:[< mat] -> 
  x:[< vec] -> beta:float -> y:[< vec] -> unit
      = "ml_gsl_blas_dgemv_bc" "ml_gsl_blas_dgemv"
external trmv : uplo -> transpose -> diag -> 
  a:[< mat] -> x:[< vec] -> unit
      = "ml_gsl_blas_dtrmv"
external trsv : uplo -> transpose -> diag -> 
  a:[< mat] -> x:[< vec] -> unit
      = "ml_gsl_blas_dtrsv"
external symv : uplo -> alpha:float -> a:[< mat] -> 
  x:[< vec] -> beta:float -> y:[< vec] -> unit
      = "ml_gsl_blas_dsymv_bc" "ml_gsl_blas_dsymv"
external dger : alpha:float -> x:[< vec] -> 
  y:[< vec] -> a:[< mat] -> unit
      = "ml_gsl_blas_dger"
external syr : uplo -> alpha:float -> x:[< vec] -> 
  a:[< mat] -> unit
      = "ml_gsl_blas_dsyr"
external syr2 : uplo -> alpha:float -> x:[< vec] -> 
  y:[< vec] -> a:[< mat] -> unit
      = "ml_gsl_blas_dsyr2"


(* LEVEL 3 *)
external gemm : ta:transpose -> tb:transpose ->
  alpha:float -> a:[< mat] -> b:[< mat] ->
    beta:float -> c:[< mat] -> unit
	= "ml_gsl_blas_dgemm_bc" "ml_gsl_blas_dgemm"
external symm : side -> uplo ->
  alpha:float -> a:[< mat] -> b:[< mat] ->
    beta:float -> c:[< mat] -> unit
	= "ml_gsl_blas_dsymm_bc" "ml_gsl_blas_dsymm"
external trmm : side -> uplo -> transpose -> diag -> 
  alpha:float -> a:[< mat] -> b:[< mat] -> unit
	= "ml_gsl_blas_dtrmm_bc" "ml_gsl_blas_dtrmm"
external trsm : side -> uplo -> transpose -> diag -> 
  alpha:float -> a:[< mat] -> b:[< mat] -> unit
	= "ml_gsl_blas_dtrsm_bc" "ml_gsl_blas_dtrsm"
external syrk : uplo -> transpose -> 
  alpha:float -> a:[< mat] -> beta:float -> c:[< mat] -> unit
	= "ml_gsl_blas_dsyrk_bc" "ml_gsl_blas_dsyrk"
external syr2k : uplo -> transpose -> 
  alpha:float -> a:[< mat] -> b:[< mat] -> 
    beta:float -> c:[< mat] -> unit
	= "ml_gsl_blas_dsyr2k_bc" "ml_gsl_blas_dsyr2k"



open Gsl_complex

module Complex =
  struct
(* LEVEL 1 *)
  external dotu : [< cvec] -> [< cvec] -> complex = "ml_gsl_blas_zdotu"
  external dotc : [< cvec] -> [< cvec] -> complex = "ml_gsl_blas_zdotc"
  external nrm2 : [< cvec] -> float = "ml_gsl_blas_znrm2"
  external asum : [< cvec] -> float = "ml_gsl_blas_zasum"
  external iamax : [< cvec] -> int = "ml_gsl_blas_izamax"
  external swap : [< cvec] -> [< cvec] -> unit = "ml_gsl_blas_zswap"
  external copy : [< cvec] -> [< cvec] -> unit = "ml_gsl_blas_zcopy"
  external axpy : complex -> [< cvec] -> [< cvec] -> unit = "ml_gsl_blas_zaxpy"
  external scal : complex -> [< cvec] -> unit = "ml_gsl_blas_zscal"
  external zdscal : float -> [< cvec] -> unit = "ml_gsl_blas_zdscal"

(* LEVEL 2 *)
  external gemv : transpose -> alpha:complex -> a:[< cmat] -> 
    x:[< cvec] -> beta:complex -> y:[< cvec] -> unit
	= "ml_gsl_blas_zgemv_bc" "ml_gsl_blas_zgemv"
  external trmv : uplo -> transpose -> diag -> 
    a:[< cmat] -> x:[< cvec] -> unit
	= "ml_gsl_blas_ztrmv"
  external trsv : uplo -> transpose -> diag -> 
    a:[< cmat] -> x:[< cvec] -> unit
	= "ml_gsl_blas_ztrsv"
  external hemv : uplo -> alpha:complex -> a:[< cmat] -> 
    x:[< cvec] -> beta:complex -> y:[< cvec] -> unit
	= "ml_gsl_blas_zhemv_bc" "ml_gsl_blas_zhemv"
  external geru : alpha:complex -> x:[< cvec] -> 
    y:[< cvec] -> a:[< cmat] -> unit
	= "ml_gsl_blas_zgeru"
  external gerc : alpha:complex -> x:[< cvec] -> 
    y:[< cvec] -> a:[< cmat] -> unit
	= "ml_gsl_blas_zgerc"
  external her : uplo -> alpha:float -> 
    x:[< cvec] -> a:[< cmat] -> unit
	= "ml_gsl_blas_zher"
  external her2 : uplo -> alpha:complex -> 
    x:[< cvec] -> y:[< cvec] -> a:[< cmat] -> unit
	= "ml_gsl_blas_zher2"

(* LEVEL 3 *)
  external gemm : ta:transpose -> tb:transpose ->
    alpha:complex -> a:[< cmat] -> b:[< cmat] ->
      beta:complex -> c:[< cmat] -> unit
	  = "ml_gsl_blas_zgemm_bc" "ml_gsl_blas_zgemm"
  external symm : side -> uplo ->
    alpha:complex -> a:[< cmat] -> b:[< cmat] ->
      beta:complex -> c:[< cmat] -> unit
	  = "ml_gsl_blas_zsymm_bc" "ml_gsl_blas_zsymm"
  external syrk : uplo -> transpose -> 
    alpha:complex -> a:[< cmat] -> beta:complex -> c:[< cmat] -> unit
	= "ml_gsl_blas_zsyrk_bc" "ml_gsl_blas_zsyrk"
  external syr2k : uplo -> transpose -> 
    alpha:complex -> a:[< cmat] -> b:[< cmat] -> 
      beta:complex -> c:[< cmat] -> unit
	  = "ml_gsl_blas_zsyr2k_bc" "ml_gsl_blas_zsyr2k"
  external trmm : side -> uplo -> transpose -> diag -> 
    alpha:complex -> a:[< cmat] -> b:[< cmat] -> unit
	= "ml_gsl_blas_ztrmm_bc" "ml_gsl_blas_ztrmm"
  external trsm : side -> uplo -> transpose -> diag -> 
    alpha:complex -> a:[< cmat] -> b:[< cmat] -> unit
	= "ml_gsl_blas_ztrsm_bc" "ml_gsl_blas_ztrsm"
  external hemm : side -> uplo -> alpha:complex -> 
    a:[< cmat] -> b:[< cmat] -> beta:complex -> c:[< cmat] -> unit
	= "ml_gsl_blas_zhemm_bc" "ml_gsl_blas_zhemm"
  external herk : uplo -> transpose -> alpha:float -> 
    a:[< cmat] -> beta:float -> c:[< cmat] -> unit
	= "ml_gsl_blas_zherk_bc" "ml_gsl_blas_zherk"
  external her2k : uplo -> transpose -> alpha:complex -> 
    a:[< cmat] -> b:[< cmat] -> beta:float -> c:[< cmat] -> unit
	= "ml_gsl_blas_zher2k_bc" "ml_gsl_blas_zher2k"
  end
  
