22// SPDX-FileCopyrightText: 2025 Ikpil Choi(ikpil@naver.com)
33// SPDX-License-Identifier: MIT
44
5+ using System ;
56using System . Runtime . CompilerServices ;
67
78namespace Box2D . NET
89{
910 public static class B2CTZs
1011 {
12+ // De Bruijn magic constant and lookup table
13+ private static readonly byte [ ] SampleMultiplyDeBruijnBitPosition = new byte [ 32 ]
14+ {
15+ 0 , 1 , 28 , 2 , 29 , 14 , 24 , 3 ,
16+ 30 , 22 , 20 , 15 , 25 , 17 , 4 , 8 ,
17+ 31 , 27 , 13 , 23 , 21 , 19 , 16 , 7 ,
18+ 26 , 12 , 18 , 6 , 11 , 5 , 10 , 9
19+ } ;
20+
21+ private static readonly byte [ ] SampleMultiplyDeBruijnBitPosition64 = new byte [ 64 ]
22+ {
23+ 63 , 0 , 1 , 52 , 2 , 6 , 53 , 26 , 3 , 37 , 40 , 7 , 33 , 54 , 47 , 27 ,
24+ 61 , 4 , 38 , 45 , 43 , 41 , 21 , 8 , 23 , 34 , 58 , 55 , 48 , 17 , 28 , 10 ,
25+ 62 , 51 , 5 , 25 , 36 , 39 , 32 , 46 , 60 , 44 , 42 , 20 , 22 , 57 , 16 , 9 ,
26+ 50 , 24 , 35 , 31 , 59 , 19 , 56 , 15 , 49 , 30 , 18 , 14 , 29 , 13 , 12 , 11
27+ } ;
28+
29+ private static readonly byte [ ] SampleClzTable = new byte [ 32 ]
30+ {
31+ 31 , 22 , 30 , 21 , 18 , 10 , 29 , 2 ,
32+ 20 , 17 , 15 , 13 , 9 , 6 , 28 , 1 ,
33+ 23 , 19 , 11 , 3 , 16 , 14 , 7 , 24 ,
34+ 12 , 4 , 8 , 25 , 5 , 26 , 27 , 0
35+ } ;
36+
37+
38+ // uint에 대해 trailing zero count (CTZ)
39+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
40+ public static uint b2CTZ32_DeRrujin ( uint block )
41+ {
42+ if ( block == 0 ) return 32 ;
43+
44+ // isolate lowest set bit and multiply
45+ uint idx = ( uint ) ( ( block & - block ) * 0x077CB531u ) >> 27 ;
46+ return SampleMultiplyDeBruijnBitPosition [ idx ] ;
47+ }
48+
49+ // uint에 대해 leading zero count (CLZ)
50+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
51+ public static uint b2CLZ32 ( uint block )
52+ {
53+ if ( block == 0 ) return 32 ;
54+
55+ block |= block >> 1 ;
56+ block |= block >> 2 ;
57+ block |= block >> 4 ;
58+ block |= block >> 8 ;
59+ block |= block >> 16 ;
60+
61+ uint idx = ( block * 0x07C4ACDDu ) >> 27 ;
62+ return SampleClzTable [ idx ] ;
63+ }
64+
65+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
66+ public static uint b2CTZ64_DeBrujin ( ulong x )
67+ {
68+ if ( x == 0 )
69+ return 64 ;
70+
71+ // x & -x : ulong 음수 연산 불가 → ~x + 1 사용
72+ ulong isolated = x & ( ~ x + 1UL ) ;
73+
74+ int index = ( int ) ( ( isolated * 0x045FBAC7992A70DAUL ) >> 58 ) ;
75+
76+ return SampleMultiplyDeBruijnBitPosition64 [ index ] ;
77+ }
78+
1179 // uint에 대해 trailing zero count (CTZ)
1280 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
1381 public static uint b2CTZ32 ( uint block )
@@ -25,7 +93,7 @@ public static uint b2CTZ32(uint block)
2593
2694 // uint에 대해 leading zero count (CLZ)
2795 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
28- public static uint b2CLZ32 ( uint value )
96+ public static uint b2CLZ32_Old ( uint value )
2997 {
3098 if ( value == 0 ) return 32 ;
3199 uint count = 0 ;
@@ -54,6 +122,7 @@ public static uint b2CTZ64(ulong block)
54122 return count ;
55123 }
56124
125+
57126 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
58127 public static int b2PopCount64 ( ulong block )
59128 {
0 commit comments