home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / disks / disk373.lzh / Multiplot / source / mplot_src / src.zoo / smooth.c < prev    next >
C/C++ Source or Header  |  1990-08-02  |  21KB  |  684 lines

  1. #include <math.h>
  2. #include <stdio.h>
  3. #include <exec/types.h>
  4. #include <exec/exec.h>
  5.  
  6. #include "struct.h"
  7. #include "plot.h"
  8. #define RESOLUTION 40
  9.  
  10. extern SHORT UpBorderVectors[];
  11.  
  12. struct Border IntUpBorder = {
  13.         0,0,  /* XY origin relative to container TopLeft */
  14.         1,0,JAM1, /* front pen, back pen and drawmode */
  15.         8,      /* number of XY vectors */
  16.         UpBorderVectors, /* pointer to XY vectors */
  17.         NULL    /* next border in list */
  18. };
  19.  
  20. struct Gadget IntUp = {
  21.         NULL,      /* next gadget */
  22.         183,70,        /* origin XY of hit box relative to window TopLeft */
  23.         15,20,  /* hit box width and height */
  24.         GADGHBOX+GADGHIMAGE,  /* gadget flags */
  25.         GADGIMMEDIATE,  /* activation flags */
  26.         BOOLGADGET,     /* gadget type flags */
  27.         (APTR)&IntUpBorder, /* gadget border or image to be rendered */
  28.         NULL,   /* alternate imagery for selection */
  29.         NULL,   /* first IntuiText structure */
  30.         NULL,   /* gadget mutual-exclude long word */
  31.         NULL,   /* SpecialInfo structure */
  32.         NULL,   /* user-definable data */
  33.         NULL    /* pointer to user-definable data */
  34. };
  35.  
  36. extern SHORT DownBorderVectors[];
  37.  
  38. struct Border IntDownBorder = {
  39.         0,0,  /* XY origin relative to container TopLeft */
  40.         1,0,JAM1, /* front pen, back pen and drawmode */
  41.         8,      /* number of XY vectors */
  42.         DownBorderVectors, /* pointer to XY vectors */
  43.         NULL    /* next border in list */
  44. };
  45.  
  46. struct Gadget IntDown = {
  47.         &IntUp,      /* next gadget */
  48.         120,70,        /* origin XY of hit box relative to window TopLeft */
  49.         15,20,  /* hit box width and height */
  50.         GADGHBOX+GADGHIMAGE,  /* gadget flags */
  51.         GADGIMMEDIATE,  /* activation flags */
  52.         BOOLGADGET,     /* gadget type flags */
  53.         (APTR)&IntDownBorder, /* gadget border or image to be rendered */
  54.         NULL,   /* alternate imagery for selection */
  55.         NULL,   /* first IntuiText structure */
  56.         NULL,   /* gadget mutual-exclude long word */
  57.         NULL,   /* SpecialInfo structure */
  58.         NULL,   /* user-definable data */
  59.         NULL    /* pointer to user-definable data */
  60. };
  61.  
  62.  
  63. SHORT IntGadgBorderVectors[] = {
  64.         0,0,
  65.         40,0,
  66.         40,17,
  67.         0,17,
  68.         0,1
  69. };
  70. struct Border IntGadgBorder = {
  71.         -1,-5,  /* XY origin relative to container TopLeft */
  72.         1,0,JAM1, /* front pen, back pen and drawmode */
  73.         5,      /* number of XY vectors */
  74.         IntGadgBorderVectors, /* pointer to XY vectors */
  75.         NULL    /* next border in list */
  76. };
  77.  
  78. UBYTE IntGadgSIBuff[7]="5";
  79. struct StringInfo IntGadgSInfo = {
  80.         IntGadgSIBuff, /* buffer where text will be edited */
  81.         NULL,   /* optional undo buffer */
  82.         0,      /* character position in buffer */
  83.         3,      /* maximum number of characters to allow */
  84.         0,      /* first displayed character buffer position */
  85.         0,0,0,0,0,      /* Intuition initialized and maintained variables */
  86.         0,      /* Rastport of gadget */
  87.         5,      /* initial value for integer gadgets */
  88.         NULL    /* alternate keymap (fill in if you set the flag) */
  89. };
  90.  
  91. struct Gadget IntGadg = {
  92.         &IntDown,       /* next gadget */
  93.         140,78,        /* origin XY of hit box relative to window TopLeft */
  94.         37,16,  /* hit box width and height */
  95.         NULL,   /* gadget flags */
  96.         RELVERIFY+LONGINT+STRINGCENTER, /* activation flags */
  97.         STRGADGET,      /* gadget type flags */
  98.         (APTR)&IntGadgBorder, /* gadget border or image to be rendered */
  99.         NULL,   /* alternate imagery for selection */
  100.         NULL,   /* first IntuiText structure */
  101.         NULL,   /* gadget mutual-exclude long word */
  102.         (APTR)&IntGadgSInfo,    /* SpecialInfo structure */
  103.         NULL,   /* user-definable data */
  104.         NULL    /* pointer to user-definable data */
  105. };
  106.  
  107. extern struct Image Continue;
  108.  
  109. struct Gadget IntContinue = {
  110.         &IntGadg,      /* next gadget */
  111.         210,135,        /* origin XY of hit box relative to window TopLeft */
  112.         99,43,  /* hit box width and height */
  113.         GADGHBOX+GADGHIMAGE+GADGIMAGE,  /* gadget flags */
  114.         GADGIMMEDIATE,  /* activation flags */
  115.         BOOLGADGET,     /* gadget type flags */
  116.         (APTR)&Continue, /* gadget border or image to be rendered */
  117.         NULL,   /* alternate imagery for selection */
  118.         NULL,   /* first IntuiText structure */
  119.         NULL,   /* gadget mutual-exclude long word */
  120.         NULL,   /* SpecialInfo structure */
  121.         NULL,   /* user-definable data */
  122.         NULL    /* pointer to user-definable data */
  123. };
  124.  
  125. struct NewWindow NewGetIntWindow = {
  126.         125,84,        /* window XY origin relative to TopLeft of screen */
  127.         340,200,        /* window width and height */
  128.         0,1,    /* detail and block pens */
  129.         GADGETDOWN|RAWKEY,   /* IDCMP flags */
  130.         ACTIVATE|NOCAREREFRESH,   /*  flags */
  131.         &IntContinue,       /* first gadget in gadget list */
  132.         NULL,   /* custom CHECKMARK imagery */
  133.         NULL,      /* window title */
  134.         NULL,   /* custom screen pointer */
  135.         NULL,   /* custom bitmap */
  136.         5,5,    /* minimum width and height */
  137.         640,200,        /* maximum width and height */
  138.         CUSTOMSCREEN    /* destination screen type */
  139. };
  140.  
  141.  
  142. struct IntuiText GetIntText2 = {
  143.         1,0,JAM2,       /* front and back text pens, drawmode and fill byte */
  144.         60,40,   /* XY origin relative to container TopLeft */
  145.         NULL,   /* font pointer or NULL for default */
  146.         "to smooth data by.",   /* pointer to text */
  147.         NULL        /* next IntuiText structure */
  148. };
  149.  
  150. struct IntuiText GetIntText1 = {
  151.         1,0,JAM2,       /* front and back text pens, drawmode and fill byte */
  152.         60,30,   /* XY origin relative to container TopLeft */
  153.         NULL,   /* font pointer or NULL for default */
  154.         "Enter the number of values",
  155.         &GetIntText2        /* next IntuiText structure */
  156. };
  157.  
  158.  
  159.  
  160. struct Window *GetIntWindow;
  161. extern struct Screen *screen;
  162.  
  163.  
  164. #define GO 1
  165. #define STOP 0
  166. #define ON TRUE
  167. int QuitGetIntFlag=GO;
  168.  
  169. GetInt(min,max)
  170. int min,max;
  171. {
  172. struct IntuiMessage  *i_message;         /* pointer to message */
  173. void ProcGetIntMes();
  174. struct RastPort *p;
  175.  
  176.  
  177.   NewGetIntWindow.Screen = screen;
  178.   if (!(GetIntWindow = (struct Window *)OpenWindow(&NewGetIntWindow)))
  179.     {
  180.        ErrorAlert(0);
  181.        CloseScreen(screen);
  182.        sexit(FALSE);
  183.     }
  184.   p = GetIntWindow->RPort;
  185.   PrintIText(p,&GetIntText1,0,0);
  186.   QuitGetIntFlag=GO;     /*** RESET FLAG IN CASE NOT FIRST TIME ***/
  187.  
  188.   while (QuitGetIntFlag !=STOP)
  189.    {
  190.      Wait(1l<<GetIntWindow->UserPort->mp_SigBit);        /* wait for a message */
  191.      while (i_message = (struct IntuiMessage *)GetMsg(GetIntWindow->UserPort))
  192.        ProcGetIntMes(i_message,min,max);
  193.    }
  194.   CloseWindow(GetIntWindow);
  195.   return(IntGadgSInfo.LongInt);
  196. }
  197.  
  198.  
  199. void ProcGetIntMes(p_message,min,max)
  200. int min, max;
  201. struct IntuiMessage *p_message;
  202. {
  203. ULONG MesClass;        /*     Fields for storing      */
  204. USHORT MesCode;        /*     intuimessage data       */
  205. APTR Pointer;          /*                             */
  206. int HandleGetIntEvent();
  207.  
  208.    MesClass = p_message->Class;             /* Store values */
  209.    MesCode = p_message->Code;
  210.    Pointer = p_message->IAddress;
  211.    ReplyMsg(p_message);                     /* Reply to message */
  212.    HandleGetIntEvent(MesClass,MesCode,Pointer,min,max);
  213. }
  214.  
  215. int HandleGetIntEvent(MesClass,MesCode,Pointer,min,max)
  216. ULONG MesClass;        /*     Fields for storing      */
  217. USHORT MesCode;        /*     intuimessage data       */
  218. APTR Pointer;          /*                             */
  219. int min,max;
  220. {
  221. short len;
  222.  
  223.   if ( MesClass == GADGETDOWN)
  224.     {
  225.       if (Pointer == (APTR)&IntDown)
  226.          {
  227.             RemoveGadget(GetIntWindow,&IntGadg);
  228.             if (IntGadgSInfo.LongInt<(min+2)) {Message("Minimum Allowable Value Reached");}
  229.             else IntGadgSInfo.LongInt--;
  230.             stci_d(IntGadgSIBuff,IntGadgSInfo.LongInt);
  231.             len =strlen(IntGadgSIBuff);
  232.             IntGadgSInfo.BufferPos=len, IntGadgSInfo.DispPos=0;
  233.             AddGadget(GetIntWindow,&IntGadg,-1L);
  234.             RefreshGadgets(&IntGadg,GetIntWindow,NULL);
  235.          }
  236.       if (Pointer == (APTR)&IntUp)
  237.          {
  238.             RemoveGadget(GetIntWindow,&IntGadg);
  239.             if (IntGadgSInfo.LongInt>(max-2)) {Message("Maximum Allowable Value Reached");}
  240.             else IntGadgSInfo.LongInt++;
  241.             stci_d(IntGadgSIBuff,IntGadgSInfo.LongInt);
  242.             len =strlen(IntGadgSIBuff);
  243.             IntGadgSInfo.BufferPos=len, IntGadgSInfo.DispPos=0;
  244.             AddGadget(GetIntWindow,&IntGadg,-1L);
  245.             RefreshGadgets(&IntGadg,GetIntWindow,NULL);
  246.          }
  247.       if (Pointer == (APTR)&IntContinue)
  248.          {
  249.             if (IntGadgSInfo.LongInt<min) {Message("  Value Entered is too Small  "); return(0);}
  250.             if (IntGadgSInfo.LongInt>max-1) {Message("  Value Entered is too Large  "); return(0);}
  251.             QuitGetIntFlag = STOP;
  252.             return(1);
  253.          }
  254.     }
  255.   if ( MesClass == RAWKEY)
  256.     {
  257.       if (MesCode ==196)  /* RETURN key RELEASED */
  258.          {
  259.             if (IntGadgSInfo.LongInt<min) {Message("  Value Entered is too Small  "); return(0);}
  260.             if (IntGadgSInfo.LongInt>max-1) {Message("  Value Entered is too Large  "); return(0);}
  261.             QuitGetIntFlag = STOP;
  262.             return(1);
  263.          }
  264.      }
  265.   return(0);
  266. }
  267.  
  268.  
  269.  
  270. SmoothData(Pict,SelectedPlot)
  271. struct Plot *SelectedPlot;
  272. struct Pict *Pict;
  273. {
  274. short i;
  275. int  numpoints=0, window;
  276. FFP  *y1array, *YArray, *YArrayStart, *GetArray();
  277. struct Plot *Plot, *PlotStart, *ClonePlot();
  278.  
  279.     if (!TestX(SelectedPlot))  return(FALSE);
  280.  
  281.    /* Calculate and get array to store Y values */
  282.     YArray=YArrayStart=GetArray(SelectedPlot,&numpoints,3);
  283.     if (!YArray) return(FALSE);
  284.  
  285.     if (!(window = GetInt(0,(int)(numpoints/2)))) return(FALSE);
  286.  
  287.     /* Fill array with Y values */
  288.     Plot=SelectedPlot;
  289.     do
  290.        {
  291.            y1array=Plot->y;
  292.            for (i=0;i<Plot->NPts;i++)
  293.               {
  294.                   *YArray=(FFP)y1array[i];
  295.                   YArray++;
  296.               }
  297.        } while ((Plot->Continued)&&(Plot=Plot->NextPlot));
  298.  
  299.     /* Calculate smoothed values and place in 2nd half of array */
  300.     smooth(YArrayStart,numpoints,window);
  301.  
  302.     if (!(PlotStart=ClonePlot(Pict,SelectedPlot))) return(FALSE);
  303.  
  304.     /* Put new values in new structure */
  305.     YArray=YArrayStart+numpoints;
  306.     for (Plot=PlotStart;Plot;Plot=Plot->NextPlot)
  307.        {
  308.            y1array=Plot->y;
  309.            for (i=0;i<Plot->NPts;i++,YArray++) { y1array[i]=(FFP)*YArray; }
  310.        }
  311.     FreeMem(YArrayStart,sizeof(FFP)*numpoints*3);
  312.     return(TRUE);
  313. }
  314.  
  315. FFP *GetArray(SelectedPlot,i,factor)
  316. struct Plot *SelectedPlot;
  317. int *i, factor;
  318. {
  319. FFP *Array;
  320. struct Plot *Plot;
  321.  
  322.     Plot=SelectedPlot;
  323.     do {(*i)+=Plot->NPts;} while ((Plot->Continued)&&(Plot=Plot->NextPlot));
  324.     Array=(FFP *)AllocMem(sizeof(FFP)*(*i)*factor,MEMF_CLEAR);
  325.     if (!Array) { Message(" Not Enough Memory for Function"); return(NULL);}
  326.     else return((FFP *)Array);
  327. }
  328.  
  329.  
  330.  
  331.  
  332. struct Plot *ClonePlot(Pict,SelectedPlot)
  333. struct Pict *Pict;
  334. struct Plot *SelectedPlot;
  335. {
  336. short i;
  337. int  numplots=0;
  338. FFP *xarray, *yarray, *x1array, *y1array;
  339. struct Plot *Plot, *TempPlot, *PlotStart, *GetStructPlot();
  340.  
  341.     /* Make new Plot structure to take smoothed values */
  342.     for (Plot=Pict->Plot;Plot->NextPlot;Plot=Plot->NextPlot);  /* go to end */
  343.     if (!(Plot->NextPlot = GetStructPlot()))
  344.       { Message(" Not Enough Memory for Function"); return(NULL); }
  345.     else PlotStart= Plot = Plot->NextPlot;
  346.  
  347.     TempPlot=SelectedPlot;
  348.     do {
  349.            Plot->NPts=TempPlot->NPts;
  350.            Plot->Continued=TempPlot->Continued;
  351.            Plot->Color=TempPlot->Color;
  352.            Plot->Lines=TRUE;
  353.            Plot->PointSize=0;
  354.            Plot->PointType=TempPlot->PointType;
  355.            Plot->Enabled=TempPlot->Enabled;
  356.            Plot->NextPlot=NULL;
  357.  
  358.            xarray=TempPlot->x; yarray=TempPlot->y;
  359.            x1array=Plot->x; y1array=Plot->y;
  360.            for (i=0;i<TempPlot->NPts;i++)  x1array[i]=xarray[i];
  361.            numplots++;
  362.            if (Plot->Continued)
  363.               {
  364.                   if (!(Plot->NextPlot = GetStructPlot()))
  365.                      {
  366.                         Message(" Not Enough Memory for Function");
  367.                         Plot->Continued=FALSE;
  368.                         Plot->Enabled=FALSE;
  369.                         return(NULL);
  370.                      }
  371.                   Plot = Plot->NextPlot;
  372.               }
  373.        } while ((TempPlot->Continued)&&(TempPlot=TempPlot->NextPlot));
  374.     Pict->NPlt++;
  375.     return(PlotStart);
  376. }
  377.  
  378.  
  379. smooth(Array,n,window)
  380. FFP *Array;       /* Which is of length 2*n */
  381. int n, window;
  382. {
  383. int i,j;
  384. FFP *ResultArray, *TempArray, median(), mean();
  385.  
  386.    ResultArray=Array+n;   /* Place results in second half of array */
  387.    TempArray=Array+(2*n);    /* Tempory data storage for sorting */
  388.  
  389.    if (!(window<n/2)) return(FALSE);
  390.    for (i=0;i<window;i++)
  391.      {
  392.         for (j=0;j<i+window+1;j++) TempArray[j]=Array[j];
  393.         ResultArray[i]=mean(TempArray,i+window+1);
  394.      }
  395.    for (i=window;i<n-window;i++)
  396.      {
  397.         for (j=0;j<2*window+1;j++) TempArray[j]=Array[j+i-window];
  398.         ResultArray[i]=mean(TempArray,2*window+1);
  399.      }
  400.    for (i=n-window;i<n;i++)
  401.      {
  402.         for (j=0;j<n+window-i;j++) TempArray[j]=Array[j+i-window];
  403.         ResultArray[i]=mean(TempArray,n+window-i);
  404.      }
  405. return(TRUE);
  406. }
  407.  
  408.  
  409.  
  410.  
  411. FFP median(data, n)
  412. FFP *data;
  413. int n;
  414. {
  415. int n2, n2p;
  416.  
  417.   fqsort(data,n);
  418.   n2p=(n2=n/2)+1;
  419.   return((FFP)(n % 2 ? data[n2p-1] : 0.5*(data[n2-1]+data[n2p-1])));
  420. }
  421.  
  422. FFP mean(data, n)
  423. FFP *data;
  424. int n;
  425. {
  426. int i;
  427. FFP sum=0.0;
  428.  
  429.   for(i=0;i<n;i++,data++) sum+=*data;
  430.   return((FFP)(sum/n));
  431. }
  432.  
  433.  
  434. FitData(Pict,SelectedPlot)
  435. struct Plot *SelectedPlot;
  436. struct Pict *Pict;
  437. {
  438. short i, j;
  439. int  numpoints=0;
  440. FFP  *y1array, *x1array, a, b=0.0, *YArray, *YArrayStart, *GetArray(), *XArray, *XArrayStart, *TArray;
  441. void FitDataFunc();
  442. struct Plot *Plot, *GetStructPlot();
  443. char legend[80];
  444.  
  445.     if (!TestX(SelectedPlot))  return(FALSE);
  446.  
  447.     YArray=YArrayStart=GetArray(SelectedPlot,&numpoints,3);
  448.     if (!YArray) return(FALSE);
  449.     TArray=(XArray=XArrayStart=YArray+numpoints)+numpoints;
  450.  
  451.     /* Fill arrays with X and Y values */
  452.     Plot=SelectedPlot;
  453.     do
  454.        {
  455.            y1array=Plot->y; x1array=Plot->x;
  456.            for (i=0;i<Plot->NPts;i++,YArray++,XArray++)
  457.                   {*YArray=(FFP)y1array[i]; *XArray=(FFP)x1array[i];}
  458.        } while ((Plot->Continued)&&(Plot=Plot->NextPlot));
  459.  
  460.  
  461.     FitDataFunc(XArrayStart,YArrayStart,TArray,numpoints,&a,&b);
  462.  
  463.     for (Plot=Pict->Plot;Plot->NextPlot;Plot=Plot->NextPlot);  /* go to end */
  464.     if (!(Plot->NextPlot = GetStructPlot()))
  465.       { Message(" Not Enough Memory for Function"); return(NULL); }
  466.     Plot=Plot->NextPlot;
  467.  
  468.     sprintf(legend,"f(x)=%2.2lf%+2.2lfx",(double)a,(double)b);
  469.     strcpy(Plot->Legend->String,legend);
  470.  
  471.     i=0;
  472.     do {
  473.          Plot->NPts=MAXPOINTS;
  474.          Plot->Continued=FALSE;
  475.          Plot->Color=SelectedPlot->Color;
  476.          Plot->Lines=TRUE;
  477.          Plot->PointSize=0;
  478.          Plot->PointType=SelectedPlot->PointType;
  479.          Plot->Enabled=TRUE;
  480.          Plot->NextPlot=NULL;
  481.          x1array=Plot->x; y1array=Plot->y;
  482.          for (j=i;((i<j+Plot->NPts)&&(i<=RESOLUTION));i++)
  483.            {
  484.                x1array[i-j]= (FFP)Pict->CurrReg->XMin+ (FFP)i*((FFP)(Pict->CurrReg->XMax-Pict->CurrReg->XMin)/(FFP)RESOLUTION);
  485.                y1array[i-j]=a+b*(x1array[i-j]);
  486.            }
  487.       } while ((i<=RESOLUTION)
  488.            &&(Plot->NextPlot=(struct Plot *)GetStructPlot())
  489.            &&(Plot->Continued=TRUE)
  490.            &&(Plot=Plot->NextPlot));
  491.     Plot->NPts=i-j;
  492.     Pict->NPlt++;
  493.  
  494.     FreeMem(YArrayStart,sizeof(FFP)*numpoints*3);
  495.     return(TRUE);
  496. }
  497.  
  498. TestX(Plot)
  499. struct Plot *Plot;
  500. {
  501. int i, start=TRUE;
  502. FFP xmin, xmax, *XArray;
  503.  
  504.   do {
  505.        XArray=Plot->x;
  506.        for (i=0;i<Plot->NPts;i++)
  507.          {
  508.             if (start) {xmin=xmax=XArray[i]; start=FALSE;}
  509.             else{
  510.                xmax=max(xmax,XArray[i]);
  511.                xmin=min(xmin,XArray[i]);
  512.                if (xmax!=XArray[i]) { Message("  Error: Data Set Not Sorted"); return(FALSE);}
  513.             }
  514.          }
  515.      } while ((Plot->Continued)&&(Plot=Plot->NextPlot));
  516.   if (xmax==xmin) { Message("    Error: X Values Invariable"); return(FALSE);}
  517.   return(TRUE);
  518. }
  519.  
  520.  
  521. void FitDataFunc(XArray,YArray,TArray,numpoints,a,b)
  522. FFP *XArray, *YArray,*TArray, *a,*b;
  523. int numpoints;
  524. {
  525. FFP sumx=0.0, sumy=0.0, sumt2=0.0;
  526. int i;
  527.  
  528.   for(i=0;i<numpoints;i++) { sumx+=XArray[i]; sumy+=YArray[i]; }
  529.   for(i=0;i<numpoints;i++)
  530.      {
  531.         TArray[i]=XArray[i]-sumx/numpoints;
  532.         sumt2+=(TArray[i]*TArray[i]);
  533.         *b+=TArray[i]*YArray[i];
  534.      }
  535.   *b/=sumt2;
  536.   *a=(sumy-sumx**b)/numpoints;
  537. }
  538.  
  539.  
  540. FitLogData(Pict,SelectedPlot)
  541. struct Plot *SelectedPlot;
  542. struct Pict *Pict;
  543. {
  544. short i,j;
  545. int  numpoints=0;
  546. FFP  *y1array, *x1array, a, b=0.0, *YArray, *YArrayStart, *GetArray(), *XArray, *XArrayStart, *TArray;
  547. void FitDataFunc();
  548. struct Plot *Plot, *GetStructPlot();
  549. char legend[80];
  550.  
  551.     if (!TestX(SelectedPlot))  return(FALSE);
  552.  
  553.     YArray=YArrayStart=GetArray(SelectedPlot,&numpoints,3);
  554.     if (!YArray) return(FALSE);
  555.     TArray=(XArrayStart=XArray=YArray+numpoints)+numpoints;
  556.  
  557.     /* Fill arrays with X and Y values */
  558.     Plot=SelectedPlot;
  559.     do
  560.        {
  561.            y1array=Plot->y; x1array=Plot->x;
  562.            for (i=0;i<Plot->NPts;i++,YArray++,XArray++)
  563.                   {
  564.                      *YArray=(FFP)log(abs((double)y1array[i]));
  565.                      *XArray=(FFP)x1array[i];
  566.                   }
  567.        } while ((Plot->Continued)&&(Plot=Plot->NextPlot));
  568.  
  569.  
  570.     FitDataFunc(XArrayStart,YArrayStart,TArray,numpoints,&a,&b);
  571.  
  572.     for (Plot=Pict->Plot;Plot->NextPlot;Plot=Plot->NextPlot);  /* go to end */
  573.     if (!(Plot->NextPlot = GetStructPlot()))
  574.       { Message(" Not Enough Memory for Function"); return(NULL); }
  575.     Plot=Plot->NextPlot;
  576.  
  577.     sprintf(legend,"f(x)=%2.2lf*exp(%2.2lfx)",exp((double)a),(double)b);
  578.     strcpy(Plot->Legend->String,legend);
  579.  
  580.     i=0;
  581.     do {
  582.          Plot->NPts=MAXPOINTS;
  583.          Plot->Continued=FALSE;
  584.          Plot->Color=SelectedPlot->Color;
  585.          Plot->Lines=TRUE;
  586.          Plot->PointSize=0;
  587.          Plot->PointType=SelectedPlot->PointType;
  588.          Plot->Enabled=TRUE;
  589.          Plot->NextPlot=NULL;
  590.          x1array=Plot->x; y1array=Plot->y;
  591.          for (j=i;((i<j+Plot->NPts)&&(i<=RESOLUTION));i++)
  592.            {
  593.                x1array[i-j]= Pict->CurrReg->XMin+ i*((Pict->CurrReg->XMax-Pict->CurrReg->XMin)/RESOLUTION);
  594.                y1array[i-j]=(FFP)exp((double)a)*exp((double)b*x1array[i-j]);
  595.            }
  596.       } while ((i<=RESOLUTION)
  597.            &&(Plot->NextPlot=(struct Plot *)GetStructPlot())
  598.            &&(Plot->Continued=TRUE)
  599.            &&(Plot=Plot->NextPlot));
  600.     Plot->NPts=i-j;
  601.     Pict->NPlt++;
  602.     FreeMem(YArrayStart,sizeof(FFP)*numpoints*3);
  603.     return(TRUE);
  604. }
  605.  
  606. SortData(Pict,SelectedPlot)
  607. struct Plot *SelectedPlot;
  608. struct Pict *Pict;
  609. {
  610. short i;
  611. int  numpoints=0;
  612. FFP  *e1array, *y1array, *x1array, *YArray, *YArrayStart, *GetArray(), *XArray, *XArrayStart, *EArray, *EArrayStart;
  613. struct Plot *Plot, *GetStructPlot();
  614.  
  615.     YArray=YArrayStart=GetArray(SelectedPlot,&numpoints,3);
  616.     if (!YArray) return(FALSE);
  617.     EArrayStart=EArray=(XArrayStart=XArray=YArray+numpoints)+numpoints;
  618.  
  619.     /* Fill arrays with X and Y values */
  620.     Plot=SelectedPlot;
  621.     do
  622.        {
  623.            y1array=Plot->y; x1array=Plot->x; e1array=Plot->e;
  624.            for (i=0;i<Plot->NPts;i++,YArray++,XArray++,EArray++)
  625.                   {
  626.                      *YArray=(FFP)y1array[i];
  627.                      *XArray=(FFP)x1array[i];
  628.                      *EArray=(FFP)e1array[i];
  629.                   }
  630.        } while ((Plot->Continued)&&(Plot=Plot->NextPlot));
  631.     LinkSort(numpoints,XArrayStart,YArrayStart,EArrayStart);
  632.     XArray=XArrayStart; YArray=YArrayStart; EArray=EArrayStart;
  633.     Plot=SelectedPlot;
  634.     do {
  635.            x1array=Plot->x; y1array=Plot->y; e1array=Plot->e;
  636.            for (i=0;i<Plot->NPts;i++,XArray++,YArray++,EArray++)
  637.              {
  638.                 x1array[i]=*XArray;
  639.                 y1array[i]=*YArray;
  640.                 e1array[i]=*EArray;
  641.              }
  642.        } while ((Plot->Continued)&&(Plot=Plot->NextPlot));
  643.     FreeMem(YArrayStart,sizeof(FFP)*numpoints*3);
  644.     return(TRUE);
  645. }
  646.  
  647.  
  648. LinkSort(n,ra,rb,rc)
  649. int n;
  650. FFP ra[], rb[], rc[];
  651. {
  652. int l, j, ir, i;
  653. float rrb, rra, rrc;
  654.  
  655.   ra--; rb--; rc--;  /* To allow an array r[1....n]  */
  656.   l=(n>>1)+1;
  657.   ir=n;
  658.   for(;;) {
  659.     if (l>1) {rra=ra[--l]; rrb=rb[l]; rrc=rc[l];}
  660.     else
  661.       {
  662.           rra=ra[ir]; rrb=rb[ir]; rrc=rc[ir];
  663.           ra[ir]=ra[1]; rb[ir]=rb[1]; rc[ir]=rc[1];
  664.           if (--ir==1) {ra[1]=rra; rb[1]=rrb; rc[1]=rrc; return(0); }
  665.       }
  666.     i=l;
  667.     j=l<<1;
  668.     while (j<=ir)
  669.       {
  670.         if ((j<ir) && (ra[j] < ra[j+1])) ++j;
  671.         if (rra< ra[j])
  672.           {
  673.             ra[i]=ra[j]; rb[i]=rb[j]; rc[i]=rc[j];
  674.             j+=(i=j);
  675.           }
  676.         else j=ir+1;
  677.       }
  678.       ra[i]=rra; rb[i]=rrb; rc[i]=rrc;
  679.    }
  680.    return(0);
  681. }
  682.  
  683.  
  684.