/* File: Fitdemo.c Copyright 1993 Microcal Software Inc
   Revised 25 August 1994 for version 3.5 */

#include	<windows.h>

/* The following entry function
 * related to Windows
 */
#ifndef _WIN32

int FAR PASCAL LibMain(hModule, wDataSeg, cbHeapSize, lpszCmdLine)
HANDLE	hModule;
WORD    wDataSeg;
WORD    cbHeapSize;
LPSTR   lpszCmdLine;
{
    return 1;/* Nothing is done, but it is necessary */
}

//	ANU v4.134 9/30/96 32_BIT_COMPATIBLE
#else  //_WIN32

BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
{
	 
   // The return value is only used for DLL_PROCESS_ATTACH; all other
   //   conditions are ignored.  
	return TRUE;   // successful DLL_PROCESS_ATTACH
}

#endif
///end 32_BIT_COMPATIBLE


/* Your DLL code starts here */

#include	<math.h>
	/* This is needed for FitFunc2
	 * which uses pow and exp
	 */
	 
#include	"..\..\include\orgdll.h"
	/* this file includes callback function
	 * information that is used in FitFunc2 to perform a convolution
	 */

///Function names have to be upper case so that origin can
//recognize the functions.
int FAR PASCAL FITFUNC1(HWND hWnd, double FAR * lpValue, short nParam, double FAR *lpParam,LPCALLBK lpfn);
int FAR PASCAL FITFUNC2(HWND hWnd, double FAR * lpValue, short nParam, double FAR *lpParam,LPCALLBK lpfn);


int FAR PASCAL FITFUNC1(
	HWND			hWnd,	/* Origin's main window */
	double FAR *	lpValue,/* input (x) ,output (y)*/
	short			nParam, /* number of parameters */
	double FAR *	lpParam,/* parameter array */
	LPCALLBK		lpfn)	/* call back function for additional info */
{
/* In this demo, the function is a simple linear
 * f(x) = A + B * x + C * x * x;
 * nParam should be 3
 */
	double	x = *lpValue;
		/* lpValue point to a temperary location
		 * that contains the X value on input
		 */
		 
	double	y;
	
	if(nParam == 0) return(0);
	/* this is an init message, we don't
	 * do anything here but we must exit
	 * before trying to evaluate the function
	 */
	 
#define	A		lpParam[0]
#define	B		lpParam[1]
#define	C		lpParam[2]

	y = A + B * x + C*x*x;
	
	*lpValue = y;
		/* result of the function is stored back to lpValue */
	
	return(0);
		/* You must return zero if there is no error
		 * otherwise you can return any number other than
		 * zero to signal an error
		 */
}


/* the following is a more complicated example that involves
 * using the call back function to access the worksheet
 * for additional data to perform a convolution
 */
int FAR PASCAL FITFUNC2(
	HWND			hWnd,		/* Origin's main window */
	double FAR *	lpValue,	/* input (x) ,output (y)*/
	short			nParam,		/* number of parameters */
	double FAR *	lpParam,	/* parameter array */
	LPCALLBK		lpfn)		/* call back function for additional info */
{
	/*
		In this example we have four parameters: H, K, M, C.
		The basic function form is f(i) = M X[i]^H /(K^H + x[i]^H)
		We convolute f(i) with an exponential decay
		
		for j = 0 to i
			y(i) += f(j) * exp((j - i) / C)
	*/
	#define	PARAM_H		lpParam[0]
	#define	PARAM_K		lpParam[1]
	#define	PARAM_M		lpParam[2]
	#define	PARAM_C		lpParam[3]

	long			i, j, N[4];
	double			/*value,*/ f_value, y_value, x_value;
	char			szTemp[80];
	DWORD			dwID;
	DATAELEMENT		stDataElement;

	if( nParam == 0 )
		return(0);
	/* this is an init message, we don't
	 * do anything here but we must exit
	 * before trying to evaluate the function
	 */
	            
/* first we need to find the data range in the worksheet */

	/*	Execute a simple script command to place the name of the current fitting
		dataset into the %A variable.  Next, copy the name from %A to our local
		buffer.  When we have the name we can get the dataset's id.
	*/
	lpfn(hWnd, WCB_EXECUTE, "%A=NLSF.FITDATA$", 0L);			// Execute script command.
	lpfn(hWnd, WCB_GET_STRING, (LPSTR)szTemp, 0);				// Copy %A string.
	dwID = lpfn(hWnd, WCB_DATA_GET_ID, (LPSTR)szTemp, (LPSTR)N);	// Get dataset's id and range.
	if( dwID == 0 )	// Zero indicates dataset was not found.
		return 1;   // Return 1 to indicate an error.
	
	/* this is C, not LabTalk, so row number starts
	 * from zero, so typically N[0] == 0
	 */
	
/* next, we need to find the current row number that
 * we need to return the function value
 */
 	i = (long)lpValue[1];
	
	/* as provided when the DLL function is called,
	 * [0] is the x value and [1] is the row number
	 * which is in C convention to start from zero 
	 */
	 
	y_value = 0;
	for( j = N[0]; j < i; j++ )
	{
		/* to evaluate f_value, we need
		 * the x_value at row j
		 */

		stDataElement.index = j;
		if( lpfn(hWnd, WCB_DATA_GET_VALUE, dwID, &stDataElement) )
			return 1;
		x_value = stDataElement.value;

		f_value = PARAM_M * pow(x_value, PARAM_H) / (pow(PARAM_K, PARAM_H) + pow(x_value, PARAM_H));
		y_value += f_value * exp((j - i) / PARAM_C);
	}
	
	/* you may need to add error checking and parameter
	 * checking in the code above and return 1 whenever
	 * anything goes wrong
	 */
	
	*lpValue = y_value;
		/* result of the function is stored back to lpValue */
	
	return(0);
}
