 /********************************************************************/
 /****                                                            ****/
 /****                                                            ****/
 /****    Program          : Diskussion.c                         ****/
 /****                                                            ****/
 /****    Version          :    03.71                             ****/
 /****                                                            ****/
 /****    Erstversion      : 04.11.1989                           ****/
 /****                                                            ****/
 /****    Letzte Änderung  : 05.08.1990                           ****/
 /****                                                            ****/
 /****    Compiliert mit   : siehe MAKEFILE                       ****/
 /****                                                            ****/
 /****    Gelinkt mit      : siehe MAKEFILE                       ****/
 /****                                                            ****/
 /********************************************************************/
 /****                                                            ****/
 /****                                                            ****/
 /****               Copyright by Rüdiger Dreier                  ****/
 /****                                                            ****/
 /****                                                            ****/
 /********************************************************************/
 
 #ifdef DEBUG
 #include "Plotter.h"
 #include <proto/tool.h>
 #endif
 #include <stdio.h>
 #include <string.h>
 #include "Plotter.h"
 
 #include <string.h>
 #include <stdlib.h>
 #define SCHRITTE 200
 
 DOUBLE BestF,BestX;
 
 char AusgabeString[125]; /* Höchster auftretender Wert : 123 */
 #undef  GRENZE1
 #define GRENZE1 0.0002
 #define GRENZE2 0.0000002
 #define NONULL  HUGE
 
 LONG ypos_Diskussion;
 LONG xpos_Diskussion;
 
 VOID discuss(char *string,DOUBLE l,DOUBLE r,int modus,unsigned short sub)
  {
   double i,var,fl,fr,add,fwert,flp,frp,Zugabe,h,vzl,vzr;
   char text[5];
   char NoNull=0;
   
   StartBlock=Init_Mem(string); /* Struktur für die zu untersuchende Funktion */
   if(!StartBlock)return;
   MatheFehler=Init_Block(StartBlock);
   MatheFehler|=PreCalc(StartBlock,Konstantenstart);
   
   switch(modus)
    {
     case 0:
      {
       Print(RastPort,DISK_NULLST,FARBE3,10,ypos_Diskussion);
       break;
      }
     case 1:
      {
       Print(RastPort,DISK_EXTREMST,FARBE3,10,ypos_Diskussion);
       break;
      }
     case 2:
      {
       Print(RastPort,DISK_WENDEST,FARBE3,10,ypos_Diskussion);
       break;
      }
    };
   add=Div(Sub(r,l),SCHRITTE);
   l=Sub(l,add); /* Die Grenzen werden etwas erweitert, um Randextrema */
   r=Add(r,add); /* zu erfassen                                        */
   Zugabe=Div(add,SCHRITTE/2);
   Calc_P(&fl,StartBlock,&l);
   flp=Abs(fl);
   
   for(i=Add(l,add);Cmp(i,r)<=0;i=Add(i,add))
    {
     Calc_P(&fr,StartBlock,&i);
     frp=Abs(fr);
     if((Tst(fl)!=Tst(fr)) || (Cmp(frp,GRENZE1)==-1 && Tst(flp)))
      {
       /* Eine Nullstelle ! */
       if(Tst(fl)!=Tst(fr))
        {
         var=Nullstelle(Sub(i,add),i);
         i=Add(i,add);
         Calc_P(&fr,StartBlock,&i);
         frp=Abs(fr);
        }
       else
        {
         var=Nullstelle2(Sub(i,add),i);
         if(Cmp(var,HUGE)==0)NoNull=1;
         
         if(Cmp(Add(var,Zugabe),i)>=1)
          {
           while(Cmp(frp,GRENZE1)==-1 && Cmp(i,r)==-1)
            {
             i=Add(i,add);
             MatheFehler=Calc_P(&fr,StartBlock,&i);
             frp=Abs(fr);
            }
          }
        }
       berechnen(&fwert,Formeln[sub],&var,(struct Konstanten *)Konstantenstart,&MatheFehler);
       
       MatheFehler=Calc_P(&h,StartBlock,&var);
       
       if(MatheFehler!=0 || Cmp(Abs(h),GRENZE2)==1)
        {
         NoNull=1;
        }
       
       if(modus>0)
        {
         h=Sub(var,GRENZE2);
         Calc_P(&vzl,StartBlock,&h); /* f(x) links  neben Nullstelle */
         h=Add(var,GRENZE2);
         Calc_P(&vzr,StartBlock,&h); /* f(x) rechts neben Nullstelle */
         if(Tst(vzl)==Tst(vzr))
          {
           NoNull=1;
          }
        }
       
       if(!NoNull)
        {
         switch(modus)
          {
           case 0:
            {
             /* f(x) */
             text[0]=0;
             /*strcpy(text,"");*/
             break;
            }
           case 1:
            {
             /* f'(x) */
             if(Cmp(fl,fr)==-1)
              {
               strcpy(text,"Min");
              }
             else
              {
               strcpy(text,"Max");
              }
             break;
            }
           case 2:
            {
             /* f''(x) */
             if(Cmp(fl,fr)==-1)
              {
               strcpy(text,"R-L");
              }
             else
              {
               strcpy(text,"L-R");
              }
             break;
            }
          }
         TextAusgabe(var,fwert,text);
        }
      }
     NoNull=0;
     fl=fr;
     flp=frp;
    }
   Free_Block(StartBlock); /* Speicher freigeben */
  }
 
 
 /* Bestimmt Nullstelle, wenn Vorzeichenwechsel vorliegt */
 DOUBLE Nullstelle(l,r)
 double l,r;
  {
   double i,fl,fr,fm,nl,nr;
   char tiefe=0;
   
   nl=l;
   nr=r;
   
   if(tiefe==0)
    {
     BestF=100.0;
     BestX=l;
    }
   
   MatheFehler=Calc_P(&fl,StartBlock,&l);
   if(MatheFehler==0&&Tst(fl)==0)return(l);
   
   MatheFehler=Calc_P(&fr,StartBlock,&r);
   if(MatheFehler==0&&Tst(fr)==0)return(r);
   /* Intervallschachtelung */
   while(tiefe<=40)
    {
     i=Div(Add(nl,nr),2.000);
     
     MatheFehler=Calc_P(&fm,StartBlock,&i);
     
     if(MatheFehler==0)
      {
       if(Cmp(Abs(fm),4000.0)==1)
        {
         tiefe=42; /* Wird wohl keine Nullstelle sein */
        }
       if(Cmp(Abs(fm),BestF)==-1L)
        {
         BestF=Abs(fm); /* Besser als bisheriger Wert */
         BestX=i;
        }
      }
     
     if(Tst(fl)!=Tst(fm))
      {
       nr=i;
      }
     else
      {
       nl=i;
      }
     tiefe++;
    }
   
   if(MatheFehler!=0 && tiefe==41)
    {
/* Ist die Funktion nur für einen Randwert des ursprünglichen Bereichs l-r */
/* definiert (z.B. sqr mit l=-0.5 und r=0.0), dann wird immer ein Fehler   */
/* beim Berechnen des Funktionswertes für die Mitte festgestellt.          */
     
     MatheFehler=Calc_P(&fm,StartBlock,&r);
     if(MatheFehler==0&&Cmp(Abs(fm),GRENZE2)==-1L)
      {
       i=r; /* Eine Näherung */
      }
     else
      {
       MatheFehler=Calc_P(&fm,StartBlock,&l);
       if(MatheFehler==0 && Cmp(Abs(fm),GRENZE2)==-1L)
        {
         i=l; /* Eine Näherung */
        }
      }
    }
   
   if(Cmp(Abs(fm),BestF)==1)i=BestX;
   return(i);
  }
 
 /* Bestimmt Nullstelle, wenn kein VZ vorliegt */
 DOUBLE Nullstelle2(l,r)
 double l,r;
  {
   double i,fl,fr,fm,flp,frp,fmp,add;
   add=(Sub(r,l));
   
   Calc_P(&fl,StartBlock,&l);
   flp=Abs(fl);
   Calc_P(&fr,StartBlock,&r);
   frp=Abs(fr);
   
   /* Sorgt dafür, daß r außerhalb des Bereiches unter GRENZE1 liegt */
   if(Cmp(frp,GRENZE1)==-1)     
    {
     /* rechte Stelle suchen, für die f(x)>GRENZE1 */
     while(Cmp(frp,GRENZE1)==-1)
      {
       r=Add(r,add);
       Calc_P(&fr,StartBlock,&r);
       frp=Abs(fr);
       if(Tst(fl)!=Tst(fr))
        {
         l=Nullstelle(l,r);
         return(l);
        }
      }
    }
   add=Div(Sub(r,l),SCHRITTE);
   i=Add(l,add);
   Calc_P(&fm,StartBlock,&i);
   fmp=Abs(fm);
   /* Tastet sich von links heran, solange wie die F-Werte immer kleiner werden */
   while(Cmp(flp,fmp)==1)
    {
     l=i;
     flp=fmp;
     i=Add(i,add);
     Calc_P(&fm,StartBlock,&i);
     fmp=Abs(fm);
     if(Tst(fl)!=Tst(fr))
      {
       l=Nullstelle(l,r);
       return(l);
      }
    }
   
   i=Sub(r,add);
   Calc_P(&fm,StartBlock,&i);
   fmp=Abs(fm);
   /* Tastet sich entsprechend von rechts heran */
   while(Cmp(frp,fmp)==1&&Cmp(r,l)==1)
    {
     r=i;
     frp=fmp;
     i=Sub(i,add);
     Calc_P(&fm,StartBlock,&i);
     fmp=Abs(fm);
     if(Tst(fl)!=Tst(fr))
      {
       l=Nullstelle(l,r);
       return(l);
      }
    }
   
   if(Cmp(Min(flp,frp),GRENZE2)==-1)
    {
     if(Cmp(flp,frp)==1)
      {
       return(r);
      }
     else
      {
       return(l);
      }
    }
   else
    {
     return(NONULL);
    }
  }
 
 VOID TextAusgabe(DOUBLE x,DOUBLE y,char *string)
  {
   char ZwischenString[50];
   char xc[10],yc[10];
   LONG max_x=562;
   SHORT *a;
   if(Groesse)
    {
     max_x=994;
    }
   
   /* Besser: min(abs(xmn,xmp)) nehmen */
   if(Cmp(Abs(x),Div(xmp,1000.0))==-1)x=0.0000; /* Runden */
   if(Cmp(Abs(y),Div(ymp,1000.0))==-1)y=0.0000;
   
   UmwFtoS(xc,&x,3);
   Laenge(xc,9);
   UmwFtoS(yc,&y,3);
   Laenge(yc,9);
   
   /*strcpy(ZwischenString,"(");*/
   a=(SHORT *)ZwischenString;
   *a=0x2800;
   
   strcat(ZwischenString,xc);
   strcat(ZwischenString,"/");
   strcat(ZwischenString,yc);
   strcat(ZwischenString,")");
   strcat(ZwischenString,string);
   if(xpos_Diskussion>=max_x)
    {
     xpos_Diskussion=146;
     ypos_Diskussion+=10;
    }
   Print(RastPort,ZwischenString,FARBE3,xpos_Diskussion,ypos_Diskussion);
   xpos_Diskussion+=216; /* 29*8 */
  }
 
 VOID TextAusgabe2(char *string)
  {
   LONG SPos=0;
   LONG Max_Zeichen=53;
   
   if(Groesse)
    {
     Max_Zeichen=107;
    }
   
   do
    {
     mid(AusgabeString,string,SPos,Max_Zeichen);
     SPos+=Max_Zeichen;
     Print(RastPort,AusgabeString,FARBE3,146L,ypos_Diskussion);
     ypos_Diskussion+=10;
    }
   while(AusgabeString[0]!=0);
   ypos_Diskussion-=10;
   xpos_Diskussion=146;
  }
 
 /* Fügt VOR dem string so viele Leerzeichen ein, */
 /* daß der String laenge lang wird               */
 VOID __asm Laenge(register __a0 char *string,
                   register __d0 int laenge)
  {
   SHORT a;
   SHORT i;
   char HILFE[18];
   
   a=laenge-(strlen(string));
   
   for(i=0;i<a;i++)
    {
     HILFE[i]=32;
    }
   HILFE[i]=0;
   strcat(HILFE,string);
   strcpy(string,HILFE);
  }
 
 VOID __asm Full_Discussion(register __d0 USHORT sub)
  {
   Loeschen();
   strcpy(Abgeleitet[0],DISK_FOR);
   UmwFtoS(&Abgeleitet[0][strlen(Abgeleitet[0])],&xmn,3);
   strcat(Abgeleitet[0],"|");
   UmwFtoS(&Abgeleitet[0][strlen(Abgeleitet[0])],&xmp,3);
   strcat(Abgeleitet[0],"]");
   Print(RastPort,Abgeleitet[0],FARBE3,10L,15L);
   ypos_Diskussion=35;
   
   /* Bilden der 1. Ableitung */
   strcpy(Formeln[10],Formeln[sub]);
   strcpy(Abgeleitet[0],Ableiten(Formeln[10]));
   
   /* Bilden der 2. Ableitung */
   strcpy(Formeln[10],Abgeleitet[0]);
   strcpy(Abgeleitet[1],Ableiten(Formeln[10]));
   
   KoordinatenKreuz_gezeichnet=FALSE;
   
   Print(RastPort,"f  (x)        =",FARBE3,10L,ypos_Diskussion);
   TextAusgabe2(Formeln[sub]);
   discuss(Formeln[sub],xmn,xmp,0,sub);
   ypos_Diskussion+=15;
   
   Print(RastPort,"f' (x)        =",FARBE3,10L,ypos_Diskussion);
   TextAusgabe2(Abgeleitet[0]);
   discuss(Abgeleitet[0],xmn,xmp,1,sub);
   ypos_Diskussion+=15;
   
   Print(RastPort,"f''(x)        =",FARBE3,10L,ypos_Diskussion);
   TextAusgabe2(Abgeleitet[1]);
   discuss(Abgeleitet[1],xmn,xmp,2,sub);
  }
