/*

   Fit function for Lorentz curve:
   Fit functions are implemented as external programms
   which will receive the following parameters:
   1. address of array (double) of x-values.
      (or shared memory ID in UNIX)
   2. address of array (double) of results.
      (or shared memory ID in UNIX)
   3. first array element
   4. last array element
   5. size of array in bytes (used for shmat() under UNIX !)
   6. 1st parameter (double)
   7. 2nd parameter (double)
      .
      .
      .
   26. last parameter (if used)
   On Amiga Computers the Address represents the
   real memory location in decimal format (%d)
   On UNIX Computers this parameter identifies
   a shared memory ID. See "examplefn.c"
   On Amiga Computers it is recommended to make
   the Fit function resident, since it will be
   called very often.

   This example contains the following parts:
   1. Commandline interface
   2. Help function (if no parameter was specified)
   3. (shared) Memory allocation
   4. Lorentz function

*/

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#ifdef UNIX
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#endif

#define MAXPARM 30

#define sqr(x) ((x)*(x))
#define SIGN(a,b) ((b)<0 ? -fabs(a) : fabs(a))

double *p;
double *shmx, *shmy;
int   shmidx, shmidy;
int   first, last;
int   max;

/* ----------------------------------------------------------------
   perhaps you need a function to avoid overflow errors on division
   ---------------------------------------------------------------- */

double divide(a,b)
double a,b;
{
   if(b != 0.0) return(a/b);
   return(1.0E10);
}

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   !!                 Here comes the function                     !!
   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
double fn(x,a,b,c,d)
double x,a,b,c,d;
{
double y;

   y = a + b * 1/(1+4*sqr((x-c)/d)) ;
   return(y);
}

/* ----------------------------------------------------------------
   You should allways supply a help function, which will be called
   when no parameter is specified.
   ---------------------------------------------------------------- */

help()
{
printf("Almeida 's erster Fitversuch :eine Lorentzkurve\n");
printf("f(x) = a + b * 1/(1+4sqr((x-c)/d))\n");
printf("Parameter:\n");
printf("p[0] = a\n");
printf("p[1] = b\n");
printf("p[2] = c\n");
printf("p[3] = d\n");
return(0);
}

/* ----------------------------------------------------------------
      shared memory allocation
   ---------------------------------------------------------------- */
alloc_shm()
{
#ifdef AMIGA
   shmx = (double *) shmidx;
   shmy = (double *) shmidy;
#endif
#ifdef UNIX
   shmx = (double *) shmat(shmidx, 0,0666);
   shmy = (double *) shmat(shmidy, 0,0666);
   if((shmx < 0) || (shmy < 0)) {
      fprintf(stderr,"could not attach Shared memory, aborting !\n");
      exit(-1);
   }
#endif
return(0);
}

free_shm()
{
#ifdef UNIX
   shmdt(shmx);
   shmdt(shmy);
#endif
return(0);
}

main(argc,argv)
int argc;
char **argv;
{
int n;
double x;

   if(argc < 3) {help(); exit(0);}

   p = (double *) calloc(MAXPARM,sizeof(double));

   shmidx = atoi(argv[1]);
   shmidy = atoi(argv[2]);
   alloc_shm();
   first = atoi(argv[3]);
   last = atoi(argv[4]);
   max = atoi(argv[5]);
   for(n = 0; n < MAXPARM; n++) {
      sscanf(argv[n + 6],"%lf",&x);
      p[n] = (double) x;
   }
   for(n = first; n <= last; n++) {
      shmy[n] = fn(shmx[n],p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],
                           p[9],p[10],p[11],p[12],p[13],p[14],p[15],
                           p[16],p[17],p[18],p[19]);
   }
   free_shm();
   free(p);
   exit(0);
}


