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

/*
Written by Kenneth E. Moore
June 26, 2001

Modified May 30, 2003 to support the "separate x, y" option
*/

#define PI 3.141592654
int __declspec(dllexport) APIENTRY UserBeamDefinition(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:
data[0]  = the total number of values in the passed data array
data[1]  = x
data[2]  = y
data[3]  = 0 if unpolarized, 1 if polarized
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]  = peak irradiance in power per lens unit area
data[7]  = dx point spacing in lens units
data[8]  = dy point spacing in lens units
data[9]  = 1 if separating x, y else 0

data[10]  = Ex real (to be computed by the dll and returned)
data[11]  = Ex imag (to be computed by the dll and returned)
data[12]  = Ey real (to be computed by the dll and returned if polarized)
data[13]  = Ey imag (to be computed by the dll and returned if polarized)
data[14]  = x pilot beam waist in lens units (to be computed by the dll and returned only if x = y = 0)
data[15]  = x rayleigh distance in lens units (to be computed by the dll and returned only if x = y = 0)
data[16]  = x pilot position in lens units (to be computed by the dll and returned only if x = y = 0)
data[17]  = y pilot beam waist in lens units (to be computed by the dll and returned only if x = y = 0)
data[18]  = y rayleigh distance in lens units (to be computed by the dll and returned only if x = y = 0)
data[19]  = y pilot position in lens units (to be computed by the dll and returned only if x = y = 0)
  

data[20] = parameter 1 from user input
data[21] = parameter 2 from user input
etc... up to data[maxdata] where maxdata = int(data[0])

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

/* this DLL models a Guassian beam. */

int __declspec(dllexport) APIENTRY UserBeamDefinition(double *data)
	{
	int separatexy;
	double x, y, wx, wy, gx, gy, amp, peak, lambda;

	separatexy = (int) data[9];
	peak = data[6]*data[7]*data[8];
	if (data[3] > 0.0) peak /= sqrt(2.0);

	x = data[1];
	y = data[2];
	wx = data[20];
	wy = data[21];

	if (wx <= 0.0 || wy <= 0.0)
		{
		return -1;
		}
	
	if (x == 0.0 && y == 0.0)
		{
		lambda = data[4]/1000.0; /* this is lambda in mm */
		lambda /= data[5]; /* lambda in lens units */

		if (separatexy)
			{
			data[14] = sqrt(wx*wx); /* the x waist size in lens units */
			data[15] = PI*(wx*wx)/lambda; /* Rayleigh in lens units */
			data[16] = 0.0; /* pilot position in lens units */
			
			data[17] = sqrt(wy*wy); /* the y waist size in lens units */
			data[18] = PI*(wy*wy)/lambda; /* Rayleigh in lens units */
			data[19] = 0.0; /* pilot position in lens units */
			}
		else
			{
			data[14] = sqrt(wx*wy); /* the waist size in lens units */
			data[15] = PI*(wx*wy)/lambda; /* Rayleigh in lens units */
			data[16] = 0.0; /* pilot position in lens units */
			
			/* make y same as x */
			data[17] = data[14];
			data[18] = data[15];
			data[19] = data[16];
			}
		}
	
	gx = (x/wx);
	gy = (y/wy);
	amp = peak*exp(-(gx*gx+gy*gy));
   
	data[10] = amp;
   data[11] = 0.0;
	if (data[3] > 0.0)
		{
		data[12] = amp;
		data[13] = 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,"Wx");
	if (i == 2) strcpy(data,"Wy");
	return 0;
	}
