Coverage Report

Created: 2026-05-16 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/svt-av1/Source/Lib/Codec/mathutils.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2017, Alliance for Open Media. All rights reserved
3
 *
4
 * This source code is subject to the terms of the BSD 2 Clause License and
5
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6
 * was not distributed with this source code in the LICENSE file, you can
7
 * obtain it at https://www.aomedia.org/license/software-license. If the Alliance for Open
8
 * Media Patent License 1.0 was not distributed with this source code in the
9
 * PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license.
10
 */
11
12
#ifndef AOM_AV1_ENCODER_MATHUTILS_H_
13
#define AOM_AV1_ENCODER_MATHUTILS_H_
14
15
#include <memory.h>
16
#include <math.h>
17
#include <stdio.h>
18
#include <stdlib.h>
19
#include <assert.h>
20
21
// Solves Ax = b, where x and b are column vectors of size nx1 and A is nxn
22
static INLINE int32_t linsolve(int32_t n, double* A, int32_t stride, double* b, double* x) {
23
    const double tiny_near_zero = 1.0E-16;
24
    int32_t      i, j, k;
25
    double       c;
26
    // Forward elimination
27
    for (k = 0; k < n - 1; k++) {
28
        // Bring the largest magnitude to the diagonal position
29
        for (i = n - 1; i > k; i--) {
30
            if (fabs(A[(i - 1) * stride + k]) < fabs(A[i * stride + k])) {
31
                for (j = 0; j < n; j++) {
32
                    c                       = A[i * stride + j];
33
                    A[i * stride + j]       = A[(i - 1) * stride + j];
34
                    A[(i - 1) * stride + j] = c;
35
                }
36
                c        = b[i];
37
                b[i]     = b[i - 1];
38
                b[i - 1] = c;
39
            }
40
        }
41
        for (i = k; i < n - 1; i++) {
42
            if (fabs(A[k * stride + k]) < tiny_near_zero) {
43
                return 0;
44
            }
45
            c = A[(i + 1) * stride + k] / A[k * stride + k];
46
            for (j = 0; j < n; j++) {
47
                A[(i + 1) * stride + j] -= c * A[k * stride + j];
48
            }
49
            b[i + 1] -= c * b[k];
50
        }
51
    }
52
    // Backward substitution
53
    for (i = n - 1; i >= 0; i--) {
54
        if (fabs(A[i * stride + i]) < tiny_near_zero) {
55
            return 0;
56
        }
57
        c = 0;
58
        for (j = i + 1; j <= n - 1; j++) {
59
            c += A[i * stride + j] * x[j];
60
        }
61
        x[i] = (b[i] - c) / A[i * stride + i];
62
    }
63
64
    return 1;
65
}
66
67
// Least-squares
68
// Solves for n-dim x in a least squares sense to minimize |Ax - b|^2
69
// The solution is simply x = (A'A)^-1 A'b or simply the solution for
70
// the system: A'A x = A'b
71
//
72
// This process is split into three steps in order to avoid needing to
73
// explicitly allocate the A matrix, which may be very large if there
74
// are many equations to solve.
75
//
76
// The process for using this is (in pseudocode):
77
//
78
// Allocate mat (size n*n), y (size n), a (size n), x (size n)
79
// least_squares_init(mat, y, n)
80
// for each equation a . x = b {
81
//    least_squares_accumulate(mat, y, a, b, n)
82
// }
83
// least_squares_solve(mat, y, x, n)
84
//
85
// where:
86
// * mat, y are accumulators for the values A'A and A'b respectively,
87
// * a, b are the coefficients of each individual equation,
88
// * x is the result vector
89
// * and n is the problem size
90
0
static INLINE void least_squares_init(double* mat, double* y, int n) {
91
0
    memset(mat, 0, n * n * sizeof(double));
92
0
    memset(y, 0, n * sizeof(double));
93
0
}
Unexecuted instantiation: noise_model.c:least_squares_init
Unexecuted instantiation: ransac.c:least_squares_init
94
95
0
static INLINE void least_squares_accumulate(double* mat, double* y, const double* a, double b, int n) {
96
0
    for (int i = 0; i < n; i++) {
97
0
        for (int j = 0; j < n; j++) {
98
0
            mat[i * n + j] += a[i] * a[j];
99
0
        }
100
0
    }
101
0
    for (int i = 0; i < n; i++) {
102
0
        y[i] += a[i] * b;
103
0
    }
104
0
}
Unexecuted instantiation: noise_model.c:least_squares_accumulate
Unexecuted instantiation: ransac.c:least_squares_accumulate
105
106
0
static INLINE int least_squares_solve(double* mat, double* y, double* x, int n) {
107
0
    return linsolve(n, mat, n, y, x);
108
0
}
Unexecuted instantiation: noise_model.c:least_squares_solve
Unexecuted instantiation: ransac.c:least_squares_solve
109
110
// Matrix multiply
111
static INLINE void multiply_mat(const double* m1, const double* m2, double* res, const int32_t m1_rows,
112
                                const int32_t inner_dim, const int32_t m2_cols) {
113
    double sum;
114
115
    int32_t row, col, inner;
116
    for (row = 0; row < m1_rows; ++row) {
117
        for (col = 0; col < m2_cols; ++col) {
118
            sum = 0;
119
            for (inner = 0; inner < inner_dim; ++inner) {
120
                sum += m1[row * inner_dim + inner] * m2[inner * m2_cols + col];
121
            }
122
            *(res++) = sum;
123
        }
124
    }
125
}
126
127
#endif // AOM_AV1_ENCODER_MATHUTILS_H_