More refactoring
This commit is contained in:
1 parent
c1070c4858
commit
e4d58db474
34 files changed
+5295
-74
No files matched your search
@@ -288,3 +288,8 @@ You can use them as Stacks, Queues and Deques, but with modern memory hierarchy
|
||||
### You can't structurally modify a collection when iterating over it
|
||||
|
||||
Modifying a collection will possibly invalidate all iterators currently initialized by it. Currently, the only collection that allows this is the LinkedList (using the node-based functions, not the iterator).
|
||||
|
||||
## Special Macros
|
||||
|
||||
* `CMC_NO_ALLOC` - disables `"cor/alloc.h"`
|
||||
* `CMC_NO_IMPORTS` - disables all imports from the standard library at `"cor/core.h"`
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bitset.h
|
||||
*
|
||||
* Creation Date: 30/04/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* BitSet
|
||||
*
|
||||
* A Bit Set is an array where each bit can be individually modified and queried
|
||||
* by using bitwise operators such as |, &, ^, ~, >> and << (or, and, xor, not,
|
||||
* right shift, left shift respectively).
|
||||
*
|
||||
* Implementation
|
||||
*
|
||||
* This BitSet implementation uses an array of type cmc_bitset_word which can be
|
||||
* typedefed to any unsigned type such as uint8_t, uint16_t, uint32_t, uint64_t,
|
||||
* size_t, etc. The BitSet does not make use of K or V. Because of that, it also
|
||||
* doesn't have Functions Tables.
|
||||
*
|
||||
* The BitSet is initialized with a custom capacity but, if a bit index accessed
|
||||
* is greater than the total capacity, the BitSet will resize. This means that
|
||||
* the BitSet will try to guarantee that every bit index is accessible, as long
|
||||
* as there is enough memory.
|
||||
*/
|
||||
|
||||
#include "cor/bitset.h"
|
||||
#include "cor/core.h"
|
||||
|
||||
/**
|
||||
* Used values
|
||||
* SNAME - struct name and prefix of other related structs
|
||||
* PFX - functions prefix
|
||||
*/
|
||||
|
||||
/* Structs definition */
|
||||
#include "cmc/bitset/struct.h"
|
||||
|
||||
/* Function declaration */
|
||||
#include "cmc/bitset/header.h"
|
||||
|
||||
/* Function implementation */
|
||||
#include "cmc/bitset/code.h"
|
||||
|
||||
/**
|
||||
* Extensions
|
||||
*
|
||||
* INIT - Initializes the struct on the stack
|
||||
* ITER - bitset iterator
|
||||
* STR - Print helper functions
|
||||
*/
|
||||
#define CMC_EXT_BITSET_PARTS INIT, ITER, STR
|
||||
/**/
|
||||
#include "cmc/bitset/ext/struct.h"
|
||||
/**/
|
||||
#include "cmc/bitset/ext/header.h"
|
||||
/**/
|
||||
#include "cmc/bitset/ext/code.h"
|
||||
|
||||
#include "cor/undef.h"
|
||||
@@ -0,0 +1,431 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Implementation Detail Functions */
|
||||
bool CMC_(PFX, _impl_resize)(struct SNAME *_bitset_, size_t n_bits, bool do_resize);
|
||||
|
||||
struct SNAME *CMC_(PFX, _new)(size_t n_bits)
|
||||
{
|
||||
return CMC_(PFX, _new_custom)(n_bits, NULL, NULL);
|
||||
}
|
||||
|
||||
struct SNAME *CMC_(PFX, _new_custom)(size_t n_bits, struct CMC_ALLOC_NODE_NAME *alloc,
|
||||
struct CMC_CALLBACKS_NAME *callbacks)
|
||||
{
|
||||
CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
|
||||
|
||||
if (n_bits < 1)
|
||||
return NULL;
|
||||
|
||||
if (!alloc)
|
||||
alloc = &cmc_alloc_node_default;
|
||||
|
||||
size_t capacity = cmc_bidx_to_widx(n_bits - 1) + 1;
|
||||
|
||||
struct SNAME *_bitset_ = alloc->malloc(sizeof(struct SNAME));
|
||||
|
||||
if (!_bitset_)
|
||||
return NULL;
|
||||
|
||||
_bitset_->buffer = alloc->calloc(capacity, sizeof(cmc_bitset_word));
|
||||
|
||||
if (!_bitset_->buffer)
|
||||
{
|
||||
alloc->free(_bitset_);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_bitset_->capacity = capacity;
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
_bitset_->alloc = alloc;
|
||||
CMC_CALLBACKS_ASSIGN(_bitset_, callbacks);
|
||||
|
||||
return _bitset_;
|
||||
}
|
||||
|
||||
struct SNAME CMC_(PFX, _init)(size_t n_bits)
|
||||
{
|
||||
return CMC_(PFX, _init_custom)(n_bits, NULL, NULL);
|
||||
}
|
||||
|
||||
struct SNAME CMC_(PFX, _init_custom)(size_t n_bits, struct CMC_ALLOC_NODE_NAME *alloc,
|
||||
struct CMC_CALLBACKS_NAME *CMC_UNUSED(callbacks))
|
||||
{
|
||||
CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
|
||||
|
||||
struct SNAME _bitset_ = { 0 };
|
||||
|
||||
if (n_bits < 1)
|
||||
return _bitset_;
|
||||
|
||||
if (!alloc)
|
||||
alloc = &cmc_alloc_node_default;
|
||||
|
||||
size_t capacity = cmc_bidx_to_widx(n_bits - 1) + 1;
|
||||
|
||||
_bitset_.buffer = alloc->calloc(capacity, sizeof(cmc_bitset_word));
|
||||
|
||||
if (!_bitset_.buffer)
|
||||
return _bitset_;
|
||||
|
||||
_bitset_.capacity = capacity;
|
||||
_bitset_.flag = CMC_FLAG_OK;
|
||||
_bitset_.alloc = alloc;
|
||||
CMC_CALLBACKS_ASSIGN(&_bitset_, callbacks);
|
||||
|
||||
return _bitset_;
|
||||
}
|
||||
|
||||
void CMC_(PFX, _free)(struct SNAME *_bitset_)
|
||||
{
|
||||
free(_bitset_->buffer);
|
||||
free(_bitset_);
|
||||
}
|
||||
|
||||
void CMC_(PFX, _release)(struct SNAME _bitset_)
|
||||
{
|
||||
free(_bitset_.buffer);
|
||||
}
|
||||
|
||||
void CMC_(PFX, _customize)(struct SNAME *_bitset_, struct CMC_ALLOC_NODE_NAME *alloc,
|
||||
struct CMC_CALLBACKS_NAME *callbacks)
|
||||
{
|
||||
CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
|
||||
|
||||
if (!alloc)
|
||||
_bitset_->alloc = &cmc_alloc_node_default;
|
||||
else
|
||||
_bitset_->alloc = alloc;
|
||||
|
||||
CMC_CALLBACKS_ASSIGN(_bitset_, callbacks);
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _set)(struct SNAME *_bitset_, size_t bit_index)
|
||||
{
|
||||
if (!CMC_(PFX, _impl_resize)(_bitset_, bit_index + 1, false))
|
||||
return false;
|
||||
|
||||
/* How many bits in a word */
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT;
|
||||
|
||||
size_t i = cmc_bidx_to_widx(bit_index);
|
||||
|
||||
_bitset_->buffer[i] |= ((cmc_bitset_word)1) << (bit_index % bits);
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_bitset_, create);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _set_range)(struct SNAME *_bitset_, size_t from, size_t to)
|
||||
{
|
||||
if (to < from)
|
||||
{
|
||||
_bitset_->flag = CMC_FLAG_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CMC_(PFX, _impl_resize)(_bitset_, to + 1, false))
|
||||
return false;
|
||||
|
||||
size_t start_index = cmc_bidx_to_widx(from);
|
||||
size_t end_index = cmc_bidx_to_widx(to);
|
||||
|
||||
/* How many bits in a word */
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT;
|
||||
|
||||
/* 1111 ... 1111 */
|
||||
const cmc_bitset_word ones = ~((cmc_bitset_word)0);
|
||||
|
||||
cmc_bitset_word shift_start = from % bits;
|
||||
cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits;
|
||||
|
||||
cmc_bitset_word start_mask = ones << shift_start;
|
||||
cmc_bitset_word end_mask = ones >> shift_end;
|
||||
|
||||
if (start_index == end_index)
|
||||
{
|
||||
_bitset_->buffer[end_index] |= (start_mask & end_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
_bitset_->buffer[start_index] |= start_mask;
|
||||
|
||||
for (size_t i = start_index + 1; i < end_index; i++)
|
||||
_bitset_->buffer[i] |= ~((cmc_bitset_word)0);
|
||||
|
||||
_bitset_->buffer[end_index] |= end_mask;
|
||||
}
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_bitset_, create);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _clear)(struct SNAME *_bitset_, size_t bit_index)
|
||||
{
|
||||
if (!CMC_(PFX, _impl_resize)(_bitset_, bit_index + 1, false))
|
||||
return false;
|
||||
|
||||
/* How many bits in a word */
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT;
|
||||
|
||||
size_t i = cmc_bidx_to_widx(bit_index);
|
||||
|
||||
_bitset_->buffer[i] &= ~(((cmc_bitset_word)1) << (bit_index % bits));
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_bitset_, delete);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _clear_range)(struct SNAME *_bitset_, size_t from, size_t to)
|
||||
{
|
||||
if (to < from)
|
||||
{
|
||||
_bitset_->flag = CMC_FLAG_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CMC_(PFX, _impl_resize)(_bitset_, to + 1, false))
|
||||
return false;
|
||||
|
||||
size_t start_index = cmc_bidx_to_widx(from);
|
||||
size_t end_index = cmc_bidx_to_widx(to);
|
||||
|
||||
/* How many bits in a word */
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT;
|
||||
|
||||
/* 1111 ... 1111 */
|
||||
const cmc_bitset_word ones = ~((cmc_bitset_word)0);
|
||||
|
||||
cmc_bitset_word shift_start = from % bits;
|
||||
cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits;
|
||||
|
||||
cmc_bitset_word start_mask = ones << shift_start;
|
||||
cmc_bitset_word end_mask = ones >> shift_end;
|
||||
|
||||
if (start_index == end_index)
|
||||
{
|
||||
_bitset_->buffer[end_index] &= ~(start_mask & end_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
_bitset_->buffer[start_index] &= ~start_mask;
|
||||
|
||||
for (size_t i = start_index + 1; i < end_index; i++)
|
||||
_bitset_->buffer[i] = 0;
|
||||
|
||||
_bitset_->buffer[end_index] &= ~end_mask;
|
||||
}
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_bitset_, delete);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _flip)(struct SNAME *_bitset_, size_t bit_index)
|
||||
{
|
||||
if (!CMC_(PFX, _impl_resize)(_bitset_, bit_index + 1, false))
|
||||
return false;
|
||||
|
||||
/* How many bits in a word */
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT;
|
||||
|
||||
size_t i = cmc_bidx_to_widx(bit_index);
|
||||
|
||||
_bitset_->buffer[i] ^= ((cmc_bitset_word)1) << (bit_index % bits);
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_bitset_, update);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _flip_range)(struct SNAME *_bitset_, size_t from, size_t to)
|
||||
{
|
||||
if (to < from)
|
||||
{
|
||||
_bitset_->flag = CMC_FLAG_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CMC_(PFX, _impl_resize)(_bitset_, to + 1, false))
|
||||
return false;
|
||||
|
||||
size_t start_index = cmc_bidx_to_widx(from);
|
||||
size_t end_index = cmc_bidx_to_widx(to);
|
||||
|
||||
/* How many bits in a word */
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT;
|
||||
|
||||
/* 1111 ... 1111 */
|
||||
const cmc_bitset_word ones = ~((cmc_bitset_word)0);
|
||||
|
||||
cmc_bitset_word shift_start = from % bits;
|
||||
cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits;
|
||||
|
||||
cmc_bitset_word start_mask = ones << shift_start;
|
||||
cmc_bitset_word end_mask = ones >> shift_end;
|
||||
|
||||
if (start_index == end_index)
|
||||
{
|
||||
_bitset_->buffer[end_index] ^= (start_mask & end_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
_bitset_->buffer[start_index] ^= start_mask;
|
||||
|
||||
for (size_t i = start_index + 1; i < end_index; i++)
|
||||
_bitset_->buffer[i] ^= ones;
|
||||
|
||||
_bitset_->buffer[end_index] ^= end_mask;
|
||||
}
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_bitset_, update);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _put)(struct SNAME *_bitset_, size_t bit_index, bool state)
|
||||
{
|
||||
if (state)
|
||||
return CMC_(PFX, _set)(_bitset_, bit_index);
|
||||
else
|
||||
return CMC_(PFX, _clear)(_bitset_, bit_index);
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _put_range)(struct SNAME *_bitset_, size_t from, size_t to, bool state)
|
||||
{
|
||||
if (state)
|
||||
return CMC_(PFX, _set_range)(_bitset_, from, to);
|
||||
else
|
||||
return CMC_(PFX, _clear_range)(_bitset_, from, to);
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _set_all)(struct SNAME *_bitset_)
|
||||
{
|
||||
for (size_t i = 0; i < _bitset_->capacity; i++)
|
||||
_bitset_->buffer[i] = ~((cmc_bitset_word)0);
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_bitset_, create);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _clear_all)(struct SNAME *_bitset_)
|
||||
{
|
||||
for (size_t i = 0; i < _bitset_->capacity; i++)
|
||||
_bitset_->buffer[i] = 0;
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_bitset_, delete);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _flip_all)(struct SNAME *_bitset_)
|
||||
{
|
||||
for (size_t i = 0; i < _bitset_->capacity; i++)
|
||||
_bitset_->buffer[i] ^= ~((cmc_bitset_word)0);
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_bitset_, create);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _get)(struct SNAME *_bitset_, size_t bit_index)
|
||||
{
|
||||
/* How many bits in a word */
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT;
|
||||
|
||||
cmc_bitset_word w = _bitset_->buffer[cmc_bidx_to_widx(bit_index)];
|
||||
|
||||
return w & ((cmc_bitset_word)1 << (bit_index % bits));
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _resize)(struct SNAME *_bitset_, size_t n_bits)
|
||||
{
|
||||
return CMC_(PFX, _impl_resize)(_bitset_, n_bits, true);
|
||||
}
|
||||
|
||||
/* When do_resize is false, then we just want to assure that the bitset */
|
||||
/* can accommodate n_bits */
|
||||
bool CMC_(PFX, _impl_resize)(struct SNAME *_bitset_, size_t n_bits, bool do_resize)
|
||||
{
|
||||
if (n_bits == 0)
|
||||
{
|
||||
_bitset_->flag = CMC_FLAG_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -1 because n_bits is 1-based and we need to pass a 0-based index */
|
||||
/* +1 to have a 1-based result */
|
||||
size_t words = cmc_bidx_to_widx(n_bits - 1) + 1;
|
||||
|
||||
/* Be sure we are not always shrinking when we just want to make */
|
||||
/* sure that we have enough size for n_bits */
|
||||
if (!do_resize && words <= _bitset_->capacity)
|
||||
return true;
|
||||
|
||||
cmc_bitset_word *new_buffer = realloc(_bitset_->buffer, words * sizeof(cmc_bitset_word));
|
||||
|
||||
if (!new_buffer)
|
||||
{
|
||||
_bitset_->flag = CMC_FLAG_ALLOC;
|
||||
return false;
|
||||
}
|
||||
|
||||
_bitset_->buffer = new_buffer;
|
||||
|
||||
/* Make new bits be all zeroes */
|
||||
if (_bitset_->capacity < words)
|
||||
memset(_bitset_->buffer + _bitset_->capacity, 0, (words - _bitset_->capacity) * sizeof(cmc_bitset_word));
|
||||
|
||||
_bitset_->capacity = words;
|
||||
|
||||
CMC_CALLBACKS_CALL(_bitset_, resize);
|
||||
|
||||
_bitset_->flag = CMC_FLAG_OK;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* INIT
|
||||
*
|
||||
* The part 'INIT' gives a new way of initializing a collection. The collection
|
||||
* struct is not heap allocated, only its internal structure (nodes, buffers).
|
||||
*/
|
||||
#ifdef CMC_EXT_BITSET_INIT
|
||||
|
||||
#endif /* CMC_EXT_BITSET_INIT */
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*
|
||||
* Bitset bi-directional iterator.
|
||||
*/
|
||||
#ifdef CMC_EXT_BITSET_ITER
|
||||
|
||||
/* Iterator Functions */
|
||||
/* Iterator Initialization */
|
||||
/* Iterator State */
|
||||
/* Iterator Movement */
|
||||
/* Iterator Access */
|
||||
|
||||
#endif /* CMC_EXT_BITSET_ITER */
|
||||
|
||||
/**
|
||||
* STR
|
||||
*
|
||||
* Print helper functions.
|
||||
*/
|
||||
#ifdef CMC_EXT_BITSET_STR
|
||||
|
||||
#endif /* CMC_EXT_BITSET_STR */
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* INIT
|
||||
*
|
||||
* The part 'INIT' gives a new way of initializing a collection. The collection
|
||||
* struct is not heap allocated, only its internal structure (nodes, buffers).
|
||||
*/
|
||||
#ifdef CMC_EXT_BITSET_INIT
|
||||
|
||||
#endif /* CMC_EXT_BITSET_INIT */
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*
|
||||
* Bitset bi-directional iterator.
|
||||
*/
|
||||
#ifdef CMC_EXT_BITSET_ITER
|
||||
|
||||
/* Iterator Functions */
|
||||
/* Iterator Initialization */
|
||||
/* Iterator State */
|
||||
/* Iterator Movement */
|
||||
/* Iterator Access */
|
||||
|
||||
#endif /* CMC_EXT_BITSET_ITER */
|
||||
|
||||
/**
|
||||
* STR
|
||||
*
|
||||
* Print helper functions.
|
||||
*/
|
||||
#ifdef CMC_EXT_BITSET_STR
|
||||
|
||||
#endif /* CMC_EXT_BITSET_STR */
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*
|
||||
* Bitset bi-directional iterator.
|
||||
*/
|
||||
#ifdef CMC_EXT_BITSET_ITER
|
||||
|
||||
/* BitSet Iterator */
|
||||
struct CMC_DEF_ITER(SNAME)
|
||||
{
|
||||
/* Target bitset */
|
||||
struct SNAME *target;
|
||||
/* Cursor's position (index) */
|
||||
size_t cursor;
|
||||
/* If the iterator has reached the start of the iteration */
|
||||
bool start;
|
||||
/* If the iterator has reached the end of the iteration */
|
||||
bool end;
|
||||
};
|
||||
|
||||
#endif /* CMC_EXT_BITSET_ITER */
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Collection Allocation and Deallocation */
|
||||
struct SNAME *CMC_(PFX, _new)(size_t n_bits);
|
||||
struct SNAME *CMC_(PFX, _new_custom)(size_t n_bits, struct CMC_ALLOC_NODE_NAME *alloc,
|
||||
struct CMC_CALLBACKS_NAME *callbacks);
|
||||
struct SNAME CMC_(PFX, _init)(size_t n_bits);
|
||||
struct SNAME CMC_(PFX, _init_custom)(size_t n_bits, struct CMC_ALLOC_NODE_NAME *alloc,
|
||||
struct CMC_CALLBACKS_NAME *callbacks);
|
||||
void CMC_(PFX, _free)(struct SNAME *_bitset_);
|
||||
void CMC_(PFX, _release)(struct SNAME _bitset_);
|
||||
void CMC_(PFX, _customize)(struct SNAME *_bitset_, struct CMC_ALLOC_NODE_NAME *alloc,
|
||||
struct CMC_CALLBACKS_NAME *callbacks);
|
||||
/* Collection Input and Output */
|
||||
bool CMC_(PFX, _set)(struct SNAME *_bitset_, size_t bit_index);
|
||||
bool CMC_(PFX, _set_range)(struct SNAME *_bitset_, size_t from, size_t to);
|
||||
bool CMC_(PFX, _clear)(struct SNAME *_bitset_, size_t bit_index);
|
||||
bool CMC_(PFX, _clear_range)(struct SNAME *_bitset_, size_t from, size_t to);
|
||||
bool CMC_(PFX, _flip)(struct SNAME *_bitset_, size_t bit_index);
|
||||
bool CMC_(PFX, _flip_range)(struct SNAME *_bitset_, size_t from, size_t to);
|
||||
bool CMC_(PFX, _put)(struct SNAME *_bitset_, size_t bit_index, bool state);
|
||||
bool CMC_(PFX, _put_range)(struct SNAME *_bitset_, size_t from, size_t to, bool state);
|
||||
bool CMC_(PFX, _set_all)(struct SNAME *_bitset_);
|
||||
bool CMC_(PFX, _clear_all)(struct SNAME *_bitset_);
|
||||
bool CMC_(PFX, _flip_all)(struct SNAME *_bitset_);
|
||||
/* Element Access */
|
||||
bool CMC_(PFX, _get)(struct SNAME *_bitset_, size_t bit_index);
|
||||
/* Collection State */
|
||||
/* Collection Utility */
|
||||
bool CMC_(PFX, _resize)(struct SNAME *_bitset_, size_t n_bits);
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* BitSet Structure */
|
||||
struct SNAME
|
||||
{
|
||||
/* Dynamic Array of Bits */
|
||||
cmc_bitset_word *buffer;
|
||||
/* Current array capacity */
|
||||
size_t capacity;
|
||||
/* Currently used bits */
|
||||
/* This should always be true: */
|
||||
/* capacity - count < sizeof(cmc_bitset_word) * CHAR_BIT */
|
||||
size_t count;
|
||||
/* Flags indicating errors or success */
|
||||
int flag;
|
||||
/* Custom allocation functions */
|
||||
struct CMC_ALLOC_NODE_NAME *alloc;
|
||||
/* Custom callback functions */
|
||||
CMC_CALLBACKS_DECL;
|
||||
};
|
||||
@@ -0,0 +1,362 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Implementation Detail Functions */
|
||||
static void CMC_(PFX, _impl_float_up)(struct SNAME *_heap_, size_t index);
|
||||
static void CMC_(PFX, _impl_float_down)(struct SNAME *_heap_, size_t index);
|
||||
|
||||
struct SNAME *CMC_(PFX, _new)(size_t capacity, enum cmc_heap_order HO, struct CMC_DEF_FVAL(SNAME) * f_val)
|
||||
{
|
||||
return CMC_(PFX, _new_custom)(capacity, HO, f_val, NULL, NULL);
|
||||
}
|
||||
|
||||
struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, enum cmc_heap_order HO, struct CMC_DEF_FVAL(SNAME) * f_val,
|
||||
struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks)
|
||||
{
|
||||
CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
|
||||
|
||||
if (capacity < 1)
|
||||
return NULL;
|
||||
|
||||
if (HO != CMC_MIN_HEAP && HO != CMC_MAX_HEAP)
|
||||
return NULL;
|
||||
|
||||
if (!f_val)
|
||||
return NULL;
|
||||
|
||||
if (!alloc)
|
||||
alloc = &cmc_alloc_node_default;
|
||||
|
||||
struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME));
|
||||
|
||||
if (!_heap_)
|
||||
return NULL;
|
||||
|
||||
_heap_->buffer = alloc->calloc(capacity, sizeof(V));
|
||||
|
||||
if (!_heap_->buffer)
|
||||
{
|
||||
alloc->free(_heap_);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_heap_->capacity = capacity;
|
||||
_heap_->count = 0;
|
||||
_heap_->HO = HO;
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
_heap_->f_val = f_val;
|
||||
_heap_->alloc = alloc;
|
||||
CMC_CALLBACKS_ASSIGN(_heap_, callbacks);
|
||||
|
||||
return _heap_;
|
||||
}
|
||||
|
||||
void CMC_(PFX, _clear)(struct SNAME *_heap_)
|
||||
{
|
||||
if (_heap_->f_val->free)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
_heap_->f_val->free(_heap_->buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
memset(_heap_->buffer, 0, sizeof(V) * _heap_->capacity);
|
||||
|
||||
_heap_->count = 0;
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
}
|
||||
|
||||
void CMC_(PFX, _free)(struct SNAME *_heap_)
|
||||
{
|
||||
if (_heap_->f_val->free)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
_heap_->f_val->free(_heap_->buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
_heap_->alloc->free(_heap_->buffer);
|
||||
_heap_->alloc->free(_heap_);
|
||||
}
|
||||
|
||||
void CMC_(PFX, _customize)(struct SNAME *_heap_, struct CMC_ALLOC_NODE_NAME *alloc,
|
||||
struct CMC_CALLBACKS_NAME *callbacks)
|
||||
{
|
||||
CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
|
||||
|
||||
if (!alloc)
|
||||
_heap_->alloc = &cmc_alloc_node_default;
|
||||
else
|
||||
_heap_->alloc = alloc;
|
||||
|
||||
CMC_CALLBACKS_ASSIGN(_heap_, callbacks);
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _insert)(struct SNAME *_heap_, V value)
|
||||
{
|
||||
if (CMC_(PFX, _full)(_heap_))
|
||||
{
|
||||
if (!CMC_(PFX, _resize)(_heap_, _heap_->count * 2))
|
||||
return false;
|
||||
}
|
||||
|
||||
_heap_->buffer[_heap_->count++] = value;
|
||||
|
||||
if (_heap_->count > 1)
|
||||
{
|
||||
CMC_(PFX, _impl_float_up)(_heap_, _heap_->count - 1);
|
||||
}
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, create);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _remove)(struct SNAME *_heap_)
|
||||
{
|
||||
if (CMC_(PFX, _empty)(_heap_))
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_EMPTY;
|
||||
return false;
|
||||
}
|
||||
|
||||
_heap_->buffer[0] = _heap_->buffer[_heap_->count - 1];
|
||||
_heap_->buffer[_heap_->count - 1] = (V){ 0 };
|
||||
|
||||
_heap_->count--;
|
||||
|
||||
CMC_(PFX, _impl_float_down)(_heap_, 0);
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, delete);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
V CMC_(PFX, _peek)(struct SNAME *_heap_)
|
||||
{
|
||||
if (CMC_(PFX, _empty)(_heap_))
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_EMPTY;
|
||||
return (V){ 0 };
|
||||
}
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, read);
|
||||
|
||||
return _heap_->buffer[0];
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _contains)(struct SNAME *_heap_, V value)
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
if (_heap_->f_val->cmp(_heap_->buffer[i], value) == 0)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, read);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _empty)(struct SNAME *_heap_)
|
||||
{
|
||||
return _heap_->count == 0;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _full)(struct SNAME *_heap_)
|
||||
{
|
||||
return _heap_->count >= _heap_->capacity;
|
||||
}
|
||||
|
||||
size_t CMC_(PFX, _count)(struct SNAME *_heap_)
|
||||
{
|
||||
return _heap_->count;
|
||||
}
|
||||
|
||||
size_t CMC_(PFX, _capacity)(struct SNAME *_heap_)
|
||||
{
|
||||
return _heap_->capacity;
|
||||
}
|
||||
|
||||
int CMC_(PFX, _flag)(struct SNAME *_heap_)
|
||||
{
|
||||
return _heap_->flag;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _resize)(struct SNAME *_heap_, size_t capacity)
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
if (_heap_->capacity == capacity)
|
||||
goto success;
|
||||
|
||||
if (capacity < _heap_->count)
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
V *new_buffer = _heap_->alloc->realloc(_heap_->buffer, sizeof(V) * capacity);
|
||||
|
||||
if (!new_buffer)
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_ALLOC;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO zero out new slots */
|
||||
|
||||
_heap_->buffer = new_buffer;
|
||||
_heap_->capacity = capacity;
|
||||
|
||||
success:
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, resize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_heap_)
|
||||
{
|
||||
struct SNAME *result = CMC_(PFX, _new_custom)(_heap_->capacity, _heap_->HO, _heap_->f_val, _heap_->alloc, NULL);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CMC_CALLBACKS_ASSIGN(result, _heap_->callbacks);
|
||||
|
||||
if (_heap_->f_val->cpy)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
result->buffer[i] = _heap_->f_val->cpy(_heap_->buffer[i]);
|
||||
}
|
||||
else
|
||||
memcpy(result->buffer, _heap_->buffer, sizeof(V) * _heap_->count);
|
||||
|
||||
result->count = _heap_->count;
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _equals)(struct SNAME *_heap1_, struct SNAME *_heap2_)
|
||||
{
|
||||
_heap1_->flag = CMC_FLAG_OK;
|
||||
_heap2_->flag = CMC_FLAG_OK;
|
||||
|
||||
if (_heap1_->count != _heap2_->count)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < _heap1_->count; i++)
|
||||
{
|
||||
if (_heap1_->f_val->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CMC_(PFX, _impl_float_up)(struct SNAME *_heap_, size_t index)
|
||||
{
|
||||
/* Current index */
|
||||
size_t C = index;
|
||||
V child = _heap_->buffer[C];
|
||||
V parent = _heap_->buffer[(index - 1) / 2];
|
||||
|
||||
int mod = _heap_->HO;
|
||||
|
||||
while (C > 0 && _heap_->f_val->cmp(child, parent) * mod > 0)
|
||||
{
|
||||
/* Swap between C (current element) and its parent */
|
||||
V tmp = _heap_->buffer[C];
|
||||
_heap_->buffer[C] = _heap_->buffer[(C - 1) / 2];
|
||||
_heap_->buffer[(C - 1) / 2] = tmp;
|
||||
|
||||
/* Go to parent */
|
||||
C = (C - 1) / 2;
|
||||
|
||||
/* Prevent the two lines below from accessing a negative index */
|
||||
if (C == 0)
|
||||
break;
|
||||
|
||||
child = _heap_->buffer[C];
|
||||
parent = _heap_->buffer[(C - 1) / 2];
|
||||
}
|
||||
}
|
||||
|
||||
static void CMC_(PFX, _impl_float_down)(struct SNAME *_heap_, size_t index)
|
||||
{
|
||||
int mod = _heap_->HO;
|
||||
|
||||
while (index < _heap_->count)
|
||||
{
|
||||
size_t L = 2 * index + 1;
|
||||
size_t R = 2 * index + 2;
|
||||
size_t C = index;
|
||||
|
||||
/* Determine if we swap with the left or right element */
|
||||
if (L < _heap_->count && _heap_->f_val->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0)
|
||||
{
|
||||
C = L;
|
||||
}
|
||||
|
||||
if (R < _heap_->count && _heap_->f_val->cmp(_heap_->buffer[R], _heap_->buffer[C]) * mod > 0)
|
||||
{
|
||||
C = R;
|
||||
}
|
||||
|
||||
/* Swap only if either left or right was picked, otherwise done */
|
||||
if (C != index)
|
||||
{
|
||||
V tmp = _heap_->buffer[index];
|
||||
_heap_->buffer[index] = _heap_->buffer[C];
|
||||
_heap_->buffer[C] = tmp;
|
||||
|
||||
index = C;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* INIT
|
||||
*
|
||||
* The part 'INIT' gives a new way of initializing a collection. The collection
|
||||
* struct is not heap allocated, only its internal structure (nodes, buffers).
|
||||
*/
|
||||
#ifdef CMC_EXT_HEAP_INIT
|
||||
|
||||
#endif /* CMC_EXT_HEAP_INIT */
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*
|
||||
* Heap bi-directional iterator.
|
||||
*/
|
||||
#ifdef CMC_EXT_HEAP_ITER
|
||||
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
|
||||
{
|
||||
struct CMC_DEF_ITER(SNAME) iter;
|
||||
|
||||
iter.target = target;
|
||||
iter.cursor = 0;
|
||||
iter.start = true;
|
||||
iter.end = CMC_(PFX, _empty)(target);
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target)
|
||||
{
|
||||
struct CMC_DEF_ITER(SNAME) iter;
|
||||
|
||||
iter.target = target;
|
||||
iter.cursor = 0;
|
||||
iter.start = CMC_(PFX, _empty)(target);
|
||||
iter.end = true;
|
||||
|
||||
if (!CMC_(PFX, _empty)(target))
|
||||
iter.cursor = target->count - 1;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
if (!CMC_(PFX, _empty)(iter->target))
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->start = true;
|
||||
iter->end = CMC_(PFX, _empty)(iter->target);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
if (!CMC_(PFX, _empty)(iter->target))
|
||||
{
|
||||
iter->cursor = iter->target->count - 1;
|
||||
iter->start = CMC_(PFX, _empty)(iter->target);
|
||||
iter->end = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
|
||||
if (iter->cursor + 1 == iter->target->count)
|
||||
{
|
||||
iter->end = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
iter->start = CMC_(PFX, _empty)(iter->target);
|
||||
|
||||
iter->cursor++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
iter->end = CMC_(PFX, _empty)(iter->target);
|
||||
|
||||
iter->cursor--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Returns true only if the iterator moved */
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
|
||||
if (iter->cursor + 1 == iter->target->count)
|
||||
{
|
||||
iter->end = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (steps == 0 || iter->cursor + steps >= iter->target->count)
|
||||
return false;
|
||||
|
||||
if (iter->end)
|
||||
return false;
|
||||
|
||||
iter->start = CMC_(PFX, _empty)(iter->target);
|
||||
|
||||
iter->cursor += steps;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Returns true only if the iterator moved */
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (steps == 0 || iter->cursor < steps)
|
||||
return false;
|
||||
|
||||
iter->end = CMC_(PFX, _empty)(iter->target);
|
||||
|
||||
iter->cursor -= steps;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Returns true only if the iterator was able to be positioned at the */
|
||||
/* given index */
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index)
|
||||
{
|
||||
if (index >= iter->target->count)
|
||||
return false;
|
||||
|
||||
if (iter->cursor > index)
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->cursor - index);
|
||||
else if (iter->cursor < index)
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->cursor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
if (CMC_(PFX, _empty)(iter->target))
|
||||
return (V){ 0 };
|
||||
|
||||
return iter->target->buffer[iter->cursor];
|
||||
}
|
||||
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
return iter->cursor;
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_HEAP_ITER */
|
||||
|
||||
/**
|
||||
* STR
|
||||
*
|
||||
* Print helper functions.
|
||||
*/
|
||||
#ifdef CMC_EXT_HEAP_STR
|
||||
|
||||
bool CMC_(PFX, _to_string)(struct SNAME *_heap_, FILE *fptr)
|
||||
{
|
||||
struct SNAME *h_ = _heap_;
|
||||
const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap";
|
||||
|
||||
return 0 <= fprintf(fptr,
|
||||
"struct %s<%s> "
|
||||
"at %p { "
|
||||
"buffer:%p, "
|
||||
"capacity:%" PRIuMAX ", "
|
||||
"count:%" PRIuMAX ", "
|
||||
"type:%s, "
|
||||
"flag:%d, "
|
||||
"f_val:%p, "
|
||||
"alloc:%p, "
|
||||
"callbacks: %p}",
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), h_, h_->buffer, h_->capacity, h_->count, t, h_->flag,
|
||||
h_->f_val, h_->alloc, CMC_CALLBACKS_GET(h_));
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _print)(struct SNAME *_heap_, FILE *fptr, const char *start, const char *separator, const char *end)
|
||||
{
|
||||
fprintf(fptr, "%s", start);
|
||||
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
if (!_heap_->f_val->str(fptr, _heap_->buffer[i]))
|
||||
return false;
|
||||
|
||||
if (i + 1 < _heap_->count)
|
||||
fprintf(fptr, "%s", separator);
|
||||
}
|
||||
|
||||
fprintf(fptr, "%s", end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_HEAP_STR */
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* INIT
|
||||
*
|
||||
* The part 'INIT' gives a new way of initializing a collection. The collection
|
||||
* struct is not heap allocated, only its internal structure (nodes, buffers).
|
||||
*/
|
||||
#ifdef CMC_EXT_HEAP_INIT
|
||||
|
||||
#endif /* CMC_EXT_HEAP_INIT */
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*
|
||||
* Heap bi-directional iterator.
|
||||
*/
|
||||
#ifdef CMC_EXT_HEAP_ITER
|
||||
|
||||
/* Iterator Initialization */
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target);
|
||||
/* Iterator State */
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
/* Iterator Movement */
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index);
|
||||
/* Iterator Access */
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#endif /* CMC_EXT_HEAP_ITER */
|
||||
|
||||
/**
|
||||
* STR
|
||||
*
|
||||
* Print helper functions.
|
||||
*/
|
||||
#ifdef CMC_EXT_HEAP_STR
|
||||
|
||||
bool CMC_(PFX, _to_string)(struct SNAME *_heap_, FILE *fptr);
|
||||
bool CMC_(PFX, _print)(struct SNAME *_heap_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_EXT_HEAP_STR */
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*
|
||||
* Heap bi-directional iterator.
|
||||
*/
|
||||
#ifdef CMC_EXT_HEAP_ITER
|
||||
|
||||
/* Heap Iterator */
|
||||
struct CMC_DEF_ITER(SNAME)
|
||||
{
|
||||
/* Target heap */
|
||||
struct SNAME *target;
|
||||
/* Cursor's position (index) */
|
||||
size_t cursor;
|
||||
/* If the iterator has reached the start of the iteration */
|
||||
bool start;
|
||||
/* If the iterator has reached the end of the iteration */
|
||||
bool end;
|
||||
};
|
||||
|
||||
#endif /* CMC_EXT_HEAP_ITER */
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Value struct function table */
|
||||
struct CMC_DEF_FVAL(SNAME)
|
||||
{
|
||||
/* Comparator function */
|
||||
CMC_DEF_FTAB_CMP(V);
|
||||
/* Copy function */
|
||||
CMC_DEF_FTAB_CPY(V);
|
||||
/* To string function */
|
||||
CMC_DEF_FTAB_STR(V);
|
||||
/* Free from memory function */
|
||||
CMC_DEF_FTAB_FREE(V);
|
||||
/* Hash function */
|
||||
CMC_DEF_FTAB_HASH(V);
|
||||
/* Priority function */
|
||||
CMC_DEF_FTAB_PRI(V);
|
||||
};
|
||||
|
||||
/* Collection Allocation and Deallocation */
|
||||
struct SNAME *CMC_(PFX, _new)(size_t capacity, enum cmc_heap_order HO, struct CMC_DEF_FVAL(SNAME) * f_val);
|
||||
struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, enum cmc_heap_order HO, struct CMC_DEF_FVAL(SNAME) * f_val,
|
||||
struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks);
|
||||
void CMC_(PFX, _clear)(struct SNAME *_heap_);
|
||||
void CMC_(PFX, _free)(struct SNAME *_heap_);
|
||||
/* Customization of Allocation and Callbacks */
|
||||
void CMC_(PFX, _customize)(struct SNAME *_heap_, struct CMC_ALLOC_NODE_NAME *alloc,
|
||||
struct CMC_CALLBACKS_NAME *callbacks);
|
||||
/* Collection Input and Output */
|
||||
bool CMC_(PFX, _insert)(struct SNAME *_heap_, V value);
|
||||
bool CMC_(PFX, _remove)(struct SNAME *_heap_);
|
||||
/* Element Access */
|
||||
V CMC_(PFX, _peek)(struct SNAME *_heap_);
|
||||
/* Collection State */
|
||||
bool CMC_(PFX, _contains)(struct SNAME *_heap_, V value);
|
||||
bool CMC_(PFX, _empty)(struct SNAME *_heap_);
|
||||
bool CMC_(PFX, _full)(struct SNAME *_heap_);
|
||||
size_t CMC_(PFX, _count)(struct SNAME *_heap_);
|
||||
size_t CMC_(PFX, _capacity)(struct SNAME *_heap_);
|
||||
int CMC_(PFX, _flag)(struct SNAME *_heap_);
|
||||
/* Collection Utility */
|
||||
bool CMC_(PFX, _resize)(struct SNAME *_heap_, size_t capacity);
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_heap_);
|
||||
bool CMC_(PFX, _equals)(struct SNAME *_heap1_, struct SNAME *_heap2_);
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
struct SNAME
|
||||
{
|
||||
/* Dynamic array of elements */
|
||||
V *buffer;
|
||||
/* Current array capacity */
|
||||
size_t capacity;
|
||||
/* Current amount of elements in the heap */
|
||||
size_t count;
|
||||
/* Heap order (MaxHeap or MinHeap) */
|
||||
enum cmc_heap_order HO;
|
||||
/* Flags indicating errors or success */
|
||||
int flag;
|
||||
/* Value function table */
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val;
|
||||
/* Custom allocation functions */
|
||||
struct CMC_ALLOC_NODE_NAME *alloc;
|
||||
/* Custom callback functions */
|
||||
CMC_CALLBACKS_DECL;
|
||||
};
|
||||
@@ -0,0 +1,761 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Implementation Detail Functions */
|
||||
static void CMC_(PFX, _impl_float_up_max)(struct SNAME *_heap_);
|
||||
static void CMC_(PFX, _impl_float_up_min)(struct SNAME *_heap_);
|
||||
static void CMC_(PFX, _impl_float_down_max)(struct SNAME *_heap_);
|
||||
static void CMC_(PFX, _impl_float_down_min)(struct SNAME *_heap_);
|
||||
|
||||
struct SNAME *CMC_(PFX, _new)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val)
|
||||
{
|
||||
return CMC_(PFX, _new_custom)(capacity, f_val, NULL, NULL);
|
||||
}
|
||||
|
||||
struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val,
|
||||
struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks)
|
||||
{
|
||||
CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
|
||||
|
||||
if (capacity == 0 || capacity == UINTMAX_MAX)
|
||||
return NULL;
|
||||
|
||||
if (!f_val)
|
||||
return NULL;
|
||||
|
||||
if (!alloc)
|
||||
alloc = &cmc_alloc_node_default;
|
||||
|
||||
struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME));
|
||||
|
||||
if (!_heap_)
|
||||
return NULL;
|
||||
|
||||
capacity = (capacity + capacity % 2) / 2;
|
||||
|
||||
_heap_->buffer = alloc->calloc(capacity, sizeof(V[2]));
|
||||
|
||||
if (!_heap_->buffer)
|
||||
{
|
||||
alloc->free(_heap_);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_heap_->capacity = capacity;
|
||||
_heap_->size = 0;
|
||||
_heap_->count = 0;
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
_heap_->f_val = f_val;
|
||||
_heap_->alloc = alloc;
|
||||
CMC_CALLBACKS_ASSIGN(_heap_, callbacks);
|
||||
|
||||
return _heap_;
|
||||
}
|
||||
|
||||
void CMC_(PFX, _clear)(struct SNAME *_heap_)
|
||||
{
|
||||
if (_heap_->f_val->free)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
_heap_->f_val->free(_heap_->buffer[i / 2][i % 2]);
|
||||
}
|
||||
}
|
||||
|
||||
memset(_heap_->buffer, 0, sizeof(V[2]) * _heap_->capacity);
|
||||
|
||||
_heap_->size = 0;
|
||||
_heap_->count = 0;
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
}
|
||||
|
||||
void CMC_(PFX, _free)(struct SNAME *_heap_)
|
||||
{
|
||||
if (_heap_->f_val->free)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
_heap_->f_val->free(_heap_->buffer[i / 2][i % 2]);
|
||||
}
|
||||
}
|
||||
|
||||
_heap_->alloc->free(_heap_->buffer);
|
||||
|
||||
_heap_->alloc->free(_heap_);
|
||||
}
|
||||
|
||||
void CMC_(PFX, _customize)(struct SNAME *_heap_, struct CMC_ALLOC_NODE_NAME *alloc,
|
||||
struct CMC_CALLBACKS_NAME *callbacks)
|
||||
{
|
||||
CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
|
||||
|
||||
if (!alloc)
|
||||
_heap_->alloc = &cmc_alloc_node_default;
|
||||
else
|
||||
_heap_->alloc = alloc;
|
||||
|
||||
CMC_CALLBACKS_ASSIGN(_heap_, callbacks);
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _insert)(struct SNAME *_heap_, V value)
|
||||
{
|
||||
if (CMC_(PFX, _full)(_heap_))
|
||||
{
|
||||
if (!CMC_(PFX, _resize)(_heap_, _heap_->capacity * 4))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_heap_->count % 2 == 0)
|
||||
{
|
||||
/* Occupying a new node */
|
||||
_heap_->buffer[_heap_->size][0] = value;
|
||||
_heap_->buffer[_heap_->size][1] = (V){ 0 };
|
||||
|
||||
_heap_->size++;
|
||||
}
|
||||
else
|
||||
{
|
||||
V(*node)[2] = &(_heap_->buffer[_heap_->size - 1]);
|
||||
|
||||
/* Decide if the new element goes into the MinHeap or MaxHeap */
|
||||
if (_heap_->f_val->cmp((*node)[0], value) > 0)
|
||||
{
|
||||
/* Swap current value and add new element to the MinHeap */
|
||||
(*node)[1] = (*node)[0];
|
||||
(*node)[0] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No need to swap and add the new element to the MaxHeap */
|
||||
(*node)[1] = value;
|
||||
}
|
||||
}
|
||||
|
||||
_heap_->count++;
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
if (_heap_->count > 2)
|
||||
{
|
||||
/* Determine wheather to do a MaxHeap insert or a MinHeap */
|
||||
/* insert. For any integer this index calculation results in */
|
||||
/* an even number representing the parent of the last value */
|
||||
V(*parent)[2] = &(_heap_->buffer[(_heap_->size - 2) / 2]);
|
||||
|
||||
if (_heap_->f_val->cmp((*parent)[0], value) > 0)
|
||||
CMC_(PFX, _impl_float_up_min)(_heap_);
|
||||
else if (_heap_->f_val->cmp((*parent)[1], value) < 0)
|
||||
CMC_(PFX, _impl_float_up_max)(_heap_);
|
||||
/* else no float up required */
|
||||
}
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, create);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _remove_max)(struct SNAME *_heap_)
|
||||
{
|
||||
if (CMC_(PFX, _empty)(_heap_))
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_EMPTY;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_heap_->count == 1)
|
||||
{
|
||||
_heap_->buffer[0][0] = (V){ 0 };
|
||||
|
||||
_heap_->count--;
|
||||
_heap_->size--;
|
||||
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* Swap the result with the last element in the MaxHeap and float */
|
||||
/* it down */
|
||||
V(*last_node)[2] = &(_heap_->buffer[_heap_->size - 1]);
|
||||
|
||||
if (_heap_->count % 2 == 1)
|
||||
{
|
||||
/* Grab from MinHeap and discard last node */
|
||||
_heap_->buffer[0][1] = (*last_node)[0];
|
||||
|
||||
(*last_node)[0] = (V){ 0 };
|
||||
|
||||
_heap_->size--;
|
||||
}
|
||||
else
|
||||
{
|
||||
_heap_->buffer[0][1] = (*last_node)[1];
|
||||
|
||||
(*last_node)[1] = (V){ 0 };
|
||||
}
|
||||
|
||||
_heap_->count--;
|
||||
|
||||
/* FLoat Down on the MaxHeap */
|
||||
CMC_(PFX, _impl_float_down_max)(_heap_);
|
||||
|
||||
success:
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, delete);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _remove_min)(struct SNAME *_heap_)
|
||||
{
|
||||
if (CMC_(PFX, _empty)(_heap_))
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_EMPTY;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_heap_->count == 1)
|
||||
{
|
||||
_heap_->buffer[0][0] = (V){ 0 };
|
||||
|
||||
_heap_->count--;
|
||||
_heap_->size--;
|
||||
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* Swap the result with the last element in the MinHeap and float */
|
||||
/* it down */
|
||||
V(*last_node)[2] = &(_heap_->buffer[_heap_->size - 1]);
|
||||
|
||||
_heap_->buffer[0][0] = (*last_node)[0];
|
||||
|
||||
if (_heap_->count % 2 == 1)
|
||||
{
|
||||
/* Discard last node */
|
||||
(*last_node)[0] = (V){ 0 };
|
||||
|
||||
_heap_->size--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Place the MaxHeap value in the MinHeap value spot */
|
||||
(*last_node)[0] = (*last_node)[1];
|
||||
(*last_node)[1] = (V){ 0 };
|
||||
}
|
||||
|
||||
_heap_->count--;
|
||||
|
||||
/* FLoat Down on the MinHeap */
|
||||
CMC_(PFX, _impl_float_down_min)(_heap_);
|
||||
|
||||
success:
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, delete);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _update_max)(struct SNAME *_heap_, V value)
|
||||
{
|
||||
if (CMC_(PFX, _empty)(_heap_))
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_EMPTY;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_heap_->count == 1)
|
||||
{
|
||||
_heap_->buffer[0][0] = value;
|
||||
}
|
||||
else if (_heap_->f_val->cmp(value, _heap_->buffer[0][0]) < 0)
|
||||
{
|
||||
/* Corner case: we are updating the Max value but it is less */
|
||||
/* than the Min value */
|
||||
_heap_->buffer[0][1] = _heap_->buffer[0][0];
|
||||
_heap_->buffer[0][0] = value;
|
||||
|
||||
CMC_(PFX, _impl_float_down_max)(_heap_);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update Max element and float it down */
|
||||
_heap_->buffer[0][1] = value;
|
||||
|
||||
CMC_(PFX, _impl_float_down_max)(_heap_);
|
||||
}
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, update);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _update_min)(struct SNAME *_heap_, V value)
|
||||
{
|
||||
if (CMC_(PFX, _empty)(_heap_))
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_EMPTY;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_heap_->count == 1)
|
||||
{
|
||||
_heap_->buffer[0][0] = value;
|
||||
}
|
||||
else if (_heap_->f_val->cmp(value, _heap_->buffer[0][1]) > 0)
|
||||
{
|
||||
/* Corner case: we are updating the Min value but it is greater */
|
||||
/* than the Max value. */
|
||||
_heap_->buffer[0][0] = _heap_->buffer[0][1];
|
||||
_heap_->buffer[0][1] = value;
|
||||
|
||||
CMC_(PFX, _impl_float_down_min)(_heap_);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update Min element and float it down */
|
||||
_heap_->buffer[0][0] = value;
|
||||
|
||||
CMC_(PFX, _impl_float_down_min)(_heap_);
|
||||
}
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, update);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
V CMC_(PFX, _max)(struct SNAME *_heap_)
|
||||
{
|
||||
if (CMC_(PFX, _empty)(_heap_))
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_EMPTY;
|
||||
return (V){ 0 };
|
||||
}
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, read);
|
||||
|
||||
/* If there is only one element, then the maximum element is the */
|
||||
/* same as the one in the MinHeap */
|
||||
if (_heap_->count == 1)
|
||||
return _heap_->buffer[0][0];
|
||||
|
||||
return _heap_->buffer[0][1];
|
||||
}
|
||||
|
||||
V CMC_(PFX, _min)(struct SNAME *_heap_)
|
||||
{
|
||||
if (CMC_(PFX, _empty)(_heap_))
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_EMPTY;
|
||||
return (V){ 0 };
|
||||
}
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, read);
|
||||
|
||||
return _heap_->buffer[0][0];
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _contains)(struct SNAME *_heap_, V value)
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
if (_heap_->f_val->cmp(_heap_->buffer[i / 2][i % 2], value) == 0)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, read);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _empty)(struct SNAME *_heap_)
|
||||
{
|
||||
return _heap_->count == 0;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _full)(struct SNAME *_heap_)
|
||||
{
|
||||
/* The heap is full if all nodes are completely filled */
|
||||
return _heap_->size >= _heap_->capacity && _heap_->count % 2 == 0;
|
||||
}
|
||||
|
||||
size_t CMC_(PFX, _count)(struct SNAME *_heap_)
|
||||
{
|
||||
return _heap_->count;
|
||||
}
|
||||
|
||||
size_t CMC_(PFX, _capacity)(struct SNAME *_heap_)
|
||||
{
|
||||
return _heap_->capacity;
|
||||
}
|
||||
|
||||
int CMC_(PFX, _flag)(struct SNAME *_heap_)
|
||||
{
|
||||
return _heap_->flag;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _resize)(struct SNAME *_heap_, size_t capacity)
|
||||
{
|
||||
if (_heap_->capacity == capacity)
|
||||
goto success;
|
||||
|
||||
if (capacity < _heap_->count)
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Prevent overflow */
|
||||
if (capacity == UINTMAX_MAX)
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
capacity += capacity % 2;
|
||||
|
||||
V(*new_buffer)[2] = _heap_->alloc->realloc(_heap_->buffer, sizeof(V[2]) * capacity);
|
||||
|
||||
if (!new_buffer)
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_ALLOC;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (capacity > _heap_->capacity)
|
||||
{
|
||||
memset(new_buffer + _heap_->capacity, 0, sizeof(V[2]) * (capacity - _heap_->capacity));
|
||||
}
|
||||
|
||||
_heap_->buffer = new_buffer;
|
||||
_heap_->capacity = capacity;
|
||||
|
||||
success:
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
CMC_CALLBACKS_CALL(_heap_, resize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_heap_)
|
||||
{
|
||||
struct SNAME *result = _heap_->alloc->malloc(sizeof(struct SNAME));
|
||||
|
||||
if (!result)
|
||||
{
|
||||
_heap_->flag = CMC_FLAG_ALLOC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(result, _heap_, sizeof(struct SNAME));
|
||||
|
||||
result->buffer = _heap_->alloc->malloc(sizeof(V[2]) * _heap_->capacity);
|
||||
|
||||
if (!result->buffer)
|
||||
{
|
||||
_heap_->alloc->free(result);
|
||||
_heap_->flag = CMC_FLAG_ALLOC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_heap_->f_val->cpy)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
result->buffer[i / 2][i % 2] = _heap_->f_val->cpy(_heap_->buffer[i / 2][i % 2]);
|
||||
}
|
||||
else
|
||||
memcpy(result->buffer, _heap_->buffer, sizeof(V[2]) * _heap_->capacity);
|
||||
|
||||
result->capacity = _heap_->capacity;
|
||||
result->size = _heap_->size;
|
||||
result->count = _heap_->count;
|
||||
result->flag = CMC_FLAG_OK;
|
||||
result->f_val = _heap_->f_val;
|
||||
result->alloc = _heap_->alloc;
|
||||
CMC_CALLBACKS_ASSIGN(result, _heap_->callbacks);
|
||||
|
||||
_heap_->flag = CMC_FLAG_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _equals)(struct SNAME *_heap1_, struct SNAME *_heap2_)
|
||||
{
|
||||
_heap1_->flag = CMC_FLAG_OK;
|
||||
_heap2_->flag = CMC_FLAG_OK;
|
||||
|
||||
if (_heap1_->count != _heap2_->count)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < _heap1_->count; i++)
|
||||
{
|
||||
V value1 = _heap1_->buffer[i / 2][i % 2];
|
||||
V value2 = _heap2_->buffer[i / 2][i % 2];
|
||||
|
||||
if (_heap1_->f_val->cmp(value1, value2) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CMC_(PFX, _impl_float_up_max)(struct SNAME *_heap_)
|
||||
{
|
||||
size_t index = _heap_->size - 1;
|
||||
|
||||
V(*curr_node)[2] = &(_heap_->buffer[index]);
|
||||
|
||||
/* FLoat Up on the MaxHeap */
|
||||
while (index > 0)
|
||||
{
|
||||
/* Parent index */
|
||||
size_t P_index = (index - 1) / 2;
|
||||
|
||||
V(*parent)[2] = &(_heap_->buffer[P_index]);
|
||||
|
||||
if (index == _heap_->size - 1 && _heap_->count % 2 != 0)
|
||||
{
|
||||
/* In this case, the current node has no MaxHeap value so */
|
||||
/* we instead compare with the MinHeap value */
|
||||
if (_heap_->f_val->cmp((*curr_node)[0], (*parent)[1]) < 0)
|
||||
break;
|
||||
|
||||
/* Since the comparison above passed now we need to swap */
|
||||
/* the current node with the parent but it will have to be */
|
||||
/* done with the node's MinHeap value since the MaxHeap */
|
||||
/* value doesn't exist */
|
||||
V tmp = (*curr_node)[0];
|
||||
(*curr_node)[0] = (*parent)[1];
|
||||
(*parent)[1] = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Usual case, just compare both MaxHeap values */
|
||||
if (_heap_->f_val->cmp((*curr_node)[1], (*parent)[1]) < 0)
|
||||
break;
|
||||
|
||||
/* Swap with parent and repeat */
|
||||
V tmp = (*curr_node)[1];
|
||||
(*curr_node)[1] = (*parent)[1];
|
||||
(*parent)[1] = tmp;
|
||||
}
|
||||
|
||||
/* Update indexe and node */
|
||||
index = P_index;
|
||||
curr_node = parent;
|
||||
}
|
||||
}
|
||||
|
||||
static void CMC_(PFX, _impl_float_up_min)(struct SNAME *_heap_)
|
||||
{
|
||||
size_t index = _heap_->size - 1;
|
||||
|
||||
V(*curr_node)[2] = &(_heap_->buffer[index]);
|
||||
|
||||
/* FLoat Up on the MinHeap */
|
||||
while (index > 0)
|
||||
{
|
||||
/* Parent index */
|
||||
size_t P_index = (index - 1) / 2;
|
||||
|
||||
V(*parent)[2] = &(_heap_->buffer[P_index]);
|
||||
|
||||
if (_heap_->f_val->cmp((*curr_node)[0], (*parent)[0]) >= 0)
|
||||
break;
|
||||
|
||||
/* Swap with parent and repeat */
|
||||
V tmp = (*curr_node)[0];
|
||||
(*curr_node)[0] = (*parent)[0];
|
||||
(*parent)[0] = tmp;
|
||||
|
||||
/* Update indexe and node */
|
||||
index = P_index;
|
||||
curr_node = parent;
|
||||
}
|
||||
}
|
||||
|
||||
static void CMC_(PFX, _impl_float_down_max)(struct SNAME *_heap_)
|
||||
{
|
||||
/* Floats Down from the MaxHeap */
|
||||
size_t index = 0;
|
||||
|
||||
V(*curr_node)[2] = &(_heap_->buffer[index]);
|
||||
|
||||
while (true)
|
||||
{
|
||||
/* If there are no children it is done */
|
||||
if (2 * index + 1 >= _heap_->size)
|
||||
break;
|
||||
|
||||
/* Child index to be compared with current value */
|
||||
size_t child;
|
||||
size_t L_index = index * 2 + 1;
|
||||
size_t R_index = index * 2 + 2;
|
||||
|
||||
/* If there are two children, pick the smallest one */
|
||||
if (R_index < _heap_->size)
|
||||
{
|
||||
V(*L)[2] = &(_heap_->buffer[L_index]);
|
||||
V(*R)[2] = &(_heap_->buffer[R_index]);
|
||||
|
||||
/* If the right child is the last node and there is no */
|
||||
/* MaxHeap value */
|
||||
/* then do the comparison with the MinHeap value */
|
||||
if (R_index == _heap_->size - 1 && _heap_->count % 2 != 0)
|
||||
child = _heap_->f_val->cmp((*L)[1], (*R)[0]) > 0 ? L_index : R_index;
|
||||
else
|
||||
child = _heap_->f_val->cmp((*L)[1], (*R)[1]) > 0 ? L_index : R_index;
|
||||
}
|
||||
/* Pick the only one available */
|
||||
else
|
||||
child = L_index;
|
||||
|
||||
V(*child_node)[2] = &(_heap_->buffer[child]);
|
||||
|
||||
/* Again, check if the child node is the last one and has no */
|
||||
/* MaxHeap value */
|
||||
if (child == _heap_->size - 1 && _heap_->count % 2 != 0)
|
||||
{
|
||||
/* Odd case, compare with MinHeap value */
|
||||
/* If current value is not less than the child node's */
|
||||
/* value it is done */
|
||||
if (_heap_->f_val->cmp((*curr_node)[1], (*child_node)[0]) >= 0)
|
||||
break;
|
||||
|
||||
/* Otherwise swap and continue */
|
||||
V tmp = (*child_node)[0];
|
||||
(*child_node)[0] = (*curr_node)[1];
|
||||
(*curr_node)[1] = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If current value is not less than the child node's */
|
||||
/* value it is done */
|
||||
if (_heap_->f_val->cmp((*curr_node)[1], (*child_node)[1]) >= 0)
|
||||
break;
|
||||
|
||||
/* Otherwise swap and continue */
|
||||
V tmp = (*child_node)[1];
|
||||
(*child_node)[1] = (*curr_node)[1];
|
||||
(*curr_node)[1] = tmp;
|
||||
|
||||
/* Check if the MinHeap and MaxHeap values need to be */
|
||||
/* swapped */
|
||||
if (_heap_->f_val->cmp((*child_node)[0], (*child_node)[1]) > 0)
|
||||
{
|
||||
/* Swap because the MinHeap value is greater than the */
|
||||
/* MaxHeap value */
|
||||
tmp = (*child_node)[0];
|
||||
(*child_node)[0] = (*child_node)[1];
|
||||
(*child_node)[1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update index and node */
|
||||
index = child;
|
||||
curr_node = child_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void CMC_(PFX, _impl_float_down_min)(struct SNAME *_heap_)
|
||||
{
|
||||
/* Floats Down from the MinHeap */
|
||||
size_t index = 0;
|
||||
|
||||
V(*curr_node)[2] = &(_heap_->buffer[index]);
|
||||
|
||||
while (true)
|
||||
{
|
||||
/* If there are no children it is done */
|
||||
if (2 * index + 1 >= _heap_->size)
|
||||
break;
|
||||
|
||||
/* Child index to be compared with current value */
|
||||
size_t child;
|
||||
size_t L_index = index * 2 + 1;
|
||||
size_t R_index = index * 2 + 2;
|
||||
|
||||
/* If there are two children, pick the smallest one */
|
||||
if (R_index < _heap_->size)
|
||||
{
|
||||
V(*L)[2] = &(_heap_->buffer[L_index]);
|
||||
V(*R)[2] = &(_heap_->buffer[R_index]);
|
||||
|
||||
child = _heap_->f_val->cmp((*L)[0], (*R)[0]) < 0 ? L_index : R_index;
|
||||
}
|
||||
/* Pick the only one available */
|
||||
else
|
||||
child = L_index;
|
||||
|
||||
V(*child_node)[2] = &(_heap_->buffer[child]);
|
||||
|
||||
/* If current value is smaller than the child node's value, it */
|
||||
/* is done */
|
||||
if (_heap_->f_val->cmp((*curr_node)[0], (*child_node)[0]) < 0)
|
||||
break;
|
||||
|
||||
/* Otherwise swap and continue */
|
||||
V tmp = (*child_node)[0];
|
||||
(*child_node)[0] = (*curr_node)[0];
|
||||
(*curr_node)[0] = tmp;
|
||||
|
||||
/* If the child node is the last node check if the MinHeap and */
|
||||
/* MaxHeap values need to be swapped */
|
||||
if (child != _heap_->size - 1 || _heap_->count % 2 == 0)
|
||||
{
|
||||
if (_heap_->f_val->cmp((*child_node)[0], (*child_node)[1]) > 0)
|
||||
{
|
||||
/* Swap because the MinHeap value is greater than the */
|
||||
/* MaxHeap value */
|
||||
tmp = (*child_node)[0];
|
||||
(*child_node)[0] = (*child_node)[1];
|
||||
(*child_node)[1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update index and node */
|
||||
index = child;
|
||||
curr_node = child_node;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* INIT
|
||||
*
|
||||
* The part 'INIT' gives a new way of initializing a collection. The collection
|
||||
* struct is not heap allocated, only its internal structure (nodes, buffers).
|
||||
*/
|
||||
#ifdef CMC_EXT_INTERVALHEAP_INIT
|
||||
|
||||
#endif /* CMC_EXT_INTERVALHEAP_INIT */
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*
|
||||
* Intervalheap bi-directional iterator.
|
||||
*
|
||||
* TODO allow creation of iterators exclusively for min or max heap
|
||||
*/
|
||||
#ifdef CMC_EXT_INTERVALHEAP_ITER
|
||||
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
|
||||
{
|
||||
struct CMC_DEF_ITER(SNAME) iter;
|
||||
|
||||
iter.target = target;
|
||||
iter.cursor = 0;
|
||||
iter.start = true;
|
||||
iter.end = CMC_(PFX, _empty)(target);
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target)
|
||||
{
|
||||
struct CMC_DEF_ITER(SNAME) iter;
|
||||
|
||||
iter.target = target;
|
||||
iter.cursor = 0;
|
||||
iter.start = CMC_(PFX, _empty)(target);
|
||||
iter.end = true;
|
||||
|
||||
if (!CMC_(PFX, _empty)(target))
|
||||
iter.cursor = target->count - 1;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
if (!CMC_(PFX, _empty)(iter->target))
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->start = true;
|
||||
iter->end = CMC_(PFX, _empty)(iter->target);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
if (!CMC_(PFX, _empty)(iter->target))
|
||||
{
|
||||
iter->cursor = iter->target->count - 1;
|
||||
iter->start = CMC_(PFX, _empty)(iter->target);
|
||||
iter->end = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
|
||||
if (iter->cursor + 1 == iter->target->count)
|
||||
{
|
||||
iter->end = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
iter->start = CMC_(PFX, _empty)(iter->target);
|
||||
|
||||
iter->cursor++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
iter->end = CMC_(PFX, _empty)(iter->target);
|
||||
|
||||
iter->cursor--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Returns true only if the iterator moved */
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
|
||||
if (iter->cursor + 1 == iter->target->count)
|
||||
{
|
||||
iter->end = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (steps == 0 || iter->cursor + steps >= iter->target->count)
|
||||
return false;
|
||||
|
||||
if (iter->end)
|
||||
return false;
|
||||
|
||||
iter->start = CMC_(PFX, _empty)(iter->target);
|
||||
|
||||
iter->cursor += steps;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Returns true only if the iterator moved */
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (steps == 0 || iter->cursor < steps)
|
||||
return false;
|
||||
|
||||
iter->end = CMC_(PFX, _empty)(iter->target);
|
||||
|
||||
iter->cursor -= steps;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Returns true only if the iterator was able to be positioned at the */
|
||||
/* given index */
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index)
|
||||
{
|
||||
if (index >= iter->target->count)
|
||||
return false;
|
||||
|
||||
if (iter->cursor > index)
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->cursor - index);
|
||||
else if (iter->cursor < index)
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->cursor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
if (CMC_(PFX, _empty)(iter->target))
|
||||
return (V){ 0 };
|
||||
|
||||
return iter->target->buffer[iter->cursor / 2][iter->cursor % 2];
|
||||
}
|
||||
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
|
||||
{
|
||||
return iter->cursor;
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_INTERVALHEAP_ITER */
|
||||
|
||||
/**
|
||||
* STR
|
||||
*
|
||||
* Print helper functions.
|
||||
*/
|
||||
#ifdef CMC_EXT_INTERVALHEAP_STR
|
||||
|
||||
bool CMC_(PFX, _to_string)(struct SNAME *_heap_, FILE *fptr)
|
||||
{
|
||||
struct SNAME *h_ = _heap_;
|
||||
|
||||
return 0 <= fprintf(fptr,
|
||||
"struct %s<%s> "
|
||||
"at %p { "
|
||||
"buffer:%p, "
|
||||
"capacity:%" PRIuMAX ", "
|
||||
"size:%" PRIuMAX ", "
|
||||
"count:%" PRIuMAX ", "
|
||||
"flag:%d, "
|
||||
"f_val:%p, "
|
||||
"alloc:%p, "
|
||||
"callbacks:%p }",
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), h_, h_->buffer, h_->capacity, h_->size, h_->count,
|
||||
h_->flag, h_->f_val, h_->alloc, CMC_CALLBACKS_GET(h_));
|
||||
}
|
||||
|
||||
bool CMC_(PFX, _print)(struct SNAME *_heap_, FILE *fptr, const char *start, const char *separator, const char *end)
|
||||
{
|
||||
fprintf(fptr, "%s", start);
|
||||
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
if (!_heap_->f_val->str(fptr, _heap_->buffer[i / 2][i % 2]))
|
||||
return false;
|
||||
|
||||
if (i + 1 < _heap_->count)
|
||||
fprintf(fptr, "%s", separator);
|
||||
}
|
||||
|
||||
fprintf(fptr, "%s", end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_INTERVALHEAP_STR */
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* INIT
|
||||
*
|
||||
* The part 'INIT' gives a new way of initializing a collection. The collection
|
||||
* struct is not heap allocated, only its internal structure (nodes, buffers).
|
||||
*/
|
||||
#ifdef CMC_EXT_INTERVALHEAP_INIT
|
||||
|
||||
#endif /* CMC_EXT_INTERVALHEAP_INIT */
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*
|
||||
* List bi-directional iterator.
|
||||
*/
|
||||
#ifdef CMC_EXT_INTERVALHEAP_ITER
|
||||
|
||||
/* IntervalHeap Iterator */
|
||||
struct CMC_DEF_ITER(SNAME)
|
||||
{
|
||||
/* Target IntervalHeap */
|
||||
struct SNAME *target;
|
||||
|
||||
/* Cursor's position (index) */
|
||||
size_t cursor;
|
||||
|
||||
/* If the iterator has reached the start of the iteration */
|
||||
bool start;
|
||||
|
||||
/* If the iterator has reached the end of the iteration */
|
||||
bool end;
|
||||
};
|
||||
|
||||
/* Iterator Initialization */
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target);
|
||||
/* Iterator State */
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
/* Iterator Movement */
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index);
|
||||
/* Iterator Access */
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#endif /* CMC_EXT_INTERVALHEAP_ITER */
|
||||
|
||||
/**
|
||||
* STR
|
||||
*
|
||||
* Print helper functions.
|
||||
*/
|
||||
#ifdef CMC_EXT_INTERVALHEAP_STR
|
||||
|
||||
bool CMC_(PFX, _to_string)(struct SNAME *_heap_, FILE *fptr);
|
||||
bool CMC_(PFX, _print)(struct SNAME *_heap_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_EXT_INTERVALHEAP_STR */
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Value struct function table */
|
||||
struct CMC_DEF_FVAL(SNAME)
|
||||
{
|
||||
/* Comparator function */
|
||||
CMC_DEF_FTAB_CMP(V);
|
||||
/* Copy function */
|
||||
CMC_DEF_FTAB_CPY(V);
|
||||
/* To string function */
|
||||
CMC_DEF_FTAB_STR(V);
|
||||
/* Free from memory function */
|
||||
CMC_DEF_FTAB_FREE(V);
|
||||
/* Hash function */
|
||||
CMC_DEF_FTAB_HASH(V);
|
||||
/* Priority function */
|
||||
CMC_DEF_FTAB_PRI(V);
|
||||
};
|
||||
|
||||
/* Collection Functions */
|
||||
/* Collection Allocation and Deallocation */
|
||||
struct SNAME *CMC_(PFX, _new)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val);
|
||||
struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val,
|
||||
struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks);
|
||||
void CMC_(PFX, _clear)(struct SNAME *_heap_);
|
||||
void CMC_(PFX, _free)(struct SNAME *_heap_);
|
||||
/* Customization of Allocation and Callbacks */
|
||||
void CMC_(PFX, _customize)(struct SNAME *_heap_, struct CMC_ALLOC_NODE_NAME *alloc,
|
||||
struct CMC_CALLBACKS_NAME *callbacks);
|
||||
/* Collection Input and Output */
|
||||
bool CMC_(PFX, _insert)(struct SNAME *_heap_, V value);
|
||||
bool CMC_(PFX, _remove_max)(struct SNAME *_heap_);
|
||||
bool CMC_(PFX, _remove_min)(struct SNAME *_heap_);
|
||||
/* Collection Update */
|
||||
bool CMC_(PFX, _update_max)(struct SNAME *_heap_, V value);
|
||||
bool CMC_(PFX, _update_min)(struct SNAME *_heap_, V value);
|
||||
/* Element Access */
|
||||
V CMC_(PFX, _max)(struct SNAME *_heap_);
|
||||
V CMC_(PFX, _min)(struct SNAME *_heap_);
|
||||
/* Collection State */
|
||||
bool CMC_(PFX, _contains)(struct SNAME *_heap_, V value);
|
||||
bool CMC_(PFX, _empty)(struct SNAME *_heap_);
|
||||
bool CMC_(PFX, _full)(struct SNAME *_heap_);
|
||||
size_t CMC_(PFX, _count)(struct SNAME *_heap_);
|
||||
size_t CMC_(PFX, _capacity)(struct SNAME *_heap_);
|
||||
int CMC_(PFX, _flag)(struct SNAME *_heap_);
|
||||
/* Collection Utility */
|
||||
bool CMC_(PFX, _resize)(struct SNAME *_heap_, size_t capacity);
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_heap_);
|
||||
bool CMC_(PFX, _equals)(struct SNAME *_heap1_, struct SNAME *_heap2_);
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
struct SNAME
|
||||
{
|
||||
/* Dynamic array of elements */
|
||||
/* buffer[n][0] is MinHeap and buffer[n][1] is MaxHeap */
|
||||
V (*buffer)[2];
|
||||
/* Current array capacity */
|
||||
size_t capacity;
|
||||
/* Current amount of pairs of values in the array */
|
||||
size_t size;
|
||||
/* Current amount of elements in the heap */
|
||||
size_t count;
|
||||
/* Flags indicating errors or success */
|
||||
int flag;
|
||||
/* Value function table */
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val;
|
||||
/* Custom allocation functions */
|
||||
struct CMC_ALLOC_NODE_NAME *alloc;
|
||||
/* Custom callback functions */
|
||||
CMC_CALLBACKS_DECL;
|
||||
};
|
||||
@@ -35,6 +35,8 @@
|
||||
#ifndef CMC_COR_ALLOC_H
|
||||
#define CMC_COR_ALLOC_H
|
||||
|
||||
#ifndef CMC_NO_ALLOC
|
||||
|
||||
#ifdef CMC_CAMEL_CASE
|
||||
#define CMC_ALLOC_NODE_NAME CMCAllocNode
|
||||
#else
|
||||
@@ -58,4 +60,6 @@ static struct CMC_ALLOC_NODE_NAME
|
||||
void (*free)(void *);
|
||||
} CMC_UNUSED cmc_alloc_node_default = { malloc, calloc, realloc, free };
|
||||
|
||||
#endif /* CMC_NO_ALLOC */
|
||||
|
||||
#endif /* CMC_COR_ALLOC_H */
|
||||
@@ -39,7 +39,7 @@
|
||||
#ifndef CMC_COR_BITSET_H
|
||||
#define CMC_COR_BITSET_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "core.h"
|
||||
|
||||
/* Defines the underlaying data type for the bitset array */
|
||||
/* Possible values: uint64_t, uint32_t, uint16_t, uint8_t, size_t */
|
||||
|
||||
@@ -45,13 +45,18 @@
|
||||
#ifndef CMC_COR_CORE_H
|
||||
#define CMC_COR_CORE_H
|
||||
|
||||
#ifndef CMC_NO_IMPORTS
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#endif /* CMC_NO_IMPORTS */
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define CMC_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* heap.h
|
||||
*
|
||||
* Creation Date: 25/03/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Heap
|
||||
*
|
||||
* The Heap is a specialized tree-based data structure which is essentially a
|
||||
* complete tree that satisfies the heap property:
|
||||
* - MaxHeap:
|
||||
* - The root node is the greatest element of the unique set of keys.
|
||||
* - A node key is always greater than or equal to its children keys.
|
||||
* - Minheap:
|
||||
* - The root node is the smallest element of the unique set of keys.
|
||||
* - A node Key is always greater than or equal to its children keys.
|
||||
*
|
||||
* The heap is mostly used to implement priority queues. Sometimes it can also
|
||||
* be used to sort elements. There are three main functions:
|
||||
* - insert : Adds an element to the heap
|
||||
* - remove_(min/max): Removes the min/max element from the heap
|
||||
* - min/max : Accesses the min/max element from the heap
|
||||
*/
|
||||
|
||||
#include "cor/core.h"
|
||||
#include "cor/heap.h"
|
||||
|
||||
/**
|
||||
* Used values
|
||||
* V - heap value data type
|
||||
* SNAME - struct name and prefix of other related structs
|
||||
* PFX - functions prefix
|
||||
*/
|
||||
|
||||
/* Structs definition */
|
||||
#include "cmc/heap/struct.h"
|
||||
|
||||
/* Function declaration */
|
||||
#include "cmc/heap/header.h"
|
||||
|
||||
/* Function implementation */
|
||||
#include "cmc/heap/code.h"
|
||||
|
||||
/**
|
||||
* Extensions
|
||||
*
|
||||
* INIT - Initializes the struct on the stack
|
||||
* ITER - heap iterator
|
||||
* STR - Print helper functions
|
||||
*/
|
||||
#define CMC_EXT_HEAP_PARTS ITER, SETF, STR
|
||||
/**/
|
||||
#include "cmc/heap/ext/struct.h"
|
||||
/**/
|
||||
#include "cmc/heap/ext/header.h"
|
||||
/**/
|
||||
#include "cmc/heap/ext/code.h"
|
||||
|
||||
#include "cor/undef.h"
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Leonardo Vencovsky
|
||||
*
|
||||
* This file is part of the C Macro Collections Libray.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* intervalheap.h
|
||||
*
|
||||
* Creation Date: 06/07/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interval Heap
|
||||
*
|
||||
* An interval heap is a specialized heap with:
|
||||
*
|
||||
* - O(1) - Find Min
|
||||
* - O(1) - Find Max
|
||||
* - O(log n) - Insert
|
||||
* - O(log n) - Remove Min
|
||||
* - O(log n) - Remove Max
|
||||
*/
|
||||
|
||||
#include "cor/core.h"
|
||||
|
||||
/**
|
||||
* Used values
|
||||
* V - intervalheap value data type
|
||||
* SNAME - struct name and prefix of other related structs
|
||||
* PFX - functions prefix
|
||||
*/
|
||||
|
||||
/* Structs definition */
|
||||
#include "cmc/intervalheap/struct.h"
|
||||
|
||||
/* Function declaration */
|
||||
#include "cmc/intervalheap/header.h"
|
||||
|
||||
/* Function implementation */
|
||||
#include "cmc/intervalheap/code.h"
|
||||
|
||||
/**
|
||||
* Extensions
|
||||
*
|
||||
* INIT - Initializes the struct on the stack
|
||||
* ITER - intervalheap iterator
|
||||
* STR - Print helper functions
|
||||
*/
|
||||
#define CMC_EXT_HEAP_PARTS ITER, SETF, STR
|
||||
/**/
|
||||
#include "cmc/intervalheap/ext/struct.h"
|
||||
/**/
|
||||
#include "cmc/intervalheap/ext/header.h"
|
||||
/**/
|
||||
#include "cmc/intervalheap/ext/code.h"
|
||||
|
||||
#include "cor/undef.h"
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -Wextra -Werror -fprofile-arcs -ftest-coverage -g -O0
|
||||
CFLAGS=-Wall -Wextra -Werror -fprofile-arcs -ftest-coverage -ftime-report -g -O0
|
||||
INCLUDE=-I ../src
|
||||
|
||||
main:
|
||||
|
||||
+12
-12
@@ -1,18 +1,18 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// #include "unt_bitset.h"
|
||||
#include "unt_bitset.h"
|
||||
#include "unt_deque.h"
|
||||
#include "unt_hashbidimap.h"
|
||||
#include "unt_hashmap.h"
|
||||
#include "unt_hashmultimap.h"
|
||||
#include "unt_hashmultiset.h"
|
||||
#include "unt_hashset.h"
|
||||
// #include "unt_heap.h"
|
||||
// #include "unt_intervalheap.h"
|
||||
#include "unt_heap.h"
|
||||
#include "unt_intervalheap.h"
|
||||
// #include "unt_linkedlist.h"
|
||||
#include "unt_list.h"
|
||||
// #include "unt_queue.h"
|
||||
#include "unt_queue.h"
|
||||
// #include "unt_sortedlist.h"
|
||||
#include "unt_stack.h"
|
||||
// #include "unt_treemap.h"
|
||||
@@ -52,8 +52,8 @@ int main(void)
|
||||
cmc_timer_start(timer);
|
||||
uintmax_t tests = 0, units = 0;
|
||||
|
||||
// cmc_run(CMCBitSet, units, tests);
|
||||
// cmc_run(CMCBitSetIter, units, tests);
|
||||
cmc_run(CMCBitSet, units, tests);
|
||||
cmc_run(CMCBitSetIter, units, tests);
|
||||
cmc_run(CMCDeque, units, tests);
|
||||
cmc_run(CMCDequeIter, units, tests);
|
||||
cmc_run(CMCHashBidiMap, units, tests);
|
||||
@@ -66,16 +66,16 @@ int main(void)
|
||||
cmc_run(CMCHashMultiSetIter, units, tests);
|
||||
cmc_run(CMCHashSet, units, tests);
|
||||
cmc_run(CMCHashSetIter, units, tests);
|
||||
// cmc_run(CMCHeap, units, tests);
|
||||
// cmc_run(CMCHeapIter, units, tests);
|
||||
// cmc_run(CMCIntervalHeap, units, tests);
|
||||
// cmc_run(CMCIntervalHeapIter, units, tests);
|
||||
cmc_run(CMCHeap, units, tests);
|
||||
cmc_run(CMCHeapIter, units, tests);
|
||||
cmc_run(CMCIntervalHeap, units, tests);
|
||||
cmc_run(CMCIntervalHeapIter, units, tests);
|
||||
// cmc_run(CMCLinkedList, units, tests);
|
||||
// cmc_run(CMCLinkedListIter, units, tests);
|
||||
cmc_run(CMCList, units, tests);
|
||||
cmc_run(CMCListIter, units, tests);
|
||||
// cmc_run(CMCQueue, units, tests);
|
||||
// cmc_run(CMCQueueIter, units, tests);
|
||||
cmc_run(CMCQueue, units, tests);
|
||||
cmc_run(CMCQueueIter, units, tests);
|
||||
// cmc_run(CMCSortedList, units, tests);
|
||||
// cmc_run(CMCSortedListIter, units, tests);
|
||||
cmc_run(CMCStack, units, tests);
|
||||
|
||||
@@ -0,0 +1,454 @@
|
||||
#ifndef CMC_TESTS_UNT_BITSET_H
|
||||
#define CMC_TESTS_UNT_BITSET_H
|
||||
|
||||
#include "utl.h"
|
||||
|
||||
#define PFX bs
|
||||
#define SNAME bitset
|
||||
#define CMC_EXT_BITSET_INIT
|
||||
#define CMC_EXT_BITSET_ITER
|
||||
#define CMC_EXT_BITSET_STR
|
||||
#include "cmc/bitset.h"
|
||||
|
||||
struct cmc_alloc_node *bs_alloc_node =
|
||||
&(struct cmc_alloc_node){ .malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free };
|
||||
|
||||
CMC_CREATE_UNIT(CMCBitSet, true, {
|
||||
const size_t word_bits = sizeof(cmc_bitset_word) * CHAR_BIT;
|
||||
|
||||
printf("%s", cmc_test_color(5));
|
||||
printf(" BitSet<" CMC_TO_STRING(CMC_BITSET_WORD_TYPE) ">\n");
|
||||
printf("%s", cmc_test_color(0));
|
||||
|
||||
CMC_CREATE_TEST(PFX##_new(), {
|
||||
struct bitset *bs = bs_new(64);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_not_equals(ptr, NULL, bs->buffer);
|
||||
cmc_assert_equals(size_t, cmc_bidx_to_widx(63) + 1, bs->capacity);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.malloc, bs->alloc->malloc);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.calloc, bs->alloc->calloc);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.realloc, bs->alloc->realloc);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.free, bs->alloc->free);
|
||||
cmc_assert_equals(ptr, NULL, bs->callbacks);
|
||||
|
||||
bs_free(bs);
|
||||
|
||||
bs = bs_new(129);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_bidx_to_widx(128) + 1, bs->capacity);
|
||||
|
||||
bs_free(bs);
|
||||
|
||||
bs = bs_new(0);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_new_custom(), {
|
||||
struct bitset *bs = bs_new_custom(64, bs_alloc_node, callbacks);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_not_equals(ptr, NULL, bs->buffer);
|
||||
cmc_assert_equals(size_t, cmc_bidx_to_widx(63) + 1, bs->capacity);
|
||||
cmc_assert_equals(ptr, bs_alloc_node, bs->alloc);
|
||||
cmc_assert_equals(ptr, callbacks, bs->callbacks);
|
||||
|
||||
bs_free(bs);
|
||||
|
||||
bs = bs_new_custom(129, NULL, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_bidx_to_widx(128) + 1, bs->capacity);
|
||||
bs_free(bs);
|
||||
|
||||
bs = bs_new_custom(0, bs_alloc_node, callbacks);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_init(), {
|
||||
struct bitset bs = bs_init(64);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs.buffer);
|
||||
cmc_assert_equals(size_t, cmc_bidx_to_widx(63) + 1, bs.capacity);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.malloc, bs.alloc->malloc);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.calloc, bs.alloc->calloc);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.realloc, bs.alloc->realloc);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.free, bs.alloc->free);
|
||||
cmc_assert_equals(ptr, NULL, bs.callbacks);
|
||||
|
||||
bs_release(bs);
|
||||
|
||||
bs = bs_init(129);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_bidx_to_widx(128) + 1, bs.capacity);
|
||||
|
||||
bs_release(bs);
|
||||
|
||||
bs = bs_init(0);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, bs.buffer);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_init_custom(), {
|
||||
struct bitset bs = bs_init_custom(64, bs_alloc_node, callbacks);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs.buffer);
|
||||
cmc_assert_equals(size_t, cmc_bidx_to_widx(63) + 1, bs.capacity);
|
||||
cmc_assert_equals(ptr, bs_alloc_node, bs.alloc);
|
||||
cmc_assert_equals(ptr, callbacks, bs.callbacks);
|
||||
|
||||
bs_release(bs);
|
||||
|
||||
bs = bs_init_custom(129, NULL, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_bidx_to_widx(128) + 1, bs.capacity);
|
||||
|
||||
bs_release(bs);
|
||||
|
||||
bs = bs_init_custom(0, bs_alloc_node, callbacks);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, bs.buffer);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_customize(), {
|
||||
struct bitset *bs = bs_new(word_bits);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
|
||||
bs->flag = CMC_FLAG_ERROR;
|
||||
bs_customize(bs, bs_alloc_node, callbacks);
|
||||
|
||||
cmc_assert_equals(ptr, bs_alloc_node, bs->alloc);
|
||||
cmc_assert_equals(ptr, callbacks, bs->callbacks);
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, bs->flag);
|
||||
|
||||
bs->flag = CMC_FLAG_ERROR;
|
||||
bs_customize(bs, NULL, NULL);
|
||||
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.malloc, bs->alloc->malloc);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.calloc, bs->alloc->calloc);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.realloc, bs->alloc->realloc);
|
||||
cmc_assert_equals(ptr, cmc_alloc_node_default.free, bs->alloc->free);
|
||||
cmc_assert_equals(ptr, NULL, bs->callbacks);
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, bs->flag);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_set(), {
|
||||
struct bitset *bs = bs_new(word_bits);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
bs->flag = CMC_FLAG_ERROR;
|
||||
cmc_assert(bs_set(bs, 0));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 1, bs->buffer[0]);
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, bs->flag);
|
||||
|
||||
bs->buffer[0] = 0;
|
||||
|
||||
cmc_assert(bs_set(bs, word_bits - 1));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ((cmc_bitset_word)1 << (word_bits - 1)), bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_set(bs, word_bits * 8 - 1));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ((cmc_bitset_word)1 << (word_bits - 1)),
|
||||
bs->buffer[cmc_bidx_to_widx(word_bits * 8 - 1)]);
|
||||
|
||||
cmc_assert(bs_set(bs, word_bits * 18 - 2));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ((cmc_bitset_word)1 << (word_bits - 2)),
|
||||
bs->buffer[cmc_bidx_to_widx(word_bits * 18 - 2)]);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_set_range(), {
|
||||
struct bitset *bs = bs_new(word_bits);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
bs->flag = CMC_FLAG_ERROR;
|
||||
cmc_assert(bs_set_range(bs, 0, 0));
|
||||
cmc_assert_equals(uint8_t, 1, bs->buffer[0]);
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, bs->flag);
|
||||
|
||||
cmc_assert(!bs_set_range(bs, 1, 0));
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_INVALID, bs->flag);
|
||||
|
||||
bs->buffer[0] = 0;
|
||||
|
||||
cmc_assert(bs_set_range(bs, 4, 7)); /* 1111 0000 */
|
||||
cmc_assert_equals(uint8_t, 240, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_set_range(bs, 2, 2)); /* 1111 0100 */
|
||||
cmc_assert_equals(uint8_t, 244, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_set_range(bs, word_bits * 6 - 2, word_bits * 6 - 2));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ((cmc_bitset_word)1 << (word_bits - 2)),
|
||||
bs->buffer[cmc_bidx_to_widx(word_bits * 6 - 2)]);
|
||||
|
||||
// Make sure we have at least word_bits * 40 slots
|
||||
bs_set(bs, word_bits * 40);
|
||||
|
||||
cmc_assert(bs_set_range(bs, word_bits * 20, word_bits * 21 - 1));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, (~(cmc_bitset_word)0), bs->buffer[cmc_bidx_to_widx(word_bits * 20)]);
|
||||
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[cmc_bidx_to_widx(word_bits * 20 - 1)]);
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[cmc_bidx_to_widx(word_bits * 21 + 1)]);
|
||||
|
||||
cmc_assert(bs_set_range(bs, 0, word_bits * 100 - 1));
|
||||
cmc_assert_equals(size_t, 100, bs->capacity);
|
||||
|
||||
for (size_t i = 0; i < bs->capacity; i++)
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ~((cmc_bitset_word)0), bs->buffer[i]);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_clear(), {
|
||||
struct bitset *bs = bs_new(word_bits * 10 - 1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
bs->buffer[0] = 1; // 0001
|
||||
cmc_assert(bs_clear(bs, 0));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
bs->buffer[0] = 10; // 1010
|
||||
cmc_assert(bs_clear(bs, 1));
|
||||
cmc_assert(bs_clear(bs, 3));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_clear(bs, word_bits * 100 - 1));
|
||||
cmc_assert_equals(size_t, 100, bs->capacity);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_clear_range(), {
|
||||
struct bitset *bs = bs_new(word_bits * 10 - 1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
cmc_assert(!bs_clear_range(bs, 1, 0));
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_INVALID, bs->flag);
|
||||
|
||||
cmc_assert(bs_clear_range(bs, 0, word_bits * 100 - 1));
|
||||
cmc_assert_equals(size_t, 100, bs->capacity);
|
||||
|
||||
cmc_assert(bs_set_range(bs, word_bits * 20, word_bits * 21 - 1));
|
||||
cmc_assert(bs_clear_range(bs, word_bits * 20, word_bits * 21 - 1));
|
||||
|
||||
cmc_assert_equals(uint32_t, 0, bs->buffer[cmc_bidx_to_widx(word_bits * 20)]);
|
||||
|
||||
for (size_t i = 0; i < bs->capacity; i++)
|
||||
bs->buffer[i] = ~((cmc_bitset_word)0);
|
||||
|
||||
cmc_assert(bs_set_range(bs, 0, word_bits * 100 - 1));
|
||||
cmc_assert(bs_clear_range(bs, 0, word_bits * 100 - 1));
|
||||
|
||||
cmc_assert_equals(size_t, 100, bs->capacity);
|
||||
|
||||
for (size_t i = 0; i < bs->capacity; i++)
|
||||
cmc_assert_equals(size_t, 0, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_clear_range(bs, 0, word_bits * 200 - 1));
|
||||
cmc_assert_equals(size_t, 200, bs->capacity);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_flip(), {
|
||||
struct bitset *bs = bs_new(word_bits * 10 - 1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_flip(bs, 0));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 1, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_flip(bs, 0));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_set_range(bs, 0, 2)); // 0111
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 7, bs->buffer[0]);
|
||||
cmc_assert(bs_flip(bs, 1)); // 0101
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 5, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_flip(bs, word_bits * 100 - 1));
|
||||
cmc_assert_equals(size_t, 100, bs->capacity);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_flip_range(), {
|
||||
struct bitset *bs = bs_new(word_bits * 10 - 1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_flip_range(bs, 0, 0));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 1, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_flip_range(bs, 0, 0));
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_flip_range(bs, 1, 4)); // 0001 1110
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 30, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_flip_range(bs, 2, 3)); // 0001 0010
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 18, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_flip_range(bs, 0, 2)); // 0001 0101
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 21, bs->buffer[0]);
|
||||
|
||||
bs->buffer[0] = 0;
|
||||
|
||||
cmc_assert(bs_flip_range(bs, 0, word_bits * 100 - 1));
|
||||
cmc_assert_equals(size_t, 100, bs->capacity);
|
||||
|
||||
for (size_t i = 0; i < bs->capacity; i++)
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ~((cmc_bitset_word)0), bs->buffer[i]);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_put(), {
|
||||
struct bitset *bs = bs_new(word_bits * 10 - 1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_put(bs, 1, true)); // 0010
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 2, bs->buffer[0]);
|
||||
cmc_assert(bs_put(bs, 0, false)); // 0010
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 2, bs->buffer[0]);
|
||||
cmc_assert(bs_put(bs, 1, false)); // 0000
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
cmc_assert(bs_put(bs, 3, true)); // 1000
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 8, bs->buffer[0]);
|
||||
cmc_assert(bs_put(bs, 0, true)); // 1001
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 9, bs->buffer[0]);
|
||||
cmc_assert(bs_put(bs, 3, false)); // 0001
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 1, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_put(bs, word_bits * 100 - 1, true));
|
||||
cmc_assert_equals(size_t, 100, bs->capacity);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_put_range(), {
|
||||
struct bitset *bs = bs_new(word_bits * 10 - 1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_put_range(bs, 1, 2, true)); // 0110
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 6, bs->buffer[0]);
|
||||
cmc_assert(bs_put_range(bs, 0, 1, false)); // 0100
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 4, bs->buffer[0]);
|
||||
cmc_assert(bs_put_range(bs, 1, 3, true)); // 1110
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 14, bs->buffer[0]);
|
||||
cmc_assert(bs_put_range(bs, 2, 3, false)); // 0010
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 2, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_put_range(bs, 0, word_bits * 100 - 1, true));
|
||||
cmc_assert_equals(size_t, 100, bs->capacity);
|
||||
|
||||
for (size_t i = 0; i < bs->capacity; i++)
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ~((cmc_bitset_word)0), bs->buffer[i]);
|
||||
|
||||
cmc_assert(bs_put_range(bs, 0, word_bits * 100 - 1, false));
|
||||
for (size_t i = 0; i < bs->capacity; i++)
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[i]);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_set_all(), {
|
||||
struct bitset *bs = bs_new(word_bits * 10 - 1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
|
||||
cmc_assert(bs_set_all(bs));
|
||||
|
||||
for (size_t i = 0; i < bs->capacity; i++)
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ~((cmc_bitset_word)0), bs->buffer[i]);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_clear_all(), {
|
||||
struct bitset *bs = bs_new(word_bits * 10 - 1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
|
||||
cmc_assert(bs_set_all(bs));
|
||||
cmc_assert(bs_clear_all(bs));
|
||||
|
||||
for (size_t i = 0; i < bs->capacity; i++)
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[i]);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_flip_all(), {
|
||||
struct bitset *bs = bs_new(word_bits * 10 - 1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
|
||||
cmc_assert(bs_flip_all(bs));
|
||||
for (size_t i = 0; i < bs->capacity; i++)
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ~((cmc_bitset_word)0), bs->buffer[i]);
|
||||
|
||||
cmc_assert(bs_flip_all(bs));
|
||||
for (size_t i = 0; i < bs->capacity; i++)
|
||||
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[i]);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_get(), {
|
||||
struct bitset *bs = bs_new(64);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
|
||||
cmc_assert(bs_set(bs, 1));
|
||||
|
||||
cmc_assert(bs_get(bs, 1));
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_resize(), {
|
||||
struct bitset *bs = bs_new(64);
|
||||
|
||||
// WIP
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
});
|
||||
|
||||
CMC_CREATE_UNIT(CMCBitSetIter, true, {
|
||||
// const size_t word_bytes = sizeof(cmc_bitset_word);
|
||||
// const size_t word_bits = sizeof(cmc_bitset_word) * CHAR_BIT;
|
||||
|
||||
printf("%s", cmc_test_color(5));
|
||||
printf(" BitSet<" CMC_TO_STRING(CMC_BITSET_WORD_TYPE) ">\n");
|
||||
printf("%s", cmc_test_color(0));
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_start(), {
|
||||
struct bitset *bs = bs_new(64);
|
||||
|
||||
// WIP
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
});
|
||||
|
||||
#endif /* CMC_TESTS_UNT_BITSET_H */
|
||||
@@ -308,6 +308,7 @@ CMC_CREATE_UNIT(CMCHashMultiMap, true, {
|
||||
cmc_assert(hmm_equals(map, map2));
|
||||
|
||||
hmm_free(map);
|
||||
hmm_free(map2);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_equals(), {
|
||||
@@ -1013,19 +1014,4 @@ CMC_CREATE_UNIT(CMCHashMultiMapIter, true, {
|
||||
});
|
||||
});
|
||||
|
||||
#ifdef CMC_TEST_MAIN
|
||||
int main(void)
|
||||
{
|
||||
int result = CMCHashMultiMap() + CMCHashMultiMapIter();
|
||||
|
||||
printf(" +---------------------------------------------------------------+");
|
||||
printf("\n");
|
||||
printf(" | CMCHashMultiMap Suit : %-41s |\n", result == 0 ? "PASSED" : "FAILED");
|
||||
printf(" +---------------------------------------------------------------+");
|
||||
printf("\n\n\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CMC_TESTS_UNT_HASHMULTIMAP_H */
|
||||
@@ -853,19 +853,4 @@ CMC_CREATE_UNIT(CMCHashMultiSetIter, true, {
|
||||
});
|
||||
});
|
||||
|
||||
#ifdef CMC_TEST_MAIN
|
||||
int main(void)
|
||||
{
|
||||
int result = CMCHashMultiSet() + CMCHashMultiSetIter();
|
||||
|
||||
printf(" +---------------------------------------------------------------+");
|
||||
printf("\n");
|
||||
printf(" | CMCHashMultiSet Suit : %-41s |\n", result == 0 ? "PASSED" : "FAILED");
|
||||
printf(" +---------------------------------------------------------------+");
|
||||
printf("\n\n\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CMC_TESTS_UNT_HASHMULTISET_H */
|
||||
@@ -1033,19 +1033,4 @@ CMC_CREATE_UNIT(CMCHashSetIter, true, {
|
||||
});
|
||||
});
|
||||
|
||||
#ifdef CMC_TEST_MAIN
|
||||
int main(void)
|
||||
{
|
||||
int result = CMCHashSet() + CMCHashSetIter();
|
||||
|
||||
printf(" +---------------------------------------------------------------+");
|
||||
printf("\n");
|
||||
printf(" | CMCHashSet Suit : %-46s |\n", result == 0 ? "PASSED" : "FAILED");
|
||||
printf(" +---------------------------------------------------------------+");
|
||||
printf("\n\n\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CMC_TESTS_UNT_HASHSET_H */
|
||||
@@ -0,0 +1,720 @@
|
||||
#ifndef CMC_TESTS_UNT_HEAP_H
|
||||
#define CMC_TESTS_UNT_HEAP_H
|
||||
|
||||
#include "utl.h"
|
||||
|
||||
#define V size_t
|
||||
#define PFX h
|
||||
#define SNAME heap
|
||||
#define CMC_EXT_HEAP_INIT
|
||||
#define CMC_EXT_HEAP_ITER
|
||||
#define CMC_EXT_HEAP_STR
|
||||
#include "cmc/heap.h"
|
||||
|
||||
struct heap_fval *h_fval = &(struct heap_fval){
|
||||
.cmp = cmc_size_cmp, .cpy = NULL, .str = cmc_size_str, .free = NULL, .hash = cmc_size_hash, .pri = cmc_size_cmp
|
||||
};
|
||||
|
||||
CMC_CREATE_UNIT(CMCHeap, true, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
struct heap *h = h_new(1000000, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
cmc_assert_not_equals(ptr, NULL, h->buffer);
|
||||
cmc_assert_equals(size_t, 1000000, h_capacity(h));
|
||||
cmc_assert_equals(size_t, 0, h_count(h));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case capacity = 0], {
|
||||
struct heap *h = h_new(0, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case capacity = UINT64_MAX], {
|
||||
struct heap *h = h_new(UINT64_MAX, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(clear[count capacity], {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 0; i < 50; i++)
|
||||
h_insert(h, i);
|
||||
|
||||
cmc_assert_equals(size_t, 50, h_count(h));
|
||||
|
||||
h_clear(h);
|
||||
|
||||
cmc_assert_equals(size_t, 0, h_count(h));
|
||||
cmc_assert_equals(size_t, 100, h_capacity(h));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(buffer_growth[edge_case capacity = 1], {
|
||||
struct heap *h = h_new(1, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 0; i < 50; i++)
|
||||
cmc_assert(h_insert(h, i));
|
||||
|
||||
cmc_assert_equals(size_t, 50, h_count(h));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert, {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
cmc_assert(h_insert(h, 10));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[item preservation], {
|
||||
struct heap *h = h_new(50, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 0; i <= 100; i++)
|
||||
cmc_assert(h_insert(h, i));
|
||||
|
||||
size_t sum = 0;
|
||||
for (size_t i = 0; i < h_count(h); i++)
|
||||
sum += h->buffer[i];
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove, {
|
||||
struct heap *h = h_new(50, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 0; i <= 100; i++)
|
||||
cmc_assert(h_insert(h, i));
|
||||
|
||||
cmc_assert_equals(size_t, 100, h_peek(h));
|
||||
cmc_assert(h_remove(h));
|
||||
cmc_assert_equals(size_t, 99, h_peek(h));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[count = 0], {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
cmc_assert(!h_remove(h));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[sorted], {
|
||||
struct heap *h = h_new(100, CMC_MIN_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(h_insert(h, i));
|
||||
|
||||
size_t i = 0;
|
||||
size_t arr[100];
|
||||
while (!h_empty(h))
|
||||
{
|
||||
arr[i++] = h_peek(h);
|
||||
cmc_assert(h_remove(h));
|
||||
}
|
||||
|
||||
cmc_assert_array_sorted_any(size_t, arr, cmc_size_cmp, 0, 99);
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(peek, {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(h_insert(h, i));
|
||||
|
||||
cmc_assert_equals(size_t, 100, h_peek(h));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(peek[count = 0], {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
cmc_assert_equals(size_t, (size_t){ 0 }, h_peek(h));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(flags, {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, h_flag(h));
|
||||
|
||||
h->flag = CMC_FLAG_ERROR;
|
||||
|
||||
// insert
|
||||
cmc_assert(h_insert(h, 10));
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, h_flag(h));
|
||||
|
||||
h->flag = CMC_FLAG_ERROR;
|
||||
|
||||
// remove
|
||||
cmc_assert(h_remove(h));
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, h_flag(h));
|
||||
|
||||
cmc_assert(!h_remove(h));
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, h_flag(h));
|
||||
|
||||
// peek
|
||||
cmc_assert(h_insert(h, 10));
|
||||
h_peek(h);
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, h_flag(h));
|
||||
cmc_assert(h_remove(h));
|
||||
h_peek(h);
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, h_flag(h));
|
||||
|
||||
// clear
|
||||
h_clear(h);
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, h_flag(h));
|
||||
|
||||
h->flag = CMC_FLAG_ERROR;
|
||||
|
||||
// contains
|
||||
h_contains(h, 10);
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, h_flag(h));
|
||||
|
||||
h->flag = CMC_FLAG_ERROR;
|
||||
|
||||
// copy of
|
||||
struct heap *h2 = h_copy_of(h);
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, h_flag(h));
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, h_flag(h2));
|
||||
|
||||
h->flag = CMC_FLAG_ERROR;
|
||||
h2->flag = CMC_FLAG_ERROR;
|
||||
|
||||
// equals
|
||||
cmc_assert(h_equals(h, h2));
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, h_flag(h));
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_OK, h_flag(h2));
|
||||
|
||||
h_free(h);
|
||||
h_free(h2);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(callbacks, {
|
||||
struct heap *h = h_new_custom(100, CMC_MAX_HEAP, h_fval, NULL, callbacks);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
total_create = 0;
|
||||
total_read = 0;
|
||||
total_update = 0;
|
||||
total_delete = 0;
|
||||
total_resize = 0;
|
||||
|
||||
cmc_assert(h_insert(h, 10));
|
||||
cmc_assert_equals(int32_t, 1, total_create);
|
||||
|
||||
cmc_assert(h_remove(h));
|
||||
cmc_assert_equals(int32_t, 1, total_delete);
|
||||
|
||||
cmc_assert(h_insert(h, 10));
|
||||
cmc_assert_equals(int32_t, 2, total_create);
|
||||
|
||||
cmc_assert_equals(size_t, 10, h_peek(h));
|
||||
cmc_assert_equals(int32_t, 1, total_read);
|
||||
|
||||
cmc_assert(h_contains(h, 10));
|
||||
cmc_assert_equals(int32_t, 2, total_read);
|
||||
|
||||
cmc_assert(h_resize(h, 1000));
|
||||
cmc_assert_equals(int32_t, 1, total_resize);
|
||||
|
||||
cmc_assert(h_resize(h, 100));
|
||||
cmc_assert_equals(int32_t, 2, total_resize);
|
||||
|
||||
cmc_assert_equals(int32_t, 2, total_create);
|
||||
cmc_assert_equals(int32_t, 2, total_read);
|
||||
cmc_assert_equals(int32_t, 0, total_update);
|
||||
cmc_assert_equals(int32_t, 1, total_delete);
|
||||
cmc_assert_equals(int32_t, 2, total_resize);
|
||||
|
||||
h_customize(h, NULL, NULL);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, h->callbacks);
|
||||
|
||||
h_clear(h);
|
||||
cmc_assert(h_insert(h, 10));
|
||||
cmc_assert(h_remove(h));
|
||||
cmc_assert(h_insert(h, 10));
|
||||
cmc_assert_equals(size_t, 10, h_peek(h));
|
||||
cmc_assert(h_contains(h, 10));
|
||||
cmc_assert(h_resize(h, 1000));
|
||||
cmc_assert(h_resize(h, 100));
|
||||
|
||||
cmc_assert_equals(int32_t, 2, total_create);
|
||||
cmc_assert_equals(int32_t, 2, total_read);
|
||||
cmc_assert_equals(int32_t, 0, total_update);
|
||||
cmc_assert_equals(int32_t, 1, total_delete);
|
||||
cmc_assert_equals(int32_t, 2, total_resize);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, h->callbacks);
|
||||
|
||||
h_free(h);
|
||||
|
||||
total_create = 0;
|
||||
total_read = 0;
|
||||
total_update = 0;
|
||||
total_delete = 0;
|
||||
total_resize = 0;
|
||||
});
|
||||
});
|
||||
|
||||
CMC_CREATE_UNIT(CMCHeapIter, true, {
|
||||
CMC_CREATE_TEST(PFX##_iter_start(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_start(h);
|
||||
|
||||
cmc_assert_equals(ptr, h, it.target);
|
||||
cmc_assert_equals(size_t, 0, it.cursor);
|
||||
cmc_assert_equals(bool, true, it.start);
|
||||
cmc_assert_equals(bool, true, it.end);
|
||||
|
||||
cmc_assert(h_iter_at_start(&it));
|
||||
cmc_assert(h_iter_at_end(&it));
|
||||
|
||||
cmc_assert(h_insert(h, 1));
|
||||
cmc_assert(h_insert(h, 2));
|
||||
|
||||
it = h_iter_start(h);
|
||||
|
||||
cmc_assert_equals(size_t, 0, it.cursor);
|
||||
cmc_assert_equals(bool, false, it.end);
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_end(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_end(h);
|
||||
|
||||
cmc_assert_equals(ptr, h, it.target);
|
||||
cmc_assert_equals(size_t, 0, it.cursor);
|
||||
cmc_assert_equals(bool, true, it.start);
|
||||
cmc_assert_equals(bool, true, it.end);
|
||||
|
||||
cmc_assert(h_iter_at_start(&it));
|
||||
cmc_assert(h_iter_at_end(&it));
|
||||
|
||||
cmc_assert(h_insert(h, 1));
|
||||
cmc_assert(h_insert(h, 2));
|
||||
cmc_assert(h_insert(h, 3));
|
||||
|
||||
it = h_iter_end(h);
|
||||
|
||||
cmc_assert_equals(size_t, h->count - 1, it.cursor);
|
||||
cmc_assert_equals(bool, false, it.start);
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_at_start(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_start(h);
|
||||
|
||||
// Empty checks
|
||||
cmc_assert(h_iter_at_start(&it));
|
||||
it = h_iter_end(h);
|
||||
cmc_assert(h_iter_at_start(&it));
|
||||
|
||||
// Non-empty check
|
||||
cmc_assert(h_insert(h, 1));
|
||||
it = h_iter_end(h);
|
||||
cmc_assert(!h_iter_at_start(&it));
|
||||
it = h_iter_start(h);
|
||||
cmc_assert(h_iter_at_start(&it));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_at_end(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_start(h);
|
||||
|
||||
// Empty check
|
||||
cmc_assert(h_iter_at_end(&it));
|
||||
it = h_iter_end(h);
|
||||
cmc_assert(h_iter_at_end(&it));
|
||||
|
||||
// Non-empty check
|
||||
cmc_assert(h_insert(h, 1));
|
||||
it = h_iter_end(h);
|
||||
cmc_assert(h_iter_at_end(&it));
|
||||
it = h_iter_start(h);
|
||||
cmc_assert(!h_iter_at_end(&it));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_to_start(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_start(h);
|
||||
|
||||
cmc_assert(!h_iter_to_start(&it));
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
h_insert(h, i);
|
||||
else
|
||||
h_insert(h, i);
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 100, h->count);
|
||||
|
||||
it = h_iter_end(h);
|
||||
cmc_assert(!h_iter_at_start(&it));
|
||||
cmc_assert(h_iter_at_end(&it));
|
||||
cmc_assert_equals(size_t, 99, it.cursor);
|
||||
|
||||
cmc_assert(h_iter_to_start(&it));
|
||||
cmc_assert(h_iter_at_start(&it));
|
||||
cmc_assert(!h_iter_at_end(&it));
|
||||
cmc_assert_equals(size_t, 0, it.cursor);
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_to_end(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_end(h);
|
||||
|
||||
cmc_assert(!h_iter_to_end(&it));
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
h_insert(h, i);
|
||||
else
|
||||
h_insert(h, i);
|
||||
}
|
||||
|
||||
it = h_iter_start(h);
|
||||
cmc_assert(h_iter_at_start(&it));
|
||||
cmc_assert(!h_iter_at_end(&it));
|
||||
|
||||
cmc_assert(h_iter_to_end(&it));
|
||||
cmc_assert(!h_iter_at_start(&it));
|
||||
cmc_assert(h_iter_at_end(&it));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_next(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_start(h);
|
||||
|
||||
cmc_assert(!h_iter_next(&it));
|
||||
|
||||
for (size_t i = 1; i <= 1000; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
h_insert(h, i);
|
||||
else
|
||||
h_insert(h, i);
|
||||
}
|
||||
|
||||
size_t sum = 0;
|
||||
for (it = h_iter_start(h); !h_iter_at_end(&it); h_iter_next(&it))
|
||||
{
|
||||
sum += h_iter_value(&it);
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 500500, sum);
|
||||
|
||||
sum = 0;
|
||||
|
||||
h_iter_to_start(&it);
|
||||
do
|
||||
{
|
||||
sum += h_iter_value(&it);
|
||||
} while (h_iter_next(&it));
|
||||
|
||||
cmc_assert_equals(size_t, 500500, sum);
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_prev(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_end(h);
|
||||
|
||||
cmc_assert(!h_iter_prev(&it));
|
||||
|
||||
for (size_t i = 1; i <= 1000; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
h_insert(h, i);
|
||||
else
|
||||
h_insert(h, i);
|
||||
}
|
||||
|
||||
size_t sum = 0;
|
||||
for (it = h_iter_end(h); !h_iter_at_start(&it); h_iter_prev(&it))
|
||||
{
|
||||
sum += h_iter_value(&it);
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 500500, sum);
|
||||
|
||||
sum = 0;
|
||||
|
||||
h_iter_to_end(&it);
|
||||
do
|
||||
{
|
||||
sum += h_iter_value(&it);
|
||||
} while (h_iter_prev(&it));
|
||||
|
||||
cmc_assert_equals(size_t, 500500, sum);
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_advance(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_start(h);
|
||||
|
||||
cmc_assert(!h_iter_advance(&it, 1));
|
||||
|
||||
for (size_t i = 1; i <= 1000; i++)
|
||||
h_insert(h, i);
|
||||
|
||||
it = h_iter_start(h);
|
||||
|
||||
cmc_assert(!h_iter_advance(&it, 0));
|
||||
cmc_assert(!h_iter_advance(&it, h->count));
|
||||
|
||||
size_t sum = 0;
|
||||
for (it = h_iter_start(h);;)
|
||||
{
|
||||
sum += h_iter_value(&it);
|
||||
|
||||
if (!h_iter_advance(&it, 2))
|
||||
break;
|
||||
|
||||
cmc_assert_equals(size_t, 0, h_iter_index(&it) % 2);
|
||||
}
|
||||
|
||||
cmc_assert(h_iter_to_start(&it));
|
||||
cmc_assert(h_iter_next(&it));
|
||||
|
||||
cmc_assert_equals(size_t, 1, h_iter_index(&it));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
sum += h_iter_value(&it);
|
||||
|
||||
if (!h_iter_advance(&it, 2))
|
||||
break;
|
||||
|
||||
cmc_assert_equals(size_t, 1, h_iter_index(&it) % 2);
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 500500, sum);
|
||||
|
||||
h_iter_to_start(&it);
|
||||
cmc_assert(h_iter_advance(&it, h->count - 1));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_rewind(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_end(h);
|
||||
|
||||
cmc_assert(!h_iter_rewind(&it, 1));
|
||||
|
||||
for (size_t i = 0; i <= 1000; i++)
|
||||
h_insert(h, i);
|
||||
|
||||
it = h_iter_end(h);
|
||||
|
||||
cmc_assert(!h_iter_rewind(&it, 0));
|
||||
cmc_assert(!h_iter_rewind(&it, h->count));
|
||||
|
||||
size_t sum = 0;
|
||||
for (it = h_iter_end(h);;)
|
||||
{
|
||||
sum += h_iter_value(&it);
|
||||
|
||||
if (!h_iter_rewind(&it, 2))
|
||||
break;
|
||||
|
||||
cmc_assert_equals(size_t, 0, h_iter_index(&it) % 2);
|
||||
}
|
||||
|
||||
cmc_assert(h_iter_to_end(&it));
|
||||
cmc_assert(h_iter_prev(&it));
|
||||
|
||||
cmc_assert_equals(size_t, h->count - 2, h_iter_index(&it));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
sum += h_iter_value(&it);
|
||||
|
||||
if (!h_iter_rewind(&it, 2))
|
||||
break;
|
||||
|
||||
cmc_assert_equals(size_t, 1, h_iter_index(&it) % 2);
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 500500, sum);
|
||||
|
||||
h_iter_to_end(&it);
|
||||
cmc_assert(h_iter_rewind(&it, h->count - 1));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_go_to(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_end(h);
|
||||
cmc_assert(!h_iter_go_to(&it, 0));
|
||||
|
||||
it = h_iter_start(h);
|
||||
cmc_assert(!h_iter_go_to(&it, 0));
|
||||
|
||||
for (size_t i = 0; i <= 1000; i++)
|
||||
h_insert(h, i);
|
||||
|
||||
cmc_assert_equals(size_t, 1001, h->count);
|
||||
|
||||
it = h_iter_start(h);
|
||||
|
||||
size_t sum = 0;
|
||||
for (size_t i = 0; i < 1001; i++)
|
||||
{
|
||||
h_iter_go_to(&it, i);
|
||||
|
||||
sum += h_iter_value(&it);
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 500500, sum);
|
||||
|
||||
sum = 0;
|
||||
for (size_t i = 1001; i > 0; i--)
|
||||
{
|
||||
cmc_assert(h_iter_go_to(&it, i - 1));
|
||||
|
||||
sum += h_iter_value(&it);
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 500500, sum);
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_value(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
struct heap_iter it = h_iter_end(h);
|
||||
|
||||
cmc_assert_equals(size_t, (size_t){ 0 }, h_iter_value(&it));
|
||||
|
||||
cmc_assert(h_insert(h, 1));
|
||||
cmc_assert(h_insert(h, 3));
|
||||
cmc_assert(h_insert(h, 2));
|
||||
|
||||
it = h_iter_start(h);
|
||||
|
||||
cmc_assert_equals(size_t, 3, h_iter_value(&it));
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_iter_index(), {
|
||||
struct heap *h = h_new(100, CMC_MAX_HEAP, h_fval);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 0; i <= 1000; i++)
|
||||
h_insert(h, i);
|
||||
|
||||
struct heap_iter it = h_iter_start(h);
|
||||
|
||||
for (size_t i = 0; i < 1001; i++)
|
||||
{
|
||||
cmc_assert_equals(size_t, i, h_iter_index(&it));
|
||||
h_iter_next(&it);
|
||||
}
|
||||
|
||||
it = h_iter_end(h);
|
||||
for (size_t i = 1001; i > 0; i--)
|
||||
{
|
||||
cmc_assert_equals(size_t, i - 1, h_iter_index(&it));
|
||||
h_iter_prev(&it);
|
||||
}
|
||||
|
||||
h_free(h);
|
||||
});
|
||||
});
|
||||
|
||||
#endif /* CMC_TESTS_UNT_HEAP_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -837,19 +837,4 @@ CMC_CREATE_UNIT(CMCStackIter, true, {
|
||||
});
|
||||
});
|
||||
|
||||
#ifdef CMC_TEST_MAIN
|
||||
int main(void)
|
||||
{
|
||||
int result = CMCStack() + CMCStackIter();
|
||||
|
||||
printf(" +---------------------------------------------------------------+");
|
||||
printf("\n");
|
||||
printf(" | CMCStack Suit : %-48s |\n", result == 0 ? "PASSED" : "FAILED");
|
||||
printf(" +---------------------------------------------------------------+");
|
||||
printf("\n\n\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CMC_TESTS_UNT_STACK_H */
|
||||
Reference in new issue
Block a user