DGtal 1.4.0
Loading...
Searching...
No Matches
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 */
43template <typename TValue>
44inline
45DGtal::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 */
57template <typename TValue>
58inline
59void
60DGtal::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 */
78template <typename TValue>
79inline
80void
81DGtal::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 */
101template <typename TValue>
102inline
103DGtal::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 */
120template <typename TValue>
121inline
122DGtal::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 */
136template <typename TValue>
137inline
138DGtal::SignalData<TValue>::~SignalData()
139{
140 if ( data != 0 ) delete[] data;
141}
142
143/**
144 * Copy constructor.
145 * @param other the data to clone.
146 */
147template <typename TValue>
148inline
149DGtal::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 */
168template <typename TValue>
169inline
170DGtal::SignalData<TValue> &
171DGtal::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 */
204template <typename TValue>
205inline
206const TValue &
207DGtal::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 */
229template <typename TValue>
230inline
231DGtal::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 */
243template <typename TValue>
244inline
245DGtal::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 */
261template <typename TValue>
262inline
263DGtal::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 */
276template <typename TValue>
277inline
278DGtal::Signal<TValue>::~Signal()
279{
280}
281
282/**
283 * Copy constructor.
284 * @param other the object to clone.
285 * Forbidden by default.
286 */
287template <typename TValue>
288inline
289DGtal::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 */
300template <typename TValue>
301inline
302DGtal::Signal<TValue> &
303DGtal::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 */
319template <typename TValue>
320inline
321void
322DGtal::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 */
338template <typename TValue>
339inline
340void
341DGtal::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*/
354template <typename TValue>
355unsigned int
356DGtal::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 */
374template <typename TValue>
375TValue &
376DGtal::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 */
399template <typename TValue>
400const TValue &
401DGtal::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 */
422template <typename TValue>
423void
424DGtal::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 */
437template <typename TValue>
438void
439DGtal::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 */
455template <typename TValue>
456DGtal::Signal<TValue>
457DGtal::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
500template <typename TValue>
501DGtal::Signal<TValue>
502DGtal::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 */
512template <typename TValue>
513DGtal::Signal<TValue>
514DGtal::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 */
526template <typename TValue>
527DGtal::Signal<TValue>
528DGtal::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
536template <typename TValue>
537DGtal::Signal<TValue>
538DGtal::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 */
547template <typename TValue>
548DGtal::Signal<TValue>
549DGtal::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 */
558template <typename TValue>
559DGtal::Signal<TValue>
560DGtal::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 */
573template <typename TValue>
574inline
575void
576DGtal::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 */
589template <typename TValue>
590inline
591bool
592DGtal::Signal<TValue>::isValid() const
593{
594 return true;
595}
596
597
598
599///////////////////////////////////////////////////////////////////////////////
600// Implementation of inline functions //
601
602template <typename TValue>
603inline
604std::ostream&
605DGtal::operator<< ( std::ostream & out,
606 const Signal<TValue> & object )
607{
608 object.selfDisplay( out );
609 return out;
610}
611
612// //
613///////////////////////////////////////////////////////////////////////////////
614
615