#include "../include/lass.h"

/**
 *
 * 	@file ddss_dsymm.c
 *
 * 	@brief LASs-DDSs ddss_dsymm routine.
 *
 * 	LASs-DDSs is a software package provided by:
 * 	Barcelona Supercomputing Center - Centro Nacional de Supercomputacion
 *
 * 	@author Pedro Valero-Lara pedro.valero@bsc.es
 * 	@date 2017-07-11
 * 	@reviewer 
 * 	@modified 
 *
 **/

/**
 *  
 *	@ingroup DDSS
 *   
 *	Performs one of the matrix-matrix operations:
 *
 *		C = ALPHA * A * B + BETA * C
 *	or
 *
 *		C = ALPHA * B * A + BETA * C
 *	
 *
 *	where op( X ) is one of:
 *
 *		op( X ) = X      or
 *		op( X ) = X**T 
 *	
 *	ALPHA and BETA are scalars, A is a symmetric matrix, and B and C 
 *	are M by N matrices.
 *
**/

/**
 *  
 * 	@param[in]
 *	SIDE	enum DDSS_SIDE.
 *	        UPLO specifies the position of the symmetric A matrix in 
 *			the operation:
 *       	- Left:  C = ALPHA *  A *  B + BETA * C
 *      	- Right: C = ALPHA *  B *  A + BETA * C
 *  
 * 	@param[in]
 *	UPLO	enum DDSS_UPLO.
 *	        UPLO specifies the form of A is stored:
 *       	- Lower: Lower triangle of A is stored. The upper traingular part is
 *       	not referenced.
 *      	- Upper: Upper triangle of A is stored. The lower triangular part is
 *      	not referenced.
 *  
 *	@param[in]
 *	M       int.
 *			M specifies the number of rows of the matrix C. 
 *			M must be equal or greater than zero.
 *  
 *	@param[in]
 *	N       int.
 *			N specifies the number of columns of the matrix C. 
 *			N must be equal or greater than zero.
 *   
 *	@param[in]
 *	ALPHA   double.
 *   
 *	@param[in]
 *	A  		double *.
 *          A is a pointer to a matrix of dimension Ma ( rows ) by Na 
 *			(columns), where Ma is M and Na is M when SIDE = Left, and
 *			Ma is N and Na is N when SIDE = Right
 *
 *
 *  @param[in]
 *	LDA     int.
 *          LDA specifies the number of columns of A ( row-major order ). 
 *			LDA must be at least max( 1, Na ). 
 *   
 *	@param[in]
 *	B  		double *.
 *          B is a pointer to a matrix of dimension M by N. 
 *   
 *  @param[in]
 *	LDB     int.
 *          LDB specifies the number of columns of B ( row-major order ). 
 *			LDB must be at least max( 1, N ). 
 *
 *	@param[in]
 *	BETA    double.
 *   
 *	@param[in,out]
 *	C  		double *.
 *	    	C is a pointer to a matrix of dimension M by N.
 *          On exit, C is overwritten by the M by N matrix. 
 *   
 *	@param[in]
 *	LDC     int.
 * 	    	LDC specifies the number of columns of C ( row-major order ).
 * 	    	LDC must be at least max( 1, N ).
 *   
 **/

/**
 *
 *	@retval Success successful exit
 *	@retval NoSuccess unsuccessful exit
 *
 **/

/**
 *
 *	@sa kdsymm
 *
 **/ 

int ddss_dsymm( enum DDSS_SIDE SIDE, enum DDSS_UPLO UPLO, 
		int M, int N,
		double ALPHA, double *A, int LDA,
					  double *B, int LDB,
		double BETA,  double *C, int LDC )
{

	// Local variables
	int nA;

	// Argument checking
	if ( ( SIDE != Left ) && ( SIDE != Right ) )
	{
		fprintf( stderr, "Illegal value of SIDE, in ddss_dsymm code\n" );
		return NoSuccess;
	}
	
	if ( ( UPLO != Upper ) && ( UPLO != Lower ) )
	{
		fprintf( stderr, "Illegal value of UPLO, in ddss_dsymm code\n" );
		return NoSuccess;
	}

	if ( M < 0 )
	{
		fprintf( stderr, "Illegal value of M, in ddss_dsymm code\n" );
		return NoSuccess;
	}
	
	if ( N < 0 )
	{
		fprintf( stderr, "Illegal value of N, in ddss_dsymm code\n" );
		return NoSuccess;
	}

	// Quick return
	if ( M == 0 || N == 0 || ( ALPHA == 0.0 && BETA == 1.0 ) )
	{
		return Success;
	}

	if ( SIDE == Left )
	{
		nA = M;
	}
	else
	{
		nA = N;
	}	

	if ( LDA < MAX( 1, nA ) )
	{
		fprintf( stderr, "Illegal value of LDA, in ddss_dsymm code\n" );	
		return NoSuccess;
	}

	if ( LDB < MAX( 1, N ) )
	{
		fprintf( stderr, "Illegal value of LDB, in ddss_dsymm code\n" );	
		return NoSuccess;
	}
	
	if ( LDC < MAX( 1, N ) )
	{
		fprintf( stderr, "Illegal value of LDC, in ddss_dsymm code\n" );	
		return NoSuccess;
	}
	
	return kdsymm( SIDE, UPLO, M, N,
                 	( const double ) ALPHA, A, LDA,
			    							B, LDB,
					( const double )  BETA, C, LDC );

} 
