211 {
212 int iArg;
213 char *boundaryFile, *boundaryColumn, *boundaryColumnUnits;
214 double *boundaryValue;
215 int64_t nBoundaryValues;
216 char **abscissaName, **columnName, **excludeName;
217 long columnNames, excludeNames, abscissaNames, column, offset;
218 long givenLowerLimits, givenUpperLimits;
219 char *input, *output;
220 long readCode, binsGiven;
221 int64_t i, rows, bins, writeBins;
222 long lowerLimitGiven, upperLimitGiven, doSides, doSeparate;
223 double autoBinsTarget;
224 long autoBinsMinimum, autoBinsMaximum;
225 char *weightColumn;
226 double *weightData;
227 short normMode = NORMALIZE_NO;
228 unsigned long pipeFlags;
229 SCANNED_ARG *scanned;
231 double binSize, *lowerLimit = NULL, *upperLimit = NULL, *givenLowerLimit, *givenUpperLimit, *dx = NULL, range, middle;
232 double **inputData, *abscissa, *histogram, *minValue, *maxValue, transferLimit, *cdf, sum;
233 long *abscissaIndex, *histogramIndex, *cdfIndex;
234 double expandRange, maxRange;
235 char *CDFONLY;
236 unsigned long dummyFlags, majorOrderFlag;
237 short columnMajorOrder = -1;
238 int threads = 1;
239
241 argc =
scanargs(&scanned, argc, argv);
242 if (argc < 3 || argc > (3 + N_OPTIONS)) {
243 fprintf(stderr, "%s", USAGE);
244 exit(EXIT_FAILURE);
245 }
246
247 minValue = maxValue = NULL;
248 output = input = NULL;
249 pipeFlags = 0;
250 abscissaName = NULL;
251 boundaryFile = boundaryColumn = boundaryColumnUnits = NULL;
252 boundaryValue = NULL;
253 offset = 0;
254 columnName = excludeName = NULL;
255 columnNames = excludeNames = abscissaNames = 0;
256 givenLowerLimits = givenUpperLimits = 0;
257 givenLowerLimit = givenUpperLimit = NULL;
258 bins = binsGiven = binSize = doSides = doSeparate = 0;
259 lowerLimitGiven = upperLimitGiven = 0;
260 expandRange = 0;
261 cdfOnly = 0;
262 freOnly = 1;
263 autoBinsTarget = 0;
264 autoBinsMinimum = autoBinsMaximum = 0;
265 weightColumn = NULL;
266 weightData = NULL;
267
268 for (iArg = 1; iArg < argc; iArg++) {
269 if (scanned[iArg].arg_type == OPTION) {
270
271 switch (
match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
272 case SET_MAJOR_ORDER:
273 majorOrderFlag = 0;
274 scanned[iArg].n_items--;
275 if (scanned[iArg].n_items > 0 && (!
scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
"row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
"column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
276 SDDS_Bomb(
"invalid -majorOrder syntax/values");
277 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
278 columnMajorOrder = 1;
279 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
280 columnMajorOrder = 0;
281 break;
282 case SET_PIPE:
283 if (!
processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
285 break;
286 case SET_COLUMNS:
287 if (columnName)
288 SDDS_Bomb(
"only one -columns option may be given");
289 if (scanned[iArg].n_items < 2)
291 if (!(columnName =
SDDS_Realloc(columnName,
sizeof(*columnName) * (columnNames + scanned[iArg].n_items - 1))))
293 for (i = 1; i < scanned[iArg].n_items; i++)
294 columnName[columnNames + i - 1] = scanned[iArg].list[i];
295 columnNames += scanned[iArg].n_items - 1;
296 break;
297 case SET_ABSCISSA:
298 if (abscissaName)
299 SDDS_Bomb(
"only one -abscissa option may be given");
300 if (scanned[iArg].n_items >= 2) {
301 if (!(abscissaName =
SDDS_Realloc(abscissaName,
sizeof(*abscissaName) * (abscissaNames + scanned[iArg].n_items - 1))))
303 for (i = 1; i < scanned[iArg].n_items; i++)
304 abscissaName[abscissaNames + i - 1] = scanned[iArg].list[i];
305 abscissaNames += scanned[iArg].n_items - 1;
306 }
307 break;
308 case SET_BINS:
309 if (binsGiven)
310 SDDS_Bomb(
"-bins specified more than once");
311 binsGiven = 1;
312 if (sscanf(scanned[iArg].list[1], "%" SCNd64, &bins) != 1 || bins <= 0)
313 SDDS_Bomb(
"invalid value for bins---give a positive value");
314 break;
315 case SET_SIZEOFBINS:
316 if (sscanf(scanned[iArg].list[1], "%le", &binSize) != 1 || binSize <= 0)
317 SDDS_Bomb(
"invalid value for bin size---give a positive value");
318 break;
319 case SET_AUTOBINS:
320 if (scanned[iArg].n_items < 2)
322 scanned[iArg].n_items -= 1;
323 autoBinsTarget = autoBinsMinimum = autoBinsMaximum = 0;
324 if (!
scanItemList(&dummyFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
326 "minimum",
SDDS_LONG, &autoBinsMinimum, 1, 0,
327 "maximum",
SDDS_LONG, &autoBinsMaximum, 1, 0, NULL) ||
328 autoBinsTarget <= 0 || autoBinsMinimum < 0 || autoBinsMaximum < 0)
329 SDDS_Bomb(
"incorrect -autoBins syntax or values");
330 break;
331 case SET_EXCLUDE:
332 if (excludeName)
333 SDDS_Bomb(
"only one -exclude option may be given");
334 if (scanned[iArg].n_items < 2)
336 if (!(excludeName =
SDDS_Realloc(excludeName,
sizeof(*excludeName) * (excludeNames + scanned[iArg].n_items - 1))))
338 for (i = 1; i < scanned[iArg].n_items; i++)
339 excludeName[excludeNames + i - 1] = scanned[iArg].list[i];
340 excludeNames += scanned[iArg].n_items - 1;
341 break;
342 case SET_LOWERLIMIT:
343 if (lowerLimitGiven)
344 SDDS_Bomb(
"-lowerLimit specified more than once");
345 lowerLimitGiven = 1;
346 if (!(givenLowerLimit =
SDDS_Realloc(givenLowerLimit,
sizeof(*givenLowerLimit) * (givenLowerLimits + scanned[iArg].n_items - 1))))
347 SDDS_Bomb(
"SET_LOWERLIMIT: memory allocation failure");
348 for (i = 1; i < scanned[iArg].n_items; i++) {
349 if (sscanf(scanned[iArg].list[i], "%lf", &transferLimit) != 1)
350 SDDS_Bomb(
"invalid value for -lowerLimit");
351 givenLowerLimit[givenLowerLimits + i - 1] = transferLimit;
352 }
353 givenLowerLimits += scanned[iArg].n_items - 1;
354 break;
355 case SET_UPPERLIMIT:
356 if (upperLimitGiven)
357 SDDS_Bomb(
"-upperLimit specified more than once");
358 upperLimitGiven = 1;
359 if (!(givenUpperLimit =
SDDS_Realloc(givenUpperLimit,
sizeof(*givenUpperLimit) * (givenUpperLimits + scanned[iArg].n_items - 1))))
360 SDDS_Bomb(
"SET_UPPERLIMIT: memory allocation failure");
361 for (i = 1; i < scanned[iArg].n_items; i++) {
362 if (sscanf(scanned[iArg].list[i], "%lf", &transferLimit) != 1)
363 SDDS_Bomb(
"invalid value for -upperLimit");
364 givenUpperLimit[givenUpperLimits + i - 1] = transferLimit;
365 }
366 givenUpperLimits += scanned[iArg].n_items - 1;
367 break;
368 case SET_SIDES:
369 doSides = DO_SIDES;
370 if (scanned[iArg].n_items == 2) {
371 static char *sideOpt[2] = {"close", "against"};
372 switch (
match_string(scanned[iArg].list[1], sideOpt, 2, 0)) {
373 case 0:
374 doSides = DO_CLOSE_SIDES;
375 break;
376 case 1:
377 doSides = DO_AGAINST_SIDES;
378 break;
379 default:
381 break;
382 }
383 }
384 break;
385 case SET_SEPARATE:
386 doSeparate = 1;
387 break;
388 case SET_EXPAND:
389 if (scanned[iArg].n_items != 2 ||
390 sscanf(scanned[iArg].list[1], "%lf", &expandRange) != 1 || expandRange <= 0)
392 break;
393 case SET_CDF:
394 if (scanned[iArg].n_items == 1)
395 cdfOnly = 0;
396 else {
397 if (scanned[iArg].n_items > 2)
399 CDFONLY = scanned[iArg].list[1];
400 if (strcmp(CDFONLY, "only") != 0)
401 SDDS_Bomb(
"invalid -cdf value, it should be -cdf or -cdf=only");
402 cdfOnly = 1;
403 }
404 freOnly = 0;
405 break;
406 case SET_BOUNDARYDATA:
407 if (scanned[iArg].n_items != 3 ||
408 !(boundaryFile = scanned[iArg].list[1]) ||
409 !strlen(boundaryFile) ||
410 !(boundaryColumn = scanned[iArg].list[2]) ||
411 !strlen(boundaryColumn))
412 SDDS_Bomb(
"invalid -boundaryData syntax or values");
413 break;
414 case SET_WEIGHT:
415 if (scanned[iArg].n_items != 2 ||
416 !(weightColumn = scanned[iArg].list[1]) ||
417 !strlen(weightColumn))
418 SDDS_Bomb(
"invalid -weightColumn syntax or values");
419 break;
420 case SET_NORMALIZE:
421 if (scanned[iArg].n_items == 1)
422 normMode = NORMALIZE_SUM;
423 else if (scanned[iArg].n_items != 2 ||
424 (normMode =
match_string(scanned[iArg].list[1], normalize_option, N_NORMALIZE_OPTIONS, 0)) < 0)
426 break;
427 case SET_THREADS:
428 if (scanned[iArg].n_items != 2 ||
429 sscanf(scanned[iArg].list[1], "%d", &threads) != 1 || threads < 1)
431 break;
432 default:
433 fprintf(stderr, "Error: unknown or ambiguous option: %s\n", scanned[iArg].list[0]);
434 fprintf(stderr, "%s", USAGE);
435 exit(EXIT_FAILURE);
436 break;
437 }
438 } else {
439 if (!input)
440 input = scanned[iArg].list[0];
441 else if (!output)
442 output = scanned[iArg].list[0];
443 else
445 }
446 }
447
448 if (boundaryColumn && (abscissaNames > 0 || doSeparate))
449 SDDS_Bomb(
"-boundaryData option is incompatible with -abscissa and -separate options");
450
451 if (columnNames <= 0)
452 SDDS_Bomb(
"Supply the names of columns to histogram with -columns");
453
455
458 exit(EXIT_FAILURE);
459 }
460
461 if ((columnNames = expandColumnPairNames(&SDDSin, &columnName, NULL, columnNames, excludeName, excludeNames, FIND_NUMERIC_TYPE, 0)) <= 0) {
463 SDDS_Bomb(
"No quantities selected to histogram.");
464 }
465
466 if (doSeparate) {
467 if (abscissaNames <= 0) {
468 if (!(abscissaName =
SDDS_Realloc(abscissaName,
sizeof(*abscissaName) * (abscissaNames + columnNames))))
470 abscissaNames = 0;
471 for (i = 0; i < columnNames; i++) {
472 abscissaName[abscissaNames + i] = columnName[i];
473 }
474 abscissaNames += columnNames;
475 }
476 if (columnNames > 1) {
477 if (abscissaNames > 0) {
478 if (columnNames != abscissaNames)
479 SDDS_Bomb(
"the number of abscissa names must match the number of columns");
480 }
481 if (givenLowerLimits)
482 if (columnNames != givenLowerLimits)
483 SDDS_Bomb(
"the number of lower limits must match the number of columns");
484 if (givenUpperLimits)
485 if (columnNames != givenUpperLimits)
486 SDDS_Bomb(
"the number of upper limits must match the number of columns");
487 } else {
488
489 if (abscissaNames > 0) {
490 if (columnNames != abscissaNames)
491 abscissaNames = 1;
492 }
493 if (givenLowerLimits)
494 if (columnNames != givenLowerLimits)
495 givenLowerLimits = 1;
496 if (givenUpperLimits)
497 if (columnNames != givenUpperLimits)
498 givenUpperLimits = 1;
499 }
500 } else if (boundaryFile) {
501 if (!(boundaryValue = ReadBoundaryData(boundaryFile, boundaryColumn, &nBoundaryValues, &boundaryColumnUnits))) {
502 SDDS_Bomb(
"Problem reading boundary data");
503 }
504 } else {
505 if (abscissaNames <= 0)
506 SDDS_Bomb(
"Supply the name of the abscissa with -abscissaName");
507 abscissaNames = 1;
508 }
509
510 SetUpOutput(&SDDSout, &SDDSin, &abscissaIndex, &cdfIndex, &histogramIndex, output, columnName, columnNames, abscissaName, abscissaNames, boundaryColumn, boundaryColumnUnits, columnMajorOrder, normMode);
511
512 if (!(inputData = (double **)malloc(columnNames * sizeof(*inputData))) ||
513 !(minValue = (double *)malloc(columnNames * sizeof(*minValue))) ||
514 !(maxValue = (double *)malloc(columnNames * sizeof(*maxValue))))
516
517 if (((binSize ? 1 : 0) + (binsGiven ? 1 : 0) + (autoBinsTarget ? 1 : 0)) > 1)
518 SDDS_Bomb(
"Specify only one of -binSize, -bins, or -autoBins");
519 if (!binSize && !binsGiven && !autoBinsTarget) {
520 binsGiven = 1;
521 bins = 20;
522 }
523
524 abscissa = histogram = cdf = NULL;
525
529
530 if (rows) {
533
534 for (column = 0; column < columnNames; column++) {
537 }
538
539 if (!boundaryColumn) {
540 if (!(lowerLimit = (double *)malloc(sizeof(*lowerLimit) * columnNames)))
542 if (!(upperLimit = (double *)malloc(sizeof(*upperLimit) * columnNames)))
544 if (!(dx = (double *)malloc(sizeof(*dx) * columnNames)))
546
547 if (doSeparate) {
548 for (column = 0; column < columnNames; column++) {
549 find_min_max(&minValue[column], &maxValue[column], inputData[column], rows);
550 lowerLimit[column] = givenLowerLimits ? givenLowerLimit[column] : minValue[column];
551 upperLimit[column] = givenUpperLimits ? givenUpperLimit[column] : maxValue[column];
552 }
553 } else {
554 for (column = 0; column < columnNames; column++)
555 find_min_max(&minValue[column], &maxValue[column], inputData[column], rows);
556 lowerLimit[0] = givenLowerLimits ? givenLowerLimit[0] :
min_in_array(minValue, columnNames);
557 upperLimit[0] = givenUpperLimits ? givenUpperLimit[0] :
max_in_array(maxValue, columnNames);
558 for (column = 1; column < columnNames; column++) {
559 lowerLimit[column] = lowerLimit[0];
560 upperLimit[column] = upperLimit[0];
561 }
562 }
563
564 range = (1 + expandRange) * (upperLimit[0] - lowerLimit[0]);
565 if (autoBinsTarget) {
566 bins = (int64_t)(rows / autoBinsTarget);
567 if (autoBinsMinimum) {
568 if (bins < autoBinsMinimum)
569 bins = autoBinsMinimum;
570 } else if (bins < 5) {
571 bins = 5;
572 }
573 if (autoBinsMaximum) {
574 if (bins > autoBinsMaximum)
575 bins = autoBinsMaximum;
576 } else if (bins > rows)
577 bins = rows;
578 }
579
580 if (binSize) {
581 maxRange = range;
582 for (column = 0; column < columnNames; column++) {
583 range = (1 + expandRange) * (upperLimit[column] - lowerLimit[column]);
584 range = ((range / binSize) + 1) * binSize;
585 if (range > maxRange)
586 maxRange = range;
587 middle = (lowerLimit[column] + upperLimit[column]) / 2;
588 lowerLimit[column] = middle - range / 2;
589 upperLimit[column] = middle + range / 2;
590 }
591 range = maxRange;
592 if (!doSeparate) {
595 dx[0] = binSize;
596 }
597 bins = maxRange / binSize + 0.5;
598 if (bins < 1 && !doSides)
599 bins = 2;
600 if (doSeparate)
601 for (column = 0; column < columnNames; column++) {
602 range = upperLimit[column] - lowerLimit[column];
603 upperLimit[column] += (maxRange - range) / 2;
604 lowerLimit[column] -= (maxRange - range) / 2;
605 dx[column] = binSize;
606 }
607 } else {
608 if (doSeparate) {
609 for (column = 0; column < columnNames; column++) {
610 range = (1 + expandRange) * (upperLimit[column] - lowerLimit[column]);
611 middle = (upperLimit[column] + lowerLimit[column]) / 2;
612 upperLimit[column] = middle + range / 2;
613 lowerLimit[column] = middle - range / 2;
614 if (upperLimit[column] == lowerLimit[column]) {
615 if (fabs(upperLimit[column]) < sqrt(DBL_MIN)) {
616 upperLimit[column] = sqrt(DBL_MIN);
617 lowerLimit[column] = -sqrt(DBL_MIN);
618 } else {
619 lowerLimit[column] = upperLimit[column] * (1 - 10000 * DBL_EPSILON);
620 upperLimit[column] = upperLimit[column] * (1 + 10000 * DBL_EPSILON);
621 }
622 }
623 dx[column] = (upperLimit[column] - lowerLimit[column]) / bins;
624 }
625 } else {
626 range = (1 + expandRange) * (upperLimit[0] - lowerLimit[0]);
627 middle = (upperLimit[0] + lowerLimit[0]) / 2;
628 upperLimit[0] = middle + range / 2;
629 lowerLimit[0] = middle - range / 2;
630 if (upperLimit[0] == lowerLimit[0]) {
631 if (fabs(upperLimit[0]) < sqrt(DBL_MIN)) {
632 upperLimit[0] = sqrt(DBL_MIN);
633 lowerLimit[0] = -sqrt(DBL_MIN);
634 } else {
635 lowerLimit[0] = upperLimit[0] * (1 - 10000 * DBL_EPSILON);
636 upperLimit[0] = upperLimit[0] * (1 + 10000 * DBL_EPSILON);
637 }
638 }
639 dx[0] = (upperLimit[0] - lowerLimit[0]) / bins;
640 }
641 }
642 if (!binsGiven || !abscissa) {
643 if (!(abscissa =
SDDS_Realloc(abscissa,
sizeof(*abscissa) * (bins + 2))) ||
644 !(cdf =
SDDS_Realloc(cdf,
sizeof(*cdf) * (bins + 2))) ||
645 !(histogram =
SDDS_Realloc(histogram,
sizeof(*histogram) * (bins + 2))))
647 }
648 writeBins = bins + (doSides ? 2 : 0);
649 offset = doSides ? 0 : 1;
650 } else {
651 bins = writeBins = nBoundaryValues;
652 abscissa = NULL;
654 !(histogram =
SDDS_Realloc(histogram,
sizeof(*histogram) * bins)))
656 }
657
660
661 if (boundaryColumn) {
662 for (column = 0; column < columnNames; column++) {
663 MakeBoundaryHistogram(histogram, cdf, boundaryValue, nBoundaryValues, inputData[column], weightData, rows);
664 NormalizeHistogram(histogram, nBoundaryValues, normMode);
665 if (!cdfOnly && !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, histogram, writeBins, histogramIndex[column]))
667 if (!freOnly && !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, cdf, writeBins, cdfIndex[column]))
669 free(inputData[column]);
670 }
671 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_NAME, boundaryValue, writeBins, boundaryColumn))
673 } else if (!doSeparate) {
674 for (i = -1; i < bins + 1; i++)
675 abscissa[i + 1] = (i + 0.5) * dx[0] + lowerLimit[0];
676 switch (doSides) {
677 case DO_CLOSE_SIDES:
678 abscissa[0] = abscissa[1] - dx[0] / 2;
679 abscissa[bins + 1] = abscissa[bins] + dx[0] / 2;
680 break;
681 case DO_AGAINST_SIDES:
682 abscissa[0] = abscissa[1];
683 abscissa[bins + 1] = abscissa[bins];
684 break;
685 }
686 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, abscissa + offset, writeBins, abscissaIndex[0]))
688 for (column = 0; column < columnNames; column++) {
689 histogram[0] = histogram[bins + 1] = 0;
690 if (!weightColumn)
691 make_histogram_threaded(histogram + 1, bins, lowerLimit[0], upperLimit[0], inputData[column], rows, 1, threads);
692 else
693 make_histogram_weighted_threaded(histogram + 1, bins, lowerLimit[0], upperLimit[0], inputData[column], rows, 1, weightData, threads);
694 NormalizeHistogram(histogram, bins, normMode);
695 sum = 0;
696 for (i = 0; i <= bins + 1; i++)
697 sum += histogram[i];
698 for (i = 0; i <= bins + 1; i++) {
699 if (!i)
700 cdf[i] = histogram[i] / sum;
701 else
702 cdf[i] = cdf[i - 1] + histogram[i] / sum;
703 }
704 if (!cdfOnly) {
705 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, histogram + offset, writeBins, histogramIndex[column]))
707 }
708 if (!freOnly) {
709 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, cdf + offset, writeBins, cdfIndex[column]))
711 }
712 free(inputData[column]);
713 }
714 } else {
715 for (column = 0; column < columnNames; column++) {
716 for (i = -1; i < bins + 1; i++)
717 abscissa[i + 1] = (i + 0.5) * dx[column] + lowerLimit[column];
718 switch (doSides) {
719 case DO_CLOSE_SIDES:
720 abscissa[0] = abscissa[1] - dx[column] / 2;
721 abscissa[bins + 1] = abscissa[bins] + dx[column] / 2;
722 break;
723 case DO_AGAINST_SIDES:
724 abscissa[0] = abscissa[1];
725 abscissa[bins + 1] = abscissa[bins];
726 break;
727 }
728 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, abscissa + offset, writeBins, abscissaIndex[column]))
730 histogram[0] = histogram[bins + 1] = 0;
731 if (!weightColumn)
732 make_histogram_threaded(histogram + 1, bins, lowerLimit[column], upperLimit[column], inputData[column], rows, 1, threads);
733 else
734 make_histogram_weighted_threaded(histogram + 1, bins, lowerLimit[column], upperLimit[column], inputData[column], rows, 1, weightData, threads);
735 NormalizeHistogram(histogram, bins + 2, normMode);
736 sum = 0;
737 for (i = 0; i <= bins + 1; i++)
738 sum += histogram[i];
739 for (i = 0; i <= bins + 1; i++) {
740 if (!i)
741 cdf[i] = histogram[i] / sum;
742 else
743 cdf[i] = cdf[i - 1] + histogram[i] / sum;
744 }
745 if (!cdfOnly) {
746 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, histogram + offset, writeBins, histogramIndex[column]))
748 }
749 if (!freOnly) {
750 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, cdf + offset, writeBins, cdfIndex[column]))
752 }
753 free(inputData[column]);
754 }
755 }
756 } else {
759 }
760 if (weightData) {
761 free(weightData);
762 weightData = NULL;
763 }
766 }
767
770 exit(EXIT_FAILURE);
771 }
774 exit(EXIT_FAILURE);
775 }
776
777 free(histogram);
778 free(cdf);
779 free(abscissa);
780 if (minValue)
781 free(minValue);
782 if (maxValue)
783 free(maxValue);
784 if (lowerLimit)
785 free(lowerLimit);
786 if (upperLimit)
787 free(upperLimit);
788 if (dx)
789 free(dx);
790
791 return EXIT_SUCCESS;
792}
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
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.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
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.
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_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_DOUBLE
Identifier for the double data type.
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
double max_in_array(double *array, long n)
Finds the maximum value in an array of doubles.
double min_in_array(double *array, long n)
Finds the minimum value in an array of doubles.
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)
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.