45 vsprintf(msg, format, ap);
50 fprintf(stderr,
"%s", msg);
76extern double*
mat(
int n,
int m) {
79 if (n <= 0 || m <= 0) {
82 if (!(p = (
double*)
malloc(
sizeof(
double) * n * m))) {
83 fatalerr(
"matrix memory allocation error: n=%d,m=%d\n", n, m);
92extern int*
imat(
int n,
int m) {
95 if (n <= 0 || m <= 0) {
98 if (!(p = (
int*)
malloc(
sizeof(
int) * n * m))) {
99 fatalerr(
"integer matrix memory allocation error: n=%d,m=%d\n", n, m);
113 for (n = n * m - 1; n >= 0; n--) p[n] = 0.0;
115 if (n <= 0 || m <= 0) {
118 if (!(p = (
double*)
calloc(
sizeof(
double), n * m))) {
119 fatalerr(
"matrix memory allocation error: n=%d,m=%d\n", n, m);
129extern double*
eye(
int n) {
133 if ((p =
zeros(n, n))) {
134 for (i = 0; i < n; i++) {
151extern double dot(
const double* a,
const double* b,
int n) {
165extern double norm(
const double* a,
int n) {
return sqrt(
dot(a, a, n)); }
172extern void cross3(
const double* a,
const double* b,
double* c) {
173 c[0] = a[1] * b[2] - a[2] * b[1];
174 c[1] = a[2] * b[0] - a[0] * b[2];
175 c[2] = a[0] * b[1] - a[1] * b[0];
183extern int normv3(
const double* a,
double* b) {
185 if ((r =
norm(a, 3)) <= 0.0) {
205extern void matcpy(
double* A,
const double* B,
int n,
int m) { memcpy(A, B,
sizeof(
double) * n * m); }
211extern void dgemm_(
const char* transa,
const char* transb,
const int* m,
const int* n,
const int* k,
212 const double* alpha,
const double* A,
const int* lda,
const double* B,
const int* ldb,
213 const double* beta,
double* C,
const int* ldc);
214extern void dgetrf_(
const int* m,
const int* n,
double* A,
const int* lda,
int* ipiv,
int* info);
215extern void dgetri_(
const int* n,
double* A,
const int* lda,
const int* ipiv,
double* work,
const int* lwork,
217extern void dgetrs_(
const char* trans,
const int* n,
const int* nrhs,
const double* A,
const int* lda,
const int* ipiv,
218 double* B,
const int* ldb,
int* info);
220#ifdef MRTK_DETERMINISTIC_BLAS
232#if defined(__GNUC__) || defined(__clang__)
233extern void openblas_set_num_threads(
int num_threads);
234__attribute__((constructor))
static void mrtk_force_single_thread_blas(
void) { openblas_set_num_threads(1); }
236#error "MRTK_DETERMINISTIC_BLAS needs GCC/Clang; use OPENBLAS_NUM_THREADS=1 at runtime instead."
250extern void matmul(
const char* tr,
int n,
int k,
int m,
double alpha,
const double* A,
const double* B,
double beta,
254 if (n <= 0 || k <= 0 || m <= 0) {
257 lda = tr[0] ==
'T' ? m : n;
258 ldb = tr[1] ==
'T' ? k : m;
260 dgemm_((
char*)tr, (
char*)tr + 1, &n, &k, &m, &alpha, (
double*)A, &lda, (
double*)B, &ldb, &beta, C, &n);
268extern int matinv(
double* A,
int n) {
270 int info, lwork = n * 16, *ipiv =
imat(n, 1);
272 work =
mat(lwork, 1);
273 dgetrf_(&n, &n, A, &n, ipiv, &info);
275 dgetri_(&n, A, &n, ipiv, work, &lwork, &info);
292extern int solve(
const char* tr,
const double* A,
const double* Y,
int n,
int m,
double* X) {
293 double* B =
mat(n, n);
294 int info, *ipiv =
imat(n, 1);
298 dgetrf_(&n, &n, B, &n, ipiv, &info);
300 dgetrs_((
char*)tr, &n, &m, B, &n, ipiv, X, &n, &info);
310extern void matmul(
const char* tr,
int n,
int k,
int m,
double alpha,
const double* A,
const double* B,
double beta,
316 f = tr[1] ==
'N' ? 1 : 2;
318 f = tr[1] ==
'N' ? 3 : 4;
321 for (i = 0; i < n; i++)
322 for (j = 0; j < k; j++) {
326 for (x = 0; x < m; x++) d += A[i + x * n] * B[x + j * m];
329 for (x = 0; x < m; x++) d += A[i + x * n] * B[j + x * k];
332 for (x = 0; x < m; x++) d += A[x + i * m] * B[x + j * m];
335 for (x = 0; x < m; x++) d += A[x + i * m] * B[j + x * k];
339 C[i + j * n] = alpha * d;
341 C[i + j * n] = alpha * d + beta * C[i + j * n];
345static int ludcmp(
double* A,
int n,
int* indx,
double* d) {
346 double big, s, tmp, *vv =
mat(n, 1);
347 int i, imax = 0, j, k;
350 for (i = 0; i < n; i++) {
352 for (j = 0; j < n; j++)
353 if ((tmp = fabs(A[i + j * n])) > big) big = tmp;
361 for (j = 0; j < n; j++) {
362 for (i = 0; i < j; i++) {
364 for (k = 0; k < i; k++) s -= A[i + k * n] * A[k + j * n];
368 for (i = j; i < n; i++) {
370 for (k = 0; k < j; k++) s -= A[i + k * n] * A[k + j * n];
372 if ((tmp = vv[i] * fabs(s)) >= big) {
378 for (k = 0; k < n; k++) {
379 tmp = A[imax + k * n];
380 A[imax + k * n] = A[j + k * n];
387 if (A[j + j * n] == 0.0) {
392 tmp = 1.0 / A[j + j * n];
393 for (i = j + 1; i < n; i++) A[i + j * n] *= tmp;
400static void lubksb(
const double* A,
int n,
const int* indx,
double* b) {
402 int i, ii = -1, ip, j;
404 for (i = 0; i < n; i++) {
409 for (j = ii; j < i; j++) s -= A[i + j * n] * b[j];
414 for (i = n - 1; i >= 0; i--) {
416 for (j = i + 1; j < n; j++) s -= A[i + j * n] * b[j];
417 b[i] = s / A[i + i * n];
428 if (
ludcmp(B, n, indx, &d)) {
433 for (j = 0; j < n; j++) {
434 for (i = 0; i < n; i++) A[i + j * n] = 0.0;
436 lubksb(B, n, indx, A + j * n);
443extern int solve(
const char* tr,
const double* A,
const double* Y,
int n,
int m,
double* X) {
444 double* B =
mat(n, n);
448 if (!(info =
matinv(B, n)))
matmul(tr[0] ==
'N' ?
"NN" :
"TN", n, m, n, 1.0, B, Y, 0.0, X);
470extern int lsq(
const double* A,
const double* y,
int n,
int m,
double* x,
double* Q) {
478 matmul(
"NN", n, 1, m, 1.0, A, y, 0.0, Ay);
479 matmul(
"NT", n, n, m, 1.0, A, A, 0.0, Q);
480 if (!(info =
matinv(Q, n))) {
481 matmul(
"NN", n, 1, n, 1.0, Q, Ay, 0.0, x);
503static int filter_(
const double* x,
const double* P,
const double* H,
const double* v,
const double* R,
int n,
int m,
504 double* xp,
double* Pp) {
505 double *F =
mat(n, m), *Q =
mat(m, m), *K =
mat(n, m), *I =
eye(n);
510 matmul(
"NN", n, m, n, 1.0, P, H, 0.0, F);
511 matmul(
"TN", m, m, n, 1.0, H, F, 1.0, Q);
512 if (!(info =
matinv(Q, m))) {
513 matmul(
"NN", n, m, m, 1.0, F, Q, 0.0, K);
514 matmul(
"NN", n, 1, m, 1.0, K, v, 1.0, xp);
515 matmul(
"NT", n, n, m, -1.0, K, H, 1.0, I);
516 matmul(
"NN", n, n, n, 1.0, I, P, 0.0, Pp);
524extern int filter(
double* x,
double* P,
const double* H,
const double* v,
const double* R,
int n,
int m) {
525 double *x_, *xp_, *P_, *Pp_, *H_;
526 int i, j, k, info, *ix;
529 for (i = k = 0; i < n; i++) {
530 if (x[i] != 0.0 && P[i + i * n] > 0.0) {
539 for (i = 0; i < k; i++) {
541 for (j = 0; j < k; j++) {
542 P_[i + j * k] = P[ix[i] + ix[j] * n];
544 for (j = 0; j < m; j++) {
545 H_[i + j * k] = H[ix[i] + j * n];
548 info =
filter_(x_, P_, H_, v, R, k, m, xp_, Pp_);
549 for (i = 0; i < k; i++) {
551 for (j = 0; j < k; j++) {
552 P[ix[i] + ix[j] * n] = Pp_[i + j * k];
579extern int smoother(
const double* xf,
const double* Qf,
const double* xb,
const double* Qb,
int n,
double* xs,
581 double *invQf =
mat(n, n), *invQb =
mat(n, n), *xx =
mat(n, 1);
587 for (i = 0; i < n * n; i++) {
588 Qs[i] = invQf[i] + invQb[i];
590 if (!(info =
matinv(Qs, n))) {
591 matmul(
"NN", n, 1, n, 1.0, invQf, xf, 0.0, xx);
592 matmul(
"NN", n, 1, n, 1.0, invQb, xb, 1.0, xx);
593 matmul(
"NN", n, 1, n, 1.0, Qs, xx, 0.0, xs);
615extern void matfprint(
const double A[],
int n,
int m,
int p,
int q, FILE* fp) {
618 for (i = 0; i < n; i++) {
619 for (j = 0; j < m; j++) {
620 fprintf(fp,
" %*.*f", p, q, A[i + j * n]);
625extern void matprint(
const double A[],
int n,
int m,
int p,
int q) {
matfprint(A, n, m, p, q, stdout); }
double * mat(int n, int m)
Allocate memory for a double matrix.
int smoother(const double *xf, const double *Qf, const double *xb, const double *Qb, int n, double *xs, double *Qs)
Combine forward and backward filters by fixed-interval smoother.
int matinv(double *A, int n)
Inverse of matrix (A = A^-1).
double * zeros(int n, int m)
Allocate a new zero matrix.
int lsq(const double *A, const double *y, int n, int m, double *x, double *Q)
Least square estimation by solving normal equation.
static void fatalerr(const char *format,...)
void matcpy(double *A, const double *B, int n, int m)
Copy matrix.
int solve(const char *tr, const double *A, const double *Y, int n, int m, double *X)
Solve linear equation (X = A\Y or X = A'\Y).
void cross3(const double *a, const double *b, double *c)
Cross product of 3D vectors.
static fatalfunc_t * fatalfunc
void matfprint(const double A[], int n, int m, int p, int q, FILE *fp)
int * imat(int n, int m)
Allocate memory for an integer matrix.
static int filter_(const double *x, const double *P, const double *H, const double *v, const double *R, int n, int m, double *xp, double *Pp)
void matprint(const double A[], int n, int m, int p, int q)
int filter(double *x, double *P, const double *H, const double *v, const double *R, int n, int m)
Kalman filter state update.
void add_fatal(fatalfunc_t *func)
Add fatal callback function for mat(), zeros(), imat().
double norm(const double *a, int n)
Euclidean norm of vector.
static void lubksb(const double *A, int n, const int *indx, double *b)
int normv3(const double *a, double *b)
Normalize 3D vector.
static int ludcmp(double *A, int n, int *indx, double *d)
void matmul(const char *tr, int n, int k, int m, double alpha, const double *A, const double *B, double beta, double *C)
Multiply matrix by matrix (C = alpha*A*B + beta*C).
double dot(const double *a, const double *b, int n)
Inner product of vectors.
double * eye(int n)
Generate a new identity matrix.
MRTKLIB Matrix Module — Matrix/vector operations and estimation.
void fatalfunc_t(const char *)
Fatal callback function type for allocation failures.