source: molecuilder/src/atom.cpp@ 473c2b

Last change on this file since 473c2b was a0bcf1, checked in by Frederik Heber <heber@…>, 17 years ago

-initial commit
-Minimum set of files needed from ESPACK SVN repository
-Switch to three tantamount package parts instead of all relating to pcp (as at some time Ralf's might find inclusion as well)

  • Property mode set to 100644
File size: 10.6 KB
Line 
1/** \file atom.cpp
2 *
3 * Function implementations for the class atom.
4 *
5 */
6
7#include "molecules.hpp"
8
9/************************************* Functions for class atom *************************************/
10
11/** Constructor of class atom.
12 */
13atom::atom()
14{
15 Name = NULL;
16 previous = NULL;
17 next = NULL;
18 father = this; // generally, father is itself
19 Ancestor = NULL;
20 type = NULL;
21 sort = NULL;
22 nr = -1;
23 GraphNr = -1;
24 ComponentNr = NULL;
25 SeparationVertex = false;
26 LowpointNr = -1;
27};
28
29/** Destructor of class atom.
30 */
31atom::~atom()
32{
33 Free((void **)&Name, "atom::~atom: *Name");
34 Free((void **)&ComponentNr, "atom::~atom: *ComponentNr");
35};
36
37
38/** Climbs up the father list until NULL, last is returned.
39 * \return true father, i.e. whose father points to itself, NULL if it could not be found or has none (added hydrogen)
40 */
41atom *atom::GetTrueFather()
42{
43 atom *walker = this;
44 do {
45 if (walker == walker->father) // top most father is the one that points on itself
46 break;
47 walker = walker->father;
48 } while (walker != NULL);
49 return walker;
50};
51
52/** Output of a single atom.
53 * \param ElementNo cardinal number of the element
54 * \param AtomNo cardinal number among these atoms of the same element
55 * \param *out stream to output to
56 */
57bool atom::Output(int ElementNo, int AtomNo, ofstream *out) const
58{
59 if (out != NULL) {
60 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t" << fixed << setprecision(9) << showpoint;
61 *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t";
62 *out << "\t" << "0\t# Number in molecule " << nr << endl;
63 return true;
64 } else
65 return false;
66};
67
68/** Output of a single atom as one lin in xyz file.
69 * \param *out stream to output to
70 */
71bool atom::OutputXYZLine(ofstream *out) const
72{
73 if (out != NULL) {
74 *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl;
75 return true;
76 } else
77 return false;
78};
79
80ostream & operator << (ostream &ost, atom &a)
81{
82 ost << "[" << a.Name << "|" << &a << "]";
83 return ost;
84};
85
86/** Compares the indices of \a this atom with a given \a ptr.
87 * \param ptr atom to compare index against
88 * \return true - this one's is smaller, false - not
89 */
90bool atom::Compare(atom &ptr)
91{
92 if (nr < ptr.nr)
93 return true;
94 else
95 return false;
96};
97
98bool operator < (atom &a, atom &b)
99{
100 return a.Compare(b);
101};
102
103/******************************** Functions for class AtomStackClass ********************************/
104
105/** Constructor of class AtomStackClass.
106 */
107AtomStackClass::AtomStackClass(int dimension)
108{
109 CurrentLastEntry = 0;
110 CurrentFirstEntry = 0;
111 NextFreeField = 0;
112 EntryCount = dimension;
113 StackList = (atom **) Malloc(sizeof(atom *)*EntryCount, "AtomStackClass::AtomStackClass: **StackList");
114};
115
116/** Destructor of class AtomStackClass.
117 */
118AtomStackClass::~AtomStackClass()
119{
120 Free((void **)&StackList, "AtomStackClass::AtomStackClass: **StackList");
121};
122
123/** Pushes an object onto the stack.
124 * \param *object atom to be pushed on stack
125 * \return true - sucess, false - failure, meaning stack field was occupied
126 */
127bool AtomStackClass::Push(atom *object)
128{
129 if (!IsFull()) { // check whether free field is really not occupied
130 StackList[NextFreeField] = object;
131 CurrentLastEntry = NextFreeField;
132 NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field
133 return true;
134 } else {
135 cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl;
136 return false;
137 }
138};
139
140/** Pops first/oldest atom from stack.
141 * First in, last out.
142 * \return atom pointer from stack, NULL - if failure (no atom pointer in field)
143 */
144atom *AtomStackClass::PopFirst()
145{
146 atom *Walker = NULL;
147 if (!IsEmpty()) {
148 Walker = StackList[CurrentFirstEntry];
149 if (Walker == NULL)
150 cerr << "ERROR: Stack's field is empty!" << endl;
151 StackList[CurrentFirstEntry] = NULL;
152 if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well?
153 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)
154 } else {
155 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)
156 CurrentLastEntry = CurrentFirstEntry;
157 }
158 } else
159 cerr << "ERROR: Stack is empty!" << endl;
160 return Walker;
161};
162
163/** Pops last atom from stack.
164 * First in, first out.
165 * \return atom pointer from stack, NULL - if failure (no atom pointer in field)
166 */
167atom *AtomStackClass::PopLast()
168{
169 atom *Walker = NULL;
170 if (!IsEmpty()) {
171 Walker = StackList[CurrentLastEntry];
172 StackList[CurrentLastEntry] = NULL;
173 if (Walker == NULL)
174 cerr << "ERROR: Stack's field is empty!" << endl;
175 NextFreeField = CurrentLastEntry;
176 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack
177 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead)
178 } else {
179 cerr << "ERROR: Stack is empty!" << endl;
180 }
181 return Walker;
182};
183
184/** Removes a certain item from the stack.
185 * Item is seeked between \a CurrentFirstEntry and \a CurrentLastEntry, if found, place in stack is NULL'd and
186 * all subsequent items shifted by one position downward (with wrapping taken into account).
187 * \param *ptr adress of item
188 * \return true - item was removed, false - item was not found
189 */
190bool AtomStackClass::RemoveItem(atom *ptr)
191{
192 bool found = false;
193 cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl;
194 int i=CurrentFirstEntry;
195 if (!IsEmpty())
196 do {
197 if (StackList[i] == ptr) { // if item found, remove
198 cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl;
199 found = true;
200 StackList[i] = NULL;
201 }
202 if ((found) && (StackList[i] != NULL)) { // means we have to shift (and not the removed item)
203 if (i == 0) { // we are down to first item in stack, have to put onto last item
204 cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl;
205 StackList[EntryCount-1] = StackList[0];
206 } else {
207 cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl;
208 StackList[i-1] = StackList[i];
209 }
210 }
211 i=((i + 1) % EntryCount); // step on
212 } while (i!=NextFreeField);
213 else
214 cerr << "ERROR: Stack is already empty!" << endl;
215 if (found) {
216 NextFreeField = CurrentLastEntry;
217 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack
218 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount;
219 }
220 return found;
221};
222
223/** Test the functionality of the stack.
224 * \param *out ofstream for debugging
225 * \param *test one item to put on stack
226 * \return true - all tests worked correctly
227 */
228void AtomStackClass::TestImplementation(ofstream *out, atom *test)
229{
230 atom *Walker = test;
231 *out << Verbose(1) << "Testing the snake stack..." << endl;
232 for (int i=0;i<EntryCount;i++) {
233 *out << Verbose(2) << "Filling " << i << "th element of stack." << endl;
234 Push(Walker);
235 Walker=Walker->next;
236 }
237 *out << endl;
238 Output(out);
239 if (IsFull())
240 *out << "Stack is full as supposed to be!" << endl;
241 else
242 *out << "ERROR: Stack is not as full as supposed to be!" << endl;
243 //if (StackList[(EntryCount+1)/2] != NULL) {
244 *out << "Removing element in the middle ..." << endl;
245 RemoveItem(StackList[(EntryCount+1)/2]);
246 Output(out);
247 //}
248 //if (StackList[CurrentFirstEntry] != NULL) {
249 *out << "Removing first element ..." << endl;
250 RemoveItem(StackList[CurrentFirstEntry]);
251 Output(out);
252 //}
253 //if (StackList[CurrentLastEntry] != NULL) {
254 *out << "Removing last element ..." << endl;
255 RemoveItem(StackList[CurrentLastEntry]);
256 Output(out);
257 //}
258 *out << "Clearing stack ... " << endl;
259 ClearStack();
260 Output(out);
261 if (IsEmpty())
262 *out << "Stack is empty as supposed to be!" << endl;
263 else
264 *out << "ERROR: Stack is not as empty as supposed to be!" << endl;
265 *out << "done." << endl;
266};
267
268/** Puts contents of stack into ofstream \a *out.
269 * \param *out ofstream for output
270 */
271void AtomStackClass::Output(ofstream *out) const
272{
273 *out << "Contents of Stack: ";
274 for(int i=0;i<EntryCount;i++) {
275 *out << "\t";
276 if (i == CurrentFirstEntry)
277 *out << " 1";
278 if (i == CurrentLastEntry)
279 *out << " "<< EntryCount;
280 if (i == NextFreeField)
281 *out << " F";
282 *out << ": " << StackList[i];
283 }
284 *out << endl;
285};
286
287/** Checks whether stack is empty.
288 * Simply checks whether AtomStackClass::NextFreeField is equal to AtomStackClass::CurrentFirstEntry and
289 * AtomStackClass::CurrentFirstEntry is equal to AtomStackClass::CurrentLastEntry.
290 * \return true - empty, false - not
291 */
292bool AtomStackClass::IsEmpty()
293{
294 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry == CurrentFirstEntry));
295};
296
297/** Checks whether stack is full.
298 * Simply checks whether AtomStackClass::NextFreeField is equal to AtomStackClass::CurrentFirstEntry and
299 * AtomStackClass::CurrentFirstEntry is _not_ equal to AtomStackClass::CurrentLastEntry.
300 * \return true - full, false - not
301 */
302bool AtomStackClass::IsFull()
303{
304 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry != CurrentFirstEntry));
305};
306
307/** Returns number of items on stack.
308 * Simply returns difference between AtomStackClass::Stacklist entry AtomStackClass::CurrentEntry-1.
309 * \return number of items on stack
310 * \warning will never return correct item count if stack is full, i.e. count would be AtomStackClass::EntryCount.
311 */
312int AtomStackClass::ItemCount()
313{
314 //cout << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tEntryCount " << EntryCount << "." << endl;
315 return((NextFreeField + (EntryCount - CurrentFirstEntry)) % EntryCount);
316};
317
318/** Clears the stack from all atoms.
319 * \return true - sucess, false - failure
320 */
321void AtomStackClass::ClearStack()
322{
323 for(int i=0;i<EntryCount; i++)
324 StackList[i] = NULL;
325 CurrentFirstEntry = 0;
326 CurrentLastEntry = 0;
327 NextFreeField = 0;
328};
329
Note: See TracBrowser for help on using the repository browser.