I use Python a lot but it’s very slow in some cases which I then use C because it can be 1,000s X faster than Python.
Here is a Vector that I just wrote to use in my new project:
vector.h
/** * Hamid Alipour */ #ifndef __VECTORH__ #define __VECTORH__ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include <assert.h> #define VECTOR_INIT_SIZE 4 #define VECTOR_HASSPACE(v) (((v)->num_elems + 1) <= (v)->num_alloc_elems) #define VECTOR_INBOUNDS(i) (((int) i) >= 0 && (i) < (v)->num_elems) #define VECTOR_INDEX(i) ((char *) (v)->elems + ((v)->elem_size * (i))) typedef struct _vector { void *elems; size_t elem_size; size_t num_elems; size_t num_alloc_elems; void (*free_func)(void *); } vector; extern void vector_init(vector *, size_t, size_t, void (*free_func)(void *)); extern void vector_dispose(vector *); extern void vector_copy(vector *, vector *); extern void vector_insert(vector *, void *, size_t index); extern void vector_insert_at(vector *, void *, size_t index); extern void vector_push(vector *, void *); extern void vector_pop(vector *, void *); extern void vector_shift(vector *, void *); extern void vector_unshift(vector *, void *); extern void vector_get(vector *, size_t, void *); extern void vector_remove(vector *, size_t); extern void vector_transpose(vector *, size_t, size_t); extern size_t vector_length(vector *); extern size_t vector_size(vector *); extern void vector_get_all(vector *, void *); extern void vector_cmp_all(vector *, void *, int (*cmp_func)(const void *, const void *)); extern void vector_qsort(vector *, int (*cmp_func)(const void *, const void *)); static void vector_grow(vector *, size_t); static void vector_swap(void *, void *, size_t); #endif
And vector.c
/** * Hamid Alipour */ #include "vector.h" extern void vector_init(vector *v, size_t elem_size, size_t init_size, void (*free_func)(void *)) { v->elem_size = elem_size; v->num_alloc_elems = (int) init_size > 0 ? init_size : VECTOR_INIT_SIZE; v->num_elems = 0; v->elems = malloc(elem_size * v->num_alloc_elems); assert(v->elems != NULL); v->free_func = free_func != NULL ? free_func : NULL; } extern void vector_dispose(vector *v) { size_t i; if (v->free_func != NULL) { for (i = 0; i < v->num_elems; i++) { v->free_func(VECTOR_INDEX(i)); } } free(v->elems); } extern void vector_copy(vector *v1, vector *v2) { v2->num_elems = v1->num_elems; v2->num_alloc_elems = v1->num_alloc_elems; v2->elem_size = v1->elem_size; v2->elems = realloc(v2->elems, v2->num_alloc_elems * v2->elem_size); assert(v2->elems != NULL); memcpy(v2->elems, v1->elems, v2->num_elems * v2->elem_size); } extern void vector_insert(vector *v, void *elem, size_t index) { void *target; if ((int) index > -1) { if (!VECTOR_INBOUNDS(index)) return; target = VECTOR_INDEX(index); } else { if (!VECTOR_HASSPACE(v)) vector_grow(v, 0); target = VECTOR_INDEX(v->num_elems); v->num_elems++; /* Only grow when adding a new item not when inserting in a spec indx */ } memcpy(target, elem, v->elem_size); } extern void vector_insert_at(vector *v, void *elem, size_t index) { if ((int) index < 0) return; if (!VECTOR_HASSPACE(v)) vector_grow(v, 0); if (index < v->num_elems) memmove(VECTOR_INDEX(index + 1), VECTOR_INDEX(index), (v->num_elems - index) * v->elem_size); /* 1: we are passing index so insert won't increment this 2: insert checks INBONDS... */ v->num_elems++; vector_insert(v, elem, index); } extern void vector_push(vector *v, void *elem) { vector_insert(v, elem, -1); } extern void vector_pop(vector *v, void *elem) { memcpy(elem, VECTOR_INDEX(v->num_elems - 1), v->elem_size); v->num_elems--; } extern void vector_shift(vector *v, void *elem) { memcpy(elem, v->elems, v->elem_size); memmove(VECTOR_INDEX(0), VECTOR_INDEX(1), v->num_elems * v->elem_size); v->num_elems--; } extern void vector_unshift(vector *v, void *elem) { if (!VECTOR_HASSPACE(v)) vector_grow(v, v->num_elems + 1); memmove(VECTOR_INDEX(1), v->elems, v->num_elems * v->elem_size); memcpy(v->elems, elem, v->elem_size); v->num_elems++; } extern void vector_transpose(vector *v, size_t index1, size_t index2) { vector_swap(VECTOR_INDEX(index1), VECTOR_INDEX(index2), v->elem_size); } static void vector_grow(vector *v, size_t size) { if (size > v->num_alloc_elems) v->num_alloc_elems = size; else v->num_alloc_elems *= 2; v->elems = realloc(v->elems, v->elem_size * v->num_alloc_elems); assert(v->elems != NULL); } extern void vector_get(vector *v, size_t index, void *elem) { assert((int) index >= 0); if (!VECTOR_INBOUNDS(index)) { elem = NULL; return; } memcpy(elem, VECTOR_INDEX(index), v->elem_size); } extern void vector_get_all(vector *v, void *elems) { memcpy(elems, v->elems, v->num_elems * v->elem_size); } extern void vector_remove(vector *v, size_t index) { assert((int) index > 0); if (!VECTOR_INBOUNDS(index)) return; memmove(VECTOR_INDEX(index), VECTOR_INDEX(index + 1), v->elem_size); v->num_elems--; } extern void vector_remove_all(vector *v) { v->num_elems = 0; v->elems = realloc(v->elems, v->num_alloc_elems); assert(v->elems != NULL); } extern size_t vector_length(vector *v) { return v->num_elems; } extern size_t vector_size(vector *v) { return v->num_elems * v->elem_size; } extern void vector_cmp_all(vector *v, void *elem, int (*cmp_func)(const void *, const void *)) { size_t i; void *best_match = VECTOR_INDEX(0); for (i = 1; i < v->num_elems; i++) if (cmp_func(VECTOR_INDEX(i), best_match) > 0) best_match = VECTOR_INDEX(i); memcpy(elem, best_match, v->elem_size); } extern void vector_qsort(vector *v, int (*cmp_func)(const void *, const void *)) { qsort(v->elems, v->num_elems, v->elem_size, cmp_func); } static void vector_swap(void *elemp1, void *elemp2, size_t elem_size) { void *tmp = malloc(elem_size); memcpy(tmp, elemp1, elem_size); memcpy(elemp1, elemp2, elem_size); memcpy(elemp2, tmp, elem_size); free(tmp); /* Thanks to gromit */ }
It works
I will write another post with some example usage soon…
Notice that, all the functions that return a value, return it through their arguments and not the “return” statement, this is because I wanted the client to be responsible for allocating/freeing memory for these variables and that makes everyone’s job easier.
As always, I’m open to criticism/ideas and please use it at your own risk.
My name is Hamid Alipour and I'm an indie developer. 
Should you not free tmp in function vector_swap() ?
Comment
Yes yes, thanks!
Comment
I may be wrong, but it seems to me that :
1)
in vector_shift(), v->num_elems–; should be placed before memmove()
2)
in vector_remove(), this size for the memmove() is wrong ; should be memmove(VECTOR_INDEX(index), VECTOR_INDEX(index + 1), v->elem_size*(v->num_elems-index+1));
3)
in vector_remove_all , this line seems wrong : v->elems = realloc(v->elems, v->num_alloc_elems);
should be v->elems = realloc(v->elems, v->elem_size*v->num_alloc_elems); but that does nothing, this is the size already allocated
to free memory space, should be : v->num_alloc_elems = VECTOR_INIT_SIZE;
v->elems = realloc(v->elems, v->elem_size*v->num_alloc_elems);
Comment
Slight nitpick but: the prototypes for vector_Grow and vector_Swap don’t belong in the header file. As static functions they are not meant to be called outside of the vector.c file.
This gives a declared ‘static’ but never defined warning if you compile with -Wunused.
Comment
Ok, how is this to be used? From Py?
Do we have actual mesurements on how much faster this is then some well known Py/C library?
Comment
DBJ, sorry I just saw your comment, you could use it by writing a Python module out of it but I recommend sticking with Python data structures, those are very fast already and if you are not satisfied you could try Psycho, Psycho is a JIT for Python and can improve performance noticeably.
I hope this answered your question…
Comment
Hi..
I am trying to use this in a C program. But how do i complete these tasks? i dont fully understand the arguments and how they should be used in you library.
I need to know how to-
create a vector e.g.= vector v;
add to a vector v e.g= v.push_back(value);
return an element at a specific location v[loc];
clear removes all element;
empty true if empty
erase
size
Comment
Hi..
I’d like to know if your implementation o f vector works fine, if I want to create 2d vector. Thanks
best regards.
Comment
Do you mean a vector to use in computer graphics or a vector as an array, if you mean the array then yes this vector works, although it’s old and I suggest going through it and you might find some bugs in it and you can make a 2D vector by creating vectors of vectors…
Comment