Index: src/Descriptors/MoleculeFormulaDescriptor.cpp
===================================================================
--- src/Descriptors/MoleculeFormulaDescriptor.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
+++ src/Descriptors/MoleculeFormulaDescriptor.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -0,0 +1,33 @@
+/*
+ * MoleculeFormulaDescriptor.cpp
+ *
+ *  Created on: Jul 22, 2010
+ *      Author: crueger
+ */
+
+#include "MoleculeFormulaDescriptor.hpp"
+#include "MoleculeFormulaDescriptor_impl.hpp"
+
+#include "molecule.hpp"
+
+
+MoleculeFormulaDescriptor_impl::MoleculeFormulaDescriptor_impl(const Formula &_formula) :
+  formula(_formula)
+{}
+
+MoleculeFormulaDescriptor_impl::~MoleculeFormulaDescriptor_impl(){}
+
+bool MoleculeFormulaDescriptor_impl::predicate(std::pair<moleculeId_t,molecule*> molecule){
+  return molecule.second->getFormula() == formula;
+}
+
+
+MoleculeDescriptor MoleculeByFormula(const Formula &formula)
+{
+  return MoleculeDescriptor(MoleculeDescriptor::impl_ptr(new MoleculeFormulaDescriptor_impl(formula)));
+}
+
+MoleculeDescriptor MoleculeByFormula(const std::string &_formula) throw(ParseError){
+  Formula formula(_formula);
+  return MoleculeByFormula(formula);
+}
Index: src/Descriptors/MoleculeFormulaDescriptor.hpp
===================================================================
--- src/Descriptors/MoleculeFormulaDescriptor.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
+++ src/Descriptors/MoleculeFormulaDescriptor.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -0,0 +1,19 @@
+/*
+ * MoleculeFormulaDescriptor.hpp
+ *
+ *  Created on: Jul 22, 2010
+ *      Author: crueger
+ */
+
+#ifndef MOLECULEFORMULADESCRIPTOR_HPP_
+#define MOLECULEFORMULADESCRIPTOR_HPP_
+
+#include "Descriptors/MoleculeDescriptor.hpp"
+#include "Exceptions/ParseError.hpp"
+
+class Formula;
+
+MoleculeDescriptor MoleculeByFormula(const Formula&);
+MoleculeDescriptor MoleculeByFormula(const std::string&) throw(ParseError);
+
+#endif /* MOLECULEFORMULADESCRIPTOR_HPP_ */
Index: src/Descriptors/MoleculeFormulaDescriptor_impl.hpp
===================================================================
--- src/Descriptors/MoleculeFormulaDescriptor_impl.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
+++ src/Descriptors/MoleculeFormulaDescriptor_impl.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -0,0 +1,24 @@
+/*
+ * MoleculeFormulaDescriptor_impl.hpp
+ *
+ *  Created on: Jul 22, 2010
+ *      Author: crueger
+ */
+
+#ifndef MOLECULEFORMULADESCRIPTOR_IMPL_HPP_
+#define MOLECULEFORMULADESCRIPTOR_IMPL_HPP_
+
+#include "Descriptors/MoleculeDescriptor_impl.hpp"
+#include "Formula.hpp"
+
+class MoleculeFormulaDescriptor_impl : public MoleculeDescriptor_impl
+{
+public:
+  MoleculeFormulaDescriptor_impl(const Formula &);
+  virtual ~MoleculeFormulaDescriptor_impl();
+  bool predicate(std::pair<moleculeId_t,molecule*> molecule);
+private:
+  Formula formula;
+};
+
+#endif /* MOLECULEFORMULADESCRIPTOR_IMPL_HPP_ */
Index: src/Descriptors/MoleculePtrDescriptor.cpp
===================================================================
--- src/Descriptors/MoleculePtrDescriptor.cpp	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/Descriptors/MoleculePtrDescriptor.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -10,4 +10,6 @@
 #include "MoleculePtrDescriptor.hpp"
 #include "MoleculePtrDescriptor_impl.hpp"
+
+#include "Patterns/ObservedContainer_impl.hpp"
 
 #include "molecule.hpp"
Index: src/Exceptions/ParseError.cpp
===================================================================
--- src/Exceptions/ParseError.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
+++ src/Exceptions/ParseError.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -0,0 +1,18 @@
+/*
+ * ParseError.cpp
+ *
+ *  Created on: Jul 21, 2010
+ *      Author: crueger
+ */
+
+#include "ParseError.hpp"
+
+ParseError::ParseError(std::string file, int line) :
+  CustomException(file,line)
+{}
+
+ParseError::~ParseError() throw(){}
+
+const char* ParseError::what() const throw(){
+  return "Could not parse string";
+}
Index: src/Exceptions/ParseError.hpp
===================================================================
--- src/Exceptions/ParseError.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
+++ src/Exceptions/ParseError.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -0,0 +1,22 @@
+/*
+ * ParseError.hpp
+ *
+ *  Created on: Jul 21, 2010
+ *      Author: crueger
+ */
+
+#ifndef PARSEERROR_HPP_
+#define PARSEERROR_HPP_
+
+#include "Exceptions/CustomException.hpp"
+
+class ParseError : public CustomException
+{
+public:
+  ParseError(std::string file, int line);
+  virtual ~ParseError() throw();
+
+  virtual const char* what() const throw();
+};
+
+#endif /* PARSEERROR_HPP_ */
Index: src/Formula.cpp
===================================================================
--- src/Formula.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
+++ src/Formula.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -0,0 +1,393 @@
+/*
+ * Formula.cpp
+ *
+ *  Created on: Jul 21, 2010
+ *      Author: crueger
+ */
+
+#include "Formula.hpp"
+
+#include <sstream>
+
+#include "World.hpp"
+#include "periodentafel.hpp"
+#include "element.hpp"
+#include "Helpers/Assert.hpp"
+#include "Helpers/Range.hpp"
+
+using namespace std;
+
+Formula::Formula() :
+  numElements(0)
+{}
+
+Formula::Formula(const Formula &src) :
+  elementCounts(src.elementCounts),
+  numElements(src.numElements)
+{}
+
+Formula::Formula(const string &formula) :
+  numElements(0)
+{
+  fromString(formula);
+}
+
+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_iterator iter=end();iter!=begin();){
+    --iter;
+    sstr << (*iter).first->symbol;
+    if((*iter).second>1)
+      sstr << (*iter).second;
+  }
+  return sstr.str();
+}
+
+void Formula::fromString(const std::string &formula) throw(ParseError){
+  // some constants needed for parsing... Assumes ASCII, change if other encodings are used
+  static const range<char> CapitalLetters = makeRange('A',static_cast<char>('Z'+1));
+  static const range<char> SmallLetters = makeRange('a',static_cast<char>('z'+1));
+  static const range<char> Numbers = makeRange('0',static_cast<char>('9'+1));
+  // clean the formula
+  clear();
+  string::const_iterator end = formula.end(); // will be used frequently
+  for(string::const_iterator it=formula.begin();it!=end;){
+    string shorthand;
+    // Atom names start with a capital letter
+    if(!CapitalLetters.isInRange(*it))
+      throw(ParseError(__FILE__,__LINE__));
+    shorthand+=(*it++);
+    // the rest of the name follows
+    while(it!=end && SmallLetters.isInRange(*it))
+      shorthand+=(*it++);
+    // now we can count the occurences
+    int count = 0;
+    while(it!=end && Numbers.isInRange(*it))
+      count = (count*10) + ((*it++)-Numbers.first);
+    // one is implicit
+    count = (count!=0)?count:1;
+    // test if the shorthand exists
+    if(!World::getInstance().getPeriode()->FindElement(shorthand))
+      throw(ParseError(__FILE__,__LINE__));
+    // done, we can get the next one
+    addElements(shorthand,count);
+  }
+}
+
+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() const{
+  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(max<atomicNumber_t>(Z,elementCounts.size()),0); // 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--;
+    // resize the Array if this was at the last position
+    if(Z==elementCounts.size()){
+      // find the first element from the back that is not equal to zero
+      set_t::reverse_iterator riter = find_if(elementCounts.rbegin(),
+                                              elementCounts.rend(),
+                                              bind1st(not_equal_to<mapped_type>(),0));
+      // see how many elements are in this range
+      set_t::reverse_iterator::difference_type diff = riter - elementCounts.rbegin();
+      elementCounts.resize(elementCounts.size()-diff);
+    }
+  }
+}
+
+void Formula::operator-=(const string &shorthand){
+  element * element = World::getInstance().getPeriode()->FindElement(shorthand);
+  operator-=(element);
+}
+
+void Formula::addElements(const element *element,unsigned int count){
+  ASSERT(element,"Invalid pointer in Formula::addElements(element*)");
+  addElements(element->getNumber(),count);
+}
+
+void Formula::addElements(atomicNumber_t Z,unsigned int count){
+  if(count==0) return;
+  ASSERT(Z>0,"Invalid atomic Number");
+  ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
+  elementCounts.resize(max<atomicNumber_t>(Z,elementCounts.size()),0); // No-op when we already have the right size
+  // might need to update number of elements
+  if(!elementCounts[Z-1]){
+    numElements++;
+  }
+  elementCounts[Z-1]+=count;
+}
+
+void Formula::addElements(const string &shorthand,unsigned int count){
+  element * element = World::getInstance().getPeriode()->FindElement(shorthand);
+  addElements(element,count);
+}
+
+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");
+  if(elementCounts.size()<Z)
+    return 0;
+  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;
+  }
+  // second quick check, size of vectors (== last element in formula)
+  if(elementCounts.size()!=rhs.elementCounts.size()){
+    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{
+  // this is the only place where this is needed, so this is better than making it mutable
+  return const_iterator(const_cast<set_t&>(elementCounts),0);
+}
+Formula::iterator Formula::end(){
+  return iterator(elementCounts);
+}
+Formula::const_iterator Formula::end() const{
+  // this is the only place where this is needed, so this is better than making it mutable
+  return const_iterator(const_cast<set_t&>(elementCounts));
+}
+
+void Formula::clear(){
+  elementCounts.clear();
+  numElements = 0;
+}
+
+/**************** Iterator structure ********************/
+
+template <class result_type>
+Formula::_iterator<result_type>::_iterator(set_t &_set) :
+    set(&_set)
+{
+  pos=set->size();
+}
+
+template <class result_type>
+Formula::_iterator<result_type>::_iterator(set_t &_set,size_t _pos) :
+  set(&_set),pos(_pos)
+{
+  ASSERT(pos<=set->size(),"invalid position in iterator construction");
+  while(pos<set->size() && (*set)[pos]==0) ++pos;
+}
+
+template <class result_type>
+Formula::_iterator<result_type>::_iterator(const _iterator &rhs) :
+  set(rhs.set),pos(rhs.pos)
+{}
+
+template <class result_type>
+Formula::_iterator<result_type>::~_iterator(){}
+
+template <class result_type>
+Formula::_iterator<result_type>&
+Formula::_iterator<result_type>::operator=(const _iterator<result_type> &rhs){
+  set=rhs.set;
+  pos=rhs.pos;
+  return *this;
+}
+
+template <class result_type>
+bool
+Formula::_iterator<result_type>::operator==(const _iterator<result_type> &rhs){
+  return set==rhs.set && pos==rhs.pos;
+}
+
+template <class result_type>
+bool
+Formula::_iterator<result_type>::operator!=(const _iterator<result_type> &rhs){
+  return !operator==(rhs);
+}
+
+template <class result_type>
+Formula::_iterator<result_type>
+Formula::_iterator<result_type>::operator++(){
+  ASSERT(pos!=set->size(),"Incrementing Formula::iterator beyond end");
+  pos++;
+  while(pos<set->size() && (*set)[pos]==0) ++pos;
+  return *this;
+}
+
+template <class result_type>
+Formula::_iterator<result_type>
+Formula::_iterator<result_type>::operator++(int){
+  Formula::_iterator<result_type> retval = *this;
+  ++(*this);
+  return retval;
+}
+
+template <class result_type>
+Formula::_iterator<result_type>
+Formula::_iterator<result_type>::operator--(){
+  ASSERT(pos!=0,"Decrementing Formula::iterator beyond begin");
+  pos--;
+  while(pos>0 && (*set)[pos]==0) --pos;
+  return *this;
+}
+
+template <class result_type>
+Formula::_iterator<result_type>
+Formula::_iterator<result_type>::operator--(int){
+  Formula::_iterator<result_type> retval = *this;
+  --(*this);
+  return retval;
+}
+
+template <class result_type>
+result_type
+Formula::_iterator<result_type>::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 <class result_type>
+result_type*
+Formula::_iterator<result_type>::operator->(){
+  // no one can keep this value around, so a static is ok to avoid temporaries
+  static value_type value=make_pair(reinterpret_cast<element*>(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;
+}
+
+// explicit instantiation of all iterator template methods
+// this is quite ugly, but there is no better way unless we expose iterator implementation
+
+// instantiate Formula::iterator
+template Formula::iterator::_iterator(set_t&);
+template Formula::iterator::_iterator(set_t&,size_t);
+template Formula::iterator::_iterator(const Formula::iterator&);
+template Formula::iterator::~_iterator();
+template Formula::iterator &Formula::iterator::operator=(const Formula::iterator&);
+template bool Formula::iterator::operator==(const Formula::iterator&);
+template bool Formula::iterator::operator!=(const Formula::iterator&);
+template Formula::iterator Formula::iterator::operator++();
+template Formula::iterator Formula::iterator::operator++(int);
+template Formula::iterator Formula::iterator::operator--();
+template Formula::iterator Formula::iterator::operator--(int);
+template Formula::value_type Formula::iterator::operator*();
+template Formula::value_type *Formula::iterator::operator->();
+
+// instantiate Formula::const_iterator
+template Formula::const_iterator::_iterator(set_t&);
+template Formula::const_iterator::_iterator(set_t&,size_t);
+template Formula::const_iterator::_iterator(const Formula::const_iterator&);
+template Formula::const_iterator::~_iterator();
+template Formula::const_iterator &Formula::const_iterator::operator=(const Formula::const_iterator&);
+template bool Formula::const_iterator::operator==(const Formula::const_iterator&);
+template bool Formula::const_iterator::operator!=(const Formula::const_iterator&);
+template Formula::const_iterator Formula::const_iterator::operator++();
+template Formula::Formula::const_iterator Formula::const_iterator::operator++(int);
+template Formula::Formula::const_iterator Formula::const_iterator::operator--();
+template Formula::Formula::const_iterator Formula::const_iterator::operator--(int);
+template const Formula::value_type Formula::const_iterator::operator*();
+template const Formula::value_type *Formula::const_iterator::operator->();
+
+/********************** I/O of Formulas ************************************************/
+
+std::ostream &operator<<(std::ostream &ost,const Formula &formula){
+  ost << formula.toString();
+  return ost;
+}
Index: src/Formula.hpp
===================================================================
--- src/Formula.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
+++ src/Formula.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -0,0 +1,110 @@
+/*
+ * Formula.hpp
+ *
+ *  Created on: Jul 21, 2010
+ *      Author: crueger
+ */
+
+#ifndef FORMULA_HPP_
+#define FORMULA_HPP_
+
+#include <vector>
+#include <iosfwd>
+#include <iterator>
+
+#include "Exceptions/ParseError.hpp"
+
+#include "types.hpp"
+
+class element;
+
+class Formula
+{
+public:
+  typedef element*                                      key_type;
+  typedef unsigned int                                  mapped_type;
+  typedef std::pair<key_type, mapped_type>              value_type;
+  typedef std::vector<unsigned int>                     set_t;
+
+  template <class result_type>
+  class _iterator : public std::iterator <std::bidirectional_iterator_tag,
+                                         result_type>
+  {
+  public:
+    _iterator(set_t&);
+    _iterator(set_t&,size_t);
+    _iterator(const _iterator &rhs);
+    ~_iterator();
+    _iterator   &operator=(const _iterator &);
+    bool         operator==(const _iterator&);
+    bool         operator!=(const _iterator&);
+    _iterator    operator++();
+    _iterator    operator++(int);
+    _iterator    operator--();
+    _iterator    operator--(int);
+    result_type  operator*();
+    result_type *operator->();
+  private:
+    set_t *set;
+    size_t pos; // cannot use an iterator, because we need a position to access the element
+  };
+
+  typedef _iterator<value_type>                 iterator;
+  typedef _iterator<const value_type>           const_iterator;
+
+  Formula();
+  Formula(const std::string&);
+  Formula(const Formula&);
+  virtual ~Formula();
+
+  Formula &operator=(const Formula&);
+
+  std::string toString() const;
+  void fromString(const std::string&) throw(ParseError);
+  bool checkOut(std::ostream*) const;
+
+  unsigned int getElementCount() const;
+  bool hasElement(const element*)       const;
+  bool hasElement(atomicNumber_t)       const;
+  bool hasElement(const std::string&)   const;
+
+  void operator+=(const element*);
+  void operator+=(atomicNumber_t);
+  void operator+=(const std::string&);
+
+  void operator-=(const element*);
+  void operator-=(atomicNumber_t);
+  void operator-=(const std::string&);
+
+  void addElements(const element*,unsigned int);
+  void addElements(atomicNumber_t,unsigned int);
+  void addElements(const std::string&,unsigned int);
+
+  // only const versions, because someone might try to increment a previously
+  // not set element
+  const unsigned int operator[](const element*) const;
+  const unsigned int operator[](atomicNumber_t) const;
+  const unsigned int operator[](std::string)    const;
+
+  bool operator==(const Formula&) const;
+  bool operator!=(const Formula&) const;
+
+  iterator       begin();
+  const_iterator begin() const;
+  iterator       end();
+  const_iterator end()   const;
+
+  void clear();
+
+private:
+  // this contains all counts of elements in the formula
+  // the size of the actual structure might be used in comparisons
+  // so be sure not to keep any zero elements at the end
+  // e.g. {5;4;0;0;0;2;1} or {0;1;0;0;2} are ok, but {1;2;3;0;0;0} is bad
+  set_t elementCounts;
+  unsigned int numElements;
+};
+
+std::ostream &operator<<(std::ostream&,const Formula&);
+
+#endif /* FORMULA_HPP_ */
Index: src/Helpers/Range.hpp
===================================================================
--- src/Helpers/Range.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
+++ src/Helpers/Range.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -0,0 +1,65 @@
+/*
+ * Range.hpp
+ *
+ *  Created on: Jul 22, 2010
+ *      Author: crueger
+ */
+
+#ifndef RANGE_HPP_
+#define RANGE_HPP_
+template <class T>
+struct range {
+  range(const T&,const T&);
+  bool isInRange(const T&) const;
+  bool isBefore(const T&) const;
+  bool isBeyond(const T&) const;
+
+  T first;
+  T last;
+};
+
+template <class T>
+inline range<T>::range(const T &_first,const T &_last) :
+first(_first),last(_last)
+{}
+
+template <class T>
+inline bool range<T>::isInRange(const T &value) const{
+  return first <= value && value < last;
+}
+
+template <class T>
+inline bool range<T>::isBefore(const T &value) const{
+  return value < first;
+}
+
+template <class T>
+inline bool range<T>::isBeyond(const T &value) const{
+ return last <= value;
+}
+
+template <class T>
+inline range<T> makeRange(const T&first, const T&last){
+  return range<T>(first,last);
+}
+
+template <class T>
+inline bool operator<(const range <T> &x, const range<T> &y){
+  return (x.first!=y.first)?x.first<y.first:x.last<y.last;
+}
+
+template <class T>
+inline bool operator==(const range<T> &x,const range<T> &y){
+  return x.first==y.first && x.last==y.last;
+}
+
+template <class T>
+inline bool operator!= (const range<T>& x, const range<T>& y) { return !(x==y); }
+template <class T>
+inline bool operator>  (const range<T>& x, const range<T>& y) { return y<x; }
+template <class T>
+inline bool operator<=(const range<T>& x, const range<T>& y) { return !(y<x); }
+template <class T>
+inline bool operator>= (const range<T>& x, const range<T>& y) { return !(x<y); }
+
+#endif /* RANGE_HPP_ */
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/Makefile.am	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -77,21 +77,25 @@
   Actions/Process.hpp
 
-EXCEPTIONSOURCE = Exceptions/CustomException.cpp \
-	Exceptions/IllegalTypeException.cpp \
-	Exceptions/LinearDependenceException.cpp \
-	Exceptions/MathException.cpp \
-	Exceptions/MissingValueException.cpp \
-	Exceptions/NotInvertibleException.cpp \
-	Exceptions/SkewException.cpp \
-	Exceptions/ZeroVectorException.cpp
+EXCEPTIONSOURCE = \
+  Exceptions/CustomException.cpp \
+  Exceptions/IllegalTypeException.cpp \
+  Exceptions/LinearDependenceException.cpp \
+  Exceptions/MathException.cpp \
+  Exceptions/MissingValueException.cpp \
+  Exceptions/NotInvertibleException.cpp \
+  Exceptions/ParseError.cpp \
+  Exceptions/SkewException.cpp \
+  Exceptions/ZeroVectorException.cpp
 				  
-EXCEPTIONHEADER = Exceptions/CustomException.hpp \
-	Exceptions/IllegalTypeException.hpp \
-	Exceptions/LinearDependenceException.hpp \
-	Exceptions/MathException.hpp \
-	Exceptions/MissingValueException.hpp \
-	Exceptions/NotInvertibleException.hpp \
-	Exceptions/SkewException.hpp \
-	Exceptions/ZeroVectorException.hpp
+EXCEPTIONHEADER = \
+  Exceptions/CustomException.hpp \
+  Exceptions/IllegalTypeException.hpp \
+  Exceptions/LinearDependenceException.hpp \
+  Exceptions/MathException.hpp \
+  Exceptions/MissingValueException.hpp \
+  Exceptions/NotInvertibleException.hpp \
+  Exceptions/ParseError.hpp \
+  Exceptions/SkewException.hpp \
+  Exceptions/ZeroVectorException.hpp
 
 PARSERSOURCE = \
@@ -151,4 +155,5 @@
   Descriptors/AtomTypeDescriptor.cpp \
   Descriptors/MoleculeDescriptor.cpp \
+  Descriptors/MoleculeFormulaDescriptor.cpp \
   Descriptors/MoleculeIdDescriptor.cpp \
   Descriptors/MoleculeNameDescriptor.cpp \
@@ -162,4 +167,5 @@
   Descriptors/AtomTypeDescriptor.hpp \
   Descriptors/MoleculeDescriptor.hpp \
+  Descriptors/MoleculeFormulaDescriptor.hpp \
   Descriptors/MoleculeIdDescriptor.hpp \
   Descriptors/MoleculeNameDescriptor.hpp \
@@ -202,4 +208,5 @@
   ellipsoid.cpp \
   errorlogger.cpp \
+  Formula.cpp \
   graph.cpp \
   helpers.cpp \
@@ -252,4 +259,5 @@
   ellipsoid.hpp \
   errorlogger.hpp \
+  Formula.hpp \
   graph.hpp \
   helpers.hpp \
Index: src/World.cpp
===================================================================
--- src/World.cpp	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/World.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -234,8 +234,8 @@
     atomIdPool_t::iterator iter=atomIdPool.begin();
     atomId_t id = iter->first;
-    pair<atomId_t,atomId_t> newRange = make_pair(id+1,iter->second);
+    range<atomId_t> newRange = makeRange(id+1,iter->last);
     // we wont use this iterator anymore, so we don't care about invalidating
     atomIdPool.erase(iter);
-    if(newRange.first<newRange.second){
+    if(newRange.first<newRange.last){
       atomIdPool.insert(newRange);
     }
@@ -247,5 +247,5 @@
 
 void World::releaseAtomId(atomId_t id){
-  atomIdPool.insert(make_pair(id,id+1));
+  atomIdPool.insert(makeRange(id,id+1));
   defragAtomIdPool();
 }
@@ -253,6 +253,6 @@
 bool World::reserveAtomId(atomId_t id){
   if(id>=currAtomId ){
-    pair<atomId_t,atomId_t> newRange = make_pair(currAtomId,id);
-    if(newRange.first<newRange.second){
+    range<atomId_t> newRange = makeRange(currAtomId,id);
+    if(newRange.first<newRange.last){
       atomIdPool.insert(newRange);
     }
@@ -263,21 +263,21 @@
   // look for a range that matches the request
   for(atomIdPool_t::iterator iter=atomIdPool.begin();iter!=atomIdPool.end();++iter){
-    if(iter->first>id){
-      // we have coverd all available ranges... nothing to be found here
+    if(iter->isBefore(id)){
+      // we have covered all available ranges... nothing to be found here
       break;
     }
     // no need to check first, since it has to be <=id, since otherwise we would have broken out
-    if(iter->second > id){
+    if(!iter->isBeyond(id)){
       // we found a matching range... get the id from this range
 
       // split up this range at the point of id
-      pair<atomId_t,atomId_t> bottomRange = make_pair(iter->first,id);
-      pair<atomId_t,atomId_t> topRange = make_pair(id+1,iter->second);
+      range<atomId_t> bottomRange = makeRange(iter->first,id);
+      range<atomId_t> topRange = makeRange(id+1,iter->last);
       // remove this range
       atomIdPool.erase(iter);
-      if(bottomRange.first<bottomRange.second){
+      if(bottomRange.first<bottomRange.last){
         atomIdPool.insert(bottomRange);
       }
-      if(topRange.first<topRange.second){
+      if(topRange.first<topRange.last){
         atomIdPool.insert(topRange);
       }
@@ -301,7 +301,7 @@
     atomIdPool_t::iterator next = iter;
     next++;
-    if(next!=atomIdPool.end() && (next->first==iter->second)){
+    if(next!=atomIdPool.end() && (next->first==iter->last)){
       // merge the two ranges
-      pair<atomId_t,atomId_t> newRange = make_pair(iter->first,next->second);
+      range<atomId_t> newRange = makeRange(iter->first,next->last);
       atomIdPool.erase(iter);
       atomIdPool.erase(next);
@@ -317,5 +317,5 @@
     atomIdPool_t::iterator iter = atomIdPool.end();
     iter--;
-    if(iter->second==currAtomId){
+    if(iter->last==currAtomId){
       currAtomId=iter->first;
       atomIdPool.erase(iter);
@@ -333,8 +333,8 @@
     moleculeIdPool_t::iterator iter=moleculeIdPool.begin();
     moleculeId_t id = iter->first;
-    pair<moleculeId_t,moleculeId_t> newRange = make_pair(id+1,iter->second);
+    range<moleculeId_t> newRange = makeRange(id+1,iter->last);
     // we wont use this iterator anymore, so we don't care about invalidating
     moleculeIdPool.erase(iter);
-    if(newRange.first<newRange.second){
+    if(newRange.first<newRange.last){
       moleculeIdPool.insert(newRange);
     }
@@ -346,5 +346,5 @@
 
 void World::releaseMoleculeId(moleculeId_t id){
-  moleculeIdPool.insert(make_pair(id,id+1));
+  moleculeIdPool.insert(makeRange(id,id+1));
   defragMoleculeIdPool();
 }
@@ -352,6 +352,6 @@
 bool World::reserveMoleculeId(moleculeId_t id){
   if(id>=currMoleculeId ){
-    pair<moleculeId_t,moleculeId_t> newRange = make_pair(currMoleculeId,id);
-    if(newRange.first<newRange.second){
+    range<moleculeId_t> newRange = makeRange(currMoleculeId,id);
+    if(newRange.first<newRange.last){
       moleculeIdPool.insert(newRange);
     }
@@ -362,21 +362,21 @@
   // look for a range that matches the request
   for(moleculeIdPool_t::iterator iter=moleculeIdPool.begin();iter!=moleculeIdPool.end();++iter){
-    if(iter->first>id){
+    if(iter->isBefore(id)){
       // we have coverd all available ranges... nothing to be found here
       break;
     }
     // no need to check first, since it has to be <=id, since otherwise we would have broken out
-    if(iter->second > id){
+    if(!iter->isBeyond(id)){
       // we found a matching range... get the id from this range
 
       // split up this range at the point of id
-      pair<moleculeId_t,moleculeId_t> bottomRange = make_pair(iter->first,id);
-      pair<moleculeId_t,moleculeId_t> topRange = make_pair(id+1,iter->second);
+      range<moleculeId_t> bottomRange = makeRange(iter->first,id);
+      range<moleculeId_t> topRange = makeRange(id+1,iter->last);
       // remove this range
       moleculeIdPool.erase(iter);
-      if(bottomRange.first<bottomRange.second){
+      if(bottomRange.first<bottomRange.last){
         moleculeIdPool.insert(bottomRange);
       }
-      if(topRange.first<topRange.second){
+      if(topRange.first<topRange.last){
         moleculeIdPool.insert(topRange);
       }
@@ -400,7 +400,7 @@
     moleculeIdPool_t::iterator next = iter;
     next++;
-    if(next!=moleculeIdPool.end() && (next->first==iter->second)){
+    if(next!=moleculeIdPool.end() && (next->first==iter->last)){
       // merge the two ranges
-      pair<moleculeId_t,moleculeId_t> newRange = make_pair(iter->first,next->second);
+      range<moleculeId_t> newRange = makeRange(iter->first,next->last);
       moleculeIdPool.erase(iter);
       moleculeIdPool.erase(next);
@@ -416,5 +416,5 @@
     moleculeIdPool_t::iterator iter = moleculeIdPool.end();
     iter--;
-    if(iter->second==currMoleculeId){
+    if(iter->last==currMoleculeId){
       currMoleculeId=iter->first;
       moleculeIdPool.erase(iter);
Index: src/World.hpp
===================================================================
--- src/World.hpp	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/World.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -24,4 +24,5 @@
 #include "Patterns/Singleton.hpp"
 #include "Patterns/ObservedContainer.hpp"
+#include "Helpers/Range.hpp"
 
 // include config.h
@@ -360,5 +361,5 @@
   AtomSet atoms;
   AtomSet selectedAtoms;
-  typedef std::set<std::pair<atomId_t, atomId_t> > atomIdPool_t;
+  typedef std::set<range<atomId_t> > atomIdPool_t;
   /**
    * stores the pool for all available AtomIds below currAtomId
@@ -373,5 +374,5 @@
   MoleculeSet molecules;
   MoleculeSet selectedMolecules;
-  typedef std::set<std::pair<moleculeId_t, moleculeId_t> > moleculeIdPool_t;
+  typedef std::set<range<atomId_t> > moleculeIdPool_t;
   /**
    * stores the pool for all available AtomIds below currAtomId
Index: src/config.cpp
===================================================================
--- src/config.cpp	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/config.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -1031,6 +1031,4 @@
 {
   bool result = true;
-  // bring MaxTypes up to date
-  mol->CountElements();
   const Matrix &domain = World::getInstance().getDomain().getM();
   ofstream * const output = new ofstream(filename, ios::out);
@@ -1138,5 +1136,5 @@
     *output << "IsAngstroem\t" << config::IsAngstroem << "\t# 0 - Bohr, 1 - Angstroem" << endl;
     *output << "RelativeCoord\t" << config::RelativeCoord << "\t# whether ion coordinates are relative (1) or absolute (0)" << endl;
-    *output << "MaxTypes\t" << mol->ElementCount <<  "\t# maximum number of different ion types" << endl;
+    *output << "MaxTypes\t" << mol->getElementCount() <<  "\t# maximum number of different ion types" << endl;
     *output << endl;
     result = result && mol->Checkout(output);
@@ -1533,6 +1531,4 @@
     mol->SetNameFromFilename(ConfigFileName);
     molecules->SimpleMultiMerge(mol, src, N);
-    mol->doCountAtoms();
-    mol->CountElements();
     //mol->CalculateOrbitals(*this);
     delete[](src);
Index: src/molecule.cpp
===================================================================
--- src/molecule.cpp	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/molecule.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -49,13 +49,9 @@
 molecule::molecule(const periodentafel * const teil) :
   Observable("molecule"),
-  elemente(teil),  MDSteps(0),  BondCount(0), ElementCount(0), NoNonHydrogen(0), NoNonBonds(0),
+  elemente(teil),  MDSteps(0),  BondCount(0), NoNonHydrogen(0), NoNonBonds(0),
   NoCyclicBonds(0), BondDistance(0.),  ActiveFlag(false), IndexNr(-1),
-  formula(this,boost::bind(&molecule::calcFormula,this),"formula"),
   AtomCount(this,boost::bind(&molecule::doCountAtoms,this),"AtomCount"), last_atom(0),  InternalPointer(atoms.begin())
 {
 
-  // other stuff
-  for(int i=MAX_ELEMENTS;i--;)
-    ElementsInMolecule[i] = 0;
   strcpy(name,World::getInstance().getDefaultName().c_str());
 };
@@ -101,21 +97,22 @@
 }
 
-const std::string molecule::getFormula(){
-  return *formula;
-}
-
-std::string molecule::calcFormula(){
-  std::map<atomicNumber_t,unsigned int> counts;
-  stringstream sstr;
-  periodentafel *periode = World::getInstance().getPeriode();
-  for (molecule::const_iterator iter = begin(); iter != end(); ++iter) {
-    counts[(*iter)->type->getNumber()]++;
-  }
-  std::map<atomicNumber_t,unsigned int>::reverse_iterator iter;
-  for(iter = counts.rbegin(); iter != counts.rend(); ++iter) {
-    atomicNumber_t Z = (*iter).first;
-    sstr << periode->FindElement(Z)->symbol << (*iter).second;
-  }
-  return sstr.str();
+const Formula &molecule::getFormula(){
+  return formula;
+}
+
+unsigned int molecule::getElementCount(){
+  return formula.getElementCount();
+}
+
+bool molecule::hasElement(const element *element) const{
+  return formula.hasElement(element);
+}
+
+bool molecule::hasElement(atomicNumber_t Z) const{
+  return formula.hasElement(Z);
+}
+
+bool molecule::hasElement(const string &shorthand) const{
+  return formula.hasElement(shorthand);
 }
 
@@ -210,7 +207,5 @@
     pointer->sort = &pointer->nr;
     if (pointer->type != NULL) {
-      if (ElementsInMolecule[pointer->type->Z] == 0)
-        ElementCount++;
-      ElementsInMolecule[pointer->type->Z]++; // increase number of elements
+      formula += pointer->type;
       if (pointer->type->Z != 1)
         NoNonHydrogen++;
@@ -651,5 +646,4 @@
 
   // copy values
-  copy->CountElements();
   if (hasBondStructure()) {  // if adjaceny list is present
     copy->BondDistance = BondDistance;
@@ -774,10 +768,5 @@
   ASSERT(pointer, "Null pointer passed to molecule::RemoveAtom().");
   OBSERVE;
-  if (ElementsInMolecule[pointer->type->Z] != 0)  { // this would indicate an error
-    ElementsInMolecule[pointer->type->Z]--;  // decrease number of atom of this element
-  } else
-    DoeLog(1) && (eLog()<< Verbose(1) << "Atom " << pointer->getName() << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl);
-  if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
-    ElementCount--;
+  formula-=pointer->type;
   RemoveBonds(pointer);
   erase(pointer);
@@ -793,10 +782,5 @@
   if (pointer == NULL)
     return false;
-  if (ElementsInMolecule[pointer->type->Z] != 0)  // this would indicate an error
-    ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element
-  else
-    DoeLog(1) && (eLog()<< Verbose(1) << "Atom " << pointer->getName() << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl);
-  if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
-    ElementCount--;
+  formula-=pointer->type;
   erase(pointer);
   return true;
@@ -871,5 +855,4 @@
 {
   int ElementNo[MAX_ELEMENTS], AtomNo[MAX_ELEMENTS];
-  CountElements();
 
   for (int i=0;i<MAX_ELEMENTS;++i) {
@@ -898,5 +881,4 @@
 {
   int ElementNo[MAX_ELEMENTS], AtomNo[MAX_ELEMENTS];
-  CountElements();
 
   if (output == NULL) {
@@ -940,5 +922,5 @@
 bool molecule::Checkout(ofstream * const output)  const
 {
-  return elemente->Checkout(output, ElementsInMolecule);
+  return formula.checkOut(output);
 };
 
@@ -998,18 +980,4 @@
 };
 
-/** Brings molecule::ElementCount and molecule::ElementsInMolecule up-to-date.
- */
-void molecule::CountElements()
-{
-  for(int i=MAX_ELEMENTS;i--;)
-    ElementsInMolecule[i] = 0;
-  ElementCount = 0;
-
-  SetIndexedArrayForEachAtomTo ( ElementsInMolecule, &element::Z, &Increment, 1);
-
-  for(int i=MAX_ELEMENTS;i--;)
-    ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);
-};
-
 /** Determines whether two molecules actually contain the same atoms and coordination.
  * \param *out output stream for debugging
@@ -1030,6 +998,4 @@
   /// first count both their atoms and elements and update lists thereby ...
   //Log() << Verbose(0) << "Counting atoms, updating list" << endl;
-  CountElements();
-  OtherMolecule->CountElements();
 
   /// ... and compare:
@@ -1041,22 +1007,10 @@
     } else Log() << Verbose(4) << "AtomCounts match: " << getAtomCount() << " == " << OtherMolecule->getAtomCount() << endl;
   }
-  /// -# ElementCount
+  /// -# Formula
   if (result) {
-    if (ElementCount != OtherMolecule->ElementCount) {
-      DoLog(4) && (Log() << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl);
+    if (formula != OtherMolecule->formula) {
+      DoLog(4) && (Log() << Verbose(4) << "Formulas don't match: " << formula << " == " << OtherMolecule->formula << endl);
       result = false;
-    } else Log() << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
-  }
-  /// -# ElementsInMolecule
-  if (result) {
-    for (flag=MAX_ELEMENTS;flag--;) {
-      //Log() << Verbose(5) << "Element " <<  flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;
-      if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])
-        break;
-    }
-    if (flag < MAX_ELEMENTS) {
-      DoLog(4) && (Log() << Verbose(4) << "ElementsInMolecule don't match." << endl);
-      result = false;
-    } else Log() << Verbose(4) << "ElementsInMolecule match." << endl;
+    } else Log() << Verbose(4) << "Formulas match: " << formula << " == " << OtherMolecule->formula << endl;
   }
   /// then determine and compare center of gravity for each molecule ...
Index: src/molecule.hpp
===================================================================
--- src/molecule.hpp	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/molecule.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -28,4 +28,5 @@
 #include "Patterns/ObservedIterator.hpp"
 #include "Patterns/Cacheable.hpp"
+#include "Formula.hpp"
 
 #include "Descriptors/MoleculeDescriptor_impl.hpp"
@@ -97,6 +98,4 @@
     //int AtomCount;          //!< number of atoms, brought up-to-date by CountAtoms()
     int BondCount;          //!< number of atoms, brought up-to-date by CountBonds()
-    int ElementCount;       //!< how many unique elements are therein
-    int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not
     mutable int NoNonHydrogen;  //!< number of non-hydrogen atoms in molecule
     mutable int NoNonBonds;     //!< number of non-hydrogen bonds in molecule
@@ -109,5 +108,5 @@
 
   private:
-    Cacheable<string> formula;
+    Formula formula;
     Cacheable<int>    AtomCount;
     moleculeId_t id;
@@ -135,6 +134,10 @@
   void setId(moleculeId_t);
   void setName(const std::string);
-  const std::string getFormula();
-  std::string calcFormula();
+  const Formula &getFormula();
+  unsigned int getElementCount();
+  bool hasElement(const element*) const;
+  bool hasElement(atomicNumber_t) const;
+  bool hasElement(const std::string&) const;
+
 
   iterator begin();
@@ -254,5 +257,4 @@
 
   /// Count and change present atoms' coordination.
-  void CountElements();
   bool CenterInBox();
   bool BoundInBox();
Index: src/molecule_dynamics.cpp
===================================================================
--- src/molecule_dynamics.cpp	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/molecule_dynamics.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -560,6 +560,4 @@
   ForceMatrix Force;
 
-  CountElements();  // make sure ElementsInMolecule is up to date
-
   const int AtomCount = getAtomCount();
   // check file
Index: src/moleculelist.cpp
===================================================================
--- src/moleculelist.cpp	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/moleculelist.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -597,5 +597,5 @@
       periodentafel::const_iterator elemIter;
       for(elemIter=periode->begin();elemIter!=periode->end();++elemIter){
-        if ((*ListRunner)->ElementsInMolecule[(*elemIter).first]) { // if this element got atoms
+        if ((*ListRunner)->hasElement((*elemIter).first)) { // if this element got atoms
           for(molecule::iterator atomIter = (*ListRunner)->begin(); atomIter !=(*ListRunner)->end();++atomIter){
             if ((*atomIter)->type->getNumber() == (*elemIter).first) {
@@ -689,5 +689,4 @@
 
     // also calculate necessary orbitals
-    (*ListRunner)->CountElements(); // this is a bugfix, atoms should shoulds actually be added correctly to this fragment
     //(*ListRunner)->CalculateOrbitals(*World::getInstance().getConfig);
 
Index: src/periodentafel.cpp
===================================================================
--- src/periodentafel.cpp	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/periodentafel.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -125,5 +125,5 @@
  * \return pointer to element
  */
-element * const periodentafel::FindElement(const char * const shorthand) const
+element * const periodentafel::FindElement(const string &shorthand) const
 {
   element *res = 0;
@@ -205,27 +205,4 @@
     for(const_iterator iter=elements.begin(); iter !=elements.end();++iter){
       result = result && (*iter).second->Output(output);
-    }
-    return result;
-  } else
-    return false;
-};
-
-/** Prints period table to given stream.
- * \param *output output stream
- * \param *checkliste elements table for this molecule
- */
-bool periodentafel::Checkout(ostream * const output, const int * const checkliste) 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=elements.begin(); iter!=elements.end();++iter){
-      if (((*iter).first < MAX_ELEMENTS) && (checkliste[(*iter).first])) {
-        (*iter).second->No = No;
-        result = result && (*iter).second->Checkout(output, No++, checkliste[(*iter).first]);
-      }
     }
     return result;
Index: src/periodentafel.hpp
===================================================================
--- src/periodentafel.hpp	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/periodentafel.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -11,4 +11,5 @@
 #include <iosfwd>
 #include <map>
+#include <string>
 
 #include "unittests/periodentafelTest.hpp"
@@ -47,5 +48,5 @@
   void CleanupPeriodtable();
   element * const FindElement(atomicNumber_t) const;
-  element * const FindElement(const char * const shorthand) const;
+  element * const FindElement(const std::string &shorthand) const;
   element * const AskElement() const;
   element * const EnterElement();
@@ -56,5 +57,4 @@
   reverse_iterator rend();
   bool Output(std::ostream * const output) const;
-  bool Checkout(std::ostream * const output, const int * const checkliste) const;
   bool LoadPeriodentafel(const char * const path);
   bool StorePeriodentafel(const char * const path) const;
Index: src/unittests/FormulaUnittest.cpp
===================================================================
--- src/unittests/FormulaUnittest.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
+++ src/unittests/FormulaUnittest.cpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -0,0 +1,197 @@
+/*
+ * FormulaUnittest.cpp
+ *
+ *  Created on: Jul 21, 2010
+ *      Author: crueger
+ */
+
+#include "FormulaUnittest.hpp"
+
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+#include <iostream>
+
+#include "Formula.hpp"
+#include "World.hpp"
+
+#ifdef HAVE_TESTRUNNER
+#include "UnitTestMain.hpp"
+#endif /*HAVE_TESTRUNNER*/
+
+using namespace std;
+
+CPPUNIT_TEST_SUITE_REGISTRATION( FormulaUnittest );
+
+void FormulaUnittest::setUp(){}
+void FormulaUnittest::tearDown(){
+  World::purgeInstance();
+}
+
+void FormulaUnittest::baseTest(){
+  Formula formula;
+  CPPUNIT_ASSERT_EQUAL(formula.getElementCount(),(unsigned int)0);
+  CPPUNIT_ASSERT(formula.begin()==formula.end());
+
+  // test some one letter element names
+  formula += "H";
+  CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)1);
+  CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula.getElementCount(),(unsigned int)1);
+  CPPUNIT_ASSERT(formula.begin()!=formula.end());
+  formula += "H";
+  CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)2);
+  CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula.getElementCount(),(unsigned int)1);
+  CPPUNIT_ASSERT(formula.begin()!=formula.end());
+  formula += "O";
+  CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)2);
+  CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)1);
+  CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula.getElementCount(),(unsigned int)2);
+  CPPUNIT_ASSERT(formula.begin()!=formula.end());
+
+  // test copy constructor
+  Formula formula2=formula;
+  CPPUNIT_ASSERT_EQUAL(formula2["H"],(unsigned int)2);
+  CPPUNIT_ASSERT_EQUAL(formula2["O"],(unsigned int)1);
+  CPPUNIT_ASSERT_EQUAL(formula2["C"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula2.getElementCount(),(unsigned int)2);
+  CPPUNIT_ASSERT(formula2.begin()!=formula2.end());
+
+  // test Assignment operator
+  formula2=Formula();
+  CPPUNIT_ASSERT_EQUAL(formula2["H"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula2["O"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula2["C"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula2.getElementCount(),(unsigned int)0);
+  CPPUNIT_ASSERT(formula2.begin()==formula2.end());
+
+  // test comparison
+  CPPUNIT_ASSERT(formula!=formula2);
+  Formula formula3;
+  formula3 += "H";
+  formula3 += "H";
+  formula3 += "O";
+  CPPUNIT_ASSERT(formula==formula3);
+
+  // inequality
+  formula3 += "O";
+  CPPUNIT_ASSERT(formula!=formula3);
+
+  // after removing it should be fine again
+  formula3 -= "O";
+  CPPUNIT_ASSERT(formula==formula3);
+
+  // add something from the far end, to test resizing
+  formula3 += "Rh";
+  CPPUNIT_ASSERT(formula!=formula3);
+  formula3 -= "Rh";
+  CPPUNIT_ASSERT(formula==formula3);
+
+  // removal of elements
+  formula -= "H";
+  CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)1);
+  CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)1);
+  CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula.getElementCount(),(unsigned int)2);
+  CPPUNIT_ASSERT(formula.begin()!=formula.end());
+
+  formula -= "O";
+  CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)1);
+  CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula.getElementCount(),(unsigned int)1);
+  CPPUNIT_ASSERT(formula.begin()!=formula.end());
+
+  formula -= "H";
+  CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  CPPUNIT_ASSERT_EQUAL(formula.getElementCount(),(unsigned int)0);
+  CPPUNIT_ASSERT(formula.begin()==formula.end());
+}
+
+void FormulaUnittest::parseTest(){
+  {
+    Formula formula("");
+    CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)0);
+    CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)0);
+    CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)0);
+    CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  }
+  {
+    Formula formula("H");
+    CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)1);
+    CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)0);
+    CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)0);
+    CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  }
+  {
+    Formula formula("H2");
+    CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)2);
+    CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)0);
+    CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)0);
+    CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  }
+  {
+    Formula formula("H2O");
+    CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)2);
+    CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)1);
+    CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)0);
+    CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  }
+  {
+    Formula formula("CH3COOH");
+    CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)4);
+    CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)2);
+    CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)2);
+    CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  }
+  {
+    Formula formula("CH3COONa");
+    CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)3);
+    CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)2);
+    CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)2);
+    CPPUNIT_ASSERT_EQUAL(formula["Na"],(unsigned int)1);
+    CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  }
+  {
+    Formula formula("NaCH3COO");
+    CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)3);
+    CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)2);
+    CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)2);
+    CPPUNIT_ASSERT_EQUAL(formula["Na"],(unsigned int)1);
+    CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  }
+  {
+    Formula formula("Na2CO3");
+    CPPUNIT_ASSERT_EQUAL(formula["H"],(unsigned int)0);
+    CPPUNIT_ASSERT_EQUAL(formula["O"],(unsigned int)3);
+    CPPUNIT_ASSERT_EQUAL(formula["C"],(unsigned int)1);
+    CPPUNIT_ASSERT_EQUAL(formula["Na"],(unsigned int)2);
+    CPPUNIT_ASSERT_EQUAL(formula["He"],(unsigned int)0);
+  }
+  {
+    CPPUNIT_ASSERT_THROW(Formula formula("74107"),ParseError);
+    CPPUNIT_ASSERT_THROW(Formula formula("  "),ParseError);
+    CPPUNIT_ASSERT_THROW(Formula formula("nAcL"),ParseError);
+    CPPUNIT_ASSERT_THROW(Formula formula("NAcL"),ParseError);
+    CPPUNIT_ASSERT_THROW(Formula formula("Na Cl"),ParseError);
+    CPPUNIT_ASSERT_THROW(Formula formula("1NaCl"),ParseError);
+    CPPUNIT_ASSERT_THROW(Formula formula("Mag"),ParseError);
+  }
+
+
+}
Index: src/unittests/FormulaUnittest.hpp
===================================================================
--- src/unittests/FormulaUnittest.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
+++ src/unittests/FormulaUnittest.hpp	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -0,0 +1,28 @@
+/*
+ * FormulaUnittest.hpp
+ *
+ *  Created on: Jul 21, 2010
+ *      Author: crueger
+ */
+
+#ifndef FORMULAUNITTEST_HPP_
+#define FORMULAUNITTEST_HPP_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class FormulaUnittest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( FormulaUnittest );
+  CPPUNIT_TEST ( baseTest );
+  CPPUNIT_TEST ( parseTest );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void baseTest();
+  void parseTest();
+};
+
+#endif /* FORMULAUNITTEST_HPP_ */
Index: src/unittests/Makefile.am
===================================================================
--- src/unittests/Makefile.am	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ src/unittests/Makefile.am	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -21,4 +21,5 @@
   CacheableTest \
   CountBondsUnitTest \
+  FormulaUnittest \
   GSLMatrixSymmetricUnitTest \
   GSLMatrixUnitTest \
@@ -66,4 +67,5 @@
   CacheableTest.cpp \
   CountBondsUnitTest.cpp \
+  FormulaUnittest.cpp \
   gslmatrixsymmetricunittest.cpp \
   gslmatrixunittest.cpp \
@@ -102,4 +104,5 @@
   CacheableTest.hpp \
   CountBondsUnitTest.hpp \
+  FormulaUnittest.hpp \
   gslmatrixsymmetricunittest.hpp \
   gslmatrixunittest.hpp \
@@ -158,4 +161,7 @@
 CountBondsUnitTest_LDADD = ${ALLLIBS}
 
+FormulaUnittest_SOURCES = UnitTestMain.cpp FormulaUnittest.cpp FormulaUnittest.hpp
+FormulaUnittest_LDADD = ${ALLLIBS}
+
 GSLMatrixSymmetricUnitTest_SOURCES = UnitTestMain.cpp gslmatrixsymmetricunittest.cpp gslmatrixsymmetricunittest.hpp
 GSLMatrixSymmetricUnitTest_LDADD = ${GSLLIBS}
Index: test_all.sh
===================================================================
--- test_all.sh	(revision b1a39b130749accaf2cd0103a233cf86ae75ba4d)
+++ test_all.sh	(revision 9106c6402d2f9b63468cbd99c4736296903cc4cb)
@@ -129,5 +129,5 @@
   echo "Valgrinding";
   retval=0;
-  for test in molecuilder/src/unittests/*
+  for test in src/unittests/*
   do
     if [ -x "$test" ]
@@ -150,4 +150,8 @@
 
   echo "Testing with \"$2\"";
+  echo "" >> $logfile;
+  echo "" >> $logfile;
+  echo "" >> $logfile;
+  echo "Testing with \"$2\"" >> $logfile;
 
   echo -n "  Configuring: " >> $outfile;
