Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
MnMatrix.cxx
Go to the documentation of this file.
1// @(#)root/minuit2:$Id$
2// Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005
3
4/**********************************************************************
5 * *
6 * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT *
7 * *
8 **********************************************************************/
9
10#include <Minuit2/MnMatrix.h>
11
12#include <cmath>
13#include <numeric>
14
15constexpr int PRECISION = 10;
16constexpr int WIDTH = PRECISION + 7;
17
18namespace {
19
20/** Inverts a symmetric matrix. Matrix is first scaled to have all ones on
21 the diagonal (equivalent to change of units) but no pivoting is done
22 since matrix is positive-definite.
23 */
24
26{
27 unsigned int nrow = a.Nrow();
31
32 for (unsigned int i = 0; i < nrow; i++) {
33 double si = a(i, i);
34 if (si < 0.)
35 return 1;
36 s(i) = 1. / std::sqrt(si);
37 }
38
39 for (unsigned int i = 0; i < nrow; i++)
40 for (unsigned int j = i; j < nrow; j++)
41 a(i, j) *= (s(i) * s(j));
42
43 for (unsigned i = 0; i < nrow; i++) {
44 unsigned int k = i;
45 if (a(k, k) == 0.)
46 return 1;
47 q(k) = 1. / a(k, k);
48 pp(k) = 1.;
49 a(k, k) = 0.;
50 unsigned int kp1 = k + 1;
51 if (k != 0) {
52 for (unsigned int j = 0; j < k; j++) {
53 pp(j) = a(j, k);
54 q(j) = a(j, k) * q(k);
55 a(j, k) = 0.;
56 }
57 }
58 if (k != nrow - 1) {
59 for (unsigned int j = kp1; j < nrow; j++) {
60 pp(j) = a(k, j);
61 q(j) = -a(k, j) * q(k);
62 a(k, j) = 0.;
63 }
64 }
65 // Loop over the packed storage in memory order: element (j, k) with j <= k is at j + k * (k + 1) / 2.
66 double *data = a.Data();
67 for (k = 0; k < nrow; k++) {
68 double *col = data + k * (k + 1) / 2;
69 for (unsigned int j = 0; j <= k; j++)
70 col[j] += (pp(j) * q(k));
71 }
72 }
73
74 for (unsigned int j = 0; j < nrow; j++)
75 for (unsigned int k = j; k < nrow; k++)
76 a(j, k) *= (s(j) * s(k));
77
78 return 0;
79}
80
81} // namespace
82
83namespace ROOT {
84
85namespace Minuit2 {
86
87inline double sum_of_elements(double const *arr, unsigned int n)
88{
89 double out = 0.0;
90 for (unsigned int i = 0; i < n; ++i) {
91 out += std::abs(arr[i]);
92 }
93 return out;
94}
95
97{
98 // calculate the absolute sum of the vector elements
99 return sum_of_elements(v.Data(), v.size());
100}
101
103{
104 // calculate the absolute sum of all the matrix elements
105 return sum_of_elements(m.Data(), m.size());
106}
107
108// Updates A := alpha*x*x' + A, where ap stores the upper triangle of A
109void mndspr(unsigned int n, double alpha, const double *x, double *ap)
110{
111 /* System generated locals */
112 int i__1, i__2;
113
114 /* Local variables */
115 double temp;
116 int i__, j, k;
117 int kk;
118
119 /* Parameter adjustments */
120 --ap;
121 --x;
122
123 /* Quick return if possible. */
124
125 if (n == 0 || alpha == 0.) {
126 return;
127 }
128
129 /* Start the operations. In this version the Elements of the array AP */
130 /* are accessed sequentially with one pass through AP. */
131
132 kk = 1;
133
134 /* Form A when Upper triangle is stored in AP. */
135
136 i__1 = n;
137 for (j = 1; j <= i__1; ++j) {
138 if (x[j] != 0.) {
139 temp = alpha * x[j];
140 k = kk;
141 i__2 = j;
142 for (i__ = 1; i__ <= i__2; ++i__) {
143 ap[k] += x[i__] * temp;
144 ++k;
145 }
146 }
147 kk += j;
148 }
149}
150
151// Updates y := alpha*A*x + beta*y, where ap stores the upper triangle of A
152void Mndspmv(unsigned int n, double alpha, const double *ap, const double *x, double beta, double *y)
153{
154 /* System generated locals */
155 int i__1, i__2;
156
157 /* Local variables */
158 double temp1, temp2;
159 int i__, j, k;
160 int kk;
161
162 /* Parameter adjustments */
163 --y;
164 --x;
165 --ap;
166
167 /* Quick return if possible. */
168
169 if ((n == 0) || (alpha == 0. && beta == 1.)) {
170 return;
171 }
172
173 /* Set up the start points in X and Y. */
174
175 /* Start the operations. In this version the Elements of the array AP */
176 /* are accessed sequentially with one pass through AP. */
177
178 /* First form y := beta*y. */
179
180 if (beta != 1.) {
181 if (beta == 0.) {
182 i__1 = n;
183 for (i__ = 1; i__ <= i__1; ++i__) {
184 y[i__] = 0.;
185 /* L10: */
186 }
187 } else {
188 i__1 = n;
189 for (i__ = 1; i__ <= i__1; ++i__) {
190 y[i__] = beta * y[i__];
191 /* L20: */
192 }
193 }
194 }
195 if (alpha == 0.) {
196 return;
197 }
198 kk = 1;
199
200 /* Form y when AP contains the Upper triangle. */
201
202 i__1 = n;
203 for (j = 1; j <= i__1; ++j) {
204 temp1 = alpha * x[j];
205 temp2 = 0.;
206 k = kk;
207 i__2 = j - 1;
208 for (i__ = 1; i__ <= i__2; ++i__) {
209 y[i__] += temp1 * ap[k];
210 temp2 += ap[k] * x[i__];
211 ++k;
212 }
213 y[j] = y[j] + temp1 * ap[kk + j - 1] + alpha * temp2;
214 kk += j;
215 }
216}
217
219 : fSize(0), fNRow(0), fData(nullptr)
220{
221 // constructor from expression based on outer product of symmetric matrices
222 // std::cout<<"LASymMatrix::LASymMatrix(const ABObj<sym, VectorOuterProduct<ABObj<vec, LAVector, double>, double>,
223 // double>& out)"<<std::endl;
224 fNRow = out.Obj().Obj().Obj().size();
225 fSize = fNRow * (fNRow + 1) / 2;
226 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
227 memset(fData, 0, fSize * sizeof(double));
228 Outer_prod(*this, out.Obj().Obj().Obj(), out.f() * out.Obj().Obj().f() * out.Obj().Obj().f());
229}
230
233{
234 // assignment operator from expression based on outer product of symmetric matrices
235 // std::cout<<"LASymMatrix& LASymMatrix::operator=(const ABObj<sym, VectorOuterProduct<ABObj<vec, LAVector,
236 // double>, double>, double>& out)"<<std::endl;
237 if (fSize == 0 && fData == nullptr) {
238 fNRow = out.Obj().Obj().Obj().size();
239 fSize = fNRow * (fNRow + 1) / 2;
240 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
241 memset(fData, 0, fSize * sizeof(double));
242 Outer_prod(*this, out.Obj().Obj().Obj(), out.f() * out.Obj().Obj().f() * out.Obj().Obj().f());
243 } else {
244 LASymMatrix tmp(out.Obj().Obj().Obj().size());
245 Outer_prod(tmp, out.Obj().Obj().Obj());
246 tmp *= double(out.f() * out.Obj().Obj().f() * out.Obj().Obj().f());
247 assert(fSize == tmp.size());
248 memcpy(fData, tmp.Data(), fSize * sizeof(double));
249 }
250 return *this;
251}
252
253void Outer_prod(LASymMatrix &A, const LAVector &v, double f)
254{
255 // function performing outer product and adding it to A
256 mndspr(v.size(), f, v.Data(), A.Data());
257}
258
259void Mndaxpy(unsigned int n, double da, const double *dx, double *dy)
260{
261 /* System generated locals */
262 int i__1;
263
264 /* Local variables */
265 int i__, m, mp1;
266
267 /* Parameter adjustments */
268 --dy;
269 --dx;
270
271 /* Function Body */
272 if (n <= 0) {
273 return;
274 }
275 if (da == 0.) {
276 return;
277 }
278 m = n % 4;
279 if (m != 0) {
280 i__1 = m;
281 for (i__ = 1; i__ <= i__1; ++i__) {
282 dy[i__] += da * dx[i__];
283 }
284 if (n < 4) {
285 return;
286 }
287 }
288 mp1 = m + 1;
289 i__1 = n;
290 for (i__ = mp1; i__ <= i__1; i__ += 4) {
291 dy[i__] += da * dx[i__];
292 dy[i__ + 1] += da * dx[i__ + 1];
293 dy[i__ + 2] += da * dx[i__ + 2];
294 dy[i__ + 3] += da * dx[i__ + 3];
295 }
296}
297
298// symmetric matrix (positive definite only)
299
301{
302 // function for inversion of symmetric matrices using mnvert function
303 // (from Fortran Minuit)
304
305 int ifail = 0;
306
307 if (t.size() == 1) {
308 double tmp = t.Data()[0];
309 if (!(tmp > 0.))
310 ifail = 1;
311 else
312 t.Data()[0] = 1. / tmp;
313 } else {
314 ifail = mnvert(t);
315 }
316
317 return ifail;
318}
319
320double inner_product(const LAVector &v1, const LAVector &v2)
321{
322 // calculate inner (dot) product of two vectors
323 return std::inner_product(v1.Data(), v1.Data() + v1.size(), v2.Data(), 0.0);
324}
325
326int mneigen(double *a, unsigned int ndima, unsigned int n, unsigned int mits, double *work)
327{
328 constexpr double precis = 1.e-6;
329
330 // compute matrix eignevalues (translation from mneig.F of Minuit)
331
332 /* System generated locals */
333 unsigned int a_dim1, a_offset, i__1, i__2, i__3;
334 double r__1, r__2;
335
336 /* Local variables */
337 double b, c__, f, h__;
338 unsigned int i__, j, k, l, m = 0;
339 double r__, s;
340 unsigned int i0, i1, j1, m1, n1;
341 double hh, gl, pr, pt;
342
343 /* PRECIS is the machine precision EPSMAC */
344 /* Parameter adjustments */
345 a_dim1 = ndima;
346 a_offset = 1 + a_dim1 * 1;
347 a -= a_offset;
348 --work;
349
350 /* Function Body */
351 int ifault = 1;
352
353 i__ = n;
354 i__1 = n;
355 for (i1 = 2; i1 <= i__1; ++i1) {
356 l = i__ - 2;
357 f = a[i__ + (i__ - 1) * a_dim1];
358 gl = (double)0.;
359
360 if (l < 1) {
361 goto L25;
362 }
363
364 i__2 = l;
365 for (k = 1; k <= i__2; ++k) {
366 /* Computing 2nd power */
367 r__1 = a[i__ + k * a_dim1];
368 gl += r__1 * r__1;
369 }
370 L25:
371 /* Computing 2nd power */
372 r__1 = f;
373 h__ = gl + r__1 * r__1;
374
375 if (gl > (double)1e-35) {
376 goto L30;
377 }
378
379 work[i__] = (double)0.;
380 work[n + i__] = f;
381 goto L65;
382 L30:
383 ++l;
384
385 gl = std::sqrt(h__);
386
387 if (f >= (double)0.) {
388 gl = -gl;
389 }
390
391 work[n + i__] = gl;
392 h__ -= f * gl;
393 a[i__ + (i__ - 1) * a_dim1] = f - gl;
394 f = (double)0.;
395 i__2 = l;
396 for (j = 1; j <= i__2; ++j) {
397 a[j + i__ * a_dim1] = a[i__ + j * a_dim1] / h__;
398 gl = (double)0.;
399 i__3 = j;
400 for (k = 1; k <= i__3; ++k) {
401 gl += a[j + k * a_dim1] * a[i__ + k * a_dim1];
402 }
403
404 if (j >= l) {
405 goto L47;
406 }
407
408 j1 = j + 1;
409 i__3 = l;
410 for (k = j1; k <= i__3; ++k) {
411 gl += a[k + j * a_dim1] * a[i__ + k * a_dim1];
412 }
413 L47:
414 work[n + j] = gl / h__;
415 f += gl * a[j + i__ * a_dim1];
416 }
417 hh = f / (h__ + h__);
418 i__2 = l;
419 for (j = 1; j <= i__2; ++j) {
420 f = a[i__ + j * a_dim1];
421 gl = work[n + j] - hh * f;
422 work[n + j] = gl;
423 i__3 = j;
424 for (k = 1; k <= i__3; ++k) {
425 a[j + k * a_dim1] = a[j + k * a_dim1] - f * work[n + k] - gl * a[i__ + k * a_dim1];
426 }
427 }
428 work[i__] = h__;
429 L65:
430 --i__;
431 }
432 work[1] = (double)0.;
433 work[n + 1] = (double)0.;
434 i__1 = n;
435 for (i__ = 1; i__ <= i__1; ++i__) {
436 l = i__ - 1;
437
438 if (work[i__] == (double)0. || l == 0) {
439 goto L100;
440 }
441
442 i__3 = l;
443 for (j = 1; j <= i__3; ++j) {
444 gl = (double)0.;
445 i__2 = l;
446 for (k = 1; k <= i__2; ++k) {
447 gl += a[i__ + k * a_dim1] * a[k + j * a_dim1];
448 }
449 i__2 = l;
450 for (k = 1; k <= i__2; ++k) {
451 a[k + j * a_dim1] -= gl * a[k + i__ * a_dim1];
452 }
453 }
454 L100:
455 work[i__] = a[i__ + i__ * a_dim1];
456 a[i__ + i__ * a_dim1] = (double)1.;
457
458 if (l == 0) {
459 goto L110;
460 }
461
462 i__2 = l;
463 for (j = 1; j <= i__2; ++j) {
464 a[i__ + j * a_dim1] = (double)0.;
465 a[j + i__ * a_dim1] = (double)0.;
466 }
467 L110:;
468 }
469
470 n1 = n - 1;
471 i__1 = n;
472 for (i__ = 2; i__ <= i__1; ++i__) {
473 i0 = n + i__ - 1;
474 work[i0] = work[i0 + 1];
475 }
476 work[n + n] = (double)0.;
477 b = (double)0.;
478 f = (double)0.;
479 i__1 = n;
480 for (l = 1; l <= i__1; ++l) {
481 j = 0;
482 h__ = precis * ((r__1 = work[l], std::fabs(r__1)) + (r__2 = work[n + l], std::fabs(r__2)));
483
484 if (b < h__) {
485 b = h__;
486 }
487
488 i__2 = n;
489 for (m1 = l; m1 <= i__2; ++m1) {
490 m = m1;
491
492 if ((r__1 = work[n + m], std::fabs(r__1)) <= b) {
493 goto L150;
494 }
495 }
496
497 L150:
498 if (m == l) {
499 goto L205;
500 }
501
502 L160:
503 if (j == mits) {
504 return ifault;
505 }
506
507 ++j;
508 pt = (work[l + 1] - work[l]) / (work[n + l] * (double)2.);
509 r__ = std::sqrt(pt * pt + (double)1.);
510 pr = pt + r__;
511
512 if (pt < (double)0.) {
513 pr = pt - r__;
514 }
515
516 h__ = work[l] - work[n + l] / pr;
517 i__2 = n;
518 for (i__ = l; i__ <= i__2; ++i__) {
519 work[i__] -= h__;
520 }
521 f += h__;
522 pt = work[m];
523 c__ = (double)1.;
524 s = (double)0.;
525 m1 = m - 1;
526 i__ = m;
527 i__2 = m1;
528 for (i1 = l; i1 <= i__2; ++i1) {
529 j = i__;
530 --i__;
531 gl = c__ * work[n + i__];
532 h__ = c__ * pt;
533
534 if (std::fabs(pt) >= (r__1 = work[n + i__], std::fabs(r__1))) {
535 goto L180;
536 }
537
538 c__ = pt / work[n + i__];
539 r__ = std::sqrt(c__ * c__ + (double)1.);
540 work[n + j] = s * work[n + i__] * r__;
541 s = (double)1. / r__;
542 c__ /= r__;
543 goto L190;
544 L180:
545 c__ = work[n + i__] / pt;
546 r__ = std::sqrt(c__ * c__ + (double)1.);
547 work[n + j] = s * pt * r__;
548 s = c__ / r__;
549 c__ = (double)1. / r__;
550 L190:
551 pt = c__ * work[i__] - s * gl;
552 work[j] = h__ + s * (c__ * gl + s * work[i__]);
553 i__3 = n;
554 for (k = 1; k <= i__3; ++k) {
555 h__ = a[k + j * a_dim1];
556 a[k + j * a_dim1] = s * a[k + i__ * a_dim1] + c__ * h__;
557 a[k + i__ * a_dim1] = c__ * a[k + i__ * a_dim1] - s * h__;
558 }
559 }
560 work[n + l] = s * pt;
561 work[l] = c__ * pt;
562
563 if ((r__1 = work[n + l], std::fabs(r__1)) > b) {
564 goto L160;
565 }
566
567 L205:
568 work[l] += f;
569 }
570 i__1 = n1;
571 for (i__ = 1; i__ <= i__1; ++i__) {
572 k = i__;
573 pt = work[i__];
574 i1 = i__ + 1;
575 i__3 = n;
576 for (j = i1; j <= i__3; ++j) {
577
578 if (work[j] >= pt) {
579 goto L220;
580 }
581
582 k = j;
583 pt = work[j];
584 L220:;
585 }
586
587 if (k == i__) {
588 goto L240;
589 }
590
591 work[k] = work[i__];
592 work[i__] = pt;
593 i__3 = n;
594 for (j = 1; j <= i__3; ++j) {
595 pt = a[j + i__ * a_dim1];
596 a[j + i__ * a_dim1] = a[j + k * a_dim1];
597 a[j + k * a_dim1] = pt;
598 }
599 L240:;
600 }
601 ifault = 0;
602
603 return ifault;
604} /* mneig_ */
605
607{
608 // calculate eigenvalues of symmetric matrices using mneigen function (translate from fortran Minuit)
609 unsigned int nrow = mat.Nrow();
610
611 LAVector tmp(nrow * nrow);
612 LAVector work(2 * nrow);
613
614 for (unsigned int i = 0; i < nrow; i++) {
615 for (unsigned int j = 0; j <= i; j++) {
616 tmp(i + j * nrow) = mat(i, j);
617 tmp(i * nrow + j) = mat(i, j);
618 }
619 }
620
621 int info = mneigen(tmp.Data(), nrow, nrow, work.size(), work.Data());
622 (void)info;
623 assert(info == 0);
624
625 LAVector result(nrow);
626 for (unsigned int i = 0; i < nrow; i++) {
627 result(i) = work(i);
628 }
629
630 return result;
631}
632
633double similarity(const LAVector &avec, const LASymMatrix &mat)
634{
635 // calculate the similarity vector-matrix product: V^T M V
636 // use matrix product and then dot function
637
638 LAVector tmp = mat * avec;
639
640 return std::inner_product(avec.Data(), avec.Data() + avec.size(), tmp.Data(), 0.0);
641}
642
643void Mndscal(unsigned int n, double da, double *dx)
644{
645 for (unsigned int i = 0; i < n; ++i) {
646 dx[i] *= da;
647 }
648}
649
650thread_local int gMaxNP = 10;
651
653{
654 std::swap(gMaxNP, value);
655 return value;
656}
657
659{
660 return gMaxNP;
661}
662
663std::ostream &operator<<(std::ostream &os, const LASymMatrix &matrix)
664{
665 // print a matrix
666 const int pr = os.precision(8);
667 const unsigned int nrow = matrix.Nrow();
668 const unsigned int n = std::min(nrow, static_cast<unsigned int>(MnMatrix::MaxNP()));
669 for (unsigned int i = 0; i < nrow; i++) {
670 os << "\n";
671 if (i == 0)
672 os << "[[";
673 else {
674 if (i >= n) {
675 os << "....\n";
676 i = nrow - 1;
677 }
678 os << " [";
679 }
680 for (unsigned int j = 0; j < nrow; j++) {
681 if (j >= n) {
682 os << ".... ";
683 j = nrow - 1;
684 }
685 os.width(15);
686 os << matrix(i, j);
687 }
688 os << "]";
689 }
690 os << "]]";
691 os.precision(pr);
692 return os;
693}
694
695std::ostream &operator<<(std::ostream &os, const LAVector &vec)
696{
697 // print a vector
698 const int pr = os.precision(PRECISION);
699 const unsigned int nrow = vec.size();
700 const unsigned int np = std::min(nrow, static_cast<unsigned int>(MnMatrix::MaxNP()));
701 os << "\t[";
702 for (unsigned int i = 0; i < np; i++) {
703 os.width(WIDTH);
704 os << vec(i);
705 }
706 if (np < nrow) {
707 os << ".... ";
708 os.width(WIDTH);
709 os << vec(nrow - 1);
710 }
711 os << "]\t";
712 os.precision(pr);
713 return os;
714}
715
716} // namespace Minuit2
717
718} // namespace ROOT
dim_t fSize
constexpr int PRECISION
Definition MnMatrix.cxx:15
constexpr int WIDTH
Definition MnMatrix.cxx:16
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
float * q
Class describing a symmetric matrix of size n.
Definition MnMatrix.h:438
const double * Data() const
Definition MnMatrix.h:677
LASymMatrix & operator=(const LASymMatrix &v)
Definition MnMatrix.h:476
LASymMatrix(unsigned int n)
Definition MnMatrix.h:443
unsigned int Nrow() const
Definition MnMatrix.h:683
unsigned int size() const
Definition MnMatrix.h:681
const double * Data() const
Definition MnMatrix.h:1028
unsigned int size() const
Definition MnMatrix.h:1032
static StackAllocator & Get()
Definition MnMatrix.h:239
void * Allocate(size_t nBytes)
Definition MnMatrix.h:87
TPaveText * pt
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
int SetMaxNP(int value)
Definition MnMatrix.cxx:652
void Mndaxpy(unsigned int, double, const double *, double *)
Definition MnMatrix.cxx:259
LAVector eigenvalues(const LASymMatrix &)
Definition MnMatrix.cxx:606
int Invert(LASymMatrix &)
Definition MnMatrix.cxx:300
void Mndscal(unsigned int, double, double *)
Definition MnMatrix.cxx:643
void Mndspmv(unsigned int, double, const double *, const double *, double, double *)
Definition MnMatrix.cxx:152
std::ostream & operator<<(std::ostream &, const LAVector &)
Definition MnMatrix.cxx:695
double sum_of_elements(const LASymMatrix &)
Definition MnMatrix.cxx:102
double similarity(const LAVector &, const LASymMatrix &)
Definition MnMatrix.cxx:633
int mneigen(double *a, unsigned int ndima, unsigned int n, unsigned int mits, double *work)
Definition MnMatrix.cxx:326
void Outer_prod(LASymMatrix &, const LAVector &, double f=1.)
Definition MnMatrix.cxx:253
double inner_product(const LAVector &, const LAVector &)
Definition MnMatrix.cxx:320
thread_local int gMaxNP
Definition MnMatrix.cxx:650
void mndspr(unsigned int n, double alpha, const double *x, double *ap)
Definition MnMatrix.cxx:109
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4