source: src/Formula.cpp@ 23761b

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 23761b was c83b98, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Made the instantiation of Formula::iterator and Formula::const_iterator less ugly by refering to typedefs

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