[BACK]Return to multprec_complex_linear_solvers.adb CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / PHC / Ada / Math_Lib / Matrices

Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Matrices/multprec_complex_linear_solvers.adb, Revision 1.1.1.1

1.1       maekawa     1: with Multprec_Complex_Numbers;           use Multprec_Complex_Numbers;
                      2:
                      3: package body Multprec_Complex_Linear_Solvers is
                      4:
                      5: -- AUXLILIARIES :
                      6:
                      7:   function dconjg ( x : Complex_Number ) return Complex_Number is
                      8:
                      9:   -- DESCRIPTION :
                     10:   --   Returns the complex conjugate of x.
                     11:
                     12:     res : Complex_Number;
                     13:     re : Floating_Number := REAL_PART(x);
                     14:     im : Floating_Number := IMAG_PART(x);
                     15:
                     16:   begin
                     17:     Min(im);
                     18:     res := Create(re,im);
                     19:     Clear(re); Clear(im);
                     20:     return res;
                     21:   end dconjg;
                     22:
                     23:   function csign ( x,y : Complex_Number ) return Complex_Number is
                     24:
                     25:   -- DESCRIPTION :
                     26:   --   Returns |x|*y/|y|.
                     27:
                     28:     res : Complex_Number;
                     29:     fltacc : Floating_Number;
                     30:     cmpacc : Complex_Number;
                     31:
                     32:   begin
                     33:     fltacc := AbsVal(x);
                     34:     res := Create(fltacc);
                     35:     Clear(fltacc);
                     36:     Mul(res,y);
                     37:     fltacc := AbsVal(y);
                     38:     cmpacc := Create(fltacc);
                     39:     Div(res,cmpacc);
                     40:     Clear(fltacc);
                     41:     Clear(cmpacc);
                     42:     return res;
                     43:   end csign;
                     44:
                     45:   function Inverse_Abs_Sum ( z : Vector ) return Floating_Number is
                     46:
                     47:   -- DESCRIPTION :
                     48:   --   Returns the reciprocal of the sum of the absolute values in z.
                     49:
                     50:     res,sum,acc : Floating_Number;
                     51:
                     52:   begin
                     53:     sum := Create(0);
                     54:     for i in z'range loop
                     55:       acc := AbsVal(z(i));
                     56:       Add(sum,acc);
                     57:       Clear(acc);
                     58:     end loop;
                     59:     res := Create(1);
                     60:     Div(res,sum);
                     61:     Clear(sum);
                     62:     return res;
                     63:   end Inverse_Abs_Sum;
                     64:
                     65: -- TARGET ROUTINES :
                     66:
                     67:   procedure Scale ( a : in out Matrix; b : in out Vector ) is
                     68:
                     69:     fac : Complex_Number;
                     70:
                     71:     function Maximum ( a : in Matrix; i : in integer ) return Complex_Number is
                     72:
                     73:       res : integer := a'first(2);
                     74:       max : Floating_Number := AbsVal(a(i,res));
                     75:       tmp : Floating_Number;
                     76:
                     77:     begin
                     78:       for j in a'first(2)+1..a'last(2) loop
                     79:         tmp := AbsVal(a(i,j));
                     80:         if tmp > max
                     81:          then max := tmp; res := j;
                     82:         end if;
                     83:       end loop;
                     84:       return a(i,res);
                     85:     end Maximum;
                     86:
                     87:     procedure Divide ( a : in out Matrix; b : in out Vector;
                     88:                        i : in integer; fac : in Complex_Number ) is
                     89:     begin
                     90:       for j in a'range(2) loop
                     91:         a(i,j) := a(i,j)/fac;
                     92:       end loop;
                     93:       b(i) := b(i)/fac;
                     94:     end Divide;
                     95:
                     96:   begin
                     97:     for i in a'range(1) loop
                     98:       fac := Maximum(a,i);
                     99:       Divide(a,b,i,fac);
                    100:     end loop;
                    101:   end Scale;
                    102:
                    103: -- TARGET ROUTINES :
                    104:
                    105:   procedure lufac ( a : in out Matrix; n : in integer;
                    106:                     ipvt : out Standard_Natural_Vectors.Vector;
                    107:                     info : out natural ) is
                    108:
                    109:     kp1,l,nm1 : integer;
                    110:     smax,fltacc : Floating_Number;
                    111:     temp,cmpacc : Complex_Number;
                    112:
                    113:   begin
                    114:     info := 0;
                    115:     nm1 := n - 1;
                    116:     if nm1 >= 1
                    117:      then for k in 1..nm1 loop
                    118:             kp1 := k + 1;
                    119:             l := k;
                    120:             smax := AbsVal(a(k,k));                  -- find the pivot index l
                    121:             for i in kp1..n loop
                    122:               fltacc := AbsVal(a(i,k));
                    123:               if fltacc > smax
                    124:                then l := i;
                    125:                     Copy(fltacc,smax);
                    126:               end if;
                    127:               Clear(fltacc);
                    128:             end loop;
                    129:             ipvt(k) := l;
                    130:             if Equal(smax,0.0)       -- this column is already triangularized
                    131:              then info := k;
                    132:              else if l /= k                       -- interchange if necessary
                    133:                    then Copy(a(l,k),temp);
                    134:                         Copy(a(k,k),a(l,k));
                    135:                         Copy(temp,a(k,k)); Clear(temp);
                    136:                   end if;
                    137:                   cmpacc := Create(1);                 -- compute multipliers
                    138:                   Div(cmpacc,a(k,k));
                    139:                   Min(cmpacc);
                    140:                   for i in kp1..n loop
                    141:                     Mul(a(i,k),cmpacc);
                    142:                   end loop;
                    143:                   Clear(cmpacc);
                    144:                   for j in kp1..n loop                     -- row elimination
                    145:                     Copy(a(l,j),temp);
                    146:                     if l /= k
                    147:                      then Copy(a(k,j),a(l,j));
                    148:                           Copy(temp,a(k,j));
                    149:                     end if;
                    150:                     for i in kp1..n loop
                    151:                       cmpacc := temp*a(i,k);
                    152:                       Add(a(i,j),cmpacc);
                    153:                       Clear(cmpacc);
                    154:                     end loop;
                    155:                   end loop;
                    156:                   Clear(temp);
                    157:             end if;
                    158:             Clear(smax);
                    159:          end loop;
                    160:     end if;
                    161:     ipvt(n) := n;
                    162:     fltacc := AbsVal(a(n,n));
                    163:     if Equal(fltacc,0.0)
                    164:      then info := n;
                    165:     end if;
                    166:     Clear(fltacc);
                    167:   end lufac;
                    168:
                    169:   procedure lufco ( a : in out Matrix; n : in integer;
                    170:                     ipvt : out Standard_Natural_Vectors.Vector;
                    171:                     rcond : out Floating_Number ) is
                    172:
                    173:   -- NOTE :
                    174:   --   rcond = 1/(norm(a)*(estimate of norm(inverse(a))))
                    175:   --   estimate = norm(z)/norm(y) where a*z = y and ctrans(a)*y = e.
                    176:   --   ctrans(a) is the conjugate transpose of a.
                    177:   --   The components of e are chosen to cause maximum local
                    178:   --   growth in teh elements of w where ctrans(u)*w = e.
                    179:   --   The vectors are frequently rescaled to avoid overflow.
                    180:
                    181:     z : Multprec_Complex_Vectors.Vector(1..n);
                    182:     info,kb,kp1,l : integer;
                    183:     s,sm,sum,anorm,ynorm,fltacc1,fltacc2 : Floating_Number;
                    184:     ek,t,wk,wkm,cmpacc1,cmpacc2 : Complex_Number;
                    185:     ipvtt : Standard_Natural_Vectors.Vector(1..n);
                    186:
                    187:   begin
                    188:     anorm := Create(0);                              -- compute 1-norm of a
                    189:     for j in 1..n loop
                    190:       sum := Create(0);
                    191:       for i in 1..n loop
                    192:         fltacc1 := AbsVal(a(i,j));
                    193:         Add(sum,fltacc1);
                    194:         Clear(fltacc1);
                    195:       end loop;
                    196:       if sum > anorm
                    197:        then Copy(sum,anorm);
                    198:       end if;
                    199:       Clear(sum);
                    200:     end loop;
                    201:     lufac(a,n,ipvtt,info);                                        -- factor
                    202:     ipvt := ipvtt;
                    203:     ek := Create(1);                               -- solve ctrans(u)*w = e
                    204:     for j in 1..n loop
                    205:       z(j) := Create(0);
                    206:     end loop;
                    207:     for k in 1..n loop
                    208:       fltacc1 := AbsVal(z(k));
                    209:       if not Equal(fltacc1,0.0)
                    210:        then cmpacc1 := -z(k);
                    211:             Clear(ek);
                    212:             ek := csign(ek,cmpacc1);
                    213:             Clear(cmpacc1);
                    214:       end if;
                    215:       Clear(fltacc1);
                    216:       cmpacc1 := ek - z(k);
                    217:       fltacc1 := AbsVal(cmpacc1);
                    218:       Clear(cmpacc1);
                    219:       fltacc2 := AbsVal(a(k,k));
                    220:       if fltacc1 > fltacc2
                    221:        then s := fltacc2/fltacc1;
                    222:             cmpacc1 := Create(s);
                    223:             Mul(z,cmpacc1);
                    224:             Mul(ek,cmpacc1);
                    225:             Clear(cmpacc1);
                    226:             Clear(s);
                    227:       end if;
                    228:       Clear(fltacc1); Clear(fltacc2);
                    229:       Clear(wk);  wk := ek - z(k);
                    230:       Clear(wkm); wkm := ek + z(k);
                    231:       Min(wkm);
                    232:       s := AbsVal(wk);
                    233:       sm := AbsVal(wkm);
                    234:       fltacc1 := AbsVal(a(k,k));
                    235:       if Equal(fltacc1,0.0)
                    236:        then Clear(wk);  wk := Create(1);
                    237:             Clear(wkm); wkm := Create(1);
                    238:        else cmpacc1 := dconjg(a(k,k));
                    239:             Div(wk,cmpacc1);
                    240:             Div(wkm,cmpacc1);
                    241:             Clear(cmpacc1);
                    242:       end if;
                    243:       Clear(fltacc1);
                    244:       kp1 := k + 1;
                    245:       if kp1 <= n
                    246:        then for j in kp1..n loop
                    247:               cmpacc2 := dconjg(a(k,j));
                    248:               cmpacc1 := wkm*cmpacc2;
                    249:               Add(cmpacc1,z(j));
                    250:               fltacc1 := AbsVal(cmpacc1);
                    251:               Add(sm,fltacc1);
                    252:               Clear(fltacc1);
                    253:               Clear(cmpacc1);
                    254:               cmpacc1 := wk*cmpacc2;
                    255:               Add(z(j),cmpacc1);
                    256:               Clear(cmpacc1);
                    257:               Clear(cmpacc2);
                    258:               fltacc1 := AbsVal(z(j));
                    259:               Add(s,fltacc1);
                    260:               Clear(fltacc1);
                    261:             end loop;
                    262:             if s < sm
                    263:              then t := wkm - wk;
                    264:                   Copy(wkm,wk);
                    265:                   for j in kp1..n loop
                    266:                     cmpacc1 := t*dconjg(a(k,j));
                    267:                     Add(z(j),cmpacc1);
                    268:                     Clear(cmpacc1);
                    269:                   end loop;
                    270:                   Clear(t);
                    271:             end if;
                    272:       end if;
                    273:       Copy(wk,z(k));
                    274:     end loop;
                    275:     s := Inverse_Abs_Sum(z);
                    276:     cmpacc1 := Create(s);
                    277:     Mul(z,cmpacc1);
                    278:     Clear(cmpacc1);
                    279:     Clear(s);
                    280:     for k in 1..n loop                           -- solve ctrans(l)*y = w
                    281:       kb := n+1-k;
                    282:       if kb < n
                    283:        then t := Create(0);
                    284:             for i in (kb+1)..n loop
                    285:               cmpacc1 := dconjg(a(i,kb))*z(i);
                    286:               Add(t,cmpacc1);
                    287:               Clear(cmpacc1);
                    288:             end loop;
                    289:             Add(z(kb),t);
                    290:       end if;
                    291:       fltacc1 := AbsVal(z(kb));
                    292:       if fltacc1 > 1.0
                    293:        then s := Create(1);
                    294:             Div(s,fltacc1);
                    295:             cmpacc1 := Create(s);
                    296:             Mul(z,cmpacc1);
                    297:             Clear(cmpacc1);
                    298:             Clear(s);
                    299:       end if;
                    300:       Clear(fltacc1);
                    301:       l := ipvtt(kb);
                    302:       if l /= kb
                    303:        then Copy(z(l),t);
                    304:             Copy(z(kb),z(l));
                    305:             Copy(t,z(kb));
                    306:             Clear(t);
                    307:       end if;
                    308:     end loop;
                    309:     s := Inverse_Abs_Sum(z);
                    310:     cmpacc1 := Create(s);
                    311:     Clear(s);
                    312:     Mul(z,cmpacc1);
                    313:     Clear(cmpacc1);
                    314:     ynorm := Create(1);
                    315:     for k in 1..n loop                                    -- solve l*v = y
                    316:       l := ipvtt(k);
                    317:       if l /= k
                    318:        then Copy(z(l),t);
                    319:             Copy(z(k),z(l));
                    320:             Copy(t,z(k));
                    321:        else Copy(z(l),t);
                    322:       end if;
                    323:       if k < n
                    324:        then for i in (k+1)..n loop
                    325:               cmpacc1 := t*a(i,k);
                    326:               Add(z(i),cmpacc1);
                    327:               Clear(cmpacc1);
                    328:             end loop;
                    329:       end if;
                    330:       Clear(t);
                    331:       fltacc1 := AbsVal(z(k));
                    332:       if fltacc1 > 1.0
                    333:        then s := Create(1);
                    334:             Div(s,fltacc1);
                    335:             cmpacc1 := Create(s);
                    336:             Mul(z,cmpacc1);
                    337:             Clear(cmpacc1);
                    338:             Mul(ynorm,s);
                    339:             Clear(s);
                    340:       end if;
                    341:       Clear(fltacc1);
                    342:     end loop;
                    343:     s := Inverse_Abs_Sum(z);
                    344:     cmpacc1 := Create(s);
                    345:     Mul(z,cmpacc1);
                    346:     Clear(cmpacc1);
                    347:     Mul(ynorm,s);
                    348:     Clear(s);
                    349:     for k in 1..n loop                                    -- solve u*z = v
                    350:       kb := n+1-k;
                    351:       fltacc1 := AbsVal(z(kb));
                    352:       fltacc2 := AbsVal(a(kb,kb));
                    353:       if fltacc1 > fltacc2
                    354:        then s := fltacc2/fltacc1;
                    355:             cmpacc1 := Create(s);
                    356:             Mul(z,cmpacc1);
                    357:             Mul(ynorm,s);
                    358:             Clear(s);
                    359:       end if;
                    360:       if Equal(fltacc2,0.0)
                    361:        then Clear(z(kb));
                    362:             z(kb) := Create(1);
                    363:        else Div(z(kb),a(kb,kb));
                    364:       end if;
                    365:       Clear(fltacc1);
                    366:       Clear(fltacc2);
                    367:       t := -z(kb);
                    368:       for i in 1..(kb-1) loop
                    369:         cmpacc1 := t*a(i,kb);
                    370:         Add(z(i),cmpacc1);
                    371:         Clear(cmpacc1);
                    372:       end loop;
                    373:       Clear(t);
                    374:     end loop;
                    375:     s := Inverse_Abs_Sum(z);                             -- make znorm = 1.0
                    376:     cmpacc1 := Create(s);
                    377:     Mul(z,cmpacc1);
                    378:     Clear(cmpacc1);
                    379:     Mul(ynorm,s);
                    380:     if Equal(anorm,0.0)
                    381:      then rcond := Create(0);
                    382:      else rcond := ynorm/anorm;
                    383:     end if;
                    384:     Clear(ynorm); Clear(s); Clear(sm);
                    385:     Clear(ek); Clear(t); Clear(wk); Clear(wkm);
                    386:     Clear(z);
                    387:   end lufco;
                    388:
                    389:   procedure lusolve ( a : in Matrix; n : in integer;
                    390:                       ipvt : in Standard_Natural_Vectors.Vector;
                    391:                       b : in out Vector ) is
                    392:
                    393:     l,nm1,kb : integer;
                    394:     temp,acc : Complex_Number;
                    395:
                    396:   begin
                    397:     nm1 := n-1;
                    398:     if nm1 >= 1                                             -- solve l*y = b
                    399:      then for k in 1..nm1 loop
                    400:             l := ipvt(k);
                    401:             Copy(b(l),temp);
                    402:             if l /= k
                    403:              then Copy(b(k),b(l));
                    404:                   Copy(temp,b(k));
                    405:             end if;
                    406:             for i in (k+1)..n loop
                    407:               acc := temp*a(i,k);
                    408:               Add(b(i),acc);
                    409:               Clear(acc);
                    410:             end loop;
                    411:             Clear(temp);
                    412:           end loop;
                    413:     end if;
                    414:     for k in 1..n loop                                     -- solve u*x = y
                    415:       kb := n+1-k;
                    416:       Div(b(kb),a(kb,kb));
                    417:       temp := -b(kb);
                    418:       for j in 1..(kb-1) loop
                    419:         acc := temp*a(j,kb);
                    420:         Add(b(j),acc);
                    421:         Clear(acc);
                    422:       end loop;
                    423:       Clear(temp);
                    424:     end loop;
                    425:   end lusolve;
                    426:
                    427:   procedure Triangulate ( a : in out Matrix; n,m : in integer ) is
                    428:
                    429:     max,cbs : Floating_Number;
                    430:     temp : Complex_Number;
                    431:     pivot,k,kcolumn : integer;
                    432:
                    433:   begin
                    434:     k := 1;
                    435:     kcolumn := 1;
                    436:     while (k <= n) and (kcolumn <= m) loop
                    437:       max := Create(0);                                        -- find pivot
                    438:       pivot := 0;
                    439:       for l in k..n loop
                    440:         cbs := AbsVal(a(l,kcolumn));
                    441:         if cbs > max
                    442:          then max := cbs;
                    443:               pivot := l;
                    444:         end if;
                    445:       end loop;
                    446:       if pivot = 0
                    447:        then kcolumn := kcolumn + 1;
                    448:        else if pivot /= k                       -- interchange if necessary
                    449:              then for i in 1..m loop
                    450:                     temp := a(pivot,i);
                    451:                     a(pivot,i) := a(k,i);
                    452:                     a(k,i) := temp;
                    453:                   end loop;
                    454:             end if;
                    455:             for j in (kcolumn+1)..m loop                   -- triangulate a
                    456:               a(k,j) := a(k,j) / a(k,kcolumn);
                    457:             end loop;
                    458:             a(k,kcolumn) := Create(1);
                    459:             for i in (k+1)..n loop
                    460:               for j in (kcolumn+1)..m loop
                    461:                 a(i,j) := a(i,j) - a(i,kcolumn) * a(k,j);
                    462:               end loop;
                    463:               a(i,kcolumn) := Create(0);
                    464:             end loop;
                    465:             k := k + 1;
                    466:             kcolumn := kcolumn + 1;
                    467:       end if;
                    468:     end loop;
                    469:   end Triangulate;
                    470:
                    471:   procedure Diagonalize ( a : in out Matrix; n,m : in integer ) is
                    472:
                    473:     max : Floating_Number;
                    474:     temp : Complex_Number;
                    475:     pivot,k,kcolumn : integer;
                    476:
                    477:   begin
                    478:     k := 1;
                    479:     kcolumn := 1;
                    480:     while (k <= n) and (kcolumn <= m) loop
                    481:       max := Create(0);                                          -- find pivot
                    482:       for l in k..n loop
                    483:         if AbsVal(a(l,kcolumn)) > max
                    484:          then max := AbsVal(a(l,kcolumn));
                    485:               pivot := l;
                    486:         end if;
                    487:       end loop;
                    488:       if Equal(max,0.0)
                    489:        then kcolumn := kcolumn + 1;
                    490:        else if pivot /= k                        -- interchange if necessary
                    491:              then for i in 1..m loop
                    492:                     temp := a(pivot,i);
                    493:                     a(pivot,i) := a(k,i);
                    494:                     a(k,i) := temp;
                    495:                   end loop;
                    496:             end if;
                    497:             for j in (kcolumn+1)..m loop                    -- diagonalize a
                    498:               a(k,j) := a(k,j) / a(k,kcolumn);
                    499:             end loop;
                    500:             a(k,kcolumn) := Create(1);
                    501:             for i in 1..(k-1) loop
                    502:               for j in (kcolumn+1)..m loop
                    503:                 a(i,j) := a(i,j) - a(i,kcolumn) * a(k,j);
                    504:               end loop;
                    505:             end loop;
                    506:             for i in (k+1)..n loop
                    507:               for j in (kcolumn+1)..m loop
                    508:                 a(i,j) := a(i,j) - a(i,kcolumn) * a(k,j);
                    509:               end loop;
                    510:             end loop;
                    511:             for j in 1..(k-1) loop
                    512:               a(j,kcolumn) := Create(0);
                    513:             end loop;
                    514:             for j in (k+1)..n loop
                    515:               a(j,kcolumn) := Create(0);
                    516:             end loop;
                    517:             k := k + 1;
                    518:             kcolumn := kcolumn + 1;
                    519:       end if;
                    520:     end loop;
                    521:   end Diagonalize;
                    522:
                    523: end Multprec_Complex_Linear_Solvers;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>