CPoint für 3 Dimensionen?



  • Gibt es irgendwo eine allgemeine Klasse für n-dimensionale Punkte bzw. Vektoren?



  • Erhard Henkes schrieb:

    Gibt es irgendwo eine allgemeine Klasse für n-dimensionale Punkte bzw. Vektoren?

    Ja klar, hier.



  • Da ja schon einige mehr oder weniger gelungene Implementierungen von einem Vektor mit drei Dimensionen die Runde gemacht haben, will ich Euch meine Variante nicht vorenthalten.

    #include <boost/operators.hpp>
    #include <iostream>
    #include <cmath>
    
    template< typename T >
    class basic_vector :    boost::additive< basic_vector< T >, 
                            boost::multiplicative< basic_vector< T >, T,
                            boost::modable< basic_vector< T > > > >
    {
    public:
        typedef T value_type;
    
        basic_vector() : m_x(), m_y(), m_z()  {}
        basic_vector( value_type x, value_type y, value_type z = value_type() )
            : m_x( x ), m_y( y ), m_z( z )
        {}
    
        // Addition, Subtraktion
        basic_vector& operator+=( const basic_vector& b )
        {
            m_x += b.m_x; m_y += b.m_y; m_z += b.m_z;
            return *this;
        }
        basic_vector& operator-=( const basic_vector& b )
        {
            m_x -= b.m_x; m_y -= b.m_y; m_z -= b.m_z;
            return *this;
        }
    
        // Multiplikation, Division mit einem Skalar
        basic_vector& operator*=( value_type f )
        {
            m_x *= f; m_y *= f; m_z *= f;
            return *this;
        }
        basic_vector& operator/=( value_type f )
        {
            m_x /= f; m_y /= f; m_z /= f;
            return *this;
        }
    
        // Betrag
        friend value_type abs( const basic_vector& v )
        {
            using namespace std;
            return sqrt( v.m_x * v.m_x + v.m_y * v.m_y + v.m_z * v.m_z );
        }
    
        // Skalerprodukt
        value_type operator*( const basic_vector& b ) const
        {
            return m_x * b.m_x + m_y * b.m_y + m_z * b.m_z
        }
        // Kreuzprodukt
        basic_vector operator%=( const basic_vector& b )
        {
            const value_type x = m_y * b.m_z - m_z * b.m_y;
            const value_type y = m_z * b.m_x - m_x * b.m_z;
            m_z = m_x * b.m_y - m_y * b.m_x;
            m_x = x;
            m_y = y;
            return *this;
        }
    
        friend std::ostream& operator<<( std::ostream& out, const basic_vector& v )
        {
            return out << v.m_x << " " << v.m_y << " " << v.m_z;
        }
    private:
        value_type m_x, m_y, m_z;
    };
    
    typedef basic_vector< double > Vector;
    

    Der Vektor bietet alle üblichen Vektor-Operationen an; benutzt boost.operators um redundanten Code zu vermeiden und der Typ der Einheit ist frei wählbar; default ist double.

    Ganz absichtlich sind weder Getter/Setter-Methoden noch Vergleichsoperatoren enthalten.

    Andere Methoden bzw. (friend-)Funktionen wie Orthogonale oder min/max sind nach eigenem Bedarf hinzuzufügen.

    Gruß
    Werner



  • Das is dochmal was... 🙂
    Ich versteh nur nicht warum jeder lieber Dividiert wenn man genausogut Multiplizieren kann. Multiplikationen von Fließkommazahlen ist schneller, wirklich!!!

    grüße



  • Eine interessante Sammlung. Danke für den Hinweis auf boost.



  • David_pb schrieb:

    Multiplikationen von Fließkommazahlen ist schneller, wirklich!!!

    Versteh' ich Dich richtig, dass

    basic_vector& operator/=( value_type f )
        {
            return *this *= (value_type(1)/f);
        }
    

    schneller sein soll, als

    basic_vector& operator/=( value_type f )
        {
            m_x /= f;
            m_y /= f;
            m_z /= f;
            return *this;
        }
    

    wäre mir neu. Um wieviel? Hast Du's gemessen?

    Fragt
    Werner



  • Ja, sollte schneller sein. Evtl solltest du nicht den *= Operator verwenden sondern direkt Implementieren.
    Ich habs auch mal gemessen, bei mir was bis zu drei mal schneller mit der Multiplikation.

    grüße



  • Warum verzichtet ihr auf SIMD? Ne gute Klasse prüft ob SIMD vorhanden ist und verwendet SIMD.
    Alternativ: Die Mathe-Funktionen aus DirectX machen das schon und man verwendet einfach DirectX.



  • David_pb schrieb:

    Ja, sollte schneller sein. Evtl solltest du nicht den *= Operator verwenden sondern direkt Implementieren.
    Ich habs auch mal gemessen, bei mir was bis zu drei mal schneller mit der Multiplikation.

    grüße

    Ja Wahnsinn, Du hast Recht. Das ist signifikant schneller - bei mir mehr als Faktor 10. 👍
    Die direkte Implementierung bringt übrigens gar nichts. Das kann man so lassen wie in meinem letzten Posting.

    Man lernt doch nie aus.

    Danke & Gruß
    Werner



  • Division ist immer langsamer wie eine Multiplikation, das wird dir jeder bestätigen der mal den schaltplan für beides erstellt hat. Und oben ist es ja eine Float-Division und die wurde ja gegen die Float-Multiplikation getauscht, das muss schneller sein.



  • Ich such gerade den Sinn deines Posts... Das die Division schneller ist war ja bereits geklärt...



  • Lolz schrieb:

    Warum verzichtet ihr auf SIMD? Ne gute Klasse prüft ob SIMD vorhanden ist und verwendet SIMD.
    Alternativ: Die Mathe-Funktionen aus DirectX machen das schon und man verwendet einfach DirectX.

    Meine Rede. f'`8k

    Gruß, TGGC (\-/ returns)



  • Es soll den Fall geben das man unabhängig von DirectX bleiben will, z.B. wenn man OpenGL als API verwendet...
    Aber die Verwendung von SIMD macht schon Sinn, soweit der Prozessor mitspielt!

    grüße


  • Administrator

    Und wie verwendet man SIMD? Das ist doch SSE Support, bzw. SSE2, SSE3 und ich dachte dies müsste man beim Compilier einstellen. Wie kann man denn sowas bei einer Klasse dazufügen? 😕

    Grüssli



  • Viele Compiler bieten die Möglichkeit, per Inline Assembler, Assemblercode in den C++ Quelltext zu integrieren.
    So kannst du auch diverse CPU Extensions unterstützen.

    grüße



  • David_pb schrieb:

    Ich such gerade den Sinn deines Posts... Das die Division schneller ist war ja bereits geklärt...

    Weiter oben aber nicht, darauf hab ich mich bezogen:

    Werner Salomon schrieb:

    David_pb schrieb:

    Multiplikationen von Fließkommazahlen ist schneller, wirklich!!!

    Versteh' ich Dich richtig, dass

    basic_vector& operator/=( value_type f )
        {
            return *this *= (value_type(1)/f);
        }
    

    schneller sein soll, als

    basic_vector& operator/=( value_type f )
        {
            m_x /= f;
            m_y /= f;
            m_z /= f;
            return *this;
        }
    

    wäre mir neu. Um wieviel? Hast Du's gemessen?

    Fragt
    Werner



  • Werner Salomon schrieb:

    David_pb schrieb:

    Ja, sollte schneller sein. Evtl solltest du nicht den *= Operator verwenden sondern direkt Implementieren.
    Ich habs auch mal gemessen, bei mir was bis zu drei mal schneller mit der Multiplikation.

    grüße

    Ja Wahnsinn, Du hast Recht. Das ist signifikant schneller - bei mir mehr als Faktor 10. 👍
    Die direkte Implementierung bringt übrigens gar nichts. Das kann man so lassen wie in meinem letzten Posting.

    Achtung: Was ist, wenn 'value_type' ein Integer-Typ ist? Dann wird zu früh gerundet.
    => Die Optimierung mit Multiplikation funktioniert nur, wenn es sich um einen Fließkommatypen handelt, für diese Fälle sollte man evtl. Template-Spezialisierungen der Methode(n) schreiben.



  • BTW: Ein schlauer Compiler wird die Optimierung (* statt /) selbst durchführen (wenn man es ihm erlaubt).


Anmelden zum Antworten