[BACK]Return to simplices.adb CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / PHC / Ada / Root_Counts / Dynlift

Annotation of OpenXM_contrib/PHC/Ada/Root_Counts/Dynlift/simplices.adb, Revision 1.1.1.1

1.1       maekawa     1: with unchecked_deallocation;
                      2: with Standard_Integer_Norms;             use Standard_Integer_Norms;
                      3: with Standard_Integer_Matrices;          use Standard_Integer_Matrices;
                      4: with Standard_Integer_Linear_Solvers;    use Standard_Integer_Linear_Solvers;
                      5: with Transformations;                    use Transformations;
                      6:
                      7: package body Simplices is
                      8:
                      9: -- DATA STRUCTURES :
                     10:
                     11:   type Point is record
                     12:     pt : Link_to_Vector;    -- the point
                     13:     si : Simplex;           -- by pivoting a new simplex is obtained
                     14:   end record;
                     15:   type Points is array ( integer range <> ) of Point;
                     16:
                     17:   type Simplex_Rep ( n : natural ) is record
                     18:     nor : vector(1..n);     -- normal to the simplex
                     19:     tra : Transfo;          -- transformation to triangulate the cell
                     20:     pts : points(1..n);     -- vector of points
                     21:   end record;
                     22:
                     23: -- AUXILIAIRIES :
                     24:
                     25:   function Diagonalize ( s : simplex ) return matrix is
                     26:
                     27:   -- DESCRIPTION :
                     28:   --   Places the vertices of the simplex, shifted w.r.t. the first point,
                     29:   --   in a matrix.  Returns the triangulated matrix.
                     30:
                     31:     a : matrix(1..s.n-1,1..s.n-1);
                     32:     x,y : Vector(1..s.n-1);
                     33:
                     34:   begin
                     35:     for k in 2..s.n loop
                     36:       x := s.pts(k).pt(x'range) - s.pts(1).pt(x'range);
                     37:       y := s.tra*x;
                     38:       for i in a'range(1) loop
                     39:         a(i,k-1) := y(i);
                     40:       end loop;
                     41:     end loop;
                     42:     return a;
                     43:   end Diagonalize;
                     44:
                     45:   function Diagonalize ( s : simplex; pt : Vector ) return matrix is
                     46:
                     47:   -- DESCRIPTION :
                     48:   --   Places the vertices of the simplex, shifted w.r.t. the first point,
                     49:   --   in a matrix.  Returns the triangulated matrix.
                     50:
                     51:     a : matrix(1..s.n-1,1..s.n);
                     52:     x,y : Vector(1..s.n-1);
                     53:
                     54:   begin
                     55:     for k in 2..s.n loop
                     56:       x := s.pts(k).pt(x'range) - s.pts(1).pt(x'range); y := s.tra*x;
                     57:       for i in a'range(1) loop
                     58:         a(i,k-1) := y(i);
                     59:       end loop;
                     60:     end loop;
                     61:     x := pt(x'range) - s.pts(1).pt(x'range); y := s.tra*x;
                     62:     for i in a'range(1) loop
                     63:       a(i,s.n) := y(i);
                     64:     end loop;
                     65:     return a;
                     66:   end Diagonalize;
                     67:
                     68:   function Create ( pts : VecVec ) return Transfo is
                     69:
                     70:     a,l : matrix(pts'first..pts'last-1,pts'first..pts'last-1);
                     71:     x : vector(pts(pts'first)'range);
                     72:
                     73:   begin
                     74:     for k in pts'first+1..pts'last loop
                     75:       x := pts(k).all - pts(pts'first).all;
                     76:       for i in a'range(1) loop
                     77:         a(i,k-1) := x(i);
                     78:       end loop;
                     79:     end loop;
                     80:     Upper_Triangulate(l,a);
                     81:     return Create(l);
                     82:   end Create;
                     83:
                     84:   function Create ( pts : VecVec ) return Vector is
                     85:
                     86:     a : matrix(pts'first..pts'last - 1,pts'range);
                     87:     res : Vector(pts'range);
                     88:
                     89:   begin
                     90:     for k in a'range(1) loop
                     91:       for i in a'range(2) loop
                     92:         a(k,i) := pts(k+1)(i) - pts(pts'first)(i);
                     93:       end loop;
                     94:     end loop;
                     95:     Upper_Triangulate(a);
                     96:     Scale(a);
                     97:     res := (res'range => 0);
                     98:     Solve0(a,res);
                     99:     Normalize(res);
                    100:     if res(res'last) < 0
                    101:      then return -res;
                    102:      else return res;
                    103:     end if;
                    104:   end Create;
                    105:
                    106: -- CREATORS :
                    107:
                    108:   function Create ( x : VecVec ) return Simplex is
                    109:
                    110:     n : natural := x'last - x'first + 1;
                    111:     res : Simplex := new Simplex_Rep(n);
                    112:     cnt : natural := x'first;
                    113:
                    114:   begin
                    115:     for k in res.pts'range loop
                    116:       res.pts(k).pt := x(cnt);
                    117:       cnt := cnt + 1;
                    118:       res.pts(k).si := Null_Simplex;
                    119:     end loop;
                    120:     res.tra := Create(x);
                    121:     res.nor := Create(x);
                    122:     return res;
                    123:   end Create;
                    124:
                    125:   procedure Update ( s : in out Simplex; x : in Link_to_Vector;
                    126:                      k : in natural ) is
                    127:
                    128:     pts : VecVec(1..s.n);
                    129:     nei : Simplex;
                    130:
                    131:   begin
                    132:     if s.pts(k).si = Null_Simplex
                    133:      then for i in pts'range loop
                    134:             if i = k
                    135:              then pts(i) := x;
                    136:              else pts(i) := s.pts(i).pt;
                    137:             end if;
                    138:           end loop;
                    139:           nei := Create(pts);
                    140:           s.pts(k).si := nei;
                    141:           nei.pts(k).si := s;
                    142:     end if;
                    143:   end Update;
                    144:
                    145:   procedure Update ( s : in out Simplex; x : in Link_to_Vector;
                    146:                      pos : in Vector ) is
                    147:   begin
                    148:     for k in pos'first..pos'last-1 loop
                    149:       if pos(k)*pos(pos'last) > 0
                    150:        then Update(s,x,k+1);
                    151:       end if;
                    152:     end loop;
                    153:   end Update;
                    154:
                    155:   procedure Update_One ( s : in out Simplex; x : in Link_to_Vector;
                    156:                          pos : in Vector ) is
                    157:
                    158:     done : boolean := false;
                    159:     nei : Simplex;
                    160:
                    161:   begin
                    162:     for k in pos'first..pos'last-1 loop
                    163:       if pos(k)*pos(pos'last) > 0
                    164:        then nei := s.pts(k+1).si;
                    165:             if nei /= Null_Simplex
                    166:              then Update_One(nei,x,Position(nei,x.all));
                    167:              else Update(s,x,k+1);
                    168:             end if;
                    169:             done := true;
                    170:       end if;
                    171:       exit when done;
                    172:     end loop;
                    173:   end Update_One;
                    174:
                    175:   procedure Update_One ( s : in out Simplex; x : in Link_to_Vector;
                    176:                          pos : in Vector; news : out Simplex ) is
                    177:
                    178:     done : boolean := false;
                    179:     nei,newsnei : Simplex;
                    180:
                    181:   begin
                    182:    -- LOOK FIRST FOR NULL SIMPLEX IN THE DIRECTION TO x :
                    183:     for k in pos'first..pos'last-1 loop
                    184:       if pos(k)*pos(pos'last) > 0
                    185:        then nei := s.pts(k+1).si;
                    186:             if nei = Null_Simplex
                    187:              then Update(s,x,k+1);
                    188:                   news := s.pts(k+1).si;
                    189:                   done := true;
                    190:             end if;
                    191:       end if;
                    192:       exit when done;
                    193:     end loop;
                    194:    -- WALK FURTHER IN THE DIRECTION TO x :
                    195:     if not done
                    196:      then Update_One(nei,x,Position(nei,x.all),newsnei);
                    197:           if newsnei /= Null_Simplex
                    198:            then news := newsnei;
                    199:                 s := nei;
                    200:           end if;
                    201:     end if;
                    202:   end Update_One;
                    203:
                    204:   procedure Update_All ( s : in out Simplex; x : in Link_to_Vector;
                    205:                          pos : in Vector; ancestor : in Simplex ) is
                    206:
                    207:     nei : Simplex;
                    208:     continue : boolean := true;
                    209:
                    210:   begin
                    211:     for k in pos'first..pos'last-1 loop
                    212:       if pos(k)*pos(pos'last) > 0
                    213:        then nei := s.pts(k+1).si;
                    214:             if nei /= Null_Simplex
                    215:              then if not Is_Vertex(nei,x.all) and nei /= ancestor
                    216:                    then Update_All(nei,x,Position(nei,x.all),s);
                    217:                   end if;
                    218:              else Update(s,x,k+1);
                    219:                   Process(s.pts(k+1).si,continue);
                    220:             end if;
                    221:       end if;
                    222:       exit when not continue;
                    223:     end loop;
                    224:   end Update_All;
                    225:
                    226:   procedure Connect ( s1,s2 : in out Simplex ) is
                    227:
                    228:     neighb : boolean;
                    229:     index1,index2 : natural;
                    230:
                    231:   begin
                    232:     neighb := true; -- assume they are neighbors
                    233:     index1 := 0;
                    234:    -- SEARCH FOR INDEX OF POINT IN s1 THAT DOES NOT BELONG TO s2 :
                    235:     for k in s1.pts'range loop
                    236:       if not Is_Vertex(s2,s1.pts(k).pt.all)
                    237:        then if (index1 = 0) and (s1.pts(k).si = Null_Simplex)
                    238:              then index1 := k;      -- kth point is not common
                    239:              else neighb := false;  -- more than one point not common
                    240:                                     -- or there is already a neighbor
                    241:             end if;
                    242:       end if;
                    243:       exit when not neighb;
                    244:     end loop;  -- either not neighb or index1 -> point in s1, not in s2
                    245:    -- SEARCH FOR INDEX OF POINT IN s2 THAT DOES NOT BELONG TO s1 :
                    246:     if neighb
                    247:      then index2 := 0;
                    248:           for k in s2.pts'range loop
                    249:             if not Is_Vertex(s1,s2.pts(k).pt.all)
                    250:              then if (index2 = 0) and (s2.pts(k).si = Null_Simplex)
                    251:                    then index2 := k;      -- kth point is not common
                    252:                    else neighb := false;  -- more than one point not common
                    253:                                           -- or there is already a neighbor
                    254:                   end if;
                    255:             end if;
                    256:             exit when not neighb;
                    257:           end loop;  -- either no neighb or index2 -> point in s2, not in s1
                    258:    -- CONNECT THE SIMPLICES WITH EACH OTHER :
                    259:           if neighb
                    260:            then s1.pts(index1).si := s2;
                    261:                 s2.pts(index2).si := s1;
                    262:           end if;
                    263:     end if;
                    264:   end Connect;
                    265:
                    266:   procedure Flatten ( s : in out Simplex ) is
                    267:   begin
                    268:     s.nor := (s.nor'range => 0);
                    269:     s.nor(s.n) := 1;
                    270:     for k in s.pts'range loop
                    271:       s.pts(k).pt(s.n) := 0;
                    272:     end loop;
                    273:   end Flatten;
                    274:
                    275: -- SELECTORS :
                    276:
                    277:   function Dimension ( s : Simplex ) return natural is
                    278:   begin
                    279:     return s.n;
                    280:   end Dimension;
                    281:
                    282:   function Normal ( s : Simplex ) return Vector is
                    283:   begin
                    284:     return s.nor;
                    285:   end Normal;
                    286:
                    287:   function Is_Flat ( s : Simplex ) return boolean is
                    288:   begin
                    289:     for i in s.nor'first..(s.nor'last-1) loop
                    290:       if s.nor(i) /= 0
                    291:        then return false;
                    292:       end if;
                    293:     end loop;
                    294:     return (s.nor(s.nor'last) = 1);
                    295:   end Is_Flat;
                    296:
                    297:   function Vertices ( s : Simplex ) return VecVec is
                    298:
                    299:     res : VecVec(s.pts'range);
                    300:
                    301:   begin
                    302:     for k in res'range loop
                    303:       res(k) := s.pts(k).pt;
                    304:     end loop;
                    305:     return res;
                    306:   end Vertices;
                    307:
                    308:   function Vertex ( s : Simplex; k : natural ) return Vector is
                    309:   begin
                    310:     return s.pts(k).pt.all;
                    311:   end Vertex;
                    312:
                    313:   function Is_Vertex ( s : Simplex; x : Vector ) return boolean is
                    314:   begin
                    315:     for k in s.pts'range loop
                    316:       if s.pts(k).pt.all = x
                    317:        then return true;
                    318:       end if;
                    319:     end loop;
                    320:     return false;
                    321:   end Is_Vertex;
                    322:
                    323:   function Equal ( s1,s2 : Simplex ) return boolean is
                    324:
                    325:     found : boolean;
                    326:
                    327:   begin
                    328:     if s1.nor /= s2.nor                -- check if normals are the same
                    329:      then return false;
                    330:      else for k in s1.pts'range loop   -- check if vertices are the same
                    331:             -- check whether s1.pts(k).pt.all occurs in s2.pts
                    332:             found := false;
                    333:             for l in s2.pts'range loop
                    334:               if s1.pts(k).pt.all = s2.pts(l).pt.all
                    335:                then found := true;
                    336:               end if;
                    337:               exit when found;
                    338:             end loop;
                    339:             if not found
                    340:              then return false;
                    341:             end if;
                    342:           end loop;
                    343:           return true;
                    344:     end if;
                    345:   end Equal;
                    346:
                    347:   function Index ( s : Simplex; x : Vector ) return natural is
                    348:   begin
                    349:     for k in s.pts'range loop
                    350:       if s.pts(k).pt.all = x
                    351:        then return k;
                    352:       end if;
                    353:     end loop;
                    354:     return 0;
                    355:   end Index;
                    356:
                    357:   function Neighbor ( s : Simplex; k : natural ) return Simplex is
                    358:   begin
                    359:     return s.pts(k).si;
                    360:   end Neighbor;
                    361:
                    362:   function Neighbor ( s : Simplex; k : natural; pos : Vector )
                    363:                     return Simplex is
                    364:   begin
                    365:     if pos(k-1)*pos(pos'last) > 0
                    366:      then return s.pts(k).si;
                    367:      else return Null_Simplex;
                    368:     end if;
                    369:   end Neighbor;
                    370:
                    371:   function Position ( s : Simplex; x : Vector ) return Vector is
                    372:
                    373:     m : matrix(x'first..x'last-1,x'range);
                    374:     pos : Vector(x'range);
                    375:     res : Vector(0..pos'last);
                    376:
                    377:   begin
                    378:    -- nbpos := nbpos + 1;
                    379:    -- put("# position computations : "); put(nbpos,1); new_line;
                    380:    -- transform point and simplex
                    381:     m := Diagonalize(s,x);
                    382:    -- solve the system
                    383:     pos := (pos'range => 0);
                    384:     Solve0(m,pos);
                    385:     res(pos'first..pos'last) := pos;
                    386:     res(0) := 0;
                    387:     for k in pos'range loop
                    388:       res(0) := res(0) + pos(k);
                    389:     end loop;
                    390:     res(0) := -res(0);
                    391:     return res;
                    392:   end Position;
                    393:
                    394:   function Is_In ( s : Simplex; x : Vector ) return boolean is
                    395:
                    396:     pos : Vector(0..x'last) := Position(s,x);
                    397:
                    398:   begin
                    399:     return Is_In(s,x,pos);
                    400:   end Is_In;
                    401:
                    402:   function Is_In ( s : Simplex; x,pos : Vector ) return boolean is
                    403:   begin
                    404:     for k in pos'first..pos'last-1 loop
                    405:       if pos(k)*pos(pos'last) > 0
                    406:        then return false;
                    407:       end if;
                    408:     end loop;
                    409:     return true;
                    410:   end Is_In;
                    411:
                    412:   function Is_In_All ( s : Simplex; x : Vector ) return boolean is
                    413:
                    414:     pos : Vector(0..x'last) := Position(s,x);
                    415:
                    416:   begin
                    417:     return Is_In_All(s,x,pos);
                    418:   end Is_In_All;
                    419:
                    420:   function Is_In_All ( s : Simplex; x : Vector ) return Simplex is
                    421:
                    422:     pos : Vector(0..x'last) := Position(s,x);
                    423:
                    424:   begin
                    425:     return Is_In_All(s,x,pos);
                    426:   end Is_In_All;
                    427:
                    428:   function Is_In_All ( s : Simplex; x,pos : Vector ) return boolean is
                    429:
                    430:     ins : boolean := true;    -- assumes that x belongs to s
                    431:
                    432:   begin
                    433:     for k in pos'first..pos'last-1 loop
                    434:       if pos(k)*pos(pos'last) > 0
                    435:        then if s.pts(k+1).si /= Null_Simplex
                    436:              then return Is_In_All(s.pts(k+1).si,x);
                    437:              else ins := false;
                    438:             end if;
                    439:       end if;
                    440:     end loop;
                    441:     return ins;
                    442:   end Is_In_All;
                    443:
                    444:   function Is_In_All ( s : Simplex; x,pos : Vector ) return Simplex is
                    445:
                    446:     ins : boolean := true;    -- assumes that x belongs to s
                    447:
                    448:   begin
                    449:     for k in pos'first..pos'last-1 loop
                    450:       if pos(k)*pos(pos'last) > 0
                    451:        then if s.pts(k+1).si /= Null_Simplex
                    452:              then return Is_In_All(s.pts(k+1).si,x);
                    453:              else ins := false;
                    454:             end if;
                    455:       end if;
                    456:     end loop;
                    457:     if ins
                    458:      then return s;
                    459:      else return Null_Simplex;
                    460:     end if;
                    461:   end Is_In_All;
                    462:
                    463:   procedure Neighbors ( s : in out Simplex; x : in Vector ) is
                    464:
                    465:     cont : boolean;
                    466:
                    467:     procedure Neighbors ( s : in out Simplex; x : in Vector;
                    468:                           cont : out boolean ) is
                    469:
                    470:       pos : Vector(0..x'last) := Position(s,x);
                    471:       continue : boolean := true;
                    472:
                    473:     begin
                    474:       for k in pos'first..pos'last-1 loop
                    475:         if pos(k)*pos(pos'last) > 0
                    476:          then if s.pts(k+1).si /= Null_Simplex
                    477:                then Neighbors(s.pts(k+1).si,x,continue);
                    478:                else Process_Neighbor(s,k+1,continue);
                    479:               end if;
                    480:         end if;
                    481:         exit when not continue;
                    482:       end loop;
                    483:       cont := continue;
                    484:     end Neighbors;
                    485:
                    486:   begin
                    487:     Neighbors(s,x,cont);
                    488:   end Neighbors;
                    489:
                    490:   function Volume ( s : Simplex ) return natural is
                    491:
                    492:     m : constant matrix := Diagonalize(s);
                    493:     vol : integer := 1;
                    494:
                    495:   begin
                    496:     for k in m'range(1) loop
                    497:       vol := vol*m(k,k);
                    498:     end loop;
                    499:     if vol >= 0
                    500:      then return vol;
                    501:      else return -vol;
                    502:     end if;
                    503:   end Volume;
                    504:
                    505: -- DESTRUCTORS :
                    506:
                    507:   procedure Destroy_Neighbor ( s : in out Simplex; k : in natural ) is
                    508:   begin
                    509:     s.pts(k).si := Null_Simplex;
                    510:   end Destroy_Neighbor;
                    511:
                    512:   procedure Destroy_Neighbors ( s : in out Simplex ) is
                    513:   begin
                    514:     for k in s.pts'range loop
                    515:       Destroy_Neighbor(s,k);
                    516:     end loop;
                    517:   end Destroy_Neighbors;
                    518:
                    519:   procedure Clear_Neighbor ( s : in out Simplex; k : in natural ) is
                    520:   begin
                    521:     Clear(s.pts(k).si);
                    522:   end Clear_Neighbor;
                    523:
                    524:   procedure Clear_Neighbors ( s : in out Simplex ) is
                    525:   begin
                    526:     for k in s.pts'range loop
                    527:       Clear_Neighbor(s,k);
                    528:     end loop;
                    529:   end Clear_Neighbors;
                    530:
                    531:   procedure Clear ( s : in out Simplex ) is
                    532:
                    533:     procedure free is new unchecked_deallocation(Simplex_Rep,Simplex);
                    534:
                    535:   begin
                    536:     Clear(s.tra);
                    537:     free(s);
                    538:   end Clear;
                    539:
                    540: end Simplices;

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