X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fexpressions%2Fhelpers.c;h=4a0a01b97b680907b0c1efe33f9bb1010e68891a;hb=bb4f63c29bd0682115e5708332289423685b30a8;hp=cfc46290b785cfad8c4d5dd8182c65fe016774cd;hpb=32dc29d70ac55ad3629053097b83c74bb0068fc0;p=pspp diff --git a/src/language/expressions/helpers.c b/src/language/expressions/helpers.c index cfc46290b7..4a0a01b97b 100644 --- a/src/language/expressions/helpers.c +++ b/src/language/expressions/helpers.c @@ -45,7 +45,8 @@ expr_ymd_to_ofs (double year, double month, double day) return SYSMIS; } - ofs = calendar_gregorian_to_offset (y, m, d, &error); + ofs = calendar_gregorian_to_offset (y, m, d, settings_get_fmt_settings (), + &error); if (error != NULL) { msg (SE, "%s", error); @@ -363,7 +364,8 @@ add_months (double date, int months, enum date_sum_method method) if (method == SUM_CLOSEST && d > calendar_days_in_month (y, m)) d = calendar_days_in_month (y, m); - output = calendar_gregorian_to_offset (y, m, d, &error); + output = calendar_gregorian_to_offset (y, m, d, settings_get_fmt_settings (), + &error); if (output != SYSMIS) output = (output * DAY_S) + fmod (date, DAY_S); else @@ -664,20 +666,30 @@ npdf_beta (double x, double a, double b, double lambda) } } -double -round_nearest (double x, double mult, double fuzzbits) +static double +round__ (double x, double mult, double fuzzbits, double adjustment) { - double adjustment; - if (fuzzbits <= 0) fuzzbits = settings_get_fuzzbits (); - adjustment = .5 + exp2 (fuzzbits - DBL_MANT_DIG); + adjustment += exp2 (fuzzbits - DBL_MANT_DIG); x /= mult; x = x >= 0. ? floor (x + adjustment) : -floor (-x + adjustment); return x * mult; } +double +round_nearest (double x, double mult, double fuzzbits) +{ + return round__ (x, mult, fuzzbits, .5); +} + +double +round_zero (double x, double mult, double fuzzbits) +{ + return round__ (x, mult, fuzzbits, 0); +} + struct substring replace_string (struct expression *e, struct substring haystack, @@ -717,3 +729,32 @@ replace_string (struct expression *e, return result; } + +static int +compare_doubles (const void *a_, const void *b_) +{ + const double *ap = a_; + const double *bp = b_; + double a = *ap; + double b = *bp; + + /* Sort SYSMIS to the end. */ + return (a == b ? 0 + : a == SYSMIS ? 1 + : b == SYSMIS ? -1 + : a > b ? 1 : -1); +} + +double +median (double *a, size_t n) +{ + /* Sort the array in-place, sorting SYSMIS to the end. */ + qsort (a, n, sizeof *a, compare_doubles); + + /* Drop SYSMIS. */ + n = count_valid (a, n); + + return (!n ? SYSMIS + : n % 2 ? a[n / 2] + : (a[n / 2 - 1] + a[n / 2]) / 2.0); +}