2 * linear least squares model
4 * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * linear least squares model
34 #define av_log(a,b,...) printf(__VA_ARGS__)
37 void av_init_lls(LLSModel
*m
, int indep_count
){
38 memset(m
, 0, sizeof(LLSModel
));
40 m
->indep_count
= indep_count
;
43 void av_update_lls(LLSModel
*m
, double *var
, double decay
){
46 for(i
=0; i
<=m
->indep_count
; i
++){
47 for(j
=i
; j
<=m
->indep_count
; j
++){
48 m
->covariance
[i
][j
] *= decay
;
49 m
->covariance
[i
][j
] += var
[i
]*var
[j
];
54 void av_solve_lls(LLSModel
*m
, double threshold
, int min_order
){
56 double (*factor
)[MAX_VARS
+1]= (void*)&m
->covariance
[1][0];
57 double (*covar
)[MAX_VARS
+1]= (void*)&m
->covariance
[1][1];
58 double *covar_y
= m
->covariance
[0];
59 int count
= m
->indep_count
;
61 for(i
=0; i
<count
; i
++){
62 for(j
=i
; j
<count
; j
++){
63 double sum
= covar
[i
][j
];
66 sum
-= factor
[i
][k
]*factor
[j
][k
];
71 factor
[i
][i
]= sqrt(sum
);
73 factor
[j
][i
]= sum
/ factor
[i
][i
];
76 for(i
=0; i
<count
; i
++){
77 double sum
= covar_y
[i
+1];
79 sum
-= factor
[i
][k
]*m
->coeff
[0][k
];
80 m
->coeff
[0][i
]= sum
/ factor
[i
][i
];
83 for(j
=count
-1; j
>=min_order
; j
--){
85 double sum
= m
->coeff
[0][i
];
87 sum
-= factor
[k
][i
]*m
->coeff
[j
][k
];
88 m
->coeff
[j
][i
]= sum
/ factor
[i
][i
];
91 m
->variance
[j
]= covar_y
[0];
93 double sum
= m
->coeff
[j
][i
]*covar
[i
][i
] - 2*covar_y
[i
+1];
95 sum
+= 2*m
->coeff
[j
][k
]*covar
[k
][i
];
96 m
->variance
[j
] += m
->coeff
[j
][i
]*sum
;
101 double av_evaluate_lls(LLSModel
*m
, double *param
, int order
){
105 for(i
=0; i
<=order
; i
++)
106 out
+= param
[i
]*m
->coeff
[order
][i
];
122 for(i
=0; i
<100; i
++){
126 var
[1] = rand() / (double)RAND_MAX
;
127 var
[2] = rand() / (double)RAND_MAX
;
128 var
[3] = rand() / (double)RAND_MAX
;
130 var
[2]= var
[1] + var
[3]/2;
132 var
[0] = var
[1] + var
[2] + var
[3] + var
[1]*var
[2]/100;
134 var
[0] = (rand() / (double)RAND_MAX
- 0.5)*2;
135 var
[1] = var
[0] + rand() / (double)RAND_MAX
- 0.5;
136 var
[2] = var
[1] + rand() / (double)RAND_MAX
- 0.5;
137 var
[3] = var
[2] + rand() / (double)RAND_MAX
- 0.5;
139 av_update_lls(&m
, var
, 0.99);
140 av_solve_lls(&m
, 0.001, 0);
141 for(order
=0; order
<3; order
++){
142 eval
= av_evaluate_lls(&m
, var
+1, order
);
143 av_log(NULL
, AV_LOG_DEBUG
, "real:%f order:%d pred:%f var:%f coeffs:%f %f %f\n",
144 var
[0], order
, eval
, sqrt(m
.variance
[order
] / (i
+1)),
145 m
.coeff
[order
][0], m
.coeff
[order
][1], m
.coeff
[order
][2]);