SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
sddsconvolve.c File Reference

Detailed Description

Perform convolution, deconvolution, and correlation operations using the SDDS library.

This program handles discrete Fourier convolution, deconvolution, and correlation between signal and response files. It assumes that the input files have uniform spacing of points and an equal number of data points.

Features:

  • Convolution: ( O = S * R )
  • Deconvolution: ( O = S / R )
  • Correlation: ( O = S * Conj(R) )

It also supports options for Wiener filtering and noise handling during deconvolution.

Usage

sddsconvolve <signal-file> <response-file> <output>
[-pipe=[input][,output]]
[-signalColumns=<indepColumn>,<dataName>]
[-responseColumns=<indepColumn>,<dataName>]
[-outputColumns=<indepColumn>,<dataName>]
[-reuse]
[-majorOrder=row|column]
[-deconvolve]
[-noiseFraction=value]
[-wienerFilter=value]
[-correlate]

Options

Option Description
-pipe Use standard input/output in place of the signal file and output file.
-signalColumns Specify the independent column and data name for the signal file.
-responseColumns Specify the independent column and data name for the response file.
-outputColumns Specify the independent column and data name for the output file.
-reuse Reuse the first page of the response file for each page of the signal file.
-majorOrder Set data ordering in the output file.
-deconvolve Perform deconvolution instead of convolution.
-noiseFraction Specify noise fraction to prevent divide-by-zero errors during deconvolution.
-wienerFilter Apply a Wiener filter with the specified fraction during deconvolution.
-correlate Perform correlation instead of convolution.

Incompatibilities

  • -deconvolve is incompatible with:
    • -correlate
  • For -deconvolve:
    • At least one of -noiseFraction or -wienerFilter must be specified.
  • Only one of the following may be specified:
    • -noiseFraction=<value>
    • -wienerFilter=<value>
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
Michael Borland, R. Soliday, H. Shang

Definition in file sddsconvolve.c.

#include "mdb.h"
#include "SDDS.h"
#include "scan.h"
#include "fftpackC.h"

Go to the source code of this file.

Functions

void complex_multiply (double *r0, double *i0, double r1, double i1, double r2, double i2)
 Multiplies two complex numbers.
 
void complex_divide (double *r0, double *i0, double r1, double i1, double r2, double i2, double threshold)
 Divides two complex numbers.
 
void wrap_around_order (double *response1, double *t, double *response, int64_t nres, int64_t nsig)
 
int main (int argc, char **argv)
 

Function Documentation

◆ complex_divide()

void complex_divide ( double * r0,
double * i0,
double r1,
double i1,
double r2,
double i2,
double threshold )

Divides two complex numbers.

Deprecated
These routines are obsolete, really, but some code uses them.
Parameters
r0Pointer to store the real part of the result.
i0Pointer to store the imaginary part of the result.
r1Real part of the numerator complex number.
i1Imaginary part of the numerator complex number.
r2Real part of the denominator complex number.
i2Imaginary part of the denominator complex number.
thresholdThe threshold to prevent division by very small numbers.

Definition at line 104 of file complex.cc.

108 {
109 double tempr, denom;
110
111 if ((denom = sqr(r2) + sqr(i2)) < threshold)
112 denom = threshold;
113 i2 = -i2;
114 tempr = (r1 * r2 - i1 * i2) / denom;
115 *i0 = (r1 * i2 + i1 * r2) / denom;
116 *r0 = tempr;
117}

◆ complex_multiply()

void complex_multiply ( double * r0,
double * i0,
double r1,
double i1,
double r2,
double i2 )

Multiplies two complex numbers.

Deprecated
These routines are obsolete, really, but some code uses them.
Parameters
r0Pointer to store the real part of the result.
i0Pointer to store the imaginary part of the result.
r1Real part of the first complex number.
i1Imaginary part of the first complex number.
r2Real part of the second complex number.
i2Imaginary part of the second complex number.

Definition at line 80 of file complex.cc.

83 {
84 double tempr;
85
86 tempr = r1 * r2 - i1 * i2;
87 *i0 = r1 * i2 + i1 * r2;
88 *r0 = tempr;
89}

◆ main()

int main ( int argc,
char ** argv )

Definition at line 140 of file sddsconvolve.c.

140 {
141 SDDS_DATASET SDDS1, SDDS2, SDDSout;
142 int i_arg;
143 SCANNED_ARG *scanned;
144 char *input1, *input2, *output;
145 long mode, doWiener;
146 double *fft_sig, *fft_res, noise, mag2, threshold, range;
147 double *signal1, *signal2, *indep1, *indep2;
148 double WienerFraction, *WienerFilter = NULL;
149 unsigned long pipeFlags, majorOrderFlag;
150 char *input1Column[2], *input2Column[2], *outputColumn[2];
151 char description[1024];
152 long tmpfile_used, code1, code2;
153 int64_t i, rows1, rows2, nfreq;
154 int32_t parameters = 0;
155 char **parameterName = NULL;
156 short columnMajorOrder = -1, reuse = 0;
157
159 argc = scanargs(&scanned, argc, argv);
160 if (argc < 4 || argc > (4 + N_OPTIONS))
161 bomb(NULL, USAGE);
162
163 input1 = input2 = output = NULL;
164 mode = MODE_CONVOLVE;
165 noise = 1e-14;
166 input1Column[0] = input1Column[1] = NULL;
167 input2Column[0] = input2Column[1] = NULL;
168 outputColumn[0] = outputColumn[1] = NULL;
169 pipeFlags = 0;
170 doWiener = 0;
171
172 for (i_arg = 1; i_arg < argc; i_arg++) {
173 if (scanned[i_arg].arg_type == OPTION) {
174 /* process options here */
175 switch (match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
176 case CLO_MAJOR_ORDER:
177 majorOrderFlag = 0;
178 scanned[i_arg].n_items--;
179 if (scanned[i_arg].n_items > 0 &&
180 (!scanItemList(&majorOrderFlag, scanned[i_arg].list + 1, &scanned[i_arg].n_items, 0,
181 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
182 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
183 SDDS_Bomb("Invalid -majorOrder syntax or values.");
184 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
185 columnMajorOrder = 1;
186 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
187 columnMajorOrder = 0;
188 break;
189 case CLO_DECONVOLVE:
190 mode = MODE_DECONVOLVE;
191 break;
192 case CLO_CORRELATE:
193 mode = MODE_CORRELATE;
194 break;
195 case CLO_PIPE:
196 if (!processPipeOption(scanned[i_arg].list + 1, scanned[i_arg].n_items - 1, &pipeFlags))
197 SDDS_Bomb("Invalid -pipe syntax.");
198 break;
199 case CLO_NOISE_FRACTION:
200 if (scanned[i_arg].n_items != 2 || sscanf(scanned[i_arg].list[1], "%lf", &noise) != 1 || noise <= 0)
201 SDDS_Bomb("Invalid -noisefraction syntax or value.");
202 break;
203 case CLO_WIENER_FILTER:
204 if (scanned[i_arg].n_items != 2 || sscanf(scanned[i_arg].list[1], "%lf", &WienerFraction) != 1 ||
205 WienerFraction <= 0 || WienerFraction >= 1)
206 SDDS_Bomb("Invalid -wienerfilter syntax or value.");
207 doWiener = 1;
208 break;
209 case CLO_SIGNALCOLUMN:
210 if (scanned[i_arg].n_items != 3 ||
211 !strlen(input1Column[0] = scanned[i_arg].list[1]) ||
212 !strlen(input1Column[1] = scanned[i_arg].list[2]))
213 SDDS_Bomb("Invalid -signalColumns syntax.");
214 break;
215 case CLO_RESPONSECOLUMN:
216 if (scanned[i_arg].n_items != 3 ||
217 !strlen(input2Column[0] = scanned[i_arg].list[1]) ||
218 !strlen(input2Column[1] = scanned[i_arg].list[2]))
219 SDDS_Bomb("Invalid -responseColumns syntax.");
220 break;
221 case CLO_OUTPUTCOLUMN:
222 if (scanned[i_arg].n_items != 3 ||
223 !strlen(outputColumn[0] = scanned[i_arg].list[1]) ||
224 !strlen(outputColumn[1] = scanned[i_arg].list[2]))
225 SDDS_Bomb("Invalid -outputColumns syntax.");
226 break;
227 case CLO_REUSE:
228 reuse = 1;
229 break;
230 default:
231 SDDS_Bomb("Unknown option provided.");
232 break;
233 }
234 } else {
235 if (!input1)
236 input1 = scanned[i_arg].list[0];
237 else if (!input2)
238 input2 = scanned[i_arg].list[0];
239 else if (!output)
240 output = scanned[i_arg].list[0];
241 else
242 SDDS_Bomb("Too many filenames provided.");
243 }
244 }
245
246 if (pipeFlags & USE_STDIN && input1) {
247 if (output)
248 SDDS_Bomb("Too many filenames provided.");
249 output = input2;
250 input2 = input1;
251 input1 = NULL;
252 }
253 if (!input1Column[0] || !input1Column[1] || !strlen(input1Column[0]) || !strlen(input1Column[1]))
254 SDDS_Bomb("SignalColumns not provided.");
255 if (!input2Column[0] || !input2Column[1] || !strlen(input2Column[0]) || !strlen(input2Column[1]))
256 SDDS_Bomb("ResponseColumns not provided.");
257 if (!outputColumn[0] || !outputColumn[1] || !strlen(outputColumn[0]) || !strlen(outputColumn[1]))
258 SDDS_Bomb("OutputColumns not provided.");
259
260 processFilenames("sddsconvolve", &input1, &output, pipeFlags, 1, &tmpfile_used);
261 if (!input2)
262 SDDS_Bomb("Second input file not specified.");
263
264 if (!SDDS_InitializeInput(&SDDS1, input1) || !SDDS_InitializeInput(&SDDS2, input2)) {
265 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
266 exit(EXIT_FAILURE);
267 }
268
269 switch (mode) {
270 case MODE_CONVOLVE:
271 sprintf(description, "Convolution of signal '%s' with response '%s'", input1Column[1], input2Column[1]);
272 break;
273 case MODE_DECONVOLVE:
274 sprintf(description, "Deconvolution of signal '%s' with response '%s'", input1Column[1], input2Column[1]);
275 break;
276 case MODE_CORRELATE:
277 sprintf(description, "Correlation of signal '%s' with response '%s'", input1Column[1], input2Column[1]);
278 break;
279 }
280
281 parameterName = SDDS_GetParameterNames(&SDDS1, &parameters);
282 if (!SDDS_InitializeOutput(&SDDSout, SDDS_BINARY, 1, NULL, NULL, output) ||
283 !SDDS_TransferColumnDefinition(&SDDSout, &SDDS1, input1Column[0], outputColumn[0]) ||
284 0 > SDDS_DefineColumn(&SDDSout, outputColumn[1], NULL, NULL, description, NULL, SDDS_DOUBLE, 0)) {
285 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
286 exit(EXIT_FAILURE);
287 }
288 if (columnMajorOrder != -1)
289 SDDSout.layout.data_mode.column_major = columnMajorOrder;
290 else
291 SDDSout.layout.data_mode.column_major = SDDS1.layout.data_mode.column_major;
292
293 if (parameters) {
294 for (i = 0; i < parameters; i++)
295 if (!SDDS_TransferParameterDefinition(&SDDSout, &SDDS1, parameterName[i], parameterName[i]))
296 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
297 }
298
299 if (!SDDS_WriteLayout(&SDDSout)) {
300 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
301 exit(EXIT_FAILURE);
302 }
303
304 code2 = -1;
305 while ((code1 = SDDS_ReadPage(&SDDS1)) > 0) {
306 if ((rows1 = SDDS_RowCount(&SDDS1)) <= 0) {
307 fprintf(stderr, "Warning (sddsconvolve): Skipping page due to no signal rows.\n");
308 continue;
309 }
310 if (rows1 < 2)
311 SDDS_Bomb("sddsconvolve requires at least two rows on each nonempty signal page");
312 if (reuse) {
313 if (code2 == -1) {
314 if ((code2 = SDDS_ReadPage(&SDDS2)) <= 0) {
315 fprintf(stderr, "Error (sddsconvolve): Couldn't read data from response file.\n");
316 exit(EXIT_FAILURE);
317 }
318 if ((rows2 = SDDS_RowCount(&SDDS2)) < 0) {
319 fprintf(stderr, "Error (sddsconvolve): Response file has zero rows on first page.\n");
320 exit(EXIT_FAILURE);
321 }
322 }
323 } else {
324 if ((code2 = SDDS_ReadPage(&SDDS2)) <= 0)
325 break;
326 rows2 = SDDS_RowCount(&SDDS2);
327 }
328 if (rows1 != rows2)
329 SDDS_Bomb("Different numbers of points for signal and response.");
330
331 if (!(signal1 = SDDS_GetColumnInDoubles(&SDDS1, input1Column[1])) ||
332 !(indep1 = SDDS_GetColumnInDoubles(&SDDS1, input1Column[0])) ||
333 !(signal2 = SDDS_GetColumnInDoubles(&SDDS2, input2Column[1])) ||
334 !(indep2 = SDDS_GetColumnInDoubles(&SDDS2, input2Column[0]))) {
335 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
336 exit(EXIT_FAILURE);
337 }
338
339 if (!(fft_sig = SDDS_Calloc(sizeof(*fft_sig), (2 * rows1 + 2))) ||
340 !(fft_res = SDDS_Calloc(sizeof(*fft_res), (2 * rows1 + 2)))) {
341 SDDS_SetError("Memory allocation failure.");
342 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
343 exit(EXIT_FAILURE);
344 }
345
346 /* Rearrange response for FFT */
347 wrap_around_order(fft_res, indep2, signal2, rows2, rows1);
348 for (i = 0; i < rows1; i++)
349 fft_sig[i] = signal1[i];
350
351 /* Perform FFT on signal and response */
352 realFFT2(fft_sig, fft_sig, 2 * rows1, 0);
353 realFFT2(fft_res, fft_res, 2 * rows1, 0);
354 nfreq = rows1 + 1;
355 range = 2 * rows1 * (indep1[rows1 - 1] - indep1[0]) / (rows1 - 1);
356
357 if (mode == MODE_CONVOLVE || mode == MODE_CORRELATE) {
358 if (mode == MODE_CORRELATE)
359 /* Take complex conjugate of response FFT */
360 for (i = 0; i < nfreq; i++)
361 fft_res[2 * i + 1] = -fft_res[2 * i + 1];
362
363 /* Multiply FFTs */
364 for (i = 0; i < nfreq; i++) {
365 complex_multiply(&fft_sig[2 * i], &fft_sig[2 * i + 1],
366 fft_sig[2 * i], fft_sig[2 * i + 1],
367 fft_res[2 * i], fft_res[2 * i + 1]);
368 }
369
370 /* Inverse FFT */
371 realFFT2(fft_sig, fft_sig, 2 * rows1, INVERSE_FFT);
372
373 /* Apply normalization factor */
374 for (i = 0; i < rows1; i++)
375 fft_sig[i] *= range;
376
377 /* Write output */
378 if (!SDDS_StartPage(&SDDSout, rows1) ||
379 !SDDS_CopyParameters(&SDDSout, &SDDS1) ||
380 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, fft_sig, rows1, outputColumn[1]) ||
381 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, indep1, rows1, outputColumn[0]) ||
382 !SDDS_WritePage(&SDDSout)) {
383 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
384 exit(EXIT_FAILURE);
385 }
386 } else if (mode == MODE_DECONVOLVE) {
387 double maxMag2;
388 /* Calculate maximum magnitude squared */
389 for (i = threshold = 0; i < nfreq; i++) {
390 if ((mag2 = sqr(fft_res[2 * i]) + sqr(fft_res[2 * i + 1])) > threshold)
391 threshold = mag2;
392 }
393 maxMag2 = threshold;
394 threshold = threshold * noise;
395
396 if (doWiener) {
397 /* Compute and apply Wiener filter */
398 double *S = NULL, *N = NULL, wThreshold;
399 if (!(WienerFilter = malloc(sizeof(*WienerFilter) * nfreq)) ||
400 !(S = malloc(sizeof(*S) * nfreq)) ||
401 !(N = malloc(sizeof(*N) * nfreq))) {
402 SDDS_Bomb("Memory allocation failure.");
403 }
404 wThreshold = maxMag2 * sqr(WienerFraction);
405 for (i = 0; i < nfreq; i++) {
406 S[i] = sqrt(sqr(fft_res[2 * i]) + sqr(fft_res[2 * i + 1]));
407 if (sqr(S[i]) < wThreshold) {
408 N[i] = S[i];
409 S[i] = 0;
410 } else {
411 S[i] = S[i] - sqrt(wThreshold);
412 N[i] = sqrt(wThreshold);
413 }
414 }
415 for (i = 0; i < nfreq; i++)
416 WienerFilter[i] = sqr(S[i]) / (sqr(S[i]) + sqr(N[i]) + threshold);
417 free(N);
418 free(S);
419 }
420
421 /* Perform division in frequency domain */
422 for (i = 0; i < nfreq; i++) {
423 complex_divide(&fft_sig[2 * i], &fft_sig[2 * i + 1],
424 fft_sig[2 * i], fft_sig[2 * i + 1],
425 fft_res[2 * i], fft_res[2 * i + 1],
426 threshold);
427 }
428
429 if (doWiener) {
430 for (i = 0; i < nfreq; i++) {
431 fft_sig[2 * i] *= WienerFilter[i];
432 fft_sig[2 * i + 1] *= WienerFilter[i];
433 }
434 free(WienerFilter);
435 }
436
437 /* Inverse FFT */
438 realFFT2(fft_sig, fft_sig, 2 * rows1, INVERSE_FFT);
439
440 /* Apply normalization factor */
441 for (i = 0; i < rows1; i++)
442 fft_sig[i] = fft_sig[i] / range;
443
444 /* Write output */
445 if (!SDDS_StartPage(&SDDSout, rows1) ||
446 !SDDS_CopyParameters(&SDDSout, &SDDS1) ||
447 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, fft_sig, rows1, outputColumn[1]) ||
448 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, indep1, rows1, outputColumn[0]) ||
449 !SDDS_WritePage(&SDDSout)) {
450 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
451 exit(EXIT_FAILURE);
452 }
453 } else {
454 SDDS_Bomb("Unexpected processing mode encountered.");
455 }
456
457 /* Free allocated memory for this iteration */
458 free(fft_sig);
459 fft_sig = NULL;
460 free(fft_res);
461 fft_res = NULL;
462 free(signal1);
463 free(indep1);
464 free(signal2);
465 free(indep2);
466 signal1 = indep1 = signal2 = indep2 = NULL;
467 }
468
469 if (!SDDS_Terminate(&SDDS1) || !SDDS_Terminate(&SDDS2) || !SDDS_Terminate(&SDDSout)) {
470 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
471 exit(EXIT_FAILURE);
472 }
473
474 if (tmpfile_used && !replaceFileAndBackUp(input1, output))
475 exit(EXIT_FAILURE);
476
477 free(parameterName);
478 free_scanargs(&scanned, argc);
479
480 return EXIT_SUCCESS;
481}
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:286
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:50
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.
int32_t SDDS_TransferParameterDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a parameter definition from a source dataset to a target dataset.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:421
char ** SDDS_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:474
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:318
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:380
void * SDDS_Calloc(size_t nelem, size_t elem_size)
Allocates zero-initialized memory for an array of elements.
Definition SDDS_utils.c:683
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
Definition replacefile.c:78
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:357
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:391
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:588
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
void complex_divide(double *r0, double *i0, double r1, double i1, double r2, double i2, double threshold)
Divides two complex numbers.
Definition complex.cc:104
void complex_multiply(double *r0, double *i0, double r1, double i1, double r2, double i2)
Multiplies two complex numbers.
Definition complex.cc:80

◆ wrap_around_order()

void wrap_around_order ( double * response1,
double * t,
double * response,
int64_t nres,
int64_t nsig )

Definition at line 483 of file sddsconvolve.c.

483 {
484 int64_t i;
485 int64_t iz;
486
487 for (iz = 0; iz < nres; iz++)
488 if (t[iz] >= 0)
489 break;
490 if (iz == nres)
491 bomb("Response function is acausal.", NULL);
492
493 fill_double_array(response1, 2 * nsig + 2, 0.0L);
494 for (i = iz; i < nres; i++)
495 response1[i - iz] = response[i];
496 for (i = 0; i < iz; i++)
497 response1[2 * nsig - (iz - i)] = response[i];
498}
void fill_double_array(double *array, long n, double value)
Fills a double array with the specified value.
Definition fill_array.c:27