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