|
Packit |
67cb25 |
/* multifit/gcv.c
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* Copyright (C) 2016 Patrick Alken
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
67cb25 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
67cb25 |
* the Free Software Foundation; either version 3 of the License, or (at
|
|
Packit |
67cb25 |
* your option) any later version.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
67cb25 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
67cb25 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
67cb25 |
* General Public License for more details.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
67cb25 |
* along with this program; if not, write to the Free Software
|
|
Packit |
67cb25 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
* References:
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* [1] P. C. Hansen, "Discrete Inverse Problems: Insight and Algorithms,"
|
|
Packit |
67cb25 |
* SIAM Press, 2010.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include <config.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_errno.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_multifit.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_blas.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_vector.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_matrix.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_linalg.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_min.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
typedef struct
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const gsl_vector * S;
|
|
Packit |
67cb25 |
const gsl_vector * UTy;
|
|
Packit |
67cb25 |
double delta0;
|
|
Packit |
67cb25 |
size_t np;
|
|
Packit |
67cb25 |
gsl_vector * workp;
|
|
Packit |
67cb25 |
} gcv_params;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static double gcv_func(double lambda, void * params);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
gsl_multifit_linear_gcv_init()
|
|
Packit |
67cb25 |
Initialize Generalized Cross Validation parameters
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Inputs: y - right hand side vector
|
|
Packit |
67cb25 |
reg_param - (output) regularization parameters
|
|
Packit |
67cb25 |
UTy - (output) U^T y
|
|
Packit |
67cb25 |
delta0 - (output) delta0
|
|
Packit |
67cb25 |
work - workspace
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_linear_gcv_init(const gsl_vector * y,
|
|
Packit |
67cb25 |
gsl_vector * reg_param,
|
|
Packit |
67cb25 |
gsl_vector * UTy,
|
|
Packit |
67cb25 |
double * delta0,
|
|
Packit |
67cb25 |
gsl_multifit_linear_workspace * work)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = y->size;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (n != work->n)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("y vector does not match workspace", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (UTy->size != work->p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("UTy vector does not match workspace", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t p = work->p;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_matrix_view U = gsl_matrix_submatrix(work->A, 0, 0, n, p);
|
|
Packit |
67cb25 |
gsl_vector_view S = gsl_vector_subvector(work->S, 0, p);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
const double smax = gsl_vector_get(&S.vector, 0);
|
|
Packit |
67cb25 |
const double smin = gsl_vector_get(&S.vector, p - 1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double dr; /* residual error from projection */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double normy = gsl_blas_dnrm2(y);
|
|
Packit |
67cb25 |
double normUTy;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* compute projection UTy = U^T y */
|
|
Packit |
67cb25 |
gsl_blas_dgemv (CblasTrans, 1.0, &U.matrix, y, 0.0, UTy);
|
|
Packit |
67cb25 |
normUTy = gsl_blas_dnrm2(UTy);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* dr = ||y||^2 - ||U^T y||^2 */
|
|
Packit |
67cb25 |
dr = (normy + normUTy) * (normy - normUTy);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* calculate regularization parameters */
|
|
Packit |
67cb25 |
gsl_multifit_linear_lreg(smin, smax, reg_param);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (n > p && dr > 0.0)
|
|
Packit |
67cb25 |
*delta0 = dr;
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
*delta0 = 0.0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
gsl_multifit_linear_gcv_curve()
|
|
Packit |
67cb25 |
Calculate Generalized Cross Validation curve for a set
|
|
Packit |
67cb25 |
of regularization parameters
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Inputs: reg_param - regularization parameters
|
|
Packit |
67cb25 |
UTy - U^T y vector, size p
|
|
Packit |
67cb25 |
delta0 - delta0
|
|
Packit |
67cb25 |
G - (output) GCV curve values
|
|
Packit |
67cb25 |
work - workspace
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_linear_gcv_curve(const gsl_vector * reg_param,
|
|
Packit |
67cb25 |
const gsl_vector * UTy,
|
|
Packit |
67cb25 |
const double delta0,
|
|
Packit |
67cb25 |
gsl_vector * G,
|
|
Packit |
67cb25 |
gsl_multifit_linear_workspace * work)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = work->n;
|
|
Packit |
67cb25 |
const size_t p = work->p;
|
|
Packit |
67cb25 |
const size_t N = reg_param->size; /* number of points on GCV curve */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (UTy->size != p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("UTy vector does not match workspace", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (G->size != N)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("size of reg_param and G vectors do not match",
|
|
Packit |
67cb25 |
GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t i;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_view S = gsl_vector_subvector(work->S, 0, p);
|
|
Packit |
67cb25 |
gsl_vector_view workp = gsl_matrix_subcolumn(work->QSI, 0, 0, p);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gcv_params params;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
params.S = &S.vector;
|
|
Packit |
67cb25 |
params.UTy = UTy;
|
|
Packit |
67cb25 |
params.delta0 = delta0;
|
|
Packit |
67cb25 |
params.np = n - p;
|
|
Packit |
67cb25 |
params.workp = &workp.vector;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < N; ++i)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double lambdai = gsl_vector_get(reg_param, i);
|
|
Packit |
67cb25 |
double Gi = gcv_func(lambdai, ¶ms);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_set(G, i, Gi);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
gsl_multifit_linear_gcv_min()
|
|
Packit |
67cb25 |
Find regularization parameter which minimizes GCV curve
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Inputs: reg_param - regularization parameters
|
|
Packit |
67cb25 |
UTy - U^T y vector, size p
|
|
Packit |
67cb25 |
G - GCV curve values
|
|
Packit |
67cb25 |
delta0 - delta0
|
|
Packit |
67cb25 |
lambda - (output) optimal regularization parameter
|
|
Packit |
67cb25 |
work - workspace
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_linear_gcv_min(const gsl_vector * reg_param,
|
|
Packit |
67cb25 |
const gsl_vector * UTy,
|
|
Packit |
67cb25 |
const gsl_vector * G,
|
|
Packit |
67cb25 |
const double delta0,
|
|
Packit |
67cb25 |
double * lambda,
|
|
Packit |
67cb25 |
gsl_multifit_linear_workspace * work)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = work->n;
|
|
Packit |
67cb25 |
const size_t p = work->p;
|
|
Packit |
67cb25 |
const size_t npts = reg_param->size; /* number of points on GCV curve */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (UTy->size != p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("UTy vector does not match workspace", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (G->size != npts)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("size of reg_param and G vectors do not match",
|
|
Packit |
67cb25 |
GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status;
|
|
Packit |
67cb25 |
const size_t max_iter = 500;
|
|
Packit |
67cb25 |
const double tol = 1.0e-4;
|
|
Packit |
67cb25 |
gsl_vector_view S = gsl_vector_subvector(work->S, 0, p);
|
|
Packit |
67cb25 |
gsl_vector_view workp = gsl_matrix_subcolumn(work->QSI, 0, 0, p);
|
|
Packit |
67cb25 |
gcv_params params;
|
|
Packit |
67cb25 |
int idxG = (int) gsl_vector_min_index(G);
|
|
Packit |
67cb25 |
double a = gsl_vector_get(reg_param, GSL_MIN(idxG + 1, (int) npts - 1));
|
|
Packit |
67cb25 |
double b = gsl_vector_get(reg_param, GSL_MAX(idxG - 1, 0));
|
|
Packit |
67cb25 |
double m = gsl_vector_get(reg_param, idxG);
|
|
Packit |
67cb25 |
size_t iter = 0;
|
|
Packit |
67cb25 |
gsl_function F;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* XXX FIXME */
|
|
Packit |
67cb25 |
gsl_min_fminimizer *min_workspace_p;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (idxG == 0 || idxG == ((int)npts - 1))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* the minimum is an endpoint of the curve, no need to search */
|
|
Packit |
67cb25 |
*lambda = m;
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* XXX FIXME */
|
|
Packit |
67cb25 |
min_workspace_p = gsl_min_fminimizer_alloc(gsl_min_fminimizer_brent);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
params.S = &S.vector;
|
|
Packit |
67cb25 |
params.UTy = UTy;
|
|
Packit |
67cb25 |
params.delta0 = delta0;
|
|
Packit |
67cb25 |
params.np = n - p;
|
|
Packit |
67cb25 |
params.workp = &workp.vector;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
F.function = gcv_func;
|
|
Packit |
67cb25 |
F.params = ¶m;;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_min_fminimizer_set(min_workspace_p, &F, m, a, b);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
do
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
iter++;
|
|
Packit |
67cb25 |
status = gsl_min_fminimizer_iterate(min_workspace_p);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
a = gsl_min_fminimizer_x_lower(min_workspace_p);
|
|
Packit |
67cb25 |
b = gsl_min_fminimizer_x_upper(min_workspace_p);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
status = gsl_min_test_interval(a, b, 0.0, tol);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
while (status == GSL_CONTINUE && iter < max_iter);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (status == GSL_SUCCESS)
|
|
Packit |
67cb25 |
*lambda = gsl_min_fminimizer_minimum(min_workspace_p);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
status = GSL_EMAXITER;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_min_fminimizer_free(min_workspace_p);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
gsl_multifit_linear_gcv_calc()
|
|
Packit |
67cb25 |
Calculate GCV function G(lambda) for given lambda
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Inputs: reg_param - regularization parameters
|
|
Packit |
67cb25 |
UTy - U^T y vector, size p
|
|
Packit |
67cb25 |
delta0 - delta0
|
|
Packit |
67cb25 |
G - (output) GCV curve values
|
|
Packit |
67cb25 |
work - workspace
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double
|
|
Packit |
67cb25 |
gsl_multifit_linear_gcv_calc(const double lambda,
|
|
Packit |
67cb25 |
const gsl_vector * UTy,
|
|
Packit |
67cb25 |
const double delta0,
|
|
Packit |
67cb25 |
gsl_multifit_linear_workspace * work)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = work->n;
|
|
Packit |
67cb25 |
const size_t p = work->p;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (UTy->size != p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_VAL("UTy vector does not match workspace", GSL_EBADLEN, 0.0);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_vector_view S = gsl_vector_subvector(work->S, 0, p);
|
|
Packit |
67cb25 |
gsl_vector_view workp = gsl_matrix_subcolumn(work->QSI, 0, 0, p);
|
|
Packit |
67cb25 |
gcv_params params;
|
|
Packit |
67cb25 |
double G;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
params.S = &S.vector;
|
|
Packit |
67cb25 |
params.UTy = UTy;
|
|
Packit |
67cb25 |
params.delta0 = delta0;
|
|
Packit |
67cb25 |
params.np = n - p;
|
|
Packit |
67cb25 |
params.workp = &workp.vector;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
G = gcv_func(lambda, ¶ms);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return G;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
gsl_multifit_linear_gcv()
|
|
Packit |
67cb25 |
Calculate Generalized Cross Validation curve for a set
|
|
Packit |
67cb25 |
of regularization parameters
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Inputs: y - right hand side vector
|
|
Packit |
67cb25 |
reg_param - (output) regularization parameters
|
|
Packit |
67cb25 |
G - (output) GCV curve values
|
|
Packit |
67cb25 |
lambda - (output) optimal regularization parameter which
|
|
Packit |
67cb25 |
minimizes GCV curve
|
|
Packit |
67cb25 |
G_lambda - (output) G(lambda) value at optimal parameter
|
|
Packit |
67cb25 |
work - workspace
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_linear_gcv(const gsl_vector * y,
|
|
Packit |
67cb25 |
gsl_vector * reg_param,
|
|
Packit |
67cb25 |
gsl_vector * G,
|
|
Packit |
67cb25 |
double * lambda,
|
|
Packit |
67cb25 |
double * G_lambda,
|
|
Packit |
67cb25 |
gsl_multifit_linear_workspace * work)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = y->size;
|
|
Packit |
67cb25 |
const size_t N = G->size; /* number of points on GCV curve */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (n != work->n)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("y vector does not match workspace", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (reg_param->size != N)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("size of reg_param and G vectors do not match",
|
|
Packit |
67cb25 |
GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status;
|
|
Packit |
67cb25 |
const size_t p = work->p;
|
|
Packit |
67cb25 |
gsl_vector_view UTy = gsl_vector_subvector(work->xt, 0, p);
|
|
Packit |
67cb25 |
double delta0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
status = gsl_multifit_linear_gcv_init(y, reg_param, &UTy.vector, &delta0, work);
|
|
Packit |
67cb25 |
if (status)
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
status = gsl_multifit_linear_gcv_curve(reg_param, &UTy.vector, delta0, G, work);
|
|
Packit |
67cb25 |
if (status)
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
status = gsl_multifit_linear_gcv_min(reg_param, &UTy.vector, G, delta0, lambda, work);
|
|
Packit |
67cb25 |
if (status)
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
*G_lambda = gsl_multifit_linear_gcv_calc(*lambda, &UTy.vector, delta0, work);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static double
|
|
Packit |
67cb25 |
gcv_func(double lambda, void * params)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gcv_params * par = (gcv_params *) params;
|
|
Packit |
67cb25 |
const gsl_vector *S = par->S;
|
|
Packit |
67cb25 |
const gsl_vector *UTy = par->UTy;
|
|
Packit |
67cb25 |
double delta0 = par->delta0;
|
|
Packit |
67cb25 |
size_t np = par->np;
|
|
Packit |
67cb25 |
gsl_vector *workp = par->workp;
|
|
Packit |
67cb25 |
const size_t p = S->size;
|
|
Packit |
67cb25 |
size_t i;
|
|
Packit |
67cb25 |
double lambda_sq = lambda * lambda;
|
|
Packit |
67cb25 |
double G, d, norm;
|
|
Packit |
67cb25 |
double sumf = 0.0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* compute workp = 1 - filter_factors */
|
|
Packit |
67cb25 |
for (i = 0; i < p; ++i)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double si = gsl_vector_get(S, i);
|
|
Packit |
67cb25 |
double fi = lambda_sq / (si * si + lambda_sq);
|
|
Packit |
67cb25 |
gsl_vector_set(workp, i, fi);
|
|
Packit |
67cb25 |
sumf += fi;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
d = (double)np + sumf;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_mul(workp, UTy);
|
|
Packit |
67cb25 |
norm = gsl_blas_dnrm2(workp);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
G = (norm*norm + delta0) / (d * d);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return G;
|
|
Packit |
67cb25 |
}
|