3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU Lesser General Public License as
5 * published by the Free Software Foundation, either version 3 of the
6 * License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * @file ImageContainerByHashTree.ih
20 * @author Nicolas Silva (\c nicolas.silva@insa-lyon.fr )
21 * @author David Coeurjolly (\c david.coeurjolly@liris.cnrs.fr )
22 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
26 * Implementation of inline methods defined in ImageContainerByHashTree.h
28 * This file is part of the DGtal library.
32//////////////////////////////////////////////////////////////////////////////
43//////////////////////////////////////////////////////////////////////////////
45///////////////////////////////////////////////////////////////////////////////
46// IMPLEMENTATION of inline methods.
47///////////////////////////////////////////////////////////////////////////////
49///////////////////////////////////////////////////////////////////////////////
50// ----------------------- Standard services ------------------------------
54 namespace experimental
57 // ---------------------------------------------------------------------
59 // ---------------------------------------------------------------------
61 template < typename Domain, typename Value, typename HashKey>
63 ImageContainerByHashTree<Domain, Value, HashKey>
64 ::ImageContainerByHashTree ( const unsigned int hashKeySize,
65 const unsigned int depth,
66 const Value defaultValue )
67 : myKeySize ( hashKeySize )
70 //Consistency check of the hashKeysize
71 ASSERT ( hashKeySize <= sizeof ( HashKey ) *8 );
73 myOrigin = Point::zero;
74 myPreComputedIntermediateMask = ~ ( static_cast<HashKey> ( ~0 ) << myKeySize );
76 unsigned int acceptedDepth = ( ( sizeof ( HashKey ) * 8 - 2 ) / dim );
77 unsigned int acceptedDomainDepth = ( sizeof ( typename Domain::Point::Coordinate ) * 8 - 1 );
78 if (( depth > acceptedDepth ) || (depth > acceptedDomainDepth))
80 trace.error() << "ImageContainerByHashTree::Constructor: error !" << std::endl;
81 trace.error() << "requested depth too high for the key type" << std::endl;
82 trace.error() << "accepted: " << acceptedDepth << " accepted (Domain): "<<acceptedDomainDepth<<" Requested: " << depth << std::endl;
84 setDepth ( ( acceptedDepth < acceptedDomainDepth) ? acceptedDepth -1 : acceptedDomainDepth -1 );
89 myDomain = Domain(Point::zero, Point::diagonal(static_cast<typename Point::Component>( pow(2.0, (int)myTreeDepth) )));
92 myArraySize = 1 << myKeySize;
93 myData = new Node*[myArraySize];
94 for ( unsigned i = 0; i < myArraySize; ++i )
97 addNode ( defaultValue, ROOT_KEY );
101 template < typename Domain, typename Value, typename HashKey>
103 ImageContainerByHashTree<Domain, Value, HashKey>
104 ::ImageContainerByHashTree ( const Domain &aDomain,
105 const unsigned int hashKeySize,
106 const Value defaultValue ):
107 myDomain(aDomain), myKeySize ( hashKeySize )
109 myOrigin = aDomain.lowerBound() ;
110 //Consistency check of the hashKeysize
111 ASSERT ( hashKeySize <= sizeof ( HashKey ) *8 );
113 Point p1 = myDomain.lowerBound();
114 Point p2 = myDomain.upperBound();
116 myPreComputedIntermediateMask = ~ ( static_cast<HashKey> ( ~0 ) << myKeySize );
118 typename Point::Component maxSize = (p2-p1).normInfinity();
119 unsigned int depth = (unsigned int)(ceil ( log2 ( (double) maxSize ))) ;
121 unsigned int acceptedDepth = ( ( sizeof ( HashKey ) * 8 - 1 ) / dim );
122 if ( depth > acceptedDepth )
124 trace.error() << "ImageContainerByHashTree::Constructor: error !"
125 << " requested depth too high for the key type" << std::endl;
126 trace.error() << "accepted: " << acceptedDepth
127 << " Requested: " << depth << std::endl;
128 setDepth ( acceptedDepth );
134 myArraySize = 1 << hashKeySize;
135 myData = new Node*[myArraySize];
136 for ( unsigned int i = 0; i < myArraySize; ++i )
138 //add the default value
139 addNode ( defaultValue, ROOT_KEY );
144 template < typename Domain, typename Value, typename HashKey>
146 ImageContainerByHashTree<Domain, Value, HashKey>
147 ::ImageContainerByHashTree ( const unsigned int hashKeySize,
150 const Value defaultValue )
151 : myDomain( p1, p2 ), myKeySize ( hashKeySize ), myOrigin ( p1 )
153 //Consistency check of the hashKeysize
154 ASSERT ( hashKeySize <= sizeof ( HashKey ) *8 );
156 myPreComputedIntermediateMask = ~ ( static_cast<HashKey> ( ~0 ) << myKeySize );
159 for ( unsigned int i = 0; i < dim; ++i )
160 if ( maxSize < p1[i] - p2[i] )
161 maxSize = p1[i] - p2[i];
162 unsigned int depth = (unsigned int)(ceil ( log ( (double) maxSize ) / log((double) 2.0) ));
164 unsigned int acceptedDepth = ( ( sizeof ( HashKey ) * 8 - 1 ) / dim );
165 if ( depth > acceptedDepth )
167 trace.error() << "ImageContainerByHashTree::Constructor: error !"
168 << " requested depth too high for the key type" << std::endl;
169 trace.error() << "accepted: " << acceptedDepth
170 << " Requested: " << depth << std::endl;
171 setDepth ( acceptedDepth );
177 myArraySize = 1 << hashKeySize;
178 myData = new Node*[myArraySize];
179 for ( unsigned int i = 0; i < myArraySize; ++i )
181 //add the default value
182 addNode ( defaultValue, ROOT_KEY );
186 // ---------------------------------------------------------------------
188 // ---------------------------------------------------------------------
190 //------------------------------------------------------------------------------
191 template < typename Domain, typename Value, typename HashKey>
193 const typename ImageContainerByHashTree<Domain, Value, HashKey >::Domain&
194 ImageContainerByHashTree<Domain, Value, HashKey >::domain() const
199 //------------------------------------------------------------------------------
200 template < typename Domain, typename Value, typename HashKey>
202 typename ImageContainerByHashTree<Domain, Value, HashKey >::ConstRange
203 ImageContainerByHashTree<Domain, Value, HashKey >::constRange() const
205 return ConstRange( *this );
207 //------------------------------------------------------------------------------
208 template < typename Domain, typename Value, typename HashKey>
210 typename ImageContainerByHashTree<Domain, Value, HashKey >::Range
211 ImageContainerByHashTree<Domain, Value, HashKey >::range()
213 return Range( *this );
216 //------------------------------------------------------------------------------
217 /*template < typename Domain, typename Value, typename HashKey>
219 typename ImageContainerByHashTree<Domain, Value, HashKey >::OutputIterator
220 ImageContainerByHashTree<Domain, Value, HashKey >::outputIterator()
222 return OutputIterator( *this );
226 template < typename Domain, typename Value, typename HashKey>
229 ImageContainerByHashTree<Domain, Value, HashKey >::setValue ( const Point& aPoint, const Value value )
231 setValue ( getKey ( aPoint ), value );
235 template < typename Domain, typename Value, typename HashKey>
238 ImageContainerByHashTree<Domain, Value, HashKey >::setValue ( const HashKey key, const Value value )
240 HashKey brothers[myN-1];
242 bool broValue = ( key != static_cast<HashKey> ( 1 ) );
243 myMorton.brotherKeys ( key, brothers );
244 for ( unsigned int i = 0; i < myN - 1; ++ i )
246 Node* n = getNode ( brothers[i] );
247 if ( ! ( n && ( n->getObject() == value ) ) )
256 setValue ( myMorton.parentKey ( key ), value );
260 // if the key already exists
261 Node* n = getNode ( key );
264 n->getObject() = value;
268 //if there's a leaf above the requested node
269 HashKey iterKey = key;
270 std::list< HashKey > nodeList;
271 while ( iterKey != 0 )
273 // cerr << "while(iter)..." << std::endl;
274 n = getNode ( iterKey );
277 Value tempVal = n->getObject();
278 if ( tempVal == value )
280 removeNode ( iterKey );
281 for ( typename std::list< HashKey >::iterator it = nodeList.begin();
282 it != nodeList.end();
285 // cerr << "adding a node ("<< bits::bitString(*it, 8)<<")" << std::endl;
286 addNode ( tempVal, *it );
288 addNode ( value, key );
289 //cerr << "return " << std::endl;
294 //cerr << " + " << std::endl;
295 HashKey brothersH[myN-1];
296 myMorton.brotherKeys ( iterKey, brothersH );
297 for ( unsigned int i = 0; i < myN - 1; ++i )
299 nodeList.push_front ( brothersH[i] );
304 addNode ( value, key );
305 unsigned int nbRecur = myTreeDepth - getKeyDepth ( key ) + 1;
306 HashKey children[myN];
307 myMorton.childrenKeys ( key, children );
308 for ( unsigned int i = 0; i < myN; ++i )
309 recursiveRemoveNode ( children[i], nbRecur );
315 template < typename Domain, typename Value, typename HashKey >
317 Value ImageContainerByHashTree<Domain, Value, HashKey >::operator() ( const HashKey key ) const
321 template < typename Domain, typename Value, typename HashKey >
323 Value ImageContainerByHashTree<Domain, Value, HashKey >::operator() ( const Point &aPoint ) const
325 return get ( aPoint );
328 template < typename Domain, typename Value, typename HashKey >
330 Value ImageContainerByHashTree<Domain, Value, HashKey >::get ( const HashKey key ) const
333 HashKey iterKey = key;
334 // node above the requested node
335 while ( iterKey != 0 )
337 Node* n = getNode ( iterKey );
339 return n->getObject();
342 //if the node is deeper than the one requested
343 return blendChildren ( key );
347 template < typename Domain, typename Value, typename HashKey >
349 Value ImageContainerByHashTree<Domain, Value, HashKey >::reverseGet ( const HashKey key ) const
352 HashKey iterKey = key;
353 // node above the requested node
354 HashKey limit = myDepthMask << 1;
355 while ( iterKey < limit )
357 Node* n = getNode ( iterKey );
359 return blendChildren ( key );
363 while ( iterKey != 0 )
365 Node* n = getNode ( iterKey );
367 return n->getObject();
374 template < typename Domain, typename Value, typename HashKey>
377 ImageContainerByHashTree<Domain, Value, HashKey >::get ( const Point & aPoint ) const
379 return get ( getKey ( aPoint ) );
382 template < typename Domain, typename Value, typename HashKey >
385 ImageContainerByHashTree<Domain, Value, HashKey >::getKey ( const Point & aPoint ) const
388 Point currentPos = aPoint - myOrigin;
390 myMorton.interleaveBits ( currentPos, result );
391 // by convention, the root node has the key 0..01
392 // it makes it easy to determine the depth of a node by it's key (looking
393 // at the position of the most significant bit that is equal to 1)
394 result |= myDepthMask;
399 template < typename Domain, typename Value, typename HashKey >
402 ImageContainerByHashTree<Domain, Value, HashKey >::getIntermediateKey ( HashKey key ) const
404 return ( key & myPreComputedIntermediateMask );
408 template < typename Domain, typename Value, typename HashKey >
411 ImageContainerByHashTree<Domain, Value, HashKey >::Iterator::next()
415 myNode = myNode->getNext();
424 myNode = myContainerData[++myCurrentCell];
425 if ( myCurrentCell >= myArraySize )
435 // ---------------------------------------------------------------------
437 // ---------------------------------------------------------------------
439 template < typename Domain, typename Value, typename HashKey >
442 ImageContainerByHashTree<Domain, Value, HashKey >::removeNode ( HashKey key )
444 HashKey key2 = getIntermediateKey ( key );
445 Node* iter = myData[key2];
446 // if the node is the first in the list we have to modify the pointer stored in myData
447 if ( iter && ( iter->getKey() == key ) )
449 myData[key2] = iter->getNext();
455 Node* next = iter->getNext();
458 if ( next->getKey() == key )
460 iter->setNext ( next->getNext() );
465 iter = iter->getNext();
470 template < typename Domain, typename Value, typename HashKey >
473 ImageContainerByHashTree<Domain, Value, HashKey >::recursiveRemoveNode ( HashKey key, unsigned int nbRecursions )
475 if ( removeNode ( key ) )
477 if ( --nbRecursions > 0 )
479 HashKey children[myN];
480 myMorton.childrenKeys ( key, children );
481 for ( unsigned int i = 0; i < myN; ++i )
483 recursiveRemoveNode ( children[i], nbRecursions );
490 // ---------------------------------------------------------------------
492 // ---------------------------------------------------------------------
494 template < typename Domain, typename Value, typename HashKey >
497 ImageContainerByHashTree<Domain, Value, HashKey >::setDepth ( unsigned int depth )
500 mySpanSize = 1 << depth;
501 //precompute the mask
502 myDepthMask = static_cast<HashKey> ( 1 ) << dim * depth;
506 template < typename Domain, typename Value, typename HashKey >
509 ImageContainerByHashTree<Domain, Value, HashKey >::getKeyDepth ( HashKey key ) const
511 for ( int i = ( sizeof ( HashKey ) << 3 ) - 1; i >= 0; --i )
512 if ( key & ( static_cast<HashKey> ( 1 ) << i ) )
520 template < typename Domain, typename Value, typename HashKey >
523 ImageContainerByHashTree<Domain, Value, HashKey >::getCoordinatesFromKey ( HashKey key ) const
525 //remove the first bit equal 1
526 for ( int i = ( sizeof ( HashKey ) << 3 ) - 1; i >= 0; --i )
528 if ( key & Bits::mask<HashKey> ( i ) )
530 key &= ~Bits::mask<HashKey> ( i );
534 int* coordinates = new int[dim];
535 //deinterleave the bits
536 for ( unsigned int i = 0; i < dim; ++i )
539 for ( unsigned int bitPos = 0; bitPos < ( sizeof ( HashKey ) << 3 ) / dim; ++bitPos )
541 if ( key & Bits::mask ( bitPos*dim + i ) )
543 coordinates[i] |= Bits::mask<HashKey> ( bitPos );
551 template < typename Domain, typename Value, typename HashKey >
554 ImageContainerByHashTree<Domain, Value, HashKey >::isKeyValid ( HashKey key ) const
558 if ( getKeyDepth ( key ) > myTreeDepth )
561 int i = ( sizeof ( HashKey ) << 3 ) - 1;
562 for ( ; i >= 0; --i )
563 if ( key & ( static_cast<HashKey> ( 1 ) << i ) )
575 // ---------------------------------------------------------------------
577 // ---------------------------------------------------------------------
578 template <typename Domain, typename Value , typename HashKey >
581 ImageContainerByHashTree<Domain, Value, HashKey >::printState ( std::ostream& out, bool displayKeys ) const
583 out << "ImageContainerByHashTree::printState" << std::endl;
584 out << "depth: " << myTreeDepth << " (" << Bits::bitString ( myDepthMask ) << ")" << std::endl;
585 out << "dim: " << dim << "myN: " << myN << std::endl;
586 printTree ( ROOT_KEY, out, displayKeys );
589 template <typename Domain, typename Value, typename HashKey >
592 ImageContainerByHashTree<Domain, Value, HashKey >::printTree ( HashKey key, std::ostream& out, bool displayKeys ) const
594 unsigned int level = getKeyDepth ( key );
595 for ( unsigned int i = 0; i < level; ++i )
597 Node* n = getNode ( key );
600 out << " < " << n->getObject() << " > ";
602 out << Bits::bitString ( key, 8 );
609 out << Bits::bitString ( key, 8 );
613 if ( level < myTreeDepth )
615 HashKey children[myN];
616 myMorton.childrenKeys ( key, children );
617 for ( unsigned int i = 0; i < myN; ++i )
618 printTree ( children[i], out, displayKeys );
622 template <typename Domain, typename Value, typename HashKey >
625 ImageContainerByHashTree<Domain, Value, HashKey >::printInternalState ( std::ostream& out, unsigned int nbBits ) const
627 out << "ImageContainerByHashTree::printInternalState ----------------------------------" << std::endl;
628 out << "| <template> dim = " << dim << " myN = " << myN << std::endl;
629 out << "| tree depth = " << myTreeDepth << " mask = " << Bits::bitString ( myDepthMask ) << std::endl;
631 for ( unsigned int i = 0; i < ( 1 << myKeySize ); ++i )
633 out << "| " << Bits::bitString ( i, myKeySize ) << " [";
638 out << Bits::bitString ( myData[i]->getKey(), nbBits ) << ":";
639 out << myData[i]->getObject() << ")";
640 Node* iter = myData[i]->getNext();
645 out << Bits::bitString ( myData[i]->getKey(), nbBits ) << ":";
646 out << iter->getObject() << ")";
647 iter = iter->getNext();
653 std::cout << "x]" << std::endl;
657 out << "| image size: " << getSpanSize() << "^" << dim << " (" << std::pow ( getSpanSize(), dim ) *sizeof ( Value ) << " bytes)" << std::endl;
658 out << "| " << getNbNodes() << " nodes - Empty lists: " << getNbEmptyLists() << " (" << getNbEmptyLists() *sizeof ( Node* ) << " bytes)" << std::endl;
659 out << "| Average collisions: " << getAverageCollisions() << " - Max collisions " << getMaxCollisions() << std::endl;
660 out << "----------------------------------------------------------------" << std::endl;
664 template <typename Domain, typename Value, typename HashKey >
667 ImageContainerByHashTree<Domain, Value, HashKey >::printInfo ( std::ostream& out ) const
669 unsigned int nbNodes = getNbNodes();
670 unsigned int totalSize = sizeof ( *this ) + ( 1 << myKeySize ) * sizeof ( Node* ) + nbNodes * sizeof ( Node );
672 out << "[ImageContainerByHashTree]: Dimension=" << ( int ) dim << ", HashKey size="
673 << myKeySize << ", Depth=" << myTreeDepth << ", image size=" << getSpanSize()
674 << "^" << ( int ) dim << " (" << std::pow ( ( double ) getSpanSize(), ( double ) dim ) *sizeof ( Value )
675 << " bytes)" << ", " << nbNodes << " nodes" << ", Empty lists=" << getNbEmptyLists()
676 << " (" << getNbEmptyLists() *sizeof ( Node* ) << " bytes)" << ", Average collisions=" << getAverageCollisions()
677 << ", Max collisions " << getMaxCollisions()
678 << ", total memory usage=" << totalSize << " bytes" << std::endl;
683 template <typename Domain, typename Value, typename HashKey >
686 ImageContainerByHashTree<Domain, Value, HashKey >::getNbNodes ( unsigned int intermediateKey ) const
688 if ( !myData[intermediateKey] )
694 unsigned int count = 1;
695 Node* n = myData[intermediateKey]->getNext();
707 template <typename Domain, typename Value, typename HashKey >
710 ImageContainerByHashTree<Domain, Value, HashKey >::getNbNodes() const
712 unsigned int count = 0;
713 unsigned int arraySize = 1 << myKeySize;
714 for ( unsigned int i = 0; i < arraySize; ++i )
716 count += getNbNodes ( i );
722 template <typename Domain, typename Value, typename HashKey >
725 ImageContainerByHashTree<Domain, Value, HashKey >::getNbEmptyLists() const
727 unsigned int count = 0;
728 unsigned int arraySize = 1 << myKeySize;
729 for ( unsigned int i = 0; i < arraySize; ++i )
738 template<typename Domain, typename Value, typename HashKey >
741 ImageContainerByHashTree<Domain, Value, HashKey >::getAverageCollisions() const
745 unsigned int arraySize = 1 << myKeySize;
746 for ( unsigned int i = 0; i < arraySize; ++i )
750 count += getNbNodes ( i ) - 1;
756 trace.error() << "ImageContainerByHashTree::getAverageCollision() - error" << std::endl
757 << "the container is empty !" << std::endl;
760 return count / nbLists;
765 template <typename Domain, typename Value, typename HashKey >
768 ImageContainerByHashTree<Domain, Value, HashKey >::getMaxCollisions() const
770 unsigned int count = 0;
771 unsigned int arraySize = 1 << myKeySize;
772 for ( unsigned int i = 0; i < arraySize; ++i )
776 unsigned int collision = getNbNodes ( i ) - 1;
777 if ( collision > count )
786 //------------------------------------------------------------------------------
787 template <typename Domain, typename Value, typename HashKey >
790 ImageContainerByHashTree<Domain, Value, HashKey >::className() const
792 return "ImageContainerByHashTree";
795 template <typename Domain, typename Value, typename HashKey >
797 ImageContainerByHashTree<Domain, Value, HashKey >::blendChildren ( HashKey key ) const
799 Node* n = getNode ( key );
802 return n->getObject();
806 HashKey children[myN];
807 myMorton.childrenKeys ( key, children );
809 for ( unsigned int i = 0; i < myN; ++i )
811 result += blendChildren ( children[i] );
813 return static_cast<Value> ( result / myN );
818 template <typename Domain, typename Value, typename HashKey >
820 ImageContainerByHashTree<Domain, Value, HashKey >::checkIntegrity ( HashKey key, bool leafAbove ) const
822 trace.info() << "Checking key=" << key << std::endl;
823 if ( !isKeyValid ( key ) )
825 trace.error() << "checkIntegrity->invalid key " << Bits::bitString ( key );
826 trace.info() << std::endl;
830 Node* n = getNode ( key );
832 if ( ( n != 0 ) && ( leafAbove ) )
834 trace.error() << "ImageContainerByHashTree::checkIntegrity - error:" << std::endl
835 << "at key " << Bits::bitString ( key ) << std::endl
836 << "several leafs found" << std::endl;
840 if ( getKeyDepth ( key ) >= myTreeDepth )
842 if ( leafAbove || n )
848 trace.error() << "ImageContainerByHashTree::checkIntegrity - error:" << std::endl
849 << "at key " << Bits::bitString ( key ) << std::endl
850 << "no leaf found" << std::endl;
855 HashKey children[myN];
856 myMorton.childrenKeys ( key, children );
857 bool returnValue = true;
858 for ( unsigned int i = 0; i < myN; ++i )
859 returnValue &= checkIntegrity ( children[i], ( n || leafAbove ) );
866 ///////////////////////////////////////////////////////////////////////////////
867 // Interface - public :
870 * Writes/Displays the object on an output stream.
871 * @param out the output stream where the object is written.
873 template < typename Domain, typename Value, typename HashKey>
876 ImageContainerByHashTree< Domain, Value, HashKey>::selfDisplay ( std::ostream & out ) const
883///////////////////////////////////////////////////////////////////////////////