Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  io.gi   Sprache: unbekannt

 
Spracherkennung für: .gi vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

################################################################################
##
##  simpcomp / io.gi
##
##  simpcomp IO functions 
##
##  $Id$
##
################################################################################

#make list to dense string (not containing any spaces
SCIntFunc.ListToDenseString:=function(item)
 if(IsStringRep(item)) then
  return Concatenation(["\"",item,"\""]);
 elif(IsList(item) and not IsStringRep(item)) then
  return Concatenation("[",
      JoinStringsWithSeparator(List(item,SCIntFunc.ListToDenseString),","),"]");
 else
  return String(item);
 fi;
end;




#parsing variables
SCIntFunc.parseDelim:=',';
SCIntFunc.parseOpenstruct:='[';
SCIntFunc.parseClosestruct:=']';
SCIntFunc.parseArray:=['0','1','2','3','4','5','6','7','8','9',' ',',',
  '[',']','\'','\"'];
SCIntFunc.parseChar:='\'';
SCIntFunc.parseString:='\"';
SCIntFunc.parseEscape:='\\';

#reader functions for reading xml (pc)data 
SCIntFunc.ReadInteger:=
function(string)
 if IsEmptyString(string) or not ForAll(string,x->IsDigitChar(x) or x='-') then
  Info(InfoSimpcomp,1,"SCIntFunc.ReadInteger: error reading from string \"",
      string,"\".");
  return fail;
 else
  return Int(string);
 fi;
end;

SCIntFunc.ReadBoolean:=
function(string)
 local b;
 b:=SCIntFunc.ReadInteger(string);
 if(b<>fail) then
  if(b=0) then
   return false;
  elif(b=1) then
   return true;
  fi;
 fi;
 Info(InfoSimpcomp,1,"SCIntFunc.ReadBoolean: error reading from string \"",
    string,"\".");
 return fail;
end;

SCIntFunc.BooleanToString:=
function(b)
 if(b=false) then
  return "0";
 elif(b=true) then
  return "1";
 else
  return "2";
 fi;
end;

SCIntFunc.ReadString:=
function(string)
 return String(string);
end;


SCIntFunc.ReadArray:=
function(string)
 local p,ret,ReadArrayInteger,ReadArrayString,ReadArrayArray;

 ReadArrayInteger:=function(arr,pos)
  local p,int;

  int:=[];

  for p in [pos..Length(arr)] do
   if(IsDigitChar(arr[p]) or arr[p]='-') then
    Add(int,arr[p]);
   else
    break;
   fi;
  od;

  if(int=[] or (p=Length(arr) and not arr[Length(arr)]=']')) then
   Info(InfoSimpcomp,1,"ReadArrayInteger: error reading from string \"",
        arr,"\" at position ",pos,".");
   return [fail,pos];
  else
   return [Int(int),p];
  fi;
 end;

 ReadArrayString:=function(arr,pos)
  local p,int,delim,escape,str;

  str:=[];
  escape:=false;
  delim:=arr[pos];
  for p in [pos+1..Length(arr)] do
   if(arr[p]=SCIntFunc.parseEscape) then
    escape:=true;
    continue;
   fi;

   if(escape) then
    Add(str,arr[p]);
    escape:=false;
   elif(arr[p]=delim) then
    return [str,p+1];
   else
    Add(str,arr[p]);
   fi;
  od;

  Info(InfoSimpcomp,1,"ReadArrayString: error reading from string \"",
      arr,"\" at position ",pos,".");
  return [fail,pos];
 end;

 ReadArrayArray:=function(arr,pos)
  local p,int,ret,a,range;

  a:=[];
  range:=false;
  p:=pos+1;
  while p<=Length(arr) do
   if(arr[p]=' ' or arr[p]=',') then
    p:=p+1;
    continue;
   fi;

   if(range and not (IsDigitChar(arr[p]) or arr[p]='-')) then
    return fail;
   fi;

   if(not range and arr[p]=']') then
    return [a,p+1];
   elif(arr[p]='[') then
    ret:=ReadArrayArray(arr,p);
   elif(IsDigitChar(arr[p]) or arr[p]='-') then
    ret:=ReadArrayInteger(arr,p);
   elif(arr[p]='\'' or arr[p]='\"') then
    ret:=ReadArrayString(arr,p);
   elif(arr[p]='.' and p<Length(arr) and arr[p+1]='.') then
    range:=true;
    p:=p+2;
    continue;
   else
    Info(InfoSimpcomp,1,"ReadArrayArray: unknown type in string \"",
          arr,"\" at position ",pos,".");
    ret:=fail;
   fi;

   if(ret=fail or ret[1]=fail) then
    return fail;
   fi;

   if(not range) then
    Add(a,ret[1]);
    p:=ret[2];
   else
    range:=[a[Length(a)]..ret[1]];
    a[Length(a)]:=range;
    p:=ret[2];
    range:=false;
   fi;
  od;

  return fail;
 end;


 for p in [1..Length(string)] do
  if(string[p]=' ') then
   continue;
  fi;

  if(string[p]='[') then
   ret:=ReadArrayArray(string,p);
   if(ret=fail) then
    return fail;
   else
    return ret[1];
   fi;
  else
   break;
  fi;
 od;

 Info(InfoSimpcomp,1,"SCIntFunc.ReadArray: no starting sequence found ",
    "in string \"",string,"\".");
 return fail;
end;

SCIntFunc.ReadPerm:=
function(arr)
 local a;
 a:=SCIntFunc.ReadArray(arr);
 if(a<>fail) then
  return PermList(a);
 else
  return fail;
 fi;
end;

SCIntFunc.PermToString:=
function(p)
 return SCIntFunc.ListToDenseString(ListPerm(p));
end;


SCIntFunc.ReadPermGroup:=
function(arr)
 local a,g;
 a:=SCIntFunc.ReadArray(arr);

 if(a<>fail) then
  if a <> [] and a<>[[]] then
   if(IsString(a[1]) and a[1]<>[]) then
    if(a[2]<>[]) then
     g:=Group(List(a[2],x->PermList(x)));
    else
     g:=Group(());
    fi;
    SetStructureDescription(g,a[1]);
    SetName(g,a[1]);
    return g;
   else
    return Group(List(a,x->PermList(x)));
   fi;
  else
   return Group(());
  fi;
 else
  return fail;
 fi;
end;

SCIntFunc.PermGroupToString:=
function(g)
 if(HasName(g) and Name(g)<>"") then
  return String([Name(g),List(GeneratorsOfGroup(g),x->ListPerm(x))]);
 else
  return String([StructureDescription(g),
      List(GeneratorsOfGroup(g),x->ListPerm(x))]);
 fi;
end;





#position object (gets splitted into elements when serialized to xml, 
#as opposed to list)
SCPositionalObjectFamily:=NewFamily("SCPositionalObjectFamily",
  SCIsPositionalObject and IsPositionalObjectRep and IsMutable);
SCPositionalObjectType:=NewType(SCPositionalObjectFamily,SCIsPositionalObject);

#create positional object from list
SCIntFunc.SCPositionalObjectFromList:=
function(list)
 return Objectify(SCPositionalObjectType,rec(data:=list));
end;

#methods for positional object
InstallMethod(
 \[\],"for SCPositionalObject",
 [SCIsPositionalObject,IsInt],
function(po, pos)
  return po!.data[pos];
end);

InstallMethod(
 IsBound\[\],"for SCPositionalObject",
 [SCIsPositionalObject,IsInt],
function(po, pos)
 return IsBound(po!.data[pos]);
end);

InstallMethod(
 \[\]\:\=,"for SCPositionalObject",
 [SCIsPositionalObject and IsMutable,IsInt,IsObject],
function(po, pos, val)
 po!.data[pos]:=val;
end);

InstallMethod(
 Unbind\[\],"for SCPositionalObject",
 [SCIsPositionalObject and IsMutable,IsInt],
function(po, pos)
 Unbind(po!.data[pos]);
end);

InstallMethod(
 Length,"for SCPositionalObject",
 [SCIsPositionalObject],
function(po)
 return Length(po!.data);
end);

InstallMethod(
 ViewObj,"for SCPositionalObject",
 [SCIsPositionalObject],
function(po)
 ViewObj(po!.data);
end);

InstallMethod(
 PrintObj,"for SCPositionalObject",
 [SCIsPositionalObject],
function(po)
 PrintObj(po!.data);
end);


#serialize object to xml
SCIntFunc.SCObjectToXML:=
function(object,name,ident)
 local type,prefix,subitems,processed;

 if(object=fail) then
  return "";
 fi;

 processed:=false;
 for type in RecNames(SCIntFunc.SCXMLIOHandlers) do
  if(not SCIntFunc.SCXMLIOHandlers.(type)[1](object)) then
   continue;
  else
   prefix:=Concatenation(ListWithIdenticalEntries(ident,"\t"));

   if(SCIntFunc.SCXMLIOHandlers.(type)[4]=true) then
    #atomic type
    return Concatenation([prefix,"<",String(name)," type=\"",type,"\">",
          SCIntFunc.SCXMLIOHandlers.(type)[2](object),"</",name,">\n"]);
   else
    #compound type
    return Concatenation([prefix,"<",String(name)," type=\"",type,"\">\n",
          SCIntFunc.SCXMLIOHandlers.(type)[2](object,ident),prefix,"</",name,
          ">\n"]);
   fi;
  fi;
 od;

 Info(InfoSimpcomp,3,"SCIntFunc.SCObjectToXML: ignoring property ",name,
    " -- unknown type.");
 return "";
end;


#element reading handler for xml reader
SCIntFunc.SCXMLElementHandler:=
function(target,pos,root)
 local type,content,c,value,data,lpos;

 if(root.name="PCDATA" or root.name="XMLPI" or 
      root.name="XMLCOMMENT" or root.name="Ignore") then
  #ignore processing instructions & comments
  return 0;
 fi;

 #assume type string
 type:="SCString";
 value:=fail;

 if "attributes" in RecNames(root) and "type" in RecNames(root.attributes) then
  type:=root.attributes.type;
 fi;


 if(type="SCEmpty") then
  return 1;
 fi;


 if(not type in RecNames(SCIntFunc.SCXMLIOHandlers)) then
  Info(InfoSimpcomp,3,"SCIntFunc.SCXMLElementHandler: warning, ignoring ",
      "unknown type \"",type,"\".");
  return 0;
 fi;

 value:=fail;
 if(SCIntFunc.SCXMLIOHandlers.(type)[4]=true) then
  #atomic content
  content:=fail;
  for c in root.content do
   if c.name="PCDATA" then
    content:=c.content;
    break;
   fi;
  od;

  if(content=fail) then
   Info(InfoSimpcomp,1,"SCIntFunc.SCXMLElementHandler: getting content of ",
        "xml node ",root," failed.");
   return -1;
  fi;

  value:=SCIntFunc.SCXMLIOHandlers.(type)[3](content);
 else
  #xml content
  value:=SCIntFunc.SCXMLIOHandlers.(type)[3](root);
 fi;

 if(value=fail) then
  Info(InfoSimpcomp,1,"SCIntFunc.SCXMLElementHandler: I/O handler ",
      "for property ",root.name," failed.");
  return -1;
 fi;

 if(IsRecord(target)) then
  target.(root.name):=value;
 elif(IsList(target)) then
  target[pos]:=value;
 else
  Info(InfoSimpcomp,1,"SCIntFunc.SCXMLElementHandler: target object ",
      "neither of Record nor of List type. target=",target,".");
  return -1;
 fi;
 
 return 1;
end;

#deserialize xml to object
SCIntFunc.SCXMLToObject:=
function(xml)
 local n,tree,items,pos;

 if(IsEmptyString(xml)) then
  return [];
 fi;
 tree:=ParseTreeXMLString(xml);
 if(tree=fail) then
  Info(InfoSimpcomp,1,"SCIntFunc.SCXMLToObject: parsing xml ",
      "input string failed.");
  return fail;
 fi;
 if tree.name="WHOLEDOCUMENT" then
  #start processing
  items:=[];
  pos:=1;
  for n in tree.content do
   if(SCIntFunc.SCXMLElementHandler(items,pos,n)>0) then
    pos:=pos+1;
    
   fi;
  od;
  return items;
 fi;

 Info(InfoSimpcomp,1,"SCIntFunc.SCXMLToObject: xml document root not found.");
 return fail;
end;


#serialize record to xml
SCIntFunc.RecordToXML:=
function(object,ident)
 local key,subitems;
 
 if(not IsRecord(object)) then
  Info(InfoSimpcomp,1,"SCIntFunc.RecordToXML: first argument must be ",
      "of type Record.");
  return "";
 fi;
 
 subitems:="";
 for key in RecNames(object) do
  Append(subitems,SCIntFunc.SCObjectToXML(object.(key),key,ident+1));
 od;
 return subitems;
end;


#deserialize record from xml
SCIntFunc.RecordFromXML:=
function(root)
 local c,r;
 r:=rec();
 for c in root.content do
  SCIntFunc.SCXMLElementHandler(r,1,c);
 od;
 return r;
end;


#serialize positional object to xml
SCIntFunc.PositionalObjectToXML:=
function(object,ident)
 local key,subitems,prefix;
 subitems:="";

 if(not SCIsPositionalObject(object)) then
  Info(InfoSimpcomp,1,"SCIntFunc.PositionalObjectToXML: first argument ",
      "must be of type SCPositionalObject.");
  return "";
 fi;
 
 
 prefix:=Concatenation(ListWithIdenticalEntries(ident,"\t"));
 for key in [1..Length(object)] do
  if(not IsBound(object[key])) then
   Append(subitems,Concatenation(prefix,
        "\t<Entry type=\"SCEmpty\"></Entry>\n"));
  else
   Append(subitems,SCIntFunc.SCObjectToXML(object[key],"Entry",ident+1));
  fi;
 od;
 return subitems;
end;


#deserialize positional object from xml
SCIntFunc.PositionalObjectFromXML:=
function(root)
 local c,po,pos;
 po:=[];
 pos:=1;
 for c in root.content do
  if(SCIntFunc.SCXMLElementHandler(po,pos,c)>0) then
   pos:=pos+1;
  fi;
 od;
 return SCIntFunc.SCPositionalObjectFromList(po);
end;



#serialize fp group to xml
SCIntFunc.FpGroupToXML:=
function(object,ident)
 local key,subitems,prefix;
 subitems:="";

 if(not IsFpGroup(object)) then
  Info(InfoSimpcomp,1,"SCIntFunc.FpGroupToXML: first argument must be ",
      "of type FpGroup.");
  return "";
 fi;
 
 
 prefix:=Concatenation(ListWithIdenticalEntries(ident,"\t"));
 
 Append(subitems,Concatenation(prefix,"\t<Generators type=\"SCArray\">",
    String(List(GeneratorsOfGroup(object),String)),"</Generators>\n"));
 Append(subitems,Concatenation(prefix,"\t<Relators type=\"SCArray\">",
    String(List(RelatorsOfFpGroup(object),String)),"</Relators>\n"));
 
 #return subitems;
 return "";
end;


#deserialize fp group from xml
SCIntFunc.FpGroupFromXML:=
function(root)
 local c,po,pos;
 po:=[];
 pos:=1;
 for c in root.content do
  if(SCIntFunc.SCXMLElementHandler(po,pos,c)>0) then
   pos:=pos+1;
  fi;
 od;
 return [];
end;


#serialize simplicial complex object to xml
SCIntFunc.SCSimplicialComplexToXML:=
function(object,ident)
 local key,subitems,prefix;
 subitems:="";
 
 if(not SCIsSimplicialComplex(object)) then
  Info(InfoSimpcomp,1,"SCIsSimplicialComplex: first argument must be of ",
      "type SCSimplicialComplex.");
  return "";
 fi;
 
 prefix:=Concatenation(ListWithIdenticalEntries(ident,"\t"));
 subitems:="";
 
 #legacy format v1
 #for key in SCPropertiesNames(object) do
 # Append(subitems,SCIntFunc.SCObjectToXML(SCPropertyByName(object,key),
  # key,ident+1));
 #od;
 
 #new format v2
 for key in KnownAttributesOfObject(object) do
  Append(subitems,SCIntFunc.SCObjectToXML(object!.(key),key,ident+1));
 od;
 
 return subitems;
end;


#deserialize simplicial complex object from xml, legacy format 1
SCIntFunc.SCSimplicialComplexFromXMLv1Legacy:=rec(
Facets:=SCFacetsEx,
Faces:=SCFaceLatticeEx,
VertexLabels:=SCFacetsEx,
StronglyConnected:=SCIsStronglyConnected,
Connected:=SCIsConnected,
Generators:=SCGeneratorsEx,
MinimalNonFaces:=SCMinimalNonFacesEx,
Pure:=SCIsPure,
PM:=SCIsPseudoManifold,
CentrallySymmetric:=SCIsCentrallySymmetric,
CohomologyBasis:=SCCohomologyBasis,
HomologyBasis:=SCHomologyBasis,
);

SCIntFunc.SCSimplicialComplexFromXMLv1:=
function(root)
 local props,key,fkey,sc;

 props:=SCIntFunc.RecordFromXML(root);
 sc:=SCIntFunc.SCNew();
 
 for key in RecNames(props) do
  if(IsBound(SCIntFunc.SCSimplicialComplexFromXMLv1Legacy.(key))) then
   fkey:=SCIntFunc.SCSimplicialComplexFromXMLv1Legacy.(key);
  elif(IsBound(SCIntFunc.SCPropertyHandlers.(key))) then
   fkey:=SCIntFunc.SCPropertyHandlers.(key);
  else
   fkey:=EvalString(key);
  fi;
  if(Setter(fkey)=false or Setter(fkey)=fail) then
   Info(InfoSimpcomp,2,"SCIntFunc.SCSimplicialComplexFromXMLv1: legacy ",
        "format, skipped loading attribute '",key,"'");
   continue;
  fi;
  Setter(fkey)(sc,props.(key));
 od;
 
 return sc;
end;


#deserialize simplicial complex object from xml, format 2
SCIntFunc.SCSimplicialComplexFromXMLv2:=
function(root)
 local props,key,sc;

 props:=SCIntFunc.RecordFromXML(root);
 sc:=SCIntFunc.SCNew();
 
 for key in RecNames(props) do
  Setter(EvalString(key))(sc,props.(key));
 od;
 
 return sc;
end;



#serialize library repository object to xml
SCIntFunc.SCLibraryRepositoryToXML:=
function(object,ident)
 local key,subitems,prefix;
 subitems:="";

 if(not SCIsLibRepository(object)) then
  Info(InfoSimpcomp,1,"SCIntFunc.SCLibraryRepositoryToXML: first argument ",
      "must be of type SCLibRepository.");
  return "";
 fi;

 prefix:=Concatenation(ListWithIdenticalEntries(ident,"\t"));
 subitems:="";
 for key in SCPropertiesNames(object) do
  if(key="Loaded") then continue; fi;
  Append(subitems,SCIntFunc.SCObjectToXML(SCPropertyByName(object,key),
      key,ident+1));
 od;
 return subitems;
end;


#deserialize library repository object from xml
SCIntFunc.SCLibraryRepositoryFromXML:=
function(root)
 local props;

 props:=SCIntFunc.RecordFromXML(root);

 if(props=fail) then
  return fail;
 fi;

 return SCIntFunc.LibRepositoryEmptyWithAttributes(props);
end;



################################################################################
##<#GAPDoc Label="SCLoad">
## <ManSection>
## <Func Name="SCLoad" Arg="filename"/>
## <Returns>simplicial complex of type <C>SCSimplicialComplex</C> upon 
## success, <K>fail</K> otherwise.</Returns>
## <Description>
## Loads a simplicial complex stored in a binary format (using 
## <C>IO_Pickle</C>) from a file specified in <Arg>filename</Arg> (as string). 
## If <Arg>filename</Arg> does not end in <C>.scb</C>, this suffix is 
## appended to the file name.
## <Example><![CDATA[
## gap> c:=SCBdSimplex(3);;
## gap> SCSave(c,"/tmp/bddelta3");
## true
## gap> d:=SCLoad("/tmp/bddelta3");
## gap> c=d;
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCLoad,
 function(filename)

 local lf,fh,c;

 if(not IsString(filename)) then
  Info(InfoSimpcomp,1,"SCLoad: first argument must be of type String.");
  return fail;
 fi;

 #try to detect format (xml,binary) by extension
 if(Length(filename)>2 and 
    filename{[Length(filename)-2..Length(filename)]}=".sc") then
  Info(InfoSimpcomp,2,"SCLoad: assuming XML format for file '",
      filename,"', falling back to SCLoadXML.");
  return SCLoadXML(filename);
 fi;
 
 lf:=ShallowCopy(filename);
 if(Length(filename)<4 or 
    filename{[Length(filename)-3..Length(filename)]}<>".scb") then
  Append(lf,".scb");
 fi;
 
 fh:=IO_File(lf,"r");
 
 if(fh=fail) then
  Info(InfoSimpcomp,1,"SCLoad: Error opening file '",lf,"' for reading.");
  return fail;
 fi;

 #unpickle
 c:=IO_Unpickle(fh);
 
 IO_Close(fh);

 if(c=IO_Error) then
  Info(InfoSimpcomp,1,"SCLoad: Error loading simplicial complex from file '",
      lf,"'.");
  return fail;
 else
  return c;
 fi;
 
end);


################################################################################
##<#GAPDoc Label="SCLoadXML">
## <ManSection>
## <Func Name="SCLoadXML" Arg="filename"/>
## <Returns>simplicial complex of type <C>SCSimplicialComplex</C> upon 
## success, <K>fail</K> otherwise.</Returns>
## <Description>
## Loads a simplicial complex stored in XML format from a file specified in 
## <Arg>filename</Arg> (as string). If <Arg>filename</Arg> does not end in 
## <C>.sc</C>, this suffix is appended to the file name.
## <Example><![CDATA[
## gap> c:=SCBdSimplex(3);;
## gap> SCSaveXML(c,"/tmp/bddelta3");
## true
## gap> d:=SCLoadXML("/tmp/bddelta3");
## gap> c=d;
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCLoadXML,
 function(filename)

 local data,obj,lf;

 if(not IsString(filename)) then
  Info(InfoSimpcomp,1,"SCLoadXML: first argument must be of type String.");
  return fail;
 fi;
 
 lf:=ShallowCopy(filename);
 if(Length(filename)<3 or 
    filename{[Length(filename)-2..Length(filename)]}<>".sc") then
  Append(lf,".sc");
 fi;

 data:=StringFile(lf);
 if(data=fail or IsEmptyString(data)) then
  Info(InfoSimpcomp,1,"SCLoadXML: error reading file \"",lf,"\".");
  return fail;
 fi;

 obj:=SCIntFunc.SCXMLToObject(data);

 if(obj=fail or Length(obj)<1 or not SCIsSimplicialComplex(obj[1])) then
  Info(InfoSimpcomp,1,"SCLoadXML: error loading simplicial complex from file.");
  return fail;
 fi;

 return obj[1];
end);



################################################################################
##<#GAPDoc Label="SCSave">
## <ManSection>
## <Func Name="SCSave" Arg="complex, filename"/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Saves a simplicial complex in a binary format (using <C>IO_Pickle</C>) to 
## a file specified in <Arg>filename</Arg> (as string). If <Arg>filename</Arg> 
## does not end in <C>.scb</C>, this suffix is appended to the file name.
## <Example><![CDATA[
## gap> c:=SCBdSimplex(3);;
## gap> SCSave(c,"/tmp/bddelta3");
## true
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCSave,
 function(complex,filename)

 local fh,lf;

 if(not SCIsSimplicialComplex(complex) or not IsString(filename)) then
  Info(InfoSimpcomp,1,"SCSave: first argument must be of type ",
      "SCSimplicialComplex, second of type String.");
  return fail;
 fi;

 lf:=ShallowCopy(filename);
 if(Length(filename)>2 and 
    filename{[Length(filename)-2..Length(filename)]}=".sc") then
  Append(lf,"b");
 fi;

 if(Length(lf)<4 or lf{[Length(lf)-3..Length(lf)]}<>".scb") then
  Append(lf,".scb");
 fi;
 
 Info(InfoSimpcomp,3,"SCSave: Saving simplicial complex to file '",lf,"'."); 
 fh:=IO_File(lf,"w");
 
 if(fh=fail) then
  Info(InfoSimpcomp,1,"SCSave: Error opening file '",lf,"' for writing.");
  return fail;
 fi;

 #pickle
 if(IO_Pickle(fh,complex)<>IO_OK) then
  Info(InfoSimpcomp,1,"SCSave: Error saving simplicial complex to file '",
      lf,"'.");
  IO_Close(fh);
  return fail;
 else
  IO_Close(fh);
  return true;
 fi;
end);


################################################################################
##<#GAPDoc Label="SCSaveXML">
## <ManSection>
## <Func Name="SCSaveXML" Arg="complex, filename"/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Saves a simplicial complex <Arg>complex</Arg> to a file specified by 
## <Arg>filename</Arg> (as string) in XML format. If <Arg>filename</Arg> does 
## not end in <C>.sc</C>, this suffix is appended to the file name.
## <Example><![CDATA[
## gap> c:=SCBdSimplex(3);;
## gap> SCSaveXML(c,"/tmp/bddelta3");
## true
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCSaveXML,
 function(complex,filename)

 local buf,lf;
 
 if(not SCIsSimplicialComplex(complex) or not IsString(filename)) then
  Info(InfoSimpcomp,1,"SCSaveXML: first argument must be of type ",
      "SCSimplicialComplex, second of type String.");
  return fail;
 fi;
 
 lf:=ShallowCopy(filename);

 if(Length(filename)>3 and 
    filename{[Length(filename)-3..Length(filename)]}=".scb") then
  lf:=lf{[1..Length(lf)-1]};
 fi;

 if(Length(lf)<3 or lf{[Length(lf)-2..Length(lf)]}<>".sc") then
  Append(lf,".sc");
 fi;

 Info(InfoSimpcomp,3,"SCSaveXML: saving simplicial complex to file '",lf,"'."); 

 buf:=Concatenation("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
 SCIntFunc.SCObjectToXML(complex,"SimplicialComplexV2",0));

 if(FileString(lf,buf)=fail) then
  Info(InfoSimpcomp,1,"SCSaveXML: file \"",filename,"\" not writeable!");
  return fail;
 else
  return true;
 fi;
end);


SCIntFunc.SCGetSimplicialComplexAttributesXMLEx:=
function(sc,attrs)
 local buf,pname,prop,ptype;

 if(Length(attrs)>0 and not ForAll(attrs,IsString)) then
  Info(InfoSimpcomp,1,"SCIntFunc.SCGetSimplicialComplexAttributesXMLEx: ",
      "invalid attribute list.");
  return fail;
 fi;

 buf:="";

 for pname in Intersection(SCPropertiesNames(sc),attrs) do
  prop:=SCPropertyByName(sc,pname);
  Append(buf,SCIntFunc.SCObjectToXML(prop,pname,1));
 od;

 return buf;
end;


SCIntFunc.SCGetSimplicialComplexAttributesXML:=
function(sc,attrs)
 local buf;

 buf:=SCIntFunc.SCGetSimplicialComplexAttributesXMLEx(sc,attrs);
 if(buf=fail) then return fail; fi;

 return Concatenation(["<SimplicialComplex>\n",buf,"</SimplicialComplex>\n\n"]);
end;

################################################################################
##<#GAPDoc Label="SCExportMacaulay2">
## <ManSection>
## <Func Name="SCExportMacaulay2" Arg="complex, ring,  filename [, alphalabels]"/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Exports the facet list of a given simplicial complex <Arg>complex</Arg> in 
## <C>Macaulay2</C> format to a file specified by <Arg>filename</Arg>. The 
## argument <Arg>ring</Arg> can either be the ring of integers (specified by 
## <C>Integers</C>) or the ring of rationals (sepcified by <C>Rationals</C>). 
## The optional boolean argument <Arg>alphalabels</Arg> labels the complex 
## with characters from <M>a, \dots ,z</M> in the exported file if a value of 
## <K>true</K> is supplied, while the standard labeling of the vertices is 
## <M>v_1, \dots ,v_n</M> where <M>n</M> is the number of vertices of 
## <Arg>complex</Arg>. If <Arg>complex</Arg> has more than <M>26</M> 
## vertices, the argument <Arg>alphalabels</Arg> is ignored. 
## <Example><![CDATA[
## gap> c:=SCBdCrossPolytope(4);;
## gap> SCExportMacaulay2(c,Integers,"/tmp/bdbeta4.m2");
## true
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCExportMacaulay2,
function(arg)
 local complex,filename,ring,alpha,buf,i,s,v,verts,lut,facets;

 if(Length(arg)<3 or Length(arg)>4 or not SCIsSimplicialComplex(arg[1]) or 
      (not IsIntegers(arg[2]) and not IsRationals(arg[2])) or 
      not IsStringRep(arg[3])) then
   Info(InfoSimpcomp,1,"SCExportMacaulay2: invalid arguments, first",
        "argument must be of type SCSimplicialComplex, seconds a ring ",
        "(Integers or Rationals), third a string.");
   return fail;
 fi;
 
 complex:=arg[1];
 ring:=arg[2];
 filename:=arg[3];
 
 if(SCIsEmpty(complex)) then
  Info(InfoSimpcomp,1,"SCExportMacaulay2: empty complex, duh.");
  return true;
 fi;
 
 if(Length(arg)=4 and IsBool(arg[4]) and arg[4]=true) then
  alpha:=true;
 else
  alpha:=false;
 fi;
 
 
 buf:=["-- simpcomp export of complex ",SCName(complex),
    "\n\nloadPackage \"SimplicialComplexes\";\n\nR = "];
 
 if(IsIntegers(ring)) then
  Add(buf,"ZZ[");
 else
  Add(buf,"QQ[");
 fi;
 
 verts:=Union(SCSkelEx(complex,0));

 #dump variables
 if(Length(verts)<27 and alpha) then
  lut:=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
      "p","q","r","s","t","u","v","w","x","y","z"];
  Add(buf,Concatenation("a..",lut[Length(verts)]));
 else
  lut:=[1..Length(verts)];
  for i in [1..Length(verts)] do
   Add(buf,Concatenation("v",String(i)));
   if(i<Length(verts)) then
    Add(buf,", ");
   fi;
  od;
 fi;
 Add(buf,"];\nFacets = {");
 
 facets:=SCFacetsEx(complex);
 for s in [1..Length(facets)] do
  for v in [1..Length(facets[s])] do
   if not alpha then
    Add(buf,Concatenation("v",String(lut[Position(verts,facets[s][v])])));
   else
    Add(buf,String(lut[Position(verts,facets[s][v])]));
   fi;
   
   if(v<Length(facets[s])) then
    Add(buf,"*");
   elif(s<Length(facets)) then
    Add(buf,", ");
   fi;
  od;
 od;
 Add(buf,"}\n");

 Add(buf,"complex = simplicialComplex Facets;\n\n-- end of export");

 if(FileString(filename,String(Concatenation(buf)))=fail) then
  Info(InfoSimpcomp,1,"SCExportMacaulay2: file \"",filename,
      "\" not writeable!");
  return fail;
 else
  return true;
 fi;

end);


################################################################################
##<#GAPDoc Label="SCExportPolymake">
## <ManSection>
## <Func Name="SCExportPolymake" Arg="complex, filename"/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Exports the facet list with vertex labels of a given simplicial complex 
## <Arg>complex</Arg> in <C>polymake</C> format to a file specified by 
## <Arg>filename</Arg>. Currently, only the export in the format of 
## <C>polymake</C> version 2.3 is supported. 
## <Example><![CDATA[
## gap> c:=SCBdCrossPolytope(4);;
## gap> SCExportPolymake(c,"/tmp/bdbeta4.poly");
## true
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCExportPolymake,
function(complex,filename)
 local buf,i,s,v,verts;

 buf:=["_application topaz\n_version 2.3\n_type SimplicialComplex\n\nFACETS\n"];

 verts:=SCVertices(complex);

 for s in SCFacetsEx(complex) do
  Add(buf,"{ ");
  for v in s do
   Append(buf,[String(Position(verts,v)-1)," "]);
  od;
  Add(buf,"}\n");
 od;

 #print vertex labels
 Add(buf,"\nVERTEX_LABELS\n");

 for i in [1..Length(verts)] do
  Add(buf,SCIntFunc.ListToDenseString(verts[i]));
  if(i<Length(verts)) then Add(buf," "); fi;
 od;
 Add(buf,"\n\n");

 if(FileString(filename,String(Concatenation(buf)))=fail) then
  Info(InfoSimpcomp,1,"SCExportPolymake: file \"",filename,"\" not ",
      "writeable!");
  return fail;
 else
  return true;
 fi;

end);


################################################################################
##<#GAPDoc Label="SCExportRecognizer">
## <ManSection>
## <Func Name="SCExportRecognizer" Arg="complex, filename"/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Exports the gluings of the tetrahedra of a given combinatorial 
## <M>3</M>-manifold <Arg>complex</Arg> in a format compatible with Matveev's 
## <M>3</M>-manifold software <C>Recognizer</C>.
## <Example><![CDATA[
## gap> c:=SCBdCrossPolytope(4);;
## gap> SCExportRecognizer(c,"/tmp/bdbeta4.mv");
## true
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCExportRecognizer,
function(complex,filename)
 local buf,i,dim,pm,facets,done,j,k,l,elm,trig,f3;

 dim := SCDim(complex);
 pm := SCIsPseudoManifold(complex);
 if dim <> 3 or pm <> true then
  Info(InfoSimpcomp,1,"SCExportRecognizer: input must be a 3-dimensional ",
      "weak pseudomanifold.");
  return fail;
 fi;

 buf:=["triangulation\n"];
 facets := SCFacetsEx(complex);
 if facets = fail then
  return fail;
 fi;
 f3 := Size(facets);
 done := List([1..f3],x->[false,false,false,false]);
 for i in [1..f3] do
  for j in [4,3,2,1] do
   if done[i][j] = true then continue; fi;
   elm := [1..4];
   Remove(elm,j);
   Append(buf,["t",String(i),"(",String(elm[1]),",",String(elm[2]),",",
        String(elm[3]),") - "]);
   trig := facets[i]{elm};
   for k in [i+1..f3] do
    if IsSubset(facets[k],trig) then
     elm := [Position(facets[k],trig[1]),Position(facets[k],trig[2]),
            Position(facets[k],trig[3])];
     Append(buf,["t",String(k),"(",String(elm[1]),",",String(elm[2]),",",
            String(elm[3]),"),\n"]);
     for l in [1..4] do
      if not l in elm then
       done[k][l] := true;
       break;
      fi;
     od;
     break;
    fi;
   od; 
  od;
 od;
 Add(buf,"end\n");
 if(FileString(filename,String(Concatenation(buf)))=fail) then
  Info(InfoSimpcomp,1,"SCExportRecognizer: file \"",filename,
      "\" not writeable!");
  return fail;
 else
  return true;
 fi;

end);

################################################################################
##<#GAPDoc Label="SCExportJavaView">
## <ManSection>
## <Func Name="SCExportJavaView" Arg="complex, file, coords"/>
## <Returns><K>true</K> on success, <K>fail</K> otherwise.</Returns>
## <Description>
## Exports the 2-skeleton of the given simplicial complex <Arg>complex</Arg> 
## (or the facets if the complex is of dimension 2 or less) in <C>JavaView</C> 
## format (file name suffix <C>.jvx</C>) to a file specified by 
## <Arg>filename</Arg> (as string). The list <Arg>coords</Arg> must contain a 
## <M>3</M>-tuple of real coordinates for each vertex of <Arg>complex</Arg>, 
## either as tuple of length three containing the coordinates (Warning: 
## as &GAP; only has rudimentary support for floating point values, currently 
## only integer numbers can be used as coordinates when providing 
## <Arg>coords</Arg> as list of <M>3</M>-tuples) or as string of the form 
## <C>"x.x y.y z.z"</C> with decimal numbers <C>x.x</C>, <C>y.y</C>, 
## <C>z.z</C> for the three coordinates (i.e. <C>"1.0 0.0 0.0"</C>).
## <Example><![CDATA[
## gap> coords:=[[1,0,0],[0,1,0],[0,0,1]];;
## gap> SCExportJavaView(SCBdSimplex(2),"/tmp/triangle.jvx",coords);
## true
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCExportJavaView,
function(complex,filename,coords)
 local buf,v,f,verts,vertices,trigs,i,name,fl,dim;

 if(SCIsEmpty(complex)) then
  Info(InfoSimpcomp,1,"SCExportJavaView: empty complex, nothing to do.");
  return true;
 fi;

 buf:=[];
 dim:=SCDim(complex);
 if(dim=fail) then
  return fail;
 fi;
 
 if(dim<3) then
  trigs:=SCFacetsEx(complex);
 else
  trigs:=SCSkelEx(complex,2);
 fi;
 
 verts:=Union(SCSkelEx(complex,0));
 
 if(trigs=fail or verts=fail or Length(verts)<>Length(coords)) then
  if(Length(verts)<>Length(coords)) then
   Info(InfoSimpcomp,1,"SCExportJavaView: vertex count must match ",
        "coordinate count.");
  fi;
  return fail;
 fi;
 
 name:=SCPropertyByName(complex,"Name");
 
 if(name=fail) then
  name:="Unnamed simplcicial complex";
 fi;
 
 
 Append(buf,Concatenation("\
 <?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>\n\
 <!DOCTYPE jvx-model SYSTEM \"http://www.javaview.de/rsrc/jvx.dtd\">\n\
 <jvx-model>\n\
  <meta generator=\"<Package>simpcomp</Package>\"/>\n\
  <meta dtd=\"1.11.001\"/>\n\
  <meta date=\"\"/>\n\
  <version type=\"dump\">1.0</version>\n\
  <title>",name,"</title>\n\
  <geometries>\n"));
 
 Append(buf,Concatenation("\
 <geometry name=\"",String(verts),"\">\n\
  <pointSet point=\"show\" dim=\"3\">\n\
   <points num=\"",String(Length(verts)),"\">\n"));
 
 vertices:=[];
 for v in [1..Length(verts)] do
  if(not IsString(coords[v])) then
   #coordinates as list
   vertices[v]:=Concatenation("<p name=\"",String(verts[v]),"\">");
   
   #convert to floating point
   for i in [1..3] do
   
    if(not IsInt(coords[v][i])) then
     Info(InfoSimpcomp,1,"SCExportJavaView: currently only integer ",
            "coordinates are supported when passed as list of coordinate ",
            "tuples. Use list of strings instead.");
     return fail;
    fi;
    
    fl:=ShallowCopy(String(coords[v][i]));
    
    if(PositionSublist(fl,".")=fail) then
     Append(fl,".0");
    fi;
    
    Append(vertices[v],fl);
    
    if(i<3) then
     Append(vertices[v]," ");
    fi;
   od;
   
   Append(vertices[v],"</p>");
  else
   #coordinates as string
   vertices[v]:=Concatenation("<p name=\"",String(verts[v]),"\">",
        coords[v],"</p>");
  fi;
  Append(buf,Concatenation("\t\t\t",vertices[v],"\n"));
 od;


 Append(buf,Concatenation("\
    <thickness>4.0</thickness>\n\
    <color type=\"rgb\">255 0 0</color>\n\
    <colorTag type=\"rgb\">255 0 255</colorTag>\n\
    <labelAtt font=\"text\" horAlign=\"head\" name=\"SansSerif\" verAlign=\"middle\" style=\"plain\" visible=\"show\">\n\
     <xOffset>0</xOffset>\n\
     <yOffset>0</yOffset>\n\
     <size>20</size>\n\
     <color type=\"rgb\">0 0 0</color>\n\
    </labelAtt>\n\
   </points>\n\
  </pointSet>\n\
  <faceSet color=\"show\" edge=\"show\" face=\"show\">\n\
   <faces num=\"",String(Length(trigs)),"\">\n"));

 for f in trigs do
  Append(buf,"\t\t\t<f>");
  for v in [1..Length(f)] do
   if(v>1) then Append(buf," "); fi;
   Append(buf,String(Position(verts,f[v])-1));
  od;
  Append(buf,"</f>\n");
 od;
  
 Append(buf,"\
    <color type=\"rgb\">0 255 0</color>\n\
    <colorTag type=\"rgb\">255 0 255</colorTag>\n\
    <creaseAngle>3.2</creaseAngle>\n\
   </faces>\n\
   <neighbours num=\"1\">\n\
    <nb>-1 -1 -1</nb>\n\
   </neighbours>\n\
   <edges>\n\
    <thickness>1.0</thickness>\n\
    <color type=\"rgb\">0 0 0</color>\n\
    <colorTag type=\"rgb\">255 0 255</colorTag>\n\
   </edges>\n\
   <colors num=\"1\" type=\"rgb\">\n\
    <c>119 236 158</c>\n\
   </colors>\n\
  </faceSet>\n\
  <center visible=\"hide\">\n\
   <p>0.0 0.0 0.0</p>\n\
  </center>\n\
  <material>\n\
   <ambientIntensity>0.2</ambientIntensity>\n\
   <diffuse>\n\
    <color type=\"rgb\">204 204 204</color>\n\
   </diffuse>\n\
   <emissive>\n\
    <color type=\"rgb\">0 0 0</color>\n\
   </emissive>\n\
   <shininess>10.0</shininess>\n\
   <specular>\n\
    <color type=\"rgb\">255 255 255</color>\n\
   </specular>\n\
   <transparency visible=\"show\">0.5</transparency>\n\
  </material>\n\
 </geometry>\n\
 </geometries>\n\
 </jvx-model>\n");
 
 if(FileString(filename,buf)=fail) then
  Info(InfoSimpcomp,1,"SCExportJavaView: filename \"",filename,
      "\" not writeable!");
  return fail;
 else
  return true;
 fi;
 
end);

################################################################################
##<#GAPDoc Label="SCExportLatexTable">
## <ManSection>
## <Func Name="SCExportLatexTable" Arg="complex, filename, itemsperline"/>
## <Returns><K>true</K> on success, <K>fail</K> otherwise.</Returns>
## <Description>
## Exports the facet list of a given simplicial complex <Arg>complex</Arg> 
## (or any list given as first argument) in form of a &LaTeX; table to a file 
## specified by <Arg>filename</Arg>. The argument <Arg>itemsperline</Arg> 
## specifies how many columns the exported table should have. The faces are 
## exported in the format <M>\langle v_1,\dots,v_k \rangle</M>.  
## <Example><![CDATA[
## gap> c:=SCBdSimplex(5);;
## gap> SCExportLatexTable(c,"/tmp/bd5simplex.tex",5);
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCExportLatexTable,
function(complex,filename,itemsperline)
 local i,j,buf,facets;

 if(not SCIsSimplicialComplex(complex) and not IsList(complex)) then
  Info(InfoSimpcomp,1,"SCExportLatexTable: first argument must be of type ",
      "SCSimplicialComplex or a list of faces.");
  return fail;
 fi;
  
 if(SCIsSimplicialComplex(complex)) then
  facets:=SCFacets(complex);
 else
  facets:=complex;
 fi;

 if(facets=fail) then
  return fail;
 fi;

 buf:=Concatenation(["\\begin{tabular}{",
    Concatenation(ListWithIdenticalEntries(itemsperline,"l")),"}\n"]);

 for i in [1..Length(facets)] do
  Append(buf,"$\\langle ");

  for j in [1..Length(facets[i])-1] do
   Append(buf,
        Concatenation([SCIntFunc.ListToDenseString(facets[i][j]),"\\,"]));
  od;
  Append(buf,SCIntFunc.ListToDenseString(facets[i][Length(facets[i])]));


  Append(buf," \\rangle$");

  if(i=Length(facets)) then
   Append(buf,".");
   Append(buf,
        Concatenation(ListWithIdenticalEntries(-(i mod itemsperline) mod itemsperline,"&")));
   Append(buf,"\n");
   break;
  fi;

  if(i mod itemsperline=0) then
   Append(buf,",\\\\\n\n");
  else
   Append(buf,", &\n");
  fi;
 od;

 Append(buf,"\\end{tabular}");
 buf:=ReplacedString(buf,"\"","");

 if(FileString(filename,buf)=fail) then
  Info(InfoSimpcomp,1,"SCExportLatexTable: file \"",filename,
      "\" not writeable!");
  return fail;
 fi;

 return true;
end);



################################################################################
##<#GAPDoc Label="SCImportPolymake">
## <ManSection>
## <Func Name="SCImportPolymake" Arg="filename"/>
## <Returns>simplicial complex of type <C>SCSimplicialComplex</C> upon 
## success, <K>fail</K> otherwise.</Returns>
## <Description>
## Imports the facet list of a <C>topaz</C> <C>polymake</C> file specified by 
## <Arg>filename</Arg> (discarding any vertex labels) and creates a 
## simplicial complex object from these facets.
## <Example><![CDATA[
## gap> c:=SCBdCrossPolytope(4);;
## gap> SCExportPolymake(c,"/tmp/bdbeta4.poly");
## gap> d:=SCImportPolymake("/tmp/bdbeta4.poly");
## gap> c=d;
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCImportPolymake,
function(filename)
 local file,lines,fpos,lidx,v,verts,s,facets,sc;
 
 file:=StringFile(filename);
 
 if(file=fail) then
  Info(InfoSimpcomp,1,"SCImportPolymake: error reading file \"",
      filename,"\".");
  return fail;
 fi;
 
 
 lines:=SplitString(file,"\n");
 Apply(lines,NormalizedWhitespace);
 
 fpos:=Position(lines,"VERTICES_IN_FACETS");
 if(fpos=fail) then
  fpos:=Position(lines,"FACETS");
 fi;
 
 
 if(fpos=fail) then
  Info(InfoSimpcomp,1,"SCImportPolymake: could neither find section ",
      "VERTICES_IN_FACETS nor section FACETS in polymake file.");
  return fail;
 fi;
 
 facets:=[];
 for lidx in [fpos+1..Length(lines)] do
  if(not IsBound(lines[lidx]) or IsEmptyString(lines[lidx]) or 
      lines[lidx]=" ") then
   break;
  fi;
  verts:=SplitString(lines[lidx]," ","{}");
  s:=[];
  for v in verts do
   if(IsEmpty(v)) then continue; fi;
   Add(s,Rat(v));
  od;
  Add(facets,s+1);
 od;
 
 sc:=SCFromFacets(facets);
 
 if(sc<>fail) then
  SCRename(sc,Concatenation("polymake import '",filename,"'"));
 fi;
 
 return sc; 
end);



#general io pickling function
SCIntFunc.GeneralPicklerIgnoreList:=[
"ComputedSCHomalgBoundaryMatricess", "ComputedSCHomalgCoboundaryMatricess", 
  "ComputedSCHomalgHomologys", "ComputedSCHomalgCohomologys" 
];
SCIntFunc.GeneralPickler:=
function(f,c,id)
 local p;
 
 # write SCSimplicialComplex tag
 IO_AddToPickled(c);
 if IO_Write(f,id) = fail then 
  IO_FinalizePickled();
  return IO_Error;
 fi;
 
 # write number of attributes
 if IO_WriteSmallInt(f,Length(KnownAttributesOfObject(c))) = IO_Error then
  IO_FinalizePickled();
  return IO_Error;
 fi;        
 
 # pickle all attributes
 for p in KnownAttributesOfObject(c) do
  if(p in SCIntFunc.GeneralPicklerIgnoreList) then
   Info(InfoSimpcomp,3,"SCIntFunc.GeneralPickler: ignoring attribute ",p,
        " as it is in ignore list (no pickler available).");
   continue;
  fi;
 
  # write attribute name
  if(IO_Pickle(f,p)<>IO_OK) then
   IO_FinalizePickled();
   return IO_Error;
  fi;

  # write attribute value
  if(IO_Pickle(f,c!.(p))<>IO_OK) then
   IO_FinalizePickled();
   return IO_Error;
  fi;
 od;

 IO_FinalizePickled();
 return IO_OK;
end;
 
#general io unpickling function
SCIntFunc.GeneralUnpickler:=
function(f,c)
    local i,len,name,ob;

    # read number of attributes
    len:=IO_ReadSmallInt(f);
    if len = IO_Error then
        Info(InfoSimpcomp,1,"SCIntFunc.GeneralUnpickler: Error during ",
          "unpicking of attribute name");
        return c;
    fi;

    # do unpickling
    IO_AddToUnpickled(c);
    for i in [1..len] do
        # read attribute name
     name:=IO_Unpickle(f);
        if name = IO_Error or not(IsString(name)) then
            Info(InfoSimpcomp,1,"SCIntFunc.GeneralUnpickler: Error while ",
                "unpicking attribute name");
        fi;
        
        # read attribute value
        ob:=IO_Unpickle(f);
        if IO_Result(ob) then
            if ob = IO_Error then
                Info(InfoSimpcomp,1,"SCIntFunc.GeneralUnpickler: Error while ",
                  "unpicking attribute value of '",name,"'");
            fi;
        else
     Setter(EvalString(name))(c,ob);
        fi;
    od;
    IO_FinalizeUnpickled();
end;


#pickler for SCSimplicialComplex
InstallMethod(IO_Pickle, "for SCSimplicialComplex",
[ IsFile, SCIsSimplicialComplex ],
function(f,c)
 return SCIntFunc.GeneralPickler(f,c,"SCSC");
end);


# unpickler for SCSimplicialComplex
IO_Unpicklers.SCSC:=
function(f)
    local c;
    
    # SCSimplicialComplex
    c:=SCIntFunc.SCNew();

    SCIntFunc.GeneralUnpickler(f,c);
    return c;
end;

# pickler for SCLibraryRepository
InstallMethod(IO_Pickle, "for SCLibRepository",
[ IsFile, SCIsLibRepository ],
function(f,lr)
 IO_AddToPickled(lr);

 # write SCLibRepository tag
 if IO_Write(f,"SCLR") = fail then 
  IO_FinalizePickled();
  return IO_Error;
 fi;
 
 if(IO_Pickle(f,lr!.Properties)<>IO_OK) then
  IO_FinalizePickled();
  return IO_Error;
 fi;
 
 IO_FinalizePickled();
 return IO_OK;
end);


# unpickler for SCLibraryRepository
IO_Unpicklers.SCLR:=
function(f)
    local prop;
 
    #get library properties    
    prop:=IO_Unpickle(f);
    
    if IO_Result(prop) then
     if prop = IO_Error then
      Info(InfoSimpcomp,1,"IO_Unpicklers.SCLR: Error while unpicking ",
          "library repository. Delete file complexes.idx and complexes.idxb ",
          "and recreate them with SCLibInit.");
      return IO_Error;
     fi;
    else
     return SCIntFunc.LibRepositoryEmptyWithAttributes(prop);
    fi;
end;

#handler functions for file load/save operations
SCIntFunc.SCXMLIOHandlers:=
rec(
 SCSimplicialComplex:=[SCIsSimplicialComplex,
    SCIntFunc.SCSimplicialComplexToXML,SCIntFunc.SCSimplicialComplexFromXMLv1,
    false],
 SCSimplicialComplexV2:=[SCIsSimplicialComplex,
    SCIntFunc.SCSimplicialComplexToXML,SCIntFunc.SCSimplicialComplexFromXMLv2,
    false],
 SCLibraryRepository:=[SCIsLibRepository,SCIntFunc.SCLibraryRepositoryToXML,
    SCIntFunc.SCLibraryRepositoryFromXML,false],
 SCRecord:=[IsRecord,SCIntFunc.RecordToXML,SCIntFunc.RecordFromXML,false],
 SCPositionalObject:=[SCIsPositionalObject,SCIntFunc.PositionalObjectToXML,
    SCIntFunc.PositionalObjectFromXML,false],
 SCInteger:=[IsInt,String,SCIntFunc.ReadInteger,true],
 SCBoolean:=[IsBool,SCIntFunc.BooleanToString,SCIntFunc.ReadBoolean,true],
 SCString:=[IsStringRep,String,SCIntFunc.ReadString,true],
 SCArray:=[IsList,SCIntFunc.ListToDenseString,SCIntFunc.ReadArray,true],
 SCPerm:=[IsPerm,SCIntFunc.PermToString,SCIntFunc.ReadPerm,true],
 SCPermGroup:=[IsPermGroup,SCIntFunc.PermGroupToString,SCIntFunc.ReadPermGroup,
    true],
 SCFpGroup:=[IsFpGroup,SCIntFunc.FpGroupToXML,SCIntFunc.FpGroupFromXML,false]
);


################################################################################

################################################################################
##<#GAPDoc Label="SCExportSnapPy">
## <ManSection>
## <Func Name="SCExportSnapPy" Arg="complex, filename"/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Exports the facet list and orientability of a given combinatorial 
## <M>3</M>-pseudomanifold <Arg>complex</Arg> in <C>SnapPy</C> format to a 
## file specified by <Arg>filename</Arg>.
## <Example><![CDATA[
## gap> SCLib.SearchByAttribute("Dim=3 and F=[8,28,56,28]");
## gap> c:=SCLib.Load(last[1][1]);;
## gap> SCExportSnapPy(c,"/tmp/M38.tri");
## true
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCExportSnapPy,
function(complex,filename)
 local curvertex,buf,dim,name,orient,lks,i,pmflag,lksconn,kleinb,torus,
    sphere,lktype,neighbors,gluings,cusps,j,k,trig,remoteidx,verts,facets;

 dim:=SCDim(complex);
 if dim=fail then
  return fail;
 fi;

 if dim<>3 then
  Info(InfoSimpcomp,1,"SCExportSnapPy: argument must be a 3-dimensional ",
      "simplicial complex.");
  return fail;
 fi;

 kleinb:=0;
 torus:=0;
 sphere:=0;

 if SCIsManifold(complex) then
  sphere:=SCNumFaces(complex,0);
  lktype:=ListWithIdenticalEntries(sphere,0);
 fi;

 if sphere=0 then

  lks:=SCLinks(complex,0);
  pmflag:=true;
  for i in [1..Size(lks)] do 
   if not SCIsManifold(lks[i]) then
    pmflag:=false;
    break;
   fi;
  od;
 
  if pmflag<>true then
   Info(InfoSimpcomp,1,"SCExportSnapPy: argument must be a combinatorial ",
        "3-pseudomanifold.");
   return fail;
  fi;

  lksconn:=true;
  for i in [1..Size(lks)] do 
   if not SCIsConnected(lks[i]) then
    lksconn:=false;
    break;
   fi;
  od;

  if lksconn<>true then
   Info(InfoSimpcomp,1,"SCExportSnapPy: argument must be a combinatorial ",
        "3-pseudomanifold with connected links.");
   return fail;
  fi;

  lktype:=[];
  for i in [1..Size(lks)] do
   if SCEulerCharacteristic(lks[i])=2 then
    lktype[i]:=0;
    sphere:=sphere+1;
   elif SCEulerCharacteristic(lks[i])=0 then
    if SCIsOrientable(lks[i]) then
     lktype[i]:=1;
     torus:=torus+1;
    else
     lktype[i]:=2;
     kleinb:=kleinb+1;
    fi;
   else
    Info(InfoSimpcomp,1,"SCExportSnapPy: argument must be a combinatorial ",
          "3-pseudomanifold with links of type S^2, T^2 or K^2.");
    return fail;
   fi;
  od;

 fi;

 name:=SCName(complex);
 if name=fail then
  return fail;
 fi;

 buf:=["% Triangulation\n"];
 Append(buf,[name,"\nunknown 0.0\n"]);

 orient:=SCIsOrientable(complex);
 if orient=fail then
  return fail;
 fi;

 if orient=true then
  Append(buf,["oriented_manifold\nCS_unknown\n\n"]);
 else
  Append(buf,["nonorientable_manifold\nCS_unknown\n\n"]);
 fi;

 verts:=SCVertices(complex);

 Append(buf,[String(torus)," ",String(kleinb),"\n"]);
 for i in [1..SCNumFaces(complex,0)] do
  if lktype[i]=0 then
   #Append(buf,["        internal   0 0\n"]);
   continue;
  elif lktype[i]=1 then
   Append(buf,["        torus   0 0\n"]);
  elif lktype[i]=2 then
   Append(buf,["        Klein bottle   0 0\n"]);
  fi;
 od;

 neighbors:=[];
 gluings:=[];
 cusps:=[];
 facets:=SCFacets(complex);
 if facets=fail then
  return fail;
 fi;
 for j in [1..Size(facets)] do
  neighbors[j]:=[];
  gluings[j]:=[];
  cusps[j]:=[];
  for trig in Combinations(facets[j],3) do
   curvertex:=Difference(facets[j],trig)[1];
   k:=Position(facets[j],curvertex);
   for i in [1..Size(facets)] do
    if facets[i] = facets[j] then continue; fi;
    if IsSubset(facets[i],trig) then
     remoteidx:=Position(facets[i],Difference(facets[i],trig)[1]);
     neighbors[j][k]:=i-1; 
     gluings[j][k]:=[];
     gluings[j][k][k]:=remoteidx-1;    
     gluings[j][k][Position(facets[j],trig[1])]:=
            Position(facets[i],trig[1])-1;
     gluings[j][k][Position(facets[j],trig[2])]:=
            Position(facets[i],trig[2])-1;
     gluings[j][k][Position(facets[j],trig[3])]:=
            Position(facets[i],trig[3])-1;
     cusps[j][k]:=curvertex-1;
     break;
    fi;
   od;
  od;
 od;

 Append(buf,["\n",String(SCNumFaces(complex,dim)),"\n"]);
 for i in [1..Size(facets)] do
  Append(buf,["    ",String(neighbors[i][1]),"    ",
      String(neighbors[i][2]),"    ",String(neighbors[i][3]),"    ",
      String(neighbors[i][4]),"\n"]);
  Append(buf,["    ",String(gluings[i][1][1]),String(gluings[i][1][2]),
      String(gluings[i][1][3]),String(gluings[i][1][4])," ",
      String(gluings[i][2][1]),String(gluings[i][2][2]),
      String(gluings[i][2][3]),String(gluings[i][2][4])," ",
      String(gluings[i][3][1]),String(gluings[i][3][2]),
      String(gluings[i][3][3]),String(gluings[i][3][4])," ",
      String(gluings[i][4][1]),String(gluings[i][4][2]),
      String(gluings[i][4][3]),String(gluings[i][4][4]),"\n"]);
  Append(buf,["    ",String(cusps[i][1]),"    ",String(cusps[i][2]),"    ",
      String(cusps[i][3]),"    ",String(cusps[i][4]),"\n"]);
  Append(buf,["    0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0\n"]);
  Append(buf,["    0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0\n"]);
  Append(buf,["    0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0\n"]);
  Append(buf,["    0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0\n"]);
  Append(buf,["    0  0\n\n"]);
 od;

 if(FileString(filename,String(Concatenation(buf)))=fail) then
  Info(InfoSimpcomp,1,"SCExportSnapPy: file \"",filename,"\" not writeable!");
  return fail;
 else
  return true;
 fi;

end);

[ Dauer der Verarbeitung: 0.49 Sekunden  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge