klayout/src/db/unit_tests/dbBoxTreeTests.cc

1123 lines
26 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2024 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dbBoxTree.h"
#include "dbBoxConvert.h"
#include "tlUnitTest.h"
#include "tlTimer.h"
#include "tlLog.h"
#include <iostream>
#include <set>
#include <stdlib.h>
template <class Box>
Box qbox (int q, const Box &bbox)
{
typedef typename Box::coord_type coord_type;
typedef db::point<coord_type> point_type;
coord_type dx = bbox.width () / 2;
coord_type dy = bbox.height () / 2;
point_type o ((((q + 3) & 2) >> 1) * dx, (((q + 2) & 2) >> 1) * dy);
o += bbox.p1 ();
return Box (o, o + point_type (dx, dy));
}
template <class Box, class Tree>
void print_tree_node (const Tree *tree, const Box &bbox, size_t pos, db::box_tree_node<Tree> *node, const std::string &in)
{
std::cout << in << "x [\n";
if (! node) {
for (size_t i = pos; i < pos + tree->size (); ++i) {
std::cout << in << " " << tree->elements ()[i]->to_string () << "\n";
}
} else {
for (size_t i = pos; i < pos + node->lenq (-1); ++i) {
std::cout << in << " " << tree->elements ()[i]->to_string () << "\n";
}
}
std::cout << in << "]\n";
if (node) {
pos += node->lenq (-1);
for (int q = 0; q < 4; ++q) {
Box qb (qbox (q, bbox));
if (node->child (q)) {
std::cout << in << q << " (" << qb.to_string () << ") [\n";
print_tree_node (tree, qb, pos, node->child (q), in + " ");
std::cout << in << "]\n";
} else {
std::cout << in << q << " (" << qb.to_string () << ") [\n";
for (size_t i = pos; i < pos + node->lenq (q); ++i) {
std::cout << in << " " << tree->elements ()[i]->to_string () << " #" << i << "\n";
}
std::cout << in << "]\n";
}
pos += node->lenq (q);
}
}
}
template <class Tree>
void print_tree (const Tree &t, db::Box bbox)
{
std::cout << "size = " << t.size () << "\n";
print_tree_node (&t, bbox, 0, t.root (), "> ");
}
template <class Box, class Tree>
void print_unstable_tree_node (const Tree *tree, const Box &bbox, size_t pos, db::box_tree_node<Tree> *node, const std::string &in)
{
std::cout << in << "x [\n";
if (! node) {
for (size_t i = pos; i < pos + tree->size (); ++i) {
std::cout << in << " " << tree->objects ()[i].to_string () << "\n";
}
} else {
for (size_t i = pos; i < pos + node->lenq (-1); ++i) {
std::cout << in << " " << tree->objects ()[i].to_string () << "\n";
}
}
std::cout << in << "]\n";
if (node) {
pos += node->lenq (-1);
for (int q = 0; q < 4; ++q) {
Box qb (qbox (q, bbox));
if (node->child (q)) {
std::cout << in << q << " (" << qb.to_string () << ") [\n";
print_unstable_tree_node (tree, qb, pos, node->child (q), in + " ");
std::cout << in << "]\n";
} else {
std::cout << in << q << " (" << qb.to_string () << ") [\n";
for (size_t i = pos; i < pos + node->lenq (q); ++i) {
std::cout << in << " " << tree->objects ()[i].to_string () << " #" << i << "\n";
}
std::cout << in << "]\n";
}
pos += node->lenq (q);
}
}
}
template <class Tree>
void print_unstable_tree (const Tree &t, db::Box bbox)
{
std::cout << "size = " << t.size () << "\n";
print_unstable_tree_node (&t, bbox, 0, t.root (), "> ");
}
struct Box2Box {
typedef db::simple_bbox_tag complexity;
const db::Box &operator() (const db::Box &b) const { return b; }
};
struct Box2BoxCmplx {
typedef db::complex_bbox_tag complexity;
const db::Box &operator() (const db::Box &b) const { return b; }
};
typedef db::box_tree<db::Box, db::Box, Box2Box, 4, 0> TestTree;
typedef db::box_tree<db::Box, db::Box, Box2BoxCmplx, 4, 0> TestTreeCmplx;
typedef db::box_tree<db::Box, db::Box, Box2Box> TestTreeL;
typedef db::box_tree<db::Box, db::Box, Box2BoxCmplx> TestTreeCmplxL;
typedef db::unstable_box_tree<db::Box, db::Box, Box2Box, 4, 0> UnstableTestTree;
typedef db::unstable_box_tree<db::Box, db::Box, Box2BoxCmplx, 4, 0> UnstableTestTreeCmplx;
typedef db::unstable_box_tree<db::Box, db::Box, Box2Box> UnstableTestTreeL;
typedef db::unstable_box_tree<db::Box, db::Box, Box2BoxCmplx> UnstableTestTreeCmplxL;
template <class Tree, class Box, class BoxConv>
static void test_tree_overlap (tl::TestBase *_this, const Tree &t, const Box &b, BoxConv conv)
{
typedef typename Tree::object_type value_type;
if (tl::verbose ()) {
std::cout << "Testing vs. " << b << " overlapping" << std::endl;
}
std::set <const value_type *> good_idx;
for (typename Tree::const_iterator e = t.begin (); e != t.end (); ++e) {
if (b.overlaps (*e)) {
good_idx.insert (&*e);
}
}
if (tl::verbose ()) {
for (typename Tree::const_iterator e = t.begin (); e != t.end (); ++e) {
std::cout << " v=" << *e << std::endl;
}
}
typename Tree::overlapping_iterator i = t.begin_overlapping (b, conv);
while (! i.at_end ()) {
if (good_idx.find (&*i) == good_idx.end ()) {
FAIL_ARG ("not found in good indices list", *i);
} else {
good_idx.erase (&*i);
}
if (tl::verbose ()) {
std::cout << *i << std::endl;
}
++i;
}
EXPECT_EQ (good_idx.size (), size_t (0));
}
template <class Tree, class Box, class BoxConv>
static void test_tree_touching (tl::TestBase *_this, const Tree &t, const Box &b, BoxConv conv)
{
typedef typename Tree::object_type value_type;
if (tl::verbose ()) {
std::cout << "Testing vs. " << b << " touching" << std::endl;
}
std::set <const value_type *> good_idx;
for (typename Tree::const_iterator e = t.begin (); e != t.end (); ++e) {
if (b.touches (*e)) {
good_idx.insert (&*e);
}
}
if (tl::verbose ()) {
for (typename Tree::const_iterator e = t.begin (); e != t.end (); ++e) {
std::cout << " v=" << *e << std::endl;
}
}
typename Tree::touching_iterator i = t.begin_touching (b, conv);
while (! i.at_end ()) {
if (good_idx.find (&*i) == good_idx.end ()) {
FAIL_ARG ("not found in good indices list", *i);
} else {
good_idx.erase (&*i);
}
if (tl::verbose ()) {
std::cout << *i << std::endl;
}
++i;
}
EXPECT_EQ (good_idx.size (), size_t (0));
}
inline int rvalue ()
{
return (rand () % 10000) - 5000;
}
inline db::Box rboxx ()
{
int x = rvalue ();
int y = 100;
return db::Box (x, y, x + rvalue () % 20, y + 200);
}
inline db::Box rboxy ()
{
int x = -100;
int y = rvalue ();
return db::Box (x, y, x + 200, y + rvalue () % 20);
}
inline db::Box rbox ()
{
int x = rvalue ();
int y = rvalue ();
return db::Box (x, y, x + rvalue () % 200, y + rvalue () % 200);
}
namespace
{
class TestMemStatistics
: public db::MemStatistics
{
public:
TestMemStatistics ()
: used (0), reqd (0)
{ }
virtual void add (const std::type_info & /*ti*/, void * /*ptr*/, size_t r, size_t u, void * /*parent*/, purpose_t /*purpose*/ = None, int /*cat*/ = 0)
{
used += u;
reqd += r;
}
void clear ()
{
used = reqd = 0;
}
public:
size_t used, reqd;
};
}
TEST(0)
{
Box2Box conv;
db::Coord m = std::numeric_limits<db::Coord>::max ();
db::Box b(-m, -m, m, m);
TestTree t;
unsigned int bitset;
TestTree::touching_iterator it;
t.insert (db::Box (10, 20, 20, 25));
t.sort (conv);
EXPECT_EQ (t.size (), size_t (1));
it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
bitset = 0;
while (! it.at_end ()) {
unsigned int b = 0;
for (TestTree::const_iterator e = t.begin (); e != t.end (); ++e, ++b) {
if (&*e == &*it) {
bitset |= (1 << b);
}
}
++it;
}
EXPECT_EQ (bitset, (unsigned int) 0x1);
t.insert (db::Box (-10, 20, 0, 100));
t.insert (db::Box (-10, -20, 20, -15));
t.insert (db::Box (-10, -20, 20, -10));
t.insert (db::Box (-10, -20, 0, -9));
t.insert (db::Box (10, 20, 20, 50));
t.insert (db::Box (-10, 20, -5, 100));
t.insert (db::Box (-10, -20, 20, 22));
t.insert (db::Box (-10, -20, 5, -10));
t.sort (conv);
EXPECT_EQ (t.size (), size_t (9));
it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
bitset = 0;
while (! it.at_end ()) {
unsigned int b = 0;
for (TestTree::const_iterator e = t.begin (); e != t.end (); ++e, ++b) {
if (&*e == &*it) {
bitset |= (1 << b);
}
}
++it;
}
EXPECT_EQ (bitset, (unsigned int) 0x1ff);
it = t.begin_touching (db::Box (-10, 20, -9, 21), conv);
bitset = 0;
while (! it.at_end ()) {
unsigned int b = 0;
for (TestTree::const_iterator e = t.begin (); e != t.end (); ++e, ++b) {
if (&*e == &*it) {
bitset |= (1 << b);
}
}
++it;
}
EXPECT_EQ (bitset, (unsigned int) 0xc2);
it = t.begin_touching (db::Box (-20, 20, -19, 21), conv);
bitset = 0;
while (! it.at_end ()) {
unsigned int b = 0;
for (TestTree::const_iterator e = t.begin (); e != t.end (); ++e, ++b) {
if (&*e == &*it) {
bitset |= (1 << b);
}
}
++it;
}
EXPECT_EQ (bitset, (unsigned int) 0);
}
TEST(1)
{
Box2Box conv;
db::Box b(-10, -10, 10, 10);
TestTree t;
t.sort (conv);
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
t.insert (db::Box (10, 20, 20, 100));
t.insert (db::Box (-10, 20, 20, 100));
t.insert (db::Box (-10, -20, 20, 100));
t.insert (db::Box (-10, -20, 20, -10));
t.insert (db::Box (-10, -20, 20, -9));
t.sort (conv);
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
TEST(2)
{
Box2Box conv;
TestTree t;
int n = 231;
for (int i = 0; i < n; ++i) {
t.insert (rbox ());
}
t.sort (conv);
for (int i = 0; i < n; ++i) {
db::Box b (rbox ());
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
}
TEST(3)
{
Box2Box conv;
TestTree t;
int n = 215;
for (int i = 0; i < n; ++i) {
// insert some empty boxes ..
if (rvalue () % 3 == 0) {
t.insert (db::Box ());
} else {
t.insert (rbox ());
}
}
t.sort (conv);
for (int i = 0; i < n; ++i) {
db::Box b (rbox ());
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
}
TEST(1C)
{
Box2BoxCmplx conv;
db::Box b(-10, -10, 10, 10);
TestTreeCmplx t;
t.sort (conv);
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
t.insert (db::Box (10, 20, 20, 100));
t.insert (db::Box (-10, 20, 20, 100));
t.insert (db::Box (-10, -20, 20, 100));
t.insert (db::Box (-10, -20, 20, -10));
t.insert (db::Box (-10, -20, 20, -9));
t.sort (conv);
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
TEST(2C)
{
Box2BoxCmplx conv;
TestTreeCmplx t;
int n = 231;
for (int i = 0; i < n; ++i) {
t.insert (rbox ());
}
t.sort (conv);
for (int i = 0; i < n; ++i) {
db::Box b (rbox ());
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
}
TEST(3C)
{
Box2BoxCmplx conv;
TestTreeCmplx t;
int n = 215;
for (int i = 0; i < n; ++i) {
// insert some empty boxes ..
if (rvalue () % 3 == 0) {
t.insert (db::Box ());
} else {
t.insert (rbox ());
}
}
t.sort (conv);
for (int i = 0; i < n; ++i) {
db::Box b (rbox ());
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
}
TEST(4)
{
Box2BoxCmplx conv;
TestTreeCmplxL t;
int n = 2000000;
int nempty = 0;
db::Box bbox;
for (int i = 0; i < n; ++i) {
// insert some empty boxes ..
db::Box bx;
if (rvalue () % 3000 == 0) {
++nempty;
} else {
bx = rbox ();
}
t.insert (bx);
bbox += bx;
}
{
tl::SelfTimer timer ("test 4 sort");
t.sort (conv);
}
{
tl::SelfTimer timer ("test 4 traverse");
db::Coord m = std::numeric_limits<db::Coord>::max ();
size_t n = 0;
for (unsigned int i = 0; i < 10; ++i) {
TestTreeCmplxL::touching_iterator it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
while (!it.at_end ()) {
++it;
++n;
}
}
EXPECT_EQ (n, (t.size () - nempty) * 10);
}
{
tl::SelfTimer timer ("test 4 lookup");
for (unsigned int i = 0; i < 10; ++i) {
for (unsigned int j = 0; j < 10; ++j) {
db::Box sbox (bbox.left () + (bbox.width () * i) / 10,
bbox.bottom () + (bbox.height () * j) / 10,
bbox.left () + (bbox.width () * (i + 1)) / 10,
bbox.bottom () + (bbox.height () * (j + 1)) / 10);
TestTreeCmplxL::touching_iterator it = t.begin_touching (sbox, conv);
while (!it.at_end ()) {
++it;
}
}
}
}
TestMemStatistics ms;
t.mem_stat (&ms, db::MemStatistics::None, 0);
tl::info << "Memory: " << ms.used;
}
TEST(4A)
{
Box2BoxCmplx conv;
TestTreeCmplxL t;
int n = 2000000;
int nempty = 0;
db::Box bbox;
for (int i = 0; i < n; ++i) {
// insert some empty boxes ..
db::Box bx;
if (rvalue () % 3000 == 0) {
++nempty;
} else {
bx = rboxx ();
}
t.insert (bx);
bbox += bx;
}
{
tl::SelfTimer timer ("test 4a sort");
t.sort (conv);
}
{
tl::SelfTimer timer ("test 4a traverse");
db::Coord m = std::numeric_limits<db::Coord>::max ();
size_t n = 0;
for (unsigned int i = 0; i < 10; ++i) {
TestTreeCmplxL::touching_iterator it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
while (!it.at_end ()) {
++it;
++n;
}
}
EXPECT_EQ (n, (t.size () - nempty) * 10);
}
{
tl::SelfTimer timer ("test 4a lookup");
for (unsigned int i = 0; i < 10; ++i) {
for (unsigned int j = 0; j < 10; ++j) {
db::Box sbox (bbox.left () + (bbox.width () * i) / 10,
bbox.bottom () + (bbox.height () * j) / 10,
bbox.left () + (bbox.width () * (i + 1)) / 10,
bbox.bottom () + (bbox.height () * (j + 1)) / 10);
TestTreeCmplxL::touching_iterator it = t.begin_touching (sbox, conv);
while (!it.at_end ()) {
++it;
}
}
}
}
TestMemStatistics ms;
t.mem_stat (&ms, db::MemStatistics::None, 0);
tl::info << "Memory: " << ms.used;
}
TEST(4B)
{
Box2BoxCmplx conv;
TestTreeCmplxL t;
int n = 2000000;
int nempty = 0;
db::Box bbox;
for (int i = 0; i < n; ++i) {
// insert some empty boxes ..
db::Box bx;
if (rvalue () % 3000 == 0) {
++nempty;
} else {
bx = rboxy ();
}
t.insert (bx);
bbox += bx;
}
{
tl::SelfTimer timer ("test 4b sort");
t.sort (conv);
}
{
tl::SelfTimer timer ("test 4b traverse");
db::Coord m = std::numeric_limits<db::Coord>::max ();
size_t n = 0;
for (unsigned int i = 0; i < 10; ++i) {
TestTreeCmplxL::touching_iterator it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
while (!it.at_end ()) {
++it;
++n;
}
}
EXPECT_EQ (n, (t.size () - nempty) * 10);
}
{
tl::SelfTimer timer ("test 4b lookup");
for (unsigned int i = 0; i < 10; ++i) {
for (unsigned int j = 0; j < 10; ++j) {
db::Box sbox (bbox.left () + (bbox.width () * i) / 10,
bbox.bottom () + (bbox.height () * j) / 10,
bbox.left () + (bbox.width () * (i + 1)) / 10,
bbox.bottom () + (bbox.height () * (j + 1)) / 10);
TestTreeCmplxL::touching_iterator it = t.begin_touching (sbox, conv);
while (!it.at_end ()) {
++it;
}
}
}
}
TestMemStatistics ms;
t.mem_stat (&ms, db::MemStatistics::None, 0);
tl::info << "Memory: " << ms.used;
}
TEST(5)
{
Box2BoxCmplx conv;
TestTreeCmplxL t;
int n = 2000000;
for (int i = n - 1; i >= 0; --i) {
t.insert (db::Box (i, n - i - 1, i + 1000, n - i - 1 + 1000));
}
{
tl::SelfTimer timer ("test 5 sort");
t.sort (conv);
}
{
tl::SelfTimer timer ("test 5 traverse");
db::Coord m = std::numeric_limits<db::Coord>::max ();
size_t n = 0;
for (unsigned int i = 0; i < 10; ++i) {
TestTreeCmplxL::touching_iterator it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
while (!it.at_end ()) {
++it;
++n;
}
}
EXPECT_EQ (n, t.size () * 10);
}
TestMemStatistics ms;
t.mem_stat (&ms, db::MemStatistics::None, 0);
tl::info << "Memory: " << ms.used;
}
TEST(0U)
{
Box2Box conv;
db::Coord m = std::numeric_limits<db::Coord>::max ();
db::Box b(-m, -m, m, m);
UnstableTestTree t;
unsigned int bitset;
UnstableTestTree::touching_iterator it;
t.insert (db::Box (10, 20, 20, 25));
t.sort (conv);
EXPECT_EQ (t.size (), size_t (1));
it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
bitset = 0;
while (! it.at_end ()) {
bitset |= (1 << (it.index ()));
++it;
}
EXPECT_EQ (bitset, (unsigned int) 0x1);
t.insert (db::Box (-10, 20, 0, 100));
t.insert (db::Box (-10, -20, 20, -15));
t.insert (db::Box (-10, -20, 20, -10));
t.insert (db::Box (-10, -20, 0, -9));
t.insert (db::Box (10, 20, 20, 50));
t.insert (db::Box (-10, 20, -5, 100));
t.insert (db::Box (-10, -20, 20, 22));
t.insert (db::Box (-10, -20, 5, -10));
t.sort (conv);
EXPECT_EQ (t.size (), size_t (9));
it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
bitset = 0;
while (! it.at_end ()) {
bitset |= (1 << (it.index ()));
++it;
}
EXPECT_EQ (bitset, (unsigned int) 0x1ff);
it = t.begin_touching (db::Box (-10, 20, -9, 21), conv);
bitset = 0;
while (! it.at_end ()) {
bitset |= (1 << (it.index ()));
++it;
}
EXPECT_EQ (bitset, (unsigned int) 0x31);
it = t.begin_touching (db::Box (-20, 20, -19, 21), conv);
bitset = 0;
while (! it.at_end ()) {
bitset |= (1 << (it.index ()));
++it;
}
EXPECT_EQ (bitset, (unsigned int) 0);
}
TEST(1U)
{
Box2Box conv;
db::Box b(-10, -10, 10, 10);
UnstableTestTree t;
t.sort (conv);
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
t.insert (db::Box (10, 20, 20, 100));
t.insert (db::Box (-10, 20, 20, 100));
t.insert (db::Box (-10, -20, 20, 100));
t.insert (db::Box (-10, -20, 20, -10));
t.insert (db::Box (-10, -20, 20, -9));
t.sort (conv);
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
TEST(2U)
{
Box2Box conv;
UnstableTestTree t;
int n = 231;
for (int i = 0; i < n; ++i) {
t.insert (rbox ());
}
t.sort (conv);
for (int i = 0; i < n; ++i) {
db::Box b (rbox ());
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
}
TEST(3U)
{
Box2Box conv;
UnstableTestTree t;
int n = 215;
for (int i = 0; i < n; ++i) {
// insert some empty boxes ..
if (rvalue () % 3 == 0) {
t.insert (db::Box ());
} else {
t.insert (rbox ());
}
}
t.sort (conv);
for (int i = 0; i < n; ++i) {
db::Box b (rbox ());
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
}
TEST(1CU)
{
Box2BoxCmplx conv;
db::Box b(-10, -10, 10, 10);
UnstableTestTreeCmplx t;
t.sort (conv);
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
t.insert (db::Box (10, 20, 20, 100));
t.insert (db::Box (-10, 20, 20, 100));
t.insert (db::Box (-10, -20, 20, 100));
t.insert (db::Box (-10, -20, 20, -10));
t.insert (db::Box (-10, -20, 20, -9));
t.sort (conv);
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
TEST(2CU)
{
Box2BoxCmplx conv;
UnstableTestTreeCmplx t;
int n = 231;
db::Box bbox;
for (int i = 0; i < n; ++i) {
db::Box b (rbox ());
bbox += b;
t.insert (b);
}
t.sort (conv);
for (int i = 0; i < n; ++i) {
db::Box b (rbox ());
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
}
TEST(3CU)
{
Box2BoxCmplx conv;
UnstableTestTreeCmplx t;
int n = 215;
for (int i = 0; i < n; ++i) {
// insert some empty boxes ..
if (rvalue () % 3 == 0) {
t.insert (db::Box ());
} else {
t.insert (rbox ());
}
}
t.sort (conv);
for (int i = 0; i < n; ++i) {
db::Box b (rbox ());
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
}
TEST(4U)
{
Box2BoxCmplx conv;
UnstableTestTreeCmplxL t;
int n = 2000000;
int nempty = 0;
db::Box bbox;
for (int i = 0; i < n; ++i) {
// insert some empty boxes ..
db::Box bx;
if (rvalue () % 3000 == 0) {
++nempty;
} else {
bx = rbox ();
}
t.insert (bx);
bbox += bx;
}
{
tl::SelfTimer timer ("test 4 sort");
t.sort (conv);
}
{
tl::SelfTimer timer ("test 4 traverse");
db::Coord m = std::numeric_limits<db::Coord>::max ();
size_t n = 0;
for (unsigned int i = 0; i < 10; ++i) {
UnstableTestTreeCmplxL::touching_iterator it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
while (!it.at_end ()) {
++it;
++n;
}
}
EXPECT_EQ (n, (t.size () - nempty) * 10);
}
{
tl::SelfTimer timer ("test 4 lookup");
for (unsigned int i = 0; i < 10; ++i) {
for (unsigned int j = 0; j < 10; ++j) {
db::Box sbox (bbox.left () + (bbox.width () * i) / 10,
bbox.bottom () + (bbox.height () * j) / 10,
bbox.left () + (bbox.width () * (i + 1)) / 10,
bbox.bottom () + (bbox.height () * (j + 1)) / 10);
UnstableTestTreeCmplxL::touching_iterator it = t.begin_touching (sbox, conv);
while (!it.at_end ()) {
++it;
}
}
}
}
TestMemStatistics ms;
t.mem_stat (&ms, db::MemStatistics::None, 0);
tl::info << "Memory: " << ms.used;
}
TEST(5U)
{
Box2BoxCmplx conv;
UnstableTestTreeCmplxL t;
int n = 2000000;
for (int i = n - 1; i >= 0; --i) {
t.insert (db::Box (i, n - i - 1, i + 1000, n - i - 1 + 1000));
}
{
tl::SelfTimer timer ("test 5 sort");
t.sort (conv);
}
{
tl::SelfTimer timer ("test 5 traverse");
db::Coord m = std::numeric_limits<db::Coord>::max ();
size_t n = 0;
for (unsigned int i = 0; i < 10; ++i) {
UnstableTestTreeCmplxL::touching_iterator it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
while (!it.at_end ()) {
++it;
++n;
}
}
EXPECT_EQ (n, t.size () * 10);
}
TestMemStatistics ms;
t.mem_stat (&ms, db::MemStatistics::None, 0);
tl::info << "Memory: " << ms.used;
}
TEST(6)
{
Box2Box conv;
TestTree t;
int n = 1000;
for (int i = 0; i < n; ++i) {
t.insert (db::Box (1, 1, 1, 1));
}
t.sort (conv);
for (int i = 0; i < n; ++i) {
db::Box b (0, 0, 10, 10);
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
}
TEST(6U)
{
Box2Box conv;
UnstableTestTree t;
int n = 1000;
for (int i = 0; i < n; ++i) {
t.insert (db::Box (1, 1, 1, 1));
}
t.sort (conv);
for (int i = 0; i < n; ++i) {
db::Box b (0, 0, 10, 10);
test_tree_overlap (_this, t, b, conv);
test_tree_touching (_this, t, b, conv);
}
}
TEST(7)
{
Box2Box conv;
TestTree t;
int n = 200000;
for (int i = n - 1; i >= 0; --i) {
t.insert (db::Box (i * 10, 0, i * 10 + 5, 5));
}
t.sort (conv);
{
tl::SelfTimer timer ("test 7 lookup");
size_t n = 0;
for (unsigned int i = 0; i < 2000; ++i) {
db::Coord sx = 0, sy = 0;
TestTree::touching_iterator it = t.begin_touching (db::Box (db::Point (2000, 0), db::Point (3000, 0)), conv);
while (!it.at_end ()) {
sx += abs (it->left ());
sy += abs (it->bottom ());
++it;
++n;
}
EXPECT_EQ (sx, 252500);
EXPECT_EQ (sy, 0);
}
EXPECT_EQ (n, size_t (101 * 2000));
}
{
tl::SelfTimer timer ("test 7 traverse");
db::Coord m = std::numeric_limits<db::Coord>::max ();
size_t n = 0;
for (unsigned int i = 0; i < 10; ++i) {
TestTree::touching_iterator it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
while (!it.at_end ()) {
++it;
++n;
}
}
EXPECT_EQ (n, t.size () * 10);
}
}
TEST(7U)
{
Box2Box conv;
UnstableTestTree t;
int n = 200000;
for (int i = n - 1; i >= 0; --i) {
t.insert (db::Box (i * 10, 0, i * 10 + 5, 5));
}
t.sort (conv);
{
tl::SelfTimer timer ("test 7U lookup");
size_t n = 0;
for (unsigned int i = 0; i < 2000; ++i) {
db::Coord sx = 0, sy = 0;
UnstableTestTree::touching_iterator it = t.begin_touching (db::Box (db::Point (2000, 0), db::Point (3000, 0)), conv);
while (!it.at_end ()) {
sx += abs (it->left ());
sy += abs (it->bottom ());
++it;
++n;
}
EXPECT_EQ (sx, 252500);
EXPECT_EQ (sy, 0);
}
EXPECT_EQ (n, size_t (101 * 2000));
}
{
tl::SelfTimer timer ("test 7U traverse");
db::Coord m = std::numeric_limits<db::Coord>::max ();
size_t n = 0;
for (unsigned int i = 0; i < 10; ++i) {
UnstableTestTree::touching_iterator it = t.begin_touching (db::Box (db::Point (-m,-m), db::Point (m, m)), conv);
while (!it.at_end ()) {
++it;
++n;
}
}
EXPECT_EQ (n, t.size () * 10);
}
}