/********************************************************************/ /**** ****/ /**** ****/ /**** 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 #endif #include #include #include "Plotter.h" #include #include #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