#include <stdio.h>
#include <math.h>
#include "pi.h"
#include "type.h"

/* structure which saves line parameters */

typedef struct {

	FILE *filein;

	} FILE_READ;

extern double T;
extern FILE *fdata;
extern COMPLEX unity,zero;

/**********************************************************************

			file()

************************************************************************

Function returns the ABCD matrix of a transfer function corresponding
to a transfer function which is read from a file

Each line of file is assumed to have following format: frequency real imag
File must have the appropriate number of lines -- automatically true
if file was generated by filtering LINEMOD output

The twoport does not affect the impedance, ie reproduces at its input
the impedance it sees at its output

Inputs: pointer to the data structure for the twoport and the frequency
Output: ABCD matrix for the twoport
*/

ABCD file(current,f)
TWOPORT *current; 	/* twoport being modeled */
double f;		/* frequency */

{
	ABCD tmsect;
	POINTER calloc();
	float f_from_file;
	char string[20];
	COMPLEX tf;
	FILE_READ *param;

/* the first time this function is called we simply read the parameters
   of the line from the input line */

	if(current->line != NULL) {

		/* allocate storage for the line parameters -- this
		   function may be called for many lines so it has to
		   be unique */

		if((current->param = calloc(1,sizeof(FILE_READ))) == NULL)
			error_alloc();

		param = (FILE_READ *) current->param;

		if(sscanf(current->line,"file %s",string) != 1) {
			fprintf(stderr,
		"file(): cannot read parameters on line\n%s\n",
			current->line);
			exit(1);
			}

		/* attempt to open the file */
		if((param->filein = fopen(string,"r")) == NULL) {
			fprintf(stderr,"Error: file %f could not\
			be opened\n",string);
			exit(2);
			}

		fprintf(fdata,"Data from file %s\n",string);
		}

/* every other time this function is called we calculate the ABCD matrix */

	else 	{

		param = (FILE_READ *) current->param;

		/* read one line from file */
		if(fscanf(param->filein,"%f %f %f",&f_from_file, 
			&tf.real,&tf.imag) == EOF) {
			fprintf(stderr,"Error:file: file ended prematurely\n");
			exit(3);
			}

		/* Exit if frequencies dont match */
		if(((f-f_from_file)*(f-f_from_file)) > (1.e-4*f*f)) {
			fprintf(stderr,"Error:file: frequencies don't match\n");
			exit(4);
			}

	/* ABCD matrix has 1/tf in A and D, zero otherwise --
	   this insures that the input impedance equals output impedance */

		/* if the transfer function is zero, 1/tf should be
		   make large to avoid float exception */
		if(tf.real*tf.real < 1.e-12 && tf.imag*tf.imag < 1.e-12)
			tmsect.a.real = tmsect.a.imag = 1.e6;
		else
			tmsect.a = cdiv(unity,tf);
		tmsect.d = tmsect.a;
		tmsect.b = tmsect.c = zero;
		}

	return(tmsect);
}
