<commit_before>#ifndef ROBUST_PCA_HPP__
#define ROBUST_PCA_HPP__

//Released under the boost licence v1.0

/*!@file
 * Robust PCA functions, following the paper of Soren Hausberg
 * @todo add proper licence

 *
 * @note These implementations assume the existence of boost somewhere. Currently, it is just used for
 * computing the norms of differences and to generate some random data (which is now TR1 and C++0X).
 */

#include <boost/numeric/conversion/bounds.hpp>
#include <boost/numeric/ublas/vector_expression.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/mersenne_twister.hpp>

namespace robust_pca
{

  //! Wrapper object for infinity/max @f$\ell_\infty@f$ norm.
  struct norm_infinity
  {
    template <class vector_t>
    double operator()(vector_t const& v) const
    {
      return boost::numeric::ublas::norm_inf(v);
    }
  };

  //! Returns the square of the @f$\ell_2@f$ norm.
  struct norm_ell2_square
  {
    template <class vector_t>
    double operator()(vector_t const& v) const
    {
      double acc(0);
      for(typename vector_t::const_iterator it(v.begin()), ite(v.end());
          it < ite;
          ++it)
      {
        typename vector_t::const_reference v(*it);
        acc += v * v;
      }
      return acc;
    }
  };

  //! Returns the @f$\ell_2@f$ norm of a vector.
  struct norm2
  {
    typedef double result_type;
    norm_ell2_square op;
    template <class vector_t>
    result_type operator()(vector_t const& v) const
    {
      return std::sqrt(op(v));
    }
  };

  /* @brief Checks the convergence of a numerical scheme.
   *
   * @tparam data_t should be default constructible and constructible with one parameter.
   *
   * The convergence is assumed when the norm between two subsequent states is less than a certain @f$epsilon@f$.
   */
  template <class data_t, class norm_t = norm_infinity>
  struct convergence_check
  {
    const double epsilon;
    norm_t norm_comparaison;
    data_t previous_state;
    convergence_check(double epsilon_) :
      epsilon(epsilon_),
      previous_state(std::numeric_limits<double>::max())
    {}

    bool operator()(data_t const& current_state)
    {
      return norm_comparaison(current_state - previous_state) < epsilon;
    }

  };

  // some issues with the random number generator
  const double fVeryBigButStillComputable = 1E10;
  const double fVerySmallButStillComputable = -1E10;

  /*@brief Used to initialize the initial guess to some random data.
   *
   *@tparam data_t the type of the data returned. It should model a vector:
   * - default, copy constructible and constructible with a size
   * - has a member @c size returning a value of type @c data_t::Size_type
   * - has a field @c data_t::Value_type
   */
  template <
    class data_t,
    class random_distribution_t =
      typename boost::mpl::if_<
        boost::is_floating_point<typename data_t::value_type>,
        boost::random::uniform_real_distribution<typename data_t::value_type>,
        boost::random::uniform_int_distribution<typename data_t::value_type>
      >::type,
    class random_number_generator_t = boost::random::mt19937
  >
  struct random_data_generator
  {
    typedef typename data_t::value_type value_type;
    mutable random_number_generator_t rng;
    value_type min_bound;
    value_type max_bound;

    //! Default construction
    random_data_generator(
      value_type min_value_ = boost::numeric::bounds<value_type>::lowest(),
      value_type max_value_ = boost::numeric::bounds<value_type>::highest()) :
      rng(),
      min_bound(min_value_),
      max_bound(max_value_)
    {}

    //! Constructs from the specified seeded random number generator.
    random_data_generator(
      random_number_generator_t const &r,
      value_type min_value_ = boost::numeric::bounds<value_type>::lowest(),
      value_type max_value_ = boost::numeric::bounds<value_type>::highest()) :
      rng(r),
      min_bound(min_value_),
      max_bound(max_value_)
    {}

    data_t operator()(const data_t& v) const
    {
      data_t out(v.size());
      random_distribution_t dist(min_bound, max_bound);
      for(typename data_t::size_type i(0), j(v.size()); i < j; i++)
      {
        out[i] = dist(rng);
      }
      return out;
    }
  };

  /*!@brief Robust PCA subspace algorithm
   *
   * This class implements the robust PCA using the Grassmanian averaging. This is the naive implementation which is
   * suitable for small datasets.
   * @todo add reference
   * @author Soren Hausberg, Raffi Enficiaud
   */
  template <class data_t, class norm_2_t = norm2>
  struct robust_pca_impl
  {
  private:
    random_data_generator<data_t> random_init_op;
    norm_2_t norm_op;

  public:
    robust_pca_impl() : random_init_op(fVerySmallButStillComputable, fVeryBigButStillComputable)
    {}

    /*! Performs the computation of the current subspace on the elements given by the two iterators.
     *  @tparam it_t an input iterator to vectors. Each element pointed by the underlying iterator should be iterable and
     *   should provide a vector.
     *  @tparam it_norm_t an output iterator on weights/norms of the vectors. The output elements should be numerical (norm output)
     *
     * @param[in] initial_guess if provided, the initial vector will be initialized to this value.
     *
     * @pre
     * - @c !(it >= ite)
     * - all the vectors given by the iterators pair should be of the same size (no check is performed).
     */
    template <class it_t, class it_norm_t>
    bool batch_process(it_t it, it_t const ite, it_norm_t it_norm_out, data_t const * initial_guess = 0)
    {
      // add some log information
      if(it >= ite)
      {
        return false;
      }

      it_norm_t it_norm_out_copy(it_norm_out);
      for(it_t it_copy(it); it_copy != ite; ++it_copy, ++it_norm_out_copy)
      {
        *it_norm_out_copy = norm_op(*it_copy);
      }

      // the first element is used for the init guess because for dynamic std::vector like element, the size is needed.
      data_t mu(initial_guess != 0 ? *initial_guess : random_init_op(*it));

      // normalizing
      typename norm_2_t::result_type norm_mu(norm_op(mu));
      mu /= norm_mu;

      return true;
    }

    /*!@brief Performs the projection of the data on the space orthogonal to the current subspace
     *
     * After having found the current subspace, all the data should be projected onto the orthogonal subspace
     * of the current state.
     */
    template <class it_t>
    bool projection_onto_subspace(it_t it, it_t const ite) const
    {
      return true;
    }
  };

}

#endif /* ROBUST_PCA_HPP__ */
<commit_msg>advances<commit_after>#ifndef ROBUST_PCA_HPP__
#define ROBUST_PCA_HPP__

//Released under the boost licence v1.0

/*!@file
 * Robust PCA functions, following the paper of Soren Hausberg
 * @todo add proper licence

 *
 * @note These implementations assume the existence of boost somewhere. Currently, it is just used for
 * computing the norms of differences and to generate some random data (which is now TR1 and C++0X).
 */

#include <boost/numeric/conversion/bounds.hpp>
#include <boost/numeric/ublas/vector_expression.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/mersenne_twister.hpp>

namespace robust_pca
{

  //! Wrapper object for infinity/max @f$\ell_\infty@f$ norm.
  struct norm_infinity
  {
    template <class vector_t>
    double operator()(vector_t const& v) const
    {
      return boost::numeric::ublas::norm_inf(v);
    }
  };

  //! Returns the square of the @f$\ell_2@f$ norm.
  struct norm_ell2_square
  {
    template <class vector_t>
    double operator()(vector_t const& v) const
    {
      double acc(0);
      for(typename vector_t::const_iterator it(v.begin()), ite(v.end());
          it < ite;
          ++it)
      {
        typename vector_t::const_reference v(*it);
        acc += v * v;
      }
      return acc;
    }
  };

  //! Returns the @f$\ell_2@f$ norm of a vector.
  struct norm2
  {
    typedef double result_type;
    norm_ell2_square op;
    template <class vector_t>
    result_type operator()(vector_t const& v) const
    {
      return std::sqrt(op(v));
    }
  };

  /* @brief Checks the convergence of a numerical scheme.
   *
   * @tparam data_t should be default constructible and constructible with one parameter.
   *
   * The convergence is assumed when the norm between two subsequent states is less than a certain @f$epsilon@f$.
   */
  template <class data_t, class norm_t = norm_infinity>
  struct convergence_check
  {
    const double epsilon;
    norm_t norm_comparaison;
    data_t previous_state;
    convergence_check(data_t const& prev, double epsilon_ = 1E-5) :
      epsilon(epsilon_),
      previous_state(prev)
    {}

    bool operator()(data_t const& current_state)
    {
      bool ret = norm_comparaison(current_state - previous_state) < epsilon;
      previous_state = current_state;
      return ret;
    }

  };

  // some issues with the random number generator
  const double fVeryBigButStillComputable = 1E10;
  const double fVerySmallButStillComputable = -1E10;

  /*@brief Used to initialize the initial guess to some random data.
   *
   *@tparam data_t the type of the data returned. It should model a vector:
   * - default, copy constructible and constructible with a size
   * - has a member @c size returning a value of type @c data_t::Size_type
   * - has a field @c data_t::Value_type
   */
  template <
    class data_t,
    class random_distribution_t =
      typename boost::mpl::if_<
        boost::is_floating_point<typename data_t::value_type>,
        boost::random::uniform_real_distribution<typename data_t::value_type>,
        boost::random::uniform_int_distribution<typename data_t::value_type>
      >::type,
    class random_number_generator_t = boost::random::mt19937
  >
  struct random_data_generator
  {
    typedef typename data_t::value_type value_type;
    mutable random_number_generator_t rng;
    value_type min_bound;
    value_type max_bound;

    //! Default construction
    random_data_generator(
      value_type min_value_ = boost::numeric::bounds<value_type>::lowest(),
      value_type max_value_ = boost::numeric::bounds<value_type>::highest()) :
      rng(),
      min_bound(min_value_),
      max_bound(max_value_)
    {}

    //! Constructs from the specified seeded random number generator.
    random_data_generator(
      random_number_generator_t const &r,
      value_type min_value_ = boost::numeric::bounds<value_type>::lowest(),
      value_type max_value_ = boost::numeric::bounds<value_type>::highest()) :
      rng(r),
      min_bound(min_value_),
      max_bound(max_value_)
    {}

    data_t operator()(const data_t& v) const
    {
      data_t out(v.size());
      random_distribution_t dist(min_bound, max_bound);
      for(typename data_t::size_type i(0), j(v.size()); i < j; i++)
      {
        out[i] = dist(rng);
      }
      return out;
    }
  };

  /*!@brief Robust PCA subspace algorithm
   *
   * This class implements the robust PCA using the Grassmanian averaging. This is the naive implementation which is
   * suitable for small datasets.
   * @todo add reference
   * @author Soren Hausberg, Raffi Enficiaud
   */
  template <class data_t, class norm_2_t = norm2>
  struct robust_pca_impl
  {
  private:
    random_data_generator<data_t> random_init_op;
    norm_2_t norm_op;

  public:
    robust_pca_impl() : random_init_op(fVerySmallButStillComputable, fVeryBigButStillComputable)
    {}

    /*! Performs the computation of the current subspace on the elements given by the two iterators.
     *  @tparam it_t an input iterator to vectors. Each element pointed by the underlying iterator should be iterable and
     *   should provide a vector.
     *  @tparam it_norm_t an output iterator on weights/norms of the vectors. The output elements should be numerical (norm output)
     *
     * @param[in] initial_guess if provided, the initial vector will be initialized to this value.
     *
     * @pre
     * - @c !(it >= ite)
     * - all the vectors given by the iterators pair should be of the same size (no check is performed).
     */
    template <class it_t, class it_norm_t>
    bool batch_process(it_t it, it_t const ite, it_norm_t it_norm_out, data_t const * initial_guess = 0)
    {
      // add some log information
      if(it >= ite)
      {
        return false;
      }

      it_norm_t it_norm_out_copy(it_norm_out);
      for(it_t it_copy(it); it_copy != ite; ++it_copy, ++it_norm_out_copy)
      {
        *it_norm_out_copy = norm_op(*it_copy);
      }

      // the first element is used for the init guess because for dynamic std::vector like element, the size is needed.
      data_t mu(initial_guess != 0 ? *initial_guess : random_init_op(*it));

      // normalizing
      typename norm_2_t::result_type norm_mu(norm_op(mu));
      mu /= norm_mu;

      for(int current_dimension = 0; current_dimension < mu.size(); current_dimension++)
      {
        //data_t previous_mu(mu);
        convergence_check<data_t> convergence_op(mu);
        for(int iterations = 0; iterations < 1000; iterations ++)
        {
          for(it_t it_copy(it); it_copy != ite; ++it_copy)
          {
            bool sign = boost::numeric::ublas::inner_prod(*it_copy, mu) < 0;
          }

          if(convergence_op(mu))
            break;
        }
      }

      return true;
    }

    /*!@brief Performs the projection of the data on the space orthogonal to the current subspace
     *
     * After having found the current subspace, all the data should be projected onto the orthogonal subspace
     * of the current state.
     */
    template <class it_t>
    bool projection_onto_subspace(it_t it, it_t const ite) const
    {
      return true;
    }
  };

}

#endif /* ROBUST_PCA_HPP__ */
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file  print.hpp
//----------------------------------------------------------------------------
/// \brief This file contains implementation of printing functions.
//----------------------------------------------------------------------------
// Copyright (c) 2014 Serge Aleynikov <saleyn@gmail.com>
// Created: 2014-09-05
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2014 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#ifndef _UTXX_PRINT_HPP_
#define _UTXX_PRINT_HPP_

#include <string>
#include <type_traits>
#include <cstdarg>
#include <iomanip>
#include <utxx/scope_exit.hpp>
#include <utxx/compiler_hints.hpp>
#include <utxx/convert.hpp>
#include <utxx/error.hpp>

namespace utxx {

/// Output a float to stream formatted with fixed precision
struct fixed {
    fixed(double a_val, int a_digits, int a_precision, char a_fill = ' ')
        : m_value(a_val), m_digits(a_digits), m_precision(a_precision)
        , m_fill(a_fill)
    {}

    inline friend std::ostream& operator<<(std::ostream& out, const fixed& f) {
        return out << std::fixed << std::setfill(f.m_fill)
                   << std::setw(f.m_digits)
                   << std::setprecision(f.m_precision) << f.m_value;
    }

    double value()     const { return m_value;     }
    int    digits()    const { return m_digits;    }
    int    precision() const { return m_precision; }
    char   fill()      const { return m_fill;      }

private:
    double m_value;
    int    m_digits;
    int    m_precision;
    char   m_fill;
};

namespace detail {
    template <size_t N = 256, class Alloc = std::allocator<char>>
    class basic_buffered_print : public Alloc
    {
        mutable char*   m_begin; // mutable so that we can write '\0' in c_str()
        char*           m_pos;
        char*           m_end;
        char            m_data[N];

        void deallocate() {
            if (m_begin == m_data) return;
            Alloc::deallocate(m_begin, max_size());
        }

        void do_print(char a) { reserve(1); *m_pos++ = a; }
        void do_print(bool a) {
            reserve(5);
            if (a) { memcpy(m_pos, "true", 4); m_pos += 4; }
            else   { memcpy(m_pos, "false",5); m_pos += 5; }
        }
        void do_print(long a) {
            reserve(20);
            itoa(a, out(m_pos));
        }
        void do_print(int a) {
            reserve(10);
            itoa(a, out(m_pos));
        }
        void do_print(double a)
        {
            int n = ftoa_left(a, m_pos, capacity(), 6, true);
            if (unlikely(n < 0)) {
                n = snprintf(m_pos, capacity(), "%.6f", a);
                if (unlikely(m_pos + n > m_end)) {
                    reserve(n);
                    snprintf(m_pos, capacity(), "%.6f", a);
                }
            }
            m_pos += n;
        }
        void do_print(fixed&& a) {
            reserve(a.digits());
            ftoa_right(a.value(), m_pos, a.digits(), a.precision(), a.fill());
            m_pos += a.digits();
        }
        void do_print(const char* a) {
            const char* p = strchr(a, '\0');
            assert(p);
            size_t n = p - a;
            reserve(n);
            memcpy(m_pos, a, n);
            m_pos += n;
        }
        void do_print(std::string&& a) {
            size_t n = a.size();
            reserve(n);
            memcpy(m_pos, a.c_str(), n);
            m_pos += n;
        }
        void do_print(const std::string& a) {
            size_t n = a.size();
            reserve(n);
            memcpy(m_pos, a.c_str(), n);
            m_pos += n;
        }
        template <int M>
        void do_print(const char (&a)[M]) {
            size_t n = strnlen(a, M);
            reserve(n);
            memcpy(m_pos, a, n);
            m_pos += n;
        }
        template <int M>
        void do_print(const std::array<char, M>& a) {
            size_t n = strnlen(a.data(), M);
            reserve(n);
            memcpy(m_pos, a, n);
            m_pos += n;
        }
        template <typename T>
        void do_print(typename std::enable_if<std::is_pointer<T>::value, T&&>::type a) {
            auto  x = reinterpret_cast<uint64_t>(a);
            char* p = m_pos + 2;
            auto  n = capacity() - 2;
            int   i = itoa_hex(x, p, n);
            if (unlikely(i > n)) {
                reserve(i + 2);
                p = m_pos + 2;
                i = itoa_hex(x, p, n);
            }
            *m_pos++ = '0';
            *m_pos++ = 'x';
            m_pos   += i;
        }
        template <class T>
        void do_print(const T& a) {
            std::stringstream s; s << a;
            print(s.str());
        }
    public:
        explicit basic_buffered_print(const Alloc& a_alloc = Alloc())
            : Alloc(a_alloc)
            , m_begin(m_data)
            , m_pos(m_begin)
            , m_end(m_begin + sizeof(m_data)-1)
        {}

        ~basic_buffered_print() {
            deallocate();
        }

        void reset() {
            deallocate();
            m_begin = m_pos = m_data;
            m_end   = m_begin + sizeof(m_data)-1;
        }

        std::string to_string() const { return std::string(m_begin, size()); }
        const char* str()       const { return m_begin; }
        char*       str()             { return m_begin; }
        const char* c_str()     const { *m_pos = '\0'; return m_begin; }
        size_t      size()      const { return m_pos - m_begin;  }
        const char* pos()       const { return m_pos;            }
        char*&      pos()             { return m_pos;            }
        void        pos(const char* p){ assert(p <= m_end); m_pos = p; }
        size_t      max_size()  const { return m_end - m_begin;  }
        size_t      capacity()  const { return m_end - m_pos;    }

        /// Reserve space in the buffer to hold additional \a a_sz bytes
        void reserve(size_t a_sz) {
            if (m_pos + a_sz <= m_end) return;
            auto sz = max_size() + a_sz + N;
            char* p = Alloc::allocate(sz);
            strncpy(p, m_begin, size());
            m_pos   = p + size();
            m_end   = p + sz;
            if (m_begin != m_data)  delete [] m_begin;
            m_begin = p;
        }

        /// Call this function if the content of this buffer needs to be
        /// written to by external snprintf:
        /// \code
        /// size_t c = buf.capacity();
        /// size_t n = snprintf(buf.str(), c, "%s", "Something");
        /// if (n > c) {
        ///     // write didn't fit - repeat
        ///     buf.reserve(n);
        ///     n = snprintf(buf.str(), c, "%s", "Something");
        /// }
        /// buf.advance(n);
        /// \endcode
        void advance(size_t n) { m_pos += n; }

        // Terminal case of template recursion:
        void print() {}

        template <class T, class... Args>
        void print(T&& a, Args&&... args) {
            do_print(std::move(a));
            print(std::forward<Args>(args)...);
        }

        void sprint(const char* a_str, size_t a_size) {
            reserve(a_size);
            memcpy(m_pos, a_str, a_size);
            m_pos += a_size;
        }

        int vprintf(const char* a_fmt, va_list a_args) {
            int n = vsnprintf(m_pos, capacity(), a_fmt, a_args);
            if (n < 0)
                return n;
            if (size_t(n) > capacity()) {
                reserve(n);
                n = vsnprintf(m_pos, capacity(), a_fmt, a_args);
            }
            m_pos += n;
            return n;
        }

        int printf(const char* a_fmt, ...) {
            va_list args; va_start(args, a_fmt);
            UTXX_SCOPE_EXIT([&args]() { va_end(args); });
            return this->vprintf(a_fmt, args);
        }

        template <typename T>
        basic_buffered_print<N>& operator<< (T&& a) {
            print(std::forward<T>(a));
            return *this;
        }
    };
}

/// Analogous to sprintf, but returns an std::string instead
template <int SizeHint = 256>
std::string print_string(const char* fmt, ...) {
    va_list args; va_start(args, fmt);
    UTXX_SCOPE_EXIT([&args]() { va_end(args); });

    std::string buf;
    buf.resize(SizeHint);
    int n = vsnprintf(const_cast<char*>(buf.c_str()), buf.capacity(), fmt, args);

    if (unlikely(n < 0))
        throw io_error(errno, "print_string(): error formatting arguments");

    buf.resize(n);

    if (unlikely(n > SizeHint)) // String didn't fit - redo
        vsnprintf(const_cast<char*>(buf.c_str()), buf.capacity(), fmt, args);
    return buf;
}

/// Print arguments to string.
/// This function is a faster alternative to printf and std::stringstream.
template <class... Args>
std::string print(Args&&... args) {
    detail::basic_buffered_print<> b;
    b.print(std::forward<Args>(args)...);
    return b.to_string();
}

using buffered_print = detail::basic_buffered_print<>;

} // namespace utxx

#endif //_UTXX_PRINT_HPP_
<commit_msg>Bug fix in print.hpp<commit_after>//----------------------------------------------------------------------------
/// \file  print.hpp
//----------------------------------------------------------------------------
/// \brief This file contains implementation of printing functions.
//----------------------------------------------------------------------------
// Copyright (c) 2014 Serge Aleynikov <saleyn@gmail.com>
// Created: 2014-09-05
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2014 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#ifndef _UTXX_PRINT_HPP_
#define _UTXX_PRINT_HPP_

#include <string>
#include <type_traits>
#include <cstdarg>
#include <iomanip>
#include <utxx/scope_exit.hpp>
#include <utxx/compiler_hints.hpp>
#include <utxx/convert.hpp>
#include <utxx/error.hpp>

namespace utxx {

/// Output a float to stream formatted with fixed precision
struct fixed {
    fixed(double a_val, int a_digits, int a_precision, char a_fill = ' ')
        : m_value(a_val), m_digits(a_digits), m_precision(a_precision)
        , m_fill(a_fill)
    {}

    inline friend std::ostream& operator<<(std::ostream& out, const fixed& f) {
        return out << std::fixed << std::setfill(f.m_fill)
                   << std::setw(f.m_digits)
                   << std::setprecision(f.m_precision) << f.m_value;
    }

    double value()     const { return m_value;     }
    int    digits()    const { return m_digits;    }
    int    precision() const { return m_precision; }
    char   fill()      const { return m_fill;      }

private:
    double m_value;
    int    m_digits;
    int    m_precision;
    char   m_fill;
};

namespace detail {
    template <size_t N = 256, class Alloc = std::allocator<char>>
    class basic_buffered_print : public Alloc
    {
        mutable char*   m_begin; // mutable so that we can write '\0' in c_str()
        char*           m_pos;
        char*           m_end;
        char            m_data[N];

        void deallocate() {
            if (m_begin == m_data) return;
            Alloc::deallocate(m_begin, max_size());
        }

        void do_print(char a) { reserve(1); *m_pos++ = a; }
        void do_print(bool a) {
            reserve(5);
            if (a) { memcpy(m_pos, "true", 4); m_pos += 4; }
            else   { memcpy(m_pos, "false",5); m_pos += 5; }
        }
        void do_print(long a) {
            reserve(20);
            itoa(a, out(m_pos));
        }
        void do_print(int a) {
            reserve(10);
            itoa(a, out(m_pos));
        }
        void do_print(double a)
        {
            int n = ftoa_left(a, m_pos, capacity(), 6, true);
            if (unlikely(n < 0)) {
                n = snprintf(m_pos, capacity(), "%.6f", a);
                if (unlikely(m_pos + n > m_end)) {
                    reserve(n);
                    snprintf(m_pos, capacity(), "%.6f", a);
                }
            }
            m_pos += n;
        }
        void do_print(fixed&& a) {
            reserve(a.digits());
            ftoa_right(a.value(), m_pos, a.digits(), a.precision(), a.fill());
            m_pos += a.digits();
        }
        void do_print(const char* a) {
            const char* p = strchr(a, '\0');
            assert(p);
            size_t n = p - a;
            reserve(n);
            memcpy(m_pos, a, n);
            m_pos += n;
        }
        void do_print(std::string&& a) {
            size_t n = a.size();
            reserve(n);
            memcpy(m_pos, a.c_str(), n);
            m_pos += n;
        }
        void do_print(const std::string& a) {
            size_t n = a.size();
            reserve(n);
            memcpy(m_pos, a.c_str(), n);
            m_pos += n;
        }
        template <int M>
        void do_print(const char (&a)[M]) {
            size_t n = strnlen(a, M);
            reserve(n);
            memcpy(m_pos, a, n);
            m_pos += n;
        }
        template <int M>
        void do_print(const std::array<char, M>& a) {
            size_t n = strnlen(a.data(), M);
            reserve(n);
            memcpy(m_pos, a, n);
            m_pos += n;
        }
        template <typename T>
        void do_print(typename std::enable_if<std::is_pointer<T>::value, T&&>::type a) {
            auto  x = reinterpret_cast<uint64_t>(a);
            char* p = m_pos + 2;
            auto  n = capacity() - 2;
            int   i = itoa_hex(x, p, n);
            if (unlikely(i > n)) {
                reserve(i + 2);
                p = m_pos + 2;
                i = itoa_hex(x, p, n);
            }
            *m_pos++ = '0';
            *m_pos++ = 'x';
            m_pos   += i;
        }
        template <class T>
        void do_print(const T& a) {
            std::stringstream s; s << a;
            print(s.str());
        }
    public:
        explicit basic_buffered_print(const Alloc& a_alloc = Alloc())
            : Alloc(a_alloc)
            , m_begin(m_data)
            , m_pos(m_begin)
            , m_end(m_begin + sizeof(m_data)-1)
        {}

        ~basic_buffered_print() {
            deallocate();
        }

        void reset() {
            deallocate();
            m_begin = m_pos = m_data;
            m_end   = m_begin + sizeof(m_data)-1;
        }

        std::string to_string() const { return std::string(m_begin, size()); }
        const char* str()       const { return m_begin; }
        char*       str()             { return m_begin; }
        const char* c_str()     const { *m_pos = '\0'; return m_begin; }
        size_t      size()      const { return m_pos - m_begin;  }
        const char* pos()       const { return m_pos;            }
        char*&      pos()             { return m_pos;            }
        void        pos(const char* p){ assert(p <= m_end); m_pos = const_cast<char*>(p); }
        size_t      max_size()  const { return m_end - m_begin;  }
        size_t      capacity()  const { return m_end - m_pos;    }

        /// Reserve space in the buffer to hold additional \a a_sz bytes
        void reserve(size_t a_sz) {
            if (m_pos + a_sz <= m_end) return;
            auto sz = max_size() + a_sz + N;
            char* p = Alloc::allocate(sz);
            strncpy(p, m_begin, size());
            m_pos   = p + size();
            m_end   = p + sz;
            if (m_begin != m_data)  delete [] m_begin;
            m_begin = p;
        }

        /// Call this function if the content of this buffer needs to be
        /// written to by external snprintf:
        /// \code
        /// size_t c = buf.capacity();
        /// size_t n = snprintf(buf.str(), c, "%s", "Something");
        /// if (n > c) {
        ///     // write didn't fit - repeat
        ///     buf.reserve(n);
        ///     n = snprintf(buf.str(), c, "%s", "Something");
        /// }
        /// buf.advance(n);
        /// \endcode
        void advance(size_t n) { m_pos += n; }

        // Terminal case of template recursion:
        void print() {}

        template <class T, class... Args>
        void print(T&& a, Args&&... args) {
            do_print(std::move(a));
            print(std::forward<Args>(args)...);
        }

        void sprint(const char* a_str, size_t a_size) {
            reserve(a_size);
            memcpy(m_pos, a_str, a_size);
            m_pos += a_size;
        }

        int vprintf(const char* a_fmt, va_list a_args) {
            int n = vsnprintf(m_pos, capacity(), a_fmt, a_args);
            if (n < 0)
                return n;
            if (size_t(n) > capacity()) {
                reserve(n);
                n = vsnprintf(m_pos, capacity(), a_fmt, a_args);
            }
            m_pos += n;
            return n;
        }

        int printf(const char* a_fmt, ...) {
            va_list args; va_start(args, a_fmt);
            UTXX_SCOPE_EXIT([&args]() { va_end(args); });
            return this->vprintf(a_fmt, args);
        }

        template <typename T>
        basic_buffered_print<N>& operator<< (T&& a) {
            print(std::forward<T>(a));
            return *this;
        }
    };
}

/// Analogous to sprintf, but returns an std::string instead
template <int SizeHint = 256>
std::string print_string(const char* fmt, ...) {
    va_list args; va_start(args, fmt);
    UTXX_SCOPE_EXIT([&args]() { va_end(args); });

    std::string buf;
    buf.resize(SizeHint);
    int n = vsnprintf(const_cast<char*>(buf.c_str()), buf.capacity(), fmt, args);

    if (unlikely(n < 0))
        throw io_error(errno, "print_string(): error formatting arguments");

    buf.resize(n);

    if (unlikely(n > SizeHint)) // String didn't fit - redo
        vsnprintf(const_cast<char*>(buf.c_str()), buf.capacity(), fmt, args);
    return buf;
}

/// Print arguments to string.
/// This function is a faster alternative to printf and std::stringstream.
template <class... Args>
std::string print(Args&&... args) {
    detail::basic_buffered_print<> b;
    b.print(std::forward<Args>(args)...);
    return b.to_string();
}

using buffered_print = detail::basic_buffered_print<>;

} // namespace utxx

#endif //_UTXX_PRINT_HPP_
<|endoftext|>


<commit_before><commit_msg>remove virtual qualifier from a bunch of VCL ListBox methods<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkPixelRef.h"
#include "include/core/SkSurface.h"
#include "include/private/SkImageInfoPriv.h"
#include "src/codec/SkColorTable.h"
#include "src/core/SkCompressedDataUtils.h"
#include "src/core/SkConvertPixels.h"
#include "src/core/SkImagePriv.h"
#include "src/core/SkTLazy.h"
#include "src/image/SkImage_Base.h"
#include "src/shaders/SkBitmapProcShader.h"

#if SK_SUPPORT_GPU
#include "include/gpu/GrContext.h"
#include "src/gpu/GrTextureAdjuster.h"
#include "src/gpu/SkGr.h"
#endif

// fixes https://bug.skia.org/5096
static bool is_not_subset(const SkBitmap& bm) {
    SkASSERT(bm.pixelRef());
    SkISize dim = SkISize::Make(bm.pixelRef()->width(), bm.pixelRef()->height());
    SkASSERT(dim != bm.dimensions() || bm.pixelRefOrigin().isZero());
    return dim == bm.dimensions();
}

class SkImage_Raster : public SkImage_Base {
public:
    static bool ValidArgs(const SkImageInfo& info, size_t rowBytes, size_t* minSize) {
        const int maxDimension = SK_MaxS32 >> 2;

        if (info.width() <= 0 || info.height() <= 0) {
            return false;
        }
        if (info.width() > maxDimension || info.height() > maxDimension) {
            return false;
        }
        if ((unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType) {
            return false;
        }
        if ((unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) {
            return false;
        }

        if (kUnknown_SkColorType == info.colorType()) {
            return false;
        }
        if (!info.validRowBytes(rowBytes)) {
            return false;
        }

        size_t size = info.computeByteSize(rowBytes);
        if (SkImageInfo::ByteSizeOverflowed(size)) {
            return false;
        }

        if (minSize) {
            *minSize = size;
        }
        return true;
    }

    SkImage_Raster(const SkImageInfo&, sk_sp<SkData>, size_t rb,
                   uint32_t id = kNeedNewImageUniqueID);
    ~SkImage_Raster() override;

    bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY,
                      CachingHint) const override;
    bool onPeekPixels(SkPixmap*) const override;
    const SkBitmap* onPeekBitmap() const override { return &fBitmap; }

#if SK_SUPPORT_GPU
    GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState,
                               SkScalar scaleAdjust[2]) const override;
#endif

    bool getROPixels(SkBitmap*, CachingHint) const override;
    sk_sp<SkImage> onMakeSubset(GrRecordingContext*, const SkIRect&) const override;

    SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }

    bool onAsLegacyBitmap(SkBitmap*) const override;

    SkImage_Raster(const SkBitmap& bm, bool bitmapMayBeMutable = false)
            : INHERITED(bm.info(),
                        is_not_subset(bm) ? bm.getGenerationID() : (uint32_t)kNeedNewImageUniqueID)
            , fBitmap(bm) {
        SkASSERT(bitmapMayBeMutable || fBitmap.isImmutable());
    }

    sk_sp<SkImage> onMakeColorTypeAndColorSpace(GrRecordingContext*,
                                                SkColorType, sk_sp<SkColorSpace>) const override;

    sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const override;

    bool onIsValid(GrContext* context) const override { return true; }
    void notifyAddedToRasterCache() const override {
        // We explicitly DON'T want to call INHERITED::notifyAddedToRasterCache. That ties the
        // lifetime of derived/cached resources to the image. In this case, we only want cached
        // data (eg mips) tied to the lifetime of the underlying pixelRef.
        SkASSERT(fBitmap.pixelRef());
        fBitmap.pixelRef()->notifyAddedToCache();
    }

#if SK_SUPPORT_GPU
    GrSurfaceProxyView refPinnedView(GrRecordingContext* context,
                                     uint32_t* uniqueID) const override;
    bool onPinAsTexture(GrContext*) const override;
    void onUnpinAsTexture(GrContext*) const override;
#endif

private:
    SkBitmap fBitmap;

#if SK_SUPPORT_GPU
    mutable GrSurfaceProxyView fPinnedView;
    mutable int32_t fPinnedCount = 0;
    mutable uint32_t fPinnedUniqueID = 0;
#endif

    typedef SkImage_Base INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

static void release_data(void* addr, void* context) {
    SkData* data = static_cast<SkData*>(context);
    data->unref();
}

SkImage_Raster::SkImage_Raster(const SkImageInfo& info, sk_sp<SkData> data, size_t rowBytes,
                               uint32_t id)
        : INHERITED(info, id) {
    void* addr = const_cast<void*>(data->data());

    fBitmap.installPixels(info, addr, rowBytes, release_data, data.release());
    fBitmap.setImmutable();
}

SkImage_Raster::~SkImage_Raster() {
#if SK_SUPPORT_GPU
    SkASSERT(!fPinnedView);  // want the caller to have manually unpinned
#endif
}

bool SkImage_Raster::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
                                  int srcX, int srcY, CachingHint) const {
    SkBitmap shallowCopy(fBitmap);
    return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
}

bool SkImage_Raster::onPeekPixels(SkPixmap* pm) const {
    return fBitmap.peekPixels(pm);
}

bool SkImage_Raster::getROPixels(SkBitmap* dst, CachingHint) const {
    *dst = fBitmap;
    return true;
}

#if SK_SUPPORT_GPU
GrSurfaceProxyView SkImage_Raster::refView(GrRecordingContext* context, GrSamplerState params,
                                           SkScalar scaleAdjust[2]) const {
    if (!context) {
        return {};
    }

    uint32_t uniqueID;
    if (GrSurfaceProxyView view = this->refPinnedView(context, &uniqueID)) {
        GrTextureAdjuster adjuster(context, std::move(view), fBitmap.info().colorInfo(),
                                   fPinnedUniqueID);
        return adjuster.viewForParams(params, scaleAdjust);
    }

    return GrRefCachedBitmapView(context, fBitmap, params, scaleAdjust);
}
#endif

#if SK_SUPPORT_GPU

GrSurfaceProxyView SkImage_Raster::refPinnedView(GrRecordingContext*, uint32_t* uniqueID) const {
    if (fPinnedView) {
        SkASSERT(fPinnedCount > 0);
        SkASSERT(fPinnedUniqueID != 0);
        *uniqueID = fPinnedUniqueID;
        return fPinnedView;
    }
    return {};
}

bool SkImage_Raster::onPinAsTexture(GrContext* ctx) const {
    if (fPinnedView) {
        SkASSERT(fPinnedCount > 0);
        SkASSERT(fPinnedUniqueID != 0);
    } else {
        SkASSERT(fPinnedCount == 0);
        SkASSERT(fPinnedUniqueID == 0);
        fPinnedView =
                GrRefCachedBitmapView(ctx, fBitmap, GrSamplerState::Filter::kNearest, nullptr);
        if (!fPinnedView) {
            return false;
        }
        SkASSERT(fPinnedView.asTextureProxy());
        fPinnedUniqueID = fBitmap.getGenerationID();
    }
    // Note: we only increment if the texture was successfully pinned
    ++fPinnedCount;
    return true;
}

void SkImage_Raster::onUnpinAsTexture(GrContext* ctx) const {
    // Note: we always decrement, even if fPinnedTexture is null
    SkASSERT(fPinnedCount > 0);
    SkASSERT(fPinnedUniqueID != 0);

    if (0 == --fPinnedCount) {
        fPinnedView = GrSurfaceProxyView();
        fPinnedUniqueID = 0;
    }
}
#endif

sk_sp<SkImage> SkImage_Raster::onMakeSubset(GrRecordingContext*, const SkIRect& subset) const {
    SkImageInfo info = fBitmap.info().makeDimensions(subset.size());
    SkBitmap bitmap;
    if (!bitmap.tryAllocPixels(info)) {
        return nullptr;
    }

    void* dst = bitmap.getPixels();
    void* src = fBitmap.getAddr(subset.x(), subset.y());
    if (!dst || !src) {
        SkDEBUGFAIL("SkImage_Raster::onMakeSubset with nullptr src or dst");
        return nullptr;
    }

    SkRectMemcpy(dst, bitmap.rowBytes(), src, fBitmap.rowBytes(), bitmap.rowBytes(),
                 subset.height());

    bitmap.setImmutable();
    return MakeFromBitmap(bitmap);
}

///////////////////////////////////////////////////////////////////////////////

sk_sp<SkImage> MakeRasterCopyPriv(const SkPixmap& pmap, uint32_t id) {
    size_t size;
    if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), &size) || !pmap.addr()) {
        return nullptr;
    }

    // Here we actually make a copy of the caller's pixel data
    sk_sp<SkData> data(SkData::MakeWithCopy(pmap.addr(), size));
    return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes(), id);
}

sk_sp<SkImage> SkImage::MakeRasterCopy(const SkPixmap& pmap) {
    return MakeRasterCopyPriv(pmap, kNeedNewImageUniqueID);
}

sk_sp<SkImage> SkImage::MakeRasterData(const SkImageInfo& info, sk_sp<SkData> data,
                                       size_t rowBytes) {
    size_t size;
    if (!SkImage_Raster::ValidArgs(info, rowBytes, &size) || !data) {
        return nullptr;
    }

    // did they give us enough data?
    if (data->size() < size) {
        return nullptr;
    }

    return sk_make_sp<SkImage_Raster>(info, std::move(data), rowBytes);
}

// TODO: this could be improved to decode and make use of the mipmap
// levels potentially present in the compressed data. For now, any
// mipmap levels are discarded.
sk_sp<SkImage> SkImage::MakeRasterFromCompressed(sk_sp<SkData> data,
                                                 int width, int height,
                                                 CompressionType type) {
    size_t expectedSize = SkCompressedFormatDataSize(type, { width, height }, false);
    if (!data || data->size() < expectedSize) {
        return nullptr;
    }

    SkAlphaType at = SkCompressionTypeIsOpaque(type) ? kOpaque_SkAlphaType
                                                     : kPremul_SkAlphaType;

    SkImageInfo ii = SkImageInfo::MakeN32(width, height, at);

    if (!SkImage_Raster::ValidArgs(ii, ii.minRowBytes(), nullptr)) {
        return nullptr;
    }

    SkBitmap bitmap;
    if (!bitmap.tryAllocPixels(ii)) {
        return nullptr;
    }

    if (!SkDecompress(std::move(data), { width, height }, type, &bitmap)) {
        return nullptr;
    }

    bitmap.setImmutable();
    return MakeFromBitmap(bitmap);
}

sk_sp<SkImage> SkImage::MakeFromRaster(const SkPixmap& pmap, RasterReleaseProc proc,
                                       ReleaseContext ctx) {
    size_t size;
    if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), &size) || !pmap.addr()) {
        return nullptr;
    }

    sk_sp<SkData> data(SkData::MakeWithProc(pmap.addr(), size, proc, ctx));
    return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes());
}

sk_sp<SkImage> SkMakeImageFromRasterBitmapPriv(const SkBitmap& bm, SkCopyPixelsMode cpm,
                                               uint32_t idForCopy) {
    if (kAlways_SkCopyPixelsMode == cpm || (!bm.isImmutable() && kNever_SkCopyPixelsMode != cpm)) {
        SkPixmap pmap;
        if (bm.peekPixels(&pmap)) {
            return MakeRasterCopyPriv(pmap, idForCopy);
        } else {
            return sk_sp<SkImage>();
        }
    }

    return sk_make_sp<SkImage_Raster>(bm, kNever_SkCopyPixelsMode == cpm);
}

sk_sp<SkImage> SkMakeImageFromRasterBitmap(const SkBitmap& bm, SkCopyPixelsMode cpm) {
    if (!SkImageInfoIsValid(bm.info()) || bm.rowBytes() < bm.info().minRowBytes()) {
        return nullptr;
    }

    return SkMakeImageFromRasterBitmapPriv(bm, cpm, kNeedNewImageUniqueID);
}

const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
    return ((const SkImage_Raster*)image)->getPixelRef();
}

bool SkImage_Raster::onAsLegacyBitmap(SkBitmap* bitmap) const {
    // When we're a snapshot from a surface, our bitmap may not be marked immutable
    // even though logically always we are, but in that case we can't physically share our
    // pixelref since the caller might call setImmutable() themselves
    // (thus changing our state).
    if (fBitmap.isImmutable()) {
        SkIPoint origin = fBitmap.pixelRefOrigin();
        bitmap->setInfo(fBitmap.info(), fBitmap.rowBytes());
        bitmap->setPixelRef(sk_ref_sp(fBitmap.pixelRef()), origin.x(), origin.y());
        return true;
    }
    return this->INHERITED::onAsLegacyBitmap(bitmap);
}

///////////////////////////////////////////////////////////////////////////////

sk_sp<SkImage> SkImage_Raster::onMakeColorTypeAndColorSpace(GrRecordingContext*,
                                                            SkColorType targetCT,
                                                            sk_sp<SkColorSpace> targetCS) const {
    SkPixmap src;
    SkAssertResult(fBitmap.peekPixels(&src));

    SkBitmap dst;
    dst.allocPixels(fBitmap.info().makeColorType(targetCT).makeColorSpace(targetCS));

    SkAssertResult(dst.writePixels(src));
    dst.setImmutable();
    return SkImage::MakeFromBitmap(dst);
}

sk_sp<SkImage> SkImage_Raster::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
    // TODO: If our bitmap is immutable, then we could theoretically create another image sharing
    // our pixelRef. That doesn't work (without more invasive logic), because the image gets its
    // gen ID from the bitmap, which gets it from the pixelRef.
    SkPixmap pixmap = fBitmap.pixmap();
    pixmap.setColorSpace(std::move(newCS));
    return SkImage::MakeRasterCopy(pixmap);
}
<commit_msg>images: Fix fuzzer crash for creating raster SkImage with invalid data.<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkPixelRef.h"
#include "include/core/SkSurface.h"
#include "include/private/SkImageInfoPriv.h"
#include "src/codec/SkColorTable.h"
#include "src/core/SkCompressedDataUtils.h"
#include "src/core/SkConvertPixels.h"
#include "src/core/SkImagePriv.h"
#include "src/core/SkTLazy.h"
#include "src/image/SkImage_Base.h"
#include "src/shaders/SkBitmapProcShader.h"

#if SK_SUPPORT_GPU
#include "include/gpu/GrContext.h"
#include "src/gpu/GrTextureAdjuster.h"
#include "src/gpu/SkGr.h"
#endif

// fixes https://bug.skia.org/5096
static bool is_not_subset(const SkBitmap& bm) {
    SkASSERT(bm.pixelRef());
    SkISize dim = SkISize::Make(bm.pixelRef()->width(), bm.pixelRef()->height());
    SkASSERT(dim != bm.dimensions() || bm.pixelRefOrigin().isZero());
    return dim == bm.dimensions();
}

class SkImage_Raster : public SkImage_Base {
public:
    static bool ValidArgs(const SkImageInfo& info, size_t rowBytes, size_t* minSize) {
        const int maxDimension = SK_MaxS32 >> 2;

        // TODO(mtklein): eliminate anything here that setInfo() has already checked.
        SkBitmap dummy;
        if (!dummy.setInfo(info, rowBytes)) {
            return false;
        }

        if (info.width() <= 0 || info.height() <= 0) {
            return false;
        }
        if (info.width() > maxDimension || info.height() > maxDimension) {
            return false;
        }
        if ((unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType) {
            return false;
        }
        if ((unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) {
            return false;
        }

        if (kUnknown_SkColorType == info.colorType()) {
            return false;
        }
        if (!info.validRowBytes(rowBytes)) {
            return false;
        }

        size_t size = info.computeByteSize(rowBytes);
        if (SkImageInfo::ByteSizeOverflowed(size)) {
            return false;
        }

        if (minSize) {
            *minSize = size;
        }
        return true;
    }

    SkImage_Raster(const SkImageInfo&, sk_sp<SkData>, size_t rb,
                   uint32_t id = kNeedNewImageUniqueID);
    ~SkImage_Raster() override;

    bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY,
                      CachingHint) const override;
    bool onPeekPixels(SkPixmap*) const override;
    const SkBitmap* onPeekBitmap() const override { return &fBitmap; }

#if SK_SUPPORT_GPU
    GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState,
                               SkScalar scaleAdjust[2]) const override;
#endif

    bool getROPixels(SkBitmap*, CachingHint) const override;
    sk_sp<SkImage> onMakeSubset(GrRecordingContext*, const SkIRect&) const override;

    SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }

    bool onAsLegacyBitmap(SkBitmap*) const override;

    SkImage_Raster(const SkBitmap& bm, bool bitmapMayBeMutable = false)
            : INHERITED(bm.info(),
                        is_not_subset(bm) ? bm.getGenerationID() : (uint32_t)kNeedNewImageUniqueID)
            , fBitmap(bm) {
        SkASSERT(bitmapMayBeMutable || fBitmap.isImmutable());
    }

    sk_sp<SkImage> onMakeColorTypeAndColorSpace(GrRecordingContext*,
                                                SkColorType, sk_sp<SkColorSpace>) const override;

    sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const override;

    bool onIsValid(GrContext* context) const override { return true; }
    void notifyAddedToRasterCache() const override {
        // We explicitly DON'T want to call INHERITED::notifyAddedToRasterCache. That ties the
        // lifetime of derived/cached resources to the image. In this case, we only want cached
        // data (eg mips) tied to the lifetime of the underlying pixelRef.
        SkASSERT(fBitmap.pixelRef());
        fBitmap.pixelRef()->notifyAddedToCache();
    }

#if SK_SUPPORT_GPU
    GrSurfaceProxyView refPinnedView(GrRecordingContext* context,
                                     uint32_t* uniqueID) const override;
    bool onPinAsTexture(GrContext*) const override;
    void onUnpinAsTexture(GrContext*) const override;
#endif

private:
    SkBitmap fBitmap;

#if SK_SUPPORT_GPU
    mutable GrSurfaceProxyView fPinnedView;
    mutable int32_t fPinnedCount = 0;
    mutable uint32_t fPinnedUniqueID = 0;
#endif

    typedef SkImage_Base INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

static void release_data(void* addr, void* context) {
    SkData* data = static_cast<SkData*>(context);
    data->unref();
}

SkImage_Raster::SkImage_Raster(const SkImageInfo& info, sk_sp<SkData> data, size_t rowBytes,
                               uint32_t id)
        : INHERITED(info, id) {
    void* addr = const_cast<void*>(data->data());

    fBitmap.installPixels(info, addr, rowBytes, release_data, data.release());
    fBitmap.setImmutable();
}

SkImage_Raster::~SkImage_Raster() {
#if SK_SUPPORT_GPU
    SkASSERT(!fPinnedView);  // want the caller to have manually unpinned
#endif
}

bool SkImage_Raster::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
                                  int srcX, int srcY, CachingHint) const {
    SkBitmap shallowCopy(fBitmap);
    return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
}

bool SkImage_Raster::onPeekPixels(SkPixmap* pm) const {
    return fBitmap.peekPixels(pm);
}

bool SkImage_Raster::getROPixels(SkBitmap* dst, CachingHint) const {
    *dst = fBitmap;
    return true;
}

#if SK_SUPPORT_GPU
GrSurfaceProxyView SkImage_Raster::refView(GrRecordingContext* context, GrSamplerState params,
                                           SkScalar scaleAdjust[2]) const {
    if (!context) {
        return {};
    }

    uint32_t uniqueID;
    if (GrSurfaceProxyView view = this->refPinnedView(context, &uniqueID)) {
        GrTextureAdjuster adjuster(context, std::move(view), fBitmap.info().colorInfo(),
                                   fPinnedUniqueID);
        return adjuster.viewForParams(params, scaleAdjust);
    }

    return GrRefCachedBitmapView(context, fBitmap, params, scaleAdjust);
}
#endif

#if SK_SUPPORT_GPU

GrSurfaceProxyView SkImage_Raster::refPinnedView(GrRecordingContext*, uint32_t* uniqueID) const {
    if (fPinnedView) {
        SkASSERT(fPinnedCount > 0);
        SkASSERT(fPinnedUniqueID != 0);
        *uniqueID = fPinnedUniqueID;
        return fPinnedView;
    }
    return {};
}

bool SkImage_Raster::onPinAsTexture(GrContext* ctx) const {
    if (fPinnedView) {
        SkASSERT(fPinnedCount > 0);
        SkASSERT(fPinnedUniqueID != 0);
    } else {
        SkASSERT(fPinnedCount == 0);
        SkASSERT(fPinnedUniqueID == 0);
        fPinnedView =
                GrRefCachedBitmapView(ctx, fBitmap, GrSamplerState::Filter::kNearest, nullptr);
        if (!fPinnedView) {
            return false;
        }
        SkASSERT(fPinnedView.asTextureProxy());
        fPinnedUniqueID = fBitmap.getGenerationID();
    }
    // Note: we only increment if the texture was successfully pinned
    ++fPinnedCount;
    return true;
}

void SkImage_Raster::onUnpinAsTexture(GrContext* ctx) const {
    // Note: we always decrement, even if fPinnedTexture is null
    SkASSERT(fPinnedCount > 0);
    SkASSERT(fPinnedUniqueID != 0);

    if (0 == --fPinnedCount) {
        fPinnedView = GrSurfaceProxyView();
        fPinnedUniqueID = 0;
    }
}
#endif

sk_sp<SkImage> SkImage_Raster::onMakeSubset(GrRecordingContext*, const SkIRect& subset) const {
    SkImageInfo info = fBitmap.info().makeDimensions(subset.size());
    SkBitmap bitmap;
    if (!bitmap.tryAllocPixels(info)) {
        return nullptr;
    }

    void* dst = bitmap.getPixels();
    void* src = fBitmap.getAddr(subset.x(), subset.y());
    if (!dst || !src) {
        SkDEBUGFAIL("SkImage_Raster::onMakeSubset with nullptr src or dst");
        return nullptr;
    }

    SkRectMemcpy(dst, bitmap.rowBytes(), src, fBitmap.rowBytes(), bitmap.rowBytes(),
                 subset.height());

    bitmap.setImmutable();
    return MakeFromBitmap(bitmap);
}

///////////////////////////////////////////////////////////////////////////////

sk_sp<SkImage> MakeRasterCopyPriv(const SkPixmap& pmap, uint32_t id) {
    size_t size;
    if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), &size) || !pmap.addr()) {
        return nullptr;
    }

    // Here we actually make a copy of the caller's pixel data
    sk_sp<SkData> data(SkData::MakeWithCopy(pmap.addr(), size));
    return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes(), id);
}

sk_sp<SkImage> SkImage::MakeRasterCopy(const SkPixmap& pmap) {
    return MakeRasterCopyPriv(pmap, kNeedNewImageUniqueID);
}

sk_sp<SkImage> SkImage::MakeRasterData(const SkImageInfo& info, sk_sp<SkData> data,
                                       size_t rowBytes) {
    size_t size;
    if (!SkImage_Raster::ValidArgs(info, rowBytes, &size) || !data) {
        return nullptr;
    }

    // did they give us enough data?
    if (data->size() < size) {
        return nullptr;
    }

    return sk_make_sp<SkImage_Raster>(info, std::move(data), rowBytes);
}

// TODO: this could be improved to decode and make use of the mipmap
// levels potentially present in the compressed data. For now, any
// mipmap levels are discarded.
sk_sp<SkImage> SkImage::MakeRasterFromCompressed(sk_sp<SkData> data,
                                                 int width, int height,
                                                 CompressionType type) {
    size_t expectedSize = SkCompressedFormatDataSize(type, { width, height }, false);
    if (!data || data->size() < expectedSize) {
        return nullptr;
    }

    SkAlphaType at = SkCompressionTypeIsOpaque(type) ? kOpaque_SkAlphaType
                                                     : kPremul_SkAlphaType;

    SkImageInfo ii = SkImageInfo::MakeN32(width, height, at);

    if (!SkImage_Raster::ValidArgs(ii, ii.minRowBytes(), nullptr)) {
        return nullptr;
    }

    SkBitmap bitmap;
    if (!bitmap.tryAllocPixels(ii)) {
        return nullptr;
    }

    if (!SkDecompress(std::move(data), { width, height }, type, &bitmap)) {
        return nullptr;
    }

    bitmap.setImmutable();
    return MakeFromBitmap(bitmap);
}

sk_sp<SkImage> SkImage::MakeFromRaster(const SkPixmap& pmap, RasterReleaseProc proc,
                                       ReleaseContext ctx) {
    size_t size;
    if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), &size) || !pmap.addr()) {
        return nullptr;
    }

    sk_sp<SkData> data(SkData::MakeWithProc(pmap.addr(), size, proc, ctx));
    return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes());
}

sk_sp<SkImage> SkMakeImageFromRasterBitmapPriv(const SkBitmap& bm, SkCopyPixelsMode cpm,
                                               uint32_t idForCopy) {
    if (kAlways_SkCopyPixelsMode == cpm || (!bm.isImmutable() && kNever_SkCopyPixelsMode != cpm)) {
        SkPixmap pmap;
        if (bm.peekPixels(&pmap)) {
            return MakeRasterCopyPriv(pmap, idForCopy);
        } else {
            return sk_sp<SkImage>();
        }
    }

    return sk_make_sp<SkImage_Raster>(bm, kNever_SkCopyPixelsMode == cpm);
}

sk_sp<SkImage> SkMakeImageFromRasterBitmap(const SkBitmap& bm, SkCopyPixelsMode cpm) {
    if (!SkImageInfoIsValid(bm.info()) || bm.rowBytes() < bm.info().minRowBytes()) {
        return nullptr;
    }

    return SkMakeImageFromRasterBitmapPriv(bm, cpm, kNeedNewImageUniqueID);
}

const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
    return ((const SkImage_Raster*)image)->getPixelRef();
}

bool SkImage_Raster::onAsLegacyBitmap(SkBitmap* bitmap) const {
    // When we're a snapshot from a surface, our bitmap may not be marked immutable
    // even though logically always we are, but in that case we can't physically share our
    // pixelref since the caller might call setImmutable() themselves
    // (thus changing our state).
    if (fBitmap.isImmutable()) {
        SkIPoint origin = fBitmap.pixelRefOrigin();
        bitmap->setInfo(fBitmap.info(), fBitmap.rowBytes());
        bitmap->setPixelRef(sk_ref_sp(fBitmap.pixelRef()), origin.x(), origin.y());
        return true;
    }
    return this->INHERITED::onAsLegacyBitmap(bitmap);
}

///////////////////////////////////////////////////////////////////////////////

sk_sp<SkImage> SkImage_Raster::onMakeColorTypeAndColorSpace(GrRecordingContext*,
                                                            SkColorType targetCT,
                                                            sk_sp<SkColorSpace> targetCS) const {
    SkPixmap src;
    SkAssertResult(fBitmap.peekPixels(&src));

    SkBitmap dst;
    dst.allocPixels(fBitmap.info().makeColorType(targetCT).makeColorSpace(targetCS));

    SkAssertResult(dst.writePixels(src));
    dst.setImmutable();
    return SkImage::MakeFromBitmap(dst);
}

sk_sp<SkImage> SkImage_Raster::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
    // TODO: If our bitmap is immutable, then we could theoretically create another image sharing
    // our pixelRef. That doesn't work (without more invasive logic), because the image gets its
    // gen ID from the bitmap, which gets it from the pixelRef.
    SkPixmap pixmap = fBitmap.pixmap();
    pixmap.setColorSpace(std::move(newCS));
    return SkImage::MakeRasterCopy(pixmap);
}
<|endoftext|>


<commit_before>/*****************************************************************************
  annotateBed.cpp

  (c) 2009 - Aaron Quinlan
  Hall Laboratory
  Department of Biochemistry and Molecular Genetics
  University of Virginia
  aaronquinlan@gmail.com

  Licenced under the GNU General Public License 2.0 license.
******************************************************************************/
#include "lineFileUtilities.h"
#include "annotateBed.h"

// build
BedAnnotate::BedAnnotate(const string &mainFile, const vector<string> &annoFileNames,
            const vector<string> &annoTitles, bool sameStrand, bool diffStrand, bool reportCounts, bool reportBoth) :

    _mainFile(mainFile),
    _annoFileNames(annoFileNames),
    _annoTitles(annoTitles),
    _sameStrand(sameStrand),
    _diffStrand(diffStrand),
    _reportCounts(reportCounts),
    _reportBoth(reportBoth)
{
    _bed = new BedFile(_mainFile);
}

// destroy and delete the open file pointers
BedAnnotate::~BedAnnotate(void) {
    delete _bed;
    CloseAnnoFiles();
}

void BedAnnotate::OpenAnnoFiles() {
    for (size_t i=0; i < _annoFileNames.size(); ++i) {
        BedFile *file = new BedFile(_annoFileNames[i]);
        file->Open();
        _annoFiles.push_back(file);
    }
}

void BedAnnotate::CloseAnnoFiles() {
    for (size_t i=0; i < _annoFiles.size(); ++i) {
        BedFile *file = _annoFiles[i];
        delete file;
        _annoFiles[i] = NULL;
    }
}

void BedAnnotate::PrintHeader() {
    // print a hash to indicate header and then write a tab
    // for each field in the main file.
    printf("#");
    for (size_t i = 0; i < _bed->bedType - 1; ++i)
        printf("\t");

    // now print the label for each file.
    if (_reportBoth == false) {
        for (size_t i = 0; i < _annoTitles.size(); ++i)
            printf("%s\t", _annoTitles[i].c_str());
        printf("\n");
    }
    else {
        for (size_t i = 0; i < _annoTitles.size(); ++i)
            printf("\t%s_cnt\t%s_pct", _annoTitles[i].c_str(), _annoTitles[i].c_str());
        printf("\n");
    }
}

void BedAnnotate::InitializeMainFile() {
    // process each chromosome
    masterBedCovListMap::iterator chromItr = _bed->bedCovListMap.begin();
    masterBedCovListMap::iterator chromEnd = _bed->bedCovListMap.end();
    for (; chromItr != chromEnd; ++chromItr) {
        // for each chrom, process each bin
        binsToBedCovLists::iterator binItr = chromItr->second.begin();
        binsToBedCovLists::iterator binEnd = chromItr->second.end();
        for (; binItr != binEnd; ++binItr) {
            // initialize BEDCOVLIST in this chrom/bin
            vector<BEDCOVLIST>::iterator bedItr = binItr->second.begin();
            vector<BEDCOVLIST>::iterator bedEnd = binItr->second.end();
            for (; bedItr != bedEnd; ++bedItr) {
                // initialize the depthMaps, counts, etc. for each anno file.
                for (size_t i = 0; i < _annoFiles.size(); ++i) {
                    map<unsigned int, DEPTH> dummy;
                    bedItr->depthMapList.push_back(dummy);
                    bedItr->counts.push_back(0);
                    bedItr->minOverlapStarts.push_back(INT_MAX);
                }
            }
        }
    }
}

void BedAnnotate::AnnotateBed() {

    // load the "main" bed file into a map so
    // that we can easily compare each annoFile to it for overlaps
    _bed->loadBedCovListFileIntoMap();
    // open the annotations files for processing;
    OpenAnnoFiles();
    // initialize counters, depths, etc. for the main file
    InitializeMainFile();

    // annotate the main file with the coverage from the annotation files.
    for (size_t annoIndex = 0; annoIndex < _annoFiles.size(); ++annoIndex) {
        // grab the current annotation file.
        BedFile *anno = _annoFiles[annoIndex];
        BED a;
        // process each entry in the current anno file
        while (anno->GetNextBed(a)) {
            if (anno->_status == BED_VALID) {
                _bed->countListHits(a, annoIndex, _sameStrand, _diffStrand);
            }
        }
    }

    // report the annotations of the main file from the anno file.
    ReportAnnotations();
    // close the annotations files;
    CloseAnnoFiles();
}

void BedAnnotate::ReportAnnotations() {

    if (_annoTitles.size() > 0) {
        PrintHeader();
    }

    // process each chromosome
    masterBedCovListMap::const_iterator chromItr = _bed->bedCovListMap.begin();
    masterBedCovListMap::const_iterator chromEnd = _bed->bedCovListMap.end();
    for (; chromItr != chromEnd; ++chromItr) {
        // for each chrom, process each bin
        binsToBedCovLists::const_iterator binItr = chromItr->second.begin();
        binsToBedCovLists::const_iterator binEnd = chromItr->second.end();
        for (; binItr != binEnd; ++binItr) {
            // for each chrom & bin, compute and report
            // the observed coverage for each feature
            vector<BEDCOVLIST>::const_iterator bedItr = binItr->second.begin();
            vector<BEDCOVLIST>::const_iterator bedEnd = binItr->second.end();
            for (; bedItr != bedEnd; ++bedItr) {
                // print the main BED entry.
                _bed->reportBedTab(*bedItr);

                // now report the coverage from each annotation file.
                for (size_t i = 0; i < _annoFiles.size(); ++i) {
                    unsigned int totalLength = 0;
                    int zeroDepthCount = 0; // number of bases with zero depth
                    int depth          = 0; // tracks the depth at the current base

                    // the start is either the first base in the feature OR
                    // the leftmost position of an overlapping feature. e.g. (s = start):
                    // A    ----------
                    // B    s    ------------
                    int start          = min(bedItr->minOverlapStarts[i], bedItr->start);

                    map<unsigned int, DEPTH>::const_iterator depthItr;
                    map<unsigned int, DEPTH>::const_iterator depthEnd;

                    // compute the coverage observed at each base in the feature marching from start to end.
                    for (CHRPOS pos = start+1; pos <= bedItr->end; pos++) {
                        // map pointer grabbing the starts and ends observed at this position
                        depthItr = bedItr->depthMapList[i].find(pos);
                        depthEnd = bedItr->depthMapList[i].end();

                        // increment coverage if starts observed at this position.
                        if (depthItr != depthEnd)
                            depth += depthItr->second.starts;
                        // update zero depth
                        if ((pos > bedItr->start) && (pos <= bedItr->end) && (depth == 0))
                            zeroDepthCount++;
                        // decrement coverage if ends observed at this position.
                        if (depthItr != depthEnd)
                            depth = depth - depthItr->second.ends;
                    }
                    // Summarize the coverage for the current interval,
                    CHRPOS length     = bedItr->end - bedItr->start;
                    totalLength       += length;
                    int nonZeroBases   = (length - zeroDepthCount);
                    float fractCovered = (float) nonZeroBases / length;
                    if (_reportCounts == false && _reportBoth == false)
                        printf("%f\t", fractCovered);
                    else if (_reportCounts == true && _reportBoth == false)
                        printf("%d\t", bedItr->counts[i]);
                    else if (_reportCounts == false && _reportBoth == true)
                        printf("%d\t%f\t", bedItr->counts[i], fractCovered);
                }
                // print newline for next feature.
                printf("\n");
            }
        }
    }
}

<commit_msg>[BUG] fix extra TAB at EOL in the annotate tool.<commit_after>/*****************************************************************************
  annotateBed.cpp

  (c) 2009 - Aaron Quinlan
  Hall Laboratory
  Department of Biochemistry and Molecular Genetics
  University of Virginia
  aaronquinlan@gmail.com

  Licenced under the GNU General Public License 2.0 license.
******************************************************************************/
#include "lineFileUtilities.h"
#include "annotateBed.h"

// build
BedAnnotate::BedAnnotate(const string &mainFile, const vector<string> &annoFileNames,
            const vector<string> &annoTitles, bool sameStrand, bool diffStrand, bool reportCounts, bool reportBoth) :

    _mainFile(mainFile),
    _annoFileNames(annoFileNames),
    _annoTitles(annoTitles),
    _sameStrand(sameStrand),
    _diffStrand(diffStrand),
    _reportCounts(reportCounts),
    _reportBoth(reportBoth)
{
    _bed = new BedFile(_mainFile);
}

// destroy and delete the open file pointers
BedAnnotate::~BedAnnotate(void) {
    delete _bed;
    CloseAnnoFiles();
}

void BedAnnotate::OpenAnnoFiles() {
    for (size_t i=0; i < _annoFileNames.size(); ++i) {
        BedFile *file = new BedFile(_annoFileNames[i]);
        file->Open();
        _annoFiles.push_back(file);
    }
}

void BedAnnotate::CloseAnnoFiles() {
    for (size_t i=0; i < _annoFiles.size(); ++i) {
        BedFile *file = _annoFiles[i];
        delete file;
        _annoFiles[i] = NULL;
    }
}

void BedAnnotate::PrintHeader() {
    // print a hash to indicate header and then write a tab
    // for each field in the main file.
    printf("#");
    for (size_t i = 0; i < _bed->bedType - 1; ++i)
        printf("\t");

    // now print the label for each file.
    if (_reportBoth == false) {
        for (size_t i = 0; i < _annoTitles.size(); ++i)
            printf("%s\t", _annoTitles[i].c_str());
        printf("\n");
    }
    else {
        for (size_t i = 0; i < _annoTitles.size(); ++i)
            printf("\t%s_cnt\t%s_pct", _annoTitles[i].c_str(), _annoTitles[i].c_str());
        printf("\n");
    }
}

void BedAnnotate::InitializeMainFile() {
    // process each chromosome
    masterBedCovListMap::iterator chromItr = _bed->bedCovListMap.begin();
    masterBedCovListMap::iterator chromEnd = _bed->bedCovListMap.end();
    for (; chromItr != chromEnd; ++chromItr) {
        // for each chrom, process each bin
        binsToBedCovLists::iterator binItr = chromItr->second.begin();
        binsToBedCovLists::iterator binEnd = chromItr->second.end();
        for (; binItr != binEnd; ++binItr) {
            // initialize BEDCOVLIST in this chrom/bin
            vector<BEDCOVLIST>::iterator bedItr = binItr->second.begin();
            vector<BEDCOVLIST>::iterator bedEnd = binItr->second.end();
            for (; bedItr != bedEnd; ++bedItr) {
                // initialize the depthMaps, counts, etc. for each anno file.
                for (size_t i = 0; i < _annoFiles.size(); ++i) {
                    map<unsigned int, DEPTH> dummy;
                    bedItr->depthMapList.push_back(dummy);
                    bedItr->counts.push_back(0);
                    bedItr->minOverlapStarts.push_back(INT_MAX);
                }
            }
        }
    }
}

void BedAnnotate::AnnotateBed() {

    // load the "main" bed file into a map so
    // that we can easily compare each annoFile to it for overlaps
    _bed->loadBedCovListFileIntoMap();
    // open the annotations files for processing;
    OpenAnnoFiles();
    // initialize counters, depths, etc. for the main file
    InitializeMainFile();

    // annotate the main file with the coverage from the annotation files.
    for (size_t annoIndex = 0; annoIndex < _annoFiles.size(); ++annoIndex) {
        // grab the current annotation file.
        BedFile *anno = _annoFiles[annoIndex];
        BED a;
        // process each entry in the current anno file
        while (anno->GetNextBed(a)) {
            if (anno->_status == BED_VALID) {
                _bed->countListHits(a, annoIndex, _sameStrand, _diffStrand);
            }
        }
    }

    // report the annotations of the main file from the anno file.
    ReportAnnotations();
    // close the annotations files;
    CloseAnnoFiles();
}

void BedAnnotate::ReportAnnotations() {

    if (_annoTitles.size() > 0) {
        PrintHeader();
    }

    // process each chromosome
    masterBedCovListMap::const_iterator chromItr = _bed->bedCovListMap.begin();
    masterBedCovListMap::const_iterator chromEnd = _bed->bedCovListMap.end();
    for (; chromItr != chromEnd; ++chromItr) {
        // for each chrom, process each bin
        binsToBedCovLists::const_iterator binItr = chromItr->second.begin();
        binsToBedCovLists::const_iterator binEnd = chromItr->second.end();
        for (; binItr != binEnd; ++binItr) {
            // for each chrom & bin, compute and report
            // the observed coverage for each feature
            vector<BEDCOVLIST>::const_iterator bedItr = binItr->second.begin();
            vector<BEDCOVLIST>::const_iterator bedEnd = binItr->second.end();
            for (; bedItr != bedEnd; ++bedItr) {
                // print the main BED entry.
                _bed->reportBedTab(*bedItr);

                // now report the coverage from each annotation file.
                for (size_t i = 0; i < _annoFiles.size(); ++i) {
                    unsigned int totalLength = 0;
                    int zeroDepthCount = 0; // number of bases with zero depth
                    int depth          = 0; // tracks the depth at the current base

                    // the start is either the first base in the feature OR
                    // the leftmost position of an overlapping feature. e.g. (s = start):
                    // A    ----------
                    // B    s    ------------
                    int start          = min(bedItr->minOverlapStarts[i], bedItr->start);

                    map<unsigned int, DEPTH>::const_iterator depthItr;
                    map<unsigned int, DEPTH>::const_iterator depthEnd;

                    // compute the coverage observed at each base in the feature marching from start to end.
                    for (CHRPOS pos = start+1; pos <= bedItr->end; pos++) {
                        // map pointer grabbing the starts and ends observed at this position
                        depthItr = bedItr->depthMapList[i].find(pos);
                        depthEnd = bedItr->depthMapList[i].end();

                        // increment coverage if starts observed at this position.
                        if (depthItr != depthEnd)
                            depth += depthItr->second.starts;
                        // update zero depth
                        if ((pos > bedItr->start) && (pos <= bedItr->end) && (depth == 0))
                            zeroDepthCount++;
                        // decrement coverage if ends observed at this position.
                        if (depthItr != depthEnd)
                            depth = depth - depthItr->second.ends;
                    }
                    // Summarize the coverage for the current interval,
                    CHRPOS length     = bedItr->end - bedItr->start;
                    totalLength       += length;
                    int nonZeroBases   = (length - zeroDepthCount);
                    float fractCovered = (float) nonZeroBases / length;
                    if (_reportCounts == false && _reportBoth == false)
                        printf("%f", fractCovered);
                    else if (_reportCounts == true && _reportBoth == false)
                        printf("%d", bedItr->counts[i]);
                    else if (_reportCounts == false && _reportBoth == true)
                        printf("%d\t%f", bedItr->counts[i], fractCovered);

                    if (i != _annoFiles.size() - 1)
                        printf("\t");
                }
                // print newline for next feature.
                printf("\n");
            }
        }
    }
}

<|endoftext|>


<commit_before><commit_msg>escape_html: use StringView instead of struct strref<commit_after><|endoftext|>


<commit_before>/*
 * ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2013, Numenta, Inc.  Unless you have purchased from
 * Numenta, Inc. a separate commercial license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

/** @file
 * Implementation for SparsePooler
 */

#include <nta/algorithms/SparsePooler.hpp>

using namespace std;

namespace nta {

  //--------------------------------------------------------------------------------
  const std::string SparsePooler::current_sparse_pooler_version_ = "SparsePooler_1.7";

  //--------------------------------------------------------------------------------
  // SPARSE POOLER INPUT MASKS
  //--------------------------------------------------------------------------------
  SparsePoolerInputMasks::SparsePoolerInputMasks()
    : segment_size_(0), min_size_(0), max_size_(0),
      sizes_(), masks_()
  {}

  //--------------------------------------------------------------------------------
  SparsePoolerInputMasks::SparsePoolerInputMasks(size_type ss,
						 const std::vector<Mask>& masks)
    : segment_size_(ss), min_size_(0), max_size_(0),
      sizes_(), masks_(masks)
  {
    compute_cache_();
  }

  //--------------------------------------------------------------------------------
  SparsePoolerInputMasks::SparsePoolerInputMasks(std::istream& inStream)
    : segment_size_(0), min_size_(0), max_size_(0),
      sizes_(), masks_()
  {
    readState(inStream);
  }

  //--------------------------------------------------------------------------------
  SparsePoolerInputMasks&
  SparsePoolerInputMasks::operator=(const SparsePoolerInputMasks& other)
  {
    if (&other != this) {
      segment_size_ = other.segment_size_;
      min_size_ = other.min_size_;
      max_size_ = other.max_size_;
      sizes_ = other.sizes_;
      masks_ = other.masks_;
    }
    return *this;
  }

  //--------------------------------------------------------------------------------
  void SparsePoolerInputMasks::saveState(std::ostream& outStream) const
  {
    outStream << segmentSize() << " " << masks_ << " ";
  }

  //--------------------------------------------------------------------------------
  void SparsePoolerInputMasks::readState(std::istream& inStream)
  {
    inStream >> segment_size_ >> general_vector >> masks_;
    compute_cache_();
  }

  //--------------------------------------------------------------------------------
  void SparsePoolerInputMasks::compute_cache_()
  {
    { // Pre-conditions
      NTA_CHECK(segment_size_ > 0)
	<< "SparsePoolerInputMasks: Invalid segment size: " << segment_size_
	<< " - Should be > 0";

      NTA_CHECK(masks_.size() > 0)
	<< "SparsePoolerInputMasks: No masks passed";

      for (size_type i = 0; i != masks_.size(); ++i) {

	NTA_CHECK(masks_[i].size() > 0)
	  << "SparsePoolerInputMasks: Empty mask";

	for (size_type j = 0; j != masks_[i].size(); ++j)
	  NTA_CHECK(masks_[i][j].second > 0)
	    << "SparsePoolerInputMasks: Empty mask segment";
      }
    } // End pre-conditions

    min_size_ = std::numeric_limits<size_type>::max();
    max_size_ = 0;
    sizes_.resize(masks_.size(), 0);

    for (size_type i = 0; i != masks_.size(); ++i) {
      size_type a_size = 0;
      for (size_type j = 0; j != masks_[i].size(); ++j)
	a_size += masks_[i][j].second;
      sizes_[i] = a_size;
      if (a_size < min_size_)
	min_size_ = a_size;
      if (a_size > max_size_)
	max_size_ = a_size;
    }
  }

  //--------------------------------------------------------------------------------
  std::ostream& operator<<(std::ostream& outStream, const SparsePoolerInputMasks& masks)
  {
    masks.saveState(outStream);
    return outStream;
  }

  //--------------------------------------------------------------------------------
  std::istream& operator>>(std::istream& inStream, SparsePoolerInputMasks& masks)
  {
    masks.readState(inStream);
    return inStream;
  }

  //--------------------------------------------------------------------------------
  // SPARSE POOLER
  //--------------------------------------------------------------------------------
  SparsePooler::SparsePooler()
    : normalize_(false),
      lp_(0),
      sparsification_mode_(none),
      k_winners_(0),
      threshold_(0),
      min_accept_distance_(0),
      min_accept_norm_(0),
      min_proto_sum_(1),
      inference_mode_(product),
      sigma_(0),
      input_masks_(),
      p_(0),
      buf_(),
      prototypes_(),
      rng_(0),
      cachedCM_()
  {}

  //------------------------------------------------------------------------------
  SparsePooler::SparsePooler(const SparsePoolerInputMasks& inputMasks,
			     size_type normalize,
			     value_type norm,
			     size_type sparsification_mode,
			     size_type inference_mode,
			     size_type kWinners,
			     value_type threshold,
			     value_type min_accept_distance,
			     value_type min_accept_norm,
			     value_type min_proto_sum,
			     value_type sigma,
			     UInt32 seed)
    : normalize_(false),
      lp_(0),
      sparsification_mode_(none),
      k_winners_(0),
      threshold_(0),
      min_accept_distance_(0),
      min_accept_norm_(0),
      min_proto_sum_(1),
      inference_mode_(product),
      sigma_(0),
      input_masks_(inputMasks),
      p_(0),
      buf_(inputMasks.maxSize()),
      prototypes_(),
      rng_(seed)
  {
    setDoNormalization(normalize);
    setNorm(norm);
    setSparsificationMode(sparsification_mode);
    setKWinners(kWinners);
    setInferenceMode(inference_mode);
    setThreshold(threshold);
    setMinAcceptDistance(min_accept_distance);
    setMinAcceptNorm(min_accept_norm);
    setMinProtoSum(min_proto_sum);
    setSigma(sigma);

    prototypes_.resize(inputMasks.nMasks());
    for (size_type i = 0; i != inputMasks.nMasks(); ++i)
      prototypes_[i].resize(0, inputMasks.size(i));

    init_invariants_();
  }

  //--------------------------------------------------------------------------------
  SparsePooler::SparsePooler(istream& inStream, UInt32 seed)
    : normalize_(false),
      lp_(0),
      sparsification_mode_(none),
      k_winners_(0),
      threshold_(0),
      min_accept_distance_(0),
      min_accept_norm_(0),
      min_proto_sum_(1),
      inference_mode_(product),
      sigma_(0),
      input_masks_(),
      p_(0),
      buf_(),
      prototypes_(),
      rng_(seed)
  {
    readState(inStream);
  }

  //--------------------------------------------------------------------------------
  SparsePooler::~SparsePooler()
  {}

  //--------------------------------------------------------------------------------
  void SparsePooler::saveState(ostream& outStream) const
  {
    outStream << getCurrentSparsePoolerVersion() << " "
	      << getSparsificationMode() << " "
	      << getInferenceMode() << " "
	      << getInputMasks() << " "
	      << getDoNormalization() << " "
	      << getNorm() << " "
	      << getKWinners() << " "
	      << getThreshold() << " "
	      << getMinAcceptDistance() << " "
	      << getMinAcceptNorm() << " "
	      << getMinProtoSum() << " "
	      << getSigma() << " ";

    for (size_type i = 0; i != prototypes_.size(); ++i)
      getPrototypes(i).toCSR(outStream);
  }

  //--------------------------------------------------------------------------------
  void SparsePooler::readState(istream& inStream)
  {
    const std::string where = "SparsePooler::readState: ";

    string flag("");
    size_type i_val = 0;
    value_type f_val = (value_type) 0;

    inStream >> flag;

    inStream >> i_val;
    setSparsificationMode(i_val);

    inStream >> i_val;
    setInferenceMode(i_val);

    inStream >> input_masks_;

    inStream >> i_val;
    setDoNormalization(i_val);

    inStream >> f_val;
    setNorm(f_val);

    inStream >> i_val;
    setKWinners(i_val);

    inStream >> f_val;
    setThreshold(f_val);

    inStream >> f_val;
    setMinAcceptDistance(f_val);

    inStream >> f_val;
    setMinAcceptNorm(f_val);

    if (flag == "SparsePooler_1.7") {
      inStream >> f_val;
      setMinProtoSum(f_val);
    }

    inStream >> f_val;
    setSigma(f_val);

    size_type n_prototypes = getInputMasks().nMasks();

    prototypes_.resize(n_prototypes);

    for (size_type i = 0; i != n_prototypes; ++i)
      prototypes_[i].fromCSR(inStream, true);

    p_ = 0;
    buf_.resize(getInputMasks().maxSize());

    init_invariants_();
  }

 //--------------------------------------------------------------------------------
  void SparsePooler::init_invariants_() const
  {
  }

  //--------------------------------------------------------------------------------
} // end namespace nta
<commit_msg>use NTA_ASSERT<commit_after>/*
 * ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2013, Numenta, Inc.  Unless you have purchased from
 * Numenta, Inc. a separate commercial license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

/** @file
 * Implementation for SparsePooler
 */

#include <nta/algorithms/SparsePooler.hpp>

using namespace std;

namespace nta {

  //--------------------------------------------------------------------------------
  const std::string SparsePooler::current_sparse_pooler_version_ = "SparsePooler_1.7";

  //--------------------------------------------------------------------------------
  // SPARSE POOLER INPUT MASKS
  //--------------------------------------------------------------------------------
  SparsePoolerInputMasks::SparsePoolerInputMasks()
    : segment_size_(0), min_size_(0), max_size_(0),
      sizes_(), masks_()
  {}

  //--------------------------------------------------------------------------------
  SparsePoolerInputMasks::SparsePoolerInputMasks(size_type ss,
						 const std::vector<Mask>& masks)
    : segment_size_(ss), min_size_(0), max_size_(0),
      sizes_(), masks_(masks)
  {
    compute_cache_();
  }

  //--------------------------------------------------------------------------------
  SparsePoolerInputMasks::SparsePoolerInputMasks(std::istream& inStream)
    : segment_size_(0), min_size_(0), max_size_(0),
      sizes_(), masks_()
  {
    readState(inStream);
  }

  //--------------------------------------------------------------------------------
  SparsePoolerInputMasks&
  SparsePoolerInputMasks::operator=(const SparsePoolerInputMasks& other)
  {
    if (&other != this) {
      segment_size_ = other.segment_size_;
      min_size_ = other.min_size_;
      max_size_ = other.max_size_;
      sizes_ = other.sizes_;
      masks_ = other.masks_;
    }
    return *this;
  }

  //--------------------------------------------------------------------------------
  void SparsePoolerInputMasks::saveState(std::ostream& outStream) const
  {
    outStream << segmentSize() << " " << masks_ << " ";
  }

  //--------------------------------------------------------------------------------
  void SparsePoolerInputMasks::readState(std::istream& inStream)
  {
    inStream >> segment_size_ >> general_vector >> masks_;
    compute_cache_();
  }

  //--------------------------------------------------------------------------------
  void SparsePoolerInputMasks::compute_cache_()
  {
    { // Pre-conditions
      NTA_ASSERT(segment_size_ > 0)
	<< "SparsePoolerInputMasks: Invalid segment size: " << segment_size_
	<< " - Should be > 0";

      NTA_ASSERT(masks_.size() > 0)
	<< "SparsePoolerInputMasks: No masks passed";

      for (size_type i = 0; i != masks_.size(); ++i) {

	NTA_ASSERT(masks_[i].size() > 0)
	  << "SparsePoolerInputMasks: Empty mask";

	for (size_type j = 0; j != masks_[i].size(); ++j)
	  NTA_ASSERT(masks_[i][j].second > 0)
	    << "SparsePoolerInputMasks: Empty mask segment";
      }
    } // End pre-conditions

    min_size_ = std::numeric_limits<size_type>::max();
    max_size_ = 0;
    sizes_.resize(masks_.size(), 0);

    for (size_type i = 0; i != masks_.size(); ++i) {
      size_type a_size = 0;
      for (size_type j = 0; j != masks_[i].size(); ++j)
	a_size += masks_[i][j].second;
      sizes_[i] = a_size;
      if (a_size < min_size_)
	min_size_ = a_size;
      if (a_size > max_size_)
	max_size_ = a_size;
    }
  }

  //--------------------------------------------------------------------------------
  std::ostream& operator<<(std::ostream& outStream, const SparsePoolerInputMasks& masks)
  {
    masks.saveState(outStream);
    return outStream;
  }

  //--------------------------------------------------------------------------------
  std::istream& operator>>(std::istream& inStream, SparsePoolerInputMasks& masks)
  {
    masks.readState(inStream);
    return inStream;
  }

  //--------------------------------------------------------------------------------
  // SPARSE POOLER
  //--------------------------------------------------------------------------------
  SparsePooler::SparsePooler()
    : normalize_(false),
      lp_(0),
      sparsification_mode_(none),
      k_winners_(0),
      threshold_(0),
      min_accept_distance_(0),
      min_accept_norm_(0),
      min_proto_sum_(1),
      inference_mode_(product),
      sigma_(0),
      input_masks_(),
      p_(0),
      buf_(),
      prototypes_(),
      rng_(0),
      cachedCM_()
  {}

  //------------------------------------------------------------------------------
  SparsePooler::SparsePooler(const SparsePoolerInputMasks& inputMasks,
			     size_type normalize,
			     value_type norm,
			     size_type sparsification_mode,
			     size_type inference_mode,
			     size_type kWinners,
			     value_type threshold,
			     value_type min_accept_distance,
			     value_type min_accept_norm,
			     value_type min_proto_sum,
			     value_type sigma,
			     UInt32 seed)
    : normalize_(false),
      lp_(0),
      sparsification_mode_(none),
      k_winners_(0),
      threshold_(0),
      min_accept_distance_(0),
      min_accept_norm_(0),
      min_proto_sum_(1),
      inference_mode_(product),
      sigma_(0),
      input_masks_(inputMasks),
      p_(0),
      buf_(inputMasks.maxSize()),
      prototypes_(),
      rng_(seed)
  {
    setDoNormalization(normalize);
    setNorm(norm);
    setSparsificationMode(sparsification_mode);
    setKWinners(kWinners);
    setInferenceMode(inference_mode);
    setThreshold(threshold);
    setMinAcceptDistance(min_accept_distance);
    setMinAcceptNorm(min_accept_norm);
    setMinProtoSum(min_proto_sum);
    setSigma(sigma);

    prototypes_.resize(inputMasks.nMasks());
    for (size_type i = 0; i != inputMasks.nMasks(); ++i)
      prototypes_[i].resize(0, inputMasks.size(i));

    init_invariants_();
  }

  //--------------------------------------------------------------------------------
  SparsePooler::SparsePooler(istream& inStream, UInt32 seed)
    : normalize_(false),
      lp_(0),
      sparsification_mode_(none),
      k_winners_(0),
      threshold_(0),
      min_accept_distance_(0),
      min_accept_norm_(0),
      min_proto_sum_(1),
      inference_mode_(product),
      sigma_(0),
      input_masks_(),
      p_(0),
      buf_(),
      prototypes_(),
      rng_(seed)
  {
    readState(inStream);
  }

  //--------------------------------------------------------------------------------
  SparsePooler::~SparsePooler()
  {}

  //--------------------------------------------------------------------------------
  void SparsePooler::saveState(ostream& outStream) const
  {
    outStream << getCurrentSparsePoolerVersion() << " "
	      << getSparsificationMode() << " "
	      << getInferenceMode() << " "
	      << getInputMasks() << " "
	      << getDoNormalization() << " "
	      << getNorm() << " "
	      << getKWinners() << " "
	      << getThreshold() << " "
	      << getMinAcceptDistance() << " "
	      << getMinAcceptNorm() << " "
	      << getMinProtoSum() << " "
	      << getSigma() << " ";

    for (size_type i = 0; i != prototypes_.size(); ++i)
      getPrototypes(i).toCSR(outStream);
  }

  //--------------------------------------------------------------------------------
  void SparsePooler::readState(istream& inStream)
  {
    const std::string where = "SparsePooler::readState: ";

    string flag("");
    size_type i_val = 0;
    value_type f_val = (value_type) 0;

    inStream >> flag;

    inStream >> i_val;
    setSparsificationMode(i_val);

    inStream >> i_val;
    setInferenceMode(i_val);

    inStream >> input_masks_;

    inStream >> i_val;
    setDoNormalization(i_val);

    inStream >> f_val;
    setNorm(f_val);

    inStream >> i_val;
    setKWinners(i_val);

    inStream >> f_val;
    setThreshold(f_val);

    inStream >> f_val;
    setMinAcceptDistance(f_val);

    inStream >> f_val;
    setMinAcceptNorm(f_val);

    if (flag == "SparsePooler_1.7") {
      inStream >> f_val;
      setMinProtoSum(f_val);
    }

    inStream >> f_val;
    setSigma(f_val);

    size_type n_prototypes = getInputMasks().nMasks();

    prototypes_.resize(n_prototypes);

    for (size_type i = 0; i != n_prototypes; ++i)
      prototypes_[i].fromCSR(inStream, true);

    p_ = 0;
    buf_.resize(getInputMasks().maxSize());

    init_invariants_();
  }

 //--------------------------------------------------------------------------------
  void SparsePooler::init_invariants_() const
  {
  }

  //--------------------------------------------------------------------------------
} // end namespace nta
<|endoftext|>


<commit_before><commit_msg>removing the doot thing<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed potential warning (forward declaration and definition didn't match signature. forward declaration only here for consistency)<commit_after><|endoftext|>