SDDSlib
Loading...
Searching...
No Matches
sddspoly.c
Go to the documentation of this file.
1/**
2 * @file sddspoly.c
3 * @brief Evaluates polynomials for N-dimensional input from SDDS files.
4 *
5 * This program reads input data and evaluates polynomials defined in an auxiliary SDDS file.
6 * It processes polynomials for multiple input columns and writes the results to an output SDDS file.
7 *
8 * ### Features:
9 * - Supports standard SDDS pipe options for input and output.
10 * - Accepts polynomial definitions with coefficients and exponents for up to 5 inputs.
11 * - Outputs evaluated results as specified columns in the output SDDS file.
12 *
13 * ### Usage:
14 * ```
15 * sddspoly [<inputfile>] [<outputfile>] \
16 * [-pipe=[input][,output]] \
17 * -evaluate=filename=<polyFilename>,output=<column>,coefficients=<column>, \
18 * input0=<inputColumn>,power0=<powerColumn>[,input1=<inputColumn>,power1=<powerColumn>]...
19 * ```
20 *
21 * - **-pipe**: Standard SDDS Toolkit pipe option for input/output streams.
22 * - **-evaluate**: Specifies polynomial evaluation with options:
23 * - `filename`: SDDS file containing polynomial definitions.
24 * - `output`: Column name for storing results in the output file.
25 * - `coefficients`: Column containing polynomial coefficients.
26 * - `input<n>`: Input column names for polynomial variables.
27 * - `power<n>`: Column names providing exponents for inputs.
28 *
29 * ### Example:
30 * ```
31 * sddspoly input.sdds output.sdds \
32 * -evaluate=filename=poly.sdds,output=Result,coefficients=Coef, \
33 * input0=X,power0=PowerX,input1=Y,power1=PowerY
34 * ```
35 *
36 * @copyright
37 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
38 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
39 *
40 * @license
41 * This file is distributed under the terms of the Software License Agreement
42 * found in the file LICENSE included with this distribution.
43 *
44 * @author M. Borland, H. Shang, R. Soliday
45 */
46
47#include "mdb.h"
48#include "SDDS.h"
49#include "scan.h"
50#include "SDDSutils.h"
51#include <ctype.h>
52
53/* Enumeration for option types */
54enum option_type {
55 CLO_PIPE,
56 CLO_EVALUATE,
57 N_OPTIONS
58};
59
60char *option[N_OPTIONS] = {
61 "pipe",
62 "evaluate",
63};
64
65static char *USAGE =
66 "Usage: sddspoly [<inputfile>] [<outputfile>] "
67 "[-pipe=[input][,output]]\n"
68 " -evaluate=filename=<polyFilename>,output=<column>,coefficients=<column>,\n"
69 " input0=<inputColumn>,power0=<powerColumn>[,input1=<inputColumn>,power1=<polyColumn>][,...]\n"
70 " [-evaluate=...]\n\n"
71 "Options:\n"
72 " -pipe Standard SDDS Toolkit pipe option.\n"
73 " -evaluate Specifies evaluation of a polynomial defined in <polyFilename>.\n"
74 " The results are stored in <outputfile> under the column name\n"
75 " specified by output=<column>.\n"
76 " The coefficients are taken from the column named\n"
77 " coefficients=<column>.\n"
78 " The input<n> qualifiers specify the column names in <inputfile>\n"
79 " that serve as inputs to the polynomial.\n"
80 " The power<n> qualifiers specify the column names in\n"
81 " <polyFilename> that provide the exponents for each input.\n\n"
82 "Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
83
84#define POLY_FILE_SEEN 0x0001U
85#define POLY_OUTPUT_SEEN 0x0002U
86#define POLY_COEF_SEEN 0x0004U
87#define POLY_IN0_SEEN 0x0008U
88#define POLY_OUT0_SEEN 0x0010U
89#define POLY_IN1_SEEN 0x0020U
90#define POLY_OUT1_SEEN 0x0040U
91#define POLY_IN2_SEEN 0x0080U
92#define POLY_OUT2_SEEN 0x0100U
93#define POLY_IN3_SEEN 0x0200U
94#define POLY_OUT3_SEEN 0x0400U
95#define POLY_IN4_SEEN 0x0800U
96#define POLY_OUT4_SEEN 0x1000U
97
98typedef struct {
99 unsigned long flags;
100 char *filename;
101 char *outputColumn;
102 char *coefColumn;
103 char **inputColumn;
104 char **powerColumn;
105 long nInputs;
106 long nTerms;
107 int32_t **power;
108 double *coef;
109 double **inputData;
110 double *input;
111} POLYNOMIAL;
112
113void initializePolynomial(POLYNOMIAL *poly, SDDS_DATASET *SDDSin, SDDS_DATASET *SDDSout);
114double evaluatePoly(double *coef, int32_t **power, long nCoef, double *input, long nInputs);
115void FreePolynormialMemory(POLYNOMIAL *poly, long npoly);
116
117int main(int argc, char **argv) {
119 long nPoly, iPoly, iInput;
120 int64_t row, rows;
121 int iArg;
122 char *input, *output;
123 unsigned long pipeFlags;
124 SCANNED_ARG *scanned;
125 SDDS_DATASET SDDSin, SDDSout;
126 double *outputData;
127
129 argc = scanargs(&scanned, argc, argv);
130 if (argc < 3) {
131 bomb(NULL, USAGE);
132 }
133
134 outputData = NULL;
135 input = output = NULL;
136 pipeFlags = 0;
137 poly = NULL;
138 nPoly = 0;
139
140 for (iArg = 1; iArg < argc; iArg++) {
141 if (scanned[iArg].arg_type == OPTION) {
142 /* process options here */
143 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
144 case CLO_EVALUATE:
145 poly = SDDS_Realloc(poly, sizeof(*poly) * (nPoly + 1));
146 if (!poly ||
147 !(poly[nPoly].inputColumn = SDDS_Malloc(sizeof(*(poly[nPoly].inputColumn)) * 5)) ||
148 !(poly[nPoly].powerColumn = SDDS_Malloc(sizeof(*(poly[nPoly].powerColumn)) * 5))) {
149 SDDS_Bomb("memory allocation failure");
150 }
151
152 scanned[iArg].n_items -= 1;
153 if (!scanItemList(&poly[nPoly].flags,
154 scanned[iArg].list + 1,
155 &scanned[iArg].n_items,
156 0,
157 "filename", SDDS_STRING, &(poly[nPoly].filename), 1, POLY_FILE_SEEN,
158 "output", SDDS_STRING, &(poly[nPoly].outputColumn), 1, POLY_OUTPUT_SEEN,
159 "coefficients", SDDS_STRING, &(poly[nPoly].coefColumn), 1, POLY_COEF_SEEN,
160 "input0", SDDS_STRING, poly[nPoly].inputColumn + 0, 1, POLY_IN0_SEEN,
161 "power0", SDDS_STRING, poly[nPoly].powerColumn + 0, 1, POLY_OUT0_SEEN,
162 "input1", SDDS_STRING, poly[nPoly].inputColumn + 1, 1, POLY_IN1_SEEN,
163 "power1", SDDS_STRING, poly[nPoly].powerColumn + 1, 1, POLY_OUT1_SEEN,
164 "input2", SDDS_STRING, poly[nPoly].inputColumn + 2, 1, POLY_IN2_SEEN,
165 "power2", SDDS_STRING, poly[nPoly].powerColumn + 2, 1, POLY_OUT2_SEEN,
166 "input3", SDDS_STRING, poly[nPoly].inputColumn + 3, 1, POLY_IN3_SEEN,
167 "power3", SDDS_STRING, poly[nPoly].powerColumn + 3, 1, POLY_OUT3_SEEN,
168 "input4", SDDS_STRING, poly[nPoly].inputColumn + 4, 1, POLY_IN4_SEEN,
169 "power4", SDDS_STRING, poly[nPoly].powerColumn + 4, 1, POLY_OUT4_SEEN,
170 NULL) ||
171 !(poly[nPoly].flags & POLY_FILE_SEEN) ||
172 !(poly[nPoly].flags & POLY_OUTPUT_SEEN) ||
173 !(poly[nPoly].flags & POLY_COEF_SEEN) ||
174 !(poly[nPoly].flags & POLY_IN0_SEEN) ||
175 !(poly[nPoly].flags & POLY_OUT0_SEEN)) {
176 SDDS_Bomb("invalid -evaluate syntax");
177 }
178 nPoly++;
179 break;
180
181 case CLO_PIPE:
182 if (!processPipeOption(scanned[iArg].list + 1,
183 scanned[iArg].n_items - 1,
184 &pipeFlags)) {
185 SDDS_Bomb("invalid -pipe syntax");
186 }
187 break;
188
189 default:
190 fprintf(stderr, "error: unknown/ambiguous option: %s\n", scanned[iArg].list[0]);
191 exit(EXIT_FAILURE);
192 break;
193 }
194 } else {
195 if (!input) {
196 input = scanned[iArg].list[0];
197 } else if (!output) {
198 output = scanned[iArg].list[0];
199 } else {
200 SDDS_Bomb("too many filenames seen");
201 }
202 }
203 }
204
205 processFilenames("sddspoly", &input, &output, pipeFlags, 0, NULL);
206
207 if (nPoly == 0) {
208 SDDS_Bomb("give at least one -evaluate option");
209 }
210
211 if (!SDDS_InitializeInput(&SDDSin, input)) {
212 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
213 }
214
215 if (!SDDS_InitializeCopy(&SDDSout, &SDDSin, output, "w")) {
216 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
217 }
218
219 for (iPoly = 0; iPoly < nPoly; iPoly++) {
220 initializePolynomial(&poly[iPoly], &SDDSin, &SDDSout);
221 }
222
223 if (!SDDS_WriteLayout(&SDDSout)) {
224 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
225 }
226
227 while (SDDS_ReadPage(&SDDSin) > 0) {
228 rows = SDDS_CountRowsOfInterest(&SDDSin);
229 if (!SDDS_CopyPage(&SDDSout, &SDDSin)) {
230 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
231 }
232
233 outputData = SDDS_Realloc(outputData, sizeof(*outputData) * rows);
234 if (!outputData) {
235 SDDS_Bomb("memory allocation failure");
236 }
237
238 for (iPoly = 0; iPoly < nPoly; iPoly++) {
239 for (iInput = 0; iInput < poly[iPoly].nInputs; iInput++) {
240 poly[iPoly].inputData[iInput] =
241 SDDS_GetColumnInDoubles(&SDDSin, poly[iPoly].inputColumn[iInput]);
242 if (!poly[iPoly].inputData[iInput]) {
243 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
244 }
245 }
246
247 for (row = 0; row < rows; row++) {
248 for (iInput = 0; iInput < poly[iPoly].nInputs; iInput++) {
249 poly[iPoly].input[iInput] = poly[iPoly].inputData[iInput][row];
250 }
251 outputData[row] = evaluatePoly(poly[iPoly].coef,
252 poly[iPoly].power,
253 poly[iPoly].nTerms,
254 poly[iPoly].input,
255 poly[iPoly].nInputs);
256 }
257
258 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_NAME, outputData, rows, poly[iPoly].outputColumn)) {
259 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
260 }
261 }
262
263 if (!SDDS_WritePage(&SDDSout)) {
264 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
265 }
266 }
267
268 free(outputData);
269
270 if (!SDDS_Terminate(&SDDSin)) {
271 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
272 exit(EXIT_FAILURE);
273 }
274
275 if (!SDDS_Terminate(&SDDSout)) {
276 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
277 exit(EXIT_FAILURE);
278 }
279
280 free_scanargs(&scanned, argc);
281 FreePolynormialMemory(poly, nPoly);
282 free(poly);
283
284 return EXIT_SUCCESS;
285}
286
287double evaluatePoly(double *coef, int32_t **power, long nCoef, double *input, long nInputs) {
288 double sum = 0.0, term;
289 long iCoef, iInput;
290
291 for (iCoef = 0; iCoef < nCoef; iCoef++) {
292 term = coef[iCoef];
293 for (iInput = 0; iInput < nInputs; iInput++) {
294 term *= ipow(input[iInput], power[iInput][iCoef]);
295 }
296 sum += term;
297 }
298
299 return sum;
300}
301
302void initializePolynomial(POLYNOMIAL *poly, SDDS_DATASET *SDDSin, SDDS_DATASET *SDDSout) {
303 long i;
304 SDDS_DATASET SDDSpoly;
305 char buffer[1024];
306
307 for (i = 1; i < 5; i++) {
308 if ((poly->flags & (POLY_IN0_SEEN << (2 * i))) &&
309 !(poly->flags & (POLY_OUT0_SEEN << (2 * i)))) {
310 SDDS_Bomb("input qualifier seen without matching output qualifier");
311 }
312 if (!(poly->flags & (POLY_IN0_SEEN << (2 * i))) &&
313 (poly->flags & (POLY_OUT0_SEEN << (2 * i)))) {
314 SDDS_Bomb("output qualifier seen without matching input qualifier");
315 }
316 if (!(poly->flags & (POLY_IN0_SEEN << (2 * i))) &&
317 !(poly->flags & (POLY_OUT0_SEEN << (2 * i)))) {
318 break;
319 }
320 }
321 poly->nInputs = i;
322
323 for (i++; i < 5; i++) {
324 if ((poly->flags & (POLY_IN0_SEEN << (2 * i))) ||
325 (poly->flags & (POLY_OUT0_SEEN << (2 * i)))) {
326 SDDS_Bomb("input<n> or output<n> qualifiers skipped");
327 }
328 }
329
330 if (!SDDS_InitializeInput(&SDDSpoly, poly->filename)) {
331 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
332 }
333
334 if (SDDS_GetColumnIndex(&SDDSpoly, poly->outputColumn) == -1) {
335 if (!SDDS_DefineSimpleColumn(SDDSout, poly->outputColumn, NULL, SDDS_DOUBLE)) {
336 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
337 }
338 } else {
339 if (SDDS_CheckColumn(&SDDSpoly, poly->outputColumn, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OKAY) {
340 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
341 }
342 }
343
344 if (SDDS_CheckColumn(&SDDSpoly, poly->coefColumn, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OKAY) {
345 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
346 }
347
348 for (i = 0; i < poly->nInputs; i++) {
349 if (SDDS_CheckColumn(SDDSin, poly->inputColumn[i], NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OKAY) {
350 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
351 }
352 if (SDDS_CheckColumn(&SDDSpoly, poly->powerColumn[i], NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OKAY) {
353 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
354 }
355 }
356
357 if (SDDS_ReadPage(&SDDSpoly) <= 0) {
358 snprintf(buffer, sizeof(buffer), "problem with file %s\n", poly->filename);
359 SDDS_SetError(buffer);
360 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
361 }
362
363 if ((poly->nTerms = SDDS_RowCount(&SDDSpoly)) <= 0) {
364 snprintf(buffer, sizeof(buffer), "problem with file %s: no rows\n", poly->filename);
365 SDDS_SetError(buffer);
366 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
367 }
368
369 poly->coef = SDDS_GetColumnInDoubles(&SDDSpoly, poly->coefColumn);
370 if (!poly->coef) {
371 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
372 }
373
374 poly->power = SDDS_Malloc(sizeof(*(poly->power)) * poly->nInputs);
375 if (!poly->power) {
376 SDDS_Bomb("memory allocation failure");
377 }
378
379 for (i = 0; i < poly->nInputs; i++) {
380 poly->power[i] = SDDS_GetColumnInLong(&SDDSpoly, poly->powerColumn[i]);
381 if (!poly->power[i]) {
382 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
383 }
384 }
385
386 if (!SDDS_Terminate(&SDDSpoly)) {
387 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
388 }
389
390 poly->input = SDDS_Malloc(sizeof(*(poly->input)) * poly->nInputs);
391 if (!poly->input) {
392 SDDS_Bomb("memory allocation failure");
393 }
394
395 poly->inputData = SDDS_Malloc(sizeof(*(poly->inputData)) * poly->nInputs);
396 if (!poly->inputData) {
397 SDDS_Bomb("memory allocation failure");
398 }
399}
400
401void FreePolynormialMemory(POLYNOMIAL *poly, long npoly) {
402 long i, j;
403
404 for (i = 0; i < npoly; i++) {
405 for (j = 0; j < poly[i].nInputs; j++) {
406 free(poly[i].power[j]);
407 free(poly[i].inputData[j]);
408 free(poly[i].inputColumn[j]);
409 free(poly[i].powerColumn[j]);
410 }
411 free(poly[i].powerColumn);
412 free(poly[i].inputColumn);
413 free(poly[i].power);
414 free(poly[i].input);
415 free(poly[i].inputData);
416 free(poly[i].coef);
417 free(poly[i].filename);
418 free(poly[i].coefColumn);
419 free(poly[i].outputColumn);
420 }
421}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
Definition SDDS_copy.c:40
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:578
int32_t SDDS_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
int32_t * SDDS_GetColumnInLong(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of 32-bit integers,...
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_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:639
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_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
Definition SDDStypes.h:157
#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
double ipow(const double x, const int64_t p)
Compute x raised to the power p (x^p).
Definition ipow.c:33
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.
double poly(double *a, long n, double x)
Evaluate a polynomial at a given point.
Definition poly.c:30
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.