MRTKLIB 0.7.14
Modernized GNSS Positioning Library
Loading...
Searching...
No Matches
mrtk_mat.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------------
2 * mrtk_mat.c : matrix and vector functions
3 *
4 * Copyright (C) 2026 H.SHIONO (MRTKLIB Project)
5 * Copyright (C) 2023-2025 Cabinet Office, Japan
6 * Copyright (C) 2024-2025 Lighthouse Technology & Consulting Co. Ltd.
7 * Copyright (C) 2023-2025 Japan Aerospace Exploration Agency
8 * Copyright (C) 2023-2025 TOSHIBA ELECTRONIC TECHNOLOGIES CORPORATION
9 * Copyright (C) 2015- Mitsubishi Electric Corp.
10 * Copyright (C) 2014 Geospatial Information Authority of Japan
11 * Copyright (C) 2014 T.SUZUKI
12 * Copyright (C) 2007-2023 T.TAKASU
13 *
14 * SPDX-License-Identifier: BSD-2-Clause
15 *----------------------------------------------------------------------------*/
16/**
17 * @file mrtk_mat.c
18 * @brief MRTKLIB Matrix Module — Matrix/vector operations and estimation.
19 *
20 * This file contains all matrix/vector and estimation functions extracted
21 * from rtkcmn.c with zero algorithmic changes (pure cut-and-paste).
22 */
23#include "mrtklib/mrtk_mat.h"
24
25#include <math.h>
26#include <stdarg.h>
27#include <stdlib.h>
28#include <string.h>
29
30/*============================================================================
31 * Static Data
32 *===========================================================================*/
33
34static fatalfunc_t* fatalfunc = NULL; /* fatal callback function */
35
36/*============================================================================
37 * Internal Helpers
38 *===========================================================================*/
39
40/* fatal error ---------------------------------------------------------------*/
41static void fatalerr(const char* format, ...) {
42 char msg[1024];
43 va_list ap;
44 va_start(ap, format);
45 vsprintf(msg, format, ap);
46 va_end(ap);
47 if (fatalfunc) {
48 fatalfunc(msg);
49 } else {
50 fprintf(stderr, "%s", msg);
51 }
52 exit(-9);
53}
54
55/*============================================================================
56 * Fatal Callback
57 *===========================================================================*/
58
59/* add fatal callback function -------------------------------------------------
60 * add fatal callback function for mat(),zeros(),imat()
61 * args : fatalfunc_t *func I callback function
62 * return : none
63 * notes : if malloc() failed in return : none
64 *-----------------------------------------------------------------------------*/
65extern void add_fatal(fatalfunc_t* func) { fatalfunc = func; }
66
67/*============================================================================
68 * Matrix Allocation
69 *===========================================================================*/
70
71/* new matrix ------------------------------------------------------------------
72 * allocate memory of matrix
73 * args : int n,m I number of rows and columns of matrix
74 * return : matrix pointer (if n<=0 or m<=0, return NULL)
75 *-----------------------------------------------------------------------------*/
76extern double* mat(int n, int m) {
77 double* p;
78
79 if (n <= 0 || m <= 0) {
80 return NULL;
81 }
82 if (!(p = (double*)malloc(sizeof(double) * n * m))) {
83 fatalerr("matrix memory allocation error: n=%d,m=%d\n", n, m);
84 }
85 return p;
86}
87/* new integer matrix ----------------------------------------------------------
88 * allocate memory of integer matrix
89 * args : int n,m I number of rows and columns of matrix
90 * return : matrix pointer (if n<=0 or m<=0, return NULL)
91 *-----------------------------------------------------------------------------*/
92extern int* imat(int n, int m) {
93 int* p;
94
95 if (n <= 0 || m <= 0) {
96 return NULL;
97 }
98 if (!(p = (int*)malloc(sizeof(int) * n * m))) {
99 fatalerr("integer matrix memory allocation error: n=%d,m=%d\n", n, m);
100 }
101 return p;
102}
103/* zero matrix -----------------------------------------------------------------
104 * generate new zero matrix
105 * args : int n,m I number of rows and columns of matrix
106 * return : matrix pointer (if n<=0 or m<=0, return NULL)
107 *-----------------------------------------------------------------------------*/
108extern double* zeros(int n, int m) {
109 double* p;
110
111#if NOCALLOC
112 if ((p = mat(n, m)))
113 for (n = n * m - 1; n >= 0; n--) p[n] = 0.0;
114#else
115 if (n <= 0 || m <= 0) {
116 return NULL;
117 }
118 if (!(p = (double*)calloc(sizeof(double), n * m))) {
119 fatalerr("matrix memory allocation error: n=%d,m=%d\n", n, m);
120 }
121#endif
122 return p;
123}
124/* identity matrix -------------------------------------------------------------
125 * generate new identity matrix
126 * args : int n I number of rows and columns of matrix
127 * return : matrix pointer (if n<=0, return NULL)
128 *-----------------------------------------------------------------------------*/
129extern double* eye(int n) {
130 double* p;
131 int i;
132
133 if ((p = zeros(n, n))) {
134 for (i = 0; i < n; i++) {
135 p[i + i * n] = 1.0;
136 }
137 }
138 return p;
139}
140
141/*============================================================================
142 * Vector Operations
143 *===========================================================================*/
144
145/* inner product ---------------------------------------------------------------
146 * inner product of vectors
147 * args : double *a,*b I vector a,b (n x 1)
148 * int n I size of vector a,b
149 * return : a'*b
150 *-----------------------------------------------------------------------------*/
151extern double dot(const double* a, const double* b, int n) {
152 double c = 0.0;
153
154 while (--n >= 0) {
155 c += a[n] * b[n];
156 }
157 return c;
158}
159/* euclid norm -----------------------------------------------------------------
160 * euclid norm of vector
161 * args : double *a I vector a (n x 1)
162 * int n I size of vector a
163 * return : || a ||
164 *-----------------------------------------------------------------------------*/
165extern double norm(const double* a, int n) { return sqrt(dot(a, a, n)); }
166/* outer product of 3d vectors -------------------------------------------------
167 * outer product of 3d vectors
168 * args : double *a,*b I vector a,b (3 x 1)
169 * double *c O outer product (a x b) (3 x 1)
170 * return : none
171 *-----------------------------------------------------------------------------*/
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];
176}
177/* normalize 3d vector ---------------------------------------------------------
178 * normalize 3d vector
179 * args : double *a I vector a (3 x 1)
180 * double *b O normlized vector (3 x 1) || b || = 1
181 * return : status (1:ok,0:error)
182 *-----------------------------------------------------------------------------*/
183extern int normv3(const double* a, double* b) {
184 double r;
185 if ((r = norm(a, 3)) <= 0.0) {
186 return 0;
187 }
188 b[0] = a[0] / r;
189 b[1] = a[1] / r;
190 b[2] = a[2] / r;
191 return 1;
192}
193
194/*============================================================================
195 * Matrix Operations
196 *===========================================================================*/
197
198/* copy matrix -----------------------------------------------------------------
199 * copy matrix
200 * args : double *A O destination matrix A (n x m)
201 * double *B I source matrix B (n x m)
202 * int n,m I number of rows and columns of matrix
203 * return : none
204 *-----------------------------------------------------------------------------*/
205extern void matcpy(double* A, const double* B, int n, int m) { memcpy(A, B, sizeof(double) * n * m); }
206/* matrix routines -----------------------------------------------------------*/
207
208#ifdef LAPACK /* with LAPACK/BLAS or MKL */
209
210/* LAPACK/BLAS Fortran interface declarations */
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,
216 int* info);
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);
219
220#ifdef MRTK_DETERMINISTIC_BLAS
221/* OpenBLAS distributes reductions across threads with a non-deterministic
222 * accumulation order, so multi-threaded results vary at the last ULP run to
223 * run. On storm-day PPP-RTK that ULP noise crosses the AR ratio threshold and
224 * flips fix/float decisions, making benchmarks irreproducible. Forcing a
225 * single thread makes every BLAS/LAPACK call bit-reproducible. This runs once
226 * at load time for any binary that links mrtklib (CLI and unit tests alike).
227 * Opt-in via the MRTK_DETERMINISTIC_BLAS CMake option, whose configure-time
228 * check guarantees the linked provider is OpenBLAS (the source of this
229 * symbol). Silent fallback is not acceptable here — an unpinned thread count
230 * would defeat the option's whole purpose — so unsupported toolchains fail
231 * the build instead. */
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); }
235#else
236#error "MRTK_DETERMINISTIC_BLAS needs GCC/Clang; use OPENBLAS_NUM_THREADS=1 at runtime instead."
237#endif
238#endif
239
240/* multiply matrix (wrapper of blas dgemm) -------------------------------------
241 * multiply matrix by matrix (C=alpha*A*B+beta*C)
242 * args : char *tr I transpose flags ("N":normal,"T":transpose)
243 * int n,k,m I size of (transposed) matrix A,B
244 * double alpha I alpha
245 * double *A,*B I (transposed) matrix A (n x m), B (m x k)
246 * double beta I beta
247 * double *C IO matrix C (n x k)
248 * return : none
249 *-----------------------------------------------------------------------------*/
250extern void matmul(const char* tr, int n, int k, int m, double alpha, const double* A, const double* B, double beta,
251 double* C) {
252 int lda, ldb;
253
254 if (n <= 0 || k <= 0 || m <= 0) {
255 return;
256 }
257 lda = tr[0] == 'T' ? m : n;
258 ldb = tr[1] == 'T' ? k : m;
259
260 dgemm_((char*)tr, (char*)tr + 1, &n, &k, &m, &alpha, (double*)A, &lda, (double*)B, &ldb, &beta, C, &n);
261}
262/* inverse of matrix -----------------------------------------------------------
263 * inverse of matrix (A=A^-1)
264 * args : double *A IO matrix (n x n)
265 * int n I size of matrix A
266 * return : status (0:ok,0>:error)
267 *-----------------------------------------------------------------------------*/
268extern int matinv(double* A, int n) {
269 double* work;
270 int info, lwork = n * 16, *ipiv = imat(n, 1);
271
272 work = mat(lwork, 1);
273 dgetrf_(&n, &n, A, &n, ipiv, &info);
274 if (!info) {
275 dgetri_(&n, A, &n, ipiv, work, &lwork, &info);
276 }
277 free(ipiv);
278 free(work);
279 return info;
280}
281/* solve linear equation -------------------------------------------------------
282 * solve linear equation (X=A\Y or X=A'\Y)
283 * args : char *tr I transpose flag ("N":normal,"T":transpose)
284 * double *A I input matrix A (n x n)
285 * double *Y I input matrix Y (n x m)
286 * int n,m I size of matrix A,Y
287 * double *X O X=A\Y or X=A'\Y (n x m)
288 * return : status (0:ok,0>:error)
289 * notes : matirix stored by column-major order (fortran convention)
290 * X can be same as Y
291 *-----------------------------------------------------------------------------*/
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);
295
296 matcpy(B, A, n, n);
297 matcpy(X, Y, n, m);
298 dgetrf_(&n, &n, B, &n, ipiv, &info);
299 if (!info) {
300 dgetrs_((char*)tr, &n, &m, B, &n, ipiv, X, &n, &info);
301 }
302 free(ipiv);
303 free(B);
304 return info;
305}
306
307#else /* without LAPACK/BLAS or MKL */
308
309/* multiply matrix -----------------------------------------------------------*/
310extern void matmul(const char* tr, int n, int k, int m, double alpha, const double* A, const double* B, double beta,
311 double* C) {
312 double d;
313 int i, j, x, f;
314
315 if (tr[0] == 'N') {
316 f = tr[1] == 'N' ? 1 : 2;
317 } else {
318 f = tr[1] == 'N' ? 3 : 4;
319 }
320
321 for (i = 0; i < n; i++)
322 for (j = 0; j < k; j++) {
323 d = 0.0;
324 switch (f) {
325 case 1:
326 for (x = 0; x < m; x++) d += A[i + x * n] * B[x + j * m];
327 break;
328 case 2:
329 for (x = 0; x < m; x++) d += A[i + x * n] * B[j + x * k];
330 break;
331 case 3:
332 for (x = 0; x < m; x++) d += A[x + i * m] * B[x + j * m];
333 break;
334 case 4:
335 for (x = 0; x < m; x++) d += A[x + i * m] * B[j + x * k];
336 break;
337 }
338 if (beta == 0.0)
339 C[i + j * n] = alpha * d;
340 else
341 C[i + j * n] = alpha * d + beta * C[i + j * n];
342 }
343}
344/* LU decomposition ----------------------------------------------------------*/
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;
348
349 *d = 1.0;
350 for (i = 0; i < n; i++) {
351 big = 0.0;
352 for (j = 0; j < n; j++)
353 if ((tmp = fabs(A[i + j * n])) > big) big = tmp;
354 if (big > 0.0)
355 vv[i] = 1.0 / big;
356 else {
357 free(vv);
358 return -1;
359 }
360 }
361 for (j = 0; j < n; j++) {
362 for (i = 0; i < j; i++) {
363 s = A[i + j * n];
364 for (k = 0; k < i; k++) s -= A[i + k * n] * A[k + j * n];
365 A[i + j * n] = s;
366 }
367 big = 0.0;
368 for (i = j; i < n; i++) {
369 s = A[i + j * n];
370 for (k = 0; k < j; k++) s -= A[i + k * n] * A[k + j * n];
371 A[i + j * n] = s;
372 if ((tmp = vv[i] * fabs(s)) >= big) {
373 big = tmp;
374 imax = i;
375 }
376 }
377 if (j != imax) {
378 for (k = 0; k < n; k++) {
379 tmp = A[imax + k * n];
380 A[imax + k * n] = A[j + k * n];
381 A[j + k * n] = tmp;
382 }
383 *d = -(*d);
384 vv[imax] = vv[j];
385 }
386 indx[j] = imax;
387 if (A[j + j * n] == 0.0) {
388 free(vv);
389 return -1;
390 }
391 if (j != n - 1) {
392 tmp = 1.0 / A[j + j * n];
393 for (i = j + 1; i < n; i++) A[i + j * n] *= tmp;
394 }
395 }
396 free(vv);
397 return 0;
398}
399/* LU back-substitution ------------------------------------------------------*/
400static void lubksb(const double* A, int n, const int* indx, double* b) {
401 double s;
402 int i, ii = -1, ip, j;
403
404 for (i = 0; i < n; i++) {
405 ip = indx[i];
406 s = b[ip];
407 b[ip] = b[i];
408 if (ii >= 0)
409 for (j = ii; j < i; j++) s -= A[i + j * n] * b[j];
410 else if (s)
411 ii = i;
412 b[i] = s;
413 }
414 for (i = n - 1; i >= 0; i--) {
415 s = b[i];
416 for (j = i + 1; j < n; j++) s -= A[i + j * n] * b[j];
417 b[i] = s / A[i + i * n];
418 }
419}
420/* inverse of matrix ---------------------------------------------------------*/
421extern int matinv(double* A, int n) {
422 double d, *B;
423 int i, j, *indx;
424
425 indx = imat(n, 1);
426 B = mat(n, n);
427 matcpy(B, A, n, n);
428 if (ludcmp(B, n, indx, &d)) {
429 free(indx);
430 free(B);
431 return -1;
432 }
433 for (j = 0; j < n; j++) {
434 for (i = 0; i < n; i++) A[i + j * n] = 0.0;
435 A[j + j * n] = 1.0;
436 lubksb(B, n, indx, A + j * n);
437 }
438 free(indx);
439 free(B);
440 return 0;
441}
442/* solve linear equation -----------------------------------------------------*/
443extern int solve(const char* tr, const double* A, const double* Y, int n, int m, double* X) {
444 double* B = mat(n, n);
445 int info;
446
447 matcpy(B, A, n, n);
448 if (!(info = matinv(B, n))) matmul(tr[0] == 'N' ? "NN" : "TN", n, m, n, 1.0, B, Y, 0.0, X);
449 free(B);
450 return info;
451}
452#endif
453/* end of matrix routines ----------------------------------------------------*/
454
455/*============================================================================
456 * Estimation Algorithms
457 *===========================================================================*/
458
459/* least square estimation -----------------------------------------------------
460 * least square estimation by solving normal equation (x=(A*A')^-1*A*y)
461 * args : double *A I transpose of (weighted) design matrix (n x m)
462 * double *y I (weighted) measurements (m x 1)
463 * int n,m I number of parameters and measurements (n<=m)
464 * double *x O estmated parameters (n x 1)
465 * double *Q O esimated parameters covariance matrix (n x n)
466 * return : status (0:ok,0>:error)
467 * notes : for weighted least square, replace A and y by A*w and w*y (w=W^(1/2))
468 * matirix stored by column-major order (fortran convention)
469 *-----------------------------------------------------------------------------*/
470extern int lsq(const double* A, const double* y, int n, int m, double* x, double* Q) {
471 double* Ay;
472 int info;
473
474 if (m < n) {
475 return -1;
476 }
477 Ay = mat(n, 1);
478 matmul("NN", n, 1, m, 1.0, A, y, 0.0, Ay); /* Ay=A*y */
479 matmul("NT", n, n, m, 1.0, A, A, 0.0, Q); /* Q=A*A' */
480 if (!(info = matinv(Q, n))) {
481 matmul("NN", n, 1, n, 1.0, Q, Ay, 0.0, x); /* x=Q^-1*Ay */
482 }
483 free(Ay);
484 return info;
485}
486/* kalman filter ---------------------------------------------------------------
487 * kalman filter state update as follows:
488 *
489 * K=P*H*(H'*P*H+R)^-1, xp=x+K*v, Pp=(I-K*H')*P
490 *
491 * args : double *x I states vector (n x 1)
492 * double *P I covariance matrix of states (n x n)
493 * double *H I transpose of design matrix (n x m)
494 * double *v I innovation (measurement - model) (m x 1)
495 * double *R I covariance matrix of measurement error (m x m)
496 * int n,m I number of states and measurements
497 * double *xp O states vector after update (n x 1)
498 * double *Pp O covariance matrix of states after update (n x n)
499 * return : status (0:ok,<0:error)
500 * notes : matirix stored by column-major order (fortran convention)
501 * if state x[i]==0.0, not updates state x[i]/P[i+i*n]
502 *-----------------------------------------------------------------------------*/
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);
506 int info;
507
508 matcpy(Q, R, m, m);
509 matcpy(xp, x, n, 1);
510 matmul("NN", n, m, n, 1.0, P, H, 0.0, F); /* Q=H'*P*H+R */
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); /* K=P*H*Q^-1 */
514 matmul("NN", n, 1, m, 1.0, K, v, 1.0, xp); /* xp=x+K*v */
515 matmul("NT", n, n, m, -1.0, K, H, 1.0, I); /* Pp=(I-K*H')*P */
516 matmul("NN", n, n, n, 1.0, I, P, 0.0, Pp);
517 }
518 free(F);
519 free(Q);
520 free(K);
521 free(I);
522 return info;
523}
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;
527
528 ix = imat(n, 1);
529 for (i = k = 0; i < n; i++) {
530 if (x[i] != 0.0 && P[i + i * n] > 0.0) {
531 ix[k++] = i;
532 }
533 }
534 x_ = mat(k, 1);
535 xp_ = mat(k, 1);
536 P_ = mat(k, k);
537 Pp_ = mat(k, k);
538 H_ = mat(k, m);
539 for (i = 0; i < k; i++) {
540 x_[i] = x[ix[i]];
541 for (j = 0; j < k; j++) {
542 P_[i + j * k] = P[ix[i] + ix[j] * n];
543 }
544 for (j = 0; j < m; j++) {
545 H_[i + j * k] = H[ix[i] + j * n];
546 }
547 }
548 info = filter_(x_, P_, H_, v, R, k, m, xp_, Pp_);
549 for (i = 0; i < k; i++) {
550 x[ix[i]] = xp_[i];
551 for (j = 0; j < k; j++) {
552 P[ix[i] + ix[j] * n] = Pp_[i + j * k];
553 }
554 }
555 free(ix);
556 free(x_);
557 free(xp_);
558 free(P_);
559 free(Pp_);
560 free(H_);
561 return info;
562}
563/* smoother --------------------------------------------------------------------
564 * combine forward and backward filters by fixed-interval smoother as follows:
565 *
566 * xs=Qs*(Qf^-1*xf+Qb^-1*xb), Qs=(Qf^-1+Qb^-1)^-1)
567 *
568 * args : double *xf I forward solutions (n x 1)
569 * args : double *Qf I forward solutions covariance matrix (n x n)
570 * double *xb I backward solutions (n x 1)
571 * double *Qb I backward solutions covariance matrix (n x n)
572 * int n I number of solutions
573 * double *xs O smoothed solutions (n x 1)
574 * double *Qs O smoothed solutions covariance matrix (n x n)
575 * return : status (0:ok,0>:error)
576 * notes : see reference [4] 5.2
577 * matirix stored by column-major order (fortran convention)
578 *-----------------------------------------------------------------------------*/
579extern int smoother(const double* xf, const double* Qf, const double* xb, const double* Qb, int n, double* xs,
580 double* Qs) {
581 double *invQf = mat(n, n), *invQb = mat(n, n), *xx = mat(n, 1);
582 int i, info = -1;
583
584 matcpy(invQf, Qf, n, n);
585 matcpy(invQb, Qb, n, n);
586 if (!matinv(invQf, n) && !matinv(invQb, n)) {
587 for (i = 0; i < n * n; i++) {
588 Qs[i] = invQf[i] + invQb[i];
589 }
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);
594 }
595 }
596 free(invQf);
597 free(invQb);
598 free(xx);
599 return info;
600}
601
602/*============================================================================
603 * Matrix Output
604 *===========================================================================*/
605
606/* print matrix ----------------------------------------------------------------
607 * print matrix to stdout
608 * args : double *A I matrix A (n x m)
609 * int n,m I number of rows and columns of A
610 * int p,q I total columns, columns under decimal point
611 * (FILE *fp I output file pointer)
612 * return : none
613 * notes : matirix stored by column-major order (fortran convention)
614 *-----------------------------------------------------------------------------*/
615extern void matfprint(const double A[], int n, int m, int p, int q, FILE* fp) {
616 int i, j;
617
618 for (i = 0; i < n; i++) {
619 for (j = 0; j < m; j++) {
620 fprintf(fp, " %*.*f", p, q, A[i + j * n]);
621 }
622 fprintf(fp, "\n");
623 }
624}
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.
Definition mrtk_mat.c:76
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.
Definition mrtk_mat.c:579
int matinv(double *A, int n)
Inverse of matrix (A = A^-1).
Definition mrtk_mat.c:421
double * zeros(int n, int m)
Allocate a new zero matrix.
Definition mrtk_mat.c:108
int lsq(const double *A, const double *y, int n, int m, double *x, double *Q)
Least square estimation by solving normal equation.
Definition mrtk_mat.c:470
static void fatalerr(const char *format,...)
Definition mrtk_mat.c:41
void matcpy(double *A, const double *B, int n, int m)
Copy matrix.
Definition mrtk_mat.c:205
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).
Definition mrtk_mat.c:443
void cross3(const double *a, const double *b, double *c)
Cross product of 3D vectors.
Definition mrtk_mat.c:172
static fatalfunc_t * fatalfunc
Definition mrtk_mat.c:34
void matfprint(const double A[], int n, int m, int p, int q, FILE *fp)
Definition mrtk_mat.c:615
int * imat(int n, int m)
Allocate memory for an integer matrix.
Definition mrtk_mat.c:92
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)
Definition mrtk_mat.c:503
void matprint(const double A[], int n, int m, int p, int q)
Definition mrtk_mat.c:625
int filter(double *x, double *P, const double *H, const double *v, const double *R, int n, int m)
Kalman filter state update.
Definition mrtk_mat.c:524
void add_fatal(fatalfunc_t *func)
Add fatal callback function for mat(), zeros(), imat().
Definition mrtk_mat.c:65
double norm(const double *a, int n)
Euclidean norm of vector.
Definition mrtk_mat.c:165
static void lubksb(const double *A, int n, const int *indx, double *b)
Definition mrtk_mat.c:400
int normv3(const double *a, double *b)
Normalize 3D vector.
Definition mrtk_mat.c:183
static int ludcmp(double *A, int n, int *indx, double *d)
Definition mrtk_mat.c:345
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).
Definition mrtk_mat.c:310
double dot(const double *a, const double *b, int n)
Inner product of vectors.
Definition mrtk_mat.c:151
double * eye(int n)
Generate a new identity matrix.
Definition mrtk_mat.c:129
MRTKLIB Matrix Module — Matrix/vector operations and estimation.
void fatalfunc_t(const char *)
Fatal callback function type for allocation failures.
Definition mrtk_mat.h:43
#define malloc(x)
Definition toml.c:52
#define calloc(x, y)
Definition toml.c:54
#define free(x)
Definition toml.c:53