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//-----------------------------------------------------------------------------
42template <typename TInteger>
44DGtal::IntegerComputer<TInteger>::~IntegerComputer()
46//-----------------------------------------------------------------------------
47template <typename TInteger>
49DGtal::IntegerComputer<TInteger>::IntegerComputer()
51//-----------------------------------------------------------------------------
52template <typename TInteger>
54DGtal::IntegerComputer<TInteger>::IntegerComputer( const Self & /*other*/ )
56//-----------------------------------------------------------------------------
57template <typename TInteger>
59DGtal::IntegerComputer<TInteger> &
60DGtal::IntegerComputer<TInteger>::operator=( const Self & /*other*/ )
64//-----------------------------------------------------------------------------
65// ----------------------- Integer services ------------------------------
66//-----------------------------------------------------------------------------
67template <typename TInteger>
70DGtal::IntegerComputer<TInteger>::
71isZero( IntegerParamType a )
73 return a == NumberTraits<Integer>::ZERO;
75//-----------------------------------------------------------------------------
76template <typename TInteger>
79DGtal::IntegerComputer<TInteger>::
80isNotZero( IntegerParamType a )
82 return a != NumberTraits<Integer>::ZERO;
84//-----------------------------------------------------------------------------
85template <typename TInteger>
88DGtal::IntegerComputer<TInteger>::
89isPositive( IntegerParamType a )
91 return a > NumberTraits<Integer>::ZERO;
93//-----------------------------------------------------------------------------
94template <typename TInteger>
97DGtal::IntegerComputer<TInteger>::
98isNegative( IntegerParamType a )
100 return a < NumberTraits<Integer>::ZERO;
102//-----------------------------------------------------------------------------
103template <typename TInteger>
106DGtal::IntegerComputer<TInteger>::
107isPositiveOrZero( IntegerParamType a )
109 return a >= NumberTraits<Integer>::ZERO;
111//-----------------------------------------------------------------------------
112template <typename TInteger>
115DGtal::IntegerComputer<TInteger>::
116isNegativeOrZero( IntegerParamType a )
118 return a <= NumberTraits<Integer>::ZERO;
120//-----------------------------------------------------------------------------
121template <typename TInteger>
123typename DGtal::IntegerComputer<TInteger>::Integer
124DGtal::IntegerComputer<TInteger>::
125abs( IntegerParamType a )
127 if ( isPositiveOrZero( a ) )
132//-----------------------------------------------------------------------------
133template <typename TInteger>
135typename DGtal::IntegerComputer<TInteger>::Integer
136DGtal::IntegerComputer<TInteger>::
137max( IntegerParamType a, IntegerParamType b )
139 return ( a >= b ) ? a : b;
141//-----------------------------------------------------------------------------
142template <typename TInteger>
144typename DGtal::IntegerComputer<TInteger>::Integer
145DGtal::IntegerComputer<TInteger>::
146max( IntegerParamType a, IntegerParamType b, IntegerParamType c )
148 return max( max(a,b), c );
150//-----------------------------------------------------------------------------
151template <typename TInteger>
153typename DGtal::IntegerComputer<TInteger>::Integer
154DGtal::IntegerComputer<TInteger>::
155min( IntegerParamType a, IntegerParamType b )
157 return ( a <= b ) ? a : b;
159//-----------------------------------------------------------------------------
160template <typename TInteger>
162typename DGtal::IntegerComputer<TInteger>::Integer
163DGtal::IntegerComputer<TInteger>::
164min( IntegerParamType a, IntegerParamType b, IntegerParamType c )
166 return min( min(a,b), c );
168//-----------------------------------------------------------------------------
169template <typename TInteger>
172DGtal::IntegerComputer<TInteger>::
173getEuclideanDiv( Integer & q, Integer & r,
174 IntegerParamType a, IntegerParamType b ) const
179//-----------------------------------------------------------------------------
180template <typename TInteger>
182typename DGtal::IntegerComputer<TInteger>::Integer
183DGtal::IntegerComputer<TInteger>::
184floorDiv( 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//-----------------------------------------------------------------------------
209template <typename TInteger>
211typename DGtal::IntegerComputer<TInteger>::Integer
212DGtal::IntegerComputer<TInteger>::
213ceilDiv( 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//-----------------------------------------------------------------------------
238template <typename TInteger>
241DGtal::IntegerComputer<TInteger>::
242getFloorCeilDiv( 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//-----------------------------------------------------------------------------
260template <typename TInteger>
262typename DGtal::IntegerComputer<TInteger>::Integer
263DGtal::IntegerComputer<TInteger>::
264staticGcd( 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//-----------------------------------------------------------------------------
280template <typename TInteger>
282typename DGtal::IntegerComputer<TInteger>::Integer
283DGtal::IntegerComputer<TInteger>::
284gcd( 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//-----------------------------------------------------------------------------
299template <typename TInteger>
302DGtal::IntegerComputer<TInteger>::
303getGcd( 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//-----------------------------------------------------------------------------
319template <typename TInteger>
321typename DGtal::IntegerComputer<TInteger>::Integer
322DGtal::IntegerComputer<TInteger>::
323getCFrac( 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//-----------------------------------------------------------------------------
339template <typename TInteger>
340template <typename OutputIterator>
342typename DGtal::IntegerComputer<TInteger>::Integer
343DGtal::IntegerComputer<TInteger>::
344getCFrac( 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//-----------------------------------------------------------------------------
361template <typename TInteger>
363typename DGtal::IntegerComputer<TInteger>::Point2I
364DGtal::IntegerComputer<TInteger>::
365convergent( 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//-----------------------------------------------------------------------------
390template <typename TInteger>
393DGtal::IntegerComputer<TInteger>::
394reduce( Vector2I & p ) const
396 _m_a = gcd( p[ 0 ], p[ 1 ] );
397 if ( ( _m_a != NumberTraits<Integer>::ONE ) && ( isNotZero( _m_a ) ) )
400//-----------------------------------------------------------------------------
401template <typename TInteger>
403typename DGtal::IntegerComputer<TInteger>::Integer
404DGtal::IntegerComputer<TInteger>::
405crossProduct( 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//-----------------------------------------------------------------------------
412template <typename TInteger>
415DGtal::IntegerComputer<TInteger>::
416getCrossProduct( Integer & cp,
417 const Vector2I & u, const Vector2I & v) const
419 cp = u[ 0 ] * v[ 1 ];
420 cp -= u[ 1 ] * v[ 0 ];
422//-----------------------------------------------------------------------------
423template <typename TInteger>
425typename DGtal::IntegerComputer<TInteger>::Integer
426DGtal::IntegerComputer<TInteger>::
427dotProduct( 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//-----------------------------------------------------------------------------
434template <typename TInteger>
437DGtal::IntegerComputer<TInteger>::
438getDotProduct( Integer & dp,
439 const Vector2I & u, const Vector2I & v) const
441 dp = u[ 0 ] * v[ 0 ];
442 dp += u[ 1 ] * v[ 1 ];
444//-----------------------------------------------------------------------------
445template <typename TInteger>
446typename DGtal::IntegerComputer<TInteger>::Vector2I
447DGtal::IntegerComputer<TInteger>::
448extendedEuclid( 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//-----------------------------------------------------------------------------
503template <typename TInteger>
506DGtal::IntegerComputer<TInteger>::
507getCoefficientIntersection( 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//-----------------------------------------------------------------------------
521template <typename TInteger>
524DGtal::IntegerComputer<TInteger>::
525getValidBezout ( 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//-----------------------------------------------------------------------------
552template <typename TInteger>
555DGtal::IntegerComputer<TInteger>::
556reduce( Vector3I & p ) const
558 _m_a = gcd( p[ 0 ], p[ 1 ] );
559 _m_r = gcd( _m_a, p[ 2 ] );
562//-----------------------------------------------------------------------------
563template <typename TInteger>
565typename DGtal::IntegerComputer<TInteger>::Integer
566DGtal::IntegerComputer<TInteger>::
567dotProduct( 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//-----------------------------------------------------------------------------
575template <typename TInteger>
578DGtal::IntegerComputer<TInteger>::
579getDotProduct( 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.
595template <typename TInteger>
598DGtal::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.
607template <typename TInteger>
610DGtal::IntegerComputer<TInteger>::isValid() const
617///////////////////////////////////////////////////////////////////////////////
618// Implementation of inline functions //
620template <typename TInteger>
623DGtal::operator<< ( std::ostream & out,
624 const IntegerComputer<TInteger> & object )
626 object.selfDisplay( out );
631///////////////////////////////////////////////////////////////////////////////