#include "linmatrix.h"
#include <float.h>
#include <math.h>

linmx* linmx_create(int rows, int cols){
         int i;
	linmx* mx=(linmx*)malloc(sizeof(linmx));
	if(mx==NULL)return NULL;
	mx->data=(double*)malloc((rows+1)*(cols+2)*sizeof(double));
	if(mx->data==NULL){
		free(mx);
		return NULL;
	}
	memset(mx->data,0,(rows+1)*(cols+2)*sizeof(double));
	mx->rows=rows;
	mx->cols=cols;
        mx->eps=EPS;
        for(i=1;i<=rows;++i) linmx_setrowfactor(mx,i,1);
        for(i=1;i<=cols;++i) linmx_setcolfactor(mx,i,1);
	return mx;
}
/******************************************************************************************/
void   linmx_dispose(linmx* mx){

	if (!mx) return;
	if (!mx->data) free(mx->data);
	free(mx);
	return;
}
/******************************************************************************************/
int    linmx_copy(linmx* from,linmx* to){
	if(!from) return 0;
	if(!to)	return 0;
	free(to->data);
	to->rows=from->rows;
	to->cols=from->cols;
        to->eps=from->eps;
        to->data=(double*)malloc((to->rows+1)*(to->cols+2)*sizeof(double));
	memcpy(to->data,from->data,(to->rows+1)*(to->cols+2)*sizeof(double));
        return 1;
}

/******************************************************************************************/
double* linmx_getcol(linmx* mx,int col){
        assert(1<=col&&col<=mx->cols);
        int i;
        double *val=(double *)malloc(mx->rows*sizeof(double));
        if (!val) return NULL;
        for(i=0;i<mx->rows;++i){
                val[i]=linmx_getat(mx,i+1,col);
        }
        return val;
}
/******************************************************************************************/
void	 linmx_setcol(linmx* mx,int col, double val[]){
        assert(1<=col&&col<=mx->cols);
        int i;
        if (!val) return ;
        for(i=0;i<mx->rows;++i){
                linmx_setat(mx,i+1,col,val[i]);
        }
}
/******************************************************************************************/

double* linmx_getrow(linmx* mx,int row){
        assert(1<=row&&row<=mx->rows);
        int i;
        double *val=(double *)malloc(mx->cols*sizeof(double));
        if (!val) return NULL;
        memcpy(val,&mx->data[row*(mx->cols+2)+1],mx->cols*sizeof(double));
        return val;

}
/******************************************************************************************/
void    linmx_setrow(linmx* mx,int row, double val[]){
        assert(1<=row&&row<=mx->rows);
        int i;
        if (!val) return ;
        memcpy(&mx->data[row*(mx->cols+2)+1],val,mx->cols*sizeof(double));

}
/******************************************************************************************/
double   linmx_getcond(linmx* mx){
         int i=0;
         int j=0;
         double max=-DBL_MAX;
         double min= DBL_MAX;

         if(mx==NULL) return 0;
         
         for(i=1;i<=mx->rows;++i){
                  for(j=1;j<=mx->cols;++j){
                      double temp=fabs(linmx_getat(mx,i,j));
                      if(temp>-EPS&&temp<EPS) continue;
                      if(temp>max) max=temp;
                      if(temp<min) min=temp;
                  }
         }
         if (min==DBL_MAX) return 0;
         return max/min;
}
/******************************************************************************************/
double*       linmx_getrhsvect(linmx* mx){
        int i;
        double *val=(double *)malloc(mx->rows*sizeof(double));
        if (!val) return NULL;
        for(i=0;i<mx->rows;++i){
                val[i]=linmx_getrhs(mx,i+1);
        }
        return val;

}
