Boost logo

Ublas :

From: Gunter Winkler (guwi17_at_[hidden])
Date: 2006-11-15 04:00:26


On Tuesday 14 November 2006 17:52, Manoj Rajagopalan wrote:
> 1. Is there already a function in ublas that does something like this? I
> looked up the documentation and some of the ublas code but I couldn't
> locate anything but I feel such a requirement should be fairly common so
> I may have missed something.

I currently use this code:

namespace functor {

  template <class T>
  struct log
  {
  public:
    typedef T value_type;
    typedef T result_type;
    
    static
    result_type apply(const value_type& x)
    {
      return std::log(x);
    }

  };

  template <class T>
  struct maximum
  {
  public:
    typedef T value_type;
    typedef T result_type;
    
    static
    result_type apply(const value_type& x, const value_type& y)
    {
      return std::max(x, y);
    }
    static
    result_type initial_value()
    {
      return (-std::numeric_limits<result_type>::max());
    }
    static
    void update(result_type& t, const value_type& x)
    {
      if (x>t) t=x;
    }
  };

  template <class T>
  struct minimum
  {
  public:
    typedef T value_type;
    typedef T result_type;
    
    static
    result_type apply(const value_type& x, const value_type& y)
    {
      return std::min(x, y);
    }
    static
    result_type initial_value()
    {
      return (std::numeric_limits<result_type>::max());
    }
    static
    void update(result_type& t, const value_type& x)
    {
      if (x<t) t=x;
    }
  };

  template <class T>
  struct log_minimum
  {
  public:
    typedef T value_type;
    typedef T result_type;
    
    static
    result_type initial_value()
    {
      return std::log(std::numeric_limits<result_type>::max());
    }
    static
    void update(result_type& t, const value_type& x)
    {
      if ( (x>0) && (std::log(x)<t) ) t = std::log(x);
    }
  };

}

  // //////////// general vector to scalar expression /////////

  // pitfalls:
  // the result is OP::initial_value() for "empty" sparse vectors,
  // zero elements that are not stored may be ignored
  template<class T, class OP>
  struct general_vector_scalar_unary:
    public vector_scalar_unary_functor<T> {
    typedef typename vector_scalar_unary_functor<T>::size_type size_type;
    typedef typename vector_scalar_unary_functor<T>::difference_type difference_type;
    typedef typename vector_scalar_unary_functor<T>::value_type value_type;
    typedef typename vector_scalar_unary_functor<T>::result_type result_type;

    // general case, access by index
    template<class E>
    static BOOST_UBLAS_INLINE
    result_type apply (const vector_expression<E> &e) {
      result_type t = OP::initial_value();
      size_type size (e ().size ());
      for (size_type i = 0; i < size; ++ i)
        OP::update(t, e () (i));
      return t;
    }
    // Dense case
    template<class I>
    static BOOST_UBLAS_INLINE
    result_type apply (difference_type size, I it) {
      result_type t = OP::initial_value();
      while (-- size >= 0)
        OP::update(t, *it), ++ it;
      return t;
    }
    // Sparse case
    template<class I>
    static BOOST_UBLAS_INLINE
    result_type apply (I it, const I &it_end) {
      result_type t = OP::initial_value();
      while (it != it_end)
        OP::update(t, *it), ++ it;
      return t;
    }
  };

  // max v = max (v [i], i=1..N)
  template<class E>
  BOOST_UBLAS_INLINE
  typename vector_scalar_unary_traits<E, general_vector_scalar_unary<typename E::value_type, functor::maximum<typename E::value_type> > >::result_type
  max (const vector_expression<E> &e) {
    typedef typename vector_scalar_unary_traits<E, general_vector_scalar_unary<typename E::value_type, functor::maximum<typename E::value_type> > >::expression_type expression_type;
    return expression_type (e ());
  }
  // min v = min (v [i], i=1..N)
  template<class E>
  BOOST_UBLAS_INLINE
  typename vector_scalar_unary_traits<E, general_vector_scalar_unary<typename E::value_type, functor::minimum<typename E::value_type> > >::result_type
  min (const vector_expression<E> &e) {
    typedef typename vector_scalar_unary_traits<E, general_vector_scalar_unary<typename E::value_type, functor::minimum<typename E::value_type> > >::expression_type expression_type;
    return expression_type (e ());
  }
  // log_min v = min ( log(v [i]), i=1..N if v[i]>0 )
  template<class E>
  BOOST_UBLAS_INLINE
  typename vector_scalar_unary_traits<E, general_vector_scalar_unary<typename E::value_type, functor::log_minimum<typename E::value_type> > >::result_type
  log_min (const vector_expression<E> &e) {
    typedef typename vector_scalar_unary_traits<E, general_vector_scalar_unary<typename E::value_type, functor::log_minimum<typename E::value_type> > >::expression_type expression_type;
    return expression_type (e ());
  }

  // //////////// general vector unary expression /////////////

  // (op v) [i] = op( v [i] )
  template<class OP, class E>
  BOOST_UBLAS_INLINE
  typename vector_unary_traits<E, OP>::result_type
  apply_to_all (const vector_expression<E> &e, const OP& op = OP()) {
    typedef typename vector_unary_traits<E, OP>::expression_type expression_type;
    return expression_type (e ());
  }

--8x---------------------------

usage:
cout << apply_to_all<functor::log<double> >( pwc ) << endl;

HTH
Gunter