für Interessierte:
Hier meine selbst geschriebenen und auch selsbt ausgedachten (außer sinus) Festpunktfunktionen.
Alle Funktionen arbeiten im Gradmaß!!! mit 7 Festkommabits das erspart einem die umrechnung mit PI
Code:int16_t arccos(long number); //Eingabe 14 Festkommabits Ausgabe 7 Festkommabits int16_t arctan(long number); //Eingabe 10 Festkommabits Ausgabe 7 Festkommabits int16_t arctan2(int16_t y,int16_t x); //Eingaben proportional Ausgabe 7 Festkommabits int16_t cosinus(long x); //Eingabe 7 Festkommabits Ausgabe 14 Festkommabits inline int8_t signf(float number); //liefert 1 für positive und -1 für negtive Zahlen des tüps float inline int8_t signl(long number); //des typs long (32-Bit) inline int8_t signi(int16_t number); //des typs int16_t int16_t sinus(long x); //Eingabe 7 Festkommabits Ausgabe 14 Festkommabits uint16_t sqroot(unsigned long number); //Eingabe positive ganzzahl //**************************************************// 100-1200 Takte* uint16_t sqroot(unsigned long number) // O(n)=log_2(n) Max Abweichung meistens 0 oder 1, selten 2 bzw. 0.1% für große zahlen { if(number==0) return 0; //triviale Fälle abfangen if(number==1) return 1; unsigned long r2; uint16_t root=0,delta; if(number>=64536) //falls die Zahl größer als eine 16 Bit Zahl ist delta=32768; //maximal mögliche Wurzel versuchen (2^15+2^14+2^13...=65535) else delta=(number>>1); //sonst beginn bei der Zahl selbst druch 2 while (delta) //liefert binnen 15 Iterationen eine Lösung { r2=(unsigned long)root*root; if(r2<number) root+=delta; else root-=delta; delta=(delta>>1); } return root; } //**************************************************// //**************************************************// 762 Takte* const long W=23040UL; //Winkel eines Halbkreises Skalierung 128 = 7 Festkommabits const long W2=46080UL; //Winkel eines Vollkreises const uint16_t Wd2=11520; //Winkel eines Viertelkreises häufige verwendung spart Rechenzeit int16_t sinus(long x) // { if(x>W2) x%=W2; //Skalierung auf den bereich [0;W2] (Sinuswelle) if(x>W) x=-x+W; //x wird auf das Intervall [-W;W] normiert (aufgrund der Achsensymmetrie um x=0) if(x<-W) x=-x-W; //Parabel const long B = 182; //2^-13 //(4/W); //linearer Formfaktor der Parabel const long C = -259;//2^-21 //(-4/(W*W)); //quadratischer Formfaktor der Parabel long y=((B*x)>>6)+((((C*x)>>11)*x*signl(x))>>10); //2^-14 //Funktionswert der einfachen Parabel //Parabel Korrektur const long Q = 99; //2^-7 //0.775; //Linearfaktor der einfachen parabel const long P = 29; //2^-7 //0.225; //Linearfaktor der quadrierten korektur Parabel y=((Q*y)>>7)+((((P*y)>>7)*y*signl(y))>>14); //2^-14 //Endergebnis nach gewichteter Summenbildung return y; } //**************************************************// //**************************************************// 768 Takte* int16_t cosinus(long x) // { // return sinus((x+Wd2)); } //**************************************************// //**************************************************// 1800 Takte* int16_t arccos(long number) // { // if (number==0) return Wd2; // 0 Abfangen else if (number>=16384) return 0; // Werte größer 1 und kleiner -1 abfangen else if (-number>=16384) return W; if (signl(number)==1) // number>=0 return ((((long)sqroot(16384-number)*151511)>>11)+(((long)(16384-number)*4101)>>15)); //Faktoren 2^-11 und 2^-8 Ergebnis 2^-7 else return (W-((((long)sqroot(16384+number)*151511)>>11)+(((long)(16384+number)*4101)>>15))); } //**************************************************// //**************************************************// 974 Takte* int16_t arctan(long number) // { // int8_t v; unsigned long x; if (number==0) return 0; if (number>0) {x= number;v=1;} // Betrag und Vorzeichen von number else {x=-number;v=-1;} if (x> 8388608UL) return (v* Wd2); //für |x|>2^13 gilt +-90° if (x<1024) //für x<1 gilt allg.: x/(1+0.28x) return v*(((209539UL*x)>>3)/(((x*x)>>10)+3657)); //zähler/nenner= 2^-17/2^-10=2^-7 else if(x<60000UL) // sonst gilt allg.: PI/2-x/(x²+0.28) return v*(Wd2-((58671UL*(x>>3))/(((x*x)>>10)+287))); //zähler/nenner= 2^-17/2^-10=2^-7 else { x=(x>>5); //anpassung zum Schutz vor Überläufen return v*(Wd2-(((58671UL*x)>>8)/(((x*x)+287)>>10))); //zähler/nenner= 2^-7/2^0=2^-7 } } //**************************************************// //**************************************************// 1729 Takte* int16_t arctan2(int16_t y,int16_t x) // { // if(x==0) //Vorzeichenorientierte Fallunterscheidung { if (y==0) return 0; else return signi(y)*Wd2; } if(x>0) return arctan(((long)y<<10)/x); else return arctan(((long)y<<10)/x)+signi(y)*W; } //**************************************************// //**************************************************// 5 Takte* inline int8_t signf(float number) { if (signbit(number)) return -1; else return 1; } inline int8_t signi(int16_t number) { if(number&(1<<15)) return -1; else return 1; } inline int8_t signl(long number) { if(number&(1<<31)) return -1; else return 1; } //**************************************************//







Zitieren
Lesezeichen