æè¿ããã¥ã¡ã³ãã®æžãæ¹ãèŠããŠããããšæãç«ã¡ãMarkdownãšããã®ã詊ãå§ããŠã¿ãŸããã èªåãæ®æ®µèå³ããåéçã«ãããã°ã©ã ã³ãŒããšæ°åŒããããã«æžãããã®ã§ãããã倧éã«äœ¿ã£ãæç« ãæžããŠã¿ãŸããã
æ°åŠçã«å
šç¶ããªããŠããªã衚çŸã§ãééããå€åã«ãããšæããŸããã容赊ãã
Continue Reading
æŽæ° \(i\) ã2鲿°è¡šèšãããšããäœåã®ããããïŒã§ããããæ°ããã æŽæ° \(i\) ãæ¬¡ã®ããã«æžãããšããã倿°ã \(n\) ãããã§ãããšãããããã¯å
šéšã§ \(n\) åããã 以äžã§ã¯ãæŽæ° \(i\) ã2鲿°è¡šèšãããšããå·Šãã \(m\) çªç® \((1 \leq m \leq n)\) ã®ãããã \(b_m\) ã§ãããšã \[ i = b_1b_2 \cdots b_m \cdots b_n \] ãšè¡šèšããã æŽæ°ã®2鲿°è¡šèšãšå¯Ÿå¿ããããšã1ã®äœã \(b_n\) ã \(2^p\) ã®äœã \(b_{n - p}\) ã§ããã ãŸããæ®éã®IEEEã§ã¯æŽæ°ãããã®åæ°ã¯2ã®çޝä¹ã«ããããšãã»ãšãã©ãªã®ã§ã \(n = 2^c\) ãšããã
ãã®æ°å \({b_i}\) ã®ãã¡ã1ã§ããåæ°ãæ°ããããšãç®çãšããã åæ¡ããšã«ãããã調ã¹ãŠãããšã \(n\) åã®ã«ãŒããš \(n\) åã®ãããæŒç®ãå¿
èŠã«ãªãã
ããã§å·¥å€«ãæœããšãé£ãåã£ããããã®ã㢠\(n/2\) åã«ã€ããŠã ããããã®ãã¢äžã«1ãäœåãããã¯3åã®ãããæŒç®ãš1åã®è¶³ãç®ã§ãŸãšããŠèšç®ã§ããã ãŸãåæ§ã®å·¥å€«ã \(r\) åæœããšãé£ãåã£ããã¢ã®ã㢠\(n/2^r\) åããããã®ãã¢ã«ã€ããŠ3åã®ãããæŒç®ãš1åã®è¶³ãç®ã§ãŸãšããŠèšç®ã§ããã ããã§å¿
èŠãªãããæŒç®ã®åæ°ã倧ããæžããããšãèããã ãããæŒç®ã®åæ°ããããã \(3\log (n)\) åã«ãªãããšãæåŸ
ãããã
ãããåã«å¯Ÿããæäœ
次ã®ãããªæŽæ°ã§æžãããã£ã«ã¿ãèããã
\(f(p)\) :0ãš1ã \(p\) åãã€äº€äºã«äžŠãã 2鲿°ãããšãã° \(f(1) = 010101\cdots\) ã \(f(3) = 000111000111 \cdots\) ã
ç¶ããŠãæŽæ° \(i = {b_m}\) ãš \(f(p) = {f_m}\) ã«æ¬¡ã®æŒç®ãããã
\(f(p)\) ãš \(i\) ã«ã€ããŠãåæ¡ããšã«è«çç©ãåãã ããªãã¡ \[ k_0 = f(p) \wedge i = (f_1 \wedge b_1)(f_2 \wedge b_2) \cdots (f_n \wedge b_n) \]
\(i\) ãå³ã« \(p\) æ¡ãããããŸãåæ¡ããšã«è«çåãåãã ããªãã¡ \[ k_1 = f(p) \wedge (i/2^p) = (f_1 \wedge b_{1 + p})(f_2 \wedge b_{2 + p}) \cdots (f_n \wedge b_{n - p}) \]
Cã§ã¯æ¬¡ã®ããã«ã³ãŒãã£ã³ã°ãããã
int k0 = f(p) & i; int k1 = f(p) & (i >> p); int k = k0 + k1;
ãã®3ã€ã®æŒç®ããŸãšã㊠\(a(p)\) ãšãããããªãã¡ã \(a(p): i \mapsto k\) ã
ãŸãæåã® \(i\) ã« \(a(1)\) ãäœçšãããŠã¿ãã \[ i = b_1b_2b_3b_4 \cdots b_{n-1}b_n \] \[ k_0 = 0b_20b_4 \cdots 0b_n \] \[ k_1 = 0b_10b_3 \cdots 0b_{n-1} \] \[ k = (0b_1 + 0b_2)(0b_3 + 0b_4) \cdots (0b_{n - 1} + 0b_n) \] ã€ãŸããé£ãåã£ã \(b_{2m}\) ãš \(b_{2m + 1}\) ã®ããããè¶³ããŠããã®å€ãå
ãã£ãïŒã€ã®ãããã«ãããŠãããèŠæ¹ãå€ãããšã \(2m\) ãš \(2m + 1\) ã®ãã¡ã®ïŒã®æ°ãããã«ïŒé²æ°ã§ãããŠããã \[ c_j = b_{2m} + b_{2m + 1} \] ãšããïŒæ¡ã«ãªãããã«ããããïŒã§åããããšãããšã \(c_m\) ã¯00ã01ã10ã®ã©ããã§ãããããã䜿ããšã \[ k = c_1c_2 \cdots c_{n/2} \] ãšããããããã \(i_1 = k\) ãšããŠããã
ç¶ããŠã \(i_1\) ã« \(a(2)\) ãäœçšãããã \[ f(2) = 001100110011 \cdots \] ãšã®è«çç©ãåæ¡ã§ãšãããšã \(c_m\) ãããããïŒæ¡ã§ããããšãèãããšã \[ k_0 = 00c_200c_4 \cdots 00c_{n/2}
\] \[ k_1 = 00c_100c_3 \cdots 00c_{n/2 - 1}
\] \[ k = (00c_1 + 00c_2)(00c_3 + 00c_4) \cdots (00c_{m/2 - 1} + 00c_{m/2}) \] ãšãªããã \(a(1)\) ã®ãšããšåæ§ã«ïŒæ¡ã®ãããã®å¡ \[ d_m = c_{2m} + c_{2m + 1} \] ãšãªãããã«å®çŸ©ãããšã \(d_m\) ã¯é£ãåã£ã \(4m\) ã \(4m + 1\) ã \(4m + 2\) ã \(4m + 3\) ã®ãã¡ïŒã®åæ°ãšãªãã0000ã0001ã0010ã0011ã0100ã®ã©ããã§ããã \[ i_2 = d_1d_2 \cdots d_{m/4} \] ãšãããã
ãªããšãªãäžè¬åãããšã \[ a(2^k): i_{k - 1} \mapsto i_k \] \[ i_k = x_1x_2 \cdots x_{m/2^k} \] ããã§ \(x_m\) 㯠\(2^k\) æ¡ã®0ãããã¯1ã®åã§ã \(b_{2^km} \cdots b_{2^{k + 1}m - 1}\) ãŸã§ã®1ã®æ°ãïŒé²æ°è¡šèšãããã®ã§è¶³ããªãæ¡ã0ã§åãããã®ã§ããã
ãã®ãŸãŸ \(n/2^k = 1\) ã€ãŸã \(k = \log_2(n)\) ã«ãªããŸã§ç¹°ãè¿ããšã \(i_c (c = \log_2(n))\) 㯠\(i = {b_m}\) äžã®1ã®æ°ãšãªãããããæŒç®ã¯ \(3c\) åã§ããã
ããšãã°8byteïŒ64bitïŒæŽæ°ã®å Žåãåæ¡ããã§ãã¯ããŠãããš64åã®ãããæŒç®ãš64åã®ã«ãŒãè¶³ãç®ãšãªãã
\(i\) ã¯64åã®0ãããã¯1ã®å \({b_m}\) ãšãããããã« \(a(1)\) ãäœçšããããšã00ã01ã10ã®ã©ããã32å䞊ãã å \(i_1 = {c_m}\) ãã§ãããããã« \(a(2)\) ãäœçšããããšã
ã®ã©ããã16å䞊ãã å \(i_2 = {d_m}\) ãšãªãã ãããã£ã¡ã \(a(4)\) ãäœçšããããšã
ã®ã©ããã8å䞊ãã \[ i_3 = e_1e_2e_3e_4e_5e_6e_7e_8 \] ãšãªãããã®ãšã \(e_m\) 㯠\(i\) ã®äžã® \(8(m - 1)\) ïœ \(8m - 1\) æ¡ã®8åã®ãããã®ãã¡ã®1ã®åæ°ã2鲿°ã§è¡šèšãããã®ãšãªã£ãŠããã çããšãªã \(i_c\) ã¯ããã \(e_1\) ãã \(e_8\) ãè¶³ããã ããã« \(a(8)\) ãäœçšããã \(i_4 = g_1g_2g_3g_4\) ã«ããŠç·å \(i_c = g_1 + g_2 + g_3 + g_4\) ãåãã åè
ã ãšãããæŒç®ã¯17åã§è¶³ãç®ã10åãåŸè
ã ãšãããæŒç®16åè¶³ãç®7åã§ããã
\(a(32)\) ãŸã§äœçšãã \(i_6\) ãŸã§ãŸãšãããšãã \(n = 2^6\) ãªã®ã§ \(i_6 = i_c\) 㯠\(i\) ã®äžã®1ã®åæ°ãšãªããããããæŒç®ã¯18åãè¶³ãç®ã¯6åã§ããã
ããããããªãã«ãŒããæžãããšããããå®éjavaã®bitcount颿°ã¯32ãããæŽæ°çšã§ãããã \(a(2^2)\) ãŸã§ã®äœçšã§å®è£
ãããã«ãŒãã䜿ãããŠããªãã
Fortranã§å®è£
ãããšä»¥äžã®ããã«ãªãã
function bitcount(i) result(r) implicit none integer(8),intent(in) :: i integer :: r integer(8) :: i1,i2,i3,i4 ! ruler 1234567890123456 integer(8),parameter :: f1 = z'5555555555555555' integer(8),parameter :: f2 = z'3333333333333333' integer(8),parameter :: f4 = z'0F0F0F0F0F0F0F0F' integer(8),parameter :: f8 = z'00FF00FF00FF00FF' integer(8),parameter :: mr = z'00000000000000FF' ! a1: 01010101010101010101010101010101 ... = z'5555 ... ! a2: 00110011001100110011001100110011 ... = z'3333 ... ! a4: 00001111000011110000111100001111 ... = z'0f0f ... ! result < 64, mr = 256 is large enough i1 = iand(i,f1) + iand(ishft(i,-1),f1) i2 = iand(i1,f2) + iand(ishft(i1,-2),f2) i3 = iand(i2,f4) + iand(ishft(i2,-4),f4) i4 = iand(i3,f8) + iand(ishft(i3,-8),f8) r = i4 + ishft(i4,-16) + ishft(i4,-32) + ishft(i4,-48) r = iand(r,mr) end function bitcount
Cèšèªã§ããã°/usr/lib/gcc/x86_64-linux-gnu/4.x/include/ã«åçš®intrin.hãããã®ã§ãpopulation count颿°ãã€ã³ã¯ã«ãŒãããã
#define __POPCNT__ #include long long unsigned int c,i; c = _mm_popcnt_u64(i)
ã§CPUæ¡åŒµåœä»€ãå©çšãããã®ã䜿ããã ããã¯CPUãæäŸããæ¡åŒµåœä»€ãå©çšããŠããã®ã§ãç°å¢ã«ãã£ãŠã¯èªåã§é¢æ°ãå®çŸ©ããããã¯ããã«éããªãã
integer :: n,p,i n = popcnt(i) !æŽæ°iäžã®1ã®æ° p = poppar(i) !æŽæ°iäžã®1ã®æ°ãå¶æ°ãªã0ã奿°ãªã1ãè¿ã
ãªã©åçš®ãããæŒç®ã«é¢ãã颿°ãçµã¿èŸŒãŸããŠããã
Fortranã«ã€ããŠãæ§èœèª¿æ»ãè¡ã£ãã1ãã1000000000ãŸã§ç¹°ãè¿ããããã£ãæéãæ¯èŒããã
program test implicit none integer(8) :: n,i,c n = 10_8**9 c = 0 do i = 1,n c = c + function_of_bitcount(i) enddo write(*,*)c !æé©åã§ã«ãŒããæ¶ããŠããŸããªãããã« stop end program test
ãã®ã³ãŒãäžã®function_of_bitcountããåçš®é¢æ°ã«çœ®ãæããŠæ¯èŒããã ã³ã³ãã€ã«ã¯ã
gfortran -o hoge -O2 -msse4.2 hoge.f03 time ./hoge
ãšãããå®è¡ç°å¢ã¯AMD A10-6800KãCygwinã åŸãã§ãã³åæµãããBOINCãåããŠããåçš®ã¯ã©ãŠããµãŒãã¹ãåããŠããããã®ã¯ãæå¬ã
颿° ããreal(ç§)ãã ã user(ç§)ã ããsys(ç§)ã å®çŽã«ãŒã 142.098 122.538 0.389 a(8)ãŸã§ 15.768 12.308 0.139 çµã¿èŸŒã¿ 3.832 2.495 0.109
å®çŽã«ãŒã: 64åãã¹ãŠã®ãããã«ã€ããŠbtestã§ãã§ãã¯ããtrueãªã1è¶³ããšããçŽ çŽãªçºæ³ã®é¢æ°ã
çµèŸŒã倧æ£çŸ©ãšããããšã§ã