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/>.
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 Pattern.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 TFraction>
44 DGtal::Pattern<TFraction>::~Pattern()
47 //-----------------------------------------------------------------------------
48 template <typename TFraction>
50 DGtal::Pattern<TFraction>::Pattern( Fraction f )
54 //-----------------------------------------------------------------------------
55 template <typename TFraction>
57 DGtal::Pattern<TFraction>::Pattern( const Self & other )
58 : mySlope( other.mySlope )
61 //-----------------------------------------------------------------------------
62 template <typename TFraction>
64 typename DGtal::Pattern<TFraction> &
65 DGtal::Pattern<TFraction>::operator=( const Self & other )
67 mySlope = other.mySlope;
70 //-----------------------------------------------------------------------------
71 template <typename TFraction>
73 DGtal::Pattern<TFraction>::Pattern( Integer p, Integer q )
75 IntegerComputer<Integer> ic;
76 Integer g = ic.gcd( p, q );
79 mySlope = Fraction( p, q );
81 //-----------------------------------------------------------------------------
82 template <typename TFraction>
85 DGtal::Pattern<TFraction>::
88 if ( mySlope.null() ) return "eps";
89 else if ( mySlope.k() == -2 )
93 else if ( mySlope.k() == -NumberTraits<Quotient>::ONE )
97 else if ( mySlope.k() == NumberTraits<Quotient>::ZERO )
99 std::string s( static_cast<int32_t>(NumberTraits<Integer>::castToInt64_t( mySlope.p() )),
107 mySlope.getSplitBerstel( f1, nb1, f2, nb2 );
111 for ( Quotient i = 0; i < nb1; ++i ) s += p1.rE();
112 for ( Quotient i = 0; i < nb2; ++i ) s += p2.rE();
116 //-----------------------------------------------------------------------------
117 template <typename TFraction>
120 DGtal::Pattern<TFraction>::
121 rEs( const std::string & seps ) const
123 if ( mySlope.null() ) return "eps";
124 else if ( mySlope.k() == -2 )
128 else if ( mySlope.k() == -NumberTraits<Quotient>::ONE )
132 else if ( mySlope.k() == NumberTraits<Quotient>::ZERO )
134 std::string s( static_cast<int32_t>(NumberTraits<Integer>::castToInt64_t( mySlope.p() )), '1' );
137 // else if ( mySlope.k() == NumberTraits<Quotient>::ONE )
139 // std::string s( NumberTraits<Quotient>::castToInt64_t( mySlope.u() ), '0' );
146 mySlope.getSplitBerstel( f1, nb1, f2, nb2 );
147 std::string s( 1, seps[ 0 ] );
150 for ( Quotient i = 0; i < nb1; ++i ) s += p1.rEs( seps );
152 for ( Quotient i = 0; i < nb2; ++i ) s += p2.rEs( seps );
157 //-----------------------------------------------------------------------------
158 template <typename TFraction>
160 typename DGtal::Pattern<TFraction>::Fraction
161 DGtal::Pattern<TFraction>::
166 //-----------------------------------------------------------------------------
167 template <typename TFraction>
169 typename DGtal::Pattern<TFraction>::Integer
170 DGtal::Pattern<TFraction>::
173 return mySlope.p() + mySlope.q();
175 //-----------------------------------------------------------------------------
176 template <typename TFraction>
178 typename DGtal::Pattern<TFraction>::Integer
179 DGtal::Pattern<TFraction>::
180 posU( Quotient k ) const
182 ASSERT( ! slope().null() );
183 if ( k == NumberTraits<Quotient>::ZERO ) return NumberTraits<Integer>::ZERO;
184 else if ( k == NumberTraits<Quotient>::ONE ) return length();
185 else return length() * ((Integer) k);
187 //-----------------------------------------------------------------------------
188 template <typename TFraction>
190 typename DGtal::Pattern<TFraction>::Integer
191 DGtal::Pattern<TFraction>::
192 posL( Quotient k ) const
194 ASSERT( ! slope().null() );
195 Integer pL = slope().odd() ? length() - previousPattern().length()
196 : previousPattern().length();
197 if ( k == NumberTraits<Quotient>::ZERO ) return pL;
198 else if ( k == NumberTraits<Quotient>::ONE ) return pL + length();
199 else return pL + length() * ((Integer) k);
201 //-----------------------------------------------------------------------------
202 template <typename TFraction>
204 typename DGtal::Pattern<TFraction>::Point2I
205 DGtal::Pattern<TFraction>::
206 U( Quotient k ) const
208 ASSERT( ! slope().null() );
209 if ( k == NumberTraits<Quotient>::ZERO )
210 return Point2I( NumberTraits<Integer>::ZERO,
211 NumberTraits<Integer>::ZERO );
212 else if ( k == NumberTraits<Quotient>::ONE )
213 return Point2I( slope().q(),
216 return Point2I( slope().q() * ((Integer) k ),
217 slope().p() * ((Integer) k) );
219 //-----------------------------------------------------------------------------
220 template <typename TFraction>
222 typename DGtal::Pattern<TFraction>::Point2I
223 DGtal::Pattern<TFraction>::
224 L( Quotient k ) const
226 ASSERT( ! slope().null() );
227 Point2I pL( NumberTraits<Integer>::ONE,
228 -NumberTraits<Integer>::ONE ); // (1,-1)
230 if ( k == NumberTraits<Quotient>::ZERO )
235 //-----------------------------------------------------------------------------
236 template <typename TFraction>
238 typename DGtal::Pattern<TFraction>::Vector2I
239 DGtal::Pattern<TFraction>::
243 ? U( 1 ) - previousPattern().U( 1 )
244 : previousPattern().U( 1 );
246 //-----------------------------------------------------------------------------
247 template <typename TFraction>
249 typename DGtal::Pattern<TFraction>::Vector2I
250 DGtal::Pattern<TFraction>::
253 return Vector2I( slope().q(), slope().p() );
255 //-----------------------------------------------------------------------------
256 template <typename TFraction>
258 DGtal::Pattern<TFraction>
259 DGtal::Pattern<TFraction>::
260 previousPattern() const
262 ASSERT( ( ! slope().null() ) );
263 // && ( slope().p() != NumberTraits<Quotient>::ZERO ) );
264 return Self( slope().previousPartial() );
266 // if ( slope().k() > NumberTraits<Quotient>::ZERO )
267 // return Self( slope().previousPartial() );
268 // else // if ( slope().k() == NumberTraits<Quotient>::ZERO )
269 // return ( slope().p() == NumberTraits<Quotient>::ZERO )
270 // ? Self( Fraction( 1, 0 ) )
271 // : Self( Fraction( 0, 1 ) );
273 //-----------------------------------------------------------------------------
274 template <typename TFraction>
277 DGtal::Pattern<TFraction>::
278 getSmallestCoveringSubpattern( Pattern & subpattern,
281 Integer posA, Integer posB,
282 bool reversed ) const
284 bool different = false;
285 Integer l = length();
287 ASSERT( ( 0 <= posA ) && ( posA < posB ) && ( posB <= l ) );
288 if ( slope().p() == 0 || slope().q() == 0 ) // trivial pattern
290 ASSERT( posA == 0 && posB == 1 );
293 startPos = Vector2I( NumberTraits<Integer>::ZERO,
294 NumberTraits<Integer>::ZERO );
297 else if ( reversed ? slope().even() : slope().odd() )
298 { // Odd pattern: E(z_n) = E( z_{n-1} )^u E( z_{n-2} )
299 Self prevP = previousPattern();
300 Integer prevL = prevP.length();
301 Integer k1 = posA / prevL;
302 // Integer r1 = posA % prevL;
303 if ( posB > slope().u() * prevL )
304 { // B at extremity in the E( z_{n-2} ) part
306 ( NumberTraits<Quotient>::castToInt64_t( slope().u() )
307 - NumberTraits<Integer>::castToInt64_t( k1 ) ); // number of E( z_{n-1} ) from A.
308 // subpattern is E( z_{n-1} )^nb E( z_{n-2} )
309 subpattern = Self( slope().father( nb ) );
311 startPos = prevP.v() * k1;
315 { // B within some pattern E( z_{n-1} )
316 Integer k2 = ( posB + prevL - 1 ) / prevL;
317 nb = (int32_t) NumberTraits<Integer>::castToInt64_t( k2 - k1 );
319 // subpattern is E( z_{n-1} )^nb
321 startPos = prevP.v() * k1;
325 else // slope() is even
326 { // Even pattern: E(z_n) = E( z_{n-2} ) E( z_{n-1} )^u
327 Self prevP = previousPattern();
328 Integer prevL = prevP.length();
329 Integer k1 = ( l - posB ) / prevL;
330 // Integer r1 = ( l - posB ) % prevL;
331 if ( ( l - posA ) > slope().u() * prevL )
332 { // A at extremity in the E( z_{n-2} ) part
334 ( NumberTraits<Quotient>::castToInt64_t( slope().u() )
335 - NumberTraits<Integer>::castToInt64_t( k1 ) ); // number of E( z_{n-1} ) from B.
336 // subpattern is E( z_{n-2} ) E( z_{n-1} )^nb
337 // slope().selfDisplay( std::cerr );
338 // std::cerr << " nb=" << nb << " ";
339 // slope().father( nb ).selfDisplay( std::cerr );
340 // std::cerr << std::endl;
341 subpattern = Self( slope().father( nb ) );
343 startPos = Vector2I( NumberTraits<Integer>::ZERO,
344 NumberTraits<Integer>::ZERO );
348 { // A within some pattern E( z_{n-1} )
349 Integer k2 = ( l - posA + prevL - 1 ) / prevL;
350 nb = (int32_t) NumberTraits<Integer>::castToInt64_t( k2 - k1 );
352 // subpattern is E( z_{n-1} )^nb
354 startPos = v() - prevP.v() * k2;
361 //-----------------------------------------------------------------------------
362 template <typename TFraction>
365 DGtal::Pattern<TFraction>::
366 getGreatestIncludedSubpattern( Pattern & subpattern,
369 Integer posA, Integer posB,
370 bool reversed ) const
372 bool null_pattern = false;
373 Integer l = length();
374 ASSERT( ( 0 <= posA ) && ( posA < posB ) && ( posB <= l ) );
375 if ( slope().p() == 0 || slope().q() == 0 ) // trivial pattern
377 ASSERT( posA == 0 && posB == 1 );
380 startPos = Vector2I( NumberTraits<Integer>::ZERO,
381 NumberTraits<Integer>::ZERO );
382 null_pattern = false;
384 else if ( reversed ? slope().even() : slope().odd() )
385 { // Odd pattern: E(z_n) = E( z_{n-1} )^u E( z_{n-2} )
386 Self prevP = previousPattern();
387 Integer prevL = prevP.length();
388 Integer k1 = ( posA + prevL - 1 ) / prevL;
390 { // B at right extremity of the E( z_{n-2} ) part
391 if ( posA > slope().u() * prevL )
393 subpattern = Fraction();
398 { // subpattern is E( z_{n-1} )^nb E( z_{n-2} )
400 ( NumberTraits<Quotient>::castToInt64_t( slope().u() )
401 - NumberTraits<Integer>::castToInt64_t( k1 ) ); // number of E( z_{n-1} ) from A.
402 subpattern = Self( slope().father( nb ) );
404 startPos = prevP.v() * k1;
405 null_pattern = false;
409 { // B within some pattern E( z_{n-1} ) or strictly in E ( z_{n-2} )
410 Integer k2 = posB / prevL;
411 nb = (int32_t) NumberTraits<Integer>::castToInt64_t( k2 - k1 );
412 // subpattern is E( z_{n-1} )^nb or null
413 if ( nb < 0 ) nb = 0;
414 subpattern = nb == 0 ? Pattern() : prevP;
415 startPos = prevP.v() * k1;
416 null_pattern = nb == 0;
419 else // slope() is even
420 { // Even pattern: E(z_n) = E( z_{n-2} ) E( z_{n-1} )^u
421 Self prevP = previousPattern();
422 Integer prevL = prevP.length();
423 Integer k1 = ( l - posB + prevL - 1 ) / prevL;
425 { // A at left extremity of the E( z_{n-2} ) part
426 // subpattern is E( z_{n-2} ) E( z_{n-1} )^nb
427 if ( ( l - posB ) > slope().u() * prevL )
429 subpattern = Fraction();
436 ( NumberTraits<Quotient>::castToInt64_t( slope().u() )
437 - NumberTraits<Integer>::castToInt64_t( k1 ) ); // number of E( z_{n-1} ) from B.
438 subpattern = Self( slope().father( nb ) );
440 startPos = Vector2I( NumberTraits<Integer>::ZERO,
441 NumberTraits<Integer>::ZERO );
442 null_pattern = false;
446 { // A within some pattern E( z_{n-1} ) or strictly in E ( z_{n-2} )
447 Integer k2 = ( l - posA ) / prevL;
448 nb = (int32_t) NumberTraits<Integer>::castToInt64_t( k2 - k1 );
449 // subpattern is E( z_{n-1} )^nb or null
450 if ( nb < 0 ) nb = 0;
451 subpattern = nb == 0 ? Pattern() : prevP;
452 startPos = v() - prevP.v() * k2;
453 null_pattern = nb == 0;
457 return ! null_pattern;
462 ///////////////////////////////////////////////////////////////////////////////
463 // Interface - public :
466 * Writes/Displays the object on an output stream.
467 * @param out the output stream where the object is written.
469 template <typename TFraction>
472 DGtal::Pattern<TFraction>::selfDisplay ( std::ostream & out ) const
474 out << "[Pattern] f=";
475 mySlope.selfDisplay( out );
479 * Checks the validity/consistency of the object.
480 * @return 'true' if the object is valid, 'false' otherwise.
482 template <typename TFraction>
485 DGtal::Pattern<TFraction>::isValid() const
492 ///////////////////////////////////////////////////////////////////////////////
493 // Implementation of inline functions //
495 template <typename TFraction>
498 DGtal::operator<< ( std::ostream & out,
499 const Pattern<TFraction> & object )
501 object.selfDisplay( out );
506 ///////////////////////////////////////////////////////////////////////////////