00001
00006 #include <bpm/bpm_wf.h>
00007
00008 complexwf_t* complexwf( int ns, double fs ) {
00009
00010 complexwf_t *w;
00011
00012 if ( fs <= 0 ) {
00013 bpm_error( "Cannot have sampling frequency <= 0. in complexwf()",
00014 __FILE__, __LINE__ );
00015 return NULL;
00016 }
00017
00018 if ( ns > MAX_ALLOWED_NS ) {
00019 bpm_error( "Maximum allowed number of samples exceeded, failed to allocate.",
00020 __FILE__, __LINE__ );
00021 return NULL;
00022 }
00023
00024 if ( ns > 1 ) {
00025 w = (complexwf_t*) calloc( 1, sizeof(complexwf_t) );
00026 if ( ! w ) {
00027 bpm_error( "Cannot allocate memory for waveform structure in complexwf()",
00028 __FILE__, __LINE__ );
00029 return NULL;
00030 }
00031 w->ns = ns;
00032 w->fs = fs;
00033 w->wf = (complex_t*) calloc( w->ns, sizeof( complex_t ) );
00034 if ( ! w->wf ) {
00035 bpm_error( "Cannot allocate memory for waveform data in complexwf()",
00036 __FILE__, __LINE__ );
00037 free( w );
00038 return NULL;
00039 }
00040 } else {
00041 bpm_error( "Invalid number of samples in complexwf()", __FILE__, __LINE__ );
00042 return NULL;
00043 }
00044
00045 return w;
00046 }
00047
00048
00049
00050 complexwf_t* complexwf_copy_new( complexwf_t *w ) {
00051
00052 int i = 0;
00053 complexwf_t *s = complexwf( w->ns, w->fs );
00054
00055 if ( ! s ) {
00056 bpm_error( "Cannot allocate memory in complexwf_copy_new()", __FILE__, __LINE__ );
00057 return NULL;
00058 };
00059
00060 for ( i=0; i<w->ns; i++ ) s->wf[i] = w->wf[i];
00061
00062 return s;
00063 }
00064
00065
00066
00067 int complexwf_copy( complexwf_t *copy, complexwf_t *src ) {
00068
00069 int i = 0;
00070
00071 if ( ! copy || ! src ) {
00072 bpm_error( "Invalid pointer arguments in complexwf_copy()", __FILE__, __LINE__ );
00073 return BPM_FAILURE;
00074 };
00075
00076 if ( complexwf_compat( copy, src ) ) {
00077 for ( i=0; i<copy->ns; i++ ) copy->wf[i] = src->wf[i];
00078 } else {
00079 bpm_error( "Incompatible waveforms for in complexwf_copy()", __FILE__, __LINE__ );
00080 return BPM_FAILURE;
00081 }
00082
00083 return BPM_SUCCESS;
00084 }
00085
00086
00087
00088 int complexwf_subset( complexwf_t *sub, complexwf_t *w, int i1, int i2 ) {
00089
00090 int i = 0;
00091
00092 if ( ! sub || ! w ) {
00093 bpm_error( "Invalid pointer arguments in complexwf_subset()", __FILE__, __LINE__ );
00094 return BPM_FAILURE;
00095 };
00096
00097
00098 sub->ns = 0;
00099 sub->fs = w->fs;
00100
00101 for ( i=MAX(0,i1); i<=MIN(w->ns-1,i2); i++ ) {
00102 sub->wf[i] = w->wf[i-i1];
00103 sub->ns++;
00104 }
00105
00106
00107 return BPM_SUCCESS;
00108 }
00109
00110
00111
00112 int complexwf_setvalues( complexwf_t *w, complex_t *x ) {
00113
00114 int i = 0;
00115 if ( ! w || ! x ) {
00116 bpm_error( "Invalid pointer arguments in complexwf_setvalues()",
00117 __FILE__, __LINE__ );
00118 return BPM_FAILURE;
00119 }
00120
00121 for ( i=0; i<w->ns; i++ ) w->wf[i] = x[i];
00122
00123 return BPM_SUCCESS;
00124 }
00125
00126
00127 int complexwf_setfunction( complexwf_t *w,
00128 complex_t (*wffun)( double, int, double* ),
00129 int npars, double *par ) {
00130
00131 int i = 0;
00132 if ( ! w || ! wffun ) {
00133 bpm_error( "Invalid pointer arguments in complexwf_setfunction()",
00134 __FILE__, __LINE__ );
00135 return BPM_FAILURE;
00136 }
00137
00138 for ( i=0; i<w->ns; i++ ) w->wf[i] = (*wffun)( (double) i / w->fs, npars, par );
00139
00140 return BPM_SUCCESS;
00141 }
00142
00143
00144
00145 int complexwf_reset( complexwf_t *w ) {
00146
00147 int i = 0;
00148
00149 if ( ! w ) {
00150 bpm_error( "Invalid pointer argument in complexwf_reset()",
00151 __FILE__, __LINE__ );
00152 return BPM_FAILURE;
00153 }
00154
00155 for ( i=0; i<w->ns; i++ ) w->wf[i] = complex( 0., 0. );
00156
00157 return BPM_SUCCESS;
00158 }
00159
00160
00161
00162 void complexwf_delete( complexwf_t *w ) {
00163
00164 if ( w ) {
00165 if ( w->wf ) free( w->wf ); else
00166 bpm_warning( "Cannot free complexwf_t::wf pointer in complexwf()_delete, already NULL !",
00167 __FILE__, __LINE__ );
00168 free( w );
00169 } else {
00170 bpm_warning( "Cannot free complexwf_t pointer in complexwf()_delete, already NULL !",
00171 __FILE__, __LINE__ );
00172 }
00173
00174 return;
00175 }
00176
00177
00178
00179 int complexwf_compat( complexwf_t *w1, complexwf_t *w2 ) {
00180
00181 if ( ! w1 || ! w2 ) {
00182 bpm_error( "Invalid pointer arguments in doublewf_compat()",
00183 __FILE__, __LINE__ );
00184 return 0;
00185 }
00186
00187 return ((w1->ns==w2->ns)&&(fabs(w1->fs-w2->fs)<WF_EPS)?1:0);
00188 }
00189
00190
00191
00192 int complexwf_add( complexwf_t *w1, complexwf_t *w2 ) {
00193
00194 int i = 0;
00195
00196 if ( ! w1 || ! w2 ) {
00197 bpm_error( "Invalid pointer arguments in complexwf_add()",
00198 __FILE__, __LINE__ );
00199 return BPM_FAILURE;
00200 }
00201
00202 if ( ! complexwf_compat( w1, w2 ) ) {
00203 bpm_warning( "Incompatible waveforms in complexwf_add()", __FILE__, __LINE__ );
00204 }
00205 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] = c_sum( w1->wf[i], w2->wf[i] );
00206
00207 return BPM_SUCCESS;
00208 }
00209
00210
00211
00212 int complexwf_subtract( complexwf_t *w1, complexwf_t *w2 ) {
00213
00214 int i = 0;
00215
00216 if ( ! w1 || ! w2 ) {
00217 bpm_error( "Invalid pointer arguments in complexwf_subtract()",
00218 __FILE__, __LINE__ );
00219 return BPM_FAILURE;
00220 }
00221
00222 if ( ! complexwf_compat( w1, w2 ) ) {
00223 bpm_warning( "Incompatible waveforms in complexwf_subtract()", __FILE__, __LINE__ );
00224 }
00225
00226 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] = c_diff( w1->wf[i], w2->wf[i] );
00227
00228 return BPM_SUCCESS;
00229 }
00230
00231
00232
00233 int complexwf_multiply( complexwf_t *w1, complexwf_t *w2 ) {
00234
00235 int i = 0;
00236
00237 if ( ! w1 || ! w2 ) {
00238 bpm_error( "Invalid pointer arguments in complexwf_multiply()",
00239 __FILE__, __LINE__ );
00240 return BPM_FAILURE;
00241 }
00242
00243 if ( ! complexwf_compat( w1, w2 ) ) {
00244 bpm_warning( "Incompatible waveforms in complexwf_multiply()",
00245 __FILE__, __LINE__ );
00246 }
00247
00248 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] = c_mult( w1->wf[i], w2->wf[i] );
00249
00250 return BPM_SUCCESS;
00251 }
00252
00253
00254
00255 int complexwf_divide( complexwf_t *w1, complexwf_t *w2 ) {
00256
00257 int i = 0;
00258
00259 if ( ! w1 || ! w2 ) {
00260 bpm_error( "Invalid pointer arguments in complexwf_divide()",
00261 __FILE__, __LINE__ );
00262 return BPM_FAILURE;
00263 }
00264
00265 if ( ! complexwf_compat( w1, w2 ) ) {
00266 bpm_warning( "Incompatible waveforms in complexwf_divide()",
00267 __FILE__, __LINE__ );
00268 }
00269
00270 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) {
00271
00272 if ( c_isequal( w2->wf[i], complex( 0., 0. ) ) ) {
00273 bpm_warning( "Trapped division by 0+0i in complexwf_divide()",
00274 __FILE__, __LINE__ );
00275 w1->wf[i] = complex(0.,0.);
00276 } else {
00277 w1->wf[i] = c_div( w1->wf[i], w2->wf[i] );
00278 }
00279
00280 }
00281
00282 return BPM_SUCCESS;
00283 }
00284
00285
00286
00287 int complexwf_scale( complex_t f, complexwf_t *w ) {
00288
00289 int i = 0;
00290
00291 if ( ! w ) {
00292 bpm_error( "Invalid pointer argument in complexwf_scale()",
00293 __FILE__, __LINE__ );
00294 return BPM_FAILURE;
00295 }
00296
00297 for ( i=0; i<w->ns; i++ ) w->wf[i] = c_mult( f, w->wf[i] );
00298
00299 return BPM_SUCCESS;
00300 }
00301
00302
00303
00304 int complexwf_bias( complex_t c, complexwf_t *w ) {
00305
00306 int i = 0;
00307
00308 if ( ! w ) {
00309 bpm_error( "Invalid pointer argument in complexwf_bias()",
00310 __FILE__, __LINE__ );
00311 return BPM_FAILURE;
00312 }
00313
00314 for ( i=0; i<w->ns; i++ ) w->wf[i] = c_sum( c, w->wf[i] );
00315
00316 return BPM_SUCCESS;
00317 }
00318
00319
00320
00321 int complexwf_add_cwtone( complexwf_t *w, double amp, double phase, double freq,
00322 double phasenoise ) {
00323
00324 int i = 0;
00325
00326 if ( ! w ) {
00327 bpm_error( "Invalid pointer argument in complexwf_add_cwtone()",
00328 __FILE__, __LINE__ );
00329 return BPM_FAILURE;
00330 }
00331
00332 for (i=0; i<w->ns; i++ ) {
00333 w->wf[i].re += amp * cos( 2. * PI * freq * (double) i / w->fs +
00334 nr_rangauss( phase, phasenoise ) );
00335
00336 w->wf[i].im += amp * sin( 2. * PI * freq * (double) i / w->fs +
00337 nr_rangauss( phase, phasenoise ) );
00338 }
00339
00340 return BPM_SUCCESS;
00341 }
00342
00343
00344
00345 int complexwf_add_dcywave( complexwf_t *w, double amp, double phase, double freq,
00346 double ttrig, double tdcy, double phasenoise ) {
00347
00348 int i = 0;
00349 double t = 0.;
00350
00351 if ( ! w ) {
00352 bpm_error( "Invalid pointer argument in complexwf_add_dcywave()",
00353 __FILE__, __LINE__ );
00354 return BPM_FAILURE;
00355 }
00356
00357 for (i=0; i<w->ns; i++ ) {
00358 t = (double) i / w->fs;
00359 if ( t >= ttrig ) {
00360 w->wf[i].re += amp * exp( -( t - ttrig ) / tdcy ) *
00361 cos( 2. * PI * freq * ( t - ttrig ) + nr_rangauss( phase, phasenoise ) );
00362 w->wf[i].im += amp * exp( -( t - ttrig ) / tdcy ) *
00363 sin( 2. * PI * freq * ( t - ttrig ) + nr_rangauss( phase, phasenoise ) );
00364 }
00365 }
00366
00367 return BPM_SUCCESS;
00368 }
00369
00370
00371
00372 int complexwf_add_noise( complexwf_t *w, double sigma ) {
00373
00374 int i = 0;
00375 double amp, phase;
00376
00377 if ( ! w ) {
00378 bpm_error( "Invalid pointer argument in complexwf_add_noise()",
00379 __FILE__, __LINE__ );
00380 return BPM_FAILURE;
00381 }
00382
00383 for (i=0; i<w->ns; i++ ) {
00384 amp = nr_rangauss( 0., sigma );
00385 phase = nr_ranuniform( 0., 2*PI );
00386
00387 w->wf[i] = c_sum( w->wf[i], complex( amp*cos(phase), amp*sin(phase) ) );
00388 }
00389
00390 return BPM_SUCCESS;
00391
00392 }
00393
00394
00395
00396 int complexwf_add_ampnoise( complexwf_t *w, double sigma ) {
00397
00398 int i = 0;
00399 double amp, phase;
00400
00401 if ( ! w ) {
00402 bpm_error( "Invalid pointer argument in complexwf_add_ampnoise()",
00403 __FILE__, __LINE__ );
00404 return BPM_FAILURE;
00405 }
00406
00407 for (i=0; i<w->ns; i++ ) {
00408 amp = nr_rangauss( c_abs( w->wf[i]), sigma );
00409 phase = c_arg( w->wf[i] );
00410
00411 w->wf[i] = complex( amp * cos( phase ), amp * sin( phase ) );
00412 }
00413
00414 return BPM_SUCCESS;
00415
00416 }
00417
00418
00419
00420 int complexwf_add_phasenoise( complexwf_t *w, double sigma ) {
00421
00422 int i = 0;
00423 double amp, phase;
00424
00425 if ( ! w ) {
00426 bpm_error( "Invalid pointer argument in complexwf_add_phasenoise()",
00427 __FILE__, __LINE__ );
00428 return BPM_FAILURE;
00429 }
00430
00431 for (i=0; i<w->ns; i++ ) {
00432 amp = c_abs( w->wf[i] );
00433 phase = nr_rangauss( c_arg( w->wf[i]), sigma );
00434
00435 w->wf[i] = complex( amp * cos( phase ), amp * sin( phase ) );
00436 }
00437
00438 return BPM_SUCCESS;
00439
00440 }
00441
00442
00443
00444
00445 void complexwf_print( FILE *of, complexwf_t *w ) {
00446
00447 int i = 0;
00448 if ( !of || !w ) {
00449 bpm_error( "Invalid pointers in comlexwf_print()", __FILE__, __LINE__ );
00450 return;
00451 }
00452
00453 fprintf( of, "Waveform:\n" );
00454 fprintf( of, "Number of samples : %d\n", w->ns );
00455 fprintf( of, "Sampling frequency : %f MHz\n", w->fs / MHz );
00456 for( i = 0; i < w->ns; i++ ) fprintf( of, " wf[%5d] = %.14e + i %.14e \n",
00457 i, w->wf[i].re, w->wf[i].im );
00458 fflush( of );
00459
00460 return;
00461 }
00462
00463
00464
00465 int complexwf_getreal( doublewf_t *re, complexwf_t *z ) {
00466
00467 int i = 0;
00468
00469 if ( ! re || ! z ) {
00470 bpm_error( "Invalid pointer argument in complexwf_getreal()",
00471 __FILE__, __LINE__ );
00472 return BPM_FAILURE;
00473 }
00474
00475 if ( re->ns != z->ns ) {
00476 bpm_warning( "Different number of samples in complex_getreal()",
00477 __FILE__, __LINE__ );
00478 }
00479
00480 for ( i=0; i < MIN(re->ns,z->ns); i++ ) re->wf[i] = z->wf[i].re;
00481
00482 return BPM_SUCCESS;
00483 }
00484
00485
00486
00487 int complexwf_getimag( doublewf_t *im, complexwf_t *z ) {
00488
00489 int i = 0;
00490
00491 if ( ! im || ! z ) {
00492 bpm_error( "Invalid pointer argument in complexwf_getimag()",
00493 __FILE__, __LINE__ );
00494 return BPM_FAILURE;
00495 }
00496
00497 if ( im->ns != z->ns ) {
00498 bpm_warning( "Different number of samples in complex_getimag()",
00499 __FILE__, __LINE__ );
00500 }
00501
00502 for ( i=0; i < MIN(im->ns,z->ns); i++ ) im->wf[i] = z->wf[i].im;
00503
00504 return BPM_SUCCESS;
00505 }
00506
00507
00508
00509 int complexwf_getamp( doublewf_t *r, complexwf_t *z ) {
00510
00511 int i = 0;
00512
00513 if ( ! r || ! z ) {
00514 bpm_error( "Invalid pointer argument in complexwf_getamp()",
00515 __FILE__, __LINE__ );
00516 return BPM_FAILURE;
00517 }
00518
00519 if ( r->ns != z->ns ) {
00520 bpm_warning( "Different number of samples in complex_getamp()",
00521 __FILE__, __LINE__ );
00522 }
00523
00524 for ( i=0; i < MIN(r->ns,z->ns); i++ ) r->wf[i] = c_abs( z->wf[i] );
00525
00526 return BPM_SUCCESS;
00527 }
00528
00529
00530
00531 int complexwf_getphase( doublewf_t *theta, complexwf_t *z ) {
00532
00533 int i = 0;
00534
00535 if ( ! theta || ! z ) {
00536 bpm_error( "Invalid pointer argument in complexwf_getphase()",
00537 __FILE__, __LINE__ );
00538 return BPM_FAILURE;
00539 }
00540
00541 if ( theta->ns != z->ns ) {
00542 bpm_warning( "Different number of samples in complexwf_getphase()",
00543 __FILE__, __LINE__ );
00544 }
00545
00546 for ( i=0; i < MIN(theta->ns,z->ns); i++ ) theta->wf[i] = c_arg( z->wf[i] );
00547
00548 return BPM_SUCCESS;
00549 }
00550
00551
00552
00553 int complexwf_setreal( complexwf_t *z, doublewf_t *re ){
00554
00555 int i = 0;
00556
00557 if ( ! re || ! z ) {
00558 bpm_error( "Invalid pointer argument in complexwf_setreal()",
00559 __FILE__, __LINE__ );
00560 return BPM_FAILURE;
00561 }
00562
00563 if ( re->ns != z->ns ) {
00564 bpm_warning( "Different number of samples in complexwf_setreal()",
00565 __FILE__, __LINE__ );
00566 }
00567
00568 for ( i=0; i < MIN(re->ns,z->ns); i++ ) z->wf[i].re = re->wf[i];
00569
00570 return BPM_SUCCESS;
00571 }
00572
00573
00574
00575 int complexwf_setimag( complexwf_t *z, doublewf_t *im ){
00576
00577 int i = 0;
00578
00579 if ( ! im || ! z ) {
00580 bpm_error( "Invalid pointer argument in complexwf_setreal()",
00581 __FILE__, __LINE__ );
00582 return BPM_FAILURE;
00583 }
00584
00585 if ( im->ns != z->ns ) {
00586 bpm_warning( "Different number of samples in complexwf_setreal()",
00587 __FILE__, __LINE__ );
00588 }
00589
00590 for ( i=0; i < MIN(im->ns,z->ns); i++ ) z->wf[i].im = im->wf[i];
00591
00592 return BPM_SUCCESS;
00593 }
00594
00595
00596
00597 doublewf_t* complexwf_getreal_new( complexwf_t *z ) {
00598
00599 int i = 0;
00600 doublewf_t *w = NULL;
00601
00602 if ( ! z ) {
00603 bpm_error( "Invalid pointer argument in complexwf_getreal_new()",
00604 __FILE__, __LINE__ );
00605 return NULL;
00606 }
00607
00608 w = doublewf( z->ns, z->fs );
00609 if ( ! w ) {
00610 bpm_error( "Unable to allocate memory for waveform in complex_getreal_new()",
00611 __FILE__, __LINE__ );
00612 return NULL;
00613 }
00614
00615 for (i=0;i<z->ns;i++) w->wf[i] = z->wf[i].re;
00616
00617 return w;
00618 }
00619
00620
00621
00622 doublewf_t* complexwf_getimag_new( complexwf_t *z ) {
00623
00624 int i = 0;
00625 doublewf_t *w = NULL;
00626
00627 if ( ! z ) {
00628 bpm_error( "Invalid pointer argument in complexwf_getimag_new()",
00629 __FILE__, __LINE__ );
00630 return NULL;
00631 }
00632
00633 w = doublewf( z->ns, z->fs );
00634 if ( ! w ) {
00635 bpm_error( "Unable to allocate memory for waveform in complex_getimag_new()",
00636 __FILE__, __LINE__ );
00637 return NULL;
00638 }
00639
00640 for (i=0;i<z->ns;i++) w->wf[i] = z->wf[i].im;
00641
00642 return w;
00643 }
00644
00645
00646
00647 doublewf_t* complexwf_getamp_new( complexwf_t *z ) {
00648
00649 int i = 0;
00650 doublewf_t *w = NULL;
00651
00652 if ( ! z ) {
00653 bpm_error( "Invalid pointer argument in complexwf_getamp_new()",
00654 __FILE__, __LINE__ );
00655 return NULL;
00656 }
00657
00658 w = doublewf( z->ns, z->fs );
00659 if ( ! w ) {
00660 bpm_error( "Unable to allocate memory for waveform in complex_getamp_new()",
00661 __FILE__, __LINE__ );
00662 return NULL;
00663 }
00664
00665 for (i=0;i<z->ns;i++) w->wf[i] = c_abs( z->wf[i] );
00666
00667 return w;
00668 }
00669
00670
00671
00672 doublewf_t* complexwf_getphase_new( complexwf_t *z ) {
00673
00674 int i = 0;
00675 doublewf_t *w = NULL;
00676
00677 if ( ! z ) {
00678 bpm_error( "Invalid pointer argument in complexwf_getphase_new()",
00679 __FILE__, __LINE__ );
00680 return NULL;
00681 }
00682
00683 w = doublewf( z->ns, z->fs );
00684 if ( ! w ) {
00685 bpm_error( "Unable to allocate memory for waveform in complex_getphase_new()",
00686 __FILE__, __LINE__ );
00687 return NULL;
00688 }
00689
00690 for (i=0;i<z->ns;i++) w->wf[i] = c_arg( z->wf[i] );
00691
00692 return w;
00693 }
00694
00695