#include <ctime>
#include <iostream>
#include <vector> // テーブルのために追加
// --- ルックアップテーブルの定義 ---
uint16_t table_a[256]; // 8bit -> 16bit (a -> 0a0a...)
uint16_t table_b[256]; // 8bit -> 16bit (b -> b0b0...)
bool tables_initialized = false;
// テーブルを初期化する関数
void init_tables() {
if (tables_initialized) return;
for (int i = 0; i < 256; i++) {
uint16_t a_val = 0;
uint16_t b_val = 0;
for (int j = 0; j < 8; j++) {
if (i & (1 << j)) {
a_val |= (1 << (j * 2 + 0));
b_val |= (1 << (j * 2 + 1));
}
}
table_a[i] = a_val;
table_b[i] = b_val;
}
tables_initialized = true;
}
// テスト用の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) {
// 16bitの入力を8bitずつに分解し、テーブルを4回引く
// 下位8ビット (a: 0-7, b: 0-7)
uint32_t low_part = table_a[a & 0xFF] | table_b[b & 0xFF];
// 上位8ビット (a: 8-15, b: 8-15)
uint32_t high_part = table_a[a >> 8] | table_b[b >> 8];
return (high_part << 16) | low_part;
}
// テスト
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() {
init_tables();
test(mix);
benchmark(mix);
return 0;
}