Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimize small 3d vector struct for performance

Tags:

c++

struct

vector

I am fairly new to C++ and have the following, let's call it, issue. In my computer simulation, I am working quite a lot with vectors. I built myself a small struct that represents a vector, and would like to learn how to make the operations (like for example the normalize() function more efficient. Also, is there any benefit in using C++'s valarray? It seems to have some useful methods pre-implemented.

I almost exclusively use the normalize() function and addition/substraction/multiplication of vectors. Since all my vectors have only three elements, I am hesitant of including 3rd party libraries in my project.

This is my struct:

struct vector_t {
    int _i, _j, _k;
    vector_t(int i, int j, int k) {
        _i = i;
        _j = j;
        _k = k;
    }
    vector_t() {}
    inline int getI() { 
        return _i; 
    }
    inline int getJ() { 
        return _j; 
    }
    inline int getK() { 
        return _k; 
    }
    inline void setI(int val) { 
        _i = val; 
    }
    inline void setJ(int val) { 
        _j = val; 
    }
    inline void setK(int val) { 
        _k = val; 
    }
    void normalize() {
        float length = sqrt(_i*_i + _k*_k + _j*_j);
        _i /= length;
        _j /= length;
        _k /= length;
    }
};

And my questions:

  • How can I speed up the normalize() function or is this already the most efficient way?
  • What would be a more C++-onic way to implement such a struct/class while keeping memory and computer time usages low?
  • Should I prefer a valarray over my own type?
like image 712
janoliver Avatar asked Mar 23 '23 02:03

janoliver


1 Answers

Use a fast reciprocal square root function to calculate 1 / length and then multiply each element by this factor. As well as being a faster function than sqrt this also trades 3 expensive division operations for 3 relatively cheap multiplies:

struct vector_t {
    float _i, _j, _k;

    // ...

    void normalize() {
        float r_length = Q_rsqrt(_i*_i + _k*_k + _j*_j);
        _i *= r_length;
        _j *= r_length;
        _k *= r_length;
    }
};

Note: you might want to think about how you're going to handle the pathological case where i == j == k == 0.

like image 58
Paul R Avatar answered Apr 02 '23 06:04

Paul R