/*!\file SeqVec.cpp
 * \brief: implementation of the SeqVec object
 */

/*Headers:*/
/*{{{1*/
#ifdef HAVE_CONFIG_H
	#include <config.h>
#else
#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
#endif

#include <stdio.h>
#include <string.h>
#include "../toolkits.h"
#include "../../shared/shared.h"

/*}}}*/

/*SeqVec constructors and destructor*/
/*FUNCTION SeqVec::SeqVec(){{{1*/
SeqVec::SeqVec(){

	this->M=0;
	this->vector=NULL;
}
/*}}}*/
/*FUNCTION SeqVec::SeqVec(int M,bool fromlocalsize){{{1*/
SeqVec::SeqVec(int pM,bool fromlocalsize){

	this->M=pM;
	this->vector=NULL;
	if(this->M) this->vector=(double*)xcalloc(pM,sizeof(double));
}
/*}}}*/
/*FUNCTION SeqVec::SeqVec(double* serial_vec,int M){{{1*/
SeqVec::SeqVec(double* buffer,int pM){

	int i,j;

	this->M=pM;
	this->vector=NULL;
	if(this->M){
		this->vector=(double*)xcalloc(pM,sizeof(double));
		memcpy(this->vector,buffer,pM*sizeof(double));
	}
}
/*}}}*/
		/*FUNCTION SeqVec::~SeqVec(){{{1*/
SeqVec::~SeqVec(){
	xfree((void**)&this->vector);
	M=0;
}
/*}}}*/

/*SeqVec specific routines: */
/*FUNCTION SeqVec::Echo{{{1*/
void SeqVec::Echo(void){

	int i;
	printf("SeqVec size %i\n",this->M);
	for(i=0;i<M;i++){
		printf("%g\n ",vector[i]);
	}
}
/*}}}*/

/*FUNCTION SeqVec::Assemble{{{1*/
void SeqVec::Assemble(void){
		
	/*do nothing*/

}
/*}}}*/
/*FUNCTION SeqVec::SetValues{{{1*/
void SeqVec::SetValues(int ssize, int* list, double* values, InsMode mode){
	
	int i;
	switch(mode){
		case ADD_VAL:
			for(i=0;i<ssize;i++) this->vector[list[i]]+=values[i];
			break;
		case INS_VAL:
			for(i=0;i<ssize;i++) this->vector[list[i]]=values[i];
			break;
		default:
			_error_("unknown insert mode!");
			break;
	}

}
/*}}}*/
/*FUNCTION SeqVec::SetValue{{{1*/
void SeqVec::SetValue(int dof, double value, InsMode mode){

	switch(mode){
		case ADD_VAL:
			this->vector[dof]+=value;
			break;
		case INS_VAL:
			this->vector[dof]=value;
			break;
		default:
			_error_("unknown insert mode!");
			break;
	}
}
/*}}}*/
/*FUNCTION SeqVec::GetValue{{{1*/
void SeqVec::GetValue(double* pvalue,int dof){

	*pvalue=this->vector[dof];

}
/*}}}*/
		
/*FUNCTION SeqVec::GetSize{{{1*/
void SeqVec::GetSize(int* pM){

	*pM=this->M;

}
/*}}}*/
/*FUNCTION SeqVec::GetLocalSize{{{1*/
void SeqVec::GetLocalSize(int* pM){
	
	*pM=this->M;

}
/*}}}*/
/*FUNCTION SeqVec::Duplicate{{{1*/
SeqVec* SeqVec::Duplicate(void){
	
	return new SeqVec(this->vector,this->M);

}
/*}}}*/
/*FUNCTION SeqVec::Set{{{1*/
void SeqVec::Set(double value){

	int i;
	for(i=0;i<this->M;i++)this->vector[i]=value;

}
/*}}}*/
/*FUNCTION SeqVec::AXPY{{{1*/
void SeqVec::AXPY(SeqVec* X, double a){

	int i;

	/*y=a*x+y where this->vector is y*/
	for(i=0;i<this->M;i++)this->vector[i]=a*X->vector[i]+this->vector[i];
	
}
/*}}}*/
/*FUNCTION SeqVec::AYPX{{{1*/
void SeqVec::AYPX(SeqVec* X, double a){
	
	int i;

	/*y=x+a*y where this->vector is y*/
	for(i=0;i<this->M;i++)this->vector[i]=X->vector[i]+a*this->vector[i];

}
/*}}}*/
/*FUNCTION SeqVec::ToMPISerial{{{1*/
double* SeqVec::ToMPISerial(void){

	double* buffer=NULL;

	if(this->M){
		buffer=(double*)xmalloc(this->M*sizeof(double));
		memcpy(buffer,this->vector,this->M*sizeof(double));
	}
	return buffer;

}
/*}}}*/
/*FUNCTION SeqVec::Copy{{{1*/
void SeqVec::Copy(SeqVec* to){

	int i;

	to->M=this->M;
	for(i=0;i<this->M;i++)to->vector[i]=this->vector[i];

}
/*}}}*/
/*FUNCTION SeqVec::Norm{{{1*/
double SeqVec::Norm(NormMode mode){

	double norm;
	int i;

	switch(mode){
		case NORM_INF:
			norm=0; for(i=0;i<this->M;i++)norm=max(norm,fabs(this->vector[i]));
			return norm;
			break;
		case NORM_TWO:
			norm=0; 
			for(i=0;i<this->M;i++)norm+=pow(this->vector[i],2);
			return sqrt(norm);
			break;
		default:
			_error_("unknown norm !");
			break;
	}
}
/*}}}*/
/*FUNCTION SeqVec::Scale{{{1*/
void SeqVec::Scale(double scale_factor){

	int i;
	for(i=0;i<this->M;i++)this->vector[i]=scale_factor*this->vector[i];
	
}
/*}}}*/
/*FUNCTION SeqVec::Dot{{{1*/
double SeqVec::Dot(SeqVec* input){

	int i;

	double dot=0;
	for(i=0;i<this->M;i++)dot+=this->vector[i]*input->vector[i];
	return dot;

}
/*}}}*/
/*FUNCTION SeqVec::PointwiseDivide{{{1*/
void SeqVec::PointwiseDivide(SeqVec* x,SeqVec* y){

	int i;
	/*pointwise w=x/y where this->vector is w: */
	for(i=0;i<this->M;i++)this->vector[i]=x->vector[i]/y->vector[i];
}
/*}}}*/
