int main() { { Deque_MyClass deq; Deque_MyClass_ctor(&deq, MyClass_less_by_id); assert(deq.size(&deq) == 0); assert(deq.empty(&deq)); // Should print "---- Deque_MyClass, 14". printf("---- %s, %d\n", deq.type_name, (int) sizeof(deq.type_name)); // std::cout << "---- " << deq.type_name << ", " << sizeof(deq.type_name) << std::endl; assert(sizeof deq.type_name == 14); deq.push_back(&deq, MyClass{1, "Joe"}); deq.push_back(&deq, MyClass{2, "Mary"}); deq.push_back(&deq, MyClass{3, "Tom"}); deq.push_front(&deq, MyClass{0, "Mike"}); deq.push_front(&deq, MyClass{-1, "Mary"}); MyClass_print(&deq.front(&deq)); MyClass_print(&deq.back(&deq)); assert(deq.front(&deq).id == -1); assert(deq.back(&deq).id == 3); deq.pop_front(&deq); deq.pop_back(&deq); assert(deq.front(&deq).id == 0); assert(deq.back(&deq).id == 2); assert(deq.size(&deq) == 3); for (Deque_MyClass_Iterator it = deq.begin(&deq); !Deque_MyClass_Iterator_equal(it, deq.end(&deq)); it.inc(&it)) { MyClass_print(&it.deref(&it)); } // Multiple iterators? for (Deque_MyClass_Iterator it1 = deq.begin(&deq); !Deque_MyClass_Iterator_equal(it1, deq.end(&deq)); it1.inc(&it1)) { MyClass_print(&it1.deref(&it1)); for (Deque_MyClass_Iterator it2 = deq.begin(&deq); !Deque_MyClass_Iterator_equal(it2, deq.end(&deq)); it2.inc(&it2)) { MyClass_print(&it2.deref(&it2)); for (Deque_MyClass_Iterator it3 = deq.begin(&deq); !Deque_MyClass_Iterator_equal(it3, deq.end(&deq)); it3.inc(&it3)) { MyClass_print(&it3.deref(&it3)); } } } // Test decrement of end. { auto it = deq.end(&deq); it.dec(&it); assert(it.deref(&it).id == 2); } // printf("Using at.\n"); for (size_t i = 0; i < 3; i++) { MyClass_print(&deq.at(&deq, i)); } // Test that front(), back(), at(), and deref() are returning a reference. // Change via at(). assert(deq.at(&deq, 0).id == 0); deq.at(&deq, 0).id = 100; assert(deq.at(&deq, 0).id == 100); // Change via front(). assert(deq.front(&deq).id == 100); deq.front(&deq).id = 0; assert(deq.front(&deq).id == 0); assert(deq.at(&deq, 0).id == 0); // Verify with at() also. { auto it = deq.end(&deq); it.dec(&it); assert(it.deref(&it).id == 2); it.deref(&it).id = 200; assert(it.deref(&it).id == 200); // Change using back(). assert(deq.back(&deq).id == 200); deq.back(&deq).id = 2; assert(deq.back(&deq).id == 2); assert(it.deref(&it).id == 2); // Verify with iterator also. } deq.clear(&deq); deq.dtor(&deq); // Test equality. Two deques compare equal if they are of the same // length and all the elements compare equal. It is undefined behavior // if the two deques were constructed with different comparison // functions. { Deque_MyClass deq1, deq2; Deque_MyClass_ctor(&deq1, MyClass_less_by_id); Deque_MyClass_ctor(&deq2, MyClass_less_by_id); deq1.push_back(&deq1, MyClass{1, "Joe"}); deq1.push_back(&deq1, MyClass{2, "Jane"}); deq1.push_back(&deq1, MyClass{3, "Mary"}); deq2.push_back(&deq2, MyClass{1, "Joe"}); deq2.push_back(&deq2, MyClass{2, "Jane"}); deq2.push_back(&deq2, MyClass{3, "Mary"}); assert(Deque_MyClass_equal(deq1, deq2)); deq1.pop_back(&deq1); assert(!Deque_MyClass_equal(deq1, deq2)); deq1.push_back(&deq1, MyClass{4, "Mary"}); assert(!Deque_MyClass_equal(deq1, deq2)); deq1.dtor(&deq1); deq2.dtor(&deq2); } } // Test that it can handle other types. Tests are the same, more or less. { Deque_int deq; Deque_int_ctor(&deq, int_less); assert(deq.size(&deq) == 0); assert(deq.empty(&deq)); // Should print "---- Deque_int, 10". printf("---- %s, %d\n", deq.type_name, int(sizeof(deq.type_name))); // std::cout << "---- " << deq.type_name << ", " << sizeof(deq.type_name) << std::endl; assert(sizeof deq.type_name == 10); deq.push_back(&deq, 1); deq.push_back(&deq, 2); deq.push_back(&deq, 3); deq.push_front(&deq, 0); deq.push_front(&deq, -1); printf("%d\n", deq.front(&deq)); printf("%d\n", deq.back(&deq)); assert(deq.front(&deq) == -1); assert(deq.back(&deq) == 3); deq.pop_front(&deq); deq.pop_back(&deq); assert(deq.front(&deq) == 0); assert(deq.back(&deq) == 2); assert(deq.size(&deq) == 3); for (Deque_int_Iterator it = deq.begin(&deq); !Deque_int_Iterator_equal(it, deq.end(&deq)); it.inc(&it)) { printf("%d\n", it.deref(&it)); } // Test decrement. { auto it = deq.end(&deq); it.dec(&it); assert(it.deref(&it) == 2); } printf("Using at.\n"); for (size_t i = 0; i < 3; i++) { printf("%d: %d\n", int(i), deq.at(&deq, i)); } deq.clear(&deq); deq.dtor(&deq); } // Test equality. It is undefined behavior if the two deques were constructed with different // comparison functions. { Deque_int deq1, deq2; Deque_int_ctor(&deq1, int_less); Deque_int_ctor(&deq2, int_less); deq1.push_back(&deq1, 1); deq1.push_back(&deq1, 2); deq1.push_back(&deq1, 3); deq2.push_back(&deq2, 1); deq2.push_back(&deq2, 2); deq2.push_back(&deq2, 3); assert(Deque_int_equal(deq1, deq2)); deq1.pop_back(&deq1); assert(!Deque_int_equal(deq1, deq2)); deq1.push_back(&deq1, 4); assert(!Deque_int_equal(deq1, deq2)); deq1.dtor(&deq1); deq2.dtor(&deq2); } // Test performance. { std::default_random_engine e; using rand = std::uniform_int_distribution<int>; std::uniform_real_distribution<float> action; Deque_int deq; Deque_int_ctor(&deq, int_less); for (int i = 0; i < 1000000; i++) { deq.push_back(&deq, i); } // In one end, out the other. for (int i = 0; i < 200000000; i++) { // fprintf(stderr, "iter: %d\n", i); deq.push_back(&deq, i); deq.pop_front(&deq); } for (int i = 0; i < 200000000; i++) { deq.push_front(&deq, i); deq.pop_back(&deq); } // Random. int pf = 0, pb = 0, pof = 0, pob = 0; for (int i = 0; i < 10000000; i++) { if (action(e) > .51) { if (rand(0, 1)(e) == 0) { deq.push_back(&deq, i); pf++; } else { deq.push_front(&deq, i); pb++; } } else { if (deq.size(&deq) > 0) { if (rand(0, 1)(e) == 0) { deq.pop_back(&deq); pob++; } else { deq.pop_front(&deq); pof++; } } } } printf("%d push_backs, %d push_fronts, %d pop_backs, %d pop_fronts, %d size\n", pb, pf, pob, pof, (int) deq.size(&deq)); deq.dtor(&deq); } // Test random access performance { size_t sum = 0; int lo = 0, hi = 100000000; Deque_int deq; Deque_int_ctor(&deq, int_less); for(int i = lo; i < hi; i++) { deq.push_back(&deq, i); } for(int i = lo; i < hi; i++) { sum += deq.at(&deq, i); } if(sum > 0) printf("sum of all integers between %d and %d calculated using a deque is %zu\n", lo, hi, sum); deq.dtor(&deq); } // Print allocation info printf("%zd allocations totalling %zd bytes\n", alloc_call_count, total_bytes_allocated); }
int main(void) { srand(time(NULL)); Deque_int d; for (size_t i = 0; i < NCYCLES; ++i) { std::deque<int> s; Deque_int_ctor(&d, int_less); Deque_int d2; for (size_t i = 0; i < NITERATIONS; ++i) { for (size_t i = 0; i < NOPERATIONS; ++i) { int val; switch(rand() % 100) { case 0: d.clear(&d); s.clear(); break; default: switch(rand() % 3) { case 0: switch(rand() % 2) { case 0: if (s.empty()) continue; d.pop_front(&d); s.pop_front(); break; case 1: if (s.empty()) continue; d.pop_back(&d); s.pop_back(); } default: switch(rand() % 2) { case 0: val = int_ctor(); d.push_front(&d, val); s.push_front(val); break; case 1: val = int_ctor(); d.push_back(&d, val); s.push_back(val); } } } } assert(d.size(&d) == s.size()); assert(d.empty(&d) == s.empty()); for (size_t i = 0; i < s.size(); ++i) { //cout<< d.at(&d, i) << " " << s.at(i) <<endl; assert(d.at(&d, i) == s.at(i)); } Deque_int_ctor(&d2, int_less); for (size_t i = 0; i < s.size(); ++i) d2.push_back(&d2, s.at(i)); assert(Deque_int_equal(d, d2)); assert(Deque_int_equal(d2, d)); d2.dtor(&d2); Deque_int_Iterator dit = d.begin(&d); std::deque<int>::iterator sit = s.begin(); for (size_t i = 0; i < NITERATOR; ++i) { switch(rand() % 2) { case 0: if (sit == s.end()) continue; ++sit; dit.inc(&dit); break; case 1: if (sit == s.begin()) continue; --sit; dit.dec(&dit); break; } assert((sit == s.begin()) == Deque_int_Iterator_equal(dit, d.begin(&d))); assert((sit == s.end()) == Deque_int_Iterator_equal(dit, d.end(&d))); if (sit == s.end()) continue; assert(*sit == dit.deref(&dit)); } Deque_int_Iterator dit2 = dit = d.begin(&d); int itval = 0, itval2 = 0; for (size_t i = 0; i < NITERATOR; ++i) { switch(rand() % 4) { case 0: if (Deque_int_Iterator_equal(dit, d.end(&d))) continue; dit.inc(&dit); ++itval; break; case 1: if (Deque_int_Iterator_equal(dit, d.begin(&d))) continue; dit.dec(&dit); --itval; break; case 2: if (Deque_int_Iterator_equal(dit2, d.end(&d))) continue; dit2.inc(&dit2); ++itval2; break; case 3: if (Deque_int_Iterator_equal(dit2, d.begin(&d))) continue; dit2.dec(&dit2); --itval2; break; } assert((itval == itval2) == Deque_int_Iterator_equal(dit, dit2)); assert((itval == itval2) == Deque_int_Iterator_equal(dit2, dit)); } if (s.empty()) continue; assert(d.front(&d) == s.front()); assert(d.back(&d) == s.back()); } d.dtor(&d); } printf("OK\n"); return 0; }