source: src/Formula.cpp@ add42a

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 Candidate_v1.7.0 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 add42a was add42a, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Removed reverse formula iterators, because they would cause memory corruptions

  • Property mode set to 100644
File size: 13.1 KB
Line 
1/*
2 * Formula.cpp
3 *
4 * Created on: Jul 21, 2010
5 * Author: crueger
6 */
7
8#include "Formula.hpp"
9
10#include <sstream>
11#include <iostream>
12
13#include "World.hpp"
14#include "periodentafel.hpp"
15#include "element.hpp"
16#include "Helpers/Assert.hpp"
17
18using namespace std;
19
20Formula::Formula() :
21 numElements(0)
22{}
23
24Formula::Formula(const Formula &src) :
25 elementCounts(src.elementCounts),
26 numElements(src.numElements)
27{}
28
29Formula::Formula(const string &formula) :
30 numElements(0)
31{
32 fromString(formula);
33}
34
35Formula::~Formula()
36{}
37
38Formula &Formula::operator=(const Formula &rhs){
39 // No self-assignment check needed
40 elementCounts=rhs.elementCounts;
41 numElements=rhs.numElements;
42 return *this;
43}
44
45std::string Formula::toString() const{
46 stringstream sstr;
47 for(const_iterator iter=end();iter!=begin();){
48 --iter;
49 sstr << (*iter).first->symbol;
50 if((*iter).second>1)
51 sstr << (*iter).second;
52 }
53 return sstr.str();
54}
55
56// quick function used for parsing
57bool isInRange(pair<char,char> range,char character){
58 return range.first<=character && character<=range.second;
59}
60
61void Formula::fromString(const std::string &formula) throw(ParseError){
62 // some constants needed for parsing... Assumes ASCII, change if other encodings are used
63 static const pair<char,char> CapitalLetters = make_pair('A','Z');
64 static const pair<char,char> SmallLetters = make_pair('a','z');
65 static const pair<char,char> Numbers = make_pair('0','9');
66 // clean the formula
67 clear();
68 string::const_iterator end = formula.end(); // will be used frequently
69 for(string::const_iterator it=formula.begin();it!=end;){
70 string shorthand;
71 // Atom names start with a capital letter
72 if(!isInRange(CapitalLetters,(*it)))
73 throw(ParseError(__FILE__,__LINE__));
74 shorthand+=(*it++);
75 cout << "Beginning of shorthand read: " << shorthand << endl;
76 // the rest of the name follows
77 while(it!=end && isInRange(SmallLetters,(*it)))
78 shorthand+=(*it++);
79 cout << "Full shorthand read: " << shorthand << endl;
80 // now we can count the occurences
81 int count = 0;
82 while(it!=end && isInRange(Numbers,(*it)))
83 count = (count*10) + ((*it++)-Numbers.first);
84 cout << "Count read: " << count << endl;
85 // one is implicit
86 count = (count!=0)?count:1;
87 cout << "Corrected implicit count: " << count << endl;
88 // done, we can get the next one
89 addElements(shorthand,count);
90 }
91}
92
93bool Formula::checkOut(ostream *output) const{
94 bool result = true;
95 int No = 1;
96
97 if (output != NULL) {
98 *output << "# Ion type data (PP = PseudoPotential, Z = atomic number)" << endl;
99 *output << "#Ion_TypeNr.\tAmount\tZ\tRGauss\tL_Max(PP)L_Loc(PP)IonMass\t# chemical name, symbol" << endl;
100 for(const_iterator iter=begin(); iter!=end();++iter){
101 (*iter).first->No = No;
102 result = result && (*iter).first->Checkout(output, No++, (*iter).second);
103 }
104 return result;
105 } else
106 return false;
107}
108
109unsigned int Formula::getElementCount() const{
110 return numElements;
111}
112
113bool Formula::hasElement(const element *element) const{
114 ASSERT(element,"Invalid pointer in Formula::hasElement(element*)");
115 return hasElement(element->getNumber());
116}
117
118bool Formula::hasElement(atomicNumber_t Z) const{
119 ASSERT(Z>0,"Invalid atomic Number");
120 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
121 return elementCounts.size()>=Z && elementCounts[Z-1];
122}
123
124bool Formula::hasElement(const string &shorthand) const{
125 element * element = World::getInstance().getPeriode()->FindElement(shorthand);
126 return hasElement(element);
127}
128
129void Formula::operator+=(const element *element){
130 ASSERT(element,"Invalid pointer in increment of Formula");
131 operator+=(element->getNumber());
132}
133
134void Formula::operator+=(atomicNumber_t Z){
135 ASSERT(Z>0,"Invalid atomic Number");
136 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
137 elementCounts.resize(Z); // No-op when we already have the right size
138 // might need to update number of elements
139 if(!elementCounts[Z-1]){
140 numElements++;
141 }
142 elementCounts[Z-1]++; // atomic numbers start at 1
143}
144
145void Formula::operator+=(const string &shorthand){
146 element * element = World::getInstance().getPeriode()->FindElement(shorthand);
147 operator+=(element);
148}
149
150void Formula::operator-=(const element *element){
151 ASSERT(element,"Invalid pointer in decrement of Formula");
152 operator-=(element->getNumber());
153}
154
155void Formula::operator-=(atomicNumber_t Z){
156 ASSERT(Z>0,"Invalid atomic Number");
157 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
158 ASSERT(elementCounts.size()>=Z && elementCounts[Z-1], "Element not in Formula upon decrement");
159 elementCounts[Z-1]--; // atomic numbers start at 1
160 // might need to update number of elements
161 if(!elementCounts[Z-1]){
162 numElements--;
163 }
164}
165
166void Formula::operator-=(const string &shorthand){
167 element * element = World::getInstance().getPeriode()->FindElement(shorthand);
168 operator-=(element);
169}
170
171void Formula::addElements(const element *element,unsigned int count){
172 ASSERT(element,"Invalid pointer in Formula::addElements(element*)");
173 addElements(element->getNumber(),count);
174}
175
176void Formula::addElements(atomicNumber_t Z,unsigned int count){
177 if(count==0) return;
178 ASSERT(Z>0,"Invalid atomic Number");
179 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
180 elementCounts.resize(Z); // No-op when we already have the right size
181 cout << "Adding " << count << " to element with number " << Z << endl;
182 // might need to update number of elements
183 if(!elementCounts[Z-1]){
184 numElements++;
185 }
186 elementCounts[Z-1]+=count;
187 cout << "Element ist now " << elementCounts[Z-1] << endl;
188}
189
190void Formula::addElements(const string &shorthand,unsigned int count){
191 element * element = World::getInstance().getPeriode()->FindElement(shorthand);
192 addElements(element,count);
193}
194
195const unsigned int Formula::operator[](const element *element) const{
196 ASSERT(element,"Invalid pointer in access of Formula");
197 return operator[](element->getNumber());
198}
199
200const unsigned int Formula::operator[](atomicNumber_t Z) const{
201 ASSERT(Z>0,"Invalid atomic Number");
202 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
203 if(elementCounts.size()<Z)
204 return 0;
205 return elementCounts[Z-1]; // atomic numbers start at 1
206}
207
208const unsigned int Formula::operator[](string shorthand) const{
209 element * element = World::getInstance().getPeriode()->FindElement(shorthand);
210 return operator[](element);
211}
212
213bool Formula::operator==(const Formula &rhs) const{
214 // quick check... number of elements used
215 if(numElements != rhs.numElements){
216 return false;
217 }
218 // slow check: all elements
219 // direct access to internal structure means all element-counts have to be compared
220 // this avoids access to periodentafel to find elements though and is probably faster
221 // in total
222 return equal(elementCounts.begin(),
223 elementCounts.end(),
224 rhs.elementCounts.begin());
225}
226
227bool Formula::operator!=(const Formula &rhs) const{
228 return !operator==(rhs);
229}
230
231Formula::iterator Formula::begin(){
232 return iterator(elementCounts,0);
233}
234Formula::const_iterator Formula::begin() const{
235 return const_iterator(elementCounts,0);
236}
237Formula::iterator Formula::end(){
238 return iterator(elementCounts);
239}
240Formula::const_iterator Formula::end() const{
241 return const_iterator(elementCounts);
242}
243
244void Formula::clear(){
245 elementCounts.clear();
246 numElements = 0;
247}
248
249/**************** Iterator structure ********************/
250
251template <class result_type>
252Formula::_iterator<result_type>::_iterator(set_t &_set) :
253 set(&_set)
254{
255 pos=set->size();
256}
257
258template <class result_type>
259Formula::_iterator<result_type>::_iterator(set_t &_set,size_t _pos) :
260 set(&_set),pos(_pos)
261{
262 ASSERT(pos<=set->size(),"invalid position in iterator construction");
263 while(pos<set->size() && (*set)[pos]==0) ++pos;
264}
265
266template <class result_type>
267Formula::_iterator<result_type>::_iterator(const _iterator &rhs) :
268 set(rhs.set),pos(rhs.pos)
269{}
270
271template <class result_type>
272Formula::_iterator<result_type>::~_iterator(){}
273
274template <class result_type>
275Formula::_iterator<result_type>&
276Formula::_iterator<result_type>::operator=(const _iterator<result_type> &rhs){
277 set=rhs.set;
278 pos=rhs.pos;
279 return *this;
280}
281
282template <class result_type>
283bool
284Formula::_iterator<result_type>::operator==(const _iterator<result_type> &rhs){
285 return set==rhs.set && pos==rhs.pos;
286}
287
288template <class result_type>
289bool
290Formula::_iterator<result_type>::operator!=(const _iterator<result_type> &rhs){
291 return !operator==(rhs);
292}
293
294template <class result_type>
295Formula::_iterator<result_type>
296Formula::_iterator<result_type>::operator++(){
297 ASSERT(pos!=set->size(),"Incrementing Formula::iterator beyond end");
298 pos++;
299 while(pos<set->size() && (*set)[pos]==0) ++pos;
300 return *this;
301}
302
303template <class result_type>
304Formula::_iterator<result_type>
305Formula::_iterator<result_type>::operator++(int){
306 Formula::_iterator<result_type> retval = *this;
307 ++(*this);
308 return retval;
309}
310
311template <class result_type>
312Formula::_iterator<result_type>
313Formula::_iterator<result_type>::operator--(){
314 ASSERT(pos!=0,"Decrementing Formula::iterator beyond begin");
315 pos--;
316 while(pos>0 && (*set)[pos]==0) --pos;
317 return *this;
318}
319
320template <class result_type>
321Formula::_iterator<result_type>
322Formula::_iterator<result_type>::operator--(int){
323 Formula::_iterator<result_type> retval = *this;
324 --(*this);
325 return retval;
326}
327
328template <class result_type>
329result_type
330Formula::_iterator<result_type>::operator*(){
331 element *element = World::getInstance().getPeriode()->FindElement(pos+1);
332 ASSERT(element,"Element with position of iterator not found");
333 return make_pair(element,(*set)[pos]);
334}
335
336template <class result_type>
337result_type*
338Formula::_iterator<result_type>::operator->(){
339 // no one can keep this value around, so a static is ok to avoid temporaries
340 static value_type value=make_pair(reinterpret_cast<element*>(0),0); // no default constructor for std::pair
341 element *element = World::getInstance().getPeriode()->FindElement(pos+1);
342 ASSERT(element,"Element with position of iterator not found");
343 value = make_pair(element,(*set)[pos]);
344 return &value;
345}
346
347// explicit instantiation of all iterator template methods
348// this is quite ugly, but there is no better way unless we expose iterator implementation
349
350// instantiate Formula::iterator
351template Formula::_iterator<Formula::value_type>::_iterator(set_t&);
352template Formula::_iterator<Formula::value_type>::_iterator(set_t&,size_t);
353template Formula::_iterator<Formula::value_type>::_iterator(const Formula::_iterator<Formula::value_type>&);
354template Formula::_iterator<Formula::value_type>::~_iterator();
355template Formula::_iterator<Formula::value_type> &Formula::_iterator<Formula::value_type>::operator=(const _iterator &);
356template bool Formula::_iterator<Formula::value_type>::operator==(const _iterator&);
357template bool Formula::_iterator<Formula::value_type>::operator!=(const _iterator&);
358template Formula::_iterator<Formula::value_type> Formula::_iterator<Formula::value_type>::operator++();
359template Formula::_iterator<Formula::value_type> Formula::_iterator<Formula::value_type>::operator++(int);
360template Formula::_iterator<Formula::value_type> Formula::_iterator<Formula::value_type>::operator--();
361template Formula::_iterator<Formula::value_type> Formula::_iterator<Formula::value_type>::operator--(int);
362template Formula::value_type Formula::_iterator<Formula::value_type>::operator*();
363template Formula::value_type *Formula::_iterator<Formula::value_type>::operator->();
364
365// instantiate Formula::const_iterator
366template Formula::_iterator<const Formula::value_type>::_iterator(set_t&);
367template Formula::_iterator<const Formula::value_type>::_iterator(set_t&,size_t);
368template Formula::_iterator<const Formula::value_type>::_iterator(const Formula::_iterator<const Formula::value_type>&);
369template Formula::_iterator<const Formula::value_type>::~_iterator();
370template Formula::_iterator<const Formula::value_type> &Formula::_iterator<const Formula::value_type>::operator=(const _iterator &);
371template bool Formula::_iterator<const Formula::value_type>::operator==(const _iterator&);
372template bool Formula::_iterator<const Formula::value_type>::operator!=(const _iterator&);
373template Formula::_iterator<const Formula::value_type> Formula::_iterator<const Formula::value_type>::operator++();
374template Formula::_iterator<const Formula::value_type> Formula::_iterator<const Formula::value_type>::operator++(int);
375template Formula::_iterator<const Formula::value_type> Formula::_iterator<const Formula::value_type>::operator--();
376template Formula::_iterator<const Formula::value_type> Formula::_iterator<const Formula::value_type>::operator--(int);
377template const Formula::value_type Formula::_iterator<const Formula::value_type>::operator*();
378template const Formula::value_type *Formula::_iterator<const Formula::value_type>::operator->();
379
380/********************** I/O of Formulas ************************************************/
381
382std::ostream &operator<<(std::ostream &ost,const Formula &formula){
383 ost << formula.toString();
384 return ost;
385}
Note: See TracBrowser for help on using the repository browser.