From 1b2df1d72f942ac68040bd5d44879729e7306bbb Mon Sep 17 00:00:00 2001 From: Chris Koeritz Date: Sun, 1 Jan 2017 13:12:52 -0500 Subject: [PATCH] renamings and add of singly linked list fixed name of "list" class to be doubly linked list, since it is that. now kind of grossed out by doubly linked list's implementation; suggest overhauling it so dl list IS a node in the dl list, rather than just a manager of node objects. also noting it has a gross iterator implementation, but it appears to be critical to the design of the class, so try to leave it intact. added a very basic singly linked list in order to have the new cycle detection algorithm. added a test for singly linked lists. added definition for eclipse on gnu unix of __UNIX__, which calmed a lot of complaints about HOOPLE_MAIN and other memset/strncpy/etc methods. --- nucleus/.cproject | 6 + .../{list.cpp => doubly_linked_list.cpp} | 89 +++++---- .../nodes/{list.h => doubly_linked_list.h} | 56 +++--- nucleus/library/nodes/makefile | 2 +- nucleus/library/nodes/singly_linked_list.cpp | 3 + nucleus/library/nodes/singly_linked_list.h | 71 ++++++++ nucleus/library/tests_nodes/makefile | 2 +- ...t_list.cpp => test_doubly_linked_list.cpp} | 44 +++-- .../tests_nodes/test_singly_linked_list.cpp | 172 ++++++++++++++++++ 9 files changed, 347 insertions(+), 98 deletions(-) rename nucleus/library/nodes/{list.cpp => doubly_linked_list.cpp} (73%) rename nucleus/library/nodes/{list.h => doubly_linked_list.h} (85%) create mode 100644 nucleus/library/nodes/singly_linked_list.cpp create mode 100644 nucleus/library/nodes/singly_linked_list.h rename nucleus/library/tests_nodes/{test_list.cpp => test_doubly_linked_list.cpp} (74%) create mode 100644 nucleus/library/tests_nodes/test_singly_linked_list.cpp diff --git a/nucleus/.cproject b/nucleus/.cproject index d05aaa79..858a68d5 100644 --- a/nucleus/.cproject +++ b/nucleus/.cproject @@ -21,9 +21,15 @@ + + diff --git a/nucleus/library/nodes/list.cpp b/nucleus/library/nodes/doubly_linked_list.cpp similarity index 73% rename from nucleus/library/nodes/list.cpp rename to nucleus/library/nodes/doubly_linked_list.cpp index 0ef4dda1..27c28864 100644 --- a/nucleus/library/nodes/list.cpp +++ b/nucleus/library/nodes/doubly_linked_list.cpp @@ -1,30 +1,25 @@ +/* +* +* Name : doubly_linked_list +* Author : Chris Koeritz +** +* Copyright (c) 1998-$now By Author. 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 is online at: +* http://www.fsf.org/copyleft/gpl.html +* Please send any updates to: fred@gruntose.com +*/ +/* + * POLICIES: + * + * + the cursor should never be stored to or deleted; it is merely a scanner that runs through the list. + * + the cursor can point at the head or tail. any storage action is taken to mean that it applies to the closest real object, if one exists. any query action is taken similarly. + */ +#include "doubly_linked_list.h" -/*****************************************************************************\ -* * -* Name : list * -* Author : Chris Koeritz * -* * -******************************************************************************* -* Copyright (c) 1998-$now By Author. 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 is online at: * -* http://www.fsf.org/copyleft/gpl.html * -* Please send any updates to: fred@gruntose.com * -\*****************************************************************************/ - -// POLICIES: -// -// the cursor should never be stored to or deleted; it is merely a scanner that -// runs through the list. -// -// the cursor can point at the head or tail. any storage action is taken to -// mean that it applies to the closest real object, if one exists. any query -// action is taken similarly. - -#include "list.h" #include "node.h" #include @@ -40,22 +35,22 @@ const int NEXT = 1; // iterator functions: -void list::iterator::operator ++() +void doubly_linked_list::iterator::operator ++() { if (is_tail()) return; // already at the end. _cursor = _cursor->get_link(NEXT); } -void list::iterator::operator --() +void doubly_linked_list::iterator::operator --() { if (is_head()) return; // already at the front. _cursor = _cursor->get_link(PREVIOUS); } -bool list::iterator::operator ==(const iterator &to_compare) const +bool doubly_linked_list::iterator::operator ==(const iterator &to_compare) const { return _cursor == to_compare._cursor; } -const node *list::iterator::observe() +const node *doubly_linked_list::iterator::observe() { if (!_manager || _manager->empty()) return NULL_POINTER; if (*this == _manager->head()) next(); @@ -63,7 +58,7 @@ const node *list::iterator::observe() return _cursor; } -node *list::iterator::access() +node *doubly_linked_list::iterator::access() { if (!_manager || _manager->empty()) return NULL_POINTER; if (*this == _manager->head()) next(); @@ -71,25 +66,25 @@ node *list::iterator::access() return _cursor; } -bool list::iterator::is_head() const +bool doubly_linked_list::iterator::is_head() const { if (!_manager) return false; return _cursor == _manager->_head; } -bool list::iterator::is_tail() const +bool doubly_linked_list::iterator::is_tail() const { if (!_manager) return false; return _cursor == _manager->_tail; } -void list::iterator::jump_head() +void doubly_linked_list::iterator::jump_head() { if (!_manager) return; _cursor = _manager->_head; } -void list::iterator::jump_tail() +void doubly_linked_list::iterator::jump_tail() { if (!_manager) return; _cursor = _manager->_tail; @@ -97,7 +92,7 @@ void list::iterator::jump_tail() ////////////// -list::list() +doubly_linked_list::doubly_linked_list() : _head(NULL_POINTER), _tail(NULL_POINTER) { _head = new node(2); @@ -106,7 +101,7 @@ list::list() _tail->set_link(PREVIOUS, _head); } -list::~list() +doubly_linked_list::~doubly_linked_list() { iterator zapper = head(); while (!empty()) @@ -115,13 +110,13 @@ list::~list() WHACK(_tail); } -bool list::empty() const +bool doubly_linked_list::empty() const { if (_head->get_link(NEXT) == _tail) return true; return false; } -bool list::set_index(iterator &where, int new_index) +bool doubly_linked_list::set_index(iterator &where, int new_index) { if (where._manager != this) return false; if (empty()) return false; @@ -134,7 +129,7 @@ bool list::set_index(iterator &where, int new_index) return true; } -bool list::forward(iterator &where, int count) +bool doubly_linked_list::forward(iterator &where, int count) { if (where._manager != this) return false; if (count <= 0) return true; @@ -144,7 +139,7 @@ bool list::forward(iterator &where, int count) return true; } -bool list::backward(iterator &where, int count) +bool doubly_linked_list::backward(iterator &where, int count) { if (where._manager != this) return false; if (count <= 0) return true; @@ -154,7 +149,7 @@ bool list::backward(iterator &where, int count) return true; } -int list::elements() const +int doubly_linked_list::elements() const { if (empty()) return 0; int to_return = 0; @@ -166,7 +161,7 @@ int list::elements() const return to_return; } -int list::items_from_head(const iterator &where) const +int doubly_linked_list::items_from_head(const iterator &where) const { if (where._manager != this) return 0; if (where.is_head()) return 0; // make sure it's not there already. @@ -179,7 +174,7 @@ int list::items_from_head(const iterator &where) const return index; } -int list::items_from_tail(const iterator &where) const +int doubly_linked_list::items_from_tail(const iterator &where) const { if (where._manager != this) return 0; if (where.is_tail()) return 0; // make sure it's not there already. @@ -204,7 +199,7 @@ node *list::get() } */ -node *list::remove(iterator &where) +node *doubly_linked_list::remove(iterator &where) { if (where._manager != this) return NULL_POINTER; if (empty()) return NULL_POINTER; @@ -223,9 +218,9 @@ node *list::remove(iterator &where) return old_cursor; } -void list::zap(iterator &where) { delete remove(where); } +void doubly_linked_list::zap(iterator &where) { delete remove(where); } -void list::append(iterator &where, node *new_node) +void doubly_linked_list::append(iterator &where, node *new_node) { if (where._manager != this) return; while (new_node->links() < 2) new_node->insert_link(0, NULL_POINTER); @@ -241,7 +236,7 @@ void list::append(iterator &where, node *new_node) where._cursor = new_node; } -void list::insert(iterator &where, node *new_node) +void doubly_linked_list::insert(iterator &where, node *new_node) { if (where._manager != this) return; while (new_node->links() < 2) new_node->insert_link(0, NULL_POINTER); @@ -257,7 +252,7 @@ void list::insert(iterator &where, node *new_node) where._cursor = new_node; } -void list::zap_all() +void doubly_linked_list::zap_all() { iterator zapper = head(); while (!empty()) zap(zapper); diff --git a/nucleus/library/nodes/list.h b/nucleus/library/nodes/doubly_linked_list.h similarity index 85% rename from nucleus/library/nodes/list.h rename to nucleus/library/nodes/doubly_linked_list.h index 5856b493..987e2480 100644 --- a/nucleus/library/nodes/list.h +++ b/nucleus/library/nodes/doubly_linked_list.h @@ -1,21 +1,17 @@ -#ifndef LIST_CLASS -#define LIST_CLASS - -/*****************************************************************************\ -* * -* Name : list * -* Author : Chris Koeritz * -* * -******************************************************************************* -* Copyright (c) 1998-$now By Author. 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 is online at: * -* http://www.fsf.org/copyleft/gpl.html * -* Please send any updates to: fred@gruntose.com * -\*****************************************************************************/ - - +#ifndef DOUBLY_LINKED_LIST_CLASS +#define DOUBLY_LINKED_LIST_CLASS + +/* +* Name : doubly_linked_list +* Author : Chris Koeritz +** +* Copyright (c) 1998-$now By Author. 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 is online at: +* http://www.fsf.org/copyleft/gpl.html +* Please send any updates to: fred@gruntose.com +*/ namespace nodes { @@ -33,13 +29,21 @@ class node; // forward. cursor is affected. Note that this list is not thread safe. */ -class list + +//hmmm: is this class really for real? it's doing all sorts of stuff with nodes, rather than with the list object itself. +// consider dropping the current implementation and providing more standard list operations, on an object that is actually using itself in its definition, rather than a different class (node). +// this would be easy to do if we just break down and define the dl list as a node itself. then we have something to work with. + +//current iterator implementation here is bunk. + + +class doubly_linked_list { public: - list(); + doubly_linked_list(); //!< constructs a blank list. - ~list(); + ~doubly_linked_list(); //!< invalidates all contents of the list and destroys all child nodes. int elements() const; @@ -57,7 +61,7 @@ public: class iterator { public: - iterator(const list *mgr, node *start) : _cursor(start), _manager(mgr) {} + iterator(const doubly_linked_list *mgr, node *start) : _cursor(start), _manager(mgr) {} //!< opens up an iterator on a list. /*!< the preferred method to construct an iterator is to use the head/tail functions in list. */ @@ -104,8 +108,8 @@ public: private: node *_cursor; //!< the current position. - friend class list; //!< lists have full access to this object. - const list *_manager; //!< our friendly manager. + friend class doubly_linked_list; //!< lists have full access to this object. + const doubly_linked_list *_manager; //!< our friendly manager. }; iterator head() const { return iterator(this, _head); } @@ -180,8 +184,8 @@ private: //!< zips the list to the position indicated by "count", if it can. // not permitted. - list(const list &); - list &operator =(const list &); + doubly_linked_list(const doubly_linked_list &); + doubly_linked_list &operator =(const doubly_linked_list &); }; } // namespace. diff --git a/nucleus/library/nodes/makefile b/nucleus/library/nodes/makefile index b114f9e7..e13af90d 100644 --- a/nucleus/library/nodes/makefile +++ b/nucleus/library/nodes/makefile @@ -2,7 +2,7 @@ include cpp/variables.def PROJECT = nodes TYPE = library -SOURCE = list.cpp node.cpp packable_tree.cpp path.cpp symbol_tree.cpp tree.cpp +SOURCE = doubly_linked_list.cpp node.cpp packable_tree.cpp path.cpp singly_linked_list.cpp symbol_tree.cpp tree.cpp TARGETS = nodes.lib include cpp/rules.def diff --git a/nucleus/library/nodes/singly_linked_list.cpp b/nucleus/library/nodes/singly_linked_list.cpp new file mode 100644 index 00000000..97eec6a8 --- /dev/null +++ b/nucleus/library/nodes/singly_linked_list.cpp @@ -0,0 +1,3 @@ + +#include "singly_linked_list.h" + diff --git a/nucleus/library/nodes/singly_linked_list.h b/nucleus/library/nodes/singly_linked_list.h new file mode 100644 index 00000000..d58f20fb --- /dev/null +++ b/nucleus/library/nodes/singly_linked_list.h @@ -0,0 +1,71 @@ +#ifndef SINGLY_LINKED_LIST_CLASS +#define SINGLY_LINKED_LIST_CLASS + +/* +* Name : singly_linked_list +* Author : Chris Koeritz +** +* Copyright (c) 1998-$now By Author. 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 is online at: +* http://www.fsf.org/copyleft/gpl.html +* Please send any updates to: fred@gruntose.com +*/ +#include "node.h" + +namespace nodes { + +//class node; // forward. + +//! Implements a singly-linked list structure. + +class singly_linked_list : public node +{ +public: + singly_linked_list() : node(1) {} + + //hmmm: clean up all children? + ~singly_linked_list() {} + + const int NEXT_NODE = 0; // symbol for the rest of the list linked here. + + int elements() const; + //!< returns the number of items currently in the list, including this node. + /*!< this is a costly operation. */ + + singly_linked_list *next() { return (singly_linked_list *)get_link(NEXT_NODE); } + + void set_next(singly_linked_list *new_next) { set_link(NEXT_NODE, new_next); } + + //! returns true if this list has a cycle in it. + static bool has_cycle(singly_linked_list *check) { + singly_linked_list *a = check; + singly_linked_list *b = check; + while ((a != NULL_POINTER) && (b!= NULL_POINTER) ) { + a = a->next(); // move position of a forward once. + // move position of b forward twice. + b = b->next(); + if (b != NULL_POINTER) b = b->next(); + + if (a == b) { + // argh, our single skipper and double skipper have arrived at the same node. + // the only way that can happen is if there's a cycle in the list. + return true; + } + } + // if we fell out of the list iteration with a null for either pointer, + // then there was no cycle in the list. + return false; + } + +private: + // not permitted. + singly_linked_list(const singly_linked_list &); + singly_linked_list &operator =(const singly_linked_list &); +}; + +} // namespace. + +#endif + diff --git a/nucleus/library/tests_nodes/makefile b/nucleus/library/tests_nodes/makefile index a8c2e75e..19f4b2d6 100644 --- a/nucleus/library/tests_nodes/makefile +++ b/nucleus/library/tests_nodes/makefile @@ -2,7 +2,7 @@ include cpp/variables.def PROJECT = tests_node TYPE = test -TARGETS = test_list.exe test_node.exe test_packable_tree.exe test_symbol_tree.exe test_tree.exe +TARGETS = test_doubly_linked_list.exe test_node.exe test_packable_tree.exe test_singly_linked_list.exe test_symbol_tree.exe test_tree.exe LOCAL_LIBS_USED = unit_test application nodes loggers processes filesystem configuration timely textual structures basis DEFINITIONS += USE_FEISTY_MEOW_DLLS RUN_TARGETS = $(ACTUAL_TARGETS) diff --git a/nucleus/library/tests_nodes/test_list.cpp b/nucleus/library/tests_nodes/test_doubly_linked_list.cpp similarity index 74% rename from nucleus/library/tests_nodes/test_list.cpp rename to nucleus/library/tests_nodes/test_doubly_linked_list.cpp index 14a4fc7b..be224b8a 100644 --- a/nucleus/library/tests_nodes/test_list.cpp +++ b/nucleus/library/tests_nodes/test_doubly_linked_list.cpp @@ -1,16 +1,14 @@ -/*****************************************************************************\ -* * -* Name : test_list * -* Author : Chris Koeritz * -* * -******************************************************************************* -* Copyright (c) 1993-$now By Author. 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 is online at: * -* http://www.fsf.org/copyleft/gpl.html * -* Please send any updates to: fred@gruntose.com * -\*****************************************************************************/ +/* +* Name : test_doubly_linked_list +* Author : Chris Koeritz +** +* Copyright (c) 1993-$now By Author. 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 is online at: +* http://www.fsf.org/copyleft/gpl.html +* Please send any updates to: fred@gruntose.com +*/ #include #include @@ -18,10 +16,10 @@ #include #include #include -#include #include #include #include +#include using namespace application; using namespace basis; @@ -48,23 +46,23 @@ typedef basket t_node; ////////////// -class test_list : virtual public unit_base, virtual public application_shell +class test_doubly_linked_list : virtual public unit_base, virtual public application_shell { public: - test_list() : unit_base() {} + test_doubly_linked_list() : unit_base() {} DEFINE_CLASS_NAME("test_list"); virtual int execute(); }; -HOOPLE_MAIN(test_list, ); +HOOPLE_MAIN(test_doubly_linked_list, ); ////////////// -int test_list::execute() +int test_doubly_linked_list::execute() { FUNCDEF("execute"); - list the_list; + doubly_linked_list the_list; chaos randomizer; int iterations_left = DEFAULT_ITERATIONS; @@ -77,7 +75,7 @@ int test_list::execute() int to_add = randomizer.inclusive(0, 100000); // seek the correct insertion place to keep the list ordered. - list::iterator iter = the_list.head(); + doubly_linked_list::iterator iter = the_list.head(); while (!iter.is_tail() && iter.observe() && (CASTER(iter.observe())->stored() <= to_add) ) iter++; @@ -87,7 +85,7 @@ int test_list::execute() { // test the list invariant (which is that all elements should be sorted // in non-decreasing order). - list::iterator iter = the_list.tail(); + doubly_linked_list::iterator iter = the_list.tail(); // initialize our comparator. int bigger = CASTER(iter.observe())->stored(); // loop backwards until we hit the head. @@ -108,7 +106,7 @@ int test_list::execute() int to_whack = randomizer.inclusive(0, elem - 1); // start at the head of the list... - list::iterator iter = the_list.head(); + doubly_linked_list::iterator iter = the_list.head(); // and jump to the element we chose. the_list.forward(iter, to_whack); ASSERT_EQUAL(the_list.index(iter), to_whack, @@ -122,7 +120,7 @@ int test_list::execute() } #ifdef DEBUG_LIST - list::iterator iter = the_list.head(); + doubly_linked_list::iterator iter = the_list.head(); log(astring("")); log(astring("list contents:")); int indy = 0; diff --git a/nucleus/library/tests_nodes/test_singly_linked_list.cpp b/nucleus/library/tests_nodes/test_singly_linked_list.cpp new file mode 100644 index 00000000..e5e88c58 --- /dev/null +++ b/nucleus/library/tests_nodes/test_singly_linked_list.cpp @@ -0,0 +1,172 @@ +/* +* Name : test_singly_linked_list +* Author : Chris Koeritz +** +* Copyright (c) 1993-$now By Author. 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 is online at: +* http://www.fsf.org/copyleft/gpl.html +* Please send any updates to: fred@gruntose.com +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace application; +using namespace basis; +using namespace configuration; +using namespace loggers; +using namespace mathematics; +using namespace nodes; +using namespace structures; +using namespace unit_test; + +//#define DEBUG_LIST + // uncomment this line to get more debugging output. + +const int DEFAULT_ITERATIONS = 50; + // the default number of times we run through our phase loop. + +typedef basket t_node; + // the object we store in the list, a templated integer. + +#define CASTER(bare_node) static_cast(bare_node) + // turns a node pointer into our special t_node. + +#define LOG(to_print) EMERGENCY_LOG(program_wide_logger::get(), to_print) + +////////////// + +class test_singly_linked_list : virtual public unit_base, virtual public application_shell +{ +public: + test_singly_linked_list() : unit_base() {} + DEFINE_CLASS_NAME("test_list"); + virtual int execute(); +}; + +HOOPLE_MAIN(test_singly_linked_list, ); + +////////////// + +int test_singly_linked_list::execute() +{ + FUNCDEF("execute"); + + // first some discrete tests, before we start looping around. + + { + // test that the cycle detector is working for finding a cycle. + singly_linked_list *a = new singly_linked_list(); + singly_linked_list *b = new singly_linked_list(); + singly_linked_list *c = new singly_linked_list(); + singly_linked_list *d = new singly_linked_list(); + singly_linked_list *e = new singly_linked_list(); + a->set_next(b); + b->set_next(c); + c->set_next(d); + d->set_next(e); + e->set_next(c); + + ASSERT_TRUE(singly_linked_list::has_cycle(a), "list should be found to have a cycle") + } + + { + // test that the cycle detector is working to not find a cycle if one doesn't exist. + singly_linked_list *a = new singly_linked_list(); + singly_linked_list *b = new singly_linked_list(); + singly_linked_list *c = new singly_linked_list(); + singly_linked_list *d = new singly_linked_list(); + singly_linked_list *e = new singly_linked_list(); + a->set_next(b); + b->set_next(c); + c->set_next(d); + d->set_next(e); +// e->set_next(NULL_POINTER); // not actually necessary, right? + + ASSERT_FALSE(singly_linked_list::has_cycle(a), "list should be found to have zero cycles") + } + + singly_linked_list *the_list = new singly_linked_list(); + + chaos randomizer; + + int iterations_left = DEFAULT_ITERATIONS; + while (iterations_left-- > 0) { + + // run through the phases below as many times as we are told. + + { + // phase for adding a random number into the list. + int to_add = randomizer.inclusive(0, 100000); + +// // seek the correct insertion place to keep the list ordered. +// singly_linked_list::iterator iter = the_list.head(); +// while (!iter.is_tail() && iter.observe() +// && (CASTER(iter.observe())->stored() <= to_add) ) +// iter++; +// the_list.insert(iter, new t_node(2, to_add)); + } + + { +// // test the list invariant (which is that all elements should be sorted +// // in non-decreasing order). +// singly_linked_list::iterator iter = the_list.tail(); +// // initialize our comparator. +// int bigger = CASTER(iter.observe())->stored(); +// // loop backwards until we hit the head. +// while (!iter.is_head()) { +// // check that the last value is not less than the current value. +// ASSERT_FALSE(bigger < CASTER(iter.observe())->stored(), +// "invariant check should not find a mal-ordering in the list"); +// bigger = CASTER(iter.observe())->stored(); +// iter--; +// } + } + + { +// // if the conditions are favorable, we whack at least one element out of +// // the list. +// if (randomizer.inclusive(1, 100) < 20) { +// int elem = the_list.elements(); +// int to_whack = randomizer.inclusive(0, elem - 1); +// +// // start at the head of the list... +// singly_linked_list::iterator iter = the_list.head(); +// // and jump to the element we chose. +// the_list.forward(iter, to_whack); +// ASSERT_EQUAL(the_list.index(iter), to_whack, +// "forward should not see logic error where index of element to zap is incorrect"); +// ASSERT_FALSE(iter.is_tail(), +// "forward should not see logic error where we get to the tail somehow"); +// the_list.zap(iter); +// } + } + + } + +//#ifdef DEBUG_LIST +// singly_linked_list::iterator iter = the_list.head(); +// log(astring("")); +// log(astring("list contents:")); +// int indy = 0; +// while (!iter.is_tail()) { +// int item = CASTER(iter.observe())->stored(); +// log(a_sprintf("item #%d: %d", indy, item)); +// indy++; +// iter++; +// } +//#endif + + return final_report(); +} + + -- 2.34.1