Skip to content

Commit cf25305

Browse files
committed
bitset
1 parent f18820a commit cf25305

6 files changed

Lines changed: 306 additions & 26 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_executable(${EXE_NAME} main.c)
1010

1111
if (MSVC)
1212
target_compile_options(${EXE_NAME} PRIVATE /W4)
13+
1314
else ()
1415
target_compile_options(${EXE_NAME} PRIVATE -Wall -Wextra -Wpedantic)
1516
endif ()

opencstl/bitset.h

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
#if !defined(OPENCSTL_BITSET_H)
2+
#define OPENCSTL_BITSET_H
3+
#include "types.h"
4+
#include "zalloc.h"
5+
#include "crossplatform.h"
6+
7+
int __popcnt_sw(int v) {
8+
v = (v & 0x55555555) + ((v >> 1) & 0x55555555);
9+
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
10+
v = (v & 0x0f0f0f0f) + ((v >> 4) & 0x0f0f0f0f);
11+
v = (v & 0x00ff00ff) + ((v >> 8) & 0x00ff00ff);
12+
v = (v & 0x0000ffff) + ((v >> 16) & 0x0000ffff);
13+
return v;
14+
}
15+
16+
int __popcnt64_sw(long long v) {
17+
v = (v & 0x5555555555555555LL) + ((v >> 1) & 0x5555555555555555LL);
18+
v = (v & 0x3333333333333333LL) + ((v >> 2) & 0x3333333333333333LL);
19+
v = (v & 0x0f0f0f0f0f0f0f0fLL) + ((v >> 4) & 0x0f0f0f0f0f0f0f0fLL);
20+
v = (v & 0x00ff00ff00ff00ffLL) + ((v >> 8) & 0x00ff00ff00ff00ffLL);
21+
v = (v & 0x0000ffff0000ffffLL) + ((v >> 16) & 0x0000ffff0000ffffLL);
22+
v = (v & 0x00000000ffffffffLL) + ((v >> 32) & 0x00000000ffffffffLL);
23+
return (int) v;
24+
}
25+
#if defined(OCSTL_OS_LINUX)
26+
#if defined (OCSTL_CC_TCC)
27+
#define __popcnt __popcnt_sw
28+
#define __popcnt64 __popcnt64_sw
29+
#else
30+
#define __popcnt(v) __builtin_popcount((unsigned int)(v))
31+
#define __popcnt64(v) __builtin_popcountll((unsigned long long)(v))
32+
#endif
33+
#elif defined(OCSTL_OS_WINDOWS)
34+
#if !defined(OCSTL_CC_TCC)
35+
36+
#include<intrin.h>
37+
#else
38+
#define __popcnt __popcnt_sw
39+
#define __popcnt64 __popcnt64_sw
40+
#endif
41+
#endif
42+
#define __BASE_SIZE 8
43+
44+
// _size로부터 바이트 용량을 계산
45+
static inline size_type __cstl_bitset_capacity(size_type size) {
46+
size_type cap = (size + 7) / 8;
47+
return cap < __BASE_SIZE ? __BASE_SIZE : cap;
48+
}
49+
50+
typedef struct {
51+
size_type nbits;
52+
ubyte_x *bits;
53+
char *str;
54+
} BITSET;
55+
56+
#define new_bitset(N) __cstl_bitset(N)
57+
58+
BITSET __cstl_bitset(size_type n) {
59+
size_type cap = __cstl_bitset_capacity(n);
60+
BITSET b;
61+
b.nbits = n;
62+
b.bits = zalloc(cap, 1);
63+
b.str = (char *) zalloc(b.nbits + 1, 1);
64+
return b;
65+
}
66+
67+
// ██████╗░██╗████████╗░██████╗███████╗████████╗░░░░░░███████╗██╗░░░██╗███╗░░██╗░█████╗░░░░░░░██████╗░████████╗██████╗░
68+
// ██╔══██╗██║╚══██╔══╝██╔════╝██╔════╝╚══██╔══╝░░░░░░██╔════╝██║░░░██║████╗░██║██╔══██╗░░░░░░██╔══██╗╚══██╔══╝██╔══██╗
69+
// ██████╦╝██║░░░██║░░░╚█████╗░█████╗░░░░░██║░░░░░░░░░█████╗░░██║░░░██║██╔██╗██║██║░░╚═╝░░░░░░██████╔╝░░░██║░░░██████╔╝
70+
// ██╔══██╗██║░░░██║░░░░╚═══██╗██╔══╝░░░░░██║░░░░░░░░░██╔══╝░░██║░░░██║██║╚████║██║░░██╗░░░░░░██╔═══╝░░░░██║░░░██╔══██╗
71+
// ██████╦╝██║░░░██║░░░██████╔╝███████╗░░░██║░░░█████╗██║░░░░░╚██████╔╝██║░╚███║╚█████╔╝█████╗██║░░░░░░░░██║░░░██║░░██║
72+
// ╚═════╝░╚═╝░░░╚═╝░░░╚═════╝░╚══════╝░░░╚═╝░░░╚════╝╚═╝░░░░░░╚═════╝░╚═╝░░╚══╝░╚════╝░╚════╝╚═╝░░░░░░░░╚═╝░░░╚═╝░░╚═╝
73+
typedef void (*bitset_fn1)(BITSET b);
74+
75+
typedef void (*bitset_fn2)(BITSET b, size_type idx, bool val);
76+
77+
typedef size_type (*bitset_fn3)(BITSET b);
78+
79+
typedef bool (*bitset_fn4)(BITSET b);
80+
81+
typedef void (*bitset_fn5)(BITSET b, size_type idx);
82+
83+
typedef bool (*bitset_fn6)(BITSET b, size_type idx);
84+
85+
typedef char * (*bitset_fn7)(BITSET b);
86+
87+
// ██████╗░██╗████████╗░██████╗███████╗████████╗░░░░░░██╗███╗░░░███╗██████╗░██╗░░░░░
88+
// ██╔══██╗██║╚══██╔══╝██╔════╝██╔════╝╚══██╔══╝░░░░░░██║████╗░████║██╔══██╗██║░░░░░
89+
// ██████╦╝██║░░░██║░░░╚█████╗░█████╗░░░░░██║░░░░░░░░░██║██╔████╔██║██████╔╝██║░░░░░
90+
// ██╔══██╗██║░░░██║░░░░╚═══██╗██╔══╝░░░░░██║░░░░░░░░░██║██║╚██╔╝██║██╔═══╝░██║░░░░░
91+
// ██████╦╝██║░░░██║░░░██████╔╝███████╗░░░██║░░░█████╗██║██║░╚═╝░██║██║░░░░░███████╗
92+
// ╚═════╝░╚═╝░░░╚═╝░░░╚═════╝░╚══════╝░░░╚═╝░░░╚════╝╚═╝╚═╝░░░░░╚═╝╚═╝░░░░░╚══════╝
93+
void __cstl_bitset_set(BITSET b) {
94+
// 모든 비트를 1로 설정
95+
size_type cap = __cstl_bitset_capacity(b.nbits);
96+
memset(b.bits, 0xFF, cap);
97+
// _size 이후의 여분 비트를 0으로 클리어
98+
size_type rem = b.nbits % 8;
99+
if (rem != 0) {
100+
b.bits[b.nbits / 8] &= (ubyte_x) ((1 << rem) - 1);
101+
}
102+
}
103+
104+
void __cstl_bitset_reset(BITSET b) {
105+
// 모든 비트를 0으로 설정
106+
size_type cap = __cstl_bitset_capacity(b.nbits);
107+
memset(b.bits, 0, cap);
108+
}
109+
110+
void __cstl_bitset_set_at(BITSET b, size_type idx, bool val) {
111+
// idx번째 비트를 val로 설정
112+
size_type byte_idx = idx / 8;
113+
size_type bit_idx = idx % 8;
114+
if (val) {
115+
b.bits[byte_idx] |= (ubyte_x) (1 << bit_idx);
116+
} else {
117+
b.bits[byte_idx] &= (ubyte_x) ~(1 << bit_idx);
118+
}
119+
}
120+
121+
size_type __cstl_bitset_count(BITSET b) {
122+
// 1로 설정된 비트의 개수를 반환
123+
size_type cap = __cstl_bitset_capacity(b.nbits);
124+
size_t count = 0;
125+
size_type i = 0;
126+
// 8바이트(64비트) 단위로 처리
127+
for (; i + 8 <= cap; i += 8) {
128+
long long chunk;
129+
memcpy(&chunk, b.bits + i, 8);
130+
count += __popcnt64(chunk);
131+
}
132+
// 남은 바이트를 4바이트 단위로 처리
133+
for (; i + 4 <= cap; i += 4) {
134+
int chunk;
135+
memcpy(&chunk, b.bits + i, 4);
136+
count += __popcnt(chunk);
137+
}
138+
// 나머지 바이트 처리
139+
for (; i < cap; i++) {
140+
count += __popcnt((int) b.bits[i]);
141+
}
142+
return count;
143+
}
144+
145+
bool __cstl_bitset_all(BITSET b) {
146+
// 모든 비트가 1인지 검사
147+
if (b.nbits == 0) return true;
148+
size_type full_bytes = b.nbits / 8;
149+
size_type rem = b.nbits % 8;
150+
for (size_type i = 0; i < full_bytes; i++) {
151+
if (b.bits[i] != 0xFF) return false;
152+
}
153+
if (rem != 0) {
154+
ubyte_x mask = (ubyte_x) ((1 << rem) - 1);
155+
if ((b.bits[full_bytes] & mask) != mask) return false;
156+
}
157+
return true;
158+
}
159+
160+
bool __cstl_bitset_any(BITSET b) {
161+
// 하나라도 1인 비트가 있는지 검사
162+
if (b.nbits == 0) return false;
163+
size_type full_bytes = b.nbits / 8;
164+
size_type rem = b.nbits % 8;
165+
for (size_type i = 0; i < full_bytes; i++) {
166+
if (b.bits[i] != 0) return true;
167+
}
168+
if (rem != 0) {
169+
ubyte_x mask = (ubyte_x) ((1 << rem) - 1);
170+
if ((b.bits[full_bytes] & mask) != 0) return true;
171+
}
172+
return false;
173+
}
174+
175+
bool __cstl_bitset_none(BITSET b) {
176+
// 모든 비트가 0인지 검사
177+
return !__cstl_bitset_any(b);
178+
}
179+
180+
void __cstl_bitset_flip(BITSET b) {
181+
// 모든 비트를 반전
182+
size_type full_bytes = b.nbits / 8;
183+
size_type rem = b.nbits % 8;
184+
for (size_type i = 0; i < full_bytes; i++) {
185+
b.bits[i] = ~b.bits[i];
186+
}
187+
if (rem != 0) {
188+
ubyte_x mask = (ubyte_x) ((1 << rem) - 1);
189+
b.bits[full_bytes] ^= mask;
190+
}
191+
}
192+
193+
void __cstl_bitset_flip_at(BITSET b, size_type idx) {
194+
// 특정 위치의 비트를 반전
195+
size_type byte_idx = idx / 8;
196+
size_type bit_idx = idx % 8;
197+
b.bits[byte_idx] ^= (ubyte_x) (1 << bit_idx);
198+
}
199+
200+
201+
size_type __cstl_bitset_nbits(BITSET b) {
202+
// 비트셋의 크기(비트 수)를 반환
203+
return b.nbits;
204+
}
205+
206+
bool __cstl_bitset_test(BITSET b, size_type idx) {
207+
// 특정 위치의 비트가 1인지 검사
208+
size_type byte_idx = idx / 8;
209+
size_type bit_idx = idx % 8;
210+
return (b.bits[byte_idx] >> bit_idx) & 1;
211+
}
212+
213+
214+
char *__cstl_bitset_to_string(BITSET b) {
215+
// 비트셋을 문자열로 변환 (MSB가 앞, C++ bitset::to_string과 동일)
216+
for (size_type i = 0; i < b.nbits; i++) {
217+
size_type bit_pos = b.nbits - 1 - i;
218+
b.str[i] = __cstl_bitset_test(b, bit_pos) ? '1' : '0';
219+
}
220+
b.str[b.nbits] = '\0';
221+
return b.str;
222+
}
223+
224+
void __cstl_bitset_free(BITSET b) {
225+
zfree(b.bits);
226+
zfree(b.str);
227+
}
228+
229+
typedef struct {
230+
bitset_fn1 set;
231+
bitset_fn1 reset;
232+
bitset_fn2 set_at;
233+
bitset_fn3 count;
234+
bitset_fn4 all;
235+
bitset_fn4 any;
236+
bitset_fn4 none;
237+
bitset_fn1 flip;
238+
bitset_fn5 flip_at;
239+
bitset_fn3 nbits;
240+
bitset_fn6 test;
241+
bitset_fn7 to_string;
242+
bitset_fn1 free;
243+
} __BITSET;
244+
245+
static __BITSET bitset = {
246+
__cstl_bitset_set,
247+
__cstl_bitset_reset,
248+
__cstl_bitset_set_at,
249+
__cstl_bitset_count,
250+
__cstl_bitset_all,
251+
__cstl_bitset_any,
252+
__cstl_bitset_none,
253+
__cstl_bitset_flip,
254+
__cstl_bitset_flip_at,
255+
__cstl_bitset_nbits,
256+
__cstl_bitset_test,
257+
__cstl_bitset_to_string,
258+
__cstl_bitset_free
259+
};
260+
261+
#endif //OPENCSTL_BITSET_H

opencstl/lprint.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,22 @@
44

55
#include <stdio.h>
66
#include <ctype.h>
7+
#include "crossplatform.h"
78

9+
#if defined(OCSTL_CC_MSVC)
10+
static void lprint(const char *text) {
11+
int len = strlen(text);
12+
for (int i = 0; i < len; i++) {
13+
putchar('=');
14+
}
15+
putchar('\n');
16+
puts(text);
17+
for (int i = 0; i < len; i++) {
18+
putchar('=');
19+
}
20+
putchar('\n');
21+
}
22+
#else
823
#define LPRINT_ROWS 6
924

1025
typedef struct {
@@ -575,7 +590,12 @@ static const lprint_glyph_t *lprint_find(char c) {
575590
}
576591

577592
static void lprint(const char *text) {
578-
for (int row = 0; row < LPRINT_ROWS; row++) {
593+
594+
#ifdef OCSTL_OS_WINDOWS
595+
UINT old_cp = GetConsoleOutputCP();
596+
SetConsoleOutputCP(CP_UTF8);
597+
#endif
598+
for (int row = 0; row<LPRINT_ROWS; row++) {
579599
for (const char *p = text; *p; p++) {
580600
char c = (char) toupper((unsigned char) *p);
581601
const lprint_glyph_t *g = lprint_find(c);
@@ -585,7 +605,10 @@ static void lprint(const char *text) {
585605
}
586606
putchar('\n');
587607
}
608+
#ifdef OCSTL_OS_WINDOWS
609+
SetConsoleOutputCP(old_cp);
610+
#endif
588611
}
589-
612+
#endif
590613

591614
#endif //OPENCSTL_LPRINT_H

opencstl/mt19937.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
#if !defined(OPENCSTL_MT19937_H)
3838
#define OPENCSTL_MT19937_H
3939
#include <stdint.h>
40-
40+
#include <time.h>
4141

4242
#define MT64_N 312
4343
#define MT64_M 156

opencstl/types.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,12 @@ typedef size_t (*cstl_hash)(void *key, size_t capacity, size_t key_size);
5656

5757
typedef int size_type;
5858

59+
60+
typedef int int32_x;
61+
typedef long long int64_x;
62+
typedef unsigned int uint32_x;
63+
typedef unsigned long long uint64_x;
64+
65+
typedef unsigned char ubyte_x;
66+
5967
#endif

test.c

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,17 @@
11
#include <stdio.h>
2+
#include "opencstl/bitset.h"
23

3-
// 리스트 정의
4-
#define ERROR_LIST \
5-
X(ERROR_NONE) \
6-
X(ERROR_INVALID) \
7-
X(ERROR_TIMEOUT) \
8-
X(ERROR_OVERFLOW)
4+
int main() {
5+
BITSET b = new_bitset(50);
96

10-
// enum 정의
11-
enum {
12-
#define X(name) name,
13-
ERROR_LIST
14-
#undef X
15-
ERROR_COUNT
16-
};
7+
bitset.set_at(b, 10,true);
8+
bitset.set_at(b, 0,true);
9+
int s = bitset.count(b);
10+
printf("%d\n", s);
1711

18-
// 문자열 배열 생성
19-
const char *ErrorNames[] = {
20-
#define X(name) #name,
21-
ERROR_LIST
22-
#undef X
23-
};
12+
char *str = bitset.to_string(b);
13+
puts(str);
2414

25-
int main() {
26-
for (int i = 0; i < ERROR_COUNT; i++) {
27-
printf("Error Code: %d, Name: %s\n", i, ErrorNames[i]);
28-
}
15+
bitset.free(b);
2916
return 0;
3017
}

0 commit comments

Comments
 (0)