[gnumeric] Mathfunc: start extracting non-R code for d/p/q functions.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Mathfunc: start extracting non-R code for d/p/q functions.
- Date: Tue, 31 Dec 2013 22:47:38 +0000 (UTC)
commit 07bf7d7bf960f568a526003bb740d796b8c5f0a1
Author: Morten Welinder <terra gnome org>
Date: Tue Dec 31 17:46:51 2013 -0500
Mathfunc: start extracting non-R code for d/p/q functions.
ChangeLog | 5 +
plugins/fn-r/extra.c | 21 +---
src/Makefile.am | 2 +
src/mathfunc.c | 278 +-----------------------------------------------
src/mathfunc.h | 15 ---
src/sf-dpq.c | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/sf-dpq.h | 22 ++++
7 files changed, 326 insertions(+), 308 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 5309379..6e8bb8d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-31 Morten Welinder <terra gnome org>
+
+ * src/sf-dpq.c (pfuncinverter, discpfuncinverter): Extract from
+ mathfunc.c
+
2013-12-30 Morten Welinder <terra gnome org>
* src/mathfunc.c (dnorm): Improve accuracy for x>5 (normalized).
diff --git a/plugins/fn-r/extra.c b/plugins/fn-r/extra.c
index 62eff8b..03c64cc 100644
--- a/plugins/fn-r/extra.c
+++ b/plugins/fn-r/extra.c
@@ -1,24 +1,11 @@
#include <gnumeric-config.h>
#include "gnumeric.h"
#include <mathfunc.h>
+#include <sf-dpq.h>
#include <sf-trig.h>
#include <sf-gamma.h>
#include "extra.h"
-#define ML_ERR_return_NAN { return gnm_nan; }
-
-/* ------------------------------------------------------------------------- */
-/* --- BEGIN MAGIC R SOURCE MARKER --- */
-
-#define R_Q_P01_check(p) \
- if ((log_p && p > 0) || \
- (!log_p && (p < 0 || p > 1)) ) \
- ML_ERR_return_NAN
-
-
-/* ------------------------------------------------------------------------ */
-/* --- END MAGIC R SOURCE MARKER --- */
-
gnm_float
qcauchy (gnm_float p, gnm_float location, gnm_float scale,
gboolean lower_tail, gboolean log_p)
@@ -26,8 +13,10 @@ qcauchy (gnm_float p, gnm_float location, gnm_float scale,
if (gnm_isnan(p) || gnm_isnan(location) || gnm_isnan(scale))
return p + location + scale;
- R_Q_P01_check(p);
- if (scale < 0 || !gnm_finite(scale)) ML_ERR_return_NAN;
+ if (log_p ? (p > 0) : (p < 0 || p > 1))
+ return gnm_nan;
+
+ if (scale < 0 || !gnm_finite(scale)) return gnm_nan;
if (log_p) {
if (p > -1)
diff --git a/src/Makefile.am b/src/Makefile.am
index 215be42..027db57 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -154,6 +154,7 @@ libspreadsheet_la_SOURCES = \
selection.c \
session.c \
sf-bessel.c \
+ sf-dpq.c \
sf-gamma.c \
sf-trig.c \
sheet.c \
@@ -283,6 +284,7 @@ libspreadsheet_include_HEADERS = \
selection.h \
session.h \
sf-bessel.h \
+ sf-dpq.h \
sf-gamma.h \
sf-trig.h \
sheet.h \
diff --git a/src/mathfunc.c b/src/mathfunc.c
index ade4892..4235a10 100644
--- a/src/mathfunc.c
+++ b/src/mathfunc.c
@@ -36,7 +36,7 @@
#include <gnumeric-config.h>
#include "gnumeric.h"
#include "mathfunc.h"
-#include "sf-trig.h"
+#include "sf-dpq.h"
#include "sf-gamma.h"
#include <glib/gi18n-lib.h>
@@ -4728,282 +4728,6 @@ pf (gnm_float x, gnm_float n1, gnm_float n2, gboolean lower_tail, gboolean log_p
/* ------------------------------------------------------------------------ */
-#undef DEBUG_pfuncinverter
-
-/**
- * pfuncinverter:
- * @p:
- * @shape:
- * @lower_tail:
- * @log_p:
- * @xlow:
- * @xhigh:
- * @x0:
- * @pfunc: (scope call):
- * @dpfunc_dx: (scope call):
- *
- * Returns:
- **/
-gnm_float
-pfuncinverter (gnm_float p, const gnm_float shape[],
- gboolean lower_tail, gboolean log_p,
- gnm_float xlow, gnm_float xhigh, gnm_float x0,
- GnmPFunc pfunc, GnmDPFunc dpfunc_dx)
-{
- gboolean have_xlow = gnm_finite (xlow);
- gboolean have_xhigh = gnm_finite (xhigh);
- gnm_float exlow, exhigh;
- gnm_float x = 0, e = 0, px;
- int i;
-
- g_return_val_if_fail (pfunc != NULL, gnm_nan);
-
- R_Q_P01_check (p);
- if (p == R_DT_0) return xlow;
- if (p == R_DT_1) return xhigh;
-
- exlow = R_DT_0 - p;
- exhigh = R_DT_1 - p;
- if (!lower_tail) {
- exlow = -exlow;
- exhigh = -exhigh;
- }
-
-#ifdef DEBUG_pfuncinverter
- g_printerr ("p=%.15g\n", p);
-#endif
-
- for (i = 0; i < 100; i++) {
- if (i == 0) {
- if (x0 > xlow && x0 < xhigh)
- /* Use supplied guess. */
- x = x0;
- else if (have_xlow && x0 <= xlow)
- x = xlow + have_xhigh ? (xhigh - xlow) / 100 : 1;
- else if (have_xhigh && x0 >= xhigh)
- x = xhigh - have_xlow ? (xhigh - xlow) / 100 : 1;
- else
- x = 0; /* Whatever */
- } else if (i == 1) {
- /*
- * Under the assumption that the initial guess was
- * good, pick a nearby point that is hopefully on
- * the other side. If we already have both sides,
- * just bisect.
- */
- if (have_xlow && have_xhigh)
- x = (xlow + xhigh) / 2;
- else if (have_xlow)
- x = xlow * 1.1;
- else
- x = xhigh / 1.1;
- } else if (have_xlow && have_xhigh) {
- switch (i % 8) {
- case 0:
- x = xhigh - (xhigh - xlow) *
- (exhigh / (exhigh - exlow));
- break;
- case 4:
- /* Half-way in log-space. */
- if (xlow >= 0 && xhigh >= 0)
- x = gnm_sqrt (MAX (GNM_MIN, xlow)) * gnm_sqrt (xhigh);
- else if (xlow <= 0 && xhigh <= 0)
- x = -gnm_sqrt (-xlow) * gnm_sqrt (MAX (GNM_MIN, -xhigh));
- else
- x = 0;
- break;
- case 2:
- x = (xhigh + 1000 * xlow) / 1001;
- break;
- case 6:
- x = (1000 * xhigh + xlow) / 1001;
- break;
- default:
- x = (xhigh + xlow) / 2;
- }
- } else if (have_xlow) {
- /* Agressively seek right in search of xhigh. */
- x = (xlow < 1) ? 1 : (2 * i) * xlow;
- } else {
- /* Agressively seek left in search of xlow. */
- x = (xhigh > -1) ? -1 : (2 * i) * xhigh;
- }
-
- newton_retry:
- if ((have_xlow && x <= xlow) || (have_xhigh && x >= xhigh))
- continue;
-
- px = pfunc (x, shape, lower_tail, log_p);
- e = px - p;
- if (!lower_tail) e = -e;
-
-#ifdef DEBUG_pfuncinverter
- g_printerr ("%3d: x=%.15g e=%.15g l=%.15g h=%.15g\n",
- i, x, e, xlow, xhigh);
-#endif
-
- if (e == 0)
- goto done;
- else if (e > 0) {
- xhigh = x;
- exhigh = e;
- have_xhigh = TRUE;
- } else if (e < 0) {
- xlow = x;
- exlow = e;
- have_xlow = TRUE;
- } else {
- /* We got a NaN. */
- }
-
- if (have_xlow && have_xhigh) {
- gnm_float prec = (xhigh - xlow) /
- (gnm_abs (xlow) + gnm_abs (xhigh));
- if (prec < GNM_EPSILON * 4) {
- x = (xhigh + xlow) / 2;
- e = pfunc (x, shape, lower_tail, log_p) - p;
- if (!lower_tail) e = -e;
- goto done;
- }
-
- if (dpfunc_dx && i % 3 < 2 && (i == 0 || prec < 0.05)) {
- gnm_float d = dpfunc_dx (x, shape, log_p);
- if (log_p) d = gnm_exp (d - px);
-#ifdef DEBUG_pfuncinverter
- g_printerr ("Newton: d=%-.14g\n", d);
-#endif
- if (d) {
- /*
- * Deliberately overshoot a bit to help
- * with getting good points on both
- * sides of the root.
- */
- x = x - e / d * 1.000001;
- if (x > xlow && x < xhigh) {
-#ifdef DEBUG_pfuncinverter
- g_printerr ("Newton ok\n");
-#endif
- i++;
- goto newton_retry;
- }
- } else {
-#ifdef DEBUG_pfuncinverter
- g_printerr ("Newton d=0\n");
-#endif
- }
- }
- }
- }
-
- ML_ERROR(ME_PRECISION);
- done:
- /* Make sure to keep a lucky near-hit. */
-
- if (have_xhigh && gnm_abs (e) > exhigh)
- e = exhigh, x = xhigh;
- if (have_xlow && gnm_abs (e) > -exlow)
- e = exlow, x = xlow;
-
-#ifdef DEBUG_pfuncinverter
- g_printerr ("--> %.15g\n\n", x);
-#endif
- return x;
-}
-
-/**
- * discpfuncinverter:
- * @p:
- * @shape:
- * @lower_tail:
- * @log_p:
- * @xlow:
- * @xhigh:
- * @x0:
- * @pfunc: (scope call):
- *
- * Discrete pfuncs only. (Specifically: only integer x are allowed).
- * Returns:
- */
-gnm_float
-discpfuncinverter (gnm_float p, const gnm_float shape[],
- gboolean lower_tail, gboolean log_p,
- gnm_float xlow, gnm_float xhigh, gnm_float x0,
- GnmPFunc pfunc)
-{
- gboolean have_xlow = gnm_finite (xlow);
- gboolean have_xhigh = gnm_finite (xhigh);
- gnm_float step;
- int i;
-
- R_Q_P01_check (p);
- if (p == R_DT_0) return xlow;
- if (p == R_DT_1) return xhigh;
-
- if (gnm_finite (x0) && x0 >= xlow && x0 <= xhigh)
- ; /* Nothing -- guess is good. */
- else if (have_xlow && have_xhigh)
- x0 = (xlow + xhigh) / 2;
- else if (have_xhigh)
- x0 = xhigh;
- else if (have_xlow)
- x0 = xlow;
- else
- x0 = 0;
- x0 = gnm_floor (x0 + 0.5);
- step = 1 + gnm_floor (gnm_abs (x0) * GNM_EPSILON);
-
-#if 0
- g_printerr ("step=%.20g\n", step);
-#endif
-
- for (i = 1; 1; i++) {
- gnm_float ex0 = pfunc (x0, shape, lower_tail, log_p) - p;
-#if 0
- g_printerr ("x=%.20g e=%.20g\n", x0, ex0);
-#endif
- if (!lower_tail) ex0 = -ex0;
- if (ex0 <= 0)
- xlow = x0, have_xlow = TRUE;
- if (ex0 >= 0)
- xhigh = x0, have_xhigh = TRUE, step = -gnm_abs (step);
-
- if (i > 1 && have_xlow && have_xhigh) {
- gnm_float xmid = gnm_floor ((xlow + xhigh) / 2);
- if (xmid - xlow < 0.5 ||
- xmid - xlow < gnm_abs (xlow) * GNM_EPSILON)
- return xhigh;
- x0 = xmid;
- } else {
- gnm_float x1 = x0 + step;
-
- if (x1 == x0) {
- /* Probably infinite. */
- return gnm_nan;
- } else if (x1 >= xlow && x1 <= xhigh) {
- x0 = x1;
- step *= 2 * i;
- } else {
- /* We went off the edge by walking too fast. */
- gnm_float newstep = 1 + gnm_floor (gnm_abs (x0) * GNM_EPSILON);
- step = (step > 0) ? newstep : -newstep;
- x1 = x0 + step;
- if (x1 >= xlow && x1 <= xhigh)
- continue;
- /*
- * We don't seem to find a finite x on the
- * other side of the root.
- */
- return (step > 0) ? xhigh : xlow;
- }
- }
- }
-
- g_assert_not_reached ();
-}
-
-
-/* ------------------------------------------------------------------------ */
-
static gnm_float
ppois1 (gnm_float x, const gnm_float *plambda,
gboolean lower_tail, gboolean log_p)
diff --git a/src/mathfunc.h b/src/mathfunc.h
index f43825e..fb52594 100644
--- a/src/mathfunc.h
+++ b/src/mathfunc.h
@@ -128,21 +128,6 @@ gnm_float qtukey(gnm_float p, gnm_float nmeans, gnm_float df, gnm_float nranges,
/* ------------------------------------------------------------------------- */
-typedef gnm_float (*GnmPFunc) (gnm_float x, const gnm_float shape[],
- gboolean lower_tail, gboolean log_p);
-typedef gnm_float (*GnmDPFunc) (gnm_float x, const gnm_float shape[],
- gboolean log_p);
-
-gnm_float pfuncinverter (gnm_float p, const gnm_float shape[],
- gboolean lower_tail, gboolean log_p,
- gnm_float xlow, gnm_float xhigh, gnm_float x0,
- GnmPFunc pfunc, GnmDPFunc dpfunc_dx);
-gnm_float discpfuncinverter (gnm_float p, const gnm_float shape[],
- gboolean lower_tail, gboolean log_p,
- gnm_float xlow, gnm_float xhigh, gnm_float x0,
- GnmPFunc pfunc);
-
-/* ------------------------------------------------------------------------- */
/* Matrix functions. */
typedef struct {
diff --git a/src/sf-dpq.c b/src/sf-dpq.c
new file mode 100644
index 0000000..b0709d3
--- /dev/null
+++ b/src/sf-dpq.c
@@ -0,0 +1,291 @@
+#include <gnumeric-config.h>
+#include <sf-dpq.h>
+
+#define R_D__0 (log_p ? gnm_ninf : 0.0)
+#define R_D__1 (log_p ? 0.0 : 1.0)
+#define R_DT_0 (lower_tail ? R_D__0 : R_D__1)
+#define R_DT_1 (lower_tail ? R_D__1 : R_D__0)
+
+/* ------------------------------------------------------------------------- */
+
+#undef DEBUG_pfuncinverter
+
+/**
+ * pfuncinverter:
+ * @p:
+ * @shape:
+ * @lower_tail:
+ * @log_p:
+ * @xlow:
+ * @xhigh:
+ * @x0:
+ * @pfunc: (scope call):
+ * @dpfunc_dx: (scope call):
+ *
+ * Returns:
+ **/
+gnm_float
+pfuncinverter (gnm_float p, const gnm_float shape[],
+ gboolean lower_tail, gboolean log_p,
+ gnm_float xlow, gnm_float xhigh, gnm_float x0,
+ GnmPFunc pfunc, GnmDPFunc dpfunc_dx)
+{
+ gboolean have_xlow = gnm_finite (xlow);
+ gboolean have_xhigh = gnm_finite (xhigh);
+ gnm_float exlow, exhigh;
+ gnm_float x = 0, e = 0, px;
+ int i;
+
+ g_return_val_if_fail (pfunc != NULL, gnm_nan);
+
+ if (log_p ? (p > 0) : (p < 0 || p > 1))
+ return gnm_nan;
+
+ if (p == R_DT_0) return xlow;
+ if (p == R_DT_1) return xhigh;
+
+ exlow = R_DT_0 - p;
+ exhigh = R_DT_1 - p;
+ if (!lower_tail) {
+ exlow = -exlow;
+ exhigh = -exhigh;
+ }
+
+#ifdef DEBUG_pfuncinverter
+ g_printerr ("p=%.15g\n", p);
+#endif
+
+ for (i = 0; i < 100; i++) {
+ if (i == 0) {
+ if (x0 > xlow && x0 < xhigh)
+ /* Use supplied guess. */
+ x = x0;
+ else if (have_xlow && x0 <= xlow)
+ x = xlow + have_xhigh ? (xhigh - xlow) / 100 : 1;
+ else if (have_xhigh && x0 >= xhigh)
+ x = xhigh - have_xlow ? (xhigh - xlow) / 100 : 1;
+ else
+ x = 0; /* Whatever */
+ } else if (i == 1) {
+ /*
+ * Under the assumption that the initial guess was
+ * good, pick a nearby point that is hopefully on
+ * the other side. If we already have both sides,
+ * just bisect.
+ */
+ if (have_xlow && have_xhigh)
+ x = (xlow + xhigh) / 2;
+ else if (have_xlow)
+ x = xlow * 1.1;
+ else
+ x = xhigh / 1.1;
+ } else if (have_xlow && have_xhigh) {
+ switch (i % 8) {
+ case 0:
+ x = xhigh - (xhigh - xlow) *
+ (exhigh / (exhigh - exlow));
+ break;
+ case 4:
+ /* Half-way in log-space. */
+ if (xlow >= 0 && xhigh >= 0)
+ x = gnm_sqrt (MAX (GNM_MIN, xlow)) * gnm_sqrt (xhigh);
+ else if (xlow <= 0 && xhigh <= 0)
+ x = -gnm_sqrt (-xlow) * gnm_sqrt (MAX (GNM_MIN, -xhigh));
+ else
+ x = 0;
+ break;
+ case 2:
+ x = (xhigh + 1000 * xlow) / 1001;
+ break;
+ case 6:
+ x = (1000 * xhigh + xlow) / 1001;
+ break;
+ default:
+ x = (xhigh + xlow) / 2;
+ }
+ } else if (have_xlow) {
+ /* Agressively seek right in search of xhigh. */
+ x = (xlow < 1) ? 1 : (2 * i) * xlow;
+ } else {
+ /* Agressively seek left in search of xlow. */
+ x = (xhigh > -1) ? -1 : (2 * i) * xhigh;
+ }
+
+ newton_retry:
+ if ((have_xlow && x <= xlow) || (have_xhigh && x >= xhigh))
+ continue;
+
+ px = pfunc (x, shape, lower_tail, log_p);
+ e = px - p;
+ if (!lower_tail) e = -e;
+
+#ifdef DEBUG_pfuncinverter
+ g_printerr ("%3d: x=%.15g e=%.15g l=%.15g h=%.15g\n",
+ i, x, e, xlow, xhigh);
+#endif
+
+ if (e == 0)
+ goto done;
+ else if (e > 0) {
+ xhigh = x;
+ exhigh = e;
+ have_xhigh = TRUE;
+ } else if (e < 0) {
+ xlow = x;
+ exlow = e;
+ have_xlow = TRUE;
+ } else {
+ /* We got a NaN. */
+ }
+
+ if (have_xlow && have_xhigh) {
+ gnm_float prec = (xhigh - xlow) /
+ (gnm_abs (xlow) + gnm_abs (xhigh));
+ if (prec < GNM_EPSILON * 4) {
+ x = (xhigh + xlow) / 2;
+ e = pfunc (x, shape, lower_tail, log_p) - p;
+ if (!lower_tail) e = -e;
+ goto done;
+ }
+
+ if (dpfunc_dx && i % 3 < 2 && (i == 0 || prec < 0.05)) {
+ gnm_float d = dpfunc_dx (x, shape, log_p);
+ if (log_p) d = gnm_exp (d - px);
+#ifdef DEBUG_pfuncinverter
+ g_printerr ("Newton: d=%-.14g\n", d);
+#endif
+ if (d) {
+ /*
+ * Deliberately overshoot a bit to help
+ * with getting good points on both
+ * sides of the root.
+ */
+ x = x - e / d * 1.000001;
+ if (x > xlow && x < xhigh) {
+#ifdef DEBUG_pfuncinverter
+ g_printerr ("Newton ok\n");
+#endif
+ i++;
+ goto newton_retry;
+ }
+ } else {
+#ifdef DEBUG_pfuncinverter
+ g_printerr ("Newton d=0\n");
+#endif
+ }
+ }
+ }
+ }
+
+#ifdef DEBUG_pfuncinverter
+ g_printerr ("Failed to converge\n");
+#endif
+
+ done:
+ /* Make sure to keep a lucky near-hit. */
+
+ if (have_xhigh && gnm_abs (e) > exhigh)
+ e = exhigh, x = xhigh;
+ if (have_xlow && gnm_abs (e) > -exlow)
+ e = exlow, x = xlow;
+
+#ifdef DEBUG_pfuncinverter
+ g_printerr ("--> %.15g\n\n", x);
+#endif
+ return x;
+}
+
+/**
+ * discpfuncinverter:
+ * @p:
+ * @shape:
+ * @lower_tail:
+ * @log_p:
+ * @xlow:
+ * @xhigh:
+ * @x0:
+ * @pfunc: (scope call):
+ *
+ * Discrete pfuncs only. (Specifically: only integer x are allowed).
+ * Returns:
+ */
+gnm_float
+discpfuncinverter (gnm_float p, const gnm_float shape[],
+ gboolean lower_tail, gboolean log_p,
+ gnm_float xlow, gnm_float xhigh, gnm_float x0,
+ GnmPFunc pfunc)
+{
+ gboolean have_xlow = gnm_finite (xlow);
+ gboolean have_xhigh = gnm_finite (xhigh);
+ gnm_float step;
+ int i;
+
+ if (log_p ? (p > 0) : (p < 0 || p > 1))
+ return gnm_nan;
+
+ if (p == R_DT_0) return xlow;
+ if (p == R_DT_1) return xhigh;
+
+ if (gnm_finite (x0) && x0 >= xlow && x0 <= xhigh)
+ ; /* Nothing -- guess is good. */
+ else if (have_xlow && have_xhigh)
+ x0 = (xlow + xhigh) / 2;
+ else if (have_xhigh)
+ x0 = xhigh;
+ else if (have_xlow)
+ x0 = xlow;
+ else
+ x0 = 0;
+ x0 = gnm_floor (x0 + 0.5);
+ step = 1 + gnm_floor (gnm_abs (x0) * GNM_EPSILON);
+
+#if 0
+ g_printerr ("step=%.20g\n", step);
+#endif
+
+ for (i = 1; 1; i++) {
+ gnm_float ex0 = pfunc (x0, shape, lower_tail, log_p) - p;
+#if 0
+ g_printerr ("x=%.20g e=%.20g\n", x0, ex0);
+#endif
+ if (!lower_tail) ex0 = -ex0;
+ if (ex0 <= 0)
+ xlow = x0, have_xlow = TRUE;
+ if (ex0 >= 0)
+ xhigh = x0, have_xhigh = TRUE, step = -gnm_abs (step);
+
+ if (i > 1 && have_xlow && have_xhigh) {
+ gnm_float xmid = gnm_floor ((xlow + xhigh) / 2);
+ if (xmid - xlow < 0.5 ||
+ xmid - xlow < gnm_abs (xlow) * GNM_EPSILON)
+ return xhigh;
+ x0 = xmid;
+ } else {
+ gnm_float x1 = x0 + step;
+
+ if (x1 == x0) {
+ /* Probably infinite. */
+ return gnm_nan;
+ } else if (x1 >= xlow && x1 <= xhigh) {
+ x0 = x1;
+ step *= 2 * i;
+ } else {
+ /* We went off the edge by walking too fast. */
+ gnm_float newstep = 1 + gnm_floor (gnm_abs (x0) * GNM_EPSILON);
+ step = (step > 0) ? newstep : -newstep;
+ x1 = x0 + step;
+ if (x1 >= xlow && x1 <= xhigh)
+ continue;
+ /*
+ * We don't seem to find a finite x on the
+ * other side of the root.
+ */
+ return (step > 0) ? xhigh : xlow;
+ }
+ }
+ }
+
+ g_assert_not_reached ();
+}
+
+/* ------------------------------------------------------------------------ */
diff --git a/src/sf-dpq.h b/src/sf-dpq.h
new file mode 100644
index 0000000..ce23223
--- /dev/null
+++ b/src/sf-dpq.h
@@ -0,0 +1,22 @@
+#ifndef GNM_SF_DPQ_H_
+#define GNM_SF_DPQ_H_
+
+#include <numbers.h>
+
+typedef gnm_float (*GnmPFunc) (gnm_float x, const gnm_float shape[],
+ gboolean lower_tail, gboolean log_p);
+typedef gnm_float (*GnmDPFunc) (gnm_float x, const gnm_float shape[],
+ gboolean log_p);
+
+gnm_float pfuncinverter (gnm_float p, const gnm_float shape[],
+ gboolean lower_tail, gboolean log_p,
+ gnm_float xlow, gnm_float xhigh, gnm_float x0,
+ GnmPFunc pfunc, GnmDPFunc dpfunc_dx);
+gnm_float discpfuncinverter (gnm_float p, const gnm_float shape[],
+ gboolean lower_tail, gboolean log_p,
+ gnm_float xlow, gnm_float xhigh, gnm_float x0,
+ GnmPFunc pfunc);
+
+/* ------------------------------------------------------------------------- */
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]