128 {
129 int i_arg;
130 char *input = NULL, *output = NULL, **interpCol = NULL, **funcOf = NULL;
131 long order = 1, dataControls = 0, valid_option = 1, monotonicity;
132
133 SCANNED_ARG *s_arg;
134 OUTRANGE_CONTROL aboveRange, belowRange;
136 unsigned long pipeFlags = 0, interpCode = 0, majorOrderFlag;
138 double *indepValue = NULL, *depenValue = NULL, **out_depenValue = NULL, atValue = 0;
139 int32_t **rowFlag = NULL;
140 long valid_data = 0, index, pages = 0;
141 int64_t *rows = NULL;
142 int64_t i, j, datarows, row;
143 short columnMajorOrder = -1;
144
146 argc =
scanargs(&s_arg, argc, argv);
147 if (argc < 3) {
148 fprintf(stderr, "%s", USAGE);
149 exit(EXIT_FAILURE);
150 }
151
152 aboveRange.flags = belowRange.flags = OUTRANGE_SATURATE;
153
154 for (i_arg = 1; i_arg < argc; i_arg++) {
155 if (s_arg[i_arg].arg_type == OPTION) {
156 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
157 case CLO_MAJOR_ORDER:
158 majorOrderFlag = 0;
159 s_arg[i_arg].n_items--;
160 if (s_arg[i_arg].n_items > 0 &&
161 !
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
162 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
163 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)) {
164 SDDS_Bomb(
"invalid -majorOrder syntax/values");
165 }
166 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
167 columnMajorOrder = 1;
168 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
169 columnMajorOrder = 0;
170 break;
171
172 case CLO_ORDER:
173 if (s_arg[i_arg].n_items != 2 ||
174 sscanf(s_arg[i_arg].list[1], "%ld", &order) != 1 ||
175 order < 1) {
176 SDDS_Bomb(
"invalid -order syntax/value");
177 }
178 break;
179
180 case CLO_PIPE:
181 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags)) {
183 }
184 break;
185
186 case CLO_ABOVERANGE:
187 s_arg[i_arg].n_items -= 1;
188 if (s_arg[i_arg].n_items < 1 ||
189 !
scanItemList(&aboveRange.flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
190 "value",
SDDS_DOUBLE, &aboveRange.value, 1, OUTRANGE_VALUE,
191 "skip", -1, NULL, 0, OUTRANGE_SKIP,
192 "saturate", -1, NULL, 0, OUTRANGE_SATURATE,
193 "extrapolate", -1, NULL, 0, OUTRANGE_EXTRAPOLATE,
194 "wrap", -1, NULL, 0, OUTRANGE_WRAP,
195 "abort", -1, NULL, 0, OUTRANGE_ABORT,
196 "warn", -1, NULL, 0, OUTRANGE_WARN, NULL)) {
197 SDDS_Bomb(
"invalid -aboveRange syntax/value");
198 }
199 if ((i =
bitsSet(aboveRange.flags & (OUTRANGE_VALUE | OUTRANGE_SKIP | OUTRANGE_SATURATE |
200 OUTRANGE_EXTRAPOLATE | OUTRANGE_WRAP | OUTRANGE_ABORT))) > 1) {
201 SDDS_Bomb(
"incompatible keywords given for -aboveRange");
202 }
203 if (i != 1)
204 aboveRange.flags |= OUTRANGE_SATURATE;
205 break;
206
207 case CLO_VERBOSE:
208
209 break;
210
211 case CLO_BELOWRANGE:
212 s_arg[i_arg].n_items -= 1;
213 if (s_arg[i_arg].n_items < 1 ||
214 !
scanItemList(&belowRange.flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
215 "value",
SDDS_DOUBLE, &belowRange.value, 1, OUTRANGE_VALUE,
216 "skip", -1, NULL, 0, OUTRANGE_SKIP,
217 "saturate", -1, NULL, 0, OUTRANGE_SATURATE,
218 "extrapolate", -1, NULL, 0, OUTRANGE_EXTRAPOLATE,
219 "wrap", -1, NULL, 0, OUTRANGE_WRAP,
220 "abort", -1, NULL, 0, OUTRANGE_ABORT,
221 "warn", -1, NULL, 0, OUTRANGE_WARN, NULL)) {
222 SDDS_Bomb(
"invalid -belowRange syntax/value");
223 }
224 if ((i =
bitsSet(belowRange.flags & (OUTRANGE_VALUE | OUTRANGE_SKIP | OUTRANGE_SATURATE |
225 OUTRANGE_EXTRAPOLATE | OUTRANGE_WRAP | OUTRANGE_ABORT))) > 1) {
226 SDDS_Bomb(
"incompatible keywords given for -belowRange");
227 }
228 if (i != 1)
229 belowRange.flags |= OUTRANGE_SATURATE;
230 break;
231
232 case CLO_DATA:
233 s_arg[i_arg].n_items -= 1;
234 if (s_arg[i_arg].n_items < 4) {
236 }
237 data_control =
SDDS_Realloc(data_control,
sizeof(*data_control) * (dataControls + 1));
238 data_control[dataControls].fileColumn = data_control[dataControls].interpCol =
239 data_control[dataControls].funcOfCol = data_control[dataControls].atCol = NULL;
240 data_control[dataControls].file = NULL;
241 data_control[dataControls].files = 0;
242 data_control[dataControls].hasdata = 0;
243 data_control[dataControls].colValue = NULL;
244 data_control[dataControls].flags = 0;
245
246 if (!
scanItemList(&data_control[dataControls].flags, s_arg[i_arg].list + 1,
247 &s_arg[i_arg].n_items, 0,
248 "fileColumn",
SDDS_STRING, &(data_control[dataControls].fileColumn), 1, 0,
249 "interpolate",
SDDS_STRING, &(data_control[dataControls].interpCol), 1, 0,
250 "functionof",
SDDS_STRING, &(data_control[dataControls].funcOfCol), 1, 0,
251 "column",
SDDS_STRING, &(data_control[dataControls].atCol), 1, AT_COLUMN,
252 "atValue",
SDDS_DOUBLE, &(data_control[dataControls].atValue), 1, AT_VALUE, NULL) ||
253 !data_control[dataControls].fileColumn ||
254 !data_control[dataControls].interpCol ||
255 !data_control[dataControls].funcOfCol) {
257 }
258
259 if (!(data_control[dataControls].flags & AT_COLUMN) &&
260 !(data_control[dataControls].flags & AT_VALUE)) {
261 SDDS_Bomb(
"Invalid -data syntax: either column or atValue option should be given.");
262 }
263
264 if ((data_control[dataControls].flags & AT_COLUMN) &&
265 (data_control[dataControls].flags & AT_VALUE)) {
266 SDDS_Bomb(
"Invalid -data syntax: column and atValue options are not compatible.");
267 }
268
269 valid_option = 1;
270 if (dataControls) {
271 if (
match_string(data_control[dataControls].funcOfCol, funcOf, dataControls, EXACT_MATCH) > 0) {
272 fprintf(stderr, "Multiple independent columns provided!\n");
273 exit(EXIT_FAILURE);
274 }
275 if (
match_string(data_control[dataControls].interpCol, interpCol, dataControls, EXACT_MATCH) > 0) {
276 fprintf(stderr, "Warning: Interpolate column '%s' has been used.\n", data_control[dataControls].interpCol);
277 valid_option = 0;
278 }
279 }
280
281 if (valid_option) {
282 interpCol =
SDDS_Realloc(interpCol,
sizeof(*interpCol) * (dataControls + 1));
283 funcOf =
SDDS_Realloc(funcOf,
sizeof(*funcOf) * (dataControls + 1));
284 interpCol[dataControls] = data_control[dataControls].interpCol;
285 funcOf[dataControls] = data_control[dataControls].funcOfCol;
286 dataControls++;
287 }
288 break;
289
290 default:
291 fprintf(stderr, "Error: Unknown or ambiguous option '%s'\n", s_arg[i_arg].list[0]);
292 exit(EXIT_FAILURE);
293 break;
294 }
295 } else {
296 if (!input)
297 input = s_arg[i_arg].list[0];
298 else if (!output)
299 output = s_arg[i_arg].list[0];
300 else
301 SDDS_Bomb(
"Too many filenames provided.");
302 }
303 }
304
306
309
310 for (i = 0; i < dataControls; i++) {
312 fprintf(stderr, "Warning: Column '%s' does not exist in input file '%s'.\n",
313 data_control[i].fileColumn, input);
314 continue;
315 }
317 fprintf(stderr, "Error: Column '%s' in input file '%s' is not a string column.\n",
318 data_control[i].fileColumn, input);
319 continue;
320 }
321 if (data_control[i].atCol) {
323 fprintf(stderr, "Warning: Column '%s' does not exist in input file '%s'.\n",
324 data_control[i].atCol, input);
325 continue;
326 }
328 fprintf(stderr, "Error: Column '%s' in input file '%s' is not a numeric column.\n",
329 data_control[i].atCol, input);
330 continue;
331 }
332 }
333 data_control[i].hasdata = 1;
334 valid_data++;
335 }
336
337 if (!valid_data) {
338 fprintf(stderr, "Error: No valid -data options provided for processing.\n");
339 exit(EXIT_FAILURE);
340 }
341
344
345 if (columnMajorOrder != -1)
346 SDDSout.layout.data_mode.column_major = columnMajorOrder;
347 else
348 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
349
352 out_depenValue =
SDDS_Realloc(out_depenValue,
sizeof(*out_depenValue) * (pages + 1));
353 rowFlag =
SDDS_Realloc(rowFlag,
sizeof(*rowFlag) * (pages + 1));
354
356 fprintf(stderr, "Error: No data found in input file '%s'.\n", input);
357 exit(EXIT_FAILURE);
358 }
359
360 rowFlag[pages] = (int32_t *)malloc(sizeof(**rowFlag) * rows[pages]);
361 out_depenValue[pages] = (double *)malloc(sizeof(**out_depenValue) * rows[pages]);
362
363 for (i = 0; i < rows[pages]; i++)
364 rowFlag[pages][i] = 1;
365
366 for (i = 0; i < dataControls; i++) {
367 if (data_control[i].hasdata) {
368 data_control[i].files = rows[pages];
369 if (!(data_control[i].file = (
char **)
SDDS_GetColumn(&SDDSin, data_control[i].fileColumn))) {
371 }
372
373 if (data_control[i].atCol) {
376 }
377 }
378
379 if (!data_control[i].atCol)
380 atValue = data_control[i].atValue;
381
382 for (j = 0; j < rows[pages]; j++) {
385
387 case SDDS_CHECK_OKAY:
388 if (j == (rows[pages] - 1)) {
389 if (!pages) {
392 }
393 }
394 break;
395 default:
396 fprintf(stderr, "Error: Column '%s' missing or invalid in file '%s'.\n",
397 data_control[i].interpCol, data_control[i].file[j]);
398 exit(EXIT_FAILURE);
399 break;
400 }
401
403 case SDDS_CHECK_OKAY:
404 if (j == (rows[pages] - 1)) {
405 if ((!pages) && !(data_control[i].atCol)) {
408 }
409 }
410 break;
411 default:
412 fprintf(stderr, "Error: Column '%s' missing or invalid in file '%s'.\n",
413 data_control[i].funcOfCol, data_control[i].file[j]);
414 exit(EXIT_FAILURE);
415 break;
416 }
417
420
422
425 }
428 }
429
432
433 if (!(monotonicity = checkMonotonicity(indepValue, datarows))) {
434 fprintf(stderr, "Error: Independent (%s) data in file '%s' is not monotonic.\n",
435 data_control[i].funcOfCol, data_control[i].file[j]);
436 exit(EXIT_FAILURE);
437 }
438
439 if (data_control[i].atCol)
440 atValue = data_control[i].colValue[j];
441
442 out_depenValue[pages][j] =
interpolate(depenValue, indepValue, datarows, atValue,
443 &belowRange, &aboveRange, order, &interpCode, monotonicity);
444
445 if (interpCode) {
446 if (interpCode & OUTRANGE_ABORT) {
447 fprintf(stderr, "Error: Value %e out of range for column '%s'.\n",
448 atValue, data_control[i].interpCol);
449 exit(EXIT_FAILURE);
450 }
451 if (interpCode & OUTRANGE_WARN)
452 fprintf(stderr, "Warning: Value %e out of range for column '%s'.\n",
453 atValue, data_control[i].interpCol);
454 if (interpCode & OUTRANGE_SKIP)
455 rowFlag[pages][j] = 0;
456 }
457
458 free(depenValue);
459 free(indepValue);
460 }
461 }
462
463 for (j = 0; j < data_control[i].files; j++)
464 free(data_control[i].file[j]);
465 free(data_control[i].file);
466 data_control[i].file = NULL;
467
468 if (data_control[i].colValue) {
469 free(data_control[i].colValue);
470 data_control[i].colValue = NULL;
471 }
472 }
473
474 if (!pages) {
477 }
478
479 if (!SDDS_StartTable(&SDDSout, rows[pages]))
481
484
487
488 for (i = 0; i < dataControls; i++) {
489 if (data_control[i].hasdata) {
491 rows[pages], data_control[i].interpCol)) {
493 }
494 if (!(data_control[i].atCol)) {
495 for (row = 0; row < rows[pages]; row++) {
497 data_control[i].funcOfCol, data_control[i].atValue, NULL)) {
499 }
500 }
501 }
502 }
503 }
504
507
510
511 pages++;
512 }
513
516
519 exit(EXIT_FAILURE);
520 }
521
522 freedatacontrol(data_control, dataControls);
523
524 if (out_depenValue) {
525 for (i = 0; i < pages; i++) {
526 free(out_depenValue[i]);
527 free(rowFlag[i]);
528 }
529 free(out_depenValue);
530 free(rowFlag);
531 }
532
533 if (interpCol)
534 free(interpCol);
535 if (funcOf)
536 free(funcOf);
537 if (rows)
538 free(rows);
539
541 return EXIT_SUCCESS;
542}
int32_t SDDS_CopyColumns(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
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.
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.
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_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.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
#define SDDS_DOUBLE
Identifier for the double data type.
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
long bitsSet(unsigned long data)
Counts the number of set bits (1s) in the given data.
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.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
void free_scanargs(SCANNED_ARG **scanned, int argc)
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.