summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2022-05-24 21:12:56 +0200
committerTyge Løvset <[email protected]>2022-05-24 21:12:56 +0200
commitebc7316ac3859bc5e2f01c85bee86d6adea45898 (patch)
treefb653c49e223cca40aea3fc2d734cd69b608b46d
parent966100106830f990bc3e1b40a5b5c39b64d5e9b0 (diff)
downloadSTC-modified-ebc7316ac3859bc5e2f01c85bee86d6adea45898.tar.gz
STC-modified-ebc7316ac3859bc5e2f01c85bee86d6adea45898.zip
API change: cbits now uses container pointers args in all member functions, except clone() ... for now. All containers may get same treatment! which will be a rather big API change. This was needed after testing fixed size cbits performance with pass-by-value: was very slow for large bitsets: now faster than std::bitset<>. Also reverted previous cbits_set_value(): much faster because it is branchless.
-rw-r--r--README.md14
-rw-r--r--benchmarks/misc/cbits_benchmark.cpp123
-rw-r--r--docs/cbits_api.md52
-rw-r--r--examples/bits.c44
-rw-r--r--examples/bits2.c24
-rw-r--r--examples/prime.c6
-rw-r--r--include/stc/cbits.h89
-rw-r--r--include/stc/ccommon.h6
8 files changed, 243 insertions, 115 deletions
diff --git a/README.md b/README.md
index 0194f906..0d402d79 100644
--- a/README.md
+++ b/README.md
@@ -249,14 +249,16 @@ After erasing elements found:
Installation
------------
-Because it is headers-only, headers can simply be included in your program. The methods are static
-by default (some inlined). You may add the *include* folder to the **CPATH** environment variable to
+Because it is headers-only, headers can simply be included in your program. By default, functions are static
+(some inlined). You may add the *include* folder to the **CPATH** environment variable to
let GCC, Clang, and TinyC locate the headers.
-If containers are used across several translation units with common instantiated container types,
-it is recommended to build as a "library" to minimize the executable size. To enable this mode,
-specify **-DSTC_HEADER** as a compiler option in your build environment and place all the instantiations
-of containers used in a single C-source file, e.g.:
+If containers are used across several translation units with common instantiated container types, it is
+recommended to build as a "library" with external linking to minimize executable size. To enable this,
+specify `-DSTC_HEADER` as compiler option in your build environment. Next, place all the instantiations
+of the containers used inside a single C-source file as in the example below, and `#define STC_IMPLEMENT` at top.
+You may also cherry-pick external linking mode on individual containers by `#define i_opt c_header` and
+`#define i_opt c_implement`, or force static symbols by `#define i_opt c_static` before container includes.
```c
// stc_libs.c
#define STC_IMPLEMENT
diff --git a/benchmarks/misc/cbits_benchmark.cpp b/benchmarks/misc/cbits_benchmark.cpp
new file mode 100644
index 00000000..50e19a7c
--- /dev/null
+++ b/benchmarks/misc/cbits_benchmark.cpp
@@ -0,0 +1,123 @@
+#include <iostream>
+#include <bitset>
+#include <cstdlib> // rand
+#include <ctime> // timer
+
+enum{ N=1<<22 }; // 4.2 mill.
+
+#include <stc/crandom.h>
+#define i_type cbits
+#define i_len N
+#include <stc/cbits.h>
+
+inline unsigned long get_time_in_ms()
+{
+ return (unsigned long)(1000 * clock() / CLOCKS_PER_SEC);
+}
+
+
+void one_sec_delay()
+{
+ unsigned long end_time = get_time_in_ms() + 1000;
+
+ while(get_time_in_ms() < end_time)
+ {
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ size_t seed = time(NULL);
+
+ using namespace std;
+ bool *bools = new bool[N];
+
+ unsigned long current_time, difference1, difference2;
+ uint64_t total;
+
+ one_sec_delay();
+
+ total = 0;
+ csrandom(seed);
+ current_time = get_time_in_ms();
+
+ c_forrange (40 * N)
+ {
+ uint64_t r = crandom();
+ bools[r & (N-1)] = r & 1<<29;
+ }
+
+ difference1 = get_time_in_ms() - current_time;
+ current_time = get_time_in_ms();
+
+ c_forrange (100) c_forrange (num, N)
+ {
+ total += bools[num];
+ }
+
+ delete [] bools;
+
+ difference2 = get_time_in_ms() - current_time;
+
+ cout << "Bool:" << endl << "sum total = " << total << ", random access time = " << difference1
+ << ", sequential access time = " << difference2 << endl << endl;
+
+ one_sec_delay();
+
+ total = 0;
+ csrandom(seed);
+ current_time = get_time_in_ms();
+ bitset<N> bits;
+
+ c_forrange (40 * N)
+ {
+ uint64_t r = crandom();
+ bits[r & (N-1)] = r & 1<<29;
+ }
+
+ difference1 = get_time_in_ms() - current_time;
+ current_time = get_time_in_ms();
+
+ c_forrange (100) c_forrange (num, N)
+ {
+ total += bits[num];
+ }
+
+ difference2 = get_time_in_ms() - current_time;
+
+ cout << "Bitset:" << endl << "sum total = " << total << ", random access time = " << difference1
+ << ", sequential access time = " << difference2 << endl << endl;
+
+ one_sec_delay();
+
+ total = 0;
+ csrandom(seed);
+ current_time = get_time_in_ms();
+ cbits bits2 = cbits_with_size(N, false);
+
+ c_forrange (40 * N)
+ {
+ uint64_t r = crandom();
+ cbits_set_value(&bits2, r & (N-1), r & 1<<29);
+ }
+
+ difference1 = get_time_in_ms() - current_time;
+ current_time = get_time_in_ms();
+
+ c_forrange (100) c_forrange (num, N)
+ {
+ total += cbits_at(&bits2, num);
+ }
+
+ cbits_drop(&bits2);
+
+ difference2 = get_time_in_ms() - current_time;
+
+ cout << "cbits:" << endl << "sum total = " << total << ", random access time = " << difference1
+ << ", sequential access time = " << difference2 << endl << endl;
+
+ //cin.get();
+
+ return 0;
+}
diff --git a/docs/cbits_api.md b/docs/cbits_api.md
index b9d54737..613c2d8c 100644
--- a/docs/cbits_api.md
+++ b/docs/cbits_api.md
@@ -21,38 +21,38 @@ All cbits definitions and prototypes are available by including a single header
```c
cbits cbits_init(void);
cbits cbits_from(const char* str);
-cbits cbits_with_size(size_t size, bool value); // size must be <= N if N is defined
+cbits cbits_with_size(size_t size, bool value); // size must be <= N if N is defined
cbits cbits_with_pattern(size_t size, uint64_t pattern);
cbits cbits_clone(cbits other);
void cbits_clear(cbits* self);
-cbits* cbits_copy(cbits* self, cbits other);
-void cbits_resize(cbits* self, size_t size, bool value); // only if i_len is not defined
+cbits* cbits_copy(cbits* self, const cbits* other);
+void cbits_resize(cbits* self, size_t size, bool value); // only if i_len is not defined
void cbits_drop(cbits* self);
-cbits* cbits_take(cbits* self, cbits other); // give other to self
-cbits cbits_move(cbits* self); // transfer self to caller
-
-size_t cbits_size(cbits set);
-size_t cbits_count(cbits set); // count number of bits set
-
-bool cbits_test(cbits set, size_t i);
-bool cbits_at(cbits set, size_t i); // same as cbits_test()
-bool cbits_subset_of(cbits set, cbits other); // is set a subset of other?
-bool cbits_disjoint(cbits set, cbits other); // no common bits
-char* cbits_to_str(cbits set, char* str, size_t start, intptr_t stop);
-
-void cbits_set(cbits *self, size_t i);
-void cbits_reset(cbits *self, size_t i);
-void cbits_set_value(cbits *self, size_t i, bool value);
-void cbits_set_all(cbits *self, bool value);
-void cbits_set_pattern(cbits *self, uint64_t pattern);
-void cbits_flip_all(cbits *self);
-void cbits_flip(cbits *self, size_t i);
-
-void cbits_intersect(cbits *self, cbits other);
-void cbits_union(cbits *self, cbits other);
-void cbits_xor(cbits *self, cbits other); // set of disjoint bits
+cbits* cbits_take(cbits* self, const cbits* other); // give other to self
+cbits cbits_move(cbits* self); // transfer self to caller
+
+size_t cbits_size(const cbits* self);
+size_t cbits_count(const cbits* self); // count number of bits set
+
+bool cbits_test(const cbits* self, size_t i);
+bool cbits_at(const cbits* self, size_t i); // same as cbits_test()
+bool cbits_subset_of(const cbits* self, const cbits* other); // is set a subset of other?
+bool cbits_disjoint(const cbits* self, const cbits* other); // no common bits
+char* cbits_to_str(const cbits* self, char* str, size_t start, intptr_t stop);
+
+void cbits_set(cbits* self, size_t i);
+void cbits_reset(cbits* self, size_t i);
+void cbits_set_value(cbits* self, size_t i, bool value);
+void cbits_set_all(cbits* self, bool value);
+void cbits_set_pattern(cbits* self, uint64_t pattern);
+void cbits_flip_all(cbits* self);
+void cbits_flip(cbits* self, size_t i);
+
+void cbits_intersect(cbits* self, const cbits* other);
+void cbits_union(cbits* self, const cbits* other);
+void cbits_xor(cbits* self, const cbits* other); // set of disjoint bits
```
## Types
diff --git a/examples/bits.c b/examples/bits.c
index bd2a9f03..8888f73e 100644
--- a/examples/bits.c
+++ b/examples/bits.c
@@ -4,21 +4,21 @@
int main()
{
c_autovar (cbits set = cbits_with_size(23, true), cbits_drop(&set)) {
- printf("count %" PRIuMAX ", %" PRIuMAX "\n", cbits_count(set), cbits_size(set));
+ printf("count %" PRIuMAX ", %" PRIuMAX "\n", cbits_count(&set), cbits_size(&set));
cbits s1 = cbits_from("1110100110111");
char buf[256];
- cbits_to_str(s1, buf, 0, -1);
- printf("buf: %s: %" PRIuMAX "\n", buf, cbits_count(s1));
+ cbits_to_str(&s1, buf, 0, -1);
+ printf("buf: %s: %" PRIuMAX "\n", buf, cbits_count(&s1));
cbits_drop(&s1);
cbits_reset(&set, 9);
cbits_resize(&set, 43, false);
- c_autobuf (str, char, cbits_size(set) + 1)
- printf(" str: %s\n", cbits_to_str(set, str, 0, -1));
+ c_autobuf (str, char, cbits_size(&set) + 1)
+ printf(" str: %s\n", cbits_to_str(&set, str, 0, -1));
- printf("%4" PRIuMAX ": ", cbits_size(set));
- c_forrange (i, cbits_size(set))
- printf("%d", cbits_test(set, i));
+ printf("%4" PRIuMAX ": ", cbits_size(&set));
+ c_forrange (i, cbits_size(&set))
+ printf("%d", cbits_test(&set, i));
puts("");
cbits_set(&set, 28);
@@ -26,14 +26,14 @@ int main()
cbits_resize(&set, 93, false);
cbits_resize(&set, 102, true);
cbits_set_value(&set, 99, false);
- printf("%4" PRIuMAX ": ", cbits_size(set));
- c_forrange (i, cbits_size(set))
- printf("%d", cbits_test(set, i));
+ printf("%4" PRIuMAX ": ", cbits_size(&set));
+ c_forrange (i, cbits_size(&set))
+ printf("%d", cbits_test(&set, i));
puts("\nIterate:");
- printf("%4" PRIuMAX ": ", cbits_size(set));
- c_forrange (i, cbits_size(set))
- printf("%d", cbits_test(set, i));
+ printf("%4" PRIuMAX ": ", cbits_size(&set));
+ c_forrange (i, cbits_size(&set))
+ printf("%d", cbits_test(&set, i));
puts("");
c_autovar (cbits s2 = cbits_clone(set), cbits_drop(&s2)) {
@@ -42,20 +42,20 @@ int main()
cbits_set(&s2, 17);
cbits_set(&s2, 18);
printf(" new: ");
- c_forrange (i, cbits_size(s2))
- printf("%d", cbits_test(s2, i));
+ c_forrange (i, cbits_size(&s2))
+ printf("%d", cbits_test(&s2, i));
puts("");
printf(" xor: ");
- cbits_xor(&set, s2);
- c_forrange (i, cbits_size(set))
- printf("%d", cbits_test(set, i));
+ cbits_xor(&set, &s2);
+ c_forrange (i, cbits_size(&set))
+ printf("%d", cbits_test(&set, i));
puts("");
cbits_set_all(&set, false);
- printf("%4" PRIuMAX ": ", cbits_size(set));
- c_forrange (i, cbits_size(set))
- printf("%d", cbits_test(set, i));
+ printf("%4" PRIuMAX ": ", cbits_size(&set));
+ c_forrange (i, cbits_size(&set))
+ printf("%d", cbits_test(&set, i));
puts("");
}
}
diff --git a/examples/bits2.c b/examples/bits2.c
index e9202efc..81e28d60 100644
--- a/examples/bits2.c
+++ b/examples/bits2.c
@@ -9,14 +9,14 @@ int main()
{
Bits s1 = Bits_from("1110100110111");
- printf("size %" PRIuMAX "\n", Bits_size(s1));
+ printf("size %" PRIuMAX "\n", Bits_size(&s1));
char buf[256];
- Bits_to_str(s1, buf, 0, -1);
- printf("buf: %s: count=%" PRIuMAX "\n", buf, Bits_count(s1));
+ Bits_to_str(&s1, buf, 0, -1);
+ printf("buf: %s: count=%" PRIuMAX "\n", buf, Bits_count(&s1));
Bits_reset(&s1, 8);
- c_autobuf (str, char, Bits_size(s1) + 1)
- printf(" s1: %s\n", Bits_to_str(s1, str, 0, -1));
+ c_autobuf (str, char, Bits_size(&s1) + 1)
+ printf(" s1: %s\n", Bits_to_str(&s1, str, 0, -1));
Bits s2 = Bits_clone(s1);
@@ -24,19 +24,19 @@ int main()
Bits_reset(&s2, 66);
Bits_reset(&s2, 67);
printf(" s2: ");
- c_forrange (i, Bits_size(s2))
- printf("%d", Bits_test(s2, i));
+ c_forrange (i, Bits_size(&s2))
+ printf("%d", Bits_test(&s2, i));
puts("");
printf("xor: ");
- Bits_xor(&s1, s2);
- c_forrange (i, Bits_size(s1))
- printf("%d", Bits_test(s1, i));
+ Bits_xor(&s1, &s2);
+ c_forrange (i, Bits_size(&s1))
+ printf("%d", Bits_test(&s1, i));
puts("");
printf("all: ");
Bits_set_pattern(&s1, 0x3333333333333333);
- c_forrange (i, Bits_size(s1))
- printf("%d", Bits_test(s1, i));
+ c_forrange (i, Bits_size(&s1))
+ printf("%d", Bits_test(&s1, i));
puts("");
}
diff --git a/examples/prime.c b/examples/prime.c
index aee0a89e..cc16603b 100644
--- a/examples/prime.c
+++ b/examples/prime.c
@@ -11,7 +11,7 @@ cbits sieveOfEratosthenes(size_t n)
for (size_t i = 3; i < q; i += 2) {
size_t j = i;
for (; j < n; j += 2) {
- if (cbits_test(bits, j>>1)) {
+ if (cbits_test(&bits, j>>1)) {
i = j;
break;
}
@@ -30,13 +30,13 @@ int main(void)
clock_t t1 = clock();
c_autovar (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) {
puts("done");
- size_t np = cbits_count(primes);
+ size_t np = cbits_count(&primes);
clock_t t2 = clock();
printf("number of primes: %" PRIuMAX ", time: %f\n", np, (t2 - t1) / (float)CLOCKS_PER_SEC);
printf("2");
for (size_t i = 3; i < 1000; i += 2)
- if (cbits_test(primes, i>>1)) printf(" %" PRIuMAX "", i);
+ if (cbits_test(&primes, i>>1)) printf(" %" PRIuMAX "", i);
puts("");
}
}
diff --git a/include/stc/cbits.h b/include/stc/cbits.h
index 3dc78b7d..9eb52cf6 100644
--- a/include/stc/cbits.h
+++ b/include/stc/cbits.h
@@ -34,8 +34,8 @@ int main() {
cbits_reset(&bset, 9);
cbits_resize(&bset, 43, false);
- printf("%4zu: ", cbits_size(bset));
- c_forrange (i, cbits_size(bset))
+ printf("%4zu: ", cbits_size(&bset));
+ c_forrange (i, cbits_size(&bset))
printf("%d", cbits_at(&bset, i));
puts("");
cbits_set(&bset, 28);
@@ -44,8 +44,8 @@ int main() {
cbits_resize(&bset, 102, true);
cbits_set_value(&bset, 99, false);
- printf("%4zu: ", cbits_size(bset));
- c_forrange (i, cbits_size(bset))
+ printf("%4zu: ", cbits_size(&bset));
+ c_forrange (i, cbits_size(&bset))
printf("%d", cbits_at(&bset, i));
puts("");
}
@@ -73,7 +73,7 @@ int main() {
#if !defined i_len
STC_API void cbits_resize(i_type* self, size_t size, bool value);
-STC_API i_type* cbits_copy(i_type* self, i_type other);
+STC_API i_type* cbits_copy(i_type* self, const i_type* other);
#endif
STC_API bool _cbits_subset_of(const uint64_t* set, const uint64_t* other, size_t sz);
STC_API bool _cbits_disjoint(const uint64_t* set, const uint64_t* other, size_t sz);
@@ -81,13 +81,13 @@ STC_API size_t _cbits_count(const uint64_t* set, const size_t sz);
STC_API char* _cbits_to_str(const uint64_t* set, const size_t sz,
char* out, size_t start, intptr_t stop);
-STC_INLINE size_t _i_memb(_size)(i_type set);
+STC_INLINE size_t _i_memb(_size)(const i_type* self);
STC_INLINE void _i_memb(_set_all)(i_type *self, const bool value)
- { memset(self->data64, value? ~0 : 0, _cbits_bytes(_i_memb(_size)(*self))); }
+ { memset(self->data64, value? ~0 : 0, _cbits_bytes(_i_memb(_size)(self))); }
STC_INLINE void _i_memb(_set_pattern)(i_type *self, const uint64_t pattern) {
- size_t n = _cbits_words(_i_memb(_size)(*self));
+ size_t n = _cbits_words(_i_memb(_size)(self));
while (n--) self->data64[n] = pattern;
}
@@ -96,7 +96,7 @@ STC_INLINE void _i_memb(_set_pattern)(i_type *self, const uint64_t pattern) {
#define _i_assert(x) (void)0
STC_INLINE i_type _i_memb(_init)(void) { return c_make(i_type){0}; }
STC_INLINE void _i_memb(_drop)(i_type* self) {}
-STC_INLINE size_t _i_memb(_size)(i_type set) { return i_len; }
+STC_INLINE size_t _i_memb(_size)(const i_type* self) { return i_len; }
STC_INLINE i_type _i_memb(_move)(i_type* self) { return *self; }
STC_INLINE i_type* _i_memb(_take)(i_type* self, i_type other)
@@ -125,7 +125,7 @@ STC_INLINE i_type _i_memb(_with_pattern)(const size_t size, const uint64_t patte
#define _i_assert(x) assert(x)
STC_INLINE i_type cbits_init(void) { return c_make(i_type){NULL}; }
STC_INLINE void cbits_drop(i_type* self) { c_free(self->data64); }
-STC_INLINE size_t cbits_size(i_type set) { return set._size; }
+STC_INLINE size_t cbits_size(const i_type* self) { return self->_size; }
STC_INLINE i_type cbits_move(i_type* self) {
i_type tmp = *self;
@@ -160,11 +160,11 @@ STC_INLINE i_type cbits_with_pattern(const size_t size, const uint64_t pattern)
}
#endif
-STC_INLINE bool _i_memb(_test)(i_type set, const size_t i)
- { return (set.data64[i>>6] & _cbits_bit(i)) != 0; }
+STC_INLINE bool _i_memb(_test)(const i_type* self, const size_t i)
+ { return (self->data64[i>>6] & _cbits_bit(i)) != 0; }
-STC_INLINE bool _i_memb(_at)(i_type set, const size_t i)
- { return (set.data64[i>>6] & _cbits_bit(i)) != 0; }
+STC_INLINE bool _i_memb(_at)(const i_type* self, const size_t i)
+ { return (self->data64[i>>6] & _cbits_bit(i)) != 0; }
STC_INLINE void _i_memb(_set)(i_type *self, const size_t i)
{ self->data64[i>>6] |= _cbits_bit(i); }
@@ -172,14 +172,15 @@ STC_INLINE void _i_memb(_set)(i_type *self, const size_t i)
STC_INLINE void _i_memb(_reset)(i_type *self, const size_t i)
{ self->data64[i>>6] &= ~_cbits_bit(i); }
-STC_INLINE void _i_memb(_set_value)(i_type *self, const size_t i, const bool value)
- { value ? _i_memb(_set)(self, i) : _i_memb(_reset)(self, i); }
+STC_INLINE void _i_memb(_set_value)(i_type *self, const size_t i, const bool b) {
+ self->data64[i>>6] ^= ((uint64_t)-(int)b ^ self->data64[i>>6]) & _cbits_bit(i);
+}
STC_INLINE void _i_memb(_flip)(i_type *self, const size_t i)
{ self->data64[i>>6] ^= _cbits_bit(i); }
STC_INLINE void _i_memb(_flip_all)(i_type *self) {
- size_t n = _cbits_words(_i_memb(_size)(*self));
+ size_t n = _cbits_words(_i_memb(_size)(self));
while (n--) self->data64[n] ^= ~(uint64_t)0;
}
@@ -191,22 +192,22 @@ STC_INLINE i_type _i_memb(_from)(const char* str) {
}
/* Intersection */
-STC_INLINE void _i_memb(_intersect)(i_type *self, i_type other) {
- _i_assert(self->_size == other._size);
- size_t n = _cbits_words(_i_memb(_size)(*self));
- while (n--) self->data64[n] &= other.data64[n];
+STC_INLINE void _i_memb(_intersect)(i_type *self, const i_type* other) {
+ _i_assert(self->_size == other->_size);
+ size_t n = _cbits_words(_i_memb(_size)(self));
+ while (n--) self->data64[n] &= other->data64[n];
}
/* Union */
-STC_INLINE void _i_memb(_union)(i_type *self, i_type other) {
- _i_assert(self->_size == other._size);
- size_t n = _cbits_words(_i_memb(_size)(*self));
- while (n--) self->data64[n] |= other.data64[n];
+STC_INLINE void _i_memb(_union)(i_type *self, const i_type* other) {
+ _i_assert(self->_size == other->_size);
+ size_t n = _cbits_words(_i_memb(_size)(self));
+ while (n--) self->data64[n] |= other->data64[n];
}
/* Exclusive disjunction */
-STC_INLINE void _i_memb(_xor)(i_type *self, i_type other) {
- _i_assert(self->_size == other._size);
- size_t n = _cbits_words(_i_memb(_size)(*self));
- while (n--) self->data64[n] ^= other.data64[n];
+STC_INLINE void _i_memb(_xor)(i_type *self, const i_type* other) {
+ _i_assert(self->_size == other->_size);
+ size_t n = _cbits_words(_i_memb(_size)(self));
+ while (n--) self->data64[n] ^= other->data64[n];
}
#if defined(__GNUC__) || defined(__clang__)
@@ -223,31 +224,31 @@ STC_INLINE void _i_memb(_xor)(i_type *self, i_type other) {
}
#endif
-STC_INLINE size_t _i_memb(_count)(i_type set)
- { return _cbits_count(set.data64, _i_memb(_size)(set)); }
+STC_INLINE size_t _i_memb(_count)(const i_type* self)
+ { return _cbits_count(self->data64, _i_memb(_size)(self)); }
-STC_INLINE char* _i_memb(_to_str)(i_type set, char* out, size_t start, intptr_t stop)
- { return _cbits_to_str(set.data64, _i_memb(_size)(set), out, start, stop); }
+STC_INLINE char* _i_memb(_to_str)(const i_type* self, char* out, size_t start, intptr_t stop)
+ { return _cbits_to_str(self->data64, _i_memb(_size)(self), out, start, stop); }
-STC_INLINE bool _i_memb(_subset_of)(i_type set, i_type other) {
- _i_assert(set._size == other._size);
- return _cbits_subset_of(set.data64, other.data64, _i_memb(_size)(set));
+STC_INLINE bool _i_memb(_subset_of)(const i_type* self, const i_type* other) {
+ _i_assert(self->_size == other->_size);
+ return _cbits_subset_of(self->data64, other->data64, _i_memb(_size)(self));
}
-STC_INLINE bool _i_memb(_disjoint)(i_type set, i_type other) {
- _i_assert(set._size == other._size);
- return _cbits_disjoint(set.data64, other.data64, _i_memb(_size)(set));
+STC_INLINE bool _i_memb(_disjoint)(const i_type* self, const i_type* other) {
+ _i_assert(self->_size == other->_size);
+ return _cbits_disjoint(self->data64, other->data64, _i_memb(_size)(self));
}
#if defined(i_implement)
#if !defined i_len
-STC_DEF i_type* cbits_copy(i_type* self, i_type other) {
- if (self->data64 == other.data64)
+STC_DEF i_type* cbits_copy(i_type* self, const i_type* other) {
+ if (self->data64 == other->data64)
return self;
- if (self->_size != other._size)
- return _i_memb(_take)(self, _i_memb(_clone)(other));
- memcpy(self->data64, other.data64, _cbits_bytes(other._size));
+ if (self->_size != other->_size)
+ return _i_memb(_take)(self, _i_memb(_clone)(*other));
+ memcpy(self->data64, other->data64, _cbits_bytes(other->_size));
return self;
}
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index ffdd0215..a0fa58fb 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -108,6 +108,7 @@
#define c_no_cmp (1<<3)
#define c_static (1<<4)
#define c_header (1<<5)
+#define c_implement (1<<6)
/* Generic algorithms */
@@ -254,7 +255,7 @@ STC_INLINE char* c_strnstrn(const char *s, const char *needle,
#undef _i_static
#undef i_implement
-#if !c_option(c_static) && (c_option(c_header) || defined(STC_HEADER) || \
+#if !c_option(c_static) && (c_option(c_header|c_implement) || defined(STC_HEADER) || \
defined(STC_IMPLEMENT) || defined(STC_IMPLEMENTATION))
# define STC_API extern
# define STC_DEF
@@ -263,6 +264,7 @@ STC_INLINE char* c_strnstrn(const char *s, const char *needle,
# define STC_API static inline
# define STC_DEF static inline
#endif
-#if defined(_i_static) || defined(STC_IMPLEMENT) || defined(STC_IMPLEMENTATION)
+#if defined(_i_static) || c_option(c_implement) || defined(STC_IMPLEMENT) \
+ || defined(STC_IMPLEMENTATION)
# define i_implement
#endif