lundi 25 avril 2016

Efficient use of unions as keys for unordered_map for 3D hasing

I would like to use C++11 std::unordered_map for hashing points on regular rectangular grid in 3D (2D,4D).

Originally I was doing manual packing and unpacking of index like this:

inline int_fast64_t xyz2i( int_fast16_t ix, int_fast16_t iy, int_fast16_t iz ){
     return ix | ( iy << 16 ) | ( iz << 32 );
}

inline void i2xyz( int_fast64_t i, int_fast16_t& ix, int_fast16_t& iy, int_fast16_t& iz ){
    iz=( i & 0xFF0000 ) >> 32;
    iy=( i & 0x00FF00 ) >> 16;
    ix=( i & 0x0000FF );
}

then I realized that using unions would be probably better:

class NodeIndex4D{
    public:
    union{
        struct{ int_fast16_t x,y,z,w; };
        int_fast16_t array[4];
        int_fast64_t i;
    };
};

but still, I have feeling that I don't do it the best way. That C++ language features can be used perhaps better for this purpose.

E.g. what is not so nice is my insertNode function:

std::unordered_map<int_fast64_t,Node> nodes;

Node& insertNode( int_fast16_t ix, int_fast16_t iy, int_fast16_t iz ){
    NodeIndex4D inod; 
    inod.x=ix; inod.y=iy; inod.z=iz; inod.w=0;  // NOT SO NICE
    int sz0 = nodes.size();
    Node& node = nodes[inod.i]; // get valid reference ( if new allocate, if old take it )
    if( nodes.size() > sz0 ){ // new element
        node.id = sz0;
        index2pos( {ix,iy,iz}, node.pos ); // not relevant here 
        node.pos.add_mul( scaling, -0.5 ); // not relevant here
    }
    return node;
}

Aucun commentaire:

Enregistrer un commentaire