Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/molecule.cpp

    rf8e486 rbab12a  
    44 *
    55 */
    6 
    7 #include "Helpers/MemDebug.hpp"
    86
    97#include <cstring>
     
    3735 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero.
    3836 */
    39 molecule::molecule(const periodentafel * const teil) :
    40   Observable("molecule"),
    41   elemente(teil),  MDSteps(0),  BondCount(0), ElementCount(0), NoNonHydrogen(0), NoNonBonds(0),
    42   NoCyclicBonds(0), BondDistance(0.),  ActiveFlag(false), IndexNr(-1),
    43   formula(this,boost::bind(&molecule::calcFormula,this),"formula"),
    44   AtomCount(this,boost::bind(&molecule::doCountAtoms,this),"AtomCount"), last_atom(0),  InternalPointer(begin())
    45 {
     37molecule::molecule(const periodentafel * const teil) : elemente(teil), start(World::getInstance().createAtom()), end(World::getInstance().createAtom()),
     38  first(new bond(start, end, 1, -1)), last(new bond(start, end, 1, -1)), MDSteps(0), AtomCount(0),
     39  BondCount(0), ElementCount(0), NoNonHydrogen(0), NoNonBonds(0), NoCyclicBonds(0), BondDistance(0.),
     40  ActiveFlag(false), IndexNr(-1),
     41  formula(this,boost::bind(&molecule::calcFormula,this)),
     42  last_atom(0),
     43  InternalPointer(start)
     44{
     45  // init atom chain list
     46  start->father = NULL;
     47  end->father = NULL;
     48  link(start,end);
     49
     50  // init bond chain list
     51  link(first,last);
    4652
    4753  // other stuff
     
    6167{
    6268  CleanupMolecule();
     69  delete(first);
     70  delete(last);
     71  end->getWorld()->destroyAtom(end);
     72  start->getWorld()->destroyAtom(start);
    6373};
    6474
     
    7383}
    7484
    75 int molecule::getAtomCount() const{
    76   return *AtomCount;
    77 }
    78 
    7985void molecule::setName(const std::string _name){
    8086  OBSERVE;
     
    98104  stringstream sstr;
    99105  periodentafel *periode = World::getInstance().getPeriode();
    100   for (molecule::const_iterator iter = begin(); iter != end(); ++iter) {
    101     counts[(*iter)->type->getNumber()]++;
     106  for(atom *Walker = start; Walker != end; Walker = Walker->next) {
     107    counts[Walker->type->getNumber()]++;
    102108  }
    103109  std::map<atomicNumber_t,unsigned int>::reverse_iterator iter;
     
    109115}
    110116
    111 /************************** Access to the List of Atoms ****************/
    112 
    113 
    114 molecule::iterator molecule::begin(){
    115   return molecule::iterator(atoms.begin(),this);
    116 }
    117 
    118 molecule::const_iterator molecule::begin() const{
    119   return atoms.begin();
    120 }
    121 
    122 molecule::iterator molecule::end(){
    123   return molecule::iterator(atoms.end(),this);
    124 }
    125 
    126 molecule::const_iterator molecule::end() const{
    127   return atoms.end();
    128 }
    129 
    130 bool molecule::empty() const
    131 {
    132   return (begin() == end());
    133 }
    134 
    135 size_t molecule::size() const
    136 {
    137   size_t counter = 0;
    138   for (molecule::const_iterator iter = begin(); iter != end (); ++iter)
    139     counter++;
    140   return counter;
    141 }
    142 
    143 molecule::const_iterator molecule::erase( const_iterator loc )
    144 {
    145   molecule::const_iterator iter = loc;
    146   iter--;
    147   atom* atom = *loc;
    148   atoms.erase( loc );
    149   atom->removeFromMolecule();
    150   return iter;
    151 }
    152 
    153 molecule::const_iterator molecule::erase( atom * key )
    154 {
    155   cout << "trying to erase atom" << endl;
    156   molecule::const_iterator iter = find(key);
    157   if (iter != end()){
    158     atoms.erase( iter++ );
    159     key->removeFromMolecule();
    160   }
    161   return iter;
    162 }
    163 
    164 molecule::const_iterator molecule::find ( atom * key ) const
    165 {
    166   return atoms.find( key );
    167 }
    168 
    169 pair<molecule::iterator,bool> molecule::insert ( atom * const key )
    170 {
    171   pair<atomSet::iterator,bool> res = atoms.insert(key);
    172   return pair<iterator,bool>(iterator(res.first,this),res.second);
    173 }
    174 
    175 bool molecule::containsAtom(atom* key){
    176   return atoms.count(key);
    177 }
    178117
    179118/** Adds given atom \a *pointer from molecule list.
     
    184123bool molecule::AddAtom(atom *pointer)
    185124{
     125  bool retval = false;
    186126  OBSERVE;
    187127  if (pointer != NULL) {
    188128    pointer->sort = &pointer->nr;
     129    pointer->nr = last_atom++;  // increase number within molecule
     130    AtomCount++;
    189131    if (pointer->type != NULL) {
    190132      if (ElementsInMolecule[pointer->type->Z] == 0)
     
    199141      }
    200142    }
    201     insert(pointer);
    202     pointer->setMolecule(this);
    203   }
    204   return true;
     143    retval = add(pointer, end);
     144  }
     145  return retval;
    205146};
    206147
     
    216157  if (pointer != NULL) {
    217158    atom *walker = pointer->clone();
    218     walker->setName(pointer->getName());
     159    stringstream sstr;
     160    sstr << pointer->getName();
     161    walker->setName(sstr.str());
    219162    walker->nr = last_atom++;  // increase number within molecule
    220     insert(walker);
     163    add(walker, end);
    221164    if ((pointer->type != NULL) && (pointer->type->Z != 1))
    222165      NoNonHydrogen++;
     166    AtomCount++;
    223167    retval=walker;
    224168  }
     
    298242    Orthovector1.MatrixMultiplication(matrix);
    299243    InBondvector -= Orthovector1; // subtract just the additional translation
    300     delete[](matrix);
     244    Free(&matrix);
    301245    bondlength = InBondvector.Norm();
    302246//    Log() << Verbose(4) << "Corrected InBondvector is now: ";
     
    307251  InBondvector.Normalize();
    308252  // get typical bond length and store as scale factor for later
    309   ASSERT(TopOrigin->type != NULL, "AddHydrogenReplacementAtom: element of TopOrigin is not given.");
    310253  BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];
    311254  if (BondRescale == -1) {
     
    529472      break;
    530473  }
    531   delete[](matrix);
     474  Free(&matrix);
    532475
    533476//  Log() << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl;
     
    612555
    613556  // copy all bonds
    614   bond *Binder = NULL;
     557  bond *Binder = first;
    615558  bond *NewBond = NULL;
    616   for(molecule::iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner)
    617     for(BondList::iterator BondRunner = (*AtomRunner)->ListOfBonds.begin(); !(*AtomRunner)->ListOfBonds.empty(); BondRunner = (*AtomRunner)->ListOfBonds.begin())
    618       if ((*BondRunner)->leftatom == *AtomRunner) {
    619         Binder = (*BondRunner);
    620 
    621         // get the pendant atoms of current bond in the copy molecule
    622         copy->ActOnAllAtoms( &atom::EqualsFather, (const atom *)Binder->leftatom, (const atom **)&LeftAtom );
    623         copy->ActOnAllAtoms( &atom::EqualsFather, (const atom *)Binder->rightatom, (const atom **)&RightAtom );
    624 
    625         NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
    626         NewBond->Cyclic = Binder->Cyclic;
    627         if (Binder->Cyclic)
    628           copy->NoCyclicBonds++;
    629         NewBond->Type = Binder->Type;
    630       }
     559  while(Binder->next != last) {
     560    Binder = Binder->next;
     561
     562    // get the pendant atoms of current bond in the copy molecule
     563    copy->ActOnAllAtoms( &atom::EqualsFather, (const atom *)Binder->leftatom, (const atom **)&LeftAtom );
     564    copy->ActOnAllAtoms( &atom::EqualsFather, (const atom *)Binder->rightatom, (const atom **)&RightAtom );
     565
     566    NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
     567    NewBond->Cyclic = Binder->Cyclic;
     568    if (Binder->Cyclic)
     569      copy->NoCyclicBonds++;
     570    NewBond->Type = Binder->Type;
     571  }
    631572  // correct fathers
    632573  ActOnAllAtoms( &atom::CorrectFather );
    633574
    634575  // copy values
     576  copy->CountAtoms();
    635577  copy->CountElements();
    636   if (hasBondStructure()) {  // if adjaceny list is present
     578  if (first->next != last) {  // if adjaceny list is present
    637579    copy->BondDistance = BondDistance;
    638580  }
     
    666608bond * molecule::AddBond(atom *atom1, atom *atom2, int degree)
    667609{
    668   OBSERVE;
    669610  bond *Binder = NULL;
    670 
    671   // some checks to make sure we are able to create the bond
    672   ASSERT(atom1, "First atom in bond-creation was an invalid pointer");
    673   ASSERT(atom2, "Second atom in bond-creation was an invalid pointer");
    674   ASSERT(FindAtom(atom1->nr),"First atom in bond-creation was not part of molecule");
    675   ASSERT(FindAtom(atom2->nr),"Second atom in bond-creation was not parto of molecule");
    676 
    677   Binder = new bond(atom1, atom2, degree, BondCount++);
    678   atom1->RegisterBond(Binder);
    679   atom2->RegisterBond(Binder);
    680   if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))
    681     NoNonBonds++;
    682 
     611  if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) {
     612    Binder = new bond(atom1, atom2, degree, BondCount++);
     613    atom1->RegisterBond(Binder);
     614    atom2->RegisterBond(Binder);
     615    if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))
     616      NoNonBonds++;
     617    add(Binder, last);
     618  } else {
     619    DoeLog(1) && (eLog()<< Verbose(1) << "Could not add bond between " << atom1->getName() << " and " << atom2->getName() << " as one or both are not present in the molecule." << endl);
     620  }
    683621  return Binder;
    684622};
     
    692630{
    693631  //DoeLog(1) && (eLog()<< Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl);
    694   delete(pointer);
     632  pointer->leftatom->RegisterBond(pointer);
     633  pointer->rightatom->RegisterBond(pointer);
     634  removewithoutcheck(pointer);
    695635  return true;
    696636};
     
    752692bool molecule::RemoveAtom(atom *pointer)
    753693{
    754   ASSERT(pointer, "Null pointer passed to molecule::RemoveAtom().");
    755   OBSERVE;
    756694  if (ElementsInMolecule[pointer->type->Z] != 0)  { // this would indicate an error
    757695    ElementsInMolecule[pointer->type->Z]--;  // decrease number of atom of this element
     696    AtomCount--;
    758697  } else
    759698    DoeLog(1) && (eLog()<< Verbose(1) << "Atom " << pointer->getName() << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl);
     
    761700    ElementCount--;
    762701  RemoveBonds(pointer);
    763   erase(pointer);
    764   return true;
     702  return remove(pointer, start, end);
    765703};
    766704
     
    779717  if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
    780718    ElementCount--;
    781   erase(pointer);
     719  unlink(pointer);
    782720  return true;
    783721};
     
    788726bool molecule::CleanupMolecule()
    789727{
    790   for (molecule::iterator iter = begin(); !empty(); iter = begin())
    791       erase(iter);
     728  return (cleanup(first,last) && cleanup(start,end));
    792729};
    793730
     
    796733 * \return pointer to atom or NULL
    797734 */
    798 atom * molecule::FindAtom(int Nr)  const
    799 {
    800   molecule::const_iterator iter = begin();
    801   for (; iter != end(); ++iter)
    802     if ((*iter)->nr == Nr)
    803       break;
    804   if (iter != end()) {
     735atom * molecule::FindAtom(int Nr)  const{
     736  atom * walker = find(&Nr, start,end);
     737  if (walker != NULL) {
    805738    //Log() << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;
    806     return (*iter);
     739    return walker;
    807740  } else {
    808741    DoLog(0) && (Log() << Verbose(0) << "Atom not found in list." << endl);
     
    934867    now = time((time_t *)NULL);   // Get the system time and put it into 'now' as 'calender time'
    935868    for (int step=0;step<MDSteps;step++) {
    936       *output << getAtomCount() << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
     869      *output << AtomCount << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
    937870      ActOnAllAtoms( &atom::OutputTrajectoryXYZ, output, step );
    938871    }
     
    951884  if (output != NULL) {
    952885    now = time((time_t *)NULL);   // Get the system time and put it into 'now' as 'calender time'
    953     *output << getAtomCount() << "\n\tCreated by molecuilder on " << ctime(&now);
     886    *output << AtomCount << "\n\tCreated by molecuilder on " << ctime(&now);
    954887    ActOnAllAtoms( &atom::OutputXYZLine, output );
    955888    return true;
     
    961894 * \param *out output stream for debugging
    962895 */
    963 int molecule::doCountAtoms()
    964 {
    965   int res = size();
     896void molecule::CountAtoms()
     897{
    966898  int i = 0;
    967   NoNonHydrogen = 0;
    968   for (molecule::const_iterator iter = atoms.begin(); iter != atoms.end(); ++iter) {
    969     (*iter)->nr = i;   // update number in molecule (for easier referencing in FragmentMolecule lateron)
    970     if ((*iter)->type->Z != 1) // count non-hydrogen atoms whilst at it
    971       NoNonHydrogen++;
    972     stringstream sstr;
    973     sstr << (*iter)->type->symbol << (*iter)->nr+1;
    974     (*iter)->setName(sstr.str());
    975     DoLog(3) && (Log() << Verbose(3) << "Naming atom nr. " << (*iter)->nr << " " << (*iter)->getName() << "." << endl);
     899  atom *Walker = start;
     900  while (Walker->next != end) {
     901    Walker = Walker->next;
    976902    i++;
    977903  }
    978   return res;
     904  if ((AtomCount == 0) || (i != AtomCount)) {
     905    DoLog(3) && (Log() << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl);
     906    AtomCount = i;
     907
     908    // count NonHydrogen atoms and give each atom a unique name
     909    if (AtomCount != 0) {
     910      i=0;
     911      NoNonHydrogen = 0;
     912      Walker = start;
     913      while (Walker->next != end) {
     914        Walker = Walker->next;
     915        Walker->nr = i;   // update number in molecule (for easier referencing in FragmentMolecule lateron)
     916        if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it
     917          NoNonHydrogen++;
     918        stringstream sstr;
     919        sstr << Walker->type->symbol << Walker->nr+1;
     920        Walker->setName(sstr.str());
     921        DoLog(3) && (Log() << Verbose(3) << "Naming atom nr. " << Walker->nr << " " << Walker->getName() << "." << endl);
     922        i++;
     923      }
     924    } else
     925      DoLog(3) && (Log() << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl);
     926  }
    979927};
    980928
     
    1038986  /// first count both their atoms and elements and update lists thereby ...
    1039987  //Log() << Verbose(0) << "Counting atoms, updating list" << endl;
     988  CountAtoms();
     989  OtherMolecule->CountAtoms();
    1040990  CountElements();
    1041991  OtherMolecule->CountElements();
     
    1044994  /// -# AtomCount
    1045995  if (result) {
    1046     if (getAtomCount() != OtherMolecule->getAtomCount()) {
    1047       DoLog(4) && (Log() << Verbose(4) << "AtomCounts don't match: " << getAtomCount() << " == " << OtherMolecule->getAtomCount() << endl);
     996    if (AtomCount != OtherMolecule->AtomCount) {
     997      DoLog(4) && (Log() << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl);
    1048998      result = false;
    1049     } else Log() << Verbose(4) << "AtomCounts match: " << getAtomCount() << " == " << OtherMolecule->getAtomCount() << endl;
     999    } else Log() << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
    10501000  }
    10511001  /// -# ElementCount
     
    10841034  if (result) {
    10851035    DoLog(5) && (Log() << Verbose(5) << "Calculating distances" << endl);
    1086     Distances = new double[getAtomCount()];
    1087     OtherDistances = new double[getAtomCount()];
     1036    Distances = Calloc<double>(AtomCount, "molecule::IsEqualToWithinThreshold: Distances");
     1037    OtherDistances = Calloc<double>(AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");
    10881038    SetIndexedArrayForEachAtomTo ( Distances, &atom::nr, &atom::DistanceSquaredToVector, (const Vector &)CenterOfGravity);
    10891039    SetIndexedArrayForEachAtomTo ( OtherDistances, &atom::nr, &atom::DistanceSquaredToVector, (const Vector &)CenterOfGravity);
    1090     for(int i=0;i<getAtomCount();i++) {
    1091       Distances[i] = 0.;
    1092       OtherDistances[i] = 0.;
    1093     }
    10941040
    10951041    /// ... sort each list (using heapsort (o(N log N)) from GSL)
    10961042    DoLog(5) && (Log() << Verbose(5) << "Sorting distances" << endl);
    1097     PermMap = new size_t[getAtomCount()];
    1098     OtherPermMap = new size_t[getAtomCount()];
    1099     for(int i=0;i<getAtomCount();i++) {
    1100       PermMap[i] = 0;
    1101       OtherPermMap[i] = 0;
    1102     }
    1103     gsl_heapsort_index (PermMap, Distances, getAtomCount(), sizeof(double), CompareDoubles);
    1104     gsl_heapsort_index (OtherPermMap, OtherDistances, getAtomCount(), sizeof(double), CompareDoubles);
    1105     PermutationMap = new int[getAtomCount()];
    1106     for(int i=0;i<getAtomCount();i++)
    1107       PermutationMap[i] = 0;
     1043    PermMap = Calloc<size_t>(AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");
     1044    OtherPermMap = Calloc<size_t>(AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
     1045    gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);
     1046    gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);
     1047    PermutationMap = Calloc<int>(AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");
    11081048    DoLog(5) && (Log() << Verbose(5) << "Combining Permutation Maps" << endl);
    1109     for(int i=getAtomCount();i--;)
     1049    for(int i=AtomCount;i--;)
    11101050      PermutationMap[PermMap[i]] = (int) OtherPermMap[i];
    11111051
     
    11131053    DoLog(4) && (Log() << Verbose(4) << "Comparing distances" << endl);
    11141054    flag = 0;
    1115     for (int i=0;i<getAtomCount();i++) {
     1055    for (int i=0;i<AtomCount;i++) {
    11161056      DoLog(5) && (Log() << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<  threshold << endl);
    11171057      if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)
     
    11201060
    11211061    // free memory
    1122     delete[](PermMap);
    1123     delete[](OtherPermMap);
    1124     delete[](Distances);
    1125     delete[](OtherDistances);
     1062    Free(&PermMap);
     1063    Free(&OtherPermMap);
     1064    Free(&Distances);
     1065    Free(&OtherDistances);
    11261066    if (flag) { // if not equal
    1127       delete[](PermutationMap);
     1067      Free(&PermutationMap);
    11281068      result = false;
    11291069    }
     
    11491089int * molecule::GetFatherSonAtomicMap(molecule *OtherMolecule)
    11501090{
     1091  atom *Walker = NULL, *OtherWalker = NULL;
    11511092  DoLog(3) && (Log() << Verbose(3) << "Begin of GetFatherAtomicMap." << endl);
    1152   int *AtomicMap = new int[getAtomCount()];
    1153   for (int i=getAtomCount();i--;)
     1093  int *AtomicMap = Malloc<int>(AtomCount, "molecule::GetAtomicMap: *AtomicMap");
     1094  for (int i=AtomCount;i--;)
    11541095    AtomicMap[i] = -1;
    11551096  if (OtherMolecule == this) {  // same molecule
    1156     for (int i=getAtomCount();i--;) // no need as -1 means already that there is trivial correspondence
     1097    for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence
    11571098      AtomicMap[i] = i;
    11581099    DoLog(4) && (Log() << Verbose(4) << "Map is trivial." << endl);
    11591100  } else {
    11601101    DoLog(4) && (Log() << Verbose(4) << "Map is ");
    1161     for (molecule::const_iterator iter = begin(); iter != end(); ++iter) {
    1162       if ((*iter)->father == NULL) {
    1163         AtomicMap[(*iter)->nr] = -2;
     1102    Walker = start;
     1103    while (Walker->next != end) {
     1104      Walker = Walker->next;
     1105      if (Walker->father == NULL) {
     1106        AtomicMap[Walker->nr] = -2;
    11641107      } else {
    1165         for (molecule::const_iterator runner = OtherMolecule->begin(); runner != OtherMolecule->end(); ++runner) {
     1108        OtherWalker = OtherMolecule->start;
     1109        while (OtherWalker->next != OtherMolecule->end) {
     1110          OtherWalker = OtherWalker->next;
    11661111      //for (int i=0;i<AtomCount;i++) { // search atom
    1167         //for (int j=0;j<OtherMolecule->getAtomCount();j++) {
    1168           //Log() << Verbose(4) << "Comparing father " << (*iter)->father << " with the other one " << (*runner)->father << "." << endl;
    1169           if ((*iter)->father == (*runner))
    1170             AtomicMap[(*iter)->nr] = (*runner)->nr;
     1112        //for (int j=0;j<OtherMolecule->AtomCount;j++) {
     1113          //Log() << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;
     1114          if (Walker->father == OtherWalker)
     1115            AtomicMap[Walker->nr] = OtherWalker->nr;
    11711116        }
    11721117      }
    1173       DoLog(0) && (Log() << Verbose(0) << AtomicMap[(*iter)->nr] << "\t");
     1118      DoLog(0) && (Log() << Verbose(0) << AtomicMap[Walker->nr] << "\t");
    11741119    }
    11751120    DoLog(0) && (Log() << Verbose(0) << endl);
     
    12051150void molecule::SetIndexedArrayForEachAtomTo ( atom **array, int ParticleInfo::*index) const
    12061151{
    1207   for (molecule::const_iterator iter = begin(); iter != end(); ++iter) {
    1208     array[((*iter)->*index)] = (*iter);
     1152  atom *Walker = start;
     1153  while (Walker->next != end) {
     1154    Walker = Walker->next;
     1155    array[(Walker->*index)] = Walker;
    12091156  }
    12101157};
Note: See TracChangeset for help on using the changeset viewer.