00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "common.h"
00020 #include "NumericLib.h"
00021
00022
00023
00024
00025
00026 #include "basis.h"
00027 #include "vmblock.h"
00028 #include "lu.h"
00029
00030
00031 #include <cfloat>
00032 #include <limits>
00033 #include <stdlib.h>
00034 #include <iostream>
00035 #include <fstream>
00036 #include <sstream>
00037
00038
00039 using std::ostringstream;
00040 using std::numeric_limits;
00041 using std::endl;
00042 using std::cout;
00043 using std::cerr;
00044 using std::min;
00045 using std::max;
00046
00047
00048
00049 using namespace Marsyas;
00050
00051
00052
00053
00054
00055 #define NumericLib_MAXCOEFF 5001
00056
00057 #define NumLib_TRUE 1
00058 #define NumLib_FALSE 0
00059
00060
00061
00062 #define Cadd(a,b) (a+b)
00063 #define Csub(a,b) (a-b)
00064 #define Cmul(a,b) (a*b)
00065 #define Cdiv(a,b) (a/b)
00066 #define Ccomplex(a,b) mrs_complex(a,b)
00067 #define Cabs(z) std::abs(z)
00068 #define Carg(z) std::arg(z)
00069 #define Conjg(z) std::conj(z)
00070 #define Csqrt(z) std::sqrt(z)
00071 #define RCmul(x,a) (x*a)
00072 #define RCadd(x,a) (x+a)
00073 #define CADD(x,a,b) {x = a + b;} //due to some legacy code...
00074 #define CMUL(x,a,b) {x = a * b;} //due to some legacy code...
00075 #define COMPLEXM(x,a,b) {x = mrs_complex(a,b);} //due to some legacy code...
00076
00077
00078 #define ITERMAXMULLER 150
00079 #define CONVERGENCE 100
00080 #define MAXDIST 1e3
00081
00082 #define FACTORMULLER 1e5
00083
00084 #define KITERMAX 1e3
00085
00086 #define FVALUEMULLER 1e36
00087 #define BOUND1 1.01
00088 #define BOUND2 0.99
00089 #define BOUND3 0.01
00090 #define BOUND4 sqrt(DBL_MAX)/1e4
00091
00092 #define BOUND6 log10(BOUND4)-4
00093
00094 #define BOUND7 1e-5
00095
00096 #define NOISESTART DBL_EPSILON*1e2
00097 #define NOISEMAX 5
00098
00099
00100 #define ITERMAXNEWTON 20
00101 #define FACTORNEWTON 5
00102
00103 #define FVALUENEWTON 1E36
00104 #define BOUND sqrt(DBL_EPSILON)
00105
00106
00107 #define NOISEMAX 5
00108
00109
00110 NumericLib::NumericLib()
00111 {
00112
00113 }
00114
00115 NumericLib::~NumericLib()
00116 {
00117
00118 }
00119
00120 bool
00121 NumericLib::polyRoots(std::vector<mrs_complex> coefs, bool complexCoefs, mrs_natural order, std::vector<mrs_complex> &roots)
00122 {
00123
00124
00125
00126 unsigned char error;
00127 mrs_real maxerr;
00128 mrs_complex* pred = new mrs_complex[NumericLib_MAXCOEFF];
00129
00130
00131 error = null(&coefs[0], pred, &order, &roots[0], &maxerr, complexCoefs);
00132
00133 delete [] pred;
00134
00135 if (error==0)
00136 return true;
00137 else
00138 {
00139 MRSERR("NumericLib::polyRoots() - numeric error in polynomial roots calculation!");
00140 return false;
00141 }
00142 }
00143
00144 mrs_real
00145 NumericLib::determinant(realvec matrix)
00146 {
00147
00148
00149
00150
00151
00152
00153 if(matrix.getCols() != matrix.getRows())
00154 {
00155 MRSERR("NumericLib::determinant() : input matrix should be square! Returning invalid determinant value...");
00156 return numeric_limits<mrs_real>::max();
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 REAL **A;
00184 int *INDX;
00185 void *vmblock = NULL;
00186
00187
00188
00189 int i, id, j, n, rc;
00190 REAL det;
00191
00192
00193 n = matrix.getCols();
00194
00195 vmblock = vminit();
00196 A = (REAL **)vmalloc(vmblock, MATRIX, n+1, n+1);
00197 INDX = (int *) vmalloc(vmblock, VEKTOR, n+1, 0);
00198
00199 if (! vmcomplete(vmblock))
00200 {
00201 MRSERR("NumericLib::determinant() : No memory! Returning invalid determinant value...");
00202 return numeric_limits<mrs_real>::max();
00203 }
00204
00205 for (i=0; i<=n; ++i)
00206 for (j=0; j<=n; j++)
00207 A[i][j] = 0.0;
00208
00209
00210 for (i=1; i<=n; ++i)
00211 for (j=1; j<=n; j++)
00212 A[i][j] = (REAL)matrix(i-1, j-1);
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 rc = LUDCMP(A,n,INDX,&id);
00226
00227
00228 det = id;
00229 if (rc==0) {
00230 for (i=1; i<=n; ++i)
00231 det *= A[i][i];
00232 return (mrs_real)det;
00233 }
00234 else {
00235 if(rc==-1)
00236 {
00237 MRSERR("NumericLib::determinant() : Memory Allocation error in LUDCMP()! Returning invalid determinant value...");
00238 return numeric_limits<mrs_real>::max();
00239 }
00240 else
00241 {
00242 MRSWARN("NumericLib::determinant() : Error in LU decomposition: singular input matrix. Determinant equals to zero.");
00243 return 0.0;
00244 }
00245 }
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 mrs_complex
00290 NumericLib::muller(mrs_complex *pred,mrs_natural nred)
00291
00292
00293 {
00294 mrs_real f1absq=FVALUEMULLER,
00295 f2absq=FVALUEMULLER,
00296 f2absqb=FVALUEMULLER,
00297 h2abs,
00298 epsilon;
00299 mrs_natural seconditer=0,
00300 noise=0,
00301 rootd=NumLib_FALSE;
00302
00303 mrs_complex xb;
00304
00305
00306 initialize(pred,&xb,&epsilon);
00307
00308 fdvalue(pred,nred,&f0MULLER_,&f0MULLER_,x0MULLER_,NumLib_FALSE);
00309 fdvalue(pred,nred,&f1MULLER_,&f1MULLER_,x1MULLER_,NumLib_FALSE);
00310 fdvalue(pred,nred,&f2MULLER_,&f2MULLER_,x2MULLER_,NumLib_FALSE);
00311
00312 do {
00313 do {
00314
00315 root_of_parabola();
00316
00317
00318 x0MULLER_ = x1MULLER_;
00319 x1MULLER_ = x2MULLER_;
00320 h2abs = Cabs(h2MULLER_);
00321
00322
00323 iteration_equation(&h2abs);
00324
00325
00326 f0MULLER_ = f1MULLER_;
00327 f1MULLER_ = f2MULLER_;
00328 f1absq = f2absq;
00329
00330
00331 compute_function(pred,nred,f1absq,&f2absq,epsilon);
00332
00333
00334
00335
00336 check_x_value(&xb,&f2absqb,&rootd,f1absq,f2absq,
00337 epsilon,&noise);
00338
00339
00340 if (fabs((Cabs(xb)-Cabs(x2MULLER_))/Cabs(xb))<NOISESTART)
00341 noise++;
00342 } while ((iterMULLER_<=ITERMAXMULLER) && (!rootd) && (noise<=NOISEMAX));
00343
00344 seconditer++;
00345
00346
00347 root_check(pred,nred,f2absqb,&seconditer,&rootd,&noise,xb);
00348 } while (seconditer==2);
00349
00350 return xb;
00351 }
00352
00353
00354 void
00355 NumericLib::initialize(mrs_complex *pred,mrs_complex *xb,mrs_real *epsilon)
00356
00357
00358
00359 {
00360
00361 (void) pred;
00362
00363
00364
00365 x0MULLER_ = Ccomplex(0.,0.);
00366 x1MULLER_ = Ccomplex(-1./sqrt(2.0),-1./sqrt(2.0));
00367 x2MULLER_ = Ccomplex(1./sqrt(2.0),1./sqrt(2.0));
00368
00369 h1MULLER_ = Csub(x1MULLER_,x0MULLER_);
00370 h2MULLER_ = Csub(x2MULLER_,x1MULLER_);
00371 q2MULLER_ = Cdiv(h2MULLER_,h1MULLER_);
00372
00373 *xb = x2MULLER_;
00374 *epsilon = FACTORMULLER*DBL_EPSILON;
00375 iterMULLER_ = 0;
00376 }
00377
00378
00379 void
00380 NumericLib::root_of_parabola(void)
00381 {
00382 mrs_complex A2,B2,C2,
00383 discr,
00384 N1,N2;
00385
00386
00387
00388
00389 A2 = Cmul(q2MULLER_,Csub(Cadd(f2MULLER_,Cmul(q2MULLER_,f0MULLER_)),
00390 Cmul(f1MULLER_,RCadd((mrs_real)1.,q2MULLER_))));
00391 B2 = Cadd(Csub(f2MULLER_,f1MULLER_),Cmul(q2MULLER_,Cadd(Cmul(q2MULLER_,
00392 Csub(f0MULLER_,f1MULLER_)),RCmul((mrs_real)2.,Csub(f2MULLER_,f1MULLER_)))));
00393 C2 = Cmul(f2MULLER_,RCadd((mrs_real)1.,q2MULLER_));
00394
00395 discr = Csub(Cmul(B2,B2),RCmul((mrs_real)4.,Cmul(A2,C2)));
00396
00397 N1 = Csub(B2,Csqrt(discr));
00398 N2 = Cadd(B2,Csqrt(discr));
00399
00400 if (Cabs(N1)>Cabs(N2) && Cabs(N1)>DBL_EPSILON)
00401 q2MULLER_ = Cdiv(RCmul((mrs_real)-2.,C2),N1);
00402 else if (Cabs(N2)>DBL_EPSILON)
00403 q2MULLER_ = Cdiv(RCmul((mrs_real)-2.,C2),N2);
00404 else
00405 q2MULLER_ = Ccomplex(cos((mrs_real)iterMULLER_),sin((mrs_real)iterMULLER_));
00406 }
00407
00408
00409 void
00410 NumericLib::iteration_equation(mrs_real *h2abs)
00411
00412 {
00413 mrs_real h2absnew,
00414 help;
00415
00416 h2MULLER_ = Cmul(h2MULLER_,q2MULLER_);
00417 h2absnew = Cabs(h2MULLER_);
00418
00419 if (h2absnew > (*h2abs*MAXDIST)) {
00420 help = MAXDIST/h2absnew;
00421 h2MULLER_ = RCmul(help,h2MULLER_);
00422 q2MULLER_ = RCmul(help,q2MULLER_);
00423 }
00424
00425 *h2abs = h2absnew;
00426
00427 x2MULLER_ = Cadd(x2MULLER_,h2MULLER_);
00428 }
00429
00430
00431 void
00432 NumericLib::suppress_overflow(mrs_natural nred)
00433
00434 {
00435 mrs_natural kiter;
00436 unsigned char loop;
00437 mrs_real help;
00438
00439 kiter = 0;
00440 do {
00441 loop=NumLib_FALSE;
00442 help = Cabs(x2MULLER_);
00443 if (help>1. && fabs(nred*log10(help))>BOUND6) {
00444 kiter++;
00445 if (kiter<KITERMAX) {
00446 h2MULLER_=RCmul((mrs_real).5,h2MULLER_);
00447 q2MULLER_=RCmul((mrs_real).5,q2MULLER_);
00448 x2MULLER_=Csub(x2MULLER_,h2MULLER_);
00449 loop=NumLib_TRUE;
00450 } else
00451 kiter=0;
00452 }
00453 } while(loop);
00454 }
00455
00456
00457 void
00458 NumericLib::too_big_functionvalues(mrs_real *f2absq)
00459
00460 {
00461 if ((fabs(f2MULLER_.real())+fabs(f2MULLER_.imag()))>BOUND4)
00462 *f2absq = fabs(f2MULLER_.real())+fabs(f2MULLER_.imag());
00463 else
00464 *f2absq = (f2MULLER_.real())*(f2MULLER_.real())+(f2MULLER_.imag())*(f2MULLER_.imag());
00465 }
00466
00467
00468 void
00469 NumericLib::convergence_check(mrs_natural *overflow,mrs_real f1absq,mrs_real f2absq,
00470 mrs_real epsilon)
00471
00472
00473
00474
00475
00476 {
00477 if ((f2absq>(CONVERGENCE*f1absq)) && (Cabs(q2MULLER_)>epsilon) &&
00478 (iterMULLER_<ITERMAXMULLER)) {
00479 q2MULLER_ = RCmul((mrs_real).5,q2MULLER_);
00480 h2MULLER_ = RCmul((mrs_real).5,h2MULLER_);
00481 x2MULLER_ = Csub(x2MULLER_,h2MULLER_);
00482 *overflow = NumLib_TRUE;
00483 }
00484 }
00485
00486
00487 void
00488 NumericLib::compute_function(mrs_complex *pred,mrs_natural nred,mrs_real f1absq,
00489 mrs_real *f2absq,mrs_real epsilon)
00490
00491
00492
00493
00494
00495 {
00496 mrs_natural overflow;
00497
00498
00499 do {
00500 overflow = NumLib_FALSE;
00501
00502
00503 suppress_overflow(nred);
00504
00505
00506 fdvalue(pred,nred,&f2MULLER_,&f2MULLER_,x2MULLER_,NumLib_FALSE);
00507
00508
00509 too_big_functionvalues(f2absq);
00510
00511
00512 iterMULLER_++;
00513
00514
00515 convergence_check(&overflow,f1absq,*f2absq,epsilon);
00516 } while (overflow);
00517 }
00518
00519
00520 void
00521 NumericLib::check_x_value(mrs_complex *xb,mrs_real *f2absqb,mrs_natural *rootd,
00522 mrs_real f1absq,mrs_real f2absq,mrs_real epsilon,
00523 mrs_natural *noise)
00524
00525
00526
00527
00528
00529
00530
00531
00532 {
00533 if ((f2absq<=(BOUND1*f1absq)) && (f2absq>=(BOUND2*f1absq))) {
00534
00535 if (Cabs(h2MULLER_)<BOUND3) {
00536 q2MULLER_ = RCmul((mrs_real)2.,q2MULLER_);
00537 h2MULLER_ = RCmul((mrs_real)2.,h2MULLER_);
00538 } else {
00539
00540 q2MULLER_ = Ccomplex(cos((mrs_real)iterMULLER_),sin((mrs_real)iterMULLER_));
00541 h2MULLER_ = Cmul(h2MULLER_,q2MULLER_);
00542 }
00543 } else if (f2absq<*f2absqb) {
00544 *f2absqb = f2absq;
00545 *xb = x2MULLER_;
00546 *noise = 0;
00547 if ((sqrt(f2absq)<epsilon) &&
00548 (Cabs(Cdiv(Csub(x2MULLER_,x1MULLER_),x2MULLER_))<epsilon))
00549 *rootd = NumLib_TRUE;
00550 }
00551 }
00552
00553
00554 void
00555 NumericLib::root_check(mrs_complex *pred,mrs_natural nred,mrs_real f2absqb,mrs_natural *seconditer,
00556 mrs_natural *rootd,mrs_natural *noise,mrs_complex xb)
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 {
00568
00569 mrs_complex df;
00570
00571 if ((*seconditer==1) && (f2absqb>0)) {
00572 fdvalue(pred,nred,&f2MULLER_,&df,xb,NumLib_TRUE);
00573 if (Cabs(f2MULLER_)/(Cabs(df)*Cabs(xb))>BOUND7) {
00574
00575
00576
00577
00578
00579 x0MULLER_ = Ccomplex(1.,0.);
00580 x1MULLER_ = Ccomplex(-1.,0.);
00581 x2MULLER_ = Ccomplex(0.,0.);
00582 fdvalue(pred,nred,&f0MULLER_,&df,x0MULLER_,NumLib_FALSE);
00583 fdvalue(pred,nred,&f1MULLER_,&df,x1MULLER_,NumLib_FALSE);
00584 fdvalue(pred,nred,&f2MULLER_,&df,x2MULLER_,NumLib_FALSE);
00585 iterMULLER_ = 0;
00586 (*seconditer)++;
00587 *rootd = NumLib_FALSE;
00588 *noise = 0;
00589 }
00590 }
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 mrs_complex
00629 NumericLib::newton(mrs_complex *p,mrs_natural n,mrs_complex ns,mrs_real *dxabs,
00630 unsigned char flag)
00631
00632
00633
00634
00635
00636
00637 {
00638 mrs_complex x0,
00639 xmin,
00640 f,
00641 df,
00642 dx,
00643 dxh;
00644 mrs_real fabsmin=FVALUENEWTON,
00645 eps=DBL_EPSILON;
00646
00647
00648 mrs_natural iter =0,
00649 noise =0;
00650
00651 x0 = ns;
00652
00653 xmin = x0;
00654 dx = Ccomplex(1.,0.);
00655 *dxabs = Cabs(dx);
00656
00657 for (iter=0;iter<ITERMAXNEWTON;iter++) {
00658 fdvalue(p,n,&f,&df,x0,NumLib_TRUE);
00659
00660 if (Cabs(f)<fabsmin) {
00661 xmin = x0;
00662 fabsmin = Cabs(f);
00663 noise = 0;
00664 }
00665
00666 if (Cabs(df)!=0.) {
00667 dxh=Cdiv(f,df);
00668 if (Cabs(dxh)<*dxabs*FACTORNEWTON) {
00669 dx = dxh;
00670 *dxabs = Cabs(dx);
00671 }
00672 }
00673
00674 if (Cabs(xmin)!=0.) {
00675 if (*dxabs/Cabs(xmin)<eps || noise == NOISEMAX) {
00676
00677 if (fabs(xmin.imag())<BOUND && flag==0) {
00678
00679 xmin = mrs_complex(xmin.real(),0.);
00680 }
00681 *dxabs=*dxabs/Cabs(xmin);
00682 return xmin;
00683 }
00684 }
00685
00686 x0 = Csub(x0,dx);
00687
00688 noise++;
00689 }
00690
00691
00692 if (fabs(xmin.imag())<BOUND && flag==0)
00693 xmin = mrs_complex(xmin.real(),0.);
00694 if (Cabs(xmin)!=0.)
00695 *dxabs=*dxabs/Cabs(xmin);
00696
00697 return xmin;
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739 unsigned char
00740 NumericLib::null(mrs_complex *p,mrs_complex *pred,mrs_natural *n,mrs_complex *root,
00741 mrs_real *maxerr,unsigned char flag)
00742
00743
00744
00745
00746
00747
00748
00749 {
00750 mrs_real newerr;
00751 mrs_complex ns;
00752 mrs_natural nred,
00753 i;
00754 unsigned char error;
00755 mrs_natural red,
00756 diff;
00757
00758 *maxerr = 0.;
00759 nred = *n;
00760
00761
00762
00763 error = poly_check(p,&nred,n,root);
00764 diff = (*n-nred);
00765 p += diff;
00766 *n = nred;
00767
00768 if (error)
00769 return error;
00770
00771
00772 if (lin_or_quad(p,nred,root)==0) {
00773 *n += diff;
00774 *maxerr = DBL_EPSILON;
00775 return 0;
00776 }
00777
00778 monic(p,n);
00779
00780 for (i=0;i<=*n;++i) pred[i]=p[i];
00781
00782
00783
00784 do {
00785
00786 ns = muller(pred,nred);
00787
00788
00789
00790
00791 root[nred-1] = newton(p,*n,ns,&newerr,flag);
00792
00793
00794 if (newerr>*maxerr)
00795 *maxerr=newerr;
00796
00797 red = poldef(pred,nred,root,flag);
00798 pred += red;
00799 nred -= red;
00800 } while (nred>2);
00801
00802 (void) lin_or_quad(pred,nred,root);
00803 if (nred==2) {
00804 root[1] = newton(p,*n,root[1],&newerr,flag);
00805 if (newerr>*maxerr)
00806 *maxerr=newerr;
00807 }
00808 root[0] = newton(p,*n,root[0],&newerr,flag);
00809 if (newerr>*maxerr)
00810 *maxerr=newerr;
00811
00812 *n += diff;
00813 return 0;
00814 }
00815
00816
00817 unsigned char
00818 NumericLib::poly_check(mrs_complex *pred,mrs_natural *nred,mrs_natural *n,mrs_complex *root)
00819
00820
00821
00822
00823 {
00824 mrs_natural i = -1,
00825 j;
00826 unsigned char
00827 notfound=NumLib_TRUE;
00828
00829
00830 if (*n<0) return 1;
00831
00832
00833 for (j=0;j<=*n;j++) {
00834 if(Cabs(pred[j])!=0.)
00835 i=j;
00836 }
00837 if (i==-1) return 2;
00838 if (i==0) return 3;
00839
00840
00841 *n=i;
00842 i=0;
00843 do {
00844 if (Cabs(pred[i])==0.)
00845 ++i;
00846 else
00847 notfound=NumLib_FALSE;
00848 } while (i<=*n && notfound);
00849
00850 if (i==0) {
00851 *nred = *n;
00852 return 0;
00853 } else {
00854 for (j=0;j<=i-1;j++)
00855 root[*n-j-1] = Ccomplex(0.,0.);
00856 *nred = *n-i;
00857 return 0;
00858 }
00859 }
00860
00861
00862 void
00863 NumericLib::quadratic(mrs_complex *pred,mrs_complex *root)
00864
00865
00866
00867 {
00868 mrs_complex discr,
00869 Z1,Z2,
00870 N;
00871
00872
00873 discr = Csub(Cmul(pred[1],pred[1]),
00874 RCmul((mrs_real)4.,Cmul(pred[2],pred[0])));
00875
00876 Z1 = Cadd(RCmul((mrs_real)-1.,pred[1]),Csqrt(discr));
00877
00878 Z2 = Csub(RCmul((mrs_real)-1.,pred[1]),Csqrt(discr));
00879
00880 N = RCmul((mrs_real)2.,pred[2]);
00881 root[0] = Cdiv(Z1,N);
00882 root[1] = Cdiv(Z2,N);
00883 }
00884
00885
00886 unsigned char
00887 NumericLib::lin_or_quad(mrs_complex *pred,mrs_natural nred,mrs_complex *root)
00888
00889
00890
00891 {
00892 if (nred==1) {
00893 root[0] = Cdiv(RCmul((mrs_real)-1.,pred[0]),pred[1]);
00894 return 0;
00895 } else if (nred==2) {
00896 quadratic(pred,root);
00897 return 0;
00898 }
00899
00900 return 1;
00901 }
00902
00903
00904 void
00905 NumericLib::monic(mrs_complex *p,mrs_natural *n)
00906
00907
00908 {
00909 mrs_real factor;
00910
00911 mrs_natural i;
00912
00913 factor=1./Cabs(p[*n]);
00914 if ( factor!=1.)
00915 for (i=0;i<=*n;++i)
00916 p[i]=RCmul(factor,p[i]);
00917 }
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 void
00955 NumericLib::hornc(mrs_complex *pred,mrs_natural nred,mrs_complex x0,unsigned char flag)
00956
00957
00958
00959
00960 {
00961 mrs_natural i;
00962 mrs_complex help1;
00963
00964 if ((flag&1)==0)
00965 for(i=nred-1; i>0; i--)
00966 pred[i] = mrs_complex(pred[i].real() + (x0.real()*pred[i+1].real()), pred[i].imag());
00967 else
00968 for (i=nred-1; i>0; i--) {
00969 CMUL(help1,pred[i+1],x0);
00970 CADD(pred[i],help1,pred[i]);
00971 }
00972 }
00973
00974
00975 void
00976 NumericLib::horncd(mrs_complex *pred,mrs_natural nred,mrs_real a,mrs_real b)
00977
00978
00979
00980
00981 {
00982 mrs_natural i;
00983
00984
00985 pred[nred-1] = mrs_complex(pred[nred-1].real() + pred[nred].real()*a, pred[nred-1].imag());
00986
00987 for (i=nred-2; i>1; i--)
00988
00989 pred[i] = mrs_complex(pred[i].real() + (a*pred[i+1].real()+b*pred[i+2].real()), pred[i].imag());
00990 }
00991
00992
00993 mrs_natural
00994 NumericLib::poldef(mrs_complex *pred,mrs_natural nred,mrs_complex *root,unsigned char flag)
00995
00996
00997
00998
00999 {
01000 mrs_real a,
01001 b;
01002 mrs_complex x0;
01003
01004
01005 x0 = root[nred-1];
01006 if (x0.imag()!=0.)
01007 flag |=2;
01008
01009 if (flag==2) {
01010 a = 2*x0.real();
01011 b = -(x0.real()*x0.real()+x0.imag()*x0.imag());
01012 root[nred-2]=Conjg(x0);
01013 horncd(pred,nred,a,b);
01014 return 2;
01015 } else {
01016 hornc(pred,nred,x0,flag);
01017 return 1;
01018 }
01019 }
01020
01021
01022 void
01023 NumericLib::fdvalue(mrs_complex *p,mrs_natural n,mrs_complex *f,mrs_complex *df,mrs_complex x0,
01024 unsigned char flag)
01025
01026
01027
01028
01029
01030
01031 {
01032 mrs_natural i;
01033 mrs_complex help1;
01034
01035 *f = p[n];
01036 if (flag==NumLib_TRUE) {
01037 COMPLEXM(*df,0.,0.);
01038 for (i=n-1; i>=0; i--) {
01039 CMUL(help1,*df,x0);
01040 CADD(*df,help1,*f);
01041 CMUL(help1,*f,x0);
01042 CADD(*f,help1,p[i]);
01043 }
01044 } else
01045 for (i=n-1; i>=0; i--) {
01046 CMUL(help1,*f,x0);
01047 CADD(*f,help1,p[i]);
01048 }
01049 }
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059 mrs_real NumericLib::add(mrs_real *a, mrs_real *b)
01060 {
01061 mrs_real ret;
01062 ret = *a + *b;
01063 return ret;
01064 }
01065
01066 mrs_real NumericLib::pow_di(mrs_real *ap, mrs_natural *bp)
01067 {
01068 mrs_real pow, x;
01069 mrs_natural n;
01070 unsigned long u;
01071
01072 pow = 1;
01073 x = *ap;
01074 n = *bp;
01075
01076 if(n != 0)
01077 {
01078 if(n < 0)
01079 {
01080 n = -n;
01081 x = 1/x;
01082 }
01083 for(u = n; ; )
01084 {
01085 if(u & 01)
01086 pow *= x;
01087 if(u >>= 1)
01088 x *= x;
01089 else
01090 break;
01091 }
01092 }
01093 return(pow);
01094 }
01095
01096
01097
01098
01099
01100
01101
01102 mrs_real NumericLib::machp(const char *cmach)
01103 {
01104 mrs_real zero, one, two, half, sixth, third, a, b, c, f, d__1, d__2, d__3, d__4, d__5, qtr, eps;
01105 mrs_real base;
01106 mrs_natural lt, rnd, i__1;
01107 lt = 0;
01108 rnd = 0;
01109 eps = 0.0;
01110
01111 one = 1.;
01112 a = 1.;
01113 c = 1.;
01114
01115
01116 while( c == one ){
01117 a *= 2;
01118 c = add(&a, &one);
01119 d__1 = -a;
01120 c = add(&c, &d__1);
01121 }
01122
01123 b = 1.;
01124 c = add( &a, &b );
01125
01126 while( c == a )
01127 {
01128 b *= 2;
01129 c = add( &a, &b );
01130 }
01131
01132 qtr = one / 4;
01133 d__1 = -a;
01134 c = add(&c, &d__1);
01135 base = (mrs_natural)(c+qtr);
01136
01137
01138 if( *cmach == 'M' || *cmach == 'm' || *cmach == 'E' || *cmach == 'e' )
01139 {
01140 lt = 0;
01141 a = 1.;
01142 c = 1.;
01143 printf("%g %g %g %g\n", c, one, a, d__1);
01144 while( c == one ){
01145 ++lt;
01146 a *= base;
01147 c = add( &a, &one );
01148 d__1 = -a;
01149 c = add( &c, &d__1 );
01150 }
01151 }
01152
01153 if( *cmach == 'R' || *cmach == 'r' || *cmach == 'E' || *cmach == 'e' )
01154 {
01155 b = (mrs_real) base;
01156 d__1 = b / 2;
01157 d__2 = -b / 100;
01158 f = add( &d__1, &d__2 );
01159 c = add( &f, &a );
01160 if( c == a ) {
01161 rnd = 1;
01162 } else {
01163 rnd = 0;
01164 }
01165 d__1 = b / 2;
01166 d__2 = b / 100;
01167 f = add( &d__1 , &d__2 );
01168 c = add( &f, &a );
01169 if( rnd && c == a ) {
01170 rnd = 0;
01171 }
01172 }
01173
01174 if( *cmach == 'E' || *cmach == 'e' )
01175 {
01176 zero = 0.;
01177 two = 2.;
01178
01179 i__1 = -lt;
01180 a = pow_di( &base, &i__1);
01181 eps = a;
01182
01183 b = two / 3;
01184 half = one / 2;
01185 d__1 = -half;
01186 sixth = add( &b, &d__1 );
01187 third = add( &sixth, &sixth );
01188 d__1 = -half;
01189 b = add( &third, &d__1 );
01190 b = add( &b, &sixth );
01191 b = fabs(b);
01192 if( b < eps )
01193 b = eps;
01194
01195 eps = 1.;
01196
01197 while( eps > b && b > zero )
01198 {
01199 eps = b;
01200 d__1 = half * eps;
01201
01202 d__3 = two, d__4 = d__3, d__3 *= d__3;
01203
01204 d__5 = eps;
01205 d__2 = d__4 * (d__3 * d__3) * (d__5 * d__5);
01206 c = add(&d__1, &d__2);
01207 d__1 = -c;
01208 c = add(&half, &d__1);
01209 b = add(&half, &c);
01210 d__1 = -b;
01211 c = add(&half, &d__1);
01212 b = add(&half, &c);
01213 }
01214
01215 if( a < eps )
01216 eps = a;
01217
01218 if( rnd == 1 ){
01219 i__1 = 1 - lt;
01220 eps = pow_di(&base, &i__1) / 2;
01221 } else {
01222 i__1 = 1 - lt;
01223 eps = pow_di( &base, &i__1 );
01224 }
01225
01226 }
01227
01228 switch(*cmach){
01229 case 'B' :
01230 case 'b' : return base; break;
01231
01232 case 'M' :
01233 case 'm' : return lt; break;
01234
01235 case 'R' :
01236 case 'r' : return rnd; break;
01237
01238 case 'E' :
01239 case 'e' : return eps; break;
01240
01241 default : return -1;
01242 }
01243 }
01244
01245
01246
01247 void
01248 NumericLib::tred2(realvec &a, mrs_natural m, realvec &d, realvec &e)
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259 {
01260 mrs_natural l, k, j, i;
01261 mrs_real scale, hh, h, g, f;
01262
01263 for (i = m-1; i > 0; i--)
01264 {
01265 l = i - 1;
01266 h = scale = 0.0;
01267 if (l > 0)
01268 {
01269 for (k = 0; k <= l; k++)
01270 scale += fabs(a(k*m+i));
01271 if (scale == 0.0)
01272 e(i) = a(l*m+i);
01273 else
01274 {
01275 for (k = 0; k <= l; k++)
01276 {
01277 a(k*m+i) /= scale;
01278 h += a(k*m+i) * a(k*m+i);
01279 }
01280 f = a(l*m+i);
01281 g = f>0 ? -sqrt(h) : sqrt(h);
01282 e(i) = scale * g;
01283
01284 h -= f * g;
01285 a(l*m+i) = f - g ;
01286 f = 0.0;
01287 for (j = 0; j <= l; j++)
01288 {
01289 a(i*m+j) = a(j*m+i)/h;
01290 g = 0.0;
01291 for (k = 0; k <= j; k++)
01292 g += a(k*m+j) * a(k*m+i) ;
01293 for (k = j+1; k <= l; k++)
01294 g += a(j*m+k) * a(k*m+i);
01295 e(j) = g / h;
01296 f += e(j) * a(j*m+i);
01297 }
01298 hh = f / (h + h);
01299 for (j = 0; j <= l; j++)
01300 {
01301 f = a(j*m+i);
01302 e(j) = g = e(j) - hh * f;
01303 for (k = 0; k <= j; k++)
01304 a(k*m+j) -= (f * e(k) + g * a(k*m+i));
01305 }
01306 }
01307 }
01308 else
01309 e(i) = a(l*m+i);
01310 d(i) = h;
01311 }
01312 d(0) = 0.0;
01313 e(0) = 0.0;
01314 for (i = 0; i < m; ++i)
01315 {
01316 l = i - 1;
01317 if (d(i))
01318 {
01319 for (j = 0; j <= l; j++)
01320 {
01321 g = 0.0;
01322 for (k = 0; k <= l; k++)
01323 g += a(k*m+i) * a(j*m+k);
01324 for (k = 0; k <= l; k++)
01325 a(j*m+k) -= g * a(i*m+k);
01326 }
01327 }
01328 d(i) = a(i*m+i);
01329 a(i*m+i) = 1.0 ;
01330
01331 for (j = 0; j <= l; j++)
01332 a(i*m+j) = a(j*m+i) = 0.0;
01333 }
01334 }
01335
01336
01337 void
01338 NumericLib::tqli(realvec &d, realvec &e, mrs_natural m, realvec &z)
01339
01340
01341
01342
01343 {
01344 mrs_natural n, l, iter, i, j, k;
01345 mrs_real s, r, p, g, f, dd, c, b, tmp;
01346
01347 for (i = 1; i < m; ++i)
01348 e(i-1) = e(i);
01349 e(m-1) = 0.0;
01350 for (l = 0; l < m; l++)
01351 {
01352 iter = 0;
01353 do
01354 {
01355 for (n = l; n < m-1; n++)
01356 {
01357 dd = fabs(d(n)) + fabs(d(n+1));
01358 if (fabs(e(n)) + dd == dd) break;
01359 }
01360 if (n != l)
01361 {
01362
01363 if( iter++ == 30 )
01364 {
01365 cerr << "tqli did not converge!" << endl;
01366 MRSERR("NumericLib.cpp: tqli did not converge!");
01367 MRSASSERT(0);
01368 return;
01369
01370 }
01371
01372 g = (d(l+1) - d(l)) / (2.0 * e(l));
01373 r = sqrt((g * g) + 1.0);
01374 g = d(n) - d(l) + e(l) / (g + SIGN(r, g));
01375 s = c = 1.0;
01376 p = 0.0;
01377 for (i = n-1; i >= l; i--)
01378 {
01379 f = s * e(i);
01380 b = c * e(i);
01381 if (fabs(f) >= fabs(g))
01382 {
01383 c = g / f;
01384 r = sqrt((c * c) + 1.0);
01385 e(i+1) = f * r;
01386 c *= (s = 1.0/r);
01387 }
01388 else
01389 {
01390 s = f / g;
01391 r = sqrt((s * s) + 1.0);
01392 e(i+1) = g * r;
01393 s *= (c = 1.0/r);
01394 }
01395 g = d(i+1) - p;
01396 r = (d(i) - g) * s + 2.0 * c * b;
01397 p = s * r;
01398 d(i+1) = g + p;
01399 g = c * r - b;
01400 for (k = 0; k < m; k++)
01401 {
01402 f = z((i+1)*m+k);
01403 z((i+1)*m+k) = s * z(i*m+k) + c * f;
01404 z(i*m+k) = c * z(i*m+k) - s * f;
01405 }
01406 }
01407 d(l) = d(l) - p;
01408 e(l) = g;
01409 e(n) = 0.0;
01410 }
01411 } while (n != l);
01412
01413 }
01414
01415 for (i = 0; i < m-1; ++i) {
01416 k = i;
01417 tmp = d(i);
01418 for (j = i+1; j < m; j++) {
01419 if (d(j) < tmp) {
01420 k = j;
01421 tmp = d(j);
01422 }
01423 }
01424 if (k != i) {
01425 d(k) = d(i);
01426 d(i) = tmp;
01427 for (j = 0; j < m; j++) {
01428 tmp = z(i*m+j);
01429 z(i*m+j) = z(k*m+j);
01430 z(k*m+j) = tmp;
01431 }
01432 }
01433 }
01434
01435 }
01436
01437
01438
01439
01440
01441 void NumericLib::svd(mrs_natural m, mrs_natural n, realvec &A, realvec &U, realvec &V, realvec &s) {
01442
01443 mrs_natural nu = min(m,n);
01444 realvec e(n);
01445 realvec work(m);
01446 mrs_natural wantu = 1;
01447 mrs_natural wantv = 1;
01448 mrs_natural i=0, j=0, k=0;
01449
01450
01451
01452 mrs_natural nct = min(m-1,n);
01453 mrs_natural nrt = max((mrs_natural) 0,min(n-2,m));
01454 for (k = 0; k < max(nct,nrt); k++) {
01455 if (k < nct) {
01456
01457
01458
01459
01460 s(k) = 0;
01461 for (i = k; i < m; ++i) {
01462 #ifdef MARSYAS_WIN32
01463 s(k) = _hypot(s(k),A(k*m+i));
01464 #else
01465 s(k) = hypot(s(k),A(k*m+i));
01466 #endif
01467 }
01468 if (s(k) != 0.0) {
01469 if (A(k*m+k) < 0.0) {
01470 s(k) = -s(k);
01471 }
01472 for (i = k; i < m; ++i) {
01473 A(k*m+i) /= s(k);
01474 }
01475 A(k*m+k) += 1.0;
01476 }
01477 s(k) = -s(k);
01478 }
01479 for (j = k+1; j < n; j++) {
01480 if ((k < nct) && (s(k) != 0.0)) {
01481
01482
01483
01484 mrs_real t = 0;
01485 for (i = k; i < m; ++i) {
01486 t += A(k*m+i)*A(j*m+i);
01487 }
01488 t = -t/A(k*m+k);
01489 for (i = k; i < m; ++i) {
01490 A(j*m+i) += t*A(k*m+i);
01491 }
01492 }
01493
01494
01495
01496
01497 e(j) = A(j*m+k);
01498 }
01499 if (wantu & (k < nct)) {
01500
01501
01502
01503
01504 for (i = k; i < m; ++i) {
01505 U(k*m+i) = A(k*m+i);
01506 }
01507 }
01508 if (k < nrt) {
01509
01510
01511
01512
01513 e(k) = 0;
01514 for (i = k+1; i < n; ++i) {
01515 #ifdef MARSYAS_WIN32
01516 e(k) = _hypot(e(k),e(i));
01517 #else
01518 e(k) = hypot(e(k),e(i));
01519 #endif
01520
01521 }
01522 if (e(k) != 0.0) {
01523 if (e(k+1) < 0.0) {
01524 e(k) = -e(k);
01525 }
01526 for (i = k+1; i < n; ++i) {
01527 e(i) /= e(k);
01528 }
01529 e(k+1) += 1.0;
01530 }
01531 e(k) = -e(k);
01532 if ((k+1 < m) & (e(k) != 0.0)) {
01533
01534
01535
01536 for (i = k+1; i < m; ++i) {
01537 work(i) = 0.0;
01538 }
01539 for (j = k+1; j < n; j++) {
01540 for (i = k+1; i < m; ++i) {
01541 work(i) += e(j)*A(j*m+i);
01542 }
01543 }
01544 for (j = k+1; j < n; j++) {
01545 mrs_real t = -e(j)/e(k+1);
01546 for (i = k+1; i < m; ++i) {
01547 A(j*m+i) += t*work(i);
01548 }
01549 }
01550 }
01551 if (wantv) {
01552
01553
01554
01555
01556 for (i = k+1; i < n; ++i) {
01557 V(k*n+i) = e(i);
01558 }
01559 }
01560 }
01561 }
01562
01563
01564
01565 mrs_natural p = min(n,m+1);
01566 if (nct < n) {
01567 s(nct) = A(nct*m+nct);
01568 }
01569 if (m < p) {
01570 s(p-1) = 0.0;
01571 }
01572 if (nrt+1 < p) {
01573 e(nrt) = A((p-1)*m+nrt);
01574 }
01575 e(p-1) = 0.0;
01576
01577
01578
01579 if (wantu) {
01580 for (j = nct; j < nu; j++) {
01581 for (i = 0; i < m; ++i) {
01582 U(j*m+i) = 0.0;
01583 }
01584 U(j*m+j) = 1.0;
01585 }
01586 for (k = nct-1; k >= 0; k--) {
01587 if (s(k) != 0.0) {
01588 for (j = k+1; j < nu; j++) {
01589 mrs_real t = 0;
01590 for (i = k; i < m; ++i) {
01591 t += U(k*m+i)*U(j*m+i);
01592 }
01593 t = -t/U(k*m+k);
01594 for (i = k; i < m; ++i) {
01595 U(j*m+i) += t*U(k*m+i);
01596 }
01597 }
01598 for (i = k; i < m; ++i ) {
01599 U(k*m+i) = -U(k*m+i);
01600 }
01601 U(k*m+k) = 1.0 + U(k*m+k);
01602 for (i = 0; i < k-1; ++i) {
01603 U(k*m+i) = 0.0;
01604 }
01605 } else {
01606 for (i = 0; i < m; ++i) {
01607 U(k*m+i) = 0.0;
01608 }
01609 U(k*m+k) = 1.0;
01610 }
01611 }
01612 }
01613
01614
01615
01616 if (wantv) {
01617 for (k = n-1; k >= 0; k--) {
01618 if ((k < nrt) & (e(k) != 0.0)) {
01619 for (j = k+1; j < nu; j++) {
01620 mrs_real t = 0;
01621 for (i = k+1; i < n; ++i) {
01622 t += V(k*n+i)*V(j*n+i);
01623 }
01624 t = -t/V(k*n+(k+1));
01625 for (i = k+1; i < n; ++i) {
01626 V(j*n+i) += t*V(k*n+i);
01627 }
01628 }
01629 }
01630 for (i = 0; i < n; ++i) {
01631 V(k*n+i) = 0.0;
01632 }
01633 V(k*n+k) = 1.0;
01634 }
01635 }
01636
01637
01638
01639 mrs_natural pp = p-1;
01640 mrs_natural iter = 0;
01641
01642 mrs_real eps = std::numeric_limits<double>::epsilon();
01643
01644
01645
01646 while (p > 0) {
01647 mrs_natural k=0;
01648 mrs_natural kase=0;
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662 for (k = p-2; k >= -1; k--) {
01663 if (k == -1) {
01664 break;
01665 }
01666 if (fabs(e(k)) <= eps*(fabs(s(k)) + fabs(s(k+1)))) {
01667 e(k) = 0.0;
01668 break;
01669 }
01670 }
01671 if (k == p-2) {
01672 kase = 4;
01673 } else {
01674 mrs_natural ks;
01675 for (ks = p-1; ks >= k; ks--) {
01676 if (ks == k) {
01677 break;
01678 }
01679 mrs_real t = (ks != p ? fabs(e(ks)) : 0.) +
01680 (ks != k+1 ? fabs(e(ks-1)) : 0.);
01681 if (fabs(s(ks)) <= eps*t) {
01682 s(ks) = 0.0;
01683 break;
01684 }
01685 }
01686 if (ks == k) {
01687 kase = 3;
01688 } else if (ks == p-1) {
01689 kase = 1;
01690 } else {
01691 kase = 2;
01692 k = ks;
01693 }
01694 }
01695 k++;
01696
01697
01698
01699 switch (kase) {
01700
01701
01702
01703 case 1: {
01704 mrs_real f = e(p-2);
01705 e(p-2) = 0.0;
01706 for (j = p-2; j >= k; j--) {
01707 #ifdef MARSYAS_WIN32
01708 mrs_real t = _hypot(s(j),f);
01709 #else
01710 mrs_real t = hypot(s(j),f);
01711 #endif
01712
01713 mrs_real cs = s(j)/t;
01714 mrs_real sn = f/t;
01715 s(j) = t;
01716 if (j != k) {
01717 f = -sn*e(j-1);
01718 e(j-1) = cs*e(j-1);
01719 }
01720 if (wantv) {
01721 for (i = 0; i < n; ++i) {
01722 t = cs*V(j*n+i) + sn*V((p-1)*n+i);
01723 V((p-1)*n+i) = -sn*V(j*n+i) + cs*V((p-1)*n+i);
01724 V(j*n+i) = t;
01725 }
01726 }
01727 }
01728 }
01729 break;
01730
01731
01732
01733 case 2: {
01734 mrs_real f = e(k-1);
01735 e(k-1) = 0.0;
01736 for (j = k; j < p; j++) {
01737 #ifdef MARSYAS_WIN32
01738 mrs_real t = _hypot(s(j),f);
01739 #else
01740 mrs_real t = hypot(s(j),f);
01741 #endif
01742 mrs_real cs = s(j)/t;
01743 mrs_real sn = f/t;
01744 s(j) = t;
01745 f = -sn*e(j);
01746 e(j) = cs*e(j);
01747 if (wantu) {
01748 for (i = 0; i < m; ++i) {
01749 t = cs*U(j*m+i) + sn*U((k-1)*m+i);
01750 U((k-1)*m+i) = -sn*U(j*m+i) + cs*U((k-1)*m+i);
01751 U(j*m+i) = t;
01752 }
01753 }
01754 }
01755 }
01756 break;
01757
01758
01759
01760 case 3: {
01761
01762
01763
01764 mrs_real scale = max(max(max(max(
01765 fabs(s(p-1)),fabs(s(p-2))),fabs(e(p-2))),
01766 fabs(s(k))),fabs(e(k)));
01767 mrs_real sp = s(p-1)/scale;
01768 mrs_real spm1 = s(p-2)/scale;
01769 mrs_real epm1 = e(p-2)/scale;
01770 mrs_real sk = s(k)/scale;
01771 mrs_real ek = e(k)/scale;
01772 mrs_real b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0;
01773 mrs_real c = (sp*epm1)*(sp*epm1);
01774 mrs_real shift = 0.0;
01775 if ((b != 0.0) || (c != 0.0)) {
01776 shift = sqrt(b*b + c);
01777 if (b < 0.0) {
01778 shift = -shift;
01779 }
01780 shift = c/(b + shift);
01781 }
01782 mrs_real f = (sk + sp)*(sk - sp) + shift;
01783 mrs_real g = sk*ek;
01784
01785
01786
01787 for (j = k; j < p-1; j++) {
01788 #ifdef MARSYAS_WIN32
01789 mrs_real t = _hypot(f,g);
01790 #else
01791 mrs_real t = hypot(f,g);
01792 #endif
01793
01794 mrs_real cs = f/t;
01795 mrs_real sn = g/t;
01796 if (j != k) {
01797 e(j-1) = t;
01798 }
01799 f = cs*s(j) + sn*e(j);
01800 e(j) = cs*e(j) - sn*s(j);
01801 g = sn*s(j+1);
01802 s(j+1) = cs*s(j+1);
01803 if (wantv) {
01804 for (i = 0; i < n; ++i) {
01805 t = cs*V(j*n+i) + sn*V((j+1)*n+i);
01806 V((j+1)*n+i) = -sn*V(j*n+i) + cs*V((j+1)*n+i);
01807 V(j*n+i) = t;
01808 }
01809 }
01810 #ifdef MARSYAS_WIN32
01811 t = _hypot(f,g);
01812 #else
01813 t = hypot(f,g);
01814 #endif
01815 cs = f/t;
01816 sn = g/t;
01817 s(j) = t;
01818 f = cs*e(j) + sn*s(j+1);
01819 s(j+1) = -sn*e(j) + cs*s(j+1);
01820 g = sn*e(j+1);
01821 e(j+1) = cs*e(j+1);
01822 if (wantu && (j < m-1)) {
01823 for (i = 0; i < m; ++i) {
01824 t = cs*U(j*m+i) + sn*U((j+1)*m+i);
01825 U((j+1)*m+i) = -sn*U(j*m+i) + cs*U((j+1)*m+i);
01826 U(j*m+i) = t;
01827 }
01828 }
01829 }
01830 e(p-2) = f;
01831 iter = iter + 1;
01832 }
01833 break;
01834
01835
01836
01837 case 4: {
01838
01839
01840
01841 if (s(k) <= 0.0) {
01842 s(k) = (s(k) < 0.0 ? -s(k) : 0.0);
01843 if (wantv) {
01844 for (i = 0; i <= pp; ++i) {
01845 V(k*n+i) = -V(k*n+i);
01846 }
01847 }
01848 }
01849
01850
01851
01852 while (k < pp) {
01853 if (s(k) >= s(k+1)) {
01854 break;
01855 }
01856 mrs_real t = s(k);
01857 s(k) = s(k+1);
01858 s(k+1) = t;
01859 if (wantv && (k < n-1)) {
01860 for (i = 0; i < n; ++i) {
01861 t = V((k+1)*n+i); V((k+1)*n+i) = V(k*n+i); V(k*n+i) = t;
01862 }
01863 }
01864 if (wantu && (k < m-1)) {
01865 for (i = 0; i < m; ++i) {
01866 t = U((k+1)*m+i); U((k+1)*m+i) = U(k*m+i); U(k*m+i) = t;
01867 }
01868 }
01869 k++;
01870 }
01871 iter = 0;
01872 p--;
01873 }
01874 break;
01875 }
01876 }
01877 }
01878
01880
01882 mrs_real
01883 NumericLib::euclideanDistance(const realvec& Vi, const realvec& Vj, const realvec& covMatrix)
01884 {
01885 mrs_real res1;
01886 mrs_real res = 0;
01887
01888
01889
01890 if(covMatrix.getSize() == 0)
01891 {
01892 for (mrs_natural r=0 ; r < Vi.getSize() ; ++r)
01893 {
01894 res1 = Vi(r)-Vj(r);
01895 res1 *= res1;
01896 res += res1;
01897 }
01898 res = sqrt(res);
01899 }
01900 else if (covMatrix.sum () > 0)
01901 {
01902
01903
01904 for (mrs_natural r=0 ; r < Vi.getSize() ; ++r)
01905 {
01906 res1 = Vi(r)-Vj(r);
01907 res1 *= res1;
01908 res1 /= covMatrix(r,r);
01909 res += res1;
01910 }
01911 res = sqrt(res);
01912 }
01913 return res;
01914 }
01915
01916 mrs_real
01917 NumericLib::mahalanobisDistance(const realvec& Vi, const realvec& Vj, const realvec& covMatrix)
01918 {
01919
01920 (void) Vi;
01921 (void) Vj;
01922 (void) covMatrix;
01923
01924
01925
01926
01927 return MINREAL;
01928 }
01929
01930 mrs_real
01931 NumericLib::cosineDistance(const realvec& Vi, const realvec& Vj, const realvec& dummy)
01932 {
01933 (void) dummy;
01934
01935
01936 mrs_real res1 = 0;
01937 mrs_real res2 = 0;
01938 mrs_real res3 = 0;
01939 mrs_real res = 0;
01940 for (mrs_natural r=0 ; r < Vi.getSize() ; ++r)
01941 {
01942 res1 += Vi(r)*Vj(r);
01943 res2 += Vi(r)*Vi(r);
01944 res3 += Vj(r)*Vj(r);
01945 }
01946 if (res2!=0 && res3!=0)
01947 {
01948 res = res1/sqrt(res2 * res3);
01949 if(res > 1.0)
01950 {
01951 if (res-1.0 > 1e-6)
01952 MRSWARN("NumericLib::cosineDistance() - cosine similarity value is > 1.0 by " << res-1.0 << " -> setting value to 1.0!");
01953 res = 1.0;
01954 }
01955 return (1.0 - res);
01956 }
01957 else
01958 {
01959 MRSERR("NumericLib::cosineDistance() - at least one of the input points have small relative magnitudes, making it effectively zero... returning invalid value of -1.0!");
01960 return -1.0;
01961 }
01962 }
01963
01964 mrs_real
01965 NumericLib::cityblockDistance(const realvec& Vi, const realvec& Vj, const realvec& dummy)
01966 {
01967 (void) Vi; (void) Vj; (void) dummy;
01968 return MINREAL;
01969 }
01970
01971 mrs_real
01972 NumericLib::correlationDistance(const realvec& Vi, const realvec& Vj, const realvec& dummy)
01973 {
01974 (void) Vi; (void) Vj; (void) dummy;
01975 return MINREAL;
01976 }
01977
01978 mrs_real
01979 NumericLib::divergenceShape(const realvec& Ci, const realvec& Cj, const realvec& dummy)
01980 {
01981 (void) dummy;
01983 if(Ci.getCols() != Cj.getCols() && Ci.getRows() != Cj.getRows() &&
01984 Ci.getCols()!= Ci.getRows())
01985 {
01986 MRSERR("realvec::divergenceShape() : input matrices should be square and equal sized. Returning invalid value (-1.0)");
01987 return -1.0;
01988 }
01989
01990 realvec Cii = Ci;
01991 realvec Cjj = Cj;
01992
01993 mrs_real res;
01994
01995 realvec Citemp(Cii.getRows(), Cii.getCols());
01996 realvec invCi(Cii);
01997
01998 realvec Cjtemp(Cjj.getRows(),Cjj.getCols());
01999 realvec invCj(Cjj);
02000
02001 #ifdef _MATLAB_REALVEC_
02002 MATLAB_PUT(Cii, "Ci");
02003 MATLAB_PUT(Cjj, "Cj");
02004 MATLAB_PUT(Citemp, "Citemp");
02005 MATLAB_PUT(Cjtemp, "Cjtemp");
02006 #endif
02007
02008
02009 invCi.invert(Citemp);
02010 invCj.invert(Cjtemp);
02011
02012 #ifdef _MATLAB_REALVEC_
02013 MATLAB_PUT(Citemp, "Citemp2");
02014 MATLAB_PUT(Cjtemp, "Cjtemp2");
02015 MATLAB_PUT(invCi, "invCi");
02016 MATLAB_PUT(invCj, "invCj");
02017 #endif
02018
02019 Cjj *= (-1.0);
02020 Cii += Cjj;
02021
02022 #ifdef _MATLAB_REALVEC_
02023 MATLAB_PUT(Cii, "Ci_minus_Cj");
02024 #endif
02025
02026 invCi *= (-1.0);
02027 invCj += invCi;
02028
02029 #ifdef _MATLAB_REALVEC_
02030 MATLAB_PUT(invCj, "invCj_minus_invCi");
02031 #endif
02032
02033 Cii *= invCj;
02034
02035 res = Cii.trace() / 2.0;
02036
02037 #ifdef _MATLAB_REALVEC_
02038 MATLAB_PUT(Cii, "divergenceMatrix");
02039 MATLAB_PUT(res, "divergence");
02040 #endif
02041
02042 return res;
02043 }
02044
02045 mrs_real
02046 NumericLib::bhattacharyyaShape(const realvec& Ci, const realvec& Cj, const realvec& dummy)
02047 {
02048 (void) dummy;
02050 if(Ci.getCols() != Cj.getCols() && Ci.getRows() != Cj.getRows() &&
02051 Ci.getCols()!= Ci.getRows())
02052 {
02053 MRSERR("realvec::bhattacharyyaShape() : input matrices should be square and equal sized. Returning invalid value (-1.0)");
02054 return -1.0;
02055 }
02056
02057 realvec Cii = Ci;
02058 realvec Cjj = Cjj;
02059
02060
02061 mrs_real sqrtdetCi = sqrt(Cii.det());
02062 mrs_real sqrtdetCj = sqrt(Cjj.det());
02063 mrs_real den = sqrtdetCi * sqrtdetCj;
02064 #ifdef _MATLAB_REALVEC_
02065 MATLAB_PUT(Cii, "Ci");
02066 MATLAB_PUT(Cjj, "Cj");
02067 MATLAB_PUT(sqrtdetCi, "sqrtdetCi");
02068 MATLAB_PUT(sqrtdetCj, "sqrtdetCj");
02069 MATLAB_PUT(den, "den");
02070 #endif
02071
02072
02073 Cii += Cjj;
02074 Cii /= 2.0;
02075 mrs_real num = Cii.det();
02076
02077
02078 return log(num/den);
02079 }
02080
02082
02084 mrs_real
02085 NumericLib::hungarianAssignment(realvec& matrixdist, realvec& matrixAssign)
02086 {
02087 mrs_real cost;
02088
02089 mrs_natural rows = matrixdist.getRows();
02090 mrs_natural cols = matrixdist.getCols();
02091
02092 if(matrixAssign.getCols() != cols || matrixAssign.getRows() != 1)
02093 {
02094 MRSERR("NumericLib::hungarianAssignemnt - wrong size for matrix Assign!");
02095 return -1.0;
02096 }
02097
02098
02099 mrs_real* distMatrix = new mrs_real[rows * cols];
02100 for(mrs_natural r=0; r < rows; ++r)
02101 for(mrs_natural c = 0; c < cols; ++c)
02102 distMatrix[r*cols + c] = matrixdist(r,c);
02103
02104 mrs_natural* assignement = new mrs_natural[cols];
02105
02106 assignmentoptimal(assignement, &cost, distMatrix, rows, cols);
02107
02108
02109 for(mrs_natural i = 0; i < cols; ++i)
02110 matrixAssign(i) = assignement[i];
02111
02112 delete [] distMatrix;
02113 delete [] assignement;
02114
02115 return cost;
02116 }
02117
02118 mrs_real
02119 NumericLib::mxGetInf()
02120 {
02121 return numeric_limits<double>::infinity();
02122 }
02123 bool
02124 NumericLib::mxIsInf(mrs_real s)
02125 {
02126 return s == numeric_limits<double>::infinity() || s == -numeric_limits<double>::infinity();
02127 }
02128
02129 void
02130 NumericLib::mxFree( void * s )
02131 {
02132 free ( s );
02133 }
02134
02135 void
02136 NumericLib::mexErrMsgTxt(const char * s)
02137 {
02138 cout << s << endl;
02139 }
02140
02141 void
02142 NumericLib::assignmentoptimal(mrs_natural *assignment, mrs_real *cost, mrs_real *distMatrixIn, mrs_natural nOfRows, mrs_natural nOfColumns)
02143 {
02144
02145 mrs_real *distMatrix, *distMatrixTemp, *distMatrixEnd, value, minValue;
02146 bool *coveredColumns, *coveredRows, *starMatrix, *newStarMatrix, *primeMatrix;
02147 mrs_natural nOfElements, minDim, row, col;
02148 #ifdef CHECK_FOR_INF
02149 bool infiniteValueFound;
02150 mrs_real maxFiniteValue, infValue;
02151 #endif
02152
02153
02154 *cost = 0;
02155 for(row=0; row<nOfRows; row++)
02156
02157
02158
02159 assignment[row] = -1;
02160
02161
02162
02163
02164 nOfElements = nOfRows * nOfColumns;
02165 distMatrix = (mrs_real *)malloc(nOfElements * sizeof(mrs_real));
02166
02167
02168 distMatrixEnd = distMatrix + nOfElements;
02169 for(row=0; row<nOfElements; row++)
02170 {
02171 value = distMatrixIn[row];
02172
02173 if((( value > -numeric_limits<double>::infinity() && value < numeric_limits<double>::infinity())) && (value < 0))
02174 mexErrMsgTxt("All matrix elements have to be non-negative.");
02175 distMatrix[row] = value;
02176 }
02177
02178
02179
02180 #ifdef CHECK_FOR_INF
02181
02182 maxFiniteValue = -1;
02183 infiniteValueFound = false;
02184
02185 distMatrixTemp = distMatrix;
02186 while(distMatrixTemp < distMatrixEnd)
02187 {
02188 value = *distMatrixTemp++;
02189
02190 if ( value > -numeric_limits<double>::infinity() && value < numeric_limits<double>::infinity())
02191 {
02192 if(value > maxFiniteValue)
02193 maxFiniteValue = value;
02194 }
02195 else
02196 infiniteValueFound = true;
02197 }
02198 if(infiniteValueFound)
02199 {
02200 if(maxFiniteValue == -1)
02201 return;
02202
02203
02204 if(maxFiniteValue > 0)
02205 infValue = 10 * maxFiniteValue * nOfElements;
02206 else
02207 infValue = 10;
02208 distMatrixTemp = distMatrix;
02209 while(distMatrixTemp < distMatrixEnd)
02210 if(mxIsInf(*distMatrixTemp++))
02211 *(distMatrixTemp-1) = infValue;
02212 }
02213 #endif
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223 coveredColumns = (bool *)calloc(nOfColumns, sizeof(bool));
02224 coveredRows = (bool *)calloc(nOfRows, sizeof(bool));
02225 starMatrix = (bool *)calloc(nOfElements, sizeof(bool));
02226 primeMatrix = (bool *)calloc(nOfElements, sizeof(bool));
02227 newStarMatrix = (bool *)calloc(nOfElements, sizeof(bool));
02228
02229
02230 if(nOfRows <= nOfColumns)
02231 {
02232 minDim = nOfRows;
02233
02234 for(row=0; row<nOfRows; row++)
02235 {
02236
02237
02238
02239
02240 distMatrixTemp = distMatrix + row*nOfColumns;
02241 minValue = *distMatrixTemp;
02242
02243
02244
02245
02246
02247
02248
02249 for (mrs_natural i=1; i< nOfColumns; ++i){
02250 value = *(distMatrixTemp++);
02251 if (value < minValue)
02252 minValue = value;
02253 }
02254
02255
02256
02257
02258
02259
02260
02261
02262 distMatrixTemp = distMatrix + row*nOfColumns;
02263 for (mrs_natural i=0; i< nOfColumns; ++i)
02264 *(distMatrixTemp++) -= minValue;
02265
02266 }
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278 for(row=0; row<nOfRows; row++)
02279 for(col=0; col<nOfColumns; col++)
02280 if(distMatrix[row*nOfColumns + col] == 0)
02281 if(!coveredColumns[col])
02282 {
02283 starMatrix[row*nOfColumns + col] = true;
02284 coveredColumns[col] = true;
02285 break;
02286 }
02287
02288 }
02289 else
02290 {
02291 minDim = nOfColumns;
02292
02293 for(col=0; col<nOfColumns; col++)
02294 {
02295
02296
02297
02298 distMatrixTemp = distMatrix + col;
02299
02300
02301 minValue = *distMatrixTemp;
02302
02303
02304
02305
02306
02307
02308 for (mrs_natural i=1; i<nOfRows; ++i){
02309 value = *(distMatrixTemp + nOfColumns*i);
02310 if (value < minValue)
02311 minValue = value;
02312 }
02313
02314
02315
02316
02317
02318 distMatrixTemp = distMatrix + col;
02319 for (mrs_natural i=0; i<nOfRows; ++i)
02320 *(distMatrixTemp + nOfColumns*i) -= minValue;
02321
02322 }
02323
02324
02325 for(col=0; col<nOfColumns; col++)
02326 for(row=0; row<nOfRows; row++)
02327 if(distMatrix[row*nOfColumns + col] == 0)
02328 if(!coveredRows[row])
02329 {
02330 starMatrix[row*nOfColumns + col] = true;
02331 coveredColumns[col] = true;
02332 coveredRows[row] = true;
02333 break;
02334 }
02335 for(row=0; row<nOfRows; row++)
02336 coveredRows[row] = false;
02337
02338 }
02339
02340
02341
02342 step2b(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim);
02343
02344
02345 computeassignmentcost(assignment, cost, distMatrixIn, nOfRows, nOfColumns);
02346
02347
02348 mxFree(distMatrix);
02349 mxFree(coveredColumns);
02350 mxFree(coveredRows);
02351 mxFree(starMatrix);
02352 mxFree(primeMatrix);
02353 mxFree(newStarMatrix);
02354
02355 return;
02356 }
02357
02358 void
02359 NumericLib::buildassignmentvector(mrs_natural *assignment, bool *starMatrix, mrs_natural nOfRows, mrs_natural nOfColumns)
02360 {
02361 mrs_natural row, col;
02362
02363 for(row=0; row<nOfRows; row++)
02364 for(col=0; col<nOfColumns; col++)
02365
02366 if(starMatrix[row*nOfColumns + col])
02367 {
02368
02369
02370
02371 assignment[row] = col;
02372
02373 break;
02374 }
02375 }
02376
02377 void
02378 NumericLib::computeassignmentcost(mrs_natural *assignment, mrs_real *cost, mrs_real *distMatrix, mrs_natural nOfRows, mrs_natural nOfColumns)
02379 {
02380 mrs_natural row, col;
02381 #ifdef CHECK_FOR_INF
02382 mrs_real value;
02383 #endif
02384
02385 for(row=0; row<nOfRows; row++)
02386 {
02387
02388
02389
02390 col = assignment[row];
02391
02392
02393 if(col >= 0)
02394 {
02395 #ifdef CHECK_FOR_INF
02396 value = distMatrix[row + nOfRows*col];
02397
02398 if( value > -numeric_limits<double>::infinity() && value < numeric_limits<double>::infinity())
02399 *cost += value;
02400 else
02401
02402
02403
02404 assignment[row] = -1.0;
02405
02406
02407 #else
02408
02409 *cost += distMatrix[row*nOfColumns + col];
02410 #endif
02411 }
02412 }
02413 }
02414
02415 void
02416 NumericLib::step2a(mrs_natural *assignment, mrs_real *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, mrs_natural nOfRows, mrs_natural nOfColumns, mrs_natural minDim)
02417 {
02418 bool *starMatrixTemp;
02419 mrs_natural col;
02420
02421
02422 for(col=0; col<nOfColumns; col++)
02423 {
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433 starMatrixTemp = starMatrix + col;
02434 for (mrs_natural i=0; i< nOfRows; ++i){
02435 if (*(starMatrixTemp + nOfColumns*i)){
02436 coveredColumns[col] = true;
02437 break;
02438 }
02439 }
02440 }
02441
02442
02443 step2b(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim);
02444 }
02445
02446 void
02447 NumericLib::step2b(mrs_natural *assignment, mrs_real *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, mrs_natural nOfRows, mrs_natural nOfColumns, mrs_natural minDim)
02448 {
02449 mrs_natural col, nOfCoveredColumns;
02450
02451
02452 nOfCoveredColumns = 0;
02453 for(col=0; col<nOfColumns; col++)
02454 if(coveredColumns[col])
02455 nOfCoveredColumns++;
02456
02457 if(nOfCoveredColumns == minDim)
02458 {
02459
02460 buildassignmentvector(assignment, starMatrix, nOfRows, nOfColumns);
02461 }
02462 else
02463 {
02464
02465 step3(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim);
02466 }
02467
02468 }
02469
02470 void
02471 NumericLib::step3(mrs_natural *assignment, mrs_real *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, mrs_natural nOfRows, mrs_natural nOfColumns, mrs_natural minDim)
02472 {
02473 bool zerosFound;
02474 mrs_natural row, col, starCol;
02475
02476 zerosFound = true;
02477 while(zerosFound)
02478 {
02479 zerosFound = false;
02480 for(col=0; col<nOfColumns; col++)
02481 if(!coveredColumns[col])
02482 for(row=0; row<nOfRows; row++)
02483
02484 if((!coveredRows[row]) && (distMatrix[row*nOfColumns + col] == 0))
02485 {
02486
02487
02488 primeMatrix[row*nOfColumns + col] = true;
02489
02490
02491 for(starCol=0; starCol<nOfColumns; starCol++)
02492
02493 if(starMatrix[row*nOfColumns + starCol])
02494 break;
02495
02496
02497 if(starCol == nOfColumns)
02498 {
02499
02500 step4(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim, row, col);
02501 return;
02502 }
02503 else
02504 {
02505 coveredRows[row] = true;
02506 coveredColumns[starCol] = false;
02507 zerosFound = true;
02508 break;
02509 }
02510 }
02511 }
02512
02513
02514 step5(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim);
02515 }
02516
02517 void
02518 NumericLib::step4(mrs_natural *assignment, mrs_real *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, mrs_natural nOfRows, mrs_natural nOfColumns, mrs_natural minDim, mrs_natural row, mrs_natural col)
02519 {
02520 mrs_natural n, starRow, starCol, primeRow, primeCol;
02521 mrs_natural nOfElements = nOfRows*nOfColumns;
02522
02523
02524 for(n=0; n<nOfElements; n++)
02525 newStarMatrix[n] = starMatrix[n];
02526
02527
02528
02529 newStarMatrix[row*nOfColumns + col] = true;
02530
02531
02532 starCol = col;
02533 for(starRow=0; starRow<nOfRows; starRow++)
02534
02535 if(starMatrix[starRow*nOfColumns + starCol])
02536 break;
02537
02538 while(starRow<nOfRows)
02539 {
02540
02541
02542 newStarMatrix[starRow*nOfColumns + starCol] = false;
02543
02544
02545 primeRow = starRow;
02546 for(primeCol=0; primeCol<nOfColumns; primeCol++)
02547
02548 if(primeMatrix[primeRow*nOfColumns + primeCol])
02549 break;
02550
02551
02552
02553 newStarMatrix[primeRow*nOfColumns + primeCol] = true;
02554
02555
02556 starCol = primeCol;
02557 for(starRow=0; starRow<nOfRows; starRow++)
02558
02559 if(starMatrix[starRow*nOfColumns + starCol])
02560 break;
02561 }
02562
02563
02564
02565 for(n=0; n<nOfElements; n++)
02566 {
02567 primeMatrix[n] = false;
02568 starMatrix[n] = newStarMatrix[n];
02569 }
02570 for(n=0; n<nOfRows; n++)
02571 coveredRows[n] = false;
02572
02573
02574 step2a(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim);
02575 }
02576
02577 void
02578 NumericLib::step5(mrs_natural *assignment, mrs_real *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, mrs_natural nOfRows, mrs_natural nOfColumns, mrs_natural minDim)
02579 {
02580 mrs_real h, value;
02581 mrs_natural row, col;
02582
02583
02584 h = mxGetInf();
02585 for(row=0; row<nOfRows; row++)
02586 if(!coveredRows[row])
02587 for(col=0; col<nOfColumns; col++)
02588 if(!coveredColumns[col])
02589 {
02590
02591 value = distMatrix[row*nOfColumns + col];
02592 if(value < h)
02593 h = value;
02594 }
02595
02596
02597 for(row=0; row<nOfRows; row++)
02598 if(coveredRows[row])
02599 for(col=0; col<nOfColumns; col++)
02600
02601 distMatrix[row*nOfColumns + col] += h;
02602
02603
02604 for(col=0; col<nOfColumns; col++)
02605 if(!coveredColumns[col])
02606 for(row=0; row<nOfRows; row++)
02607
02608 distMatrix[row*nOfColumns + col] -= h;
02609
02610
02611 step3(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim);
02612 }