added qse_arr_setheapposoffset()
This commit is contained in:
		| @ -149,6 +149,8 @@ struct qse_arr_t | |||||||
| 	qse_arr_keeper_t keeper; /* data keeper */ | 	qse_arr_keeper_t keeper; /* data keeper */ | ||||||
| 	qse_arr_sizer_t  sizer;  /* size calculator */ | 	qse_arr_sizer_t  sizer;  /* size calculator */ | ||||||
| 	qse_byte_t       scale;  /* scale factor */ | 	qse_byte_t       scale;  /* scale factor */ | ||||||
|  | 	qse_size_t       heap_pos_offset; /* offset in the data element where position  | ||||||
|  | 	                                   * is stored when heap operation is performed. */ | ||||||
| 	qse_size_t       size;   /* number of items */ | 	qse_size_t       size;   /* number of items */ | ||||||
| 	qse_size_t       capa;   /* capacity */ | 	qse_size_t       capa;   /* capacity */ | ||||||
| 	qse_arr_slot_t** slot; | 	qse_arr_slot_t** slot; | ||||||
| @ -446,6 +448,36 @@ QSE_EXPORT qse_size_t qse_arr_updateheap ( | |||||||
| 	qse_size_t dlen | 	qse_size_t dlen | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | QSE_EXPORT qse_size_t qse_arr_getheapposoffset ( | ||||||
|  | 	qse_arr_t* arr | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The qse_arr_setheapposoffset() function sets the offset to a position holding  | ||||||
|  |  * field within a data element. It assumes that the field is of the qse_size_t type. | ||||||
|  |  * | ||||||
|  |  * \code | ||||||
|  |  * struct data_t | ||||||
|  |  * { | ||||||
|  |  *    int v; | ||||||
|  |  *    qse_size_t pos; | ||||||
|  |  * }; | ||||||
|  |  * struct data_t d; | ||||||
|  |  * qse_arr_setheapposoffset (arr, QSE_OFFSETOF(struct data_t, pos));  | ||||||
|  |  * d.v = 20; | ||||||
|  |  * qse_arr_pushheap (arr, &d, 1); | ||||||
|  |  * \endcode | ||||||
|  |  *  | ||||||
|  |  * In the code above, the 'pos' field of the first element in the array must be 0. | ||||||
|  |  *  | ||||||
|  |  * If it's set to QSE_ARR_NIL, position is not updated when heapification is  | ||||||
|  |  * performed.   | ||||||
|  |  */ | ||||||
|  | QSE_EXPORT void qse_arr_setheapposoffset ( | ||||||
|  | 	qse_arr_t* arr, | ||||||
|  | 	qse_size_t offset | ||||||
|  | ); | ||||||
|  |  | ||||||
| #if defined(__cplusplus) | #if defined(__cplusplus) | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -135,6 +135,7 @@ int qse_arr_init (arr_t* arr, mmgr_t* mmgr, size_t capa) | |||||||
| 	arr->capa = 0; | 	arr->capa = 0; | ||||||
| 	arr->slot = QSE_NULL; | 	arr->slot = QSE_NULL; | ||||||
| 	arr->scale = 1; | 	arr->scale = 1; | ||||||
|  | 	arr->heap_pos_offset = QSE_ARR_NIL; | ||||||
|  |  | ||||||
| 	arr->copier = QSE_ARR_COPIER_SIMPLE; | 	arr->copier = QSE_ARR_COPIER_SIMPLE; | ||||||
| 	arr->comper = default_comparator; | 	arr->comper = default_comparator; | ||||||
| @ -608,13 +609,20 @@ void qse_arr_popstack (arr_t* arr) | |||||||
| #define HEAP_LEFT(x)   ((x)*2 + 1) | #define HEAP_LEFT(x)   ((x)*2 + 1) | ||||||
| #define HEAP_RIGHT(x)  ((x)*2 + 2) | #define HEAP_RIGHT(x)  ((x)*2 + 2) | ||||||
|  |  | ||||||
| size_t sift_up (arr_t* arr, size_t index) | #define HEAP_UPDATE_POS(arr, index) \ | ||||||
|  | 	do { \ | ||||||
|  | 		if (arr->heap_pos_offset != QSE_ARR_NIL) \ | ||||||
|  | 			*(qse_size_t*)((qse_byte_t*)DPTR(arr->slot[index]) + arr->heap_pos_offset) = index; \ | ||||||
|  | 	} while(0) | ||||||
|  |  | ||||||
|  | qse_size_t sift_up (arr_t* arr, qse_size_t index) | ||||||
| { | { | ||||||
| 	size_t parent; | 	qse_size_t parent; | ||||||
| 	int n; |  | ||||||
|  |  | ||||||
| 	if (index > 0) | 	if (index > 0) | ||||||
| 	{ | 	{ | ||||||
|  | 		int n; | ||||||
|  |  | ||||||
| 		parent = HEAP_PARENT(index); | 		parent = HEAP_PARENT(index); | ||||||
| 		n = arr->comper (arr, | 		n = arr->comper (arr, | ||||||
| 			DPTR(arr->slot[index]), DLEN(arr->slot[index]), | 			DPTR(arr->slot[index]), DLEN(arr->slot[index]), | ||||||
| @ -628,6 +636,7 @@ size_t sift_up (arr_t* arr, size_t index) | |||||||
| 			while (1) | 			while (1) | ||||||
| 			{ | 			{ | ||||||
| 				arr->slot[index] = arr->slot[parent]; | 				arr->slot[index] = arr->slot[parent]; | ||||||
|  | 				HEAP_UPDATE_POS (arr, index); | ||||||
|  |  | ||||||
| 				index = parent; | 				index = parent; | ||||||
| 				parent = HEAP_PARENT(parent); | 				parent = HEAP_PARENT(parent); | ||||||
| @ -641,6 +650,7 @@ size_t sift_up (arr_t* arr, size_t index) | |||||||
| 			}  | 			}  | ||||||
|  |  | ||||||
| 			arr->slot[index] = tmp; | 			arr->slot[index] = tmp; | ||||||
|  | 			HEAP_UPDATE_POS (arr, index); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return index; | 	return index; | ||||||
| @ -684,11 +694,13 @@ size_t sift_down (arr_t* arr, size_t index) | |||||||
| 			if (n > 0) break; | 			if (n > 0) break; | ||||||
|  |  | ||||||
| 			arr->slot[index] = arr->slot[child]; | 			arr->slot[index] = arr->slot[child]; | ||||||
|  | 			HEAP_UPDATE_POS (arr, index); | ||||||
| 			index = child; | 			index = child; | ||||||
| 		} | 		} | ||||||
| 		while (index < base); | 		while (index < base); | ||||||
|  |  | ||||||
| 		arr->slot[index] = tmp; | 		arr->slot[index] = tmp; | ||||||
|  | 		HEAP_UPDATE_POS (arr, index); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return index; | 	return index; | ||||||
| @ -701,6 +713,7 @@ size_t qse_arr_pushheap (arr_t* arr, void* dptr, size_t dlen) | |||||||
| 	/* add a value at the back of the array  */ | 	/* add a value at the back of the array  */ | ||||||
| 	index = arr->size; | 	index = arr->size; | ||||||
| 	if (qse_arr_insert (arr, index, dptr, dlen) == QSE_ARR_NIL) return QSE_ARR_NIL; | 	if (qse_arr_insert (arr, index, dptr, dlen) == QSE_ARR_NIL) return QSE_ARR_NIL; | ||||||
|  | 	HEAP_UPDATE_POS (arr, index); | ||||||
|  |  | ||||||
| 	QSE_ASSERT (arr->size == index + 1); | 	QSE_ASSERT (arr->size == index + 1); | ||||||
|  |  | ||||||
| @ -715,7 +728,7 @@ void qse_arr_popheap (arr_t* arr) | |||||||
| 	qse_arr_deleteheap (arr, 0); | 	qse_arr_deleteheap (arr, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| void qse_arr_deleteheap (arr_t* arr, size_t index) | void qse_arr_deleteheap (arr_t* arr, qse_size_t index) | ||||||
| { | { | ||||||
| 	slot_t* tmp; | 	slot_t* tmp; | ||||||
|  |  | ||||||
| @ -732,6 +745,7 @@ void qse_arr_deleteheap (arr_t* arr, size_t index) | |||||||
|  |  | ||||||
| 		/* move the last item to the deleting position */ | 		/* move the last item to the deleting position */ | ||||||
| 		arr->slot[index] = arr->slot[arr->size]; | 		arr->slot[index] = arr->slot[arr->size]; | ||||||
|  | 		HEAP_UPDATE_POS (arr, index); | ||||||
|  |  | ||||||
| 		/* move it up if the last item is greater than the item to be deleted, | 		/* move it up if the last item is greater than the item to be deleted, | ||||||
| 		 * move it down otherwise. */ | 		 * move it down otherwise. */ | ||||||
| @ -750,7 +764,7 @@ void qse_arr_deleteheap (arr_t* arr, size_t index) | |||||||
| 	arr->slot[arr->size] = QSE_NULL; | 	arr->slot[arr->size] = QSE_NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| size_t qse_arr_updateheap (qse_arr_t* arr, qse_size_t index, void* dptr, qse_size_t dlen) | qse_size_t qse_arr_updateheap (qse_arr_t* arr, qse_size_t index, void* dptr, qse_size_t dlen) | ||||||
| { | { | ||||||
| 	slot_t* tmp; | 	slot_t* tmp; | ||||||
| 	int n; | 	int n; | ||||||
| @ -762,9 +776,21 @@ size_t qse_arr_updateheap (qse_arr_t* arr, qse_size_t index, void* dptr, qse_siz | |||||||
| 	if (n) | 	if (n) | ||||||
| 	{ | 	{ | ||||||
| 		if (qse_arr_update (arr, index, dptr, dlen) == QSE_ARR_NIL) return QSE_ARR_NIL; | 		if (qse_arr_update (arr, index, dptr, dlen) == QSE_ARR_NIL) return QSE_ARR_NIL; | ||||||
|  | 		HEAP_UPDATE_POS (arr, index); | ||||||
|  |  | ||||||
| 		if (n > 0) sift_up (arr, index); | 		if (n > 0) sift_up (arr, index); | ||||||
| 		else sift_down (arr, index); | 		else sift_down (arr, index); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return index; | 	return index; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | qse_size_t qse_arr_getheapposoffset (qse_arr_t* arr) | ||||||
|  | { | ||||||
|  | 	return arr->heap_pos_offset; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void qse_arr_setheapposoffset (qse_arr_t* arr, qse_size_t offset) | ||||||
|  | { | ||||||
|  | 	arr->heap_pos_offset = offset; | ||||||
|  | } | ||||||
|  | |||||||
| @ -19,20 +19,20 @@ void keeper1 (qse_arr_t* arr, void* dptr, qse_size_t dlen) | |||||||
| qse_arr_walk_t walker1 (qse_arr_t* arr, qse_size_t index, void* arg) | qse_arr_walk_t walker1 (qse_arr_t* arr, qse_size_t index, void* arg) | ||||||
| { | { | ||||||
| 	qse_printf (QSE_T("%d => [%.*s]\n"),  | 	qse_printf (QSE_T("%d => [%.*s]\n"),  | ||||||
| 		index, (int)QSE_ARR_DLEN(arr,index), QSE_ARR_DPTR(arr,index)); | 		(int)index, (int)QSE_ARR_DLEN(arr,index), QSE_ARR_DPTR(arr,index)); | ||||||
| 	return QSE_ARR_WALK_FORWARD; | 	return QSE_ARR_WALK_FORWARD; | ||||||
| } | } | ||||||
| qse_arr_walk_t rwalker1 (qse_arr_t* arr, qse_size_t index, void* arg) | qse_arr_walk_t rwalker1 (qse_arr_t* arr, qse_size_t index, void* arg) | ||||||
| { | { | ||||||
| 	qse_printf (QSE_T("%d => [%.*s]\n"),  | 	qse_printf (QSE_T("%d => [%.*s]\n"),  | ||||||
| 		index, (int)QSE_ARR_DLEN(arr,index), QSE_ARR_DPTR(arr,index)); | 		(int)index, (int)QSE_ARR_DLEN(arr,index), QSE_ARR_DPTR(arr,index)); | ||||||
| 	return QSE_ARR_WALK_BACKWARD; | 	return QSE_ARR_WALK_BACKWARD; | ||||||
| } | } | ||||||
|  |  | ||||||
| qse_arr_walk_t walker3 (qse_arr_t* arr, qse_size_t index, void* arg) | qse_arr_walk_t walker3 (qse_arr_t* arr, qse_size_t index, void* arg) | ||||||
| { | { | ||||||
| 	qse_printf (QSE_T("%d => [%d]\n"),  | 	qse_printf (QSE_T("%d => [%d]\n"),  | ||||||
| 		index, *(int*)QSE_ARR_DPTR(arr,index)); | 		(int)index, *(int*)QSE_ARR_DPTR(arr,index)); | ||||||
| 	return QSE_ARR_WALK_FORWARD; | 	return QSE_ARR_WALK_FORWARD; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -476,6 +476,113 @@ static int test5 () | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | struct test6_data_t | ||||||
|  | { | ||||||
|  | 	int v; | ||||||
|  | 	qse_size_t pos;	 | ||||||
|  | }; | ||||||
|  | typedef struct test6_data_t test6_data_t; | ||||||
|  |  | ||||||
|  | static int test6_comparator (qse_arr_t* arr, | ||||||
|  |         const void* dptr1, size_t dlen1, | ||||||
|  |         const void* dptr2, size_t dlen2) | ||||||
|  | { | ||||||
|  | 	return ((test6_data_t*)dptr1)->v > ((test6_data_t*)dptr2)->v? 1: | ||||||
|  | 	       ((test6_data_t*)dptr1)->v < ((test6_data_t*)dptr2)->v? -1: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | qse_arr_walk_t test6_walker (qse_arr_t* arr, qse_size_t index, void* arg) | ||||||
|  | { | ||||||
|  | 	test6_data_t* x; | ||||||
|  |  | ||||||
|  | 	x = QSE_ARR_DPTR(arr,index); | ||||||
|  | 	qse_printf (QSE_T("%d => [%d] pos=%d\n"), (int)index, (int)x->v, (int)x->pos); | ||||||
|  | 	QSE_ASSERT (index == x->pos); | ||||||
|  | 	return QSE_ARR_WALK_FORWARD; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int test6 () | ||||||
|  | { | ||||||
|  | 	qse_arr_t* s1; | ||||||
|  | 	int i, oldv, newv; | ||||||
|  | 	test6_data_t j; | ||||||
|  |  | ||||||
|  | 	s1 = qse_arr_open (QSE_MMGR_GETDFL(), 0, 3); | ||||||
|  | 	if (s1 == QSE_NULL) | ||||||
|  | 	{ | ||||||
|  | 		qse_printf (QSE_T("cannot open an array\n")); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_arr_setcopier (s1, QSE_ARR_COPIER_INLINE); | ||||||
|  | 	qse_arr_setscale (s1, QSE_SIZEOF(j)); | ||||||
|  | 	qse_arr_setcomper (s1, test6_comparator); | ||||||
|  | 	qse_arr_setheapposoffset (s1, QSE_OFFSETOF(test6_data_t, pos)); | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < 100; i++) | ||||||
|  | 	{ | ||||||
|  | 		j.v = rand () % 65535; | ||||||
|  | 		qse_arr_pushheap (s1, &j, 1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	j.v = 88888888; | ||||||
|  | 	qse_arr_updateheap (s1, QSE_ARR_SIZE(s1) / 2, &j, 1); | ||||||
|  | 	j.v = -123; | ||||||
|  | 	qse_arr_updateheap (s1, QSE_ARR_SIZE(s1) / 2, &j, 1); | ||||||
|  |  | ||||||
|  | 	qse_printf (QSE_T("arr size => %lu\n"), QSE_ARR_SIZE(s1)); | ||||||
|  | 	qse_arr_walk (s1, test6_walker, QSE_NULL); | ||||||
|  |  | ||||||
|  | 	oldv = 99999999; | ||||||
|  | 	while (QSE_ARR_SIZE(s1) > 50) | ||||||
|  | 	{ | ||||||
|  | 		newv = ((test6_data_t*)QSE_ARR_DPTR(s1,0))->v; | ||||||
|  | 		qse_printf (QSE_T("top => %d prevtop => %d\n"), newv, oldv); | ||||||
|  | 		QSE_ASSERT (newv <= oldv); | ||||||
|  | 		qse_arr_popheap (s1); | ||||||
|  | 		oldv = newv; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_printf (QSE_T("arr size => %lu\n"), QSE_ARR_SIZE(s1)); | ||||||
|  | 	qse_arr_walk (s1, test6_walker, QSE_NULL); | ||||||
|  |  | ||||||
|  | 	while (QSE_ARR_SIZE(s1) > 10) | ||||||
|  | 	{ | ||||||
|  | 		newv = ((test6_data_t*)QSE_ARR_DPTR(s1,0))->v; | ||||||
|  | 		qse_printf (QSE_T("top => %d prevtop => %d\n"), newv, oldv); | ||||||
|  | 		QSE_ASSERT (newv <= oldv); | ||||||
|  | 		qse_arr_popheap (s1); | ||||||
|  | 		oldv = newv; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_printf (QSE_T("arr size => %lu\n"), QSE_ARR_SIZE(s1)); | ||||||
|  | 	qse_arr_walk (s1, test6_walker, QSE_NULL); | ||||||
|  |  | ||||||
|  | 	while (QSE_ARR_SIZE(s1) > 1) | ||||||
|  | 	{ | ||||||
|  | 		newv = ((test6_data_t*)QSE_ARR_DPTR(s1,0))->v; | ||||||
|  | 		qse_printf (QSE_T("top => %d prevtop => %d\n"), newv, oldv); | ||||||
|  | 		QSE_ASSERT (newv <= oldv); | ||||||
|  | 		qse_arr_popheap (s1); | ||||||
|  | 		oldv = newv; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_printf (QSE_T("arr size => %lu\n"), QSE_ARR_SIZE(s1)); | ||||||
|  | 	qse_arr_walk (s1, test6_walker, QSE_NULL); | ||||||
|  |  | ||||||
|  | 	while (QSE_ARR_SIZE(s1) > 0) | ||||||
|  | 	{ | ||||||
|  | 		newv = ((test6_data_t*)QSE_ARR_DPTR(s1,0))->v; | ||||||
|  | 		qse_printf (QSE_T("top => %d prevtop => %d\n"), newv, oldv); | ||||||
|  | 		QSE_ASSERT (newv <= oldv); | ||||||
|  | 		qse_arr_popheap (s1); | ||||||
|  | 		oldv = newv; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_arr_close (s1); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| int main () | int main () | ||||||
| { | { | ||||||
| 	qse_openstdsios (); | 	qse_openstdsios (); | ||||||
| @ -484,6 +591,7 @@ int main () | |||||||
| 	R (test3); | 	R (test3); | ||||||
| 	R (test4); | 	R (test4); | ||||||
| 	R (test5); | 	R (test5); | ||||||
|  | 	R (test6); | ||||||
| 	qse_closestdsios (); | 	qse_closestdsios (); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user