277 {
279 long stats;
281 long requests;
282 SCANNED_ARG *scanned;
284 long i_arg, code, power, iStat, pages, nowarnings = 0;
285 int64_t i, rows, firstRows;
286 char *input, *output;
287 double *inputData, *otherData, indepData, *weight;
288 unsigned long pipeFlags, majorOrderFlag;
289 double decilePoint[2] = {10.0, 90.0}, decileResult[2];
290 double percentilePoint, percentileResult;
291 double percentile;
292 short columnMajorOrder = -1;
293
295 argc =
scanargs(&scanned, argc, argv);
296 if (argc < 2) {
297 bomb(
"too few arguments", USAGE);
298 exit(EXIT_FAILURE);
299 }
300 weight = NULL;
301 input = output = NULL;
302 stat = NULL;
303 request = NULL;
304 stats = requests = pipeFlags = 0;
305 rows = firstRows = i = 0;
306
307 for (i_arg = 1; i_arg < argc; i_arg++) {
308 if (scanned[i_arg].arg_type == OPTION) {
309
310 switch (code =
match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
311 case SET_COPY:
312 case SET_MINIMA:
313 case SET_MAXIMA:
314 case SET_LARGEST:
315 case SET_SIGNEDLARGEST:
316 case SET_MEANS:
317 case SET_SDS:
318 case SET_SIGMAS:
319 case SET_RMSS:
320 case SET_MEDIAN:
321 case SET_DRANGE:
322 case SET_EXMM_MEAN:
323 if (scanned[i_arg].n_items < 2) {
324 fprintf(stderr, "error: invalid -%s syntax\n", option[code]);
325 exit(EXIT_FAILURE);
326 }
327 requests = addStatRequests(&request, requests, scanned[i_arg].list + 1, scanned[i_arg].n_items - 1, code, 0, 0, NULL, 0, NULL);
328 break;
329 case SET_WMEANS:
330 case SET_WSDS:
331 case SET_WRMSS:
332 case SET_WSIGMAS:
333 if (scanned[i_arg].n_items < 3) {
334 fprintf(stderr, "error: invalid -%s syntax\n", option[code]);
335 exit(EXIT_FAILURE);
336 }
337
338 requests = addStatRequests(&request, requests, scanned[i_arg].list + 1, scanned[i_arg].n_items - 1, code, 0, 0, NULL, 1, NULL);
339 break;
340 case SET_SUMS:
341 if (scanned[i_arg].n_items < 3) {
342 fprintf(stderr, "error: invalid -%s syntax\n", option[code]);
343 exit(EXIT_FAILURE);
344 }
345 if (sscanf(scanned[i_arg].list[1], "%ld", &power) != 1 || power < 1) {
346 fprintf(stderr, "error: invalid -%s syntax--bad power in field %s\n", option[code], scanned[i_arg].list[2]);
347 exit(EXIT_FAILURE);
348 }
349 requests = addStatRequests(&request, requests, scanned[i_arg].list + 2, scanned[i_arg].n_items - 2, code, 0, power, NULL, 0, NULL);
350 break;
351 case SET_PERCENTILE:
352 if (scanned[i_arg].n_items < 3) {
353 fprintf(stderr, "error: invalid -%s syntax\n", option[code]);
354 exit(EXIT_FAILURE);
355 }
356 if (sscanf(scanned[i_arg].list[1], "%lf", &percentile) != 1 || percentile < 0 || percentile > 100) {
357 fprintf(stderr, "error: invalid -%s syntax--bad percentage in field %s\n", option[code], scanned[i_arg].list[1]);
358 exit(EXIT_FAILURE);
359 }
360 requests = addStatRequests(&request, requests, scanned[i_arg].list + 2, scanned[i_arg].n_items - 2, code, percentile, 0, NULL, 0, scanned[i_arg].list[1]);
361 break;
362 case SET_SLOPE:
363 case SET_INTERCEPT:
364 case SET_PMINIMA:
365 case SET_PMAXIMA:
366 case SET_CMINIMA:
367 case SET_CMAXIMA:
368 if (scanned[i_arg].n_items < 3) {
369 fprintf(stderr, "error: invalid -%s syntax\n", option[code]);
370 exit(EXIT_FAILURE);
371 }
372 requests = addStatRequests(&request, requests, scanned[i_arg].list + 2, scanned[i_arg].n_items - 2, code, 0, 0, scanned[i_arg].list[1], 0, NULL);
373 break;
374 case SET_PIPE:
375 if (!
processPipeOption(scanned[i_arg].list + 1, scanned[i_arg].n_items - 1, &pipeFlags))
377 break;
378 case SET_NOWARNINGS:
379 nowarnings = 1;
380 break;
381 case SET_MAJOR_ORDER:
382 majorOrderFlag = 0;
383 scanned[i_arg].n_items--;
384 if (scanned[i_arg].n_items > 0 && (!
scanItemList(&majorOrderFlag, scanned[i_arg].list + 1, &scanned[i_arg].n_items, 0,
"row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
"column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
385 SDDS_Bomb(
"invalid -majorOrder syntax/values");
386 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
387 columnMajorOrder = 1;
388 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
389 columnMajorOrder = 0;
390 break;
391 default:
392 fprintf(stderr, "error: unknown option '%s' given\n", scanned[i_arg].list[0]);
393 exit(EXIT_FAILURE);
394 break;
395 }
396 } else {
397
398 if (!input)
399 input = scanned[i_arg].list[0];
400 else if (!output)
401 output = scanned[i_arg].list[0];
402 else
404 }
405 }
406
408
409 if (!requests)
411
414
415 pages = 0;
417 pages++;
419 SDDS_Bomb(
"empty data page in input file");
420 if (code == 1) {
421 firstRows = rows;
422 if (!(stat = compileStatDefinitions(&inTable, &stats, request, requests))) {
424 exit(EXIT_FAILURE);
425 }
426 if (!setupOutputFile(&outTable, output, &inTable, stat, stats, rows, columnMajorOrder)) {
429 else
430 fprintf(stderr, "Error setting up output file.\n");
431 exit(EXIT_FAILURE);
432 }
433 } else if (firstRows != rows)
434 SDDS_Bomb(
"inconsistent number of rows in input file");
435 for (iStat = 0; iStat < stats; iStat++) {
436 if (stat[iStat].optionCode == SET_COPY) {
437 if (code == 1 && !(stat[iStat].copy =
SDDS_GetColumn(&inTable, stat[iStat].sourceColumn)))
439 continue;
440 }
441 stat[iStat].copy = NULL;
444 switch (stat[iStat].optionCode) {
445 case SET_MINIMA:
446 if (code == 1)
447 for (i = 0; i < rows; i++)
448 stat[iStat].value1[i] = inputData[i];
449 else
450 for (i = 0; i < rows; i++)
451 if (stat[iStat].value1[i] > inputData[i])
452 stat[iStat].value1[i] = inputData[i];
453 break;
454 case SET_MAXIMA:
455 if (code == 1)
456 for (i = 0; i < rows; i++)
457 stat[iStat].value1[i] = inputData[i];
458 else
459 for (i = 0; i < rows; i++)
460 if (stat[iStat].value1[i] < inputData[i])
461 stat[iStat].value1[i] = inputData[i];
462 break;
463 case SET_CMINIMA:
464
467 if (code == 1)
468 for (i = 0; i < rows; i++) {
469 stat[iStat].value2[i] = inputData[i];
470 stat[iStat].value1[i] = otherData[i];
471 }
472 else
473 for (i = 0; i < rows; i++)
474 if (stat[iStat].value2[i] > inputData[i]) {
475 stat[iStat].value2[i] = inputData[i];
476 stat[iStat].value1[i] = otherData[i];
477 }
478 free(otherData);
479 break;
480 case SET_CMAXIMA:
481
484 if (code == 1)
485 for (i = 0; i < rows; i++) {
486 stat[iStat].value2[i] = inputData[i];
487 stat[iStat].value1[i] = otherData[i];
488 }
489 else
490 for (i = 0; i < rows; i++)
491 if (stat[iStat].value2[i] < inputData[i]) {
492 stat[iStat].value2[i] = inputData[i];
493 stat[iStat].value1[i] = otherData[i];
494 }
495 free(otherData);
496 break;
497 case SET_LARGEST:
498 if (code == 1)
499 for (i = 0; i < rows; i++)
500 stat[iStat].value1[i] = fabs(inputData[i]);
501 else
502 for (i = 0; i < rows; i++)
503 if (stat[iStat].value1[i] < fabs(inputData[i]))
504 stat[iStat].value1[i] = fabs(inputData[i]);
505 break;
506 case SET_SIGNEDLARGEST:
507 if (code == 1)
508 for (i = 0; i < rows; i++)
509 stat[iStat].value1[i] = inputData[i];
510 else
511 for (i = 0; i < rows; i++)
512 if (fabs(stat[iStat].value1[i]) < fabs(inputData[i]))
513 stat[iStat].value1[i] = inputData[i];
514 break;
515 case SET_MEANS:
516 if (code == 1)
517 for (i = 0; i < rows; i++)
518 stat[iStat].value1[i] = inputData[i];
519 else
520 for (i = 0; i < rows; i++)
521 stat[iStat].value1[i] += inputData[i];
522 break;
523 case SET_WMEANS:
526 for (i = 0; i < rows; i++) {
527 stat[iStat].sumWeight[i] += weight[i];
528 stat[iStat].value1[i] += inputData[i] * weight[i];
529 }
530 free(weight);
531 break;
532 case SET_SDS:
533 case SET_SIGMAS:
534 if (code == 1)
535 for (i = 0; i < rows; i++) {
536 stat[iStat].value1[i] = inputData[i];
537 stat[iStat].value2[i] = inputData[i] * inputData[i];
538 }
539 else
540 for (i = 0; i < rows; i++) {
541 stat[iStat].value1[i] += inputData[i];
542 stat[iStat].value2[i] += inputData[i] * inputData[i];
543 }
544 break;
545 case SET_WSDS:
546 case SET_WSIGMAS:
549 for (i = 0; i < rows; i++) {
550 stat[iStat].sumWeight[i] += weight[i];
551 stat[iStat].value1[i] += inputData[i] * weight[i];
552 stat[iStat].value2[i] += inputData[i] * inputData[i] * weight[i];
553 }
554 free(weight);
555 break;
556 case SET_RMSS:
557 if (code == 1)
558 for (i = 0; i < rows; i++)
559 stat[iStat].value1[i] = inputData[i] * inputData[i];
560 else
561 for (i = 0; i < rows; i++)
562 stat[iStat].value1[i] += inputData[i] * inputData[i];
563 break;
564 case SET_WRMSS:
567 for (i = 0; i < rows; i++) {
568 stat[iStat].sumWeight[i] += weight[i];
569 stat[iStat].value1[i] += inputData[i] * inputData[i] * weight[i];
570 }
571 free(weight);
572 break;
573 case SET_SUMS:
574 if (code == 1)
575 for (i = 0; i < rows; i++)
576 stat[iStat].value1[i] =
ipow(inputData[i], stat[iStat].sumPower);
577 else
578 for (i = 0; i < rows; i++)
579 stat[iStat].value1[i] +=
ipow(inputData[i], stat[iStat].sumPower);
580 break;
581 case SET_PMINIMA:
583 fprintf(stderr, "error: unable to get value of parameter %s\n", stat[iStat].functionOf);
585 }
586 if (code == 1)
587 for (i = 0; i < rows; i++) {
588 stat[iStat].value2[i] = inputData[i];
589 stat[iStat].value1[i] = indepData;
590 }
591 else
592 for (i = 0; i < rows; i++) {
593 if (stat[iStat].value2[i] > inputData[i]) {
594 stat[iStat].value2[i] = inputData[i];
595 stat[iStat].value1[i] = indepData;
596 }
597 }
598 break;
599 case SET_PMAXIMA:
601 fprintf(stderr, "error: unable to get value of parameter %s\n", stat[iStat].functionOf);
603 }
604 if (code == 1)
605 for (i = 0; i < rows; i++) {
606 stat[iStat].value2[i] = inputData[i];
607 stat[iStat].value1[i] = indepData;
608 }
609 else
610 for (i = 0; i < rows; i++) {
611 if (stat[iStat].value2[i] < inputData[i]) {
612 stat[iStat].value2[i] = inputData[i];
613 stat[iStat].value1[i] = indepData;
614 }
615 }
616 break;
617 case SET_SLOPE:
618 case SET_INTERCEPT:
620 fprintf(stderr, "error: unable to get value of parameter %s\n", stat[iStat].functionOf);
622 }
623
624
625
626
627
628
629 if (code == 1)
630 for (i = 0; i < rows; i++) {
631 stat[iStat].value1[i] = indepData;
632 stat[iStat].value2[i] = indepData * indepData;
633 stat[iStat].value3[i] = inputData[i];
634 stat[iStat].value4[i] = indepData * inputData[i];
635 }
636 else
637 for (i = 0; i < rows; i++) {
638 stat[iStat].value1[i] += indepData;
639 stat[iStat].value2[i] += indepData * indepData;
640 stat[iStat].value3[i] += inputData[i];
641 stat[iStat].value4[i] += indepData * inputData[i];
642 }
643 break;
644 case SET_MEDIAN:
645 case SET_DRANGE:
646 case SET_PERCENTILE:
647 case SET_EXMM_MEAN:
648 if (code == 1)
649 for (i = 0; i < rows; i++) {
650 stat[iStat].array[i] =
tmalloc(
sizeof(*stat[iStat].array[i]));
651 stat[iStat].array[i][pages - 1] = inputData[i];
652 }
653 else {
654 for (i = 0; i < rows; i++) {
655 stat[iStat].array[i] =
SDDS_Realloc(stat[iStat].array[i],
sizeof(*stat[iStat].array[i]) * pages);
656 stat[iStat].array[i][pages - 1] = inputData[i];
657 }
658 }
659 break;
660 default:
661 SDDS_Bomb(
"invalid statistic code (accumulation loop)");
662 break;
663 }
664 free(inputData);
665 }
666 }
667 if (pages == 0)
669 for (iStat = 0; iStat < stats; iStat++) {
670 switch (stat[iStat].optionCode) {
671 case SET_COPY:
672 case SET_MINIMA:
673 case SET_MAXIMA:
674 case SET_PMINIMA:
675 case SET_PMAXIMA:
676 case SET_CMINIMA:
677 case SET_CMAXIMA:
678 case SET_LARGEST:
679 case SET_SIGNEDLARGEST:
680 case SET_SUMS:
681 break;
682 case SET_MEANS:
683 for (i = 0; i < rows; i++)
684 stat[iStat].value1[i] /= pages;
685 break;
686 case SET_WMEANS:
687 for (i = 0; i < rows; i++)
688 if (stat[iStat].sumWeight[i])
689 stat[iStat].value1[i] /= stat[iStat].sumWeight[i];
690 else {
691 if (!nowarnings)
692 fprintf(stderr, "warning: the total weight for the %" PRId64 "th row of %s is zero.\n", i + 1, stat[iStat].sourceColumn);
693 stat[iStat].value1[i] = DBL_MAX;
694 }
695 break;
696 case SET_SDS:
697 if (pages < 2)
698 stat[iStat].value1[i] = DBL_MAX;
699 else
700 for (i = 0; i < rows; i++) {
701 double tmp1;
702 if ((tmp1 = stat[iStat].value2[i] / pages - sqr(stat[iStat].value1[i] / pages)) <= 0)
703 stat[iStat].value1[i] = 0;
704 else
705 stat[iStat].value1[i] = sqrt(tmp1 * pages / (pages - 1.0));
706 }
707 break;
708 case SET_WSDS:
709 if (pages < 2)
710 stat[iStat].value1[i] = DBL_MAX;
711 else
712 for (i = 0; i < rows; i++) {
713 double tmp1;
714 if (stat[iStat].sumWeight[i]) {
715 if ((tmp1 = stat[iStat].value2[i] / stat[iStat].sumWeight[i] - sqr(stat[iStat].value1[i] / stat[iStat].sumWeight[i])) <= 0)
716 stat[iStat].value1[i] = 0;
717 else
718 stat[iStat].value1[i] = sqrt(tmp1 * pages / (pages - 1.0));
719 } else {
720 if (!nowarnings)
721 fprintf(stderr, "Warning, the total weight for the %" PRId64 "th row of %s is zero.\n", i + 1, stat[iStat].sourceColumn);
722 stat[iStat].value1[i] = DBL_MAX;
723 }
724 }
725 break;
726 case SET_SIGMAS:
727 if (pages < 2)
728 stat[iStat].value1[i] = DBL_MAX;
729 else
730 for (i = 0; i < rows; i++) {
731 double tmp1;
732 if ((tmp1 = stat[iStat].value2[i] / pages - sqr(stat[iStat].value1[i] / pages)) <= 0)
733 stat[iStat].value1[i] = 0;
734 else
735 stat[iStat].value1[i] = sqrt(tmp1 / (pages - 1.0));
736 }
737 break;
738 case SET_WSIGMAS:
739 if (pages < 2)
740 stat[iStat].value1[i] = DBL_MAX;
741 else
742 for (i = 0; i < rows; i++) {
743 double tmp1;
744 if (stat[iStat].sumWeight[i]) {
745 if ((tmp1 = stat[iStat].value2[i] / stat[iStat].sumWeight[i] - sqr(stat[iStat].value1[i] / stat[iStat].sumWeight[i])) <= 0)
746 stat[iStat].value1[i] = 0;
747 else
748 stat[iStat].value1[i] = sqrt(tmp1 / (pages - 1.0));
749 } else {
750 if (!nowarnings)
751 fprintf(stderr, "Warning, the total weight for the %" PRId64 "th row of %s is zero.\n", i + 1, stat[iStat].sourceColumn);
752 stat[iStat].value1[i] = DBL_MAX;
753 }
754 }
755 break;
756 case SET_RMSS:
757 for (i = 0; i < rows; i++)
758 stat[iStat].value1[i] = sqrt(stat[iStat].value1[i] / pages);
759 break;
760 case SET_WRMSS:
761 for (i = 0; i < rows; i++) {
762 if (stat[iStat].sumWeight[i])
763 stat[iStat].value1[i] = sqrt(stat[iStat].value1[i] / stat[iStat].sumWeight[i]);
764 else {
765 if (!nowarnings)
766 fprintf(stderr, "Warning, the total weight for the %" PRId64 "th row of %s is zero.\n", i + 1, stat[iStat].sourceColumn);
767 stat[iStat].value1[i] = DBL_MAX;
768 }
769 }
770 break;
771 case SET_SLOPE:
772 for (i = 0; i < rows; i++) {
773 double D;
774 D = pages * stat[iStat].value2[i] - stat[iStat].value1[i] * stat[iStat].value1[i];
775 stat[iStat].value1[i] = (pages * stat[iStat].value4[i] - stat[iStat].value1[i] * stat[iStat].value3[i]) / D;
776 }
777 break;
778 case SET_INTERCEPT:
779 for (i = 0; i < rows; i++) {
780 double D;
781 D = pages * stat[iStat].value2[i] - stat[iStat].value1[i] * stat[iStat].value1[i];
782 stat[iStat].value1[i] = (stat[iStat].value2[i] * stat[iStat].value3[i] - stat[iStat].value1[i] * stat[iStat].value4[i]) / D;
783 }
784 break;
785 case SET_MEDIAN:
786 for (i = 0; i < rows; i++) {
787 compute_median(&stat[iStat].value1[i], stat[iStat].array[i], pages);
788 }
789 break;
790 case SET_DRANGE:
791 for (i = 0; i < rows; i++) {
793 stat[iStat].value1[i] = 0;
794 else
795 stat[iStat].value1[i] = decileResult[1] - decileResult[0];
796 }
797 break;
798 case SET_PERCENTILE:
799 percentilePoint = stat[iStat].percentile;
800 for (i = 0; i < rows; i++) {
801 if (!
compute_percentiles(&percentileResult, &percentilePoint, 1, stat[iStat].array[i], pages))
802 stat[iStat].value1[i] = 0;
803 else
804 stat[iStat].value1[i] = percentileResult;
805 }
806 break;
807 case SET_EXMM_MEAN:
808 for (i = 0; i < rows; i++)
809 if (!compute_mean_exclude_min_max(&(stat[iStat].value1[i]), stat[iStat].array[i], pages))
810 stat[iStat].value1[i] = 0;
811 break;
812 default:
813 SDDS_Bomb(
"invalid statistic code (final loop)");
814 break;
815 }
816 if (stat[iStat].optionCode == SET_COPY) {
817 if (!
SDDS_SetColumn(&outTable, SDDS_SET_BY_NAME, stat[iStat].copy, rows, stat[iStat].resultColumn)) {
818 fprintf(stderr, "error setting column values for column %s\n", stat[iStat].resultColumn);
820 }
821 }
else if (!
SDDS_SetColumnFromDoubles(&outTable, SDDS_SET_BY_NAME, stat[iStat].value1, rows, stat[iStat].resultColumn)) {
822 fprintf(stderr, "error setting column values for column %s\n", stat[iStat].resultColumn);
824 }
825 if (stat[iStat].value1)
826 free(stat[iStat].value1);
827 if (stat[iStat].value2)
828 free(stat[iStat].value2);
829 if (stat[iStat].value3)
830 free(stat[iStat].value3);
831 if (stat[iStat].value4)
832 free(stat[iStat].value4);
833 if (stat[iStat].copy)
834 free(stat[iStat].copy);
835 if (stat[iStat].array) {
836 for (i = 0; i < rows; i++) {
837 free(stat[iStat].array[i]);
838 }
839 free(stat[iStat].array);
840 }
841 if (stat[iStat].sumWeight)
842 free(stat[iStat].sumWeight);
843 free(stat[iStat].sourceColumn);
844 free(stat[iStat].resultColumn);
845 stat[iStat].value1 = stat[iStat].value2 = stat[iStat].value3 = stat[iStat].value4 = NULL;
846 stat[iStat].copy = NULL;
847 stat[iStat].array = NULL;
848 }
849 free(stat);
852 return EXIT_SUCCESS;
853}
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_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_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
int32_t SDDS_NumberOfErrors()
Retrieves the number of errors recorded by SDDS library routines.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
double ipow(const double x, const int64_t p)
Compute x raised to the power p (x^p).
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.