lean2/src/tests/util/pdeque.cpp

231 lines
6.1 KiB
C++
Raw Normal View History

/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <iostream>
#include <cstdlib>
#include <deque>
#include <vector>
#include "test.h"
#include "pdeque.h"
using namespace lean;
// #define PDEQUE_PERF_TEST
/**
\brief Naive equality test for debugging
*/
template<typename T>
bool operator==(pdeque<T> const & q1, pdeque<T> const & q2) {
if (q1.size() != q2.size())
return false;
for (unsigned i = 0; i < q1.size(); i++) {
if (q1[i] != q2[i])
return false;
}
return true;
}
template<typename T>
bool operator==(pdeque<T> const & q1, std::deque<T> const & q2) {
if (q1.size() != q2.size())
return false;
for (unsigned i = 0; i < q1.size(); i++) {
if (q1[i] != q2[i])
return false;
}
return true;
}
static void tst1() {
pdeque<int> q;
lean_assert(empty(q));
lean_assert(size(q) == 0);
q = push_back(q, 1);
lean_assert(size(q) == 1);
std::cout << "q: " << q << "\n";
lean_assert(front(q) == 1);
lean_assert(back(q) == 1);
lean_assert(!empty(q));
q = push_back(q, 2);
lean_assert(front(q) == 1);
lean_assert(back(q) == 2);
std::cout << "q: " << q << "\n";
q = push_front(q, 3);
std::cout << "q: " << q << "\n";
lean_assert(size(q) == 3);
lean_assert(front(q) == 3);
lean_assert(back(q) == 2);
lean_assert(size(pop_front(q)) == 2);
lean_assert(front(pop_front(q)) == 1);
lean_assert(front(pop_front(pop_front(q))) == 2);
lean_assert(empty(pop_front(pop_front(pop_front(q)))));
lean_assert(pop_front(push_front(q, 3)) == q);
lean_assert(pop_back(push_back(q, 3)) == q);
}
static void driver(unsigned max_sz, unsigned max_val, unsigned num_ops, double push_freq, double copy_freq) {
std::deque<int> q1;
pdeque<int> q2;
pdeque<int> q3;
std::vector<pdeque<int>> copies;
for (unsigned i = 0; i < num_ops; i++) {
double f = static_cast<double>(std::rand() % 10000) / 10000.0;
if (f < copy_freq)
copies.push_back(q3);
// read random positions of q3
if (!empty(q3)) {
for (unsigned j = 0; j < rand() % 5; j++) {
unsigned idx = rand() % size(q3);
lean_assert(q3[idx] == q1[idx]);
}
}
f = static_cast<double>(std::rand() % 10000) / 10000.0;
if (f < push_freq) {
if (q1.size() >= max_sz)
continue;
int v = std::rand() % max_val;
if (std::rand() % 2 == 0) {
q1.push_front(v);
q2 = push_front(q2, v);
q3.push_front(v);
} else {
q1.push_back(v);
q2 = push_back(q2, v);
q3.push_back(v);
}
} else {
if (q1.size() == 0)
continue;
if (std::rand() % 2 == 0) {
lean_assert(front(q2) == q1.front());
lean_assert(front(q3) == q1.front());
q1.pop_front();
q2 = pop_front(q2);
q3.pop_front();
} else {
lean_assert(back(q2) == q1.back());
lean_assert(back(q3) == q1.back());
q1.pop_back();
q2 = pop_back(q2);
q3.pop_back();
}
}
lean_assert(q2 == q1);
lean_assert(q3 == q1);
}
std::cout << "Copies created: " << copies.size() << "\n";
}
static void tst2() {
driver(4, 32, 10000, 0.5, 0.01);
driver(4, 32, 10000, 0.5, 0.3);
driver(2, 32, 10000, 0.8, 0.5);
driver(2, 32, 10000, 0.3, 0.01);
driver(4, 32, 10000, 0.3, 0.5);
driver(16, 32, 10000, 0.5, 0.1);
driver(16, 32, 10000, 0.5, 0.01);
driver(16, 32, 10000, 0.5, 0.5);
driver(16, 32, 10000, 0.7, 0.1);
driver(16, 32, 10000, 0.7, 0.5);
driver(16, 32, 10000, 0.7, 0.01);
driver(16, 32, 10000, 0.1, 0.1);
driver(16, 32, 10000, 0.8, 0.1);
driver(16, 32, 10000, 0.8, 0.3);
driver(16, 1000, 10000, 0.8, 0.01);
driver(16, 1000, 10000, 0.8, 0.0);
driver(16, 1000, 10000, 0.8, 0.5);
driver(16, 1000, 10000, 0.8, 0.1);
driver(128, 1000, 10000, 0.5, 0.01);
driver(128, 1000, 10000, 0.5, 0.1);
driver(128, 1000, 10000, 0.5, 0.5);
driver(128, 1000, 10000, 0.2, 0.1);
}
#ifdef PDEQUE_PERF_TEST
#include "timeit.h"
static void perf_deque(unsigned n) {
std::deque<int> q;
for (unsigned i = 0; i < n; i++) {
q.push_back(i);
}
for (unsigned i = 0; i < n; i++) {
q.pop_front();
}
}
static void perf_pdeque(unsigned n) {
pdeque<int> q;
for (unsigned i = 0; i < n; i++) {
q.push_back(i);
}
for (unsigned i = 0; i < n; i++) {
q.pop_front();
}
}
static void tst4() {
unsigned N = 100000;
unsigned M = 100;
{
timeit t(std::cout, "deque time");
for (unsigned i = 0; i < N; i++) perf_deque(M);
}
{
timeit t(std::cout, "pdeque time");
for (unsigned i = 0; i < N; i++) perf_pdeque(M);
}
}
static void perf_deque2(std::deque<int> q, unsigned n) {
for (unsigned i = 0; i < n; i++) {
q.push_back(i);
}
for (unsigned i = 0; i < n; i++) {
q.pop_front();
}
}
static void perf_pdeque2(pdeque<int> q, unsigned n) {
for (unsigned i = 0; i < n; i++) {
q.push_back(i);
}
for (unsigned i = 0; i < n; i++) {
q.pop_front();
}
}
static void tst5() {
unsigned N = 100000;
unsigned SZ1 = 10000;
unsigned M = 5;
{
timeit t(std::cout, "deque time");
std::deque<int> q;
for (unsigned i = 0; i < SZ1; i++) { q.push_back(i); }
for (unsigned i = 0; i < N; i++) perf_deque2(q, M);
}
{
timeit t(std::cout, "pdeque time");
pdeque<int> q;
for (unsigned i = 0; i < SZ1 + 1; i++) { q.push_back(i); }
for (unsigned i = 0; i < N; i++) perf_pdeque2(q, M);
}
}
#endif
int main() {
tst1();
tst2();
#ifdef PDEQUE_PERF_TEST
tst4();
tst5();
#endif
return has_violations() ? 1 : 0;
}