SDDSlib
Loading...
Searching...
No Matches
sddsconvolve.c
Go to the documentation of this file.
1/**
2 * @file sddsconvolve.c
3 * @brief Perform convolution, deconvolution, and correlation operations using the SDDS library.
4 *
5 * This program is designed to handle 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.
6 *
7 * Features include:
8 * - Convolution: \‍( O = S * R \‍)
9 * - Deconvolution: \‍( O = S / R \‍)
10 * - Correlation: \‍( O = S * Conj(R) \‍)
11 *
12 * The program also supports options for Wiener filtering and noise handling during deconvolution.
13 *
14 * @authors Michael Borland
15 * @date Originally written in 1991, updated in 1993, 1998
16 * @version SVN revision: " SVN_VERSION "
17 *
18 * @usage
19 * sddsconvolve <signal-file> <response-file> <output>
20 *
21 * Options:
22 * - `-signalColumns=<indepColumn>,<dataName>`: Specify the independent column and data name for the signal file.
23 * - `-responseColumns=<indepColumn>,<dataName>`: Specify the independent column and data name for the response file.
24 * - `-outputColumns=<indepColumn>,<dataName>`: Specify the independent column and data name for the output file.
25 * - `-reuse`: Reuse the first page of the response file for each page of the signal file.
26 * - `-majorOrder=row|column`: Set data ordering in the output file.
27 * - `-deconvolve`: Perform deconvolution instead of convolution.
28 * - `-noiseFraction=<value>`: Specify noise fraction to prevent divide-by-zero.
29 * - `-wienerFilter=<value>`: Apply a Wiener filter with the specified fraction.
30 * - `-correlate`: Perform correlation instead of convolution.
31 * - `-pipe`: Use standard input/output in place of file arguments.
32 *
33 * @copyright
34 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
35 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
36 *
37 * @license
38 * This file is distributed under the terms of the Software License Agreement
39 * found in the file LICENSE included with this distribution.
40 *
41 * @author M. Borland, R. Soliday, H. Shang
42 */
43
44#include "mdb.h"
45#include "SDDS.h"
46#include "scan.h"
47#include "fftpackC.h"
48
49/* Enumeration for option types */
50enum option_type {
51 CLO_DECONVOLVE,
52 CLO_PIPE,
53 CLO_NOISE_FRACTION,
54 CLO_CORRELATE,
55 CLO_INDEPENDENTCOLUMN,
56 CLO_SIGNALCOLUMN,
57 CLO_RESPONSECOLUMN,
58 CLO_OUTPUTCOLUMN,
59 CLO_WIENER_FILTER,
60 CLO_MAJOR_ORDER,
61 CLO_REUSE,
62 N_OPTIONS
63};
64
65char *option[N_OPTIONS] = {
66 "deconvolve",
67 "pipe",
68 "noisefraction",
69 "correlate",
70 "independentcolumn",
71 "signalcolumn",
72 "responsecolumn",
73 "outputcolumn",
74 "wienerfilter",
75 "majorOrder",
76 "reuse",
77};
78
79#define USAGE "Usage: sddsconvolve <signal-file> <response-file> <output>\n\
80 -signalColumns=<indepColumn>,<dataName>\n\
81 -responseColumns=<indepColumn>,<dataName> [-reuse]\n\
82 -outputColumns=<indepColumn>,<dataName> [-majorOrder=row|column]\n\
83 [{-deconvolve [{-noiseFraction=<value> | -wienerFilter=<value>}] | -correlate}]\n\n\
84Description:\n\
85 Performs discrete Fourier convolution, deconvolution, or correlation between signal and response files.\n\
86 Assumes uniform spacing of points in both input files and that both files contain the same number of data points.\n\
87\n\
88Mathematical Operations:\n\
89 - Convolution: O = S * R\n\
90 - Deconvolution: O = S / R\n\
91 - Correlation: O = S * Conj(R)\n\
92\n\
93Options:\n\
94 -signalColumns=<indepColumn>,<dataName> Specify the independent column and data name for the signal file.\n\
95 -responseColumns=<indepColumn>,<dataName> Specify the independent column and data name for the response file.\n\
96 -outputColumns=<indepColumn>,<dataName> Specify the independent column and data name for the output file.\n\
97 -reuse Reuse the first page of the response file for each page of the signal file.\n\
98 -majorOrder=row|column Set data ordering in the output file.\n\
99 -deconvolve Perform deconvolution instead of convolution.\n\
100 -noiseFraction=<value> Specify noise fraction to prevent divide-by-zero.\n\
101 -wienerFilter=<value> Apply a Wiener filter with the specified fraction.\n\
102 -correlate Perform correlation instead of convolution.\n\
103 -pipe Use standard input/output in place of file arguments.\n\
104\n\
105Program Information:\n\
106 Michael Borland (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n"
107
108void complex_multiply(double *r0, double *i0, double r1, double i1, double r2, double i2);
109void complex_divide(double *r0, double *i0, double r1, double i1, double r2, double i2, double threshold);
110void wrap_around_order(double *response1, double *t, double *response, int64_t nres, int64_t nsig);
111
112#define MODE_CONVOLVE 1
113#define MODE_DECONVOLVE 2
114#define MODE_CORRELATE 3
115
116int main(int argc, char **argv) {
117 SDDS_DATASET SDDS1, SDDS2, SDDSout;
118 int i_arg;
119 SCANNED_ARG *scanned;
120 char *input1, *input2, *output;
121 long mode, doWiener;
122 double *fft_sig, *fft_res, noise, mag2, threshold, range;
123 double *signal1, *signal2, *indep1, *indep2;
124 double WienerFraction, *WienerFilter = NULL;
125 unsigned long pipeFlags, majorOrderFlag;
126 char *input1Column[2], *input2Column[2], *outputColumn[2];
127 char description[1024];
128 long tmpfile_used, code1, code2;
129 int64_t i, rows1, rows2, nfreq;
130 int32_t parameters = 0;
131 char **parameterName = NULL;
132 short columnMajorOrder = -1, reuse = 0;
133
135 argc = scanargs(&scanned, argc, argv);
136 if (argc < 4 || argc > (4 + N_OPTIONS))
137 bomb(NULL, USAGE);
138
139 input1 = input2 = output = NULL;
140 mode = MODE_CONVOLVE;
141 noise = 1e-14;
142 input1Column[0] = input1Column[1] = NULL;
143 input2Column[0] = input2Column[1] = NULL;
144 outputColumn[0] = outputColumn[1] = NULL;
145 pipeFlags = 0;
146 doWiener = 0;
147
148 for (i_arg = 1; i_arg < argc; i_arg++) {
149 if (scanned[i_arg].arg_type == OPTION) {
150 /* process options here */
151 switch (match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
152 case CLO_MAJOR_ORDER:
153 majorOrderFlag = 0;
154 scanned[i_arg].n_items--;
155 if (scanned[i_arg].n_items > 0 &&
156 (!scanItemList(&majorOrderFlag, scanned[i_arg].list + 1, &scanned[i_arg].n_items, 0,
157 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
158 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
159 SDDS_Bomb("Invalid -majorOrder syntax or values.");
160 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
161 columnMajorOrder = 1;
162 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
163 columnMajorOrder = 0;
164 break;
165 case CLO_DECONVOLVE:
166 mode = MODE_DECONVOLVE;
167 break;
168 case CLO_CORRELATE:
169 mode = MODE_CORRELATE;
170 break;
171 case CLO_PIPE:
172 if (!processPipeOption(scanned[i_arg].list + 1, scanned[i_arg].n_items - 1, &pipeFlags))
173 SDDS_Bomb("Invalid -pipe syntax.");
174 break;
175 case CLO_NOISE_FRACTION:
176 if (scanned[i_arg].n_items != 2 || sscanf(scanned[i_arg].list[1], "%lf", &noise) != 1 || noise <= 0)
177 SDDS_Bomb("Invalid -noisefraction syntax or value.");
178 break;
179 case CLO_WIENER_FILTER:
180 if (scanned[i_arg].n_items != 2 || sscanf(scanned[i_arg].list[1], "%lf", &WienerFraction) != 1 ||
181 WienerFraction <= 0 || WienerFraction >= 1)
182 SDDS_Bomb("Invalid -wienerfilter syntax or value.");
183 doWiener = 1;
184 break;
185 case CLO_SIGNALCOLUMN:
186 if (scanned[i_arg].n_items != 3 ||
187 !strlen(input1Column[0] = scanned[i_arg].list[1]) ||
188 !strlen(input1Column[1] = scanned[i_arg].list[2]))
189 SDDS_Bomb("Invalid -signalColumns syntax.");
190 break;
191 case CLO_RESPONSECOLUMN:
192 if (scanned[i_arg].n_items != 3 ||
193 !strlen(input2Column[0] = scanned[i_arg].list[1]) ||
194 !strlen(input2Column[1] = scanned[i_arg].list[2]))
195 SDDS_Bomb("Invalid -responseColumns syntax.");
196 break;
197 case CLO_OUTPUTCOLUMN:
198 if (scanned[i_arg].n_items != 3 ||
199 !strlen(outputColumn[0] = scanned[i_arg].list[1]) ||
200 !strlen(outputColumn[1] = scanned[i_arg].list[2]))
201 SDDS_Bomb("Invalid -outputColumns syntax.");
202 break;
203 case CLO_REUSE:
204 reuse = 1;
205 break;
206 default:
207 SDDS_Bomb("Unknown option provided.");
208 break;
209 }
210 } else {
211 if (!input1)
212 input1 = scanned[i_arg].list[0];
213 else if (!input2)
214 input2 = scanned[i_arg].list[0];
215 else if (!output)
216 output = scanned[i_arg].list[0];
217 else
218 SDDS_Bomb("Too many filenames provided.");
219 }
220 }
221
222 if (pipeFlags & USE_STDIN && input1) {
223 if (output)
224 SDDS_Bomb("Too many filenames provided.");
225 output = input2;
226 input2 = input1;
227 input1 = NULL;
228 }
229 if (!input1Column[0] || !input1Column[1] || !strlen(input1Column[0]) || !strlen(input1Column[1]))
230 SDDS_Bomb("SignalColumns not provided.");
231 if (!input2Column[0] || !input2Column[1] || !strlen(input2Column[0]) || !strlen(input2Column[1]))
232 SDDS_Bomb("ResponseColumns not provided.");
233 if (!outputColumn[0] || !outputColumn[1] || !strlen(outputColumn[0]) || !strlen(outputColumn[1]))
234 SDDS_Bomb("OutputColumns not provided.");
235
236 processFilenames("sddsconvolve", &input1, &output, pipeFlags, 1, &tmpfile_used);
237 if (!input2)
238 SDDS_Bomb("Second input file not specified.");
239
240 if (!SDDS_InitializeInput(&SDDS1, input1) || !SDDS_InitializeInput(&SDDS2, input2)) {
241 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
242 exit(EXIT_FAILURE);
243 }
244
245 switch (mode) {
246 case MODE_CONVOLVE:
247 sprintf(description, "Convolution of signal '%s' with response '%s'", input1Column[1], input2Column[1]);
248 break;
249 case MODE_DECONVOLVE:
250 sprintf(description, "Deconvolution of signal '%s' with response '%s'", input1Column[1], input2Column[1]);
251 break;
252 case MODE_CORRELATE:
253 sprintf(description, "Correlation of signal '%s' with response '%s'", input1Column[1], input2Column[1]);
254 break;
255 }
256
257 parameterName = SDDS_GetParameterNames(&SDDS1, &parameters);
258 if (!SDDS_InitializeOutput(&SDDSout, SDDS_BINARY, 1, NULL, NULL, output) ||
259 !SDDS_TransferColumnDefinition(&SDDSout, &SDDS1, input1Column[0], outputColumn[0]) ||
260 0 > SDDS_DefineColumn(&SDDSout, outputColumn[1], NULL, NULL, description, NULL, SDDS_DOUBLE, 0)) {
261 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
262 exit(EXIT_FAILURE);
263 }
264 if (columnMajorOrder != -1)
265 SDDSout.layout.data_mode.column_major = columnMajorOrder;
266 else
267 SDDSout.layout.data_mode.column_major = SDDS1.layout.data_mode.column_major;
268
269 if (parameters) {
270 for (i = 0; i < parameters; i++)
271 if (!SDDS_TransferParameterDefinition(&SDDSout, &SDDS1, parameterName[i], parameterName[i]))
272 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
273 }
274
275 if (!SDDS_WriteLayout(&SDDSout)) {
276 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
277 exit(EXIT_FAILURE);
278 }
279
280 code2 = -1;
281 while ((code1 = SDDS_ReadPage(&SDDS1)) > 0) {
282 if ((rows1 = SDDS_RowCount(&SDDS1)) <= 0) {
283 fprintf(stderr, "Warning (sddsconvolve): Skipping page due to no signal rows.\n");
284 continue;
285 }
286 if (reuse) {
287 if (code2 == -1) {
288 if ((code2 = SDDS_ReadPage(&SDDS2)) <= 0) {
289 fprintf(stderr, "Error (sddsconvolve): Couldn't read data from response file.\n");
290 exit(EXIT_FAILURE);
291 }
292 if ((rows2 = SDDS_RowCount(&SDDS2)) < 0) {
293 fprintf(stderr, "Error (sddsconvolve): Response file has zero rows on first page.\n");
294 exit(EXIT_FAILURE);
295 }
296 }
297 } else {
298 if ((code2 = SDDS_ReadPage(&SDDS2)) <= 0)
299 break;
300 rows2 = SDDS_RowCount(&SDDS2);
301 }
302 if (rows1 != rows2)
303 SDDS_Bomb("Different numbers of points for signal and response.");
304
305 if (!(signal1 = SDDS_GetColumnInDoubles(&SDDS1, input1Column[1])) ||
306 !(indep1 = SDDS_GetColumnInDoubles(&SDDS1, input1Column[0])) ||
307 !(signal2 = SDDS_GetColumnInDoubles(&SDDS2, input2Column[1])) ||
308 !(indep2 = SDDS_GetColumnInDoubles(&SDDS2, input2Column[0]))) {
309 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
310 exit(EXIT_FAILURE);
311 }
312
313 if (!(fft_sig = SDDS_Calloc(sizeof(*fft_sig), (2 * rows1 + 2))) ||
314 !(fft_res = SDDS_Calloc(sizeof(*fft_res), (2 * rows1 + 2)))) {
315 SDDS_SetError("Memory allocation failure.");
316 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
317 exit(EXIT_FAILURE);
318 }
319
320 /* Rearrange response for FFT */
321 wrap_around_order(fft_res, indep2, signal2, rows2, rows1);
322 for (i = 0; i < rows1; i++)
323 fft_sig[i] = signal1[i];
324
325 /* Perform FFT on signal and response */
326 realFFT2(fft_sig, fft_sig, 2 * rows1, 0);
327 realFFT2(fft_res, fft_res, 2 * rows1, 0);
328 nfreq = rows1 + 1;
329 range = 2 * rows1 * (indep1[rows1 - 1] - indep1[0]) / (rows1 - 1);
330
331 if (mode == MODE_CONVOLVE || mode == MODE_CORRELATE) {
332 if (mode == MODE_CORRELATE)
333 /* Take complex conjugate of response FFT */
334 for (i = 0; i < nfreq; i++)
335 fft_res[2 * i + 1] = -fft_res[2 * i + 1];
336
337 /* Multiply FFTs */
338 for (i = 0; i < nfreq; i++) {
339 complex_multiply(&fft_sig[2 * i], &fft_sig[2 * i + 1],
340 fft_sig[2 * i], fft_sig[2 * i + 1],
341 fft_res[2 * i], fft_res[2 * i + 1]);
342 }
343
344 /* Inverse FFT */
345 realFFT2(fft_sig, fft_sig, 2 * rows1, INVERSE_FFT);
346
347 /* Apply normalization factor */
348 for (i = 0; i < rows1; i++)
349 fft_sig[i] *= range;
350
351 /* Write output */
352 if (!SDDS_StartPage(&SDDSout, rows1) ||
353 !SDDS_CopyParameters(&SDDSout, &SDDS1) ||
354 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, fft_sig, rows1, outputColumn[1]) ||
355 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, indep1, rows1, outputColumn[0]) ||
356 !SDDS_WritePage(&SDDSout)) {
357 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
358 exit(EXIT_FAILURE);
359 }
360 } else if (mode == MODE_DECONVOLVE) {
361 double maxMag2;
362 /* Calculate maximum magnitude squared */
363 for (i = threshold = 0; i < nfreq; i++) {
364 if ((mag2 = sqr(fft_res[2 * i]) + sqr(fft_res[2 * i + 1])) > threshold)
365 threshold = mag2;
366 }
367 maxMag2 = threshold;
368 threshold = threshold * noise;
369
370 if (doWiener) {
371 /* Compute and apply Wiener filter */
372 double *S = NULL, *N = NULL, wThreshold;
373 if (!(WienerFilter = malloc(sizeof(*WienerFilter) * nfreq)) ||
374 !(S = malloc(sizeof(*S) * nfreq)) ||
375 !(N = malloc(sizeof(*N) * nfreq))) {
376 SDDS_Bomb("Memory allocation failure.");
377 }
378 wThreshold = maxMag2 * sqr(WienerFraction);
379 for (i = 0; i < nfreq; i++) {
380 S[i] = sqrt(sqr(fft_res[2 * i]) + sqr(fft_res[2 * i + 1]));
381 if (sqr(S[i]) < wThreshold) {
382 N[i] = S[i];
383 S[i] = 0;
384 } else {
385 S[i] = S[i] - sqrt(wThreshold);
386 N[i] = sqrt(wThreshold);
387 }
388 }
389 for (i = 0; i < nfreq; i++)
390 WienerFilter[i] = sqr(S[i]) / (sqr(S[i]) + sqr(N[i]) + threshold);
391 free(N);
392 free(S);
393 }
394
395 /* Perform division in frequency domain */
396 for (i = 0; i < nfreq; i++) {
397 complex_divide(&fft_sig[2 * i], &fft_sig[2 * i + 1],
398 fft_sig[2 * i], fft_sig[2 * i + 1],
399 fft_res[2 * i], fft_res[2 * i + 1],
400 threshold);
401 }
402
403 if (doWiener) {
404 for (i = 0; i < nfreq; i++) {
405 fft_sig[2 * i] *= WienerFilter[i];
406 fft_sig[2 * i + 1] *= WienerFilter[i];
407 }
408 free(WienerFilter);
409 }
410
411 /* Inverse FFT */
412 realFFT2(fft_sig, fft_sig, 2 * rows1, INVERSE_FFT);
413
414 /* Apply normalization factor */
415 for (i = 0; i < rows1; i++)
416 fft_sig[i] = fft_sig[i] / range;
417
418 /* Write output */
419 if (!SDDS_StartPage(&SDDSout, rows1) ||
420 !SDDS_CopyParameters(&SDDSout, &SDDS1) ||
421 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, fft_sig, rows1, outputColumn[1]) ||
422 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, indep1, rows1, outputColumn[0]) ||
423 !SDDS_WritePage(&SDDSout)) {
424 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
425 exit(EXIT_FAILURE);
426 }
427 } else {
428 SDDS_Bomb("Unexpected processing mode encountered.");
429 }
430
431 /* Free allocated memory for this iteration */
432 free(fft_sig);
433 fft_sig = NULL;
434 free(fft_res);
435 fft_res = NULL;
436 free(signal1);
437 free(indep1);
438 free(signal2);
439 free(indep2);
440 signal1 = indep1 = signal2 = indep2 = NULL;
441 }
442
443 if (!SDDS_Terminate(&SDDS1) || !SDDS_Terminate(&SDDS2) || !SDDS_Terminate(&SDDSout)) {
444 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
445 exit(EXIT_FAILURE);
446 }
447
448 if (tmpfile_used && !replaceFileAndBackUp(input1, output))
449 exit(EXIT_FAILURE);
450
451 free(parameterName);
452 free_scanargs(&scanned, argc);
453
454 return EXIT_SUCCESS;
455}
456
457void wrap_around_order(double *response1, double *t, double *response, int64_t nres, int64_t nsig) {
458 int64_t i;
459 int64_t iz;
460
461 for (iz = 0; iz < nres; iz++)
462 if (t[iz] >= 0)
463 break;
464 if (iz == nres)
465 bomb("Response function is acausal.", NULL);
466
467 fill_double_array(response1, 2 * nsig + 2, 0.0L);
468 for (i = iz; i < nres; i++)
469 response1[i - iz] = response[i];
470 for (i = 0; i < iz; i++)
471 response1[2 * nsig - (iz - i)] = response[i];
472}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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:49
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:379
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:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void * SDDS_Calloc(size_t nelem, size_t elem_size)
Allocates zero-initialized memory for an array of elements.
Definition SDDS_utils.c:617
#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
void fill_double_array(double *array, long n, double value)
Fills a double array with the specified value.
Definition fill_array.c:27
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:75
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:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
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:105
void complex_multiply(double *r0, double *i0, double r1, double i1, double r2, double i2)
Multiplies two complex numbers.
Definition complex.cc:81