Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/linalg/densemat.cpp
3206 views
1
#include <mystdlib.h>
2
3
#include <linalg.hpp>
4
5
6
namespace netgen
7
{
8
DenseMatrix :: DenseMatrix ()
9
{
10
data = NULL;
11
height = 0;
12
width = 0;
13
}
14
15
DenseMatrix :: DenseMatrix (int h, int w)
16
{
17
if (!w) w = h;
18
width = w;
19
height = h;
20
if (h*w)
21
data = new double[h*w];
22
else
23
data = 0;
24
25
for (int i = 0 ; i < (h * w); i++)
26
data[i] = 0;
27
}
28
29
/*
30
DenseMatrix :: DenseMatrix (int h, int w, const double * d)
31
: BaseMatrix (h, w)
32
{
33
int size = h * w;
34
int i;
35
36
if (size)
37
{
38
data = new double[size];
39
for (i = 0; i < size; i++)
40
data[i] = d[i];
41
}
42
else
43
data = NULL;
44
}
45
*/
46
47
DenseMatrix :: DenseMatrix (const DenseMatrix & m2)
48
{
49
data = NULL; height = width = 0;
50
SetSize (m2.Height(), m2.Width());
51
memcpy (data, m2.data, sizeof(double) * Height() * Width());
52
}
53
54
DenseMatrix :: ~DenseMatrix ()
55
{
56
delete [] data;
57
}
58
59
60
void DenseMatrix :: SetSize (int h, int w)
61
{
62
if (!w) w = h;
63
if (height == h && width == w)
64
return;
65
66
height = h;
67
width = w;
68
69
delete[] data;
70
71
if (h*w)
72
data = new double[h*w];
73
else
74
data = NULL;
75
}
76
77
78
/*
79
DenseMatrix & DenseMatrix :: operator= (const BaseMatrix & m2)
80
{
81
int i, j;
82
83
SetSize (m2.Height(), m2.Width());
84
85
if (data)
86
for (i = 1; i <= Height(); i++)
87
for (j = 1; j <= Width(); j++)
88
Set (i, j, m2(i, j));
89
else
90
(*myerr) << "DenseMatrix::Operator=: Matrix not allocated" << endl;
91
92
return *this;
93
}
94
*/
95
96
97
DenseMatrix & DenseMatrix :: operator= (const DenseMatrix & m2)
98
{
99
SetSize (m2.Height(), m2.Width());
100
101
if (data) memcpy (data, m2.data, sizeof(double) * m2.Height() * m2.Width());
102
return *this;
103
}
104
105
106
DenseMatrix & DenseMatrix :: operator+= (const DenseMatrix & m2)
107
{
108
int i;
109
double * p, * q;
110
111
if (Height() != m2.Height() || Width() != m2.Width())
112
{
113
(*myerr) << "DenseMatrix::Operator+=: Sizes don't fit" << endl;
114
return *this;
115
}
116
117
if (data)
118
{
119
p = data;
120
q = m2.data;
121
for (i = Width() * Height(); i > 0; i--)
122
{
123
*p += *q;
124
p++;
125
q++;
126
}
127
}
128
else
129
(*myerr) << "DenseMatrix::Operator+=: Matrix not allocated" << endl;
130
131
return *this;
132
}
133
134
135
DenseMatrix & DenseMatrix :: operator-= (const DenseMatrix & m2)
136
{
137
int i;
138
double * p, * q;
139
140
if (Height() != m2.Height() || Width() != m2.Width())
141
{
142
(*myerr) << "DenseMatrix::Operator-=: Sizes don't fit" << endl;
143
return *this;
144
}
145
146
if (data)
147
{
148
p = data;
149
q = m2.data;
150
for (i = Width() * Height(); i > 0; i--)
151
{
152
*p -= *q;
153
p++;
154
q++;
155
}
156
}
157
else
158
(*myerr) << "DenseMatrix::Operator-=: Matrix not allocated" << endl;
159
160
return *this;
161
}
162
163
164
165
166
/*
167
double & DenseMatrix :: operator() (int i, int j)
168
{
169
if (i >= 1 && j >= 1 && i <= height && j <= width)
170
return Elem(i,j);
171
else (*myerr) << "DenseMatrix: index (" << i << "," << j << ") out of range (1.."
172
<< height << ",1.." << width << ")\n";
173
static double dummy = 0;
174
return dummy;
175
}
176
177
double DenseMatrix :: operator() (int i, int j) const
178
{
179
if (i >= 1 && j >= 1 && i <= height && j <= width)
180
return Get(i,j);
181
else (*myerr) << "DenseMatrix: index (" << i << "," << j << ") out of range (1.."
182
<< height << ",1.." << width << ")\n";
183
184
static double dummy = 0;
185
return dummy;
186
}
187
*/
188
189
DenseMatrix & DenseMatrix :: operator= (double v)
190
{
191
int i;
192
double * p = data;
193
194
if (data)
195
for (i = width*height; i > 0; i--, p++)
196
*p = v;
197
198
return *this;
199
}
200
201
202
203
DenseMatrix & DenseMatrix :: operator*= (double v)
204
{
205
int i;
206
double * p = data;
207
208
if (data)
209
for (i = width*height; i > 0; i--, p++)
210
*p *= v;
211
212
return *this;
213
}
214
215
216
double DenseMatrix :: Det () const
217
{
218
if (width != height)
219
{
220
(*myerr) << "DenseMatrix :: Det: width != height" << endl;
221
return 0;
222
}
223
224
switch (width)
225
{
226
case 1: return Get(1, 1);
227
case 2: return Get(1) * Get(4) - Get(2) * Get(3);
228
229
case 3: return Get(1) * Get(5) * Get(9)
230
+ Get(2) * Get(6) * Get(7)
231
+ Get(3) * Get(4) * Get(8)
232
- Get(1) * Get(6) * Get(8)
233
- Get(2) * Get(4) * Get(9)
234
- Get(3) * Get(5) * Get(7);
235
default:
236
{
237
(*myerr) << "Matrix :: Det: general size not implemented (size=" << width << ")" << endl;
238
return 0;
239
}
240
}
241
}
242
243
244
void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2)
245
{
246
// int i, j, k, n;
247
double det;
248
// DenseMatrix m1 = hm1;
249
250
if (m1.width != m1.height)
251
{
252
(*myerr) << "CalcInverse: matrix not symmetric" << endl;
253
return;
254
}
255
if (m1.width != m2.width || m1.height != m2.height)
256
{
257
(*myerr) << "CalcInverse: dim(m2) != dim(m1)" << endl;
258
return;
259
}
260
261
262
if (m1.Width() <= 3)
263
{
264
det = m1.Det();
265
if (det == 0)
266
{
267
(*myerr) << "CalcInverse: Matrix singular" << endl;
268
return;
269
}
270
271
det = 1e0 / det;
272
switch (m1.width)
273
{
274
case 1:
275
{
276
m2.Set(1, 1, det);
277
return;
278
}
279
case 2:
280
{
281
m2.Set(1, 1, det * m1.Get(4));
282
m2.Set(2, 2, det * m1.Get(1));
283
m2.Set(1, 2, - det * m1.Get(2));
284
m2.Set(2, 1, - det * m1.Get(3));
285
return;
286
}
287
case 3:
288
{
289
m2.Set(1, 1, det * (m1.Get(5) * m1.Get(9) - m1.Get(6) * m1.Get(8)));
290
m2.Set(2, 1, -det * (m1.Get(4) * m1.Get(9) - m1.Get(6) * m1.Get(7)));
291
m2.Set(3, 1, det * (m1.Get(4) * m1.Get(8) - m1.Get(5) * m1.Get(7)));
292
293
m2.Set(1, 2, -det * (m1.Get(2) * m1.Get(9) - m1.Get(3) * m1.Get(8)));
294
m2.Set(2, 2, det * (m1.Get(1) * m1.Get(9) - m1.Get(3) * m1.Get(7)));
295
m2.Set(3, 2, -det * (m1.Get(1) * m1.Get(8) - m1.Get(2) * m1.Get(7)));
296
297
m2.Set(1, 3, det * (m1.Get(2) * m1.Get(6) - m1.Get(3) * m1.Get(5)));
298
m2.Set(2, 3, -det * (m1.Get(1) * m1.Get(6) - m1.Get(3) * m1.Get(4)));
299
m2.Set(3, 3, det * (m1.Get(1) * m1.Get(5) - m1.Get(2) * m1.Get(4)));
300
return;
301
}
302
}
303
}
304
305
else
306
{
307
int i, j, k, n;
308
n = m1.Height();
309
310
311
#ifdef CHOL
312
int dots = (n > 200);
313
314
// Cholesky
315
316
double x;
317
Vector p(n);
318
319
m2 = m1;
320
/*
321
m2.SetSymmetric();
322
if (!m2.Symmetric())
323
cerr << "m should be symmetric for Cholesky" << endl;
324
*/
325
326
for (i = 1; i <= n; i++)
327
for (j = 1; j < i; j++)
328
m2.Elem(j, i) = m2.Get(i, j);
329
330
for (i = 1; i <= n; i++)
331
{
332
if (dots && i % 10 == 0)
333
(*mycout) << "." << flush;
334
335
for (j = i; j <= n; j++)
336
{
337
x = m2.Get(i, j);
338
339
const double * pik = &m2.Get(i, 1);
340
const double * pjk = &m2.Get(j, 1);
341
342
for (k = i-2; k >= 0; --k, ++pik, ++pjk)
343
x -= (*pik) * (*pjk);
344
345
// for (k = i-1; k >= 1; --k)
346
// x -= m2.Get(j, k) * m2.Get(i, k);
347
348
if (i == j)
349
{
350
if (x <= 0)
351
{
352
cerr << "Matrix indefinite 1" << endl;
353
return;
354
}
355
356
p.Elem(i) = 1 / sqrt(x);
357
}
358
else
359
{
360
m2.Elem(j, i) = x * p.Get(i);
361
}
362
}
363
}
364
365
for (i = 1; i <= n; i++)
366
m2.Elem(i, i) = 1 / p.Get(i);
367
368
// check: A = L L^t
369
370
// for (i = 1; i <= n; i++)
371
// for (j = 1; j <= n; j++)
372
// {
373
// x = 0;
374
// for (k = 1; k <= i && k <= j; k++)
375
// x += m2.Get(i, k) * m2.Get(j, k);
376
// (*testout) << "err " << i << "," << j << " = " << (m1.Get(i, j) - x) << endl;
377
// }
378
379
380
381
// calc L^{-1}, store upper triangle
382
383
// DenseMatrix hm(n);
384
// hm = m2;
385
386
for (i = 1; i <= n; i++)
387
{
388
if (dots && i % 10 == 0)
389
(*mycout) << "+" << flush;
390
391
for (j = i; j <= n; j++)
392
{
393
x = 0;
394
if (j == i) x = 1;
395
396
const double * pjk = &m2.Get(j, i);
397
const double * pik = &m2.Get(i, i);
398
for (k = i; k < j; k++, ++pjk, ++pik)
399
x -= *pik * *pjk;
400
401
// for (k = i; k < j; k++)
402
// x -= m2.Get(j, k) * m2.Get(i, k);
403
404
m2.Elem(i, j) = x / m2.Get(j, j);
405
}
406
}
407
408
// (*testout) << "check L^-1" << endl;
409
// for (i = 1; i <= n; i++)
410
// for (j = 1; j <= n; j++)
411
// {
412
// x = 0;
413
// for (k = j; k <= i; k++)
414
// x += hm.Get(i, k) * m2.Get(j, k);
415
// (*testout) << "i, j = " << i << "," << j << " x = " << x << endl;
416
// }
417
418
419
// calc A^-1 = L^-T * L^-1
420
421
for (i = 1; i <= n; i++)
422
{
423
if (dots && i % 10 == 0)
424
(*mycout) << "-" << flush;
425
426
for (j = 1; j <= i; j++)
427
{
428
x = 0;
429
k = i;
430
if (j > i) k = j;
431
432
const double * pik = &m2.Get(i, k);
433
const double * pjk = &m2.Get(j, k);
434
435
for ( ; k <= n; ++k, ++pik, ++pjk)
436
x += *pik * *pjk;
437
// for ( ; k <= n; k++)
438
// x += m2.Get(i, k) * m2.Get(j, k);
439
440
m2.Elem(i, j) = x;
441
}
442
}
443
444
for (i = 1; i <= n; i++)
445
for (j = 1; j < i; j++)
446
m2.Elem(j, i) = m2.Get(i, j);
447
448
if (dots) (*mycout) << endl;
449
#endif
450
451
452
453
// Gauss - Jordan - algorithm
454
455
int r, hi;
456
double max, hr;
457
458
459
ARRAY<int> p(n); // pivot-permutation
460
Vector hv(n);
461
462
463
m2 = m1;
464
465
/*
466
if (m2.Symmetric())
467
for (i = 1; i <= n; i++)
468
for (j = 1; j < i; j++)
469
m2.Elem(j, i) = m2.Get(i, j);
470
*/
471
472
// Algorithm of Stoer, Einf. i. d. Num. Math, S 145
473
474
for (j = 1; j <= n; j++)
475
p.Set(j, j);
476
477
for (j = 1; j <= n; j++)
478
{
479
// pivot search
480
481
max = fabs(m2.Get(j, j));
482
r = j;
483
484
for (i = j+1; i <= n ;i++)
485
if (fabs (m2.Get(i, j)) > max)
486
{
487
r = i;
488
max = fabs (m2.Get(i, j));
489
}
490
491
if (max < 1e-20)
492
{
493
cerr << "Inverse matrix: matrix singular" << endl;
494
return;
495
}
496
497
r = j;
498
499
// exchange rows
500
if (r > j)
501
{
502
for (k = 1; k <= n; k++)
503
{
504
hr = m2.Get(j, k);
505
m2.Elem(j, k) = m2.Get(r, k);
506
m2.Elem(r, k) = hr;
507
}
508
hi = p.Get(j);
509
p.Elem(j) = p.Get(r);
510
p.Elem(r) = hi;
511
}
512
513
514
// transformation
515
516
hr = 1 / m2.Get(j, j);
517
for (i = 1; i <= n; i++)
518
m2.Elem(i, j) *= hr;
519
m2.Elem(j, j) = hr;
520
521
for (k = 1; k <= n; k++)
522
if (k != j)
523
{
524
for (i = 1; i <= n; i++)
525
if (i != j)
526
m2.Elem(i, k) -= m2.Elem(i, j) * m2.Elem(j, k);
527
m2.Elem(j, k) *= -hr;
528
}
529
}
530
531
// col exchange
532
533
for (i = 1; i <= n; i++)
534
{
535
for (k = 1; k <= n; k++)
536
hv.Elem(p.Get(k)) = m2.Get(i, k);
537
for (k = 1; k <= n; k++)
538
m2.Elem(i, k) = hv.Get(k);
539
}
540
541
542
543
/*
544
if (m1.Symmetric())
545
for (i = 1; i <= n; i++)
546
for (j = 1; j < i; j++)
547
m1.Elem(j, i) = m1.Get(i, j);
548
549
m2 = 0;
550
551
for (i = 1; i <= n; i++)
552
m2.Elem(i, i) = 1;
553
554
for (i = 1; i <= n; i++)
555
{
556
// (*mycout) << '.' << flush;
557
q = m1.Get(i, i);
558
for (k = 1; k <= n; k++)
559
{
560
m1.Elem(i, k) /= q;
561
m2.Elem(i, k) /= q;
562
}
563
564
for (j = i+1; j <= n; j++)
565
{
566
q = m1.Elem(j, i);
567
568
double * m1pi = &m1.Elem(i, i);
569
double * m1pj = &m1.Elem(j, i);
570
571
for (k = n; k >= i; --k, ++m1pi, ++m1pj)
572
*m1pj -= q * (*m1pi);
573
574
double * m2pi = &m2.Elem(i, 1);
575
double * m2pj = &m2.Elem(j, 1);
576
577
for (k = i; k > 0; --k, ++m2pi, ++m2pj)
578
*m2pj -= q * (*m2pi);
579
580
// for (k = 1; k <= n; k++)
581
// {
582
// m1.Elem(j, k) -= q * m1.Elem(i, k);
583
// m2.Elem(j, k) -= q * m2.Elem(i, k);
584
// }
585
586
}
587
}
588
589
for (i = n; i >= 1; i--)
590
{
591
// (*mycout) << "+" << flush;
592
for (j = 1; j < i; j++)
593
{
594
q = m1.Elem(j, i);
595
596
double * m2pi = &m2.Elem(i, 1);
597
double * m2pj = &m2.Elem(j, 1);
598
599
for (k = n; k > 0; --k, ++m2pi, ++m2pj)
600
*m2pj -= q * (*m2pi);
601
602
603
// for (k = 1; k <= n; k++)
604
// {
605
// m1.Elem(j, k) -= q * m1.Elem(i, k);
606
// m2.Elem(j, k) -= q * m2.Elem(i, k);
607
// }
608
}
609
}
610
611
if (m2.Symmetric())
612
{
613
for (i = 1; i <= n; i++)
614
for (j = 1; j < i; j++)
615
m2.Elem(i, j) = m2.Elem(j, i);
616
}
617
*/
618
}
619
}
620
621
622
void CalcAAt (const DenseMatrix & a, DenseMatrix & m2)
623
{
624
int n1 = a.Height();
625
int n2 = a.Width();
626
int i, j, k;
627
double sum;
628
const double *p, *q, *p0;
629
630
if (m2.Height() != n1 || m2.Width() != n1)
631
{
632
(*myerr) << "CalcAAt: sizes don't fit" << endl;
633
return;
634
}
635
636
for (i = 1; i <= n1; i++)
637
{
638
sum = 0;
639
p = &a.ConstElem(i, 1);
640
for (k = 1; k <= n2; k++)
641
{
642
sum += *p * *p;
643
p++;
644
}
645
m2.Set(i, i, sum);
646
647
p0 = &a.ConstElem(i, 1);
648
q = a.data;
649
for (j = 1; j < i; j++)
650
{
651
sum = 0;
652
p = p0;
653
654
for (k = 1; k <= n2; k++)
655
{
656
sum += *p * *q;
657
p++;
658
q++;
659
}
660
m2.Set(i, j, sum);
661
m2.Set(j, i, sum);
662
}
663
}
664
}
665
666
667
668
#ifdef ABC
669
BaseMatrix * DenseMatrix :: InverseMatrix (const BitArray * /* inner */) const
670
{
671
if (Height() != Width())
672
{
673
(*myerr) << "BaseMatrix::InverseMatrix(): Matrix not symmetric" << endl;
674
return new DenseMatrix(1);
675
}
676
else
677
{
678
if (Symmetric())
679
{
680
(*mycout) << "Invmat not available" << endl;
681
BaseMatrix * invmat = NULL;
682
return invmat;
683
}
684
685
DenseMatrix * invmat = new DenseMatrix (Height());
686
687
CalcInverse (*this, *invmat);
688
return invmat;
689
}
690
}
691
#endif
692
693
694
695
void CalcAtA (const DenseMatrix & a, DenseMatrix & m2)
696
{
697
int n1 = a.Height();
698
int n2 = a.Width();
699
int i, j, k;
700
double sum;
701
702
if (m2.Height() != n2 || m2.Width() != n2)
703
{
704
(*myerr) << "CalcAtA: sizes don't fit" << endl;
705
return;
706
}
707
708
for (i = 1; i <= n2; i++)
709
for (j = 1; j <= n2; j++)
710
{
711
sum = 0;
712
for (k = 1; k <= n1; k++)
713
sum += a.Get(k, i) * a.Get(k, j);
714
m2.Elem(i, j) = sum;
715
}
716
}
717
718
719
720
721
722
723
void CalcABt (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2)
724
{
725
int n1 = a.Height();
726
int n2 = a.Width();
727
int n3 = b.Height();
728
int i, j, k;
729
double sum;
730
731
if (m2.Height() != n1 || m2.Width() != n3 || b.Width() != n2)
732
{
733
(*myerr) << "CalcABt: sizes don't fit" << endl;
734
return;
735
}
736
737
double * pm2 = &m2.Elem(1, 1);
738
const double * pa1 = &a.Get(1, 1);
739
740
for (i = 1; i <= n1; i++)
741
{
742
const double * pb = &b.Get(1, 1);
743
for (j = 1; j <= n3; j++)
744
{
745
sum = 0;
746
const double * pa = pa1;
747
748
for (k = 1; k <= n2; k++)
749
{
750
sum += *pa * *pb;
751
pa++; pb++;
752
}
753
754
*pm2 = sum;
755
pm2++;
756
}
757
pa1 += n2;
758
}
759
}
760
761
762
void CalcAtB (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2)
763
{
764
int n1 = a.Height();
765
int n2 = a.Width();
766
int n3 = b.Width();
767
int i, j, k;
768
769
if (m2.Height() != n2 || m2.Width() != n3 || b.Height() != n1)
770
{
771
(*myerr) << "CalcAtB: sizes don't fit" << endl;
772
return;
773
}
774
775
for (i = 1; i <= n2 * n3; i++)
776
m2.data[i-1] = 0;
777
778
for (i = 1; i <= n1; i++)
779
for (j = 1; j <= n2; j++)
780
{
781
const double va = a.Get(i, j);
782
double * pm2 = &m2.Elem(j, 1);
783
const double * pb = &b.Get(i, 1);
784
785
for (k = 1; k <= n3; ++k, ++pm2, ++pb)
786
*pm2 += va * *pb;
787
// for (k = 1; k <= n3; k++)
788
// m2.Elem(j, k) += va * b.Get(i, k);
789
}
790
/*
791
for (i = 1; i <= n2; i++)
792
for (j = 1; j <= n3; j++)
793
{
794
sum = 0;
795
for (k = 1; k <= n1; k++)
796
sum += a.Get(k, i) * b.Get(k, j);
797
m2.Elem(i, j) = sum;
798
}
799
*/
800
}
801
802
803
804
805
806
807
808
DenseMatrix operator* (const DenseMatrix & m1, const DenseMatrix & m2)
809
{
810
DenseMatrix temp (m1.Height(), m2.Width());
811
812
if (m1.Width() != m2.Height())
813
{
814
(*myerr) << "DenseMatrix :: operator*: Matrix Size does not fit" << endl;
815
}
816
else if (temp.Height() != m1.Height())
817
{
818
(*myerr) << "DenseMatrix :: operator*: temp not allocated" << endl;
819
}
820
else
821
{
822
Mult (m1, m2, temp);
823
}
824
return temp;
825
}
826
827
828
void Mult (const DenseMatrix & m1, const DenseMatrix & m2, DenseMatrix & m3)
829
{
830
double sum;
831
double *p1, *p1s, *p1sn, *p1snn, *p2, *p2s, *p2sn, *p3;
832
833
if (m1.Width() != m2.Height() || m1.Height() != m3.Height() ||
834
m2.Width() != m3.Width() )
835
{
836
(*myerr) << "DenseMatrix :: Mult: Matrix Size does not fit" << endl;
837
(*myerr) << "m1: " << m1.Height() << " x " << m1.Width() << endl;
838
(*myerr) << "m2: " << m2.Height() << " x " << m2.Width() << endl;
839
(*myerr) << "m3: " << m3.Height() << " x " << m3.Width() << endl;
840
return;
841
}
842
/*
843
else if (m1.Symmetric() || m2.Symmetric() || m3.Symmetric())
844
{
845
(*myerr) << "DenseMatrix :: Mult: not implemented for symmetric matrices" << endl;
846
return;
847
}
848
*/
849
else
850
{
851
// int i, j, k;
852
int n1 = m1.Height();
853
int n2 = m2.Width();
854
int n3 = m1.Width();
855
856
/*
857
for (i = n1 * n2-1; i >= 0; --i)
858
m3.data[i] = 0;
859
860
const double * pm1 = &m1.Get(1, 1);
861
for (i = 1; i <= n1; i++)
862
{
863
const double * pm2 = &m2.Get(1, 1);
864
double * pm3i = &m3.Elem(i, 1);
865
866
for (j = 1; j <= n3; j++)
867
{
868
const double vm1 = *pm1;
869
++pm1;
870
// const double vm1 = m1.Get(i, j);
871
double * pm3 = pm3i;
872
// const double * pm2 = &m2.Get(j, 1);
873
874
for (k = 0; k < n2; k++)
875
{
876
*pm3 += vm1 * *pm2;
877
++pm2;
878
++pm3;
879
}
880
881
// for (k = 1; k <= n2; k++)
882
// m3.Elem(i, k) += m1.Get(i, j) * m2.Get(j, k);
883
}
884
}
885
*/
886
887
/*
888
for (i = 1; i <= n1; i++)
889
for (j = 1; j <= n2; j++)
890
{
891
sum = 0;
892
for (k = 1; k <= n3; k++)
893
sum += m1.Get(i, k) * m2.Get(k, j);
894
m3.Set(i, j, sum);
895
}
896
*/
897
898
899
/*
900
for (i = 1; i <= n1; i++)
901
{
902
const double pm1i = &m1.Get(i, 1);
903
const double pm2j = &m2.Get(1, 1);
904
905
for (j = 1; j <= n2; j++)
906
{
907
double sum = 0;
908
const double * pm1 = pm1i;
909
const double * pm2 = pm2j;
910
pm2j++;
911
912
for (k = 1; k <= n3; k++)
913
{
914
sum += *pm1 * *pm2;
915
++pm1;
916
pm2 += n2;
917
}
918
919
m3.Set (i, j, sum);
920
}
921
}
922
*/
923
924
925
p3 = m3.data;
926
p1s = m1.data;
927
p2sn = m2.data + n2;
928
p1snn = p1s + n1 * n3;
929
930
while (p1s != p1snn)
931
{
932
p1sn = p1s + n3;
933
p2s = m2.data;
934
935
while (p2s != p2sn)
936
{
937
sum = 0;
938
p1 = p1s;
939
p2 = p2s;
940
p2s++;
941
942
while (p1 != p1sn)
943
{
944
sum += *p1 * *p2;
945
p1++;
946
p2 += n2;
947
}
948
*p3++ = sum;
949
}
950
p1s = p1sn;
951
}
952
}
953
}
954
955
956
957
DenseMatrix operator+ (const DenseMatrix & m1, const DenseMatrix & m2)
958
{
959
DenseMatrix temp (m1.Height(), m1.Width());
960
int i, j;
961
962
if (m1.Width() != m2.Width() || m1.Height() != m2.Height())
963
{
964
(*myerr) << "BaseMatrix :: operator+: Matrix Size does not fit" << endl;
965
}
966
else if (temp.Height() != m1.Height())
967
{
968
(*myerr) << "BaseMatrix :: operator+: temp not allocated" << endl;
969
}
970
else
971
{
972
for (i = 1; i <= m1.Height(); i++)
973
for (j = 1; j <= m1.Width(); j++)
974
{
975
temp.Set(i, j, m1.Get(i, j) + m2.Get(i, j));
976
}
977
}
978
return temp;
979
}
980
981
982
983
984
void Transpose (const DenseMatrix & m1, DenseMatrix & m2)
985
{
986
int w = m1.Width();
987
int h = m1.Height();
988
int i, j;
989
990
m2.SetSize (w, h);
991
992
double * pm2 = &m2.Elem(1, 1);
993
for (j = 1; j <= w; j++)
994
{
995
const double * pm1 = &m1.Get(1, j);
996
for (i = 1; i <= h; i++)
997
{
998
*pm2 = *pm1;
999
pm2 ++;
1000
pm1 += w;
1001
}
1002
}
1003
}
1004
1005
1006
/*
1007
void DenseMatrix :: Mult (const Vector & v, Vector & prod) const
1008
{
1009
double sum, val;
1010
const double * mp, * sp;
1011
double * dp;
1012
// const Vector & v = bv.CastToVector();
1013
// Vector & prod = bprod.CastToVector();
1014
1015
1016
int n = Height();
1017
int m = Width();
1018
1019
if (prod.Size() != n)
1020
prod.SetSize (n);
1021
1022
#ifdef DEVELOP
1023
if (!n)
1024
{
1025
cout << "DenseMatrix::Mult mheight = 0" << endl;
1026
}
1027
if (!m)
1028
{
1029
cout << "DenseMatrix::Mult mwidth = 0" << endl;
1030
}
1031
1032
if (m != v.Size())
1033
{
1034
(*myerr) << "\nMatrix and Vector don't fit" << endl;
1035
}
1036
else if (Height() != prod.Size())
1037
{
1038
(*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl;
1039
}
1040
else
1041
#endif
1042
{
1043
if (Symmetric())
1044
{
1045
int i, j;
1046
1047
1048
for (i = 1; i <= n; i++)
1049
{
1050
sp = &v.Get(1);
1051
dp = &prod.Elem(1);
1052
mp = &Get(i, 1);
1053
1054
val = v.Get(i);
1055
sum = Get(i, i) * val;
1056
1057
for (j = 1; j < i; ++j, ++mp, ++sp, ++dp)
1058
{
1059
sum += *mp * *sp;
1060
*dp += val * *mp;
1061
}
1062
1063
prod.Elem(i) = sum;
1064
}
1065
}
1066
else
1067
{
1068
mp = data;
1069
dp = &prod.Elem(1);
1070
for (int i = 1; i <= n; i++)
1071
{
1072
sum = 0;
1073
sp = &v.Get(1);
1074
1075
for (int j = 1; j <= m; j++)
1076
{
1077
// sum += Get(i,j) * v.Get(j);
1078
sum += *mp * *sp;
1079
mp++;
1080
sp++;
1081
}
1082
1083
// prod.Set (i, sum);
1084
*dp = sum;
1085
dp++;
1086
}
1087
}
1088
}
1089
}
1090
*/
1091
1092
void DenseMatrix :: MultTrans (const Vector & v, Vector & prod) const
1093
{
1094
// const Vector & v = (const Vector&)bv; // .CastToVector();
1095
// Vector & prod = (Vector & )bprod; // .CastToVector();
1096
1097
/*
1098
if (Height() != v.Size())
1099
{
1100
(*myerr) << "\nMatrix and Vector don't fit" << endl;
1101
}
1102
else if (Width() != prod.Size())
1103
{
1104
(*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl;
1105
}
1106
else
1107
*/
1108
{
1109
int i, j;
1110
int w = Width(), h = Height();
1111
if (prod.Size() != w)
1112
prod.SetSize (w);
1113
1114
const double * pmat = &Get(1, 1);
1115
const double * pv = &v.Get(1);
1116
1117
prod = 0;
1118
1119
for (i = 1; i <= h; i++)
1120
{
1121
double val = *pv;
1122
++pv;
1123
1124
double * pprod = &prod.Elem(1);
1125
1126
for (j = w-1; j >= 0; --j, ++pmat, ++pprod)
1127
{
1128
*pprod += val * *pmat;
1129
}
1130
}
1131
1132
/*
1133
double sum;
1134
1135
for (i = 1; i <= Width(); i++)
1136
{
1137
sum = 0;
1138
1139
for (int j = 1; j <= Height(); j++)
1140
sum += Get(j, i) * v.Get(j);
1141
1142
prod.Set (i, sum);
1143
}
1144
*/
1145
}
1146
}
1147
1148
1149
void DenseMatrix :: Residuum (const Vector & x, const Vector & b,
1150
Vector & res) const
1151
{
1152
double sum;
1153
// const Vector & x = bx.CastToVector();
1154
// const Vector & b = bb.CastToVector();
1155
// Vector & res = bres.CastToVector();
1156
1157
res.SetSize (Height());
1158
1159
if (Width() != x.Size() || Height() != b.Size())
1160
{
1161
(*myerr) << "\nMatrix and Vector don't fit" << endl;
1162
}
1163
else if (Height() != res.Size())
1164
{
1165
(*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl;
1166
}
1167
else
1168
{
1169
int i, j;
1170
int h = Height();
1171
int w = Width();
1172
const double * mp = &Get(1, 1);
1173
1174
for (i = 1; i <= h; i++)
1175
{
1176
sum = b.Get(i);
1177
const double * xp = &x.Get(1);
1178
1179
for (j = 1; j <= w; ++j, ++mp, ++xp)
1180
sum -= *mp * *xp;
1181
1182
res.Elem(i) = sum;
1183
}
1184
}
1185
}
1186
1187
#ifdef ABC
1188
double DenseMatrix :: EvaluateBilinearform (const Vector & hx) const
1189
{
1190
double sum = 0, hsum;
1191
// const Vector & hx = x.CastToVector();
1192
int i, j;
1193
1194
if (Width() != hx.Size() || Height() != hx.Size())
1195
{
1196
(*myerr) << "Matrix::EvaluateBilinearForm: sizes don't fit" << endl;
1197
}
1198
else
1199
{
1200
for (i = 1; i <= Height(); i++)
1201
{
1202
hsum = 0;
1203
for (j = 1; j <= Height(); j++)
1204
{
1205
hsum += Get(i, j) * hx.Get(j);
1206
}
1207
sum += hsum * hx.Get(i);
1208
}
1209
}
1210
1211
// testout << "sum = " << sum << endl;
1212
return sum;
1213
}
1214
1215
1216
void DenseMatrix :: MultElementMatrix (const ARRAY<int> & pnum,
1217
const Vector & hx, Vector & hy)
1218
{
1219
int i, j;
1220
// const Vector & hx = x.CastToVector();
1221
// Vector & hy = y.CastToVector();
1222
1223
if (Symmetric())
1224
{
1225
for (i = 1; i <= Height(); i++)
1226
{
1227
for (j = 1; j < i; j++)
1228
{
1229
hy.Elem(pnum.Get(i)) += Get(i, j) * hx.Get(pnum.Get(j));
1230
hy.Elem(pnum.Get(j)) += Get(i, j) * hx.Get(pnum.Get(i));
1231
}
1232
hy.Elem(pnum.Get(j)) += Get(i, i) * hx.Get(pnum.Get(i));
1233
}
1234
}
1235
else
1236
for (i = 1; i <= Height(); i++)
1237
for (j = 1; j <= Width(); j++)
1238
hy.Elem(pnum.Get(i)) += Get(i, j) * hx.Get(pnum.Get(j));
1239
1240
}
1241
1242
void DenseMatrix :: MultTransElementMatrix (const ARRAY<int> & pnum,
1243
const Vector & hx, Vector & hy)
1244
{
1245
int i, j;
1246
// const Vector & hx = x.CastToVector();
1247
// Vector & hy = y.CastToVector();
1248
1249
if (Symmetric())
1250
MultElementMatrix (pnum, hx, hy);
1251
else
1252
for (i = 1; i <= Height(); i++)
1253
for (j = 1; j <= Width(); j++)
1254
hy.Elem(pnum.Get(i)) += Get(j, i) * hx.Get(pnum.Get(j));
1255
}
1256
#endif
1257
1258
1259
void DenseMatrix :: Solve (const Vector & v, Vector & sol) const
1260
{
1261
DenseMatrix temp (*this);
1262
temp.SolveDestroy (v, sol);
1263
}
1264
1265
1266
void DenseMatrix :: SolveDestroy (const Vector & v, Vector & sol)
1267
{
1268
double q;
1269
1270
if (Width() != Height())
1271
{
1272
(*myerr) << "SolveDestroy: Matrix not square";
1273
return;
1274
}
1275
if (Width() != v.Size())
1276
{
1277
(*myerr) << "SolveDestroy: Matrix and Vector don't fit";
1278
return;
1279
}
1280
1281
sol = v;
1282
if (Height() != sol.Size())
1283
{
1284
(*myerr) << "SolveDestroy: Solution Vector not ok";
1285
return;
1286
}
1287
1288
1289
if (0 /* Symmetric() */)
1290
{
1291
1292
// Cholesky factorization
1293
1294
int i, j, k, n;
1295
n = Height();
1296
1297
// Cholesky
1298
1299
double x;
1300
Vector p(n);
1301
1302
for (i = 1; i <= n; i++)
1303
for (j = 1; j < i; j++)
1304
Elem(j, i) = Get(i, j);
1305
1306
for (i = 1; i <= n; i++)
1307
{
1308
// (*mycout) << "." << flush;
1309
for (j = i; j <= n; j++)
1310
{
1311
x = Get(i, j);
1312
1313
const double * pik = &Get(i, 1);
1314
const double * pjk = &Get(j, 1);
1315
1316
for (k = i-2; k >= 0; --k, ++pik, ++pjk)
1317
x -= (*pik) * (*pjk);
1318
1319
// for (k = i-1; k >= 1; --k)
1320
// x -= Get(j, k) * Get(i, k);
1321
1322
if (i == j)
1323
{
1324
if (x <= 0)
1325
{
1326
cerr << "Matrix indefinite" << endl;
1327
return;
1328
}
1329
1330
p.Elem(i) = 1 / sqrt(x);
1331
}
1332
else
1333
{
1334
Elem(j, i) = x * p.Get(i);
1335
}
1336
}
1337
}
1338
1339
for (i = 1; i <= n; i++)
1340
Elem(i, i) = 1 / p.Get(i);
1341
1342
// A = L L^t
1343
// L stored in left-lower triangle
1344
1345
1346
sol = v;
1347
1348
// Solve L sol = sol
1349
1350
for (i = 1; i <= n; i++)
1351
{
1352
double val = sol.Get(i);
1353
1354
const double * pij = &Get(i, 1);
1355
const double * solj = &sol.Get(1);
1356
1357
for (j = 1; j < i; j++, ++pij, ++solj)
1358
val -= *pij * *solj;
1359
// for (j = 1; j < i; j++)
1360
// val -= Get(i, j) * sol.Get(j);
1361
1362
sol.Elem(i) = val / Get(i, i);
1363
}
1364
1365
// Solve L^t sol = sol
1366
1367
for (i = n; i >= 1; i--)
1368
{
1369
double val = sol.Get(i) / Get(i, i);
1370
sol.Elem(i) = val;
1371
1372
double * solj = &sol.Elem(1);
1373
const double * pij = &Get(i, 1);
1374
1375
for (j = 1; j < i; ++j, ++pij, ++solj)
1376
*solj -= val * *pij;
1377
// for (j = 1; j < i; j++)
1378
// sol.Elem(j) -= Get(i, j) * val;
1379
}
1380
1381
1382
}
1383
else
1384
{
1385
// (*mycout) << "gauss" << endl;
1386
int i, j, k, n = Height();
1387
for (i = 1; i <= n; i++)
1388
{
1389
for (j = i+1; j <= n; j++)
1390
{
1391
q = Get(j,i) / Get(i,i);
1392
if (q)
1393
{
1394
const double * pik = &Get(i, i+1);
1395
double * pjk = &Elem(j, i+1);
1396
1397
for (k = i+1; k <= n; ++k, ++pik, ++pjk)
1398
*pjk -= q * *pik;
1399
1400
// for (k = i+1; k <= Height(); k++)
1401
// Elem(j, k) -= q * Get(i,k);
1402
1403
1404
sol.Elem(j) -= q * sol.Get(i);
1405
}
1406
}
1407
}
1408
1409
for (i = n; i >= 1; i--)
1410
{
1411
q = sol.Get(i);
1412
for (j = i+1; j <= n; j++)
1413
q -= Get(i,j) * sol.Get(j);
1414
1415
sol.Elem(i) = q / Get(i,i);
1416
}
1417
}
1418
}
1419
1420
1421
/*
1422
BaseMatrix * DenseMatrix :: Copy () const
1423
{
1424
return new DenseMatrix (*this);
1425
}
1426
*/
1427
1428
1429
1430
1431
ostream & operator<< (ostream & ost, const DenseMatrix & m)
1432
{
1433
for (int i = 0; i < m.Height(); i++)
1434
{
1435
for (int j = 0; j < m.Width(); j++)
1436
ost << m.Get(i+1,j+1) << " ";
1437
ost << endl;
1438
}
1439
return ost;
1440
}
1441
1442
1443
1444
}
1445
1446