DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
SternBrocot.ih
1 
32 
33 #include <cstdlib>
34 #include "DGtal/arithmetic/IntegerComputer.h"
36 
38 // IMPLEMENTATION of inline methods.
40 
42 // ----------------------- Standard services ------------------------------
43 
45 // DGtal::SternBrocot<TInteger, TQuotient>::Node
46 //-----------------------------------------------------------------------------
47 template <typename TInteger, typename TQuotient>
48 inline
51  Node* ascendant_left1, Node* ascendant_right1,
52  Node* descendant_left1, Node* descendant_right1,
53  Node* inverse1 )
54  : p( p1 ), q( q1 ), u( u1 ), k( k1 ),
55  ascendantLeft( ascendant_left1 ),
56  ascendantRight( ascendant_right1 ),
57  descendantLeft( descendant_left1 ),
58  descendantRight( descendant_right1 ),
59  inverse( inverse1 )
60 {
61  // std::cerr << "(" << p1 << "/" << q1 << "," << u1 << "," << k1 << ")";
62 }
63 
65 // DGtal::SternBrocot<TInteger, TQuotient>::Fraction
66 //-----------------------------------------------------------------------------
67 template <typename TInteger, typename TQuotient>
68 inline
70 Fraction( Integer aP, Integer aQ, Fraction ancestor )
71 {
72  this->operator=( SternBrocotTree::fraction( aP, aQ, ancestor ) );
73 }
74 //-----------------------------------------------------------------------------
75 template <typename TInteger, typename TQuotient>
76 inline
78 Fraction( Node* sb_node )
79  : myNode( sb_node )
80 {
81 }
82 //-----------------------------------------------------------------------------
83 template <typename TInteger, typename TQuotient>
84 inline
86 Fraction( const Self & other )
87  : myNode( other.myNode )
88 {
89 }
90 //-----------------------------------------------------------------------------
91 template <typename TInteger, typename TQuotient>
92 inline
95 operator=( const Self & other )
96 {
97  if ( this != &other )
98  {
99  myNode = other.myNode;
100  }
101  return *this;
102 }
103 //-----------------------------------------------------------------------------
104 template <typename TInteger, typename TQuotient>
105 inline
106 bool
108 null() const
109 {
110  return myNode == 0;
111 }
112 //-----------------------------------------------------------------------------
113 template <typename TInteger, typename TQuotient>
114 inline
117 p() const
118 {
119  return myNode ? myNode->p : 0;
120 }
121 //-----------------------------------------------------------------------------
122 template <typename TInteger, typename TQuotient>
123 inline
126 q() const
127 {
128  return myNode ? myNode->q : 0;
129 }
130 //-----------------------------------------------------------------------------
131 template <typename TInteger, typename TQuotient>
132 inline
135 u() const
136 {
137  ASSERT( myNode != 0 );
138  return myNode->u;
139 }
140 //-----------------------------------------------------------------------------
141 template <typename TInteger, typename TQuotient>
142 inline
145 k() const
146 {
147  ASSERT( myNode != 0 );
148  return myNode->k;
149 }
150 //-----------------------------------------------------------------------------
151 template <typename TInteger, typename TQuotient>
152 inline
153 bool
155 equals( Integer p1, Integer q1 ) const
156 {
157  return ( this->p() == p1 ) && ( this->q() == q1 );
158 }
159 //-----------------------------------------------------------------------------
160 template <typename TInteger, typename TQuotient>
161 inline
162 bool
164 lessThan( Integer p1, Integer q1 ) const
165 {
166  Integer d = p() * q1 - q() * p1;
167  return d < NumberTraits<Integer>::ZERO;
168 }
169 //-----------------------------------------------------------------------------
170 template <typename TInteger, typename TQuotient>
171 inline
172 bool
174 moreThan( Integer p1, Integer q1 ) const
175 {
176  Integer d = p() * q1 - q() * p1;
177  return d > NumberTraits<Integer>::ZERO;
178 }
179 //-----------------------------------------------------------------------------
180 template <typename TInteger, typename TQuotient>
181 inline
182 bool
184 operator==( const Fraction & other ) const
185 {
186  return myNode == other.myNode;
187 }
188 //-----------------------------------------------------------------------------
189 template <typename TInteger, typename TQuotient>
190 inline
191 bool
193 operator!=( const Fraction & other ) const
194 {
195  return myNode != other.myNode;
196 }
197 //-----------------------------------------------------------------------------
198 template <typename TInteger, typename TQuotient>
199 inline
200 bool
202 operator<( const Fraction & other ) const
203 {
204  return this->lessThan( other.p(), other.q() );
205 }
206 //-----------------------------------------------------------------------------
207 template <typename TInteger, typename TQuotient>
208 inline
209 bool
211 operator>( const Fraction & other ) const
212 {
213  return this->moreThan( other.p(), other.q() );
214 }
215 //-----------------------------------------------------------------------------
216 template <typename TInteger, typename TQuotient>
217 inline
220 left() const
221 {
222  if ( myNode->descendantLeft == 0 )
223  {
224  Node* pleft = myNode->ascendantLeft;
225  Node* n = new Node( p() + pleft->p,
226  q() + pleft->q,
227  odd() ? u() + 1 : (Quotient) 2,
228  odd() ? k() : k() + 1,
229  pleft, myNode,
230  0, 0, 0 );
231  Fraction inv = Fraction( myNode->inverse );
232  Node* invpright = inv.myNode->ascendantRight;
233  Node* invn = new Node( inv.p() + invpright->p,
234  inv.q() + invpright->q,
235  inv.even() ? inv.u() + 1 : (Quotient) 2,
236  inv.even() ? inv.k() : inv.k() + 1,
237  myNode->inverse, invpright,
238  0, 0, n );
239  n->inverse = invn;
240  myNode->inverse->descendantRight = invn;
241  myNode->descendantLeft = n;
242  instance().nbFractions += 2;
243  }
244  return Fraction( myNode->descendantLeft );
245 }
246 //-----------------------------------------------------------------------------
247 template <typename TInteger, typename TQuotient>
248 inline
251 right() const
252 {
253  if ( myNode->descendantRight == 0 )
254  {
255  Fraction inv( myNode->inverse );
256  inv.left();
257  ASSERT( myNode->descendantRight != 0 );
258  }
259  return Fraction( myNode->descendantRight );
260 }
261 //-----------------------------------------------------------------------------
262 template <typename TInteger, typename TQuotient>
263 inline
264 bool
266 even() const
267 {
268  return ( k() & 1 ) == 0;
269 }
270 //-----------------------------------------------------------------------------
271 template <typename TInteger, typename TQuotient>
272 inline
273 bool
275 odd() const
276 {
277  return ( k() & 1 ) != 0;
278 }
279 //-----------------------------------------------------------------------------
280 template <typename TInteger, typename TQuotient>
281 inline
284 father() const
285 {
286  return Fraction( odd() ? myNode->ascendantRight : myNode->ascendantLeft );
287 }
288 //-----------------------------------------------------------------------------
289 template <typename TInteger, typename TQuotient>
290 inline
293 father( Quotient m ) const
294 {
295  if ( m > NumberTraits<Quotient>::ONE ) // > 1
296  {
297  Node* n = myNode;
298  while ( n->u > m )
299  n = odd() ? n->ascendantRight : n->ascendantLeft;
300  return Fraction( n );
301  }
302  else if ( m != NumberTraits<Quotient>::ZERO ) // == 1
303  {
304  return odd() ? previousPartial().right() : previousPartial().left();
305  }
306  else // == 0
307  return reduced( 2 ); //previousPartial().previousPartial();
308 }
309 //-----------------------------------------------------------------------------
310 template <typename TInteger, typename TQuotient>
311 inline
315 {
316  return Fraction( odd() ? myNode->ascendantLeft : myNode->ascendantRight );
317  // return Fraction( odd()
318  // ? myNode->ascendantLeft->descendantRight
319  // : myNode->ascendantRight->descendantLeft );
320 }
321 //-----------------------------------------------------------------------------
322 template <typename TInteger, typename TQuotient>
323 inline
326 inverse() const
327 {
328  return Fraction( myNode->inverse );
329 }
330 //-----------------------------------------------------------------------------
331 template <typename TInteger, typename TQuotient>
332 inline
335 partial( Quotient kp ) const
336 {
337  ASSERT( ( ((Quotient)-2) <= kp ) && ( kp <= k() ) );
338  return reduced( k() - kp );
339 }
340 //-----------------------------------------------------------------------------
341 template <typename TInteger, typename TQuotient>
342 inline
345 reduced( Quotient i ) const
346 {
347  ASSERT( ( ((Quotient)0) <= i ) && ( i <= ( k()+((Quotient)2) ) ) );
348  Node* n = this->myNode;
349 
350  bool bleft = ( n->k & NumberTraits<Quotient>::ONE )
352  while ( i-- > NumberTraits<Quotient>::ZERO )
353  {
354  n = bleft ? n->ascendantLeft : n->ascendantRight;
355  bleft = ! bleft;
356  }
357  return Fraction( n );
358 }
359 //-----------------------------------------------------------------------------
360 template <typename TInteger, typename TQuotient>
361 inline
362 void
364 push_back( const std::pair<Quotient, Quotient> & quotient )
365 {
366  pushBack( quotient );
367 }
368 //-----------------------------------------------------------------------------
369 template <typename TInteger, typename TQuotient>
370 inline
371 void
373 pushBack( const std::pair<Quotient, Quotient> & quotient )
374 {
375  // std::vector<Quotient> quots;
376  // if ( ! null() )
377  // {
378  // this->getCFrac( quots );
379  // std::cerr << "F[";
380  // for ( unsigned int i = 0; i < quots.size(); ++i )
381  // std::cerr << " " << quots[ i ];
382  // }
383  // else std::cerr << "[";
384  // std::cerr << "] + " << "(" << quotient.first
385  // << "," << quotient.second << ")";
386  if ( null() )
387  {
388  ASSERT( quotient.second <= NumberTraits<Quotient>::ZERO );
389  if ( quotient.second < NumberTraits<Quotient>::ZERO )
390  this->operator=( oneOverZero() );
391  else if ( quotient.first == NumberTraits<Quotient>::ZERO ) // (0,0)
392  this->operator=( zeroOverOne() );
393  else
394  {
395  Fraction f = zeroOverOne();
396  for ( Quotient i = 0; i < quotient.first; ++i )
397  f = f.right();
398  this->operator=( f );
399  }
400  }
401  else if ( NumberTraits<Quotient>::even( quotient.second ) )
402  {
403  Fraction f = left();
404  for ( Quotient i = 1; i < quotient.first; ++i )
405  f = f.right();
406  this->operator=( f );
407  }
408  else
409  {
410  Fraction f = right();
411  for ( Quotient i = 1; i < quotient.first; ++i )
412  f = f.left();
413  this->operator=( f );
414  }
415  // quots.clear();
416  // this->getCFrac( quots );
417  // std::cerr << " => F[";
418  // for ( unsigned int i = 0; i < quots.size(); ++i )
419  // std::cerr << " " << quots[ i ];
420  // std::cerr << "]" << std::endl;
421 }
422 //-----------------------------------------------------------------------------
423 template <typename TInteger, typename TQuotient>
424 inline
425 void
427 getSplit( Fraction & f1, Fraction & f2 ) const
428 {
429  f1.myNode = myNode->ascendantLeft;
430  f2.myNode = myNode->ascendantRight;
431 }
432 //-----------------------------------------------------------------------------
433 template <typename TInteger, typename TQuotient>
434 inline
435 void
438  Fraction & f2, Quotient & nb2 ) const
439 {
440  if ( odd() )
441  {
442  f1.myNode = myNode->ascendantLeft;
443  nb1 = this->u();
444  f2.myNode = f1.myNode->ascendantRight;
445  nb2 = 1;
446  }
447  else
448  {
449  f2.myNode = myNode->ascendantRight;
450  nb2 = this->u();
451  f1.myNode = f2.myNode->ascendantLeft;
452  nb1 = 1;
453  }
454 }
455 //-----------------------------------------------------------------------------
456 template <typename TInteger, typename TQuotient>
457 inline
458 void
460 getCFrac( std::vector<Quotient> & quotients ) const
461 {
462  ASSERT( this->k() >= NumberTraits<Quotient>::ZERO );
464  quotients.resize( (unsigned int)i + 1 );
465  quotients[ (unsigned int)i-- ] = this->u();
466  Node* n = myNode;
467  bool bleft = odd() ? true : false;
468  while ( i >= 0 )
469  {
470  ASSERT( n->k >= NumberTraits<Quotient>::ZERO );
471  n = bleft ? n->ascendantLeft : n->ascendantRight;
472  quotients[ (unsigned int)i ] =
473  ( i == NumberTraits<Quotient>::castToInt64_t( n->k ) ) ? n->u : 1;
474  --i;
475  bleft = ! bleft;
476  }
477 }
478 //-----------------------------------------------------------------------------
479 template <typename TInteger, typename TQuotient>
480 inline
483 begin() const
484 {
485  CFracSequence* seq = new CFracSequence;
486  this->getCFrac( *seq );
487  return ConstIterator( seq, seq->begin() );
488 }
489 //-----------------------------------------------------------------------------
490 template <typename TInteger, typename TQuotient>
491 inline
494 end() const
495 {
496  static CFracSequence dummy;
497  return ConstIterator( 0, dummy.end() );
498 }
499 //-----------------------------------------------------------------------------
500 template <typename TInteger, typename TQuotient>
501 inline
502 void
504 selfDisplay( std::ostream & out ) const
505 {
506  if ( this->null() ) out << "[Fraction null]";
507  else
508  {
509  out << "[Fraction f=" << this->p()
510  << "/" << this->q()
511  << " u=" << this->u()
512  << " k=" << this->k()
513  << std::flush;
514  std::vector<Quotient> quotients;
515  if ( this->k() >= 0 )
516  {
517  this->getCFrac( quotients );
518  out << " [" << quotients[ 0 ];
519  for ( unsigned int i = 1; i < quotients.size(); ++i )
520  out << "," << quotients[ i ];
521  out << "]";
522  }
523  out << " ]";
524  }
525 }
526 
528 // DGtal::SternBrocot<TInteger, TQuotient>
529 
530 //-----------------------------------------------------------------------------
531 template <typename TInteger, typename TQuotient>
532 inline
534 {
535  if ( myOneOverOne != 0 ) delete myOneOverOne;
536  if ( myOneOverZero != 0 ) delete myOneOverZero;
537  if ( myZeroOverOne != 0 ) delete myZeroOverOne;
538 }
539 //-----------------------------------------------------------------------------
540 template <typename TInteger, typename TQuotient>
541 inline
543 {
549  myZeroOverOne );
555  myOneOverZero );
561  myOneOverOne );
568  nbFractions = 3;
569 }
570 //-----------------------------------------------------------------------------
571 template <typename TInteger, typename TQuotient>
572 inline
575 {
576  if ( singleton == 0 )
577  singleton = new SternBrocot;
578  return *singleton;
579 }
580 
581 
582 //-----------------------------------------------------------------------------
583 template <typename TInteger, typename TQuotient>
584 inline
587 {
588  return Fraction( instance().myZeroOverOne );
589 }
590 //-----------------------------------------------------------------------------
591 template <typename TInteger, typename TQuotient>
592 inline
595 {
596  return Fraction( instance().myOneOverZero );
597 }
598 
600 // Interface - public :
601 
606 template <typename TInteger, typename TQuotient>
607 inline
608 void
610  const Fraction & f )
611 {
612  if ( f.null() ) out << "[Fraction null]";
613  else
614  {
615  out << "[Fraction f=" << f.p()
616  << "/" << f.q()
617  << " u=" << f.u()
618  << " k=" << f.k()
619  << std::flush;
620  std::vector<Quotient> quotients;
621  if ( f.k() >= 0 )
622  {
623  f.getCFrac( quotients );
624  out << " [" << quotients[ 0 ];
625  for ( unsigned int i = 1; i < quotients.size(); ++i )
626  out << "," << quotients[ i ];
627  out << "]";
628  }
629  out << " ]";
630  }
631 }
632 
637 template <typename TInteger, typename TQuotient>
638 inline
639 bool
641 {
642  return true;
643 }
644 
646 // class SternBrocot
648 template <typename TInteger, typename TQuotient>
649 inline
653  Fraction ancestor )
654 {
656  Integer g = ic.gcd( p, q );
657  if ( g != NumberTraits<Integer>::ZERO )
658  {
659  p /= g;
660  q /= g;
661  }
662  // special case 1/0
663  if ( ( p == NumberTraits<Integer>::ONE )
664  && ( q == NumberTraits<Integer>::ZERO ) ) return oneOverZero();
665  // other positive fractions
666  while ( ! ancestor.equals( p, q ) )
667  {
668  ASSERT( ( p + q ) >= ( ancestor.p() + ancestor.q() )
669  && "[ImaGene::SternBrocot::fraction] bad ancestor." );
670  ancestor = ancestor.lessThan( p, q )
671  ? ancestor.right()
672  : ancestor.left();
673  }
674  return ancestor;
675 }
676 
677 
679 // Implementation of inline functions //
680 
681 // JOL: invalid overloading
682 // template <typename TInteger, typename TQuotient>
683 // inline
684 // std::ostream&
685 // DGtal::operator<< ( std::ostream & out,
686 // const typename SternBrocot<TInteger, TQuotient>::Fraction & object )
687 // {
688 // typedef SternBrocot<TInteger,TQuotient> SB;
689 // SB::display( out, object );
690 // return out;
691 // }
692 
693 // //
695 
696