/IntegerProgramming/list.cc

https://github.com/burcin/Singular · C++ · 1166 lines · 600 code · 440 blank · 126 comment · 36 complexity · 8de0f661f92613ae91bd59b3b51636a4 MD5 · raw file

  1. // list.cc
  2. // implementation of class list and class list iterator
  3. #ifndef LIST_CC
  4. #define LIST_CC
  5. #include "list.h"
  6. /////////////////////////////////////////////////////////////////////////////
  7. ///////////////////////// class list ////////////////////////////////////////
  8. /////////////////////////////////////////////////////////////////////////////
  9. /////////////////// constructors and destructor /////////////////////////////
  10. list::list()
  11. {
  12. #ifdef DL_LIST
  13. element* begin_dummy=new element;
  14. #endif // DL_LIST
  15. element* end_dummy=new element;
  16. #ifdef DL_LIST
  17. begin_dummy->previous=NULL;
  18. begin_dummy->next=end_dummy;
  19. begin_dummy->entry=NULL;
  20. begin_dummy->done=FALSE;
  21. begin_dummy->head_reduced=FALSE;
  22. end_dummy->previous=begin_dummy;
  23. #endif // DL_LIST
  24. end_dummy->next=NULL;
  25. end_dummy->entry=NULL;
  26. end_dummy->done=TRUE;
  27. end_dummy->head_reduced=TRUE;
  28. #ifdef DL_LIST
  29. start=begin_dummy;
  30. #endif // DL_LIST
  31. #ifdef SL_LIST
  32. start=end_dummy;
  33. #endif // SL_LIST
  34. }
  35. // The dummy elements have the following functions:
  36. // - The end_dummy guarantees that the deletion method of the simply linked
  37. // list works: Deletion is done by copying the next element to the actual
  38. // position and then deleting the original, see below for an explaination.
  39. // This would cause problems when deleting the last element; then the
  40. // next-pointer of the preceeding element would reference freed memory
  41. // (it cannot be manipulated, is unknown). So the end_dummy as an
  42. // artificial last element avoids this problem.
  43. // - With the described deletion method for a simply linked list, the start
  44. // pointer of a list has never to be changed by the list_iterator class
  45. // (as long as the list is not empty; but with the end_dummy, the list
  46. // never becomes empty). So a list iterator must never know on which list
  47. // he operates on.
  48. // Doubly linked lists use another, more secure deletion method (which
  49. // really deletes the actual element). Therefore, the comfort of a start
  50. // pointer which has never to be manipulated by the iterators must be
  51. // reached in another way: This is the purpose of the begin_dummy, an
  52. // artificial first element which is referenced by the start pointer and
  53. // never changed.
  54. // - With the dummy elements, we do need to distinguish the cases of inserting
  55. // or deleting at the beginning or the end of a list.
  56. // - Furthermore, the end_dummy is a stopper for Buchberger's algorithm:
  57. // By setting all flags to TRUE, we can eliminate many calls of the
  58. // is_at_end()-function of the list iterator class.
  59. // The dummy elements should never be deleted (the dletion method is not
  60. // secure)!
  61. list::list(const list& l)
  62. {
  63. #ifdef DL_LIST
  64. element* begin_dummy=new element;
  65. #endif // DL_LIST
  66. element* end_dummy=new element;
  67. #ifdef DL_LIST
  68. begin_dummy->previous=NULL;
  69. begin_dummy->next=end_dummy;
  70. begin_dummy->entry=NULL;
  71. begin_dummy->done=FALSE;
  72. begin_dummy->head_reduced=FALSE;
  73. end_dummy->previous=NULL;
  74. #endif // DL_LIST
  75. end_dummy->next=NULL;
  76. end_dummy->entry=NULL;
  77. end_dummy->done=TRUE;
  78. end_dummy->head_reduced=TRUE;
  79. #ifdef DL_LIST
  80. start=begin_dummy;
  81. element *iter=(l.start)->next;
  82. #endif // DL_LIST
  83. #ifdef SL_LIST
  84. element* iter=l.start;
  85. #endif // SL_LIST
  86. if(iter==NULL)
  87. {
  88. cerr<<"\nWARNING: list::list(const list&):\ntry to construct a list from"
  89. " a corrupt one; empty list created"<<endl;
  90. return;
  91. }
  92. while((iter->next)!=NULL)
  93. // end_dummy not reached
  94. {
  95. copy_insert(*(iter->entry));
  96. iter=iter->next;
  97. }
  98. }
  99. list::~list()
  100. {
  101. #ifdef DL_LIST
  102. element *iter=start->next;
  103. #endif // DL_LIST
  104. #ifdef SL_LIST
  105. element *iter=start;
  106. #endif // SL_LIST
  107. while(iter->next!=NULL)
  108. // delete non-dummy elements
  109. {
  110. element* aux=iter;
  111. iter=iter->next;
  112. delete aux->entry;
  113. delete aux;
  114. }
  115. // end_dummy reached, delete it
  116. delete iter;
  117. #ifdef DL_LIST
  118. // delete begin_dummy
  119. delete start;
  120. #endif // DL_LIST
  121. }
  122. ///////////////////// inserting ////////////////////////////////////////////
  123. // For a better overview, the code for the simply and for the doubly linked
  124. // list is separated (except from the "copy-insert"-routines).
  125. #ifdef DL_LIST
  126. list& list::insert(binomial& bin)
  127. {
  128. // insert at the beginning (after the begin_dummy)
  129. // initialize element
  130. element* aux=new element;
  131. aux->entry=&bin;
  132. aux->done=FALSE;
  133. aux->head_reduced=FALSE;
  134. // set pointers
  135. aux->next=start->next;
  136. aux->next->previous=aux;
  137. aux->previous=start;
  138. start->next=aux;
  139. return(*this);
  140. }
  141. list& list::_insert(binomial& bin)
  142. {
  143. // insert at the beginning
  144. // initialize element
  145. element* aux=new element;
  146. aux->entry=&bin;
  147. // set pointers
  148. aux->next=start->next;
  149. aux->next->previous=aux;
  150. aux->previous=start;
  151. start->next=aux;
  152. return(*this);
  153. }
  154. list& list::ordered_insert(binomial& bin, const term_ordering& w)
  155. {
  156. // search for the place to insert
  157. element* iter=start->next;
  158. while(iter->entry!=NULL)
  159. // end_dummy not reached
  160. {
  161. if(w.compare(*(iter->entry),bin)<=0)
  162. // bin is bigger in term ordering then the referenced binomial
  163. iter=iter->next;
  164. else
  165. break;
  166. }
  167. // now bin is smaller in term ordering then the referenced binomial
  168. // or the referenced binomial is the end_dummy
  169. // initialize element
  170. element*aux=new element;
  171. aux->entry=&bin;
  172. aux->done=FALSE;
  173. aux->head_reduced=FALSE;
  174. // set pointers
  175. aux->previous=iter->previous;
  176. aux->previous->next=aux;
  177. aux->next=iter;
  178. iter->previous=aux;
  179. return *this;
  180. }
  181. list& list::_ordered_insert(binomial& bin, const term_ordering& w)
  182. {
  183. // search for the place to insert
  184. element* iter=start->next;
  185. while(iter->entry!=NULL)
  186. // end_dummy not reached
  187. {
  188. if(w.compare(*(iter->entry),bin)<=0)
  189. // bin is bigger in term ordering then the referenced binomial
  190. iter=iter->next;
  191. else
  192. break;
  193. }
  194. // now bin is smaller in term ordering then the referenced binomial
  195. // or the referenced binomial is the end_dummy
  196. // initialize element
  197. element*aux=new element;
  198. aux->entry=&bin;
  199. // set pointers
  200. aux->previous=iter->previous;
  201. aux->previous->next=aux;
  202. aux->next=iter;
  203. iter->previous=aux;
  204. return *this;
  205. }
  206. #endif // DL_LIST
  207. #ifdef SL_LIST
  208. list& list::insert(binomial& bin)
  209. {
  210. // insert at the beginning
  211. // initialize element
  212. element* aux=new element;
  213. aux->entry=&bin;
  214. aux->done=FALSE;
  215. aux->head_reduced=FALSE;
  216. // set pointers
  217. aux->next=start;
  218. start=aux;
  219. return(*this);
  220. }
  221. list& list::_insert(binomial& bin)
  222. {
  223. // insert at the beginning
  224. // initialize element
  225. element* aux=new element;
  226. aux->entry=&bin;
  227. // set pointers
  228. aux->next=start;
  229. start=aux;
  230. return(*this);
  231. }
  232. list& list::ordered_insert(binomial& bin, const term_ordering& w)
  233. {
  234. // search for the place to insert
  235. element* iter=start;
  236. while(iter->entry!=NULL)
  237. // end_dummy not reached
  238. {
  239. if(w.compare(*(iter->entry),bin)<=0)
  240. // bin is bigger in term ordering then the referenced binomial
  241. iter=iter->next;
  242. else
  243. break;
  244. }
  245. // now bin is smaller in term ordering then the referenced binomial
  246. // or the referenced binomial is the end_dummy
  247. // here we have to consider a special case
  248. if(iter==start)
  249. return insert(bin);
  250. // insert new element by first allocating a new list place behind the
  251. // referenced element, then moving the referenced element to that
  252. // new place...
  253. element*aux=new element;
  254. aux->entry=iter->entry;
  255. aux->done=iter->done;
  256. aux->head_reduced=iter->head_reduced;
  257. aux->next=iter->next;
  258. // .. and finally inserting bin at the old place
  259. // Remember that we cannot insert a new element between the referenced
  260. // element and its preceeding (we do not know the preceeding element)
  261. iter->entry=&bin;
  262. iter->done=FALSE;
  263. iter->head_reduced=FALSE;
  264. iter->next=aux;
  265. return *this;
  266. }
  267. list& list::_ordered_insert(binomial& bin, const term_ordering& w)
  268. {
  269. // search for the place to insert
  270. element* iter=start;
  271. while(iter->entry!=NULL)
  272. // end_dummy not reached
  273. {
  274. if(w.compare(*(iter->entry),bin)<=0)
  275. // bin is bigger in term ordering then the referenced binomial
  276. iter=iter->next;
  277. else
  278. break;
  279. }
  280. // now bin is smaller in term ordering then the referenced binomial
  281. // or the referenced binomial is the end_dummy
  282. // here we have to consider a special case
  283. if(iter==start)
  284. return _insert(bin);
  285. // insert new element by first allocating a new list place behind the
  286. // referenced element, then moving the referenced element to that
  287. // new place...
  288. element*aux=new element;
  289. aux->entry=iter->entry;
  290. aux->next=iter->next;
  291. // .. and finally inserting bin at the old place
  292. // Remember that we cannot insert a new element between the referenced
  293. // element and its preceeding (we do not know the preceeding element)
  294. iter->entry=&bin;
  295. iter->next=aux;
  296. return *this;
  297. }
  298. #endif // SL_LIST
  299. // copy-insert routines
  300. list& list::copy_insert(const binomial& bin)
  301. {
  302. binomial* _bin=new binomial(bin);
  303. return insert(*_bin);
  304. }
  305. list& list::_copy_insert(const binomial& bin)
  306. {
  307. binomial *_bin=new binomial(bin);
  308. return _insert(*_bin);
  309. }
  310. list& list::ordered_copy_insert(const binomial& bin, const term_ordering& w)
  311. {
  312. binomial *_bin=new binomial(bin);
  313. return ordered_insert(*_bin,w);
  314. }
  315. list& list::_ordered_copy_insert(const binomial& bin, const term_ordering& w)
  316. {
  317. binomial *_bin=new binomial(bin);
  318. return _ordered_insert(*_bin,w);
  319. }
  320. /////////////////////////// output //////////////////////////////////////////
  321. void list::print() const
  322. {
  323. #ifdef DL_LIST
  324. element* iter=start->next;
  325. #endif // DL_LIST
  326. #ifdef SL_LIST
  327. element *iter=start;
  328. #endif // SL_LIST
  329. if(iter==NULL)
  330. {
  331. cerr<<"\nWARNING: void list::print() const:\ncannot print corrupt list"
  332. <<endl;
  333. return;
  334. }
  335. while(iter->next!=NULL)
  336. {
  337. iter->entry->print();
  338. iter=iter->next;
  339. }
  340. }
  341. void list::ordered_print(const term_ordering& w) const
  342. {
  343. #ifdef DL_LIST
  344. element* iter=start->next;
  345. #endif // DL_LIST
  346. #ifdef SL_LIST
  347. element *iter=start;
  348. #endif // SL_LIST
  349. if(iter==NULL)
  350. {
  351. cerr<<"\nWARNING: void list::print(const term_ordering&) const:\n"
  352. "cannot print corrupt list"<<endl;
  353. return;
  354. }
  355. list aux;
  356. while(iter->next!=NULL)
  357. {
  358. aux._ordered_insert(*(iter->entry),w);
  359. iter=iter->next;
  360. }
  361. aux.print();
  362. // delete aux, but only the element structs, not the binomials
  363. // (these are still stored in the actual list!)
  364. #ifdef DL_LIST
  365. iter=aux.start->next;
  366. #endif // DL_LIST
  367. #ifdef SL_LIST
  368. iter=aux.start;
  369. #endif
  370. while(iter->next!=NULL)
  371. // end_dummy not reached
  372. {
  373. element* aux2=iter->next;
  374. iter->next=iter->next->next;
  375. delete aux2;
  376. }
  377. // the dummy elements are deleted by the destructor
  378. }
  379. void list::print(FILE* output) const
  380. {
  381. #ifdef DL_LIST
  382. element* iter=start->next;
  383. #endif // DL_LIST
  384. #ifdef SL_LIST
  385. element *iter=start;
  386. #endif // SL_LIST
  387. if(iter==NULL)
  388. {
  389. cerr<<"\nWARNING: void list::print(FILE*) const:\ncannot print corrupt "
  390. "list"<<endl;
  391. fprintf(output,"\nWARNING: void list::print(FILE*) const:\ncannot print "
  392. "corrupt list\n");
  393. return;
  394. }
  395. while(iter->next!=NULL)
  396. {
  397. iter->entry->print(output);
  398. iter=iter->next;
  399. }
  400. }
  401. void list::ordered_print(FILE* output, const term_ordering& w) const
  402. {
  403. #ifdef DL_LIST
  404. element* iter=start->next;
  405. #endif // DL_LIST
  406. #ifdef SL_LIST
  407. element *iter=start;
  408. #endif // SL_LIST
  409. if(iter==NULL)
  410. {
  411. cerr<<"\nWARNING: void list::print(const term_ordering&) const:\n"
  412. "cannot print corrupt list"<<endl;
  413. fprintf(output,"\nWARNING: void list::print(const term_ordering&) const:\n"
  414. "cannot print corrupt list\n");
  415. return;
  416. }
  417. list aux;
  418. while(iter->next!=NULL)
  419. {
  420. aux._ordered_insert(*(iter->entry),w);
  421. iter=iter->next;
  422. }
  423. aux.print(output);
  424. // delete aux, but only the element structs, not the binomials
  425. // (these are still stored in the actual list!)
  426. #ifdef DL_LIST
  427. iter=aux.start->next;
  428. #endif // DL_LIST
  429. #ifdef SL_LIST
  430. iter=aux.start;
  431. #endif
  432. while(iter->next!=NULL)
  433. // end_dummy not reached
  434. {
  435. element* aux2=iter->next;
  436. iter->next=iter->next->next;
  437. delete aux2;
  438. }
  439. // the dummy elements are deleted by the destructor
  440. }
  441. void list::print(ofstream& output) const
  442. {
  443. #ifdef DL_LIST
  444. element* iter=start->next;
  445. #endif // DL_LIST
  446. #ifdef SL_LIST
  447. element *iter=start;
  448. #endif // SL_LIST
  449. if(iter==NULL)
  450. {
  451. cerr<<"\nWARNING: void list::print(ofstream&) const:\n"
  452. "cannot print corrupt list"<<endl;
  453. output<<"\nWARNING: void list::print(oftream&) const:\ncannot print "
  454. "corrupt list"<<endl;
  455. return;
  456. }
  457. while(iter->next!=NULL)
  458. {
  459. iter->entry->print(output);
  460. iter=iter->next;
  461. }
  462. }
  463. void list::ordered_print(ofstream& output, const term_ordering& w) const
  464. {
  465. #ifdef DL_LIST
  466. element* iter=start->next;
  467. #endif // DL_LIST
  468. #ifdef SL_LIST
  469. element *iter=start;
  470. #endif // SL_LIST
  471. if(iter==NULL)
  472. {
  473. cerr<<"\nWARNING: void list::ordered_print(const term_ordering&) const:\n"
  474. "cannot print corrupt list"<<endl;
  475. output<<"\nWARNING: void list::ordered_print(const term_ordering&) const:"
  476. "\n"
  477. "cannot print corrupt list\n"<<endl;
  478. return;
  479. }
  480. list aux;
  481. while(iter->next!=NULL)
  482. {
  483. aux._ordered_insert(*(iter->entry),w);
  484. iter=iter->next;
  485. }
  486. aux.print(output);
  487. // delete aux, but only the element structs, not the binomials
  488. // (these are still stored in the actual list!)
  489. #ifdef DL_LIST
  490. iter=(aux.start)->next;
  491. #endif // DL_LIST
  492. #ifdef SL_LIST
  493. iter=aux.start;
  494. #endif
  495. while((iter->next)!=NULL)
  496. {
  497. element* aux1=iter->next;
  498. iter->next=iter->next->next;
  499. delete aux1;
  500. }
  501. // the dummy elements are deleted by the destructor
  502. }
  503. void list::format_print(ofstream& output) const
  504. {
  505. #ifdef DL_LIST
  506. element* iter=start->next;
  507. #endif // DL_LIST
  508. #ifdef SL_LIST
  509. element *iter=start;
  510. #endif // SL_LIST
  511. if(iter==NULL)
  512. {
  513. cerr<<"\nWARNING: void list::print(ofstream&) const:\n"
  514. "cannot print corrupt list"<<endl;
  515. output<<"\nWARNING: void list::print(oftream&) const:\ncannot print "
  516. "corrupt list"<<endl;
  517. return;
  518. }
  519. while(iter->next!=NULL)
  520. {
  521. iter->entry->format_print(output);
  522. iter=iter->next;
  523. }
  524. }
  525. void list::ordered_format_print(ofstream& output, const term_ordering& w) const
  526. {
  527. #ifdef DL_LIST
  528. element* iter=start->next;
  529. #endif // DL_LIST
  530. #ifdef SL_LIST
  531. element *iter=start;
  532. #endif // SL_LIST
  533. if(iter==NULL)
  534. {
  535. cerr<<"\nWARNING: void list::ordered_format_print(const term_ordering&) "
  536. "const:\n"
  537. "cannot print corrupt list"<<endl;
  538. output<<"\nWARNING: void list::ordered_format_print(const term_ordering&) "
  539. "const:\n"
  540. "cannot print corrupt list\n"<<endl;
  541. return;
  542. }
  543. list aux;
  544. while(iter->next!=NULL)
  545. {
  546. aux._ordered_insert(*(iter->entry),w);
  547. iter=iter->next;
  548. }
  549. aux.format_print(output);
  550. // delete aux, but only the element structs, not the binomials
  551. // (these are still stored in the actual list!)
  552. #ifdef DL_LIST
  553. iter=(aux.start)->next;
  554. #endif // DL_LIST
  555. #ifdef SL_LIST
  556. iter=aux.start;
  557. #endif
  558. while((iter->next)!=NULL)
  559. {
  560. element* aux1=iter->next;
  561. iter->next=iter->next->next;
  562. delete aux1;
  563. }
  564. // the dummy elements are deleted by the destructor
  565. }
  566. /////////////////////////////////////////////////////////////////////////////
  567. ////////////////////// class list_iterator //////////////////////////////////
  568. /////////////////////////////////////////////////////////////////////////////
  569. // implementation of class list_iterator
  570. // Most of these function can be inlined. I have tried this and not improved
  571. // the performance. Perhaps the compiler does this automatically...
  572. ///////////////////////// constructors and destructor ///////////////////////
  573. list_iterator::list_iterator()
  574. {
  575. actual=NULL;
  576. }
  577. list_iterator::list_iterator(list& l)
  578. {
  579. #ifdef DL_LIST
  580. actual=(l.start)->next;
  581. #endif // DL_LIST
  582. #ifdef SL_LIST
  583. actual=l.start;
  584. #endif // SL_LIST
  585. }
  586. list_iterator::list_iterator(list_iterator& iter)
  587. {
  588. actual=iter.actual;
  589. }
  590. list_iterator::~list_iterator()
  591. {
  592. }
  593. /////////////////// object information /////////////////////////////////////
  594. BOOLEAN list_iterator::element_is_marked_done() const
  595. {
  596. return(actual->done);
  597. }
  598. BOOLEAN list_iterator::element_is_marked_head_reduced() const
  599. {
  600. return(actual->head_reduced);
  601. }
  602. BOOLEAN list_iterator::is_at_end() const
  603. {
  604. if(actual==NULL)
  605. // actual references no list
  606. return(TRUE);
  607. if(actual->next==NULL)
  608. // actual references dummy element
  609. return(TRUE);
  610. // actual references a real element
  611. return(FALSE);
  612. }
  613. ////////////////////////// assigment ///////////////////////////////////////
  614. list_iterator& list_iterator::set_to_list(const list& l)
  615. {
  616. #ifdef DL_LIST
  617. actual=(l.start)->next;
  618. #endif // DL_LIST
  619. #ifdef SL_LIST
  620. actual=l.start;
  621. #endif // SL_LIST
  622. return *this;
  623. }
  624. list_iterator& list_iterator::operator=(const list_iterator& iter)
  625. {
  626. if((&iter)!=this)
  627. actual=iter.actual;
  628. return *this;
  629. }
  630. list_iterator& list_iterator::next()
  631. {
  632. actual=actual->next;
  633. return *this;
  634. }
  635. /////////////////// comparison ////////////////////////////////////////////
  636. int list_iterator::operator==(const list_iterator& iter) const
  637. {
  638. return(actual==iter.actual);
  639. }
  640. int list_iterator::operator!=(const list_iterator& iter) const
  641. {
  642. return(!(actual==iter.actual));
  643. }
  644. int list_iterator::next_is(const list_iterator& iter) const
  645. {
  646. return ((actual->next)==iter.actual);
  647. }
  648. ////////////// manipulation of list elements //////////////////////////////
  649. // For a better overview, the code of the delete- and extract-routine is
  650. // separated for simply and doubly linked lists.
  651. binomial& list_iterator::get_element()
  652. {
  653. return(*(actual->entry));
  654. }
  655. #ifdef DL_LIST
  656. list_iterator& list_iterator::delete_element()
  657. {
  658. binomial* aux1=actual->entry;
  659. element* aux2=actual;
  660. actual->previous->next=actual->next;
  661. actual->next->previous=actual->previous;
  662. actual=actual->next;
  663. delete aux1;
  664. delete aux2;
  665. return *this;
  666. }
  667. list_iterator& list_iterator::extract_element()
  668. {
  669. element* aux=actual;
  670. actual->previous->next=actual->next;
  671. actual->next->previous=actual->previous;
  672. actual=actual->next;
  673. delete aux;
  674. return *this;
  675. }
  676. #endif // DL_LIST
  677. #ifdef SL_LIST
  678. // When deleting or extracting an element of a simply linked list, the
  679. // next-pointer of the previous element cannot be manipulated (is unkonwn!).
  680. // So deletion must be done by copying the next element to the actual position
  681. // and then deleting the original. Notice that only pointers are copies, never
  682. // binomials.
  683. list_iterator& list_iterator::delete_element()
  684. {
  685. binomial* aux1=actual->entry;
  686. element* aux2=actual->next;
  687. actual->done=actual->next->done;
  688. actual->head_reduced=actual->next->head_reduced;
  689. actual->entry=actual->next->entry;
  690. actual->next=actual->next->next;
  691. delete aux1;
  692. delete aux2;
  693. return *this;
  694. }
  695. list_iterator& list_iterator::extract_element()
  696. {
  697. element* aux=actual->next;
  698. actual->done=actual->next->done;
  699. actual->head_reduced=actual->next->head_reduced;
  700. actual->entry=actual->next->entry;
  701. actual->next=actual->next->next;
  702. delete aux;
  703. return *this;
  704. }
  705. #endif // SL_LIST
  706. list_iterator& list_iterator::mark_element_done()
  707. {
  708. actual->done=TRUE;
  709. return *this;
  710. }
  711. list_iterator& list_iterator::mark_element_undone()
  712. {
  713. actual->done=FALSE;
  714. return *this;
  715. }
  716. list_iterator& list_iterator::mark_element_head_reduced()
  717. {
  718. actual->head_reduced=TRUE;
  719. return *this;
  720. }
  721. list_iterator& list_iterator::mark_element_head_unreduced()
  722. {
  723. actual->head_reduced=FALSE;
  724. return *this;
  725. }
  726. #endif // LIST_CC