DGtal  1.2.0
Signal.ih
1 /**
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.
6  *
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.
11  *
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/>.
14  *
15  **/
16 
17 /**
18  * @file Signal.ih
19  * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20  * Laboratory of Mathematics (CNRS, UMR 5807), University of Savoie, France
21  *
22  * @date 2011/07/06
23  *
24  * Implementation of inline methods defined in Signal.h
25  *
26  * This file is part of the DGtal library.
27  */
28 
29 
30 //////////////////////////////////////////////////////////////////////////////
31 #include <cstdlib>
32 #include <iomanip>
33 //////////////////////////////////////////////////////////////////////////////
34 
35 
36 //////////////////////////////////////////////////////////////////////////////
37 // class SignalData<TValue>
38 //////////////////////////////////////////////////////////////////////////////
39 
40 /**
41  * Constructor.
42  */
43 template <typename TValue>
44 inline
45 DGtal::SignalData<TValue>::SignalData()
46  : data( 0 )
47 {}
48 
49 /**
50  * Constructor.
51  *
52  * @param s the number of data in the signal.
53  * @param z the index of the zero-th element.
54  * @param p 'true' if the signal is periodic.
55  * @param def the default value.
56  */
57 template <typename TValue>
58 inline
59 void
60 DGtal::SignalData<TValue>::init
61 ( unsigned int s, int z, bool p, const Value & def )
62 {
63  if ( data != 0 ) delete[] data;
64  size = s; zero = z; periodic = p;
65  data = new TValue[ size + 1 ];
66  data[ size ] = def;
67 }
68 
69 /**
70  * Constructor.
71  *
72  * @param t the array containing initial data.
73  * @param s the number of data in the signal.
74  * @param z the index of the zero-th element.
75  * @param p 'true' if the signal is periodic.
76  * @param def the default value.
77  */
78 template <typename TValue>
79 inline
80 void
81 DGtal::SignalData<TValue>::init
82 ( const Value* t, unsigned int s, int z, bool p, const Value& def )
83 {
84  if ( data != 0 ) delete[] data;
85  size = s; zero = z; periodic = p;
86  data = new TValue[ size + 1 ];
87  for ( unsigned int i = 0; i < size; ++i, ++t )
88  data[ i ] = *t;
89  data[ size ] = def;
90 }
91 
92 
93 /**
94  * Constructor.
95  *
96  * @param s the number of data in the signal.
97  * @param z the index of the zero-th element.
98  * @param p 'true' if the signal is periodic.
99  * @param def the default value.
100  */
101 template <typename TValue>
102 inline
103 DGtal::SignalData<TValue>::SignalData
104 ( unsigned int s, int z, bool p, const Value & def )
105  : size( s ), zero( z ), periodic( p )
106 {
107  data = new TValue[ size + 1 ];
108  data[ size ] = def;
109 }
110 
111 /**
112  * Constructor.
113  *
114  * @param t the array containing initial data.
115  * @param s the number of data in the signal.
116  * @param z the index of the zero-th element.
117  * @param p 'true' if the signal is periodic.
118  * @param def the default value.
119  */
120 template <typename TValue>
121 inline
122 DGtal::SignalData<TValue>::SignalData
123 ( const TValue* t, unsigned int s, int z, bool p, const Value & def )
124  : size( s ), zero( z ), periodic( p )
125 {
126  data = new TValue[ size + 1 ];
127  for ( unsigned int i = 0; i < size; ++i )
128  data[ i ] = *t++;
129  data[ size ] = def;
130 }
131 
132 
133 /**
134  * Destructor.
135  */
136 template <typename TValue>
137 inline
138 DGtal::SignalData<TValue>::~SignalData()
139 {
140  if ( data != 0 ) delete[] data;
141 }
142 
143 /**
144  * Copy constructor.
145  * @param other the data to clone.
146  */
147 template <typename TValue>
148 inline
149 DGtal::SignalData<TValue>::SignalData
150 ( const SignalData & other )
151  : size( other.size ), zero( other.zero ), periodic( other.periodic )
152 {
153  if ( other.data != 0 )
154  {
155  data = new TValue[ size + 1 ];
156  for ( unsigned int i = 0; i <= size; ++i )
157  data[ i ] = other.data[ i ];
158  }
159  else
160  data = 0;
161 }
162 
163 /**
164  * Assignment.
165  * @param other the data to clone.
166  * @return 'this'.
167  */
168 template <typename TValue>
169 inline
170 DGtal::SignalData<TValue> &
171 DGtal::SignalData<TValue>::operator=
172 ( const SignalData & other )
173 {
174  if ( this != &other )
175  {
176  if ( other.data == 0 )
177  {
178  if ( data != 0 )
179  delete[] data;
180  data = 0;
181  }
182  else
183  {
184  if ( size < other.size )
185  {
186  delete[] data;
187  data = new TValue[ other.size + 1 ];
188  }
189  size = other.size;
190  zero = other.zero;
191  periodic = other.periodic;
192  for ( unsigned int i = 0; i <= size; ++i )
193  data[ i ] = other.data[ i ];
194  }
195  }
196  return *this;
197 }
198 
199 
200 /**
201  * Default value.
202  * @return the default value.
203  */
204 template <typename TValue>
205 inline
206 const TValue &
207 DGtal::SignalData<TValue>::defaut() const
208 {
209  ASSERT( data != 0 );
210  return data[ size ];
211 }
212 
213 
214 
215 ///////////////////////////////////////////////////////////////////////////////
216 // IMPLEMENTATION of inline methods.
217 ///////////////////////////////////////////////////////////////////////////////
218 
219 ///////////////////////////////////////////////////////////////////////////////
220 // ----------------------- Standard services ------------------------------
221 
222 
223 /////////////////////////////////////////////////////////////////////////////
224 // class Signal
225 /////////////////////////////////////////////////////////////////////////////
226 /**
227  * Destructor.
228  */
229 template <typename TValue>
230 inline
231 DGtal::Signal<TValue>::Signal()
232  : m_data( 0 )
233 {
234 }
235 
236 /**
237  * Constructor.
238  * @param asize the size of the signal.
239  * @param z the index of the zero-th element.
240  * @param periodic 'true' if the signal is periodic.
241  * @param def the default value.
242  */
243 template <typename TValue>
244 inline
245 DGtal::Signal<TValue>::Signal
246 ( unsigned int asize, int z, bool periodic, const TValue & def )
247  : m_data( new SignalData<TValue>() )
248 {
249  m_data->init( asize, z, periodic, def );
250 }
251 
252 
253 /**
254  * Constructor.
255  * @param t the array containing initial data.
256  * @param asize the size of the signal.
257  * @param z the index of the zero-th element.
258  * @param periodic 'true' if the signal is periodic.
259  * @param def the default value.
260  */
261 template <typename TValue>
262 inline
263 DGtal::Signal<TValue>::Signal
264 ( const TValue* t, unsigned int asize, int z, bool periodic,
265  const TValue & def )
266  : m_data( new SignalData<TValue>() )
267 {
268  m_data->init( t, asize, z, periodic, def );
269 }
270 
271 
272 
273 /**
274  * Destructor.
275  */
276 template <typename TValue>
277 inline
278 DGtal::Signal<TValue>::~Signal()
279 {
280 }
281 
282 /**
283  * Copy constructor.
284  * @param other the object to clone.
285  * Forbidden by default.
286  */
287 template <typename TValue>
288 inline
289 DGtal::Signal<TValue>::Signal( const Signal & other )
290  : m_data( other.m_data )
291 {
292 }
293 
294 /**
295  * Assignment.
296  * @param other the object to copy.
297  * @return a reference on 'this'.
298  * Forbidden by default.
299  */
300 template <typename TValue>
301 inline
302 DGtal::Signal<TValue> &
303 DGtal::Signal<TValue>::operator=( const Signal & other )
304 {
305  if ( this != & other )
306  m_data = other.m_data;
307  return *this;
308 
309 }
310 
311 
312 /**
313  * Initializer.
314  * @param aSize the size of the signal.
315  * @param z the index of the zero-th element.
316  * @param periodic 'true' if the signal is periodic.
317  * @param def the default value.
318  */
319 template <typename TValue>
320 inline
321 void
322 DGtal::Signal<TValue>::init
323 ( unsigned int aSize, int z, bool periodic, const TValue & def )
324 {
325  m_data = CowPtr< SignalData<TValue> >( new SignalData<TValue>() );
326  m_data->init( aSize, z, periodic, def );
327 }
328 
329 
330 /**
331  * Constructor.
332  * @param t the array containing initial data.
333  * @param aSize the size of the signal.
334  * @param z the index of the zero-th element.
335  * @param periodic 'true' if the signal is periodic.
336  * @param def the default value.
337  */
338 template <typename TValue>
339 inline
340 void
341 DGtal::Signal<TValue>::init
342 ( const TValue* t, unsigned int aSize, int z, bool periodic,
343  const TValue & def )
344 {
345  m_data = CowPtr< SignalData<TValue> >( new SignalData<TValue>() );
346  m_data->init( t, aSize, z, periodic, def );
347 }
348 
349 
350 
351 /**
352  @return the number of elements in the signal.
353 */
354 template <typename TValue>
355 unsigned int
356 DGtal::Signal<TValue>::size() const
357 {
358  return m_data->size;
359 }
360 
361 
362 ///////////////////////////////////////////////////////////////////////////////
363 // ----------------------- Signal services ----------------------------
364 
365 
366 /**
367  * Protected rw access to value. If index is out of bound, return 0
368  * if not periodic or the correct value otherwise.
369  *
370  * @param i the index in the signal .
371  *
372  * @return the i-th value in the signal.
373  */
374 template <typename TValue>
375 TValue &
376 DGtal::Signal<TValue>::operator[]( int i )
377 {
378  SignalData<TValue> & sd = *m_data;
379  int idx = i + sd.zero;
380  if ( ( idx >= 0 ) && ( idx < (int) sd.size ) )
381  return sd.data[ idx ];
382  else if ( sd.periodic )
383  {
384  idx = idx - ( idx / (int) sd.size ) * sd.size;
385  return sd.data[ ( idx + sd.size ) % sd.size ];
386  }
387  else
388  return sd.data[ sd.size ];
389 }
390 
391 /**
392  * Protected ro access to value. If index is out of bound, return 0
393  * if not periodic or the correct value otherwise.
394  *
395  * @param i the index in the signal .
396  *
397  * @return the i-th value in the signal.
398  */
399 template <typename TValue>
400 const TValue &
401 DGtal::Signal<TValue>::operator[]( int i ) const
402 {
403  const SignalData<TValue> & sd = *m_data;
404  int idx = i + sd.zero;
405  if ( ( idx >= 0 ) && ( idx < (int) sd.size ) )
406  return sd.data[ idx ];
407  else if ( sd.periodic )
408  {
409  idx = idx - ( idx / (int) sd.size ) * sd.size;
410  return sd.data[ ( idx + sd.size ) % sd.size ];
411  }
412  else
413  return sd.data[ sd.size ];
414 }
415 
416 
417 /**
418  * The signal becomes a constant signal of value [val].
419  *
420  * @param val the value of the whole signal.
421  */
422 template <typename TValue>
423 void
424 DGtal::Signal<TValue>::setAll( const TValue & val )
425 {
426  SignalData<TValue> & sd = *m_data;
427  for ( unsigned int i = 0; i <= sd.size; ++i )
428  sd.data[ i ] = val;
429 }
430 
431 
432 /**
433  * External product of a signal by a scalar value.
434  *
435  * @param l the external value.
436  */
437 template <typename TValue>
438 void
439 DGtal::Signal<TValue>::multiply( const TValue & l )
440 {
441  SignalData<TValue> & sd = *m_data;
442  for ( unsigned int i = 0; i <= sd.size; ++i )
443  sd.data[ i ] *= l;
444 }
445 
446 
447 /**
448  * Convolution product of two signals (F = this).
449  * F*G( a ) = sum F(a-i)G(i)
450  *
451  * @param G the second signal (not periodic)
452  *
453  * @return the signal that is the convolution of F and G, of type F.
454  */
455 template <typename TValue>
456 DGtal::Signal<TValue>
457 DGtal::Signal<TValue>::operator*( const Signal<TValue>& G )
458 {
459  const SignalData<TValue>& Fd = *m_data;
460  const SignalData<TValue>& Gd = *G.m_data;
461 
462 
463  unsigned int aSize = Fd.periodic ? Fd.size : Fd.size + Gd.size - 1;
464  int zero = Fd.periodic ? Fd.zero : Fd.zero + Gd.zero;
465  Signal<TValue> FG( aSize, zero, Fd.periodic, Fd.defaut() );
466  SignalData<TValue>& FGd = *FG.m_data;
467 
468  if ( Fd.periodic )
469  {
470  for ( int a = 0; a < (int) FGd.size; ++a )
471  {
472  TValue sum = TValue( 0 );
473  for ( unsigned int i = 0; i < Gd.size; ++i )
474  {
475  sum += this->operator[]( a - ( i - Gd.zero ) )
476  * Gd.data[ i ];
477  }
478  FG[ a ] = sum;
479  }
480  }
481  else
482  {
483  for ( unsigned int a = 0; a < FGd.size; ++a )
484  {
485  TValue sum = TValue( 0 );
486  for ( unsigned int i = 0; i < Gd.size; ++i )
487  {
488  sum += this->operator[]( a - ( Fd.zero + Gd.zero )
489  - ( i - Gd.zero ) )
490  * Gd.data[ i ];
491  }
492  FGd.data[ a ] = sum;
493  }
494  }
495  return FG;
496 }
497 
498 
499 
500 template <typename TValue>
501 DGtal::Signal<TValue>
502 DGtal::Signal<TValue>::G2()
503 {
504  Signal<TValue> G = H2();
505  G.multiply( 0.25 );
506  return G;
507 }
508 
509 /**
510  * @return the binomial signal of order 2.
511  */
512 template <typename TValue>
513 DGtal::Signal<TValue>
514 DGtal::Signal<TValue>::H2()
515 {
516  Signal<TValue> H( 3, 1, false, TValue( 0 ) );
517  H[ -1 ] = 1;
518  H[ 0 ] = 2;
519  H[ 1 ] = 1;
520  return H;
521 }
522 
523 /**
524  * @return the right difference signal.
525  */
526 template <typename TValue>
527 DGtal::Signal<TValue>
528 DGtal::Signal<TValue>::Delta()
529 {
530  Signal<TValue> D( 2, 0, false, TValue( 0 ) );
531  D[ 0 ] = -1;
532  D[ 1 ] = 1;
533  return D;
534 }
535 
536 template <typename TValue>
537 DGtal::Signal<TValue>
538 DGtal::Signal<TValue>::G2n( unsigned int n )
539 {
540  if ( n <= 1 ) return G2();
541  else return G2n( n - 1 ) * G2();
542 }
543 
544 /**
545  * @return the binomial signal of order 2n.
546  */
547 template <typename TValue>
548 DGtal::Signal<TValue>
549 DGtal::Signal<TValue>::H2n( unsigned int n )
550 {
551  if ( n <= 1 ) return H2();
552  else return H2n( n - 1 ) * H2();
553 }
554 
555 /**
556  * @return the differential operator with binomial weights of order 2n.
557  */
558 template <typename TValue>
559 DGtal::Signal<TValue>
560 DGtal::Signal<TValue>::D2n( unsigned int n )
561 {
562  return H2n( n ) * Delta();
563 }
564 
565 
566 ///////////////////////////////////////////////////////////////////////////////
567 // Interface - public :
568 
569 /**
570  * Writes/Displays the object on an output stream.
571  * @param out the output stream where the object is written.
572  */
573 template <typename TValue>
574 inline
575 void
576 DGtal::Signal<TValue>::selfDisplay ( std::ostream & out ) const
577 {
578  out << "[Signal" << std::fixed << std::setprecision( 5 );
579  for ( unsigned int i = 0; i < size(); ++i )
580  out << " " << ( ( i == (unsigned int) m_data->zero ) ? "*" : "" )
581  << m_data->data[ i ];
582  out << " ]";
583 }
584 
585 /**
586  * Checks the validity/consistency of the object.
587  * @return 'true' if the object is valid, 'false' otherwise.
588  */
589 template <typename TValue>
590 inline
591 bool
592 DGtal::Signal<TValue>::isValid() const
593 {
594  return true;
595 }
596 
597 
598 
599 ///////////////////////////////////////////////////////////////////////////////
600 // Implementation of inline functions //
601 
602 template <typename TValue>
603 inline
604 std::ostream&
605 DGtal::operator<< ( std::ostream & out,
606  const Signal<TValue> & object )
607 {
608  object.selfDisplay( out );
609  return out;
610 }
611 
612 // //
613 ///////////////////////////////////////////////////////////////////////////////
614 
615