2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file IntegerComputer.ih
19 * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20 * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
24 * Implementation of inline methods defined in IntegerComputer.h
26 * This file is part of the DGtal library.
30 //////////////////////////////////////////////////////////////////////////////
32 //////////////////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////////////////
35 // IMPLEMENTATION of inline methods.
36 ///////////////////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////////
39 // ----------------------- Standard services ------------------------------
41 //-----------------------------------------------------------------------------
42 template <typename TInteger>
44 DGtal::IntegerComputer<TInteger>::~IntegerComputer()
46 //-----------------------------------------------------------------------------
47 template <typename TInteger>
49 DGtal::IntegerComputer<TInteger>::IntegerComputer()
51 //-----------------------------------------------------------------------------
52 template <typename TInteger>
54 DGtal::IntegerComputer<TInteger>::IntegerComputer( const Self & /*other*/ )
56 //-----------------------------------------------------------------------------
57 template <typename TInteger>
59 DGtal::IntegerComputer<TInteger> &
60 DGtal::IntegerComputer<TInteger>::operator=( const Self & /*other*/ )
64 //-----------------------------------------------------------------------------
65 // ----------------------- Integer services ------------------------------
66 //-----------------------------------------------------------------------------
67 template <typename TInteger>
70 DGtal::IntegerComputer<TInteger>::
71 isZero( IntegerParamType a )
73 return a == NumberTraits<Integer>::ZERO;
75 //-----------------------------------------------------------------------------
76 template <typename TInteger>
79 DGtal::IntegerComputer<TInteger>::
80 isNotZero( IntegerParamType a )
82 return a != NumberTraits<Integer>::ZERO;
84 //-----------------------------------------------------------------------------
85 template <typename TInteger>
88 DGtal::IntegerComputer<TInteger>::
89 isPositive( IntegerParamType a )
91 return a > NumberTraits<Integer>::ZERO;
93 //-----------------------------------------------------------------------------
94 template <typename TInteger>
97 DGtal::IntegerComputer<TInteger>::
98 isNegative( IntegerParamType a )
100 return a < NumberTraits<Integer>::ZERO;
102 //-----------------------------------------------------------------------------
103 template <typename TInteger>
106 DGtal::IntegerComputer<TInteger>::
107 isPositiveOrZero( IntegerParamType a )
109 return a >= NumberTraits<Integer>::ZERO;
111 //-----------------------------------------------------------------------------
112 template <typename TInteger>
115 DGtal::IntegerComputer<TInteger>::
116 isNegativeOrZero( IntegerParamType a )
118 return a <= NumberTraits<Integer>::ZERO;
120 //-----------------------------------------------------------------------------
121 template <typename TInteger>
123 typename DGtal::IntegerComputer<TInteger>::Integer
124 DGtal::IntegerComputer<TInteger>::
125 abs( IntegerParamType a )
127 if ( isPositiveOrZero( a ) )
132 //-----------------------------------------------------------------------------
133 template <typename TInteger>
135 typename DGtal::IntegerComputer<TInteger>::Integer
136 DGtal::IntegerComputer<TInteger>::
137 max( IntegerParamType a, IntegerParamType b )
139 return ( a >= b ) ? a : b;
141 //-----------------------------------------------------------------------------
142 template <typename TInteger>
144 typename DGtal::IntegerComputer<TInteger>::Integer
145 DGtal::IntegerComputer<TInteger>::
146 max( IntegerParamType a, IntegerParamType b, IntegerParamType c )
148 return max( max(a,b), c );
150 //-----------------------------------------------------------------------------
151 template <typename TInteger>
153 typename DGtal::IntegerComputer<TInteger>::Integer
154 DGtal::IntegerComputer<TInteger>::
155 min( IntegerParamType a, IntegerParamType b )
157 return ( a <= b ) ? a : b;
159 //-----------------------------------------------------------------------------
160 template <typename TInteger>
162 typename DGtal::IntegerComputer<TInteger>::Integer
163 DGtal::IntegerComputer<TInteger>::
164 min( IntegerParamType a, IntegerParamType b, IntegerParamType c )
166 return min( min(a,b), c );
168 //-----------------------------------------------------------------------------
169 template <typename TInteger>
172 DGtal::IntegerComputer<TInteger>::
173 getEuclideanDiv( Integer & q, Integer & r,
174 IntegerParamType a, IntegerParamType b ) const
179 //-----------------------------------------------------------------------------
180 template <typename TInteger>
182 typename DGtal::IntegerComputer<TInteger>::Integer
183 DGtal::IntegerComputer<TInteger>::
184 floorDiv( IntegerParamType na, IntegerParamType nb ) const
188 if ( isNegative( _m_b ) )
193 // if ( isNegative( _m_a ) && isNegative( _m_b ) )
198 // else if ( isNegative( _m_b ) )
203 if ( isPositive( _m_a ) || isZero( _m_a % _m_b ) )
206 return _m_a/_m_b - NumberTraits<Integer>::ONE;
208 //-----------------------------------------------------------------------------
209 template <typename TInteger>
211 typename DGtal::IntegerComputer<TInteger>::Integer
212 DGtal::IntegerComputer<TInteger>::
213 ceilDiv( IntegerParamType na, IntegerParamType nb ) const
217 if ( isNegative( _m_b ) )
222 // if ( isNegative( _m_a ) && isNegative( _m_b ) )
227 // else if ( isNegative( _m_b ) )
232 if ( isNegative( _m_a ) || isZero( _m_a % _m_b ) )
235 return _m_a/_m_b + NumberTraits<Integer>::ONE;
237 //-----------------------------------------------------------------------------
238 template <typename TInteger>
241 DGtal::IntegerComputer<TInteger>::
242 getFloorCeilDiv( Integer & fl, Integer & ce,
243 IntegerParamType na, IntegerParamType nb ) const
247 if ( isNegative( _m_b ) )
253 if ( isNotZero( _m_a % _m_b ) )
255 if ( isNegativeOrZero( _m_a ) ) --fl;
256 if ( isPositiveOrZero( _m_a ) ) ++ce;
259 //-----------------------------------------------------------------------------
260 template <typename TInteger>
262 typename DGtal::IntegerComputer<TInteger>::Integer
263 DGtal::IntegerComputer<TInteger>::
264 staticGcd( IntegerParamType a, IntegerParamType b )
266 Integer _m_a = abs( a );
267 Integer _m_b = abs( b );
268 Integer _m_a0 = max( _m_a, _m_b );
269 Integer _m_a1 = min( _m_a, _m_b );
271 while ( isNotZero( _m_a1 ) )
273 _m_r = _m_a0 % _m_a1;
279 //-----------------------------------------------------------------------------
280 template <typename TInteger>
282 typename DGtal::IntegerComputer<TInteger>::Integer
283 DGtal::IntegerComputer<TInteger>::
284 gcd( IntegerParamType a, IntegerParamType b ) const
288 _m_a0 = max( _m_a, _m_b );
289 _m_a1 = min( _m_a, _m_b );
290 while ( isNotZero( _m_a1 ) )
292 _m_r = _m_a0 % _m_a1;
298 //-----------------------------------------------------------------------------
299 template <typename TInteger>
302 DGtal::IntegerComputer<TInteger>::
303 getGcd( Integer & g, IntegerParamType a, IntegerParamType b ) const
305 // std::cerr << "gcd(" << a << ", " << b << ")=";
308 _m_a0 = max( _m_a, _m_b );
309 _m_a1 = min( _m_a, _m_b );
310 while ( isNotZero( _m_a1 ) )
312 _m_r = _m_a0 % _m_a1;
318 //-----------------------------------------------------------------------------
319 template <typename TInteger>
321 typename DGtal::IntegerComputer<TInteger>::Integer
322 DGtal::IntegerComputer<TInteger>::
323 getCFrac( std::vector<Integer> & quotients,
324 IntegerParamType a, IntegerParamType b ) const
326 ASSERT( isPositiveOrZero( a ) && isPositiveOrZero( b ) );
329 while ( isNotZero( _m_a1 ) )
331 getEuclideanDiv( _m_q, _m_r, _m_a0, _m_a1 );
332 quotients.push_back( _m_q );
338 //-----------------------------------------------------------------------------
339 template <typename TInteger>
340 template <typename OutputIterator>
342 typename DGtal::IntegerComputer<TInteger>::Integer
343 DGtal::IntegerComputer<TInteger>::
344 getCFrac( OutputIterator outIt,
345 IntegerParamType a, IntegerParamType b ) const
347 BOOST_CONCEPT_ASSERT(( boost::OutputIterator< OutputIterator, Integer > ));
348 ASSERT( isPositiveOrZero( a ) && isPositiveOrZero( b ) );
351 while ( isNotZero( _m_a1 ) )
353 getEuclideanDiv( _m_q, _m_r, _m_a0, _m_a1 );
360 //-----------------------------------------------------------------------------
361 template <typename TInteger>
363 typename DGtal::IntegerComputer<TInteger>::Point2I
364 DGtal::IntegerComputer<TInteger>::
365 convergent( const std::vector<Integer> & quotients,
366 unsigned int k ) const
368 _m_bezout[ 0 ].clear(); // p
369 _m_bezout[ 0 ].push_back( NumberTraits<Integer>::ZERO );
370 _m_bezout[ 0 ].push_back( NumberTraits<Integer>::ONE );
371 _m_bezout[ 1 ].clear(); // q
372 _m_bezout[ 1 ].push_back( NumberTraits<Integer>::ONE );
373 _m_bezout[ 1 ].push_back( NumberTraits<Integer>::ZERO );
374 if ( k >= quotients.size() )
375 k = (quotients.size() - 1);
376 for ( unsigned int i = 0; i <= k; ++i )
378 _m_bezout[ 0 ].push_back( quotients[ i ] * _m_bezout[ 0 ][ i + 1 ]
379 + _m_bezout[ 0 ][ i ] );
380 _m_bezout[ 1 ].push_back( quotients[ i ] * _m_bezout[ 1 ][ i + 1 ]
381 + _m_bezout[ 1 ][ i ] );
383 _m_v[ 0 ] = _m_bezout[ 0 ].back();
384 _m_v[ 1 ] = _m_bezout[ 1 ].back();
387 //-----------------------------------------------------------------------------
388 // ----------------------- Point2I services ------------------------------
389 //-----------------------------------------------------------------------------
390 template <typename TInteger>
393 DGtal::IntegerComputer<TInteger>::
394 reduce( Vector2I & p ) const
396 _m_a = gcd( p[ 0 ], p[ 1 ] );
397 if ( ( _m_a != NumberTraits<Integer>::ONE ) && ( isNotZero( _m_a ) ) )
400 //-----------------------------------------------------------------------------
401 template <typename TInteger>
403 typename DGtal::IntegerComputer<TInteger>::Integer
404 DGtal::IntegerComputer<TInteger>::
405 crossProduct( const Vector2I & u, const Vector2I & v) const
407 _m_a0 = u[ 0 ] * v[ 1 ];
408 _m_a1 = u[ 1 ] * v[ 0 ];
409 return _m_a0 - _m_a1;
411 //-----------------------------------------------------------------------------
412 template <typename TInteger>
415 DGtal::IntegerComputer<TInteger>::
416 getCrossProduct( Integer & cp,
417 const Vector2I & u, const Vector2I & v) const
419 cp = u[ 0 ] * v[ 1 ];
420 cp -= u[ 1 ] * v[ 0 ];
422 //-----------------------------------------------------------------------------
423 template <typename TInteger>
425 typename DGtal::IntegerComputer<TInteger>::Integer
426 DGtal::IntegerComputer<TInteger>::
427 dotProduct( const Vector2I & u, const Vector2I & v ) const
429 _m_a0 = u[ 0 ] * v[ 0 ];
430 _m_a1 = u[ 1 ] * v[ 1 ];
431 return _m_a0 + _m_a1;
433 //-----------------------------------------------------------------------------
434 template <typename TInteger>
437 DGtal::IntegerComputer<TInteger>::
438 getDotProduct( Integer & dp,
439 const Vector2I & u, const Vector2I & v) const
441 dp = u[ 0 ] * v[ 0 ];
442 dp += u[ 1 ] * v[ 1 ];
444 //-----------------------------------------------------------------------------
445 template <typename TInteger>
446 typename DGtal::IntegerComputer<TInteger>::Vector2I
447 DGtal::IntegerComputer<TInteger>::
448 extendedEuclid( IntegerParamType a, IntegerParamType b,
449 IntegerParamType c ) const
451 if( isZero( a ) ) return Point2I( NumberTraits<Integer>::ZERO, b * c );
452 if( isZero( b ) ) return Point2I( a * c, NumberTraits<Integer>::ZERO );
454 for ( unsigned int i = 0; i < 4; ++i )
455 _m_bezout[ i ].clear();
457 _m_bezout[ 0 ].push_back( abs( a ) );
458 _m_bezout[ 0 ].push_back( abs( b ) );
459 _m_bezout[ 1 ].push_back( NumberTraits<Integer>::ZERO );
460 _m_bezout[ 2 ].push_back( NumberTraits<Integer>::ONE );
461 _m_bezout[ 2 ].push_back( NumberTraits<Integer>::ZERO );
462 _m_bezout[ 3 ].push_back( NumberTraits<Integer>::ZERO );
463 _m_bezout[ 3 ].push_back( NumberTraits<Integer>::ONE );
465 unsigned int k = 0; // index of the iteration during the computation.
466 while( isNotZero( _m_bezout[ 0 ][ k+1 ] ) )
468 _m_bezout[ 1 ].push_back( _m_bezout[ 0 ][ k ]
469 / _m_bezout[ 0 ][ k+1 ] );
470 _m_bezout[ 0 ].push_back( _m_bezout[ 0 ][ k ]
471 % _m_bezout[ 0 ][ k+1 ] );
472 _m_bezout[ 2 ].push_back( _m_bezout[ 2 ][ k ]
473 - _m_bezout[ 1 ][ k+1 ]
474 * _m_bezout[ 2 ][ k+1 ] );
475 _m_bezout[ 3 ].push_back( _m_bezout[ 3 ][ k ]
476 - _m_bezout[ 1 ][ k+1 ]
477 *_m_bezout[ 3 ][ k+1 ] );
481 _m_v[ 0 ] = _m_bezout[ 2 ][ k ];
482 _m_v[ 1 ] = _m_bezout[ 3 ][ k ];
485 _m_v[ 0 ] = abs( b ) + _m_bezout[ 2 ][ k ];
486 _m_v[ 1 ] = -abs( a ) + _m_bezout[ 3 ][ k ];
488 // choose sgn(a) = sgn(x) when x != 0, iff c > 0
489 // |x| <= |bc|, |y| < |ac|
490 _m_v *= c / _m_bezout[ 0 ][ k ]; // c / gcd(a,b)
491 if ( isNegative( a ) ) _m_v[ 0 ] = - _m_v[ 0 ];
492 if ( isNegative( b ) ) _m_v[ 1 ] = - _m_v[ 1 ];
493 // std::cout << "a * x + b * y == c, "
494 // << a << " * " << _m_v[ 0 ] << " + " << b << " * " << _m_v[ 1 ] << " == " << c << std::endl;
495 ASSERT( (a*_m_v[ 0 ]+b*_m_v[ 1 ]) == c );
496 ASSERT( isNegative( c ) || ( ( isPositive( a ) == isPositive( _m_v[ 0 ] ) ) || isZero( _m_v[ 0 ] ) ) );
497 ASSERT( isPositive( c ) || ( ( isPositive( a ) == isNegative( _m_v[ 0 ] ) ) || isZero( _m_v[ 0 ] ) ) );
498 ASSERT( abs( _m_v[ 0 ] ) <= abs( b*c ) );
499 ASSERT( abs( _m_v[ 1 ] ) < abs( a*c ) );
502 //-----------------------------------------------------------------------------
503 template <typename TInteger>
506 DGtal::IntegerComputer<TInteger>::
507 getCoefficientIntersection( Integer & fl, Integer & ce,
511 IntegerParamType c ) const
513 getDotProduct( _m_c0, p, N );
514 getDotProduct( _m_c1, u, N );
516 fl = floorDiv( _m_c2, _m_c1 );
517 ce = ceilDiv( _m_c2, _m_c1 );
518 // getFloorCeilDiv( fl, ce, _m_c2, _m_c1 );
520 //-----------------------------------------------------------------------------
521 template <typename TInteger>
524 DGtal::IntegerComputer<TInteger>::
525 getValidBezout ( Vector2I & v,
526 const Point2I & A, const Vector2I & u,
527 const Vector2I & N, IntegerParamType c,
528 const Vector2I & N2, IntegerParamType c2,
529 bool compute_v ) const
533 v = extendedEuclid( -u[ 1 ], u[ 0 ], NumberTraits<Integer>::ONE );
535 getDotProduct( _m_c0, _m_v0, N );
544 getCoefficientIntersection( _m_a0, _m_a1,
546 _m_v1 = u * _m_a0; // floor value
548 ASSERT( N2.dot( A + v ) <= c2 );
549 ASSERT( N2.dot( A + v + u ) > c2 );
551 //-----------------------------------------------------------------------------
552 template <typename TInteger>
555 DGtal::IntegerComputer<TInteger>::
556 reduce( Vector3I & p ) const
558 _m_a = gcd( p[ 0 ], p[ 1 ] );
559 _m_r = gcd( _m_a, p[ 2 ] );
562 //-----------------------------------------------------------------------------
563 template <typename TInteger>
565 typename DGtal::IntegerComputer<TInteger>::Integer
566 DGtal::IntegerComputer<TInteger>::
567 dotProduct( const Vector3I & u, const Vector3I & v) const
569 _m_a0 = u[ 0 ] * v[ 0 ];
570 _m_a0 += u[ 1 ] * v[ 1 ];
571 _m_a0 += u[ 2 ] * v[ 2 ];
574 //-----------------------------------------------------------------------------
575 template <typename TInteger>
578 DGtal::IntegerComputer<TInteger>::
579 getDotProduct( Integer & dp,
580 const Vector3I & u, const Vector3I & v) const
582 dp = u[ 0 ] * v[ 0 ];
583 dp += u[ 1 ] * v[ 1 ];
584 dp += u[ 2 ] * v[ 2 ];
588 ///////////////////////////////////////////////////////////////////////////////
589 // Interface - public :
592 * Writes/Displays the object on an output stream.
593 * @param out the output stream where the object is written.
595 template <typename TInteger>
598 DGtal::IntegerComputer<TInteger>::selfDisplay ( std::ostream & out ) const
600 out << "[IntegerComputer]";
604 * Checks the validity/consistency of the object.
605 * @return 'true' if the object is valid, 'false' otherwise.
607 template <typename TInteger>
610 DGtal::IntegerComputer<TInteger>::isValid() const
617 ///////////////////////////////////////////////////////////////////////////////
618 // Implementation of inline functions //
620 template <typename TInteger>
623 DGtal::operator<< ( std::ostream & out,
624 const IntegerComputer<TInteger> & object )
626 object.selfDisplay( out );
631 ///////////////////////////////////////////////////////////////////////////////