code:
/*=============================================================================
    Copyright (c) 2011 Hartmut Kaiser

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/

#if !defined(BOOST_PHOENIX_PREPROCESSED_BIND_FUNCTION_OBJECT_HPP)
#define BOOST_PHOENIX_PREPROCESSED_BIND_FUNCTION_OBJECT_HPP

#if BOOST_PHOENIX_LIMIT <= 10
#include <boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object_10.hpp>
#elif BOOST_PHOENIX_LIMIT <= 20
#include <boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object_20.hpp>
#elif BOOST_PHOENIX_LIMIT <= 30
#include <boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object_30.hpp>
#elif BOOST_PHOENIX_LIMIT <= 40
#include <boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object_40.hpp>
#elif BOOST_PHOENIX_LIMIT <= 50
#include <boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object_50.hpp>
#else
#error "BOOST_PHOENIX_LIMIT out of bounds for preprocessed headers"
#endif

#endif


code:
// Copyright (C) 2004-2008 The Trustees of Indiana University.

// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

//  Authors: Douglas Gregor
//           Nick Edmonds
//           Andrew Lumsdaine

// The placement of this #include probably looks very odd relative to
// the #ifndef/#define pair below. However, this placement is
// extremely important to allow the various property map headers to be
// included in any order.
#include <boost/property_map/property_map.hpp>

#ifndef BOOST_PARALLEL_DISTRIBUTED_PROPERTY_MAP_HPP
#define BOOST_PARALLEL_DISTRIBUTED_PROPERTY_MAP_HPP

#include <boost/assert.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/optional.hpp>
#include <boost/property_map/parallel/process_group.hpp>
#include <boost/function/function1.hpp>
#include <vector>
#include <set>
#include <boost/property_map/parallel/basic_reduce.hpp>
#include <boost/property_map/parallel/detail/untracked_pair.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/property_map/parallel/local_property_map.hpp>
#include <map>
#include <boost/version.hpp>
#include <boost/property_map/parallel/unsafe_serialize.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/sequenced_index.hpp>

// Serialization functions for constructs we use
#include <boost/serialization/utility.hpp>

namespace boost { namespace parallel {

namespace detail {
  /**************************************************************************
   * Metafunction that degrades an Lvalue Property Map category tag to
   * a Read Write Property Map category tag.
   **************************************************************************/
  template<bool IsLvaluePropertyMap>
  struct make_nonlvalue_property_map
  {
    template<typename T> struct apply { typedef T type; };
  };

  template<>
  struct make_nonlvalue_property_map<true>
  {
    template<typename>
    struct apply
    {
      typedef read_write_property_map_tag type;
    };
  };

  /**************************************************************************
   * Performs a "put" on a property map so long as the property map is
   * a Writable Property Map or a mutable Lvalue Property Map. This
   * is required because the distributed property map's message
   * handler handles "put" messages even for a const property map,
   * although receipt of a "put" message is ill-formed.
   **************************************************************************/
  template<bool IsLvaluePropertyMap>
  struct maybe_put_in_lvalue_pm
  {
    template<typename PropertyMap, typename Key, typename Value>
    static inline void
    do_put(PropertyMap, const Key&, const Value&)
    { BOOST_ASSERT(false); }
  };

  template<>
  struct maybe_put_in_lvalue_pm<true>
  {
    template<typename PropertyMap, typename Key, typename Value>
    static inline void
    do_put(PropertyMap pm, const Key& key, const Value& value)
    {
      using boost::put;

      put(pm, key, value);
    }
  };

  template<typename PropertyMap, typename Key, typename Value>
  inline void
  maybe_put_impl(PropertyMap pm, const Key& key, const Value& value,
                 writable_property_map_tag)
  {
    using boost::put;

    put(pm, key, value);
  }

  template<typename PropertyMap, typename Key, typename Value>
  inline void
  maybe_put_impl(PropertyMap pm, const Key& key, const Value& value,
                 lvalue_property_map_tag)
  {
    typedef typename property_traits<PropertyMap>::value_type value_type;
    typedef typename property_traits<PropertyMap>::reference reference;
    // DPG TBD: Some property maps are improperly characterized as
    // lvalue_property_maps, when in fact they do not provide true
    // references. The most typical example is those property maps
    // built from vector<bool> and its iterators, which deal with
    // proxies. We don't want to mischaracterize these as not having a
    // "put" operation, so we only consider an lvalue_property_map as
    // constant if its reference is const value_type&. In fact, this
    // isn't even quite correct (think of a
    // vector<bool>::const_iterator), but at present C++ doesn't
    // provide us with any alternatives.
    typedef is_same<const value_type&, reference> is_constant;

    maybe_put_in_lvalue_pm<(!is_constant::value)>::do_put(pm, key, value);
  }

  template<typename PropertyMap, typename Key, typename Value>
  inline void
  maybe_put_impl(PropertyMap, const Key&, const Value&, ...)
  { BOOST_ASSERT(false); }

  template<typename PropertyMap, typename Key, typename Value>
  inline void
  maybe_put(PropertyMap pm, const Key& key, const Value& value)
  {
    maybe_put_impl(pm, key, value,
                   typename property_traits<PropertyMap>::category());
  }
} // end namespace detail

/** The consistency model used by the distributed property map. */
enum consistency_model {
  cm_forward = 1 << 0,
  cm_backward = 1 << 1,
  cm_bidirectional = cm_forward | cm_backward,
  cm_flush = 1 << 2,
  cm_reset = 1 << 3,
  cm_clear = 1 << 4
};

/** Distributed property map adaptor.
 *
 *  The distributed property map adaptor is a property map whose
 *  stored values are distributed across multiple non-overlapping
 *  memory spaces on different processes. Values local to the current
 *  process are stored within a local property map and may be
 *  immediately accessed via @c get and @c put. Values stored on
 *  remote processes may also be access via @c get and @c put, but the
 *  behavior differs slightly:
 *
 *  - @c put operations update a local ghost cell and send a "put"
 *    message to the process that owns the value. The owner is free to
 *    update its own "official" value or may ignore the put request.
 *
 *  - @c get operations returns the contents of the local ghost
 *    cell. If no ghost cell is available, one is created using the
 *    default value provided by the "reduce" operation. See, e.g.,
 *    @ref basic_reduce and @ref property_reduce.
 *
 * Using distributed property maps requires a bit more care than using
 * local, sequential property maps. While the syntax and semantics are
 * similar, distributed property maps may contain out-of-date
 * information that can only be guaranteed to be synchronized by
 * calling the @ref synchronize function in all processes.
 *
 * To address the issue of out-of-date values, distributed property
 * maps are supplied with a reduction operation. The reduction
 * operation has two roles:
 *
 *   -# When a value is needed for a remote key but no value is
 *      immediately available, the reduction operation provides a
 *      suitable default. For instance, a distributed property map
 *      storing distances may have a reduction operation that returns
 *      an infinite value as the default, whereas a distributed
 *      property map for vertex colors may return white as the
 *      default.
 *
 *   -# When a value is received from a remote process, the process
 *      owning the key associated with that value must determine which
 *      value---the locally stored value, the value received from a
 *      remote process, or some combination of the two---will be
 *      stored as the "official" value in the property map. The
 *      reduction operation transforms the local and remote values
 *      into the "official" value to be stored.
 *
 * @tparam ProcessGroup the type of the process group over which the
 * property map is distributed and is also the medium for
 * communication.
 *
 * @tparam StorageMap the type of the property map that will
 * store values for keys local to this processor. The @c value_type of
 * this property map will become the @c value_type of the distributed
 * property map. The distributed property map models the same property
 * map concepts as the @c LocalPropertyMap, with one exception: a
 * distributed property map cannot be an LvaluePropertyMap (because
 * remote values are not addressable), and is therefore limited to
 * ReadWritePropertyMap.
 */
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
class distributed_property_map
{
 public:
  /// The key type of the property map.
  typedef typename property_traits<GlobalMap>::key_type key_type;

  /// The value type of the property map.
  typedef typename property_traits<StorageMap>::value_type value_type;
  typedef typename property_traits<StorageMap>::reference  reference;
  typedef ProcessGroup                        process_group_type;

 private:
  typedef distributed_property_map            self_type;
  typedef typename property_traits<StorageMap>::category local_category;
  typedef typename property_traits<StorageMap>::key_type local_key_type;
  typedef typename property_traits<GlobalMap>::value_type owner_local_pair;
  typedef typename ProcessGroup::process_id_type process_id_type;

  enum property_map_messages {
    /** A request to store a value in a property map. The message
     * contains a std::pair<key, data>.
     */
    property_map_put,

    /** A request to retrieve a particular value in a property
     *  map. The message contains a key. The owner of that key will
     *  reply with a value.
     */
    property_map_get,

    /** A request to update values stored on a remote processor. The
     * message contains a vector of keys for which the source
     * requests updated values. This message will only be transmitted
     * during synchronization.
     */
    property_map_multiget,

    /** A request to store values in a ghost cell. This message
     * contains a vector of key/value pairs corresponding to the
     * sequence of keys sent to the source processor.
     */
    property_map_multiget_reply,

    /** The payload containing a vector of local key-value pairs to be
     * put into the remote property map. A key-value std::pair will be
     * used to store each local key-value pair.
     */
    property_map_multiput
  };

  // Code from Joaquín M López Muñoz to work around unusual implementation of
  // std::pair in VC++ 10:
  template<typename First,typename Second>
  class pair_first_extractor {
    typedef std::pair<First,Second> value_type;

    public:
    typedef First result_type;
    const result_type& operator()(const value_type& x) const {
      return x.first;
    }

    result_type& operator()(value_type& x) const {
      return x.first;
    }
  };

 public:
  /// The type of the ghost cells
  typedef multi_index::multi_index_container<
            std::pair<key_type, value_type>,
            multi_index::indexed_by<
              multi_index::sequenced<>,
              multi_index::hashed_unique<
                pair_first_extractor<key_type, value_type>
              >
            >
          > ghost_cells_type;

  /// Iterator into the ghost cells
  typedef typename ghost_cells_type::iterator iterator;

  /// Key-based index into the ghost cells
  typedef typename ghost_cells_type::template nth_index<1>::type
    ghost_cells_key_index_type;

  /// Iterator into the ghost cells (by key)
  typedef typename ghost_cells_key_index_type::iterator key_iterator;

  /** The property map category.  A distributed property map cannot be
   * an Lvalue Property Map, because values on remote processes cannot
   * be addresses.
   */
  typedef typename detail::make_nonlvalue_property_map<
    (is_base_and_derived<lvalue_property_map_tag, local_category>::value
     || is_same<lvalue_property_map_tag, local_category>::value)>
    ::template apply<local_category>::type category;

  /** Default-construct a distributed property map.  This function
   * creates an initialized property map that must be assigned to a
   * valid value before being used. It is only provided here because
   * property maps must be Default Constructible.
   */
  distributed_property_map() {}

  /** Construct a distributed property map.  Builds a distributed
   * property map communicating over the given process group and using
   * the given local property map for storage. Since no reduction
   * operation is provided, the default reduction operation @c
   * basic_reduce<value_type> is used.
   */
  distributed_property_map(const ProcessGroup& pg, const GlobalMap& global,
                           const StorageMap& pm)
    : data(new data_t(pg, global, pm, basic_reduce<value_type>(), false))
  {
    typedef handle_message<basic_reduce<value_type> > Handler;

    data->ghost_cells.reset(new ghost_cells_type());
    Handler handler(data);
    data->process_group.replace_handler(handler, true);
    data->process_group.template get_receiver<Handler>()
      ->setup_triggers(data->process_group);
  }

  /** Construct a distributed property map.  Builds a distributed
   * property map communicating over the given process group and using
   * the given local property map for storage. The given @p reduce
   * parameter is used as the reduction operation.
   */
  template<typename Reduce>
  distributed_property_map(const ProcessGroup& pg, const GlobalMap& global,
                           const StorageMap& pm,
                           const Reduce& reduce);

  ~distributed_property_map();

  /// Set the reduce operation of the distributed property map.
  template<typename Reduce>
  void set_reduce(const Reduce& reduce);

  // Set the consistency model for the distributed property map
  void set_consistency_model(int model);

  // Get the consistency model
  int get_consistency_model() const { return data->model; }

  // Set the maximum number of ghost cells that we are allowed to
  // maintain. If 0, all ghost cells will be retained.
  void set_max_ghost_cells(std::size_t max_ghost_cells);

  // Clear out all ghost cells
  void clear();

  // Reset the values in all ghost cells to the default value
  void reset();

  // Flush all values destined for remote processors
  void flush();

  reference operator[](const key_type& key) const
  {
    owner_local_pair p = get(data->global, key);

    if (p.first == process_id(data->process_group)) {
      return data->storage[p.second];
    } else {
      return cell(key);
    }
  }

  process_group_type process_group() const
  {
    return data->process_group.base();
  }

  StorageMap&       base()       { return data->storage; }
  const StorageMap& base() const { return data->storage; }

  /** Sends a "put" request.
   * \internal
   *
   */
  void
  request_put(process_id_type p, const key_type& k, const value_type& v) const
  {
    send(data->process_group, p, property_map_put,
         boost::parallel::detail::make_untracked_pair(k, v));
  }

  /** Access the ghost cell for the given key.
   * \internal
   */
  value_type& cell(const key_type& k, bool request_if_missing = true) const;

  /** Perform synchronization
   * \internal
   */
  void do_synchronize();

  const GlobalMap& global() const { return data->global; }
  GlobalMap&       global()       { return data->global; }

  struct data_t
  {
    data_t(const ProcessGroup& pg, const GlobalMap& global,
           const StorageMap& pm, const function1<value_type, key_type>& dv,
           bool has_default_resolver)
      : process_group(pg), global(global), storage(pm),
        ghost_cells(), max_ghost_cells(1000000), get_default_value(dv),
        has_default_resolver(has_default_resolver), model(cm_forward) { }

    /// The process group
    ProcessGroup process_group;

    /// A mapping from the keys of this property map to the global
    /// descriptor.
    GlobalMap global;

    /// Local property map
    StorageMap storage;

    /// The ghost cells
    shared_ptr<ghost_cells_type> ghost_cells;

    /// The maximum number of ghost cells we are permitted to hold. If
    /// zero, we are permitted to have an infinite number of ghost
    /// cells.
    std::size_t max_ghost_cells;

    /// Default value for remote ghost cells, as defined by the
    /// reduction operation.
    function1<value_type, key_type> get_default_value;

    /// True if this resolver is the "default" resolver, meaning that
    /// we should not be able to get() a default value; it needs to be
    /// request()ed first.
    bool has_default_resolver;

    // Current consistency model
    int model;

    // Function that resets all of the ghost cells to their default
    // values. It knows the type of the resolver, so we can eliminate
    // a large number of calls through function pointers.
    void (data_t::*reset)();

    // Clear out all ghost cells
    void clear();

    // Flush all values destined for remote processors
    void flush();

    // Send out requests to "refresh" the values of ghost cells that
    // we're holding.
    void refresh_ghost_cells();

  private:
    template<typename Resolver> void do_reset();

    friend class distributed_property_map;
  };
  friend struct data_t;

  shared_ptr<data_t> data;

 private:
  // Prunes the least recently used ghost cells until we have @c
  // max_ghost_cells or fewer ghost cells.
  void prune_ghost_cells() const;

  /** Handles incoming messages.
   *
   * This function object is responsible for handling all incoming
   * messages for the distributed property map.
   */
  template<typename Reduce>
  struct handle_message
  {
    explicit handle_message(const shared_ptr<data_t>& data,
                            const Reduce& reduce = Reduce())
      : data_ptr(data), reduce(reduce) { }

    void operator()(process_id_type source, int tag);

    /// Individual message handlers
    void
    handle_put(int source, int tag,
               const boost::parallel::detail::untracked_pair<key_type, value_type>& data,
               trigger_receive_context);

    value_type
    handle_get(int source, int tag, const key_type& data,
               trigger_receive_context);

    void
    handle_multiget(int source, int tag,
                    const std::vector<key_type>& data,
                    trigger_receive_context);

    void
    handle_multiget_reply
      (int source, int tag,
       const std::vector<boost::parallel::detail::untracked_pair<key_type, value_type> >& msg,
       trigger_receive_context);

    void
    handle_multiput
      (int source, int tag,
       const std::vector<unsafe_pair<local_key_type, value_type> >& data,
       trigger_receive_context);

    void setup_triggers(process_group_type& pg);

  private:
    weak_ptr<data_t> data_ptr;
    Reduce reduce;
  };

  /* Sets up the next stage in a multi-stage synchronization, for
     bidirectional consistency. */
  struct on_synchronize
  {
    explicit on_synchronize(const shared_ptr<data_t>& data) : data_ptr(data) { }

    void operator()();

  private:
    weak_ptr<data_t> data_ptr;
  };
};

/* An implementation helper macro for the common case of naming
   distributed property maps with all of the normal template
   parameters. */
#define PBGL_DISTRIB_PMAP                                       \
  distributed_property_map<ProcessGroup, GlobalMap, StorageMap>

/* Request that the value for the given remote key be retrieved in
   the next synchronization round. */
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline void
request(const PBGL_DISTRIB_PMAP& pm,
        typename PBGL_DISTRIB_PMAP::key_type const& key)
{
  if (get(pm.data->global, key).first != process_id(pm.data->process_group))
    pm.cell(key, false);
}

/** Get the value associated with a particular key.  Retrieves the
 * value associated with the given key. If the key denotes a
 * locally-owned object, it returns the value from the local property
 * map; if the key denotes a remotely-owned object, retrieves the
 * value of the ghost cell for that key, which may be the default
 * value provided by the reduce operation.
 *
 * Complexity: For a local key, O(1) get operations on the underlying
 * property map. For a non-local key, O(1) accesses to the ghost cells.
 */
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline
typename PBGL_DISTRIB_PMAP::value_type
get(const PBGL_DISTRIB_PMAP& pm,
    typename PBGL_DISTRIB_PMAP::key_type const& key)
{
  using boost::get;

  typename property_traits<GlobalMap>::value_type p =
    get(pm.data->global, key);

  if (p.first == process_id(pm.data->process_group)) {
    return get(pm.data->storage, p.second);
  } else {
    return pm.cell(key);
  }
}

/** Put a value associated with the given key into the property map.
 * When the key denotes a locally-owned object, this operation updates
 * the underlying local property map. Otherwise, the local ghost cell
 * is updated and a "put" message is sent to the processor owning this
 * key.
 *
 * Complexity: For a local key, O(1) put operations on the underlying
 * property map. For a nonlocal key, O(1) accesses to the ghost cells
 * and will send O(1) messages of size O(sizeof(key) + sizeof(value)).
 */
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
void
put(const PBGL_DISTRIB_PMAP& pm,
    typename PBGL_DISTRIB_PMAP::key_type const & key,
    typename PBGL_DISTRIB_PMAP::value_type const & value)
{
  using boost::put;

  typename property_traits<GlobalMap>::value_type p =
    get(pm.data->global, key);

  if (p.first == process_id(pm.data->process_group)) {
    put(pm.data->storage, p.second, value);
  } else {
    if (pm.data->model & cm_forward)
      pm.request_put(p.first, key, value);

    pm.cell(key, false) = value;
  }
}

/** Put a value associated with a given key into the local view of the
 * property map. This operation is equivalent to @c put, but with one
 * exception: no message will be sent to the owning processor in the
 * case of a remote update. The effect is that any value written via
 * @c local_put for a remote key may be overwritten in the next
 * synchronization round.
 */
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
void
local_put(const PBGL_DISTRIB_PMAP& pm,
          typename PBGL_DISTRIB_PMAP::key_type const & key,
          typename PBGL_DISTRIB_PMAP::value_type const & value)
{
  using boost::put;

  typename property_traits<GlobalMap>::value_type p =
    get(pm.data->global, key);

  if (p.first == process_id(pm.data->process_group))
    put(pm.data->storage, p.second, value);
  else pm.cell(key, false) = value;
}

/** Cache the value associated with the given remote key. If the key
 *  is local, ignore the operation. */
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline void
cache(const PBGL_DISTRIB_PMAP& pm,
      typename PBGL_DISTRIB_PMAP::key_type const & key,
      typename PBGL_DISTRIB_PMAP::value_type const & value)
{
  typename ProcessGroup::process_id_type id = get(pm.data->global, key).first;

  if (id != process_id(pm.data->process_group)) pm.cell(key, false) = value;
}

/// Synchronize the property map.
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
void
synchronize(PBGL_DISTRIB_PMAP& pm)
{
  pm.do_synchronize();
}

/// Create a distributed property map.
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline distributed_property_map<ProcessGroup, GlobalMap, StorageMap>
make_distributed_property_map(const ProcessGroup& pg, GlobalMap global,
                              StorageMap storage)
{
  typedef distributed_property_map<ProcessGroup, GlobalMap, StorageMap>
    result_type;
  return result_type(pg, global, storage);
}

/**
 * \overload
 */
template<typename ProcessGroup, typename GlobalMap, typename StorageMap,
         typename Reduce>
inline distributed_property_map<ProcessGroup, GlobalMap, StorageMap>
make_distributed_property_map(const ProcessGroup& pg, GlobalMap global,
                              StorageMap storage, Reduce reduce)
{
  typedef distributed_property_map<ProcessGroup, GlobalMap, StorageMap>
    result_type;
  return result_type(pg, global, storage, reduce);
}

} } // end namespace boost::parallel

#include <boost/property_map/parallel/impl/distributed_property_map.ipp>

#undef PBGL_DISTRIB_PMAP

#endif // BOOST_PARALLEL_DISTRIBUTED_PROPERTY_MAP_HPP

license: mit


code:
//  Copyright (c) 2000-2011 Joerg Walter, Mathias Koch, David Bellot
//
//  Distributed under the Boost Software License, Version 1.0. (See
//  accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
//  The authors gratefully acknowledge the support of
//  GeNeSys mbH & Co. KG in producing this work.

#ifndef _BOOST_UBLAS_BLAS_
#define _BOOST_UBLAS_BLAS_

#include <boost/numeric/ublas/traits.hpp>

namespace boost { namespace numeric { namespace ublas {

    /** Interface and implementation of BLAS level 1
     * This includes functions which perform \b vector-vector operations.
     * More information about BLAS can be found at
     * http://en.wikipedia.org/wiki/BLAS
     */
    namespace blas_1 {

        /** 1-Norm: \f$\sum_i |x_i|\f$ (also called \f$\mathcal{L}_1\f$ or Manhattan norm)
     *
     * \param v a vector or vector expression
     * \return the 1-Norm with type of the vector's type
     *
     * \tparam V type of the vector (not needed by default)
     */
        template<class V>
        typename type_traits<typename V::value_type>::real_type
        asum (const V &v) {
            return norm_1 (v);
        }

        /** 2-Norm: \f$\sum_i |x_i|^2\f$ (also called \f$\mathcal{L}_2\f$ or Euclidean norm)
     *
     * \param v a vector or vector expression
     * \return the 2-Norm with type of the vector's type
     *
     * \tparam V type of the vector (not needed by default)
     */
        template<class V>
        typename type_traits<typename V::value_type>::real_type
        nrm2 (const V &v) {
            return norm_2 (v);
        }

        /** Infinite-norm: \f$\max_i |x_i|\f$ (also called \f$\mathcal{L}_\infty\f$ norm)
     *
     * \param v a vector or vector expression
     * \return the Infinite-Norm with type of the vector's type
     *
     * \tparam V type of the vector (not needed by default)
     */
        template<class V>
        typename type_traits<typename V::value_type>::real_type
        amax (const V &v) {
            return norm_inf (v);
        }

        /** Inner product of vectors \f$v_1\f$ and \f$v_2\f$
     *
     * \param v1 first vector of the inner product
     * \param v2 second vector of the inner product
     * \return the inner product of the type of the most generic type of the 2 vectors
     *
     * \tparam V1 type of first vector (not needed by default)
     * \tparam V2 type of second vector (not needed by default)
     */
        template<class V1, class V2>
        typename promote_traits<typename V1::value_type, typename V2::value_type>::promote_type
        dot (const V1 &v1, const V2 &v2) {
            return inner_prod (v1, v2);
        }

        /** Copy vector \f$v_2\f$ to \f$v_1\f$
     *
     * \param v1 target vector
     * \param v2 source vector
     * \return a reference to the target vector
     *
     * \tparam V1 type of first vector (not needed by default)
     * \tparam V2 type of second vector (not needed by default)
     */
        template<class V1, class V2>
        V1 & copy (V1 &v1, const V2 &v2)
    {
            return v1.assign (v2);
        }

        /** Swap vectors \f$v_1\f$ and \f$v_2\f$
     *
     * \param v1 first vector
     * \param v2 second vector
     *
         * \tparam V1 type of first vector (not needed by default)
     * \tparam V2 type of second vector (not needed by default)
     */
    template<class V1, class V2>
        void swap (V1 &v1, V2 &v2)
    {
            v1.swap (v2);
        }

        /** scale vector \f$v\f$ with scalar \f$t\f$
     *
     * \param v vector to be scaled
     * \param t the scalar
     * \return \c t*v
     *
     * \tparam V type of the vector (not needed by default)
     * \tparam T type of the scalar (not needed by default)
     */
        template<class V, class T>
        V & scal (V &v, const T &t)
    {
            return v *= t;
        }

        /** Compute \f$v_1= v_1 +  t.v_2\f$
     *
     * \param v1 target and first vector
     * \param t the scalar
     * \param v2 second vector
     * \return a reference to the first and target vector
     *
     * \tparam V1 type of the first vector (not needed by default)
     * \tparam T type of the scalar (not needed by default)
     * \tparam V2 type of the second vector (not needed by default)
     */
        template<class V1, class T, class V2>
        V1 & axpy (V1 &v1, const T &t, const V2 &v2)
    {
            return v1.plus_assign (t * v2);
        }

    /** Performs rotation of points in the plane and assign the result to the first vector
     *
     * Each point is defined as a pair \c v1(i) and \c v2(i), being respectively
     * the \f$x\f$ and \f$y\f$ coordinates. The parameters \c t1 and \t2 are respectively
     * the cosine and sine of the angle of the rotation.
     * Results are not returned but directly written into \c v1.
     *
     * \param t1 cosine of the rotation
     * \param v1 vector of \f$x\f$ values
     * \param t2 sine of the rotation
     * \param v2 vector of \f$y\f$ values
     *
     * \tparam T1 type of the cosine value (not needed by default)
     * \tparam V1 type of the \f$x\f$ vector (not needed by default)
     * \tparam T2 type of the sine value (not needed by default)
     * \tparam V2 type of the \f$y\f$ vector (not needed by default)
     */
        template<class T1, class V1, class T2, class V2>
        void rot (const T1 &t1, V1 &v1, const T2 &t2, V2 &v2)
    {
            typedef typename promote_traits<typename V1::value_type, typename V2::value_type>::promote_type promote_type;
            vector<promote_type> vt (t1 * v1 + t2 * v2);
            v2.assign (- t2 * v1 + t1 * v2);
            v1.assign (vt);
        }

    }

    /** \brief Interface and implementation of BLAS level 2
     * This includes functions which perform \b matrix-vector operations.
     * More information about BLAS can be found at
     * http://en.wikipedia.org/wiki/BLAS
     */
    namespace blas_2 {

       /** \brief multiply vector \c v with triangular matrix \c m
    *
    * \param v a vector
    * \param m a triangular matrix
    * \return the result of the product
    *
    * \tparam V type of the vector (not needed by default)
    * \tparam M type of the matrix (not needed by default)
        */
        template<class V, class M>
        V & tmv (V &v, const M &m)
    {
            return v = prod (m, v);
        }

        /** \brief solve \f$m.x = v\f$ in place, where \c m is a triangular matrix
     *
     * \param v a vector
     * \param m a matrix
     * \param C (this parameter is not needed)
     * \return a result vector from the above operation
     *
     * \tparam V type of the vector (not needed by default)
     * \tparam M type of the matrix (not needed by default)
     * \tparam C n/a
         */
        template<class V, class M, class C>
        V & tsv (V &v, const M &m, C)
    {
            return v = solve (m, v, C ());
        }

        /** \brief compute \f$ v_1 = t_1.v_1 + t_2.(m.v_2)\f$, a general matrix-vector product
     *
     * \param v1 a vector
     * \param t1 a scalar
     * \param t2 another scalar
     * \param m a matrix
     * \param v2 another vector
     * \return the vector \c v1 with the result from the above operation
     *
     * \tparam V1 type of first vector (not needed by default)
     * \tparam T1 type of first scalar (not needed by default)
     * \tparam T2 type of second scalar (not needed by default)
     * \tparam M type of matrix (not needed by default)
     * \tparam V2 type of second vector (not needed by default)
         */
        template<class V1, class T1, class T2, class M, class V2>
        V1 & gmv (V1 &v1, const T1 &t1, const T2 &t2, const M &m, const V2 &v2)
    {
            return v1 = t1 * v1 + t2 * prod (m, v2);
        }

        /** \brief Rank 1 update: \f$ m = m + t.(v_1.v_2^T)\f$
     *
     * \param m a matrix
     * \param t a scalar
     * \param v1 a vector
     * \param v2 another vector
     * \return a matrix with the result from the above operation
     *
     * \tparam M type of matrix (not needed by default)
     * \tparam T type of scalar (not needed by default)
     * \tparam V1 type of first vector (not needed by default)
     * \tparam V2type of second vector (not needed by default)
     */
        template<class M, class T, class V1, class V2>
        M & gr (M &m, const T &t, const V1 &v1, const V2 &v2)
    {
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
            return m += t * outer_prod (v1, v2);
#else
            return m = m + t * outer_prod (v1, v2);
#endif
        }

        /** \brief symmetric rank 1 update: \f$m = m + t.(v.v^T)\f$
     *
     * \param m a matrix
     * \param t a scalar
     * \param v a vector
     * \return a matrix with the result from the above operation
     *
     * \tparam M type of matrix (not needed by default)
     * \tparam T type of scalar (not needed by default)
     * \tparam V type of vector (not needed by default)
     */
        template<class M, class T, class V>
        M & sr (M &m, const T &t, const V &v)
    {
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
            return m += t * outer_prod (v, v);
#else
            return m = m + t * outer_prod (v, v);
#endif
        }

        /** \brief hermitian rank 1 update: \f$m = m + t.(v.v^H)\f$
     *
     * \param m a matrix
     * \param t a scalar
     * \param v a vector
     * \return a matrix with the result from the above operation
     *
     * \tparam M type of matrix (not needed by default)
     * \tparam T type of scalar (not needed by default)
     * \tparam V type of vector (not needed by default)
     */
        template<class M, class T, class V>
        M & hr (M &m, const T &t, const V &v)
    {
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
            return m += t * outer_prod (v, conj (v));
#else
            return m = m + t * outer_prod (v, conj (v));
#endif
        }

         /** \brief symmetric rank 2 update: \f$ m=m+ t.(v_1.v_2^T + v_2.v_1^T)\f$
      *
      * \param m a matrix
      * \param t a scalar
      * \param v1 a vector
      * \param v2 another vector
      * \return a matrix with the result from the above operation
      *
      * \tparam M type of matrix (not needed by default)
      * \tparam T type of scalar (not needed by default)
      * \tparam V1 type of first vector (not needed by default)
      * \tparam V2type of second vector (not needed by default)
          */
        template<class M, class T, class V1, class V2>
        M & sr2 (M &m, const T &t, const V1 &v1, const V2 &v2)
    {
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
            return m += t * (outer_prod (v1, v2) + outer_prod (v2, v1));
#else
            return m = m + t * (outer_prod (v1, v2) + outer_prod (v2, v1));
#endif
        }

        /** \brief hermitian rank 2 update: \f$m=m+t.(v_1.v_2^H) + v_2.(t.v_1)^H)\f$
     *
     * \param m a matrix
     * \param t a scalar
     * \param v1 a vector
     * \param v2 another vector
     * \return a matrix with the result from the above operation
     *
     * \tparam M type of matrix (not needed by default)
     * \tparam T type of scalar (not needed by default)
     * \tparam V1 type of first vector (not needed by default)
     * \tparam V2type of second vector (not needed by default)
         */
        template<class M, class T, class V1, class V2>
        M & hr2 (M &m, const T &t, const V1 &v1, const V2 &v2)
    {
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
            return m += t * outer_prod (v1, conj (v2)) + type_traits<T>::conj (t) * outer_prod (v2, conj (v1));
#else
            return m = m + t * outer_prod (v1, conj (v2)) + type_traits<T>::conj (t) * outer_prod (v2, conj (v1));
#endif
        }

    }

    /** \brief Interface and implementation of BLAS level 3
     * This includes functions which perform \b matrix-matrix operations.
     * More information about BLAS can be found at
     * http://en.wikipedia.org/wiki/BLAS
     */
    namespace blas_3 {

        /** \brief triangular matrix multiplication \f$m_1=t.m_2.m_3\f$ where \f$m_2\f$ and \f$m_3\f$ are triangular
     *
     * \param m1 a matrix for storing result
     * \param t a scalar
     * \param m2 a triangular matrix
     * \param m3 a triangular matrix
     * \return the matrix \c m1
     *
     * \tparam M1 type of the result matrix (not needed by default)
     * \tparam T type of the scalar (not needed by default)
     * \tparam M2 type of the first triangular matrix (not needed by default)
     * \tparam M3 type of the second triangular matrix (not needed by default)
     *
        */
        template<class M1, class T, class M2, class M3>
        M1 & tmm (M1 &m1, const T &t, const M2 &m2, const M3 &m3)
    {
            return m1 = t * prod (m2, m3);
        }

        /** \brief triangular solve \f$ m_2.x = t.m_1\f$ in place, \f$m_2\f$ is a triangular matrix
     *
     * \param m1 a matrix
     * \param t a scalar
     * \param m2 a triangular matrix
     * \param C (not used)
     * \return the \f$m_1\f$ matrix
     *
     * \tparam M1 type of the first matrix (not needed by default)
     * \tparam T type of the scalar (not needed by default)
     * \tparam M2 type of the triangular matrix (not needed by default)
     * \tparam C (n/a)
         */
        template<class M1, class T, class M2, class C>
        M1 & tsm (M1 &m1, const T &t, const M2 &m2, C)
    {
            return m1 = solve (m2, t * m1, C ());
        }

        /** \brief general matrix multiplication \f$m_1=t_1.m_1 + t_2.m_2.m_3\f$
     *
     * \param m1 first matrix
     * \param t1 first scalar
     * \param t2 second scalar
     * \param m2 second matrix
     * \param m3 third matrix
     * \return the matrix \c m1
     *
     * \tparam M1 type of the first matrix (not needed by default)
     * \tparam T1 type of the first scalar (not needed by default)
     * \tparam T2 type of the second scalar (not needed by default)
     * \tparam M2 type of the second matrix (not needed by default)
     * \tparam M3 type of the third matrix (not needed by default)
         */
        template<class M1, class T1, class T2, class M2, class M3>
        M1 & gmm (M1 &m1, const T1 &t1, const T2 &t2, const M2 &m2, const M3 &m3)
    {
            return m1 = t1 * m1 + t2 * prod (m2, m3);
        }

        /** \brief symmetric rank \a k update: \f$m_1=t.m_1+t_2.(m_2.m_2^T)\f$
     *
     * \param m1 first matrix
     * \param t1 first scalar
     * \param t2 second scalar
     * \param m2 second matrix
     * \return matrix \c m1
     *
     * \tparam M1 type of the first matrix (not needed by default)
     * \tparam T1 type of the first scalar (not needed by default)
     * \tparam T2 type of the second scalar (not needed by default)
     * \tparam M2 type of the second matrix (not needed by default)
     * \todo use opb_prod()
         */
        template<class M1, class T1, class T2, class M2>
        M1 & srk (M1 &m1, const T1 &t1, const T2 &t2, const M2 &m2)
    {
            return m1 = t1 * m1 + t2 * prod (m2, trans (m2));
        }

        /** \brief hermitian rank \a k update: \f$m_1=t.m_1+t_2.(m_2.m2^H)\f$
     *
     * \param m1 first matrix
     * \param t1 first scalar
     * \param t2 second scalar
     * \param m2 second matrix
     * \return matrix \c m1
     *
     * \tparam M1 type of the first matrix (not needed by default)
     * \tparam T1 type of the first scalar (not needed by default)
     * \tparam T2 type of the second scalar (not needed by default)
     * \tparam M2 type of the second matrix (not needed by default)
     * \todo use opb_prod()
         */
        template<class M1, class T1, class T2, class M2>
        M1 & hrk (M1 &m1, const T1 &t1, const T2 &t2, const M2 &m2)
    {
            return m1 = t1 * m1 + t2 * prod (m2, herm (m2));
        }

        /** \brief generalized symmetric rank \a k update: \f$m_1=t_1.m_1+t_2.(m_2.m3^T)+t_2.(m_3.m2^T)\f$
     *
     * \param m1 first matrix
     * \param t1 first scalar
     * \param t2 second scalar
     * \param m2 second matrix
     * \param m3 third matrix
     * \return matrix \c m1
     *
     * \tparam M1 type of the first matrix (not needed by default)
     * \tparam T1 type of the first scalar (not needed by default)
     * \tparam T2 type of the second scalar (not needed by default)
     * \tparam M2 type of the second matrix (not needed by default)
     * \tparam M3 type of the third matrix (not needed by default)
     * \todo use opb_prod()
         */
        template<class M1, class T1, class T2, class M2, class M3>
        M1 & sr2k (M1 &m1, const T1 &t1, const T2 &t2, const M2 &m2, const M3 &m3)
    {
            return m1 = t1 * m1 + t2 * (prod (m2, trans (m3)) + prod (m3, trans (m2)));
        }

        /** \brief generalized hermitian rank \a k update: * \f$m_1=t_1.m_1+t_2.(m_2.m_3^H)+(m_3.(t_2.m_2)^H)\f$
     *
     * \param m1 first matrix
     * \param t1 first scalar
     * \param t2 second scalar
     * \param m2 second matrix
     * \param m3 third matrix
     * \return matrix \c m1
     *
     * \tparam M1 type of the first matrix (not needed by default)
     * \tparam T1 type of the first scalar (not needed by default)
     * \tparam T2 type of the second scalar (not needed by default)
     * \tparam M2 type of the second matrix (not needed by default)
     * \tparam M3 type of the third matrix (not needed by default)
     * \todo use opb_prod()
         */
        template<class M1, class T1, class T2, class M2, class M3>
        M1 & hr2k (M1 &m1, const T1 &t1, const T2 &t2, const M2 &m2, const M3 &m3)
    {
            return m1 =
              t1 * m1
            + t2 * prod (m2, herm (m3))
            + type_traits<T2>::conj (t2) * prod (m3, herm (m2));
        }

    }

}}}

#endif


code:
#### Version 2.0.0-beta released on 13.09.16 ####

Added major features:
  - Axis tick and tick label generation was completely refactored and is now handled in the QCPAxisTicker class (also see QCPAxis::setTicker). Available ticker subclasses for special uses cases:
    QCPAxisTicker, QCPAxisTickerFixed, QCPAxisTickerLog, QCPAxisTickerPi, QCPAxisTickerTime, QCPAxisTickerDateTime, QCPAxisTickerText
  - Data container is now based on QCPDataContainer template for unified data interface and significantly improved memory footprint and better performance for common use-cases, especially data adding/removing.
  - New data selection mechanism allows selection of single data points and data ranges for plottables. See special documentation page "data selection mechanism".
  - Rubber band/selection rect for data point selection and axis zooming is now available, see documentation of QCustomPlot::setSelectionRectMode and QCPSelectionRect. For this purpose, the new default
    layer "overlay" was introduced, which is now the top layer, and holds the QCustomPlot's QCPSelectionRect instance.
  - Data sharing between plottables of the same type (see setData methods taking a QSharedPointer)
  - OpenGL hardware acceleration is now available across all Qt versions (including Qt4) in a unified, simple interface, with QCustomPlot::setOpenGl
  - QCPStatisticalBox can now display a series of statistical boxes instead of only a single one
  - New QCPErrorBars plottable allows attaching error bars to any one-dimensional plottable (QCPGraph has thus lost its own error-bar capability)
  - QCPColorMap now supports transparency via alpha in its color gradient stops, and via a dedicated cell-wise alpha map (see QCPColorMapData::setAlpha)
  - Layers may now be individually replotted (QCPLayer::replot), if the mode (QCPLayer::setMode) is set to lmBuffered. Mutually adjacent lmLogical layers share a single paint buffer to save resources.
    By default, the new topmost "overlay" layer which contains the selection rect is an lmBuffered layer. Updating the selection rect is thus very fast, independent of the plot contents.
  - QCPLayerable (and thus practically all objects in QCP) now have virtual methods to receive mouse press/move/release/doubleclick/wheel events. Before, only QCPLayoutElement provided them.
    this makes it much easier to subclass e.g. items and plottables to provide custom mouse interactions that were cumbersome and awkward with the simpler signal-based interface

Added minor features:
  - High-DPI support for Qt versions 5.0 and up, using device pixel ratio detected by Qt (can be changed manually via QCustomPlot::setBufferDevicePixelRatio).
  - QCPGraph and QCPCurve can now be configured to only display every n'th scatter symbol, see ::setScatterSkip() method
  - QCPFinancial allows to define bar width in absolute pixels and axis rect ratio, instead of only in plot key coordinates (see QCPFinancial::setWidthType)
  - Range dragging/zooming can now be configured to affect more than one axis per orientation (see new overloads of QCPAxisRect::setRangeDragAxes/setRangeZoomAxes)
  - Added QCPTextElement (replaces QCPPlotTitle) for general texts in layouts. Provides clicked and doubleClicked signals, as replacement for the removed QCustomPlot::titleClicked/titleDoubleClicked
  - Export functions (QCustomPlot::savePng etc.) now support specifying the resolution that will be written to the image file header. This improves operability with other tools which respect metadata.
  - Replots can now be queued to the next event loop iteration with replot(QCP::rpQueuedReplot). This way you can successively ask for a replot at multiple code locations without causing redundant replots
  - QCPAxisRect::zoom(...) allows to zoom to a specific rectangular region given in pixel coordinates, either affecting all axes or a specified subset of axes.
  - QCPRange::bounded returns a bounded range, trying to preserve its size. Works with rangeChanged signal to limit the allowed range (see rangeChanged doc)
  - Plottable rescaleValueAxis method (and getValueRange) now take parameter inKeyRange, which allows rescaling of the value axis only with respect to data in the currently visible key range
  - plottableClick and plottableDoubleClick signals now carry the clicked data point index as second parameter
  - Added QCPAxis::scaleRange overload without "center" argument, which scales around the current axis range center
  - Added QCPRange::expand/expanded overloads which take only one double parameter
  - Plottables addToLegend/removeFromLegend methods now have overloads that take any QCPLegend, to make working with non-default legends easier (legends that are not QCustomPlot::legend)
  - Added QCPStatisticalBox::setWhiskerAntialiased to allow controlling antialiasing state of whiskers independently of quartile box/median line
  - The virtual method QCPLayoutElement::layoutChanged() now allows subclasses to react on a move of the layout element between logical positions in the parent layout, or between layouts
  - QCPMarginGroup::commonMargin is now virtual, to facilitate subclassing of QCPMarginGroup
  - QCPGraph::getPreparedData is now virtual, and thus allows subclasses to easily generate own plotted data, e.g. on-the-fly.
  - Added QCPRange qDebug stream operator
  - QCPLayoutGrid (and thus QCPLegend) can now wrap rows or columns at specified row/column counts, see setFillOrder, setWrap and the new addElement overload which doesn't have row/column index

Bugfixes [Also backported to 1.3.2]:
  - Fixed possible crash when having a QCPGraph with scatters only and a non-transparent main/fill brush of the graph
  - Fixed QCPItemPixmap not updating internally cached scaled pixmap if new pixmap set with same scaled dimensions
  - When using log axis scale and zooming out as far as possible (~1e-280..1e280), axis doesn't end up in (via mouse) unrecoverable range with strange axis ticks anymore
  - Axis tick label algorithm for beautifully typeset powers now checks whether "e" in tick label is actually part of a number before converting the exponent to superscript
  - Fixed QCustomPlot::moveLayer performing incorrect move and possible crash in certain situations
  - Fixed possible crash on QCustomPlot destruction due to wrong QObject-hierarchy. Only occurs if a QCPAxisRect is removed from the normal QCustomPlot destruction hierarchy by taking it out of its layout
  - Fixed possible freeze when data values become infinity after coord-to-pixel transformation (e.g. maximally zoomed out log axis), and line style is not solid (e.g. dashed) or phFastPolylines is disabled
  - Fixed a few missing enums in meta type system, by unifying usage of Q_ENUMS, Q_FLAGS and Q_DECLARE_METATYPE
Bugfixes [Not in 1.3.2]:
  - Fixed QCPItemLine/QCPItemStraightLine not being selectable when defining coords are many orders of magnitude (>1e8) larger than currently viewed range
  - Fixed/worked around crash due to bug in QPainter::drawPixmap with very large negative x/y pixel coordinates, when drawing sparse pixmap scatters
  - Fixed possible (but unlikely) int overflow in adaptive sampling algorithm, that could cause plot artifacts when using extremely sparse data (with respect to current key axis range).
  - Fixed QCPBarsGroup bug which caused stPlotCoords spacing to be wrong with vertical key axes
  - A QCPBars axis rescale in the main window constructor (i.e. without well-defined plot size) now falls back to a datapoint-tight rescaling instead of doing nothing (because bar width can't be determined)
  - Improved QCPBars stacking when using bars with very large keys and key separation at limit of double precision

Summary of backward incompatible changes:
  Plottable related:
  - Removed QCustomPlot::addPlottable, not needed anymore as plottables now automatically register in their constructor
  - Removed QCustomPlot::addItem, not needed anymore as items now automatically register in their constructor
  - QCPAbstractPlottable::addToLegend/removeFromLegend are not virtual anymore. If your plottable requires a custom legend item, add it to the legend manually.
  - setData/addData method overloads of plottables have changed to facilitate data sharing and new data container (see documentation)
  - plottableClick and plottableDoubleClick signals now carry the clicked data point index as second parameter, and the QMouseEvent parameter has moved to third.
    Check all your usages of those signals, because Qt's connect method only reports problems during runtime!
  - setSelectable now not only limits what can be selected by the user, but limits also any programmatic selection changes via setSelected.
  - enum QCPAbstractPlottable::SignDomain has changed namespace to QCP::SignDomain
  Axis related:
  - Removed QCPAxis::setAutoTicks, setAutoTickCount, setAutoTickLabels, setAutoTickStep, setAutoSubTicks, setTickLabelType, setDateTimeFormat, setDateTimeSpec,
    setTickStep, setTickVector, setTickVectorLabels, setSubTickCount in favor of new QCPAxisTicker-based interface
  - Added QCPAxis::setSubTicks to enable/disable subticks (manually controlling the subtick count needs subclassing of QCPAxisTicker, e.g. QCPAxisTickerText and QCPAxisTickerLog provide setSubTickCount)
  Item related:
  - Renamed QCPAbstractItem::rectSelectTest to rectDistance, to prevent confusion with new QCPAbstractPlottable1D::selectTestRect
  - Renamed QCPItemAnchor::pixelPoint to QCPItemAnchor::pixelPosition (also affects subclass QCPItemPosition)
  General:
  - Renamed QCustomPlot::RefreshPriority enums (parameter of the replot() method): rpImmediate to rpImmediateRefresh, rpQueued to rpQueuedRefresh, rpHint to rpRefreshHint
  - Renamed QCustomPlot::PlottingHint enum phForceRepaint to phImmediateRefresh
  - Removed QCPPlotTitle layout element (See new QCPTextElement for almost drop-in replacement)
  - Removed signals QCustomPlot::titleClicked/titleDoubleClicked, replaced by QCPTextElement signals clicked/doubleClicked.
  - QCustomPlot::savePdf has changed parameters from (fileName, bool noCosmeticPen, width, height,...) to (fileName, width, height, QCP::ExportPen exportPen,...)
  - Virtual methods QCPLayoutElement::mouseMoveEvent/mouseReleaseEvent (which are now introduced already in the superclass QCPLayerable) have gained an additional parameter const QPointF &startPos.
    If you have reimplemented these methods, make sure to update your function signatures, otherwise your reimplementations will likely be ignored by the compiler without warning
  - Creating a new QCPColorGradient without supplying a preset parameter in the constructor now creates an empty gradient, instead of loading the gpCold preset

Other:
  - Replaced usage of Qt's QVector2D with own QCPVector2D which uses double precision and offers some convenience functions
  - Extended relative range to which QCPItemLine/QCPItemStraightLine can be zoomed before vanishing from ~1e9 to ~1e16
  - Removed QCPItemStraightLine::distToStraightLine (replaced by QCPVector2D::distanceToStraightLine)
  - Removed QCPAbstractPlottable::distSqrToLine and QCPAbstractItem::distSqrToLine (replaced by QCPVector2D::distanceSquaredToLine)
  - Qt5.5 compatibility (If you use PDF export, test your outputs, as output dimensions might change when switching Qt versions -- QCP does not try to emulate previous Qt version behaviour here)
  - QCP now includes <QtPrintSupport/QtPrintSupport> instead of just <QtPrintSupport> because some users had problems with the latter. Please report if you now experience issues due to the new include.
  - QCPGraph can now use a brush (filled polygon under the graph data) without having a graph line (line style lsNone)
  - QCPFinancial is now two-colored (setTwoColored(true)) by default, and has green/red as default two-colored brushes and pens
  - Plottable pixelsToCoords/coordsToPixels methods are now public, and offer transformations from pixel to plot coordinates and vice versa, using the plottable's axes
  - Plottable getKeyRange/getValueRange methods are now public
  - QCPBarsGroup now always places the QCPBars that was added to the group first towards lower keys, independent of axis orientation or direction (the ordering used to flip with axis orientation)
  - Default focus policy for QCustomPlot is now Qt::ClickFocus, instead of Qt::NoFocus.
  - tweaked QCPLegend and QCPAbstractLegendItem margins: The items have by default zero own margins, and QCPLegend row- and column spacing was increased to compensate. Legend was made slightly denser by default.
  - Used doxygen version is now 1.8.12, and documentation/postprocessing-scripts were adapted accordingly. Expect minor issues and some warnings when using older doxygen.

#### Version 1.3.2 released on 22.12.15 ####

  Bugfixes [Backported from 2.0.0 branch]:
    - Fixed possible crash when having a QCPGraph with scatters only and a non-transparent main/fill brush of the graph
    - Fixed QCPItemPixmap not updating internally cached scaled pixmap if new pixmap set with same scaled dimensions
    - When using log axis scale and zooming out as far as possible (~1e-280..1e280), axis doesn't end up in (via mouse) unrecoverable range with strange axis ticks anymore
    - Axis tick label algorithm for beautifully typeset powers now checks whether "e" in tick label is actually part of a number before converting the exponent to superscript
    - Fixed QCustomPlot::moveLayer performing incorrect move and possible crash in certain situations
    - Fixed possible crash on QCustomPlot destruction due to wrong QObject-hierarchy. Only occurs if a QCPAxisRect is removed from the normal QCustomPlot destruction hierarchy by taking it out of its layout
    - Fixed possible freeze when data values become infinity after coord-to-pixel transformation (e.g. maximally zoomed out log axis), and line style is not solid (e.g. dashed) or phFastPolylines is disabled

  Other [Backported from 2.0.0 branch]:
    - A few documentation fixes/improvements
    - Qt5.5 compatibility (If you use PDF export, test your outputs, as output dimensions might change when switching Qt versions -- QCP does not try to emulate previous Qt version behaviour here)
    - QCP now includes <QtPrintSupport/QtPrintSupport> instead of just <QtPrintSupport> because some users had problems with the latter. Please report if you now experience issues due to the new include.

#### Version 1.3.1 released on 25.04.15 ####

  Bugfixes:
    - Fixed bug that prevented automatic axis rescaling when some graphs/curves had only NaN data points
    - Improved QCPItemBracket selection boundaries, especially bsCurly and bsCalligraphic
    - Fixed bug of axis rect and colorscale background shifted downward by one logical pixel (visible in scaled png and pdf export)
    - Replot upon mouse release is now only performed if a selection change has actually happened (improves responsivity on particularly complex plots)
    - Fixed bug that allowed scatter-only graphs to be selected by clicking the non-existent line between scatters
    - Fixed crash when trying to select a scatter-only QCPGraph whose only points in the visible key range are at identical key coordinates and vertically off-screen, with adaptive sampling enabled
    - Fixed pdf export of QCPColorMap with enabled interpolation (didn't appear interpolated in pdf)
    - Reduced QCPColorMap jitter of internal cell boundaries for small sized maps when viewed with high zoom, by applying oversampling factors dependant on map size
    - Fixed bug of QCPColorMap::fill() not causing the buffered internal image map to be updated, and thus the change didn't become visible immediately
    - Axis labels with size set in pixels (setPixelSize) instead of points now correctly calculate the exponent's font size if beautifully typeset powers are enabled
    - Fixed QCPColorMap appearing at the wrong position for logarithmic axes and color map spanning larger ranges

  Other:
    - Pdf export used to embed entire QCPColorMaps, potentially leading to large files. Now only the visible portion of the map is embedded in the pdf
    - Many documentation fixes and extensions, style modernization
    - Reduced documentation file size (and thus full package size) by automatically reducing image palettes during package build
    - Fixed MSVC warning message (at warning level 4) due to temporary QLists in some foreach statements

#### Version 1.3.0 released on 27.12.14 ####

  Added features:
    - New plottable class QCPFinancial allows display of candlestick/ohlc data
    - New class QCPBarsGroup allows horizontal grouping of multiple QCPBars plottables
    - Added QCPBars feature allowing non-zero base values (see property QCPBars::setBaseValue)
    - Added QCPBars width type, for more flexible bar widths (see property QCPBars::setWidthType)
    - New QCPCurve optimization algorithm, fixes bug which caused line flicker at deep zoom into curve segment
    - Item positions can now have different position types and anchors for their x and y coordinates (QCPItemPosition::setTypeX/Y, setParentAnchorX/Y)
    - QCPGraph and QCPCurve can now display gaps in their lines, when inserting quiet NaNs as values (std::numeric_limits<double>::quiet_NaN())
    - QCPAxis now supports placing the tick labels inside the axis rect, for particularly space saving plots (QCPAxis::setTickLabelSide)
  Added features after beta:
    - Made code compatible with QT_NO_CAST_FROM_ASCII, QT_NO_CAST_TO_ASCII
    - Added compatibility with QT_NO_KEYWORDS after sending code files through a simple reg-ex script
    - Added possibility to inject own QCPAxis(-subclasses) via second, optional QCPAxisRect::addAxis parameter
    - Added parameter to QCPItemPixmap::setScaled to specify transformation mode

  Bugfixes:
    - Fixed bug in QCPCurve rendering of very zoomed-in curves (via new optimization algorithm)
    - Fixed conflict with MSVC-specific keyword "interface" in text-document-integration example
    - Fixed QCPScatterStyle bug ignoring the specified pen in the custom scatter shape constructor
    - Fixed bug (possible crash) during QCustomPlot teardown, when a QCPLegend that has no parent layout (i.e. was removed from layout manually) gets deleted
  Bugfixes after beta:
    - Fixed bug of QCPColorMap/QCPColorGradient colors being off by one color sampling step (only noticeable in special cases)
    - Fixed bug of QCPGraph adaptive sampling on vertical key axis, causing staggered look
    - Fixed low (float) precision in QCPCurve optimization algorithm, by not using QVector2D anymore

  Other:
    - Qt 5.3 and Qt 5.4 compatibility

#### Version 1.2.1 released on 07.04.14 ####

  Bugfixes:
    - Fixed regression which garbled date-time tick labels on axes, if setTickLabelType is ltDateTime and setNumberFormat contains the "b" option

#### Version 1.2.0 released on 14.03.14 ####

  Added features:
    - Adaptive Sampling for QCPGraph greatly improves performance for high data densities (see QCPGraph::setAdaptiveSampling)
    - QCPColorMap plottable with QCPColorScale layout element allows plotting of 2D color maps
    - QCustomPlot::savePdf now has additional optional parameters pdfCreator and pdfTitle to set according PDF metadata fields
    - QCustomPlot::replot now allows specifying whether the widget update is immediate (repaint) or queued (update)
    - QCPRange operators +, -, *, / with double operand for range shifting and scaling, and ==, != for range comparison
    - Layers now have a visibility property (QCPLayer::setVisible)
    - static functions QCPAxis::opposite and QCPAxis::orientation now offer more convenience when handling axis types
    - added notification signals for selectability change (selectableChanged) on all objects that have a selected/selectable property
    - added notification signal for QCPAxis scaleType property
    - added notification signal QCPLayerable::layerChanged

  Bugfixes:
    - Fixed assert halt, when QCPAxis auto tick labels not disabled but nevertheless a custom non-number tick label ending in "e" given
    - Fixed painting glitches when QCustomPlot resized inside a QMdiArea or under certain conditions inside a QLayout
    - If changing QCPAxis::scaleType and thus causing range sanitizing and a range modification, rangeChanged wouldn't be emitted
    - Fixed documentation bug that caused indentation to be lost in code examples
  Bugfixes after beta:
    - Fixed bug that caused crash if clicked-on legend item is removed in mousePressEvent.
    - On some systems, font size defaults to -1, which used to cause a debug output in QCPAxisPainterPrivate::TickLabelDataQCP. Now it's checked before setting values based on the default font size.
    - When using multiple axes on one side, setting one to invisible didn't properly compress the freed space.
    - Fixed bug that allowed selection of plottables when clicking in the bottom or top margin of a QCPAxisRect (outside the inner rect)

  Other:
    - In method QCPAbstractPlottable::getKeyRange/getValueRange, renamed parameter "validRange" to "foundRange", to better reflect its meaning (and contrast it from QCPRange::validRange)
    - QCPAxis low-level axis painting methods exported to QCPAxisPainterPrivate

#### Version 1.1.1 released on 09.12.13 ####

  Bugfixes:
    - Fixed bug causing legends blocking input events from reaching underlying axis rect even if legend is invisible
    - Added missing Q_PROPERTY for QCPAxis::setDateTimeSpec
    - Fixed behaviour of QCPAxisRect::setupFullAxesBox (now transfers more properties from bottom/left to top/right axes and sets visibility of bottom/left axes to true)
    - Made sure PDF export doesn't default to grayscale output on some systems

  Other:
    - Plotting hint QCP::phForceRepaint is now enabled on all systems (and not only on windows) by default
    - Documentation improvements

#### Version 1.1.0 released on 04.11.13 ####

  Added features:
    - Added QCPRange::expand and QCPRange::expanded
    - Added QCPAxis::rescale to rescale axis to all associated plottables
    - Added QCPAxis::setDateTimeSpec/dateTimeSpec to allow axis labels either in UTC or local time
    - QCPAxis now additionally emits a rangeChanged signal overload that provides the old range as second parameter

  Bugfixes:
    - Fixed QCustomPlot::rescaleAxes not rescaling properly if first plottable has an empty range
    - QCPGraph::rescaleAxes/rescaleKeyAxis/rescaleValueAxis are no longer virtual (never were in base class, was a mistake)
    - Fixed bugs in QCPAxis::items and QCPAxisRect::items not properly returning associated items and potentially stalling

  Other:
    - Internal change from QWeakPointer to QPointer, thus got rid of deprecated Qt functionality
    - Qt5.1 and Qt5.2 (beta1) compatibility
    - Release packages now extract to single subdirectory and don't place multiple files in current working directory

#### Version 1.0.1 released on 05.09.13 ####

  Bugfixes:
    - using define flag QCUSTOMPLOT_CHECK_DATA caused debug output when data was correct, instead of invalid (fixed QCP::isInvalidData)
    - documentation images are now properly shown when viewed with Qt Assistant
    - fixed various documentation mistakes

  Other:
    - Adapted documentation style sheet to better match Qt5 documentation

#### Version 1.0.0 released on 01.08.13 ####

  Quick Summary:
    - Layout system for multiple axis rects in one plot
    - Multiple axes per side
    - Qt5 compatibility
    - More flexible and consistent scatter configuration with QCPScatterStyle
    - Various interface cleanups/refactoring
    - Pixmap-cached axis labels for improved replot performance

  Changes that break backward compatibility:
    - QCustomPlot::axisRect() changed meaning due to the extensive changes to how axes and axis rects are handled
      it now returns a pointer to a QCPAxisRect and takes an integer index as parameter.
    - QCPAxis constructor changed to now take QCPAxisRect* as parent
    - setAutoMargin, setMarginLeft/Right/Top/Bottom removed due to the axis rect changes (see QCPAxisRect::setMargins/setAutoMargins)
    - setAxisRect removed due to the axis rect changes
    - setAxisBackground(-Scaled/-ScaledMode) now moved to QCPAxisRect as setBackground(-Scaled/ScaledMode) (access via QCustomPlot::axisRects())
    - QCPLegend now is a QCPLayoutElement
    - QCPAbstractPlottable::drawLegendIcon parameter "rect" changed from QRect to QRectF
    - QCPAbstractLegendItem::draw second parameter removed (position/size now handled via QCPLayoutElement base class)
    - removed QCPLegend::setMargin/setMarginLeft/Right/Top/Bottom (now inherits the capability from QCPLayoutElement::setMargins)
    - removed QCPLegend::setMinimumSize (now inherits the capability from QCPLayoutElement::setMinimumSize)
    - removed enum QCPLegend::PositionStyle, QCPLegend::positionStyle/setPositionStyle/position/setPosition (replaced by capabilities of QCPLayoutInset)
    - QCPLegend transformed to work with new layout system (almost everything changed)
    - removed entire title interface: QCustomPlot::setTitle/setTitleFont/setTitleColor/setTitleSelected/setTitleSelectedFont/setTitleSelectedColor and
      the QCustomPlot::iSelectTitle interaction flag (all functionality is now given by the layout element "QCPPlotTitle" which can be added to the plot layout)
    - selectTest functions now take two additional parameters: bool onlySelectable and QVariant *details=0
    - selectTest functions now ignores visibility of objects and (if parameter onlySelectable is true) does not anymore ignore selectability of the object
    - moved QCustomPlot::Interaction/Interactions to QCP namespace as QCP::Interaction/Interactions
    - moved QCustomPlot::setupFullAxesBox() to QCPAxisRect::setupFullAxesBox. Now also accepts parameter to decide whether to connect opposite axis ranges
    - moved range dragging/zooming interface from QCustomPlot to QCPAxisRect (setRangeDrag, setRangeZoom, setRangeDragAxes, setRangeZoomAxes,...)
    - rangeDrag/Zoom is now set to Qt::Horizontal|Qt::Vertical instead of 0 by default, on the other hand, iRangeDrag/Zoom is unset in interactions by
      default (this makes enabling dragging/zooming easier by just adding the interaction flags)
    - QCPScatterStyle takes over everything related to handling scatters in all plottables
    - removed setScatterPen/Size on QCPGraph and QCPCurve, removed setOutlierPen/Size on QCPStatisticalBox (now handled via QCPScatterStyle)
    - modified setScatterStyle on QCPGraph and QCPCurve, and setOutlierStyle on QCPStatisticalBox, to take QCPScatterStyle
    - axis grid and subgrid are now reachable via the QCPGrid *QCPAxis::grid() method. (e.g. instead of xAxis->setGrid(true), write xAxis->grid()->setVisible(true))

  Added features:
    - Axis tick labels are now pixmap-cached, thus increasing replot performance (in usual setups by about 24%). See plotting hint phCacheLabels which is set by default
    - Advanced layout system, including the classes QCPLayoutElement, QCPLayout, QCPLayoutGrid, QCPLayoutInset, QCPAxisRect
    - QCustomPlot::axisRects() returns all the axis rects in the QCustomPlot.
    - QCustomPlot::plotLayout() returns the top level layout (initially a QCPLayoutGrid with one QCPAxisRect inside)
    - QCPAxis now may have an offset to the axis rect (setOffset)
    - Multiple axes per QCPAxisRect side are now supported (see QCPAxisRect::addAxis)
    - QCustomPlot::toPixmap renders the plot into a pixmap and returns it
    - When setting tick label rotation to +90 or -90 degrees on a vertical axis, the labels are now centered vertically on the tick height
      (This allows space saving vertical tick labels by having the text direction parallel to the axis)
    - Substantially increased replot performance when using very large manual tick vectors (> 10000 ticks) via QCPAxis::setTickVector
    - QCPAxis and QCPAxisRect now allow easy access to all plottables(), graphs() and items() that are associated with them
    - Added QCustomPlot::hasItem method for consistency with plottable interface, hasPlottable
    - Added QCPAxisRect::setMinimumMargins as replacement for hardcoded minimum axis margin (15 px) when auto margin is enabled
    - Added Flags type QCPAxis::AxisTypes (from QCPAxis::AxisType), used in QCPAxisRect interface
    - Automatic margin calculation can now be enabled/disabled on a per-side basis, see QCPAxisRect::setAutoMargins
    - QCPAxisRect margins of multiple axis rects can be coupled via QCPMarginGroup
    - Added new default layers "background" and "legend" (QCPAxisRect draws its background on the "background" layer, QCPLegend is on the "legend" layer by default)
    - Custom scatter style via QCP::ssCustom and respective setCustomScatter functions that take a QPainterPath
    - Filled scatters via QCPScatterStyle::setBrush
  Added features after beta:
    - Added QCustomPlot::toPainter method, to allow rendering with existing painter
    - QCPItemEllipse now provides a center anchor

  Bugfixes:
    - Fixed compile error on ARM
    - Wrong legend icons were displayed if using pixmaps for scatters that are smaller than the legend icon rect
    - Fixed clipping inaccuracy for rotated tick labels (were hidden too early, because the non-rotated bounding box was used)
    - Fixed bug that caused wrong clipping of axis ticks and subticks when the ticks were given manually by QCPAxis::setTickVector
    - Fixed Qt5 crash when dragging graph out of view (iterator out of bounds in QCPGraph::getVisibleDataBounds)
    - Fixed QCPItemText not scaling properly when using scaled raster export
  Bugfixes after beta:
    - Fixed bug that clipped the rightmost pixel column of tick labels when caching activated (only visible on windows for superscript exponents)
    - Restored compatibility to Qt4.6
    - Restored support for -no-RTTI compilation
    - Empty manual tick labels are handled more gracefully (no QPainter qDebug messages anymore)
    - Fixed type ambiguity in QCPLineEnding::draw causing compile error on ARM
    - Fixed bug of grid layouts not propagating the minimum size from their child elements to the parent layout correctly
    - Fixed bug of child elements (e.g. axis rects) of inset layouts not properly receiving mouse events

  Other:
    - Opened up non-amalgamated project structure to public via git repository

#### Version released on 09.06.12 ####

  Quick Summary:
    - Items (arrows, text,...)
    - Layers (easier control over rendering order)
    - New antialiasing system (Each objects controls own antialiasing with setAntialiased)
    - Performance Improvements
    - improved pixel-precise drawing
    - easier shared library creation/usage

  Changes that (might) break backward compatibility:
    - enum QCPGraph::ScatterSymbol was moved to QCP namespace (now QCP::ScatterSymbol).
      This replace should fix your code: "QCPGraph::ss" -> "QCP::ss"
    - enum QCustomPlot::AntialiasedElement and flag QCustomPlot::AntialiasedElements was moved to QCP namespace
      This replace should fix your code: "QCustomPlot::ae" -> "QCP::ae"
    - the meaning of QCustomPlot::setAntialiasedElements has changed slightly: It is now an override to force elements to be antialiased. If you want to force
      elements to not be drawn antialiased, use the new setNotAntialiasedElements. If an element is mentioned in neither of those functions, it now controls
      its antialiasing itself via its "setAntialiased" function(s). (e.g. QCPAxis::setAntialiased(bool), QCPAbstractPlottable::setAntialiased(bool),
      QCPAbstractPlottable::setAntialiasedScatters(bool), etc.)
    - QCPAxis::setTickVector and QCPAxis::setTickVectorLabels no longer take a pointer but a const reference of the respective QVector as parameter.
      (handing over a pointer didn't give any noticeable performance benefits but was inconsistent with the rest of the interface)
    - Equally QCPAxis::tickVector and QCPAxis::tickVectorLabels don't return by pointer but by value now
    - QCustomPlot::savePngScaled was removed, its purpose is now included as optional parameter "scale" of savePng.
    - If you have derived from QCPAbstractPlottable: all selectTest functions now consistently take the argument "const QPointF &pos" which is the test point in pixel coordinates.
      (the argument there was "double key, double value" in plot coordinates, before).
    - QCPAbstractPlottable, QCPAxis and QCPLegend now inherit from QCPLayerable
    - If you have derived from QCPAbstractPlottable: the draw method signature has changed from "draw (..) const" to "draw (..)", i.e. the method
      is not const anymore. This allows the draw function of your plottable to perform buffering/caching operations, if necessary.

  Added features:
    - Item system: QCPAbstractItem, QCPItemAnchor, QCPItemPosition, QCPLineEnding. Allows placing of lines, arrows, text, pixmaps etc.
      - New Items: QCPItemStraightLine, QCPItemLine, QCPItemCurve, QCPItemEllipse, QCPItemRect, QCPItemPixmap, QCPItemText, QCPItemBracket, QCPItemTracer
      - QCustomPlot::addItem/itemCount/item/removeItem/selectedItems
      - signals QCustomPlot::itemClicked/itemDoubleClicked
      - the QCustomPlot interactions property now includes iSelectItems (for selection of QCPAbstractItem)
      - QCPLineEnding. Represents the different styles a line/curve can end (e.g. different arrows, circle, square, bar, etc.), see e.g. QCPItemCurve::setHead
    - Layer system: QCPLayerable, QCPLayer. Allows more sophisticated control over drawing order and a kind of grouping.
      - QCPAbstractPlottable, QCPAbstractItem, QCPAxis, QCPGrid, QCPLegend are layerables and derive from QCPLayerable
      - QCustomPlot::addLayer/moveLayer/removeLayer/setCurrentLayer/layer/currentLayer/layerCount
      - Initially there are three layers: "grid", "main", and "axes". The "main" layer is initially empty and set as current layer, so new plottables/items are put there.
    - QCustomPlot::viewport now makes the previously inaccessible viewport rect read-only-accessible (needed that for item-interface)
    - PNG export now allows transparent background by calling QCustomPlot::setColor(Qt::transparent) before savePng
    - QCPStatisticalBox outlier symbols may now be all scatter symbols, not only hardcoded circles.
    - perfect precision of scatter symbol/error bar drawing and clipping in both antialiased and non-antialiased mode, by introducing QCPPainter
      that works around some QPainter bugs/inconveniences. Further, more complex symbols like ssCrossSquare used to look crooked, now they look good.
    - new antialiasing control system: Each drawing element now has its own "setAntialiased" function to control whether it is drawn antialiased.
      - QCustomPlot::setAntialiasedElements and QCustomPlot::setNotAntialiasedElements can be used to override the individual settings.
      - Subclasses of QCPAbstractPlottable can now use the convenience functions like applyFillAntialiasingHint or applyScattersAntialiasingHint to
        easily make their drawing code comply with the overall antialiasing system.
    - QCustomPlot::setNoAntialiasingOnDrag allows greatly improved performance and responsiveness by temporarily disabling all antialiasing while
      the user is dragging axis ranges
    - QCPGraph can now show scatter symbols at data points and hide its line (see QCPGraph::setScatterStyle, setScatterSize, setScatterPixmap, setLineStyle)
    - Grid drawing code was sourced out from QCPAxis to QCPGrid. QCPGrid is mainly an internal class and every QCPAxis owns one. The grid interface still
      works through QCPAxis and hasn't changed. The separation allows the grid to be drawn on a different layer as the axes, such that e.g. a graph can
      be above the grid but below the axes.
    - QCustomPlot::hasPlottable(plottable), returns whether the QCustomPlot contains the plottable
    - QCustomPlot::setPlottingHint/setPlottingHints, plotting hints control details about the plotting quality/speed
    - export to jpg and bmp added (QCustomPlot::saveJpg/saveBmp), as well as control over compression quality for png and jpg
    - multi-select-modifier may now be specified with QCustomPlot::setMultiSelectModifier and is not fixed to Ctrl anymore

  Bugfixes:
    - fixed QCustomPlot ignores replot after it had size (0,0) even if size becomes valid again
    - on Windows, a repaint used to be delayed during dragging/zooming of a complex plot, until the drag operation was done.
      This was fixed, i.e. repaints are forced after a replot() call. See QCP::phForceRepaint and setPlottingHints.
    - when using the raster paintengine and exporting to scaled PNG, pen widths are now scaled correctly (QPainter bug workaround via QCPPainter)
    - PDF export now respects QCustomPlot background color (QCustomPlot::setColor), also Qt::transparent
    - fixed a bug on QCPBars and QCPStatisticalBox where auto-rescaling of axis would fail when all data is very small (< 1e-11)
    - fixed mouse event propagation bug that prevented range dragging from working on KDE (GNU/Linux)
    - fixed a compiler warning on 64-bit systems due to pointer cast to int instead of quintptr in a qDebug output

  Other:
    - Added support for easier shared library creation (including examples for compiling and using QCustomPlot as shared library)
    - QCustomPlot now has the Qt::WA_OpaquePaintEvent widget attribute (gives slightly improved performance).
    - QCP::aeGraphs (enum QCP::AntialiasedElement, previously QCustomPlot::aeGraphs) has been marked deprecated since version 02.02.12 and
      was now removed. Use QCP::aePlottables instead.
    - optional performance-quality-tradeoff for solid graph lines (see QCustomPlot::setPlottingHints).
    - marked data classes and QCPRange as Q_MOVABLE_TYPE
    - replaced usage of own macro FUNCNAME with Qt macro Q_FUNC_INFO
    - QCustomPlot now returns a minimum size hint of 50*50

#### Version released on 31.03.12 ####

  Changes that (might) break backward compatibility:
  - QCPAbstractLegendItem now inherits from QObject
  - mousePress, mouseMove and mouseRelease signals are now emitted before and not after any QCustomPlot processing (range dragging, selecting, etc.)

  Added features:
  - Interaction system: now allows selecting of objects like plottables, axes, legend and plot title, see QCustomPlot::setInteractions documentation
  - Interaction system for plottables:
    - setSelectable, setSelected, setSelectedPen, setSelectedBrush, selectTest on QCPAbstractPlottable and all derived plottables
    - setSelectionTolerance on QCustomPlot
    - selectedPlottables and selectedGraphs on QCustomPlot (returns the list of currently selected plottables/graphs)
  - Interaction system for axes:
    - setSelectable, setSelected, setSelectedBasePen, setSelectedTickPen, setSelectedSubTickPen, setSelectedLabelFont, setSelectedTickLabelFont,
      setSelectedLabelColor, setSelectedTickLabelColor, selectTest on QCPAxis
    - selectedAxes on QCustomPlot (returns a list of the axes that currently have selected parts)
  - Interaction system for legend:
    - setSelectable, setSelected, setSelectedBorderPen, setSelectedIconBorderPen, setSelectedBrush, setSelectedFont, setSelectedTextColor, selectedItems on QCPLegend
    - setSelectedFont, setSelectedTextColor, setSelectable, setSelected on QCPAbstractLegendItem
    - selectedLegends on QCustomPlot
  - Interaction system for title:
    - setSelectedTitleFont, setSelectedTitleColor, setTitleSelected on QCustomPlot
  - new signals in accordance with the interaction system:
    - selectionChangedByUser on QCustomPlot
    - selectionChanged on QCPAbstractPlottable
    - selectionChanged on QCPAxis
    - selectionChanged on QCPLegend and QCPAbstractLegendItem
    - plottableClick, legendClick, axisClick, titleClick, plottableDoubleClick, legendDoubleClick, axisDoubleClick, titleDoubleClick on QCustomPlot
  - QCustomPlot::deselectAll (deselects everything, i.e. axes and plottables)
  - QCPAbstractPlottable::pixelsToCoords (inverse function to the already existing coordsToPixels function)
  - QCPRange::contains(double value)
  - QCPAxis::setLabelColor and setTickLabelColor
  - QCustomPlot::setTitleColor
  - QCustomPlot now emits beforeReplot and afterReplot signals. Note that it is safe to make two customPlots mutually call eachothers replot functions
    in one of these slots, it will not cause an infinite loop. (usefull for synchronizing axes ranges between two customPlots, because setRange alone doesn't replot)
  - If the Qt version is 4.7 or greater, the tick label strings in date-time-mode now support sub-second accuracy (e.g. with format like "hh:mm:ss.zzz").

  Bugfixes:
  - tick labels/margins should no longer oscillate by one pixel when dragging range or replotting repeatedly while changing e.g. data. This
    was caused by a bug in Qt's QFontMetrics::boundingRect function when the font has an integer point size (probably some rounding problem).
    The fix hence consists of creating a temporary font (only for bounding-box calculation) which is 0.05pt larger and thus avoiding the
    jittering rounding outcome.
  - tick label, axis label and plot title colors used to be undefined. This was fixed by providing explicit color properties.

  Other:
  - fixed some glitches in the documentation
  - QCustomPlot::replot and QCustomPlot::rescaleAxes are now slots

#### Version released on 02.02.12 ####

  Changes that break backward compatibility:
  - renamed all secondary classes from QCustomPlot[...] to QCP[...]:
    QCustomPlotAxis -> QCPAxis
    QCustomPlotGraph -> QCPGraph
    QCustomPlotRange -> QCPRange
    QCustomPlotData -> QCPData
    QCustomPlotDataMap -> QCPDataMap
    QCustomPlotLegend -> QCPLegend
    QCustomPlotDataMapIterator -> QCPDataMapIterator
    QCustomPlotDataMutableMapIterator -> QCPDataMutableMapIterator
    A simple search and replace on all code files should make your code run again, e.g. consider the regex "QCustomPlot(?=[AGRDL])" -> "QCP".
    Make sure not to just replace "QCustomPlot" with "QCP" because the main class QCustomPlot hasn't changed to QCP.
    This change was necessary because class names became unhandy, pardon my bad naming decision in the beginning.
  - QCPAxis::tickLength() and QCPAxis::subTickLength() now each split into two functions for inward and outward ticks (tickLengthIn/tickLengthOut).
  - QCPLegend now uses QCPAbstractLegendItem to carry item data (before, the legend was passed QCPGraphs directly)
  - QCustomPlot::addGraph() now doesn't return the index of the created graph anymore, but a pointer to the created QCPGraph.
  - QCustomPlot::setAutoAddGraphToLegend is replaced by setAutoAddPlottableToLegend

  Added features:
  - Reversed axis range with QCPAxis::setRangeReversed(bool)
  - Tick labels are now only drawn if not clipped by the viewport (widget border) on the sides (e.g. left and right on a horizontal axis).
  - Zerolines. Like grid lines only with a separate pen (QCPAxis::setZeroLinePen), at tick position zero.
  - Outward ticks. QCPAxis::setTickLength/setSubTickLength now accepts two arguments for inward and outward tick length. This doesn't break
    backward compatibility because the second argument (outward) has default value zero and thereby a call with one argument hasn't changed its meaning.
  - QCPGraph now inherits from QCPAbstractPlottable
  - QCustomPlot::addPlottable/plottable/removePlottable/clearPlottables added to interface with the new QCPAbstractPlottable-based system. The simpler interface
    which only acts on QCPGraphs (addGraph, graph, removeGraph, etc.) was adapted internally and is kept for backward compatibility and ease of use.
  - QCPLegend items for plottables (e.g. graphs) can automatically wrap their texts to fit the widths, see QCPLegend::setMinimumSize and QCPPlottableLegendItem::setTextWrap.
  - QCustomPlot::rescaleAxes. Adapts axis ranges to show all plottables/graphs, by calling QCPAbstractPlottable::rescaleAxes on all plottables in the plot.
  - QCPCurve. For plotting of parametric curves.
  - QCPBars. For plotting of bar charts.
  - QCPStatisticalBox. For statistical box plots.

  Bugfixes:
  - Fixed QCustomPlot::removeGraph(int) not being able to remove graph index 0
  - made QCustomPlot::replot() abort painting when painter initialization fails (e.g. because width/height of QCustomPlot is zero)
  - The distance of the axis label from the axis ignored the tick label padding, this could have caused overlapping axis labels and tick labels
  - fixed memory leak in QCustomPlot (dtor didn't delete legend)
  - fixed bug that prevented QCPAxis::setRangeLower/Upper from setting the value to exactly 0.

  Other:
  - Changed default error bar handle size (QCustomPlotGraph::setErrorBarSize) from 4 to 6.
  - Removed QCustomPlotDataFetcher. Was deprecated and not used class.
  - Extended documentation, especially class descriptions.

#### Version released on 15.01.12 ####

  Changes that (might) break backward compatibility:
  - QCustomPlotGraph now inherits from QObject

  Added features:
  - Added axis background pixmap (QCustomPlot::setAxisBackground, setAxisBackgroundScaled, setAxisBackgroundScaledMode)
  - Added width and height parameter on PDF export function QCustomPlot::savePdf(). This now allows PDF export to
    have arbitrary dimensions, independent of the current geometry of the QCustomPlot.
  - Added overload of QCustomPlot::removeGraph that takes QCustomPlotGraph* as parameter, instead the index of the graph
  - Added all enums to the Qt meta system via Q_ENUMS(). The enums can now be transformed
    to QString values easily with the Qt meta system, which makes saving state e.g. as XML
    significantly nicer.
  - added typedef QMapIterator<double,QCustomPlotData> QCustomPlotDataMapIterator
    and typedef QMutableMapIterator<double,QCustomPlotData> QCustomPlotDataMutableMapIterator
    for improved information hiding, when using iterators outside QCustomPlot code

  Bugfixes:
  - Fixed savePngScaled. Axis/label drawing functions used to reset the painter transform
    and thereby break savePngScaled. Now they buffer the current transform and restore it afterwards.
  - Fixed some glitches in the doxygen comments (affects documentation only)

  Other:
  - Changed the default tickLabelPadding of top axis from 3 to 6 pixels. Looks better.
  - Changed the default QCustomPlot::setAntialiasedElements setting: Graph fills are now antialiased
    by default. That's a bit slower, but makes fill borders look better.

#### Version released on 19.11.11 ####

  Changes that break backward compatibility:
  - QCustomPlotAxis: tickFont and setTickFont renamed to tickLabelFont and setTickLabelFont (for naming consistency)

  Other:
  - QCustomPlotAxis: Added rotated tick labels, see setTickLabelRotation


code:
// -*- Mode: C++ -*-
#ifndef DISPLAYTEXT_H
#define DISPLAYTEXT_H

#include <QTextEdit>
#include <QFont>
#include <QHash>
#include <QPair>
#include <QString>

#include "logbook/logbook.h"
#include "decodedtext.h"

class QAction;

class DisplayText
  : public QTextEdit
{
  Q_OBJECT
public:
  explicit DisplayText(QWidget *parent = 0);

  void setContentFont (QFont const&);
  void insertLineSpacer(QString const&);
  void displayDecodedText(DecodedText const& decodedText, QString const& myCall, bool displayDXCCEntity,
        LogBook const& logBook, QColor color_CQ, QColor color_MyCall,
        QColor color_DXCC, QColor color_NewCall, bool ppfx, bool bCQonly=false);
  void displayTransmittedText(QString text, QString modeTx, qint32 txFreq,
			      QColor color_TxMsg, bool bFastMode);
  void displayQSY(QString text);
  void displayFoxToBeCalled(QString t, QColor bg);

  Q_SIGNAL void selectCallsign (Qt::KeyboardModifiers);
  Q_SIGNAL void erased ();

  Q_SLOT void appendText (QString const& text, QColor bg = Qt::white
                          , QString const& call1 = QString {}, QString const& call2 = QString {});
  Q_SLOT void erase ();
  Q_SLOT void highlight_callsign (QString const& callsign, QColor const& bg, QColor const& fg, bool last_only);

protected:
  void mouseDoubleClickEvent(QMouseEvent *e);

private:
  bool m_bPrincipalPrefix;
  QString appendDXCCWorkedB4(QString message, QString const& callsign, QColor * bg, LogBook const& logBook,
			     QColor color_CQ, QColor color_DXCC, QColor color_NewCall);

  QFont char_font_;
  QAction * erase_action_;
  QHash<QString, QPair<QColor, QColor>> highlighted_calls_;
};

#endif // DISPLAYTEXT_H


code:
// Copyright (C) 2004, 2005 Arkadiy Vertleyb
// Copyright (C) 2005 Peder Holt
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_TYPEOF_TYPEOF_IMPL_HPP_INCLUDED
#define BOOST_TYPEOF_TYPEOF_IMPL_HPP_INCLUDED

#include <boost/mpl/size_t.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/typeof/encode_decode.hpp>
#include <boost/typeof/vector.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/utility/enable_if.hpp>

#define BOOST_TYPEOF_VECTOR(n) BOOST_PP_CAT(boost::type_of::vector, n)

#define BOOST_TYPEOF_sizer_item(z, n, _)\
    char item ## n[V::item ## n ::value];

namespace boost { namespace type_of {
    template<class V>
    struct sizer
    {
        // char item0[V::item0::value];
        // char item1[V::item1::value];
        // ...

        BOOST_PP_REPEAT(BOOST_TYPEOF_LIMIT_SIZE, BOOST_TYPEOF_sizer_item, ~)
    };
}}

#undef BOOST_TYPEOF_sizer_item

//
namespace boost { namespace type_of {
# ifdef BOOST_NO_SFINAE
    template<class V, class T>
    sizer<typename encode_type<V, T>::type> encode(const T&);
# else
    template<class V, class T>
    typename enable_if<
        typename is_function<T>::type,
        sizer<typename encode_type<V, T>::type> >::type encode(T&);

    template<class V, class T>
    typename disable_if<
        typename is_function<T>::type,
        sizer<typename encode_type<V, T>::type> >::type encode(const T&);
# endif
}}
//
namespace boost { namespace type_of {

    template<class V>
    struct decode_begin
    {
        typedef typename decode_type<typename V::begin>::type type;
    };
}}

#define BOOST_TYPEOF_TYPEITEM(z, n, expr)\
    boost::mpl::size_t<sizeof(boost::type_of::encode<BOOST_TYPEOF_VECTOR(0)<> >(expr).item ## n)>

#define BOOST_TYPEOF_ENCODED_VECTOR(Expr)                                   \
    BOOST_TYPEOF_VECTOR(BOOST_TYPEOF_LIMIT_SIZE)<                           \
        BOOST_PP_ENUM(BOOST_TYPEOF_LIMIT_SIZE, BOOST_TYPEOF_TYPEITEM, Expr) \
    >

#define BOOST_TYPEOF(Expr)\
    boost::type_of::decode_begin<BOOST_TYPEOF_ENCODED_VECTOR(Expr) >::type

#define BOOST_TYPEOF_TPL typename BOOST_TYPEOF

//offset_vector is used to delay the insertion of data into the vector in order to allow
//encoding to be done in many steps
namespace boost { namespace type_of {
    template<typename V,typename Offset>
    struct offset_vector {
    };

    template<class V,class Offset,class T>
    struct push_back<boost::type_of::offset_vector<V,Offset>,T> {
        typedef offset_vector<V,typename Offset::prior> type;
    };

    template<class V,class T>
    struct push_back<boost::type_of::offset_vector<V,mpl::size_t<0> >,T> {
        typedef typename push_back<V,T>::type type;
    };
}}

#define BOOST_TYPEOF_NESTED_TYPEITEM(z, n, expr)\
    BOOST_STATIC_CONSTANT(int,BOOST_PP_CAT(value,n) = sizeof(boost::type_of::encode<_typeof_start_vector>(expr).item ## n));\
    typedef boost::mpl::size_t<BOOST_PP_CAT(self_t::value,n)> BOOST_PP_CAT(item,n);

#ifdef __DMC__
#define BOOST_TYPEOF_NESTED_TYPEITEM_2(z,n,expr)\
    typedef typename _typeof_encode_fraction<iteration>::BOOST_PP_CAT(item,n) BOOST_PP_CAT(item,n);

#define BOOST_TYPEOF_FRACTIONTYPE()\
    BOOST_PP_REPEAT(BOOST_TYPEOF_LIMIT_SIZE,BOOST_TYPEOF_NESTED_TYPEITEM_2,_)\
    typedef _typeof_fraction_iter<Pos> fraction_type;
#else
#define BOOST_TYPEOF_FRACTIONTYPE()\
    typedef _typeof_encode_fraction<self_t::iteration> fraction_type;
#endif

#ifdef __BORLANDC__
namespace boost { namespace type_of {
    template<typename Pos,typename Iter>
    struct generic_typeof_fraction_iter {
        typedef generic_typeof_fraction_iter<Pos,Iter> self_t;
        static const int pos=(Pos::value);
        static const int iteration=(pos/5);
        static const int where=pos%5;
        typedef typename Iter::template _apply_next<self_t::iteration>::type fraction_type;
        typedef generic_typeof_fraction_iter<typename Pos::next,Iter> next;
        typedef typename v_iter<fraction_type,mpl::int_<self_t::where> >::type type;
    };
}}
#define BOOST_TYPEOF_NESTED_TYPEDEF_IMPL(expr) \
        template<int _Typeof_Iteration>\
        struct _typeof_encode_fraction {\
            typedef _typeof_encode_fraction<_Typeof_Iteration> self_t;\
            BOOST_STATIC_CONSTANT(int,_typeof_encode_offset = (_Typeof_Iteration*BOOST_TYPEOF_LIMIT_SIZE));\
            typedef boost::type_of::offset_vector<BOOST_TYPEOF_VECTOR(0)<>,boost::mpl::size_t<self_t::_typeof_encode_offset> > _typeof_start_vector;\
            BOOST_PP_REPEAT(BOOST_TYPEOF_LIMIT_SIZE,BOOST_TYPEOF_NESTED_TYPEITEM,expr)\
            template<int Next>\
            struct _apply_next {\
                typedef _typeof_encode_fraction<Next> type;\
            };\
        };\
        template<typename Pos>\
        struct _typeof_fraction_iter {\
            typedef boost::type_of::generic_typeof_fraction_iter<Pos,_typeof_encode_fraction<0> > self_t;\
            typedef typename self_t::next next;\
            typedef typename self_t::type type;\
        };
#else
#define BOOST_TYPEOF_NESTED_TYPEDEF_IMPL(expr) \
        template<int _Typeof_Iteration>\
        struct _typeof_encode_fraction {\
            typedef _typeof_encode_fraction<_Typeof_Iteration> self_t;\
            BOOST_STATIC_CONSTANT(int,_typeof_encode_offset = (_Typeof_Iteration*BOOST_TYPEOF_LIMIT_SIZE));\
            typedef boost::type_of::offset_vector<BOOST_TYPEOF_VECTOR(0)<>,boost::mpl::size_t<self_t::_typeof_encode_offset> > _typeof_start_vector;\
            BOOST_PP_REPEAT(BOOST_TYPEOF_LIMIT_SIZE,BOOST_TYPEOF_NESTED_TYPEITEM,expr)\
        };\
        template<typename Pos>\
        struct _typeof_fraction_iter {\
            typedef _typeof_fraction_iter<Pos> self_t;\
            BOOST_STATIC_CONSTANT(int,pos=(Pos::value));\
            BOOST_STATIC_CONSTANT(int,iteration=(pos/BOOST_TYPEOF_LIMIT_SIZE));\
            BOOST_STATIC_CONSTANT(int,where=pos%BOOST_TYPEOF_LIMIT_SIZE);\
            BOOST_TYPEOF_FRACTIONTYPE()\
            typedef typename boost::type_of::v_iter<fraction_type,boost::mpl::int_<self_t::where> >::type type;\
            typedef _typeof_fraction_iter<typename Pos::next> next;\
        };
#endif
#ifdef __MWERKS__

# define BOOST_TYPEOF_NESTED_TYPEDEF(name,expr) \
template<typename T>\
struct BOOST_PP_CAT(_typeof_template_,name) {\
    BOOST_TYPEOF_NESTED_TYPEDEF_IMPL(expr)\
    typedef typename boost::type_of::decode_type<_typeof_fraction_iter<boost::mpl::size_t<0> > >::type type;\
};\
typedef BOOST_PP_CAT(_typeof_template_,name)<int> name;

# define BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr) BOOST_TYPEOF_NESTED_TYPEDEF(name,expr)

#else
# define BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr) \
    struct name {\
        BOOST_TYPEOF_NESTED_TYPEDEF_IMPL(expr)\
        typedef typename boost::type_of::decode_type<_typeof_fraction_iter<boost::mpl::size_t<0> > >::type type;\
    };

# define BOOST_TYPEOF_NESTED_TYPEDEF(name,expr) \
    struct name {\
        BOOST_TYPEOF_NESTED_TYPEDEF_IMPL(expr)\
        typedef boost::type_of::decode_type<_typeof_fraction_iter<boost::mpl::size_t<0> > >::type type;\
    };
#endif

#endif//BOOST_TYPEOF_COMPLIANT_TYPEOF_IMPL_HPP_INCLUDED