Boost logo

Boost Users :

Subject: [Boost-users] [math] finding c such that w1/c+...+wn/c < math::tools::max_value<T>()
From: er (erwann.rogard_at_[hidden])
Date: 2009-04-17 20:12:20


Hi All,

A little while back the following code was suggested to find c such that
(x/c)+(y/c) <= C = math::tools::max_value<T>()

         template<class T>//
         static T scale_to_max(
             const T& x,
             const T& y
         ) {
             double max = (std::numeric_limits<T>::max)();
             if(x > max - y) {
                 double c = x/max + y/max;
                 while(!boost::math::isinf(x/c + y/c)) {
                     c = boost::math::float_prior(c);
                 }
                 while(boost::math::isinf(x/c + y/c)) {
                     c = boost::math::float_next(c);
                 }
                 return(c);
             } else {
                 return(static_cast<T>(1));
             }
         }

I'm now trying to generalize this i.e. find c such that w1/c+...+wn/c <= C:
1) split w1,..,wn into maximal size, sum less than C, subgroups.
2) apply scale_to_max iteratively over adjacent groups.
This does not always suceed (see example at the bottom). Any suggestion
would be appreciated.

*.hpp

template<typename T>
class scale_sum_to_max{
     public:
     typedef void result_type;
     typedef T argument_type;

     scale_sum_to_max(T cum_sum):cum_sum_(cum_sum),c_(static_cast<T>(1)){}
     scale_sum_to_max():cum_sum_(static_cast<T>(0)),c_(static_cast<T>(1)){}

     void operator()(T x){
         if(
             math::isinf(scaled_sum()+(x/c_))
         ){
             T s =
                 scale_to_max(
                     scaled_sum(),
                     x/c_
                 );
             cum_sum_ /= s;
             c_ *= s;
             BOOST_ASSERT(!math::isinf(cum_sum_+x/c_));
         }
         cum_sum_ += x/c_;
     }

     T scaling_factor()const{ return c_; }
     T scaled_sum()const{ return cum_sum_; }

     private:
         T cum_sum_;
         T c_;
};

     template<typename T>
     class finite_sums{
         typedef std::vector<T> cont_t;
         public:
             typedef void result_type;
             typedef T argument_type;

         finite_sums()
         {
             coll_.push_back(static_cast<T>(0));
         }
         void operator()(T x){
             if(math::isinf(sum()+x)){
                 coll_.push_back(x);
             }else{
                 coll_.back() += x;
             }
         }
         const cont_t&
         collected()const{
             return coll_;
         }

         T scaling_factor()const{
             return for_each(
                 begin(coll_),
                 end(coll_),
                 scale_sum_to_max<T>()
             ).scaling_factor();
         }

         private:
         T sum()const{ return coll_.back(); }
         cont_t coll_;
     };

}}

*.cpp

     typedef double value_t;
     typedef std::vector<value_t> vec_t;

     const unsigned n = 1e5; //n = 1e3 OK
     value_t w = math::tools::max_value<value_t>();
     w /= 2;

     vec_t vec_w(n,w);

     value_t scaling_factor =
         for_each(
             begin(vec_w),
             end(vec_w),
             math_limit::finite_sums<value_t>()
         ).scaling_factor();
//assertion failed: (!math::isinf(cum_sum_+x/c_))


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net