#include <ctime>
#include <iostream>
// テスト用のmix(この関数は遅いよ!これより早いの作ってね!)
uint32_t mix_test(uint16_t a, uint16_t b) {
uint32_t o = 0;
for (int i = 0; i < 16; i++) {
if (a & (1 << i)) o |= 1 << (i * 2 + 0);
if (b & (1 << i)) o |= 1 << (i * 2 + 1);
}
return o;
}
// mixはaとbのbitを交互に詰めて返す。aが下位に来る。
// (例)
// a : 1111111111111111
// b : 0000000000000000
// o : 01010101010101010101010101010101
uint32_t mix(uint16_t a, uint16_t b) {
// ここに実装
// uint32_t c = a;
// uint32_t d = b;
// c = (c | (c << 8)) & 0x00ff00ff;
// c = (c | (c << 4)) & 0x0f0f0f0f;
// c = (c | (c << 2)) & 0x33333333;
// c = (c | (c << 1)) & 0x55555555;
// d = (d | (d << 8)) & 0x00ff00ff;
// d = (d | (d << 4)) & 0x0f0f0f0f;
// d = (d | (d << 2)) & 0x33333333;
// d = (d | (d << 1)) & 0x55555555;
// return c | d << 1;
uint64_t c = ((uint64_t)b << 32) | a;
c = (c | (c << 8)) & 0x00ff00ff00ff00ffULL;
c = (c | (c << 4)) & 0x0f0f0f0f0f0f0f0fULL;
c = (c | (c << 2)) & 0x3333333333333333ULL;
c = (c | (c << 1)) & 0x5555555555555555ULL;
return uint32_t(c >> 31) | uint32_t(c & 0xffffffff);
}
// テスト
void test(uint32_t(*func)(uint16_t, uint16_t)) {
std::cout << "test...";
for (int i = 0; i < 100; i++) {
uint16_t a = rand(), b = rand();
if (func(a, b) != mix_test(a, b)) {
std::cout << "failed" << std::endl;
exit(EXIT_FAILURE);
}
}
std::cout << "passed!" << std::endl;
}
// ベンチマーク
void benchmark(uint32_t (*func)(uint16_t, uint16_t)) {
std::cout << "benchmark...";
uint32_t dammy = 0;
double start = clock();
for (int i = 0; i < 50000000; i++) dammy ^= func(rand(), rand());
double end = clock();
std::cout << "end! elapsed:" << (end - start) / CLOCKS_PER_SEC << "s " << dammy << std::endl;
}
int main() {
test(mix);
benchmark(mix);
return 0;
}