/* * SetValue.hpp * * Created on: Jun 25, 2012 * Author: heber */ #ifndef SETVALUE_HPP_ #define SETVALUE_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include #include #include "IndexSet.hpp" #include "IndexSetContainer.hpp" #include "ZeroInstance.hpp" #include "CodePatterns/Cacheable.hpp" #include "CodePatterns/Log.hpp" #include "CodePatterns/Observer/Observable.hpp" class SetValueTest; template class SetValue : public Observable { //!> grant unit test access to allow setting static function friend class SetValueTest; //!> grant OrthogonalSummation access to static lookup functions template friend class OrthogonalSummation; //!> grant Summation access to static lookup functions template friend class Summation; public: typedef boost::shared_ptr< SetValue > ptr; SetValue(const IndexSet_ptr &_indices, const T &_value) : Observable("SubsetValue"), value(_value), indices(_indices), contribution(this,boost::bind(&SetValue::calcSum,this),"contribution") {}; SetValue & operator+=(const SetValue &other) { if (indices->contains(*other.indices)) { OBSERVE; value += other.value; } return *this; } SetValue & operator-=(const SetValue &other) { if (indices->contains(*other.indices)) { OBSERVE; value -= other.value; } return *this; } const IndexSet_ptr& getIndexSet() const { return indices; } /** Getter for the contribution. * * @return contribution */ const T getContribution() const { return *contribution; } /** Getter for the value. * * @return value */ const T getValue() const { return value; } /** Setter for the value. * * This function is observed to notify all sets that contain us of a change. * * @param _value value to set value to */ void setValue(const T& _value) { OBSERVE; value = _value; } private: // prohibit copies SetValue(const SetValue &_value); private: //!> static lookup function to get to the subsets static boost::function< IndexSetContainer::ptr & (const IndexSet_ptr &)> lookupSubset; //!> static lookup function to get the SetValue for a specific IndexSet static boost::function< typename SetValue::ptr & (const IndexSet_ptr &)> lookupValue; /** Calculates the contribution for this subset. * * We calculate by value minus the summed contributions(!) from all subsets * of this subset. If the value is ZeroInstance however, we set its * contribution to zero, as it is designated thereby as not contributing. * * \note This is internal function that is bound to the Cacheable contribution. * * @return value minus the summed contribution's from all subsets */ const T calcSum() { LOG(2, "DEBUG: Summing up contribution for " << *indices << "."); // we initialize with value T result = getValue(); // ZeroInstance() is a specific value, if set, this subset does not contribute if (result != ZeroInstance()) { // compare directly, not numerically! // then subtract contributions from all subsets const IndexSetContainer::ptr &container = lookupSubset(indices); if (container) { const IndexSetContainer::Container_t &subsets = container->getContainer(); for (IndexSetContainer::Container_t::const_iterator iter = subsets.begin(); iter != subsets.end(); ++iter) { LOG(3, "DEBUG: Current subset is " << **iter << "."); // NOTE: our subset is not contained in the number of subsets typename SetValue::ptr ptr = lookupValue(*iter); if (ptr) result -= ptr->getContribution(); else ELOG(1, "Cannot find " << **iter << " via lookup."); } } else { ELOG(1, "Cannot find subsets for " << *indices << " via lookup."); } } // else we return ZeroInstance() as contribution return result; } private: //!> value associated with this IndexSet T value; //!> shared_ptr to the index set IndexSet_ptr indices; //!> stores the (orthogonal) contribution for this SubsetValue Cacheable contribution; }; template boost::function< IndexSetContainer::ptr & (const IndexSet_ptr &)> SetValue::lookupSubset = NULL; template boost::function< typename SetValue::ptr & (const IndexSet_ptr &)> SetValue::lookupValue = NULL; #endif /* SETVALUE_HPP_ */