summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2020-09-02 20:56:22 +0200
committerTyge Løvset <[email protected]>2020-09-02 20:56:22 +0200
commit7fd50323b46599090d5cd9ade43a7cdb69c1e145 (patch)
treead8db17822f117499356b374edc02a8db239acc3
parentaf12926547b1a09b4513ba149d13ea9f84d4c528 (diff)
downloadSTC-modified-7fd50323b46599090d5cd9ade43a7cdb69c1e145.tar.gz
STC-modified-7fd50323b46599090d5cd9ade43a7cdb69c1e145.zip
Added cqueue.h, cstack.h and renamed cpqueue.h to cprique.h
-rw-r--r--README.md2
-rw-r--r--examples/geek7.c14
-rw-r--r--examples/heap.c18
-rw-r--r--examples/inits.c14
-rw-r--r--examples/priority.c18
-rw-r--r--examples/queue.c31
-rw-r--r--stc/clist.h22
-rw-r--r--stc/cprique.h (renamed from stc/cpqueue.h)90
-rw-r--r--stc/cqueue.h95
-rw-r--r--stc/cstack.h82
10 files changed, 304 insertions, 82 deletions
diff --git a/README.md b/README.md
index 03ecaf99..1b957255 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ An elegant, fully typesafe, generic, customizable, user-friendly, consistent, an
- **stc/cset.h** - A generic **unordered set** implemented in tandem with *unordered map*
- **stc/cstr.h** - Compact and powerful **string** class.
- **stc/cvec.h** - Dynamic generic **vector** class, works well as a **stack**.
-- **stc/cpqueue.h** - Priority queue adapter for **cvec.h**, as a **heap**.
+- **stc/cprique.h** - Priority queue adapter for **cvec.h**, as a **heap**.
- **stc/copt.h** - Implementation of a **getopt_long()**-like function, *copt_get()*, to parse command line arguments.
- **stc/crandom.h** - A few very efficent modern random number generators *pcg32* and my own *64-bit PRNG* inspired by *sfc64*. Both uniform and normal distributions.
- **stc/cdefs.h** - A common include file with a few general definitions.
diff --git a/examples/geek7.c b/examples/geek7.c
index 9004a1a8..c686b014 100644
--- a/examples/geek7.c
+++ b/examples/geek7.c
@@ -25,11 +25,11 @@ After inserting all the elements excluding the ones which are to be deleted, Pop
#include <stc/clist.h>
#include <stc/cmap.h>
#include <stc/cvec.h>
-#include <stc/cpqueue.h>
+#include <stc/cprique.h>
declare_cmap(ii, int, int);
declare_cvec(i, int);
-declare_cpqueue(i, cvec_i, >);
+declare_cprique(i, cvec_i, >);
// Find k minimum element from arr[0..m-1] after deleting
// elements from del[0..n-1]
@@ -44,7 +44,7 @@ void findElementsAfterDel(int arr[], int m, int del[],
cmap_ii_insert(&mp, del[i], 0)->value++;
}
- cpqueue_i heap = cpqueue_i_init();
+ cprique_i heap = cprique_i_init();
for (int i = 0; i < m; ++i) {
@@ -63,17 +63,17 @@ void findElementsAfterDel(int arr[], int m, int del[],
// Else push it in the min heap
else
- cpqueue_i_push(&heap, arr[i]);
+ cprique_i_push(&heap, arr[i]);
}
// Print top k elements in the min heap
for (int i = 0; i < k; ++i) {
- printf("%d ", *cpqueue_i_top(&heap));
+ printf("%d ", *cprique_i_top(&heap));
// Pop the top element
- cpqueue_i_pop(&heap);
+ cprique_i_pop(&heap);
}
- cpqueue_i_destroy(&heap);
+ cprique_i_destroy(&heap);
}
int main()
diff --git a/examples/heap.c b/examples/heap.c
index 5917dd30..fbcef0cd 100644
--- a/examples/heap.c
+++ b/examples/heap.c
@@ -2,10 +2,10 @@
#include <time.h>
#include <stc/crandom.h>
#include <stc/cvec.h>
-#include <stc/cpqueue.h>
+#include <stc/cprique.h>
declare_cvec(f, float);
-declare_cpqueue(f, cvec_f, >);
+declare_cprique(f, cvec_f, >);
int main()
{
@@ -13,33 +13,33 @@ int main()
crand_rng32_t pcg;
int N = 3000000, M = 100;
- cpqueue_f pq = cpqueue_f_init();
+ cprique_f pq = cprique_f_init();
pcg = crand_rng32_init(seed);
clock_t start = clock();
for (int i=0; i<N; ++i)
cvec_f_push_back(&pq, crand_i32(&pcg));
- cpqueue_f_build(&pq);
+ cprique_f_build(&pq);
printf("Built priority queue: %f secs\n", (clock() - start) / (float) CLOCKS_PER_SEC);
for (int i=0; i<M; ++i)
- printf("%.0f ", *cpqueue_f_top(&pq)), cpqueue_f_pop(&pq);
+ printf("%.0f ", *cprique_f_top(&pq)), cprique_f_pop(&pq);
start = clock();
for (int i=M; i<N; ++i)
- cpqueue_f_pop(&pq);
+ cprique_f_pop(&pq);
printf("\n\npopped PQ: %f secs\n", (clock() - start) / (float) CLOCKS_PER_SEC);
pcg = crand_rng32_init(seed);
start = clock();
for (int i=0; i<N; ++i)
- cpqueue_f_push(&pq, crand_i32(&pcg));
+ cprique_f_push(&pq, crand_i32(&pcg));
printf("pushed PQ: %f secs\n", (clock() - start) / (float) CLOCKS_PER_SEC);
for (int i=0; i<M; ++i)
- printf("%.0f ", *cpqueue_f_top(&pq)), cpqueue_f_pop(&pq);
+ printf("%.0f ", *cprique_f_top(&pq)), cprique_f_pop(&pq);
puts("");
- cpqueue_f_destroy(&pq);
+ cprique_f_destroy(&pq);
}
diff --git a/examples/inits.c b/examples/inits.c
index d7b7a37b..dada8fac 100644
--- a/examples/inits.c
+++ b/examples/inits.c
@@ -2,7 +2,7 @@
#include <stc/cstr.h>
#include <stc/cmap.h>
#include <stc/cvec.h>
-#include <stc/cpqueue.h>
+#include <stc/cprique.h>
#include <stc/clist.h>
declare_cmap(id, int, cstr_t, cstr_destroy); // Map of int -> cstr_t
@@ -17,7 +17,7 @@ declare_cvec(ip, ipair_t, c_default_destroy, ipair_compare);
declare_clist(ip, ipair_t, c_default_destroy, ipair_compare);
declare_cvec(f, float);
-declare_cpqueue(f, cvec_f, >);
+declare_cprique(f, cvec_f, >);
int main(void) {
@@ -31,16 +31,16 @@ int main(void) {
// CVEC PRIORITY QUEUE
- cpqueue_f_build(&floats); // reorganise vec
- c_push(&floats, cpqueue_f, c_items(40.0f, 20.0f, 50.0f, 30.0f, 10.0f));
+ cprique_f_build(&floats); // reorganise vec
+ c_push(&floats, cprique_f, c_items(40.0f, 20.0f, 50.0f, 30.0f, 10.0f));
// sorted:
while (cvec_size(floats) > 0) {
- printf("%.1f ", *cpqueue_f_top(&floats));
- cpqueue_f_pop(&floats);
+ printf("%.1f ", *cprique_f_top(&floats));
+ cprique_f_pop(&floats);
}
puts("\n");
- cpqueue_f_destroy(&floats);
+ cprique_f_destroy(&floats);
// CMAP ID
diff --git a/examples/priority.c b/examples/priority.c
index 82e78621..fc0526bf 100644
--- a/examples/priority.c
+++ b/examples/priority.c
@@ -2,34 +2,34 @@
#include <stdio.h>
#include <time.h>
#include <stc/cvec.h>
-#include <stc/cpqueue.h>
+#include <stc/cprique.h>
#include <stc/cmap.h>
#include <stc/crandom.h>
declare_cvec(i, int64_t);
-declare_cpqueue(i, cvec_i, >); // min-heap (increasing values)
+declare_cprique(i, cvec_i, >); // min-heap (increasing values)
int main() {
size_t N = 10000000;
crand_rng64_t pcg = crand_rng64_init(time(NULL));
crand_uniform_i64_t dist = crand_uniform_i64_init(pcg, 0, N * 10);
- cpqueue_i heap = cpqueue_i_init();
+ cprique_i heap = cprique_i_init();
// Push ten million random numbers to priority queue
for (int i=0; i<N; ++i)
- cpqueue_i_push(&heap, crand_uniform_i64(&dist));
+ cprique_i_push(&heap, crand_uniform_i64(&dist));
// push some negative numbers too.
- c_push(&heap, cpqueue_i, c_items(-231, -32, -873, -4, -343));
+ c_push(&heap, cprique_i, c_items(-231, -32, -873, -4, -343));
for (int i=0; i<N; ++i)
- cpqueue_i_push(&heap, crand_uniform_i64(&dist));
+ cprique_i_push(&heap, crand_uniform_i64(&dist));
// Extract the hundred smallest.
for (int i=0; i<100; ++i) {
- printf("%zd ", *cpqueue_i_top(&heap));
- cpqueue_i_pop(&heap);
+ printf("%zd ", *cprique_i_top(&heap));
+ cprique_i_pop(&heap);
}
- cpqueue_i_destroy(&heap);
+ cprique_i_destroy(&heap);
}
diff --git a/examples/queue.c b/examples/queue.c
new file mode 100644
index 00000000..fa8700fe
--- /dev/null
+++ b/examples/queue.c
@@ -0,0 +1,31 @@
+#include <stc/crandom.h>
+#include <stc/cqueue.h>
+#include <stdio.h>
+
+declare_clist(i, int);
+declare_cqueue(i, clist_i); // min-heap (increasing values)
+
+int main() {
+ int n = 10000000;
+ crand_rng32_t gen = crand_rng32_init(1234);
+ crand_uniform_i32_t dist = crand_uniform_i32_init(gen, 0, n);
+
+ cqueue_i queue = cqueue_i_init();
+
+ // Push ten million random numbers onto the queue.
+ for (int i=0; i<n; ++i)
+ cqueue_i_push(&queue, crand_uniform_i32(&dist));
+
+ // Push or pop on the queue ten million times
+ printf("%d\n", n);
+ for (int i=n; i>0; --i) {
+ int r = crand_uniform_i32(&dist);
+ if (r & 1)
+ ++n, cqueue_i_push(&queue, r);
+ else
+ --n, cqueue_i_pop(&queue);
+ }
+ printf("%d\n", n);
+ printf("%zu\n", n, cqueue_i_size(queue));
+ cqueue_i_destroy(&queue);
+}
diff --git a/stc/clist.h b/stc/clist.h
index 4cba9d1f..1415bcd5 100644
--- a/stc/clist.h
+++ b/stc/clist.h
@@ -85,6 +85,10 @@
#define clist_init {NULL}
#define clist_empty(list) ((list).last == NULL)
+
+declare_clist_types(void, int);
+STC_API size_t _clist_size(const clist_void* self);
+
#define declare_clist_7(tag, Value, valueDestroy, RawValue, valueCompareRaw, valueToRaw, valueFromRaw) \
\
declare_clist_types(tag, Value); \
@@ -94,7 +98,9 @@
STC_INLINE clist_##tag \
clist_##tag##_init(void) {clist_##tag x = clist_init; return x;} \
STC_INLINE bool \
- clist_##tag##_empty(clist_##tag l) {return clist_empty(l);} \
+ clist_##tag##_empty(clist_##tag ls) {return clist_empty(ls);} \
+ STC_INLINE size_t \
+ clist_##tag##_size(clist_##tag ls) {return _clist_size((const clist_void*) &ls);} \
STC_INLINE Value \
clist_##tag##_value_from_raw(RawValue rawValue) {return valueFromRaw(rawValue);} \
\
@@ -278,9 +284,7 @@
free(del)
-declare_clist_types(void, int);
-
-STC_API void \
+STC_API void
_clist_splice_after(clist_void* self, clist_void_iter_t pos, clist_void* other) {
if (!pos.item)
self->last = other->last;
@@ -293,6 +297,16 @@ _clist_splice_after(clist_void* self, clist_void_iter_t pos, clist_void* other)
other->last = NULL;
}
+STC_API size_t
+_clist_size(const clist_void* self) {
+ const clist_void_node_t *i = self->last;
+ if (!i) return 0;
+ size_t n = 1;
+ while ((i = i->next) != self->last) ++n;
+ return n;
+}
+
+
/* Singly linked list Mergesort implementation by Simon Tatham. O(n*log n).
* https://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
*/
diff --git a/stc/cpqueue.h b/stc/cprique.h
index b2c81478..7a303152 100644
--- a/stc/cpqueue.h
+++ b/stc/cprique.h
@@ -24,24 +24,24 @@
/* Priority Queue using heap, with adapter class (normally cvec).
#include <stc/crandom.h>
- #include <stc/cpqueue.h>
+ #include <stc/cprique.h>
declare_cvec(f, float);
- declare_cpqueue(f, cvec_f, >); // min-heap (increasing values)
+ declare_cprique(f, cvec_f, >); // min-heap (increasing values)
int main() {
crand_rng32_t gen = crand_rng32_init(1234);
crand_uniform_f32_t dist = crand_uniform_f32_init(10.0f, 100.0f);
- cpqueue_f queue = cpqueue_f_init();
+ cprique_f queue = cprique_f_init();
// Push ten million random numbers onto the queue.
for (int i=0; i<10000000; ++i)
- cpqueue_f_push(&queue, crand_uniform_f32(&gen, dist));
+ cprique_f_push(&queue, crand_uniform_f32(&gen, dist));
// Extract the 100 smallest.
for (int i=0; i<100; ++i) {
- printf("%f ", *cpqueue_f_top(queue));
- cpqueue_f_pop(&queue);
+ printf("%f ", *cprique_f_top(queue));
+ cprique_f_pop(&queue);
}
- cpqueue_f_destroy(&queue);
+ cprique_f_destroy(&queue);
}
*/
@@ -50,52 +50,52 @@
#include "cvec.h"
-#define declare_cpqueue(tag, ctype, cmpOpr) /* cmpOpr: < or > */ \
+#define declare_cprique(tag, ctype, cmpOpr) /* cmpOpr: < or > */ \
\
-typedef ctype cpqueue_##tag; \
-typedef ctype##_value_t cpqueue_##tag##_value_t; \
-typedef ctype##_rawvalue_t cpqueue_##tag##_rawvalue_t; \
-typedef ctype##_input_t cpqueue_##tag##_input_t; \
-STC_INLINE cpqueue_##tag \
-cpqueue_##tag##_init() {return ctype##_init();} \
+typedef ctype cprique_##tag; \
+typedef ctype##_value_t cprique_##tag##_value_t; \
+typedef ctype##_rawvalue_t cprique_##tag##_rawvalue_t; \
+typedef ctype##_input_t cprique_##tag##_input_t; \
+STC_INLINE cprique_##tag \
+cprique_##tag##_init() {return ctype##_init();} \
STC_INLINE size_t \
-cpqueue_##tag##_size(cpqueue_##tag pq) {return ctype##_size(pq);} \
+cprique_##tag##_size(cprique_##tag pq) {return ctype##_size(pq);} \
STC_INLINE bool \
-cpqueue_##tag##_empty(cpqueue_##tag pq) {return ctype##_empty(pq);} \
+cprique_##tag##_empty(cprique_##tag pq) {return ctype##_empty(pq);} \
STC_INLINE void \
-cpqueue_##tag##_destroy(cpqueue_##tag* self) {ctype##_destroy(self);} \
+cprique_##tag##_destroy(cprique_##tag* self) {ctype##_destroy(self);} \
STC_API void \
-cpqueue_##tag##_build(cpqueue_##tag* self); \
+cprique_##tag##_build(cprique_##tag* self); \
STC_API void \
-cpqueue_##tag##_erase(cpqueue_##tag* self, size_t i); \
-STC_INLINE const cpqueue_##tag##_value_t* \
-cpqueue_##tag##_top(const cpqueue_##tag* self) {return &self->data[0];} \
+cprique_##tag##_erase(cprique_##tag* self, size_t i); \
+STC_INLINE const cprique_##tag##_value_t* \
+cprique_##tag##_top(const cprique_##tag* self) {return &self->data[0];} \
STC_INLINE void \
-cpqueue_##tag##_pop(cpqueue_##tag* self) {cpqueue_##tag##_erase(self, 0);} \
+cprique_##tag##_pop(cprique_##tag* self) {cprique_##tag##_erase(self, 0);} \
STC_API void \
-cpqueue_##tag##_push_v(cpqueue_##tag* self, cpqueue_##tag##_value_t value); \
+cprique_##tag##_push_v(cprique_##tag* self, cprique_##tag##_value_t value); \
STC_INLINE void \
-cpqueue_##tag##_push(cpqueue_##tag* self, cpqueue_##tag##_rawvalue_t rawValue) { \
- cpqueue_##tag##_push_v(self, ctype##_value_from_raw(rawValue)); \
+cprique_##tag##_push(cprique_##tag* self, cprique_##tag##_rawvalue_t rawValue) { \
+ cprique_##tag##_push_v(self, ctype##_value_from_raw(rawValue)); \
} \
STC_API void \
-cpqueue_##tag##_push_n(cpqueue_##tag *self, const cpqueue_##tag##_input_t in[], size_t size); \
+cprique_##tag##_push_n(cprique_##tag *self, const cprique_##tag##_input_t in[], size_t size); \
\
-implement_cpqueue(tag, ctype, cmpOpr)
+implement_cprique(tag, ctype, cmpOpr)
/* -------------------------- IMPLEMENTATION ------------------------- */
#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION)
-#define implement_cpqueue(tag, ctype, cmpOpr) \
+#define implement_cprique(tag, ctype, cmpOpr) \
\
STC_INLINE void \
-_cpqueue_##tag##_sift_down(cpqueue_##tag##_value_t* arr, size_t i, size_t n) { \
+_cprique_##tag##_sift_down(cprique_##tag##_value_t* arr, size_t i, size_t n) { \
size_t r = i, c = i << 1; \
while (c <= n) { \
if (c < n && ctype##_value_compare(&arr[c], &arr[c + 1]) cmpOpr 0) \
++c; \
if (ctype##_value_compare(&arr[r], &arr[c]) cmpOpr 0) { \
- cpqueue_##tag##_value_t t = arr[r]; arr[r] = arr[c]; arr[r = c] = t; \
+ cprique_##tag##_value_t t = arr[r]; arr[r] = arr[c]; arr[r = c] = t; \
} else \
return; \
c <<= 1; \
@@ -103,39 +103,39 @@ _cpqueue_##tag##_sift_down(cpqueue_##tag##_value_t* arr, size_t i, size_t n) { \
} \
\
STC_API void \
-cpqueue_##tag##_build(cpqueue_##tag* self) { \
- size_t n = cpqueue_##tag##_size(*self); \
- cpqueue_##tag##_value_t *arr = self->data - 1; \
+cprique_##tag##_build(cprique_##tag* self) { \
+ size_t n = cprique_##tag##_size(*self); \
+ cprique_##tag##_value_t *arr = self->data - 1; \
for (size_t k = n >> 1; k != 0; --k) \
- _cpqueue_##tag##_sift_down(arr, k, n); \
+ _cprique_##tag##_sift_down(arr, k, n); \
} \
\
STC_API void \
-cpqueue_##tag##_erase(cpqueue_##tag* self, size_t i) { \
- size_t n = cpqueue_##tag##_size(*self) - 1; \
+cprique_##tag##_erase(cprique_##tag* self, size_t i) { \
+ size_t n = cprique_##tag##_size(*self) - 1; \
self->data[i] = self->data[n]; \
ctype##_pop_back(self); \
- _cpqueue_##tag##_sift_down(self->data - 1, i + 1, n); \
+ _cprique_##tag##_sift_down(self->data - 1, i + 1, n); \
} \
\
STC_API void \
-cpqueue_##tag##_push_v(cpqueue_##tag* self, cpqueue_##tag##_value_t value) { \
+cprique_##tag##_push_v(cprique_##tag* self, cprique_##tag##_value_t value) { \
ctype##_push_back(self, value); /* sift-up the value */ \
- size_t n = cpqueue_##tag##_size(*self), c = n; \
- cpqueue_##tag##_value_t *arr = self->data - 1; \
+ size_t n = cprique_##tag##_size(*self), c = n; \
+ cprique_##tag##_value_t *arr = self->data - 1; \
for (; c > 1 && ctype##_value_compare(&arr[c >> 1], &value) cmpOpr 0; c >>= 1) \
arr[c] = arr[c >> 1]; \
if (c != n) arr[c] = value; \
} \
STC_API void \
-cpqueue_##tag##_push_n(cpqueue_##tag *self, const cpqueue_##tag##_input_t in[], size_t size) { \
- ctype##_reserve(self, cpqueue_##tag##_size(*self) + size); \
- for (size_t i=0; i<size; ++i) cpqueue_##tag##_push(self, in[i]); \
+cprique_##tag##_push_n(cprique_##tag *self, const cprique_##tag##_input_t in[], size_t size) { \
+ ctype##_reserve(self, cprique_##tag##_size(*self) + size); \
+ for (size_t i=0; i<size; ++i) cprique_##tag##_push(self, in[i]); \
} \
-typedef int cpqueue_##tag##_dud
+typedef int cprique_##tag##_dud
#else
-#define implement_cpqueue(tag, ctype, cmpOpr)
+#define implement_cprique(tag, ctype, cmpOpr)
#endif
#endif
diff --git a/stc/cqueue.h b/stc/cqueue.h
new file mode 100644
index 00000000..2cdfb753
--- /dev/null
+++ b/stc/cqueue.h
@@ -0,0 +1,95 @@
+/* MIT License
+ *
+ * Copyright (c) 2020 Tyge Løvset, NORCE, www.norceresearch.no
+ *
+ * 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.
+ */
+
+/* Priority Queue using heap, with adapter class (normally cvec).
+
+ #include <stc/crandom.h>
+ #include <stc/cqueue.h>
+ declare_clist(i, int);
+ declare_cqueue(i, clist_i); // min-heap (increasing values)
+
+ int main() {
+ int n = 10000000;
+ crand_rng32_t gen = crand_rng32_init(1234);
+ crand_uniform_i32_t dist = crand_uniform_i32_init(gen, 0, n);
+
+ cqueue_i queue = cqueue_i_init();
+
+ // Push ten million random numbers onto the queue.
+ for (int i=0; i<n; ++i)
+ cqueue_i_push(&queue, crand_uniform_i32(&dist));
+
+ // Push or pop on the queue ten million times
+ printf("%d\n", n);
+ for (int i=n; i>0; --i) {
+ int r = crand_uniform_i32(&dist);
+ if (r & 1)
+ ++n, cqueue_i_push(&queue, r);
+ else
+ --n, cqueue_i_pop(&queue);
+ }
+ printf("%d\n", n);
+ cqueue_i_destroy(&queue);
+ }
+*/
+
+#ifndef CQUEUE__H__
+#define CQUEUE__H__
+
+#include "clist.h"
+
+#define declare_cqueue(tag, ctype) \
+ \
+typedef ctype cqueue_##tag; \
+typedef ctype##_value_t cqueue_##tag##_value_t; \
+typedef ctype##_rawvalue_t cqueue_##tag##_rawvalue_t; \
+typedef ctype##_input_t cqueue_##tag##_input_t; \
+STC_INLINE cqueue_##tag \
+cqueue_##tag##_init() {return ctype##_init();} \
+STC_INLINE void \
+cqueue_##tag##_destroy(cqueue_##tag* self) {ctype##_destroy(self);} \
+STC_INLINE size_t \
+cqueue_##tag##_size(cqueue_##tag pq) {return ctype##_size(pq);} \
+STC_INLINE bool \
+cqueue_##tag##_empty(cqueue_##tag pq) {return ctype##_empty(pq);} \
+STC_INLINE cqueue_##tag##_value_t* \
+cqueue_##tag##_front(cqueue_##tag* self) {return ctype##_front(self);} \
+STC_INLINE cqueue_##tag##_value_t* \
+cqueue_##tag##_back(cqueue_##tag* self) {return ctype##_back(self);} \
+STC_INLINE void \
+cqueue_##tag##_pop(cqueue_##tag* self) {ctype##_pop_front(self);} \
+STC_API void \
+cqueue_##tag##_push_v(cqueue_##tag* self, ctype##_value_t value) { \
+ ctype##_push_back_v(self, value); \
+} \
+STC_INLINE void \
+cqueue_##tag##_push(cqueue_##tag* self, cqueue_##tag##_rawvalue_t rawValue) { \
+ ctype##_push_back(self, rawValue); \
+} \
+STC_API void \
+cqueue_##tag##_push_n(cqueue_##tag *self, const cqueue_##tag##_input_t in[], size_t size) { \
+ ctype##_push_n(self, in, size); \
+} \
+typedef int cqueue_##tag##_dud
+
+#endif
diff --git a/stc/cstack.h b/stc/cstack.h
new file mode 100644
index 00000000..8c806523
--- /dev/null
+++ b/stc/cstack.h
@@ -0,0 +1,82 @@
+/* MIT License
+ *
+ * Copyright (c) 2020 Tyge Løvset, NORCE, www.norceresearch.no
+ *
+ * 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.
+ */
+
+/* Stack adapter (normally uses cvec).
+
+ #include <stc/cstack.h>
+ #include <stdio.h>
+
+ declare_cvec(i, int);
+ declare_cstack(i, cvec_i);
+
+ int main() {
+ cstack_i stack = cstack_i_init();
+
+ for (int i=0; i<100; ++i)
+ cstack_i_push(&stack, i*i);
+
+ for (int i=0; i<90; ++i)
+ cstack_i_pop(&stack);
+
+ printf("top: %d\n", *cstack_i_top(&stack));
+ }
+*/
+
+#ifndef CSTACK__H__
+#define CSTACK__H__
+
+#include "cvec.h"
+
+#define declare_cstack(tag, ctype) \
+ \
+typedef ctype cstack_##tag; \
+typedef ctype##_value_t cstack_##tag##_value_t; \
+typedef ctype##_rawvalue_t cstack_##tag##_rawvalue_t; \
+typedef ctype##_input_t cstack_##tag##_input_t; \
+STC_INLINE cstack_##tag \
+cstack_##tag##_init() {return ctype##_init();} \
+STC_INLINE void \
+cstack_##tag##_destroy(cstack_##tag* self) {ctype##_destroy(self);} \
+STC_INLINE size_t \
+cstack_##tag##_size(cstack_##tag pq) {return ctype##_size(pq);} \
+STC_INLINE bool \
+cstack_##tag##_empty(cstack_##tag pq) {return ctype##_empty(pq);} \
+STC_INLINE cstack_##tag##_value_t* \
+cstack_##tag##_top(cstack_##tag* self) {return ctype##_back(self);} \
+STC_INLINE void \
+cstack_##tag##_pop(cstack_##tag* self) {ctype##_pop_back(self);} \
+STC_API void \
+cstack_##tag##_push_v(cstack_##tag* self, ctype##_value_t value) { \
+ ctype##_push_back_v(self, value); \
+} \
+STC_INLINE void \
+cstack_##tag##_push(cstack_##tag* self, cstack_##tag##_rawvalue_t rawValue) { \
+ ctype##_push_back(self, rawValue); \
+} \
+STC_API void \
+cstack_##tag##_push_n(cstack_##tag *self, const cstack_##tag##_input_t in[], size_t size) { \
+ ctype##_push_n(self, in, size); \
+} \
+typedef int cstack_##tag##_dud
+
+#endif