// -*-C++-*- 

// Copyright (C) 2004 
// Christian Stimming <stimming@tuhh.de>

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2, or (at
// your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public License along
// with this library; see the file COPYING.  If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.

//      LAPACK++ (V. 1.1)
//      (C) 1992-1996 All Rights Reserved.

/** @file blas3pp.h
 * @brief Blas Level-3 Routines: Matrix-Matrix Operations and Matrix norms.
 */


#ifndef _BLAS3_PP_H_
#define _BLAS3_PP_H_

#include <cmath>
#include "lafnames.h"
#include "arch.h" // needed for DLLIMPORT

#ifdef LA_COMPLEX_SUPPORT
# include "lacomplex.h"
#endif

#ifndef DOXYGEN_IGNORE
// Forward declaration of classes
class LaGenMatDouble;
class LaVectorDouble;
class LaGenMatComplex;
class LaSymmMatDouble;

class LaBandMatDouble;
class LaSpdMatDouble;
class LaSymmTridiagMatDouble;
class LaTridiagMatDouble;
#endif // DOXYGEN_IGNORE

/** @name Real-valued general matrices */
//@{
/** Perform the matrix-matrix operation C := alpha*A*B + beta*C
 * where A and B are used in either non-transposed or transposed
 * form, depending on the function arguments.
 *
 * Internally this uses @c dgemm .
 *
 * @param transpose_A If true, use transposed A, i.e. A' instead
 * of A. If false, use A directly in non-transposed form.
 *
 * @param transpose_B If true, use transposed B, i.e. B' instead
 * of B. If false, use B directly in non-transposed form.
 *
 * (New in lapackpp-2.4.14.) */
DLLIMPORT
void Blas_Mat_Mat_Mult(const LaGenMatDouble &A, 
		       const LaGenMatDouble &B, LaGenMatDouble &C, 
		       bool transpose_A, bool transpose_B = false,
		       double alpha = 1.0, double beta = 0.0);

/** Perform the matrix-matrix operation C := alpha*A*B + beta*C */
DLLIMPORT
void Blas_Mat_Mat_Mult(const LaGenMatDouble &A, 
            const LaGenMatDouble &B, LaGenMatDouble &C, 
            double alpha = 1.0, double beta = 0.0);

/** Perform the matrix-matrix operation C := alpha*A'*B + beta*C */
DLLIMPORT
void Blas_Mat_Trans_Mat_Mult(const LaGenMatDouble &A, 
            const LaGenMatDouble &B, LaGenMatDouble &C, 
            double alpha = 1.0, double beta = 0.0);

/** Perform the matrix-matrix operation C := alpha*A*B' + beta*C */
DLLIMPORT
void Blas_Mat_Mat_Trans_Mult(const LaGenMatDouble &A, 
            const LaGenMatDouble &B, LaGenMatDouble &C, 
            double alpha = 1.0, double beta = 0.0);

/** Perform a matrix-matrix multiplication, returning only the
    diagonal of the result: C := diag(A * B). FIXME: needs verification. */
DLLIMPORT
void Blas_Mat_Mat_Mult(const LaGenMatDouble &A, 
		       const LaGenMatDouble &B, LaVectorDouble &C);

/** Perform a matrix-matrix multiplication, returning only the
    diagonal of the result: C := diag(A' * B). FIXME: needs verification.  */
DLLIMPORT
void Blas_Mat_Trans_Mat_Mult(const LaGenMatDouble &A, 
			     const LaGenMatDouble &B, LaVectorDouble &C);

/** Perform a matrix-matrix multiplication, returning only the
    diagonal of the result: C := diag(A * B'). FIXME: needs verification.  */
DLLIMPORT
void Blas_Mat_Mat_Trans_Mult(const LaGenMatDouble &A, 
			     const LaGenMatDouble &B, LaVectorDouble &C);

/** Matrix scaling: A := s * A
 *
 * (New in lapackpp-2.4.7.) */
DLLIMPORT
void Blas_Scale(double s, LaGenMatDouble &A);

//@}


#ifdef LA_COMPLEX_SUPPORT
/** @name Complex-valued matrices */
//@{
/** Perform the matrix-matrix operation C := alpha*A*B + beta*C
 * where A and B are used in either non-hermitian or hermitian
 * form (matrix transpose and complex conjugate), depending on the
 * function arguments.
 *
 * Internally this uses @c zgemm .
 *
 * @param hermit_A If true, use hermitian A, i.e. A* (sometimes
 * denoted conj(A')), the matrix transpose and complex conjugate,
 * instead of A. If false, use A directly in non-hermitian form.
 *
 * @param hermit_B If true, use hermitian B, i.e. B* (sometimes
 * denoted conj(B')), the matrix transpose and complex conjugate,
 * instead of B. If false, use B directly in non-hermitian form.
 *
 * (New in lapackpp-2.4.14.) */
DLLIMPORT
void Blas_Mat_Mat_Mult(const LaGenMatComplex &A, 
		       const LaGenMatComplex &B, LaGenMatComplex &C, 
		       bool hermit_A, bool hermit_B = false, 
		       LaComplex alpha = 1.0, LaComplex beta = 0.0);

/** Perform the matrix-matrix operation C := alpha*A*B + beta*C */
DLLIMPORT
void Blas_Mat_Mat_Mult(const LaGenMatComplex &A, 
            const LaGenMatComplex &B, LaGenMatComplex &C, 
            LaComplex alpha = 1.0, LaComplex beta = 0.0);

/** Perform the matrix-matrix operation C := alpha*A'*B + beta*C */
DLLIMPORT
void Blas_Mat_Trans_Mat_Mult(const LaGenMatComplex &A, 
            const LaGenMatComplex &B, LaGenMatComplex &C, 
            LaComplex alpha = 1.0, LaComplex beta = 0.0);

/** Perform the matrix-matrix operation C := alpha*A*B' + beta*C */
DLLIMPORT
void Blas_Mat_Mat_Trans_Mult(const LaGenMatComplex &A, 
            const LaGenMatComplex &B, LaGenMatComplex &C, 
            LaComplex alpha = 1.0, LaComplex beta = 0.0);

/** Matrix scaling: A := s * A
 *
 * (New in lapackpp-2.4.7.) */
DLLIMPORT
void Blas_Scale(COMPLEX s, LaGenMatComplex &A);
//@}
#endif // LA_COMPLEX_SUPPORT

#ifdef _LA_UNIT_LOWER_TRIANG_MAT_DOUBLE_H_

DLLIMPORT
void Blas_Mat_Mat_Solve(LaUnitLowerTriangMatDouble &A, 
            LaGenMatDouble &B, double alpha = 1.0);

#endif

#ifdef _LA_UNIT_UPPER_TRIANG_MAT_DOUBLE_H_
DLLIMPORT
void Blas_Mat_Mat_Mult(LaUnitUpperTriangMatDouble &A,
            LaGenMatDouble &B, double alpha = 1.0);

DLLIMPORT
void Blas_Mat_Mat_Solve(LaUnitUpperTriangMatDouble &A, 
            LaGenMatDouble &B, double alpha = 1.0);

#endif

#ifdef _LA_LOWER_TRIANG_MAT_DOUBLE_H_
DLLIMPORT
void Blas_Mat_Mat_Mult(LaLowerTriangMatDouble &A,
            LaGenMatDouble &B, double alpha = 1.0);

DLLIMPORT
void Blas_Mat_Mat_Solve(LaLowerTriangMatDouble &A, 
            LaGenMatDouble &B, double alpha = 1.0);
#endif


#ifdef _LA_UPPER_TRIANG_MAT_DOUBLE_H_
DLLIMPORT
void Blas_Mat_Mat_Mult(LaUpperTriangMatDouble &A,
            LaGenMatDouble &B, double alpha = 1.0);

DLLIMPORT
void Blas_Mat_Mat_Solve(LaUpperTriangMatDouble &A, 
            LaGenMatDouble &B, double alpha = 1.0);
#endif


#ifdef _LA_UNIT_LOWER_TRIANG_MAT_DOUBLE_H_
DLLIMPORT
void Blas_Mat_Trans_Mat_Solve(LaUnitLowerTriangMatDouble &A,
            LaGenMatDouble &B, double alpha = 1.0);
#endif

#ifdef _LA_UNIT_UPPER_TRIANG_MAT_DOUBLE_H_
DLLIMPORT
void Blas_Mat_Trans_Mat_Solve(LaUnitUpperTriangMatDouble &A,
            LaGenMatDouble &B, double alpha = 1.0);
#endif

#ifdef _LA_UNIT_LOWER_TRIANG_MAT_DOUBLE_H_
DLLIMPORT
void Blas_Mat_Mat_Mult(LaUnitLowerTriangMatDouble &A,
            LaGenMatDouble &B, double alpha = 1.0);

#endif

#ifdef _LA_LOWER_TRIANG_MAT_DOUBLE_H_
DLLIMPORT
void Blas_Mat_Trans_Mat_Solve(LaLowerTriangMatDouble &A,
            LaGenMatDouble &B, double alpha = 1.0);
#endif


#ifdef _LA_UPPER_TRIANG_MAT_DOUBLE_H_ 
DLLIMPORT
void Blas_Mat_Trans_Mat_Solve(LaUpperTriangMatDouble &A,
            LaGenMatDouble &B, double alpha = 1.0);

#endif

/** @name Symmetric matrices */
//@{

/**
* Perform one of the matrix-matrix operations
*  - A := alpha*B*C + beta*A if b_left_side is true
*  - A := alpha*C*B + beta*A if b_left_side is false
*
*/
DLLIMPORT
void Blas_Mat_Mat_Mult(LaSymmMatDouble &A, LaGenMatDouble &B, 
		       LaGenMatDouble &C,
		       double alpha = 1.0, double beta = 1.0,
		       bool b_left_side = true);

/**
* Perform one of the matrix-matrix operations
*  - C := alpha*A*A' + beta*C if right_transposed is true
*  - C := alpha*A'*A + beta*C if right_transposed is false
*
* with A' as transposition of A.
*
*/
DLLIMPORT
void Blas_R1_Update(LaSymmMatDouble &C, LaGenMatDouble &A,
		    double alpha = 1.0, double beta = 1.0,
		    bool right_transposed = true);

/**
* Perform one of the matrix-matrix operations
*  - C := alpha*A*B' + alpha*B*A' + beta*C if right_transposed is true
*  - C := alpha*A'*B + alpha*B'*A + beta*C if right_transposed is false
*
* with A' and B' as transposition of A and B.
*
*/
DLLIMPORT
void Blas_R2_Update(LaSymmMatDouble &C, LaGenMatDouble &A,
		    LaGenMatDouble &B,
		    double alpha = 1.0, double beta = 1.0,
		    bool right_transposed = true);

//@}



//-------------------------------------
/// @name Matrix Norms
//-------------------------------------
//@{
/** \brief 1-Norm: Maximum column sum 
 *
 * Returns the 1-Norm of matrix A, which is the maximum
 * absolute column sum: \f$||A||_{\infty}=\max_j\sum_{i=1}^M|a_{ij}|\f$,
 *
 * \see Eric W. Weisstein. "Matrix Norm." From MathWorld--A Wolfram
 * Web Resource. http://mathworld.wolfram.com/MatrixNorm.html */
DLLIMPORT
double Blas_Norm1(const LaGenMatDouble &A);

/** \brief Infinity-Norm: Maximum row sum
 *
 * Returns the Infinity-Norm of matrix A, which is the maximum
 * absolute row sum: \f$||A||_{\infty}=\max_i\sum_{j=1}^N|a_{ij}|\f$,
 *
 * \see Eric W. Weisstein. "Matrix Norm." From MathWorld--A Wolfram
 * Web Resource. http://mathworld.wolfram.com/MatrixNorm.html */
DLLIMPORT
double Blas_Norm_Inf(const LaGenMatDouble &A);

/** \brief Frobenius-Norm
 *
 * Returns the Frobenius-Norm of matrix A (also called the Schur-
 * or Euclidean norm): \f$||A||_F=\sqrt{\sum_{i,j}|a_{ij}|^2}\f$,
 * i.e. the square root of the sum of the absolute squares of its
 * elements. 
 *
 * \see Eric W. Weisstein. "Matrix Norm." From MathWorld--A Wolfram
 * Web Resource. http://mathworld.wolfram.com/MatrixNorm.html */
DLLIMPORT
double Blas_NormF(const LaGenMatDouble &A);

/** \brief 1-Norm: Maximum column sum 
 *
 * Returns the 1-Norm of matrix A, which is the maximum
 * absolute column sum: \f$||A||_{\infty}=\max_j\sum_{i=1}^M|a_{ij}|\f$,
 *
 * \see Eric W. Weisstein. "Matrix Norm." From MathWorld--A Wolfram
 * Web Resource. http://mathworld.wolfram.com/MatrixNorm.html */
DLLIMPORT
double Blas_Norm1(const LaGenMatComplex &A);

/** \brief Infinity-Norm: Maximum row sum
 *
 * Returns the Infinity-Norm of matrix A, which is the maximum
 * absolute row sum: \f$||A||_{\infty}=\max_i\sum_{j=1}^N|a_{ij}|\f$,
 *
 * \see Eric W. Weisstein. "Matrix Norm." From MathWorld--A Wolfram
 * Web Resource. http://mathworld.wolfram.com/MatrixNorm.html */
DLLIMPORT
double Blas_Norm_Inf(const LaGenMatComplex &A);

/** \brief Frobenius-Norm
 *
 * Returns the Frobenius-Norm of matrix A (also called the Schur-
 * or Euclidean norm): \f$||A||_F=\sqrt{\sum_{i,j}|a_{ij}|^2}\f$,
 * i.e. the square root of the sum of the absolute squares of its
 * elements. 
 *
 * \see Eric W. Weisstein. "Matrix Norm." From MathWorld--A Wolfram
 * Web Resource. http://mathworld.wolfram.com/MatrixNorm.html */
DLLIMPORT
double Blas_NormF(const LaGenMatComplex &A);

#ifndef DOXYGEN_IGNORE
/** DEPRECATED, use Blas_Norm_Inf instead. */
DLLIMPORT
double Norm_Inf(const LaGenMatDouble &A);
/** DEPRECATED, use Blas_Norm_Inf instead. */
DLLIMPORT
double Norm_Inf(const LaGenMatComplex &A);
#endif // DOXYGEN_IGNORE


DLLIMPORT
double Norm_Inf(const LaBandMatDouble &A);
DLLIMPORT
double Norm_Inf(const LaSymmMatDouble &S);
DLLIMPORT
double Norm_Inf(const LaSpdMatDouble &S);
DLLIMPORT
double Norm_Inf(const LaSymmTridiagMatDouble &S);
DLLIMPORT
double Norm_Inf(const LaTridiagMatDouble &T);
//@}


#endif 
    // _BLAS3_PP_H_
            


syntax highlighted by Code2HTML, v. 0.9.1