mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
296 lines
6.7 KiB
C++
296 lines
6.7 KiB
C++
/* Fibonacci heap for GNU compiler.
|
|
Copyright (C) 2016-2024 Free Software Foundation, Inc.
|
|
Contributed by Martin Liska <mliska@suse.cz>
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC 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 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC 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 GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "alloc-pool.h"
|
|
#include "fibonacci_heap.h"
|
|
#include "selftest.h"
|
|
|
|
#if CHECKING_P
|
|
|
|
namespace selftest {
|
|
|
|
/* Selftests. */
|
|
|
|
/* Verify that operations with empty heap work. */
|
|
|
|
typedef fibonacci_node <int, int> int_heap_node_t;
|
|
typedef fibonacci_heap <int, int> int_heap_t;
|
|
|
|
static void
|
|
test_empty_heap ()
|
|
{
|
|
pool_allocator allocator ("fibheap test", sizeof (int_heap_node_t));
|
|
int_heap_t *h1 = new int_heap_t (INT_MIN, &allocator);
|
|
|
|
ASSERT_TRUE (h1->empty ());
|
|
ASSERT_EQ (0, h1->nodes ());
|
|
ASSERT_EQ (NULL, h1->min ());
|
|
|
|
int_heap_t *h2 = new int_heap_t (INT_MIN, &allocator);
|
|
|
|
int_heap_t *r = h1->union_with (h2);
|
|
ASSERT_TRUE (r->empty ());
|
|
ASSERT_EQ (0, r->nodes ());
|
|
ASSERT_EQ (NULL, r->min ());
|
|
|
|
delete r;
|
|
}
|
|
|
|
#define TEST_HEAP_N 100
|
|
#define TEST_CALCULATE_VALUE(i) ((3 * i) + 10000)
|
|
|
|
/* Verify heap basic operations. */
|
|
|
|
static void
|
|
test_basic_heap_operations ()
|
|
{
|
|
int values[TEST_HEAP_N];
|
|
int_heap_t *h1 = new int_heap_t (INT_MIN);
|
|
|
|
for (unsigned i = 0; i < TEST_HEAP_N; i++)
|
|
{
|
|
values[i] = TEST_CALCULATE_VALUE (i);
|
|
ASSERT_EQ (i, h1->nodes ());
|
|
h1->insert (i, &values[i]);
|
|
ASSERT_EQ (0, h1->min_key ());
|
|
ASSERT_EQ (values[0], *h1->min ());
|
|
}
|
|
|
|
for (unsigned i = 0; i < TEST_HEAP_N; i++)
|
|
{
|
|
ASSERT_EQ (TEST_HEAP_N - i, h1->nodes ());
|
|
ASSERT_EQ ((int)i, h1->min_key ());
|
|
ASSERT_EQ (values[i], *h1->min ());
|
|
|
|
h1->extract_min ();
|
|
}
|
|
|
|
ASSERT_TRUE (h1->empty ());
|
|
|
|
delete h1;
|
|
}
|
|
|
|
/* Builds a simple heap with values in interval 0..TEST_HEAP_N-1, where values
|
|
of each key is equal to 3 * key + 10000. BUFFER is used as a storage
|
|
of values and NODES points to inserted nodes. */
|
|
|
|
static int_heap_t *
|
|
build_simple_heap (int *buffer, int_heap_node_t **nodes)
|
|
{
|
|
int_heap_t *h = new int_heap_t (INT_MIN);
|
|
|
|
for (unsigned i = 0; i < TEST_HEAP_N; i++)
|
|
{
|
|
buffer[i] = TEST_CALCULATE_VALUE (i);
|
|
nodes[i] = h->insert (i, &buffer[i]);
|
|
}
|
|
|
|
return h;
|
|
}
|
|
|
|
/* Verify that fibonacci_heap::replace_key works. */
|
|
|
|
static void
|
|
test_replace_key ()
|
|
{
|
|
int values[TEST_HEAP_N];
|
|
int_heap_node_t *nodes[TEST_HEAP_N];
|
|
|
|
int_heap_t *heap = build_simple_heap (values, nodes);
|
|
|
|
int N = 10;
|
|
for (unsigned i = 0; i < (unsigned)N; i++)
|
|
heap->replace_key (nodes[i], 100 * 1000 + i);
|
|
|
|
ASSERT_EQ (TEST_HEAP_N, heap->nodes ());
|
|
ASSERT_EQ (N, heap->min_key ());
|
|
ASSERT_EQ (TEST_CALCULATE_VALUE (N), *heap->min ());
|
|
|
|
for (int i = 0; i < TEST_HEAP_N - 1; i++)
|
|
heap->extract_min ();
|
|
|
|
ASSERT_EQ (1, heap->nodes ());
|
|
ASSERT_EQ (100 * 1000 + N - 1, heap->min_key ());
|
|
|
|
delete heap;
|
|
}
|
|
|
|
/* Verify that heap can handle duplicate keys. */
|
|
|
|
static void
|
|
test_duplicate_keys ()
|
|
{
|
|
int values[3 * TEST_HEAP_N];
|
|
int_heap_t *heap = new int_heap_t (INT_MIN);
|
|
|
|
for (unsigned i = 0; i < 3 * TEST_HEAP_N; i++)
|
|
{
|
|
values[i] = TEST_CALCULATE_VALUE (i);
|
|
heap->insert (i / 3, &values[i]);
|
|
}
|
|
|
|
ASSERT_EQ (3 * TEST_HEAP_N, heap->nodes ());
|
|
ASSERT_EQ (0, heap->min_key ());
|
|
ASSERT_EQ (TEST_CALCULATE_VALUE (0), *heap->min ());
|
|
|
|
for (unsigned i = 0; i < 9; i++)
|
|
heap->extract_min ();
|
|
|
|
for (unsigned i = 0; i < 3; i++)
|
|
{
|
|
ASSERT_EQ (3, heap->min_key ());
|
|
heap->extract_min ();
|
|
}
|
|
|
|
delete heap;
|
|
}
|
|
|
|
/* Verify that heap can handle union. */
|
|
|
|
static void
|
|
test_union ()
|
|
{
|
|
int value = 777;
|
|
pool_allocator allocator ("fibheap test", sizeof (int_heap_node_t));
|
|
|
|
int_heap_t *heap1 = new int_heap_t (INT_MIN, &allocator);
|
|
for (unsigned i = 0; i < 2 * TEST_HEAP_N; i++)
|
|
heap1->insert (i, &value);
|
|
|
|
int_heap_t *heap2 = new int_heap_t (INT_MIN, &allocator);
|
|
for (unsigned i = 2 * TEST_HEAP_N; i < 3 * TEST_HEAP_N; i++)
|
|
heap2->insert (i, &value);
|
|
|
|
int_heap_t *union_heap = heap1->union_with (heap2);
|
|
|
|
for (int i = 0; i < 3 * TEST_HEAP_N; i++)
|
|
{
|
|
ASSERT_EQ (i, union_heap->min_key ());
|
|
union_heap->extract_min ();
|
|
}
|
|
|
|
delete union_heap;
|
|
}
|
|
|
|
/* Verify that heap can handle union with a heap having exactly the same
|
|
keys. */
|
|
|
|
static void
|
|
test_union_of_equal_heaps ()
|
|
{
|
|
int value = 777;
|
|
pool_allocator allocator ("fibheap test", sizeof (int_heap_node_t));
|
|
|
|
int_heap_t *heap1 = new int_heap_t (INT_MIN, &allocator);
|
|
for (unsigned i = 0; i < TEST_HEAP_N; i++)
|
|
heap1->insert (i, &value);
|
|
|
|
int_heap_t *heap2 = new int_heap_t (INT_MIN, &allocator);
|
|
for (unsigned i = 0; i < TEST_HEAP_N; i++)
|
|
heap2->insert (i, &value);
|
|
|
|
int_heap_t *union_heap = heap1->union_with (heap2);
|
|
|
|
for (int i = 0; i < TEST_HEAP_N; i++)
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
ASSERT_EQ (i, union_heap->min_key ());
|
|
union_heap->extract_min ();
|
|
}
|
|
|
|
delete union_heap;
|
|
}
|
|
|
|
/* Dummy struct for testing. */
|
|
|
|
class heap_key
|
|
{
|
|
public:
|
|
heap_key (int k): key (k)
|
|
{
|
|
}
|
|
|
|
int key;
|
|
|
|
bool operator< (const heap_key &other) const
|
|
{
|
|
return key > other.key;
|
|
}
|
|
|
|
bool operator== (const heap_key &other) const
|
|
{
|
|
return key == other.key;
|
|
}
|
|
|
|
bool operator> (const heap_key &other) const
|
|
{
|
|
return !(*this == other || *this < other);
|
|
}
|
|
};
|
|
|
|
typedef fibonacci_heap<heap_key, int> class_fibonacci_heap_t;
|
|
|
|
/* Verify that heap can handle a struct as key type. */
|
|
|
|
static void
|
|
test_struct_key ()
|
|
{
|
|
int value = 123456;
|
|
class_fibonacci_heap_t *heap = new class_fibonacci_heap_t (INT_MIN);
|
|
|
|
heap->insert (heap_key (1), &value);
|
|
heap->insert (heap_key (10), &value);
|
|
heap->insert (heap_key (100), &value);
|
|
heap->insert (heap_key (1000), &value);
|
|
|
|
ASSERT_EQ (1000, heap->min_key ().key);
|
|
ASSERT_EQ (4, heap->nodes ());
|
|
heap->extract_min ();
|
|
heap->extract_min ();
|
|
ASSERT_EQ (10, heap->min_key ().key);
|
|
heap->extract_min ();
|
|
ASSERT_EQ (&value, heap->min ());
|
|
heap->extract_min ();
|
|
ASSERT_TRUE (heap->empty ());
|
|
|
|
delete heap;
|
|
}
|
|
|
|
/* Run all of the selftests within this file. */
|
|
|
|
void
|
|
fibonacci_heap_cc_tests ()
|
|
{
|
|
test_empty_heap ();
|
|
test_basic_heap_operations ();
|
|
test_replace_key ();
|
|
test_duplicate_keys ();
|
|
test_union ();
|
|
test_union_of_equal_heaps ();
|
|
test_struct_key ();
|
|
}
|
|
|
|
} // namespace selftest
|
|
|
|
#endif /* #if CHECKING_P */
|