[BACK]Return to predictors.adb CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / PHC / Ada / Continuation

Annotation of OpenXM_contrib/PHC/Ada/Continuation/predictors.adb, Revision 1.1.1.1

1.1       maekawa     1: with Standard_Mathematical_Functions;    use Standard_Mathematical_Functions;
                      2: with Standard_Natural_Vectors;
                      3: with Standard_Complex_Linear_Solvers;    use Standard_Complex_Linear_Solvers;
                      4:
                      5: package body Predictors is
                      6:
                      7: -- PREDICTORS for t :
                      8:
                      9:   procedure Real_Predictor
                     10:               ( t : in out Complex_Number; target : in Complex_Number;
                     11:                 h,tol : in double_float; pow : in positive := 1;
                     12:                 hh : out double_float ) is
                     13:
                     14:     nt : Complex_Number;
                     15:
                     16:   begin
                     17:     if pow = 1
                     18:      then nt := t + Create(h);
                     19:      else nt := Create((h+REAL_PART(t)**pow)**(1.0/double_float(pow)));
                     20:     end if;
                     21:     if REAL_PART(nt) >= REAL_PART(target)
                     22:       or else abs( REAL_PART(nt) - REAL_PART(target) ) <= tol
                     23:      then hh := REAL_PART(target) - REAL_PART(t);
                     24:           t := target;
                     25:      else hh := h;
                     26:           t := nt;
                     27:     end if;
                     28:   end Real_Predictor;
                     29:
                     30:   procedure Complex_Predictor
                     31:                ( t : in out Complex_Number; target : in Complex_Number;
                     32:                  h,tol : in double_float; hh : out double_float;
                     33:                  distance : in double_float; trial : in natural ) is
                     34:
                     35:     nt,target_direction,step : Complex_Number;
                     36:     dre,dim,d,x,y,alfa,absnt : double_float;
                     37:     tr3 : natural range 0..2;
                     38:
                     39:   begin
                     40:     target_direction := target - t;
                     41:     d := AbsVal(target_direction);
                     42:     if d < tol
                     43:      then nt := target - Create(distance);
                     44:           hh := AbsVal(nt - t);
                     45:      else tr3 := trial mod 3;
                     46:          case tr3 is
                     47:            when 0 => target_direction := target_direction / Create(d);
                     48:                       if (d - h) > distance
                     49:                        then step := Create(h) * target_direction;
                     50:                        else step := (d - distance) * target_direction;
                     51:                       end if;
                     52:                       nt := t + step;
                     53:            when 1 => dre := REAL_PART(target_direction);
                     54:                       dim := IMAG_PART(target_direction);
                     55:                       alfa := ARCTAN(dim/dre);
                     56:                       x := h * COS(alfa + PI/4.0);
                     57:                       y := h * SIN(alfa + PI/4.0);
                     58:                       step := Create(x,y);
                     59:                       nt := t + step;
                     60:                       absnt := AbsVal(nt);
                     61:                       if (absnt > AbsVal(target))
                     62:                          or else (AbsVal(nt - target) < distance)
                     63:                         then step := Create(0.0,y) * Create(h);
                     64:                              nt := t + step;
                     65:                       end if;
                     66:            when 2 => dre := REAL_PART(target_direction);
                     67:                       dim := IMAG_PART(target_direction);
                     68:                       alfa := ARCTAN(dim/dre);
                     69:                       x := h * COS(alfa - PI/4.0);
                     70:                       y := h * SIN(alfa - PI/4.0);
                     71:                       step := Create(x,y);
                     72:                       nt := t + step;
                     73:                       absnt := AbsVal(nt);
                     74:                       if (absnt > AbsVal(target))
                     75:                          or else (AbsVal(nt - target) < distance)
                     76:                         then step := Create(0.0,-y) * Create(h);
                     77:                              nt := t + step;
                     78:                       end if;
                     79:           end case;
                     80:           hh := AbsVal(step);
                     81:     end if;
                     82:     t := nt;
                     83:   end Complex_Predictor;
                     84:
                     85:   procedure Circular_Predictor
                     86:               ( t : in out Complex_Number; theta : in out double_float;
                     87:                 t0_min_target,target : in Complex_Number;
                     88:                 h : in double_float ) is
                     89:
                     90:     e_i_theta : Complex_Number;
                     91:
                     92:   begin
                     93:     theta := theta + h;
                     94:     e_i_theta := Create(COS(theta),SIN(theta));
                     95:     t := target + t0_min_target * e_i_theta;
                     96:   end Circular_Predictor;
                     97:
                     98:   procedure Geometric_Predictor
                     99:               ( t : in out Complex_Number; target : in Complex_Number;
                    100:                 h,tol : in double_float ) is
                    101:
                    102:     nt : Complex_Number;
                    103:
                    104:   begin
                    105:     nt := target - Create(h)*(target - t);
                    106:     if abs( REAL_PART(nt) - REAL_PART(target) ) <= tol
                    107:      then t := target;
                    108:      else t := nt;
                    109:     end if;
                    110:   end Geometric_Predictor;
                    111:
                    112: -- PREDICTORS FOR x :
                    113:
                    114:   procedure Secant_Predictor
                    115:               ( x : in out Solution_Array; prev_x : in Solution_Array;
                    116:                 fac : in Complex_Number; dist_x : in double_float ) is
                    117:
                    118:     j : natural;
                    119:     xx : Solution_Array(x'range);
                    120:
                    121:   begin
                    122:     Copy(x,xx);
                    123:     for i in x'range loop
                    124:       x(i).v := x(i).v + fac * ( x(i).v - prev_x(i).v );
                    125:       j := xx'first;
                    126:       Equals(xx,x(i).v,i,dist_x,j);
                    127:       if j /= i
                    128:        then Copy(xx,x);
                    129:             exit;
                    130:       end if;
                    131:     end loop;
                    132:     Clear(xx);
                    133:   end Secant_Predictor;
                    134:
                    135: -- PREDICTORS FOR t AND x :
                    136:
                    137:   procedure Secant_Single_Real_Predictor
                    138:                ( x : in out Vector; prev_x : in Vector;
                    139:                  t : in out Complex_Number; prev_t,target : in Complex_Number;
                    140:                  h,tol : in double_float; pow : in positive := 1 ) is
                    141:
                    142:     hh,tmp : double_float;
                    143:     factor : Complex_Number;
                    144:
                    145:   begin
                    146:     tmp := AbsVal(t - prev_t);
                    147:     Real_Predictor(t,target,h,tol,pow,hh);
                    148:     if tmp > tol
                    149:      then factor := Create(hh/tmp);
                    150:           x := x + factor * ( x - prev_x );
                    151:     end if;
                    152:   end Secant_Single_Real_Predictor;
                    153:
                    154:   procedure Secant_Multiple_Real_Predictor
                    155:                ( x : in out Solution_Array; prev_x : in Solution_Array;
                    156:                  t : in out Complex_Number; prev_t,target : in Complex_Number;
                    157:                  h,tol,dist_x : in double_float; pow : in positive := 1 ) is
                    158:
                    159:     hh,tmp : double_float;
                    160:     factor : Complex_Number;
                    161:
                    162:   begin
                    163:     tmp := AbsVal(t - prev_t);
                    164:     Real_Predictor(t,target,h,tol,pow,hh);
                    165:     if tmp > tol
                    166:      then factor := Create(hh/tmp);
                    167:           Secant_Predictor(x,prev_x,factor,dist_x);
                    168:     end if;
                    169:     for k in x'range loop
                    170:       x(k).t := t;
                    171:     end loop;
                    172:   end Secant_Multiple_Real_Predictor;
                    173:
                    174:   procedure Secant_Single_Complex_Predictor
                    175:                ( x : in out Vector; prev_x : in Vector;
                    176:                  t : in out Complex_Number; prev_t,target : in Complex_Number;
                    177:                  h,tol,dist_t : in double_float; trial : in natural ) is
                    178:
                    179:     hh,tmp : double_float;
                    180:     factor : Complex_Number;
                    181:
                    182:   begin
                    183:     tmp := AbsVal(t - prev_t);
                    184:     Complex_Predictor(t,target,h,tol,hh,dist_t,trial);
                    185:     if tmp > tol
                    186:      then factor := Create(hh/tmp);
                    187:           x := x + factor * ( x - prev_x );
                    188:     end if;
                    189:   end Secant_Single_Complex_Predictor;
                    190:
                    191:   procedure Secant_Multiple_Complex_Predictor
                    192:                ( x : in out Solution_Array; prev_x : in Solution_Array;
                    193:                  t : in out Complex_Number; prev_t,target : in Complex_Number;
                    194:                  h,tol,dist_x,dist_t : in double_float; trial : in natural ) is
                    195:
                    196:     hh,tmp : double_float;
                    197:     factor : Complex_Number;
                    198:
                    199:   begin
                    200:     tmp := AbsVal(t - prev_t);
                    201:     Complex_Predictor(t,target,h,tol,hh,dist_t,trial);
                    202:     if tmp > tol
                    203:      then factor := Create(hh/tmp);
                    204:           Secant_Predictor(x,prev_x,factor,dist_x);
                    205:     end if;
                    206:     for k in x'range loop
                    207:       x(k).t := t;
                    208:     end loop;
                    209:   end Secant_Multiple_Complex_Predictor;
                    210:
                    211:   procedure Secant_Circular_Predictor
                    212:                ( x : in out Vector; prev_x : in Vector;
                    213:                  t : in out Complex_Number; theta : in out double_float;
                    214:                  prev_t,t0_min_target,target : in Complex_Number;
                    215:                  h,tol : in double_float ) is
                    216:
                    217:     factor : Complex_Number;
                    218:     tmp : double_float := AbsVal(t-prev_t);
                    219:
                    220:   begin
                    221:     if tmp <= tol
                    222:      then Circular_Predictor(t,theta,t0_min_target,target,h);
                    223:      else factor := Create(h/tmp);
                    224:           Circular_Predictor(t,theta,t0_min_target,target,h);
                    225:           x := x + factor * ( x - prev_x );
                    226:     end if;
                    227:   end Secant_Circular_Predictor;
                    228:
                    229:   procedure Secant_Geometric_Predictor
                    230:                ( x : in out Vector; prev_x : in Vector;
                    231:                  t : in out Complex_Number; prev_t,target : in Complex_Number;
                    232:                  h,tol : in double_float ) is
                    233:
                    234:     dist_prev,dist : double_float;
                    235:     factor,tmp : Complex_Number;
                    236:
                    237:   begin
                    238:     dist_prev := AbsVal(t - prev_t);     -- old stepsize
                    239:     tmp := t;
                    240:     Geometric_Predictor(t,target,h,tol);
                    241:     dist := AbsVal(t - tmp);             -- new stepsize
                    242:     if dist_prev > tol
                    243:      then factor := Create(dist/dist_prev);
                    244:           x := x + factor * ( x - prev_x );
                    245:     end if;
                    246:   end Secant_Geometric_Predictor;
                    247:
                    248:   procedure Tangent_Single_Real_Predictor
                    249:                ( x : in out Vector; t : in out Complex_Number;
                    250:                  target : in Complex_Number; h,tol : in double_float;
                    251:                  pow : in positive := 1 ) is
                    252:
                    253:     n : natural := x'last;
                    254:     info : integer;
                    255:     norm_tan,hh : double_float;
                    256:     rhs : Vector(x'range);
                    257:     j : Matrix(1..n,1..n);
                    258:     ipvt : Standard_Natural_Vectors.Vector(1..n);
                    259:     prev_t : Complex_Number := t;
                    260:
                    261:   begin
                    262:     Real_Predictor(t,target,h,tol,pow,hh);
                    263:     j := dH(x,prev_t);
                    264:     lufac(j,n,ipvt,info);
                    265:     if info = 0
                    266:      then rhs := dH(x,prev_t);
                    267:           Min(rhs);
                    268:           lusolve(j,n,ipvt,rhs);
                    269:           norm_tan := Norm(rhs);
                    270:           if norm_tan > tol
                    271:            then hh := hh / norm_tan;
                    272:                 Mul(rhs,Create(hh));
                    273:                 Add(x,rhs);
                    274:           end if;
                    275:     end if;
                    276:   end Tangent_Single_Real_Predictor;
                    277:
                    278:   procedure Tangent_Multiple_Real_Predictor
                    279:                ( x : in out Solution_Array; t : in out Complex_Number;
                    280:                  target : in Complex_Number; h,tol,dist_x : in double_float;
                    281:                  nsys : in out natural; pow : in positive := 1 ) is
                    282:
                    283:     n : natural := x(x'first).n;
                    284:     norm_tan,hh : double_float;
                    285:     rhs : Vector(1..n);
                    286:     info : integer;
                    287:     j : Matrix(1..n,1..n);
                    288:     ipvt : Standard_Natural_Vectors.Vector(1..n);
                    289:     xx : Solution_Array(x'range);
                    290:     jj : natural;
                    291:     prev_t : Complex_Number := t;
                    292:
                    293:   begin
                    294:     Real_Predictor(t,target,h,tol,pow,hh);
                    295:     Copy(x,xx);
                    296:     for i in x'range loop
                    297:       j := dH(x(i).v,prev_t);
                    298:       lufac(j,n,ipvt,info);
                    299:       if info = 0
                    300:        then rhs := dH(x(i).v,prev_t);
                    301:             Min(rhs);
                    302:             lusolve(j,n,ipvt,rhs);
                    303:             nsys := nsys + 1;
                    304:             norm_tan := Norm(rhs);
                    305:             if norm_tan > tol
                    306:              then hh := hh / norm_tan;
                    307:                   Mul(rhs,Create(hh));
                    308:                   Add(x(i).v,rhs);
                    309:             end if;
                    310:             jj := xx'first;
                    311:             Equals(xx,x(i).v,i,dist_x,jj);
                    312:             if jj /= i
                    313:              then Copy(xx,x); exit;
                    314:             end if;
                    315:        else Copy(xx,x); exit;
                    316:       end if;
                    317:     end loop;
                    318:     Clear(xx);
                    319:     for k in x'range loop
                    320:       x(k).t := t;
                    321:     end loop;
                    322:   end Tangent_Multiple_Real_Predictor;
                    323:
                    324:   procedure Tangent_Single_Complex_Predictor
                    325:                ( x : in out Vector; t : in out Complex_Number;
                    326:                  target : in Complex_Number;
                    327:                  h,tol,dist_t : in double_float; trial : in natural) is
                    328:
                    329:     n : natural := x'last;
                    330:     info : integer;
                    331:     norm_tan,hh : double_float;
                    332:     rhs : Vector(x'range);
                    333:     j : Matrix(1..n,1..n);
                    334:     ipvt : Standard_Natural_Vectors.Vector(1..n);
                    335:     prev_t : Complex_Number := t;
                    336:
                    337:   begin
                    338:     Complex_Predictor(t,target,h,tol,hh,dist_t,trial);
                    339:     j := dH(x,prev_t);
                    340:     lufac(j,n,ipvt,info);
                    341:     if info = 0
                    342:      then rhs := dH(x,prev_t);
                    343:           Min(rhs);
                    344:           lusolve(j,n,ipvt,rhs);
                    345:           norm_tan := Norm(rhs);
                    346:           if norm_tan > tol
                    347:            then hh := hh / norm_tan;
                    348:                 Mul(rhs,Create(hh));
                    349:                 Add(x,rhs);
                    350:           end if;
                    351:     end if;
                    352:   end Tangent_Single_Complex_Predictor;
                    353:
                    354:   procedure Tangent_Multiple_Complex_Predictor
                    355:                ( x : in out Solution_Array; t : in out Complex_Number;
                    356:                  target : in Complex_Number;
                    357:                  h,tol,dist_x,dist_t : in double_float;
                    358:                  trial : in natural; nsys : in out natural) is
                    359:
                    360:     n : natural := x(x'first).n;
                    361:     norm_tan,hh : double_float;
                    362:     rhs : Vector(1..n);
                    363:     info : integer;
                    364:     j : Matrix(1..n,1..n);
                    365:     ipvt : Standard_Natural_Vectors.Vector(1..n);
                    366:     xx : Solution_Array(x'range);
                    367:     jj : natural;
                    368:     prev_t : Complex_Number := t;
                    369:
                    370:   begin
                    371:     Complex_Predictor(t,target,h,tol,hh,dist_t,trial);
                    372:     Copy(x,xx);
                    373:     for i in x'range loop
                    374:       j := dH(x(i).v,prev_t);
                    375:       lufac(j,n,ipvt,info);
                    376:       if info = 0
                    377:        then rhs := dH(x(i).v,prev_t);
                    378:             Min(rhs);
                    379:             lusolve(j,n,ipvt,rhs);
                    380:             nsys := nsys + 1;
                    381:             norm_tan := Norm(rhs);
                    382:             if norm_tan > tol
                    383:              then hh := hh / norm_tan;
                    384:                   Mul(rhs,Create(hh));
                    385:                   Add(x(i).v,rhs);
                    386:             end if;
                    387:             jj := xx'first;
                    388:             Equals(xx,x(i).v,i,dist_x,jj);
                    389:             if jj /= i
                    390:              then Copy(xx,x); exit;
                    391:             end if;
                    392:        else Copy(xx,x); exit;
                    393:       end if;
                    394:     end loop;
                    395:     Clear(xx);
                    396:     for k in x'range loop
                    397:       x(k).t := t;
                    398:     end loop;
                    399:   end Tangent_Multiple_Complex_Predictor;
                    400:
                    401:   procedure Tangent_Circular_Predictor
                    402:               ( x : in out Vector; t : in out Complex_Number;
                    403:                 theta : in out double_float;
                    404:                 t0_min_target,target : in Complex_Number;
                    405:                 h,tol : in double_float ) is
                    406:
                    407:     n : natural := x'last;
                    408:     info : integer;
                    409:     norm_tan : double_float;
                    410:     rhs : Vector(x'range);
                    411:     j : Matrix(1..n,1..n);
                    412:     ipvt : Standard_Natural_Vectors.Vector(1..n);
                    413:
                    414:   begin
                    415:     lufac(j,n,ipvt,info);
                    416:     if info = 0
                    417:      then rhs := dH(x,t);
                    418:           Min(rhs);
                    419:           lusolve(j,n,ipvt,rhs);
                    420:     end if;
                    421:     Circular_Predictor(t,theta,t0_min_target,target,h);
                    422:     if info = 0
                    423:      then norm_tan := Norm(rhs);
                    424:           if norm_tan > tol
                    425:            then Mul(rhs,Create(h/norm_tan));
                    426:                 Add(x,rhs);
                    427:           end if;
                    428:     end if;
                    429:   end Tangent_Circular_Predictor;
                    430:
                    431:   procedure Tangent_Geometric_Predictor
                    432:                ( x : in out Vector; t : in out Complex_Number;
                    433:                  target : in Complex_Number; h,tol : in double_float ) is
                    434:
                    435:     n : natural := x'last;
                    436:     info : integer;
                    437:     norm_tan,step : double_float;
                    438:     rhs : Vector(x'range);
                    439:     j : Matrix(1..n,1..n);
                    440:     ipvt : Standard_Natural_Vectors.Vector(1..n);
                    441:     prev_t : Complex_Number := t;
                    442:
                    443:   begin
                    444:     Geometric_Predictor(t,target,h,tol);
                    445:     j := dH(x,prev_t);
                    446:     lufac(j,n,ipvt,info);
                    447:     if info = 0
                    448:      then rhs := dH(x,prev_t);
                    449:           Min(rhs);
                    450:           lusolve(j,n,ipvt,rhs);
                    451:           norm_tan := Norm(rhs);
                    452:           if norm_tan > tol
                    453:            then step := AbsVal(t-prev_t) / norm_tan;
                    454:                 Mul(rhs,Create(step));
                    455:                 Add(x,rhs);
                    456:           end if;
                    457:     end if;
                    458:   end Tangent_Geometric_Predictor;
                    459:
                    460:   function Hermite ( t0,t1,t,x0,x1,v0,v1 : Complex_Number )
                    461:                    return Complex_Number is
                    462:
                    463:   -- DESCRIPTION :
                    464:   --   Returns the value of the third degree interpolating polynomial x(t),
                    465:   --   such that x(t0) = x0, x(t1) = x1, x'(t0) = v0 and x'(t1) = v1.
                    466:
                    467:   -- REQUIRED : t0 /= t1.
                    468:
                    469:   -- IMPLEMENTATION :
                    470:   --   x(t) = a3*t^3 + a2*t^2 + a1*t + a0,
                    471:   --   The four interpolation conditions lead to a linear system in
                    472:   --   the coefficients of x(t).  This system is first solved explicitly
                    473:   --   and then the polynomial x(t) is evaluated.
                    474:
                    475:     a0,a1,a2,a3,t10,v10 : Complex_Number;
                    476:
                    477:   begin
                    478:     t10 := t1 - t0;
                    479:     v10 := (x1 - x0)/t10;
                    480:     a3 := (v1 + v0 - Create(2.0)*v10)/(t10**2);
                    481:     a2 := (v10 - v0 - (t1**2 + t1*t0 - Create(2.0)*t0**2)*a3)/t10;
                    482:     a1 := v0 - (Create(3.0)*a3*t0 + Create(2.0)*a2)*t0;
                    483:     a0 := x0 - ((a3*t0 + a2)*t0 + a1)*t0;
                    484:     return (((a3*t + a2)*t + a1)*t + a0);
                    485:   end Hermite;
                    486:
                    487:   function Hermite ( t0,t1,t : Complex_Number; x0,x1,v0,v1 : Vector )
                    488:                    return Vector is
                    489:
                    490:   -- DESCRIPTION :
                    491:   --   Returns the value of the third degree interpolating polynomial x(t),
                    492:   --   such that x(t0) = x0, x(t1) = x1, x'(t0) = v0 and x'(t1) = v1,
                    493:   --   for every component.
                    494:
                    495:   -- REQUIRED : t0 /= t1.
                    496:
                    497:     res : Vector(x0'range);
                    498:
                    499:   begin
                    500:     for i in res'range loop
                    501:       res(i) := Hermite(t0,t1,t,x0(i),x1(i),v0(i),v1(i));
                    502:     end loop;
                    503:     return res;
                    504:   end Hermite;
                    505:
                    506:   procedure Hermite_Single_Real_Predictor
                    507:                 ( x : in out Vector; prev_x : in Vector;
                    508:                   t : in out Complex_Number; prev_t,target : in Complex_Number;
                    509:                   v : in out Vector; prev_v : in Vector;
                    510:                   h,tol : in double_float; pow : in positive := 1 ) is
                    511:
                    512:     n : natural := x'last;
                    513:     info : integer;
                    514:     hh : double_float;
                    515:     j : Matrix(1..n,1..n);
                    516:     ipvt : Standard_Natural_Vectors.Vector(1..n);
                    517:     t1 : Complex_Number := t;
                    518:
                    519:   begin
                    520:     Real_Predictor(t,target,h,tol,pow,hh);
                    521:     j := dH(x,t1);
                    522:     lufac(j,n,ipvt,info);
                    523:     if info = 0
                    524:      then v := dH(x,t1);
                    525:           Min(v);
                    526:           lusolve(j,n,ipvt,v);
                    527:           if AbsVal(prev_t - t1) > tol
                    528:            then x := Hermite(prev_t,t1,t,prev_x,x,prev_v,v);
                    529:           end if;
                    530:     end if;
                    531:   end Hermite_Single_Real_Predictor;
                    532:
                    533: end Predictors;

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