00001 #include "ReVolt.h"
00002 #include "Gaussian.h"
00003
00004
00005 #ifndef _PSX
00006 #include "main.h"
00007 #include "Geom.h"
00008 #endif
00009
00010 int SolveLinearEquations(BIGMAT *a, BIGVEC *b, REAL resTol, REAL coefTol, int *origRow, int *origCol, BIGVEC *z, BIGVEC *x);
00011 void ClearBigMat(BIGMAT *a);
00012 void ClearBigVec(BIGVEC *b);
00013 void CopyBigMat(BIGMAT *src, BIGMAT *dest);
00014 void BigMatMulVec(BIGMAT *matLeft, BIGVEC *vecRight, BIGVEC *vecOut);
00015 REAL BigVecDotVec(BIGVEC *vLeft, BIGVEC *vRight);
00016 void BigVecPlusScalarVec(BIGVEC *vLeft, REAL s, BIGVEC *vRight, BIGVEC *vOut);
00017 void ConjGrad(BIGMAT *A, BIGVEC *b, REAL tol, int maxIts, BIGVEC *x, REAL *res, int *nIts);
00018
00019 #ifdef DEBUG_SOLVER
00020 void TestSolver();
00021 void TestConjGrad();
00022 #endif
00023
00024
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00049
00050 int SolveLinearEquations(BIGMAT *a, BIGVEC *b, REAL resTol, REAL coefTol, int *origRow, int *origCol, BIGVEC *z, BIGVEC *x)
00051 {
00052 int ii, jj, kk;
00053 int nSolvable, tInt;
00054 int maxRow, maxCol;
00055 REAL maxCoef, maxRes;
00056 REAL tReal;
00057
00058
00059
00060 if (NRows(a) == 0) return 0;
00061
00062
00063 for (ii = 0; ii < NRows(a); ii++) {
00064 origRow[ii] = origCol[ii] = ii;
00065 }
00066
00067
00068
00069 for (kk = 0; kk < NRows(a); kk++) {
00070
00071
00072 maxRow = kk;
00073 maxRes = abs(b->v[maxRow]);
00074 for (ii = kk + 1; ii < NRows(a); ii++) {
00075 if (abs(b->v[ii]) > maxRes) {
00076 maxRes = abs(b->v[ii]);
00077 maxRow = ii;
00078 }
00079 }
00080
00081
00082
00083 if (maxRes < resTol) {
00084 break;
00085 }
00086
00087
00088 maxCol = kk;
00089 maxCoef = abs(a->m[maxRow][maxCol]);
00090 for (ii = kk + 1; ii < NRows(a); ii++) {
00091 if (abs(a->m[maxRow][ii]) > maxCoef) {
00092 maxCoef = abs(a->m[maxRow][ii]);
00093 maxCol = ii;
00094 }
00095 }
00096
00097
00098
00099 if (maxCoef < coefTol) {
00100 maxCoef = ZERO;
00101 for (ii = kk; ii < NRows(a); ii++) {
00102 for (jj = kk; jj < NRows(a); jj++) {
00103 if (abs(a->m[ii][jj]) > maxCoef) {
00104 maxCoef = abs(a->m[ii][jj]);
00105 maxRow = ii;
00106 maxCol = jj;
00107 }
00108 }
00109 }
00110
00111
00112 if (maxCoef < coefTol) {
00113 break;
00114 }
00115 }
00116
00117
00118
00119 if (maxRow != kk) {
00120 for (jj = 0; jj < NRows(a); jj++) {
00121 tReal = a->m[kk][jj];
00122 a->m[kk][jj] = a->m[maxRow][jj];
00123 a->m[maxRow][jj] = tReal;
00124 }
00125 tReal = b->v[kk];
00126 b->v[kk] = b->v[maxRow];
00127 b->v[maxRow] = tReal;
00128 tInt = origRow[kk];
00129 origRow[kk] = origRow[maxRow];
00130 origRow[maxRow] = tInt;
00131 }
00132
00133
00134
00135 if (maxCol != kk) {
00136 for (jj = 0; jj < NRows(a); jj++) {
00137 tReal = a->m[jj][kk];
00138 a->m[jj][kk] = a->m[jj][maxCol];
00139 a->m[jj][maxCol] = tReal;
00140 }
00141 tInt = origCol[kk];
00142 origCol[kk] = origCol[maxCol];
00143 origCol[maxCol] = tInt;
00144 }
00145
00146
00147 tReal = - ONE / a->m[kk][kk];
00148
00149 for (ii = kk + 1; ii < NRows(a); ii++) {
00150 a->m[ii][kk] *= tReal;
00151 }
00152
00153 for (jj = kk + 1; jj < NRows(a); jj++) {
00154 tReal = a->m[kk][jj];
00155 for (ii = kk + 1; ii < NRows(a); ii++) {
00156 a->m[ii][jj] += tReal * a->m[ii][kk];
00157 }
00158 }
00159
00160 tReal = b->v[kk];
00161 for (ii = kk + 1; ii < NRows(a); ii++) {
00162 b->v[ii] += tReal * a->m[ii][kk];
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 }
00175
00176
00177
00178 if (abs(b->v[kk - 1]) < resTol) {
00179 nSolvable = kk -1;
00180 } else {
00181 nSolvable = kk;
00182 }
00183
00184
00185 if (nSolvable <= 0) {
00186 return 0;
00187 }
00188
00189
00190 if (nSolvable > 1) {
00191 for (jj = nSolvable - 1; jj > 0; jj--) {
00192 z->v[jj] = b->v[jj] / a->m[jj][jj];
00193 tReal = - z->v[jj];
00194 for (ii = 0; ii < jj; ii++) {
00195 b->v[ii] += tReal * a->m[ii][jj];
00196 }
00197 }
00198 }
00199 z->v[0] = b->v[0] / a->m[0][0];
00200
00201
00202 for (ii = nSolvable; ii < NRows(a); ii++) {
00203 z->v[ii] = ZERO;
00204 }
00205
00206
00207 for (ii = 0; ii < NRows(a); ii++) {
00208 x->v[origCol[ii]] = z->v[ii];
00209 }
00210
00211 return nSolvable;
00212 }
00213
00214
00215
00216
00218
00219
00220
00222
00223 void ClearBigMat(BIGMAT *a)
00224 {
00225 int i,j;
00226
00227 for (i = 0; i < NRows(a); i++) {
00228 for (j = 0; j < NCols(a); j++) {
00229 a->m[i][j] = ZERO;
00230 }
00231 }
00232 }
00233
00234 void ClearBigVec(BIGVEC *b)
00235 {
00236 int i;
00237
00238 for (i = 0; i < NSize(b); i++) {
00239 b->v[i] = ZERO;
00240 }
00241 }
00242
00243 void CopyBigMat(BIGMAT *src, BIGMAT *dest)
00244 {
00245 int i, j;
00246
00247 SetBigMatSize((dest), NRows(src), NCols(src));
00248 for (i = 0; i < NRows(src); i++) {
00249 for (j = 0; j < NCols(src); j++) {
00250 (dest)->m[i][j] = (src)->m[i][j];
00251 }
00252 }
00253 }
00254
00255 void CopyBigVec(BIGVEC *src, BIGVEC *dest)
00256 {
00257 int i;
00258
00259 SetBigVecSize((dest), NSize(src));
00260 for (i = 0; i < NSize(src); i++) {
00261 (dest)->v[i] = (src)->v[i];
00262 }
00263 }
00264
00265 void BigMatMulVec(BIGMAT *matLeft, BIGVEC *vecRight, BIGVEC *vecOut)
00266 {
00267 int ii, jj;
00268
00269 if (NCols(matLeft) != NSize(vecRight)) return;
00270
00271 for (ii = 0; ii < NRows(matLeft); ii++) {
00272 vecOut->v[ii] = ZERO;
00273 for (jj = 0; jj < NCols(matLeft); jj++) {
00274 vecOut->v[ii] += MulScalar(matLeft->m[ii][jj], vecRight->v[jj]);
00275 }
00276 }
00277 }
00278
00279 REAL BigVecDotVec(BIGVEC *vLeft, BIGVEC *vRight)
00280 {
00281 int ii;
00282 REAL dot;
00283
00284 Assert(NSize(vLeft) == NSize(vRight));
00285
00286 dot = ZERO;
00287 for (ii = 0; ii < NSize(vLeft); ii++) {
00288 dot += MulScalar(vLeft->v[ii], vRight->v[ii]);
00289 }
00290
00291 return dot;
00292 }
00293
00294 void BigVecPlusScalarVec(BIGVEC *vLeft, REAL s, BIGVEC *vRight, BIGVEC *vOut)
00295 {
00296 int ii;
00297
00298 Assert(NSize(vLeft) == NSize(vRight));
00299
00300 for (ii = 0; ii < NSize(vLeft); ii++) {
00301 vOut->v[ii] = vLeft->v[ii] + MulScalar(s, vRight->v[ii]);
00302 }
00303
00304 }
00305
00306
00307
00309
00310
00311
00313 #if DEBUG_SOLVER
00314 static BIGMAT Coef, OrigCoef;
00315 static BIGVEC Res, NewRes, OrigRes;
00316 static BIGVEC Soln;
00317 static BIGVEC Work;
00318 static int OrigRow[BIG_NMAX];
00319 static int OrigCol[BIG_NMAX];
00320
00321
00322 void TestSolver()
00323 {
00324 int ii, kk;
00325 REAL xx;
00326
00328
00329
00330 SetBigMatSize(&Coef, 4, 4);
00331 SetBigVecSize(&Res, 4);
00332
00333 Coef.m[0][0] = 1.0f;
00334 Coef.m[0][1] = 0.0f;
00335 Coef.m[0][2] = 1.0f;
00336 Coef.m[0][3] = 0.0f;
00337
00338 Coef.m[1][0] = 1.0f;
00339 Coef.m[1][1] = 0.0f;
00340 Coef.m[1][2] = 1.0f;
00341 Coef.m[1][3] = 0.0f;
00342
00343 Coef.m[2][0] = 0.0f;
00344 Coef.m[2][1] = 1.0f;
00345 Coef.m[2][2] = 0.0f;
00346 Coef.m[2][3] = 1.0f;
00347
00348 Coef.m[3][0] = 0.0f;
00349 Coef.m[3][1] = 1.0f;
00350 Coef.m[3][2] = 1.0f;
00351 Coef.m[3][3] = 1.0f;
00352
00353 Res.v[0] = 2.0f;
00354 Res.v[1] = 2.0f;
00355 Res.v[2] = 2.0f;
00356 Res.v[3] = 2.0f;
00357
00358 SolveLinearEquations(&Coef, &Res, 0.0001f, 0.01f, OrigRow, OrigCol, &Work, &Soln);
00359
00360
00362
00363
00364 SetBigMatSize(&Coef, 2, 2);
00365 SetBigVecSize(&Res, 2);
00366
00367 Coef.m[0][0] = 1.0f;
00368 Coef.m[0][1] = 0.0f;
00369 Coef.m[1][0] = 1.01f;
00370 Coef.m[1][1] = 0.0f;
00371
00372 Res.v[0] = 2.0f;
00373 Res.v[1] = 1.0f;
00374
00375 SolveLinearEquations(&Coef, &Res, 0.0001f, 0.01f, OrigRow, OrigCol, &Work, &Soln);
00376
00377
00379
00380
00381 SetBigMatSize(&Coef, 5, 5);
00382 SetBigVecSize(&Res, 5);
00383 SetBigVecSize(&Soln, 5);
00384 for (ii = 0; ii < NRows(&Coef); ii++) {
00385 xx = (ii + 1) * Real(0.25);
00386 for (kk = 0; kk < NRows(&Coef); kk++) {
00387 Coef.m[ii][kk] = (REAL)pow(xx, kk + 1);
00388 }
00389 Res.v[ii] = xx * (REAL)exp(-xx);
00390 }
00391 CopyBigMat(&Coef, &OrigCoef);
00392 CopyBigVec(&Res, &OrigRes);
00393 SolveLinearEquations(&Coef, &Res, 0.0f, 0.0001f, OrigRow, OrigCol, &Work, &Soln);
00394
00395 BigMatMulVec(&OrigCoef, &Soln, &NewRes);
00396
00398
00399
00400 SetBigMatSize(&Coef, 9, 9);
00401 SetBigVecSize(&Res, 9);
00402 SetBigVecSize(&Soln, 9);
00403 ClearBigMat(&Coef);
00404 ClearBigVec(&Res);
00405
00406 for (ii = 0; ii < NRows(&Coef); ii++) {
00407 xx = ii / Real(8.0);
00408 Coef.m[ii][0] = ONE;
00409 Coef.m[ii][1] = xx;
00410 Coef.m[ii][2] = xx - ONE;
00411 Coef.m[ii][3] = (REAL)pow(xx, 2);
00412 Coef.m[ii][4] = (REAL)pow(xx, 2) - xx;
00413 Coef.m[ii][5] = (REAL)pow(xx, 3);
00414 Coef.m[ii][6] = (REAL)pow(xx, 3) - (REAL)pow(xx, 2);
00415 Coef.m[ii][7] = (REAL)pow(xx, 4);
00416 Coef.m[ii][8] = (REAL)pow(xx, 4) - (REAL)pow(xx, 3);
00417 Res.v[ii] = (REAL)exp(xx);
00418 }
00419 CopyBigMat(&Coef, &OrigCoef);
00420 CopyBigVec(&Res, &OrigRes);
00421 SolveLinearEquations(&Coef, &Res, 0.0f, 0.0001f, OrigRow, OrigCol, &Work, &Soln);
00422
00423 BigMatMulVec(&OrigCoef, &Soln, &NewRes);
00424
00426
00427
00428 SetBigMatSize(&Coef, 2, 2);
00429 SetBigVecSize(&Res, 2);
00430 SetBigVecSize(&Soln, 2);
00431 ClearBigMat(&Coef);
00432 ClearBigVec(&Res);
00433
00434 Coef.m[0][0] = ONE;
00435 Coef.m[0][1] = ZERO;
00436 Coef.m[1][0] = ZERO;
00437 Coef.m[1][1] = 0.00001f;
00438 Res.v[0] = ONE;
00439 Res.v[1] = 1.00001f;
00440
00441 CopyBigMat(&Coef, &OrigCoef);
00442 CopyBigVec(&Res, &OrigRes);
00443 SolveLinearEquations(&Coef, &Res, 0.0f, 0.0001f, OrigRow, OrigCol, &Work, &Soln);
00444
00445 BigMatMulVec(&OrigCoef, &Soln, &NewRes);
00446
00447 }
00448
00449
00450 void TestConjGrad()
00451 {
00452 int ii, kk, nIts;
00453 REAL res;
00454 float xx;
00455
00457
00458
00459 SetBigMatSize(&Coef, 4, 4);
00460 SetBigVecSize(&Res, 4);
00461 SetBigVecSize(&Soln, 4);
00462
00463 Coef.m[0][0] = ONE;
00464 Coef.m[0][1] = ZERO;
00465 Coef.m[0][2] = ZERO;
00466 Coef.m[0][3] = ZERO;
00467
00468 Coef.m[1][0] = ZERO;
00469 Coef.m[1][1] = ONE;
00470 Coef.m[1][2] = ZERO;
00471 Coef.m[1][3] = ZERO;
00472
00473 Coef.m[2][0] = ZERO;
00474 Coef.m[2][1] = ZERO;
00475 Coef.m[2][2] = ZERO;
00476 Coef.m[2][3] = ONE;
00477
00478 Coef.m[3][0] = ZERO;
00479 Coef.m[3][1] = ZERO;
00480 Coef.m[3][2] = ONE;
00481 Coef.m[3][3] = ZERO;
00482
00483 Res.v[0] = Real(1.0);
00484 Res.v[1] = Real(5.0);
00485 Res.v[2] = Real(1.0);
00486 Res.v[3] = Real(2.0);
00487
00488 ConjGrad(&Coef, &Res, Real(0.0001), 10, &Soln, &res, &nIts);
00489
00490 #ifdef _PSX
00491 printf("Solution:\n%d %d %d %d\n", Soln.v[0], Soln.v[1], Soln.v[2], Soln.v[3]);
00492 printf("Res: %d Its: %d\n", res, nIts);
00493 #endif
00494
00496
00497
00498 SetBigMatSize(&Coef, 2, 2);
00499 SetBigVecSize(&Res, 2);
00500
00501 Coef.m[0][0] = ONE;
00502 Coef.m[0][1] = ZERO;
00503 Coef.m[1][0] = ONE;
00504 Coef.m[1][1] = ZERO;
00505
00506 Res.v[0] = Real(2.0f);
00507 Res.v[1] = Real(1.0f);
00508
00509 ConjGrad(&Coef, &Res, Real(0.0001), 10, &Soln, &res, &nIts);
00510
00511 #ifdef _PSX
00512 printf("Solution:\n%d %d\n", Soln.v[0], Soln.v[1]);
00513 printf("Res: %d Its: %d\n", res, nIts);
00514 #endif
00515
00516
00518
00519
00520 SetBigMatSize(&Coef, 5, 5);
00521 SetBigVecSize(&Res, 5);
00522 SetBigVecSize(&Soln, 5);
00523 for (ii = 0; ii < NRows(&Coef); ii++) {
00524 xx = (ii + 1) * 0.25f;
00525 for (kk = 0; kk < NRows(&Coef); kk++) {
00526 Coef.m[ii][kk] = (REAL)pow(xx, kk + 1);
00527 }
00528 xx = xx * (float)exp(-xx);
00529 Res.v[ii] = Real(xx);
00530 }
00531 CopyBigMat(&Coef, &OrigCoef);
00532 CopyBigVec(&Res, &OrigRes);
00533 ConjGrad(&Coef, &Res, Real(0.0001), 10, &Soln, &res, &nIts);
00534
00535 #ifdef _PSX
00536 printf("Solution:\n%d %d %d %d %d\n", Soln.v[0], Soln.v[1], Soln.v[2], Soln.v[3], Soln.v[4]);
00537 printf("Res: %d Its: %d\n", res, nIts);
00538 #endif
00539
00540
00541 BigMatMulVec(&OrigCoef, &Soln, &NewRes);
00542
00544
00545
00546 SetBigMatSize(&Coef, 9, 9);
00547 SetBigVecSize(&Res, 9);
00548 SetBigVecSize(&Soln, 9);
00549 ClearBigMat(&Coef);
00550 ClearBigVec(&Res);
00551
00552 for (ii = 0; ii < NRows(&Coef); ii++) {
00553 xx = ii / 8.0f;
00554 Coef.m[ii][0] = ONE;
00555 Coef.m[ii][1] = Real(xx);
00556 Coef.m[ii][2] = Real(xx - 1.0f);
00557 Coef.m[ii][3] = Real(pow(xx, 2));
00558 Coef.m[ii][4] = Real(pow(xx, 2) - xx);
00559 Coef.m[ii][5] = Real(pow(xx, 3));
00560 Coef.m[ii][6] = Real(pow(xx, 3) - pow(xx, 2));
00561 Coef.m[ii][7] = Real(pow(xx, 4));
00562 Coef.m[ii][8] = Real(pow(xx, 4) - pow(xx, 3));
00563 Res.v[ii] = Real(exp(xx));
00564 }
00565 CopyBigMat(&Coef, &OrigCoef);
00566 CopyBigVec(&Res, &OrigRes);
00567 ConjGrad(&Coef, &Res, Real(0.0001), 100, &Soln, &res, &nIts);
00568
00569 #ifdef _PSX
00570 printf("Solution:\n%d %d %d %d\n%d %d %d %d\n", Soln.v[0], Soln.v[1], Soln.v[2], Soln.v[3], Soln.v[4], Soln.v[5], Soln.v[6], Soln.v[7]);
00571 printf("Res: %d Its: %d\n", res, nIts);
00572 #endif
00573
00574
00575 BigMatMulVec(&OrigCoef, &Soln, &NewRes);
00576
00578
00579
00580 SetBigMatSize(&Coef, 2, 2);
00581 SetBigVecSize(&Res, 2);
00582 SetBigVecSize(&Soln, 2);
00583 ClearBigMat(&Coef);
00584 ClearBigVec(&Res);
00585
00586 Coef.m[0][0] = ONE;
00587 Coef.m[0][1] = ZERO;
00588 Coef.m[1][0] = ONE;
00589 Coef.m[1][1] = Real(0.001);
00590 Res.v[0] = ONE;
00591 Res.v[1] = Real(1.001);
00592
00593 CopyBigMat(&Coef, &OrigCoef);
00594 CopyBigVec(&Res, &OrigRes);
00595 ConjGrad(&Coef, &Res, Real(0.001), 10, &Soln, &res, &nIts);
00596
00597 #ifdef _PSX
00598 printf("Solution:\n%d %d\n", Soln.v[0], Soln.v[1]);
00599 printf("Res: %d Its: %d\n", res, nIts);
00600 #endif
00601
00602 BigMatMulVec(&OrigCoef, &Soln, &NewRes);
00603
00605
00606
00607 SetBigMatSize(&Coef, 1, 1);
00608 SetBigVecSize(&Res, 1);
00609 SetBigVecSize(&Soln, 1);
00610 ClearBigMat(&Coef);
00611 ClearBigVec(&Res);
00612
00613 Coef.m[0][0] = Real(0.908250);
00614 Res.v[0] = Real(0.002644);
00615
00616 CopyBigMat(&Coef, &OrigCoef);
00617 CopyBigVec(&Res, &OrigRes);
00618 ConjGrad(&Coef, &Res, Real(0.001), 10, &Soln, &res, &nIts);
00619
00620 #ifdef _PSX
00621 printf("Solution:\n%d %d\n", Soln.v[0], Soln.v[1]);
00622 printf("Res: %d Its: %d\n", res, nIts);
00623 #endif
00624
00625 BigMatMulVec(&OrigCoef, &Soln, &NewRes);
00626
00627 }
00628 #endif
00629
00630 bool CheckSolution(BIGMAT *origCoef, BIGVEC *origRes, BIGVEC *soln, BIGVEC *newRes, REAL error)
00631 {
00632 int ii;
00633 REAL diff, diffSq;
00634 bool solnOkay = TRUE;
00635
00636
00637 BigMatMulVec(origCoef, soln, newRes);
00638
00639 for (ii = 0; ii < NRows(origCoef); ii++) {
00640 diff = newRes->v[ii] - origRes->v[ii];
00641 diffSq = diff * diff;
00642 if (abs(diff) > error) {
00643 solnOkay = FALSE;
00644 }
00645 }
00646
00647 return solnOkay;
00648 }
00649
00650
00651
00653
00654
00655
00656
00658
00659 BIGVEC r, p, t;
00660
00661 void ConjGrad(BIGMAT *A, BIGVEC *b, REAL tol, int maxIts, BIGVEC *x, REAL *res, int *nIts)
00662 {
00663 REAL alpha, beta;
00664 REAL rSq, rSqOld, rNorm, pDott;
00665 bool terminate = FALSE;;
00666
00667 Assert((tol > ZERO) && (maxIts > 0));
00668
00669
00670 SetBigVecSize(&r, NSize(b));
00671 SetBigVecSize(&t, NSize(b));
00672 SetBigVecSize(x, NSize(b));
00673 ClearBigVec(x);
00674 CopyBigVec(b, &p);
00675 CopyBigVec(b, &r);
00676 beta = ZERO;
00677 rSq = ZERO;
00678 rNorm = MulScalar( Real(2), tol );
00679
00680
00681 *nIts = 0;
00682
00683 do {
00684
00685 rSqOld = rSq;
00686 rSq = BigVecDotVec(&r, &r);
00687
00688 #ifdef _PSX
00689 rNorm = SquareRoot1616(rSq);
00690 #else
00691 rNorm = (REAL)sqrt(rSq);
00692 #endif
00693
00694 if ((*nIts < maxIts) && ((*res = rNorm - tol) > ZERO)) {
00695
00696 if (*nIts > 0) {
00697
00698
00699
00700
00701
00702
00703
00704 beta = DivScalar( rSq, rSqOld);
00705 BigVecPlusScalarVec(&r, beta, &p, &p);
00706 }
00707
00708 BigMatMulVec(A, &p, &t);
00709
00710 pDott = BigVecDotVec(&p, &t);
00711 if (abs(pDott) > SMALL_REAL) {
00712 alpha = DivScalar( rSq, pDott);
00713 BigVecPlusScalarVec(x, alpha, &p, x);
00714
00715 BigMatMulVec(A, &p, &t);
00716 BigVecPlusScalarVec(&r, -alpha, &t, &r);
00717 (*nIts)++;
00718 } else {
00719 terminate = TRUE;
00720 }
00721 } else {
00722 terminate = TRUE;
00723 }
00724
00725 } while(!terminate);
00726 }