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 ) );
383 template < typename Domain, typename Value, typename HashKey >
386 ImageContainerByHashTree<Domain, Value, HashKey >::upwardGet ( const HashKey key ) const
388 //cerr << "ImageContainerByHashTree::upWardGet" << std::endl;
393 HashKey key2 = getIntermediateKey ( aKey );
394 Node* iter = myData[key2];
398 if ( iter->getKey() == aKey )
399 return iter->getObject();
400 iter = iter->getNext();
402 aKey >>= dim; // transorm the key to search in an upper level
406 template < typename Domain, typename Value, typename HashKey >
409 ImageContainerByHashTree<Domain, Value, HashKey >::getKey ( const Point & aPoint ) const
412 Point currentPos = aPoint - myOrigin;
414 myMorton.interleaveBits ( currentPos, result );
415 // by convention, the root node has the key 0..01
416 // it makes it easy to determine the depth of a node by it's key (looking
417 // at the position of the most significant bit that is equal to 1)
418 result |= myDepthMask;
423 template < typename Domain, typename Value, typename HashKey >
426 ImageContainerByHashTree<Domain, Value, HashKey >::getIntermediateKey ( HashKey key ) const
428 return ( key & myPreComputedIntermediateMask );
432 template < typename Domain, typename Value, typename HashKey >
435 ImageContainerByHashTree<Domain, Value, HashKey >::Iterator::next()
439 myNode = myNode->getNext();
448 myNode = myContainerData[++myCurrentCell];
449 if ( myCurrentCell >= myArraySize )
459 // ---------------------------------------------------------------------
461 // ---------------------------------------------------------------------
463 template < typename Domain, typename Value, typename HashKey >
466 ImageContainerByHashTree<Domain, Value, HashKey >::removeNode ( HashKey key )
468 HashKey key2 = getIntermediateKey ( key );
469 Node* iter = myData[key2];
470 // if the node is the first in the list we have to modify the pointer stored in myData
471 if ( iter && ( iter->getKey() == key ) )
473 myData[key2] = iter->getNext();
479 Node* next = iter->getNext();
482 if ( next->getKey() == key )
484 iter->setNext ( next->getNext() );
489 iter = iter->getNext();
494 template < typename Domain, typename Value, typename HashKey >
497 ImageContainerByHashTree<Domain, Value, HashKey >::recursiveRemoveNode ( HashKey key, unsigned int nbRecursions )
499 if ( removeNode ( key ) )
501 if ( --nbRecursions > 0 )
503 HashKey children[myN];
504 myMorton.childrenKeys ( key, children );
505 for ( unsigned int i = 0; i < myN; ++i )
507 recursiveRemoveNode ( children[i], nbRecursions );
514 // ---------------------------------------------------------------------
516 // ---------------------------------------------------------------------
518 template < typename Domain, typename Value, typename HashKey >
521 ImageContainerByHashTree<Domain, Value, HashKey >::setDepth ( unsigned int depth )
524 mySpanSize = 1 << depth;
525 //precompute the mask
526 myDepthMask = static_cast<HashKey> ( 1 ) << dim * depth;
530 template < typename Domain, typename Value, typename HashKey >
533 ImageContainerByHashTree<Domain, Value, HashKey >::getKeyDepth ( HashKey key ) const
535 for ( int i = ( sizeof ( HashKey ) << 3 ) - 1; i >= 0; --i )
536 if ( key & ( static_cast<HashKey> ( 1 ) << i ) )
544 template < typename Domain, typename Value, typename HashKey >
547 ImageContainerByHashTree<Domain, Value, HashKey >::getCoordinatesFromKey ( HashKey key ) const
549 //remove the first bit equal 1
550 for ( int i = ( sizeof ( HashKey ) << 3 ) - 1; i >= 0; --i )
552 if ( key & Bits::mask<HashKey> ( i ) )
554 key &= ~Bits::mask<HashKey> ( i );
558 int* coordinates = new int[dim];
559 //deinterleave the bits
560 for ( unsigned int i = 0; i < dim; ++i )
563 for ( unsigned int bitPos = 0; bitPos < ( sizeof ( HashKey ) << 3 ) / dim; ++bitPos )
565 if ( key & Bits::mask ( bitPos*dim + i ) )
567 coordinates[i] |= Bits::mask<HashKey> ( bitPos );
575 template < typename Domain, typename Value, typename HashKey >
578 ImageContainerByHashTree<Domain, Value, HashKey >::isKeyValid ( HashKey key ) const
582 if ( getKeyDepth ( key ) > myTreeDepth )
585 int i = ( sizeof ( HashKey ) << 3 ) - 1;
586 for ( ; i >= 0; --i )
587 if ( key & ( static_cast<HashKey> ( 1 ) << i ) )
599 // ---------------------------------------------------------------------
601 // ---------------------------------------------------------------------
602 template <typename Domain, typename Value , typename HashKey >
605 ImageContainerByHashTree<Domain, Value, HashKey >::printState ( std::ostream& out, bool displayKeys ) const
607 out << "ImageContainerByHashTree::printState" << std::endl;
608 out << "depth: " << myTreeDepth << " (" << Bits::bitString ( myDepthMask ) << ")" << std::endl;
609 out << "dim: " << dim << "myN: " << myN << std::endl;
610 printTree ( ROOT_KEY, out, displayKeys );
613 template <typename Domain, typename Value, typename HashKey >
616 ImageContainerByHashTree<Domain, Value, HashKey >::printTree ( HashKey key, std::ostream& out, bool displayKeys ) const
618 unsigned int level = getKeyDepth ( key );
619 for ( unsigned int i = 0; i < level; ++i )
621 Node* n = getNode ( key );
624 out << " < " << n->getObject() << " > ";
626 out << Bits::bitString ( key, 8 );
633 out << Bits::bitString ( key, 8 );
637 if ( level < myTreeDepth )
639 HashKey children[myN];
640 myMorton.childrenKeys ( key, children );
641 for ( unsigned int i = 0; i < myN; ++i )
642 printTree ( children[i], out, displayKeys );
646 template <typename Domain, typename Value, typename HashKey >
649 ImageContainerByHashTree<Domain, Value, HashKey >::printInternalState ( std::ostream& out, unsigned int nbBits ) const
651 out << "ImageContainerByHashTree::printInternalState ----------------------------------" << std::endl;
652 out << "| <template> dim = " << dim << " myN = " << myN << std::endl;
653 out << "| tree depth = " << myTreeDepth << " mask = " << Bits::bitString ( myDepthMask ) << std::endl;
655 for ( unsigned int i = 0; i < ( 1 << myKeySize ); ++i )
657 out << "| " << Bits::bitString ( i, myKeySize ) << " [";
662 out << Bits::bitString ( myData[i]->getKey(), nbBits ) << ":";
663 out << myData[i]->getObject() << ")";
664 Node* iter = myData[i]->getNext();
669 out << Bits::bitString ( myData[i]->getKey(), nbBits ) << ":";
670 out << iter->getObject() << ")";
671 iter = iter->getNext();
677 std::cout << "x]" << std::endl;
681 out << "| image size: " << getSpanSize() << "^" << dim << " (" << std::pow ( getSpanSize(), dim ) *sizeof ( Value ) << " bytes)" << std::endl;
682 out << "| " << getNbNodes() << " nodes - Empty lists: " << getNbEmptyLists() << " (" << getNbEmptyLists() *sizeof ( Node* ) << " bytes)" << std::endl;
683 out << "| Average collisions: " << getAverageCollisions() << " - Max collisions " << getMaxCollisions() << std::endl;
684 out << "----------------------------------------------------------------" << std::endl;
688 template <typename Domain, typename Value, typename HashKey >
691 ImageContainerByHashTree<Domain, Value, HashKey >::printInfo ( std::ostream& out ) const
693 unsigned int nbNodes = getNbNodes();
694 unsigned int totalSize = sizeof ( *this ) + ( 1 << myKeySize ) * sizeof ( Node* ) + nbNodes * sizeof ( Node );
696 out << "[ImageContainerByHashTree]: Dimension=" << ( int ) dim << ", HashKey size="
697 << myKeySize << ", Depth=" << myTreeDepth << ", image size=" << getSpanSize()
698 << "^" << ( int ) dim << " (" << std::pow ( ( double ) getSpanSize(), ( double ) dim ) *sizeof ( Value )
699 << " bytes)" << ", " << nbNodes << " nodes" << ", Empty lists=" << getNbEmptyLists()
700 << " (" << getNbEmptyLists() *sizeof ( Node* ) << " bytes)" << ", Average collisions=" << getAverageCollisions()
701 << ", Max collisions " << getMaxCollisions()
702 << ", total memory usage=" << totalSize << " bytes" << std::endl;
707 template <typename Domain, typename Value, typename HashKey >
710 ImageContainerByHashTree<Domain, Value, HashKey >::getNbNodes ( unsigned int intermediateKey ) const
712 if ( !myData[intermediateKey] )
718 unsigned int count = 1;
719 Node* n = myData[intermediateKey]->getNext();
731 template <typename Domain, typename Value, typename HashKey >
734 ImageContainerByHashTree<Domain, Value, HashKey >::getNbNodes() const
736 unsigned int count = 0;
737 unsigned int arraySize = 1 << myKeySize;
738 for ( unsigned int i = 0; i < arraySize; ++i )
740 count += getNbNodes ( i );
746 template <typename Domain, typename Value, typename HashKey >
749 ImageContainerByHashTree<Domain, Value, HashKey >::getNbEmptyLists() const
751 unsigned int count = 0;
752 unsigned int arraySize = 1 << myKeySize;
753 for ( unsigned int i = 0; i < arraySize; ++i )
762 template<typename Domain, typename Value, typename HashKey >
765 ImageContainerByHashTree<Domain, Value, HashKey >::getAverageCollisions() const
769 unsigned int arraySize = 1 << myKeySize;
770 for ( unsigned int i = 0; i < arraySize; ++i )
774 count += getNbNodes ( i ) - 1;
780 trace.error() << "ImageContainerByHashTree::getAverageCollision() - error" << std::endl
781 << "the container is empty !" << std::endl;
784 return count / nbLists;
789 template <typename Domain, typename Value, typename HashKey >
792 ImageContainerByHashTree<Domain, Value, HashKey >::getMaxCollisions() const
794 unsigned int count = 0;
795 unsigned int arraySize = 1 << myKeySize;
796 for ( unsigned int i = 0; i < arraySize; ++i )
800 unsigned int collision = getNbNodes ( i ) - 1;
801 if ( collision > count )
810 //------------------------------------------------------------------------------
811 template <typename Domain, typename Value, typename HashKey >
814 ImageContainerByHashTree<Domain, Value, HashKey >::className() const
816 return "ImageContainerByHashTree";
819 template <typename Domain, typename Value, typename HashKey >
821 ImageContainerByHashTree<Domain, Value, HashKey >::blendChildren ( HashKey key ) const
823 Node* n = getNode ( key );
826 return n->getObject();
830 HashKey children[myN];
831 myMorton.childrenKeys ( key, children );
833 for ( unsigned int i = 0; i < myN; ++i )
835 result += blendChildren ( children[i] );
837 return static_cast<Value> ( result / myN );
842 template <typename Domain, typename Value, typename HashKey >
844 ImageContainerByHashTree<Domain, Value, HashKey >::checkIntegrity ( HashKey key, bool leafAbove ) const
846 trace.info() << "Checking key=" << key << std::endl;
847 if ( !isKeyValid ( key ) )
849 trace.error() << "checkIntegrity->invalid key " << Bits::bitString ( key );
850 trace.info() << std::endl;
854 Node* n = getNode ( key );
856 if ( ( n != 0 ) && ( leafAbove ) )
858 trace.error() << "ImageContainerByHashTree::checkIntegrity - error:" << std::endl
859 << "at key " << Bits::bitString ( key ) << std::endl
860 << "several leafs found" << std::endl;
864 if ( getKeyDepth ( key ) >= myTreeDepth )
866 if ( leafAbove || n )
872 trace.error() << "ImageContainerByHashTree::checkIntegrity - error:" << std::endl
873 << "at key " << Bits::bitString ( key ) << std::endl
874 << "no leaf found" << std::endl;
879 HashKey children[myN];
880 myMorton.childrenKeys ( key, children );
881 bool returnValue = true;
882 for ( unsigned int i = 0; i < myN; ++i )
883 returnValue &= checkIntegrity ( children[i], ( n || leafAbove ) );
890 ///////////////////////////////////////////////////////////////////////////////
891 // Interface - public :
894 * Writes/Displays the object on an output stream.
895 * @param out the output stream where the object is written.
897 template < typename Domain, typename Value, typename HashKey>
900 ImageContainerByHashTree< Domain, Value, HashKey>::selfDisplay ( std::ostream & out ) const
907 ///////////////////////////////////////////////////////////////////////////////