[gnumeric] Add RANDSNORM and RANDSTDIST. [#144717]



commit 9aa04633550e4e5a5317245986a3a3e86795264d
Author: Andreas J. Guelzow <aguelzow pyrshep ca>
Date:   Sun Oct 11 11:13:50 2009 -0600

    Add RANDSNORM and RANDSTDIST. [#144717]
    
    2009-10-11  Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* plugin.xml.in: add randsnorm and randstdist
    	* functions.c (help_randtdist): use a more reasonable degrees
    	  of freedom
    	(help_randsnorm): new
    	(gnumeric_randsnorm): new
    	(help_randstdist): new
    	(gnumeric_randstdist): new
    	(random_functions): add randsnorm and randstdist
    
    2009-10-11  Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* src/mathfunc.c (random_skew_normal): new
    	(random_skew_tdist): new
    	* src/mathfunc.h (random_skew_normal): new
    	(random_skew_tdist): new

 ChangeLog                       |    7 ++++
 NEWS                            |    3 ++
 plugins/fn-random/ChangeLog     |   11 ++++++
 plugins/fn-random/functions.c   |   71 +++++++++++++++++++++++++++++++++++++-
 plugins/fn-random/plugin.xml.in |    2 +
 src/mathfunc.c                  |   48 ++++++++++++++++++++++++++
 src/mathfunc.h                  |    2 +
 7 files changed, 142 insertions(+), 2 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 2355748..45c0bb8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-10-11  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* src/mathfunc.c (random_skew_normal): new
+	(random_skew_tdist): new
+	* src/mathfunc.h (random_skew_normal): new
+	(random_skew_tdist): new
+
 2009-10-11  Morten Welinder <terra gnome org>
 
 	* configure.in: Post-release bump.
diff --git a/NEWS b/NEWS
index 26dbe63..89e6455 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
 Gnumeric 1.9.15
 
+Andreas:
+	* Add RANDSNORM and RANDSTDIST. [#144717]
+
 --------------------------------------------------------------------------
 Gnumeric 1.9.14
 
diff --git a/plugins/fn-random/ChangeLog b/plugins/fn-random/ChangeLog
index 32a2d28..8f0d16c 100644
--- a/plugins/fn-random/ChangeLog
+++ b/plugins/fn-random/ChangeLog
@@ -1,3 +1,14 @@
+2009-10-11  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* plugin.xml.in: add randsnorm and randstdist
+	* functions.c (help_randtdist): use a more reasonable degrees
+	  of freedom
+	(help_randsnorm): new
+	(gnumeric_randsnorm): new
+	(help_randstdist): new
+	(gnumeric_randstdist): new
+	(random_functions): add randsnorm and randstdist
+
 2009-10-11  Morten Welinder <terra gnome org>
 
 	* Release 1.9.14
diff --git a/plugins/fn-random/functions.c b/plugins/fn-random/functions.c
index 42b92ac..a21e29f 100644
--- a/plugins/fn-random/functions.c
+++ b/plugins/fn-random/functions.c
@@ -669,8 +669,8 @@ gnumeric_randchisq (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 static GnmFuncHelp const help_randtdist[] = {
         { GNM_FUNC_HELP_NAME, F_("RANDTDIST:random variate from a Student t distribution") },
         { GNM_FUNC_HELP_ARG, F_("df:degrees of freedom") },
-        { GNM_FUNC_HELP_EXAMPLES, "=RANDTDIST(0.5)" },
-        { GNM_FUNC_HELP_EXAMPLES, "=RANDTDIST(0.5)" },
+        { GNM_FUNC_HELP_EXAMPLES, "=RANDTDIST(5)" },
+        { GNM_FUNC_HELP_EXAMPLES, "=RANDTDIST(5)" },
         { GNM_FUNC_HELP_SEEALSO, "RAND" },
         { GNM_FUNC_HELP_END}
 };
@@ -878,6 +878,67 @@ gnumeric_simtable (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
 
 /***************************************************************************/
 
+static GnmFuncHelp const help_randsnorm[] = {
+        { GNM_FUNC_HELP_NAME, F_("RANDNORM:random variate from a skew normal distribution") },
+        { GNM_FUNC_HELP_ARG, F_("a: amount of skew, defaults to 0") },
+        { GNM_FUNC_HELP_ARG, F_("\xce\xbc:mean of the underlying normal distribution, defaults to 0") },
+        { GNM_FUNC_HELP_ARG, F_("\xcf\x83:standard deviation of the underlying normal distribution, defaults to 1") },
+	{ GNM_FUNC_HELP_NOTE, F_("If @{\xcf\x83} < 0, RANDSNORM returns #NUM!") },
+        { GNM_FUNC_HELP_EXAMPLES, "=RANDSNORM(-3,0,1)" },
+        { GNM_FUNC_HELP_EXAMPLES, "=RANDSNORM(-3,0,1)" },
+        { GNM_FUNC_HELP_SEEALSO, "RANDNORM" },
+        { GNM_FUNC_HELP_END}
+};
+
+static GnmValue *
+gnumeric_randsnorm (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
+{
+	gnm_float alpha  = 0.;
+	gnm_float mean  = 0.;
+	gnm_float stdev = 1.;
+	gnm_float result;
+	
+	if (argv[0]) {
+		alpha  = value_get_as_float (argv[0]);
+		if (argv[1]) {
+			mean  = value_get_as_float (argv[1]);
+			if (argv[2])
+				stdev = value_get_as_float (argv[2]);	
+		}
+	}
+
+       	if (stdev < 0)
+		return value_new_error_NUM (ei->pos);
+
+	result = ((alpha == 0.) ? random_normal () : random_skew_normal (alpha));
+
+        return value_new_float (stdev * result + mean);
+}
+
+/***************************************************************************/
+
+static GnmFuncHelp const help_randstdist[] = {
+        { GNM_FUNC_HELP_NAME, F_("RANDSTDIST:random variate from a skew t distribution") },
+        { GNM_FUNC_HELP_ARG, F_("df:degrees of freedom") },
+        { GNM_FUNC_HELP_ARG, F_("a: amount of skew, defaults to 0") },
+        { GNM_FUNC_HELP_EXAMPLES, "=RANDSTDIST(5,-2)" },
+        { GNM_FUNC_HELP_EXAMPLES, "=RANDSTDIST(5,2)" },
+        { GNM_FUNC_HELP_SEEALSO, "RANDTDIST" },
+        { GNM_FUNC_HELP_END}
+};
+
+static GnmValue *
+gnumeric_randstdist (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
+{
+	gnm_float nu = value_get_as_float (argv[0]);
+	gnm_float alpha = argv[1] ? value_get_as_float (argv[1]) : 0.;
+
+	return ((alpha == 0.) ? value_new_float (random_tdist (nu)) 
+		: value_new_float (random_skew_tdist (nu, alpha)));;
+}
+
+/***************************************************************************/
+
 GnmFuncDescriptor const random_functions[] = {
 	{ "rand",    "", help_rand,
 	  gnumeric_rand, NULL, NULL, NULL, NULL,
@@ -963,6 +1024,12 @@ GnmFuncDescriptor const random_functions[] = {
         { "randrayleightail", "ff",  help_randrayleightail,
 	  gnumeric_randrayleightail, NULL, NULL, NULL, NULL,
 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
+        { "randsnorm", "|fff",  help_randsnorm,
+	  gnumeric_randsnorm, NULL, NULL, NULL, NULL,
+	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
+        { "randstdist", "ff",  help_randstdist,
+	  gnumeric_randstdist, NULL, NULL, NULL, NULL,
+	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
         { "randtdist", "f",  help_randtdist,
 	  gnumeric_randtdist, NULL, NULL, NULL, NULL,
 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
diff --git a/plugins/fn-random/plugin.xml.in b/plugins/fn-random/plugin.xml.in
index 36cf18d..5c1508c 100644
--- a/plugins/fn-random/plugin.xml.in
+++ b/plugins/fn-random/plugin.xml.in
@@ -39,6 +39,8 @@
 				<function name="randpoisson"/>
 				<function name="randrayleigh"/>
 				<function name="randrayleightail"/>
+				<function name="randsnorm"/>
+				<function name="randstdist"/>
 				<function name="randtdist"/>
 				<function name="randuniform"/>
 				<function name="randweibull"/>
diff --git a/src/mathfunc.c b/src/mathfunc.c
index d1b0a07..42bf902 100644
--- a/src/mathfunc.c
+++ b/src/mathfunc.c
@@ -7617,6 +7617,54 @@ random_landau (void)
 
 /* ------------------------------------------------------------------------ */
 
+/*
+ * Generate a skew-normal distributed random number. 
+ * 
+ * based on the information provided at
+ * http://azzalini.stat.unipd.it/SN/faq.html
+ *
+ */
+
+gnm_float 
+random_skew_normal (gnm_float a)
+{
+	gnm_float result;
+	gnm_float asq = a * a;
+	gnm_float delta = gnm_sqrt (asq / (1 + asq));
+	gnm_float u = random_normal ();
+	gnm_float v = random_normal ();
+	
+	if (a < 0.)
+		delta *= -1.;
+	result = delta * u + gnm_sqrt (1-delta*delta) * v;
+	
+	return ((u < 0.) ? -result : result);
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+/*
+ * Generate a skew-t distributed random number. 
+ * 
+ * based on the information provided at
+ * http://azzalini.stat.unipd.it/SN/faq.html
+ *
+ */
+
+gnm_float 
+random_skew_tdist (gnm_float nu, gnm_float a)
+{
+	gnm_float chi = random_chisq (nu);
+	gnm_float z = random_skew_normal (a);;
+
+	return (z / gnm_sqrt(chi/nu));
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+
 
 gnm_float
 combin (gnm_float n, gnm_float k)
diff --git a/src/mathfunc.h b/src/mathfunc.h
index 5179221..38796be 100644
--- a/src/mathfunc.h
+++ b/src/mathfunc.h
@@ -155,6 +155,8 @@ gnm_float random_levy_skew      (gnm_float c, gnm_float alpha,
 gnm_float random_exppow         (gnm_float a, gnm_float b);
 gnm_float random_landau         (void);
 gnm_float random_gaussian_tail  (gnm_float a, gnm_float sigma);
+gnm_float random_skew_normal    (gnm_float a);
+gnm_float random_skew_tdist     (gnm_float nu, gnm_float a);
 
 /* The probability density functions. */
 gnm_float random_exppow_pdf     (gnm_float x, gnm_float a, gnm_float b);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]