box2d-ruby 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +336 -0
  4. data/examples/contact_events.rb +22 -0
  5. data/examples/debug_draw.rb +15 -0
  6. data/examples/falling_ball.rb +19 -0
  7. data/examples/rugl_debug_draw.rb +68 -0
  8. data/examples/stagecraft_debug_draw.rb +64 -0
  9. data/examples/support/box2d_debug_lines.rb +125 -0
  10. data/ext/box2d/CMakeLists.txt +35 -0
  11. data/ext/box2d/extconf.rb +42 -0
  12. data/ext/box2d/native.c +9 -0
  13. data/ext/box2d/vendor/box2d/LICENSE +21 -0
  14. data/ext/box2d/vendor/box2d/VERSION +1 -0
  15. data/ext/box2d/vendor/box2d/include/box2d/base.h +131 -0
  16. data/ext/box2d/vendor/box2d/include/box2d/box2d.h +1222 -0
  17. data/ext/box2d/vendor/box2d/include/box2d/collision.h +830 -0
  18. data/ext/box2d/vendor/box2d/include/box2d/id.h +144 -0
  19. data/ext/box2d/vendor/box2d/include/box2d/math_functions.h +761 -0
  20. data/ext/box2d/vendor/box2d/include/box2d/types.h +1457 -0
  21. data/ext/box2d/vendor/box2d/src/CMakeLists.txt +223 -0
  22. data/ext/box2d/vendor/box2d/src/aabb.c +132 -0
  23. data/ext/box2d/vendor/box2d/src/aabb.h +56 -0
  24. data/ext/box2d/vendor/box2d/src/arena_allocator.c +112 -0
  25. data/ext/box2d/vendor/box2d/src/arena_allocator.h +48 -0
  26. data/ext/box2d/vendor/box2d/src/array.c +8 -0
  27. data/ext/box2d/vendor/box2d/src/array.h +179 -0
  28. data/ext/box2d/vendor/box2d/src/atomic.h +79 -0
  29. data/ext/box2d/vendor/box2d/src/bitset.c +67 -0
  30. data/ext/box2d/vendor/box2d/src/bitset.h +65 -0
  31. data/ext/box2d/vendor/box2d/src/body.c +1884 -0
  32. data/ext/box2d/vendor/box2d/src/body.h +194 -0
  33. data/ext/box2d/vendor/box2d/src/box2d.natvis +41 -0
  34. data/ext/box2d/vendor/box2d/src/broad_phase.c +524 -0
  35. data/ext/box2d/vendor/box2d/src/broad_phase.h +83 -0
  36. data/ext/box2d/vendor/box2d/src/constants.h +54 -0
  37. data/ext/box2d/vendor/box2d/src/constraint_graph.c +322 -0
  38. data/ext/box2d/vendor/box2d/src/constraint_graph.h +58 -0
  39. data/ext/box2d/vendor/box2d/src/contact.c +650 -0
  40. data/ext/box2d/vendor/box2d/src/contact.h +148 -0
  41. data/ext/box2d/vendor/box2d/src/contact_solver.c +2120 -0
  42. data/ext/box2d/vendor/box2d/src/contact_solver.h +54 -0
  43. data/ext/box2d/vendor/box2d/src/core.c +178 -0
  44. data/ext/box2d/vendor/box2d/src/core.h +149 -0
  45. data/ext/box2d/vendor/box2d/src/ctz.h +112 -0
  46. data/ext/box2d/vendor/box2d/src/distance.c +1415 -0
  47. data/ext/box2d/vendor/box2d/src/distance_joint.c +556 -0
  48. data/ext/box2d/vendor/box2d/src/dynamic_tree.c +1989 -0
  49. data/ext/box2d/vendor/box2d/src/geometry.c +1028 -0
  50. data/ext/box2d/vendor/box2d/src/hull.c +328 -0
  51. data/ext/box2d/vendor/box2d/src/id_pool.c +79 -0
  52. data/ext/box2d/vendor/box2d/src/id_pool.h +35 -0
  53. data/ext/box2d/vendor/box2d/src/island.c +977 -0
  54. data/ext/box2d/vendor/box2d/src/island.h +89 -0
  55. data/ext/box2d/vendor/box2d/src/joint.c +1272 -0
  56. data/ext/box2d/vendor/box2d/src/joint.h +335 -0
  57. data/ext/box2d/vendor/box2d/src/manifold.c +1726 -0
  58. data/ext/box2d/vendor/box2d/src/math_functions.c +159 -0
  59. data/ext/box2d/vendor/box2d/src/motor_joint.c +283 -0
  60. data/ext/box2d/vendor/box2d/src/mouse_joint.c +214 -0
  61. data/ext/box2d/vendor/box2d/src/mover.c +73 -0
  62. data/ext/box2d/vendor/box2d/src/prismatic_joint.c +656 -0
  63. data/ext/box2d/vendor/box2d/src/revolute_joint.c +534 -0
  64. data/ext/box2d/vendor/box2d/src/sensor.c +389 -0
  65. data/ext/box2d/vendor/box2d/src/sensor.h +36 -0
  66. data/ext/box2d/vendor/box2d/src/shape.c +1714 -0
  67. data/ext/box2d/vendor/box2d/src/shape.h +123 -0
  68. data/ext/box2d/vendor/box2d/src/solver.c +2038 -0
  69. data/ext/box2d/vendor/box2d/src/solver.h +155 -0
  70. data/ext/box2d/vendor/box2d/src/solver_set.c +613 -0
  71. data/ext/box2d/vendor/box2d/src/solver_set.h +57 -0
  72. data/ext/box2d/vendor/box2d/src/table.c +238 -0
  73. data/ext/box2d/vendor/box2d/src/table.h +37 -0
  74. data/ext/box2d/vendor/box2d/src/timer.c +185 -0
  75. data/ext/box2d/vendor/box2d/src/types.c +151 -0
  76. data/ext/box2d/vendor/box2d/src/weld_joint.c +310 -0
  77. data/ext/box2d/vendor/box2d/src/wheel_joint.c +551 -0
  78. data/ext/box2d/vendor/box2d/src/world.c +3301 -0
  79. data/ext/box2d/vendor/box2d/src/world.h +192 -0
  80. data/generator/generate.rb +316 -0
  81. data/generator/layout_probe.c +507 -0
  82. data/generator/verify_layouts.rb +32 -0
  83. data/lib/box2d/body.rb +172 -0
  84. data/lib/box2d/body_definition.rb +38 -0
  85. data/lib/box2d/body_shapes.rb +135 -0
  86. data/lib/box2d/chain.rb +61 -0
  87. data/lib/box2d/debug_draw.rb +118 -0
  88. data/lib/box2d/events.rb +103 -0
  89. data/lib/box2d/fixed_stepper.rb +39 -0
  90. data/lib/box2d/handle.rb +46 -0
  91. data/lib/box2d/hit.rb +5 -0
  92. data/lib/box2d/joint.rb +197 -0
  93. data/lib/box2d/native.rb +1462 -0
  94. data/lib/box2d/native_loader.rb +45 -0
  95. data/lib/box2d/pixel_scale.rb +29 -0
  96. data/lib/box2d/shape.rb +109 -0
  97. data/lib/box2d/shape_definition.rb +44 -0
  98. data/lib/box2d/value_conversion.rb +80 -0
  99. data/lib/box2d/version.rb +7 -0
  100. data/lib/box2d/world.rb +135 -0
  101. data/lib/box2d/world_joints.rb +156 -0
  102. data/lib/box2d/world_queries.rb +122 -0
  103. data/lib/box2d/world_registry.rb +95 -0
  104. data/lib/box2d.rb +31 -0
  105. data/script/build_platform_gem.rb +24 -0
  106. data/script/deterministic_scene.rb +56 -0
  107. data/script/update_deterministic_snapshot.rb +11 -0
  108. data/script/verify_platform_gem.rb +24 -0
  109. metadata +164 -0
@@ -0,0 +1,54 @@
1
+ // SPDX-FileCopyrightText: 2023 Erin Catto
2
+ // SPDX-License-Identifier: MIT
3
+
4
+ #pragma once
5
+
6
+ #include "solver.h"
7
+
8
+ typedef struct b2ContactSim b2ContactSim;
9
+
10
+ typedef struct b2ContactConstraintPoint
11
+ {
12
+ b2Vec2 anchorA, anchorB;
13
+ float baseSeparation;
14
+ float relativeVelocity;
15
+ float normalImpulse;
16
+ float tangentImpulse;
17
+ float totalNormalImpulse;
18
+ float normalMass;
19
+ float tangentMass;
20
+ } b2ContactConstraintPoint;
21
+
22
+ typedef struct b2ContactConstraint
23
+ {
24
+ int indexA;
25
+ int indexB;
26
+ b2ContactConstraintPoint points[2];
27
+ b2Vec2 normal;
28
+ float invMassA, invMassB;
29
+ float invIA, invIB;
30
+ float friction;
31
+ float restitution;
32
+ float tangentSpeed;
33
+ float rollingResistance;
34
+ float rollingMass;
35
+ float rollingImpulse;
36
+ b2Softness softness;
37
+ int pointCount;
38
+ } b2ContactConstraint;
39
+
40
+ int b2GetContactConstraintSIMDByteCount( void );
41
+
42
+ // Overflow contacts don't fit into the constraint graph coloring
43
+ void b2PrepareOverflowContacts( b2StepContext* context );
44
+ void b2WarmStartOverflowContacts( b2StepContext* context );
45
+ void b2SolveOverflowContacts( b2StepContext* context, bool useBias );
46
+ void b2ApplyOverflowRestitution( b2StepContext* context );
47
+ void b2StoreOverflowImpulses( b2StepContext* context );
48
+
49
+ // Contacts that live within the constraint graph coloring
50
+ void b2PrepareContactsTask( int startIndex, int endIndex, b2StepContext* context );
51
+ void b2WarmStartContactsTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex );
52
+ void b2SolveContactsTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex, bool useBias );
53
+ void b2ApplyRestitutionTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex );
54
+ void b2StoreImpulsesTask( int startIndex, int endIndex, b2StepContext* context );
@@ -0,0 +1,178 @@
1
+ // SPDX-FileCopyrightText: 2023 Erin Catto
2
+ // SPDX-License-Identifier: MIT
3
+
4
+ #include "core.h"
5
+
6
+ #if defined( B2_COMPILER_MSVC )
7
+ #define _CRTDBG_MAP_ALLOC
8
+ #include <crtdbg.h>
9
+ #include <stdlib.h>
10
+ #else
11
+ #include <stdlib.h>
12
+ #endif
13
+
14
+ #include <stdio.h>
15
+ #include <string.h>
16
+
17
+ #ifdef BOX2D_PROFILE
18
+
19
+ #include <tracy/TracyC.h>
20
+ #define b2TracyCAlloc( ptr, size ) TracyCAlloc( ptr, size )
21
+ #define b2TracyCFree( ptr ) TracyCFree( ptr )
22
+
23
+ #else
24
+
25
+ #define b2TracyCAlloc( ptr, size )
26
+ #define b2TracyCFree( ptr )
27
+
28
+ #endif
29
+
30
+ #include "atomic.h"
31
+
32
+ // This allows the user to change the length units at runtime
33
+ float b2_lengthUnitsPerMeter = 1.0f;
34
+
35
+ void b2SetLengthUnitsPerMeter( float lengthUnits )
36
+ {
37
+ B2_ASSERT( b2IsValidFloat( lengthUnits ) && lengthUnits > 0.0f );
38
+ b2_lengthUnitsPerMeter = lengthUnits;
39
+ }
40
+
41
+ float b2GetLengthUnitsPerMeter( void )
42
+ {
43
+ return b2_lengthUnitsPerMeter;
44
+ }
45
+
46
+ static int b2DefaultAssertFcn( const char* condition, const char* fileName, int lineNumber )
47
+ {
48
+ printf( "BOX2D ASSERTION: %s, %s, line %d\n", condition, fileName, lineNumber );
49
+
50
+ // return non-zero to break to debugger
51
+ return 1;
52
+ }
53
+
54
+ b2AssertFcn* b2AssertHandler = b2DefaultAssertFcn;
55
+
56
+ void b2SetAssertFcn( b2AssertFcn* assertFcn )
57
+ {
58
+ B2_ASSERT( assertFcn != NULL );
59
+ b2AssertHandler = assertFcn;
60
+ }
61
+
62
+ #if !defined( NDEBUG ) || defined( B2_ENABLE_ASSERT )
63
+ int b2InternalAssertFcn( const char* condition, const char* fileName, int lineNumber )
64
+ {
65
+ return b2AssertHandler( condition, fileName, lineNumber );
66
+ }
67
+ #endif
68
+
69
+ b2Version b2GetVersion( void )
70
+ {
71
+ return (b2Version){
72
+ .major = 3,
73
+ .minor = 1,
74
+ .revision = 0,
75
+ };
76
+ }
77
+
78
+ static b2AllocFcn* b2_allocFcn = NULL;
79
+ static b2FreeFcn* b2_freeFcn = NULL;
80
+
81
+ b2AtomicInt b2_byteCount;
82
+
83
+ void b2SetAllocator( b2AllocFcn* allocFcn, b2FreeFcn* freeFcn )
84
+ {
85
+ b2_allocFcn = allocFcn;
86
+ b2_freeFcn = freeFcn;
87
+ }
88
+
89
+ // Use 32 byte alignment for everything. Works with 256bit SIMD.
90
+ #define B2_ALIGNMENT 32
91
+
92
+ void* b2Alloc( int size )
93
+ {
94
+ if ( size == 0 )
95
+ {
96
+ return NULL;
97
+ }
98
+
99
+ // This could cause some sharing issues, however Box2D rarely calls b2Alloc.
100
+ b2AtomicFetchAddInt( &b2_byteCount, size );
101
+
102
+ // Allocation must be a multiple of 32 or risk a seg fault
103
+ // https://en.cppreference.com/w/c/memory/aligned_alloc
104
+ int size32 = ( ( size - 1 ) | 0x1F ) + 1;
105
+
106
+ if ( b2_allocFcn != NULL )
107
+ {
108
+ void* ptr = b2_allocFcn( size32, B2_ALIGNMENT );
109
+ b2TracyCAlloc( ptr, size );
110
+
111
+ B2_ASSERT( ptr != NULL );
112
+ B2_ASSERT( ( (uintptr_t)ptr & 0x1F ) == 0 );
113
+
114
+ return ptr;
115
+ }
116
+
117
+ #ifdef B2_PLATFORM_WINDOWS
118
+ void* ptr = _aligned_malloc( size32, B2_ALIGNMENT );
119
+ #elif defined( B2_PLATFORM_ANDROID )
120
+ void* ptr = NULL;
121
+ if ( posix_memalign( &ptr, B2_ALIGNMENT, size32 ) != 0 )
122
+ {
123
+ // allocation failed, exit the application
124
+ exit( EXIT_FAILURE );
125
+ }
126
+ #else
127
+ void* ptr = aligned_alloc( B2_ALIGNMENT, size32 );
128
+ #endif
129
+
130
+ b2TracyCAlloc( ptr, size );
131
+
132
+ B2_ASSERT( ptr != NULL );
133
+ B2_ASSERT( ( (uintptr_t)ptr & 0x1F ) == 0 );
134
+
135
+ return ptr;
136
+ }
137
+
138
+ void b2Free( void* mem, int size )
139
+ {
140
+ if ( mem == NULL )
141
+ {
142
+ return;
143
+ }
144
+
145
+ b2TracyCFree( mem );
146
+
147
+ if ( b2_freeFcn != NULL )
148
+ {
149
+ b2_freeFcn( mem );
150
+ }
151
+ else
152
+ {
153
+ #ifdef B2_PLATFORM_WINDOWS
154
+ _aligned_free( mem );
155
+ #else
156
+ free( mem );
157
+ #endif
158
+ }
159
+
160
+ b2AtomicFetchAddInt( &b2_byteCount, -size );
161
+ }
162
+
163
+ void* b2GrowAlloc( void* oldMem, int oldSize, int newSize )
164
+ {
165
+ B2_ASSERT( newSize > oldSize );
166
+ void* newMem = b2Alloc( newSize );
167
+ if ( oldSize > 0 )
168
+ {
169
+ memcpy( newMem, oldMem, oldSize );
170
+ b2Free( oldMem, oldSize );
171
+ }
172
+ return newMem;
173
+ }
174
+
175
+ int b2GetByteCount( void )
176
+ {
177
+ return b2AtomicLoadInt( &b2_byteCount );
178
+ }
@@ -0,0 +1,149 @@
1
+ // SPDX-FileCopyrightText: 2023 Erin Catto
2
+ // SPDX-License-Identifier: MIT
3
+
4
+ #pragma once
5
+
6
+ #include "box2d/math_functions.h"
7
+
8
+ // clang-format off
9
+
10
+ #define B2_NULL_INDEX ( -1 )
11
+
12
+ // for performance comparisons
13
+ #define B2_RESTRICT restrict
14
+
15
+ #ifdef NDEBUG
16
+ #define B2_DEBUG 0
17
+ #else
18
+ #define B2_DEBUG 1
19
+ #endif
20
+
21
+ #if defined( BOX2D_VALIDATE ) && !defined( NDEBUG )
22
+ #define B2_VALIDATE 1
23
+ #else
24
+ #define B2_VALIDATE 0
25
+ #endif
26
+
27
+ // Define platform
28
+ #if defined(_WIN32) || defined(_WIN64)
29
+ #define B2_PLATFORM_WINDOWS
30
+ #elif defined( __ANDROID__ )
31
+ #define B2_PLATFORM_ANDROID
32
+ #elif defined( __linux__ )
33
+ #define B2_PLATFORM_LINUX
34
+ #elif defined( __APPLE__ )
35
+ #include <TargetConditionals.h>
36
+ #if defined( TARGET_OS_IPHONE ) && !TARGET_OS_IPHONE
37
+ #define B2_PLATFORM_MACOS
38
+ #else
39
+ #define B2_PLATFORM_IOS
40
+ #endif
41
+ #elif defined( __EMSCRIPTEN__ )
42
+ #define B2_PLATFORM_WASM
43
+ #else
44
+ #define B2_PLATFORM_UNKNOWN
45
+ #endif
46
+
47
+ // Define CPU
48
+ #if defined( __x86_64__ ) || defined( _M_X64 ) || defined( __i386__ ) || defined( _M_IX86 )
49
+ #define B2_CPU_X86_X64
50
+ #elif defined( __aarch64__ ) || defined( _M_ARM64 ) || defined( __arm__ ) || defined( _M_ARM )
51
+ #define B2_CPU_ARM
52
+ #elif defined( __EMSCRIPTEN__ )
53
+ #define B2_CPU_WASM
54
+ #else
55
+ #define B2_CPU_UNKNOWN
56
+ #endif
57
+
58
+ // Define SIMD
59
+ #if defined( BOX2D_DISABLE_SIMD )
60
+ #define B2_SIMD_NONE
61
+ // note: I tried width of 1 and got no performance change
62
+ #define B2_SIMD_WIDTH 4
63
+ #else
64
+ #if defined( B2_CPU_X86_X64 )
65
+ #if defined( BOX2D_AVX2 )
66
+ #define B2_SIMD_AVX2
67
+ #define B2_SIMD_WIDTH 8
68
+ #else
69
+ #define B2_SIMD_SSE2
70
+ #define B2_SIMD_WIDTH 4
71
+ #endif
72
+ #elif defined( B2_CPU_ARM )
73
+ #define B2_SIMD_NEON
74
+ #define B2_SIMD_WIDTH 4
75
+ #elif defined( B2_CPU_WASM )
76
+ #define B2_CPU_WASM
77
+ #define B2_SIMD_SSE2
78
+ #define B2_SIMD_WIDTH 4
79
+ #else
80
+ #define B2_SIMD_NONE
81
+ #define B2_SIMD_WIDTH 4
82
+ #endif
83
+ #endif
84
+
85
+ // Define compiler
86
+ #if defined( __clang__ )
87
+ #define B2_COMPILER_CLANG
88
+ #elif defined( __GNUC__ )
89
+ #define B2_COMPILER_GCC
90
+ #elif defined( _MSC_VER )
91
+ #define B2_COMPILER_MSVC
92
+ #endif
93
+
94
+ /// Tracy profiler instrumentation
95
+ /// https://github.com/wolfpld/tracy
96
+ #ifdef BOX2D_PROFILE
97
+ #include <tracy/TracyC.h>
98
+ #define b2TracyCZoneC( ctx, color, active ) TracyCZoneC( ctx, color, active )
99
+ #define b2TracyCZoneNC( ctx, name, color, active ) TracyCZoneNC( ctx, name, color, active )
100
+ #define b2TracyCZoneEnd( ctx ) TracyCZoneEnd( ctx )
101
+ #else
102
+ #define b2TracyCZoneC( ctx, color, active )
103
+ #define b2TracyCZoneNC( ctx, name, color, active )
104
+ #define b2TracyCZoneEnd( ctx )
105
+ #endif
106
+
107
+ // clang-format on
108
+
109
+ // Returns the number of elements of an array
110
+ #define B2_ARRAY_COUNT( A ) (int)( sizeof( A ) / sizeof( A[0] ) )
111
+
112
+ // Used to prevent the compiler from warning about unused variables
113
+ #define B2_UNUSED( ... ) (void)sizeof( ( __VA_ARGS__, 0 ) )
114
+
115
+ // Use to validate definitions. Do not take my cookie.
116
+ #define B2_SECRET_COOKIE 1152023
117
+
118
+ // Snoop counters. These should be disabled in optimized builds because they are expensive.
119
+ #if defined( box2d_EXPORTS )
120
+ #define B2_SNOOP_TABLE_COUNTERS B2_DEBUG
121
+ #define B2_SNOOP_PAIR_COUNTERS B2_DEBUG
122
+ #define B2_SNOOP_TOI_COUNTERS B2_DEBUG
123
+ #else
124
+ #define B2_SNOOP_TABLE_COUNTERS 0
125
+ #define B2_SNOOP_PAIR_COUNTERS 0
126
+ #define B2_SNOOP_TOI_COUNTERS 0
127
+ #endif
128
+
129
+ #define B2_CHECK_DEF( DEF ) B2_ASSERT( DEF->internalValue == B2_SECRET_COOKIE )
130
+
131
+ typedef struct b2AtomicInt
132
+ {
133
+ int value;
134
+ } b2AtomicInt;
135
+
136
+ typedef struct b2AtomicU32
137
+ {
138
+ uint32_t value;
139
+ } b2AtomicU32;
140
+
141
+ void* b2Alloc( int size );
142
+ #define B2_ALLOC_STRUCT( type ) b2Alloc(sizeof(type))
143
+ #define B2_ALLOC_ARRAY( count, type ) b2Alloc(count * sizeof(type))
144
+
145
+ void b2Free( void* mem, int size );
146
+ #define B2_FREE_STRUCT( mem, type ) b2Free( mem, sizeof(type));
147
+ #define B2_FREE_ARRAY( mem, count, type ) b2Free(mem, count * sizeof(type))
148
+
149
+ void* b2GrowAlloc( void* oldMem, int oldSize, int newSize );
@@ -0,0 +1,112 @@
1
+ // SPDX-FileCopyrightText: 2023 Erin Catto
2
+ // SPDX-License-Identifier: MIT
3
+
4
+ #pragma once
5
+
6
+ #include <stdbool.h>
7
+ #include <stdint.h>
8
+
9
+ #if defined( _MSC_VER ) && !defined( __clang__ )
10
+ #include <intrin.h>
11
+
12
+ // https://en.wikipedia.org/wiki/Find_first_set
13
+
14
+ static inline uint32_t b2CTZ32( uint32_t block )
15
+ {
16
+ unsigned long index;
17
+ _BitScanForward( &index, block );
18
+ return index;
19
+ }
20
+
21
+ // This function doesn't need to be fast, so using the Ivy Bridge fallback.
22
+ static inline uint32_t b2CLZ32( uint32_t value )
23
+ {
24
+ #if 1
25
+
26
+ // Use BSR (Bit Scan Reverse) which is available on Ivy Bridge
27
+ unsigned long index;
28
+ if ( _BitScanReverse( &index, value ) )
29
+ {
30
+ // BSR gives the index of the most significant 1-bit
31
+ // We need to invert this to get the number of leading zeros
32
+ return 31 - index;
33
+ }
34
+ else
35
+ {
36
+ // If x is 0, BSR sets the zero flag and doesn't modify index
37
+ // LZCNT should return 32 for an input of 0
38
+ return 32;
39
+ }
40
+
41
+ #else
42
+
43
+ return __lzcnt( value );
44
+
45
+ #endif
46
+ }
47
+
48
+ static inline uint32_t b2CTZ64( uint64_t block )
49
+ {
50
+ unsigned long index;
51
+
52
+ #ifdef _WIN64
53
+ _BitScanForward64( &index, block );
54
+ #else
55
+ // 32-bit fall back
56
+ if ( (uint32_t)block != 0 )
57
+ {
58
+ _BitScanForward( &index, (uint32_t)block );
59
+ }
60
+ else
61
+ {
62
+ _BitScanForward( &index, (uint32_t)( block >> 32 ) );
63
+ index += 32;
64
+ }
65
+ #endif
66
+
67
+ return index;
68
+ }
69
+
70
+ #else
71
+
72
+ static inline uint32_t b2CTZ32( uint32_t block )
73
+ {
74
+ return __builtin_ctz( block );
75
+ }
76
+
77
+ static inline uint32_t b2CLZ32( uint32_t value )
78
+ {
79
+ return __builtin_clz( value );
80
+ }
81
+
82
+ static inline uint32_t b2CTZ64( uint64_t block )
83
+ {
84
+ return __builtin_ctzll( block );
85
+ }
86
+
87
+ #endif
88
+
89
+ static inline bool b2IsPowerOf2( int x )
90
+ {
91
+ return ( x & ( x - 1 ) ) == 0;
92
+ }
93
+
94
+ static inline int b2BoundingPowerOf2( int x )
95
+ {
96
+ if ( x <= 1 )
97
+ {
98
+ return 1;
99
+ }
100
+
101
+ return 32 - (int)b2CLZ32( (uint32_t)x - 1 );
102
+ }
103
+
104
+ static inline int b2RoundUpPowerOf2( int x )
105
+ {
106
+ if ( x <= 1 )
107
+ {
108
+ return 1;
109
+ }
110
+
111
+ return 1 << ( 32 - (int)b2CLZ32( (uint32_t)x - 1 ) );
112
+ }