/* 
 * VecTest.c - homogeneous 4 vector abstract data type test program.
 * 
 * Author:   L. Van Warren
 * Date:     April 1984
 * Copyright (c) 1984-1995 L. Van Warren * All Rights Reserved
 */

#include "Van.h"

#define N 1000000 /* Change this to 1 to count debugger instructions. */
#define TIMEUP(label, x) {elapsed=clock()-start;fprintf(stdout, "%s\t%f\n",label,(float)(elapsed)/CLOCKS_PER_SEC);x+=elapsed;}

extern void testVec(int portion);
extern void testVecCorrect(void);
extern void testVecIO(void);
extern void testVecTiming(void);

void
testVecCorrect(void)
{
	int i, j, k;
    Vec a, b;

	fprintf(stdout, "PART ONE: CORRECTNESS TEST\n");
     
	a = asnVec(1.0, -2.0, 3.0, 0.0);
	b = asnVec(3.0,  2.0, 1.0, 0.0);
	 
	fprintf(stdout, "             a is: "); fprintVec(stdout, a);
	fprintf(stdout, "             b is: "); fprintVec(stdout, b);
	fprintf(stdout, "         a + b is: "); fprintVec(stdout, addVec(a, b));
	fprintf(stdout, "         a - b is: "); fprintVec(stdout, subVec(a, b));
	fprintf(stdout, "         a * b is: "); fprintVec(stdout, mulVec(a, b));
	fprintf(stdout, "         2 * a is: "); fprintVec(stdout, sclVec(2.0, a));
	fprintf(stdout, "         a x b is: "); fprintVec(stdout, crsVec(a, b));
	fprintf(stdout, "        abs(a) is: "); fprintVec(stdout, absVec(a));
	fprintf(stdout, "        nrm(a) is: "); fprintVec(stdout, nrmVec(a));
	fprintf(stdout, " lrp(a,b, 0.5) is: "); fprintVec(stdout, lrpVec(a, b, 0.5));
	fprintf(stdout, "         a . b is: "); fprintf(stdout, "%10.6f\n", dotVec(a, b));
	
	for(i = -1; i < 2; i += 2)
	for(j = -1; j < 2; j += 2)
	    for(k = -1; k < 2; k += 2)
	    {
	        a = asnVec( FLOAT(i), FLOAT(j), FLOAT(k), 0.0);
	        fprintf(stdout, "a is: "); fprintVec(stdout, a);
	
	        fprintf(stdout, "CartesianTospherical(a): ");
	        fprintVec(stdout, b=CartesianTosphericalVec(a));
	
	        fprintf(stdout, "sphericalToCartesian(b): ");
	        fprintVec(stdout, sphericalToCartesianVec(b));
	        fprintf(stdout, "\n");
	    }
	
	for(i = -1; i < 2; i += 2)
	for(j = -1; j < 2; j += 2)
	    for(k = -1; k < 2; k += 2)
	    {
	        a = asnVec( FLOAT(i), FLOAT(j), FLOAT(k), 0.0);
	        fprintf(stdout, "a is: "); fprintVec(stdout, a);
	
	        fprintf(stdout, "CartesianTolatlonrho(a): ");
	        fprintVec(stdout, b=CartesianTolatlonrhoVec(a));
	
	        fprintf(stdout, "latlonrhoToCartesian(b): ");
	        fprintVec(stdout, latlonrhoToCartesianVec(b));
	        fprintf(stdout, "\n");
	    }
	
	for(i = -1; i < 2; i += 2)
	for(j = -1; j < 2; j += 2)
	    for(k = -1; k < 2; k += 2)
	    {
	        a = asnVec( FLOAT(i), FLOAT(j), FLOAT(k), 0.0);
	        fprintf(stdout, "a is: "); fprintVec(stdout, a);
	
	        fprintf(stdout, "CartesianTocylindrical(a): ");
	        fprintVec(stdout, b=CartesianTocylindricalVec(a));
	
	        fprintf(stdout, "cylindricalToCartesian(b): ");
	        fprintVec(stdout, cylindricalToCartesianVec(b));
	        fprintf(stdout, "\n");
	    }
}

void
testVecIO(void)
{
	Vec a;
	FILE *asc_file, *bin_file;


	fprintf(stdout, "\nPART TWO: I/O TEST\n");

	a = asnVec(3.0, 2.0, 1.0, 1.0);
	fprintf(stdout, " a  is: ");
	fprintVec(stdout, a);
	
	fprintf(stdout, "writing vector a to ascii file:\n");
	asc_file = fopen("test.asc", "w");
	fprintVec(asc_file, a);
	fclose(asc_file);
	
	fprintf(stdout, "reading a from ascii file:\n");
	asc_file = fopen("test.asc", "r");
	a = fscanVec(asc_file);
	fprintVec(stdout, a);
	fclose(asc_file);
	
	fprintf(stdout, "writing vector a to binary file:\n");
	bin_file = fopen("test.bin", "w");
	fwriteVec(bin_file, a);
	fclose(bin_file);
	
	fprintf(stdout, "reading a from binary file:\n");
	bin_file = fopen("test.bin", "r");
	fprintVec(stdout, freadVec(bin_file));
	fclose(bin_file);
}


void
testVecTiming(void)
{
	int n;
	double f;
	clock_t start, elapsed, CTotal=0;
	Vec a, b, c;

	fprintf(stdout, "\nPART THREE: TIMING TEST\n");	
	
	a = asnVec(1, 2, 3, 0);
	
	fprintf(stdout, "C Vec4\n");
	fprintf(stdout, "%d\tcalls\n", N);
	fprintf(stdout, "Function\tElapsed Time (s)\n");
	
	for(start = clock (), n = 0; n < N; n++) { b = asnVec(1, 2, 3, 0);}
	TIMEUP("asn", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = addVec(a, b);}
	TIMEUP("add", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = subVec(a, b);}
	TIMEUP("sub", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = mulVec(a, b);}
	TIMEUP("mul", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = divVec(a, b);}
	TIMEUP("div", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = sclVec(2, b);}
	TIMEUP("scl", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = crsVec(a, b);}
	TIMEUP("crs", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = absVec(a);}
	TIMEUP("abs", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = nrmVec(a);}
	TIMEUP("nrm", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = lrpVec(a, b, 0.5);}
	TIMEUP("lrp", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { f = dotVec(a, b);}
	TIMEUP("dot", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = latlonrhoToCartesianVec(a);}
	TIMEUP("l2c", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = CartesianTolatlonrhoVec(a);}
	TIMEUP("c2l", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = sphericalToCartesianVec(a);}
	TIMEUP("s2C", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = CartesianTosphericalVec(a);}
	TIMEUP("C2s", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = sphericalTolatlonrhoVec(a);}
	TIMEUP("s2l", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = latlonrhoTosphericalVec(a);}
	TIMEUP("l2s", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = cylindricalToCartesianVec(a);}
	TIMEUP("c2C", CTotal);
	
	for(start = clock (), n = 0; n < N; n++) { c = CartesianTocylindricalVec(a);}
	TIMEUP("C2c", CTotal);

	fprintf(stdout, "Elapsed Time\t%f\ts.\n", (float)CTotal/CLOCKS_PER_SEC);
}

void testVec(int portion)
{
	fprintf(stdout, "Vector numerical algebra library: \n");
    
	while(1)
	{
			
		fprintf(stdout, "0) Return\n");
		fprintf(stdout, "1) Correctness\n");
		fprintf(stdout, "2) I/O\n");
		fprintf(stdout, "3) Timing\n");
		fprintf(stdout, "Press a number to test a package.\n");
		
		fscanf(stdin, "%d", &portion);
		
		fprintf(stdout, "You typed %d.\n", portion);
	
		switch(portion)
		{
			case 0:
				return;
			break;
			
			case 1:
				testVecCorrect();
			break;
			
			case 2:
				testVecIO();
			break;
			
			case 3:
				testVecTiming();
			break;
							
			default:
				fprintf(stdout, "No such choice as %d\n", portion);
			break;
		}
	}
}