#include <windows.h>
#include <math.h>
#include <string.h>

/*
Written by Kenneth E. Moore
June 5, 2000
*/

int __declspec(dllexport) APIENTRY UserGrinDefinition(double *data);
int __declspec(dllexport) APIENTRY UserParamNames(char *data);

BOOL WINAPI DllMain (HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
	{
   return TRUE;
   }

/* the data is stored as follows:
ndata = the number of elements in the array data
data[0]  = the total number of values in the passed data array
data[1]  = x
data[2]  = y
data[3]  = z
data[4]  = wavelength in microns
data[5]  = millimeters per unit length (1.0 for mm, 25.4 for inches, 10.0 for cm and 1000.0 for meters)
data[6]  = n (to be computed by the dll and returned)
data[7]  = n * dn/dx (to be computed by the dll and returned)
data[8]  = n * dn/dy (to be computed by the dll and returned)
data[9]  = n * dn/dz (to be computed by the dll and returned)
data[10] = parameter 1 from user input
data[11] = parameter 2 from user input
etc... up to data[maxdata] where maxdata = int(data[0])

The DLL must compute data 6 through 9 given the other data,
and return 0 if it works; else return -1
*/

/* this DLL models a GRIN media similar to the GRIN 6 surface type. */

int __declspec(dllexport) APIENTRY UserGrinDefinition(double *data)
	{
	double r2, index;
	double A0, B0, C0, D0;
	double A1, B1, C1, D1;
	double A2, B2, C2, D2;
	double n00, n10, n20;
	double lambda, lambda2, lambda4, x, y, temp;

	A0 = data[10];
	B0 = data[11];
	C0 = data[12];
	D0 = data[13];
	A1 = data[14];
	B1 = data[15];
	C1 = data[16];
	D1 = data[17];
	A2 = data[18];
	B2 = data[19];
	C2 = data[20];
	D2 = data[21];

   x = data[1];
   y = data[2];
   r2 = x*x + y*y;
	lambda  = data[4]*1000.0; /* this converts to nanometers */
	lambda2 = lambda*lambda;
	lambda4 = lambda2*lambda2;

	n00 = A0 + B0*lambda2 + C0/lambda2 + D0/lambda4;
	n10 = A1 + B1*lambda2 + C1/lambda2 + D1/lambda4;
	n20 = A2 + B2*lambda2 + C2/lambda2 + D2/lambda4;

   index = n00 + r2*(n10 + n20*r2);
	data[6] = index;

   if (index < 1.0)
		{
		return -1;
		}

	/* now the derivatives, note they are multiplied by index */
	temp    = (2.0*n10 + 4.0*n20*r2)*index;
   data[7] = temp*x;
   data[8] = temp*y;
   data[9] = 0.0;
	return 0;
   }


int __declspec(dllexport) APIENTRY UserParamNames(char *data)
	{
	/* this function returns the name of the parameter requested */
	int i;
	i = (int) data[0];
	strcpy(data,"");
	if (i == 1) strcpy(data,"A0");
	if (i == 2) strcpy(data,"B0");
	if (i == 3) strcpy(data,"C0");
	if (i == 4) strcpy(data,"D0");
	if (i == 5) strcpy(data,"A1");
	if (i == 6) strcpy(data,"B1");
	if (i == 7) strcpy(data,"C1");
	if (i == 8) strcpy(data,"D1");
	if (i == 9) strcpy(data,"A2");
	if (i ==10) strcpy(data,"B2");
	if (i ==11) strcpy(data,"C2");
	if (i ==12) strcpy(data,"D2");
	return 0;
	}
