DGtal  0.9.2
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 size 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 size 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 size 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  * @return the signal where each term has been multiplied by [l].
438  */
439 template <typename TValue>
440 void
441 DGtal::Signal<TValue>::multiply( const TValue & l )
442 {
443  SignalData<TValue> & sd = *m_data;
444  for ( unsigned int i = 0; i <= sd.size; ++i )
445  sd.data[ i ] *= l;
446 }
447 
448 
449 /**
450  * Convolution product of two signals (F = this).
451  * F*G( a ) = sum F(a-i)G(i)
452  *
453  * @param G the second signal (not periodic)
454  *
455  * @return the signal that is the convolution of F and G, of type F.
456  */
457 template <typename TValue>
458 DGtal::Signal<TValue>
459 DGtal::Signal<TValue>::operator*( const Signal<TValue>& G )
460 {
461  const SignalData<TValue>& Fd = *m_data;
462  const SignalData<TValue>& Gd = *G.m_data;
463 
464 
465  unsigned int aSize = Fd.periodic ? Fd.size : Fd.size + Gd.size - 1;
466  int zero = Fd.periodic ? Fd.zero : Fd.zero + Gd.zero;
467  Signal<TValue> FG( aSize, zero, Fd.periodic, Fd.defaut() );
468  SignalData<TValue>& FGd = *FG.m_data;
469 
470  if ( Fd.periodic )
471  {
472  for ( int a = 0; a < (int) FGd.size; ++a )
473  {
474  TValue sum = TValue( 0 );
475  for ( unsigned int i = 0; i < Gd.size; ++i )
476  {
477  sum += this->operator[]( a - ( i - Gd.zero ) )
478  * Gd.data[ i ];
479  }
480  FG[ a ] = sum;
481  }
482  }
483  else
484  {
485  for ( unsigned int a = 0; a < FGd.size; ++a )
486  {
487  TValue sum = TValue( 0 );
488  for ( unsigned int i = 0; i < Gd.size; ++i )
489  {
490  sum += this->operator[]( a - ( Fd.zero + Gd.zero )
491  - ( i - Gd.zero ) )
492  * Gd.data[ i ];
493  }
494  FGd.data[ a ] = sum;
495  }
496  }
497  return FG;
498 }
499 
500 
501 
502 template <typename TValue>
503 DGtal::Signal<TValue>
504 DGtal::Signal<TValue>::G2()
505 {
506  Signal<TValue> G = H2();
507  G.multiply( 0.25 );
508  return G;
509 }
510 
511 /**
512  * @return the binomial signal of order 2.
513  */
514 template <typename TValue>
515 DGtal::Signal<TValue>
516 DGtal::Signal<TValue>::H2()
517 {
518  Signal<TValue> H( 3, 1, false, TValue( 0 ) );
519  H[ -1 ] = 1;
520  H[ 0 ] = 2;
521  H[ 1 ] = 1;
522  return H;
523 }
524 
525 /**
526  * @return the right difference signal.
527  */
528 template <typename TValue>
529 DGtal::Signal<TValue>
530 DGtal::Signal<TValue>::Delta()
531 {
532  Signal<TValue> D( 2, 0, false, TValue( 0 ) );
533  D[ 0 ] = -1;
534  D[ 1 ] = 1;
535  return D;
536 }
537 
538 template <typename TValue>
539 DGtal::Signal<TValue>
540 DGtal::Signal<TValue>::G2n( unsigned int n )
541 {
542  if ( n <= 1 ) return G2();
543  else return G2n( n - 1 ) * G2();
544 }
545 
546 /**
547  * @return the binomial signal of order 2n.
548  */
549 template <typename TValue>
550 DGtal::Signal<TValue>
551 DGtal::Signal<TValue>::H2n( unsigned int n )
552 {
553  if ( n <= 1 ) return H2();
554  else return H2n( n - 1 ) * H2();
555 }
556 
557 /**
558  * @return the differential operator with binomial weights of order 2n.
559  */
560 template <typename TValue>
561 DGtal::Signal<TValue>
562 DGtal::Signal<TValue>::D2n( unsigned int n )
563 {
564  return H2n( n ) * Delta();
565 }
566 
567 
568 ///////////////////////////////////////////////////////////////////////////////
569 // Interface - public :
570 
571 /**
572  * Writes/Displays the object on an output stream.
573  * @param out the output stream where the object is written.
574  */
575 template <typename TValue>
576 inline
577 void
578 DGtal::Signal<TValue>::selfDisplay ( std::ostream & out ) const
579 {
580  out << "[Signal" << std::fixed << std::setprecision( 5 );
581  for ( unsigned int i = 0; i < size(); ++i )
582  out << " " << ( ( i == (unsigned int) m_data->zero ) ? "*" : "" )
583  << m_data->data[ i ];
584  out << " ]";
585 }
586 
587 /**
588  * Checks the validity/consistency of the object.
589  * @return 'true' if the object is valid, 'false' otherwise.
590  */
591 template <typename TValue>
592 inline
593 bool
594 DGtal::Signal<TValue>::isValid() const
595 {
596  return true;
597 }
598 
599 
600 
601 ///////////////////////////////////////////////////////////////////////////////
602 // Implementation of inline functions //
603 
604 template <typename TValue>
605 inline
606 std::ostream&
607 DGtal::operator<< ( std::ostream & out,
608  const Signal<TValue> & object )
609 {
610  object.selfDisplay( out );
611  return out;
612 }
613 
614 // //
615 ///////////////////////////////////////////////////////////////////////////////
616 
617