Annotation of OpenXM_contrib/PHC/Ada/Root_Counts/Dynlift/simplices.adb, Revision 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>