diff --git a/README.md b/README.md index ac00791..344f998 100644 --- a/README.md +++ b/README.md @@ -99,12 +99,12 @@ int main( void ) int *our_vec = NULL; vec_push( our_vec, 5 ); printf( "%d\n", our_vec[ 0 ] ); - free( our_vec ); + vec_cleanup( our_vec ); int_float_pair *our_map = NULL; map_insert( our_map, 5, 0.5f ); printf( "%f\n", *map_get( our_map, 5 ) ); - free( our_map ); + map_cleanup( our_map ); } ``` @@ -560,11 +560,13 @@ int main( void ) ``` -### Custom comparison and hash functions +### Custom hash and comparison functions -**CC** includes default comparison and hash functions for fundamental integer types and `NULL`-terminated strings (`char *`). Hence, these types can be used as `map` and `omap` keys, and `set` and `oset` elements, straight away. +**CC** includes default hash and comparison functions for fundamental integer types and `NULL`-terminated strings (`char *`). Hence, these types can be used as map and ordered map keys, and set and ordered set elements, straight away. -To use other types or overwrite the default functions for the aforementioned types, define custom comparison and hash functions with the signatures `int ( type val_1, type val_2 )` and `size_t ( type val )`, respectively. +To use other types or overwrite the default functions for the aforementioned types, define custom hash and/or comparison functions with the signatures `int ( type val_1, type val_2 )` and `size_t ( type val )`, respectively. + +Maps and sets require both a hash and comparison function, whereas ordered maps and ordered sets require only a comparison function. ```c #include "cc.h" @@ -583,9 +585,11 @@ typedef struct int main( void ) { - // Now we can use our own type as map keys and set elements. + // Now we can use our own type as map and ordered map keys and set and ordered set elements. map( our_type, int ) our_map; + omap( our_type, int ) our_omap; set( our_type ) our_set; + oset( our_type ) our_oset; } ``` diff --git a/benchmarks/omap_and_oset/bench_omap_and_oset.cpp b/benchmarks/omap_and_oset/bench_omap_and_oset.cpp new file mode 100644 index 0000000..937d033 --- /dev/null +++ b/benchmarks/omap_and_oset/bench_omap_and_oset.cpp @@ -0,0 +1,200 @@ +/* + +Convenient Containers v1.3.0 - benchmarks/omap_and_oset/bench_omap_and_oset.cpp + +This file benchmarks CC's ordered map and ordered set against the equivalent C++ STL containers. + +License (MIT): + + Copyright (c) 2024 Jackson L. Allan + + 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. + +*/ + +#define NDEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CC_NO_SHORT_NAMES +#include "../../cc.h" + +int main() +{ + constexpr int key_count = 10000000; + constexpr int run_count = 10; + + std::vector keys( key_count ); + std::iota( keys.begin(), keys.end(), 1 ); + std::shuffle( + keys.begin(), + keys.end(), + std::default_random_engine( std::chrono::system_clock::now().time_since_epoch().count() ) + ); + + std::chrono::time_point start; + std::chrono::time_point end; + unsigned long long optimization_preventer = 0; + + double total_omap_insert_time = 0.0; + double total_omap_lookup_time = 0.0; + double total_omap_erase_time = 0.0; + double total_map_insert_time = 0.0; + double total_map_lookup_time = 0.0; + double total_map_erase_time = 0.0; + double total_oset_insert_time = 0.0; + double total_oset_lookup_time = 0.0; + double total_oset_erase_time = 0.0; + double total_set_insert_time = 0.0; + double total_set_lookup_time = 0.0; + double total_set_erase_time = 0.0; + + for( int run = 0; run < run_count; ++run ) + { + std::cout << "Run " << run << '\n'; + + // omap. + { + cc_omap( int, int ) our_omap; + cc_init( &our_omap ); + std::this_thread::sleep_for( std::chrono::seconds( 1 ) ); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + cc_insert( &our_omap, keys[ i ], 0 ); + end = std::chrono::high_resolution_clock::now(); + total_omap_insert_time += std::chrono::duration_cast>( end - start ).count(); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + optimization_preventer += *cc_key_for( &our_omap, cc_get( &our_omap, keys[ i ] ) ); + end = std::chrono::high_resolution_clock::now(); + total_omap_lookup_time += std::chrono::duration_cast>( end - start ).count(); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + cc_erase( &our_omap, keys[ i ] ); + end = std::chrono::high_resolution_clock::now(); + total_omap_erase_time += std::chrono::duration_cast>( end - start ).count(); + + cc_cleanup( &our_omap ); + } + + // std::map. + { + std::map our_map; + std::this_thread::sleep_for( std::chrono::seconds( 1 ) ); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + our_map.insert( { keys[ i ], 0 } ); + end = std::chrono::high_resolution_clock::now(); + total_map_insert_time += std::chrono::duration_cast>( end - start ).count(); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + optimization_preventer += our_map.find( keys[ i ] )->first; + end = std::chrono::high_resolution_clock::now(); + total_map_lookup_time += std::chrono::duration_cast>( end - start ).count(); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + our_map.erase( keys[ i ] ); + end = std::chrono::high_resolution_clock::now(); + total_map_erase_time += std::chrono::duration_cast>( end - start ).count(); + } + + // oset. + { + cc_oset( int ) our_oset; + cc_init( &our_oset ); + std::this_thread::sleep_for( std::chrono::seconds( 1 ) ); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + cc_insert( &our_oset, keys[ i ] ); + end = std::chrono::high_resolution_clock::now(); + total_oset_insert_time += std::chrono::duration_cast>( end - start ).count(); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + optimization_preventer += *cc_get( &our_oset, keys[ i ] ); + end = std::chrono::high_resolution_clock::now(); + total_oset_lookup_time += std::chrono::duration_cast>( end - start ).count(); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + cc_erase( &our_oset, keys[ i ] ); + end = std::chrono::high_resolution_clock::now(); + total_oset_erase_time += std::chrono::duration_cast>( end - start ).count(); + + cc_cleanup( &our_oset ); + } + + // std::set. + { + std::set our_set; + std::this_thread::sleep_for( std::chrono::seconds( 1 ) ); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + our_set.insert( keys[ i ] ); + end = std::chrono::high_resolution_clock::now(); + total_set_insert_time += std::chrono::duration_cast>( end - start ).count(); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + optimization_preventer += *our_set.find( keys[ i ] ); + end = std::chrono::high_resolution_clock::now(); + total_set_lookup_time += std::chrono::duration_cast>( end - start ).count(); + + start = std::chrono::high_resolution_clock::now(); + for( size_t i = 0; i < key_count; ++i ) + our_set.erase( keys[ i ] ); + end = std::chrono::high_resolution_clock::now(); + total_set_erase_time += std::chrono::duration_cast>( end - start ).count(); + } + } + + std::cout << std::setprecision( 2 ) << std::fixed; + + std::cout << "---Insert results---\n"; + std::cout << "omap: " << total_omap_insert_time / run_count << "s\n"; + std::cout << "map: " << total_map_insert_time / run_count << "s\n"; + std::cout << "oset: " << total_oset_insert_time / run_count << "s\n"; + std::cout << "set: " << total_set_insert_time / run_count << "s\n"; + + std::cout << "---Lookup results---\n"; + std::cout << "omap: " << total_omap_lookup_time / run_count << "s\n"; + std::cout << "map: " << total_map_lookup_time / run_count << "s\n"; + std::cout << "oset: " << total_oset_lookup_time / run_count << "s\n"; + std::cout << "set: " << total_set_lookup_time / run_count << "s\n"; + + std::cout << "---Erase results---\n"; + std::cout << "omap: " << total_omap_erase_time / run_count << "s\n"; + std::cout << "map: " << total_map_erase_time / run_count << "s\n"; + std::cout << "oset: " << total_oset_erase_time / run_count << "s\n"; + std::cout << "set: " << total_set_erase_time / run_count << "s\n"; + + std::cout << "Done " << optimization_preventer << '\n'; +} diff --git a/cc.h b/cc.h index ffb9453..c846194 100644 --- a/cc.h +++ b/cc.h @@ -771,7 +771,7 @@ Including the library: Version history: - 28/07/2024 1.3.0: Added ordered map and ordered set. + 29/07/2024 1.3.0: Added ordered map and ordered set. Fixed cc_erase_itr to return a correctly typed pointer-iterator instead of void *. Fixed a bug in list that caused cc_next and cc_prev to behave incorrectly when passed an r_end and end pointer-iterator, respectively. diff --git a/omap_bench/main.cpp b/omap_bench/main.cpp deleted file mode 100644 index 99d1008..0000000 --- a/omap_bench/main.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#define NDEBUG - -#include -#include -#include -#include -#include - -#define CC_NO_SHORT_NAMES -#include "../cc.h" - -int main( void ) -{ - const int key_count = 10000000; - - int *keys = (int *)malloc( sizeof( int ) * key_count ); - if( !keys ) - return 1; - - for( int i = 0; i < key_count; ++i ) - { - unsigned long long val = i; - val ^= val >> 23; - val *= 0x2127599BF4325C37ULL; - val ^= val >> 47; - keys[ i ] = val; - } - - std::chrono::time_point start; - std::chrono::time_point end; - unsigned long long total; - - // omap. - { - cc_omap( int, int ) our_omap; - cc_init( &our_omap ); - std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) ); - - start = std::chrono::high_resolution_clock::now(); - for( int i = 0; i < key_count; ++i ) - cc_insert( &our_omap, keys[ i ], 0 ); - end = std::chrono::high_resolution_clock::now(); - printf( "omap insert %lld\n", std::chrono::duration_cast( end - start ).count() ); - - total = 0; - start = std::chrono::high_resolution_clock::now(); - for( int i = 0; i < key_count; ++i ) - total += *cc_key_for( &our_omap, cc_get( &our_omap, keys[ i ] ) ); - end = std::chrono::high_resolution_clock::now(); - printf( "omap lookup %lld, total: %llu\n", std::chrono::duration_cast( end - start ).count(), total ); - } - - // std::map. - { - std::map our_map; - std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) ); - - start = std::chrono::high_resolution_clock::now(); - for( int i = 0; i < key_count; ++i ) - our_map.insert( { keys[ i ], 0 } ); - end = std::chrono::high_resolution_clock::now(); - printf( "std::map insert %lld\n", std::chrono::duration_cast( end - start ).count() ); - - total = 0; - start = std::chrono::high_resolution_clock::now(); - for( int i = 0; i < key_count; ++i ) - total += our_map.find( keys[ i ] )->first; - end = std::chrono::high_resolution_clock::now(); - printf( "std::map lookup %lld, total: %llu\n", std::chrono::duration_cast( end - start ).count(), total ); - } - - // oset. - { - cc_oset( int ) our_oset; - cc_init( &our_oset ); - std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) ); - - start = std::chrono::high_resolution_clock::now(); - for( int i = 0; i < key_count; ++i ) - cc_insert( &our_oset, keys[ i ] ); - end = std::chrono::high_resolution_clock::now(); - printf( "oset insert %lld\n", std::chrono::duration_cast( end - start ).count() ); - - total = 0; - start = std::chrono::high_resolution_clock::now(); - for( int i = 0; i < key_count; ++i ) - total += *cc_get( &our_oset, keys[ i ] ); - end = std::chrono::high_resolution_clock::now(); - printf( "oset lookup %lld, total: %llu\n", std::chrono::duration_cast( end - start ).count(), total ); - } - - // std::set. - { - std::set our_set; - std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) ); - - start = std::chrono::high_resolution_clock::now(); - for( int i = 0; i < key_count; ++i ) - our_set.insert( keys[ i ] ); - end = std::chrono::high_resolution_clock::now(); - printf( "std::set insert %lld\n", std::chrono::duration_cast( end - start ).count() ); - - total = 0; - start = std::chrono::high_resolution_clock::now(); - for( int i = 0; i < key_count; ++i ) - total += *our_set.find( keys[ i ] ); - end = std::chrono::high_resolution_clock::now(); - printf( "std::set lookup %lld, total: %llu\n", std::chrono::duration_cast( end - start ).count(), total ); - } - - free( keys ); - printf( "Done\n" ); -} diff --git a/omap_test/omap_test.c b/omap_test/omap_test.c deleted file mode 100644 index 362508d..0000000 --- a/omap_test/omap_test.c +++ /dev/null @@ -1,316 +0,0 @@ -#include -#include - -#include "../cc.h" - -void check_node( void *cntr, cc_omapnode_hdr_ty *node, int branch_black_depth, int *overall_black_depth ) -{ - if( node == cc_omap_hdr( cntr )->sentinel ) - { - if( *overall_black_depth == -1 ) - *overall_black_depth = branch_black_depth; - else - assert( branch_black_depth == *overall_black_depth ); - - return; - } - - assert( !node->is_red || !node->parent->is_red ); - - if( !node->is_red ) - ++branch_black_depth; - - check_node( cntr, node->children[ 0 ], branch_black_depth, overall_black_depth ); - check_node( cntr, node->children[ 1 ], branch_black_depth, overall_black_depth ); -} - -void check( void *cntr ) -{ - if( cc_omap_hdr( cntr )->root == cc_omap_hdr( cntr )->sentinel ) - return; - - assert( !cc_omap_hdr( cntr )->root->is_red ); - - int overall_black_depth = -1; - check_node( cntr, cc_omap_hdr( cntr )->root, 0, &overall_black_depth ); -} - -#if 0 -int main( void ) -{ - const int run_count = 50000; - const int key_count = 5000; - - int *keys = (int *)malloc( sizeof( int ) * key_count ); - if( !keys ) - return 1; - - unsigned long long seed = 1; - - omap( int, int ) tree; - init( &tree ); - - for( int run = 0; run < run_count; ++run ) - { - unsigned long long total = 0; - for( int i = 0; i < key_count; ++i ) - { - unsigned long long val = seed++; - val ^= val >> 23; - val *= 0x2127599BF4325C37ULL; - val ^= val >> 47; - keys[ i ] = val; - // keys[ i ] = i; - total += keys[ i ]; - } - - for( int i = 0; i < key_count; ++i ) - for( int j = i + 1; j < key_count; ++j ) - assert( keys[ i ] != keys[ j ] ); - - printf( "Run %d\n", run ); - - for( int i = 0; i < key_count; ++i ) - insert( &tree, keys[ i ], keys[ i ] / 2 ); - - assert( size( &tree ) == key_count ); - - for( int i = 0; i < key_count; ++i ) - { - int *el = get_or_insert( &tree, keys[ i ], 0 ); - assert( *el == keys[ i ] / 2 ); - } - - for( int i = 0; i < key_count; ++i ) - { - int *el = get( &tree, keys[ i ] ); - assert( *el == keys[ i ] / 2 ); - assert( *key_for( &tree, el ) == keys[ i ] ); - } - - check( tree ); - -//// - omap( int, int ) clone; - assert( init_clone( &clone, &tree ) ); - cleanup( &tree ); - tree = clone; - - for( int i = 0; i < key_count; ++i ) - { - int *el = get( &tree, keys[ i ] ); - assert( *el == keys[ i ] / 2 ); - assert( *key_for( &tree, el ) == keys[ i ] ); - } -//// - - unsigned long long iterations = 0; - unsigned long long total_ = 0; - int last = 0; - // for( int *itr = first( &tree ); itr != end( &tree ); itr = next( &tree, itr ) ) - for_each( &tree, itr ) - { - assert( last == 0 || *key_for( &tree, itr ) > last ); - last = *key_for( &tree, itr ); - total_ += *key_for( &tree, itr ); - ++iterations; - } - printf( "iterations: %llu\n", iterations ); - assert( total_ == total ); - - iterations = 0; - total_ = 0; - last = INT_MAX; - for( int *itr = last( &tree ); itr != r_end( &tree ); itr = prev( &tree, itr ) ) - { - assert( last == INT_MAX || *key_for( &tree, itr ) < last ); - last = *key_for( &tree, itr ); - total_ += *key_for( &tree, itr ); - ++iterations; - } - assert( total_ == total ); - - iterations = 0; - for( - int *itr = first( &tree, 1000000 ), *range_end = first( &tree, 2000000 ); - itr != range_end; - itr = next( &tree, itr ) - ) - ++iterations; - printf( "Range: %zu\n", iterations ); - - iterations = 0; - for( - int *itr = last( &tree, 1999999 ), *range_end = last( &tree, 999999 ); - itr != range_end; - itr = prev( &tree, itr ) - ) - ++iterations; - printf( "Range: %zu\n", iterations ); - -/* - int_rbt_node *start = int_rbt_first_above_equal( &tree, 100 ); - int_rbt_node *end = int_rbt_first_above( &tree, 200 ); - for( int_rbt_node *node = start; node != end; node = int_rbt_next( &tree, node ) ) - printf( "... %d\n", node->key ); -*/ - - for( int *itr = first( &tree ); itr != end( &tree ); ) - { - if( *key_for( &tree, itr ) % 2 ) - itr = erase_itr( &tree, itr ); - else - itr = next( &tree, itr ); - } - - for( int i = 0; i < key_count; ++i ) - { - int *el = get( &tree, keys[ i ] ); - if( el ) - assert( *key_for( &tree, el ) % 2 == 0 ); - } - - clear( &tree ); - } - - cleanup( &tree ); - - free( keys ); - printf( "Done\n" ); -} -#endif - -int main( void ) -{ - const int run_count = 50000; - const int key_count = 5000; - - int *keys = (int *)malloc( sizeof( int ) * key_count ); - if( !keys ) - return 1; - - unsigned long long seed = 1; - - oset( int ) tree; - init( &tree ); - - for( int run = 0; run < run_count; ++run ) - { - unsigned long long total = 0; - for( int i = 0; i < key_count; ++i ) - { - unsigned long long val = seed++; - val ^= val >> 23; - val *= 0x2127599BF4325C37ULL; - val ^= val >> 47; - keys[ i ] = val; - // keys[ i ] = i; - total += keys[ i ]; - } - - for( int i = 0; i < key_count; ++i ) - for( int j = i + 1; j < key_count; ++j ) - assert( keys[ i ] != keys[ j ] ); - - printf( "Run %d\n", run ); - - for( int i = 0; i < key_count; ++i ) - insert( &tree, keys[ i ] ); - - assert( size( &tree ) == key_count ); - - for( int i = 0; i < key_count; ++i ) - { - int *el = get_or_insert( &tree, keys[ i ] ); - assert( *el == keys[ i ] ); - } - - for( int i = 0; i < key_count; ++i ) - { - int *el = get( &tree, keys[ i ] ); - assert( *el == keys[ i ] ); - } - - - check( tree ); - -//// - oset( int ) clone; - assert( init_clone( &clone, &tree ) ); - cleanup( &tree ); - tree = clone; - - for( int i = 0; i < key_count; ++i ) - { - int *el = get( &tree, keys[ i ] ); - assert( *el == keys[ i ] ); - } -//// - - unsigned long long iterations = 0; - unsigned long long total_ = 0; - int last = 0; - // for( int *itr = first( &tree ); itr != end( &tree ); itr = next( &tree, itr ) ) - for_each( &tree, itr ) - { - assert( last == 0 || *itr > last ); - last = *itr; - total_ += *itr; - ++iterations; - } - printf( "iterations: %llu\n", iterations ); - assert( total_ == total ); - - iterations = 0; - total_ = 0; - last = INT_MAX; - for( int *itr = last( &tree ); itr != r_end( &tree ); itr = prev( &tree, itr ) ) - { - assert( last == INT_MAX || *itr < last ); - last = *itr; - total_ += *itr; - ++iterations; - } - assert( total_ == total ); - - iterations = 0; - for( - int *itr = first( &tree, 1000000 ), *range_end = first( &tree, 2000000 ); - itr != range_end; - itr = next( &tree, itr ) - ) - ++iterations; - printf( "Range: %zu\n", iterations ); - - iterations = 0; - for( - int *itr = last( &tree, 1999999 ), *range_end = last( &tree, 999999 ); - itr != range_end; - itr = prev( &tree, itr ) - ) - ++iterations; - printf( "Range: %zu\n", iterations ); - - for( int *itr = first( &tree ); itr != end( &tree ); ) - { - if( *itr % 2 ) - itr = erase_itr( &tree, itr ); - else - itr = next( &tree, itr ); - } - - for( int i = 0; i < key_count; ++i ) - { - int *el = get( &tree, keys[ i ] ); - if( el ) - assert( *el % 2 == 0 ); - } - - clear( &tree ); - } - - cleanup( &tree ); - - free( keys ); - printf( "Done\n" ); -} diff --git a/tests/tests_against_stl.cpp b/tests/tests_against_stl.cpp index 6bd7a33..4a9e475 100644 --- a/tests/tests_against_stl.cpp +++ b/tests/tests_against_stl.cpp @@ -2,7 +2,7 @@ Convenient Containers v1.3.0 - tests/tests_against_stl.cpp -This file tests CC containers against equivalent C++ STL containers. +This file tests CC containers against the equivalent C++ STL containers. Primarily, it checks that a CC container and its equivalent STL container end up in the same state after a random series of the same operations are performed on both. It also checks that results of API calls that return iterators are as expected. diff --git a/vec_iteration_bench/main.cpp b/vec_iteration_bench/main.cpp deleted file mode 100644 index 103d8d4..0000000 --- a/vec_iteration_bench/main.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#define NDEBUG - -#include -#include -#include - -#define CC_NO_SHORT_NAMES -#include "../cc.h" - -int main( void ) -{ - const int key_count = 10000000; - - unsigned int *keys = (unsigned int *)malloc( sizeof( unsigned int ) * key_count ); - if( !keys ) - return 1; - - for( unsigned int i = 0; i < key_count; ++i ) - { - unsigned long long val = i; - val ^= val >> 23; - val *= 0x2127599BF4325C37ULL; - val ^= val >> 47; - keys[ i ] = val; - } - - std::chrono::time_point start; - std::chrono::time_point end; - - // - { - cc_vec( unsigned int ) our_vec; - cc_init( &our_vec ); - std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) ); - - cc_push_n( &our_vec, keys, key_count ); - - int total = 0; - start = std::chrono::high_resolution_clock::now(); - cc_for_each( &our_vec, itr ) - total += *itr; - end = std::chrono::high_resolution_clock::now(); - printf( "%lld, %u\n", std::chrono::duration_cast( end - start ).count(), total ); - - cc_cleanup( &our_vec ); - } - - // - { - cc_vec( unsigned int ) our_vec; - cc_init( &our_vec ); - std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) ); - - cc_push_n( &our_vec, keys, key_count ); - - int total = 0; - start = std::chrono::high_resolution_clock::now(); - for( unsigned int *itr = cc_first( &our_vec ); itr != cc_end( &our_vec ); itr = (unsigned int *)cc_vec_next_original( our_vec, itr, CC_EL_SIZE( our_vec ), 0 ) ) - total += *itr; - end = std::chrono::high_resolution_clock::now(); - printf( "%lld, %u\n", std::chrono::duration_cast( end - start ).count(), total ); - - cc_cleanup( &our_vec ); - } - - free( keys ); - printf( "Done\n" ); -}