-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathregression.c
75 lines (64 loc) · 2.1 KB
/
regression.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "regression.h"
#include "scale.h"
/* Linear regression. */
// lr:{m:{(+/x)%1.0*#x};mx:m@x;my:m@y;dx:x-mx;n:+/dx*y-my;d:+/dx^2;s:n%d;(s;my-s*mx)}
static bool calc_means(point *points, size_t point_count, transform_t t, double *mx, double *my);
static double calc_num(point *points, size_t point_count, transform_t t, double mx, double my);
static double calc_den(point *points, size_t point_count, transform_t t, double mx);
void regression(point *points, size_t point_count, transform_t t,
double *slope, double *intercept) {
assert(slope);
assert(intercept);
double mx = 0;
double my = 0;
if (!calc_means(points, point_count, t, &mx, &my)) {
*slope = EMPTY_VALUE;
*intercept = EMPTY_VALUE;
return;
}
double num = calc_num(points, point_count, t, mx, my);
double den = calc_den(points, point_count, t, mx);
*slope = num / den;
*intercept = my - *slope * mx;
LOG(1, "-- slope: %g, intercept: %g\n", *slope, *intercept);
}
static bool calc_means(point *points, size_t point_count, transform_t t, double *mx, double *my) {
double tx = 0;
double ty = 0;
size_t cx = 0;
size_t cy = 0;
for (size_t i = 0; i < point_count; i++) {
point *p = &points[i];
if (IS_EMPTY_POINT(p)) { continue; }
cx++;
cy++;
point tp;
scale_transform(p, t, &tp);
tx += tp.x;
ty += tp.y;
}
if (cx == 0) { return false; }
*mx = tx / cx;
*my = ty / cy;
return true;
}
static double calc_num(point *points, size_t point_count, transform_t t, double mx, double my) {
double sum = 0;
for (size_t i = 0; i < point_count; i++) {
point *p = &points[i];
point tp;
scale_transform(p, t, &tp);
sum += (tp.x - mx) * (tp.y - my);
}
return sum;
}
static double calc_den(point *points, size_t point_count, transform_t t, double mx) {
double sum = 0;
for (size_t i = 0; i < point_count; i++) {
point *p = &points[i];
point tp;
scale_transform(p, t, &tp);
sum += (tp.x - mx) * (tp.x - mx);
}
return sum;
}