sin/cos in/um atan2 anders ausdruecken/optimieren?



  • v = atan2(cos(c),sin(c)) / 2
    sin_v = sin(v)
    cos_v = cos(v)

    ich moechte so schnell wie moeglich (also am besten so viel wie möglich auf sin/cos verzichten) an sin_v und cos_v - gibt es hier irgendeinen Bezug den ich nicht sehe und nutzen könnte?



  • c ist eine Reele Zahl, die Funktionssignatur sieht so aus atan2(y,x)



  • koennte man damit was anfangen?

    sin(x/2) => sqrt(1 - cos(x)) / sqrt(2)
    cos(x/2) => sqrt(1 + cos(x)) / sqrt(2)

    sqrt ist schneller als sin/cos - nach meinen bisherigen Tests


  • Mod

    Also der Sinus und Cosinus von der Hälfte des Winkels c? Wie wäre es mit sin(c/2) und cos(c/2)?



  • Wie wäre es mit sin(c/2) und cos(c/2)?

    du meinst

    aus
    v = atan2(cos(c),sin(c)) / 2.0
    sin_v = sin(v)
    cos_v = cos(v)

    wird?
    sin_v_= sin(c/2.0)
    cos_v_ = cos(c/2.0)

    ?

    da kommt aber was anderes raus

    z.B. bei c = 22.33

    cos_v = 0,57775252148063361
    sin_v = -0,81621199692406510

    dein
    cos_v_ = 0,16861631212423742
    sin_v_ = -0,98568176369740235



  • ich stütze mich gerade auf:
    http://www.arndt-bruenner.de/mathe/Allgemein/trigsimpl.htm
    (wobei das sin(x/2)=sqrt((1-cos(x))/2) wohl eher abs(sin(x/2)) sein soll - also mein Idee von oben nicht funktioniert 😞
    http://www.aia.rwth-aachen.de/vlueb/vl/aerodynamik_ii/oldexam/A_WSSS1011_AeroIIrel.pdf



  • Gast3 schrieb:

    die Funktionssignatur sieht so aus atan2(y,x)

    v = atan2(cos(c),sin(c)) / 2.0

    hast du dich da nur vertippt?

    kann es sein, dass du da grad mit radiant vermischt hast?

    also nachrechnen mit grad hat bei mir funktioniert, nachrechnen mit radiant auch, aber in beiden fällen stimmen deine ergebnisse nicht.



  • Ich habs mal Online-Kompilieren/Rechnen lassen mit diesem Code

    http://cpp.sh/46hsr

    #include <stdio.h>
    #include <math.h>
    
    int main()
    {
        double c = 22.33;
        double sin_c = sin(c);
        double cos_c = cos(c);
        double v = atan2(cos_c, sin_c)/2.0;
        double sin_v = sin(v);
        double cos_v = cos(v);
        double sin_v2 = sin(c/2.0);
        double cos_v2 = cos(c/2.0);
        printf("sin_v: %.3f, cos_v: %.3f, sin_v2: %.3f, cos_v2: %.3f\n", sin_v, cos_v, sin_v2, cos_v2);
    }
    

    Ergebnis: sin_v: -0.816, cos_v: 0.578, sin_v2: -0.986, cos_v2: 0.169



  • du hast bei der atan2 x und y vertauscht. sinus alpha ergibt y und cosinus alpha ergibt x.
    wenn du atan2(sin_c,cos_c) aufrufst gehts. http://cpp.sh/44ccw



  • du hast bei der atan2 x und y vertauscht.

    mein y ist aber cos(c) und x ist sin(c) - das kann ich nicht so einfach aendern sonst kommen bei der Berechung voellig andere Werte raus



  • also ich weiß ja nicht, was du da jetzt genau berechnen willst, aber

    tangens x ist sinus x/cosinus x. wenn du davon dann den arkustangens nimmst, hast du wieder x und wenn du das ganze durch 2 teilst, hast du x/2 und deshalb macht es (mathematisch) keinen unterschied, ob du cos(arctan(sin(x)/cos(x))/2) oder cos(x/2) rechnest.

    und bei gängigen kartesischen koordinatensystemen gibt der sinus die höhe des dreiecks 👍 und der cosinus die breite (x) an, weshalb du entweder atan2 falsch aufrufst, oder irgendetwas berechnen willst, dass so nicht funktioniert.



  • Wade1234 schrieb:

    tangens x ist sinus x/cosinus x. wenn du davon dann den arkustangens nimmst, hast du wieder x und wenn du das ganze durch 2 teilst, hast du x/2 und deshalb macht es (mathematisch) keinen unterschied, ob du cos(arctan(sin(x)/cos(x))/2) oder cos(x/2) rechnest.

    Und wenn er Sinus und Cosinus vertauscht, ergibt arctan den Gegenwinkel (bzw. dessen Bogenmaß bis auf Vorzeichen). Mithin

    double v2 = (M_PI/2 - c)/2;
    


  • und bei gängigen kartesischen koordinatensystemen gibt der sinus die höhe des dreiecks 👍 und der cosinus die breite (x) an, weshalb du entweder atan2 falsch aufrufst, oder irgendetwas berechnen willst, dass so nicht funktioniert.

    ich habe eine seit 10 Jahren im (Dauer)Einsatz befindliche (2 Glieder)5-Achs-Kinematik-Brechnung durch Mathematica Simplify usw gejagt und das ganze ca. um Faktor 20 beschleunigt - als Test läuft der optimierte Code parallel zum Original und durchläuft alle statischen und fixen Testcases die ich finden konnte, nebst Daten die eine Voll-Abdeckung des alten Berechungs-Codes verursachen - dahingehend würde ich mal vorsichtig behaupten meine Optimierung arbeitet wenigstens korrekt - die Sin/Cos sind Ergebnisse für einen Quaternian mit dem ich dann viel weiter rotieren



  • double v2 = (M_PI/2 - c)/2;

    Danke camper sieht schon mal ein wenig besser aus

    http://cpp.sh/6tbio

    kann man die Vorzeichnen noch angleichen - die sin(v2) und cos(v2) gehen nur
    noch multiplikativ ein - da ist das Vorzeichen wichtig 🙂



  • kann man die Vorzeichnen noch angleichen

    wird wohl schwer ohne atan2



  • sorry für die blöde frage, aber was willst du da eigentlich genau berechnen?



  • sorry für die blöde frage, aber was willst du da eigentlich genau berechnen?

    den Kontaktpunkt einer 2-Glider 5-Achs-Kinematik - ich habe aber bisher nur geprüft wie weit sich die Berechnungen aus dem Original-Code reduzieren lassen (bei 100% gleichen Daten zum Original)
    im wesentlichen sind das jetzt sin/cos von 2 Achsen und atan2 darauf - von dem m
    athematischen Zusammenhang erkennt man jetzt aber glaube ich nicht mehr viel

    meine letzte Idee war es jetzt noch den sin und cos von atan2(cos(c),sin(c))/2.0 auszuspezialisieren - dann werden alle weiteren sin/cos durch ein paar sqrts(die scheinbar weniger Power brauchen) ersetzt - bringt nochmal fast 5 sek bei 70Mio Durchläufen 🙂



  • Gast3 schrieb:

    double v2 = (M_PI/2 - c)/2;

    Danke camper sieht schon mal ein wenig besser aus

    http://cpp.sh/6tbio

    kann man die Vorzeichnen noch angleichen - die sin(v2) und cos(v2) gehen nur
    noch multiplikativ ein - da ist das Vorzeichen wichtig 🙂

    Die Vorzeichen sind entweder beide richtig oder beide falsch. Was letztlich damit zu tun hat, dass deine sin_v(c) und cos_v(c) keine richtigen sinus/cosinus-Funktionen sind.
    Wenns drauf ankommt, muss man eben beachten, in welchem Quadranten c liegt:

    double v2 = remainder(M_PI / 2 - c, 2 * M_PI) / 2;
    

  • Mod

    Versuch doch mal von den Mathematica-Umformungen weg zu kommen (die wahrscheinlich nicht funktionieren, da du wahrscheinlich mit komplexen Zahlen rechnest) und denk darüber nach, was die Formel tun soll. Denkst du, ich hätte für meine Antwort gerechnet und umgeformt? Ich habe nur gesehen, dass die Kombination sin, cos einen Winkel in ein Koordinatenpaar umwandelt, atan2 ein Koordinatenpaar zurück in einen Winkel umwandelt und du dann einfach nur wieder sin und cos von dem halben Winkel nimmst, man sich die ganze Umformerei auch hätte sparen können. Das ganze Geplänkel danach, wo du sin und cos vertauscht und/oder Minuszeichen einführst geht doch nur noch darum, wie genau du deine Winkel definierst. Also denk mal darüber nach, welchen Winkel genau du hier aus welchen Gründen halbieren möchtest, dann hast du deine Lösung sofort.



  • Versuch doch mal von den Mathematica-Umformungen weg zu kommen (die wahrscheinlich nicht funktionieren, da du wahrscheinlich mit komplexen Zahlen rechnest) und denk darüber nach, was die Formel tun soll.

    ich hab auch schon langsam gemerkt das Mathematica und Konsorten keine Wunder vollbringen - bisher habe ich es einfach vermieden mich tiefer einzuarbeiten - ist nur ein On-Off Projekt von mir und normalerweise mache ich gar nichts mit Mathe - oder ist 10 Jahre her das ich mal was gemacht habe - d.h. ich muss mich in jedes Detail wieder reinarbeiten - aber ihr öffnet mir gerade die Augen


Log in to reply