vnl_fastops.cxx
Go to the documentation of this file.
1 // This is core/vnl/vnl_fastops.cxx
2 //:
3 // \file
4 // \author Andrew W. Fitzgibbon, Oxford RRG
5 // \date 08 Dec 96
6 //
7 //-----------------------------------------------------------------------------
8 
9 #include <cstdlib>
10 #include <cstring>
11 #include <iostream>
12 #include "vnl_fastops.h"
13 
14 //: Compute $A^\top A$.
16 {
17  const unsigned int n = A.columns();
18  // Verify output is the right size
19  if (out.rows() != n || out.columns() != n)
20  out.set_size(n,n);
21 
22  const unsigned int m = A.rows();
23 
24  double const* const* a = A.data_array();
25  double** ata = out.data_array();
26 
27 /* Simple Implementation for reference:
28  for (unsigned int i = 0; i < n; ++i)
29  for (unsigned int j = i; j < n; ++j) {
30  double accum = 0;
31  for (unsigned int k = 0; k < m; ++k)
32  accum += a[k][i] * a[k][j];
33  ata[i][j] = ata[j][i] = accum;
34  }
35  Next is 5 times faster on 600 Mhz Pentium III for m = 10000, n = 50
36 */
37  std::memset(ata[0], 0, n * n * sizeof ata[0][0]);
38  for (unsigned int k = 0; k < m; ++k)
39  for (unsigned int i = 0; i < n; ++i) {
40  const double aki = a[k][i];
41  double const* arow = a[k] + i;
42  double* atarow = ata[i] + i;
43  double const* arowend = a[k] + n;
44  while (arow != arowend)
45  *atarow++ += aki * *arow++;
46  }
47  for (unsigned int i = 0; i < n; ++i)
48  for (unsigned int j = i+1; j < n; ++j)
49  ata[j][i] = ata[i][j];
50 }
51 
52 //: Compute AxB.
54 {
55  const unsigned int na = A.columns();
56  const unsigned int mb = B.rows();
57 
58  // Verify matrices compatible
59  if (na != mb) {
60  std::cerr << "vnl_fastops::AB: argument sizes do not match: " << na << " != " << mb << '\n';
61  std::abort();
62  }
63 
64  const unsigned int ma = A.rows();
65  const unsigned int nb = B.columns();
66 
67  // Verify output is the right size
68  if (out.rows() != ma || out.columns() != nb)
69  out.set_size(ma,nb);
70 
71  double const* const* a = A.data_array();
72  double const* const* b = B.data_array();
73  double** outdata = out.data_array();
74 
75  for (unsigned int i = 0; i < ma; ++i)
76  for (unsigned int j = 0; j < nb; ++j) {
77  double accum = 0;
78  for (unsigned int k = 0; k < na; ++k)
79  accum += a[i][k] * b[k][j];
80  outdata[i][j] = accum;
81  }
82 }
83 
84 //: Compute $A^\top B$.
86 {
87  const unsigned int ma = A.rows();
88  const unsigned int mb = B.rows();
89 
90  // Verify matrices compatible
91  if (ma != mb) {
92  std::cerr << "vnl_fastops::AtB: argument sizes do not match: " << ma << " != " << mb << '\n';
93  std::abort();
94  }
95 
96  const unsigned int na = A.columns();
97  const unsigned int nb = B.columns();
98 
99  // Verify output is the right size
100  if (out.rows() != na || out.columns() != nb)
101  out.set_size(na,nb);
102 
103  double const* const* a = A.data_array();
104  double const* const* b = B.data_array();
105  double** outdata = out.data_array();
106 
107  for (unsigned int i = 0; i < na; ++i)
108  for (unsigned int j = 0; j < nb; ++j) {
109  double accum = 0;
110  for (unsigned int k = 0; k < ma; ++k)
111  accum += a[k][i] * b[k][j];
112  outdata[i][j] = accum;
113  }
114 }
115 
116 //: Compute $A^\top b$ for vector b. out may not be b.
118 {
119  const unsigned int m = A.rows();
120  const unsigned int l = B.size();
121 
122  // Verify matrices compatible
123  if (m != l) {
124  std::cerr << "vnl_fastops::AtB: argument sizes do not match: " << m << " != " << l << '\n';
125  std::abort();
126  }
127 
128  const unsigned int n = A.columns();
129 
130  // Verify output is the right size
131  if (out.size() != n)
132  out.set_size(n);
133 
134  double const* const* a = A.data_array();
135  double const* b = B.data_block();
136  double* outdata = out.data_block();
137 
138  for (unsigned int i = 0; i < n; ++i) {
139  double accum = 0;
140  for (unsigned int k = 0; k < l; ++k)
141  accum += a[k][i] * b[k];
142  outdata[i] = accum;
143  }
144 }
145 
146 //: Compute $A b$ for vector b. out may not be b.
148 {
149  const unsigned int m = A.cols();
150  const unsigned int l = b.size();
151 
152  // Verify matrices compatible
153  if (m != l) {
154  std::cerr << "vnl_fastops::Ab: argument sizes do not match: " << m << " != " << l << '\n';
155  std::abort();
156  }
157 
158  const unsigned int n = A.rows();
159 
160  // Verify output is the right size
161  if (out.size() != n)
162  out.set_size(n);
163 
164  double const* const* a = A.data_array();
165  double const* bb = b.data_block();
166  double* outdata = out.data_block();
167 
168  for (unsigned int i = 0; i < n; ++i) {
169  double accum = 0;
170  for (unsigned int k = 0; k < l; ++k)
171  accum += a[i][k] * bb[k];
172  outdata[i] = accum;
173  }
174 }
175 
176 //: Compute $A B^\top$.
178 {
179  const unsigned int na = A.columns();
180  const unsigned int nb = B.columns();
181 
182  // Verify matrices compatible
183  if (na != nb) {
184  std::cerr << "vnl_fastops::ABt: argument sizes do not match: " << na << " != " << nb << '\n';
185  std::abort();
186  }
187 
188  const unsigned int ma = A.rows();
189  const unsigned int mb = B.rows();
190 
191  // Verify output is the right size
192  if (out.rows() != ma || out.columns() != mb)
193  out.set_size(ma,mb);
194 
195  double const* const* a = A.data_array();
196  double const* const* b = B.data_array();
197  double** outdata = out.data_array();
198 
199  for (unsigned int i = 0; i < ma; ++i)
200  for (unsigned int j = 0; j < mb; ++j) {
201  double accum = 0;
202  for (unsigned int k = 0; k < na; ++k)
203  accum += a[i][k] * b[j][k];
204  outdata[i][j] = accum;
205  }
206 }
207 
208 //: Compute $A B A^\top$.
210 {
211  const unsigned int na = A.columns();
212  const unsigned int mb = B.rows();
213 
214  // Verify matrices compatible
215  if (na != mb) {
216  std::cerr << "vnl_fastops::ABAt: argument sizes do not match: " << na << " != " << mb << '\n';
217  std::abort();
218  }
219 
220  const unsigned int ma = A.rows();
221  const unsigned int nb = B.columns();
222 
223  // Verify matrices compatible
224  if (na != nb) {
225  std::cerr << "vnl_fastops::ABAt: argument sizes do not match: " << na << " != " << nb << '\n';
226  std::abort();
227  }
228 
229  // Verify output is the right size
230  if (out.rows() != ma || out.columns() != ma)
231  out.set_size(ma,mb);
232 
233 
234  double const* const* a = A.data_array();
235  double const* const* b = B.data_array();
236  double** outdata = out.data_array();
237 
238  // initialize
239  for (unsigned int i = 0; i < ma; ++i)
240  for (unsigned int w = 0; w < ma; ++w)
241  outdata[i][w] = 0.0;
242 
243  for (unsigned int i = 0; i < ma; ++i)
244  for (unsigned int j = 0; j < nb; ++j) {
245  double accum = 0;
246  for (unsigned int k = 0; k < na; ++k)
247  accum += a[i][k] * b[k][j];
248  for (unsigned int w = 0; w < ma; ++w)
249  outdata[i][w] += accum * a[w][j];
250  }
251 }
252 
253 //: Compute $b^\top A b$ for vector b and matrix A
255 {
256  const unsigned int m = A.rows();
257  const unsigned int n = A.cols();
258  const unsigned int l = b.size();
259 
260  // Verify matrices compatible
261  if (m != l ) {
262  std::cerr << "vnl_fastops::btAb: argument sizes do not match: " << m << " != " << l << '\n';
263  std::abort();
264  }
265  if ( m != n ) {
266  std::cerr << "vnl_fastops::btAb: not a square matrix: " << m << " != " << n << '\n';
267  std::abort();
268  }
269 
270 
271  double const* const* a = A.data_array();
272  double const* bb = b.data_block();
273 
274  double accum = 0;
275  for (unsigned int i = 0; i < n; ++i)
276  for (unsigned int j = 0; j < n; ++j) {
277  accum += bb[j] * a[i][j] * bb[i];
278  }
279  return accum;
280 }
281 
282 //: Compute $ X += A^\top A$
284 {
285  const unsigned int m = X.rows();
286  const unsigned int n = X.columns();
287 
288  // Verify output is the right size
289  if (m != n || m != A.columns()) {
290  std::cerr << "vnl_fastops::inc_X_by_AtA: argument sizes do not match\n";
291  std::abort();
292  }
293 
294  const unsigned int l = A.rows();
295 
296  double const* const* a = A.data_array();
297  double** x = X.data_array();
298 
299  if (l == 2) {
300  for (unsigned int i = 0; i < n; ++i) {
301  x[i][i] += (a[0][i] * a[0][i] + a[1][i] * a[1][i]);
302  for (unsigned int j = i+1; j < n; ++j) {
303  double accum = (a[0][i] * a[0][j] + a[1][i] * a[1][j]);
304  x[i][j] += accum;
305  x[j][i] += accum;
306  }
307  }
308  } else {
309  for (unsigned int i = 0; i < n; ++i)
310  for (unsigned int j = i; j < n; ++j) {
311  double accum = 0;
312  for (unsigned int k = 0; k < l; ++k)
313  accum += a[k][i] * a[k][j];
314  x[i][j] += accum;
315  if (i != j)
316  x[j][i] += accum;
317  }
318  }
319 }
320 
321 //: Compute $X += A B$
323 {
324  const unsigned int na = A.columns();
325  const unsigned int mb = B.rows();
326 
327  // Verify matrices compatible
328  if (na != mb) {
329  std::cerr << "vnl_fastops::inc_X_by_AB: argument sizes do not match: " << na << " != " << mb << '\n';
330  std::abort();
331  }
332 
333  const unsigned int ma = A.rows();
334  const unsigned int nb = B.columns();
335  const unsigned int mx = X.rows();
336  const unsigned int nx = X.columns();
337 
338  // Verify output is the right size
339  if (mx != ma || nx != nb) {
340  std::cerr << "vnl_fastops::inc_X_by_AB: argument sizes do not match\n";
341  std::abort();
342  }
343 
344  double const* const* a = A.data_array();
345  double const* const* b = B.data_array();
346  double** x = X.data_array();
347 
348  for (unsigned int i = 0; i < ma; ++i)
349  for (unsigned int j = 0; j < nb; ++j)
350  for (unsigned int k = 0; k < na; ++k)
351  x[i][j] += a[i][k] * b[k][j];
352 }
353 
354 //: Compute $X -= A B$
356 {
357  const unsigned int na = A.columns();
358  const unsigned int mb = B.rows();
359 
360  // Verify matrices compatible
361  if (na != mb) {
362  std::cerr << "vnl_fastops::dec_X_by_AB: argument sizes do not match: " << na << " != " << mb << '\n';
363  std::abort();
364  }
365 
366  const unsigned int ma = A.rows();
367  const unsigned int nb = B.columns();
368  const unsigned int mx = X.rows();
369  const unsigned int nx = X.columns();
370 
371  // Verify output is the right size
372  if (mx != ma || nx != nb) {
373  std::cerr << "vnl_fastops::dec_X_by_AB: argument sizes do not match\n";
374  std::abort();
375  }
376 
377  double const* const* a = A.data_array();
378  double const* const* b = B.data_array();
379  double** x = X.data_array();
380 
381  for (unsigned int i = 0; i < ma; ++i)
382  for (unsigned int j = 0; j < nb; ++j)
383  for (unsigned int k = 0; k < na; ++k)
384  x[i][j] -= a[i][k] * b[k][j];
385 }
386 
387 //: Compute $X += A^\top B$
389 {
390  const unsigned int ma = A.rows();
391  const unsigned int mb = B.rows();
392 
393  // Verify matrices compatible
394  if (ma != mb) {
395  std::cerr << "vnl_fastops::inc_X_by_AtB: argument sizes do not match: " << ma << " != " << mb << '\n';
396  std::abort();
397  }
398 
399  const unsigned int na = A.columns();
400  const unsigned int nb = B.columns();
401  const unsigned int mx = X.rows();
402  const unsigned int nx = X.columns();
403 
404  // Verify output is the right size
405  if (mx != na || nx != nb) {
406  std::cerr << "vnl_fastops::inc_X_by_AtB: argument sizes do not match\n";
407  std::abort();
408  }
409 
410  double const* const* a = A.data_array();
411  double const* const* b = B.data_array();
412  double** x = X.data_array();
413 
414  for (unsigned int i = 0; i < na; ++i)
415  for (unsigned int j = 0; j < nb; ++j) {
416  double accum = 0;
417  for (unsigned int k = 0; k < ma; ++k)
418  accum += a[k][i] * b[k][j];
419  x[i][j] += accum;
420  }
421 }
422 
423 //: Compute $X -= A^\top B$
425 {
426  const unsigned int ma = A.rows();
427  const unsigned int mb = B.rows();
428 
429  // Verify matrices compatible
430  if (ma != mb) {
431  std::cerr << "vnl_fastops::dec_X_by_AtB: argument sizes do not match: " << ma << " != " << mb << '\n';
432  std::abort();
433  }
434 
435  const unsigned int na = A.columns();
436  const unsigned int nb = B.columns();
437  const unsigned int mx = X.rows();
438  const unsigned int nx = X.columns();
439 
440  // Verify output is the right size
441  if (mx != na || nx != nb) {
442  std::cerr << "vnl_fastops::dec_X_by_AtB: argument sizes do not match\n";
443  std::abort();
444  }
445 
446  double const* const* a = A.data_array();
447  double const* const* b = B.data_array();
448  double** x = X.data_array();
449 
450  for (unsigned int i = 0; i < na; ++i)
451  for (unsigned int j = 0; j < nb; ++j) {
452  double accum = 0;
453  for (unsigned int k = 0; k < ma; ++k)
454  accum += a[k][i] * b[k][j];
455  x[i][j] -= accum;
456  }
457 }
458 
459 //: Compute $X += A^\top b$
461 {
462  const unsigned int ma = A.rows();
463  const unsigned int mb = B.size();
464 
465  // Verify matrices compatible
466  if (ma != mb) {
467  std::cerr << "vnl_fastops::inc_X_by_AtB: argument sizes do not match: " << ma << " != " << mb << '\n';
468  std::abort();
469  }
470 
471  const unsigned int mx = X.size();
472  const unsigned int na = A.columns();
473 
474  // Verify output is the right size
475  if (mx != na) {
476  std::cerr << "vnl_fastops::inc_X_by_AtB: argument sizes do not match\n";
477  std::abort();
478  }
479 
480  double const* const* a = A.data_array();
481  double const* b = B.data_block();
482  double* x = X.data_block();
483 
484  for (unsigned int i = 0; i < na; ++i) {
485  double accum = 0;
486  for (unsigned int k = 0; k < ma; ++k)
487  accum += a[k][i] * b[k];
488  x[i] += accum;
489  }
490 }
491 
492 //: Compute $X -= A^\top b$
494 {
495  const unsigned int ma = A.rows();
496  const unsigned int mb = B.size();
497 
498  // Verify matrices compatible
499  if (ma != mb) {
500  std::cerr << "vnl_fastops::dec_X_by_AtB: argument sizes do not match: " << ma << " != " << mb << '\n';
501  std::abort();
502  }
503 
504  const unsigned int mx = X.size();
505  const unsigned int na = A.columns();
506 
507  // Verify output is the right size
508  if (mx != na) {
509  std::cerr << "vnl_fastops::dec_X_by_AtB: argument sizes do not match\n";
510  std::abort();
511  }
512 
513  double const* const* a = A.data_array();
514  double const* b = B.data_block();
515  double* x = X.data_block();
516 
517  for (unsigned int i = 0; i < na; ++i) {
518  double accum = 0;
519  for (unsigned int k = 0; k < ma; ++k)
520  accum += a[k][i] * b[k];
521  x[i] -= accum;
522  }
523 }
524 
525 //: Compute $ X -= A^\top A$
527 {
528  const unsigned int m = X.rows();
529  const unsigned int n = X.columns();
530 
531  // Verify output is the right size
532  if (m != n || m != A.columns()) {
533  std::cerr << "vnl_fastops::dec_X_by_AtA: argument sizes do not match\n";
534  std::abort();
535  }
536 
537  const unsigned int l = A.rows();
538 
539  double const* const* a = A.data_array();
540  double** x = X.data_array();
541 
542  if (l == 2) {
543  for (unsigned int i = 0; i < n; ++i) {
544  x[i][i] -= (a[0][i] * a[0][i] + a[1][i] * a[1][i]);
545  for (unsigned int j = i+1; j < n; ++j) {
546  double accum = (a[0][i] * a[0][j] + a[1][i] * a[1][j]);
547  x[i][j] -= accum;
548  x[j][i] -= accum;
549  }
550  }
551  } else {
552  for (unsigned int i = 0; i < n; ++i)
553  for (unsigned int j = i; j < n; ++j) {
554  double accum = 0;
555  for (unsigned int k = 0; k < l; ++k)
556  accum += a[k][i] * a[k][j];
557  x[i][j] -= accum;
558  if (i != j)
559  x[j][i] -= accum;
560  }
561  }
562 }
563 
564 //: Compute dot product of a and b
565 double vnl_fastops::dot(const double* a, const double* b, unsigned int n)
566 {
567 #define METHOD 3 // Method 2 is fastest on the u170 -- weird.
568  double accum = 0;
569 #if METHOD == 1
570  const double* aend = a + n;
571  while (a != aend)
572  accum += *a++ * *b++;
573 #endif
574 #if METHOD == 2
575  for (unsigned int k = 0; k < n; ++k)
576  accum += a[k] * b[k];
577 #endif
578 #if METHOD == 3
579  while (n--)
580  accum += a[n] * b[n];
581 #endif
582 #if METHOD == 4
583  unsigned int k = n;
584  while (k > 0)
585  --k, accum += a[k] * b[k];
586 #endif
587  return accum;
588 #undef METHOD
589 }
590 
591 //: Compute $X += A B^\top$
593 {
594  const unsigned int na = A.columns();
595  const unsigned int nb = B.columns();
596 
597  // Verify matrices compatible
598  if (na != nb) {
599  std::cerr << "vnl_fastops::inc_X_by_ABt: argument sizes do not match: " << na << " != " << nb << '\n';
600  std::abort();
601  }
602 
603  const unsigned int mx = X.rows();
604  const unsigned int nx = X.columns();
605  const unsigned int ma = A.rows();
606  const unsigned int mb = B.rows();
607 
608  // Verify output is the right size
609  if (mx != ma || nx != mb) {
610  std::cerr << "vnl_fastops::inc_X_by_ABt: argument sizes do not match\n";
611  std::abort();
612  }
613 
614  double const* const* a = A.data_array();
615  double const* const* b = B.data_array();
616  double** x = X.data_array();
617 
618  if (na == 3) {
619  for (unsigned int i = 0; i < mb; ++i)
620  for (unsigned int j = 0; j < ma; ++j)
621  x[j][i] += (a[j][0] * b[i][0] +
622  a[j][1] * b[i][1] +
623  a[j][2] * b[i][2]);
624  } else if (na == 2) {
625  for (unsigned int i = 0; i < mb; ++i)
626  for (unsigned int j = 0; j < ma; ++j)
627  x[j][i] += (a[j][0] * b[i][0] +
628  a[j][1] * b[i][1]);
629  } else if (na == 1) {
630  for (unsigned int i = 0; i < mb; ++i)
631  for (unsigned int j = 0; j < ma; ++j)
632  x[j][i] += a[j][0] * b[i][0];
633  } else {
634  for (unsigned int i = 0; i < mb; ++i)
635  for (unsigned int j = 0; j < ma; ++j)
636  x[j][i] += dot(a[j], b[i], na);
637  }
638 }
639 
640 //: Compute $X -= A B^\top$
642 {
643  const unsigned int na = A.columns();
644  const unsigned int nb = B.columns();
645 
646  // Verify matrices compatible
647  if (na != nb) {
648  std::cerr << "vnl_fastops::dec_X_by_ABt: argument sizes do not match: " << na << " != " << nb << '\n';
649  std::abort();
650  }
651 
652  const unsigned int mx = X.rows();
653  const unsigned int nx = X.columns();
654  const unsigned int ma = A.rows();
655  const unsigned int mb = B.rows();
656 
657  // Verify output is the right size
658  if (mx != ma || nx != mb) {
659  std::cerr << "vnl_fastops::dec_X_by_ABt: argument sizes do not match\n";
660  std::abort();
661  }
662 
663  double const* const* a = A.data_array();
664  double const* const* b = B.data_array();
665  double** x = X.data_array();
666 
667  if (na == 3) {
668  for (unsigned int i = 0; i < mb; ++i)
669  for (unsigned int j = 0; j < ma; ++j)
670  x[j][i] -= (a[j][0] * b[i][0] +
671  a[j][1] * b[i][1] +
672  a[j][2] * b[i][2]);
673  } else if (na == 2) {
674  for (unsigned int i = 0; i < mb; ++i)
675  for (unsigned int j = 0; j < ma; ++j)
676  x[j][i] -= (a[j][0] * b[i][0] +
677  a[j][1] * b[i][1]);
678  } else if (na == 1) {
679  for (unsigned int i = 0; i < mb; ++i)
680  for (unsigned int j = 0; j < ma; ++j)
681  x[j][i] -= a[j][0] * b[i][0];
682  } else {
683  for (unsigned int i = 0; i < mb; ++i)
684  for (unsigned int j = 0; j < ma; ++j)
685  x[j][i] -= dot(a[j], b[i], na);
686  }
687 }
688 
689 
690 //: Compute $X += A B A^\top$.
692 {
693  const unsigned int na = A.columns();
694  const unsigned int mb = B.rows();
695 
696  // Verify matrices compatible
697  if (na != mb) {
698  std::cerr << "vnl_fastops::ABAt: argument sizes do not match: " << na << " != " << mb << '\n';
699  std::abort();
700  }
701 
702  const unsigned int ma = A.rows();
703  const unsigned int nb = B.columns();
704 
705  // Verify matrices compatible
706  if (na != nb) {
707  std::cerr << "vnl_fastops::ABAt: argument sizes do not match: " << na << " != " << nb << '\n';
708  std::abort();
709  }
710 
711  // Verify output is the right size
712  if (X.rows() != ma || X.columns() != ma)
713  X.set_size(ma,mb);
714 
715 
716  double const* const* a = A.data_array();
717  double const* const* b = B.data_array();
718  double** Xdata = X.data_array();
719 
720  for (unsigned int i = 0; i < ma; ++i)
721  for (unsigned int j = 0; j < nb; ++j) {
722  double accum = 0;
723  for (unsigned int k = 0; k < na; ++k)
724  accum += a[i][k] * b[k][j];
725  for (unsigned int w = 0; w < ma; ++w)
726  Xdata[i][w] += accum * a[w][j];
727  }
728 }
unsigned int cols() const
Return the number of columns.
Definition: vnl_matrix.h:183
static double dot(const double *a, const double *b, unsigned int n)
Compute dot product of a and b.
static void dec_X_by_AB(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X -= A B$.
bool set_size(size_t n)
Resize to n elements.
Definition: vnl_vector.hxx:250
static void AB(vnl_matrix< double > &out, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute AxB.
Definition: vnl_fastops.cxx:52
#define m
Definition: vnl_vector.h:43
static void inc_X_by_AtB(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X += A^\top B$.
size_t size() const
Return the length, number of elements, dimension of this vector.
Definition: vnl_vector.h:126
T const * data_block() const
Access the contiguous block storing the elements in the vector. O(1).
Definition: vnl_vector.h:230
static double btAb(const vnl_matrix< double > &A, const vnl_vector< double > &b)
Compute $b^\top A b$ for vector b and matrix A.
static void inc_X_by_ABt(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X += A B^\top$.
static void AtA(vnl_matrix< double > &out, const vnl_matrix< double > &A)
Compute $A^\top A$.
Definition: vnl_fastops.cxx:14
static void AtB(vnl_matrix< double > &out, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $A^\top B$.
Definition: vnl_fastops.cxx:84
Collection of C-style matrix functions.
static void dec_X_by_AtA(vnl_matrix< double > &X, const vnl_matrix< double > &A)
Compute $ X -= A^\top A$.
static void inc_X_by_AB(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X += A B$.
static void Ab(vnl_vector< double > &out, const vnl_matrix< double > &A, const vnl_vector< double > &b)
Compute $A b$ for vector b. out may not be b.
static void dec_X_by_AtB(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X -= A^\top B$.
static void inc_X_by_ABAt(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X += A B A^\top$.
static void ABAt(vnl_matrix< double > &out, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $A B A^\top$.
T const *const * data_array() const
Access the 2D array, so that elements can be accessed with array[row][col] directly.
Definition: vnl_matrix.h:609
unsigned int rows() const
Return the number of rows.
Definition: vnl_matrix.h:179
bool set_size(unsigned r, unsigned c)
Resize to r rows by c columns. Old data lost.
Definition: vnl_matrix.hxx:390
static void inc_X_by_AtA(vnl_matrix< double > &X, const vnl_matrix< double > &A)
Compute $ X += A^\top A$.
unsigned int columns() const
Return the number of columns.
Definition: vnl_matrix.h:187
static void ABt(vnl_matrix< double > &out, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $A B^\top$.
static void dec_X_by_ABt(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X -= A B^\top$.