summaryrefslogtreecommitdiffhomepage
path: root/include/stc
diff options
context:
space:
mode:
Diffstat (limited to 'include/stc')
-rw-r--r--include/stc/algo/crange.h13
-rw-r--r--include/stc/algo/filter.h16
-rw-r--r--include/stc/algo/sort.h2
-rw-r--r--include/stc/algorithm.h (renamed from include/stc/calgo.h)1
-rw-r--r--include/stc/ccommon.h6
-rw-r--r--include/stc/cdeq.h19
-rw-r--r--include/stc/coroutine.h (renamed from include/stc/algo/coroutine.h)100
-rw-r--r--include/stc/cqueue.h206
-rw-r--r--include/stc/crand.h43
-rw-r--r--include/stc/cspan.h12
-rw-r--r--include/stc/cstr.h34
-rw-r--r--include/stc/priv/cqueue_hdr.h117
-rw-r--r--include/stc/priv/cqueue_imp.h129
-rw-r--r--include/stc/priv/template.h8
-rw-r--r--include/stc/priv/template2.h2
15 files changed, 395 insertions, 313 deletions
diff --git a/include/stc/algo/crange.h b/include/stc/algo/crange.h
index 03162a2d..faeda162 100644
--- a/include/stc/algo/crange.h
+++ b/include/stc/algo/crange.h
@@ -27,14 +27,14 @@
int main(void)
{
- crange r1 = crange_make(80, 90);
+ crange r1 = crange_init(80, 90);
c_foreach (i, crange, r1)
printf(" %lld", *i.ref);
puts("");
// use a temporary crange object.
int a = 100, b = INT32_MAX;
- crange r2 = crange_make(a, b, 8);
+ crange r2 = crange_init(a, b, 8);
c_forfilter (i, crange, r2,
c_flt_skip(i, 10) &&
c_flt_take(i, 3))
@@ -51,11 +51,12 @@ typedef long long crange_value;
typedef struct { crange_value start, end, step, value; } crange;
typedef struct { crange_value *ref, end, step; } crange_iter;
-#define crange_make(...) c_MACRO_OVERLOAD(crange_make, __VA_ARGS__)
-#define crange_make_1(stop) crange_make_3(0, stop, 1)
-#define crange_make_2(start, stop) crange_make_3(start, stop, 1)
+#define crange_make crange_init // [deprecated]
+#define crange_init(...) c_MACRO_OVERLOAD(crange_init, __VA_ARGS__)
+#define crange_init_1(stop) crange_init_3(0, stop, 1)
+#define crange_init_2(start, stop) crange_init_3(start, stop, 1)
-STC_INLINE crange crange_make_3(crange_value start, crange_value stop, crange_value step)
+STC_INLINE crange crange_init_3(crange_value start, crange_value stop, crange_value step)
{ crange r = {start, stop - (step > 0), step}; return r; }
STC_INLINE crange_iter crange_begin(crange* self)
diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h
index 4a227927..1a62c3e1 100644
--- a/include/stc/algo/filter.h
+++ b/include/stc/algo/filter.h
@@ -85,6 +85,21 @@ int main(void)
if (it.ref == _endref) it.ref = NULL; \
} while (0)
+#define c_all_of(boolptr, it, C, cnt, pred) do { \
+ C##_iter it; \
+ c_find_if_4(it, C, cnt, !(pred)); \
+ *(boolptr) = it.ref == NULL; \
+} while (0)
+#define c_any_of(boolptr, it, C, cnt, pred) do { \
+ C##_iter it; \
+ c_find_if_4(it, C, cnt, pred); \
+ *(boolptr) = it.ref != NULL; \
+} while (0)
+#define c_none_of(boolptr, it, C, cnt, pred) do { \
+ C##_iter it; \
+ c_find_if_4(it, C, cnt, pred); \
+ *(boolptr) = it.ref == NULL; \
+} while (0)
// Use with: clist, cmap, cset, csmap, csset:
#define c_erase_if(it, C, cnt, pred) do { \
@@ -95,7 +110,6 @@ int main(void)
} \
} while (0)
-
// Use with: cstack, cvec, cdeq, cqueue:
#define c_eraseremove_if(it, C, cnt, pred) do { \
C* _cnt = &cnt; \
diff --git a/include/stc/algo/sort.h b/include/stc/algo/sort.h
index 06d7395f..86c9b9f1 100644
--- a/include/stc/algo/sort.h
+++ b/include/stc/algo/sort.h
@@ -70,7 +70,7 @@ int main(void) {
#ifndef i_tag
#define i_tag i_key
#endif
- #define i_type c_PASTE(i_tag, array)
+ #define i_type c_PASTE(i_tag, s)
typedef i_key i_type;
#endif
#ifndef i_at
diff --git a/include/stc/calgo.h b/include/stc/algorithm.h
index 63ef97b9..cf3ab328 100644
--- a/include/stc/calgo.h
+++ b/include/stc/algorithm.h
@@ -4,6 +4,5 @@
#include "algo/raii.h"
#include "algo/crange.h"
#include "algo/filter.h"
-#include "algo/coroutine.h"
#endif
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index 1f9ea80d..77f754fa 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -69,7 +69,7 @@ typedef long long _llong;
#define c_new(T, ...) ((T*)memcpy(malloc(sizeof(T)), ((T[]){__VA_ARGS__}), sizeof(T)))
#define c_LITERAL(T) (T)
#endif
-#define c_new_n(T, n) ((T*)malloc(sizeof(T)*(n)))
+#define c_new_n(T, n) ((T*)malloc(sizeof(T)*(size_t)(n)))
#define c_malloc(sz) malloc(c_i2u(sz))
#define c_calloc(n, sz) calloc(c_i2u(n), c_i2u(sz))
#define c_realloc(p, sz) realloc(p, c_i2u(sz))
@@ -191,10 +191,6 @@ STC_INLINE intptr_t cnextpow2(intptr_t n) {
for (C##_iter it = start, *_endref = (C##_iter*)(finish).ref \
; it.ref != (C##_value*)_endref; C##_next(&it))
-#define c_foreach_rv(it, C, cnt) \
- for (C##_iter it = {.ref=C##_end(&cnt).end - 1, .end=(cnt).data - 1} \
- ; it.ref != it.end; --it.ref)
-
#define c_forpair(key, val, C, cnt) /* structured binding */ \
for (struct {C##_iter it; const C##_key* key; C##_mapped* val;} _ = {.it=C##_begin(&cnt)} \
; _.it.ref && (_.key = &_.it.ref->first, _.val = &_.it.ref->second) \
diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h
index 056ef005..9892f6f1 100644
--- a/include/stc/cdeq.h
+++ b/include/stc/cdeq.h
@@ -20,16 +20,19 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+#include "priv/linkage.h"
+
+#ifndef CDEQ_H_INCLUDED
+#include "ccommon.h"
+#include "forward.h"
+#include <stdlib.h>
+#include <string.h>
+#endif // CDEQ_H_INCLUDED
+
#define _i_prefix cdeq_
#define _pop _pop_front
#define _pull _pull_front
-#ifdef i_more
- #include "cqueue.h"
- #define i_more
-#else
- #define i_more
- #include "cqueue.h"
-#endif
+#include "priv/cqueue_hdr.h"
#undef _pop
STC_API _cx_value* _cx_MEMB(_push_front)(_cx_Self* self, i_key value);
@@ -122,6 +125,8 @@ _cx_MEMB(_get_mut)(_cx_Self* self, _cx_raw raw)
/* -------------------------- IMPLEMENTATION ------------------------- */
#if defined(i_implement) || defined(i_static)
+#include "priv/cqueue_imp.h"
+
STC_DEF _cx_value*
_cx_MEMB(_push_front)(_cx_Self* self, i_key value) {
intptr_t start = (self->start - 1) & self->capmask;
diff --git a/include/stc/algo/coroutine.h b/include/stc/coroutine.h
index 3a5382f3..42905744 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/coroutine.h
@@ -24,7 +24,7 @@
#define STC_COROUTINE_INCLUDED
/*
#include <stdio.h>
-#include <stc/algo/coroutine.h>
+#include <stc/coroutine.h>
struct iterpair {
int max_x, max_y;
@@ -56,7 +56,7 @@ int main(void) {
return 0;
}
*/
-#include "../ccommon.h"
+#include "ccommon.h"
enum {
CCO_STATE_CLEANUP = -1,
@@ -64,9 +64,8 @@ enum {
};
typedef enum {
CCO_DONE = 0,
- CCO_YIELD = 1,
- CCO_AWAIT = 2,
- CCO_ERROR = -1,
+ CCO_AWAIT = 1<<0,
+ CCO_YIELD = 1<<1,
} cco_result;
#define cco_initial(co) ((co)->cco_state == 0)
@@ -74,7 +73,7 @@ typedef enum {
#define cco_done(co) ((co)->cco_state == CCO_STATE_DONE)
#define cco_routine(co) \
- for (int *_state = &(co)->cco_state; *_state != CCO_STATE_DONE; *_state = CCO_STATE_DONE) \
+ for (int* _state = &(co)->cco_state; *_state != CCO_STATE_DONE; *_state = CCO_STATE_DONE) \
_resume: switch (*_state) case 0: // thanks, @liigo!
#define cco_yield() cco_yield_v(CCO_YIELD)
@@ -84,26 +83,27 @@ typedef enum {
case __LINE__:; \
} while (0)
-#define cco_await(promise) cco_await_v_2(promise, CCO_AWAIT)
-#define cco_await_v(...) c_MACRO_OVERLOAD(cco_await_v, __VA_ARGS__)
-#define cco_await_v_1(promise) cco_await_v_2(promise, )
-#define cco_await_v_2(promise, ret) \
+#define cco_await(promise) cco_await_and_return(promise, CCO_AWAIT)
+#define cco_await_v(promise) cco_await_and_return(promise, )
+#define cco_await_and_return(promise, ret) \
do { \
*_state = __LINE__; \
case __LINE__: if (!(promise)) {return ret; goto _resume;} \
} while (0)
-/* cco_await_on(): assumes coroutine returns a cco_result value (int) */
-#define cco_await_on(corocall) \
+/* cco_call_await(): assumes coroutine returns a cco_result value (int) */
+#define cco_call_await(...) c_MACRO_OVERLOAD(cco_call_await, __VA_ARGS__)
+#define cco_call_await_1(corocall) cco_call_await_2(corocall, CCO_DONE)
+#define cco_call_await_2(corocall, resultbits) \
do { \
*_state = __LINE__; \
- case __LINE__: { int _r = corocall; if (_r != CCO_DONE) {return _r; goto _resume;} } \
+ case __LINE__: { int _r = corocall; if (!(_r & ~(resultbits))) {return _r; goto _resume;} } \
} while (0)
-/* cco_block_on(): assumes coroutine returns a cco_result value (int) */
-#define cco_block_on(...) c_MACRO_OVERLOAD(cco_block_on, __VA_ARGS__)
-#define cco_block_on_1(corocall) while ((corocall) != CCO_DONE)
-#define cco_block_on_2(corocall, result) while ((*(result) = (corocall)) != CCO_DONE)
+/* cco_call_blocking(): assumes coroutine returns a cco_result value (int) */
+#define cco_call_blocking(...) c_MACRO_OVERLOAD(cco_call_blocking, __VA_ARGS__)
+#define cco_call_blocking_1(corocall) while ((corocall) != CCO_DONE)
+#define cco_call_blocking_2(corocall, result) while ((*(result) = (corocall)) != CCO_DONE)
#define cco_cleanup \
*_state = CCO_STATE_CLEANUP; case CCO_STATE_CLEANUP
@@ -132,26 +132,44 @@ typedef enum {
(void)((co)->cco_state = 0)
/*
- * Closure (optional)
+ * Tasks (optional)
*/
-#define cco_closure(Name, ...) \
+struct cco_runtime;
+
+#define cco_task_struct(Name, ...) \
struct Name { \
- int (*cco_fn)(struct Name*); \
- int cco_state; \
+ int (*cco_func)(struct Name*, struct cco_runtime*); \
+ int cco_state, cco_expect; \
__VA_ARGS__ \
}
-typedef struct cco_base {
- int (*cco_fn)(struct cco_base*);
- int cco_state;
-} cco_base;
+typedef cco_task_struct(cco_task, /**/) cco_task;
+
+typedef struct cco_runtime {
+ int result, top; cco_task* stack[];
+} cco_runtime;
+
+#define cco_cast_task(task) \
+ ((cco_task *)(task) + 0*sizeof((task)->cco_func(task, (cco_runtime*)0) + ((int*)0 == &(task)->cco_state)))
+
+#define cco_task_resume(task, rt) \
+ (task)->cco_func(task, rt)
-#define cco_resume(closure) \
- (closure)->cco_fn(closure)
+#define cco_task_await(...) c_MACRO_OVERLOAD(cco_task_await, __VA_ARGS__)
+#define cco_task_await_2(task, rt) cco_task_await_3(task, rt, CCO_DONE)
+#define cco_task_await_3(task, rt, resultbits) \
+ do { \
+ cco_runtime* _rt = rt; \
+ (_rt->stack[++_rt->top] = cco_cast_task(task))->cco_expect = (resultbits); \
+ cco_yield_v(CCO_AWAIT); \
+ } while (0)
-#define cco_cast(closure) \
- ((cco_base *)(closure) + 0*sizeof((cco_resume(closure), (int*)0 == &(closure)->cco_state)))
+#define cco_task_blocking(...) c_MACRO_OVERLOAD(cco_task_blocking, __VA_ARGS__)
+#define cco_task_blocking_1(task) cco_task_blocking_3(task, _rt, 16)
+#define cco_task_blocking_3(task, rt, STACKDEPTH) \
+ for (struct { int result, top; cco_task* stack[STACKDEPTH]; } rt = {.stack={cco_cast_task(task)}}; \
+ (((rt.result = cco_task_resume(rt.stack[rt.top], (cco_runtime*)&rt)) & ~rt.stack[rt.top]->cco_expect) || --rt.top >= 0); )
/*
* Semaphore
@@ -159,12 +177,11 @@ typedef struct cco_base {
typedef struct { intptr_t count; } cco_sem;
-#define cco_sem_await(sem) cco_sem_await_v_2(sem, CCO_AWAIT)
-#define cco_sem_await_v(...) c_MACRO_OVERLOAD(cco_sem_await_v, __VA_ARGS__)
-#define cco_sem_await_v_1(sem) cco_sem_await_v_2(sem, )
-#define cco_sem_await_v_2(sem, ret) \
+#define cco_sem_await(sem) cco_sem_await_and_return(sem, CCO_AWAIT)
+#define cco_sem_await_v(sem) cco_sem_await_and_return(sem, )
+#define cco_sem_await_and_return(sem, ret) \
do { \
- cco_await_v_2((sem)->count > 0, ret); \
+ cco_await_and_return((sem)->count > 0, ret); \
--(sem)->count; \
} while (0)
@@ -178,17 +195,22 @@ typedef struct { intptr_t count; } cco_sem;
#ifdef _WIN32
#ifdef __cplusplus
- #define _c_LINKC extern "C" __declspec(dllimport)
+ #define _c_LINKC extern "C" __declspec(dllimport)
+ #else
+ #define _c_LINKC __declspec(dllimport)
+ #endif
+ #if 1 // _WIN32_WINNT < _WIN32_WINNT_WIN8 || defined __TINYC__
+ #define _c_getsystime GetSystemTimeAsFileTime
#else
- #define _c_LINKC __declspec(dllimport)
+ #define _c_getsystime GetSystemTimePreciseAsFileTime
#endif
struct _FILETIME;
- _c_LINKC void GetSystemTimePreciseAsFileTime(struct _FILETIME*);
+ _c_LINKC void _c_getsystime(struct _FILETIME*);
_c_LINKC void Sleep(unsigned long);
static inline double cco_time(void) { /* seconds since epoch */
unsigned long long quad; /* 64-bit value representing 1/10th usecs since Jan 1 1601, 00:00 UTC */
- GetSystemTimePreciseAsFileTime((struct _FILETIME*)&quad);
+ _c_getsystime((struct _FILETIME*)&quad);
return (double)(quad - 116444736000000000ULL)*1e-7; /* time diff Jan 1 1601-Jan 1 1970 in 1/10th usecs */
}
@@ -219,7 +241,7 @@ typedef struct { double interval, start; } cco_timer;
#define cco_timer_await_v_3(tm, sec, ret) \
do { \
cco_timer_start(tm, sec); \
- cco_await_v_2(cco_timer_expired(tm), ret); \
+ cco_await_and_return(cco_timer_expired(tm), ret); \
} while (0)
static inline void cco_timer_start(cco_timer* tm, double sec) {
diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h
index 5d38ca89..8a609b96 100644
--- a/include/stc/cqueue.h
+++ b/include/stc/cqueue.h
@@ -32,211 +32,11 @@
#ifndef _i_prefix
#define _i_prefix cqueue_
#endif
-#include "priv/template.h"
-
-#ifndef i_is_forward
-_cx_DEFTYPES(_c_cdeq_types, _cx_Self, i_key);
-#endif
-typedef i_keyraw _cx_raw;
-
-STC_API _cx_Self _cx_MEMB(_with_capacity)(const intptr_t n);
-STC_API bool _cx_MEMB(_reserve)(_cx_Self* self, const intptr_t n);
-STC_API void _cx_MEMB(_clear)(_cx_Self* self);
-STC_API void _cx_MEMB(_drop)(_cx_Self* self);
-STC_API _cx_value* _cx_MEMB(_push)(_cx_Self* self, i_key value); // push_back
-STC_API void _cx_MEMB(_shrink_to_fit)(_cx_Self *self);
-STC_API _cx_iter _cx_MEMB(_advance)(_cx_iter it, intptr_t n);
-
-#define _cdeq_toidx(self, pos) (((pos) - (self)->start) & (self)->capmask)
-#define _cdeq_topos(self, idx) (((self)->start + (idx)) & (self)->capmask)
-
-STC_INLINE _cx_Self _cx_MEMB(_init)(void)
- { _cx_Self cx = {0}; return cx; }
-STC_INLINE void _cx_MEMB(_put_n)(_cx_Self* self, const _cx_raw* raw, intptr_t n)
- { while (n--) _cx_MEMB(_push)(self, i_keyfrom(*raw++)); }
-STC_INLINE _cx_Self _cx_MEMB(_from_n)(const _cx_raw* raw, intptr_t n)
- { _cx_Self cx = {0}; _cx_MEMB(_put_n)(&cx, raw, n); return cx; }
-STC_INLINE void _cx_MEMB(_value_drop)(_cx_value* val) { i_keydrop(val); }
-
-#if !defined i_no_emplace
-STC_INLINE _cx_value* _cx_MEMB(_emplace)(_cx_Self* self, _cx_raw raw)
- { return _cx_MEMB(_push)(self, i_keyfrom(raw)); }
-#endif
-
-#if defined _i_has_eq || defined _i_has_cmp
-STC_API bool _cx_MEMB(_eq)(const _cx_Self* self, const _cx_Self* other);
-#endif
-
-#if !defined i_no_clone
-STC_API _cx_Self _cx_MEMB(_clone)(_cx_Self cx);
-STC_INLINE i_key _cx_MEMB(_value_clone)(i_key val)
- { return i_keyclone(val); }
-#endif // !i_no_clone
-STC_INLINE intptr_t _cx_MEMB(_size)(const _cx_Self* self)
- { return _cdeq_toidx(self, self->end); }
-STC_INLINE intptr_t _cx_MEMB(_capacity)(const _cx_Self* self)
- { return self->capmask; }
-STC_INLINE bool _cx_MEMB(_empty)(const _cx_Self* self)
- { return self->start == self->end; }
-STC_INLINE _cx_raw _cx_MEMB(_value_toraw)(const _cx_value* pval)
- { return i_keyto(pval); }
-
-STC_INLINE _cx_value* _cx_MEMB(_front)(const _cx_Self* self)
- { return self->data + self->start; }
-
-STC_INLINE _cx_value* _cx_MEMB(_back)(const _cx_Self* self)
- { return self->data + ((self->end - 1) & self->capmask); }
-
-STC_INLINE void _cx_MEMB(_pop)(_cx_Self* self) { // pop_front
- c_assert(!_cx_MEMB(_empty)(self));
- i_keydrop((self->data + self->start));
- self->start = (self->start + 1) & self->capmask;
-}
-
-STC_INLINE _cx_value _cx_MEMB(_pull)(_cx_Self* self) { // move front out of queue
- c_assert(!_cx_MEMB(_empty)(self));
- intptr_t s = self->start;
- self->start = (s + 1) & self->capmask;
- return self->data[s];
-}
-
-STC_INLINE void _cx_MEMB(_copy)(_cx_Self* self, const _cx_Self* other) {
- if (self->data == other->data) return;
- _cx_MEMB(_drop)(self);
- *self = _cx_MEMB(_clone)(*other);
-}
-
-STC_INLINE _cx_iter _cx_MEMB(_begin)(const _cx_Self* self) {
- return c_LITERAL(_cx_iter){
- _cx_MEMB(_empty)(self) ? NULL : self->data + self->start,
- self->start, self
- };
-}
-
-STC_INLINE _cx_iter _cx_MEMB(_end)(const _cx_Self* self)
- { return c_LITERAL(_cx_iter){.pos=self->end, ._s=self}; }
-
-STC_INLINE void _cx_MEMB(_next)(_cx_iter* it) {
- if (it->pos != it->_s->capmask) { ++it->ref; ++it->pos; }
- else { it->ref -= it->pos; it->pos = 0; }
- if (it->pos == it->_s->end) it->ref = NULL;
-}
-
-STC_INLINE intptr_t _cx_MEMB(_index)(const _cx_Self* self, _cx_iter it)
- { return _cdeq_toidx(self, it.pos); }
-
-STC_INLINE void _cx_MEMB(_adjust_end_)(_cx_Self* self, intptr_t n)
- { self->end = (self->end + n) & self->capmask; }
+#include "priv/cqueue_hdr.h"
/* -------------------------- IMPLEMENTATION ------------------------- */
#if defined(i_implement) || defined(i_static)
-
-STC_DEF _cx_iter _cx_MEMB(_advance)(_cx_iter it, intptr_t n) {
- intptr_t len = _cx_MEMB(_size)(it._s);
- intptr_t pos = it.pos, idx = _cdeq_toidx(it._s, pos);
- it.pos = (pos + n) & it._s->capmask;
- it.ref += it.pos - pos;
- if (!c_LTu(idx + n, len)) it.ref = NULL;
- return it;
-}
-
-STC_DEF void
-_cx_MEMB(_clear)(_cx_Self* self) {
- c_foreach (i, _cx_Self, *self)
- { i_keydrop(i.ref); }
- self->start = 0, self->end = 0;
-}
-
-STC_DEF void
-_cx_MEMB(_drop)(_cx_Self* self) {
- _cx_MEMB(_clear)(self);
- i_free(self->data);
-}
-
-STC_DEF _cx_Self
-_cx_MEMB(_with_capacity)(const intptr_t n) {
- _cx_Self cx = {0};
- _cx_MEMB(_reserve)(&cx, n);
- return cx;
-}
-
-STC_DEF bool
-_cx_MEMB(_reserve)(_cx_Self* self, const intptr_t n) {
- if (n <= self->capmask)
- return true;
- intptr_t oldcap = self->capmask + 1, newcap = cnextpow2(n + 1);
- _cx_value* d = (_cx_value *)i_realloc(self->data, newcap*c_sizeof *self->data);
- if (!d)
- return false;
- intptr_t head = oldcap - self->start;
- if (self->start <= self->end)
- ;
- else if (head < self->end) {
- self->start = newcap - head;
- c_memmove(d + self->start, d + oldcap - head, head*c_sizeof *d);
- } else {
- c_memmove(d + oldcap, d, self->end*c_sizeof *d);
- self->end += oldcap;
- }
- self->capmask = newcap - 1;
- self->data = d;
- return true;
-}
-
-STC_DEF _cx_value*
-_cx_MEMB(_push)(_cx_Self* self, i_key value) { // push_back
- intptr_t end = (self->end + 1) & self->capmask;
- if (end == self->start) { // full
- _cx_MEMB(_reserve)(self, self->capmask + 3); // => 2x expand
- end = (self->end + 1) & self->capmask;
- }
- _cx_value *v = self->data + self->end;
- self->end = end;
- *v = value;
- return v;
-}
-
-STC_DEF void
-_cx_MEMB(_shrink_to_fit)(_cx_Self *self) {
- intptr_t sz = _cx_MEMB(_size)(self), j = 0;
- if (sz > self->capmask/2)
- return;
- _cx_Self out = _cx_MEMB(_with_capacity)(sz);
- if (!out.data)
- return;
- c_foreach (i, _cx_Self, *self)
- out.data[j++] = *i.ref;
- out.end = sz;
- i_free(self->data);
- *self = out;
-}
-
-#if !defined i_no_clone
-STC_DEF _cx_Self
-_cx_MEMB(_clone)(_cx_Self cx) {
- intptr_t sz = _cx_MEMB(_size)(&cx), j = 0;
- _cx_Self out = _cx_MEMB(_with_capacity)(sz);
- if (out.data)
- c_foreach (i, _cx_Self, cx)
- out.data[j++] = i_keyclone((*i.ref));
- out.end = sz;
- return out;
-}
-#endif // i_no_clone
-
-#if defined _i_has_eq || defined _i_has_cmp
-STC_DEF bool
-_cx_MEMB(_eq)(const _cx_Self* self, const _cx_Self* other) {
- if (_cx_MEMB(_size)(self) != _cx_MEMB(_size)(other)) return false;
- for (_cx_iter i = _cx_MEMB(_begin)(self), j = _cx_MEMB(_begin)(other);
- i.ref; _cx_MEMB(_next)(&i), _cx_MEMB(_next)(&j))
- {
- const _cx_raw _rx = i_keyto(i.ref), _ry = i_keyto(j.ref);
- if (!(i_eq((&_rx), (&_ry)))) return false;
- }
- return true;
-}
-#endif
+#include "priv/cqueue_imp.h"
#endif // IMPLEMENTATION
-#include "priv/template2.h"
#define CQUEUE_H_INCLUDED
+#include "priv/template2.h"
diff --git a/include/stc/crand.h b/include/stc/crand.h
index 0a6aa9e0..32722762 100644
--- a/include/stc/crand.h
+++ b/include/stc/crand.h
@@ -32,20 +32,20 @@
int main(void) {
uint64_t seed = 123456789;
crand_t rng = crand_init(seed);
- crand_unif_t dist1 = crand_unif_init(1, 6);
- crand_norm_t dist3 = crand_norm_init(1.0, 10.0);
+ crand_uniform_t dist1 = crand_uniform_init(1, 6);
+ crand_normal_t dist3 = crand_normal_init(1.0, 10.0);
uint64_t i = crand_u64(&rng);
- int64_t iu = crand_unif(&rng, &dist1);
- double xn = crand_norm(&rng, &dist3);
+ int64_t iu = crand_uniform(&rng, &dist1);
+ double xn = crand_normal(&rng, &dist3);
}
*/
#include <string.h>
#include <math.h>
typedef struct crand { uint64_t state[5]; } crand_t;
-typedef struct crand_unif { int64_t lower; uint64_t range, threshold; } crand_unif_t;
-typedef struct crand_norm { double mean, stddev, next; int has_next; } crand_norm_t;
+typedef struct crand_uniform { int64_t lower; uint64_t range, threshold; } crand_uniform_t;
+typedef struct crand_normal { double mean, stddev, next; int has_next; } crand_normal_t;
/* PRNG crand_t.
* Very fast PRNG suited for parallel usage with Weyl-sequence parameter.
@@ -67,14 +67,14 @@ STC_API double crandf(void);
STC_API crand_t crand_init(uint64_t seed);
/* Unbiased bounded uniform distribution. range [low, high] */
-STC_API crand_unif_t crand_unif_init(int64_t low, int64_t high);
-STC_API int64_t crand_unif(crand_t* rng, crand_unif_t* dist);
+STC_API crand_uniform_t crand_uniform_init(int64_t low, int64_t high);
+STC_API int64_t crand_uniform(crand_t* rng, crand_uniform_t* dist);
/* Normal/gaussian distribution. */
-STC_INLINE crand_norm_t crand_norm_init(double mean, double stddev)
- { crand_norm_t r = {mean, stddev, 0.0, 0}; return r; }
+STC_INLINE crand_normal_t crand_normal_init(double mean, double stddev)
+ { crand_normal_t r = {mean, stddev, 0.0, 0}; return r; }
-STC_API double crand_norm(crand_t* rng, crand_norm_t* dist);
+STC_API double crand_normal(crand_t* rng, crand_normal_t* dist);
/* Main crand_t prng */
STC_INLINE uint64_t crand_u64(crand_t* rng) {
@@ -95,11 +95,10 @@ STC_INLINE double crand_f64(crand_t* rng) {
/* -------------------------- IMPLEMENTATION ------------------------- */
#if defined(i_implement) || defined(i_static)
-/* Global random() */
-static crand_t crand_global = {{
- 0x26aa069ea2fb1a4d, 0x70c72c95cd592d04,
- 0x504f333d3aa0b359, 0x9e3779b97f4a7c15,
- 0x6a09e667a754166b
+/* Global random seed */
+static crand_t crand_global = {{ // csrand(0)
+ 0x9e3779b97f4a7c15, 0x6f68261b57e7a770,
+ 0xe220a838bf5c9dde, 0x7c17d1800457b1ba, 0x1,
}};
STC_DEF void csrand(uint64_t seed)
@@ -116,20 +115,20 @@ STC_DEF crand_t crand_init(uint64_t seed) {
s[0] = seed + 0x9e3779b97f4a7c15;
s[1] = (s[0] ^ (s[0] >> 30))*0xbf58476d1ce4e5b9;
s[2] = (s[1] ^ (s[1] >> 27))*0x94d049bb133111eb;
- s[3] = (s[2] ^ (s[2] >> 31));
- s[4] = ((seed + 0x6aa069ea2fb1a4d) << 1) | 1;
+ s[3] = s[0] ^ s[2] ^ (s[2] >> 31);
+ s[4] = (seed << 1) | 1;
return rng;
}
/* Init unbiased uniform uint RNG with bounds [low, high] */
-STC_DEF crand_unif_t crand_unif_init(int64_t low, int64_t high) {
- crand_unif_t dist = {low, (uint64_t) (high - low + 1)};
+STC_DEF crand_uniform_t crand_uniform_init(int64_t low, int64_t high) {
+ crand_uniform_t dist = {low, (uint64_t) (high - low + 1)};
dist.threshold = (uint64_t)(0 - dist.range) % dist.range;
return dist;
}
/* Int64 uniform distributed RNG, range [low, high]. */
-STC_DEF int64_t crand_unif(crand_t* rng, crand_unif_t* d) {
+STC_DEF int64_t crand_uniform(crand_t* rng, crand_uniform_t* d) {
uint64_t lo, hi;
#ifdef c_umul128
do { c_umul128(crand_u64(rng), d->range, &lo, &hi); } while (lo < d->threshold);
@@ -140,7 +139,7 @@ STC_DEF int64_t crand_unif(crand_t* rng, crand_unif_t* d) {
}
/* Normal distribution PRNG. Marsaglia polar method */
-STC_DEF double crand_norm(crand_t* rng, crand_norm_t* dist) {
+STC_DEF double crand_normal(crand_t* rng, crand_normal_t* dist) {
double u1, u2, s, m;
if (dist->has_next++ & 1)
return dist->next*dist->stddev + dist->mean;
diff --git a/include/stc/cspan.h b/include/stc/cspan.h
index dcb02961..08045010 100644
--- a/include/stc/cspan.h
+++ b/include/stc/cspan.h
@@ -80,19 +80,19 @@ int demo2() {
STC_INLINE Self Self##_from_n(Self##_raw* raw, const intptr_t n) { \
return (Self){.data=raw, .shape={(int32_t)n}}; \
} \
- STC_INLINE Self Self##_slice_(Self##_value* v, const int32_t shape[], const int32_t stri[], \
+ STC_INLINE Self Self##_slice_(Self##_value* d, const int32_t shape[], const int32_t stri[], \
const int rank, const int32_t a[][2]) { \
- Self s; s.data = v; int outrank; \
- s.data += _cspan_slice(s.shape, s.stride.d, &outrank, shape, stri, rank, a); \
+ Self s; int outrank; \
+ s.data = d + _cspan_slice(s.shape, s.stride.d, &outrank, shape, stri, rank, a); \
c_assert(outrank == RANK); \
return s; \
} \
STC_INLINE Self##_iter Self##_begin(const Self* self) { \
- Self##_iter it = {.ref=self->data, .pos={0}, ._s=self}; \
+ Self##_iter it = {.ref=self->data, ._s=self}; \
return it; \
} \
STC_INLINE Self##_iter Self##_end(const Self* self) { \
- Self##_iter it = {.ref=NULL}; \
+ Self##_iter it = {0}; \
return it; \
} \
STC_INLINE void Self##_next(Self##_iter* it) { \
@@ -120,7 +120,7 @@ using_cspan_tuple(7); using_cspan_tuple(8);
#define cspan_init(SpanType, ...) \
{.data=(SpanType##_value[])__VA_ARGS__, .shape={sizeof((SpanType##_value[])__VA_ARGS__)/sizeof(SpanType##_value)}, .stride={.d={1}}}
-/* create a cspan from a cvec, cstack, cdeq, cqueue, or cpque (heap) */
+/* create a cspan from a cvec, cstack, or cpque (heap) */
#define cspan_from(container) \
{.data=(container)->data, .shape={(int32_t)(container)->_len}, .stride={.d={1}}}
diff --git a/include/stc/cstr.h b/include/stc/cstr.h
index 17943ad5..2648e267 100644
--- a/include/stc/cstr.h
+++ b/include/stc/cstr.h
@@ -170,14 +170,14 @@ STC_INLINE intptr_t cstr_capacity(const cstr* self)
// utf8 methods defined in/depending on src/utf8code.c:
-STC_API cstr cstr_casefold_sv(csview sv);
-STC_API cstr cstr_tolower_sv(csview sv);
-STC_API cstr cstr_toupper_sv(csview sv);
-STC_API cstr cstr_tolower(const char* str);
-STC_API cstr cstr_toupper(const char* str);
-STC_API void cstr_lowercase(cstr* self);
-STC_API void cstr_uppercase(cstr* self);
-STC_API bool cstr_valid_utf8(const cstr* self);
+extern cstr cstr_casefold_sv(csview sv);
+extern cstr cstr_tolower_sv(csview sv);
+extern cstr cstr_toupper_sv(csview sv);
+extern cstr cstr_tolower(const char* str);
+extern cstr cstr_toupper(const char* str);
+extern void cstr_lowercase(cstr* self);
+extern void cstr_uppercase(cstr* self);
+extern bool cstr_valid_utf8(const cstr* self);
// other utf8
@@ -394,7 +394,7 @@ fn_tocase[] = {{tolower, utf8_casefold},
{tolower, utf8_tolower},
{toupper, utf8_toupper}};
-STC_DEF cstr cstr_tocase(csview sv, int k) {
+static cstr cstr_tocase(csview sv, int k) {
cstr out = cstr_init();
char *buf = cstr_reserve(&out, sv.size*3/2);
const char *end = sv.str + sv.size;
@@ -415,28 +415,28 @@ STC_DEF cstr cstr_tocase(csview sv, int k) {
return out;
}
-STC_DEF cstr cstr_casefold_sv(csview sv)
+cstr cstr_casefold_sv(csview sv)
{ return cstr_tocase(sv, 0); }
-STC_DEF cstr cstr_tolower_sv(csview sv)
+cstr cstr_tolower_sv(csview sv)
{ return cstr_tocase(sv, 1); }
-STC_DEF cstr cstr_toupper_sv(csview sv)
+cstr cstr_toupper_sv(csview sv)
{ return cstr_tocase(sv, 2); }
-STC_DEF cstr cstr_tolower(const char* str)
+cstr cstr_tolower(const char* str)
{ return cstr_tolower_sv(c_sv(str, c_strlen(str))); }
-STC_DEF cstr cstr_toupper(const char* str)
+cstr cstr_toupper(const char* str)
{ return cstr_toupper_sv(c_sv(str, c_strlen(str))); }
-STC_DEF void cstr_lowercase(cstr* self)
+void cstr_lowercase(cstr* self)
{ cstr_take(self, cstr_tolower_sv(cstr_sv(self))); }
-STC_DEF void cstr_uppercase(cstr* self)
+void cstr_uppercase(cstr* self)
{ cstr_take(self, cstr_toupper_sv(cstr_sv(self))); }
-STC_DEF bool cstr_valid_utf8(const cstr* self)
+bool cstr_valid_utf8(const cstr* self)
{ return utf8_valid(cstr_str(self)); }
#endif // i_import
diff --git a/include/stc/priv/cqueue_hdr.h b/include/stc/priv/cqueue_hdr.h
new file mode 100644
index 00000000..90539f36
--- /dev/null
+++ b/include/stc/priv/cqueue_hdr.h
@@ -0,0 +1,117 @@
+/* MIT License
+ *
+ * Copyright (c) 2023 Tyge Løvset
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "template.h"
+#ifndef i_is_forward
+_cx_DEFTYPES(_c_cdeq_types, _cx_Self, i_key);
+#endif
+typedef i_keyraw _cx_raw;
+
+STC_API _cx_Self _cx_MEMB(_with_capacity)(const intptr_t n);
+STC_API bool _cx_MEMB(_reserve)(_cx_Self* self, const intptr_t n);
+STC_API void _cx_MEMB(_clear)(_cx_Self* self);
+STC_API void _cx_MEMB(_drop)(_cx_Self* self);
+STC_API _cx_value* _cx_MEMB(_push)(_cx_Self* self, i_key value); // push_back
+STC_API void _cx_MEMB(_shrink_to_fit)(_cx_Self *self);
+STC_API _cx_iter _cx_MEMB(_advance)(_cx_iter it, intptr_t n);
+
+#define _cdeq_toidx(self, pos) (((pos) - (self)->start) & (self)->capmask)
+#define _cdeq_topos(self, idx) (((self)->start + (idx)) & (self)->capmask)
+
+STC_INLINE _cx_Self _cx_MEMB(_init)(void)
+ { _cx_Self cx = {0}; return cx; }
+STC_INLINE void _cx_MEMB(_put_n)(_cx_Self* self, const _cx_raw* raw, intptr_t n)
+ { while (n--) _cx_MEMB(_push)(self, i_keyfrom(*raw++)); }
+STC_INLINE _cx_Self _cx_MEMB(_from_n)(const _cx_raw* raw, intptr_t n)
+ { _cx_Self cx = {0}; _cx_MEMB(_put_n)(&cx, raw, n); return cx; }
+STC_INLINE void _cx_MEMB(_value_drop)(_cx_value* val) { i_keydrop(val); }
+
+#if !defined i_no_emplace
+STC_INLINE _cx_value* _cx_MEMB(_emplace)(_cx_Self* self, _cx_raw raw)
+ { return _cx_MEMB(_push)(self, i_keyfrom(raw)); }
+#endif
+
+#if defined _i_has_eq || defined _i_has_cmp
+STC_API bool _cx_MEMB(_eq)(const _cx_Self* self, const _cx_Self* other);
+#endif
+
+#if !defined i_no_clone
+STC_API _cx_Self _cx_MEMB(_clone)(_cx_Self cx);
+STC_INLINE i_key _cx_MEMB(_value_clone)(i_key val)
+ { return i_keyclone(val); }
+#endif // !i_no_clone
+STC_INLINE intptr_t _cx_MEMB(_size)(const _cx_Self* self)
+ { return _cdeq_toidx(self, self->end); }
+STC_INLINE intptr_t _cx_MEMB(_capacity)(const _cx_Self* self)
+ { return self->capmask; }
+STC_INLINE bool _cx_MEMB(_empty)(const _cx_Self* self)
+ { return self->start == self->end; }
+STC_INLINE _cx_raw _cx_MEMB(_value_toraw)(const _cx_value* pval)
+ { return i_keyto(pval); }
+
+STC_INLINE _cx_value* _cx_MEMB(_front)(const _cx_Self* self)
+ { return self->data + self->start; }
+
+STC_INLINE _cx_value* _cx_MEMB(_back)(const _cx_Self* self)
+ { return self->data + ((self->end - 1) & self->capmask); }
+
+STC_INLINE void _cx_MEMB(_pop)(_cx_Self* self) { // pop_front
+ c_assert(!_cx_MEMB(_empty)(self));
+ i_keydrop((self->data + self->start));
+ self->start = (self->start + 1) & self->capmask;
+}
+
+STC_INLINE _cx_value _cx_MEMB(_pull)(_cx_Self* self) { // move front out of queue
+ c_assert(!_cx_MEMB(_empty)(self));
+ intptr_t s = self->start;
+ self->start = (s + 1) & self->capmask;
+ return self->data[s];
+}
+
+STC_INLINE void _cx_MEMB(_copy)(_cx_Self* self, const _cx_Self* other) {
+ if (self->data == other->data) return;
+ _cx_MEMB(_drop)(self);
+ *self = _cx_MEMB(_clone)(*other);
+}
+
+STC_INLINE _cx_iter _cx_MEMB(_begin)(const _cx_Self* self) {
+ return c_LITERAL(_cx_iter){
+ _cx_MEMB(_empty)(self) ? NULL : self->data + self->start,
+ self->start, self
+ };
+}
+
+STC_INLINE _cx_iter _cx_MEMB(_end)(const _cx_Self* self)
+ { return c_LITERAL(_cx_iter){.pos=self->end, ._s=self}; }
+
+STC_INLINE void _cx_MEMB(_next)(_cx_iter* it) {
+ if (it->pos != it->_s->capmask) { ++it->ref; ++it->pos; }
+ else { it->ref -= it->pos; it->pos = 0; }
+ if (it->pos == it->_s->end) it->ref = NULL;
+}
+
+STC_INLINE intptr_t _cx_MEMB(_index)(const _cx_Self* self, _cx_iter it)
+ { return _cdeq_toidx(self, it.pos); }
+
+STC_INLINE void _cx_MEMB(_adjust_end_)(_cx_Self* self, intptr_t n)
+ { self->end = (self->end + n) & self->capmask; }
diff --git a/include/stc/priv/cqueue_imp.h b/include/stc/priv/cqueue_imp.h
new file mode 100644
index 00000000..2ad9c811
--- /dev/null
+++ b/include/stc/priv/cqueue_imp.h
@@ -0,0 +1,129 @@
+/* MIT License
+ *
+ * Copyright (c) 2023 Tyge Løvset
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+STC_DEF _cx_iter _cx_MEMB(_advance)(_cx_iter it, intptr_t n) {
+ intptr_t len = _cx_MEMB(_size)(it._s);
+ intptr_t pos = it.pos, idx = _cdeq_toidx(it._s, pos);
+ it.pos = (pos + n) & it._s->capmask;
+ it.ref += it.pos - pos;
+ if (!c_LTu(idx + n, len)) it.ref = NULL;
+ return it;
+}
+
+STC_DEF void
+_cx_MEMB(_clear)(_cx_Self* self) {
+ c_foreach (i, _cx_Self, *self)
+ { i_keydrop(i.ref); }
+ self->start = 0, self->end = 0;
+}
+
+STC_DEF void
+_cx_MEMB(_drop)(_cx_Self* self) {
+ _cx_MEMB(_clear)(self);
+ i_free(self->data);
+}
+
+STC_DEF _cx_Self
+_cx_MEMB(_with_capacity)(const intptr_t n) {
+ _cx_Self cx = {0};
+ _cx_MEMB(_reserve)(&cx, n);
+ return cx;
+}
+
+STC_DEF bool
+_cx_MEMB(_reserve)(_cx_Self* self, const intptr_t n) {
+ if (n <= self->capmask)
+ return true;
+ intptr_t oldcap = self->capmask + 1, newcap = cnextpow2(n + 1);
+ _cx_value* d = (_cx_value *)i_realloc(self->data, newcap*c_sizeof *self->data);
+ if (!d)
+ return false;
+ intptr_t head = oldcap - self->start;
+ if (self->start <= self->end)
+ ;
+ else if (head < self->end) {
+ self->start = newcap - head;
+ c_memmove(d + self->start, d + oldcap - head, head*c_sizeof *d);
+ } else {
+ c_memmove(d + oldcap, d, self->end*c_sizeof *d);
+ self->end += oldcap;
+ }
+ self->capmask = newcap - 1;
+ self->data = d;
+ return true;
+}
+
+STC_DEF _cx_value*
+_cx_MEMB(_push)(_cx_Self* self, i_key value) { // push_back
+ intptr_t end = (self->end + 1) & self->capmask;
+ if (end == self->start) { // full
+ _cx_MEMB(_reserve)(self, self->capmask + 3); // => 2x expand
+ end = (self->end + 1) & self->capmask;
+ }
+ _cx_value *v = self->data + self->end;
+ self->end = end;
+ *v = value;
+ return v;
+}
+
+STC_DEF void
+_cx_MEMB(_shrink_to_fit)(_cx_Self *self) {
+ intptr_t sz = _cx_MEMB(_size)(self), j = 0;
+ if (sz > self->capmask/2)
+ return;
+ _cx_Self out = _cx_MEMB(_with_capacity)(sz);
+ if (!out.data)
+ return;
+ c_foreach (i, _cx_Self, *self)
+ out.data[j++] = *i.ref;
+ out.end = sz;
+ i_free(self->data);
+ *self = out;
+}
+
+#if !defined i_no_clone
+STC_DEF _cx_Self
+_cx_MEMB(_clone)(_cx_Self cx) {
+ intptr_t sz = _cx_MEMB(_size)(&cx), j = 0;
+ _cx_Self out = _cx_MEMB(_with_capacity)(sz);
+ if (out.data)
+ c_foreach (i, _cx_Self, cx)
+ out.data[j++] = i_keyclone((*i.ref));
+ out.end = sz;
+ return out;
+}
+#endif // i_no_clone
+
+#if defined _i_has_eq || defined _i_has_cmp
+STC_DEF bool
+_cx_MEMB(_eq)(const _cx_Self* self, const _cx_Self* other) {
+ if (_cx_MEMB(_size)(self) != _cx_MEMB(_size)(other)) return false;
+ for (_cx_iter i = _cx_MEMB(_begin)(self), j = _cx_MEMB(_begin)(other);
+ i.ref; _cx_MEMB(_next)(&i), _cx_MEMB(_next)(&j))
+ {
+ const _cx_raw _rx = i_keyto(i.ref), _ry = i_keyto(j.ref);
+ if (!(i_eq((&_rx), (&_ry)))) return false;
+ }
+ return true;
+}
+#endif
diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h
index 30ed5732..ccdce718 100644
--- a/include/stc/priv/template.h
+++ b/include/stc/priv/template.h
@@ -103,7 +103,7 @@
#define i_no_emplace
#endif
#if c_option(c_native_cmp)
- #define i_native_cmp
+ #define i_cmp_native
#endif
#if c_option(c_no_clone) || defined _i_carc
#define i_no_clone
@@ -203,10 +203,10 @@
#endif
#ifndef i_no_cmp
- #if defined i_cmp || defined i_less || defined i_native_cmp
+ #if defined i_cmp || defined i_less || defined i_cmp_native
#define _i_has_cmp
#endif
- #if defined i_eq || defined i_native_cmp
+ #if defined i_eq || defined i_cmp_native
#define _i_has_eq
#endif
@@ -228,7 +228,7 @@
#endif
#endif
-#if !defined i_hash && (!(defined _i_cbox || defined _i_carc) || defined i_native_cmp)
+#if !defined i_hash && (!(defined _i_cbox || defined _i_carc) || defined i_cmp_native)
#define i_hash c_default_hash
#endif
diff --git a/include/stc/priv/template2.h b/include/stc/priv/template2.h
index def5d01e..351defde 100644
--- a/include/stc/priv/template2.h
+++ b/include/stc/priv/template2.h
@@ -67,7 +67,7 @@
#undef i_realloc
#undef i_free
-#undef i_native_cmp
+#undef i_cmp_native
#undef i_no_cmp
#undef i_no_hash
#undef i_no_clone