プリプロセス時足し算・引き算・かけ算・剰余演算を定数時間で
#include <boost/preprocessor/cat.hpp> #define PP_ADD_C(x, y) PP_NAT_TO_LIT(PP_NAT(x) PP_NAT(y)) #define PP_SUB_C(x, y) PP_COMPL(PP_ADD_C(PP_COMPL(x), y)) #define PP_MUL_C(x, y) PP_NAT_TO_LIT(PP_CST_REPEAT(x, PP_NAT(y))) #define PP_MOD_C(x, y) \ PP_CST_ELEM_16(PP_NAT(x) PP_MOD_MAKE_MOD_TABLE(y)) /** * m-1,m-2...,0の繰り返しを作って、CST_ELEM_16で0が来るように先頭に16%m+1個要素を追加 * * PP_CST_DROP_16(PP_NAT(PP_SUB_C(m,1)) NAT_TABLE) 必要なオフセット * の繰り返しのF番目まで * 2,1,0,2,1,0,2,1,0,2,1,0,2,1,0,2,1, 16%3 + 1 * 3,2,1,0,3,2,1,0,3,2,1,0,3,2,1,0,3, 16%4 + 1 * 4,3,2,1,0,4,3,2,1,0,4,3,2,1,0,4,3, 16%5 + 1 * 5,4,3,2,1,0,5,4,3,2,1,0,5,4,3,2,1, 16%6 + 1 * 6,5,4,3,2,1,0,6,5,4,3,2,1,0,6,5,4, 16%7 + 1 * 7,6,5,4,3,2,1,0,7,6,5,4,3,2,1,0,7, 16%8 + 1 */ #define PP_MOD_MAKE_MOD_TABLE(m) \ PP_CST_DROP_16(PP_NAT(PP_REM_OF_DIV_16(m)) NAT_TABLE) \ PP_CST_REPEAT(16, PP_CST_DROP_16(PP_NAT(PP_SUB_C(m,1)) NAT_TABLE)) #define PP_COMPL(n) PP_NAT_TO_COMPL(PP_NAT(n)) #define PP_NAT_TO_LIT(...) PP_CST_ELEM_16(__VA_ARGS__ NAT_TABLE) #define PP_NAT_TO_COMPL(...) PP_CST_ELEM_16(__VA_ARGS__ COMPL_TABLE) #define PP_REM_OF_DIV_16(x) PP_CST_ELEM_16(PP_NAT(x) REM_TABLE) #define NAT_TABLE 16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0, #define COMPL_TABLE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, #define REM_TABLE 0,1,2,3,4,5,6,7,0,2,4,1,0,1,0,0,ERROR, #define PP_NAT(n) PP_NAT_I(n) #define PP_NAT_I(n) PP_NAT_ ## n #define PP_NAT_0 #define PP_NAT_1 , #define PP_NAT_2 ,, #define PP_NAT_3 ,,, #define PP_NAT_4 ,,,, #define PP_NAT_5 ,,,,, #define PP_NAT_6 ,,,,,, #define PP_NAT_7 ,,,,,,, #define PP_NAT_8 ,,,,,,,, #define PP_NAT_9 ,,,,,,,,, #define PP_NAT_10 ,,,,,,,,,, #define PP_NAT_11 ,,,,,,,,,,, #define PP_NAT_12 ,,,,,,,,,,,, #define PP_NAT_13 ,,,,,,,,,,,,, #define PP_NAT_14 ,,,,,,,,,,,,,, #define PP_NAT_15 ,,,,,,,,,,,,,,, #define PP_NAT_16 ,,,,,,,,,,,,,,,, // tuple operations #define PP_TUPLE_REM(...) __VA_ARGS__ // comma-separated-tokens operations #define PP_CST_ELEM_16(...) PP_CST_HEAD(PP_CST_DROP_16(__VA_ARGS__)) #define PP_CST_HEAD(...) PP_CST_HEAD_I(__VA_ARGS__) #define PP_CST_HEAD_I(_0,...) _0 #define PP_CST_DROP_16(...) PP_CST_DROP_16_I(__VA_ARGS__) #define PP_CST_DROP_16_I(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_c,_d,_e,_f,...) __VA_ARGS__ #define PP_CST_REPEAT(m, ...) PP_CST_REPEAT_I(m, (__VA_ARGS__)) #define PP_CST_REPEAT_I(m, x) PP_CST_REPEAT_ ## m(PP_TUPLE_REM x) // PP_CST_REPEAT_n で __VA_ARGS__ を繰り返すのがめんどくさいので // 1トークン列として認識させる #define PP_CST_REPEAT_0(x) #define PP_CST_REPEAT_1(x) x #define PP_CST_REPEAT_2(x) x x #define PP_CST_REPEAT_3(x) x x x #define PP_CST_REPEAT_4(x) x x x x #define PP_CST_REPEAT_5(x) x x x x x #define PP_CST_REPEAT_6(x) x x x x x x #define PP_CST_REPEAT_7(x) x x x x x x x #define PP_CST_REPEAT_8(x) x x x x x x x x #define PP_CST_REPEAT_9(x) x x x x x x x x x #define PP_CST_REPEAT_10(x) x x x x x x x x x x #define PP_CST_REPEAT_11(x) x x x x x x x x x x x #define PP_CST_REPEAT_12(x) x x x x x x x x x x x x #define PP_CST_REPEAT_13(x) x x x x x x x x x x x x x #define PP_CST_REPEAT_14(x) x x x x x x x x x x x x x x #define PP_CST_REPEAT_15(x) x x x x x x x x x x x x x x x #define PP_CST_REPEAT_16(x) x x x x x x x x x x x x x x x x #include <iostream> int main() { std::cout << PP_ADD_C(PP_MUL_C(1,3),5) << '\n'; std::cout << PP_SUB_C(PP_ADD_C(7,4),6) << '\n'; std::cout << PP_MUL_C(3,PP_MOD_C(14,6)) << '\n'; }
ループを回さない、テーブルを大きくしすぎない、あたりを目標に作ってみました。割り算は無理でした。割り算難しい。
まぁここまでやるならテーブルを二段構えに、つまり16のカンマ区切りテーブルを16個カンマで区切って九九表ならぬ十六十六表作ってもいいのかも知れませんが。