analistica/ex-3/common.c
2020-03-06 02:24:32 +01:00

127 lines
3.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "common.h"
/* `vector_fprint(fp, x)` prints to file `fp`
* the components of a gsl_vector.
*/
void vector_fprint(FILE *fp, const gsl_vector *x) {
fprintf(fp, "[");
for (size_t i = 0; i < x->size; i++) {
fprintf(fp, i < x->size -1 ? "%10.4g, " : "%10.4g",
gsl_vector_get(x, i));
}
fprintf(fp, "]\n");
}
/* `matrix_fprint(fp, x)` prints to file `fp`
* the components of a gsl_vector.
*/
void matrix_fprint(FILE *fp, const gsl_matrix *x) {
gsl_vector row;
for (size_t i = 0; i < x->size1; i++) {
row = gsl_matrix_const_row(x, i).vector;
fputs(" ", fp);
vector_fprint(fp, &row);
}
}
/* `vector_map(f, v)` applies the function
* `f` to each element of the vector `v`, inplace.
* The function return a GSL exit code to either
* report success or a failure.
*/
int vector_map(double (*f)(double x), gsl_vector *v) {
double y;
for (size_t i = 0; i < v->size; i++ ) {
y = (*f)(gsl_vector_get(v, i));
gsl_vector_set(v, i, y);
}
return GSL_SUCCESS;
}
/* Angular distribution function F(θ,φ; α,β,γ)
* Takes three parameters α,β,γ and the angles θ,φ.
*/
double distr(const gsl_vector *par,
const struct event *event){
double a = gsl_vector_get(par, 0),
b = gsl_vector_get(par, 1),
c = gsl_vector_get(par, 2);
double th = event->th,
ph = event->ph;
double A = 3 /(4 * M_PI);
double B = 0.5 * (1 - a);
double C = 0.5 * (3 * a - 1) * pow(cos(th), 2);
double D = b * pow(sin(th), 2) * cos(2 * ph);
double E = sqrt(2) * c * sin(2 * th) * cos(ph);
return A * (B + C - D - E);
}
/* `grad_distr(par, event, grad)`
* computes the gradient of F(α,β,γ; α,β) as:
*
* ⎡ 3/2⋅cos²(θ) - 1/2 ⎤
* ⎢ ⎥
* ⎢ sin²(θ)⋅cos(2φ) ⎥ 3/(4π)
* ⎢ ⎥
* ⎣ √2⋅sin(2θ)⋅cos(φ) ⎦
*
* where `par` is [α,β,γ], `event` is the angle
* structure. The results is stored in the
* gsl_vector `grad`
*/
void grad_distr(const gsl_vector *par,
const struct event *event,
gsl_vector *grad) {
double th = event->th,
ph = event->ph;
gsl_vector_set(grad, 0, 1.5*pow(cos(th), 2) - 0.5);
gsl_vector_set(grad, 1, -pow(sin(th), 2) * cos(2*ph));
gsl_vector_set(grad, 2, -sqrt(2)*sin(2*th) * cos(ph));
gsl_vector_scale(grad, 3.0/(4.0 * M_PI));
}
/* Test the compatibility between the original
* parameters `def` and the estimates `est.par`
* with standard errors `est.err`.
*/
void compatibility(gsl_vector *def,
min_result est) {
char* names[] = { "α", "β", "γ" };
double a, b;
double t, sigma, alpha;
fprintf(stderr, "| par | σ | α-value |\n");
fprintf(stderr, "|-----|----------|----------|\n");
for (size_t i = 0; i < def->size; i++) {
// discrepancy
a = gsl_vector_get(def, i);
b = gsl_vector_get(est.par, i);
sigma = gsl_vector_get(est.err, i);
// normal t-statistic
t = fabs(a - b)/sigma;
// α-value / significance
alpha = 1 - erf(t/sqrt(2));
fprintf(stderr, "| %s | %-8.2g | %-8.2g |\n",
names[i], sigma, alpha);
}
}
/* Free a min_result structure.
*/
void min_result_free(min_result x) {
gsl_vector_free(x.par);
gsl_matrix_free(x.cov);
}