Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
二分探索法
2014/05/24
Boost.勉強会#15 札幌
でちまる
二分探索法
で
2014/05/24
Boost.勉強会#15 札幌
でちまる
二分探索法
で作る
2014/05/24
Boost.勉強会#15 札幌
でちまる
二分探索法
で作る
再帰呼び出しできる
2014/05/24
Boost.勉強会#15 札幌
でちまる
二分探索法
で作る
再帰呼び出しできる
Cプリプロセッサマクロ
よく知られた事実
マクロは再帰できない
でも
#include <iostream>
#include <boost/preprocessor/repetition/for.hpp>
#include <boost/preprocessor/arithmetic/dec.hpp>
#define M1(r, x) BOOST_PP_FOR(x, P, OP, M2)
#define M2(r, x) x,
#define P(r, x) x
#define OP(r, x) BOOST_PP_DEC(x)
int main() {
int xs[] = { BOOST_PP_FOR(5, P, OP, M1) }; // A.
for (auto x : xs) std::cout << x << ' ';
}
> 5 4 3 2 1 4 3 2 1 3 2 1 2 1 1
BOOST_PP_FORの中でBOOST_PP_FORの呼び出しがあるけどうまくいく
BOOST_PP_FORを読んでみよう
これがBOOST_PP_FORだ
# if 0
# define BOOST_PP_FOR(state, pred, op, macro)
# endif
#
# define BOOST_PP_FOR BOOST_PP_CAT(BOOST_PP_FOR_, BOOST_PP_AUTO_REC(BOOST_PP_FOR_P, 256))
#
# define BOOST_PP_FOR_P(n) BOOST_PP_CAT(BOOST_PP_FOR_CHECK_, BOOST_PP_FOR_ ## n(1, BOOST_PP_FOR_SR_P, BOOST_PP_FOR_SR_O,
BOOST_PP_FOR_SR_M))
#
# define BOOST_PP_FOR_SR_P(r, s) s
# define BOOST_PP_FOR_SR_O(r, s) 0
# define BOOST_PP_FOR_SR_M(r, s) BOOST_PP_NIL
#
# define BOOST_PP_FOR_257(s, p, o, m) BOOST_PP_ERROR(0x0002)
#
# define BOOST_PP_FOR_CHECK_BOOST_PP_NIL 1
#
# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_1(s, p, o, m) 0
# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_2(s, p, o, m) 0
# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_3(s, p, o, m) 0
……
# define BOOST_PP_FOR_1(s, p, o, m) BOOST_PP_FOR_1_C(BOOST_PP_BOOL(p(2, s)), s, p, o, m)
# define BOOST_PP_FOR_2(s, p, o, m) BOOST_PP_FOR_2_C(BOOST_PP_BOOL(p(3, s)), s, p, o, m)
# define BOOST_PP_FOR_3(s, p, o, m) BOOST_PP_FOR_3_C(BOOST_PP_BOOL(p(4, s)), s, p, o, m)
……
# define BOOST_PP_FOR_1_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(2, s) BOOST_PP_IIF(c, BOOST_PP_FOR_2, BOOST_PP_TUPLE_EAT_4)
(BOOST_PP_EXPR_IIF(c, o)(2, s), p, o, m)
# define BOOST_PP_FOR_2_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(3, s) BOOST_PP_IIF(c, BOOST_PP_FOR_3, BOOST_PP_TUPLE_EAT_4)
(BOOST_PP_EXPR_IIF(c, o)(3, s), p, o, m)
# define BOOST_PP_FOR_3_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(4, s) BOOST_PP_IIF(c, BOOST_PP_FOR_4, BOOST_PP_TUPLE_EAT_4)
(BOOST_PP_EXPR_IIF(c, o)(4, s), p, o, m)
……
まだ諦めない
# if 0
# define BOOST_PP_FOR(state, pred, op, macro)
# endif
#
# define BOOST_PP_FOR 
BOOST_PP_CAT( 
BOOST_PP_FOR_, 
BOOST_PP_AUTO_REC( 
BOOST_PP_FOR_P, 256))
# if 0
# define BOOST_PP_FOR(state, pred, op, macro)
# endif
#
# define BOOST_PP_FOR 
BOOST_PP_CAT( 
BOOST_PP_FOR_, 
BOOST_PP_AUTO_REC( 
BOOST_PP_FOR_P, 256))
関数マクロじゃなかった
● BOOST_PP_FOR_n が本体っぽい
● BOOST_PP_FOR はオブジェクトマクロで
最終的に BOOST_PP_FOR_n に
展開されるっぽい
– nは負でない整数
● BOOST_PP_FOR_n はなんかループの1ステップ
の処理っぽい
# if 0
# define BOOST_PP_FOR(state, pred, op, macro)
# endif
#
# define BOOST_PP_FOR 
BOOST_PP_CAT( 
BOOST_PP_FOR_, 
BOOST_PP_AUTO_REC( 
BOOST_PP_FOR_P, 256))
なんかいかにも再帰してる感じの名前
こ れ が BOOST_PP_AUTO_REC だ
(要約)
# define AUTO_REC(pred, n) NODE_ENTRY_ ## n(pred)
#
# define NODE_ENTRY_8(p) NODE_4(p)(p)(p)
# define NODE_ENTRY_4(p) NODE_2(p)(p)
# define NODE_ENTRY_2(p) NODE_1(p)
#
# define NODE_4(p) IF(p(4), NODE_2, NODE_6)
# define NODE_2(p) IF(p(2), NODE_1, NODE_3)
# define NODE_1(p) IF(p(1), 1, 2)
# define NODE_3(p) IF(p(3), 3, 4)
# define NODE_6(p) IIF(p(6), NODE_5, NODE_7)
# define NODE_5(p) IF(p(5), 5, 6)
# define NODE_7(p) IF(p(7), 7, 8)
諦めるな
まだいける
p(1)
2 1
p(3)
4 3
p(5)
6 5
p(7)
8 7
p(6) p(2)
p(4)
true
true
true
false
分かりやすい図
どうみても二分探索です
本当にありがとうございました
● マクロは再帰展開できない
– 大元の呼び出し→展開できる
– その呼び出し中に現われた呼び出し→展開できない
● #define F(x) x という Fについて
BOOST_PP_CAT(CHECK_, F(OK)) が
– 展開できる → CHECK_OK
– 展開できない → CHECK_F(OK)
● CHECK_OK と CHECK_F(x) を0と1に置き換え
れば展開したかどうか検出できる
# define BOOST_PP_FOR_P(n) 
BOOST_PP_CAT( 
BOOST_PP_FOR_CHECK_, 
BOOST_PP_FOR_ ## n( 
1, 
BOOST_PP_FOR_SR_P, 
BOOST_PP_FOR_SR_O, 
BOOST_PP_FOR_SR_M))
#
# define BOOST_PP_FOR_SR_P(r, s) s
# define BOOST_PP_FOR_SR_O(r, s) 0
# define BOOST_PP_FOR_SR_M(r, s) BOOST_PP_NIL
#
# define BOOST_PP_FOR_CHECK_BOOST_PP_NIL 1
#
# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_1(s, p, o, m) 0
● これを BOOST_PP_AUTO_REC に使え
ば,BOOST_PP_FOR_n が展開済みかどうか検
出できる
● 展開済みなら BOOST_PP_FOR_n+1 を使う
● めでたしめでたし

More Related Content

二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ

  • 7. でも #include <iostream> #include <boost/preprocessor/repetition/for.hpp> #include <boost/preprocessor/arithmetic/dec.hpp> #define M1(r, x) BOOST_PP_FOR(x, P, OP, M2) #define M2(r, x) x, #define P(r, x) x #define OP(r, x) BOOST_PP_DEC(x) int main() { int xs[] = { BOOST_PP_FOR(5, P, OP, M1) }; // A. for (auto x : xs) std::cout << x << ' '; } > 5 4 3 2 1 4 3 2 1 3 2 1 2 1 1 BOOST_PP_FORの中でBOOST_PP_FORの呼び出しがあるけどうまくいく
  • 9. これがBOOST_PP_FORだ # if 0 # define BOOST_PP_FOR(state, pred, op, macro) # endif # # define BOOST_PP_FOR BOOST_PP_CAT(BOOST_PP_FOR_, BOOST_PP_AUTO_REC(BOOST_PP_FOR_P, 256)) # # define BOOST_PP_FOR_P(n) BOOST_PP_CAT(BOOST_PP_FOR_CHECK_, BOOST_PP_FOR_ ## n(1, BOOST_PP_FOR_SR_P, BOOST_PP_FOR_SR_O, BOOST_PP_FOR_SR_M)) # # define BOOST_PP_FOR_SR_P(r, s) s # define BOOST_PP_FOR_SR_O(r, s) 0 # define BOOST_PP_FOR_SR_M(r, s) BOOST_PP_NIL # # define BOOST_PP_FOR_257(s, p, o, m) BOOST_PP_ERROR(0x0002) # # define BOOST_PP_FOR_CHECK_BOOST_PP_NIL 1 # # define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_1(s, p, o, m) 0 # define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_2(s, p, o, m) 0 # define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_3(s, p, o, m) 0 …… # define BOOST_PP_FOR_1(s, p, o, m) BOOST_PP_FOR_1_C(BOOST_PP_BOOL(p(2, s)), s, p, o, m) # define BOOST_PP_FOR_2(s, p, o, m) BOOST_PP_FOR_2_C(BOOST_PP_BOOL(p(3, s)), s, p, o, m) # define BOOST_PP_FOR_3(s, p, o, m) BOOST_PP_FOR_3_C(BOOST_PP_BOOL(p(4, s)), s, p, o, m) …… # define BOOST_PP_FOR_1_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(2, s) BOOST_PP_IIF(c, BOOST_PP_FOR_2, BOOST_PP_TUPLE_EAT_4) (BOOST_PP_EXPR_IIF(c, o)(2, s), p, o, m) # define BOOST_PP_FOR_2_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(3, s) BOOST_PP_IIF(c, BOOST_PP_FOR_3, BOOST_PP_TUPLE_EAT_4) (BOOST_PP_EXPR_IIF(c, o)(3, s), p, o, m) # define BOOST_PP_FOR_3_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(4, s) BOOST_PP_IIF(c, BOOST_PP_FOR_4, BOOST_PP_TUPLE_EAT_4) (BOOST_PP_EXPR_IIF(c, o)(4, s), p, o, m) ……
  • 11. # if 0 # define BOOST_PP_FOR(state, pred, op, macro) # endif # # define BOOST_PP_FOR BOOST_PP_CAT( BOOST_PP_FOR_, BOOST_PP_AUTO_REC( BOOST_PP_FOR_P, 256))
  • 12. # if 0 # define BOOST_PP_FOR(state, pred, op, macro) # endif # # define BOOST_PP_FOR BOOST_PP_CAT( BOOST_PP_FOR_, BOOST_PP_AUTO_REC( BOOST_PP_FOR_P, 256)) 関数マクロじゃなかった
  • 13. ● BOOST_PP_FOR_n が本体っぽい ● BOOST_PP_FOR はオブジェクトマクロで 最終的に BOOST_PP_FOR_n に 展開されるっぽい – nは負でない整数 ● BOOST_PP_FOR_n はなんかループの1ステップ の処理っぽい
  • 14. # if 0 # define BOOST_PP_FOR(state, pred, op, macro) # endif # # define BOOST_PP_FOR BOOST_PP_CAT( BOOST_PP_FOR_, BOOST_PP_AUTO_REC( BOOST_PP_FOR_P, 256)) なんかいかにも再帰してる感じの名前
  • 15. こ れ が BOOST_PP_AUTO_REC だ (要約) # define AUTO_REC(pred, n) NODE_ENTRY_ ## n(pred) # # define NODE_ENTRY_8(p) NODE_4(p)(p)(p) # define NODE_ENTRY_4(p) NODE_2(p)(p) # define NODE_ENTRY_2(p) NODE_1(p) # # define NODE_4(p) IF(p(4), NODE_2, NODE_6) # define NODE_2(p) IF(p(2), NODE_1, NODE_3) # define NODE_1(p) IF(p(1), 1, 2) # define NODE_3(p) IF(p(3), 3, 4) # define NODE_6(p) IIF(p(6), NODE_5, NODE_7) # define NODE_5(p) IF(p(5), 5, 6) # define NODE_7(p) IF(p(7), 7, 8)
  • 17. p(1) 2 1 p(3) 4 3 p(5) 6 5 p(7) 8 7 p(6) p(2) p(4) true true true false 分かりやすい図
  • 19. ● マクロは再帰展開できない – 大元の呼び出し→展開できる – その呼び出し中に現われた呼び出し→展開できない ● #define F(x) x という Fについて BOOST_PP_CAT(CHECK_, F(OK)) が – 展開できる → CHECK_OK – 展開できない → CHECK_F(OK) ● CHECK_OK と CHECK_F(x) を0と1に置き換え れば展開したかどうか検出できる
  • 20. # define BOOST_PP_FOR_P(n) BOOST_PP_CAT( BOOST_PP_FOR_CHECK_, BOOST_PP_FOR_ ## n( 1, BOOST_PP_FOR_SR_P, BOOST_PP_FOR_SR_O, BOOST_PP_FOR_SR_M)) # # define BOOST_PP_FOR_SR_P(r, s) s # define BOOST_PP_FOR_SR_O(r, s) 0 # define BOOST_PP_FOR_SR_M(r, s) BOOST_PP_NIL # # define BOOST_PP_FOR_CHECK_BOOST_PP_NIL 1 # # define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_1(s, p, o, m) 0
  • 21. ● これを BOOST_PP_AUTO_REC に使え ば,BOOST_PP_FOR_n が展開済みかどうか検 出できる ● 展開済みなら BOOST_PP_FOR_n+1 を使う ● めでたしめでたし