text:
///////////////////////////////////////////////////////////////////////////////
// extended_session.hpp
//
// unicomm - Unified Communication protocol C++ library.
//
// Unicomm extended session. Allows to map different event handlers via
// boost::signals and boost::function. Just an optional facade.
//
// 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)
//
// 2010, (c) Dmitry Timoshenko.

#ifdef _MSC_VER
# pragma once
#endif // _MSC_VER

#ifndef UNI_EXTENDED_SESSION_HPP_
#define UNI_EXTENDED_SESSION_HPP_

/** @file extended_session.hpp Extended session that
 *    allows to bind handlers to events.
 *
 *  Allows to map different event handlers via boost::signals
 *  and boost::function.
 */

#include <unicomm/basic.hpp>
#include <unicomm/basic_session.hpp>
#include <unicomm/comm.hpp>

#ifdef UNI_VISUAL_CPP
# pragma warning (push)
# pragma warning (disable : 4512) // warning C4512: 'boost::function_output_iterator<UnaryFunction>::output_proxy' : assignment operator could not be generated
# pragma warning (disable : 4244) // warning C4244: 'argument' : conversion from 'int' to 'unsigned short', possible loss of data
# pragma warning (disable : 4100) // warning C4100: 'is_group' : unreferenced formal parameter
#endif // UNI_VISUAL_CPP

#include <boost/system/error_code.hpp>
#include <boost/signals2.hpp>
#include <boost/thread/mutex.hpp>

#ifdef UNI_VISUAL_CPP
# pragma warning (pop)
#endif // UNI_VISUAL_CPP

#include <string>

/** @namespace unicomm Unicomm library root namespace. */
namespace unicomm
{

#ifdef _MSC_VER
# pragma warning (disable : 4505)  // warning C4505: 'unicomm::extended_session<DerivedT>::connected_handler' : unreferenced local function has been removed
#endif // _MSC_VER

// forward
class communicator;

/** @brief Session class which allows to map callable objects to events.
 *
 *  @tparam DerivedT Type that inherits extended_session.
 *  @tparam SessionParamsT Parameters type that will be passed to the
 *    session constructor. By default void_session_params is used.
 *
 *  @tparam BaseT Base type for the session. Default is session_base.
 */
template <
  typename DerivedT,
  typename SessionParamsT = void_session_params,
  typename BaseT = session_base>
class extended_session : public basic_session<DerivedT, SessionParamsT, BaseT>
{
//////////////////////////////////////////////////////////////////////////
// public interface
public:
  /** This type. */
  typedef extended_session<DerivedT, SessionParamsT, BaseT> this_type;

  /** Smart pointer to a session. */
  typedef boost::shared_ptr<this_type> pointer_type;

public:
  /** Default constructor. */
  extended_session(void) { /* empty */ }

  /** Constructor that takes extra session parameters.
   *
   *  @param extra_params Extra parameters having type SessionParamsT.
   */
  explicit extended_session(const SessionParamsT& extra_params):
    basic_session<DerivedT, SessionParamsT, BaseT>(extra_params)
  {
    // empty
  }

public:
  /** Adds connected handler.
   *
   *  The sequence of handlers is called when the event occurs.
   *
   *  @param handler Connected handler.
   *  @return An instance of boost::signals2::connection.
   *  @note To remove handler use returned boost::signals2::connection.
   *    More details on boost signals are available at http://boost.org.
   *
   *  @see session_base::connected_handler().
   */
  boost::signals2::connection
  add_connected_handler(const connected_signal_type::slot_type& handler);

  /** Adds disconnected handler.
   *
   *  The sequence of handlers is called when the event occurs.
   *
   *  @param handler Disconnected handler.
   *  @return An instance of boost::signals2::connection.
   *  @note To remove handler use returned boost::signals2::connection.
   *    More details on boost signals are available at http://boost.org.
   *
   *  @see session_base::disconnected_handler().
   */
  boost::signals2::connection
  add_disconnected_handler(const disconnected_signal_type::slot_type& handler);
  // fixme: Add remove connected/disconnected handler?

  /** Sets any message arrived handler.
   *
   *  This handler is called when message is arrived.
   *
   *  @param handler Message arrived handler.
   *  @see session_base::message_arrived_handler().
   */
  void set_any_message_arrived_handler(const message_arrived_handler_type& handler);

  /** Clears any message arrived handler.
   *
   *  @see session_base::message_arrived_handler().
   */
  void clear_any_message_arrived_handler(void);

  /** Maps message arrived handler to given name.
   *
   *  @param name Message name to map handler to.
   *  @param handler Message arrived handler.
   *  @note When message is received mapped handler is called first if there is.
   *    After that any message arrived handler is called.
   *
   *  @see session_base::message_arrived_handler().
   */
  void set_message_arrived_handler(const std::string& name,
                                   const message_arrived_handler_type& handler);

  /** Clears message arrived handler mapped to the given name.
   *
   *  @param name Name (identifier) of the message to clear handler mapped to.
   *  @see session_base::message_arrived_handler().
   */
  void clear_message_arrived_handler(const std::string& name);

  /** Sets message sent handler.
   *
   *  This handler is called after the handler mapped to specific
   *  message id is called.
   *
   *  @param handler Message sent handler.
   *  @note Sent handler can be mapped to certain message by using
   *    unicomm::dispatcher::send_one() and unicomm::dispatcher::send_all().
   *
   *  @see session_base::message_sent_handler().
   */
  void set_message_sent_handler(const message_sent_handler_type& handler);

  /** Clears message sent handler.
   *
   *  @see session_base::message_sent_handler().
   */
  void clear_message_sent_handler(void);

  /** Sets message timeout handler.
   *
   *  If timeouts enabled this handler is called instead handler is ignored.
   *
   *  @param handler Message timeout handler.
   *  @see session_base::message_timeout_handler().
   */
  void set_message_timeout_handler(const message_timeout_handler_type& handler);

  /** Clears message timeout handler.
   *
   *  @see session_base::message_timeout_handler().
   */
  void clear_message_timeout_handler(void);

  /** Sets error handler.
   *
   *  If any error occurs in working thread this handler is called.
   *  The handler is called from catch block, so it possible to
   *  rethrow and catch the exception to obtain exception type information.
   *
   *  @param handler Error handler.
   *
   *  @see session_base::error_handler().
   */
  void set_error_handler(const error_handler_type& handler);

  /** Clears error handler. */
  void clear_error_handler(void);

  /** Sets after processed handler.
   *
   *  Called when all the operations completed.
   *  At the end of communicator::process().
   *
   *  @param handler After processed handler.
   *  @see session_base::after_processed_handler().
   */
  void set_after_processed_handler(const after_processed_handler_type& handler);

  /** Clears after processed handler.
   *
   *  @see session_base::after_processed_handler().
   */
  void clear_after_processed_handler(void);

//////////////////////////////////////////////////////////////////////////
// protected interface
protected:
  //////////////////////////////////////////////////////////////////////////
  // virtual unicomm handlers, lowest level

  /** Connected handler.
   *
   *  Calls connected signal.
   *
   *  @param params Connected handler parameters.
   *  @see session_base::connected_handler().
   */
  void connected_handler(const connected_params& params);

  /** Disconnected handler.
   *
   *  @param params Disconnected handler parameters.
   *  @see session_base::disconnected_handler().
   */
  void disconnected_handler(const disconnected_params& params);

  /** Message arrived handler.
   *
   *  @param params Message arrived handler parameters.
   *  @see session_base::message_arrived_handler().
   */
  void message_arrived_handler(message_arrived_params& params);

  /** Message is actually sent handler.
   *
   *  @param params Message sent handler parameters.
   *  @see session_base::message_sent_handler().
   */
  void message_sent_handler(const message_sent_params& params);

  /** Message timeout handler.
   *
   *  @param params Message timeout handler parameters.
   *  @see session_base::message_timeout_handler().
   */
  void message_timeout_handler(const message_timeout_params& params);

  /** Error handler.
   *
   *  @param params Error handler parameters.
   *  @see session_base::error_handler().
   */
  void error_handler(const error_params& params);

  /** After processed handler.
   *
   *  @param params After processed handler parameters.
   *  @see session_base::after_processed_handler().
   */
  void after_processed_handler(const after_processed_params& params);

//////////////////////////////////////////////////////////////////////////
// private stuff
private:
  /** Maps handler to the given message identifier.
   *
   *  Register message sent handler with given message id. When message is sent
   *  this handler (if not null) called first, then called common message sent handler.
   *
   *  @param mid Message id to map the handler to.
   *  @param handler Message sent handler.
   */
  void reg_messsage_sent(const messageid_type& mid,
    const message_sent_handler_type& handler);

private:
  //////////////////////////////////////////////////////////////////////////
  // aux
  const message_arrived_handler_type find_message_arrived_handler(
    const std::string& name) const;
  const message_sent_handler_type find_message_sent_handler(
    const messageid_type& mid);
  const message_arrived_handler_type get_any_message_arrived_handler(void) const;
  const message_sent_handler_type get_message_sent_handler(void) const;
  const message_timeout_handler_type get_message_timeout_handler(void);
  const error_handler_type get_error_handler(void) const;
  const after_processed_handler_type get_after_processed_handler(void) const;

  //////////////////////////////////////////////////////////////////////////
  // handler callers
  void call_message_arrived(message_arrived_params& params);
  void call_connected(const connected_params& params);
  void call_disconnected(const disconnected_params& params);
  void call_message_sent(const message_sent_params& params);
  void call_message_timeout(const message_timeout_params& params);
  void call_error(const error_params& params);
  void call_after_processed(const after_processed_params& params);

  //////////////////////////////////////////////////////////////////////////
  // misc
  void unreg_message_sent(const messageid_type& mid);
  bool is_message_sent_registered(messageid_type mid) const;

private:
  //////////////////////////////////////////////////////////////////////////
  // data
  //mutable boost::recursive_mutex _mutex; //
  mutable boost::mutex _mutex;
  message_arrived_handlers_collection_type _mes_arrived_handlers;
  message_arrived_handler_type _any_mes_arrived_handler;
  message_sent_handlers_collection_type _sent_handlers;
  message_sent_handler_type _def_message_sent_handler;
  //message_timeout_handlers_collection_type _timeout_handlers;
  message_timeout_handler_type _def_message_timeout_handler;
  error_handler_type _err_handler;
  after_processed_handler_type _after_processed_handler;
  connected_signal_type _connected_signal;
  disconnected_signal_type _disconnected_signal;
};

} // namespace unicomm

#include "extended_session.ipp"

#endif // UNI_EXTENDED_SESSION_HPP_

ext: hpp

max_stars_repo_name: Chrizzly/libunicomm

max_issues_repo_name: Chrizzly/libunicomm

max_forks_repo_name: Chrizzly/libunicomm


text:
#ifndef OSRM_EXTRACTION_TURN_HPP
#define OSRM_EXTRACTION_TURN_HPP

#include <boost/numeric/conversion/cast.hpp>

#include <extractor/guidance/intersection.hpp>

#include <cstdint>

namespace osrm
{
namespace extractor
{

struct ExtractionTurn
{
    ExtractionTurn(const guidance::ConnectedRoad &turn, bool has_traffic_light)
        : angle(180. - turn.angle), turn_type(turn.instruction.type),
          direction_modifier(turn.instruction.direction_modifier),
          has_traffic_light(has_traffic_light), weight(0.), duration(0.), source_restricted(false),
          target_restricted(false)
    {
    }

    const double angle;
    const guidance::TurnType::Enum turn_type;
    const guidance::DirectionModifier::Enum direction_modifier;
    const bool has_traffic_light;
    double weight;
    double duration;
    bool source_restricted;
    bool target_restricted;
};
}
}

#endif

max_stars_repo_name: mbeckem/msc

max_issues_repo_name: mbeckem/msc

max_forks_repo_name: mbeckem/msc


text:
/*********************************************************************************
 *  OKVIS - Open Keyframe-based Visual-Inertial SLAM
 *  Copyright (c) 2015, Autonomous Systems Lab / ETH Zurich
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *   * Neither the name of Autonomous Systems Lab / ETH Zurich nor the names of
 *     its contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 *  Created on: Jan 29, 2015
 *      Author: Stefan Leutenegger (s.leutenegger@imperial.ac.uk)
 *********************************************************************************/

/**
 * @file DistortionBase.hpp
 * @brief Header file for the DistortionBase class.
 * @author Stefan Leutenegger
 */

#ifndef INCLUDE_VIO_CAMERAS_DISTORTIONBASE_HPP_
#define INCLUDE_VIO_CAMERAS_DISTORTIONBASE_HPP_

#include <Eigen/Core>
#include "CameraBase.hpp"
#include <glog/logging.h>
#include <string>

/// \brief vio Main namespace of this package.
namespace vio {
/// \brief cameras Namespace for camera-related functionality.
namespace cameras {

/// \class DistortionBase
/// \brief Base class for all distortion models.
class DistortionBase {
 public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW

  /// \brief Destructor -- not doing anything
  virtual ~DistortionBase() {
  }

  //////////////////////////////////////////////////////////////
  /// \name Methods related to generic parameters
  /// @{

  /// \brief set the generic parameters
  /// @param[in] parameters Parameter vector -- length must correspond numDistortionIntrinsics().
  /// @return    True if the requirements were followed.
  virtual bool setParameters(const Eigen::VectorXd & parameters) = 0;

  /// \brief Obtain the generic parameters.
  virtual bool getParameters(Eigen::VectorXd & parameters) const = 0;  // NOLINT

  /// \brief The derived class type.
  virtual std::string type() const = 0;

  /// \brief Number of derived class distortion parameters
  virtual int numDistortionIntrinsics() const = 0;
  /// @}

  //////////////////////////////////////////////////////////////
  /// \name Distortion functions
  /// @{

  /// \brief Distortion only
  /// @param[in]  pointUndistorted The undistorted normalised (!) image point.
  /// @param[out] pointDistorted   The distorted normalised (!) image point.
  /// @return     True on success (no singularity)
  virtual bool distort(const Eigen::Vector2f & pointUndistorted,
                       Eigen::Vector2f * pointDistorted) const {
    LOG(FATAL) << "not implemented in derived class";
    return false;
  }
  virtual bool distort(const Eigen::Vector2d & pointUndistorted,
                       Eigen::Vector2d * pointDistorted) const = 0;

  /// \brief Distortion and Jacobians.
  /// @param[in]  pointUndistorted  The undistorted normalised (!) image point.
  /// @param[out] pointDistorted    The distorted normalised (!) image point.
  /// @param[out] pointJacobian     The Jacobian w.r.t. changes on the image point.
  /// @param[out] parameterJacobian The Jacobian w.r.t. changes on the intrinsics vector.
  /// @return     True on success (no singularity)
  virtual bool distort(const Eigen::Vector2f & pointUndistorted,
                       Eigen::Vector2f * pointDistorted,
                       Eigen::Matrix2f * pointJacobian,
                       Eigen::Matrix2Xf * parameterJacobian = NULL) const {
    LOG(FATAL) << "not implemented in derived class";
    return false;
  }
  virtual bool distort(const Eigen::Vector2d & pointUndistorted,
                       Eigen::Vector2d * pointDistorted,
                       Eigen::Matrix2d * pointJacobian,
                       Eigen::Matrix2Xd * parameterJacobian = NULL) const = 0;

  /// \brief Distortion and Jacobians using external distortion intrinsics parameters.
  /// @param[in]  pointUndistorted  The undistorted normalised (!) image point.
  /// @param[in]  parameters        The distortion intrinsics vector.
  /// @param[out] pointDistorted    The distorted normalised (!) image point.
  /// @param[out] pointJacobian     The Jacobian w.r.t. changes on the image point.
  /// @param[out] parameterJacobian The Jacobian w.r.t. changes on the intrinsics vector.
  /// @return     True on success (no singularity)
  virtual bool distortWithExternalParameters(
      const Eigen::Vector2d & pointUndistorted,
      const Eigen::VectorXd & parameters, Eigen::Vector2d * pointDistorted,
      Eigen::Matrix2d * pointJacobian = NULL,
      Eigen::Matrix2Xd * parameterJacobian = NULL) const = 0;
  /// @}

  //////////////////////////////////////////////////////////////
  /// \name Undistortion functions
  /// @{

  /// \brief Undistortion only
  /// @param[in]  pointDistorted   The distorted normalised (!) image point.
  /// @param[out] pointUndistorted The undistorted normalised (!) image point.
  /// @return     True on success (no singularity)
  virtual bool undistort(const Eigen::Vector2d & pointDistorted,
                         Eigen::Vector2d * pointUndistorted) const = 0;
  virtual bool undistort(const Eigen::Vector2f & pointDistorted,
                         Eigen::Vector2f * pointUndistorted) const {
    LOG(FATAL) << "not implemented in derived class";
    return false;
  }
#ifdef __ARM_NEON__
  virtual void undistort4f(const float* uv_dist4f, float* uv_undist4f,
                           unsigned int status[4]) const {
    LOG(FATAL) << "not implemented in derived class";
  }
  virtual void undistort4f(const float* uv_dist4f, float* uv_undist4f,
                           float* jacobians_out, unsigned int status[4]) const {
    LOG(FATAL) << "not implemented in derived class";
  }
  virtual void distort4f(const float* uv_undist4f, float* uv_dist4f,
                         unsigned int status[4]) const {
    LOG(FATAL) << "not implemented in derived class";
  }
#endif

  /// \brief Undistortion only
  /// @param[in]  pointDistorted   The distorted normalised (!) image point.
  /// @param[out] pointUndistorted The undistorted normalised (!) image point.
  /// @param[out] pointJacobian    The Jacobian w.r.t. changes on the image point.
  /// @return     True on success (no singularity)
  virtual bool undistort(const Eigen::Vector2d & pointDistorted,
                         Eigen::Vector2d * pointUndistorted,
                         Eigen::Matrix2d * pointJacobian) const = 0;
  virtual bool undistort(const Eigen::Vector2f& pointDistorted,
                         Eigen::Vector2f* pointUndistorted,
                         Eigen::Matrix2f* pointJacobian) const = 0;
  /// @}
};

}  // namespace cameras
}  // namespace vio

#endif /* INCLUDE_VIO_CAMERAS_DISTORTIONBASE_HPP_ */

max_stars_repo_name: zjcs/ICE-BA

max_issues_repo_name: zjcs/ICE-BA

max_forks_repo_name: zjcs/ICE-BA


text:
#pragma once

#include <eosio/chain/controller.hpp>
#include <eosio/chain/fork_database.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <fc/bitutil.hpp>

namespace eosio {
    namespace chain {
        using boost::multi_index_container;
        using namespace boost::multi_index;
        using namespace std;

        using pbft_view_type = uint32_t;

        constexpr uint16_t oldest_stable_checkpoint = 10000;

        enum class pbft_message_type : uint8_t {
            prepare,
            commit,
            checkpoint,
            view_change,
            new_view
        };

        struct block_info_type {
            block_id_type   block_id;

            block_num_type  block_num() const {
                return fc::endian_reverse_u32(block_id._hash[0]);
            }

            bool operator==(const block_info_type& rhs) const {
                return block_id == rhs.block_id;
            }

            bool operator!=(const block_info_type& rhs) const {
                return !(*this == rhs);
            }

            bool empty() const {
                return block_id == block_id_type();
            }
        };

        using fork_info_type = vector<block_info_type>;

        struct pbft_message_common {
            explicit pbft_message_common(pbft_message_type t): type{t} {};

            pbft_message_type   type;
            time_point          timestamp = time_point::now();

            ~pbft_message_common() = default;
        };

        template<typename pbft_message_body>
        struct pbft_message_metadata {
            explicit pbft_message_metadata(pbft_message_body m, chain_id_type& chain_id): msg{m} {
                try {
                    sender_key = crypto::public_key(msg.sender_signature, msg.digest(chain_id), true);
                } catch (fc::exception & /*e*/) {
                    wlog("bad pbft message signature: ${m}", ("m", msg));
                }
            }

            pbft_message_body   msg;
            public_key_type     sender_key;
        };

        template<typename pbft_message_body>
        using pbft_metadata_ptr = std::shared_ptr<pbft_message_metadata<pbft_message_body>>;

        struct pbft_prepare {
            explicit pbft_prepare() = default;

            pbft_message_common common = pbft_message_common(pbft_message_type::prepare);
            pbft_view_type      view = 0;
            block_info_type     block_info;
            signature_type      sender_signature;

            bool operator<(const pbft_prepare& rhs) const {
                if (block_info.block_num() < rhs.block_info.block_num()) {
                    return true;
                } else if (block_info.block_num() == rhs.block_info.block_num()) {
                    return view < rhs.view;
                } else {
                    return false;
                }
            }

            bool empty() const {
                return !view
                && block_info.empty()
                && sender_signature == signature_type();
            }

            digest_type digest(chain_id_type chain_id) const {
                digest_type::encoder enc;
                fc::raw::pack(enc, chain_id);
                fc::raw::pack(enc, common);
                fc::raw::pack(enc, view);
                fc::raw::pack(enc, block_info);
                return enc.result();
            }
        };

        using pbft_prepare_ptr = std::shared_ptr<pbft_prepare>;

        struct pbft_commit {
            explicit pbft_commit() = default;

            pbft_message_common common = pbft_message_common(pbft_message_type::commit);
            pbft_view_type      view = 0;
            block_info_type     block_info;
            signature_type      sender_signature;

            bool operator<(const pbft_commit& rhs) const {
                if (block_info.block_num() < rhs.block_info.block_num()) {
                    return true;
                } else if (block_info.block_num() == rhs.block_info.block_num()) {
                    return view < rhs.view;
                } else {
                    return false;
                }
            }

            bool empty() const {
                return !view
                && block_info.empty()
                && sender_signature == signature_type();
            }

            digest_type digest(chain_id_type chain_id) const {
                digest_type::encoder enc;
                fc::raw::pack(enc, chain_id);
                fc::raw::pack(enc, common);
                fc::raw::pack(enc, view);
                fc::raw::pack(enc, block_info);
                return enc.result();
            }
        };

        using pbft_commit_ptr = std::shared_ptr<pbft_commit>;

        struct pbft_checkpoint {
            explicit pbft_checkpoint() = default;

            pbft_message_common common = pbft_message_common(pbft_message_type::checkpoint);
            block_info_type     block_info;
            signature_type      sender_signature;

            bool operator<(const pbft_checkpoint& rhs) const {
                return block_info.block_num() < rhs.block_info.block_num();
            }

            digest_type digest(chain_id_type chain_id) const {
                digest_type::encoder enc;
                fc::raw::pack(enc, chain_id);
                fc::raw::pack(enc, common);
                fc::raw::pack(enc, block_info);
                return enc.result();
            }
        };

        using pbft_checkpoint_ptr = std::shared_ptr<pbft_checkpoint>;

        struct pbft_stable_checkpoint {
            explicit pbft_stable_checkpoint() = default;

            block_info_type         block_info;
            vector<pbft_checkpoint> checkpoints;

            bool operator<(const pbft_stable_checkpoint& rhs) const {
                return block_info.block_num() < rhs.block_info.block_num();
            }

            bool empty() const {
                return block_info == block_info_type()
                && checkpoints.empty();
            }
        };

        struct pbft_prepared_certificate {
            explicit pbft_prepared_certificate() = default;

            block_info_type      block_info;
            set<block_id_type>   pre_prepares;
            vector<pbft_prepare> prepares;

            bool operator<(const pbft_prepared_certificate& rhs) const {
                return block_info.block_num() < rhs.block_info.block_num();
            }

            bool empty() const {
                return block_info == block_info_type()
                && prepares.empty();
            }
        };

        struct pbft_committed_certificate {
            explicit pbft_committed_certificate() = default;

            block_info_type     block_info;
            vector<pbft_commit> commits;

            bool operator<(const pbft_committed_certificate& rhs) const {
                return block_info.block_num() < rhs.block_info.block_num();
            }

            bool empty() const {
                return block_info == block_info_type()
                && commits.empty();
            }
        };

        struct pbft_view_change {
            explicit pbft_view_change() = default;

            pbft_message_common                 common = pbft_message_common(pbft_message_type::view_change);
            pbft_view_type                      current_view = 0;
            pbft_view_type                      target_view = 1;
            pbft_prepared_certificate           prepared_cert;
            vector<pbft_committed_certificate>  committed_certs;
            pbft_stable_checkpoint              stable_checkpoint;
            signature_type                      sender_signature;

            bool operator<(const pbft_view_change& rhs) const {
                return target_view < rhs.target_view;
            }

            digest_type digest(chain_id_type chain_id) const {
                digest_type::encoder enc;
                fc::raw::pack(enc, chain_id);
                fc::raw::pack(enc, common);
                fc::raw::pack(enc, current_view);
                fc::raw::pack(enc, target_view);
                fc::raw::pack(enc, prepared_cert);
                fc::raw::pack(enc, committed_certs);
                fc::raw::pack(enc, stable_checkpoint);
                return enc.result();
            }

            bool empty() const {
                return !current_view
                && target_view == 1
                && prepared_cert.empty()
                && committed_certs.empty()
                && stable_checkpoint.empty()
                && sender_signature == signature_type();
            }
        };

        using pbft_view_change_ptr = std::shared_ptr<pbft_view_change>;

        struct pbft_view_changed_certificate {
            explicit pbft_view_changed_certificate() = default;

            pbft_view_type              target_view = 0;
            vector<pbft_view_change>    view_changes;

            bool empty() const {
                return !target_view
                && view_changes.empty();
            }
        };

        struct pbft_new_view {
            explicit pbft_new_view() = default;

            pbft_message_common                 common = pbft_message_common(pbft_message_type::new_view);
            pbft_view_type                      new_view = 0;
            pbft_prepared_certificate           prepared_cert;
            vector<pbft_committed_certificate>  committed_certs;
            pbft_stable_checkpoint              stable_checkpoint;
            pbft_view_changed_certificate       view_changed_cert;
            signature_type                      sender_signature;

            bool operator<(const pbft_new_view& rhs) const {
                return new_view < rhs.new_view;
            }

            digest_type digest(chain_id_type chain_id) const {
                digest_type::encoder enc;
                fc::raw::pack(enc, chain_id);
                fc::raw::pack(enc, common);
                fc::raw::pack(enc, new_view);
                fc::raw::pack(enc, prepared_cert);
                fc::raw::pack(enc, committed_certs);
                fc::raw::pack(enc, stable_checkpoint);
                fc::raw::pack(enc, view_changed_cert);
                return enc.result();
            }

            bool empty() const {
                return !new_view
                && prepared_cert.empty()
                && committed_certs.empty()
                && stable_checkpoint.empty()
                && view_changed_cert.empty()
                && sender_signature == signature_type();
            }
        };

        using pbft_new_view_ptr = std::shared_ptr<pbft_new_view>;

        struct pbft_state {
            block_id_type                                                       block_id;
            block_num_type                                                      block_num = 0;
            flat_map<std::pair<pbft_view_type, public_key_type>, pbft_prepare>  prepares;
            bool                                                                is_prepared = false;
            flat_map<std::pair<pbft_view_type, public_key_type>, pbft_commit>   commits;
            bool                                                                is_committed = false;
        };

        struct pbft_view_change_state {
            pbft_view_type                              view;
            flat_map<public_key_type, pbft_view_change> view_changes;
            bool                                        is_view_changed = false;
        };

        struct pbft_checkpoint_state {
            block_id_type                               block_id;
            block_num_type                              block_num = 0;
            flat_map<public_key_type, pbft_checkpoint>  checkpoints;
            bool                                        is_stable = false;
        };

        using producer_and_block_info = std::pair<public_key_type, block_info_type>;

        struct validation_state {
            block_id_type           block_id;
            block_num_type          block_num = 0;
            vector<public_key_type> producers;
            bool                    enough = false;
        };

        using pbft_state_ptr = std::shared_ptr<pbft_state>;
        using pbft_view_change_state_ptr = std::shared_ptr<pbft_view_change_state>;
        using pbft_checkpoint_state_ptr = std::shared_ptr<pbft_checkpoint_state>;
        using validation_state_ptr = std::shared_ptr<validation_state>;

        struct by_block_id;
        struct by_num;
        struct by_prepare_and_num;
        struct by_commit_and_num;
        typedef multi_index_container<
                pbft_state_ptr,
                indexed_by<
                        hashed_unique <
                                tag<by_block_id>,
                                member<pbft_state, block_id_type, &pbft_state::block_id>,
                                std::hash<block_id_type>
                        >,
                        ordered_non_unique<
                                tag<by_num>,
                                member<pbft_state, uint32_t, &pbft_state::block_num>,
                                less<>
                        >,
                        ordered_non_unique<
                                tag<by_prepare_and_num>,
                                composite_key<
                                        pbft_state,
                                        member<pbft_state, bool, &pbft_state::is_prepared>,
                                        member<pbft_state, uint32_t, &pbft_state::block_num>
                                >,
                                composite_key_compare< greater<>, greater<> >
                        >,
                        ordered_non_unique<
                                tag<by_commit_and_num>,
                                composite_key<
                                        pbft_state,
                                        member<pbft_state, bool, &pbft_state::is_committed>,
                                        member<pbft_state, uint32_t, &pbft_state::block_num>
                                >,
                                composite_key_compare< greater<>, greater<> >
                        >
                >
        > pbft_state_multi_index_type;

        struct by_view;
        struct by_count_and_view;
        typedef multi_index_container<
                pbft_view_change_state_ptr,
                indexed_by<
                        ordered_unique<
                                tag<by_view>,
                                member<pbft_view_change_state, pbft_view_type, &pbft_view_change_state::view>,
                                greater<>
                        >,
                        ordered_non_unique<
                                tag<by_count_and_view>,
                                composite_key<
                                        pbft_view_change_state,
                                        member<pbft_view_change_state, bool, &pbft_view_change_state::is_view_changed>,
                                        member<pbft_view_change_state, pbft_view_type, &pbft_view_change_state::view>
                                >,
                                composite_key_compare<greater<>, greater<>>
                        >
                >
        > pbft_view_state_multi_index_type;

        struct by_block_id;
        struct by_num;
        typedef multi_index_container<
                pbft_checkpoint_state_ptr,
                indexed_by<
                        hashed_unique<
                                tag<by_block_id>,
                                member<pbft_checkpoint_state, block_id_type, &pbft_checkpoint_state::block_id>,
                                std::hash<block_id_type>
                        >,
                        ordered_non_unique<
                                tag<by_num>,
                                member<pbft_checkpoint_state, uint32_t, &pbft_checkpoint_state::block_num>,
                                less<>
                        >
                >
        > pbft_checkpoint_state_multi_index_type;

        struct by_block_id;
        struct by_status_and_num;
        typedef multi_index_container<
                validation_state_ptr,
                indexed_by<
                        hashed_unique <
                                tag<by_block_id>,
                                member<validation_state, block_id_type, &validation_state::block_id>,
                                std::hash<block_id_type>
                        >,
                        ordered_non_unique<
                                tag<by_status_and_num>,
                                composite_key<
                                        validation_state,
                                        member<validation_state, bool, &validation_state::enough>,
                                        member<validation_state, uint32_t, &validation_state::block_num>
                                >,
                                composite_key_compare< greater<>, greater<> >
                        >
                >
        > local_state_multi_index_type;

        class pbft_database {
        public:
            explicit pbft_database(controller& ctrl);
            ~pbft_database();

            void add_pbft_prepare(const pbft_prepare& p, const public_key_type& pk);
            void add_pbft_commit(const pbft_commit& c, const public_key_type& pk);
            void add_pbft_view_change(const pbft_view_change& vc, const public_key_type& pk);
            void add_pbft_checkpoint(const pbft_checkpoint& cp, const public_key_type& pk);

            vector<pbft_prepare> generate_and_add_pbft_prepare(const pbft_prepare& cached_prepare = pbft_prepare());
            vector<pbft_commit> generate_and_add_pbft_commit(const pbft_commit& cached_commit = pbft_commit());
            vector<pbft_view_change> generate_and_add_pbft_view_change(
                    const pbft_view_change& cached_view_change = pbft_view_change(),
                    const pbft_prepared_certificate& ppc = pbft_prepared_certificate(),
                    const vector<pbft_committed_certificate>& pcc = vector<pbft_committed_certificate>{},
                    pbft_view_type target_view = 1);
            pbft_new_view generate_pbft_new_view(
                    const pbft_view_changed_certificate& vcc = pbft_view_changed_certificate(),
                    pbft_view_type new_view = 1);
            vector<pbft_checkpoint> generate_and_add_pbft_checkpoint();

            bool should_prepared();
            bool should_committed();
            pbft_view_type should_view_change();
            bool should_new_view(pbft_view_type target_view);

            //new view
            bool has_new_primary(const public_key_type& pk);
            pbft_view_type get_proposed_new_view_num();
            pbft_view_type get_committed_view();
            public_key_type get_new_view_primary_key(pbft_view_type target_view);

            void mark_as_prepared(const block_id_type& bid);
            void mark_as_committed(const block_id_type& bid);
            void commit_local();
            void checkpoint_local();

            //view change
            pbft_prepared_certificate generate_prepared_certificate();
            vector<pbft_committed_certificate> generate_committed_certificate();
            pbft_view_changed_certificate generate_view_changed_certificate(pbft_view_type target_view);
            bool should_stop_view_change(const pbft_view_change& vc);

            //validations
            bool is_valid_prepare(const pbft_prepare& p, const public_key_type& pk);
            bool is_valid_commit(const pbft_commit& c, const public_key_type& pk);
            bool is_valid_checkpoint(const pbft_checkpoint& cp, const public_key_type& pk);
            bool is_valid_view_change(const pbft_view_change& vc, const public_key_type& pk);
            void validate_new_view(const pbft_new_view& nv, const public_key_type& pk);
            bool is_valid_stable_checkpoint(const pbft_stable_checkpoint& scp, bool add_to_pbft_db = false);
            bool should_send_pbft_msg();
            bool should_recv_pbft_msg(const public_key_type& pub_key);

            bool pending_pbft_lib();
            chain_id_type& get_chain_id() { return chain_id; }
            pbft_stable_checkpoint get_stable_checkpoint_by_id(const block_id_type& block_id, bool incl_blk_extn = true);
            pbft_stable_checkpoint fetch_stable_checkpoint_from_blk_extn(const signed_block_ptr& b);

            void cleanup_on_new_view();
            void update_fork_schedules();
            uint16_t get_view_change_timeout() const;
            uint16_t get_checkpoint_interval() const;
            const pbft_view_type get_current_view() { return _current_view; }
            void set_current_view(pbft_view_type view) { _current_view = view; }

            //api related
            pbft_state_ptr get_pbft_state_by_id(const block_id_type& id) const;
            vector<pbft_checkpoint_state> get_checkpoints_by_num(block_num_type num) const;
            pbft_view_change_state_ptr get_view_changes_by_target_view(pbft_view_type tv) const;
            vector<block_num_type> get_pbft_watermarks() const;
            flat_map<public_key_type, uint32_t> get_pbft_fork_schedules() const;

            producer_schedule_type lscb_active_producers() const;
        private:
            controller&                                 ctrl;
            pbft_state_multi_index_type                 pbft_state_index;
            pbft_view_state_multi_index_type            view_state_index;
            pbft_checkpoint_state_multi_index_type      checkpoint_index;
            fc::path                                    pbft_db_dir;
            fc::path                                    checkpoints_dir;
            vector<block_num_type>                      prepare_watermarks;
            flat_map<public_key_type, block_num_type>   fork_schedules;
            chain_id_type                               chain_id = ctrl.get_chain_id();
            pbft_view_type                              _current_view = 0;

            block_info_type cal_pending_stable_checkpoint() const;
            bool is_less_than_high_watermark(block_num_type bnum);
            bool is_valid_prepared_certificate(const pbft_prepared_certificate& certificate, bool add_to_pbft_db = false);
            bool is_valid_committed_certificate(const pbft_committed_certificate& certificate, bool add_to_pbft_db = false, bool at_the_top = false);
            bool is_valid_longest_fork(const vector<producer_and_block_info>& producers, const block_info_type& cert_info, bool at_the_top = false);

            vector<block_num_type>& get_updated_watermarks();
            flat_map<public_key_type, uint32_t>& get_updated_fork_schedules();
            block_num_type get_current_pbft_watermark();

            void set(const pbft_state_ptr& s);
            void set(const pbft_checkpoint_state_ptr& s);
            void prune(const pbft_state_ptr& h);
            void prune(const pbft_checkpoint_state_ptr& h);
        };
    }
} /// namespace eosio::chain

FC_REFLECT(eosio::chain::block_info_type, (block_id))
FC_REFLECT_ENUM(eosio::chain::pbft_message_type, (prepare)(commit)(checkpoint)(view_change)(new_view))

FC_REFLECT(eosio::chain::pbft_message_common, (type)(timestamp))

FC_REFLECT_TEMPLATE((typename pbft_message_body), eosio::chain::pbft_message_metadata<pbft_message_body>, (msg)(sender_key))

FC_REFLECT(eosio::chain::pbft_prepare, (common)(view)(block_info)(sender_signature))
FC_REFLECT(eosio::chain::pbft_commit, (common)(view)(block_info)(sender_signature))
FC_REFLECT(eosio::chain::pbft_checkpoint,(common)(block_info)(sender_signature))
FC_REFLECT(eosio::chain::pbft_view_change, (common)(current_view)(target_view)(prepared_cert)(committed_certs)(stable_checkpoint)(sender_signature))
FC_REFLECT(eosio::chain::pbft_new_view, (common)(new_view)(prepared_cert)(committed_certs)(stable_checkpoint)(view_changed_cert)(sender_signature))

FC_REFLECT(eosio::chain::pbft_prepared_certificate, (block_info)(pre_prepares)(prepares))
FC_REFLECT(eosio::chain::pbft_committed_certificate,(block_info)(commits))
FC_REFLECT(eosio::chain::pbft_view_changed_certificate, (target_view)(view_changes))
FC_REFLECT(eosio::chain::pbft_stable_checkpoint, (block_info)(checkpoints))

FC_REFLECT(eosio::chain::pbft_state, (block_id)(block_num)(prepares)(is_prepared)(commits)(is_committed))
FC_REFLECT(eosio::chain::pbft_view_change_state, (view)(view_changes)(is_view_changed))
FC_REFLECT(eosio::chain::pbft_checkpoint_state, (block_id)(block_num)(checkpoints)(is_stable))
FC_REFLECT(eosio::chain::validation_state, (block_id)(block_num)(producers)(enough))


text:
// normal_misc_examples.cpp

// Copyright Paul A. Bristow 2007.

// Use, modification and distribution are 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)

// Example of using normal distribution.

// Note that this file contains Quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!

//[normal_basic1
/*`
First we need some includes to access the normal distribution
(and some std output of course).
*/

#include <boost/math/distributions/normal.hpp> // for normal_distribution
  using boost::math::normal; // typedef provides default type is double.

#include <iostream>
  using std::cout; using std::endl; using std::left; using std::showpoint; using std::noshowpoint;
#include <iomanip>
  using std::setw; using std::setprecision;
#include <limits>
  using std::numeric_limits;

int main()
{
  cout << "Example: Normal distribution, Miscellaneous Applications.";

  try
  {
    { // Traditional tables and values.
/*`Let's start by printing some traditional tables.
*/
      double step = 1.; // in z
      double range = 4; // min and max z = -range to +range.
      int precision = 17; // traditional tables are only computed to much lower precision.

      // Construct a standard normal distribution s
        normal s; // (default mean = zero, and standard deviation = unity)
        cout << "Standard normal distribution, mean = "<< s.mean()
          << ", standard deviation = " << s.standard_deviation() << endl;

/*` First the probability distribution function (pdf).
*/
      cout << "Probability distribution function values" << endl;
      cout << "  z " "      pdf " << endl;
      cout.precision(5);
      for (double z = -range; z < range + step; z += step)
      {
        cout << left << setprecision(3) << setw(6) << z << " "
          << setprecision(precision) << setw(12) << pdf(s, z) << endl;
      }
      cout.precision(6); // default
      /*`And the area under the normal curve from -[infin] up to z,
      the cumulative distribution function (cdf).
*/
      // For a standard normal distribution
      cout << "Standard normal mean = "<< s.mean()
        << ", standard deviation = " << s.standard_deviation() << endl;
      cout << "Integral (area under the curve) from - infinity up to z " << endl;
      cout << "  z " "      cdf " << endl;
      for (double z = -range; z < range + step; z += step)
      {
        cout << left << setprecision(3) << setw(6) << z << " "
          << setprecision(precision) << setw(12) << cdf(s, z) << endl;
      }
      cout.precision(6); // default

/*`And all this you can do with a nanoscopic amount of work compared to
the team of *human computers* toiling with Milton Abramovitz and Irene Stegen
at the US National Bureau of Standards (now [@http://www.nist.gov NIST]).
Starting in 1938, their "Handbook of Mathematical Functions with Formulas, Graphs and Mathematical Tables",
was eventually published in 1964, and has been reprinted numerous times since.
(A major replacement is planned at [@http://dlmf.nist.gov Digital Library of Mathematical Functions]).

Pretty-printing a traditional 2-dimensional table is left as an exercise for the student,
but why bother now that the Math Toolkit lets you write
*/
    double z = 2.;
    cout << "Area for z = " << z << " is " << cdf(s, z) << endl; // to get the area for z.
/*`
Correspondingly, we can obtain the traditional 'critical' values for significance levels.
For the 95% confidence level, the significance level usually called alpha,
is 0.05 = 1 - 0.95 (for a one-sided test), so we can write
*/
     cout << "95% of area has a z below " << quantile(s, 0.95) << endl;
   // 95% of area has a z below 1.64485
/*`and a two-sided test (a comparison between two levels, rather than a one-sided test)

*/
     cout << "95% of area has a z between " << quantile(s, 0.975)
       << " and " << -quantile(s, 0.975) << endl;
   // 95% of area has a z between 1.95996 and -1.95996
/*`

First, define a table of significance levels: these are the probabilities
that the true occurrence frequency lies outside the calculated interval.

It is convenient to have an alpha level for the probability that z lies outside just one standard deviation.
This will not be some nice neat number like 0.05, but we can easily calculate it,
*/
    double alpha1 = cdf(s, -1) * 2; // 0.3173105078629142
    cout << setprecision(17) << "Significance level for z == 1 is " << alpha1 << endl;
/*`
    and place in our array of favorite alpha values.
*/
    double alpha[] = {0.3173105078629142, // z for 1 standard deviation.
      0.20, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 };
/*`

Confidence value as % is (1 - alpha) * 100 (so alpha 0.05 == 95% confidence)
that the true occurrence frequency lies *inside* the calculated interval.

*/
    cout << "level of significance (alpha)" << setprecision(4) << endl;
    cout << "2-sided       1 -sided          z(alpha) " << endl;
    for (int i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i)
    {
      cout << setw(15) << alpha[i] << setw(15) << alpha[i] /2 << setw(10) << quantile(complement(s,  alpha[i]/2)) << endl;
      // Use quantile(complement(s, alpha[i]/2)) to avoid potential loss of accuracy from quantile(s,  1 - alpha[i]/2)
    }
    cout << endl;

/*`Notice the distinction between one-sided (also called one-tailed)
where we are using a > *or* < test (and not both)
and considering the area of the tail (integral) from z up to +[infin],
and a two-sided test where we are using two > *and* < tests, and thus considering two tails,
from -[infin] up to z low and z high up to +[infin].

So the 2-sided values alpha[i] are calculated using alpha[i]/2.

If we consider a simple example of alpha = 0.05, then for a two-sided test,
the lower tail area from -[infin] up to -1.96 is 0.025 (alpha/2)
and the upper tail area from +z up to +1.96 is also  0.025 (alpha/2),
and the area between -1.96 up to 12.96 is alpha = 0.95.
and the sum of the two tails is 0.025 + 0.025 = 0.05,

*/
//] [/[normal_basic1]

//[normal_basic2

/*`Armed with the cumulative distribution function, we can easily calculate the
easy to remember proportion of values that lie within 1, 2 and 3 standard deviations from the mean.

*/
    cout.precision(3);
    cout << showpoint << "cdf(s, s.standard_deviation()) = "
      << cdf(s, s.standard_deviation()) << endl;  // from -infinity to 1 sd
    cout << "cdf(complement(s, s.standard_deviation())) = "
      << cdf(complement(s, s.standard_deviation())) << endl;
    cout << "Fraction 1 standard deviation within either side of mean is "
      << 1 -  cdf(complement(s, s.standard_deviation())) * 2 << endl;
    cout << "Fraction 2 standard deviations within either side of mean is "
      << 1 -  cdf(complement(s, 2 * s.standard_deviation())) * 2 << endl;
    cout << "Fraction 3 standard deviations within either side of mean is "
      << 1 -  cdf(complement(s, 3 * s.standard_deviation())) * 2 << endl;

/*`
To a useful precision, the 1, 2 & 3 percentages are 68, 95 and 99.7,
and these are worth memorising as useful 'rules of thumb', as, for example, in
[@http://en.wikipedia.org/wiki/Standard_deviation standard deviation]:

[pre
Fraction 1 standard deviation within either side of mean is 0.683
Fraction 2 standard deviations within either side of mean is 0.954
Fraction 3 standard deviations within either side of mean is 0.997
]

We could of course get some really accurate values for these
[@http://en.wikipedia.org/wiki/Confidence_interval confidence intervals]
by using cout.precision(15);

[pre
Fraction 1 standard deviation within either side of mean is 0.682689492137086
Fraction 2 standard deviations within either side of mean is 0.954499736103642
Fraction 3 standard deviations within either side of mean is 0.997300203936740
]

But before you get too excited about this impressive precision,
don't forget that the *confidence intervals of the standard deviation* are surprisingly wide,
especially if you have estimated the standard deviation from only a few measurements.
*/
//] [/[normal_basic2]

//[normal_bulbs_example1
/*`
Examples from K. Krishnamoorthy, Handbook of Statistical Distributions with Applications,
ISBN 1 58488 635 8, page 125... implemented using the Math Toolkit library.

A few very simple examples are shown here:
*/
// K. Krishnamoorthy, Handbook of Statistical Distributions with Applications,
 // ISBN 1 58488 635 8, page 125, example 10.3.5
/*`Mean lifespan of 100 W bulbs is 1100 h with standard deviation of 100 h.
Assuming, perhaps with little evidence and much faith, that the distribution is normal,
we construct a normal distribution called /bulbs/ with these values:
*/
    double mean_life = 1100.;
    double life_standard_deviation = 100.;
    normal bulbs(mean_life, life_standard_deviation);
    double expected_life = 1000.;

/*`The we can use the Cumulative distribution function to predict fractions
(or percentages, if * 100) that will last various lifetimes.
*/
    cout << "Fraction of bulbs that will last at best (<=) " // P(X <= 1000)
      << expected_life << " is "<< cdf(bulbs, expected_life) << endl;
    cout << "Fraction of bulbs that will last at least (>) " // P(X > 1000)
      << expected_life << " is "<< cdf(complement(bulbs, expected_life)) << endl;
    double min_life = 900;
    double max_life = 1200;
    cout << "Fraction of bulbs that will last between "
      << min_life << " and " << max_life << " is "
      << cdf(bulbs, max_life)  // P(X <= 1200)
       - cdf(bulbs, min_life) << endl; // P(X <= 900)
/*`
[note Real-life failures are often very ab-normal,
with a significant number that 'dead-on-arrival' or suffer failure very early in their life:
the lifetime of the survivors of 'early mortality' may be well described by the normal distribution.]
*/
//] [/normal_bulbs_example1 Quickbook end]
  }
  {
    // K. Krishnamoorthy, Handbook of Statistical Distributions with Applications,
    // ISBN 1 58488 635 8, page 125, Example 10.3.6

//[normal_bulbs_example3
/*`Weekly demand for 5 lb sacks of onions at a store is normally distributed with mean 140 sacks and standard deviation 10.
*/
  double mean = 140.; // sacks per week.
  double standard_deviation = 10;
  normal sacks(mean, standard_deviation);

  double stock = 160.; // per week.
  cout << "Percentage of weeks overstocked "
    << cdf(sacks, stock) * 100. << endl; // P(X <=160)
  // Percentage of weeks overstocked 97.7

/*`So there will be lots of mouldy onions!
So we should be able to say what stock level will meet demand 95% of the weeks.
*/
  double stock_95 = quantile(sacks, 0.95);
  cout << "Store should stock " << int(stock_95) << " sacks to meet 95% of demands." << endl;
/*`And it is easy to estimate how to meet 80% of demand, and waste even less.
*/
  double stock_80 = quantile(sacks, 0.80);
  cout << "Store should stock " << int(stock_80) << " sacks to meet 8 out of 10 demands." << endl;
//] [/normal_bulbs_example3 Quickbook end]
  }
  { // K. Krishnamoorthy, Handbook of Statistical Distributions with Applications,
    // ISBN 1 58488 635 8, page 125, Example 10.3.7

//[normal_bulbs_example4

/*`A machine is set to pack 3 kg of ground beef per pack.
Over a long period of time it is found that the average packed was 3 kg
with a standard deviation of 0.1 kg.
Assuming the packing is normally distributed,
we can find the fraction (or %) of packages that weigh more than 3.1 kg.
*/

double mean = 3.; // kg
double standard_deviation = 0.1; // kg
normal packs(mean, standard_deviation);

double max_weight = 3.1; // kg
cout << "Percentage of packs > " << max_weight << " is "
<< cdf(complement(packs, max_weight)) << endl; // P(X > 3.1)

double under_weight = 2.9;
cout <<"fraction of packs <= " << under_weight << " with a mean of " << mean
  << " is " << cdf(complement(packs, under_weight)) << endl;
// fraction of packs <= 2.9 with a mean of 3 is 0.841345
// This is 0.84 - more than the target 0.95
// Want 95% to be over this weight, so what should we set the mean weight to be?
// KK StatCalc says:
double over_mean = 3.0664;
normal xpacks(over_mean, standard_deviation);
cout << "fraction of packs >= " << under_weight
<< " with a mean of " << xpacks.mean()
  << " is " << cdf(complement(xpacks, under_weight)) << endl;
// fraction of packs >= 2.9 with a mean of 3.06449 is 0.950005
double under_fraction = 0.05;  // so 95% are above the minimum weight mean - sd = 2.9
double low_limit = standard_deviation;
double offset = mean - low_limit - quantile(packs, under_fraction);
double nominal_mean = mean + offset;

normal nominal_packs(nominal_mean, standard_deviation);
cout << "Setting the packer to " << nominal_mean << " will mean that "
  << "fraction of packs >= " << under_weight
  << " is " << cdf(complement(nominal_packs, under_weight)) << endl;

/*`
Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95.

Setting the packer to 3.13263 will mean that fraction of packs >= 2.9 is 0.99,
but will more than double the mean loss from 0.0644 to 0.133.

Alternatively, we could invest in a better (more precise) packer with a lower standard deviation.

To estimate how much better (how much smaller standard deviation) it would have to be,
we need to get the 5% quantile to be located at the under_weight limit, 2.9
*/
double p = 0.05; // wanted p th quantile.
cout << "Quantile of " << p << " = " << quantile(packs, p)
  << ", mean = " << packs.mean() << ", sd = " << packs.standard_deviation() << endl; //
/*`
Quantile of 0.05 = 2.83551, mean = 3, sd = 0.1

With the current packer (mean = 3, sd = 0.1), the 5% quantile is at 2.8551 kg,
a little below our target of 2.9 kg.
So we know that the standard deviation is going to have to be smaller.

Let's start by guessing that it (now 0.1) needs to be halved, to a standard deviation of 0.05
*/
normal pack05(mean, 0.05);
cout << "Quantile of " << p << " = " << quantile(pack05, p)
  << ", mean = " << pack05.mean() << ", sd = " << pack05.standard_deviation() << endl;

cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean
  << " and standard deviation of " << pack05.standard_deviation()
  << " is " << cdf(complement(pack05, under_weight)) << endl;
//
/*`
Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.9772

So 0.05 was quite a good guess, but we are a little over the 2.9 target,
so the standard deviation could be a tiny bit more. So we could do some
more guessing to get closer, say by increasing to 0.06
*/

normal pack06(mean, 0.06);
cout << "Quantile of " << p << " = " << quantile(pack06, p)
  << ", mean = " << pack06.mean() << ", sd = " << pack06.standard_deviation() << endl;

cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean
  << " and standard deviation of " << pack06.standard_deviation()
  << " is " << cdf(complement(pack06, under_weight)) << endl;
/*`
Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.9522

Now we are getting really close, but to do the job properly,
we could use root finding method, for example the tools provided, and used elsewhere,
in the Math Toolkit, see
[link math_toolkit.toolkit.internals1.roots2  Root Finding Without Derivatives].

But in this normal distribution case, we could be even smarter and make a direct calculation.
*/

normal s; // For standard normal distribution,
double sd = 0.1;
double x = 2.9; // Our required limit.
// then probability p = N((x - mean) / sd)
// So if we want to find the standard deviation that would be required to meet this limit,
// so that the p th quantile is located at x,
// in this case the 0.95 (95%) quantile at 2.9 kg pack weight, when the mean is 3 kg.

double prob =  pdf(s, (x - mean) / sd);
double qp = quantile(s, 0.95);
cout << "prob = " << prob << ", quantile(p) " << qp << endl; // p = 0.241971, quantile(p) 1.64485
// Rearranging, we can directly calculate the required standard deviation:
double sd95 = abs((x - mean)) / qp;

cout << "If we want the "<< p << " th quantile to be located at "
  << x << ", would need a standard deviation of " << sd95 << endl;

normal pack95(mean, sd95);  // Distribution of the 'ideal better' packer.
cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean
  << " and standard deviation of " << pack95.standard_deviation()
  << " is " << cdf(complement(pack95, under_weight)) << endl;

// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0608 is 0.95

/*`Notice that these two deceptively simple questions
(do we over-fill or measure better) are actually very common.
The weight of beef might be replaced by a measurement of more or less anything.
But the calculations rely on the accuracy of the standard deviation - something
that is almost always less good than we might wish,
especially if based on a few measurements.
*/

//] [/normal_bulbs_example4 Quickbook end]
  }

  { // K. Krishnamoorthy, Handbook of Statistical Distributions with Applications,
    // ISBN 1 58488 635 8, page 125, example 10.3.8
//[normal_bulbs_example5
/*`A bolt is usable if between 3.9 and 4.1 long.
From a large batch of bolts, a sample of 50 show a
mean length of 3.95 with standard deviation 0.1.
Assuming a normal distribution, what proportion is usable?
The true sample mean is unknown,
but we can use the sample mean and standard deviation to find approximate solutions.
*/

    normal bolts(3.95, 0.1);
    double top = 4.1;
    double bottom = 3.9;

cout << "Fraction long enough [ P(X <= " << top << ") ] is " << cdf(bolts, top) << endl;
cout << "Fraction too short [ P(X <= " << bottom << ") ] is " << cdf(bolts, bottom) << endl;
cout << "Fraction OK  -between " << bottom << " and " << top
  << "[ P(X <= " << top  << ") - P(X<= " << bottom << " ) ] is "
  << cdf(bolts, top) - cdf(bolts, bottom) << endl;

cout << "Fraction too long [ P(X > " << top << ") ] is "
  << cdf(complement(bolts, top)) << endl;

cout << "95% of bolts are shorter than " << quantile(bolts, 0.95) << endl;

//] [/normal_bulbs_example5 Quickbook end]
  }
  }
  catch(const std::exception& e)
  { // Always useful to include try & catch blocks because default policies
    // are to throw exceptions on arguments that cause errors like underflow, overflow.
    // Lacking try & catch blocks, the program will abort without a message below,
    // which may give some helpful clues as to the cause of the exception.
    std::cout <<
      "\n""Message from thrown exception was:\n   " << e.what() << std::endl;
  }
  return 0;
}  // int main()

/*

Output is:

Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\normal_misc_examples.exe"
Example: Normal distribution, Miscellaneous Applications.Standard normal distribution, mean = 0, standard deviation = 1
Probability distribution function values
  z       pdf
-4     0.00013383022576488537
-3     0.0044318484119380075
-2     0.053990966513188063
-1     0.24197072451914337
0      0.3989422804014327
1      0.24197072451914337
2      0.053990966513188063
3      0.0044318484119380075
4      0.00013383022576488537
Standard normal mean = 0, standard deviation = 1
Integral (area under the curve) from - infinity up to z
  z       cdf
-4     3.1671241833119979e-005
-3     0.0013498980316300959
-2     0.022750131948179219
-1     0.1586552539314571
0      0.5
1      0.84134474606854293
2      0.97724986805182079
3      0.9986501019683699
4      0.99996832875816688
Area for z = 2 is 0.97725
95% of area has a z below 1.64485
95% of area has a z between 1.95996 and -1.95996
Significance level for z == 1 is 0.3173105078629142
level of significance (alpha)
2-sided       1 -sided          z(alpha)
0.3173         0.1587         1
0.2            0.1            1.282
0.1            0.05           1.645
0.05           0.025          1.96
0.01           0.005          2.576
0.001          0.0005         3.291
0.0001         5e-005         3.891
1e-005         5e-006         4.417
cdf(s, s.standard_deviation()) = 0.841
cdf(complement(s, s.standard_deviation())) = 0.159
Fraction 1 standard deviation within either side of mean is 0.683
Fraction 2 standard deviations within either side of mean is 0.954
Fraction 3 standard deviations within either side of mean is 0.997
Fraction of bulbs that will last at best (<=) 1.00e+003 is 0.159
Fraction of bulbs that will last at least (>) 1.00e+003 is 0.841
Fraction of bulbs that will last between 900. and 1.20e+003 is 0.819
Percentage of weeks overstocked 97.7
Store should stock 156 sacks to meet 95% of demands.
Store should stock 148 sacks to meet 8 out of 10 demands.
Percentage of packs > 3.10 is 0.159
fraction of packs <= 2.90 with a mean of 3.00 is 0.841
fraction of packs >= 2.90 with a mean of 3.07 is 0.952
Setting the packer to 3.06 will mean that fraction of packs >= 2.90 is 0.950
Quantile of 0.0500 = 2.84, mean = 3.00, sd = 0.100
Quantile of 0.0500 = 2.92, mean = 3.00, sd = 0.0500
Fraction of packs >= 2.90 with a mean of 3.00 and standard deviation of 0.0500 is 0.977
Quantile of 0.0500 = 2.90, mean = 3.00, sd = 0.0600
Fraction of packs >= 2.90 with a mean of 3.00 and standard deviation of 0.0600 is 0.952
prob = 0.242, quantile(p) 1.64
If we want the 0.0500 th quantile to be located at 2.90, would need a standard deviation of 0.0608
Fraction of packs >= 2.90 with a mean of 3.00 and standard deviation of 0.0608 is 0.950
Fraction long enough [ P(X <= 4.10) ] is 0.933
Fraction too short [ P(X <= 3.90) ] is 0.309
Fraction OK  -between 3.90 and 4.10[ P(X <= 4.10) - P(X<= 3.90 ) ] is 0.625
Fraction too long [ P(X > 4.10) ] is 0.0668
95% of bolts are shorter than 4.11

*/

ext: cpp

max_issues_repo_name: jonstewart/boost-svn

max_forks_repo_name: jonstewart/boost-svn


text:
// ---------------------------------------------------------------------
// pion:  a Boost C++ framework for building lightweight HTTP interfaces
// ---------------------------------------------------------------------
// Copyright (C) 2007-2012 Cloudmeter, Inc.  (http://www.cloudmeter.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//

#include <pion/config.hpp>
#include <pion/http/response.hpp>
#include <boost/test/unit_test.hpp>

using namespace pion;

class NewHTTPResponse_F : public http::response {
public:
    NewHTTPResponse_F() {
    }
    ~NewHTTPResponse_F() {
    }
};

BOOST_FIXTURE_TEST_SUITE(NewHTTPResponse_S, NewHTTPResponse_F)

BOOST_AUTO_TEST_CASE(checkClear) {
    prepare_headers_for_send(true, false);
    BOOST_CHECK(!get_headers().empty());
    clear();
    BOOST_CHECK(get_headers().empty());
}

BOOST_AUTO_TEST_CASE(checkStatusCodeAccessors) {
    set_status_code(http::types::RESPONSE_CODE_NOT_FOUND);
    BOOST_CHECK_EQUAL(get_status_code(), http::types::RESPONSE_CODE_NOT_FOUND);
    set_status_code(http::types::RESPONSE_CODE_CREATED);
    BOOST_CHECK_EQUAL(get_status_code(), http::types::RESPONSE_CODE_CREATED);
}

BOOST_AUTO_TEST_CASE(checkStatusMessageAccessors) {
    set_status_message(http::types::RESPONSE_MESSAGE_NOT_FOUND);
    BOOST_CHECK_EQUAL(get_status_message(), http::types::RESPONSE_MESSAGE_NOT_FOUND);
    set_status_message(http::types::RESPONSE_MESSAGE_CREATED);
    BOOST_CHECK_EQUAL(get_status_message(), http::types::RESPONSE_MESSAGE_CREATED);
}

BOOST_AUTO_TEST_CASE(checkSetLastModified) {
    set_last_modified(0);
    BOOST_CHECK_EQUAL(get_header(HEADER_LAST_MODIFIED), get_date_string(0));
    set_last_modified(100000000);
    BOOST_CHECK_EQUAL(get_header(HEADER_LAST_MODIFIED), get_date_string(100000000));
    set_last_modified(1000000000);
    BOOST_CHECK_EQUAL(get_header(HEADER_LAST_MODIFIED), get_date_string(1000000000));
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: paolovolpi/pion

max_issues_repo_name: pmed/pion

max_forks_repo_name: pmed/pion


text:
// Copyright 2015-2019 Hans Dembinski and Henry Schreiner
//
// 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)
//
// Based on boost/histogram/accumulators/mean.hpp
// Changes:
//  * Internal values are public for access from Python
//  * A special constructor added for construction from Python

#pragma once

#include <boost/core/nvp.hpp>
#include <boost/histogram/weight.hpp>

namespace accumulators {

/** Calculates mean and variance of sample.

  Uses Welford's incremental algorithm to improve the numerical
  stability of mean and variance computation.
*/
template <class ValueType>
struct mean {
    using value_type      = ValueType;
    using const_reference = const value_type&;

    mean() = default;

    mean(const value_type& n,
         const value_type& mean,
         const value_type& variance) noexcept
        : count(n)
        , value(mean)
        , _sum_of_deltas_squared(variance * (n - 1)) {}

    mean(const value_type& sum,
         const value_type& mean,
         const value_type& _sum_of_deltas_squared,
         bool /* Tag to trigger python internal constructor */)
        : count(sum)
        , value(mean)
        , _sum_of_deltas_squared(_sum_of_deltas_squared) {}

    void operator()(const value_type& x) noexcept {
        count += static_cast<value_type>(1);
        const auto delta = x - value;
        value += delta / count;
        _sum_of_deltas_squared += delta * (x - value);
    }

    void operator()(const boost::histogram::weight_type<value_type>& w,
                    const value_type& x) noexcept {
        count += w.value;
        const auto delta = x - value;
        value += w.value * delta / count;
        _sum_of_deltas_squared += w.value * delta * (x - value);
    }

    mean& operator+=(const mean& rhs) noexcept {
        if(rhs.count == 0)
            return *this;

        const auto mu1 = value;
        const auto mu2 = rhs.value;
        const auto n1  = count;
        const auto n2  = rhs.count;

        count += rhs.count;
        value = (n1 * mu1 + n2 * mu2) / count;
        _sum_of_deltas_squared += rhs._sum_of_deltas_squared;
        _sum_of_deltas_squared
            += n1 * (value - mu1) * (value - mu1) + n2 * (value - mu2) * (value - mu2);

        return *this;
    }

    mean& operator*=(const value_type& s) noexcept {
        value *= s;
        _sum_of_deltas_squared *= s * s;
        return *this;
    }

    bool operator==(const mean& rhs) const noexcept {
        return count == rhs.count && value == rhs.value
               && _sum_of_deltas_squared == rhs._sum_of_deltas_squared;
    }

    bool operator!=(const mean& rhs) const noexcept { return !operator==(rhs); }

    value_type variance() const noexcept {
        return _sum_of_deltas_squared / (count - 1);
    }

    template <class Archive>
    void serialize(Archive& ar, unsigned) {
        ar& boost::make_nvp("count", count);
        ar& boost::make_nvp("value", value);
        ar& boost::make_nvp("_sum_of_deltas_squared", _sum_of_deltas_squared);
    }

    value_type count{};
    value_type value{};
    value_type _sum_of_deltas_squared{};
};

} // namespace accumulators

max_stars_repo_name: andrzejnovak/boost-histogram

max_issues_repo_name: andrzejnovak/boost-histogram

max_forks_repo_name: andrzejnovak/boost-histogram


text:
/**********************************************************************
 *  Copyright (c) 2008-2014, Alliance for Sustainable Energy.
 *  All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 **********************************************************************/

#ifndef OPENSTUDIO_VARIABLESTABVIEW_H
#define OPENSTUDIO_VARIABLESTABVIEW_H

#include <openstudio_lib/MainTabView.hpp>
#include <model/Model.hpp>
#include <model/OutputVariable.hpp>
#include <boost/optional.hpp>

class QComboBox;
class QPushButton;
class QVBoxLayout;

namespace openstudio {
  class OSSwitch;
  class OSComboBox;

  class VariableListItem : public QWidget
  {
    Q_OBJECT;

    public:
      VariableListItem(const std::string &t_name,
          const boost::optional<openstudio::model::OutputVariable> &t_variable,
          const openstudio::model::Model &t_model);

      virtual ~VariableListItem() { }

    public slots:
      void setVariableEnabled(bool);

    private slots:
      void onOffClicked(bool);
      void indexChanged(const QString &t_frequency);

    private:
      REGISTER_LOGGER("openstudio.VariableListItem");

      std::string m_name;
      boost::optional<openstudio::model::OutputVariable> m_variable;
      openstudio::model::Model m_model;

      OSComboBox *m_combobox;
      OSSwitch *m_onOffButton;
  };

  class VariablesList : public QWidget
  {
    Q_OBJECT;

    public:
      VariablesList(openstudio::model::Model t_model);
      virtual ~VariablesList();

    private slots:
      void onAdded(const WorkspaceObject&, const openstudio::IddObjectType&, const openstudio::UUID&);
      void onRemoved(const WorkspaceObject&, const openstudio::IddObjectType&, const openstudio::UUID&);

      void allOnClicked();
      void allOffClicked();

      void enableAll(bool);
      void updateVariableList();

    private:
      REGISTER_LOGGER("openstudio.VariablesList");
      openstudio::model::Model m_model;
      QPushButton *m_allOnBtn;
      QPushButton *m_allOffBtn;
      QVBoxLayout *m_listLayout;
      bool m_dirty;
      std::vector<VariableListItem *> m_variables;
  };

  class VariablesTabView : public MainTabView
  {
    Q_OBJECT;

    public:

      VariablesTabView(openstudio::model::Model t_model, QWidget * parent = 0);

      virtual ~VariablesTabView() {}

    private:
      REGISTER_LOGGER("openstudio.VariablesTabView");
  };

} // openstudio

#endif // OPENSTUDIO_VARIABLESTABVIEW_H

max_stars_repo_name: ORNL-BTRIC/OpenStudio

max_issues_repo_name: ORNL-BTRIC/OpenStudio

max_forks_repo_name: ORNL-BTRIC/OpenStudio


text:
// Copyright 2010-2013 The Trustees of Indiana University.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:

// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//  Authors: Jeremiah Willcock
//           Andrew Lumsdaine

#ifndef AMPLUSPLUS_LOCK_FREE_COALESCED_MESSAGE_TYPE_PACKED_HPP
#define AMPLUSPLUS_LOCK_FREE_COALESCED_MESSAGE_TYPE_PACKED_HPP

#include <am++/detail/atomics.hpp>
#include <am++/traits.hpp>
#include <utility>
#include <vector>
#include <boost/smart_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/assert.hpp>
#include <stdint.h>
#include <am++/scoped_raw_handler.hpp>

namespace amplusplus {

// Thread-safe functions:
//   Handler calls (from progress on underlying engine)
//   send
//   flush (both versions)
//
// This version is like the basic lock_free_coalesced_message_type but with the
// message buffer pointer and size packed into 64 bits to avoid cmpxchg16b on
// old Opterons that don't have it.  Assumptions are that the message buffer
// has size at most (1 << 16) - 1 and only the last 48 bits (signed) of
// pointers are significant.

namespace detail {
  template <typename T>
  inline uint64_t pack_pointer_and_size(T* p, unsigned int n) {
    BOOST_ASSERT (((int64_t(p) << 16) >> 16) == intptr_t(p));
    return ((uint64_t)(uintptr_t)p << 16) | (n & 0xffffu);
  }

  template <typename T>
  inline T* unpack_pointer(uint64_t packed) {
    return (T*)(int64_t(packed) >> 16); // Sign extension is important here
  }

  inline unsigned int unpack_size(uint64_t packed) {
    return (unsigned int)(packed & 0xffffu);
  }
}

template <typename Arg, typename Handler, typename AMEngine, size_t BufferSize>
class lock_free_coalesced_message_type_packed {
  BOOST_STATIC_ASSERT(BufferSize <= 0xffff);

  struct message_buffer {
    volatile size_t elements_written;
    Arg data[BufferSize];
    message_buffer(): elements_written(0), data(data) {}
  };

  public:
  typedef Arg arg_type;
  typedef AMEngine engine_type;
  typedef Handler handler_type;
  typedef typename am_engine_traits<AMEngine>::rank_type rank_type;

  lock_free_coalesced_message_type_packed(AMEngine& engine)
    : engine(engine),
      mpi_datatype(),
      handler_scope(engine, BufferSize, mpi_datatype.get(), BufferSize * sizeof(Arg), raw_message_handler(*this)),
      buffers_to_swap_in((void (*)(message_buffer*))0)
  {
    message_index = handler_scope.get_message_index();
    size_t nranks = num_processes(engine);
    for (size_t i = 0; i < 2 * nranks + 1; ++i) {
      buffer_pool.push_back(create_buffer());
    }
    for (size_t i = 0; i < nranks; ++i) {
      outgoing_buffers_packed.push_back(detail::pack_pointer_and_size(alloc_buffer(), 0));
    }
    flush_signal(engine, message_index).connect(typename lock_free_coalesced_message_type_packed::flush_message_buffer(*this));
  }

  private:
  void send_buffer(message_buffer* buf,
                   uintptr_t count,
                   typename am_engine_traits<AMEngine>::rank_type dest) {
    while (buf->elements_written != count) {} // Wait for all elements to be written, not just allocated
    send(engine, message_index, buf->data, count, mpi_datatype.get(), dest, typename lock_free_coalesced_message_type_packed::free_buffer(*this, buf));
  }

  struct flush_message_buffer {
    lock_free_coalesced_message_type_packed& mt;
    flush_message_buffer(lock_free_coalesced_message_type_packed& mt): mt(mt) {}
    void operator()(typename am_engine_traits<AMEngine>::rank_type dest) {
      BOOST_ASSERT (is_valid_rank(mt.engine, dest));
      if (mt.buffers_to_swap_in.get() == NULL) {
        mt.buffers_to_swap_in.reset(mt.alloc_buffer());
      }
      message_buffer* buffer_to_swap_in = mt.buffers_to_swap_in.get();
      volatile uint64_t* old_buf_ptr = &mt.outgoing_buffers_packed[dest];
      uint64_t old_buf_packed = *old_buf_ptr;
      while (true) { // Use CAS for atomic swap
        if (detail::unpack_size(old_buf_packed) == 0) return;
        message_buffer* new_buf_first = buffer_to_swap_in;
        uintptr_t new_buf_second = 0;
        uint64_t old_val = detail::atomic_cas(*old_buf_ptr, old_buf_packed, detail::pack_pointer_and_size(new_buf_first, new_buf_second));
        if (old_val == old_buf_packed) break;
        old_buf_packed = old_val;
      }
      uintptr_t count = detail::unpack_size(old_buf_packed);
      mt.send_buffer(detail::unpack_pointer<message_buffer>(old_buf_packed), count, dest);
      mt.buffers_to_swap_in.reset(mt.alloc_buffer());
    }
  };

  struct raw_message_handler {
    lock_free_coalesced_message_type_packed& mt;
    raw_message_handler(lock_free_coalesced_message_type_packed& mt): mt(mt) {}
    void operator()(typename am_engine_traits<AMEngine>::rank_type src, const void* buf, size_t count) {
      const Arg* actual_buf = (const Arg*)buf;
      for (size_t i = 0; i < count; ++i) {
        mt.handler(src, actual_buf[i]);
      }
    }
  };

  public:
  friend void set_handler(lock_free_coalesced_message_type_packed& mt, const handler_type& handler) {
    mt.handler = handler;
  }

  friend void send(lock_free_coalesced_message_type_packed& mt, const arg_type& arg, rank_type dest) {
    BOOST_ASSERT (is_valid_rank(mt.engine, dest));
    if (mt.buffers_to_swap_in.get() == NULL) {
      mt.buffers_to_swap_in.reset(mt.alloc_buffer());
    }
    message_buffer* buffer_to_swap_in = mt.buffers_to_swap_in.get();
    volatile uint64_t* old_buf_ptr = &mt.outgoing_buffers_packed[dest];
    uint64_t old_buf_packed = *old_buf_ptr;
    while (true) {
      message_buffer* new_buf_first = detail::unpack_size(old_buf_packed) + 1 == BufferSize ? buffer_to_swap_in : detail::unpack_pointer<message_buffer>(old_buf_packed);
      uintptr_t new_buf_second = detail::unpack_size(old_buf_packed) + 1 == BufferSize ? 0 : detail::unpack_size(old_buf_packed) + 1;
      uint64_t old_val = detail::atomic_cas(*old_buf_ptr, old_buf_packed, detail::pack_pointer_and_size(new_buf_first, new_buf_second));
      if (old_val == old_buf_packed) break;
      old_buf_packed = old_val;
    }
    uintptr_t count = detail::unpack_size(old_buf_packed);
    message_buffer* old_buf_first = detail::unpack_pointer<message_buffer>(old_buf_packed);
    old_buf_first->data[count] = arg;
    detail::atomic_inc(old_buf_first->elements_written);
    if (count + 1 == BufferSize) {
      mt.send_buffer(old_buf_first, count + 1, dest);
      mt.buffers_to_swap_in.reset(mt.alloc_buffer());
    }
  }

  friend void flush(lock_free_coalesced_message_type_packed& mt) {
    flush(mt.engine, mt.message_index); // Calls my flush through hook signal
  }

  friend void flush(lock_free_coalesced_message_type_packed& mt, typename am_engine_traits<AMEngine>::rank_type dest) {
    flush(mt.engine, dest, mt.message_index); // Calls my flush through hook signal
  }

  private:
  AMEngine& engine;
  make_mpi_datatype<Arg> mpi_datatype;
  typename am_engine_traits<AMEngine>::msg_index_type message_index;
  handler_type handler;
  scoped_raw_handler<AMEngine> handler_scope;
  std::vector<boost::shared_ptr<void> > all_buffers; // Free and used, keeps ownership of them
  boost::mutex buffer_pool_lock;
  std::vector<message_buffer*> buffer_pool;
  std::vector<uint64_t> outgoing_buffers_packed; // Packed using functions in detail
  boost::thread_specific_ptr<message_buffer> buffers_to_swap_in; // One per thread

  message_buffer* create_buffer() {
    boost::shared_ptr<void> buf = alloc_memory(engine, sizeof(message_buffer));
    all_buffers.push_back(buf);
    message_buffer* result = (message_buffer*)buf.get();
    result->elements_written = 0;
    return result;
  }

  message_buffer* alloc_buffer() {
#if 0
    boost::lock_guard<boost::mutex> l(buffer_pool_lock);
    if (buffer_pool.empty()) {
      return create_buffer();
    } else {
      message_buffer* buf = buffer_pool.back();
      buffer_pool.pop_back();
      buf->elements_written = 0;
      return buf;
    }
#endif
    return create_buffer();
  }

  struct free_buffer {
    lock_free_coalesced_message_type_packed& mt;
    message_buffer* buf;
    free_buffer(lock_free_coalesced_message_type_packed& mt, message_buffer* buf): mt(mt), buf(buf) {}
    void operator()(const MPI_Status&) const {
#if 0
      boost::lock_guard<boost::mutex> l(mt.buffer_pool_lock);
      mt.buffer_pool.push_back(buf);
#endif
    }
  };
};

}

#endif // AMPLUSPLUS_LOCK_FREE_COALESCED_MESSAGE_TYPE_PACKED_HPP

max_stars_repo_name: thejkane/AGM

max_issues_repo_name: thejkane/AGM

max_forks_repo_name: thejkane/AGM