lean4-htt/src/tests/library/parray.cpp

192 lines
5.5 KiB
C++

/*
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <utility>
#include <random>
#include <vector>
#include "util/test.h"
#include "util/init_module.h"
#include "util/sexpr/init_module.h"
#include "kernel/init_module.h"
#include "library/init_module.h"
#include "library/parray.h"
using namespace lean;
void tst1() {
parray<unsigned> a(10, 0);
lean_assert(a[0] == 0);
lean_assert(a.size() == 10);
parray<unsigned> b = a;
a.set(0, 1);
lean_assert(a[0] == 1);
lean_assert(a[1] == 0);
lean_assert(b[0] == 0);
lean_assert(a[0] == 1);
}
void driver(unsigned max_sz, unsigned max_val, unsigned num_it,
double push_back_freq,
double pop_back_freq,
double set_freq,
double copy_freq) {
parray<unsigned> v1;
std::vector<unsigned> v2;
std::mt19937 rng;
rng.seed(static_cast<unsigned int>(time(0)));
std::uniform_int_distribution<unsigned int> uint_dist;
std::vector<std::pair<parray<unsigned>, std::vector<unsigned>>> copies;
size_t acc_sz = 0;
for (unsigned i = 0; i < num_it; i++) {
acc_sz += v1.size();
double f = static_cast<double>(uint_dist(rng) % 10000) / 10000.0;
if (f < copy_freq) {
copies.emplace_back(v1, v2);
}
f = static_cast<double>(uint_dist(rng) % 10000) / 10000.0;
if (f < push_back_freq) {
if (v1.size() < max_sz) {
unsigned a = uint_dist(rng) % max_val;
v1.push_back(a);
v2.push_back(a);
}
}
if (v1.size() > 0) {
f = static_cast<double>(uint_dist(rng) % 10000) / 10000.0;
if (f < pop_back_freq) {
if (v1.size() >= max_sz)
continue;
v1.pop_back();
v2.pop_back();
}
}
if (v1.size() > 0) {
f = static_cast<double>(uint_dist(rng) % 10000) / 10000.0;
if (f < set_freq) {
unsigned idx = uint_dist(rng) % v1.size();
unsigned a = uint_dist(rng) % max_val;
v1.set(idx, a);
v2[idx] = a;
}
}
f = static_cast<double>(uint_dist(rng) % 10000) / 10000.0;
lean_assert(v1.size() == v2.size());
for (unsigned i = 0; i < v2.size(); i++) {
lean_assert(v1[i] == v2[i]);
}
}
for (std::pair<parray<unsigned>, std::vector<unsigned>> const & p : copies) {
lean_assert(p.first.size() == p.second.size());
for (unsigned i = 0; i < p.second.size(); i++) {
lean_assert(p.first[i] == p.second[i]);
}
}
std::cout << "\n";
std::cout << "Copies created: " << copies.size() << "\n";
std::cout << "Average size: " << static_cast<double>(acc_sz) / static_cast<double>(num_it) << "\n";
}
static void tst2() {
driver(4, 32, 10000, 0.5, 0.1, 0.5, 0.1);
driver(4, 32, 10000, 0.5, 0.1, 0.5, 0.1);
driver(4, 32, 10000, 0.5, 0.1, 0.5, 0.5);
driver(16, 16, 100000, 0.5, 0.5, 0.5, 0.01);
driver(16, 16, 100000, 0.5, 0.1, 0.5, 0.01);
driver(16, 16, 100000, 0.5, 0.6, 0.5, 0.01);
driver(16, 16, 10000, 0.5, 0.1, 0.5, 0.0);
}
static void tst3(unsigned n) {
parray<unsigned> v1;
v1.push_back(0);
parray<unsigned> v2 = v1;
for (unsigned i = 0; i < n; i++)
v1.push_back(i);
unsigned r = 0;
for (unsigned i = 0; i < n; i++)
r += v1[n - i - 1];
std::cout << ">> " << r << "\n";
}
static void tst_perf(unsigned sz, unsigned n) {
parray<unsigned> v1(sz, 0);
parray<unsigned> v2 = v1;
for (unsigned i = 0; i < sz; i++) {
v1.set(i, i);
}
/* The following loop is very expensive without ensure_unshared */
v1.ensure_unshared();
for (unsigned i = 0; i < n; i++) {
unsigned u1 = v1[i];
unsigned u2 = v2[i];
lean_assert(u1 == i);
lean_assert(u2 == 0);
}
}
class Foo {
unsigned * m_data;
public:
Foo():m_data(new unsigned(1)) {}
Foo(Foo const & src):m_data(new unsigned(*src.m_data)) {}
Foo(Foo && src):m_data(new unsigned(*src.m_data)) {}
Foo(unsigned n):m_data(new unsigned(n)) {}
~Foo() { delete m_data; }
Foo & operator=(Foo const & src) {
*m_data = *src.m_data;
return *this;
}
Foo & operator=(Foo const && src) {
*m_data = *src.m_data;
return *this;
}
unsigned get_val() const { return *m_data; }
};
static void tst4() {
parray<Foo> v1;
v1.push_back(Foo(2));
v1.push_back(Foo(3));
parray<Foo> v2 = v1;
for (unsigned i = 0; i < 10; i++)
v1.push_back(Foo(i));
v1.set(0, Foo(100));
v1.set(1, Foo(100));
lean_assert(v2.size() == 2);
lean_assert(v2[0].get_val() == 2);
lean_assert(v2[1].get_val() == 3);
parray<Foo> v3 = v1;
v1.pop_back();
v1.pop_back();
lean_assert(v1.size() == 10);
lean_assert(v3.size() == 12);
}
int main() {
save_stack_info();
initialize_util_module();
initialize_sexpr_module();
initialize_kernel_module();
initialize_library_core_module();
initialize_library_module();
std::cout << "sizeof(parray::cell) = " << parray<unsigned>::sizeof_cell() << "\n";
tst1();
tst2();
tst3(100000);
tst4();
tst_perf(100000, 10000);
finalize_library_module();
finalize_library_core_module();
finalize_kernel_module();
finalize_sexpr_module();
finalize_util_module();
return has_violations() ? 1 : 0;
}