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

Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Polynomials/generic_polynomial_functions.adb, Revision 1.1.1.1

1.1       maekawa     1: with unchecked_deallocation;
                      2: with Standard_Natural_Vectors;
                      3: with Standard_Natural_Matrices;          use Standard_Natural_Matrices;
                      4:
                      5: package body Generic_Polynomial_Functions is
                      6:
                      7: -- DATA STRUCTURES :
                      8:
                      9:   type kind is (coefficient,polynomial);
                     10:   type Poly_Rec ( k : kind := coefficient ) is record
                     11:     case k is
                     12:       when coefficient => c : number;
                     13:       when polynomial  => p : Eval_Poly;
                     14:     end case;
                     15:   end record;
                     16:   type Coeff_Poly_Rec ( k : kind := coefficient ) is record
                     17:     case k is
                     18:       when coefficient => c : integer;
                     19:       when polynomial  => p : Eval_Coeff_Poly;
                     20:     end case;
                     21:   end record;
                     22:
                     23:   type Eval_Poly_Rep is array(integer range <>) of Poly_Rec;
                     24:   type Eval_Coeff_Poly_Rep is array(integer range <>) of Coeff_Poly_Rec;
                     25:
                     26:   procedure free is new unchecked_deallocation(Eval_Poly_Rep,Eval_Poly);
                     27:   procedure free is
                     28:     new unchecked_deallocation(Eval_Coeff_Poly_Rep,Eval_Coeff_Poly);
                     29:
                     30: -- AUXILIARY OPERATIONS :
                     31:
                     32:   function Convert ( c : number; n : natural ) return natural is
                     33:
                     34:   -- DESCRIPTION :
                     35:   --   Returns the corresponding value for c, when it lies in 1..n,
                     36:   --   otherwise 0 is returned.
                     37:
                     38:   begin
                     39:     for i in 1..n loop
                     40:       if c = Create(i)
                     41:        then return i;
                     42:       end if;
                     43:     end loop;
                     44:     return 0;
                     45:   end Convert;
                     46:
                     47:   function Head_Term ( p : Poly ) return Term is
                     48:
                     49:   -- DESCRIPTION :
                     50:   --   Returns the leading term of the polynomial.
                     51:
                     52:     res : Term;
                     53:
                     54:     procedure Scan_Term ( t : in Term; continue : out boolean ) is
                     55:     begin
                     56:       res := t;
                     57:       continue := false;
                     58:     end Scan_Term;
                     59:     procedure Scan_Terms is new Visiting_Iterator(Scan_Term);
                     60:
                     61:   begin
                     62:     Scan_Terms(p);
                     63:     return res;
                     64:   end Head_Term;
                     65:
                     66:   procedure Initialize ( evpr : in out Eval_Poly_Rep ) is
                     67:   begin
                     68:     for i in evpr'range loop
                     69:       declare
                     70:         nullpr : Poly_Rec(polynomial);
                     71:       begin
                     72:         nullpr.p := null;
                     73:         evpr(i) := nullpr;
                     74:       end;
                     75:     end loop;
                     76:   end Initialize;
                     77:
                     78:   procedure Initialize ( evpr : in out Eval_Coeff_Poly_Rep ) is
                     79:   begin
                     80:     for i in evpr'range loop
                     81:       declare
                     82:         nullpr : Coeff_Poly_Rec(polynomial);
                     83:       begin
                     84:         nullpr.p := null;
                     85:         evpr(i) := nullpr;
                     86:       end;
                     87:     end loop;
                     88:   end Initialize;
                     89:
                     90:   procedure Initialize ( p : in Poly; cff : out Vector; deg : out Matrix ) is
                     91:
                     92:   -- DESCRIPTION :
                     93:   --   Returns a vector/matrix representation of the polynomial p.
                     94:   --   Starts filling in backwards, since the highest degrees are in front
                     95:   --   of the list.  This could reduce the sorting time later.
                     96:
                     97:     ind : natural := cff'last+1;
                     98:
                     99:     procedure Scan_Term ( t : in Term; continue : out boolean ) is
                    100:     begin
                    101:       ind := ind-1;
                    102:       Copy(t.cf,cff(ind));
                    103:       for j in t.dg'range loop
                    104:         deg(ind,j) := t.dg(j);
                    105:       end loop;
                    106:       continue := true;
                    107:     end Scan_Term;
                    108:     procedure Scan_Terms is new Visiting_Iterator(Scan_Term);
                    109:
                    110:   begin
                    111:     Scan_Terms(p);
                    112:   end Initialize;
                    113:
                    114:   procedure Swap ( cff : in out Vector; deg : in out Matrix;
                    115:                    i,j,k : in natural ) is
                    116:
                    117:   -- DESCRIPTION :
                    118:   --   Swaps the ith row with the jth row, starting from the kth column.
                    119:
                    120:     tmpcff : number;
                    121:     tmpdeg : natural;
                    122:
                    123:   begin
                    124:     Copy(cff(i),tmpcff);
                    125:     Copy(cff(j),cff(i));
                    126:     Copy(tmpcff,cff(j));
                    127:     Clear(tmpcff);
                    128:     for kk in k..deg'last(2) loop
                    129:       tmpdeg := deg(i,kk);
                    130:       deg(i,kk) := deg(j,kk);
                    131:       deg(j,kk) := tmpdeg;
                    132:     end loop;
                    133:   end Swap;
                    134:
                    135:   procedure Sort ( cff : in out Vector; deg : in out Matrix;
                    136:                    i1,i2,k : in natural ) is
                    137:
                    138:   -- DESCRIPTION :
                    139:   --   Sorts the elements in the kth column of the degree matrix, in
                    140:   --   the range i1..i2.  The coefficient vector gets sorted along.
                    141:
                    142:     ind,min : natural;
                    143:
                    144:   begin
                    145:     for i in i1..i2 loop                  -- sort by swapping minimal element
                    146:       min := deg(i,k);
                    147:       ind := i;
                    148:       for j in i+1..i2 loop               -- search for minimal element
                    149:         if deg(j,k) < min
                    150:          then min := deg(j,k);
                    151:               ind := j;
                    152:         end if;
                    153:       end loop;
                    154:       if ind /= i                         -- swap cff and deg
                    155:        then Swap(cff,deg,i,ind,k);
                    156:       end if;
                    157:     end loop;
                    158:   end Sort;
                    159:
                    160:   procedure Create ( cff : in out Vector; deg : in out Matrix;
                    161:                      i1,i2,k : in natural; ep : out Eval_Poly ) is
                    162:
                    163:   -- DESCRIPTION :
                    164:   --   Returns in ep a nested Horner scheme to evaluate a polynomial given
                    165:   --   in vector/matrix representation with coefficients in cff and degrees
                    166:   --   in deg.  The range being considered is i1..i2, from the kth column.
                    167:
                    168:   -- REQUIRED :
                    169:   --   The entries in the kth column of deg in i1..i2 are sorted
                    170:   --   in increasing order.
                    171:
                    172:     evpr : Eval_Poly_Rep(0..deg(i2,k));
                    173:     ind,j1,j2 : natural;
                    174:
                    175:   begin
                    176:     Initialize(evpr);
                    177:     if k = deg'last(2)                            -- polynomial in one unknown
                    178:      then for i in i1..i2 loop
                    179:             declare
                    180:               pr : Poly_Rec(Coefficient);
                    181:             begin
                    182:               Copy(cff(i),pr.c);
                    183:               evpr(deg(i,k)) := pr;
                    184:             end;
                    185:           end loop;
                    186:      else ind := i1;                              -- recursive call
                    187:           while ind <= i2 loop
                    188:             j1 := ind; j2 := ind;
                    189:             while j2 < i2 and then deg(j1,k) = deg(j2+1,k) loop
                    190:               j2 := j2 + 1;
                    191:             end loop;
                    192:             declare
                    193:               pr : Poly_Rec(Polynomial);
                    194:             begin
                    195:               Sort(cff,deg,j1,j2,k+1);
                    196:               Create(cff,deg,j1,j2,k+1,pr.p);
                    197:               evpr(deg(ind,k)) := pr;
                    198:             end;
                    199:             ind := j2+1;
                    200:           end loop;
                    201:     end if;
                    202:     ep := new Eval_Poly_Rep'(evpr);
                    203:   end Create;
                    204:
                    205: -- CONSTRUCTORS :
                    206:
                    207:   function Create ( p : Poly; n,nb : natural; d : integer )
                    208:                   return Eval_Coeff_Poly is
                    209:
                    210:   -- DESCRIPTION :
                    211:   --   An evaluable polynomial is returned for p, with d = Degree(p,x1),
                    212:   --   n = Number_of_Unknowns(p) >= 1 and nb = Number_of_Terms(p).
                    213:   --   The coefficients of p are converted natural numbers.
                    214:
                    215:     res : Eval_Coeff_Poly;
                    216:     evpr : Eval_Coeff_Poly_Rep(0..d);
                    217:     terms : array(0..d) of Poly := (0..d => Null_Poly);
                    218:
                    219:     procedure Add_Term1 ( t : in Term; cont : out boolean ) is
                    220:
                    221:       pr : Coeff_Poly_Rec(coefficient);
                    222:
                    223:     begin
                    224:       pr.c := Convert(t.cf,nb);
                    225:       evpr(t.dg(t.dg'first)) := pr;
                    226:       cont := true;
                    227:     end Add_Term1;
                    228:     procedure Add_Terms1 is new Visiting_Iterator(Add_Term1);
                    229:
                    230:     procedure Add_Term ( t : in Term; cont : out boolean ) is
                    231:
                    232:       nt : Term;
                    233:
                    234:     begin
                    235:       Copy(t.cf,nt.cf);
                    236:       nt.dg := new Standard_Natural_Vectors.Vector(t.dg'first..t.dg'last-1);
                    237:       for i in nt.dg'range loop
                    238:         nt.dg(i) := t.dg(i+1);
                    239:       end loop;
                    240:       Add(terms(t.dg(t.dg'first)),nt);
                    241:       Clear(nt);
                    242:       cont := true;
                    243:     end Add_Term;
                    244:     procedure Add_Terms is new Visiting_Iterator(Add_Term);
                    245:
                    246:   begin
                    247:     Initialize(evpr);
                    248:     if n = 1
                    249:      then Add_Terms1(p);
                    250:      else Add_Terms(p);
                    251:           for i in terms'range loop
                    252:             declare
                    253:               pr : Coeff_Poly_Rec(polynomial);
                    254:               ind : integer;
                    255:             begin
                    256:               if terms(i) = Null_Poly
                    257:                then pr.p := null;
                    258:                else ind := Head_Term(terms(i)).dg'first;
                    259:                     pr.p := Create(terms(i),n-1,nb,Degree(terms(i),ind));
                    260:               end if;
                    261:               evpr(i) := pr;
                    262:               Clear(terms(i));
                    263:             end;
                    264:           end loop;
                    265:     end if;
                    266:     res := new Eval_Coeff_Poly_Rep'(evpr);
                    267:     return res;
                    268:   end Create;
                    269:
                    270:   function Create ( p : Poly ) return Eval_Poly is
                    271:
                    272:     res : Eval_Poly;
                    273:     nbvar : constant natural := Number_of_Unknowns(p);
                    274:     nbtms : constant natural := Number_of_Terms(p);
                    275:     cff : Vector(1..nbtms);
                    276:     deg : Matrix(1..nbtms,1..nbvar);
                    277:
                    278:   begin
                    279:     if (p = Null_Poly) or else (nbvar = 0)
                    280:      then return null;
                    281:      else Initialize(p,cff,deg);
                    282:           Sort(cff,deg,1,nbtms,1);
                    283:           Create(cff,deg,1,nbtms,1,res);
                    284:           Clear(cff);
                    285:           return res;
                    286:     end if;
                    287:   end Create;
                    288:
                    289:   function Create ( p : Poly ) return Eval_Coeff_Poly is
                    290:
                    291:     res : Eval_Coeff_Poly;
                    292:     lp : Poly := Null_Poly;
                    293:     n : constant natural := Number_of_Unknowns(p);
                    294:     nb : constant natural := Number_of_Terms(p);
                    295:     cnt : natural := 0;
                    296:     ind : integer;
                    297:
                    298:     procedure Label_Term ( t : in Term; cont : out boolean ) is
                    299:
                    300:       lt : Term;
                    301:
                    302:     begin
                    303:       cnt := cnt + 1;
                    304:       lt.cf := Create(cnt);
                    305:       lt.dg := new Standard_Natural_Vectors.Vector'(t.dg.all);
                    306:       Add(lp,lt);
                    307:       cont := true;
                    308:     end Label_Term;
                    309:     procedure Label_Terms is new Visiting_Iterator(Label_Term);
                    310:
                    311:   begin
                    312:     if (p = Null_Poly) or else (nb = 0)
                    313:      then return null;
                    314:      else Label_Terms(p);
                    315:           ind := Head_Term(p).dg'first;
                    316:           res := Create(lp,n,nb,Degree(p,ind));
                    317:           Clear(lp);
                    318:     end if;
                    319:     return res;
                    320:   end Create;
                    321:
                    322:   procedure Diff ( p : in Poly; i : in integer;
                    323:                    cp : out Eval_Coeff_Poly; m : out Vector ) is
                    324:
                    325:     nb : constant natural := Number_of_Terms(p);
                    326:     n : constant natural := Number_of_Unknowns(p);
                    327:     ind,cnt : integer;
                    328:     dp : Poly := Null_Poly;
                    329:
                    330:     procedure Diff_Term ( t : in Term; cont : out boolean ) is
                    331:
                    332:       dt : Term;
                    333:
                    334:     begin
                    335:       cnt := cnt + 1;
                    336:       if t.dg(i) > 0
                    337:        then dt.cf := Create(cnt);
                    338:             dt.dg := new Standard_Natural_Vectors.Vector'(t.dg.all);
                    339:             m(cnt) := Create(t.dg(i));
                    340:             dt.dg(i) := dt.dg(i) - 1;
                    341:             Add(dp,dt);
                    342:             Clear(dt);
                    343:        else m(cnt) := Create(0);
                    344:       end if;
                    345:       cont := true;
                    346:     end Diff_Term;
                    347:     procedure Diff_Terms is new Visiting_Iterator(Diff_Term);
                    348:
                    349:   begin
                    350:     cnt := 0;
                    351:     Diff_Terms(p);
                    352:     if dp /= Null_Poly
                    353:      then ind := Head_Term(dp).dg'first;
                    354:           cp := Create(dp,n,nb,Degree(dp,ind));
                    355:     end if;
                    356:   end Diff;
                    357:
                    358:   function Coeff ( p : Poly ) return Vector is
                    359:
                    360:     res : Vector(1..Number_of_Terms(p));
                    361:     cnt : natural := 0;
                    362:
                    363:     procedure Collect_Term ( t : in Term; cont : out boolean ) is
                    364:     begin
                    365:       cnt := cnt + 1;
                    366:       copy(t.cf,res(cnt));
                    367:       cont := true;
                    368:     end Collect_Term;
                    369:     procedure Collect_Terms is new Visiting_Iterator(Collect_Term);
                    370:
                    371:   begin
                    372:     Collect_Terms(p);
                    373:     return res;
                    374:   end Coeff;
                    375:
                    376: -- EVALUATORS :
                    377:
                    378:   function Eval ( p : Poly; x : number; i : integer ) return Poly is
                    379:
                    380:     res : Poly := Null_Poly;
                    381:
                    382:     procedure Eval_Term ( t : in Term; cont : out boolean ) is
                    383:
                    384:       nt : Term;
                    385:
                    386:     begin
                    387:       Copy(t.cf,nt.cf);
                    388:       nt.dg := new Standard_Natural_Vectors.Vector(t.dg'first..t.dg'last-1);
                    389:       for j in t.dg'range loop
                    390:         if j < i
                    391:          then nt.dg(j) := t.dg(j);
                    392:          elsif j > i
                    393:              then nt.dg(j-1) := t.dg(j);
                    394:              else for k in 1..t.dg(i) loop
                    395:                     Mul(nt.cf,x);
                    396:                   end loop;
                    397:         end if;
                    398:       end loop;
                    399:       Add(res,nt);
                    400:       Clear(nt);
                    401:       cont := true;
                    402:     end Eval_Term;
                    403:     procedure Eval_Terms is new Visiting_Iterator(Eval_Term);
                    404:
                    405:   begin
                    406:     Eval_Terms(p);
                    407:     return res;
                    408:   end Eval;
                    409:
                    410:   function Eval ( d : Degrees; c : number; x : Vector ) return number is
                    411:
                    412:     res : number;
                    413:
                    414:   begin
                    415:     Copy(c,res);
                    416:     for i in d'range loop
                    417:       for j in 1..d(i) loop
                    418:         Mul(res,x(i));
                    419:       end loop;
                    420:     end loop;
                    421:     return res;
                    422:   end Eval;
                    423:
                    424:   function Eval ( t : Term; x : Vector ) return number is
                    425:   begin
                    426:     return Eval(t.dg,t.cf,x);
                    427:   end Eval;
                    428:
                    429:   function Eval ( t : Term; c : number; x : Vector ) return number is
                    430:   begin
                    431:     return Eval(t.dg,c,x);
                    432:   end Eval;
                    433:
                    434:   function Eval ( p : Poly; x : Vector ) return number is
                    435:
                    436:     res : number;
                    437:
                    438:     procedure Eval_Term ( t : in Term; cont : out boolean ) is
                    439:
                    440:       tmp : number := Eval(t,x);
                    441:
                    442:     begin
                    443:       Add(res,tmp);
                    444:       Clear(tmp);
                    445:       cont := true;
                    446:     end Eval_Term;
                    447:     procedure Eval_Terms is new Visiting_Iterator(Eval_Term);
                    448:
                    449:   begin
                    450:     Copy(zero,res);
                    451:     Eval_Terms(p);
                    452:     return res;
                    453:   end Eval;
                    454:
                    455:   function Eval ( p : Poly; c,x : Vector ) return number is
                    456:
                    457:     res : number;
                    458:     cnt : natural := 0;
                    459:
                    460:     procedure Eval_Term ( t : in Term; cont : out boolean ) is
                    461:
                    462:       tmp : number := Eval(t,c(cnt),x);
                    463:
                    464:     begin
                    465:       cnt := cnt + 1;
                    466:       Add(res,tmp);
                    467:       Clear(tmp);
                    468:       cont := true;
                    469:     end Eval_Term;
                    470:     procedure Eval_Terms is new Visiting_Iterator(Eval_Term);
                    471:
                    472:   begin
                    473:     Copy(zero,res);
                    474:     Eval_Terms(p);
                    475:     return res;
                    476:   end Eval;
                    477:
                    478:   function Eval ( vp : Eval_Poly_Rep; x : Vector; i : integer ) return number;
                    479:
                    480:   function Eval ( vprec : Poly_Rec; x : Vector; i : integer ) return number is
                    481:
                    482:     res : number;
                    483:
                    484:   begin
                    485:     if vprec.k = coefficient
                    486:      then Copy(vprec.c,res);
                    487:      elsif vprec.p = null
                    488:          then Copy(zero,res);
                    489:          else res := Eval(vprec.p.all,x,i);
                    490:     end if;
                    491:     return res;
                    492:   end Eval;
                    493:
                    494:   function Eval ( vp : Eval_Poly_Rep; x : Vector; i : integer )
                    495:                 return number is
                    496:
                    497:     deg : natural := vp'length-1;
                    498:     res : number;
                    499:
                    500:   begin
                    501:     if deg = 0
                    502:      then res := Eval(vp(0),x,i+1);
                    503:      else res := Eval(vp(deg),x,i+1);
                    504:           for j in reverse 0..(deg-1) loop
                    505:             Mul(res,x(i));
                    506:             if (vp(j).k = coefficient) or else (vp(j).p /= null)
                    507:              then declare
                    508:                     temp : number := Eval(vp(j),x,i+1);
                    509:                   begin
                    510:                     Add(res,temp);
                    511:                     Clear(temp);
                    512:                   end;
                    513:             end if;
                    514:           end loop;
                    515:     end if;
                    516:     return res;
                    517:   end Eval;
                    518:
                    519:   function Eval ( p : Eval_Poly; x : Vector ) return number is
                    520:   begin
                    521:     if p = null
                    522:      then declare
                    523:             res : number;
                    524:           begin
                    525:             Copy(zero,res);
                    526:             return res;
                    527:           end;
                    528:      else return Eval(p.all,x,x'first);
                    529:     end if;
                    530:   end Eval;
                    531:
                    532:   function Eval ( vp : Eval_Coeff_Poly_Rep; c,x : Vector; i : integer )
                    533:                 return number;
                    534:
                    535:   function Eval ( vprec : Coeff_Poly_Rec; c,x : Vector; i : integer )
                    536:                 return number is
                    537:
                    538:     res : number;
                    539:
                    540:   begin
                    541:     if vprec.k = coefficient
                    542:      then Copy(c(vprec.c),res);
                    543:      else res := Eval(vprec.p.all,c,x,i);
                    544:     end if;
                    545:     return res;
                    546:   end Eval;
                    547:
                    548:   function Eval ( vp : Eval_Coeff_Poly_Rep; c,x : Vector;
                    549:                   i : integer ) return number is
                    550:
                    551:     deg : natural := vp'length-1;
                    552:     res : number;
                    553:
                    554:   begin
                    555:     if deg = 0
                    556:      then res := Eval(vp(0),c,x,i+1);
                    557:      else res := Eval(vp(deg),c,x,i+1);
                    558:           for j in reverse 0..(deg-1) loop
                    559:             Mul(res,x(i));
                    560:             if (vp(j).k = coefficient) or else (vp(j).p /= null)
                    561:              then declare
                    562:                     temp : number := Eval(vp(j),c,x,i+1);
                    563:                   begin
                    564:                     Add(res,temp);
                    565:                     Clear(temp);
                    566:                   end;
                    567:             end if;
                    568:           end loop;
                    569:     end if;
                    570:     return res;
                    571:   end Eval;
                    572:
                    573:   function Eval ( p : Eval_Coeff_Poly; c,x : Vector ) return number is
                    574:   begin
                    575:     if p = null
                    576:      then declare
                    577:             res : number;
                    578:           begin
                    579:             Copy(zero,res);
                    580:             return res;
                    581:           end;
                    582:      else return Eval(p.all,c,x,x'first);
                    583:     end if;
                    584:   end Eval;
                    585:
                    586: -- DESTRUCTORS :
                    587:
                    588:   procedure Clear ( p : in out Eval_Poly ) is
                    589:   begin
                    590:     if p /= null
                    591:      then declare
                    592:             vp : Eval_Poly_Rep renames p.all;
                    593:           begin
                    594:             for i in vp'range loop
                    595:               if vp(i).k = coefficient
                    596:                then Clear(vp(i).c);
                    597:                else Clear(vp(i).p);
                    598:               end if;
                    599:             end loop;
                    600:           end;
                    601:           free(p);
                    602:     end if;
                    603:   end Clear;
                    604:
                    605:   procedure Clear ( p : in out Eval_Coeff_Poly ) is
                    606:   begin
                    607:     if p /= null
                    608:      then declare
                    609:             vp : Eval_Coeff_Poly_Rep renames p.all;
                    610:           begin
                    611:             for i in vp'range loop
                    612:               if vp(i).k /= coefficient
                    613:                then Clear(vp(i).p);
                    614:               end if;
                    615:             end loop;
                    616:           end;
                    617:           free(p);
                    618:     end if;
                    619:   end Clear;
                    620:
                    621: end Generic_Polynomial_Functions;

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