source: src/stackclass.hpp@ 390248

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 390248 was 7f3b9d, checked in by Frederik Heber <heber@…>, 17 years ago

Lots of for loops now count in reverse order where it does not matter, some 3 -> NDIM

for(i=0;i<var;i++) is slower than for (i=var;i--;) if the order of the i's is not important (note: i-- is also a value and it stops when on i == 0 automatically)
in builder.cpp there were some remnant 3 actually meant to be NDIM

  • Property mode set to 100644
File size: 9.0 KB
Line 
1#ifndef STACKCLASS_HPP_
2#define STACKCLASS_HPP_
3
4template <typename T> class StackClass;
5
6/******************************** Functions for class StackClass ********************************/
7
8/* Stack of Stuff.
9 * Is used during DepthFirstSearchAnalysis() to detect nonseparable components.
10 */
11template <typename T> class StackClass {
12 public:
13 StackClass<T>(int dimension);
14 ~StackClass<T>();
15
16 bool Push(T object);
17 T PopFirst();
18 T PopLast();
19 bool RemoveItem(T ptr);
20 void ClearStack();
21 bool IsEmpty();
22 bool IsFull();
23 int ItemCount();
24 void Output(ofstream *out) const;
25 void TestImplementation(ofstream *out, T test);
26
27 private:
28 T *StackList; //!< the list containing the atom pointers
29 int EntryCount; //!< number of entries in the stack
30 int CurrentLastEntry; //!< Current last entry (newest item on stack)
31 int CurrentFirstEntry; //!< Current first entry (oldest item on stack)
32 int NextFreeField; //!< Current index of next free field
33};
34
35/** Constructor of class StackClass.
36 */
37template <typename T> StackClass<T>::StackClass(int dimension)
38{
39 CurrentLastEntry = 0;
40 CurrentFirstEntry = 0;
41 NextFreeField = 0;
42 EntryCount = dimension;
43 StackList = (T *) Malloc(sizeof(T)*EntryCount, "StackClass::StackClass: **StackList");
44};
45
46/** Destructor of class StackClass.
47 */
48template <typename T> StackClass<T>::~StackClass()
49{
50 Free((void **)&StackList, "StackClass::StackClass: **StackList");
51};
52
53/** Pushes an object onto the stack.
54 * \param *object atom to be pushed on stack
55 * \return true - sucess, false - failure, meaning stack field was occupied
56 */
57template <typename T> bool StackClass<T>::Push(T object)
58{
59 if (!IsFull()) { // check whether free field is really not occupied
60 StackList[NextFreeField] = object;
61 CurrentLastEntry = NextFreeField;
62 NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field
63 return true;
64 } else {
65 cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl;
66 return false;
67 }
68};
69
70/** Pops first/oldest atom from stack.
71 * First in, last out.
72 * \return atom pointer from stack, NULL - if failure (no atom pointer in field)
73 */
74template <typename T> T StackClass<T>::PopFirst()
75{
76 T Walker = NULL;
77 if (!IsEmpty()) {
78 Walker = StackList[CurrentFirstEntry];
79 if (Walker == NULL)
80 cerr << "ERROR: Stack's field is empty!" << endl;
81 StackList[CurrentFirstEntry] = NULL;
82 if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well?
83 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)
84 } else {
85 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)
86 CurrentLastEntry = CurrentFirstEntry;
87 }
88 } else
89 cerr << "ERROR: Stack is empty!" << endl;
90 return Walker;
91};
92
93/** Pops last element from stack.
94 * First in, first out.
95 * \return element pointer from stack, NULL - if failure (no atom pointer in field)
96 */
97template <typename T> T StackClass<T>::PopLast()
98{
99 T Walker = NULL;
100 if (!IsEmpty()) {
101 Walker = StackList[CurrentLastEntry];
102 StackList[CurrentLastEntry] = NULL;
103 if (Walker == NULL)
104 cerr << "ERROR: Stack's field is empty!" << endl;
105 NextFreeField = CurrentLastEntry;
106 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack
107 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead)
108 } else {
109 cerr << "ERROR: Stack is empty!" << endl;
110 }
111 return Walker;
112};
113
114/** Removes a certain item from the stack.
115 * Item is seeked between \a CurrentFirstEntry and \a CurrentLastEntry, if found, place in stack is NULL'd and
116 * all subsequent items shifted by one position downward (with wrapping taken into account).
117 * \param *ptr adress of item
118 * \return true - item was removed, false - item was not found
119 */
120template <typename T> bool StackClass<T>::RemoveItem(T ptr)
121{
122 bool found = false;
123 cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl;
124 int i=CurrentFirstEntry;
125 if (!IsEmpty())
126 do {
127 if (StackList[i] == ptr) { // if item found, remove
128 cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl;
129 found = true;
130 StackList[i] = NULL;
131 }
132 if ((found) && (StackList[i] != NULL)) { // means we have to shift (and not the removed item)
133 if (i == 0) { // we are down to first item in stack, have to put onto last item
134 cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl;
135 StackList[EntryCount-1] = StackList[0];
136 } else {
137 cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl;
138 StackList[i-1] = StackList[i];
139 }
140 }
141 i=((i + 1) % EntryCount); // step on
142 } while (i!=NextFreeField);
143 else
144 cerr << "ERROR: Stack is already empty!" << endl;
145 if (found) {
146 NextFreeField = CurrentLastEntry;
147 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack
148 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount;
149 }
150 return found;
151};
152
153/** Test the functionality of the stack.
154 * \param *out ofstream for debugging
155 * \param *test one item to put on stack
156 * \return true - all tests worked correctly
157 */
158template <typename T> void StackClass<T>::TestImplementation(ofstream *out, T test)
159{
160 T Walker = test;
161 *out << Verbose(1) << "Testing the snake stack..." << endl;
162 for (int i=0;i<EntryCount;i++) {
163 *out << Verbose(2) << "Filling " << i << "th element of stack." << endl;
164 Push(Walker);
165 Walker=Walker->next;
166 }
167 *out << endl;
168 Output(out);
169 if (IsFull())
170 *out << "Stack is full as supposed to be!" << endl;
171 else
172 *out << "ERROR: Stack is not as full as supposed to be!" << endl;
173 //if (StackList[(EntryCount+1)/2] != NULL) {
174 *out << "Removing element in the middle ..." << endl;
175 RemoveItem(StackList[(EntryCount+1)/2]);
176 Output(out);
177 //}
178 //if (StackList[CurrentFirstEntry] != NULL) {
179 *out << "Removing first element ..." << endl;
180 RemoveItem(StackList[CurrentFirstEntry]);
181 Output(out);
182 //}
183 //if (StackList[CurrentLastEntry] != NULL) {
184 *out << "Removing last element ..." << endl;
185 RemoveItem(StackList[CurrentLastEntry]);
186 Output(out);
187 //}
188 *out << "Clearing stack ... " << endl;
189 ClearStack();
190 Output(out);
191 if (IsEmpty())
192 *out << "Stack is empty as supposed to be!" << endl;
193 else
194 *out << "ERROR: Stack is not as empty as supposed to be!" << endl;
195 *out << "done." << endl;
196};
197
198/** Puts contents of stack into ofstream \a *out.
199 * \param *out ofstream for output
200 */
201template <typename T> void StackClass<T>::Output(ofstream *out) const
202{
203 *out << "Contents of Stack: ";
204 for(int i=0;i<EntryCount;i++) {
205 *out << "\t";
206 if (i == CurrentFirstEntry)
207 *out << " 1";
208 if (i == CurrentLastEntry)
209 *out << " "<< EntryCount;
210 if (i == NextFreeField)
211 *out << " F";
212 *out << ": " << StackList[i];
213 }
214 *out << endl;
215};
216
217/** Checks whether stack is empty.
218 * Simply checks whether StackClass::NextFreeField is equal to StackClass::CurrentFirstEntry and
219 * StackClass::CurrentFirstEntry is equal to StackClass::CurrentLastEntry.
220 * \return true - empty, false - not
221 */
222template <typename T> bool StackClass<T>::IsEmpty()
223{
224 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry == CurrentFirstEntry));
225};
226
227/** Checks whether stack is full.
228 * Simply checks whether StackClass::NextFreeField is equal to StackClass::CurrentFirstEntry and
229 * StackClass::CurrentFirstEntry is _not_ equal to StackClass::CurrentLastEntry.
230 * \return true - full, false - not
231 */
232template <typename T> bool StackClass<T>::IsFull()
233{
234 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry != CurrentFirstEntry));
235};
236
237/** Returns number of items on stack.
238 * Simply returns difference between StackClass::Stacklist entry StackClass::CurrentEntry-1.
239 * \return number of items on stack
240 * \warning will never return correct item count if stack is full, i.e. count would be StackClass::EntryCount.
241 */
242template <typename T> int StackClass<T>::ItemCount()
243{
244 //cout << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tEntryCount " << EntryCount << "." << endl;
245 return((NextFreeField + (EntryCount - CurrentFirstEntry)) % EntryCount);
246};
247
248/** Clears the stack from all atoms.
249 * \return true - sucess, false - failure
250 */
251template <typename T> void StackClass<T>::ClearStack()
252{
253 for(int i=EntryCount; i--;)
254 StackList[i] = NULL;
255 CurrentFirstEntry = 0;
256 CurrentLastEntry = 0;
257 NextFreeField = 0;
258};
259
260
261
262#endif /*STACKCLASS_HPP_*/
Note: See TracBrowser for help on using the repository browser.