[BACK]Return to generic_integer_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/generic_integer_linear_solvers.adb, Revision 1.1

1.1     ! maekawa     1: package body Generic_Integer_Linear_Solvers is
        !             2:
        !             3:   use Common_Divisors;
        !             4:
        !             5: -- SCALERS :
        !             6:
        !             7:   function Divisors ( a : Matrix ) return Vectors.Vector is
        !             8:
        !             9:   -- DESCRIPTION :
        !            10:   --   Returns a vector containing the gcd of the elements of each row.
        !            11:
        !            12:     v : Vectors.Vector(a'range(1));
        !            13:
        !            14:   begin
        !            15:     for i in a'range(1) loop
        !            16:       v(i) := a(i,a'first(2));
        !            17:       if not Equal(v(i),one)
        !            18:        then for j in (a'first(2)+1)..a'last(2) loop
        !            19:               v(i) := gcd(v(i),a(i,j));
        !            20:               exit when Equal(v(i),one);
        !            21:             end loop;
        !            22:       end if;
        !            23:     end loop;
        !            24:     return v;
        !            25:   end Divisors;
        !            26:
        !            27:   function Scale ( a : Matrix ) return Matrix is
        !            28:
        !            29:     v : Vectors.Vector(a'range(1)) := Divisors(a);
        !            30:     b : Matrix(a'range(1),a'range(2));
        !            31:
        !            32:   begin
        !            33:     for i in b'range(1) loop
        !            34:       if (Equal(v(i),one) or Equal(v(i),zero))
        !            35:        then for j in b'range(2) loop
        !            36:              b(i,j) := a(i,j);
        !            37:             end loop;
        !            38:        else for j in b'range(2) loop
        !            39:              b(i,j) := a(i,j) / v(i);
        !            40:             end loop;
        !            41:       end if;
        !            42:     end loop;
        !            43:     return b;
        !            44:   end Scale;
        !            45:
        !            46:   procedure Scale ( a : in out Matrix; v : out Vectors.Vector ) is
        !            47:
        !            48:     dv : Vectors.Vector(a'range(1)) := Divisors(a);
        !            49:
        !            50:   begin
        !            51:     for i in a'range(1) loop
        !            52:       if (Equal(dv(i),one) or Equal(dv(i),zero))
        !            53:        then null;
        !            54:        else for j in a'range(2) loop
        !            55:              a(i,j) := a(i,j) / dv(i);
        !            56:             end loop;
        !            57:       end if;
        !            58:     end loop;
        !            59:     v := dv;
        !            60:   end Scale;
        !            61:
        !            62:   procedure Scale ( a : in out Matrix ) is
        !            63:
        !            64:     v : Vectors.Vector(a'range(1)) := Divisors(a);
        !            65:
        !            66:   begin
        !            67:     for i in a'range(1) loop
        !            68:       if (Equal(v(i),one) or Equal(v(i),zero))
        !            69:        then null;
        !            70:        else for j in a'range(2) loop
        !            71:              a(i,j) := a(i,j) / v(i);
        !            72:             end loop;
        !            73:       end if;
        !            74:     end loop;
        !            75:   end Scale;
        !            76:
        !            77:   procedure Scale ( a : in out Matrix; row,col : in integer ) is
        !            78:
        !            79:     g : number := a(row,col);
        !            80:
        !            81:   begin
        !            82:     if not Equal(g,one)
        !            83:      then for l in (col+1)..a'last(2) loop
        !            84:             g := gcd(g,a(row,l));
        !            85:             exit when Equal(g,one);
        !            86:           end loop;
        !            87:     end if;
        !            88:     if (not Equal(g,zero)) and (not Equal(g,one))
        !            89:      then for l in row..a'last(2) loop
        !            90:             a(row,l) := a(row,l)/g;
        !            91:           end loop;
        !            92:     end if;
        !            93:   end Scale;
        !            94:
        !            95: -- STATIC TRIANGULATORS :
        !            96:
        !            97:   procedure Upper_Triangulate ( l : out Matrix; a : in out Matrix ) is
        !            98:
        !            99:     row,pivot : integer;
        !           100:     temp,aa,bb,ka,lb,d,a_rowk,a_ik : number;
        !           101:     ll : Matrix(a'range(1),a'range(1));
        !           102:
        !           103:   begin
        !           104:     for i in ll'range(1) loop
        !           105:       for j in ll'range(2) loop
        !           106:         Copy(zero,ll(i,j));
        !           107:       end loop;
        !           108:       Copy(one,ll(i,i));
        !           109:     end loop;
        !           110:     row := a'first(1);
        !           111:     for j in a'first(2)..a'last(2) loop
        !           112:       pivot := row-1;                                         -- find pivot
        !           113:       for i in row..a'last(1) loop
        !           114:         if not Equal(a(i,j),zero)
        !           115:          then pivot := i;
        !           116:               exit;
        !           117:         end if;
        !           118:       end loop;
        !           119:       if pivot >= row
        !           120:        then if pivot /= row                      -- interchange if necessary
        !           121:              then for k in a'range(2) loop
        !           122:                     Copy(a(row,k),temp);
        !           123:                     Copy(a(pivot,k),a(row,k));
        !           124:                     Copy(temp,a(pivot,k));
        !           125:                   end loop;
        !           126:                   for k in ll'range(2) loop
        !           127:                     Copy(ll(row,k),temp);
        !           128:                     Copy(ll(pivot,k),ll(row,k));
        !           129:                     Copy(temp,ll(pivot,k));
        !           130:                   end loop;
        !           131:             end if;
        !           132:             for i in (row+1)..a'last(1) loop                  -- make zeroes
        !           133:               if not Equal(a(i,j),zero)
        !           134:                then gcd(a(row,j),a(i,j),ka,lb,d);
        !           135:                     aa := a(row,j)/d;     bb := a(i,j)/d;
        !           136:                     if Equal(aa,bb) and then Equal(ka,zero)
        !           137:                      then Copy(lb,ka); Copy(zero,lb);
        !           138:                     end if;
        !           139:                     if Equal(aa,-bb) and then Equal(ka,zero)
        !           140:                      then ka := -lb; Copy(zero,lb);
        !           141:                     end if;
        !           142:                     for k in j..a'last(2) loop
        !           143:                       Copy(a(row,k),a_rowk); Clear(a(row,k));
        !           144:                          -- a_rowk := a(row,k);
        !           145:                       Copy(a(i,k),a_ik); Clear(a(i,k)); -- a_ik := a(i,k);
        !           146:                       a(row,k) :=  ka*a_rowk + lb*a_ik;
        !           147:                       a(i,k)   := -bb*a_rowk + aa*a_ik;
        !           148:                     end loop;
        !           149:                     for k in ll'range(2) loop
        !           150:                       a_rowk := ll(row,k);
        !           151:                       a_ik := ll(i,k);
        !           152:                       ll(row,k) :=  ka*a_rowk + lb*a_ik;
        !           153:                       ll(i,k)   := -bb*a_rowk + aa*a_ik;
        !           154:                     end loop;
        !           155:               end if;
        !           156:            end loop;
        !           157:            row := row + 1;
        !           158:       end if;
        !           159:       exit when row > a'last(1);
        !           160:     end loop;
        !           161:     l := ll;
        !           162:   end Upper_Triangulate;
        !           163:
        !           164:   procedure Upper_Triangulate ( a : in out Matrix ) is
        !           165:
        !           166:     row,pivot : integer;
        !           167:     temp,aa,bb,ka,lb,d,a_rowk,a_ik : number;
        !           168:
        !           169:   begin
        !           170:     row := a'first(1);
        !           171:     for j in a'first(2)..a'last(2) loop
        !           172:       pivot := row-1;                                           -- find pivot
        !           173:       for i in row..a'last(1) loop
        !           174:         if not Equal(a(i,j),zero)
        !           175:          then pivot := i;
        !           176:               exit;
        !           177:         end if;
        !           178:       end loop;
        !           179:       if pivot >= row
        !           180:        then if pivot /= row                       -- interchange if necessary
        !           181:             then for k in a'range(2) loop
        !           182:                   Copy(a(row,k),temp);
        !           183:                   Copy(a(pivot,k),a(row,k));
        !           184:                   Copy(temp,a(pivot,k));
        !           185:                 end loop;
        !           186:            end if;
        !           187:            for i in (row+1)..a'last(1) loop                    -- make zeroes
        !           188:              if not Equal(a(i,j),zero)
        !           189:               then gcd(a(row,j),a(i,j),ka,lb,d);
        !           190:                    aa := a(row,j)/d;     bb := a(i,j)/d;
        !           191:                    if Equal(aa,bb) and then Equal(ka,zero)
        !           192:                     then Copy(lb,ka); Copy(zero,lb);
        !           193:                    end if;
        !           194:                    if Equal(aa,-bb) and then Equal(ka,zero)
        !           195:                     then ka := -lb; Copy(zero,lb);
        !           196:                    end if;
        !           197:                   for k in j..a'last(2) loop
        !           198:                      Copy(a(row,k),a_rowk); Clear(a(row,k));
        !           199:                                --a_rowk := a(row,k);
        !           200:                      Copy(a(i,k),a_ik); Clear(a(i,k)); --a_ik   := a(i,k);
        !           201:                      a(row,k) :=  ka*a_rowk + lb*a_ik;
        !           202:                      a(i,k)   := -bb*a_rowk + aa*a_ik;
        !           203:                    end loop;
        !           204:              end if;
        !           205:            end loop;
        !           206:           row := row + 1;
        !           207:        end if;
        !           208:        exit when row > a'last(1);
        !           209:     end loop;
        !           210:   end Upper_Triangulate;
        !           211:
        !           212:   procedure Upper_Triangulate
        !           213:                  ( a : in out Matrix;
        !           214:                    ipvt : in out Standard_Integer_Vectors.Vector ) is
        !           215:
        !           216:     row,pivot,tmppiv : integer;
        !           217:     temp,aa,bb,ka,lb,d,a_rowk,a_ik : number;
        !           218:
        !           219:   begin
        !           220:     row := a'first(1);
        !           221:     for j in a'first(2)..a'last(2) loop
        !           222:       pivot := row-1;                                           -- find pivot
        !           223:       for i in row..a'last(1) loop
        !           224:         if not Equal(a(i,j),zero)
        !           225:          then pivot := i;
        !           226:               exit;
        !           227:         end if;
        !           228:       end loop;
        !           229:       if pivot >= row
        !           230:        then if pivot /= row                       -- interchange if necessary
        !           231:             then for k in a'range(2) loop
        !           232:                    Copy(a(row,k),temp);
        !           233:                    Copy(a(pivot,k),a(row,k));
        !           234:                    Copy(temp,a(pivot,k));
        !           235:                 end loop;
        !           236:                  tmppiv := ipvt(row);
        !           237:                  ipvt(row) := ipvt(pivot);
        !           238:                  ipvt(pivot) := tmppiv;
        !           239:            end if;
        !           240:            for i in (row+1)..a'last(1) loop                   -- make zeroes
        !           241:              if not Equal(a(i,j),zero)
        !           242:               then gcd(a(row,j),a(i,j),ka,lb,d);
        !           243:                    aa := a(row,j)/d;     bb := a(i,j)/d;
        !           244:                    if Equal(aa,bb) and then Equal(ka,zero)
        !           245:                     then Copy(lb,ka); Copy(zero,lb);
        !           246:                    end if;
        !           247:                    if Equal(aa,-bb) and then Equal(ka,zero)
        !           248:                     then ka := -lb; Copy(zero,lb);
        !           249:                    end if;
        !           250:                    for k in j..a'last(2) loop
        !           251:                      Copy(a(row,k),a_rowk); Clear(a(row,k));
        !           252:                          -- a_rowk := a(row,k);
        !           253:                      Copy(a(i,k),a_ik); Clear(a(i,k)); -- a_ik   := a(i,k);
        !           254:                      a(row,k) :=  ka*a_rowk + lb*a_ik;
        !           255:                      a(i,k)   := -bb*a_rowk + aa*a_ik;
        !           256:                    end loop;
        !           257:              end if;
        !           258:            end loop;
        !           259:           row := row + 1;
        !           260:        end if;
        !           261:        exit when row > a'last(1);
        !           262:     end loop;
        !           263:   end Upper_Triangulate;
        !           264:
        !           265:   procedure Lower_Triangulate ( a : in out Matrix; u : out Matrix ) is
        !           266:
        !           267:     column,pivot : integer;
        !           268:     temp,aa,bb,ka,lb,d,a_kcolumn,a_kj : number;
        !           269:     uu : Matrix(a'range(2),a'range(2));
        !           270:
        !           271:   begin
        !           272:
        !           273:     for i in uu'range(1) loop
        !           274:       for j in uu'range(2) loop
        !           275:         Copy(zero,uu(i,j));
        !           276:       end loop;
        !           277:       Copy(one,uu(i,i));
        !           278:     end loop;
        !           279:     column := a'first(2);
        !           280:     for i in a'first(1)..a'last(1) loop
        !           281:       pivot := column-1;                                      -- find pivot
        !           282:       for j in column..a'last(2) loop
        !           283:         if not Equal(a(i,j),zero)
        !           284:          then pivot := j;
        !           285:               exit;
        !           286:         end if;
        !           287:       end loop;
        !           288:       if pivot >= column
        !           289:        then if pivot /= column                  -- interchange if necessary
        !           290:              then for k in a'range(1) loop
        !           291:                     Copy(a(k,column),temp);
        !           292:                     Copy(a(k,pivot),a(k,column));
        !           293:                     Copy(temp,a(k,pivot));
        !           294:                   end loop;
        !           295:                   for k in uu'range(1) loop
        !           296:                     Copy(uu(k,column),temp);
        !           297:                     Copy(uu(k,pivot),uu(k,column));
        !           298:                     Copy(temp,uu(k,pivot));
        !           299:                   end loop;
        !           300:             end if;
        !           301:             for j in (column+1)..a'last(2) loop               -- make zeroes
        !           302:               if not Equal(a(i,j),zero)
        !           303:                then gcd(a(i,column),a(i,j),ka,lb,d);
        !           304:                     aa := a(i,column)/d;        bb := a(i,j)/d;
        !           305:                     if Equal(aa,bb) and then Equal(ka,zero)
        !           306:                      then Copy(lb,ka); Copy(zero,lb);
        !           307:                     end if;
        !           308:                     if Equal(aa,-bb) and then Equal(ka,zero)
        !           309:                      then ka := -lb; Copy(zero,lb);
        !           310:                     end if;
        !           311:                     for k in i..a'last(1) loop
        !           312:                       Copy(a(k,column),a_kcolumn); Clear(a(k,column));
        !           313:                                               -- a_kcolumn := a(k,column);
        !           314:                       Copy(a(k,j),a_kj); Clear(a(k,j)); -- a_kj := a(k,j);
        !           315:                       a(k,column) := a_kcolumn*ka    + a_kj*lb;
        !           316:                       a(k,j)      := a_kcolumn*(-bb) + a_kj*aa;
        !           317:                     end loop;
        !           318:                     for k in uu'range(1) loop
        !           319:                       Copy(uu(k,column),a_kcolumn); Clear(uu(k,column));
        !           320:                                                -- a_kcolumn := uu(k,column);
        !           321:                       Copy(uu(k,j),a_kj); Clear(u(k,j)); -- a_kj := uu(k,j);
        !           322:                       uu(k,column) := a_kcolumn*ka    + a_kj*lb;
        !           323:                       uu(k,j)      := a_kcolumn*(-bb) + a_kj*aa;
        !           324:                     end loop;
        !           325:               end if;
        !           326:             end loop;
        !           327:             column := column + 1;
        !           328:       end if;
        !           329:       exit when column > a'last(2);
        !           330:     end loop;
        !           331:     u := uu;
        !           332:   end Lower_Triangulate;
        !           333:
        !           334:   procedure Lower_Triangulate ( a : in out Matrix ) is
        !           335:
        !           336:     column,pivot : integer;
        !           337:     temp,aa,bb,ka,lb,d,a_kcolumn,a_kj : number;
        !           338:
        !           339:   begin
        !           340:     column := a'first(2);
        !           341:     for i in a'first(1)..a'last(1) loop
        !           342:       pivot := column-1;                                      -- find pivot
        !           343:       for j in column..a'last(2) loop
        !           344:         if not Equal(a(i,j),zero)
        !           345:          then pivot := j;
        !           346:               exit;
        !           347:         end if;
        !           348:       end loop;
        !           349:       if pivot >= column
        !           350:        then if pivot /= column                  -- interchange if necessary
        !           351:              then for k in a'range(1) loop
        !           352:                     Copy(a(k,column),temp);
        !           353:                     Copy(a(k,pivot),a(k,column));
        !           354:                     Copy(temp,a(k,pivot));
        !           355:                   end loop;
        !           356:             end if;
        !           357:             for j in (column+1)..a'last(2) loop               -- make zeroes
        !           358:              if not Equal(a(i,j),zero)
        !           359:               then gcd(a(i,column),a(i,j),ka,lb,d);
        !           360:                    aa := a(i,column)/d; bb := a(i,j)/d;
        !           361:                    if Equal(aa,bb) and then Equal(ka,zero)
        !           362:                     then Copy(lb,ka); Copy(zero,lb);
        !           363:                    end if;
        !           364:                    if Equal(aa,-bb) and then Equal(ka,zero)
        !           365:                     then ka := -lb; Copy(zero,lb);
        !           366:                    end if;
        !           367:                    for k in i..a'last(1) loop
        !           368:                      Copy(a(k,column),a_kcolumn); Clear(a(k,column));
        !           369:                                          -- a_kcolumn := a(k,column);
        !           370:                      Copy(a(k,j),a_kj); Clear(a(k,j)); -- a_kj := a(k,j);
        !           371:                      a(k,column) := a_kcolumn*ka    + a_kj*lb;
        !           372:                      a(k,j)      := a_kcolumn*(-bb) + a_kj*aa;
        !           373:                    end loop;
        !           374:              end if;
        !           375:            end loop;
        !           376:            column := column + 1;
        !           377:       end if;
        !           378:       exit when column > a'last(2);
        !           379:     end loop;
        !           380:   end Lower_Triangulate;
        !           381:
        !           382:   procedure Lower_Triangulate
        !           383:                ( a : in out Matrix;
        !           384:                  ipvt : in out Standard_Integer_Vectors.Vector ) is
        !           385:
        !           386:     column,pivot,tmppiv : integer;
        !           387:     temp,aa,bb,ka,lb,d,a_kcolumn,a_kj : number;
        !           388:
        !           389:   begin
        !           390:     column := a'first(2);
        !           391:     for i in a'first(1)..a'last(1) loop
        !           392:       pivot := column-1;                                       -- find pivot
        !           393:       for j in column..a'last(2) loop
        !           394:         if not Equal(a(i,j),zero)
        !           395:          then pivot := j;
        !           396:               exit;
        !           397:         end if;
        !           398:       end loop;
        !           399:       if pivot >= column
        !           400:        then if pivot /= column                   -- interchange if necessary
        !           401:              then for k in a'range(1) loop
        !           402:                     Copy(a(k,column),temp);
        !           403:                     Copy(a(k,pivot),a(k,column));
        !           404:                     Copy(temp,a(k,pivot));
        !           405:                   end loop;
        !           406:                   tmppiv := ipvt(column);
        !           407:                   ipvt(column) := ipvt(pivot);
        !           408:                   ipvt(pivot) := tmppiv;
        !           409:             end if;
        !           410:             for j in (column+1)..a'last(2) loop               -- make zeroes
        !           411:               if not Equal(a(i,j),zero)
        !           412:                then gcd(a(i,column),a(i,j),ka,lb,d);
        !           413:                     aa := a(i,column)/d; bb := a(i,j)/d;
        !           414:                     if Equal(aa,bb) and then Equal(ka,zero)
        !           415:                      then Copy(lb,ka); Copy(zero,lb);
        !           416:                     end if;
        !           417:                     if Equal(aa,-bb) and then Equal(ka,zero)
        !           418:                      then ka := -lb; Copy(zero,lb);
        !           419:                     end if;
        !           420:                     for k in i..a'last(1) loop
        !           421:                       Copy(a(k,column),a_kcolumn); Clear(a(k,column));
        !           422:                                                 -- a_kcolumn := a(k,column);
        !           423:                       Copy(a(k,j),a_kj); Clear(a(k,j)); -- a_kj := a(k,j);
        !           424:                       a(k,column) := a_kcolumn*ka    + a_kj*lb;
        !           425:                       a(k,j)      := a_kcolumn*(-bb) + a_kj*aa;
        !           426:                     end loop;
        !           427:               end if;
        !           428:             end loop;
        !           429:             column := column + 1;
        !           430:       end if;
        !           431:       exit when column > a'last(2);
        !           432:     end loop;
        !           433:   end Lower_Triangulate;
        !           434:
        !           435: -- SELECTORS :
        !           436:
        !           437:   function Det ( a : Matrix ) return number is
        !           438:
        !           439:   -- NOTE :
        !           440:   --   The triangulation is implemented independently to keep track
        !           441:   --   of row interchanges.
        !           442:
        !           443:     res : number := one;
        !           444:     m : matrix(a'range(1),a'range(2));
        !           445:     row,pivot : integer;
        !           446:     temp,aa,bb,ka,lb,d,m_rowk,m_ik : number;
        !           447:
        !           448:   begin
        !           449:     Copy(a,m);   -- triangulate m
        !           450:     row := m'first(1);
        !           451:     for j in m'first(2)..m'last(2) loop
        !           452:       pivot := row-1;                                           -- find pivot
        !           453:       for i in row..m'last(1) loop
        !           454:         if not Equal(m(i,j),zero)
        !           455:          then pivot := i;
        !           456:               exit;
        !           457:         end if;
        !           458:       end loop;
        !           459:       if pivot >= row
        !           460:        then if pivot /= row                       -- interchange if necessary
        !           461:              then for k in m'range(2) loop
        !           462:                     Copy(m(row,k),temp);
        !           463:                     Copy(m(pivot,k),m(row,k));
        !           464:                     Copy(temp,m(pivot,k));
        !           465:                   end loop;
        !           466:                   Min(res);
        !           467:             end if;
        !           468:             for i in (row+1)..m'last(1) loop                   -- make zeroes
        !           469:               if not Equal(m(i,j),zero)
        !           470:                then gcd(m(row,j),m(i,j),ka,lb,d);
        !           471:                     aa := m(row,j)/d; bb := m(i,j)/d;
        !           472:                     if Equal(aa,bb) and then Equal(ka,zero)
        !           473:                      then Copy(lb,ka); Copy(zero,lb);
        !           474:                     end if;
        !           475:                     if Equal(aa,-bb) and then Equal(ka,zero)
        !           476:                      then ka := -lb; Copy(zero,lb);
        !           477:                     end if;
        !           478:                     for k in j..m'last(2) loop
        !           479:                       Copy(m(row,k),m_rowk); Clear(m(row,k));
        !           480:                                                          -- m_rowk := m(row,k);
        !           481:                       Copy(m(i,k),m_ik); Clear(m(i,k));  -- m_ik   := m(i,k);
        !           482:                       m(row,k) :=  ka*m_rowk + lb*m_ik;
        !           483:                       m(i,k)   := -bb*m_rowk + aa*m_ik;
        !           484:                     end loop;
        !           485:               end if;
        !           486:             end loop;
        !           487:             row := row + 1;
        !           488:        end if;
        !           489:        exit when row > m'last(1);
        !           490:     end loop;
        !           491:     for k in m'range(1) loop
        !           492:       Mul(res,m(k,k));
        !           493:     end loop;
        !           494:     Clear(m);
        !           495:     return res;
        !           496:   end Det;
        !           497:
        !           498:   function Per ( i,n : natural; a : matrix;
        !           499:                  kk : Standard_Integer_Vectors.Vector ) return number is
        !           500:   begin
        !           501:     if i = n+1
        !           502:      then return one;
        !           503:      else declare
        !           504:             res,acc : number;
        !           505:             kkk : Standard_Integer_Vectors.Vector(kk'range) := kk;
        !           506:           begin
        !           507:             Copy(zero,res);
        !           508:             for j in kk'range loop
        !           509:               if not Equal(a(i,j),zero) and then (kk(j) /= 0)
        !           510:                then kkk(j) := kkk(j) - 1;
        !           511:                     acc := Per(i+1,n,a,kkk);
        !           512:                     Add(res,acc);
        !           513:                     Clear(acc);
        !           514:                     kkk(j) := kkk(j) + 1;
        !           515:               end if;
        !           516:             end loop;
        !           517:             return res;
        !           518:           end;
        !           519:     end if;
        !           520:   end Per;
        !           521:
        !           522:   function Per ( i,n : natural; a : matrix;
        !           523:                  kk : Standard_Integer_Vectors.Vector; max : number )
        !           524:                return number is
        !           525:   begin
        !           526:     if i = n+1
        !           527:      then return one;
        !           528:      else declare
        !           529:             res,acc : number;
        !           530:             kkk : Standard_Integer_Vectors.Vector(kk'range) := kk;
        !           531:           begin
        !           532:             Copy(zero,res);
        !           533:             for j in kk'range loop
        !           534:               if not Equal(a(i,j),zero) and then (kk(j) /= 0)
        !           535:                then kkk(j) := kkk(j) - 1;
        !           536:                     acc := a(i,j)*Per(i+1,n,a,kkk,max);
        !           537:                     Add(res,acc);
        !           538:                     Clear(acc);
        !           539:                     kkk(j) := kkk(j) + 1;
        !           540:               end if;
        !           541:               exit when (res > max) or Equal(res,max);
        !           542:             end loop;
        !           543:             return res;
        !           544:           end;
        !           545:     end if;
        !           546:   end Per;
        !           547:
        !           548:   function Per ( a : matrix; k : Standard_Integer_Vectors.Vector )
        !           549:                return number is
        !           550:
        !           551:   -- ALGORITHM :
        !           552:   --   Row expansion without memory, as developed by C.W. Wampler,
        !           553:   --   see `Bezout Number Calculations for Multi-Homogeneous Polynomial
        !           554:   --        Systems', Appl. Math. Comput. 51:(2-3), 143-157, 1992.
        !           555:
        !           556:   begin
        !           557:     return Per(1,a'last(1),a,k);
        !           558:   end Per;
        !           559:
        !           560:   function Per ( a : matrix; k : Standard_Integer_Vectors.Vector;
        !           561:                  max : number ) return number is
        !           562:
        !           563:   -- ALGORITHM :
        !           564:   --   Row expansion without memory, as developed by C.W. Wampler,
        !           565:   --   see `Bezout Number Calculations for Multi-Homogeneous Polynomial
        !           566:   --        Systems', Appl. Math. Comput. 51:(2-3), 143-157, 1992.
        !           567:
        !           568:   begin
        !           569:     return Per(1,a'last(1),a,k,max);
        !           570:   end Per;
        !           571:
        !           572:   function Rank ( a : Matrix ) return natural is
        !           573:
        !           574:     res : natural := 0;
        !           575:     m : Matrix(a'range(1),a'range(2));
        !           576:     column : integer;
        !           577:
        !           578:   begin
        !           579:     Copy(a,m);
        !           580:     Upper_Triangulate(m);
        !           581:    -- compute the length of chain of nonzero elements in m :
        !           582:    -- search first nonzero element in first row of m :
        !           583:     column := m'first(2)-1;
        !           584:     for k in m'range(2) loop
        !           585:       if not Equal(m(m'first(1),k),zero)
        !           586:        then column := k;
        !           587:       end if;
        !           588:       exit when (column = k);
        !           589:     end loop;
        !           590:     if column < m'first(2)
        !           591:      then return 0;   -- all elements of m are zero
        !           592:      else for k in m'range(1) loop
        !           593:             exit when column > m'last(2);
        !           594:             if not Equal(m(k,column),zero)
        !           595:              then res := res + 1;
        !           596:              else -- search for next nonzero element on row k :
        !           597:                   for l in column+1..m'last(2) loop
        !           598:                     if not Equal(m(k,l),zero)
        !           599:                      then column := l;
        !           600:                           res := res + 1;
        !           601:                     end if;
        !           602:                     exit when (column = l);
        !           603:                   end loop;
        !           604:             end if;
        !           605:             column := column + 1;
        !           606:           end loop;
        !           607:     end if;
        !           608:     Clear(m);
        !           609:     return res;
        !           610:   end Rank;
        !           611:
        !           612: -- DYNAMIC TRIANGULATOR :
        !           613:
        !           614:   procedure Triangulate ( l : in integer; m : in out matrix;
        !           615:                           ipvt : in out Standard_Integer_Vectors.vector;
        !           616:                           piv : out integer ) is
        !           617:
        !           618:   -- DESCRIPTION :
        !           619:   --   Updates lth row of m such that m remains upper triangular.
        !           620:
        !           621:     tmp,a,b,lcmab,faca,facb : number;
        !           622:     pivot,index,tmppiv : integer;
        !           623:
        !           624:   begin
        !           625:     Switch(ipvt,l,m);                      -- pivoting for previous unknowns
        !           626:     index := 1;                         -- update : make l-1 zeroes in row l
        !           627:     for k in 1..(l-1) loop
        !           628:       if (not Equal(m(l,index),zero))
        !           629:          and then (not Equal(m(k,index),zero))    -- make m(l,index) zero
        !           630:        then a := m(k,index); b := m(l,index);
        !           631:             lcmab := lcm(a,b);
        !           632:             if lcmab < zero then lcmab := -lcmab; end if;
        !           633:             facb := lcmab/b; faca := lcmab/a;
        !           634:             if facb > zero
        !           635:              then for i in index..m'last(2) loop
        !           636:                     m(l,i) :=  facb*m(l,i) - faca*m(k,i);
        !           637:                   end loop;
        !           638:              else for i in index..m'last(2) loop
        !           639:                     m(l,i) := -facb*m(l,i) + faca*m(k,i);
        !           640:                   end loop;
        !           641:             end if;
        !           642:       end if;
        !           643:       if not Equal(m(k,index),zero)
        !           644:        then index := index + 1;
        !           645:       end if;
        !           646:     end loop;
        !           647:     pivot := 0;                                              -- search pivot
        !           648:     for k in l..m'last(2)-1 loop
        !           649:       if not Equal(m(l,k),zero)
        !           650:        then pivot := k;
        !           651:       end if;
        !           652:       exit when pivot /= 0;
        !           653:     end loop;
        !           654:     if pivot > l
        !           655:      then for k in 1..l loop              -- interchange columns l and pivot
        !           656:             Copy(m(k,l),tmp);
        !           657:             Copy(m(k,pivot),m(k,l));
        !           658:             Copy(tmp,m(k,pivot));
        !           659:           end loop;
        !           660:           tmppiv := ipvt(l);
        !           661:           ipvt(l) := ipvt(pivot);
        !           662:           ipvt(pivot) := tmppiv;
        !           663:     end if;
        !           664:     piv := pivot;
        !           665:   end Triangulate;
        !           666:
        !           667:   procedure Switch ( ipvt : in Standard_Integer_Vectors.vector;
        !           668:                      index : in integer; m : in out matrix ) is
        !           669:
        !           670:     tmpv : Vectors.Vector(m'range(2));
        !           671:
        !           672:   begin
        !           673:     for k in tmpv'range loop
        !           674:       Copy(m(index,k),tmpv(k));
        !           675:     end loop;
        !           676:     for k in tmpv'range loop
        !           677:       Copy(tmpv(ipvt(k)),m(index,k));
        !           678:     end loop;
        !           679:     Vectors.Clear(tmpv);
        !           680:   end Switch;
        !           681:
        !           682:   procedure Switch ( ipvt : in Standard_Integer_Vectors.vector;
        !           683:                      first,last : in integer; m : in out matrix) is
        !           684:
        !           685:     tmpv : Vectors.Vector(m'range(2));
        !           686:
        !           687:   begin
        !           688:     for index in first..last loop
        !           689:       for k in tmpv'range loop
        !           690:         Copy(m(index,k),tmpv(k));
        !           691:       end loop;
        !           692:       for k in tmpv'range loop
        !           693:         Copy(tmpv(ipvt(k)),m(index,k));
        !           694:       end loop;
        !           695:       Vectors.Clear(tmpv);
        !           696:     end loop;
        !           697:   end Switch;
        !           698:
        !           699:   procedure Switch ( l,pivot,index : in integer; m : in out matrix ) is
        !           700:
        !           701:     tmp : number;
        !           702:
        !           703:   begin
        !           704:     if l /= pivot
        !           705:      then Copy(m(index,l),tmp);
        !           706:           Copy(m(index,pivot),m(index,l));
        !           707:           Copy(tmp,m(index,pivot));
        !           708:     end if;
        !           709:   end Switch;
        !           710:
        !           711:   procedure Switch ( l,pivot : in integer;
        !           712:                      first,last : in integer; m : in out matrix ) is
        !           713:
        !           714:     tmp : number;
        !           715:
        !           716:   begin
        !           717:     if l /= pivot
        !           718:      then for index in first..last loop
        !           719:             Copy(m(index,l),tmp);
        !           720:             Copy(m(index,pivot),m(index,l));
        !           721:             Copy(tmp,m(index,pivot));
        !           722:           end loop;
        !           723:     end if;
        !           724:   end Switch;
        !           725:
        !           726: -- SOLVERS :
        !           727:
        !           728:   function Check0 ( a : Matrix; x : Vectors.Vector ) return boolean is
        !           729:
        !           730:    -- DESCRIPTION :
        !           731:    --   Returns true if x is a solution of the system a*x = 0.
        !           732:
        !           733:     tmp : Vectors.Vector(a'range(1));
        !           734:
        !           735:   begin
        !           736:     tmp := a*x;
        !           737:     for i in tmp'range loop
        !           738:       if not Equal(tmp(i),zero)
        !           739:        then Vectors.Clear(tmp); return false;
        !           740:       end if;
        !           741:     end loop;
        !           742:     Vectors.Clear(tmp);
        !           743:     return true;
        !           744:   end Check0;
        !           745:
        !           746:   procedure Solve0 ( a : in Matrix; x : in out Vectors.Vector ) is
        !           747:
        !           748:   -- ALGORITHM :
        !           749:   --   An intermediate, generating matrix tmp will be constructed,
        !           750:   --   such that
        !           751:   --      1) the solution x to tmp*x = 0 is the same of a*x = 0;
        !           752:   --      2) tmp(i,i) and tmp(i,ind) are the only nonzero entries.
        !           753:   --   Before this construction, it will be checked whether there
        !           754:   --   exists a zero column and the index ind must be determined.
        !           755:   --   After the definition of tmp, the back substitution process
        !           756:   --   yields a solution.
        !           757:
        !           758:     piv,ind : integer;
        !           759:     tmp : Matrix(a'first(1)..(a'last(1)+1),a'range(2));
        !           760:     res : Vectors.Vector(x'range);
        !           761:     pivots : Standard_Integer_Vectors.Vector(x'range);
        !           762:     zero_column : boolean;
        !           763:
        !           764:   begin
        !           765:    -- initialization of tmp,ind and pivots :
        !           766:     for i in tmp'range(1) loop
        !           767:       for j in tmp'range(2) loop
        !           768:        Copy(zero,tmp(i,j));
        !           769:       end loop;
        !           770:     end loop;
        !           771:     for i in pivots'range loop
        !           772:       pivots(i) := i;
        !           773:     end loop;
        !           774:     ind := x'first(1)-1;
        !           775:     for i in a'range(1) loop
        !           776:       piv := pivots'first-1;
        !           777:       for j in a'range(2) loop
        !           778:        if not Equal(a(i,j),zero)
        !           779:          then piv := pivots(j);
        !           780:              pivots(j) := pivots(i);
        !           781:              pivots(i) := piv;
        !           782:              exit;
        !           783:         end if;
        !           784:       end loop;
        !           785:       zero_column := true;
        !           786:       for j in a'first(1)..i loop
        !           787:         Copy(a(j,pivots(i)),tmp(j,i));
        !           788:        if zero_column and then not Equal(tmp(j,i),zero)
        !           789:         then zero_column := false;
        !           790:         end if;
        !           791:       end loop;
        !           792:       if piv < pivots'first or else zero_column or else Equal(tmp(i,i),zero)
        !           793:        then ind := i; exit;
        !           794:       end if;
        !           795:     end loop;
        !           796:     if zero_column
        !           797:      then for i in x'range loop
        !           798:             Copy(zero,x(i));
        !           799:           end loop;
        !           800:          Copy(one,x(ind));
        !           801:      elsif (ind < x'first(1)) and (a'last(1) >= a'last(2))
        !           802:          then for i in x'range loop
        !           803:                 Copy(zero,x(i));
        !           804:               end loop;
        !           805:          else
        !           806:            if ind < x'first(1)
        !           807:            then ind := a'last(1)+1;
        !           808:                 for j in tmp'range(2) loop
        !           809:                   Copy(zero,tmp(ind,j));
        !           810:                  end loop;
        !           811:                 zero_column := true;
        !           812:                 for j in a'range(1) loop
        !           813:                   Copy(a(j,pivots(ind)),tmp(j,ind));
        !           814:                   if zero_column and then not Equal(tmp(j,ind),zero)
        !           815:                    then zero_column := false;
        !           816:                    end if;
        !           817:                  end loop;
        !           818:            end if;
        !           819:            if zero_column
        !           820:            then for i in x'range loop
        !           821:                    Copy(zero,x(i));
        !           822:                  end loop;
        !           823:                 Copy(one,x(ind));
        !           824:             else
        !           825:              -- construct generating matrix :
        !           826:               for i in reverse (tmp'first(2)+1)..(ind-1) loop  -- i = column
        !           827:                 for k in tmp'first(1)..(i-1) loop
        !           828:                   if not Equal(tmp(k,i),zero)  -- make tmp(k,i) zero
        !           829:                    then declare
        !           830:                           aa,bb,d : number;
        !           831:                         begin
        !           832:                           d := gcd(tmp(i,i),tmp(k,i));
        !           833:                           aa := tmp(i,i)/d;     bb := tmp(k,i)/d;
        !           834:                           for l in k..(i-1) loop
        !           835:                             Mul(tmp(k,l),aa);
        !           836:                           end loop;
        !           837:                           Copy(zero,tmp(k,i)); --aa*tmp(k,i) - bb*tmp(i,i);
        !           838:                           tmp(k,ind) := aa*tmp(k,ind) - bb*tmp(i,ind);
        !           839:                         end;
        !           840:                         Scale(tmp,k,k);  -- to avoid numeric_error
        !           841:                   end if;
        !           842:                 end loop; -- upper half of ith colum consists of zero entries
        !           843:               end loop;
        !           844:              -- generate x by back substitution :
        !           845:               x(ind) := tmp(x'first,x'first);
        !           846:               for i in (x'first+1)..(ind-1) loop
        !           847:                if not Equal(tmp(i,i),zero)
        !           848:                  then x(ind) := lcm(tmp(i,i),x(ind));
        !           849:                 end if;
        !           850:               end loop;
        !           851:               for i in x'first..(ind-1) loop
        !           852:                if Equal(tmp(i,i),zero)
        !           853:                 then Copy(zero,x(i));
        !           854:                  else x(i) := -(tmp(i,ind)*x(ind))/tmp(i,i);
        !           855:                 end if;
        !           856:               end loop;
        !           857:            end if;
        !           858:     end if;
        !           859:     for i in res'range loop                      -- take pivots into account
        !           860:       Copy(zero,res(i));
        !           861:     end loop;
        !           862:     for i in x'first..ind loop
        !           863:       Copy(x(i),res(pivots(i)));
        !           864:     end loop;
        !           865:     Vectors.Copy(res,x);
        !           866:   end Solve0;
        !           867:
        !           868:   procedure Solve1 ( a : in Matrix; x : in out Vectors.Vector;
        !           869:                      b : in Vectors.Vector; fail : out boolean ) is
        !           870:
        !           871:     acc : number;
        !           872:
        !           873:   begin
        !           874:     fail := false;
        !           875:     for i in reverse x'range loop
        !           876:       Copy(b(i),x(i));
        !           877:       for j in (i+1)..x'last loop
        !           878:         acc := a(i,j)*x(j);
        !           879:         Sub(x(i),acc);
        !           880:         Clear(acc);
        !           881:       end loop;
        !           882:       if not Equal(x(i),zero) and then not Equal(a(i,i),zero)
        !           883:        then acc := Rmd(x(i),a(i,i));
        !           884:             if Equal(acc,zero)
        !           885:              then Div(x(i),a(i,i));
        !           886:              else fail := true;
        !           887:             end if;
        !           888:             Clear(acc);
        !           889:             if fail
        !           890:              then Vectors.Clear(x); return;
        !           891:             end if;
        !           892:       end if;
        !           893:     end loop;
        !           894:   end Solve1;
        !           895:
        !           896:   procedure Solve1 ( a : in Matrix; b : in out Vectors.Vector;
        !           897:                      fail : out boolean ) is
        !           898:
        !           899:     acc : number;
        !           900:
        !           901:   begin
        !           902:     fail := false;
        !           903:     for i in reverse b'range loop
        !           904:       for j in (i+1)..b'last loop
        !           905:         acc := a(i,j)*b(j);
        !           906:         Sub(b(i),acc);
        !           907:         Clear(acc);
        !           908:       end loop;
        !           909:       if not Equal(b(i),zero) and then not Equal(a(i,i),zero)
        !           910:        then acc := Rmd(b(i),a(i,i));
        !           911:             if Equal(acc,zero)
        !           912:              then Div(b(i),a(i,i));
        !           913:              else fail := true;
        !           914:             end if;
        !           915:             Clear(acc);
        !           916:             if fail
        !           917:              then Vectors.Clear(b); return;
        !           918:             end if;
        !           919:       end if;
        !           920:     end loop;
        !           921:   end Solve1;
        !           922:
        !           923:   function Solve ( m : Matrix; ipvt : Standard_Integer_Vectors.Vector )
        !           924:                  return Vectors.Vector is
        !           925:
        !           926:     x,res : Vectors.Vector(ipvt'range);
        !           927:     a : matrix(m'first(1)..m'last(1)-1,m'range(2));
        !           928:     ind : integer := a'first(1);       -- index for the current row number
        !           929:     cnt0 : natural := 0;                 -- counts the number of zero rows
        !           930:
        !           931:   begin
        !           932:     for k in a'range(1) loop
        !           933:       if not Equal(m(k,k),zero)               -- otherwise : skip zero row !
        !           934:        then for l in a'range(2) loop
        !           935:               Copy(m(k,l),a(ind,l));
        !           936:             end loop;
        !           937:             ind := ind + 1;
        !           938:        else for l in a'range(2) loop
        !           939:               Copy(m(k,l),a(a'last(1) - cnt0,l));
        !           940:             end loop;
        !           941:             cnt0 := cnt0 + 1;
        !           942:       end if;
        !           943:     end loop;
        !           944:     for i in x'range loop
        !           945:       Copy(zero,x(i));
        !           946:     end loop;
        !           947:     Solve0(a,x);
        !           948:     for k in res'range loop
        !           949:       res(ipvt(k)) := x(k);
        !           950:     end loop;
        !           951:     if res(res'last) < zero
        !           952:      then Vectors.Min(res);
        !           953:     end if;
        !           954:     Clear(a);
        !           955:     return res;
        !           956:   end Solve;
        !           957:
        !           958: end Generic_Integer_Linear_Solvers;

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