++, 1,6 . , . true/false / ( ).
4 , , 16 , ( 16 ) , , nibble . AND , . AND nibble 0.
inline unsigned set( unsigned char X ) {
return (1 << (X & 15)) | (1 << (X >> 4));
}
inline bool match( unsigned char A, unsigned char B ) {
return set( A ) & set( B ) & ~set( 0 );
}
I dated it to Intel Xeon X5570 @ 2.93 GHz, and it is 1.6 times faster than the original in question. Here is the code I used for its time:
#include <time.h>
#include <iostream>
bool original( unsigned char A, unsigned char B ) {
unsigned char a1 = A >> 4;
unsigned char a2 = A & 15;
unsigned char b1 = B >> 4;
unsigned char b2 = B & 15;
return (a1 != 0 && (a1 == b1 || a1 == b2)) || (a2 != 0 && (a2 == b1 || a2 == b2));
}
static inline unsigned set( unsigned char X ) {
return (1 << (X & 15)) | (1 << ((X >> 4)&15));
}
bool faster( unsigned char A, unsigned char B ) {
return set( A ) & set( B ) & ~set( 0 );
}
class Timer {
size_t _time;
size_t & _elapsed;
size_t nsec() {
timespec ts;
clock_gettime( CLOCK_REALTIME, &ts );
return ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
}
public:
Timer(size_t & elapsed) : _time(nsec()), _elapsed(elapsed) {}
~Timer() { _elapsed = nsec() - _time; }
};
int main()
{
size_t original_nsec, faster_nsec;
const size_t iterations = 200000000ULL;
size_t count = 0;
{ Timer t(original_nsec);
for(size_t i=0; i < iterations; ++i) {
count += original( 0xA5 , i & 0xFF );
}
}
{ Timer t(faster_nsec);
for(size_t i=0; i < iterations; ++i) {
count += faster( 0xA5 , i & 0xFF );
}
}
std::cout << double(original_nsec) / double(faster_nsec)
<< "x faster" << std::endl;
return count > 0 ? 0 : 1;
}
Here's the conclusion:
$ g++ -o match -O3 match.cpp -lrt && ./match
1.61564x faster
$
source
share