// this matrix_c09.cpp file has the file I/O subroutines.



#include <stdio.h>
#include "matrix_dll.h"
#include "StdAfx.h"
#include "matrix_h09.h"





void matrix_print(FILE *outfile, MAT *array, char *title) {
	unsigned long i, j, imx, jmx;
	imx = array->imx; jmx = array->jmx;
	fprintf(outfile, "%s\n", title);
	for(i=0; i<imx; i++) {
		fprintf(outfile, "row=%d  ", i);
		for(j=0; j<jmx; j++) {
			fprintf(outfile, "%+1.6f  ", arsub(array, i, j)); };
		fprintf(outfile, "\n"); };
	return; };


//	 writes a title.
//	 the file must be open for writing and pre-positioned.

void matrix_write_title(FILE *event_data_file, unsigned long code, char *title) {
	fprintf(event_data_file, "%d %s\n", code, title);
	return; };


//	 reads a title.
//	 the file must be open for writing and pre-positioned.

int matrix_read_title(FILE *event_data_file, unsigned long code, char *title) {
	const char *string[]={"an event-data", "a real-array", "a complex-array"};
	unsigned long code_in_file, cif, c;
	int y=0;
	fscanf(event_data_file, "%d %s", &code_in_file, title);
	cif = (code_in_file - 1) % 3; c = (code - 1) % 3;
	if(cif != c) {
		printf("reading %d %s file; but, expecting %d %s file. \n", code_in_file, string[cif], code, string[c]);
		y = 8; };
	if(y != 0) goto tie_point;
tie_point:
	return(y); };


//	 writes an event data-file header.
//	 the file must be open for writing and pre-positioned.

void matrix_write_event_data_header(FILE *event_data_file, char *title, unsigned long left_size,
								   unsigned long right_size, unsigned long multiplier,
								   unsigned long amount) {
	const unsigned long code=1;
	matrix_write_title(event_data_file, code, title);
	fprintf(event_data_file, "%d %d %d %d\n", left_size, right_size, multiplier, amount);
	return; };


//	 writes a single row of an event data-file data.
//	 the file must be open for writing and pre-positioned.

void matrix_write_event_data_row(FILE *event_data_file, unsigned long left_size,
								   unsigned long right_size, double *xx, double *yy,
								   unsigned long multiplier) {
	unsigned long j;
	for(j=0; j<left_size; j++) fprintf(event_data_file, "%.0f ", xx[j] * multiplier);
	fprintf(event_data_file, "   ");
	for(j=0; j<right_size; j++) fprintf(event_data_file, "%.0f ", yy[j] * multiplier);
	fprintf(event_data_file, "\n");
	return; };


//	writes a pseudo-random event data-file.  the title string must not contain any spaces.
//	the file must be open for writing and pre-positioned.

int matrix_write_event_data(FILE *event_data_file, char *title,
							unsigned long left_size, unsigned long right_size,
							unsigned long multiplier, unsigned long amount) {
	double u, v, xx[MAX_SIZE], yy[MAX_SIZE];
	unsigned long size, j, k;
	int y=0;
	matrix_write_event_data_header(event_data_file, title, left_size, right_size,
		multiplier, amount);
	size = matrix_max(left_size, right_size);
	for(k=0; k<amount; k++) {
		for(j=0; j<size; j++) {
			u = pseudo_random(); v = pseudo_random();
			y = Gaussian_event_coords(u, v, &(xx[j]), &(yy[j]));
			if(y != 0) goto tie_point; };
		matrix_write_event_data_row(event_data_file, left_size, right_size,
			xx, yy, multiplier); };
	fprintf(event_data_file, "this_is_the_end_of_the_data_file\n");
tie_point:
	return(y); };


//	reads an event data-file header.
//	the file must be open for reading and pre-positioned.

int matrix_read_event_data_header(FILE *event_data_file, char *title, unsigned long *left_size,
								   unsigned long *right_size, unsigned long *multiplier,
								   double *divisor, unsigned long *amount) {
	const double ONE=1.0;
	const unsigned long code=1;
	int y=0;
	y = matrix_read_title(event_data_file, code, title);
	if(y != 0) goto tie_point;
	fscanf(event_data_file, "%d %d %d %d", left_size, right_size, multiplier, amount);
	printf("the title %s, left size %d, right size %d, multiplier %d, and amount %d \n",
		title, *left_size, *right_size, *multiplier, *amount);
	*divisor = ONE / ((double )*multiplier);
tie_point:
	return(y); };


//	 reads a single row of an event data-file data.
//	 the file must be open for reading and pre-positioned.

void matrix_read_event_data_row(FILE *event_data_file, unsigned long size,
								double *vect_x, double divisor) {
	double x;
	unsigned long j;
	for(j=0; j<size; j++) {
		fscanf(event_data_file, "%lf", &x);
		vect_x[j] = x * divisor; };
		return; };


//	reads an event data-file.  yields the title, variance, and average.
//	the file must be open for reading and pre-positioned.

int matrix_read_event_data(FILE *event_data_file, char *title, MAT *array, MAT *average) {
	const double ONE=1.0;
	double zz[2 * MAX_SIZE], divisor, one_over_amount;
	unsigned long left_size, right_size, size, multiplier, amount, i, j, k;
	int y=0;
	y =	matrix_read_event_data_header(event_data_file, title, &left_size, &right_size,
			&multiplier, &divisor, &amount);
	if(y != 0) goto tie_point;
	size = left_size + right_size; one_over_amount = ONE / ((double )amount);
	array->imx = size; array->jmx = size;
	y = matrix_zero(array);
	if(y != 0) goto tie_point;
	average->imx = 1; average->jmx = size;
	y = matrix_zero(average);
	if(y != 0) goto tie_point;
	for(k=0; k<amount; k++) {
		matrix_read_event_data_row(event_data_file, size, zz, divisor);
		for(j=0; j<size; j++) {
			arsub(average, 0, j) += zz[j];
			for(i=0; i<size; i++) {
				arsub(array, i, j) += zz[i] * zz[j]; }; }; };
	for(j=0; j<size; j++) {
		arsub(average, 0, j) *= one_over_amount; };
	for(i=0; i<size; i++) {
		for(j=0; j<size; j++) {
			arsub(array, i, j) *= one_over_amount;
			arsub(array, i, j) -= arsub(average, 0, i) * arsub(average, 0, j); }; };
	array->imp = left_size; array->jmp = left_size; array->part = 1;
	array->sym = 1; array->positive = 1;
	average->jmp = left_size; average->part = 1; average->sym = 0;
tie_point:
	return(y); };


//	writes a matrix to a file, which must be open for writing and pre-positioned.
//	the title string must not contain any spaces.

int matrix_write_array(FILE *array_file, char *title, unsigned long multiplier,
					   MAT *array, MAT *scratch_1) {
	const unsigned long code=2;
	double norm, x;
	unsigned long i, j, imx, jmx, mult;
	int y=0;
	y = matrix_validate(array);
	if(y != 0) goto tie_point;
	imx = array->imx; jmx = array->jmx;
	y = matrix_norm(array, 1, &norm, scratch_1);
	if(y != 0) goto tie_point;
	mult = (unsigned long) (multiplier / norm);
	matrix_write_title(array_file, code, title);
	fprintf(array_file, "%d %d %d %d %d %d %d %d %d    %d %d \n",
		array->imx, array->jmx, array->mx, array->imp, array->jmp,
		array->sym, array->cmp, array->part, array->positive,
		array->inh.valid_t, array->inh.valid_d);
	fprintf(array_file, "%d   %.0f %.0f \n", mult,
		array->inh.trace * mult, array->inh.determinant * mult);
	for(i=0; i<imx; i++) {
		for(j=0; j<jmx; j++) {
			x = arsub(array, i, j) * mult;
			fprintf(array_file, "%.0f ", x); };
		fprintf(array_file, "\n"); };
	fprintf(array_file, "this_is_the_end_of_the_array_file\n");
tie_point:
	return(y); };


//	reads a matrix from a file, which must be open for reading and pre-positioned.
//	yields a title and an array.

int matrix_read_array(FILE *array_file, char *title, MAT *array) {
	const double ONE=1.0;
	const unsigned long code=2;
	double x1, x2, x, divisor;
	unsigned long multiplier, i, j, imx, jmx;
	int y=0;
	y = matrix_read_title(array_file, code, title);
	if(y != 0) goto tie_point;
	fscanf(array_file, "%d %d", &imx, &jmx);
	array->imx = imx; array->jmx = jmx;
	y = matrix_zero(array);
	if(y != 0) goto tie_point;
	fscanf(array_file, "%d %d %d %d %d %d %d    %d %d ",
		&array->mx, &array->imp, &array->jmp,
		&array->sym, &array->cmp, &array->part, &array->positive,
		&array->inh.valid_t, &array->inh.valid_d);
	fscanf(array_file, "%d %lf %lf", &multiplier, &x1, &x2);
	divisor = ONE / ((double )multiplier);
	array->inh.trace = x1 * divisor; array->inh.determinant = x2 * divisor;
	y = matrix_validate(array);
	if(y != 0) {
		printf("the array did not validate! \n");
		goto tie_point; };
	for(i=0; i<imx; i++) {
		for(j=0; j<jmx; j++) {
			fscanf(array_file, "%lf ", &x);
			arsub(array, i, j) = x * divisor; }; };
tie_point:
	return(y); };


//	writes a complex matrix to a file, which must be open for writing and pre-positioned.
//	the title string must not contain any spaces.

int matrix_write_complex_array(FILE *array_file, char *title, unsigned long multiplier,
					   matrix_cmplx *array, MAT *scratch_1, MAT *scratch_2,
					   MAT *scratch_3, MAT *scratch_4, MAT *scratch_5) {
	const unsigned long code=3;
	double norm, u, v;
	unsigned long i, j, imx, jmx, mult, subs;
	int y=0;
	y = matrix_validate_cmplx(array);
	if(y != 0) goto tie_point;
	imx = array->imx; jmx = array->jmx;
	y=matrix_cmplx_real(array, scratch_2, scratch_3, scratch_4, scratch_5);
	if(y != 0) goto tie_point;
	y = matrix_norm(scratch_2, 1, &norm, scratch_1);
	if(y != 0) goto tie_point;
	mult = (unsigned long) (multiplier / norm);
	matrix_write_title(array_file, code, title);
	fprintf(array_file, "%d %d %d %d    %d %d \n",
		array->imx, array->jmx, array->mx, array->sym,
		array->inh.valid_t, array->inh.valid_d);
	fprintf(array_file, "%d   %.0f %.0f \n", mult,
		array->inh.trace.a * mult, array->inh.trace.b * mult, array->inh.sqmagdet * mult * mult);
	for(i=0; i<imx; i++) {
		for(j=0; j<jmx; j++) {
			subs = i+j*imx;
			u = array->a[subs].a * mult; v = array->a[subs].b * mult;
			fprintf(array_file, "%.0f %.0f  ", u, v); };
		fprintf(array_file, "\n"); };
	fprintf(array_file, "this_is_the_end_of_the_complex_array_file\n");
tie_point:
	return(y); };


//	reads a complex matrix from a file, which must be open for reading and pre-positioned.
//	yields a title and an array.

int matrix_read_complex_array(FILE *array_file, char *title, matrix_cmplx *array,
							  MAT *scratch_1, MAT *scratch_2, MAT *scratch_3, MAT *scratch_4,
							  MAT *scratch_5, MAT *scratch_6, MAT *scratch_7) {
	const double ONE=1.0;
	const unsigned long code=3;
	double u, v, x2, divisor;
	unsigned long multiplier, i, j, imx, jmx, subs;
	int y=0;
	y = matrix_read_title(array_file, code, title);
	if(y != 0) goto tie_point;
	fscanf(array_file, "%d %d", &imx, &jmx);
	scratch_1->imx = 2 * imx; scratch_1->jmx = 2 * jmx;
	y = matrix_zero(scratch_1);
	if(y != 0) goto tie_point;
	scratch_1->cmp = 1; scratch_1->imp = imx; scratch_1->jmp = jmx;
	y = matrix_real_cmplx(scratch_1, array, scratch_2, scratch_3, scratch_4,
			scratch_5, scratch_6, scratch_7);
	if(y != 0) goto tie_point;
	fscanf(array_file, "%d %d    %d %d ",
		&array->mx, &array->sym, &array->inh.valid_t, &array->inh.valid_d);
	fscanf(array_file, "%d %lf %lf %lf", &multiplier, &u, &v, &x2);
	divisor = ONE / ((double )multiplier);
	array->inh.trace.a = u * divisor; array->inh.trace.b = v * divisor;
	array->inh.sqmagdet = x2 * divisor * divisor;
	y = matrix_validate_cmplx(array);
	if(y != 0) {
		printf("the array did not validate! \n");
		goto tie_point; };
	for(i=0; i<imx; i++) {
		for(j=0; j<jmx; j++) {
			fscanf(array_file, "%lf %lf ", &u, &v);
			subs = i+j*imx;
			array->a[subs].a = u * divisor; array->a[subs].b = v * divisor; }; };
tie_point:
	return(y); };

//	reads an event_data_file_x.  yields the title_x.
//	performs the linear transformation y = (x - average_x) * array + average_y.
//	writes a new event_data_file_y, with the provided title_y.
//	within the scope of Linear Algebra, the array should be a positive definite
//		partitioned symmetric matrix; but, this subroutine will accept any array.
//		also, the partitioning should correspond to that of the event_data_file_x.
//	the file event_data_file_x must be open for reading and pre-positioned.
//	the file event_date_file_y must be open for writing and pre-popitioned.
//	will return an error-code of 64 if the left_size + right_size of the event_data_file_x
//		is not equal to the jmx (horizontal size) of the average_x.

int matrix_read_process_event_data1(FILE *event_data_file_x, char *title_x,
									MAT *average_x, MAT *array, MAT *average_y,
									FILE *event_data_file_y, char *title_y,
									MAT *scratch) {
	double x_vect[2 * MAX_SIZE], xo_vect[2 * MAX_SIZE], yo_vect[2 * MAX_SIZE],
		y_vect[2 * MAX_SIZE], divisor;
	unsigned long j, k, jmx, jmy, left_size_x, right_size_x, size_x, multiplier, amount,
		left_size_y, right_size_y, size_y;
	int y;
	y = matrix_validate(average_x) + matrix_validate(array)+matrix_validate(average_y) +
			matrix_check_compatibility_multiply(average_x, array);
	if(y != 0) goto tie_point;
	y = matrix_transpose(average_y, scratch);
	if(y != 0) goto tie_point;
	y = matrix_check_compatibility_multiply(array, scratch);
	if(y != 0) goto tie_point;
	jmx = average_x->jmx;
	for(j=0; j<jmx; j++) {
		xo_vect[j] = arsub(average_x, 0, j); };
	jmy = average_y->jmx;
	for(j=0; j<jmy; j++) {
		yo_vect[j] = arsub(average_y, 0, j); };
	matrix_read_event_data_header(event_data_file_x, title_x, &left_size_x, &right_size_x,
		&multiplier, &divisor, &amount);
	size_x = left_size_x + right_size_x;
	if(size_x != jmx) y += 64;
	if(y != 0) goto tie_point;
	left_size_y = (array->part == 0)? (0): (array->jmp);
	size_y = array->jmx; right_size_y = size_y - left_size_y;
	matrix_write_event_data_header(event_data_file_y, title_y, left_size_y, right_size_y,
		multiplier, amount);
	for(k=0; k<amount; k++) {
		matrix_read_event_data_row(event_data_file_x, size_x, x_vect, divisor);
		y = matrix_compute_regression(x_vect, xo_vect, array, yo_vect, y_vect);
		if(y != 0) goto tie_point;
		matrix_write_event_data_row(event_data_file_y, left_size_y, right_size_y,
			y_vect, &(y_vect[left_size_y]), multiplier); };
	fprintf(event_data_file_y, "this_is_the_end_of_the_data_file\n");
tie_point:
	return(y); };


//	reads an event_data_file_x.  yields the title_x.
//	performs the linear transformation y = (x - average_x) * array + average_y.
//	writes the regression as a new event_data_file_y, with the provided title_y and
//		the residue as a new event_data_file_r, with the provided title_r.
//	within the scope of Linear Algebra, the array should be a positive definite
//		symmetric matrix; but, this subroutine will accept any array.
//	the file event_data_file_x must be open for reading and pre-positioned.
//	the file event_date_file_y must be open for writing and pre-popitioned.
//	the file event_date_file_r must be open for writing and pre-popitioned.
//	will return an error-code of 64 if either the left_size of the event_data_file_x
//		is not equal to the jmx (horizontal size) of the average_x or
//		the right_size of the event_data_file_x
//		is not equal to the jmx (horizontal size) of the average_y.
//	sw:  0=x to y, 1=y to x.
int matrix_read_process_event_data2(FILE *event_data_file_x, char *title_x,
									MAT *average_x, MAT *array, MAT *average_y,
									unsigned long sw,
									FILE *event_data_file_y, char *title_y,
									FILE *event_data_file_r, char *title_r,
									MAT *scratch) {
	double x_vect[2 * MAX_SIZE], xo_vect[MAX_SIZE], yo_vect[MAX_SIZE],
		y_vect[MAX_SIZE], r_vect[MAX_SIZE], divisor;
	unsigned long j, k, left_size_x, right_size_x, size_x, multiplier, amount;
	int y;
	y = matrix_validate(average_x) + matrix_validate(array)+matrix_validate(average_y) +
			matrix_check_compatibility_multiply(average_x, array);
	if(y != 0) goto tie_point;
	y = matrix_transpose(average_y, scratch);
	if(y != 0) goto tie_point;
	y = matrix_check_compatibility_multiply(array, scratch);
	if(y != 0) goto tie_point;
	matrix_read_event_data_header(event_data_file_x, title_x, &left_size_x, &right_size_x,
		&multiplier, &divisor, &amount);
	size_x = left_size_x + right_size_x;
	if(left_size_x != average_x->jmx || right_size_x != average_y->jmx) y += 64;
	if(y != 0) goto tie_point;
	for(j=0; j<left_size_x; j++) {
		xo_vect[j] = arsub(average_x, 0, j); };
	for(j=0; j<right_size_x; j++) {
		yo_vect[j] = arsub(average_y, 0, j); };
	matrix_write_event_data_header(event_data_file_y, title_y, left_size_x, right_size_x,
		multiplier, amount);
	matrix_write_event_data_header(event_data_file_r, title_r, left_size_x, right_size_x,
		multiplier, amount);
	for(k=0; k<amount; k++) {
		matrix_read_event_data_row(event_data_file_x, size_x, x_vect, divisor);
		if((sw % 2) == 0) {			// x to y.
			y = matrix_compute_regression(x_vect, xo_vect, array, yo_vect, y_vect);
			if(y != 0) goto tie_point;
			matrix_write_event_data_row(event_data_file_y, left_size_x, right_size_x,
				x_vect, y_vect, multiplier);
			for(j=0; j<right_size_x; j++) {
				r_vect[j] = x_vect[j + left_size_x] - y_vect[j]; };
			matrix_write_event_data_row(event_data_file_r, left_size_x, right_size_x,
				x_vect, r_vect, multiplier); }
		else {						// y to x.
			y = matrix_compute_regression(&x_vect[left_size_x], yo_vect, array, xo_vect, y_vect);
			if(y != 0) goto tie_point;
			matrix_write_event_data_row(event_data_file_y, left_size_x, right_size_x,
				y_vect, &x_vect[left_size_x], multiplier);
			for(j=0; j<right_size_x; j++) {
				r_vect[j] = y_vect[j] - x_vect[j]; };
			matrix_write_event_data_row(event_data_file_r, left_size_x, right_size_x,
				r_vect, &x_vect[left_size_x], multiplier); }; };
	fprintf(event_data_file_y, "this_is_the_end_of_the_data_file\n");
	fprintf(event_data_file_r, "this_is_the_end_of_the_data_file\n");
tie_point:
	return(y); };


//	from the positive-definite symmetric-matrix variance_in and horizontal-vector average_in,
//		generates or constructs the ellipsoidal events file.
//	then, computes its variance and average.
//	also, checks this variance matrix to be symmetric --> residue_symmetric,
//	this variance to be equal to the variance_in --> relative_var, and
//	this average to be equal to the average_in.
//	if construct is zero, will only generate; if one, will actually construct.
//		the average_in must be a horizontal-vector of the same size and
//		partitioning as the variance_in.
//	to be usable directly as an event data-set for a channel,
//		the partitioning must be in the middle.
int matrix_ellipsoidal_events(MAT *array_var_in, MAT *array_ave_in, unsigned long construct,
							  unsigned long multiplier, unsigned long amount,
							  char *ellipsoidal_events_name, char *ellipsoidal_events_title,
							  MAT *array_var, MAT *array_ave,
							  double *residue_symmetric,
							  double *relative_var, double *relative_ave,
							  char *scratch_events_name, char *scratch_events_title,
							  MAT *scratch_1, MAT *scratch_2, MAT *scratch_3, MAT *scratch_4,
							  MAT *scratch_5, MAT *scratch_6, MAT *scratch_7) {
	unsigned long amt;
	int y=0;
	FILE *scratch_events, *ellipsoidal_events;
	unsigned long sort=0, left_size, right_size;
	char title[200];
	y = matrix_validate(array_var_in) + matrix_validate(array_ave_in) +
			matrix_check_compatibility_multiply(array_ave_in, array_var_in);
	if(array_var_in->sym != 1 && array_var_in->sym != 4 && array_var_in->sym != 5) y += 16;
	if(y != 0) goto tie_point;
	left_size = (array_var_in->part == 0)? (0): (array_var_in->imp);
	right_size = array_var_in->imx - left_size;
	if(construct != 0) {
		amt = (array_var_in->imx + 1) * (array_var_in->imx + 1);
		if(amount < amt) amount = amt; };
	scratch_events = fopen(scratch_events_name, "w");
	y = matrix_write_event_data(scratch_events, scratch_events_title, left_size, right_size,
			multiplier, amount);
	fclose(scratch_events);
	if(y != 0) goto tie_point;
	scratch_events = fopen(scratch_events_name, "r");
	y = matrix_read_event_data(scratch_events, title, scratch_1, scratch_3);
	fclose(scratch_events);
	if(y != 0) goto tie_point;
	if(construct == 0) {		// generate.
		scratch_2->imx = scratch_2->imx; scratch_2->jmx = scratch_3->jmx;
		if(y != 0) goto tie_point;
		y = matrix_zero(scratch_2);
		if(y != 0) goto tie_point;
		matrix_propagate_default(scratch_3, scratch_2);
		y = matrix_square_root0(array_var_in, sort, scratch_3, scratch_4, scratch_5,
				scratch_6, scratch_7);
		if(y != 0) goto tie_point; }
	else {						// construct.
		y = matrix_copy(scratch_3, scratch_2);
		if(y != 0) goto tie_point;
		y = matrix_square_root2(scratch_1, array_var_in, sort, scratch_3, scratch_4,
				scratch_5, scratch_6, scratch_7, array_var, array_ave); 
		if(y != 0) goto tie_point; };	// array_var and array_ave are employed as scratch.
	scratch_events = fopen(scratch_events_name, "r");
	ellipsoidal_events = fopen(ellipsoidal_events_name, "w");
	y = matrix_read_process_event_data1(scratch_events, title, scratch_2, scratch_3,
			array_ave_in, ellipsoidal_events, ellipsoidal_events_title, scratch_1);
	fclose(scratch_events);
	fclose(ellipsoidal_events);
	if(y != 0) goto tie_point;
	ellipsoidal_events = fopen(ellipsoidal_events_name, "r");
	y = matrix_read_event_data(ellipsoidal_events, title, array_var, array_ave);
	fclose(ellipsoidal_events);
	if(y != 0) goto tie_point;
	y = matrix_isit_symmetric(array_var, residue_symmetric, scratch_1, scratch_2,
			scratch_3, scratch_4);
	if(y != 0) goto tie_point;
	y = matrix_isit_equal(array_var_in, array_var, relative_var, scratch_1, scratch_2);
	if(y != 0) goto tie_point;
	y = matrix_isit_equal(array_ave_in, array_ave, relative_ave, scratch_1, scratch_2);
	if(y != 0) goto tie_point;
tie_point:
	return(y); };
	
	
//	employing the resources of the channel, performs a linear-regression upon the
//		ellipsoidal_events.  writes the regression into the regress_events and
//		the residues into the residues.
//	then, analyzes this residue file, to obtain its variance and average.
//	also, checks the variance to be symmetric --> residue_symmetric and
//		the norm of the average.
//	finally, computes the channel-rate R (and the corresponding Theta and rho) of the variance.
//	sw:  0=forward x to y, 1=forward y to x, 2=inverse x to y, 3=inverse y to x.
//	for the results to be meaningful,
//		the channel should be that obtained by analyzing the events or a relative.
int matrix_events_regress(CHN *chan, char *ellipsoidal_events_name, char *regress_events_name,
						  char *regress_events_title, char *residues_name, char *residues_title,
						  unsigned long sw, MAT *array_var, double *residue_symmetric,
						  double *R, double *Theta, double *rho,
						  MAT *array_ave, double *ave_norm, MAT *scratch_1, MAT *scratch_2,
						  MAT *scratch_3, MAT *scratch_4, MAT *scratch_5, MAT *scratch_6,
						  MAT *scratch_7) {
	FILE *ellipsoidal_events, *regress_events, *residues;
	unsigned long regression;
	int y=0;
	char title_ellipsoidal[200], title_check[200];
	y = matrix_validate(&chan->eleven[LAVE]) + matrix_validate(&chan->eleven[RAVE]) +
			matrix_validate(&chan->eleven[REGRxyFWD]) + matrix_validate(&chan->eleven[REGRxyINV]) +
			matrix_validate(&chan->eleven[REGRyxFWD]) + matrix_validate(&chan->eleven[REGRyxINV]);
	if(y != 0) goto tie_point;
	switch(sw %= 4) {
		case 0:			// x to y, forward.
			regression = REGRxyFWD;
			break;
		case 1:			// y to x  forward.
			regression = REGRyxFWD;
			break;
		case 2:			// x to y  inverse.		
			regression = REGRxyINV;
			break;
		case 3:			// y to x  inverse.
			regression = REGRyxINV;
			break; };
	ellipsoidal_events = fopen(ellipsoidal_events_name, "r");
	regress_events = fopen(regress_events_name, "w");
	residues = fopen(residues_name, "w");
	y = matrix_read_process_event_data2(ellipsoidal_events, title_ellipsoidal,
			&chan->eleven[LAVE], &chan->eleven[regression], &chan->eleven[RAVE], (sw % 2),
			regress_events, regress_events_title, residues, residues_title, scratch_1);
	fclose(ellipsoidal_events);
	fclose(regress_events);
	fclose(residues);
	if(y != 0) goto tie_point;
	residues = fopen(residues_name, "r");
	y = matrix_read_event_data(residues, title_check, array_var, array_ave);
	fclose(residues);
	if(y != 0) goto tie_point;	
	y = matrix_channel_rate(array_var, R, Theta, rho,
			scratch_1, scratch_2, scratch_3, scratch_4, scratch_5, scratch_6);
	if(y != 0) goto tie_point;
	y = matrix_isit_symmetric(array_var, residue_symmetric, scratch_1, scratch_2,
			scratch_3, scratch_4);
	if(y != 0) goto tie_point;
	y = matrix_norm(array_ave, 1, ave_norm, scratch_1);
	if(y != 0) goto tie_point;
tie_point:
	return(y); };


							  
							  
							  
// copyright (c) 2004 by R.I. 'Scibor-Marchocki.  last modified Wednesday 28-th April 2004.

// eof


