/** \file atom.cpp * * Function implementations for the class atom. * */ #include "molecules.hpp" /************************************* Functions for class atom *************************************/ /** Constructor of class atom. */ atom::atom() { Name = NULL; previous = NULL; next = NULL; father = this; // generally, father is itself Ancestor = NULL; type = NULL; sort = NULL; FixedIon = 0; nr = -1; GraphNr = -1; ComponentNr = NULL; SeparationVertex = false; LowpointNr = -1; }; /** Destructor of class atom. */ atom::~atom() { Free((void **)&Name, "atom::~atom: *Name"); Free((void **)&ComponentNr, "atom::~atom: *ComponentNr"); }; /** Climbs up the father list until NULL, last is returned. * \return true father, i.e. whose father points to itself, NULL if it could not be found or has none (added hydrogen) */ atom *atom::GetTrueFather() { atom *walker = this; do { if (walker == walker->father) // top most father is the one that points on itself break; walker = walker->father; } while (walker != NULL); return walker; }; /** Output of a single atom. * \param ElementNo cardinal number of the element * \param AtomNo cardinal number among these atoms of the same element * \param *out stream to output to */ bool atom::Output(int ElementNo, int AtomNo, ofstream *out) const { if (out != NULL) { *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t" << fixed << setprecision(9) << showpoint; *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2]; *out << "\t" << FixedIon; if (v.Norm() > MYEPSILON) *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t"; *out << " # Number in molecule " << nr << endl; return true; } else return false; }; /** Output of a single atom as one lin in xyz file. * \param *out stream to output to */ bool atom::OutputXYZLine(ofstream *out) const { if (out != NULL) { *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl; return true; } else return false; }; ostream & operator << (ostream &ost, atom &a) { ost << "[" << a.Name << "|" << &a << "]"; return ost; }; /** Compares the indices of \a this atom with a given \a ptr. * \param ptr atom to compare index against * \return true - this one's is smaller, false - not */ bool atom::Compare(atom &ptr) { if (nr < ptr.nr) return true; else return false; }; bool operator < (atom &a, atom &b) { return a.Compare(b); }; /******************************** Functions for class AtomStackClass ********************************/ /** Constructor of class AtomStackClass. */ AtomStackClass::AtomStackClass(int dimension) { CurrentLastEntry = 0; CurrentFirstEntry = 0; NextFreeField = 0; EntryCount = dimension; StackList = (atom **) Malloc(sizeof(atom *)*EntryCount, "AtomStackClass::AtomStackClass: **StackList"); }; /** Destructor of class AtomStackClass. */ AtomStackClass::~AtomStackClass() { Free((void **)&StackList, "AtomStackClass::AtomStackClass: **StackList"); }; /** Pushes an object onto the stack. * \param *object atom to be pushed on stack * \return true - sucess, false - failure, meaning stack field was occupied */ bool AtomStackClass::Push(atom *object) { if (!IsFull()) { // check whether free field is really not occupied StackList[NextFreeField] = object; CurrentLastEntry = NextFreeField; NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field return true; } else { cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl; return false; } }; /** Pops first/oldest atom from stack. * First in, last out. * \return atom pointer from stack, NULL - if failure (no atom pointer in field) */ atom *AtomStackClass::PopFirst() { atom *Walker = NULL; if (!IsEmpty()) { Walker = StackList[CurrentFirstEntry]; if (Walker == NULL) cerr << "ERROR: Stack's field is empty!" << endl; StackList[CurrentFirstEntry] = NULL; if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well? CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1) } else { CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1) CurrentLastEntry = CurrentFirstEntry; } } else cerr << "ERROR: Stack is empty!" << endl; return Walker; }; /** Pops last atom from stack. * First in, first out. * \return atom pointer from stack, NULL - if failure (no atom pointer in field) */ atom *AtomStackClass::PopLast() { atom *Walker = NULL; if (!IsEmpty()) { Walker = StackList[CurrentLastEntry]; StackList[CurrentLastEntry] = NULL; if (Walker == NULL) cerr << "ERROR: Stack's field is empty!" << endl; NextFreeField = CurrentLastEntry; if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead) } else { cerr << "ERROR: Stack is empty!" << endl; } return Walker; }; /** Removes a certain item from the stack. * Item is seeked between \a CurrentFirstEntry and \a CurrentLastEntry, if found, place in stack is NULL'd and * all subsequent items shifted by one position downward (with wrapping taken into account). * \param *ptr adress of item * \return true - item was removed, false - item was not found */ bool AtomStackClass::RemoveItem(atom *ptr) { bool found = false; cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl; int i=CurrentFirstEntry; if (!IsEmpty()) do { if (StackList[i] == ptr) { // if item found, remove cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl; found = true; StackList[i] = NULL; } if ((found) && (StackList[i] != NULL)) { // means we have to shift (and not the removed item) if (i == 0) { // we are down to first item in stack, have to put onto last item cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl; StackList[EntryCount-1] = StackList[0]; } else { cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl; StackList[i-1] = StackList[i]; } } i=((i + 1) % EntryCount); // step on } while (i!=NextFreeField); else cerr << "ERROR: Stack is already empty!" << endl; if (found) { NextFreeField = CurrentLastEntry; if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; } return found; }; /** Test the functionality of the stack. * \param *out ofstream for debugging * \param *test one item to put on stack * \return true - all tests worked correctly */ void AtomStackClass::TestImplementation(ofstream *out, atom *test) { atom *Walker = test; *out << Verbose(1) << "Testing the snake stack..." << endl; for (int i=0;inext; } *out << endl; Output(out); if (IsFull()) *out << "Stack is full as supposed to be!" << endl; else *out << "ERROR: Stack is not as full as supposed to be!" << endl; //if (StackList[(EntryCount+1)/2] != NULL) { *out << "Removing element in the middle ..." << endl; RemoveItem(StackList[(EntryCount+1)/2]); Output(out); //} //if (StackList[CurrentFirstEntry] != NULL) { *out << "Removing first element ..." << endl; RemoveItem(StackList[CurrentFirstEntry]); Output(out); //} //if (StackList[CurrentLastEntry] != NULL) { *out << "Removing last element ..." << endl; RemoveItem(StackList[CurrentLastEntry]); Output(out); //} *out << "Clearing stack ... " << endl; ClearStack(); Output(out); if (IsEmpty()) *out << "Stack is empty as supposed to be!" << endl; else *out << "ERROR: Stack is not as empty as supposed to be!" << endl; *out << "done." << endl; }; /** Puts contents of stack into ofstream \a *out. * \param *out ofstream for output */ void AtomStackClass::Output(ofstream *out) const { *out << "Contents of Stack: "; for(int i=0;i