From 8e80fc63c9ef72c379958f8b9d53f4897224c426 Mon Sep 17 00:00:00 2001 From: Attractive Chaos Date: Thu, 13 Jan 2011 12:47:54 -0500 Subject: [PATCH] Added kvec.h and klist.h --- klist.h | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ klist_test.c | 19 ++++++++ kvec.h | 90 ++++++++++++++++++++++++++++++++++++++ kvec_test.cc | 69 +++++++++++++++++++++++++++++ 4 files changed, 299 insertions(+) create mode 100644 klist.h create mode 100644 klist_test.c create mode 100644 kvec.h create mode 100644 kvec_test.cc diff --git a/klist.h b/klist.h new file mode 100644 index 0000000..984bb10 --- /dev/null +++ b/klist.h @@ -0,0 +1,121 @@ +/* The MIT License + + Copyright (c) 2008-2009, by Attractive Chaos + + 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. +*/ + +#ifndef _AC_KLIST_H +#define _AC_KLIST_H + +#include + +#define KMEMPOOL_INIT(name, kmptype_t, kmpfree_f) \ + typedef struct { \ + size_t cnt, n, max; \ + kmptype_t **buf; \ + } kmp_##name##_t; \ + static inline kmp_##name##_t *kmp_init_##name() { \ + return calloc(1, sizeof(kmp_##name##_t)); \ + } \ + static inline void kmp_destroy_##name(kmp_##name##_t *mp) { \ + size_t k; \ + for (k = 0; k < mp->n; ++k) { \ + kmpfree_f(mp->buf[k]); free(mp->buf[k]); \ + } \ + free(mp->buf); free(mp); \ + } \ + static inline kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \ + ++mp->cnt; \ + if (mp->n == 0) return calloc(1, sizeof(kmptype_t)); \ + return mp->buf[--mp->n]; \ + } \ + static inline void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \ + --mp->cnt; \ + if (mp->n == mp->max) { \ + mp->max = mp->max? mp->max<<1 : 16; \ + mp->buf = realloc(mp->buf, sizeof(void*) * mp->max); \ + } \ + mp->buf[mp->n++] = p; \ + } + +#define kmempool_t(name) kmp_##name##_t +#define kmp_init(name) kmp_init_##name() +#define kmp_destroy(name, mp) kmp_destroy_##name(mp) +#define kmp_alloc(name, mp) kmp_alloc_##name(mp) +#define kmp_free(name, mp, p) kmp_free_##name(mp, p) + +#define KLIST_INIT(name, kltype_t, kmpfree_t) \ + struct __kl1_##name { \ + kltype_t data; \ + struct __kl1_##name *next; \ + }; \ + typedef struct __kl1_##name kl1_##name; \ + KMEMPOOL_INIT(name, kl1_##name, kmpfree_t) \ + typedef struct { \ + kl1_##name *head, *tail; \ + kmp_##name##_t *mp; \ + size_t size; \ + } kl_##name##_t; \ + static inline kl_##name##_t *kl_init_##name() { \ + kl_##name##_t *kl = calloc(1, sizeof(kl_##name##_t)); \ + kl->mp = kmp_init(name); \ + kl->head = kl->tail = kmp_alloc(name, kl->mp); \ + kl->head->next = 0; \ + return kl; \ + } \ + static inline void kl_destroy_##name(kl_##name##_t *kl) { \ + kl1_##name *p; \ + for (p = kl->head; p != kl->tail; p = p->next) \ + kmp_free(name, kl->mp, p); \ + kmp_free(name, kl->mp, p); \ + kmp_destroy(name, kl->mp); \ + free(kl); \ + } \ + static inline kltype_t *kl_pushp_##name(kl_##name##_t *kl) { \ + kl1_##name *q, *p = kmp_alloc(name, kl->mp); \ + q = kl->tail; p->next = 0; kl->tail->next = p; kl->tail = p; \ + ++kl->size; \ + return &q->data; \ + } \ + static inline int kl_shift_##name(kl_##name##_t *kl, kltype_t *d) { \ + kl1_##name *p; \ + if (kl->head->next == 0) return -1; \ + --kl->size; \ + p = kl->head; kl->head = kl->head->next; \ + if (d) *d = p->data; \ + kmp_free(name, kl->mp, p); \ + return 0; \ + } + +#define kliter_t(name) kl1_##name +#define klist_t(name) kl_##name##_t +#define kl_val(iter) ((iter)->data) +#define kl_next(iter) ((iter)->next) +#define kl_begin(kl) ((kl)->head) +#define kl_end(kl) ((kl)->tail) + +#define kl_init(name) kl_init_##name() +#define kl_destroy(name, kl) kl_destroy_##name(kl) +#define kl_pushp(name, kl) kl_pushp_##name(kl) +#define kl_shift(name, kl, d) kl_shift_##name(kl, d) + +#endif diff --git a/klist_test.c b/klist_test.c new file mode 100644 index 0000000..cd13813 --- /dev/null +++ b/klist_test.c @@ -0,0 +1,19 @@ +#include +#include "klist.h" + +#define __int_free(x) +KLIST_INIT(32, int, __int_free) + +int main() +{ + klist_t(32) *kl; + kliter_t(32) *p; + kl = kl_init(32); + *kl_pushp(32, kl) = 1; + *kl_pushp(32, kl) = 10; + kl_shift(32, kl, 0); + for (p = kl_begin(kl); p != kl_end(kl); p = kl_next(p)) + printf("%d\n", kl_val(p)); + kl_destroy(32, kl); + return 0; +} diff --git a/kvec.h b/kvec.h new file mode 100644 index 0000000..301f1b9 --- /dev/null +++ b/kvec.h @@ -0,0 +1,90 @@ +/* The MIT License + + Copyright (c) 2008, by Attractive Chaos + + 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. +*/ + +/* + An example: + +#include "kvec.h" +int main() { + kvec_t(int) array; + kv_init(array); + kv_push(int, array, 10); // append + kv_a(int, array, 20) = 5; // dynamic + kv_A(array, 20) = 4; // static + kv_destroy(array); + return 0; +} +*/ + +/* + 2008-09-22 (0.1.0): + + * The initial version. + +*/ + +#ifndef AC_KVEC_H +#define AC_KVEC_H + +#include + +#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) + +#define kvec_t(type) struct { size_t n, m; type *a; } +#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0) +#define kv_destroy(v) free((v).a) +#define kv_A(v, i) ((v).a[(i)]) +#define kv_pop(v) ((v).a[--(v).n]) +#define kv_size(v) ((v).n) +#define kv_max(v) ((v).m) + +#define kv_resize(type, v, s) ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m)) + +#define kv_copy(type, v1, v0) do { \ + if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \ + (v1).n = (v0).n; \ + memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \ + } while (0) \ + +#define kv_push(type, v, x) do { \ + if ((v).n == (v).m) { \ + (v).m = (v).m? (v).m<<1 : 2; \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ + } \ + (v).a[(v).n++] = (x); \ + } while (0) + +#define kv_pushp(type, v) (((v).n == (v).m)? \ + ((v).m = ((v).m? (v).m<<1 : 2), \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ + : 0), ((v).a + ((v).n++)) + +#define kv_a(type, v, i) ((v).m <= (size_t)(i)? \ + ((v).m = (v).n = (i) + 1, kv_roundup32((v).m), \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ + : (v).n <= (size_t)(i)? (v).n = (i) \ + : 0), (v).a[(i)] + +#endif diff --git a/kvec_test.cc b/kvec_test.cc new file mode 100644 index 0000000..1015574 --- /dev/null +++ b/kvec_test.cc @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include "kvec.h" + +int main() +{ + int M = 10, N = 20000000, i, j; + clock_t t; + t = clock(); + for (i = 0; i < M; ++i) { + int *array = (int*)malloc(N * sizeof(int)); + for (j = 0; j < N; ++j) array[j] = j; + free(array); + } + printf("C array, preallocated: %.3f sec\n", + (float)(clock() - t) / CLOCKS_PER_SEC); + t = clock(); + for (i = 0; i < M; ++i) { + int *array = 0, max = 0; + for (j = 0; j < N; ++j) { + if (j == max) { + max = !max? 1 : max << 1; + array = (int*)realloc(array, sizeof(int)*max); + } + array[j] = j; + } + free(array); + } + printf("C array, dynamic: %.3f sec\n", + (float)(clock() - t) / CLOCKS_PER_SEC); + t = clock(); + for (i = 0; i < M; ++i) { + kvec_t(int) array; + kv_init(array); + kv_resize(int, array, N); + for (j = 0; j < N; ++j) kv_a(int, array, j) = j; + kv_destroy(array); + } + printf("C vector, dynamic(kv_a): %.3f sec\n", + (float)(clock() - t) / CLOCKS_PER_SEC); + t = clock(); + for (i = 0; i < M; ++i) { + kvec_t(int) array; + kv_init(array); + for (j = 0; j < N; ++j) + kv_push(int, array, j); + kv_destroy(array); + } + printf("C vector, dynamic(kv_push): %.3f sec\n", + (float)(clock() - t) / CLOCKS_PER_SEC); + t = clock(); + for (i = 0; i < M; ++i) { + std::vector array; + array.reserve(N); + for (j = 0; j < N; ++j) array[j] = j; + } + printf("C++ vector, preallocated: %.3f sec\n", + (float)(clock() - t) / CLOCKS_PER_SEC); + t = clock(); + for (i = 0; i < M; ++i) { + std::vector array; + for (j = 0; j < N; ++j) array.push_back(j); + } + printf("C++ vector, dynamic: %.3f sec\n", + (float)(clock() - t) / CLOCKS_PER_SEC); + return 0; +} -- 2.47.3