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