diff --git a/anabatic/src/anabatic/Dijkstra.h b/anabatic/src/anabatic/Dijkstra.h index 2c6df9b5..9601ef3f 100644 --- a/anabatic/src/anabatic/Dijkstra.h +++ b/anabatic/src/anabatic/Dijkstra.h @@ -497,52 +497,52 @@ namespace Anabatic { public: typedef std::function distance_t; public: - Dijkstra ( AnabaticEngine* ); - ~Dijkstra (); - public: - inline bool isBipoint () const; - inline bool isSourceVertex ( Vertex* ) const; - inline bool isTargetVertex ( Vertex* ) const; - inline DbU::Unit getSearchAreaHalo () const; - template - inline DistanceT* setDistance ( DistanceT ); - inline void setSearchAreaHalo ( DbU::Unit ); - void load ( Net* net ); - void run ( Mode mode=Mode::Standart ); - inline const VertexSet& getSources () const; - private: - Dijkstra ( const Dijkstra& ); - Dijkstra& operator= ( const Dijkstra& ); - static DbU::Unit _distance ( const Vertex*, const Vertex*, const Edge* ); - Point _getPonderedPoint () const; - void _cleanup (); - bool _propagate ( Flags enabledSides ); - void _traceback ( Vertex* ); - void _materialize (); - void _selectFirstSource (); - void _toSources ( Vertex*, int connexId ); - void _getConnecteds ( Vertex*, VertexSet& ); - void _checkEdges () const; - void _createSelfSymSeg ( Segment* ); - - inline void setAxisTarget (); - inline bool needAxisTarget () const; - inline void setFlags ( Flags ); - inline void unsetFlags ( Flags ); - void setAxisTargets (); - void unsetAxisTargets (); - - bool _attachSymContactsHook ( RoutingPad* ); - void _limitSymSearchArea ( RoutingPad* rp ); - void _setSourcesGRAData ( Vertex*, RoutingPad*); - bool _checkFrom2 ( Edge*, Vertex* ); - bool _isDistance2Shorter ( DbU::Unit&, Vertex*, Vertex*, Edge* ); - void _pushEqualDistance ( DbU::Unit, bool, Vertex*, Vertex*, Edge* ); - void _updateGRAData ( Vertex*, bool, Vertex* ); - void _initiateUpdateIntervals ( Vertex* ); - bool _updateIntervals ( bool&, Vertex*, bool&, int&, Edge* ); - void _updateRealOccupancy ( Vertex* ); - + Dijkstra ( AnabaticEngine* ); + ~Dijkstra (); + public: + inline bool isBipoint () const; + inline bool isSourceVertex ( Vertex* ) const; + inline Net* getNet () const; + inline bool isTargetVertex ( Vertex* ) const; + inline DbU::Unit getSearchAreaHalo () const; + template + inline DistanceT* setDistance ( DistanceT ); + inline void setSearchAreaHalo ( DbU::Unit ); + void load ( Net* net ); + void run ( Mode mode=Mode::Standart ); + inline const VertexSet& getSources () const; + private: + Dijkstra ( const Dijkstra& ); + Dijkstra& operator= ( const Dijkstra& ); + static DbU::Unit _distance ( const Vertex*, const Vertex*, const Edge* ); + Point _getPonderedPoint () const; + void _cleanup (); + bool _propagate ( Flags enabledSides ); + void _traceback ( Vertex* ); + void _materialize (); + void _selectFirstSource (); + void _toSources ( Vertex*, int connexId ); + void _getConnecteds ( Vertex*, VertexSet& ); + void _checkEdges () const; + void _createSelfSymSeg ( Segment* ); + + inline void setAxisTarget (); + inline bool needAxisTarget () const; + inline void setFlags ( Flags ); + inline void unsetFlags ( Flags ); + void setAxisTargets (); + void unsetAxisTargets (); + + bool _attachSymContactsHook ( RoutingPad* ); + void _limitSymSearchArea ( RoutingPad* rp ); + void _setSourcesGRAData ( Vertex*, RoutingPad*); + bool _checkFrom2 ( Edge*, Vertex* ); + bool _isDistance2Shorter ( DbU::Unit&, Vertex*, Vertex*, Edge* ); + void _pushEqualDistance ( DbU::Unit, bool, Vertex*, Vertex*, Edge* ); + void _updateGRAData ( Vertex*, bool, Vertex* ); + void _initiateUpdateIntervals ( Vertex* ); + bool _updateIntervals ( bool&, Vertex*, bool&, int&, Edge* ); + void _updateRealOccupancy ( Vertex* ); private: AnabaticEngine* _anabatic; vector _vertexes; @@ -566,6 +566,7 @@ namespace Anabatic { inline bool Dijkstra::isBipoint () const { return _net and (_targets.size()+_sources.size() == 2); } inline bool Dijkstra::isSourceVertex ( Vertex* v ) const { return (_sources.find(v) != _sources.end()); } inline bool Dijkstra::isTargetVertex ( Vertex* v ) const { return (_targets.find(v) != _targets.end()); } + inline Net* Dijkstra::getNet () const { return _net; } inline DbU::Unit Dijkstra::getSearchAreaHalo () const { return _searchAreaHalo; } inline void Dijkstra::setSearchAreaHalo ( DbU::Unit halo ) { _searchAreaHalo = halo; } diff --git a/bootstrap/build.conf b/bootstrap/build.conf index 918a5484..de43eaeb 100644 --- a/bootstrap/build.conf +++ b/bootstrap/build.conf @@ -36,6 +36,7 @@ projects = [ , "cumulus" , "stratus1" , "documentation" + , "unittests" ] , 'repository': 'ssh://asim-t/users/largo2/git/coriolis.git' } ] diff --git a/bora/src/BoraEngine.cpp b/bora/src/BoraEngine.cpp index df6972be..e6816644 100644 --- a/bora/src/BoraEngine.cpp +++ b/bora/src/BoraEngine.cpp @@ -229,7 +229,7 @@ namespace Bora { if ( not (state and state->isSymSlave()) ) { slicingtree->setVertexRestriction( net, katana ); dijkstra->run(); - slicingtree->updateWireOccupation( dijkstra->getSources() ); + slicingtree->updateWireOccupation( dijkstra ); } } katana->setState( Anabatic::EngineState::EngineGlobalLoaded ); diff --git a/bora/src/ChannelRouting.cpp b/bora/src/ChannelRouting.cpp index 9b3c63a8..eff1e744 100644 --- a/bora/src/ChannelRouting.cpp +++ b/bora/src/ChannelRouting.cpp @@ -27,6 +27,7 @@ namespace Bora { ChannelRouting::ChannelRouting () + : _wireIntervals() { } @@ -48,16 +49,13 @@ namespace Bora { void ChannelRouting::reset () { - _limits.clear(); - _counts.clear(); + _wireIntervals.clear(); } int ChannelRouting::getMaxCount () const { - int maxCount = 0; - for ( int count : _counts ) maxCount = std::max( maxCount, count ); - return maxCount; + return _wireIntervals.getThickness(); } @@ -68,92 +66,28 @@ namespace Bora { << DbU::getValueString(xy2) << "] width:" << w << endl; - for ( unsigned int i=0; i _limits.back()) { - _limits.push_back( min ); - _limits.push_back( max ); - _counts.push_back( 0 ); - _counts.push_back( 1 ); - } else { - int index = 0; - vector::iterator itL = _limits.begin(); - vector::iterator itC = _counts.begin(); - - if (min < (*itL)) { - _limits.insert( itL, min ); - _counts.insert( itC, 1 ); - } else { - while( ((*itL) < min) and (itL != _limits.end()) ) { - itL++; - index++; - if (itC != _counts.end()) itC++; - } - - if ((*itL) != min) { - _limits.insert( itL, min ); - _counts.insert( itC, *(itC-1) ); - itL = _limits.begin() + index; - itC = _counts.begin() + index; - } - itL = _limits.begin() + index; - itC = _counts.begin() + index; - - while( ((*itL) < max) && (itL != _limits.end()) ){ - itL++; - index++; - if (itC != _counts.end()) { - (*itC) += 1; - itC++; - } - } - if (itL != _limits.end()) { - if ((*(itL)) > max){ - _limits.insert( itL, max ); - _counts.insert( itC, *(itC-1)-1 ); - } - } else { - if ((*(itL-1)) != max) { - _limits.push_back( max ); - _counts.push_back( 1 ); - } - } - } - } - } + _wireIntervals.insert( WireInterval(net,xy1,xy2) ); } void ChannelRouting::print () const { - cerr << "limits: "; - for ( DbU::Unit limit : _limits ) cerr << DbU::getPhysical(limit,DbU::Micro) << " - "; - cerr << endl; - - cerr << "count: "; - for ( int count : _counts ) cerr << count << " - "; - cerr << endl; + cerr << "Thickness: " << getMaxCount() << endl; + cerr << "Wires:" << endl; + for ( const WireInterval& wire : _wireIntervals.getElements() ) + cerr << "| " << wire << endl; } diff --git a/bora/src/HVSlicingNode.cpp b/bora/src/HVSlicingNode.cpp index c1632929..96dad935 100644 --- a/bora/src/HVSlicingNode.cpp +++ b/bora/src/HVSlicingNode.cpp @@ -1279,12 +1279,12 @@ namespace Bora { } - void HVSlicingNode::updateWireOccupation ( Anabatic::VertexSet sources ) + void HVSlicingNode::updateWireOccupation ( Anabatic::Dijkstra* dijkstra ) { cdebug_log(535,1) << "HVSlicingNode::updateWireOccupation() on " << this << endl; if (not _parent) { - for ( Anabatic::Vertex* vertex : sources ) { + for ( Anabatic::Vertex* vertex : dijkstra->getSources() ) { cdebug_log(535,0) << "> " << vertex << endl; Anabatic::GCell* gcell = vertex->getGCell(); @@ -1294,7 +1294,7 @@ namespace Bora { cdebug_log(535,0) << "| isRouting():" << snode->isRouting() << endl; if (snode->isRouting() and vertex->hasAData() ) - snode->addWireOccupation( vertex->getIMin(), vertex->getIMax() ); + snode->addWireOccupation( vertex->getIMin(), vertex->getIMax(), dijkstra->getNet() ); } } } diff --git a/bora/src/RHVSlicingNode.cpp b/bora/src/RHVSlicingNode.cpp index 89cec408..f6ca6cb8 100644 --- a/bora/src/RHVSlicingNode.cpp +++ b/bora/src/RHVSlicingNode.cpp @@ -175,8 +175,8 @@ namespace Bora { } - void RHVSlicingNode::addWireOccupation ( DbU::Unit min, DbU::Unit max ) - { if ( _wireOccupation and (min != max) ) _wireOccupation->insertChannel(min, max); } + void RHVSlicingNode::addWireOccupation ( DbU::Unit min, DbU::Unit max, Net* net ) + { if ( _wireOccupation and (min != max) ) _wireOccupation->insertChannel(min, max, net); } void RHVSlicingNode::resetWireOccupation () diff --git a/bora/src/SlicingNode.cpp b/bora/src/SlicingNode.cpp index 2813f004..a76042c7 100644 --- a/bora/src/SlicingNode.cpp +++ b/bora/src/SlicingNode.cpp @@ -871,7 +871,7 @@ namespace Bora { { cerr << Error( "SlicingNode::updateMatrixGContacts(): Base class method must never be called." ) << endl; } - void SlicingNode::addWireOccupation ( DbU::Unit , DbU::Unit ) + void SlicingNode::addWireOccupation ( DbU::Unit , DbU::Unit, Net* ) { cerr << Error( "SlicingNode::addWireOccupation(): Base class method must never be called." ) << endl; } @@ -1158,7 +1158,7 @@ namespace Bora { { cerr << Error( "SlicingNode::flattenDigitalNets(): Base class method must never be called." ) << endl; } - void SlicingNode::updateWireOccupation ( Anabatic::VertexSet ) + void SlicingNode::updateWireOccupation ( Anabatic::Dijkstra* ) { cerr << Error( "SlicingNode::updateWireOccupation(): Base class method must never be called." ) << endl; } diff --git a/bora/src/bora/ChannelRouting.h b/bora/src/bora/ChannelRouting.h index 56fb6ba3..c19be6e8 100644 --- a/bora/src/bora/ChannelRouting.h +++ b/bora/src/bora/ChannelRouting.h @@ -18,12 +18,17 @@ #define BORA_CHANNEL_ROUTING_H -#include "hurricane/DbU.h" - +#include "hurricane/IntervalTree.h" +namespace Hurricane { + class Net; +} namespace Bora { using Hurricane::DbU; + using Hurricane::IntervalData; + using Hurricane::IntervalTree; + using Hurricane::Net; // ------------------------------------------------------------------- @@ -32,6 +37,9 @@ namespace Bora { class ChannelRouting { + private: + typedef IntervalData WireInterval; + typedef IntervalTree WireIntervals; private: ChannelRouting (); ~ChannelRouting (); @@ -39,13 +47,12 @@ namespace Bora { static ChannelRouting* create (); void destroy (); int getMaxCount () const; - void insertChannel ( DbU::Unit xy1, DbU::Unit xy2 ); + void insertChannel ( DbU::Unit xy1, DbU::Unit xy2, Net* ); void insertChannel ( DbU::Unit xy1, DbU::Unit xy2, unsigned int w ); void reset (); void print () const; private: - std::vector _limits; - std::vector _counts; + WireIntervals _wireIntervals; }; diff --git a/bora/src/bora/HVSlicingNode.h b/bora/src/bora/HVSlicingNode.h index c66b5a53..bd9d8572 100644 --- a/bora/src/bora/HVSlicingNode.h +++ b/bora/src/bora/HVSlicingNode.h @@ -145,7 +145,7 @@ namespace Bora { void updateSymNetAxis (); void flattenDigitalNets (); - void updateWireOccupation ( Anabatic::VertexSet ); + void updateWireOccupation ( Anabatic::Dijkstra* ); void resetWireOccupation (); protected: VSlicingNodes _children; diff --git a/bora/src/bora/RHVSlicingNode.h b/bora/src/bora/RHVSlicingNode.h index 825d0cb1..6072931a 100644 --- a/bora/src/bora/RHVSlicingNode.h +++ b/bora/src/bora/RHVSlicingNode.h @@ -56,7 +56,7 @@ namespace Bora { void _place ( DbU::Unit x=0, DbU::Unit y=0, bool replace=false ); void setRailInstance ( Hurricane::Instance* i ); inline Hurricane::Instance* getRailInstance () const ; - void addWireOccupation ( DbU::Unit min, DbU::Unit max ); + void addWireOccupation ( DbU::Unit min, DbU::Unit max, Net* ); void resetWireOccupation (); int getMaxWireOccupation (); protected: diff --git a/bora/src/bora/SlicingNode.h b/bora/src/bora/SlicingNode.h index d8d1c4b2..77c1ca67 100644 --- a/bora/src/bora/SlicingNode.h +++ b/bora/src/bora/SlicingNode.h @@ -287,9 +287,9 @@ namespace Bora { static bool isRailSegments ( Hurricane::Plug* ); void createRailCell (); virtual void flattenDigitalNets (); - virtual void updateWireOccupation ( Anabatic::VertexSet ); + virtual void updateWireOccupation ( Anabatic::Dijkstra* ); virtual void resetWireOccupation (); - virtual void addWireOccupation ( DbU::Unit min, DbU::Unit max ); + virtual void addWireOccupation ( DbU::Unit min, DbU::Unit max, Net* ); virtual int getMaxWireOccupation (); protected: static CRL::RoutingGauge* _rg; diff --git a/hurricane/src/hurricane/CMakeLists.txt b/hurricane/src/hurricane/CMakeLists.txt index d47de7eb..dbbddbcf 100644 --- a/hurricane/src/hurricane/CMakeLists.txt +++ b/hurricane/src/hurricane/CMakeLists.txt @@ -49,6 +49,8 @@ hurricane/Interval.h hurricane/Intervals.h hurricane/IntrusiveMap.h hurricane/IntrusiveSet.h + hurricane/RbTree.h + hurricane/IntervalTree.h hurricane/Layer.h hurricane/Layers.h hurricane/Libraries.h hurricane/Library.h hurricane/ListCollection.h diff --git a/hurricane/src/hurricane/Interval.cpp b/hurricane/src/hurricane/Interval.cpp index 48792861..cd338d5a 100644 --- a/hurricane/src/hurricane/Interval.cpp +++ b/hurricane/src/hurricane/Interval.cpp @@ -105,17 +105,20 @@ bool Interval::contains(const Interval& interval) const return !isEmpty() && !interval.isEmpty() && (_vMin <= interval._vMin) && (interval._vMax <= _vMax); } -bool Interval::intersect(const Interval& interval) const -// ***************************************************** +bool Interval::intersect(const Interval& interval, bool strict) const +// ****************************************************************** { - return !isEmpty() && !interval.isEmpty() && !((_vMax < interval._vMin) || (interval._vMax < _vMin)); + if (isEmpty() or interval.isEmpty()) return false; + if ( (_vMax < interval._vMin) or (interval._vMax < _vMin) ) return false; + + return not strict or ( (_vMax != interval._vMin) and (interval._vMax != _vMin) ); } bool Interval::inferior(const Interval& interval, bool strict) const // ***************************************************************** { if (_vMax < interval._vMin) return true; - return !strict && (_vMax == interval._vMin); + return not strict and (_vMax == interval._vMin); } bool Interval::superior(const Interval& interval, bool strict) const @@ -234,8 +237,8 @@ string Interval::_getString() const // ******************************** { if ( isEmpty() ) - return "<" + _TName("Interval") + " (empty) " + DbU::getValueString(_vMin) + " " + DbU::getValueString(_vMax) + ">"; - return "<" + _TName("Interval") + " " + DbU::getValueString(_vMin) + " " + DbU::getValueString(_vMax) + ">"; + return "[empty " + DbU::getValueString(_vMin) + " " + DbU::getValueString(_vMax) + "]"; + return "[" + DbU::getValueString(_vMin) + " " + DbU::getValueString(_vMax) + "]"; } Record* Interval::_getRecord() const diff --git a/hurricane/src/hurricane/Record.cpp b/hurricane/src/hurricane/Record.cpp index e7f1212f..76dcaf03 100644 --- a/hurricane/src/hurricane/Record.cpp +++ b/hurricane/src/hurricane/Record.cpp @@ -19,12 +19,7 @@ // License along with Hurricane. If not, see // . // -// =================================================================== -// -// $Id$ -// -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | // | | @@ -32,10 +27,7 @@ // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./Record.cpp" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x +// +-----------------------------------------------------------------+ #include "hurricane/Commons.h" diff --git a/hurricane/src/hurricane/hurricane/Interval.h b/hurricane/src/hurricane/hurricane/Interval.h index 27c69f5e..fdaea5bf 100644 --- a/hurricane/src/hurricane/hurricane/Interval.h +++ b/hurricane/src/hurricane/hurricane/Interval.h @@ -1,109 +1,112 @@ -// **************************************************************************************************** -// File: ./hurricane/Interval.h -// Authors: R. Escassut +// -*- C++ -*- +// // Copyright (c) BULL S.A. 2000-2018, All Rights Reserved // // This file is part of Hurricane. // -// Hurricane is free software: you can redistribute it and/or modify it under the terms of the GNU -// Lesser General Public License as published by the Free Software Foundation, either version 3 of the +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // -// Hurricane 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 Lesser GNU +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU // General Public License for more details. // -// You should have received a copy of the Lesser GNU General Public License along with Hurricane. If -// not, see . -// **************************************************************************************************** +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Rémy Escassut | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/Interval.h" | +// +-----------------------------------------------------------------+ -#ifndef HURRICANE_INTERVAL -#define HURRICANE_INTERVAL + +#ifndef HURRICANE_INTERVAL_H +#define HURRICANE_INTERVAL_H #include "hurricane/DbU.h" namespace Hurricane { +// ------------------------------------------------------------------- +// Class : "Hurricane::Interval". -// **************************************************************************************************** -// Interval declaration -// **************************************************************************************************** -class Interval { -// *********** + class Interval { + public: + class CompareByMin { + public: + inline bool operator() ( const Interval& rhs, const Interval& lhs ) const; + inline bool operator() ( const Interval* rhs, const Interval* lhs ) const; + }; + public: + Interval ( bool makeEmpty=true ); + Interval ( const DbU::Unit& ); + Interval ( const DbU::Unit& v1, const DbU::Unit& v2 ); + Interval ( const Interval& ); + public: + Interval& operator= ( const Interval& ); + bool operator== ( const Interval& ) const; + bool operator!= ( const Interval& ) const; + public: + inline const DbU::Unit& getVMin () const; + inline const DbU::Unit& getVMax () const; + inline DbU::Unit& getVMin (); + inline DbU::Unit& getVMax (); + inline DbU::Unit getCenter () const; + inline DbU::Unit getSize () const; + inline DbU::Unit getHalfSize () const; + Interval getUnion ( const Interval& ) const; + Interval getIntersection ( const Interval& ) const; + inline bool isEmpty () const; + inline bool isFull () const; + inline bool isPonctual () const; + bool contains ( const DbU::Unit& ) const; + bool contains ( const Interval& ) const; + bool intersect ( const Interval& , bool strict=false ) const; + bool inferior ( const Interval& , bool strict=true ) const; + bool superior ( const Interval& , bool strict=true ) const; + bool isConstrainedBy ( const Interval& ) const; + public: + Interval& makeEmpty (); + Interval& shrinkVMin ( const DbU::Unit& vMin ); + Interval& shrinkVMax ( const DbU::Unit& vMax ); + Interval& inflate ( const DbU::Unit& dv ); + Interval& inflate ( const DbU::Unit& dvMin, const DbU::Unit& dvMax ); + Interval& merge ( const DbU::Unit& ); + Interval& merge ( const Interval& ); + Interval& intersection ( const DbU::Unit& vMin, const DbU::Unit& vMax ); + Interval& intersection ( const Interval& ); + Interval& translate ( const DbU::Unit& ); + public: + inline string _getTypeName () const; + string _getString () const; + Record* _getRecord () const; + private: + DbU::Unit _vMin; + DbU::Unit _vMax; + }; -// Attributes -// ********** - - private: DbU::Unit _vMin; - private: DbU::Unit _vMax; - -// Constructors -// ************ - - public: Interval(bool makeEmpty=true); - public: Interval(const DbU::Unit& v); - public: Interval(const DbU::Unit& v1, const DbU::Unit& v2); - public: Interval(const Interval& interval); - -// Operators -// ********* - - public: Interval& operator=(const Interval& interval); - - public: bool operator==(const Interval& interval) const; - public: bool operator!=(const Interval& interval) const; - -// Accessors -// ********* - - public: const DbU::Unit& getVMin() const {return _vMin;}; - public: const DbU::Unit& getVMax() const {return _vMax;}; - public: DbU::Unit& getVMin() {return _vMin;}; - public: DbU::Unit& getVMax() {return _vMax;}; - public: DbU::Unit getCenter() const {return ((_vMin + _vMax) / 2);}; - public: DbU::Unit getSize() const; - public: DbU::Unit getHalfSize() const {return (getSize() / 2);}; - public: Interval getUnion(const Interval& interval) const; - public: Interval getIntersection(const Interval& interval) const; - -// Predicates -// ********** - - public: bool isEmpty() const { return (_vMax < _vMin);}; - public: bool isFull() const { return (_vMin == DbU::Min) and (_vMax == DbU::Max); }; - public: bool isPonctual() const { return (_vMax == _vMin);}; - public: bool contains(const DbU::Unit& v) const; - public: bool contains(const Interval& interval) const; - public: bool intersect(const Interval& interval) const; - public: bool inferior(const Interval& interval, bool strict=true) const; - public: bool superior(const Interval& interval, bool strict=true) const; - public: bool isConstrainedBy(const Interval& interval) const; - -// Updators -// ******** - - public: Interval& makeEmpty(); - public: Interval& shrinkVMin(const DbU::Unit& vMin); - public: Interval& shrinkVMax(const DbU::Unit& vMax); - public: Interval& inflate(const DbU::Unit& dv); - public: Interval& inflate(const DbU::Unit& dvMin, const DbU::Unit& dvMax); - public: Interval& merge(const DbU::Unit& v); - public: Interval& merge(const Interval& interval); - public: Interval& intersection(const DbU::Unit& vMin, const DbU::Unit& vMax); - public: Interval& intersection(const Interval& interval); - public: Interval& translate(const DbU::Unit& dv); - -// Others -// ****** - - public: string _getTypeName() const { return _TName("Interval"); }; - public: string _getString() const; - public: Record* _getRecord() const; - -}; + inline const DbU::Unit& Interval::getVMin () const {return _vMin;}; + inline const DbU::Unit& Interval::getVMax () const {return _vMax;}; + inline DbU::Unit& Interval::getVMin () {return _vMin;}; + inline DbU::Unit& Interval::getVMax () {return _vMax;}; + inline DbU::Unit Interval::getCenter () const {return ((_vMin + _vMax) / 2);}; + inline DbU::Unit Interval::getHalfSize () const {return (getSize() / 2);}; + inline bool Interval::isEmpty () const { return (_vMax < _vMin);}; + inline bool Interval::isFull () const { return (_vMin == DbU::Min) and (_vMax == DbU::Max); }; + inline bool Interval::isPonctual () const { return (_vMax == _vMin);}; + inline string Interval::_getTypeName () const { return _TName("Interval"); }; inline DbU::Unit Interval::getSize () const { @@ -113,8 +116,15 @@ class Interval { } + inline bool Interval::CompareByMin::operator() ( const Interval& lhs, const Interval& rhs ) const + { return lhs.getVMin() < rhs.getVMin(); } -} // End of Hurricane namespace. + + inline bool Interval::CompareByMin::operator() ( const Interval* lhs, const Interval* rhs ) const + { return lhs->getVMin() < rhs->getVMin(); } + + +} // Hurricane namespace. inline void jsonWrite ( JsonWriter* w, const std::string& key, const Hurricane::Interval* interval ) @@ -129,9 +139,4 @@ inline void jsonWrite ( JsonWriter* w, const std::string& key, const Hurricane: INSPECTOR_PV_SUPPORT(Hurricane::Interval); -#endif // HURRICANE_INTERVAL - - -// **************************************************************************************************** -// Copyright (c) BULL S.A. 2000-2018, All Rights Reserved -// **************************************************************************************************** +#endif // HURRICANE_INTERVAL_H diff --git a/hurricane/src/hurricane/hurricane/IntervalTree.h b/hurricane/src/hurricane/hurricane/IntervalTree.h new file mode 100644 index 00000000..b026cbf0 --- /dev/null +++ b/hurricane/src/hurricane/hurricane/IntervalTree.h @@ -0,0 +1,415 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2018-2018, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/IntervalTree.h" | +// +-----------------------------------------------------------------+ +// +// References: +// 1. Wikipedia, https://en.wikipedia.org/wiki/Red-black_tree +// 2. Introduction to Algorithms, Cormen & Al, +// Third edition, MIT press, 2011, p. 348. + + +#ifndef HURRICANE_INTERVAL_TREE_H +#define HURRICANE_INTERVAL_TREE_H + +#include "hurricane/Interval.h" +#include "hurricane/RbTree.h" + +namespace Hurricane { + + +// ------------------------------------------------------------------- +// Class : "Hurricane::IntervalData". + + + template< typename Data > + class IntervalData : public Interval { + public: + inline IntervalData (); + inline IntervalData ( const Data&, DbU::Unit vmin, DbU::Unit vmax ); + inline Data& getData () const; + inline DbU::Unit getChildsVMax () const; + inline DbU::Unit updateChildsVMax ( DbU::Unit lvmax, DbU::Unit rvmax ); + string _getString () const; + Record* _getRecord () const; + private: + DbU::Unit childsVMax_; + Data data_; + }; + + + template< typename Data > + inline IntervalData::IntervalData () + : Interval(1,-1) + , childsVMax_(0) + , data_ () + { } + + + template< typename Data > + inline IntervalData::IntervalData ( const Data& data, DbU::Unit vmin, DbU::Unit vmax ) + : Interval(vmin,vmax) + , childsVMax_(vmax) + , data_ (data) + { } + + + template< typename Data > + inline Data& IntervalData::getData () const + { return const_cast< IntervalData* >( this )->data_; } + + + template< typename Data > + inline DbU::Unit IntervalData::getChildsVMax () const + { return childsVMax_; } + + + template< typename Data > + inline DbU::Unit IntervalData::updateChildsVMax ( DbU::Unit lvmax, DbU::Unit rvmax ) + { childsVMax_ = std::max( getVMax(), std::max( lvmax, rvmax ) ); return childsVMax_; } + + + template< typename Data > + std::string IntervalData::_getString () const + { + string s = Interval::_getString(); + s.insert( s.size(), " max:"+DbU::getValueString(childsVMax_) ); + s.insert( s.size(), " v:"+getString(data_) ); + return s; + } + + + template< typename Data > + Record* IntervalData::_getRecord () const + { + Record* record = Interval::_getRecord(); + if (record) { + record->add(DbU::getValueSlot("childsVMax_", &childsVMax_)); + record->add(getSlot ("data_" , &data_ )); + } + return record; + } + +// ------------------------------------------------------------------- +// Class : "Hurricane::IntervalTree". + + + template< typename Data > + class IntervalTree : public RbTree< IntervalData, Interval::CompareByMin > { + public: + typedef RbTree< IntervalData, Interval::CompareByMin > Super; + public: + class overlap_iterator : public Super::iterator { + public: + friend class IntervalTree; + private: + inline overlap_iterator ( const typename Super::Node*, const Interval& ); + public: + virtual overlap_iterator& operator++ (); + private: + Interval overlap_; + }; + public: + class OverlapElements : public Collection< IntervalData > { + public: + // Sub-Class: Locator. + class Locator : public Hurricane::Locator< IntervalData > { + public: + Locator ( const IntervalTree&, const Interval& span ); + inline Locator ( const Locator& ); + virtual IntervalData getElement () const; + virtual Locator* getClone () const; + virtual bool isValid () const; + virtual void progress (); + virtual string _getString () const; + protected: + overlap_iterator iterator_; + }; + public: + // Class Elements. + inline OverlapElements ( const IntervalTree&, const Interval& ); + inline OverlapElements ( const OverlapElements& ); + virtual Collection< IntervalData >* getClone () const; + virtual Locator* getLocator () const; + virtual string _getString () const; + protected: + const IntervalTree& tree_; + const Interval span_; + }; + public: + virtual void postRotateLeft ( typename Super::Node* ); + virtual void postRotateRight ( typename Super::Node* ); + virtual void postInsert ( typename Super::Node* ); + virtual void postRemove ( typename Super::Node* ); + size_t getThickness () const; + overlap_iterator beginOverlaps ( const Interval& ) const; + inline OverlapElements getOverlaps ( const Interval& ) const; + private: + inline void updateChildsVMax ( typename Super::Node* ); + }; + + + template< typename Data > + IntervalTree::overlap_iterator::overlap_iterator ( const typename Super::Node* node, const Interval& overlap ) + : Super::iterator(node) + , overlap_(overlap) + { } + + + template< typename Data > + typename IntervalTree::overlap_iterator& IntervalTree::overlap_iterator::operator++ () + { + while (this->isValid()) { + Super::iterator::operator++(); + + cdebug_log(0,0) << "IntervalTree::overlap_iterator::operator++() " + << ::getString(this->getNode()) << std::endl; + + if (this->getNode()->getValue().intersect(overlap_,true)) break; + cdebug_log(0,0) << "NO intersections" << endl; + if (overlap_.inferior(this->getNode()->getValue(),true)) { + cdebug_log(0,0) << "Node is inferior, stop here." << endl; + this->setNode( NULL ); + break; + } + } + return *this; + } + + +// ------------------------------------------------------------------- +// Class : "Hurricane::IntervalTree::OverlapOverlapElements" (implementation) + + + template< typename Data > + inline IntervalTree::OverlapElements::Locator::Locator ( const Locator &locator ) + : Hurricane::Locator< IntervalData >() + , iterator_(locator.iterator_) + { } + + + template< typename Data > + IntervalTree::OverlapElements::Locator::Locator ( const IntervalTree& tree, const Interval& span ) + : Hurricane::Locator< IntervalData >() + , iterator_(tree.beginOverlaps(span)) + { } + + + template< typename Data > + typename IntervalTree::OverlapElements::Locator* IntervalTree::OverlapElements::Locator::getClone () const + { return new Locator(*this); } + + + template< typename Data > + IntervalData IntervalTree::OverlapElements::Locator::getElement () const + { return (*iterator_); } + + + template< typename Data > + bool IntervalTree::OverlapElements::Locator::isValid () const + { return iterator_.isValid(); } + + + template< typename Data > + void IntervalTree::OverlapElements::Locator::progress () + { + if (isValid()) ++iterator_; + } + + + template< typename Data > + std::string IntervalTree::OverlapElements::Locator::_getString () const + { + std::string s = "<" + _TName("OverlapElements::Locator") + + ">"; + return s; + } + + + template< typename Data > + inline IntervalTree::OverlapElements::OverlapElements ( const IntervalTree& tree, const Interval& span ) + : Collection< IntervalData >() + , tree_(tree) + , span_(span) + { } + + + template< typename Data > + inline IntervalTree::OverlapElements::OverlapElements ( const OverlapElements& elements ) + : Collection< IntervalData >() + , tree_(elements.tree_) + , span_(elements.span_) + { } + + + template< typename Data > + Collection< IntervalData >* IntervalTree::OverlapElements::getClone () const + { return new OverlapElements(*this); } + + + template< typename Data > + typename IntervalTree::OverlapElements::Locator* IntervalTree::OverlapElements::getLocator () const + { return new Locator( tree_, span_ ); } + + + template< typename Data > + std::string IntervalTree::OverlapElements::_getString () const + { + std::string s = "<" + _TName("OverlapElements") + " " + + getString(tree_) + + ">"; + return s; + } + + +// ------------------------------------------------------------------- +// Class : "Hurricane::IntervalTree" (implementation). + + + template< typename Data > + inline void IntervalTree::updateChildsVMax ( typename Super::Node* node ) + { + DbU::Unit lchildVMax = (node->getLeft ()) ? node->getLeft ()->getValue().getChildsVMax() : node->getValue().getVMax(); + DbU::Unit rchildVMax = (node->getRight()) ? node->getRight()->getValue().getChildsVMax() : node->getValue().getVMax(); + + const_cast< IntervalData& >( node->getValue() ).updateChildsVMax( lchildVMax, rchildVMax ); + } + + + template< typename Data > + void IntervalTree::postRotateLeft ( typename Super::Node* node ) + { + updateChildsVMax( node ); + if (node->getParent()) updateChildsVMax( node->getParent() ); + } + + + template< typename Data > + void IntervalTree::postRotateRight ( typename Super::Node* node ) + { + updateChildsVMax( node ); + if (node->getParent()) updateChildsVMax( node->getParent() ); + } + + + template< typename Data > + void IntervalTree::postInsert ( typename Super::Node* node ) + { + cdebug_log(0,1) << "IntervalTree::postInsert() " << node << std::endl; + + while ( node ) { + cdebug_log(0,0) << "| " << node << std::endl; + + updateChildsVMax( node ); + node = node->getParent(); + } + + cdebug_tabw(0,-1); + } + + + template< typename Data > + void IntervalTree::postRemove ( typename Super::Node* node ) + { + typename Super::Node* parent = node->getParent(); + if (parent) { + typename Super::Node* child = NULL; + + if (parent->hasLeftChild(node)) child = parent->getRight(); + else child = parent->getLeft (); + + DbU::Unit childVMax = (child) ? child->getValue().getChildsVMax() : parent->getValue().getVMax(); + const_cast< IntervalData& >( parent->getValue() ).updateChildsVMax( childVMax, childVMax ); + + postInsert( parent->getParent() ); + } + } + + + template< typename Data > + size_t IntervalTree::getThickness () const + { + cdebug_log(0,0) << "IntervalTree::getThickness() " << std::endl; + + vector intervalMaxes; + for ( const Interval& interval : *this ) { + intervalMaxes.push_back( interval.getVMax() ); + } + std::sort( intervalMaxes.begin(), intervalMaxes.end() ); + + size_t maxThickness = 0; + size_t curThickness = 0; + size_t iMax = 0; + for ( const Interval& interval : *this ) { + while ( (iMax < intervalMaxes.size()) and (intervalMaxes[iMax] <= interval.getVMin()) ) { + --curThickness; + cdebug_log(0,0) << "| end:" << intervalMaxes[iMax] << " thickness:" << curThickness << endl; + ++iMax; + } + + maxThickness = std::max( maxThickness, ++curThickness ); + cdebug_log(0,0) << "| begin:" << interval << " thickness:" << curThickness << endl; + } + + return maxThickness; + } + + + template< typename Data > + typename IntervalTree::overlap_iterator IntervalTree::beginOverlaps ( const Interval& overlap ) const + { + cdebug_log(0,0) << "IntervalTree::beginOverlaps() " << overlap << std::endl; + + const typename Super::Node* current = this->getRoot(); + const typename Super::Node* leftMost = NULL; + while ( current ) { + cdebug_log(0,0) << "| " << ::getString(current) << endl; + + if (current->getValue().intersect(overlap)) leftMost = current; + if ( current->getLeft() + and (overlap.getVMin() < current->getLeft()->getValue().getChildsVMax()) ) + current = current->getLeft(); + else + current = current->getRight(); + } + return overlap_iterator( leftMost, overlap ); + } + + + template< typename Data > + typename IntervalTree::OverlapElements IntervalTree::getOverlaps ( const Interval& overlap ) const + { + cdebug_log(0,0) << "IntervalTree::getOverlaps() " << overlap << std::endl; + return OverlapElements( *this, overlap ); + } + + + +} // HUrricane namespace. + +#endif // HURRICANE_INTERVAL_TREE_H diff --git a/hurricane/src/hurricane/hurricane/RbTree.h b/hurricane/src/hurricane/hurricane/RbTree.h new file mode 100644 index 00000000..5e527a6e --- /dev/null +++ b/hurricane/src/hurricane/hurricane/RbTree.h @@ -0,0 +1,1036 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2018-2018, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/RbTree.h" | +// +-----------------------------------------------------------------+ +// +// References: +// 1. Wikipedia, https://en.wikipedia.org/wiki/Red-black_tree +// 2. Introduction to Algorithms, Cormen & Al, +// Third edition, MIT press, 2011, p. 308. + + +#ifndef HURRICANE_RBTREE_H +#define HURRICANE_RBTREE_H + +#include +#include +#include +#include "hurricane/Error.h" +#include "hurricane/Collection.h" + + +namespace Hurricane { + + +// ------------------------------------------------------------------- +// Class : "Hurricane::RbTree". + + template< typename Data, typename Compare=std::less > + class RbTree { + public: + typedef Data DataType; + typedef Compare CompareType; + public: + static const long NoFlags = 0; + static const long Black = (1<< 0); + static const long GoRight = (1<< 1); + public: + class Node { + public: + inline Node ( const Data& value, Node* parent ); + inline ~Node (); + inline bool isRed () const; + inline bool isBlack () const; + inline bool isRoot () const; + inline bool isLeaf () const; + inline bool hasLeftChild ( const Node* ) const; + inline bool hasRightChild ( const Node* ) const; + inline const Data& getValue () const; + inline Node* getLeft () const; + inline Node* getRight () const; + inline Node* getParent () const; + inline Node* getGrandParent () const; + inline Node* getSibling () const; + inline Node* getUncle () const; + inline Node* getMin () const; + inline Node* getMax () const; + inline long getFlags () const; + inline void setLeft ( Node* ); + inline void setRight ( Node* ); + inline void setParent ( Node* ); + inline void setFlags ( long ); + inline void resetFlags ( long ); + inline void setRed (); + inline void setBlack (); + inline void copyColor ( Node* ); + void updateEdge ( Node* oldChild, Node* newChild ); + void clear (); + inline void copy ( const Node* ); + virtual std::string _getString () const; + virtual Record* _getRecord () const; + private: + Data value_; + long flags_; + Node* parent_; + Node* left_; + Node* right_; + }; + public: + class iterator { + friend class RbTree; + protected: + inline iterator ( const Node* ); + public: + virtual iterator& operator++ (); + inline bool operator== ( const iterator& ) const; + inline bool operator!= ( const iterator& ) const; + inline const Data& operator* () const; + inline bool isValid () const; + inline const Node* getNode () const; + inline void setNode ( const Node* ); + private: + const Node* node_; + }; + public: + class Elements : public Collection { + public: + // Sub-Class: Locator. + class Locator : public Hurricane::Locator { + public: + Locator ( const RbTree& ); + inline Locator ( const Locator& ); + virtual Data getElement () const; + virtual Locator* getClone () const; + virtual bool isValid () const; + virtual void progress (); + virtual string _getString () const; + protected: + iterator iterator_; + }; + public: + // Class Elements. + inline Elements ( const RbTree& ); + inline Elements ( const Elements& ); + virtual Collection* getClone () const; + virtual Locator* getLocator () const; + virtual string _getString () const; + protected: + const RbTree& tree_; + }; + public: + RbTree (); + ~RbTree (); + void rotateLeft ( Node* ); + void rotateRight ( Node* ); + virtual void postRotateLeft ( Node* ); + virtual void postRotateRight ( Node* ); + iterator find ( const Data& value ); + void insert ( const Data& value ); + void remove ( const Data& value ); + virtual void postInsert ( Node* ); + virtual void postRemove ( Node* ); + inline size_t size () const; + inline bool empty () const; + inline iterator begin () const; + inline iterator end () const; + iterator lower_bound ( const Data& value ) const; + iterator upper_bound ( const Data& value ) const; + inline Elements getElements () const; + inline void write ( std::string ) const; + inline void clear (); + virtual std::string _getTypeName () const; + virtual std::string _getString () const; + virtual Record* _getRecord () const; + friend std::ostream& operator<< ( std::ostream& o, const Node* node ) + { + if (node) { + o << "getValue()) << " "; + o << ((node->isBlack ()) ? "B" : "R"); + o << ((node->getLeft ()) ? "l" : "-"); + o << ((node->getRight()) ? "r" : "-"); + o << ">"; + } else + o << ""; + return o; + } + public: + inline Node* getRoot () const; + private: + void insertRecurse ( Node* ); + void insertRepair ( Node*, size_t rdepth ); + void removeRepair ( Node*, size_t rdepth ); + private: + size_t count_; + Node* root_; + Compare compare_; + }; + + +// ------------------------------------------------------------------- +// Class : "Hurricane::RbTree::Node". + + + template< typename Data, typename Compare > + inline RbTree::Node::Node ( const Data& value, Node* parent ) + : value_ (value) + , flags_ (NoFlags) + , parent_(parent) + , left_ (NULL) + , right_ (NULL) + { } + + template< typename Data, typename Compare > + inline RbTree::Node::~Node () + { } + + template< typename Data, typename Compare >inline bool RbTree::Node::isRed () const { return not isBlack(); } + template< typename Data, typename Compare >inline bool RbTree::Node::isBlack () const { return (flags_ & RbTree::Black); } + template< typename Data, typename Compare >inline bool RbTree::Node::isRoot () const { return not parent_; } + template< typename Data, typename Compare >inline bool RbTree::Node::isLeaf () const { return not left_ and not right_; } + template< typename Data, typename Compare >inline bool RbTree::Node::hasLeftChild ( const Node* child ) const { return (left_ == child); } + template< typename Data, typename Compare >inline bool RbTree::Node::hasRightChild ( const Node* child ) const { return (right_ == child); } + template< typename Data, typename Compare >inline const Data& RbTree::Node::getValue () const { return value_; } + template< typename Data, typename Compare >inline long RbTree::Node::getFlags () const { return flags_; } + template< typename Data, typename Compare >inline void RbTree::Node::setLeft ( Node* node ) { left_ = node; if (node) node->setParent( this ); } + template< typename Data, typename Compare >inline void RbTree::Node::setRight ( Node* node ) { right_ = node; if (node) node->setParent( this ); } + template< typename Data, typename Compare >inline void RbTree::Node::setParent ( Node* node ) { parent_ = node; } + template< typename Data, typename Compare >inline void RbTree::Node::setFlags ( long flags ) { flags_ |= flags; } + template< typename Data, typename Compare >inline void RbTree::Node::resetFlags ( long flags ) { flags_ &= ~flags; } + template< typename Data, typename Compare >inline void RbTree::Node::setRed () { resetFlags( RbTree::Black ); } + template< typename Data, typename Compare >inline void RbTree::Node::setBlack () { setFlags( RbTree::Black ); } + + + template< typename Data, typename Compare > + inline typename RbTree::Node* RbTree::Node::getLeft () const + { return left_; } + + + template< typename Data, typename Compare > + inline typename RbTree::Node* RbTree::Node::getRight () const + { return right_; } + + + template< typename Data, typename Compare > + inline typename RbTree::Node* RbTree::Node::getParent () const + { return parent_; } + + + template< typename Data, typename Compare > + inline typename RbTree::Node* RbTree::Node::getGrandParent () const + { return (parent_) ? parent_->parent_ : NULL; } + + + template< typename Data, typename Compare > + inline typename RbTree::Node* RbTree::Node::getSibling () const + { + if (not parent_) return NULL; + return (parent_->getLeft() == this) ? parent_->getRight() : parent_->getLeft(); + } + + + template< typename Data, typename Compare > + inline typename RbTree::Node* RbTree::Node::getUncle () const + { + if (not getParent()) return NULL; + return getParent()->getSibling(); + } + + + template< typename Data, typename Compare > + inline typename RbTree::Node* RbTree::Node::getMin () const + { + if (not getLeft()) return NULL; + + Node* left = getLeft(); + while ( left->getLeft() ) left = left->getLeft(); + return left; + } + + + template< typename Data, typename Compare > + inline typename RbTree::Node* RbTree::Node::getMax () const + { + if (not getRight()) return NULL; + + Node* right = getRight(); + while ( right->getRight() ) right = right->getRight(); + return right; + } + + + template< typename Data, typename Compare > + inline void RbTree::Node::copy ( const Node* other ) + { value_ = other->value_; } + + + template< typename Data, typename Compare > + inline void RbTree::Node::copyColor ( Node* node ) + { resetFlags( RbTree::Black ); setFlags( node->getFlags() & RbTree::Black ); } + + + template< typename Data, typename Compare > + void RbTree::Node::updateEdge ( Node* oldChild, Node* newChild ) + { + if (left_ == oldChild) { left_ = newChild; return; } + if (right_ == oldChild) { right_ = newChild; } + } + + + template< typename Data, typename Compare > + void RbTree::Node::clear () + { + if (left_ ) left_ ->clear(); + if (right_) right_->clear(); + delete this; + } + + + template< typename Data, typename Compare > + std::string RbTree::Node::_getString () const + { return "::Node " + getString(getValue()) + ">"; } + + + template< typename Data, typename Compare > + Record* RbTree::Node::_getRecord () const + { + Record* record = new Record( getString(this) ); + record->add(getSlot( "value_" , &value_ )); + record->add(getSlot( "flags_" , flags_ )); + record->add(getSlot( "parent_", parent_ )); + record->add(getSlot( "left_" , left_ )); + record->add(getSlot( "right_" , right_ )); + return record; + } + + +// ------------------------------------------------------------------- +// Class : "Hurricane::RbTree::iterator". + + + template< typename Data, typename Compare > + inline RbTree::iterator::iterator ( const Node* node ) + : node_(node) + { } + + + template< typename Data, typename Compare > inline bool RbTree::iterator::operator== ( const iterator& other ) const { return (node_ == other.node_); } + template< typename Data, typename Compare > inline bool RbTree::iterator::operator!= ( const iterator& other ) const { return (node_ != other.node_); } + template< typename Data, typename Compare > inline const Data& RbTree::iterator::operator* () const { return node_->getValue(); } + template< typename Data, typename Compare > inline bool RbTree::iterator::isValid () const { return (node_); } + template< typename Data, typename Compare > inline void RbTree::iterator::setNode ( const Node* node ) { node_ = node; } + + + template< typename Data, typename Compare > + inline const typename RbTree::Node* RbTree::iterator::getNode () const + { return node_; } + + + template< typename Data, typename Compare > + typename RbTree::iterator& RbTree::iterator::operator++ () + { + if (node_) { + const Node* right = node_->getRight(); + if (right) { + const Node* minChild = right->getMin(); + if (minChild) node_ = minChild; + else node_ = right; + } else { + const Node* parent = node_->getParent(); + while ( parent and not parent->hasLeftChild(node_)) { + node_ = parent; + parent = parent->getParent(); + } + node_ = parent; + } + } + + return *this; + } + + +// ------------------------------------------------------------------- +// Class : "Hurricane::RbTree::Elements". + + + template< typename Data, typename Compare > + inline RbTree::Elements::Locator::Locator ( const Locator &locator ) + : Hurricane::Locator() + , iterator_(locator.iterator_) + { } + + + template< typename Data, typename Compare > + RbTree::Elements::Locator::Locator ( const RbTree& tree ) + : Hurricane::Locator() + , iterator_(tree.begin()) + { } + + + template< typename Data, typename Compare > + typename RbTree::Elements::Locator* RbTree::Elements::Locator::getClone () const + { return new Locator(*this); } + + + template< typename Data, typename Compare > + Data RbTree::Elements::Locator::getElement () const + { return (*iterator_); } + + + template< typename Data, typename Compare > + bool RbTree::Elements::Locator::isValid () const + { return iterator_.isValid(); } + + + template< typename Data, typename Compare > + void RbTree::Elements::Locator::progress () + { + if (isValid()) ++iterator_; + } + + + template< typename Data, typename Compare > + std::string RbTree::Elements::Locator::_getString () const + { + std::string s = "<" + _TName("Elements::Locator") + + ">"; + return s; + } + + + template< typename Data, typename Compare > + inline RbTree::Elements::Elements ( const RbTree& tree ) + : Collection() + , tree_ (tree) + { } + + + template< typename Data, typename Compare > + inline RbTree::Elements::Elements ( const Elements& elements ) + : Collection() + , tree_ (elements.tree_) + { } + + + template< typename Data, typename Compare > + Collection* RbTree::Elements::getClone () const + { return new Elements(*this); } + + + template< typename Data, typename Compare > + typename RbTree::Elements::Locator* RbTree::Elements::getLocator () const + { return new Locator( tree_ ); } + + + template< typename Data, typename Compare > + std::string RbTree::Elements::_getString () const + { + std::string s = "<" + _TName("Elements") + " " + + getString(tree_) + + ">"; + return s; + } + + +// ------------------------------------------------------------------- +// Class : "Hurricane::RbTree". + + + template< typename Data, typename Compare > + RbTree::RbTree () + : count_ (0) + , root_ (NULL) + , compare_() + { } + + + template< typename Data, typename Compare > + RbTree::~RbTree () + { } + + + template< typename Data, typename Compare > inline bool RbTree::empty () const { return not count_; } + template< typename Data, typename Compare > inline size_t RbTree::size () const { return count_; } + + + template< typename Data, typename Compare > + inline typename RbTree::Node* RbTree::getRoot () const + { return root_; } + + + template< typename Data, typename Compare > + inline typename RbTree::iterator RbTree::end () const + { return iterator( NULL ); } + + + template< typename Data, typename Compare > + inline typename RbTree::iterator RbTree::begin () const + { return iterator( (root_ and root_->getLeft()) ? root_->getMin() : root_ ); } + + + template< typename Data, typename Compare > + void RbTree::postRotateLeft ( typename RbTree::Node* ) + { } + + + template< typename Data, typename Compare > + void RbTree::postRotateRight ( typename RbTree::Node* ) + { } + + + template< typename Data, typename Compare > + void RbTree::postInsert ( typename RbTree::Node* ) + { } + + + template< typename Data, typename Compare > + void RbTree::postRemove ( typename RbTree::Node* ) + { } + + + template< typename Data, typename Compare > + void RbTree::rotateLeft ( typename RbTree::Node* node ) + { + cdebug_log(0,0) << "RbTree::rotateLeft() " << node << std::endl; + + Node* rchild = node->getRight(); + + rchild->setParent( node->getParent() ); + node ->setParent( rchild ); + node ->setRight ( rchild->getLeft() ); + rchild->setLeft ( node ); + + if (not rchild->getParent()) root_ = rchild; + else rchild->getParent()->updateEdge( node, rchild ); + + postRotateLeft( node ); + } + + + template< typename Data, typename Compare > + void RbTree::rotateRight ( typename RbTree::Node* node ) + { + cdebug_log(0,0) << "RbTree::rotateRight() " << node << std::endl; + + Node* lchild = node->getLeft(); + + lchild->setParent( node->getParent() ); + node ->setParent( lchild ); + node ->setLeft ( lchild->getRight() ); + lchild->setRight ( node ); + + if (not lchild->getParent()) root_ = lchild; + else lchild->getParent()->updateEdge( node, lchild ); + + postRotateRight( node ); + } + + + template< typename Data, typename Compare > + typename RbTree::iterator RbTree::find ( const Data& value ) + { + cdebug_log(0,1) << "RbTree::find() value:" << value << std::endl; + + Node* current = root_; + while ( current ) { + cdebug_log(0,0) << "| " << current << std::endl; + + if (current->getValue() == value) { + cdebug_log(0,-1) << "> Value found: " << current <getValue())) current = current->getLeft (); + else current = current->getRight(); + } + + cdebug_log(0,-1) << "Value not found." << std::endl; + return end(); + } + + + template< typename Data, typename Compare > + typename RbTree::iterator RbTree::lower_bound ( const Data& value ) const + { + cdebug_log(0,1) << "RbTree::lower_bound() value:" << value << std::endl; + if (not root_) { cdebug_tabw(0,-1); return end(); } + + Node* current = root_; + Node* lbound = NULL; + while ( current ) { + cdebug_log(0,0) << "| " << current <getValue())) { current = current->getLeft (); continue; } + if (compare_(current->getValue(),value)) { current = current->getRight(); continue; } + + lbound = current; + current = current->getLeft(); + } + + cdebug_log(0,-1) << "lower_bound: " << lbound < + typename RbTree::iterator RbTree::upper_bound ( const Data& value ) const + { + cdebug_log(0,1) << "RbTree::uppper_bound() value:" << value << std::endl; + if (not root_) { cdebug_tabw(0,-1); return end(); } + + Node* ubound = NULL; + Node* current = root_; + while ( current ) { + cdebug_log(0,0) << "| " << current << std::endl; + + if (compare_(value,current->getValue())) { ubound = current; current = current->getLeft (); continue; } + if (compare_(current->getValue(),value)) { current = current->getRight(); continue; } + + current = current->getRight(); + } + + cdebug_log(0,-1) << "upper_bound: " << ubound << std::endl; + return iterator( ubound ); + } + + + template< typename Data, typename Compare > + typename RbTree::Elements RbTree::getElements () const + { return Elements( *this ); } + + + template< typename Data, typename Compare > + void RbTree::remove ( const Data& value ) + { + cdebug_log(0,1) << "RbTree::remove() value:" << value << std::endl; + + Node* rmNode = const_cast( find( value ).getNode() ); + if (not rmNode) { + cdebug_log(0,1) << "No node of value=" << value << std::endl; + return; + } + + if (rmNode->getLeft() and rmNode->getRight()) { + Node* rmLeaf = rmNode->getLeft(); + Node* rmMax = rmLeaf->getMax(); + if (rmMax) rmLeaf = rmMax; + + rmNode->copy( rmLeaf ); + rmNode = rmLeaf; + } + + postRemove ( rmNode ); + removeRepair( rmNode, 0 ); + + Node* parent = rmNode->getParent(); + Node* child = (rmNode->getLeft()) ? rmNode->getLeft() : rmNode->getRight(); + + if (parent) { + if (parent->hasLeftChild(rmNode)) parent->setLeft ( child ); + else parent->setRight( child ); + } else { + root_ = child; + if (child) { + child->setParent( NULL ); + child->setBlack (); + } + } + + cdebug_log(0,0) << "delete " << rmNode << std::endl; + delete rmNode; + --count_; + + cdebug_tabw(0,-1); + } + + + template< typename Data, typename Compare > + void RbTree::removeRepair ( typename RbTree::Node* rmNode, size_t depth ) + { + cdebug_log(0,1) << "RbTree::removeRepair() rmNode:" << rmNode + << " depth:" << depth << std::endl; + + if (rmNode->isBlack()) { + Node* parent = rmNode->getParent(); + // Case 1. + if (not parent) { + cdebug_log(0,0) << "Case 1: Do nothing." << std::endl; + cdebug_tabw(0,-1); + return; + } else { + // Case 2. + Node* sibling = rmNode->getSibling(); + + if (sibling->isRed()) { + cdebug_log(0,0) << "Case 2" << std::endl; + + parent ->setRed(); + sibling->setBlack(); + if (parent->hasLeftChild(rmNode)) rotateLeft ( parent ); + else rotateRight( parent ); + } + + // Case 3. + sibling = rmNode->getSibling(); + + if ( parent->isBlack() + and sibling->isBlack() + and (not sibling->getLeft () or sibling->getLeft ()->isBlack()) + and (not sibling->getRight() or sibling->getRight()->isBlack()) ) { + cdebug_log(0,0) << "Case 3" << std::endl; + + sibling->setRed(); + removeRepair( parent, depth+1 ); + + cdebug_tabw(0,-1); + return; + } + + // Case 4. + if ( parent->isRed() + and sibling->isBlack() + and (not sibling->getLeft () or sibling->getLeft ()->isBlack()) + and (not sibling->getRight() or sibling->getRight()->isBlack()) ) { + cdebug_log(0,0) << "Case 4" << std::endl; + + sibling->setRed (); + parent ->setBlack(); + + cdebug_tabw(0,-1); + return; + } + + // Case 5. + if (sibling->isBlack()) { + if (parent->hasLeftChild(rmNode) + and (not sibling->getRight() or sibling->getRight()->isBlack()) + and ( sibling->getLeft () and sibling->getLeft ()->isRed ()) ) { + cdebug_log(0,0) << "Case 5 (rmNode is *left* child)" << std::endl; + + sibling->setRed(); + sibling->getLeft()->setBlack(); + rotateRight( sibling ); + } else if (parent->hasRightChild(rmNode) + and (not sibling->getLeft () or sibling->getLeft ()->isBlack()) + and ( sibling->getRight() and sibling->getRight()->isRed ()) ) { + cdebug_log(0,0) << "Case 5 (rmNode is *right* child)" << std::endl; + + sibling->setRed(); + sibling->getRight()->setBlack(); + rotateLeft( sibling ); + } + sibling = rmNode->getSibling(); + } + + // Case 6. + sibling->copyColor( parent ); + parent->setBlack(); + + if (parent->hasLeftChild(rmNode)) { + cdebug_log(0,0) << "Case 6 (rmNode is *left* child)" << std::endl; + + sibling->getRight()->setBlack(); + rotateLeft( parent ); + } else { + cdebug_log(0,0) << "Case 6 (rmNode is *right* child)" << std::endl; + + sibling->getLeft()->setBlack(); + rotateRight( parent ); + } + } + } + + cdebug_tabw(0,-1); + } + + + template< typename Data, typename Compare > + void RbTree::insert ( const Data& value ) + { + cdebug_log(0,1) << "RbTree::insert() value:" << value << std::endl; + + Node* node = new Node( value, NULL ); + ++count_; + cdebug_log(0,0) << "New node:" << node << std::endl; + + insertRecurse( node ); + postInsert ( node ); + insertRepair ( node, 0 ); + + cdebug_tabw(0,-1); + } + + + template< typename Data, typename Compare > + void RbTree::insertRecurse ( typename RbTree::Node* node ) + { + cdebug_log(0,1) << "RbTree::insertRecurse() id:" << node << std::endl; + + if (not root_) { root_ = node; cdebug_tabw(0,-1); return; } + + Node* current = root_; + while ( current ) { + Node* child = NULL; + + if (compare_(node->getValue(),current->getValue())) { + child = current->getLeft(); + if (not child) { + cdebug_log(0,0) << "* Set as left child." << std::endl; + + current->setLeft( node ); + node->setParent( current ); + break; + } + } else { + child = current->getRight(); + if (not child) { + cdebug_log(0,0) << "* Set as right child." << std::endl; + + current->setRight( node ); + node->setParent( current ); + break; + } + } + + cdebug_log(0,0) << "> Down L/R child:" << child << std::endl; + current = child; + } + + cdebug_tabw(0,-1); + } + + + template< typename Data, typename Compare > + void RbTree::insertRepair ( typename RbTree::Node* node, size_t rdepth ) + { + cdebug_log(0,1) << "RbTree::insertRepair() id:" << node << std::endl; + + ++rdepth; + + // Case 1. + if (node == root_) { + cdebug_log(0,-1) << "Case 1" << std::endl; + node->setBlack(); + return; + } + + // Case 2. + if (node->getParent()->isBlack()) { + cdebug_log(0,-1) << "Case 2" << std::endl; + return; + } + + // Case 3. + Node* uncle = node->getUncle(); + if (uncle and uncle->isRed()) { + cdebug_log(0,0) << "Case 3: uncle:" << uncle << std::endl; + + node->getParent()->setBlack(); + uncle->setBlack(); + Node* grandParent = node->getGrandParent(); + grandParent->setRed(); + insertRepair( grandParent, rdepth ); + + cdebug_tabw(0,-1); + return; + } + + // Case 4, step 1. + Node* parent = node->getParent(); + Node* grandParent = node->getGrandParent(); + + if (grandParent->getLeft() and (node == grandParent->getLeft()->getRight()) ) { + cdebug_log(0,0) << "Case 4.1: right of left" << std::endl; + rotateLeft( parent ); + node = node->getLeft(); + } else if (grandParent->getRight() and (node == grandParent->getRight()->getLeft()) ) { + cdebug_log(0,0) << "Case 4.1: left of right" << std::endl; + rotateRight( parent ); + node = node->getRight(); + } + + // Case 4, step 2. + cdebug_log(0,0) << "Case 4.2" << std::endl; + parent = node->getParent(); + grandParent = node->getGrandParent(); + + if (node == parent->getLeft()) rotateRight( grandParent ); + else rotateLeft ( grandParent ); + + parent->setBlack(); + grandParent->setRed(); + + cdebug_tabw(0,-1); + } + + + template< typename Data, typename Compare > + inline void RbTree::clear () + { if (root_) root_->clear(); root_ = NULL; count_ = 0; } + + + template< typename Data, typename Compare > + std::string RbTree::_getTypeName () const + { return "RbTree<>"; } + + + template< typename Data, typename Compare > + std::string RbTree::_getString () const + { return "<" + _getTypeName() + " " + getString(size()) + ">"; } + + + template< typename Data, typename Compare > + Record* RbTree::_getRecord () const + { + cerr << "RbTree::_getRecord() root_:" << root_ << endl; + + Record* record = new Record( getString(this) ); + record->add(getSlot ( "count_", count_ )); + record->add(getSlot( "root_" , root_ )); + + cerr << "Root Record: 0x" << dynamic_cast< SlotTemplate* >(record->getSlot(1))->getDataRecord() << endl; + return record; + } + + +// ------------------------------------------------------------------- +// Class : "RbTreeToDot". + + + template< typename Data, typename Compare, template class RbTree > + class RbTreeToDot { + public: + RbTreeToDot ( const RbTree* tree ); + public: + void write ( std::string ) const; + void write ( std::ostream& ) const; + private: + void setupIds ( typename RbTree::Node* ); + void toDot ( std::ostream&, typename RbTree::Node* ) const; + inline size_t getId ( typename RbTree::Node* ) const; + private: + const RbTree* tree_; + map::Node*,size_t> nodeIds_; + }; + + + template< typename Data, typename Compare, template class RbTree > + inline size_t RbTreeToDot::getId ( typename RbTree::Node* r ) const + { + typename map::Node*,size_t>::const_iterator it = nodeIds_.find( r ); + return (it != nodeIds_.end()) ? (*it).second : 0; + } + + + template< typename Data, typename Compare, template class RbTree > + RbTreeToDot::RbTreeToDot ( const RbTree* tree ) + : tree_ ( tree ) + , nodeIds_() + { setupIds( tree_->getRoot() ); } + + + template< typename Data, typename Compare, template class RbTree > + void RbTreeToDot::setupIds ( typename RbTree::Node* node ) + { + if (not node) return; + + setupIds( node->getLeft() ); + nodeIds_.insert( make_pair( node, nodeIds_.size() ) ); + setupIds( node->getRight() ); + } + + + template< typename Data, typename Compare, template class RbTree > + void RbTreeToDot::write ( std::string path ) const + { + cdebug_log(0,0) << "RbTreeToDot::write() path=\"" << path << "\"" << endl; + + std::ofstream dotstream ( path ); + write( dotstream ); + dotstream.close(); + } + + + template< typename Data, typename Compare, template class RbTree > + void RbTreeToDot::write ( std::ostream& o ) const + { + o << "digraph RbTree {\n"; + toDot( o, tree_->getRoot() ); + o << "}"; + } + + + template< typename Data, typename Compare, template class RbTree > + void RbTreeToDot::toDot ( ostream& o, typename RbTree::Node* node ) const + { + if (not node) return; + + o << " id_" << getId(node) << " " + << "[label=\"id:" << getId(node) << "\\n" << ::getString(node->getValue()) + << "\"" + << ",color=" << (node->isRed() ? "red" : "black") + << ",fontcolor=" << (node->isRed() ? "red" : "black") + << "];\n"; + + if (node->getParent()) { + o << " id_" << getId(node) << " -> id_" << getId(node->getParent()) << " " + << "[label=\" p \"" + << ",color=" << (node->getParent()->isRed() ? "red" : "black") + << ",fontcolor=" << (node->getParent()->isRed() ? "red" : "black") + << ",style=dotted" + << "];\n"; + } + + if (node->getLeft()) { + o << " id_" << getId(node) << " -> id_" << getId(node->getLeft()) << " " + << "[label=\" L \"" + << ",color=" << (node->isRed() ? "red" : "black") + << ",fontcolor=" << (node->isRed() ? "red" : "black") + << "];\n"; + } + if (node->getRight()) { + o << " id_" << getId(node) << " -> id_" << getId(node->getRight()) << " " + << "[label=\" R \",style=bold" + << ",color=" << (node->isRed() ? "red" : "black") + << ",fontcolor=" << (node->isRed() ? "red" : "black") + << "];\n"; + } + + if (node->getLeft ()) toDot( o, node->getLeft () ); + if (node->getRight()) toDot( o, node->getRight() ); + } + + + template< typename Data, typename Compare > + inline void RbTree::write ( std::string path ) const + { RbTreeToDot(this).write( path ); } + + +} // Hurricane namespace. + + +#endif // HURRICANE_RBTREE_H diff --git a/hurricane/src/hurricane/hurricane/Slot.h b/hurricane/src/hurricane/hurricane/Slot.h index f8b50e8d..82ff27bf 100644 --- a/hurricane/src/hurricane/hurricane/Slot.h +++ b/hurricane/src/hurricane/hurricane/Slot.h @@ -81,23 +81,17 @@ namespace Hurricane { template class SlotTemplate : public Slot { - public: - // Constructor. SlotTemplate ( const string& name, Data data ); SlotTemplate ( string& name, Data data ); - // Accessors. virtual string getDataString () const; virtual Record* getDataRecord () const; virtual SlotTemplate* getClone () const; - + const Data& getData () const; protected: - // Internal: Attributes. Data _data; - private: - // Internal: Constructors. SlotTemplate ( const SlotTemplate& ); SlotTemplate& operator= ( const SlotTemplate& ); }; @@ -106,7 +100,10 @@ namespace Hurricane { // Inline Member Functions. template SlotTemplate::SlotTemplate ( const string& name, Data data ) - : Slot(name), _data(data) { } + : Slot(name), _data(data) + { + //std::cerr << "SlotTemplate::SlotTemplate() ( \"" << name << "\" )" << std::endl; + } template SlotTemplate::SlotTemplate ( string& name, Data data ) @@ -122,29 +119,30 @@ namespace Hurricane { SlotTemplate* SlotTemplate::getClone () const { return new SlotTemplate(_name,_data); } + template + const Data& SlotTemplate::getData () const + { + //std::cerr << "SlotTemplate::getData()" << std::endl; + return _data; + } + // ------------------------------------------------------------------- // Class : "SlotTemplate". template class SlotTemplate : public Slot { - public: - // Constructor. SlotTemplate ( const string& name, const Data data ); SlotTemplate ( string& name, const Data data ); - // Accessors. virtual string getDataString () const; virtual Record* getDataRecord () const; virtual SlotTemplate* getClone () const; - + const Data& getData () const; protected: - // Internal: Attributes. const Data _data; - private: - // Internal: Constructors. SlotTemplate ( const SlotTemplate& ); SlotTemplate& operator= ( const SlotTemplate& ); }; @@ -153,22 +151,29 @@ namespace Hurricane { // Inline Member Functions. template SlotTemplate::SlotTemplate ( const string& name, const Data data ) - : Slot(name), _data(data) { } + : Slot(name), _data(data) + { + //std::cerr << "SlotTemplate::SlotTemplate(const Data) ( \"" << name << "\" )" << std::endl; + } template SlotTemplate::SlotTemplate ( string& name, const Data data ) : Slot(name), _data(data) { } template - string SlotTemplate::getDataString () const { return getString(_data); } + string SlotTemplate::getDataString () const { return ::getString(_data); } template - Record* SlotTemplate::getDataRecord () const { return getRecord(_data); } + Record* SlotTemplate::getDataRecord () const { return ::getRecord(_data); } template SlotTemplate* SlotTemplate::getClone () const { return new SlotTemplate(_name,_data); } + template + const Data& SlotTemplate::getData () const + { return _data; } + // ------------------------------------------------------------------- // Class : "SlotTemplate". @@ -176,32 +181,29 @@ namespace Hurricane { template class SlotTemplate : public Slot { - public: - // Constructor. - SlotTemplate ( const string& name, Data* data ); - SlotTemplate ( string& name, Data* data ); - // Accessors. - virtual string getDataString () const; - virtual Record* getDataRecord () const; + SlotTemplate ( const string& name, Data* data ); + SlotTemplate ( string& name, Data* data ); + virtual string getDataString () const; + virtual Record* getDataRecord () const; virtual SlotTemplate* - getClone () const; - + getClone () const; + Data* getData () const; + private: + SlotTemplate ( const SlotTemplate& ); + SlotTemplate& operator= ( const SlotTemplate& ); protected: - // Internal: Attributes. Data* _data; - - private: - // Internal: Constructors. - SlotTemplate ( const SlotTemplate& ); - SlotTemplate& operator= ( const SlotTemplate& ); }; // Inline Member Functions. template SlotTemplate::SlotTemplate ( const string& name, Data* data ) - : Slot(name), _data(data) {} + : Slot(name), _data(data) + { + //std::cerr << "SlotTemplate::SlotTemplate(Data*) \"" << name << "\"" << std::endl; + } template SlotTemplate::SlotTemplate ( string& name, Data* data ) @@ -211,12 +213,23 @@ namespace Hurricane { string SlotTemplate::getDataString () const { return ::getString(_data); } template - Record* SlotTemplate::getDataRecord () const { return ::getRecord(_data); } + Record* SlotTemplate::getDataRecord () const + { + //std::cerr << "SlotTemplate::getDataRecord()" << std::endl; + return ::getRecord(_data); + } template SlotTemplate* SlotTemplate::getClone () const { return new SlotTemplate(_name,_data); } + template + Data* SlotTemplate::getData () const + { + //std::cerr << "SlotTemplate::getData()" << _data << std::endl; + return _data; + } + // ------------------------------------------------------------------- // Class : "SlotTemplate". @@ -224,32 +237,29 @@ namespace Hurricane { template class SlotTemplate : public Slot { - public: - // Constructor. - SlotTemplate ( const string& name, Data* const data ); - SlotTemplate ( string& name, Data* const data ); - // Accessors. - virtual string getDataString () const; - virtual Record* getDataRecord () const; + SlotTemplate ( const string& name, Data* const data ); + SlotTemplate ( string& name, Data* const data ); + virtual string getDataString () const; + virtual Record* getDataRecord () const; virtual SlotTemplate* - getClone () const; - + getClone () const; + Data* const getData () const; + private: + SlotTemplate ( const SlotTemplate& ); + SlotTemplate& operator= ( const SlotTemplate& ); protected: - // Internal: Attributes. Data* const _data; - - private: - // Internal: Constructors. - SlotTemplate ( const SlotTemplate& ); - SlotTemplate& operator= ( const SlotTemplate& ); }; // Inline Member Functions. template SlotTemplate::SlotTemplate ( const string& name, Data* const data ) - : Slot(name), _data(data) {} + : Slot(name), _data(data) + { + //std::cerr << "SlotTemplate::SlotTemplate(Data* const) ( \"" << name << "\" )" << std::endl; + } template SlotTemplate::SlotTemplate ( string& name, Data* const data ) @@ -265,6 +275,10 @@ namespace Hurricane { SlotTemplate* SlotTemplate::getClone () const { return new SlotTemplate(_name,_data); } + template + Data* const SlotTemplate::getData () const + { return _data; } + // ------------------------------------------------------------------- // Class : "SlotTemplate". @@ -272,31 +286,27 @@ namespace Hurricane { template<> class SlotTemplate : public Slot { - public: - // Constructor. - inline SlotTemplate ( const string& name, Record* data ); - inline SlotTemplate ( string& name, Record* data ); - // Accessors. - inline virtual string getDataString () const; - inline virtual Record* getDataRecord () const; + inline SlotTemplate ( const string& name, Record* data ); + inline SlotTemplate ( string& name, Record* data ); + inline virtual string getDataString () const; + inline virtual Record* getDataRecord () const; inline virtual SlotTemplate* - getClone () const; - - protected: - // Internal: Attributes. - Record* _data; - + getClone () const; private: - // Internal: Constructors. - SlotTemplate ( const SlotTemplate& ); - SlotTemplate& operator= ( const SlotTemplate& ); + SlotTemplate ( const SlotTemplate& ); + SlotTemplate& operator= ( const SlotTemplate& ); + protected: + Record* _data; }; // Inline Member Functions. inline SlotTemplate::SlotTemplate ( const string& name, Record* data ) - : Slot(name), _data(data) {} + : Slot(name), _data(data) + { + //std::cerr << "SlotTemplate::SlotTemplate(Record*) ( \"" << name << "\" )" << std::endl; + } inline SlotTemplate::SlotTemplate ( string& name, Record* data ) : Slot(name), _data(data) {} @@ -331,6 +341,7 @@ template inline Hurricane::Slot* getSlot( const std::string& name, Data d ) { //std::cerr << "getSlot( \"" << name << "\" )" << std::endl; +//std::cerr << " Data = " << typeid(d).name() << std::endl; return new Hurricane::SlotTemplate ( name, d ); } @@ -339,6 +350,7 @@ template inline Hurricane::Slot* getSlot( const std::string& name, Data* d ) { //std::cerr << "getSlot( \"" << name << "\" )" << std::endl; +//std::cerr << " Data = " << typeid(d).name() << std::endl; return new Hurricane::SlotTemplate ( name, d ); } diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt new file mode 100644 index 00000000..789013cd --- /dev/null +++ b/unittests/CMakeLists.txt @@ -0,0 +1,30 @@ +# -*- mode: CMAKE explicit-buffer-name: "CMakeLists.txt" -*- + + set(CMAKE_LEGACY_CYGWIN_WIN32 0) + project(UNITTEST) + + cmake_minimum_required(VERSION 2.8.9) + + set(ignoreVariables "${BUILD_DOC}") + + list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/") + find_package(Bootstrap REQUIRED) + setup_project_paths(CORIOLIS) + list(INSERT CMAKE_MODULE_PATH 0 "${CRLCORE_SOURCE_DIR}/cmake_modules/") + print_cmake_module_path() + + set_cmake_policies() + check_distribution() + setup_sysconfdir("${CMAKE_INSTALL_PREFIX}") + setup_boost(program_options python regex wave) + setup_qt() + + find_package(Libbfd) + find_package(Libexecinfo REQUIRED) + find_package(PythonLibs 2 REQUIRED) + find_package(PythonSitePackages REQUIRED) + find_package(VLSISAPD REQUIRED) + find_package(HURRICANE REQUIRED) + find_package(CORIOLIS REQUIRED) + + add_subdirectory(src) diff --git a/unittests/src/CMakeLists.txt b/unittests/src/CMakeLists.txt new file mode 100644 index 00000000..1f98c001 --- /dev/null +++ b/unittests/src/CMakeLists.txt @@ -0,0 +1,43 @@ +# -*- explicit-buffer-name: "CMakeLists.txt" -*- + + include_directories ( ${CORIOLIS_INCLUDE_DIR} + ${HURRICANE_INCLUDE_DIR} + ${UTILITIES_INCLUDE_DIR} + ${QtX_INCLUDE_DIR} + ${Boost_INCLUDE_DIR} + ) + + set ( mocincludes + ) + set ( cpps unittests.cpp + ) + + qtX_wrap_cpp ( mocCpps ${mocincludes} ) + +if(NOT WITH_QT5) + list ( APPEND cpps ${mocCpps} ) +endif() + + add_executable ( unittests ${cpps} ) + target_link_libraries ( unittests ${CORIOLIS_PYTHON_LIBRARIES} + ${CORIOLIS_LIBRARIES} + ${HURRICANE_PYTHON_LIBRARIES} + ${HURRICANE_GRAPHICAL_LIBRARIES} + ${HURRICANE_LIBRARIES} + ${BOOKSHELF_LIBRARY} + ${AGDS_LIBRARY} + ${CIF_LIBRARY} + ${CONFIGURATION_LIBRARY} + ${UTILITIES_LIBRARY} + ${LEFDEF_LIBRARIES} + ${OA_LIBRARIES} + ${QtX_LIBRARIES} + ${Boost_LIBRARIES} + ${PYTHON_LIBRARIES} + -lutil + ${LIBXML2_LIBRARIES} + ${LIBEXECINFO_LIBRARIES} + ${LIBBFD_LIBRARIES} + ) + install ( TARGETS unittests DESTINATION bin ) + diff --git a/unittests/src/unittests.cpp b/unittests/src/unittests.cpp new file mode 100644 index 00000000..cbc0f24f --- /dev/null +++ b/unittests/src/unittests.cpp @@ -0,0 +1,197 @@ + + +#include +namespace boptions = boost::program_options; + +#include "hurricane/DebugSession.h" +#include "hurricane/Interval.h" +#include "hurricane/RbTree.h" +#include "hurricane/IntervalTree.h" +#include "crlcore/Utilities.h" + +namespace Hurricane { + + typedef IntervalData IntvString; + typedef RbTree RbInterval; + typedef IntervalTree IntervalTreeString; + typedef GenericCollection Intervals; + typedef GenericCollection IntvStrings; + +} + +INSPECTOR_PV_SUPPORT(Hurricane::RbInterval); +INSPECTOR_PV_SUPPORT(Hurricane::RbInterval::Node); +INSPECTOR_PV_SUPPORT(Hurricane::IntvString); +INSPECTOR_PV_SUPPORT(Hurricane::IntervalTreeString); +INSPECTOR_PV_SUPPORT(Hurricane::IntervalTreeString::Node); + +using namespace std; +using namespace Hurricane; +using namespace CRL; + + +namespace { + + using namespace std; + using namespace Hurricane; + + + inline DbU::Unit l ( long v ) { return DbU::fromLambda(v); } + + +// ------------------------------------------------------------------- +// Test : "testRbTree". + + + int testRbTree () + { + //typedef IntervalTree RbInterval; + RbInterval rb; + + long count = 13; + for ( long key=0 ; key intv : itree.getElements() ) { + cerr << intv << endl; + } + + IntervalTreeString::overlap_iterator ob = itree.beginOverlaps( Interval(l(2),l(4)) ); + cerr << "overlap of [2:4]: [ "; + for ( ; ob != itree.end() ; ++ob ) + cerr << *ob << " "; + cerr << "]" << endl; + cerr << endl << endl; + + ob = itree.beginOverlaps( Interval(l(-2),l(-1)) ); + cerr << "overlap of [-2:-1]: [ "; + for ( ; ob != itree.end() ; ++ob ) + cerr << *ob << " "; + cerr << "]" << endl; + cerr << endl << endl; + + ob = itree.beginOverlaps( Interval(l(6),l(9)) ); + cerr << "overlap of [6:9]: [ "; + for ( ; ob != itree.end() ; ++ob ) + cerr << *ob << " "; + cerr << "]" << endl; + cerr << endl << endl; + + cerr << "overlap of [6:9]: [ "; + for ( const IntvString& intv : itree.getOverlaps( Interval( l(6), l(9) ) ) ) + cerr << intv << " "; + cerr << "]" << endl; + + return 0; + } + + +} // Anonymous namespace. + + +int main ( int argc, char* argv[] ) +{ + int returnCode = 0; + + try { + bool coreDump = false; + bool rbTree = false; + bool intvTree = false; + + boptions::options_description options ("Command line arguments & options"); + options.add_options() + ( "help,h" , "Print this help." ) + ( "core-dump,D", boptions::bool_switch(&coreDump)->default_value(false) + , "Enable core dumping.") + ( "rb-tree" , boptions::bool_switch(&rbTree )->default_value(false) + , "Test of the red/black tree \"hurricane/RbTree.h\".") + ( "intv-tree" , boptions::bool_switch(&intvTree)->default_value(false) + , "Test of the interval tree \"hurricane/IntervalTree.h\"."); + + boptions::variables_map arguments; + boptions::store ( boptions::parse_command_line(argc,argv,options), arguments ); + boptions::notify( arguments ); + + if (arguments.count("help")) { + cerr << options << endl; + exit( 0 ); + } + + + System::get()->setCatchCore( not coreDump ); + DebugSession::open( 0, 1000 ); + + if (rbTree ) returnCode += testRbTree(); + if (intvTree) returnCode += testIntervalTree(); + + DebugSession::close(); + } + catch ( Error& e ) { + cerr << e.what() << endl; + exit( 127 ); + } + catch ( boptions::error& e ) { + cerr << "[ERROR] " << e.what() << endl; + exit( 127 ); + } + catch ( exception& e ) { + cerr << "[ERROR] " << e.what() << endl; + exit( 127 ); + } + catch ( ... ) { + cerr << "[ERROR] Abnormal termination: unmanaged exception.\n" << endl; + exit( 126 ); + } + + return returnCode; +}