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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +336 -0
- data/examples/contact_events.rb +22 -0
- data/examples/debug_draw.rb +15 -0
- data/examples/falling_ball.rb +19 -0
- data/examples/rugl_debug_draw.rb +68 -0
- data/examples/stagecraft_debug_draw.rb +64 -0
- data/examples/support/box2d_debug_lines.rb +125 -0
- data/ext/box2d/CMakeLists.txt +35 -0
- data/ext/box2d/extconf.rb +42 -0
- data/ext/box2d/native.c +9 -0
- data/ext/box2d/vendor/box2d/LICENSE +21 -0
- data/ext/box2d/vendor/box2d/VERSION +1 -0
- data/ext/box2d/vendor/box2d/include/box2d/base.h +131 -0
- data/ext/box2d/vendor/box2d/include/box2d/box2d.h +1222 -0
- data/ext/box2d/vendor/box2d/include/box2d/collision.h +830 -0
- data/ext/box2d/vendor/box2d/include/box2d/id.h +144 -0
- data/ext/box2d/vendor/box2d/include/box2d/math_functions.h +761 -0
- data/ext/box2d/vendor/box2d/include/box2d/types.h +1457 -0
- data/ext/box2d/vendor/box2d/src/CMakeLists.txt +223 -0
- data/ext/box2d/vendor/box2d/src/aabb.c +132 -0
- data/ext/box2d/vendor/box2d/src/aabb.h +56 -0
- data/ext/box2d/vendor/box2d/src/arena_allocator.c +112 -0
- data/ext/box2d/vendor/box2d/src/arena_allocator.h +48 -0
- data/ext/box2d/vendor/box2d/src/array.c +8 -0
- data/ext/box2d/vendor/box2d/src/array.h +179 -0
- data/ext/box2d/vendor/box2d/src/atomic.h +79 -0
- data/ext/box2d/vendor/box2d/src/bitset.c +67 -0
- data/ext/box2d/vendor/box2d/src/bitset.h +65 -0
- data/ext/box2d/vendor/box2d/src/body.c +1884 -0
- data/ext/box2d/vendor/box2d/src/body.h +194 -0
- data/ext/box2d/vendor/box2d/src/box2d.natvis +41 -0
- data/ext/box2d/vendor/box2d/src/broad_phase.c +524 -0
- data/ext/box2d/vendor/box2d/src/broad_phase.h +83 -0
- data/ext/box2d/vendor/box2d/src/constants.h +54 -0
- data/ext/box2d/vendor/box2d/src/constraint_graph.c +322 -0
- data/ext/box2d/vendor/box2d/src/constraint_graph.h +58 -0
- data/ext/box2d/vendor/box2d/src/contact.c +650 -0
- data/ext/box2d/vendor/box2d/src/contact.h +148 -0
- data/ext/box2d/vendor/box2d/src/contact_solver.c +2120 -0
- data/ext/box2d/vendor/box2d/src/contact_solver.h +54 -0
- data/ext/box2d/vendor/box2d/src/core.c +178 -0
- data/ext/box2d/vendor/box2d/src/core.h +149 -0
- data/ext/box2d/vendor/box2d/src/ctz.h +112 -0
- data/ext/box2d/vendor/box2d/src/distance.c +1415 -0
- data/ext/box2d/vendor/box2d/src/distance_joint.c +556 -0
- data/ext/box2d/vendor/box2d/src/dynamic_tree.c +1989 -0
- data/ext/box2d/vendor/box2d/src/geometry.c +1028 -0
- data/ext/box2d/vendor/box2d/src/hull.c +328 -0
- data/ext/box2d/vendor/box2d/src/id_pool.c +79 -0
- data/ext/box2d/vendor/box2d/src/id_pool.h +35 -0
- data/ext/box2d/vendor/box2d/src/island.c +977 -0
- data/ext/box2d/vendor/box2d/src/island.h +89 -0
- data/ext/box2d/vendor/box2d/src/joint.c +1272 -0
- data/ext/box2d/vendor/box2d/src/joint.h +335 -0
- data/ext/box2d/vendor/box2d/src/manifold.c +1726 -0
- data/ext/box2d/vendor/box2d/src/math_functions.c +159 -0
- data/ext/box2d/vendor/box2d/src/motor_joint.c +283 -0
- data/ext/box2d/vendor/box2d/src/mouse_joint.c +214 -0
- data/ext/box2d/vendor/box2d/src/mover.c +73 -0
- data/ext/box2d/vendor/box2d/src/prismatic_joint.c +656 -0
- data/ext/box2d/vendor/box2d/src/revolute_joint.c +534 -0
- data/ext/box2d/vendor/box2d/src/sensor.c +389 -0
- data/ext/box2d/vendor/box2d/src/sensor.h +36 -0
- data/ext/box2d/vendor/box2d/src/shape.c +1714 -0
- data/ext/box2d/vendor/box2d/src/shape.h +123 -0
- data/ext/box2d/vendor/box2d/src/solver.c +2038 -0
- data/ext/box2d/vendor/box2d/src/solver.h +155 -0
- data/ext/box2d/vendor/box2d/src/solver_set.c +613 -0
- data/ext/box2d/vendor/box2d/src/solver_set.h +57 -0
- data/ext/box2d/vendor/box2d/src/table.c +238 -0
- data/ext/box2d/vendor/box2d/src/table.h +37 -0
- data/ext/box2d/vendor/box2d/src/timer.c +185 -0
- data/ext/box2d/vendor/box2d/src/types.c +151 -0
- data/ext/box2d/vendor/box2d/src/weld_joint.c +310 -0
- data/ext/box2d/vendor/box2d/src/wheel_joint.c +551 -0
- data/ext/box2d/vendor/box2d/src/world.c +3301 -0
- data/ext/box2d/vendor/box2d/src/world.h +192 -0
- data/generator/generate.rb +316 -0
- data/generator/layout_probe.c +507 -0
- data/generator/verify_layouts.rb +32 -0
- data/lib/box2d/body.rb +172 -0
- data/lib/box2d/body_definition.rb +38 -0
- data/lib/box2d/body_shapes.rb +135 -0
- data/lib/box2d/chain.rb +61 -0
- data/lib/box2d/debug_draw.rb +118 -0
- data/lib/box2d/events.rb +103 -0
- data/lib/box2d/fixed_stepper.rb +39 -0
- data/lib/box2d/handle.rb +46 -0
- data/lib/box2d/hit.rb +5 -0
- data/lib/box2d/joint.rb +197 -0
- data/lib/box2d/native.rb +1462 -0
- data/lib/box2d/native_loader.rb +45 -0
- data/lib/box2d/pixel_scale.rb +29 -0
- data/lib/box2d/shape.rb +109 -0
- data/lib/box2d/shape_definition.rb +44 -0
- data/lib/box2d/value_conversion.rb +80 -0
- data/lib/box2d/version.rb +7 -0
- data/lib/box2d/world.rb +135 -0
- data/lib/box2d/world_joints.rb +156 -0
- data/lib/box2d/world_queries.rb +122 -0
- data/lib/box2d/world_registry.rb +95 -0
- data/lib/box2d.rb +31 -0
- data/script/build_platform_gem.rb +24 -0
- data/script/deterministic_scene.rb +56 -0
- data/script/update_deterministic_snapshot.rb +11 -0
- data/script/verify_platform_gem.rb +24 -0
- metadata +164 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2023 Erin Catto
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include "core.h"
|
|
7
|
+
|
|
8
|
+
// Macro generated functions for dynamic arrays
|
|
9
|
+
// Pros
|
|
10
|
+
// - type safe
|
|
11
|
+
// - array data debuggable (visible count and capacity)
|
|
12
|
+
// - bounds checking
|
|
13
|
+
// - forward declaration
|
|
14
|
+
// - simple implementation
|
|
15
|
+
// - generates functions (like C++ templates)
|
|
16
|
+
// - functions have https://en.wikipedia.org/wiki/Sequence_point
|
|
17
|
+
// - avoids stretchy buffer dropped pointer update bugs
|
|
18
|
+
// Cons
|
|
19
|
+
// - cannot debug
|
|
20
|
+
// - breaks code navigation
|
|
21
|
+
|
|
22
|
+
// todo_erin consider code-gen: https://github.com/IbrahimHindawi/haikal
|
|
23
|
+
|
|
24
|
+
// Array declaration that doesn't need the type T to be defined
|
|
25
|
+
#define B2_ARRAY_DECLARE( T, PREFIX ) \
|
|
26
|
+
typedef struct \
|
|
27
|
+
{ \
|
|
28
|
+
struct T* data; \
|
|
29
|
+
int count; \
|
|
30
|
+
int capacity; \
|
|
31
|
+
} PREFIX##Array; \
|
|
32
|
+
PREFIX##Array PREFIX##Array_Create( int capacity ); \
|
|
33
|
+
void PREFIX##Array_Reserve( PREFIX##Array* a, int newCapacity ); \
|
|
34
|
+
void PREFIX##Array_Destroy( PREFIX##Array* a )
|
|
35
|
+
|
|
36
|
+
#define B2_DECLARE_ARRAY_NATIVE( T, PREFIX ) \
|
|
37
|
+
typedef struct \
|
|
38
|
+
{ \
|
|
39
|
+
T* data; \
|
|
40
|
+
int count; \
|
|
41
|
+
int capacity; \
|
|
42
|
+
} PREFIX##Array; \
|
|
43
|
+
/* Create array with initial capacity. Zero initialization is also supported */ \
|
|
44
|
+
PREFIX##Array PREFIX##Array_Create( int capacity ); \
|
|
45
|
+
void PREFIX##Array_Reserve( PREFIX##Array* a, int newCapacity ); \
|
|
46
|
+
void PREFIX##Array_Destroy( PREFIX##Array* a )
|
|
47
|
+
|
|
48
|
+
// Inline array functions that need the type T to be defined
|
|
49
|
+
#define B2_ARRAY_INLINE( T, PREFIX ) \
|
|
50
|
+
/* Resize */ \
|
|
51
|
+
static inline void PREFIX##Array_Resize( PREFIX##Array* a, int count ) \
|
|
52
|
+
{ \
|
|
53
|
+
PREFIX##Array_Reserve( a, count ); \
|
|
54
|
+
a->count = count; \
|
|
55
|
+
} \
|
|
56
|
+
/* Get */ \
|
|
57
|
+
static inline T* PREFIX##Array_Get( PREFIX##Array* a, int index ) \
|
|
58
|
+
{ \
|
|
59
|
+
B2_ASSERT( 0 <= index && index < a->count ); \
|
|
60
|
+
return a->data + index; \
|
|
61
|
+
} \
|
|
62
|
+
/* Add */ \
|
|
63
|
+
static inline T* PREFIX##Array_Add( PREFIX##Array* a ) \
|
|
64
|
+
{ \
|
|
65
|
+
if ( a->count == a->capacity ) \
|
|
66
|
+
{ \
|
|
67
|
+
int newCapacity = a->capacity < 2 ? 2 : a->capacity + ( a->capacity >> 1 ); \
|
|
68
|
+
PREFIX##Array_Reserve( a, newCapacity ); \
|
|
69
|
+
} \
|
|
70
|
+
a->count += 1; \
|
|
71
|
+
return a->data + ( a->count - 1 ); \
|
|
72
|
+
} \
|
|
73
|
+
/* Push */ \
|
|
74
|
+
static inline void PREFIX##Array_Push( PREFIX##Array* a, T value ) \
|
|
75
|
+
{ \
|
|
76
|
+
if ( a->count == a->capacity ) \
|
|
77
|
+
{ \
|
|
78
|
+
int newCapacity = a->capacity < 2 ? 2 : a->capacity + ( a->capacity >> 1 ); \
|
|
79
|
+
PREFIX##Array_Reserve( a, newCapacity ); \
|
|
80
|
+
} \
|
|
81
|
+
a->data[a->count] = value; \
|
|
82
|
+
a->count += 1; \
|
|
83
|
+
} \
|
|
84
|
+
/* Set */ \
|
|
85
|
+
static inline void PREFIX##Array_Set( PREFIX##Array* a, int index, T value ) \
|
|
86
|
+
{ \
|
|
87
|
+
B2_ASSERT( 0 <= index && index < a->count ); \
|
|
88
|
+
a->data[index] = value; \
|
|
89
|
+
} \
|
|
90
|
+
/* RemoveSwap */ \
|
|
91
|
+
static inline int PREFIX##Array_RemoveSwap( PREFIX##Array* a, int index ) \
|
|
92
|
+
{ \
|
|
93
|
+
B2_ASSERT( 0 <= index && index < a->count ); \
|
|
94
|
+
int movedIndex = B2_NULL_INDEX; \
|
|
95
|
+
if ( index != a->count - 1 ) \
|
|
96
|
+
{ \
|
|
97
|
+
movedIndex = a->count - 1; \
|
|
98
|
+
a->data[index] = a->data[movedIndex]; \
|
|
99
|
+
} \
|
|
100
|
+
a->count -= 1; \
|
|
101
|
+
return movedIndex; \
|
|
102
|
+
} \
|
|
103
|
+
/* Pop */ \
|
|
104
|
+
static inline T PREFIX##Array_Pop( PREFIX##Array* a ) \
|
|
105
|
+
{ \
|
|
106
|
+
B2_ASSERT( a->count > 0 ); \
|
|
107
|
+
T value = a->data[a->count - 1]; \
|
|
108
|
+
a->count -= 1; \
|
|
109
|
+
return value; \
|
|
110
|
+
} \
|
|
111
|
+
/* Clear */ \
|
|
112
|
+
static inline void PREFIX##Array_Clear( PREFIX##Array* a ) \
|
|
113
|
+
{ \
|
|
114
|
+
a->count = 0; \
|
|
115
|
+
} \
|
|
116
|
+
/* ByteCount */ \
|
|
117
|
+
static inline int PREFIX##Array_ByteCount( PREFIX##Array* a ) \
|
|
118
|
+
{ \
|
|
119
|
+
return (int)( a->capacity * sizeof( T ) ); \
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Array implementations to be instantiated in a source file where the type T is known
|
|
123
|
+
#define B2_ARRAY_SOURCE( T, PREFIX ) \
|
|
124
|
+
/* Create */ \
|
|
125
|
+
PREFIX##Array PREFIX##Array_Create( int capacity ) \
|
|
126
|
+
{ \
|
|
127
|
+
PREFIX##Array a = { 0 }; \
|
|
128
|
+
if ( capacity > 0 ) \
|
|
129
|
+
{ \
|
|
130
|
+
a.data = b2Alloc( capacity * sizeof( T ) ); \
|
|
131
|
+
a.capacity = capacity; \
|
|
132
|
+
} \
|
|
133
|
+
return a; \
|
|
134
|
+
} \
|
|
135
|
+
/* Reserve */ \
|
|
136
|
+
void PREFIX##Array_Reserve( PREFIX##Array* a, int newCapacity ) \
|
|
137
|
+
{ \
|
|
138
|
+
if ( newCapacity <= a->capacity ) \
|
|
139
|
+
{ \
|
|
140
|
+
return; \
|
|
141
|
+
} \
|
|
142
|
+
a->data = b2GrowAlloc( a->data, a->capacity * sizeof( T ), newCapacity * sizeof( T ) ); \
|
|
143
|
+
a->capacity = newCapacity; \
|
|
144
|
+
} \
|
|
145
|
+
/* Destroy */ \
|
|
146
|
+
void PREFIX##Array_Destroy( PREFIX##Array* a ) \
|
|
147
|
+
{ \
|
|
148
|
+
b2Free( a->data, a->capacity * sizeof( T ) ); \
|
|
149
|
+
a->data = NULL; \
|
|
150
|
+
a->count = 0; \
|
|
151
|
+
a->capacity = 0; \
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
B2_DECLARE_ARRAY_NATIVE( int, b2Int );
|
|
155
|
+
B2_ARRAY_INLINE( int, b2Int )
|
|
156
|
+
|
|
157
|
+
// Declare all the arrays
|
|
158
|
+
B2_ARRAY_DECLARE( b2Body, b2Body );
|
|
159
|
+
B2_ARRAY_DECLARE( b2BodyMoveEvent, b2BodyMoveEvent );
|
|
160
|
+
B2_ARRAY_DECLARE( b2BodySim, b2BodySim );
|
|
161
|
+
B2_ARRAY_DECLARE( b2BodyState, b2BodyState );
|
|
162
|
+
B2_ARRAY_DECLARE( b2ChainShape, b2ChainShape );
|
|
163
|
+
B2_ARRAY_DECLARE( b2Contact, b2Contact );
|
|
164
|
+
B2_ARRAY_DECLARE( b2ContactBeginTouchEvent, b2ContactBeginTouchEvent );
|
|
165
|
+
B2_ARRAY_DECLARE( b2ContactEndTouchEvent, b2ContactEndTouchEvent );
|
|
166
|
+
B2_ARRAY_DECLARE( b2ContactHitEvent, b2ContactHitEvent );
|
|
167
|
+
B2_ARRAY_DECLARE( b2ContactSim, b2ContactSim );
|
|
168
|
+
B2_ARRAY_DECLARE( b2Island, b2Island );
|
|
169
|
+
B2_ARRAY_DECLARE( b2IslandSim, b2IslandSim );
|
|
170
|
+
B2_ARRAY_DECLARE( b2Joint, b2Joint );
|
|
171
|
+
B2_ARRAY_DECLARE( b2JointSim, b2JointSim );
|
|
172
|
+
B2_ARRAY_DECLARE( b2Sensor, b2Sensor );
|
|
173
|
+
B2_ARRAY_DECLARE( b2SensorBeginTouchEvent, b2SensorBeginTouchEvent );
|
|
174
|
+
B2_ARRAY_DECLARE( b2SensorEndTouchEvent, b2SensorEndTouchEvent );
|
|
175
|
+
B2_ARRAY_DECLARE( b2SensorTaskContext, b2SensorTaskContext );
|
|
176
|
+
B2_ARRAY_DECLARE( b2Shape, b2Shape );
|
|
177
|
+
B2_ARRAY_DECLARE( b2ShapeRef, b2ShapeRef );
|
|
178
|
+
B2_ARRAY_DECLARE( b2SolverSet, b2SolverSet );
|
|
179
|
+
B2_ARRAY_DECLARE( b2TaskContext, b2TaskContext );
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2023 Erin Catto
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include "core.h"
|
|
7
|
+
|
|
8
|
+
#include <stdint.h>
|
|
9
|
+
|
|
10
|
+
#if defined( _MSC_VER )
|
|
11
|
+
#include <intrin.h>
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
static inline void b2AtomicStoreInt( b2AtomicInt* a, int value )
|
|
15
|
+
{
|
|
16
|
+
#if defined( _MSC_VER )
|
|
17
|
+
(void)_InterlockedExchange( (long*)&a->value, value );
|
|
18
|
+
#elif defined( __GNUC__ ) || defined( __clang__ )
|
|
19
|
+
__atomic_store_n( &a->value, value, __ATOMIC_SEQ_CST );
|
|
20
|
+
#else
|
|
21
|
+
#error "Unsupported platform"
|
|
22
|
+
#endif
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static inline int b2AtomicLoadInt( b2AtomicInt* a )
|
|
26
|
+
{
|
|
27
|
+
#if defined( _MSC_VER )
|
|
28
|
+
return _InterlockedOr( (long*)&a->value, 0 );
|
|
29
|
+
#elif defined( __GNUC__ ) || defined( __clang__ )
|
|
30
|
+
return __atomic_load_n( &a->value, __ATOMIC_SEQ_CST );
|
|
31
|
+
#else
|
|
32
|
+
#error "Unsupported platform"
|
|
33
|
+
#endif
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static inline int b2AtomicFetchAddInt( b2AtomicInt* a, int increment )
|
|
37
|
+
{
|
|
38
|
+
#if defined( _MSC_VER )
|
|
39
|
+
return _InterlockedExchangeAdd( (long*)&a->value, (long)increment );
|
|
40
|
+
#elif defined( __GNUC__ ) || defined( __clang__ )
|
|
41
|
+
return __atomic_fetch_add( &a->value, increment, __ATOMIC_SEQ_CST );
|
|
42
|
+
#else
|
|
43
|
+
#error "Unsupported platform"
|
|
44
|
+
#endif
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static inline bool b2AtomicCompareExchangeInt( b2AtomicInt* a, int expected, int desired )
|
|
48
|
+
{
|
|
49
|
+
#if defined( _MSC_VER )
|
|
50
|
+
return _InterlockedCompareExchange( (long*)&a->value, (long)desired, (long)expected ) == expected;
|
|
51
|
+
#elif defined( __GNUC__ ) || defined( __clang__ )
|
|
52
|
+
// The value written to expected is ignored
|
|
53
|
+
return __atomic_compare_exchange_n( &a->value, &expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST );
|
|
54
|
+
#else
|
|
55
|
+
#error "Unsupported platform"
|
|
56
|
+
#endif
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static inline void b2AtomicStoreU32( b2AtomicU32* a, uint32_t value )
|
|
60
|
+
{
|
|
61
|
+
#if defined( _MSC_VER )
|
|
62
|
+
(void)_InterlockedExchange( (long*)&a->value, value );
|
|
63
|
+
#elif defined( __GNUC__ ) || defined( __clang__ )
|
|
64
|
+
__atomic_store_n( &a->value, value, __ATOMIC_SEQ_CST );
|
|
65
|
+
#else
|
|
66
|
+
#error "Unsupported platform"
|
|
67
|
+
#endif
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
static inline uint32_t b2AtomicLoadU32( b2AtomicU32* a )
|
|
71
|
+
{
|
|
72
|
+
#if defined( _MSC_VER )
|
|
73
|
+
return (uint32_t)_InterlockedOr( (long*)&a->value, 0 );
|
|
74
|
+
#elif defined( __GNUC__ ) || defined( __clang__ )
|
|
75
|
+
return __atomic_load_n( &a->value, __ATOMIC_SEQ_CST );
|
|
76
|
+
#else
|
|
77
|
+
#error "Unsupported platform"
|
|
78
|
+
#endif
|
|
79
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2023 Erin Catto
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
#include "bitset.h"
|
|
5
|
+
|
|
6
|
+
#include <string.h>
|
|
7
|
+
|
|
8
|
+
b2BitSet b2CreateBitSet( uint32_t bitCapacity )
|
|
9
|
+
{
|
|
10
|
+
b2BitSet bitSet = { 0 };
|
|
11
|
+
|
|
12
|
+
bitSet.blockCapacity = ( bitCapacity + sizeof( uint64_t ) * 8 - 1 ) / ( sizeof( uint64_t ) * 8 );
|
|
13
|
+
bitSet.blockCount = 0;
|
|
14
|
+
bitSet.bits = b2Alloc( bitSet.blockCapacity * sizeof( uint64_t ) );
|
|
15
|
+
memset( bitSet.bits, 0, bitSet.blockCapacity * sizeof( uint64_t ) );
|
|
16
|
+
return bitSet;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void b2DestroyBitSet( b2BitSet* bitSet )
|
|
20
|
+
{
|
|
21
|
+
b2Free( bitSet->bits, bitSet->blockCapacity * sizeof( uint64_t ) );
|
|
22
|
+
bitSet->blockCapacity = 0;
|
|
23
|
+
bitSet->blockCount = 0;
|
|
24
|
+
bitSet->bits = NULL;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
void b2SetBitCountAndClear( b2BitSet* bitSet, uint32_t bitCount )
|
|
28
|
+
{
|
|
29
|
+
uint32_t blockCount = ( bitCount + sizeof( uint64_t ) * 8 - 1 ) / ( sizeof( uint64_t ) * 8 );
|
|
30
|
+
if ( bitSet->blockCapacity < blockCount )
|
|
31
|
+
{
|
|
32
|
+
b2DestroyBitSet( bitSet );
|
|
33
|
+
uint32_t newBitCapacity = bitCount + ( bitCount >> 1 );
|
|
34
|
+
*bitSet = b2CreateBitSet( newBitCapacity );
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
bitSet->blockCount = blockCount;
|
|
38
|
+
memset( bitSet->bits, 0, bitSet->blockCount * sizeof( uint64_t ) );
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
void b2GrowBitSet( b2BitSet* bitSet, uint32_t blockCount )
|
|
42
|
+
{
|
|
43
|
+
B2_ASSERT( blockCount > bitSet->blockCount );
|
|
44
|
+
if ( blockCount > bitSet->blockCapacity )
|
|
45
|
+
{
|
|
46
|
+
uint32_t oldCapacity = bitSet->blockCapacity;
|
|
47
|
+
bitSet->blockCapacity = blockCount + blockCount / 2;
|
|
48
|
+
uint64_t* newBits = b2Alloc( bitSet->blockCapacity * sizeof( uint64_t ) );
|
|
49
|
+
memset( newBits, 0, bitSet->blockCapacity * sizeof( uint64_t ) );
|
|
50
|
+
B2_ASSERT( bitSet->bits != NULL );
|
|
51
|
+
memcpy( newBits, bitSet->bits, oldCapacity * sizeof( uint64_t ) );
|
|
52
|
+
b2Free( bitSet->bits, oldCapacity * sizeof( uint64_t ) );
|
|
53
|
+
bitSet->bits = newBits;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
bitSet->blockCount = blockCount;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
void b2InPlaceUnion( b2BitSet* B2_RESTRICT setA, const b2BitSet* B2_RESTRICT setB )
|
|
60
|
+
{
|
|
61
|
+
B2_ASSERT( setA->blockCount == setB->blockCount );
|
|
62
|
+
uint32_t blockCount = setA->blockCount;
|
|
63
|
+
for ( uint32_t i = 0; i < blockCount; ++i )
|
|
64
|
+
{
|
|
65
|
+
setA->bits[i] |= setB->bits[i];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2023 Erin Catto
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include "core.h"
|
|
7
|
+
|
|
8
|
+
#include <stdbool.h>
|
|
9
|
+
#include <stdint.h>
|
|
10
|
+
|
|
11
|
+
// Bit set provides fast operations on large arrays of bits.
|
|
12
|
+
typedef struct b2BitSet
|
|
13
|
+
{
|
|
14
|
+
uint64_t* bits;
|
|
15
|
+
uint32_t blockCapacity;
|
|
16
|
+
uint32_t blockCount;
|
|
17
|
+
} b2BitSet;
|
|
18
|
+
|
|
19
|
+
b2BitSet b2CreateBitSet( uint32_t bitCapacity );
|
|
20
|
+
void b2DestroyBitSet( b2BitSet* bitSet );
|
|
21
|
+
void b2SetBitCountAndClear( b2BitSet* bitSet, uint32_t bitCount );
|
|
22
|
+
void b2InPlaceUnion( b2BitSet* setA, const b2BitSet* setB );
|
|
23
|
+
void b2GrowBitSet( b2BitSet* bitSet, uint32_t blockCount );
|
|
24
|
+
|
|
25
|
+
static inline void b2SetBit( b2BitSet* bitSet, uint32_t bitIndex )
|
|
26
|
+
{
|
|
27
|
+
uint32_t blockIndex = bitIndex / 64;
|
|
28
|
+
B2_ASSERT( blockIndex < bitSet->blockCount );
|
|
29
|
+
bitSet->bits[blockIndex] |= ( (uint64_t)1 << bitIndex % 64 );
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static inline void b2SetBitGrow( b2BitSet* bitSet, uint32_t bitIndex )
|
|
33
|
+
{
|
|
34
|
+
uint32_t blockIndex = bitIndex / 64;
|
|
35
|
+
if ( blockIndex >= bitSet->blockCount )
|
|
36
|
+
{
|
|
37
|
+
b2GrowBitSet( bitSet, blockIndex + 1 );
|
|
38
|
+
}
|
|
39
|
+
bitSet->bits[blockIndex] |= ( (uint64_t)1 << bitIndex % 64 );
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static inline void b2ClearBit( b2BitSet* bitSet, uint32_t bitIndex )
|
|
43
|
+
{
|
|
44
|
+
uint32_t blockIndex = bitIndex / 64;
|
|
45
|
+
if ( blockIndex >= bitSet->blockCount )
|
|
46
|
+
{
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
bitSet->bits[blockIndex] &= ~( (uint64_t)1 << bitIndex % 64 );
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static inline bool b2GetBit( const b2BitSet* bitSet, uint32_t bitIndex )
|
|
53
|
+
{
|
|
54
|
+
uint32_t blockIndex = bitIndex / 64;
|
|
55
|
+
if ( blockIndex >= bitSet->blockCount )
|
|
56
|
+
{
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return ( bitSet->bits[blockIndex] & ( (uint64_t)1 << bitIndex % 64 ) ) != 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static inline int b2GetBitSetBytes( b2BitSet* bitSet )
|
|
63
|
+
{
|
|
64
|
+
return bitSet->blockCapacity * sizeof( uint64_t );
|
|
65
|
+
}
|