/********************************************************************/ /**** ****/ /**** ****/ /**** Program : Ableitung.c ****/ /**** ****/ /**** Version : 03.70 ****/ /**** ****/ /**** Erstversion : 09.03.1990 ****/ /**** ****/ /**** Letzte Änderung : 03.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 #ifndef LAENGE #define LAENGE 500 #endif char * __asm Ableiten(register __a0 char *string) { char Ergebnis[MAXCHARS]; char *EString; StartBlock=Init_Mem(string); MatheFehler=Init_Block(StartBlock); MatheFehler|=PreCalc(StartBlock,Konstantenstart); EString=Ableitung(StartBlock); strcpy(Ergebnis,EString); Free_Block(StartBlock); FreeMem(EString,LAENGE); return(Ergebnis); } VOID __asm Umklammern(register __a0 char *string) { char *HILFE; HILFE=AllocMem(LAENGE,MEMF_CLEAR); if(HILFE==NULL)return; if(check('+','-',0L,(LONG)strlen(string),string)!=-1L) { HILFE[0]='('; strcat(HILFE,string); strcat(HILFE,")"); strcpy(string,HILFE); } FreeMem(HILFE,LAENGE); } VOID __asm Umklammern_2(register __a0 char *string) { char *HILFE; Umklammern(string); HILFE=AllocMem(LAENGE,MEMF_CLEAR); if(HILFE==NULL)return; if(check('*','/',0L,(LONG)strlen(string),string)!=-1L) { HILFE[0]='('; strcat(HILFE,string); strcat(HILFE,")"); strcpy(string,HILFE); } FreeMem(HILFE,LAENGE); } VOID Zusammensetzen(char *string,LONG Anzahl,char *ABL,struct Block *Start) { char *abgeleitet; SHORT *a; LONG Anz; abgeleitet=Ableitung(Start->Right); strcpy(string,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(string); a=(SHORT *)string; /* if(strcmp(string,"0")) */ if((0x3000!=*a)) { /* if(strcmp(string,"1")==NULL) */ if(0x3100==*a) { string[0]=0; } else { strcat(string,"*"); } strcat(string,ABL); Anz=Start->Rechts-Start->Links-Anzahl; mid(&string[strlen(string)],Start->String,Start->Links+Anzahl+1,Anz); } } LONG __asm Mit_X(register __a0 struct Block *block) { LONG i,Flag=0; i=block->Links; while(i<=block->Rechts) { if(block->String[i]=='x')Flag++; i++; } return(Flag); } char * __asm Ableitung(register __a0 struct Block *Start) { LONG Anz; char *links,*rechts,*abgeleitet,*HILFE; /* Speicher reservieren */ rechts=AllocMem(LAENGE,MEMF_CLEAR); if(!rechts)return(0); HILFE=AllocMem(LAENGE,MEMF_CLEAR); if(!HILFE)return(0); switch(Start->RechenArt) { case ADDI: { SHORT *a; /* u+v --> u' + v' */ /* Speicher reservieren */ links=AllocMem(LAENGE,MEMF_CLEAR); if(!links)return(0); /* Ableitung von links */ abgeleitet=Ableitung(Start->Left); strcpy(links ,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(links); /* Ableitung von rechts */ abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); /* Zusammenfügen */ /* 0+ wird nicht gebraucht */ a=(SHORT *)links; /*if(strcmp(links,"0"))*/ if(0x3000!=*a) { a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { /* +0 wird auch nicht gebraucht */ strcat(links,"+"); strcat(links,rechts); } } else { /* Nur rechts nehmen */ strcpy(links,rechts); } strcpy(rechts,links); /* Wenn links und rechts 0 sind ... */ if(rechts[0]==0) { SHORT *a; a=(SHORT *)rechts; *a=0x3000; /* rechts[0]='0';rechts[1]=0; */ } FreeMem(links,LAENGE); break; } case SUBT: { SHORT *a; /* u-v --> u' - v' */ /* Speicher reservieren */ links=AllocMem(LAENGE,MEMF_CLEAR); if(!links)return(0); abgeleitet=Ableitung(Start->Left); strcpy(links ,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(links); abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); /*if(strcmp(links,"0"))*/ a=(SHORT *)links; if(0x3000!=*a) { a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { strcat(links,"-"); strcat(links,rechts); } } else { SHORT *a; a=(SHORT *)links; *a=0x2d00; /* links[0]='-'; links[1]=0; */ strcat(links,rechts); } strcpy(rechts,links); /*if(!strcmp(rechts,""))*/ if(0==rechts[0]) { SHORT *a; a=(SHORT *)rechts; *a=0x3000; /* rechts[0]='0';rechts[1]=0; */ } FreeMem(links,LAENGE); break; } case MULT: { SHORT *a; /* u*v --> u*v' + u'*v */ /* Speicher reservieren */ links=AllocMem(LAENGE,MEMF_CLEAR); if(!links)return(0); abgeleitet=Ableitung(Start->Left); strcpy(links ,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(links); abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { Anz=Start->Left->Rechts-Start->Left->Links+1; mid(HILFE,Start->String,Start->Left->Links,Anz); a=(SHORT *)rechts; /*if(strcmp(rechts,"1"))*/ if(0x3100!=*a) { Umklammern(HILFE); if(Vereinfachung(rechts,HILFE)) { rechts[0]=0; } else { strcat(rechts,"*"); } } else { rechts[0]=0; } strcat(rechts,HILFE); } a=(SHORT *)links; /*if(strcmp(links,"0"))*/ if(0x3000!=*a) { SHORT *a,*b; Anz=Start->Right->Rechts-Start->Right->Links+1; mid(HILFE,Start->String,Start->Right->Links,Anz); a=(SHORT *)links; /*if(strcmp(links,"1"))*/ if(0x3100!=*a) { Umklammern(HILFE); if(Vereinfachung(links,HILFE)) { links[0]=0; } else { strcat(links,"*"); } } else { links[0]=0; } strcat(links,HILFE); a=(SHORT *)links; b=(SHORT *)rechts; /*if(strcmp(links,"0") && strcmp(rechts,"0")) */ if((0x3000!=*a) && (0x3000!=*b)) { strcat(links,"+"); strcat(links,rechts); } strcpy(rechts,links); } FreeMem(links,LAENGE); break; } case DIVI: { SHORT *a; /* u/v --> (u'*v - u*v')/v^2 */ /* Speicher reservieren */ links=AllocMem(LAENGE,MEMF_CLEAR); if(!links)return(0); abgeleitet=Ableitung(Start->Left); strcpy(links ,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(links); abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { Anz=Start->Left->Rechts-Start->Left->Links+1; mid(HILFE,Start->String,Start->Left->Links,Anz); /*if(strcmp(rechts,"1"))*/ if(0x3100!=*a) { Umklammern(HILFE); strcat(rechts,"*"); } else { rechts[0]=0; } strcat(rechts,HILFE); } a=(SHORT *)links; /*if(strcmp(links,"0"))*/ if(0x3000!=*a) { Anz=Start->Right->Rechts-Start->Right->Links+1; mid(HILFE,Start->String,Start->Right->Links,Anz); /*if(strcmp(links,"1"))*/ if(0x3100!=*a) { Umklammern(HILFE); strcat(links,"*"); } else { links[0]=0; } strcat(links,HILFE); } if(strcmp(links,rechts)) { SHORT *a; Umklammern(rechts); a=(SHORT *)links; /*if(strcmp(links,"0"))*/ if(0x3000!=*a) { a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { strcat(links,"-"); strcat(links,rechts); } } else { a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { SHORT *a; a=(SHORT *)links; *a=0x2d00; /* links[0]='-'; links[1]=0; */ strcat(links,rechts); } } strcpy(rechts,links); } else { SHORT *a; a=(SHORT *)rechts; *a=0x3000; /* rechts[0]='0';rechts[1]=0; */ } a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { Umklammern(rechts); Anz=Start->Right->Rechts-Start->Right->Links+1; mid(HILFE,Start->String,Start->Right->Links,Anz); Umklammern(HILFE); strcat(HILFE,"^2"); strcat(rechts,"/"); strcat(rechts,HILFE); } FreeMem(links,LAENGE); break; } case POWE: { /* Speicher reservieren */ links=AllocMem(LAENGE,MEMF_CLEAR); if(!links)return(0); Anz=0; if(Mit_X(Start->Right))Anz=1; if(Mit_X(Start->Left ))Anz+=2; switch(Anz) { case 0: { /* Von X nicht abhängig */ /* rechts[0]='0';rechts[1]=0; */ SHORT *a; a=(SHORT *)rechts; *a=0x3000; break; } case 2: { SHORT *a; /* Basis von X abhängig */ /* x^a --> a*x^(a-1) */ Anz=Start->Right->Rechts-Start->Right->Links+1; mid(HILFE,Start->String,Start->Right->Links,Anz); Umklammern(HILFE); abgeleitet=Ableitung(Start->Left); strcat(links ,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(links); a=(SHORT *)links; /*if(strcmp(links,"1"))*/ if(0x3100!=*a) { strcat(links,"*"); } else { links[0]=0; } strcat(links,HILFE); strcat(links,"*"); Anz=Start->Left->Rechts-Start->Left->Links+1; mid(HILFE,Start->String,Start->Left->Links,Anz); Umklammern_2(HILFE); strcat(links,HILFE); strcat(links,"^("); Anz=Start->Right->Rechts-Start->Right->Links+1; mid(rechts,Start->String,Start->Right->Links,Anz); strcat(rechts,"-1)"); strcat(links,rechts); strcpy(rechts,links); break; } case 1: { SHORT *a; /* a^x --> a^x*ln(a) */ abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); a=(SHORT *)rechts; /*if(strcmp(rechts,"1"))*/ if(0x3100!=*a) { strcat(rechts,"*"); } else { rechts[0]=0; } /* Die Originalfunktion wieder zusammenstellen */ Anz=Start->Left->Rechts-Start->Left->Links+1; mid(links,Start->String,Start->Left->Links,Anz); Umklammern_2(links); strcat(rechts,links); strcat(rechts,"^"); Anz=Start->Right->Rechts-Start->Right->Links+1; mid(HILFE,Start->String,Start->Right->Links,Anz); Umklammern_2(HILFE); strcat(rechts,HILFE); strcat(rechts,"*ln("); strcat(rechts,links); strcat(rechts,")"); break; } case 3: { struct Block *New_START; char *NewFunc; /* 15.07.90: Fehler beseitigt. f(x) und g(x) waren vertauscht */ /* f(x)^g(x) <=> e^(ln(f(x)^g(x))) */ /* <=> e^g(x)*ln(f(x)) */ /* Abgeleitet => */ /* (g(x)*ln(f(x)))'*e^g(x)*ln(f(x)) */ /* <=> (g(x)*ln(f(x)))'*f(x)^g(x) */ /* Die Ableitung wird rekur. gebildet */ Anz=Start->Right->Rechts-Start->Right->Links+1; mid(HILFE,Start->String,Start->Right->Links,Anz); Umklammern_2(HILFE); strcpy(links,HILFE); strcat(links,"*ln("); Anz=Start->Left->Rechts-Start->Left->Links+1; mid(HILFE,Start->String,Start->Left->Links,Anz); strcat(links,HILFE); strcat(links,")"); New_START=Init_Mem(links); if(!New_START)return(0); Anz=Init_Block(New_START); NewFunc=Ableitung(New_START); strcpy(rechts,NewFunc); FreeMem(NewFunc,LAENGE); Free_Block(New_START); Umklammern(rechts); strcat(rechts,"*"); /* Die Originalfunktion wieder zusammenstellen */ Anz=Start->Left->Rechts-Start->Left->Links+1; mid(links,Start->String,Start->Left->Links,Anz); Umklammern_2(links); strcat(rechts,links); strcat(rechts,"^"); Anz=Start->Right->Rechts-Start->Right->Links+1; mid(HILFE,Start->String,Start->Right->Links,Anz); Umklammern_2(HILFE); strcat(rechts,HILFE); } } FreeMem(links,LAENGE); break; } case SINU: { /* sin(x) --> cos(x) */ Zusammensetzen(rechts,3,"cos(",Start); break; } case COSI: { SHORT *a; /* cos(x) --> -sin(x) */ Zusammensetzen(rechts,3,"sin(",Start); a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { SHORT *a; a=(SHORT *)HILFE; /* Hilfe = '-'; */ *a=0x2d00; strcat(HILFE,rechts); strcpy(rechts,HILFE); } break; } case TANG: { SHORT *a; /* tan(x) --> 1/cos^2(x) */ abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { strcat(rechts,"/cos("); Anz=Start->Right->Rechts-Start->Right->Links+1; mid(&rechts[strlen(rechts)],Start->String,Start->Right->Links,Anz); strcat(rechts,")^2"); } break; } case ASIN: { SHORT *a; /* asin --> 1/sqr(1-x^2) */ abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { strcat(rechts,"/sqr(1-"); Anz=Start->Right->Rechts-Start->Right->Links+1; mid(&rechts[strlen(rechts)],Start->String,Start->Right->Links,Anz); strcat(rechts,"^2)"); } break; } case ACOS: { SHORT *a; /* acos(x) --> -1/sqr(1-x^2) */ abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { strcat(rechts,"/sqr(1-"); Anz=Start->Right->Rechts-Start->Right->Links+1; mid(&rechts[strlen(rechts)],Start->String,Start->Right->Links,Anz); strcat(rechts,"^2)"); } if(0x3000!=*a) /*if(strcmp(rechts,"0"))*/ { /*strcpy(HILFE,"-");*/ SHORT *a; a=(SHORT *)HILFE; *a=0x2d00; strcat(HILFE,rechts); strcpy(rechts,HILFE); } break; } case ATAN: { SHORT *a; /* atan(x) --> 1/(1+x^2) */ abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { strcat(rechts,"/(1+"); Anz=Start->Right->Rechts-Start->Right->Links+1; mid(&rechts[strlen(rechts)],Start->String,Start->Right->Links,Anz); strcat(rechts,"^2)"); } break; } case LOG1: { SHORT *a; /* log(x) --> 1/(x*ln10) */ abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x300!=*a) { strcat(rechts,"/("); Anz=Start->Right->Rechts-Start->Right->Links+1; mid(&rechts[strlen(rechts)],Start->String,Start->Right->Links,Anz); strcat(rechts,"*"); strcat(rechts,"ln(10))"); } break; } case LNAT: { SHORT *a; /* ln(x) --> 1/x */ abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { Anz=Start->Right->Rechts-Start->Right->Links+1; mid(HILFE,Start->String,Start->Right->Links,Anz); strcat(rechts,"/"); Umklammern_2(HILFE); strcat(rechts,HILFE); } break; } case ABSO: { /* Kann man drüber diskutieren.... */ /* abs(x) --> sgn(x) */ Zusammensetzen(rechts,3,"sgn(",Start); break; } case SQRT: { SHORT *a; /* sqr(x) --> 1/2*x^-1/2 */ abgeleitet=Ableitung(Start->Right); strcpy(rechts,abgeleitet); FreeMem(abgeleitet,LAENGE); Umklammern(rechts); a=(SHORT *)rechts; /*if(strcmp(rechts,"0"))*/ if(0x3000!=*a) { /*if(!strcmp(rechts,"1"))*/ if(0x3100==*a) { SHORT *a; a=(SHORT *)rechts; *a=0x3100; /* rechts[0]='1';rechts[1]=0; */ } strcat(rechts,"/2*"); Anz=Start->Right->Rechts-Start->Right->Links+1; mid(HILFE,Start->String,Start->Right->Links,Anz); Umklammern_2(HILFE); strcat(rechts,HILFE); strcat(rechts,"^(-1/2)"); } break; } case FLOO: case ZIFF: case UKON: case MKON: case SIGU: { SHORT *a; a=(SHORT *)rechts; *a=0x3000; /* rechts[0]='0';rechts[1]=0; */ break; } case X: { SHORT *a; a=(SHORT *)rechts; *a=0x3100; /* rechts[0]='1';rechts[1]=0; */ break; } default: { /* FEHLER, es sollten alle Fälle abgedeckt sein */ } } FreeMem(HILFE,LAENGE); return(rechts); } /* Funktion, die den Term a/b*b auf a vereinfacht */ /* Wenn b von x abhängig ist, dann stimmt das so eigentlich nur für b<>0 */ LONG __asm Vereinfachung(register __a0 char *a, register __a1 char *b) { char *HILFE; LONG Pos,Flag=0; Umklammern(a); Umklammern(b); HILFE=AllocMem(LAENGE,MEMF_CLEAR); if(!HILFE)return(0); if(Pos=check('/','/',0L,(LONG)strlen(a),a)!=-1L) { strcpy(HILFE,&a[Pos+1]); if(!strcmp(HILFE,b)) { left(HILFE,a,Pos); Flag=1; } } if(Pos=check('/','/',0L,(LONG)strlen(b),b)!=-1L) { strcpy(HILFE,&b[Pos+1]); if(!strcmp(HILFE,a)) { left(HILFE,b,Pos); Flag=1; } } if(Flag)strcpy(b,HILFE); FreeMem(HILFE,LAENGE); return(Flag); }