 /********************************************************************/
 /****                                                            ****/
 /****                                                            ****/
 /****    Program          : BerechnungsRoutinen.c                ****/
 /****                                                            ****/
 /****    Version          :    03.71                             ****/
 /****                                                            ****/
 /****    Erstversion      : 14.08.1988                           ****/
 /****                                                            ****/
 /****    Letzte Änderung  : 05.08.1990                           ****/
 /****                                                            ****/
 /****    Compiliert mit   : siehe MAKEFILE                       ****/
 /****                                                            ****/
 /****    Gelinkt mit      : siehe MAKEFILE                       ****/
 /****                                                            ****/
 /********************************************************************/
 /****                                                            ****/
 /****                                                            ****/
 /****               Copyright by Rüdiger Dreier                  ****/
 /****                                                            ****/
 /****                                                            ****/
 /********************************************************************/
 
 /* Einbinden der Include-Files */
 
 #ifdef DEBUG
 #include "Plotter.h"
 #include <proto/tool.h>
 #endif
 #include <string.h>
 #include <graphics/gfxmacros.h>
 #include <proto/mathieeedoubbas.h>
 #include <proto/mathieeedoubtrans.h>
 #include <graphics/regions.h>
 #include <proto/layers.h>
 #include <stdio.h>
 
 LONG MatheFehler;
 char flagg;
 
 SHORT Genauigkeiten[3]=
  {
   8,4,1
  };
 
 /* Funktion testet, ob ein Fehler aufgetreten ist */
 VOID FehlerAbfrage(VOID)
  {
   /* Abfrage auf Mathe-Fehler */
   if (MatheFehler)
    {
     request("OK","OK",BE_ERROR);
    }
   MatheFehler=0;
  }
 
 
 /* Zeichnet die n-te Ableitung der Funktion nr */
 VOID __asm ZeichneFunktion(register __d0 USHORT nr,
                            register __d1 int Ableitung)
  {
   USHORT ZEICHNEN=TRUE;
   double i,xalt,yalt,y;
   ULONG OldIDCMP;
   SHORT MaxXPos,Pos;
   LONG H;
   
   MaxXPos=(SHORT)(xx-Genauigkeiten[GE]);
   
   SetAPen(RastPort,FARBE1);
   
   /* Berechnet Position der x/y-Achse */
   x0=Add(Mul(Div(Neg(xmn),Sub(xmp,xmn)),Flt(xx-1)),1.0);
   y0= Add(Mul(Div(ymp,Sub(ymp,ymn)),Flt(yy-1)),1.0);
   
   /* Bestimmt Zeichenmaßstab */
   xm=Div(Flt(xx-1),Sub(xmp,xmn));
   ym=Div(Flt(yy-1),Sub(ymp,ymn));
   
   
   OldIDCMP=Window->IDCMPFlags;
   ModifyIDCMP(Window,MOUSEBUTTONS);
   
   if(!KoordinatenKreuz_gezeichnet)Loeschen();
   SetAPen(RastPort,FARBE3);
   flagg=1;    /* ersten Punkt nur setzen     */
   
   StartBlock=Init_Mem(Formeln[nr]);
   MatheFehler=Init_Block(StartBlock);
   MatheFehler|=PreCalc(StartBlock,Konstantenstart);
   if(MatheFehler)
    {
     FehlerAbfrage(); /* Es ist ein Fehler aufgetreten ! */
    }
   else
    {
     yalt=FunktionsWert(nr,xmn,Ableitung);
     if(StartBlock->Fehler)flagg=2; /* NICHT MatheFehler */
     xalt=xmn;
     Verbinden(xalt,yalt);
     
     for (Pos=1+Genauigkeiten[GE];Pos<=MaxXPos;Pos+=Genauigkeiten[GE])
      {
       i=Div(Sub(Flt(Pos),x0),xm);
       /* Berechnet für einige x-Werte den Funktionswert und zeichnet ihn */
       y=FunktionsWert(nr,i,Ableitung);
       
       if(StartBlock->Fehler)
        {
         flagg=2;
        }
       Plotte(nr,xalt,i,yalt,y,0,Ableitung); /* Zeichnet den Punkt */
       xalt=i;
       yalt=y;
       /* Abfrage auf Unterbrechnung */
       H=EventAbfrage(Window,&msgInfo);
       if (H==MOUSEBUTTONS)
        {
         if(request(BE_JA,BE_NEIN,BE_QUEST))
          {
           Pos=MaxXPos;
           ZEICHNEN=FALSE;
          }
        }
      }
     
     if(ZEICHNEN)
      {
       y=FunktionsWert(nr,xmp,Ableitung);
       Plotte(nr,xalt,xmp,yalt,y,0,Ableitung); /* Zeichnet den letzten Punkt */
      }
     
     /* Alles, was in FARBE3 über den Rand hinausgezeichnet wurde, wird hier gelöscht.*/
     /* Dabei wird auch alles FARBE1 gelöscht. Beim Überschreiben wird darauf         */
     /* geachtet, daß FARBE3 nicht beeinträchtigt wird. Es wird nur ein Bit in der    */
     /* ersten BitPlane gesetzt, wenn dort FARBE3 erscheinen soll. Die zweite         */
     /* BitPlane wird nicht berührt.                                                  */
     
     WaitBlit();
     Forbid();
     SetAPen(RastPort,FARBE0);
     RectFill(RastPort,0,yy+Abstand+1,999,299);
     RectFill(RastPort,0,0,1000,Abstand);
     SetAPen(RastPort,FARBE1);
     /* Und neu zeichnen */
     SetWrMsk(RastPort,1);
     
     if(Cmp(x0,0.0)>=0 && (Fix(x0)<(xx)))
      {
       Line(x0,1.0,x0,Flt(yy));
      }
     if(Cmp(y0,0.0)>=0 && Cmp(y0,Flt(yy))<1)
      {
       Line(1.0,y0,Flt(xx),y0);
      }
     zeichne();
     SetWrMsk(RastPort,0xff);
     Permit();
     
     KoordinatenKreuz_gezeichnet=TRUE;
     FehlerAbfrage(); /* Ist ein Fehler aufgetreten ? */
    }
   while(H=EventAbfrage(Window,&msgInfo));
   ModifyIDCMP(Window,OldIDCMP);
   Free_Block(StartBlock);
  }
 
 /* Arbeitet rekursiv, bis y-Abstand zweier Punkte klein genug */
 VOID Plotte(nr,xl,xr,yl,yr,st,Ableitung)
 unsigned short nr;
 double xl,xr,yr,yl;
 int st,Ableitung;
  {
   double x,y,a;
   SHORT a1;
   long Sprung;
   
   /* GE liegt zwischen 1 und 3 */
   Sprung=4-GE;
   a=Sub(yl,yr);
   if(Cmp(Abs(a),MAXLONG)==1)
    {
     a1=0;
    }
   else
    {
     a1=(abs(Fix(a))>Sprung);
    }
   /* Großer Sprung zwischen 2 Werten (z.B. Pole) */
   if(a1)
    {
     /* Rekursionstiefe aufgrund der Zeichengenauigkeit */
     if(st<=10 && Cmp(Min(yl,yr),Flt(yy))==-1 && Tst(Max(yr,yl))==1)
      {
       x=Div((Add(xl,xr)),2.0); /* x-Wert zwischen den beiden Stellen */
                                /* Berechnen des Funktionswertes      */
       y=FunktionsWert(nr,x,Ableitung);
       Plotte(nr,xl,x,yl,y,st+1,Ableitung);
       Plotte(nr,x,xr,y,yr,st+1,Ableitung);
      }
     else
      {
       flagg=1; /* 2 Punkte werden nicht verbunden */
                /* z. B. 1/x bei x um 0            */
       Verbinden(xr,yr);
      }
    }
   else
    {
     Verbinden(xr,yr);
    }
  }
 
 double FunktionsWert(nr,i,Ableitung)
 int Ableitung;
 unsigned short nr;
 double i;
  {
   double ywert;
   double y;
   switch(Ableitung)
    {
     case 0:
      {
       MatheFehler|=Calc_P(&ywert,StartBlock,&i);
       goto Einsprung_B1;
      }
     case 1:    
      {
       double H1,H2,Help1;
       if(Ableitung==1)
        {
         Help1=(Add(i,deltah));
         MatheFehler|=Calc_P(&H1,StartBlock,&Help1);
         MatheFehler|=Calc_P(&H2,StartBlock,&i);
         ywert=Div(Sub(H1,H2),deltah);
         Einsprung_B1:
         y=Sub(y0,Mul(ym,ywert));
         break;
        }
       case 2:      
        {
         Help1=Add(i,deltahh);
         H1=FunktionsWert(nr,i,1);
         H2=FunktionsWert(nr,Help1,1);
         ywert=Div(Sub(H1,H2),deltahh);
         y=Sub(y0,ywert);
         break;
        }
      }
    }
   return(y);
  }
 
 
 VOID Verbinden(xr,yr)
 double xr,yr;
  {
   xr=Add(x0,Mul(xm,xr));
   
   if(Cmp(Abs(yr),MAXLONG)==-1)
    {
     /* Wenn zu zeichen (innerhalb Zeichenbereichs) */
     switch(flagg)
      {
       /* 2 Punkte nicht verbinden */
       case 1:
        {
         Pset(xr,yr);
         flagg=0;
         break;
        }
       case 2:
        {
         flagg=1;
         break;
        }
       case 0: 
        {
         /* Zum nächsten Punkt zeichnen. Wenn Koordinaten wie bei Pset, dann */
         /* wird nur ein Punkt gesetzt.                                      */
         DrawTo(xr,yr);
         break;
        }
      }
    }
   else
    {
     flagg=1;
    }
  }
 
 DOUBLE Max(a,b)
 DOUBLE a,b;
  {
   if(a>b)
    {
     return(a);
    }
   else
    {
     return(b);
    }
  }
 
 DOUBLE Min(a,b)
 DOUBLE a,b;
  {
   if(a>b)
    {
     return(b);
    }
   else
    {
     return(a);
    }
  }
 
  /* Hier kommen die Stub-Routinen, die für dieses Programm nicht */
  /* gebraucht werden. Dadurch werden sie nicht angelinkt.        */
 VOID MemCleanup(VOID)
  {
  }
 
 
 VOID chkabort(VOID)
  {
  }
 
 
 
