module edsequiv;

% Check if EDS structures are equivalent

% Author: David Hartley

fluid '(xtruncate!*);


infix equiv;
precedence equiv,equal;

symbolic operator equiv;
symbolic procedure equiv(u,v);
   if cfrmp u then cfrmp v and equalcfrm(u,v)
   else if edsp u then edsp v and edscall equaleds(u,v)
   else rerror(eds,000,"Don't know how to test equivalence");


symbolic procedure equalcfrm(m,n);
   % m,n:cfrm -> equalcfrm:bool
   equall(cfrm_cob m,cfrm_cob n) and
   equall(cfrm_crd m,cfrm_crd n) and
   equaldrv(cfrm_drv m,cfrm_drv n) and
   equalrsx(cfrm_rsx m,cfrm_rsx n);


symbolic procedure equall(u,v);
   % u,v:list -> equall:bool
   (length u = length v) and subsetp(u,v);


symbolic procedure equaldrv(d1,d2);
   % d1,d2:drv -> equaldrv:bool
   equall(d1,d2) or
   equall(foreach r in d1 collect cadr r,
      	  foreach r in d2 collect cadr r) and
   equall(foreach r in d1 collect resimp simp!* caddr r,
      	  foreach r in d2 collect resimp simp!* caddr r);


symbolic procedure equalrsx(r1,r2);
   % r1,r2:rsx -> equalrsx:bool
   equall(r1,r2) or
   equall(foreach r in r1 collect absf numr simp!* r,
      	  foreach r in r2 collect absf numr simp!* r);


symbolic procedure equaleds(s1,s2);
   % s1,s2:eds -> equaleds:bool
   equalcfrm(eds_cfrm s1,eds_cfrm s2) and
   equivsys(eds_sys s1,eds_sys s2) and
   equivsys(eds_ind s1,eds_ind s2);


symbolic procedure equivsys(p,q);
   % p,q:sys -> equivsys:bool
   % Assumes background coframing set up correctly.
   equall(p := xreordersys p,q := xreordersys q) or
   begin scalar p1,q1,g,xtruncate!*; integer d;
   p1 := foreach f in setdiff(p,q) join
      if f := xreduce(f,q) then {f};
   q1 := foreach f in setdiff(q,p) join
      if f := xreduce(f,p) then {f};
   if null p1 and null q1 then return t;
   if scalarpart p1 or scalarpart q1 then
      rerror(eds,000,"Can't compare systems with 0-forms");
   if p1 then
   << d := 0; foreach f in p1 do d := max(d,degreepf f);
      xtruncate!* := d; g := xidealpf q;
      p1 := foreach f in p1 join
      	 if f := xreduce(f,g) then {f}>>;
   if p1 then return nil;
   if q1 then
   << d := 0; foreach f in q1 do d := max(d,degreepf f);
      xtruncate!* := d; g := xidealpf p;
      q1 := foreach f in q1 join
      	 if f := xreduce(f,g) then {f}>>;
   return null q1;
   end;
   
endmodule;

end;
