[gnumeric] Regression: add and use new LEVERAGE function.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Regression: add and use new LEVERAGE function.
- Date: Fri, 18 Jan 2013 00:11:38 +0000 (UTC)
commit 5ed961f03579d3ea06992b7c1f87453555486f0a
Author: Morten Welinder <terra gnome org>
Date: Thu Jan 17 19:10:43 2013 -0500
Regression: add and use new LEVERAGE function.
This avoids using m-times-m matrices where m is the number of observations.
NEWS | 1 +
configure.ac | 2 +-
plugins/fn-math/ChangeLog | 4 +++
plugins/fn-math/functions.c | 58 +++++++++++++++++++++++++++++++++++++++++
plugins/fn-math/plugin.xml.in | 1 +
src/regression.h | 2 +
src/tools/ChangeLog | 5 +++
src/tools/analysis-tools.c | 38 ++++----------------------
8 files changed, 78 insertions(+), 33 deletions(-)
---
diff --git a/NEWS b/NEWS
index cd97c7a..dfdfdf7 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,7 @@ Morten:
* Add LINSOLVE function.
* Restrict size of MUNIT to avoid thrashing the system. [#625544]
* Fix text import crash.
+ * Add LEVERAGE function for regression tool. [#691913]
--------------------------------------------------------------------------
Gnumeric 1.12.0
diff --git a/configure.ac b/configure.ac
index 1a71f85..29408c9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -146,7 +146,7 @@ PKG_PROG_PKG_CONFIG(0.18)
dnl *****************************
libspreadsheet_reqs="
- libgoffice-${GOFFICE_API_VER} >= 0.10.0
+ libgoffice-${GOFFICE_API_VER} >= 0.10.1
libgsf-1 >= 1.14.24
libxml-2.0 >= 2.4.12
"
diff --git a/plugins/fn-math/ChangeLog b/plugins/fn-math/ChangeLog
index b90fdf6..5c3df7f 100644
--- a/plugins/fn-math/ChangeLog
+++ b/plugins/fn-math/ChangeLog
@@ -1,3 +1,7 @@
+2013-01-17 Morten Welinder <terra gnome org>
+
+ * functions.c (gnumeric_leverage): New function.
+
2013-01-14 Morten Welinder <terra gnome org>
* functions.c (gnumeric_munit): Restrict size to what would fit in
diff --git a/plugins/fn-math/functions.c b/plugins/fn-math/functions.c
index 2d0c24e..ad38ae1 100644
--- a/plugins/fn-math/functions.c
+++ b/plugins/fn-math/functions.c
@@ -2924,6 +2924,61 @@ gnumeric_mmult (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
/***************************************************************************/
+static GnmFuncHelp const help_leverage[] = {
+ { GNM_FUNC_HELP_NAME, F_("LEVERAGE:calculate leverate")},
+ { GNM_FUNC_HELP_ARG, F_("A:a matrix")},
+ { GNM_FUNC_HELP_DESCRIPTION,
+ F_("Returns the diagonal of @{A} (@{A}^T @{A})^-1 @{A}T as a column vector.") },
+ { GNM_FUNC_HELP_NOTE, F_("If the matrix is singular, #VALUE! is returned.") },
+ { GNM_FUNC_HELP_END}
+};
+
+
+static GnmValue *
+gnumeric_leverage (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
+{
+ GnmEvalPos const * const ep = ei->pos;
+ int rows, cols;
+ GORegressionResult regres;
+ gnm_float **A;
+ GnmStdError err;
+ GnmValue const *mat = argv[0];
+ gnm_float *x;
+ GnmValue *res;
+
+ if (validate_range_numeric_matrix (ep, mat, &rows, &cols, &err))
+ return value_new_error_std (ei->pos, err);
+
+ /* Guarantee shape and non-zero size */
+ if (!cols || !rows)
+ return value_new_error_VALUE (ei->pos);
+
+ A = value_to_matrix (mat, cols, rows, ep);
+ x = g_new (gnm_float, rows);
+ regres = gnm_linear_regression_leverage (A, x, rows, cols);
+ free_matrix (A, cols, rows);
+
+ if (regres != GO_REG_ok && regres != GO_REG_near_singular_good) {
+ res = value_new_error_VALUE (ei->pos);
+ } else {
+ int c, r;
+
+ res = value_new_array_non_init (1, rows);
+ for (c = 0; c < 1; c++) {
+ res->v_array.vals[c] = g_new (GnmValue *, rows);
+ for (r = 0; r < rows; r++)
+ res->v_array.vals[c][r] =
+ value_new_float (x[r]);
+ }
+ }
+
+ g_free (x);
+
+ return res;
+}
+
+/***************************************************************************/
+
static GnmFuncHelp const help_linsolve[] = {
{ GNM_FUNC_HELP_NAME, F_("LINSOLVE:solve linear equation")},
{ GNM_FUNC_HELP_ARG, F_("mat:a matrix")},
@@ -3560,6 +3615,9 @@ GnmFuncDescriptor const math_functions[] = {
{ "minverse","A", help_minverse,
gnumeric_minverse, NULL, NULL, NULL,
GNM_FUNC_RETURNS_NON_SCALAR, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
+ { "leverage", "A", help_leverage,
+ gnumeric_leverage, NULL, NULL, NULL,
+ GNM_FUNC_RETURNS_NON_SCALAR, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
{ "linsolve", "AA", help_linsolve,
gnumeric_linsolve, NULL, NULL, NULL,
GNM_FUNC_RETURNS_NON_SCALAR, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
diff --git a/plugins/fn-math/plugin.xml.in b/plugins/fn-math/plugin.xml.in
index 457df3e..e266b6d 100644
--- a/plugins/fn-math/plugin.xml.in
+++ b/plugins/fn-math/plugin.xml.in
@@ -54,6 +54,7 @@
<function name="hypot"/>
<function name="int"/>
<function name="lcm"/>
+ <function name="leverage"/>
<function name="linsolve"/>
<function name="ln"/>
<function name="ln1p"/>
diff --git a/src/regression.h b/src/regression.h
index 1627b2c..d9a0c7b 100644
--- a/src/regression.h
+++ b/src/regression.h
@@ -12,6 +12,7 @@ G_BEGIN_DECLS
# define gnm_regression_stat_new go_regression_stat_newl
# define gnm_regression_stat_destroy go_regression_stat_destroyl
# define gnm_linear_regression go_linear_regressionl
+# define gnm_linear_regression_leverage go_linear_regression_leveragel
# define gnm_exponential_regression go_exponential_regressionl
# define gnm_logarithmic_regression go_logarithmic_regressionl
# define gnm_logarithmic_fit go_logarithmic_fitl
@@ -25,6 +26,7 @@ G_BEGIN_DECLS
# define gnm_regression_stat_new go_regression_stat_new
# define gnm_regression_stat_destroy go_regression_stat_destroy
# define gnm_linear_regression go_linear_regression
+# define gnm_linear_regression_leverage go_linear_regression_leverage
# define gnm_exponential_regression go_exponential_regression
# define gnm_logarithmic_regression go_logarithmic_regression
# define gnm_logarithmic_fit go_logarithmic_fit
diff --git a/src/tools/ChangeLog b/src/tools/ChangeLog
index 6389699..7ce79b6 100644
--- a/src/tools/ChangeLog
+++ b/src/tools/ChangeLog
@@ -1,3 +1,8 @@
+2013-01-17 Morten Welinder <terra gnome org>
+
+ * analysis-tools.c (analysis_tool_regression_engine_run): Simplify
+ using new LEVERAGE function.
+
2012-12-18 Morten Welinder <terra gnome org>
* Release 1.12.0
diff --git a/src/tools/analysis-tools.c b/src/tools/analysis-tools.c
index 5c469ee..16aae31 100644
--- a/src/tools/analysis-tools.c
+++ b/src/tools/analysis-tools.c
@@ -2881,8 +2881,7 @@ analysis_tool_regression_engine_run (data_analysis_output_t *dao,
GnmFunc *fd_offset = NULL;
GnmFunc *fd_sumproduct = NULL;
GnmFunc *fd_mmult = NULL;
- GnmFunc *fd_minverse = NULL;
- GnmFunc *fd_munit = NULL;
+ GnmFunc *fd_leverage = NULL;
GnmFunc *fd_sumsq = NULL;
char const *str = ((info->group_by == GROUPED_BY_ROW) ? "row" : "col");
@@ -2898,8 +2897,7 @@ analysis_tool_regression_engine_run (data_analysis_output_t *dao,
if (info->residual) {
fd_sumproduct = analysis_tool_get_function ("SUMPRODUCT", dao);
fd_mmult = analysis_tool_get_function ("MMULT", dao);
- fd_minverse = analysis_tool_get_function ("MINVERSE", dao);
- fd_munit = analysis_tool_get_function ("MUNIT", dao);
+ fd_leverage = analysis_tool_get_function ("LEVERAGE", dao);
fd_sumsq = analysis_tool_get_function ("SUMSQ", dao);
}
@@ -3343,31 +3341,9 @@ analysis_tool_regression_engine_run (data_analysis_output_t *dao,
if (dao_cell_is_visible (dao, xdim + 4, n_obs)) {
GnmExpr const *expr_X = dao_get_rangeref (dao, info->intercept ? 0 : 1, 1, xdim, n_obs);
- GnmExpr const *expr_X_t =
- gnm_expr_new_funcall1 (fd_transpose, gnm_expr_copy (expr_X));
- GnmExpr const *expr_X_hat =
- gnm_expr_new_funcall2
- (fd_mmult,
- gnm_expr_new_funcall2
- (fd_mmult,
- expr_X,
- gnm_expr_new_funcall1
- (fd_minverse,
- gnm_expr_new_funcall2
- (fd_mmult,
- gnm_expr_copy (expr_X_t),
- gnm_expr_copy (expr_X)))),
- expr_X_t);
GnmExpr const *expr_diagonal =
- gnm_expr_new_funcall2
- (fd_mmult,
- gnm_expr_new_binary
- (expr_X_hat, GNM_EXPR_OP_MULT,
- gnm_expr_new_funcall1
- (fd_munit, gnm_expr_new_binary
- (dao_get_cellref (dao, 1, - 11 - xdim),
- GNM_EXPR_OP_ADD, gnm_expr_new_constant (value_new_int (1))))),
- dao_get_rangeref (dao, 0, 1, 0, n_obs));
+ gnm_expr_new_funcall1
+ (fd_leverage, expr_X);
GnmExpr const *expr_var =
gnm_expr_new_binary
(gnm_expr_new_funcall1
@@ -3463,10 +3439,8 @@ analysis_tool_regression_engine_run (data_analysis_output_t *dao,
gnm_func_unref (fd_sumproduct);
if (fd_mmult != NULL)
gnm_func_unref (fd_mmult);
- if (fd_minverse != NULL)
- gnm_func_unref (fd_minverse);
- if (fd_munit != NULL)
- gnm_func_unref (fd_munit);
+ if (fd_leverage != NULL)
+ gnm_func_unref (fd_leverage);
if (fd_sumsq != NULL)
gnm_func_unref (fd_sumsq);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]