driver: New function output_log_nocopy().
[pspp] / src / language / expressions / helpers.c
index cfc46290b785cfad8c4d5dd8182c65fe016774cd..4a0a01b97b680907b0c1efe33f9bb1010e68891a 100644 (file)
@@ -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);
+}