#
# This file contains the formal problem description for
# a subset of the BLAS library (including some simplified versions)
#
# Content :
#              ddot
#              daxpy
#              zaxpy
#              dgemv
#              dgemm
#              zgemm
#              dmatmul  (wrapper around BLAS routine dgemm)
#              zmatmul  (wrapper around BLAS routine zgemm)
########
# ddot
########
@PROBLEM ddot
@FUNCTION ddot
@LIB $(BLAS_LIB_LINK)
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /BLAS/Level1/
@DESCRIPTION
From BLAS -

Forms the dot product of two vectors.
Double Precision routine.

MATLAB Example : [a] = netsolve('ddot',n,dx,incx,dy,incy)
http://www.netlib.org/blas/
@INPUT 5
@OBJECT SCALAR I n
Length of vector (needed to calculate n*incx or n*incy)
@OBJECT VECTOR D dx
vector dx (length specified as max(1,n*|incx|))
@OBJECT SCALAR I incx
Integer increment for vector dx (incx)
@OBJECT VECTOR D dy
vector dy (length specified as max(1,n*|incy|))
@OBJECT SCALAR I incy
Integer increment for vector dy (incy)

@OUTPUT 1
@OBJECT SCALAR D product
Dot product

@COMPLEXITY 2,1

@CALLINGSEQUENCE
@ARG I0
# n
@ARG I1
# dx (length specified as max(1,n*|incx|))
@ARG I2
# incx
@ARG I3
# dy (length specified as max(1,n*|incy|))
@ARG I4
# incy
@ARG O0
# dot product result
@COMP mI1=op(*,array(I0,0),array(I2,0))
# I need to set mI1=max(1,n*abs(incx)) but COMP functionality doesn't
# permit that
#@COMP mI1=if(op(*,array(I0,0),array(I2,0))>1,op(*,array(I0,0),array(I2,0)),1)
# or
#@COMP mI1=(op(*,array(I0,0),array(I2,0))>1)?op(*,array(I0,0),array(I2,0)):1
@COMP mI3=op(*,array(I0,0),array(I4,0))
# I need to set mI3=max(1,n*abs(incy)) but COMP functionality doesn't
# permit that
#@COMP mI3=(op(*,array(I0,0),array(I4,0))>1)?op(*,array(I0,0),array(I4,0)):1

@CODE
extern double ddot(int *n, double *x, int *incx, double *y, int *incy);
@O0@ = (double *)malloc(sizeof(double)*1);
*@O0@ = (double)ddot(@I0@,@I1@,@I2@,@I3@,@I4@);

@END_CODE

#
# daxpy
#

@PROBLEM daxpy
@FUNCTION daxpy
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /BLAS/Level1/
@DESCRIPTION
From BLAS -

Computes y <- alpha * x + y
where y and x are the two double precision real vectors, and
alpha is a double precision real scalar.

MATLAB Example : [y] = netsolve('daxpy',n,alpha,x,incx,y,incy)
http://www.netlib.org/blas/
@INPUT 6
@OBJECT SCALAR I n
Length of vector (needed to calculate n*incx or n*incy)
@OBJECT SCALAR D alpha
scalar alpha
@OBJECT VECTOR D x
vector x (length specified as max(1,n*|incx|))
@OBJECT SCALAR I incx
Integer increment for vector x (incx)
@OBJECT VECTOR D y
vector y (length specified as max(1,n*|incy|))
@OBJECT SCALAR I incy
Integer increment for vector y (incy)

@OUTPUT 1
@OBJECT VECTOR D result
vector y

@COMPLEXITY 3,1

@CALLINGSEQUENCE
@ARG I0
# n
@ARG I1
# alpha
@ARG I2
# x
@ARG I3
# incx
@ARG I4,O0
# y
@ARG I5
# incy
@COMP mI2=op(*,array(I0,0),array(I3,0))
# I need to set mI2=max(1,n*abs(incx)) but COMP functionality doesn't
# permit that
@COMP mI4=op(*,array(I0,0),array(I5,0))
# I need to set mI4=max(1,n*abs(incy)) but COMP functionality doesn't
# permit that

@CODE
extern void daxpy(int *n, double *alpha, double *x, int *incx,
                  double *y, int *incy);
daxpy(@I0@,@I1@,@I2@,@I3@,@I4@,@I5@);
*@mO0@ = *@mI4@;
@O0@ = @I4@;

@END_CODE


#
# zaxpy
#

@PROBLEM zaxpy
@FUNCTION zaxpy
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /BLAS/Level1/
@DESCRIPTION
From BLAS -

Computes y <- alpha * x + y
where y and x are the two double precision complex vectors, and
alpha is a double precision complex scalar.

MATLAB Example : [y] = netsolve('zaxpy',n,alpha,x,incx,y,incy)
http://www.netlib.org/blas/
@INPUT 6
@OBJECT SCALAR I n
Length of vector (needed to calculate n*incx or n*incy)
@OBJECT SCALAR Z alpha
scalar alpha
@OBJECT VECTOR Z x
vector x (length specified as max(1,n*|incx|))
@OBJECT SCALAR I incx
Integer increment for vector x (incx)
@OBJECT VECTOR Z y
vector y (length specified as max(1,n*|incy|))
@OBJECT SCALAR I incy
Integer increment for vector y (incy)

@OUTPUT 1
@OBJECT VECTOR Z result
vector y

@COMPLEXITY 6,1

@CALLINGSEQUENCE
@ARG I0
# n
@ARG I1
# alpha
@ARG I2
# x
@ARG I3
# incx
@ARG I4,O0
# y
@ARG I5
# incy
@COMP mI2=op(*,array(I0,0),array(I3,0))
# I need to set mI2=max(1,n*abs(incx)) but COMP functionality doesn't
# permit that
@COMP mI4=op(*,array(I0,0),array(I5,0))
# I need to set mI4=max(1,n*abs(incy)) but COMP functionality doesn't
# permit that

@CODE
extern void zaxpy(int *n, void *alpha, void *x, int *incx, void *y, int *incy);
zaxpy(@I0@,@I1@,@I2@,@I3@,@I4@,@I5@);
*@mO0@ = *@mI4@;
@O0@ = @I4@;

@END_CODE

#
# dgemv 
#
@PROBLEM dgemv
@FUNCTION dgemv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /BLAS/Level2/
@DESCRIPTION
DGEMV  performs one of the matrix-vector operations
  y := alpha*A*x + beta*y,   or   y := alpha*A'*x + beta*y,
where alpha and beta are scalars, x and y are vectors and A is an
m by n matrix.
http://www.netlib.org/blas/index.html
@INPUT 8
@OBJECT SCALAR CHAR trans
On entry, TRANS specifies the operation to be performed as
follows:
   TRANS = 'N' or 'n'   y := alpha*A*x + beta*y.
   TRANS = 'T' or 't'   y := alpha*A'*x + beta*y.
   TRANS = 'C' or 'c'   y := alpha*A'*x + beta*y.
@OBJECT SCALAR D alpha
   On entry, ALPHA specifies the scalar alpha.
@OBJECT MATRIX D a
A      - DOUBLE PRECISION array of DIMENSION ( LDA, n ).
Before entry, the leading m by n part of the array A must
contain the matrix of coefficients.
@OBJECT VECTOR D x
X      - DOUBLE PRECISION array of DIMENSION at least
   ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n'
and at least
   ( 1 + ( m - 1 )*abs( INCX ) ) otherwise.
Before entry, the incremented array X must contain the
vector x.
@OBJECT SCALAR I incx
On entry, INCX specifies the increment for the elements of
X. INCX must not be zero.
@OBJECT SCALAR D beta
On entry, BETA specifies the scalar beta. When BETA is
supplied as zero then Y need not be set on input.
@OBJECT VECTOR D y
Y      - DOUBLE PRECISION array of DIMENSION at least
   ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n'
and at least
   ( 1 + ( n - 1 )*abs( INCY ) ) otherwise.
Before entry with BETA non-zero, the incremented array Y
must contain the vector y. On exit, Y is overwritten by the
updated vector y.
@OBJECT SCALAR I incy
On entry, INCY specifies the increment for the elements of
Y. INCY must not be zero.
@OUTPUT 1
@OBJECT VECTOR D answer
Answer.
@COMPLEXITY 3,2
@CALLINGSEQUENCE
# trans, char
@ARG I0
# rows of matrix A
@ARG mI2
# col of matrix A
@ARG nI2
# scalar alpha
@ARG I1
# matrix A
@ARG I2
# LDA
@ARG lI2
# vector X
@ARG I3
# scalar incx
@ARG I4
# double scalar beta
@ARG I5
# vector Y
@ARG I6,O0
# scalar incy
@ARG I7
#
# Ugly Formulas
#
@COMP mI3=if(array(I0,0)='n',op(+,1,op(*,op(-,nI2,1),array(I4,0))),\
if(array(I0,0)='N',op(+,1,op(*,op(-,nI2,1),array(I4,0))),\
op(+,1,op(*,op(-,mI2,1),array(I4,0)))))
@COMP mI6=if(array(I0,0)='n',op(+,1,op(*,op(-,mI2,1),array(I7,0))),\
if(array(I0,0)='N',op(+,1,op(*,op(-,mI2,1),array(I7,0))),\
op(+,1,op(*,op(-,nI2,1),array(I7,0)))))
@CODE
extern void dgemv(char *trans, int *m, int *n, double *alpha, double *a,
                  int *lda, double *x, int *incx, double *beta,
                  double *y, int *incy);
dgemv(@I0@, @mI2@, @nI2@, @I1@, @I2@, @mI2@, @I3@, @I4@, @I5@, @I6@, @I7@);
@O0@ = @I6@;
*@mO0@ = *@mI6@;
@END_CODE
#
# dgemm
#
@PROBLEM dgemm
@FUNCTION dgemm
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /BLAS/Level3/
@DESCRIPTION
From BLAS -

C := alpha*op( A )*op( B ) + beta*C,

where  op( X ) is one of
op( X ) = X   or   op( X ) = X',

alpha and beta are scalars, and A, B and C are matrices, with op( A )
an m by k matrix,  op( B )  a  k by n matrix and  C an m by n matrix.

MATLAB Example : [C] = netsolve('dgemm','N','N',2.3,a,b,2.1,c)
http://www.netlib.org/blas/index.html
@INPUT 7
@OBJECT SCALAR CHAR transa
TRANSA -
TRANSA specifies the form of op( A ) to be used in
the matrix multiplication as follows:

 TRANSA = 'N' or 'n',  op( A ) = A.
 TRANSA = 'T' or 't',  op( A ) = A'.
 TRANSA = 'C' or 'c',  op( A ) = A'.
@OBJECT SCALAR CHAR transb
TRANSB -
TRANSB specifies the form of op( A ) to be used in
the matrix multiplication as follows:

 TRANSB = 'N' or 'n',  op( A ) = A.
 TRANSB = 'T' or 't',  op( A ) = A'.
 TRANSB = 'C' or 'c',  op( A ) = A'.
@OBJECT SCALAR D alpha
alpha
@OBJECT MATRIX D a
Matrix A
# I3
@OBJECT MATRIX D b
Matrix B
# I4
@OBJECT SCALAR D beta
beta
@OBJECT MATRIX D c
Matrix C
# I6
@OUTPUT 1
@OBJECT MATRIX D c
Matrix C after performing the computation

@COMPLEXITY 2,3

@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG mI3,mI6
@ARG nI4,nI6
@ARG nI3,mI4
@ARG I2
@ARG I3
@ARG lI3
@ARG I4
@ARG lI4
@ARG I5
@ARG I6,O0
@ARG lI6,lO0

@CODE
extern void dgemm(char *transa, char *transb, int *m, int *n, int *k,
                  double *alpha, double *a, int *lda, double *b,
                  int *ldb, double *beta, double *c, int *ldc);

if (*(@mI3@) != *(@mI6@))
  return NS_PROT_DIM_MISMATCH;
if (*(@nI4@) != *(@nI6@))
  return NS_PROT_DIM_MISMATCH;
if (*(@nI3@) != *(@mI4@))
  return NS_PROT_DIM_MISMATCH;

*@mO0@ = *@mI6@;
*@nO0@ = *@nI6@;

dgemm(@I0@,@I1@,@mI3@,@nI4@,@nI3@,@I2@,@I3@,@mI3@,@I4@,@mI4@,@I5@,@I6@,@mI6@);
@O0@ = @I6@;

@END_CODE
#
# zgemm
#
@PROBLEM zgemm
@FUNCTION zgemm
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /BLAS/Level3/
@DESCRIPTION
From BLAS -

C := alpha*op( A )*op( B ) + beta*C,

where  op( X ) is one of
op( X ) = X   or   op( X ) = X', or op( X ) = conjg( X' ),

alpha and beta are scalars, and A, B and C are matrices, with op( A )
an m by k matrix,  op( B )  a  k by n matrix and  C an m by n matrix.

MATLAB Example : [C] = netsolve('zgemm','N','N',2.3,a,b,2.1,c)

@INPUT 7
@OBJECT SCALAR CHAR transa
TRANSA -
TRANSA specifies the form of op( A ) to be used in
the matrix multiplication as follows:

 TRANSA = 'N' or 'n',  op( A ) = A.
 TRANSA = 'T' or 't',  op( A ) = A'.
 TRANSA = 'C' or 'c',  op( A ) = conjg( A' ).
@OBJECT SCALAR CHAR transb
TRANSB -
TRANSB specifies the form of op( A ) to be used in
the matrix multiplication as follows:

 TRANSB = 'N' or 'n',  op( A ) = A.
 TRANSB = 'T' or 't',  op( A ) = A'.
 TRANSB = 'C' or 'c',  op( A ) = conjg( A' ).
@OBJECT SCALAR Z alpha
alpha
@OBJECT MATRIX Z a
Matrix A
# I3
@OBJECT MATRIX Z b
Matrix B
# I4
@OBJECT SCALAR Z beta
beta
@OBJECT MATRIX Z c
Matrix C
# I6

@OUTPUT 1
@OBJECT MATRIX Z c
Matrix C after performing the computation

@COMPLEXITY 4,3

@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG mI3,mI6
@ARG nI4,nI6
@ARG nI3,mI4
@ARG I2
@ARG I3
@ARG lI3
@ARG I4
@ARG lI4
@ARG I5
@ARG I6,O0
@ARG lI6,lO0

@CODE
extern void zgemm(char *transa, char *transb, int *m, int *n, int *k,
                  void *alpha, void *a, int *lda,
                  void *b, int *ldb, void *beta,
                  void *c, int *ldc);

if (*(@mI3@) != *(@mI6@))
  return NS_PROT_DIM_MISMATCH;
if (*(@nI4@) != *(@nI6@))
  return NS_PROT_DIM_MISMATCH;
if (*(@nI3@) != *(@mI4@))
  return NS_PROT_DIM_MISMATCH;

*@mO0@ = *@mI6@;
*@nO0@ = *@nI6@;

zgemm(@I0@,@I1@,@mI3@,@nI4@,@nI3@,@I2@,@I3@,@mI3@,@I4@,@mI4@,@I5@,@I6@,@mI6@);
@O0@ = @I6@;

@END_CODE

#############
# dmatmul   
#   Simplified version of dgemm
#############
@PROBLEM dmatmul
@FUNCTION dmatmul
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /BLAS-wrappers/Level3/
@DESCRIPTION
Wrapper around the BLAS routine DGEMM -
Simplified version

C := A*B

MATLAB Example : [c] = netsolve('dmatmul',a,b)
http://www.netlib.org/blas/
@INPUT 2
@OBJECT MATRIX D A
Matrix A
@OBJECT MATRIX D B
Matrix B
@OUTPUT 1
@OBJECT MATRIX D C
Matrix C

@COMPLEXITY 3,3

@CALLINGSEQUENCE
@ARG mI0
@ARG nI1
@ARG nI0,mI1
@ARG I0
@ARG lI0
@ARG I1
@ARG lI1
@ARG lO0
@ARG O0

@CODE
extern void dgemm(char *transa, char *transb, int *m, int *n, int *k,
                  double *alpha, double *a, int *lda, double *b,
                  int *ldb, double *beta, double *c, int *ldc);

double alpha,beta;

alpha = 1.0; beta = 1.0;

if (*(@nI0@) != *(@mI1@))
  return NS_PROT_DIM_MISMATCH;

*@mO0@ = *@mI0@;
*@nO0@ = *@nI1@;
@O0@ = (double *)calloc((*@mI0@)*(*@nI1@),sizeof(double));

dgemm("N","N",@mI0@,@nI1@,@nI0@,&alpha,@I0@,@mI0@,@I1@,@mI1@,&beta,@O0@,@mO0@);

@END_CODE

#############
# zmatmul   
#   Simplified version of zgemm
#############
@PROBLEM zmatmul
@FUNCTION zmatmul
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /BLAS-wrappers/Level3/
@DESCRIPTION
Wrapper around the BLAS routine ZGEMM --
Simplified version

C := A*B

MATLAB Example : [c] = netsolve('zmatmul',a,b)
http://www.netlib.org/blas/
@INPUT 2
@OBJECT MATRIX Z A
Matrix A
@OBJECT MATRIX Z B
Matrix B
@OUTPUT 1
@OBJECT MATRIX Z C
Matrix C

@COMPLEXITY 4,3

@CALLINGSEQUENCE
@ARG mI0
@ARG nI1
@ARG nI0,mI1
@ARG I0
@ARG lI0
@ARG I1
@ARG lI1
@ARG O0

@CODE
extern void zgemm(char *transa, char *transb, int *m, int *n, int *k,
                  void *alpha, void *a, int *lda,
                  void *b, int *ldb, void *beta,
                  void *c, int *ldc);

dcomplex alpha,beta;

alpha.r = 1.0;
alpha.i = 0.0;

beta.r = 1.0;
beta.i = 0.0;

if (*(@nI0@) != *(@mI1@))
  return NS_PROT_DIM_MISMATCH;

*@mO0@ = *@mI0@;
*@nO0@ = *@nI1@;
@O0@ = (dcomplex *)calloc((*@mI0@)*(*@nI1@),sizeof(dcomplex));

zgemm("N","N",@mI0@,@nI1@,@nI0@,&alpha,@I0@,@mI0@,@I1@,@mI1@,&beta,@O0@,@mO0@);

@END_CODE
