C ++ bitwise operations on structures and classes

I am developing a shared library of genetic algorithms where the chromosome of each organism is its bit representation in memory. So, for example, if I want to mutate an organism, I randomly flip the object's bits.

At first I tried to use a class bitset

from the C ++ standard library, but when accessing the object, T

my only option was using a member function to_ullong

, which was a problem for views with oversized bits unsigned long long

.

Then I decided to create a shared library for bitwise operations on any object T

, so I could apply those operations directly to the objects themselves, instead of converting them to first bitset

.

So you can see what I am trying to achieve, here's a function from the library:

template<typename T>
void flip(T& x, size_t const i)
{
    x ^= 1 << i;
}

      

And it is used in GA library like this:

template<typename T>
void GeneticAlgorithm<T>::mutate(T& organism, double const rate)
{
    std::random_device rd;
    std::mt19937 mt(rd());

    std::uniform_real_distribution<double> dist(0, 1);

    for(size_t i = 0; i < m_nBits; ++i)
        if(dist(mt) <= rate)
            bit::flip(organism, i);
}

      

It would be really nice if it worked, however I am now getting this error message from the VC ++ 2015 RC compiler:

Severity Code Description Project file line error C2677 binary '^': no ​​global operator found that takes type "T" (or no acceptable conversion) Genetic Algorithm Path \ Genetic Algorithm \ Genetic Algorithm \ BitManip.hpp 57

If I fix this error for ^

, I get more for other operators.

I haven't used bitwise operators in my code before, so my guess is that these operators shouldn't be used with any object? If so, how could I solve the problem?

+3


source to share


2 answers


What you want to achieve can be done like this (see Peter Schneider's comment):

template<typename T> void flip(T& x, size_t const i) {
    unsigned char* data = reinterpret_cast<unsigned char*>(&x);
    data[i/8] ^= (1 << (i%8));
}

      

what it does is reinterpret your x data as an array of bytes (unsigned char) and then determine which byte should be flipped (i / 8) and then which bit in the byte (i% 8).



Note: Also, at the beginning of the function it may be safe to add:

assert(i < sizeof(T)*8)

      

+2


source


I am under the impression that you are not yet fully evaluating C ++ object oriented features. (It is not typical when you transition from more data-oriented programming to C. C ++ specifically to make the transition as fast and painless as you want.)

My suggestion is to encapsulate the flip operation in the body and let the body handle it. By way of illustration (untested but compileable):



#include<climits>  // CHAR_BIT
#include<cstdlib>  // exit()

class string;
void log(const char *);

// inaccessible from the outside
constexpr int NUM_TRAITS = 1000;
constexpr size_t TRAIT_ARR_SZ = (NUM_TRAITS+CHAR_BIT-1)/CHAR_BIT;

class Organism
{ 

    char traits[TRAIT_ARR_SZ];
    int flips[NUM_TRAITS];

    /////////////////////////////////////////////////////////////
    public:

    Organism()  {  /* set traits and flips zero */  }

    // Consider a virtual function if you may derive 
    /** Invert the trait at index traitIndex */
    void flipTrait(int traitIndex)
    {
        if( traitIndex >= NUM_TRAITS ) { log("trait overflow"); exit(1); }

        int charInd = traitIndex / CHAR_BIT;
        int bitInd = traitIndex % CHAR_BIT;

        traits[traitIndex] ^= 1 << bitInd;
        flips[traitIndex]++;
    }

    // Organisms can do so much more!
    void display();
    void store(string &path);
    void load(string &path);
    void mutate(float traitRatio);
    Organism clone();
};

      

+1


source







All Articles