From c12ea6023d97118ffffbfb9053b7f863dabacff5 Mon Sep 17 00:00:00 2001 From: Jason Stover Date: Fri, 7 Apr 2006 19:37:13 +0000 Subject: [PATCH] added residual computation; improved handling of bad input --- src/math/linreg/ChangeLog | 9 +++++++++ src/math/linreg/coefficient.c | 34 ++++++++++++++++++++++++++-------- src/math/linreg/linreg.h | 5 ++++- src/math/linreg/predict.c | 34 ++++++++++++++++++++++++++++++---- 4 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/math/linreg/ChangeLog b/src/math/linreg/ChangeLog index 7b6ee73d..5c8b9c1f 100644 --- a/src/math/linreg/ChangeLog +++ b/src/math/linreg/ChangeLog @@ -1,3 +1,12 @@ +2006-04-07 Jason Stover + + * predict.c (pspp_linreg_predict): Improved handling of null + pointer args. + + * predict.c (pspp_linreg_residuals): New function. + + * coefficient.c: Improved handling of null pointer args. + 2006-04-05 Jason Stover * predict.c: New file. pspp_linreg_predict() uses a linear model diff --git a/src/math/linreg/coefficient.c b/src/math/linreg/coefficient.c index d09432b3..cca02bcb 100644 --- a/src/math/linreg/coefficient.c +++ b/src/math/linreg/coefficient.c @@ -105,7 +105,10 @@ pspp_linreg_coeff_set_std_err (struct pspp_linreg_coeff *c, double std_err) double pspp_linreg_coeff_get_est (const struct pspp_linreg_coeff *c) { - assert (c != NULL); + if (c == NULL) + { + return 0.0; + } return c->estimate; } /* @@ -114,7 +117,10 @@ pspp_linreg_coeff_get_est (const struct pspp_linreg_coeff *c) double pspp_linreg_coeff_get_std_err (const struct pspp_linreg_coeff *c) { - assert (c != NULL); + if (c == NULL) + { + return 0.0; + } return c->std_err; } /* @@ -123,6 +129,10 @@ pspp_linreg_coeff_get_std_err (const struct pspp_linreg_coeff *c) int pspp_linreg_coeff_get_n_vars (struct pspp_linreg_coeff *c) { + if (c == NULL) + { + return 0; + } return c->n_vars; } @@ -132,6 +142,10 @@ pspp_linreg_coeff_get_n_vars (struct pspp_linreg_coeff *c) const struct variable * pspp_linreg_coeff_get_var (struct pspp_linreg_coeff *c, int i) { + if (c == NULL) + { + return NULL; + } assert (i < c->n_vars); return (c->v_info + i)->v; } @@ -146,6 +160,10 @@ pspp_linreg_coeff_get_value (struct pspp_linreg_coeff *c, int i = 0; const struct variable *candidate; + if (c == NULL || v == NULL) + { + return NULL; + } while (i < c->n_vars) { candidate = pspp_linreg_coeff_get_var (c, i); @@ -170,11 +188,10 @@ pspp_linreg_get_coeff (const pspp_linreg_cache *c, struct pspp_linreg_coeff *result; const struct variable *tmp; - assert (c != NULL); - assert (c->coeff != NULL); - assert (c->n_indeps > 0); - assert (v != NULL); - assert (val != NULL); + if (c == NULL || c->coeff == NULL || c->n_indeps == NULL || v == NULL) + { + return NULL; + } result = c->coeff + i; tmp = pspp_linreg_coeff_get_var (result, 0); @@ -192,7 +209,7 @@ pspp_linreg_get_coeff (const pspp_linreg_cache *c, { return result; } - else + else if (val != NULL) { /* If v is categorical, we need to ensure the coefficient @@ -211,5 +228,6 @@ pspp_linreg_get_coeff (const pspp_linreg_cache *c, } return result; } + return NULL; } diff --git a/src/math/linreg/linreg.h b/src/math/linreg/linreg.h index 2852dd77..be5803fd 100644 --- a/src/math/linreg/linreg.h +++ b/src/math/linreg/linreg.h @@ -22,7 +22,7 @@ #ifndef LINREG_H #define LINREG_H - +#include #include #include @@ -181,4 +181,7 @@ int pspp_linreg (const gsl_vector * Y, const gsl_matrix * X, double pspp_linreg_predict (const struct variable *, const union value *, const pspp_linreg_cache *, int); +double +pspp_linreg_residual (const struct variable *, const union value *, + const union value *, const pspp_linreg_cache *, int); #endif diff --git a/src/math/linreg/predict.c b/src/math/linreg/predict.c index f2539c0e..fdd94097 100644 --- a/src/math/linreg/predict.c +++ b/src/math/linreg/predict.c @@ -38,10 +38,15 @@ pspp_linreg_predict (const struct variable *predictors, double result; double tmp; - assert (predictors != NULL); - assert (vals != NULL); - assert (c != NULL); - + if (predictors == NULL || vals == NULL || c == NULL) + { + return GSL_NAN; + } + if (c->coeff == NULL) + { + /* The stupid model: just guess the mean. */ + return c->depvar_mean; + } result = c->coeff->estimate; /* Intercept. */ /* @@ -60,3 +65,24 @@ pspp_linreg_predict (const struct variable *predictors, } return result; } + +double +pspp_linreg_residual (const struct variable *predictors, + const union value *vals, + const union value *obs, + const pspp_linreg_cache *c, + int n_vals) +{ + double pred; + double result; + + if (predictors == NULL || vals == NULL || c == NULL || obs == NULL) + { + return GSL_NAN; + } + + pred = pspp_linreg_predict (predictors, vals, c, n_vals); + + result = gsl_isnan (pred) ? GSL_NAN : (obs->f - pred); + return result; +} -- 2.30.2