/* * Formula.cpp * * Created on: Jul 21, 2010 * Author: crueger */ #include "Formula.hpp" #include #include "World.hpp" #include "periodentafel.hpp" #include "element.hpp" #include "Helpers/Assert.hpp" using namespace std; Formula::Formula() : numElements(0) {} Formula::Formula(const Formula &src) : elementCounts(src.elementCounts), numElements(src.numElements) {} Formula::~Formula() {} Formula &Formula::operator=(const Formula &rhs){ // No self-assignment check needed elementCounts=rhs.elementCounts; numElements=rhs.numElements; return *this; } std::string Formula::toString() const{ stringstream sstr; for(const_reverse_iterator iter=rbegin();iter!=rend();++iter){ sstr << (*iter).first->symbol << (*iter).second; } return sstr.str(); } bool Formula::checkOut(ostream *output) const{ bool result = true; int No = 1; if (output != NULL) { *output << "# Ion type data (PP = PseudoPotential, Z = atomic number)" << endl; *output << "#Ion_TypeNr.\tAmount\tZ\tRGauss\tL_Max(PP)L_Loc(PP)IonMass\t# chemical name, symbol" << endl; for(const_iterator iter=begin(); iter!=end();++iter){ (*iter).first->No = No; result = result && (*iter).first->Checkout(output, No++, (*iter).second); } return result; } else return false; } unsigned int Formula::getElementCount(){ return numElements; } bool Formula::hasElement(const element *element) const{ ASSERT(element,"Invalid pointer in Formula::hasElement(element*)"); return hasElement(element->getNumber()); } bool Formula::hasElement(atomicNumber_t Z) const{ ASSERT(Z>0,"Invalid atomic Number"); ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel"); return elementCounts.size()>=Z && elementCounts[Z-1]; } bool Formula::hasElement(const string &shorthand) const{ element * element = World::getInstance().getPeriode()->FindElement(shorthand); return hasElement(element); } void Formula::operator+=(const element *element){ ASSERT(element,"Invalid pointer in increment of Formula"); operator+=(element->getNumber()); } void Formula::operator+=(atomicNumber_t Z){ ASSERT(Z>0,"Invalid atomic Number"); ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel"); elementCounts.resize(Z); // No-op when we already have the right size // might need to update number of elements if(!elementCounts[Z-1]){ numElements++; } elementCounts[Z-1]++; // atomic numbers start at 1 } void Formula::operator+=(const string &shorthand){ element * element = World::getInstance().getPeriode()->FindElement(shorthand); operator+=(element); } void Formula::operator-=(const element *element){ ASSERT(element,"Invalid pointer in decrement of Formula"); operator-=(element->getNumber()); } void Formula::operator-=(atomicNumber_t Z){ ASSERT(Z>0,"Invalid atomic Number"); ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel"); ASSERT(elementCounts.size()>=Z && elementCounts[Z-1], "Element not in Formula upon decrement"); elementCounts[Z-1]--; // atomic numbers start at 1 // might need to update number of elements if(!elementCounts[Z-1]){ numElements--; } } void Formula::operator-=(const string &shorthand){ element * element = World::getInstance().getPeriode()->FindElement(shorthand); operator-=(element); } const unsigned int &Formula::operator[](const element *element) const{ ASSERT(element,"Invalid pointer in access of Formula"); return operator[](element->getNumber()); } const unsigned int &Formula::operator[](atomicNumber_t Z) const{ ASSERT(Z>0,"Invalid atomic Number"); ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel"); elementCounts.resize(Z); // No-op when we already have the right size return elementCounts[Z-1]; // atomic numbers start at 1 } const unsigned int &Formula::operator[](string shorthand) const{ element * element = World::getInstance().getPeriode()->FindElement(shorthand); return operator[](element); } bool Formula::operator==(const Formula &rhs) const{ // quick check... number of elements used if(numElements != rhs.numElements){ return false; } // slow check: all elements // direct access to internal structure means all element-counts have to be compared // this avoids access to periodentafel to find elements though and is probably faster // in total return equal(elementCounts.begin(), elementCounts.end(), rhs.elementCounts.begin()); } bool Formula::operator!=(const Formula &rhs) const{ return !operator==(rhs); } Formula::iterator Formula::begin(){ return iterator(elementCounts,0); } Formula::const_iterator Formula::begin() const{ return const_iterator(elementCounts,0); } Formula::iterator Formula::end(){ return iterator(elementCounts); } Formula::const_iterator Formula::end() const{ return const_iterator(elementCounts); } Formula::reverse_iterator Formula::rbegin(){ return reverse_iterator(end()); } Formula::const_reverse_iterator Formula::rbegin() const{ return const_reverse_iterator(end()); } Formula::reverse_iterator Formula::rend(){ return reverse_iterator(begin()); } Formula::const_reverse_iterator Formula::rend() const{ return const_reverse_iterator(begin()); } /**************** Iterator structure ********************/ template Formula::_iterator::_iterator(set_t &_set) : set(&_set) { pos=set->size(); } template Formula::_iterator::_iterator(set_t &_set,size_t _pos) : set(&_set),pos(_pos) { ASSERT(pos<=set->size(),"invalid position in iterator construction"); while(possize() && (*set)[pos]!=0) ++pos; } template Formula::_iterator::~_iterator(){} template Formula::_iterator& Formula::_iterator::operator=(const _iterator &rhs){ set=rhs.set; pos=rhs.pos; return *this; } template bool Formula::_iterator::operator==(const _iterator &rhs){ return set==rhs.set && pos==rhs.pos; } template bool Formula::_iterator::operator!=(const _iterator &rhs){ return !operator==(rhs); } template Formula::_iterator Formula::_iterator::operator++(){ ASSERT(pos!=set->size(),"Incrementing Formula::iterator beyond end"); while(possize() && (*set)[pos]!=0) ++pos; return *this; } template Formula::_iterator Formula::_iterator::operator--(){ ASSERT(pos!=0,"Decrementing Formula::iterator beyobd begin"); while(pos>0 && (*set)[pos]!=0) ++pos; return *this; } template result_type Formula::_iterator::operator*(){ element *element = World::getInstance().getPeriode()->FindElement(pos+1); ASSERT(element,"Element with position of iterator not found"); return make_pair(element,(*set)[pos]); } template result_type* Formula::_iterator::operator->(){ // no one can keep this value around, so a static is ok to avoid temporaries static value_type value=make_pair(reinterpret_cast(0),0); // no default constructor for std::pair element *element = World::getInstance().getPeriode()->FindElement(pos+1); ASSERT(element,"Element with position of iterator not found"); value = make_pair(element,(*set)[pos]); return &value; } /********************** I/O of Formulas ************************************************/ std::ostream &operator<<(std::ostream &ost,const Formula &formula){ ost << formula.toString(); return ost; }