<commit_before>#ifndef HMLIB_MATH_DIFFERENTIATION_INC
#define HMLIB_MATH_DIFFERENTIATION_INC 100
#
namespace hmLib {
	namespace math {
		//both first and second order derivatives
		template<typename func_type, typename real_type>
		void derivative(func_type fn, real_type x, real_type abserr, real_type relerr,
			real_type& dx, real_type& dx2) {
			auto hx = x * relerr + abserr;

			auto v0 = fn(x);
			auto vP = fn(x + hx);
			auto vN = fn(x - hx);

			dx = (vP - vN) / 2 / hx;
			dx2 = (vP + vN - 2 * v0) / hx / hx;
		}
		//both first and second order derivatives
		template<typename func_type, typename real_type>
		void derivative(func_type fn, real_type x, real_type abserr, real_type relerr,
			real_type& dx) {
			auto hx = x * relerr + abserr;

			auto vP = fn(x + hx);
			auto vN = fn(x - hx);

			dx = (vP - vN) / 2 / hx;
		}
		//both first and second order derivatives
		template<typename plane_func_type, typename real_type>
		void plane_derivative(plane_func_type fn, real_type x, real_type y, real_type abserr, real_type relerr,
			real_type& dx, real_type& dy, real_type& dx2, real_type& dxdy, real_type& dy2) {
			auto hx = x * relerr + abserr;
			auto hy = y * relerr + abserr;

			auto v00 = fn(x, y);
			auto vP0 = fn(x + hx, y);
			auto vN0 = fn(x - hx, y);
			auto v0P = fn(x, y + hy);
			auto vPP = fn(x + hx, y + hy);
			auto vNP = fn(x - hx, y + hy);
			auto v0N = fn(x, y - hy);
			auto vPN = fn(x + hx, y - hy);
			auto vNN = fn(x - hx, y - hy);

			dx = (vP0 - vN0) / 2 / hx;
			dy = (v0P - v0N) / 2 / hy;

			dx2 = (vP0 + vN0 - 2 * v00) / hx / hx;
			dy2 = (v0P + v0N - 2 * v00) / hy / hy;
			dxdy = (vPP + vNN - vPN - vNP) / 4 / hx / hy;
		}
		//only first order derivatives
		template<typename plane_func_type, typename real_type>
		void plane_derivative(plane_func_type fn, real_type x, real_type y, real_type abserr, real_type relerr,
			real_type& dx, real_type& dy) {
			auto hx = x * relerr + abserr;
			auto hy = y * relerr + abserr;

			auto vP0 = fn(x + hx, y);
			auto vN0 = fn(x - hx, y);
			auto v0P = fn(x, y + hy);
			auto v0N = fn(x, y - hy);

			dx = (vP0 - vN0) / 2 / hx;
			dy = (v0P - v0N) / 2 / hy;
		}

	}
}
#
#endif
<commit_msg>Fix: stepin differentiation can be negative when the value is negative.<commit_after>#ifndef HMLIB_MATH_DIFFERENTIATION_INC
#define HMLIB_MATH_DIFFERENTIATION_INC 100
#
namespace hmLib {
	namespace math {
		//both first and second order derivatives
		template<typename func_type, typename real_type>
		void derivative(func_type fn, real_type x, real_type abserr, real_type relerr,
			real_type& dx, real_type& dx2) {
			auto hx = x * relerr + abserr;

			auto v0 = fn(x);
			auto vP = fn(x + hx);
			auto vN = fn(x - hx);

			dx = (vP - vN) / 2 / hx;
			dx2 = (vP + vN - 2 * v0) / hx / hx;
		}
		//both first and second order derivatives
		template<typename func_type, typename real_type>
		void derivative(func_type fn, real_type x, real_type abserr, real_type relerr,
			real_type& dx) {
			auto hx = x * relerr + abserr;

			auto vP = fn(x + hx);
			auto vN = fn(x - hx);

			dx = (vP - vN) / 2 / hx;
		}
		//both first and second order derivatives
		template<typename plane_func_type, typename real_type>
		void plane_derivative(plane_func_type fn, real_type x, real_type y, real_type abserr, real_type relerr,
			real_type& dx, real_type& dy, real_type& dx2, real_type& dxdy, real_type& dy2) {
			auto hx = std::abs(x) * relerr + abserr;
			auto hy = std::abs(y) * relerr + abserr;

			auto v00 = fn(x, y);
			auto vP0 = fn(x + hx, y);
			auto vN0 = fn(x - hx, y);
			auto v0P = fn(x, y + hy);
			auto vPP = fn(x + hx, y + hy);
			auto vNP = fn(x - hx, y + hy);
			auto v0N = fn(x, y - hy);
			auto vPN = fn(x + hx, y - hy);
			auto vNN = fn(x - hx, y - hy);

			dx = (vP0 - vN0) / 2 / hx;
			dy = (v0P - v0N) / 2 / hy;

			dx2 = (vP0 + vN0 - 2 * v00) / hx / hx;
			dy2 = (v0P + v0N - 2 * v00) / hy / hy;
			dxdy = (vPP + vNN - vPN - vNP) / 4 / hx / hy;
		}
		//only first order derivatives
		template<typename plane_func_type, typename real_type>
		void plane_derivative(plane_func_type fn, real_type x, real_type y, real_type abserr, real_type relerr,
			real_type& dx, real_type& dy) {
			auto hx = x * relerr + abserr;
			auto hy = y * relerr + abserr;

			auto vP0 = fn(x + hx, y);
			auto vN0 = fn(x - hx, y);
			auto v0P = fn(x, y + hy);
			auto v0N = fn(x, y - hy);

			dx = (vP0 - vN0) / 2 / hx;
			dy = (v0P - v0N) / 2 / hy;
		}

	}
}
#
#endif
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#ifndef NIX_BLOCK_H
#define NIX_BLOCK_H

#include <string>

#include <nix/base/EntityWithMetadata.hpp>
#include <nix/base/IBlock.hpp>
#include <nix/Source.hpp>
#include <nix/DataArray.hpp>
#include <nix/SimpleTag.hpp>
#include <nix/DataTag.hpp>

#include <nix/Platform.hpp>

namespace nix {

/**
 * @brief Class for grouping further data entities.
 *
 * The Block entity is a top-level, summarizing element that allows to
 * group the other data entities belonging for example to the same recording session.
 * All data entities such as {@link nix::Source}, {@link nix::DataArray}, {@link nix::SimpleTag} and
 * {@link nix::DataTag} have to be associated with one Block.
 *
 * ### Create a new Block
 * A block can only be created on an existing file object. Do not use the blocks constructors for this
 * purpose.
 *
 * ~~~
 * File f = ...;
 * Block b = f.createBlock("session one", "recording_session");
 * ~~~
 *
 * ### Working with blocks
 * After a block was created it can be used to create further entities. See the documentation of
 * {@link nix::Source}, {@link nix::DataArray}, {@link nix::SimpleTag} and {@link nix::DataTag}
 * for more information.
 * The next example shows how some properties of a block can be accessed.
 *
 * ~~~
 * File f = ...;
 * Block b = f.getBlock(some_id);
 *
 * // set the blocks name
 * std::string name = b.name("session two")
 *
 * // add metadata to a block
 * Section s = f.getSection(sec_id);
 * b.metadata(s);
 *
 * // get associated metadata from a block
 * b.metadata();
 *
 * // remove associated metadata from a block
 * b.metadata(boost::none);
 * ~~~
 *
 * ### Deleting a block
 * When a block is deleted from a file all contained data e.g. sources, data arrays and tags will
 * be removed too.
 *
 * ~~~
 * File f = ...;
 * bool deleted = f.deleteBlock(some_id);
 * cout << "The block was " << deleted ? "" : "not " << "deleted" << endl;
 * ~~~
 */
class NIXAPI Block : public base::EntityWithMetadata<base::IBlock> {

public:

    /**
     * @brief Constructor that creates an uninitialized Block.
     *
     * Calling any method on an uninitialized block will throw a {@link nix::UninitializedEntity}
     * exception. The following code illustrates how to check if a block is initialized:
     *
     * ~~~
     * Block e = ...;
     * if (e) {
     *     // e is initialised
     * } else {
     *     // e is uninitialized
     * }
     * ~~~
     */
    Block() {}

    /**
     * @brief Copy constructor.
     *
     * Copying of all NIX front facing objects like block is a rather cheap operation.
     * Semantically this is equivalent to the creation of another reference to the original
     * object.
     *
     * @param other     The block to copy.
     */
    Block(const Block &other)
        : EntityWithMetadata(other.impl())
    {
    }

    /**
     * @brief Constructor that creates a new entity from a shared pointer to
     * an implementation instance.
     *
     * This constructor should only be used in the back-end.
     */
    Block(const std::shared_ptr<base::IBlock> &p_impl)
        : EntityWithMetadata(p_impl)
    {
    }

    /**
     * @brief Constructor with move semantics that creates a new entity from a shared pointer to
     * an implementation instance.
     *
     * This constructor should only be used in the back-end.
     */
    Block(std::shared_ptr<base::IBlock> &&ptr)
        : EntityWithMetadata(std::move(ptr))
    {
    }

    //--------------------------------------------------
    // Methods concerning sources
    //--------------------------------------------------

    bool hasSource(const std::string &id) const {
        return backend()->hasSource(id);
    }

    bool hasSource(const Source &source) const;

    Source getSource(const std::string &id) const {
        return backend()->getSource(id);
    }

    Source getSource(size_t index) const {
        return backend()->getSource(index);
    }

    size_t sourceCount() const {
        return backend()->sourceCount();
    }

    /**
     * @brief Get all root sources associated with this block.
     *
     * The parameter filter can be used to filter sources by various
     * criteria. By default a filter is used that accepts all sources.
     *
     * @param filter    A filter function.
     *
     * @return A vector containing the matching root sources.
     */
    std::vector<Source> sources(util::Filter<Source>::type filter = util::AcceptAll<Source>()) const;

    /**
     * @brief Get all sources in this block recursively.
     *
     * This method traverses the tree of all sources in the block. The traversal
     * is accomplished via breadth first and can be limited in depth. On each node or
     * source a filter is applied. If the filter returns true the respective source
     * will be added to the result list.
     * By default a filter is used that accepts all sources.
     *
     * @param filter       A filter function.
     * @param max_depth    The maximum depth of traversal.
     *
     * @return A vector containing the matching sources.
     */
    std::vector<Source> findSources(util::Filter<Source>::type filter = util::AcceptAll<Source>(),
                                    size_t max_depth = std::numeric_limits<size_t>::max()) const;

    Source createSource(const std::string &name, const std::string &type) {
        return backend()->createSource(name, type);
    }

    bool deleteSource(const std::string &id) {
        return backend()->deleteSource(id);
    }

    /**
    * @brief Deletes a root source.
    *
    * This will also delete all child sources of this root source from the file.
    * The deletion of a source can't be undone.
    *
    * @param source    The source to delete.
    *
    * @return True if the source was deleted, false otherwise.
    */
    bool deleteSource(const Source &source);

    //--------------------------------------------------
    // Methods concerning data arrays
    //--------------------------------------------------

    bool hasDataArray(const std::string &id) const {
        return backend()->hasDataArray(id);
    }

    /**
    * @brief Checks if a specific data array exists in this block.
    *
    * @param data_array        The data array to check.
    *
    * @return True if the data array exists, false otherwise.
    */
    bool hasDataArray(const DataArray &data_array) const;

    DataArray getDataArray(const std::string &id) const {
        return backend()->getDataArray(id);
    }

    DataArray getDataArray(size_t index) const {
        return backend()->getDataArray(index);
    }

    /**
     * @brief Get data arrays within this block.
     *
     * The parameter filter can be used to filter data arrays by various
     * criteria. By default a filter is used that accepts all data arrays.
     *
     * @param filter    A filter function.
     *
     * @return A vector that contains all filtered data arrays.
     */
    std::vector<DataArray> dataArrays(util::AcceptAll<DataArray>::type filter
                                      = util::AcceptAll<DataArray>()) const;

    size_t dataArrayCount() const {
        return backend()->dataArrayCount();
    }

    /**
    * @brief Create a new data array associated with this block.
    *
    * @param name      The name of the data array to create.
    * @param type      The type of the data array.
    * @param data_type A nix::DataType indicating the format to store values.
    * @param shape     A NDSize holding the extent of the array to create.
    *
    * @return The newly created data array.
    */
    DataArray createDataArray(const std::string &name,
                              const std::string &type,
                              nix::DataType      data_type,
                              const NDSize      &shape) {
        return backend()->createDataArray(name, type, data_type, shape);
    }

    /**
    * @brief Create a new data array associated with this block.
    *
    * @param name      The name of the data array to create.
    * @param type      The type of the data array.
    * @param data      Data to create array with.
    *
    * Create a data array with shape and type inferred from data. After
    * successful creation, the contents of data will be written to the
    * data array.
    *
    * @return The newly created data array.
    */
    template<typename T>
    DataArray createDataArray(const std::string &name,
                              const std::string &type,
                              const T &data) {
         const Hydra<const T> hydra(data);
         DataType dtype = hydra.element_data_type();

         const NDSize shape = hydra.shape();
         DataArray da = createDataArray(name, type, dtype, shape);

         const NDSize offset(shape.size(), 0);
         da.setData(data, offset);

         return da;
    }

    bool deleteDataArray(const std::string &id) {
        return backend()->deleteDataArray(id);
    }

    /**
    * @brief Deletes a data array from this block.
    *
    * This deletes a data array and all its dimensions from the block and the file.
    * The deletion can't be undone.
    *
    * @param data_array        The data array to delete.
    *
    * @return True if the data array was deleted, false otherwise.
    */
    bool deleteDataArray(const DataArray &data_array);

    //--------------------------------------------------
    // Methods concerning simple tags.
    //--------------------------------------------------

    bool hasSimpleTag(const std::string &id) const {
        return backend()->hasSimpleTag(id);
    }

    /**
    * @brief Checks if a specific simple tag exists in the block.
    *
    * @param simple_tag        The simple tag to check.
    *
    * @return True if the simple tag exists, false otherwise.
    */
    bool hasSimpleTag(const SimpleTag &simple_tag) const;

    SimpleTag getSimpleTag(const std::string &id) const {
        return backend()->getSimpleTag(id);
    }

    SimpleTag getSimpleTag(size_t index) const {
        return backend()->getSimpleTag(index);
    }

    /**
     * @brief Get simple tags within this block.
     *
     * The parameter filter can be used to filter simple tags by various
     * criteria. By default a filter is used that accepts all tags.
     *
     * @param filter    A filter function.
     *
     * @return A vector that contains all filtered simple tags.
     */
    std::vector<SimpleTag> simpleTags(util::Filter<SimpleTag>::type filter
                                      = util::AcceptAll<SimpleTag>()) const;

    size_t simpleTagCount() const {
        return backend()->simpleTagCount();
    }

    SimpleTag createSimpleTag(const std::string &name, const std::string &type,
                              const std::vector<DataArray> &refs) {
        return backend()->createSimpleTag(name, type, refs);
    }

    bool deleteSimpleTag(const std::string &id) {
        return backend()->deleteSimpleTag(id);
    }

    /**
    * @brief Deletes a simple tag from the block.
    *
    * Deletes a simple tag with all its features from the block and the file.
    * The deletion can't be undone.
    *
    * @param simple_tag        The tag to remove.
    *
    * @return True if the tag was removed, false otherwise.
    */
    bool deleteSimpleTag(const SimpleTag &simple_tag);

    //--------------------------------------------------
    // Methods concerning data tags.
    //--------------------------------------------------

    bool hasDataTag(const std::string &id) const {
        return backend()->hasDataTag(id);
    }

    /**
    * @brief Checks if a specific data tag exists in the block.
    *
    * @param data_tag          The data tag to check.
    *
    * @return True if the data tag exists, false otherwise.
    */
    bool hasDataTag(const DataTag &data_tag) const;

    DataTag getDataTag(const std::string &id) const {
        return backend()->getDataTag(id);
    }

    DataTag getDataTag(size_t index) const {
        return backend()->getDataTag(index);
    }

    /**
     * @brief Get data tags within this block.
     *
     * The parameter filter can be used to filter data tags by various
     * criteria. By default a filter is used that accepts all tags.
     *
     * @param filter    A filter function.
     *
     * @return A vector that contains all filtered data tags.
     */
    std::vector<DataTag> dataTags(util::AcceptAll<DataTag>::type filter
                                  = util::AcceptAll<DataTag>()) const;

    size_t dataTagCount() const {
        return backend()->dataTagCount();
    }

    DataTag createDataTag(const std::string &name, const std::string &type,
                          const DataArray position) {
        return backend()->createDataTag(name, type, position);
    }

    bool deleteDataTag(const std::string &id) {
        return backend()->deleteDataTag(id);
    }

    /**
    * @brief Deletes a data tag from the block.
    *
    * Deletes a data tag and all its features from the block and the file.
    * The deletion can't be undone.
    *
    * @param data_tag  The tag to remove.
    *
    * @return True if the tag was removed, false otherwise.
    */
    bool deleteDataTag(const DataTag &data_tag);

    //------------------------------------------------------
    // Operators and other functions
    //------------------------------------------------------

    /**
     * @brief Assignment operator for none.
     */
    virtual Block &operator=(none_t) {
        nullify();
        return *this;
    }

    /**
     * @brief Output operator
     */
    friend std::ostream & operator<<(std::ostream &out, const Block &ent);

};

}

#endif // NIX_BLOCK_H
<commit_msg>fixed the createDataTag signature from position to positionS<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#ifndef NIX_BLOCK_H
#define NIX_BLOCK_H

#include <string>

#include <nix/base/EntityWithMetadata.hpp>
#include <nix/base/IBlock.hpp>
#include <nix/Source.hpp>
#include <nix/DataArray.hpp>
#include <nix/SimpleTag.hpp>
#include <nix/DataTag.hpp>

#include <nix/Platform.hpp>

namespace nix {

/**
 * @brief Class for grouping further data entities.
 *
 * The Block entity is a top-level, summarizing element that allows to
 * group the other data entities belonging for example to the same recording session.
 * All data entities such as {@link nix::Source}, {@link nix::DataArray}, {@link nix::SimpleTag} and
 * {@link nix::DataTag} have to be associated with one Block.
 *
 * ### Create a new Block
 * A block can only be created on an existing file object. Do not use the blocks constructors for this
 * purpose.
 *
 * ~~~
 * File f = ...;
 * Block b = f.createBlock("session one", "recording_session");
 * ~~~
 *
 * ### Working with blocks
 * After a block was created it can be used to create further entities. See the documentation of
 * {@link nix::Source}, {@link nix::DataArray}, {@link nix::SimpleTag} and {@link nix::DataTag}
 * for more information.
 * The next example shows how some properties of a block can be accessed.
 *
 * ~~~
 * File f = ...;
 * Block b = f.getBlock(some_id);
 *
 * // set the blocks name
 * std::string name = b.name("session two")
 *
 * // add metadata to a block
 * Section s = f.getSection(sec_id);
 * b.metadata(s);
 *
 * // get associated metadata from a block
 * b.metadata();
 *
 * // remove associated metadata from a block
 * b.metadata(boost::none);
 * ~~~
 *
 * ### Deleting a block
 * When a block is deleted from a file all contained data e.g. sources, data arrays and tags will
 * be removed too.
 *
 * ~~~
 * File f = ...;
 * bool deleted = f.deleteBlock(some_id);
 * cout << "The block was " << deleted ? "" : "not " << "deleted" << endl;
 * ~~~
 */
class NIXAPI Block : public base::EntityWithMetadata<base::IBlock> {

public:

    /**
     * @brief Constructor that creates an uninitialized Block.
     *
     * Calling any method on an uninitialized block will throw a {@link nix::UninitializedEntity}
     * exception. The following code illustrates how to check if a block is initialized:
     *
     * ~~~
     * Block e = ...;
     * if (e) {
     *     // e is initialised
     * } else {
     *     // e is uninitialized
     * }
     * ~~~
     */
    Block() {}

    /**
     * @brief Copy constructor.
     *
     * Copying of all NIX front facing objects like block is a rather cheap operation.
     * Semantically this is equivalent to the creation of another reference to the original
     * object.
     *
     * @param other     The block to copy.
     */
    Block(const Block &other)
        : EntityWithMetadata(other.impl())
    {
    }

    /**
     * @brief Constructor that creates a new entity from a shared pointer to
     * an implementation instance.
     *
     * This constructor should only be used in the back-end.
     */
    Block(const std::shared_ptr<base::IBlock> &p_impl)
        : EntityWithMetadata(p_impl)
    {
    }

    /**
     * @brief Constructor with move semantics that creates a new entity from a shared pointer to
     * an implementation instance.
     *
     * This constructor should only be used in the back-end.
     */
    Block(std::shared_ptr<base::IBlock> &&ptr)
        : EntityWithMetadata(std::move(ptr))
    {
    }

    //--------------------------------------------------
    // Methods concerning sources
    //--------------------------------------------------

    bool hasSource(const std::string &id) const {
        return backend()->hasSource(id);
    }

    bool hasSource(const Source &source) const;

    Source getSource(const std::string &id) const {
        return backend()->getSource(id);
    }

    Source getSource(size_t index) const {
        return backend()->getSource(index);
    }

    size_t sourceCount() const {
        return backend()->sourceCount();
    }

    /**
     * @brief Get all root sources associated with this block.
     *
     * The parameter filter can be used to filter sources by various
     * criteria. By default a filter is used that accepts all sources.
     *
     * @param filter    A filter function.
     *
     * @return A vector containing the matching root sources.
     */
    std::vector<Source> sources(util::Filter<Source>::type filter = util::AcceptAll<Source>()) const;

    /**
     * @brief Get all sources in this block recursively.
     *
     * This method traverses the tree of all sources in the block. The traversal
     * is accomplished via breadth first and can be limited in depth. On each node or
     * source a filter is applied. If the filter returns true the respective source
     * will be added to the result list.
     * By default a filter is used that accepts all sources.
     *
     * @param filter       A filter function.
     * @param max_depth    The maximum depth of traversal.
     *
     * @return A vector containing the matching sources.
     */
    std::vector<Source> findSources(util::Filter<Source>::type filter = util::AcceptAll<Source>(),
                                    size_t max_depth = std::numeric_limits<size_t>::max()) const;

    Source createSource(const std::string &name, const std::string &type) {
        return backend()->createSource(name, type);
    }

    bool deleteSource(const std::string &id) {
        return backend()->deleteSource(id);
    }

    /**
    * @brief Deletes a root source.
    *
    * This will also delete all child sources of this root source from the file.
    * The deletion of a source can't be undone.
    *
    * @param source    The source to delete.
    *
    * @return True if the source was deleted, false otherwise.
    */
    bool deleteSource(const Source &source);

    //--------------------------------------------------
    // Methods concerning data arrays
    //--------------------------------------------------

    bool hasDataArray(const std::string &id) const {
        return backend()->hasDataArray(id);
    }

    /**
    * @brief Checks if a specific data array exists in this block.
    *
    * @param data_array        The data array to check.
    *
    * @return True if the data array exists, false otherwise.
    */
    bool hasDataArray(const DataArray &data_array) const;

    DataArray getDataArray(const std::string &id) const {
        return backend()->getDataArray(id);
    }

    DataArray getDataArray(size_t index) const {
        return backend()->getDataArray(index);
    }

    /**
     * @brief Get data arrays within this block.
     *
     * The parameter filter can be used to filter data arrays by various
     * criteria. By default a filter is used that accepts all data arrays.
     *
     * @param filter    A filter function.
     *
     * @return A vector that contains all filtered data arrays.
     */
    std::vector<DataArray> dataArrays(util::AcceptAll<DataArray>::type filter
                                      = util::AcceptAll<DataArray>()) const;

    size_t dataArrayCount() const {
        return backend()->dataArrayCount();
    }

    /**
    * @brief Create a new data array associated with this block.
    *
    * @param name      The name of the data array to create.
    * @param type      The type of the data array.
    * @param data_type A nix::DataType indicating the format to store values.
    * @param shape     A NDSize holding the extent of the array to create.
    *
    * @return The newly created data array.
    */
    DataArray createDataArray(const std::string &name,
                              const std::string &type,
                              nix::DataType      data_type,
                              const NDSize      &shape) {
        return backend()->createDataArray(name, type, data_type, shape);
    }

    /**
    * @brief Create a new data array associated with this block.
    *
    * @param name      The name of the data array to create.
    * @param type      The type of the data array.
    * @param data      Data to create array with.
    *
    * Create a data array with shape and type inferred from data. After
    * successful creation, the contents of data will be written to the
    * data array.
    *
    * @return The newly created data array.
    */
    template<typename T>
    DataArray createDataArray(const std::string &name,
                              const std::string &type,
                              const T &data) {
         const Hydra<const T> hydra(data);
         DataType dtype = hydra.element_data_type();

         const NDSize shape = hydra.shape();
         DataArray da = createDataArray(name, type, dtype, shape);

         const NDSize offset(shape.size(), 0);
         da.setData(data, offset);

         return da;
    }

    bool deleteDataArray(const std::string &id) {
        return backend()->deleteDataArray(id);
    }

    /**
    * @brief Deletes a data array from this block.
    *
    * This deletes a data array and all its dimensions from the block and the file.
    * The deletion can't be undone.
    *
    * @param data_array        The data array to delete.
    *
    * @return True if the data array was deleted, false otherwise.
    */
    bool deleteDataArray(const DataArray &data_array);

    //--------------------------------------------------
    // Methods concerning simple tags.
    //--------------------------------------------------

    bool hasSimpleTag(const std::string &id) const {
        return backend()->hasSimpleTag(id);
    }

    /**
    * @brief Checks if a specific simple tag exists in the block.
    *
    * @param simple_tag        The simple tag to check.
    *
    * @return True if the simple tag exists, false otherwise.
    */
    bool hasSimpleTag(const SimpleTag &simple_tag) const;

    SimpleTag getSimpleTag(const std::string &id) const {
        return backend()->getSimpleTag(id);
    }

    SimpleTag getSimpleTag(size_t index) const {
        return backend()->getSimpleTag(index);
    }

    /**
     * @brief Get simple tags within this block.
     *
     * The parameter filter can be used to filter simple tags by various
     * criteria. By default a filter is used that accepts all tags.
     *
     * @param filter    A filter function.
     *
     * @return A vector that contains all filtered simple tags.
     */
    std::vector<SimpleTag> simpleTags(util::Filter<SimpleTag>::type filter
                                      = util::AcceptAll<SimpleTag>()) const;

    size_t simpleTagCount() const {
        return backend()->simpleTagCount();
    }

    SimpleTag createSimpleTag(const std::string &name, const std::string &type,
                              const std::vector<DataArray> &refs) {
        return backend()->createSimpleTag(name, type, refs);
    }

    bool deleteSimpleTag(const std::string &id) {
        return backend()->deleteSimpleTag(id);
    }

    /**
    * @brief Deletes a simple tag from the block.
    *
    * Deletes a simple tag with all its features from the block and the file.
    * The deletion can't be undone.
    *
    * @param simple_tag        The tag to remove.
    *
    * @return True if the tag was removed, false otherwise.
    */
    bool deleteSimpleTag(const SimpleTag &simple_tag);

    //--------------------------------------------------
    // Methods concerning data tags.
    //--------------------------------------------------

    bool hasDataTag(const std::string &id) const {
        return backend()->hasDataTag(id);
    }

    /**
    * @brief Checks if a specific data tag exists in the block.
    *
    * @param data_tag          The data tag to check.
    *
    * @return True if the data tag exists, false otherwise.
    */
    bool hasDataTag(const DataTag &data_tag) const;

    DataTag getDataTag(const std::string &id) const {
        return backend()->getDataTag(id);
    }

    DataTag getDataTag(size_t index) const {
        return backend()->getDataTag(index);
    }

    /**
     * @brief Get data tags within this block.
     *
     * The parameter filter can be used to filter data tags by various
     * criteria. By default a filter is used that accepts all tags.
     *
     * @param filter    A filter function.
     *
     * @return A vector that contains all filtered data tags.
     */
    std::vector<DataTag> dataTags(util::AcceptAll<DataTag>::type filter
                                  = util::AcceptAll<DataTag>()) const;

    size_t dataTagCount() const {
        return backend()->dataTagCount();
    }

    DataTag createDataTag(const std::string &name, const std::string &type,
                          const DataArray positions) {
        return backend()->createDataTag(name, type, positions);
    }

    bool deleteDataTag(const std::string &id) {
        return backend()->deleteDataTag(id);
    }

    /**
    * @brief Deletes a data tag from the block.
    *
    * Deletes a data tag and all its features from the block and the file.
    * The deletion can't be undone.
    *
    * @param data_tag  The tag to remove.
    *
    * @return True if the tag was removed, false otherwise.
    */
    bool deleteDataTag(const DataTag &data_tag);

    //------------------------------------------------------
    // Operators and other functions
    //------------------------------------------------------

    /**
     * @brief Assignment operator for none.
     */
    virtual Block &operator=(none_t) {
        nullify();
        return *this;
    }

    /**
     * @brief Output operator
     */
    friend std::ostream & operator<<(std::ostream &out, const Block &ent);

};

}

#endif // NIX_BLOCK_H
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, 2016, 2017, Intel Corporation
 *
 * 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 Intel Corporation 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 LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sstream>
#include <fstream>
#include <string>
#include <map>
#include "gtest/gtest.h"

#include "geopm_sched.h"
#include "PlatformIO.hpp"
#include "PlatformIOInternal.hpp"
#include "MSRIO.hpp"
#include "Exception.hpp"

class TestPlatformIO : public geopm::PlatformIO
{
    public:
        TestPlatformIO(int cpuid);
        virtual ~TestPlatformIO();
    protected:
        int cpuid(void);

        int m_cpuid;
};

class PlatformIOTest : public :: testing :: Test
{
    protected:
        void SetUp();
        void TearDown();

        geopm::IPlatformIO *m_platform_io;
};

namespace geopm
{
    class TestPlatformIOMSRIO : public MSRIO
    {
        public:
            TestPlatformIOMSRIO();
            virtual ~TestPlatformIOMSRIO();
        protected:
            void msr_path(int cpu_idx,
                          bool is_fallback,
                          std::string &path);
            void msr_batch_path(std::string &path);

            std::vector<std::string> m_test_dev_path;
    };

    TestPlatformIOMSRIO::TestPlatformIOMSRIO()
    {
        const size_t MAX_OFFSET = 4096;
        int num_cpu = geopm_sched_num_cpu();
        for (int cpu_idx = 0; cpu_idx < num_cpu; ++cpu_idx) {
            std::ostringstream path;
            path << "test_msrio_dev_cpu_" << cpu_idx << "_msr_safe";
            m_test_dev_path.push_back(path.str());
        }

        union field_u {
            uint64_t field;
            uint16_t off[4];
        };
        union field_u fu;
        for (auto &path : m_test_dev_path) {
            int fd = open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
            int err = ftruncate(fd, MAX_OFFSET);
            if (err) {
                throw Exception("TestMSRIO: ftruncate failed", GEOPM_ERROR_RUNTIME, __FILE__, __LINE__);
            }
            uint64_t *contents = (uint64_t *)mmap(NULL, MAX_OFFSET, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
            close(fd);
            size_t num_field = MAX_OFFSET / sizeof(uint64_t);
            for (size_t field_idx = 0; field_idx < num_field; ++field_idx) {
                uint16_t offset = field_idx * sizeof(uint64_t);
                for (int off_idx = 0; off_idx < 4; ++off_idx) {
                   fu.off[off_idx] = offset;
                }
                contents[field_idx] = fu.field;
            }
            munmap(contents, MAX_OFFSET);
        }
    }

    TestPlatformIOMSRIO::~TestPlatformIOMSRIO()
    {
        for (auto &path : m_test_dev_path) {
            unlink(path.c_str());
        }
    }

    void TestPlatformIOMSRIO::msr_path(int cpu_idx,
                             bool is_fallback,
                             std::string &path)
    {
        path = m_test_dev_path[cpu_idx];
    }

    void TestPlatformIOMSRIO::msr_batch_path(std::string &path)
    {
        path = "test_dev_msr_safe";
    }
}

TestPlatformIO::TestPlatformIO(int cpuid)
    : m_cpuid(cpuid)
{
    m_msrio = new geopm::TestPlatformIOMSRIO;
}

TestPlatformIO::~TestPlatformIO()
{

}

int TestPlatformIO::cpuid(void)
{
    return m_cpuid;
}

void PlatformIOTest::SetUp()
{
    m_platform_io = new TestPlatformIO(0x657); // KNL CPUID
}

void PlatformIOTest::TearDown()
{
    delete m_platform_io;
}

TEST_F(PlatformIOTest, whitelist)
{
    std::ifstream file("test/legacy_whitelist.out");
    std::string line;
    uint64_t offset;
    uint64_t  mask;
    std::string comment;
    std::map<uint64_t, uint64_t> legacy_map;
    std::map<uint64_t, uint64_t> curr_map;
    while (std::getline(file, line)) {
        if (line.compare(0, 1, "#") == 0) continue;
        std::string tmp;
        size_t sz;
        std::istringstream iss(line);
        iss >> tmp;
        offset = std::stoull(tmp, &sz, 16);
        iss >> tmp;
        mask = std::stoull(tmp, &sz, 16);
        iss >> comment;// #
        iss >> comment;// comment
        legacy_map[offset] = mask;
    }

    std::string whitelist = m_platform_io->msr_whitelist();
    std::istringstream iss(whitelist);
    std::getline(iss, line);// throw away title line
    while (std::getline(iss, line)) {
        std::string tmp;
        size_t sz;
        std::istringstream iss(line);
        iss >> tmp;
        offset = std::stoull(tmp, &sz, 16);
        iss >> tmp;
        mask = std::stoull(tmp, &sz, 16);
        iss >> comment;// #
        iss >> comment;// comment
        curr_map[offset] = mask;
    }

    for (auto it = curr_map.begin(); it != curr_map.end(); ++it) {
        offset = it->first;
        mask = it->second;
        auto leg_it = legacy_map.find(offset);
        if (leg_it == legacy_map.end()) {
            //not found error
            if (!mask) {
                EXPECT_TRUE(false) << std::setfill('0') << std::hex << "new read offset 0x" << std::setw(8) << offset << " introduced";
            }
            continue;
        }
        uint64_t leg_mask = leg_it->second;
        EXPECT_EQ(mask, mask & leg_mask) << std::setfill('0') << std::hex << "offset 0x" << std::setw(8) << offset << "write mask change detected, from 0x"
            << std::setw(16) << leg_mask << " to 0x" << mask << " bitwise AND yields 0x" << (mask & leg_mask);
    }
}

TEST_F(PlatformIOTest, freq_ctl)
{
    int fd = open("test_msrio_dev_cpu_0_msr_safe",  O_RDWR);
    ASSERT_NE(-1, fd);
    uint64_t value;
    size_t num_read;
    num_read = pread(fd, &value, sizeof(value), 0x0);
    EXPECT_EQ(8ULL, num_read);
    EXPECT_EQ(0x0ULL, value);
    num_read = pread(fd, &value, sizeof(value), 0x198);
    EXPECT_EQ(8ULL, num_read);
    EXPECT_EQ(0x0198019801980198ULL, value);
    num_read = pread(fd, &value, sizeof(value), 0x1A0);
    EXPECT_EQ(8ULL, num_read);
    EXPECT_EQ(0x01A001A001A001A0ULL, value);

    int idx = m_platform_io->push_control("PERF_CTL:FREQ", geopm::IPlatformIO::M_DOMAIN_CPU, 0);
    ASSERT_EQ(0, idx);
    // Set frequency to 1 GHz
    m_platform_io->adjust(std::vector<double>{1e9});
    num_read = pread(fd, &value, sizeof(value), 0x199);
    EXPECT_EQ(8ULL, num_read);
    EXPECT_EQ(0xA00ULL, (value & 0xFF00));
    // Set frequency to 5 GHz
    m_platform_io->adjust(std::vector<double>{5e9});
    num_read = pread(fd, &value, sizeof(value), 0x199);
    EXPECT_EQ(8ULL, num_read);
    EXPECT_EQ(0x3200ULL, (value & 0xFF00));
    close(fd);
}

TEST_F(PlatformIOTest, time_signal)
{
    int idx = m_platform_io->push_signal("TIME", geopm::IPlatformIO::M_DOMAIN_CPU, 0);
    ASSERT_EQ(0, idx);
    std::vector<double> sample(1);
    double time_0 = m_platform_io->sample(idx);
    sleep(1);
    double time_1 = m_platform_io->sample(idx);
    EXPECT_LT(1, time_1 - time_0);
    EXPECT_LE(0, time_0);
    EXPECT_LE(0, time_1);
}
<commit_msg>Allow small time errors in TimeSignal test.<commit_after>/*
 * Copyright (c) 2015, 2016, 2017, Intel Corporation
 *
 * 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 Intel Corporation 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 LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sstream>
#include <fstream>
#include <string>
#include <map>
#include "gtest/gtest.h"

#include "geopm_sched.h"
#include "PlatformIO.hpp"
#include "PlatformIOInternal.hpp"
#include "MSRIO.hpp"
#include "Exception.hpp"

class TestPlatformIO : public geopm::PlatformIO
{
    public:
        TestPlatformIO(int cpuid);
        virtual ~TestPlatformIO();
    protected:
        int cpuid(void);

        int m_cpuid;
};

class PlatformIOTest : public :: testing :: Test
{
    protected:
        void SetUp();
        void TearDown();

        geopm::IPlatformIO *m_platform_io;
};

namespace geopm
{
    class TestPlatformIOMSRIO : public MSRIO
    {
        public:
            TestPlatformIOMSRIO();
            virtual ~TestPlatformIOMSRIO();
        protected:
            void msr_path(int cpu_idx,
                          bool is_fallback,
                          std::string &path);
            void msr_batch_path(std::string &path);

            std::vector<std::string> m_test_dev_path;
    };

    TestPlatformIOMSRIO::TestPlatformIOMSRIO()
    {
        const size_t MAX_OFFSET = 4096;
        int num_cpu = geopm_sched_num_cpu();
        for (int cpu_idx = 0; cpu_idx < num_cpu; ++cpu_idx) {
            std::ostringstream path;
            path << "test_msrio_dev_cpu_" << cpu_idx << "_msr_safe";
            m_test_dev_path.push_back(path.str());
        }

        union field_u {
            uint64_t field;
            uint16_t off[4];
        };
        union field_u fu;
        for (auto &path : m_test_dev_path) {
            int fd = open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
            int err = ftruncate(fd, MAX_OFFSET);
            if (err) {
                throw Exception("TestMSRIO: ftruncate failed", GEOPM_ERROR_RUNTIME, __FILE__, __LINE__);
            }
            uint64_t *contents = (uint64_t *)mmap(NULL, MAX_OFFSET, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
            close(fd);
            size_t num_field = MAX_OFFSET / sizeof(uint64_t);
            for (size_t field_idx = 0; field_idx < num_field; ++field_idx) {
                uint16_t offset = field_idx * sizeof(uint64_t);
                for (int off_idx = 0; off_idx < 4; ++off_idx) {
                   fu.off[off_idx] = offset;
                }
                contents[field_idx] = fu.field;
            }
            munmap(contents, MAX_OFFSET);
        }
    }

    TestPlatformIOMSRIO::~TestPlatformIOMSRIO()
    {
        for (auto &path : m_test_dev_path) {
            unlink(path.c_str());
        }
    }

    void TestPlatformIOMSRIO::msr_path(int cpu_idx,
                             bool is_fallback,
                             std::string &path)
    {
        path = m_test_dev_path[cpu_idx];
    }

    void TestPlatformIOMSRIO::msr_batch_path(std::string &path)
    {
        path = "test_dev_msr_safe";
    }
}

TestPlatformIO::TestPlatformIO(int cpuid)
    : m_cpuid(cpuid)
{
    m_msrio = new geopm::TestPlatformIOMSRIO;
}

TestPlatformIO::~TestPlatformIO()
{

}

int TestPlatformIO::cpuid(void)
{
    return m_cpuid;
}

void PlatformIOTest::SetUp()
{
    m_platform_io = new TestPlatformIO(0x657); // KNL CPUID
}

void PlatformIOTest::TearDown()
{
    delete m_platform_io;
}

TEST_F(PlatformIOTest, whitelist)
{
    std::ifstream file("test/legacy_whitelist.out");
    std::string line;
    uint64_t offset;
    uint64_t  mask;
    std::string comment;
    std::map<uint64_t, uint64_t> legacy_map;
    std::map<uint64_t, uint64_t> curr_map;
    while (std::getline(file, line)) {
        if (line.compare(0, 1, "#") == 0) continue;
        std::string tmp;
        size_t sz;
        std::istringstream iss(line);
        iss >> tmp;
        offset = std::stoull(tmp, &sz, 16);
        iss >> tmp;
        mask = std::stoull(tmp, &sz, 16);
        iss >> comment;// #
        iss >> comment;// comment
        legacy_map[offset] = mask;
    }

    std::string whitelist = m_platform_io->msr_whitelist();
    std::istringstream iss(whitelist);
    std::getline(iss, line);// throw away title line
    while (std::getline(iss, line)) {
        std::string tmp;
        size_t sz;
        std::istringstream iss(line);
        iss >> tmp;
        offset = std::stoull(tmp, &sz, 16);
        iss >> tmp;
        mask = std::stoull(tmp, &sz, 16);
        iss >> comment;// #
        iss >> comment;// comment
        curr_map[offset] = mask;
    }

    for (auto it = curr_map.begin(); it != curr_map.end(); ++it) {
        offset = it->first;
        mask = it->second;
        auto leg_it = legacy_map.find(offset);
        if (leg_it == legacy_map.end()) {
            //not found error
            if (!mask) {
                EXPECT_TRUE(false) << std::setfill('0') << std::hex << "new read offset 0x" << std::setw(8) << offset << " introduced";
            }
            continue;
        }
        uint64_t leg_mask = leg_it->second;
        EXPECT_EQ(mask, mask & leg_mask) << std::setfill('0') << std::hex << "offset 0x" << std::setw(8) << offset << "write mask change detected, from 0x"
            << std::setw(16) << leg_mask << " to 0x" << mask << " bitwise AND yields 0x" << (mask & leg_mask);
    }
}

TEST_F(PlatformIOTest, freq_ctl)
{
    int fd = open("test_msrio_dev_cpu_0_msr_safe",  O_RDWR);
    ASSERT_NE(-1, fd);
    uint64_t value;
    size_t num_read;
    num_read = pread(fd, &value, sizeof(value), 0x0);
    EXPECT_EQ(8ULL, num_read);
    EXPECT_EQ(0x0ULL, value);
    num_read = pread(fd, &value, sizeof(value), 0x198);
    EXPECT_EQ(8ULL, num_read);
    EXPECT_EQ(0x0198019801980198ULL, value);
    num_read = pread(fd, &value, sizeof(value), 0x1A0);
    EXPECT_EQ(8ULL, num_read);
    EXPECT_EQ(0x01A001A001A001A0ULL, value);

    int idx = m_platform_io->push_control("PERF_CTL:FREQ", geopm::IPlatformIO::M_DOMAIN_CPU, 0);
    ASSERT_EQ(0, idx);
    // Set frequency to 1 GHz
    m_platform_io->adjust(std::vector<double>{1e9});
    num_read = pread(fd, &value, sizeof(value), 0x199);
    EXPECT_EQ(8ULL, num_read);
    EXPECT_EQ(0xA00ULL, (value & 0xFF00));
    // Set frequency to 5 GHz
    m_platform_io->adjust(std::vector<double>{5e9});
    num_read = pread(fd, &value, sizeof(value), 0x199);
    EXPECT_EQ(8ULL, num_read);
    EXPECT_EQ(0x3200ULL, (value & 0xFF00));
    close(fd);
}

TEST_F(PlatformIOTest, time_signal)
{
    int idx = m_platform_io->push_signal("TIME", geopm::IPlatformIO::M_DOMAIN_CPU, 0);
    ASSERT_EQ(0, idx);
    std::vector<double> sample(1);
    double time_0 = m_platform_io->sample(idx);
    sleep(1);
    double time_1 = m_platform_io->sample(idx);
    EXPECT_NEAR(1, time_1 - time_0, 0.1);
    EXPECT_LE(0, time_0);
    EXPECT_LE(0, time_1);
}
<|endoftext|>


<commit_before>/*
 * exception.cpp
 *
 *  Created on: Jun 5, 2017
 *      Author: jiang
 */

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <metaverse/bitcoin/error.hpp>
#include <metaverse/explorer/extensions/exception.hpp>

namespace libbitcoin {
namespace explorer {

explorer_exception::explorer_exception(uint32_t code, const std::string& message) :
        code_{code}, message_{message}
{
}

std::ostream& operator<<(std::ostream& out, const explorer_exception& ex)
{
    boost::format fmt{"{\"code\":%d, \"message\":\"%s\", \"result\":null}"};
    out << (fmt % ex.code() % ex.message());
    return out;
}

void relay_exception(std::stringstream& ss)
{
    // parse json
    using namespace boost::property_tree;
    try
    {
        ptree pt;
        read_json(ss, pt);
        uint32_t code = pt.get<uint32_t>("code");
        std::string msg = pt.get<std::string>("message");
        if (code)
            return;
        throw explorer_exception{code, msg};
    }
    catch (const explorer_exception& e)
    {
        throw e;
    }
    catch (const std::exception& e)
    {
    }
}

} //namespace explorer
} //namespace libbitcoin
<commit_msg>compat to exception json. it means add a feild of error to json sentence<commit_after>/*
 * exception.cpp
 *
 *  Created on: Jun 5, 2017
 *      Author: jiang
 */

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <metaverse/bitcoin/error.hpp>
#include <metaverse/explorer/extensions/exception.hpp>

namespace libbitcoin {
namespace explorer {

explorer_exception::explorer_exception(uint32_t code, const std::string& message) :
        code_{code}, message_{message}
{
}

std::ostream& operator<<(std::ostream& out, const explorer_exception& ex)
{
    boost::format fmt{"{\"code\":%d, \"message\":\"%s\", \"error\":\"%s\", \"result\":null}"};
    out << (fmt % ex.code() % ex.message() % ex.message());
    return out;
}

void relay_exception(std::stringstream& ss)
{
    // parse json
    using namespace boost::property_tree;
    try
    {
        ptree pt;
        read_json(ss, pt);
        uint32_t code = pt.get<uint32_t>("code");
        std::string msg = pt.get<std::string>("message");
        if (code)
            return;
        throw explorer_exception{code, msg};
    }
    catch (const explorer_exception& e)
    {
        throw e;
    }
    catch (const std::exception& e)
    {
    }
}

} //namespace explorer
} //namespace libbitcoin
<|endoftext|>


<commit_before>#ifndef WRAP_ITER_HPP__
#define WRAP_ITER_HPP__

namespace iter {
    template <typename Iterator>
    struct wrap_iter {
        public:
            Iterator iter;
            typename std::iterator_traits<Iterator>::difference_type step;

            wrap_iter(const Iterator & iter,
                    typename std::iterator_traits<Iterator>::difference_type step) :
                iter(iter),
                step(step)
            { }

            wrap_iter & operator++() {
                iter += step;
                return *this;
            }

            bool operator!=(const wrap_iter & rhs) {
                return this->iter != rhs.iter;
            }

            auto operator*() -> decltype(*iter)
            {
                return *iter;
            }
    };

    template <typename Iterator>
    wrap_iter<Iterator> make_wrap_iter(const Iterator & iter,
            typename std::iterator_traits<Iterator>::difference_type step) {
        return wrap_iter<Iterator>(iter,step);
    }
}

#endif //WRAP_ITER_HPP__
<commit_msg>Adds private and constness to wrap_iter<commit_after>#ifndef WRAP_ITER_HPP__
#define WRAP_ITER_HPP__

namespace iter {
    template <typename Iterator>
    class wrap_iter {
        private:
            Iterator iter;
            typename std::iterator_traits<Iterator>::difference_type step;

        public:
            wrap_iter(const Iterator & iter,
                    typename std::iterator_traits<Iterator>::difference_type step) :
                iter(iter),
                step(step)
            { }

            wrap_iter & operator++() {
                iter += step;
                return *this;
            }

            bool operator!=(const wrap_iter & rhs) const {
                return this->iter != rhs.iter;
            }

            auto operator*() const -> decltype(*iter)
            {
                return *iter;
            }
    };

    template <typename Iterator>
    wrap_iter<Iterator> make_wrap_iter(const Iterator & iter,
            typename std::iterator_traits<Iterator>::difference_type step) {
        return wrap_iter<Iterator>(iter,step);
    }
}

#endif //WRAP_ITER_HPP__
<|endoftext|>


<commit_before>#include "mugen_background.h"

#include <math.h>
#include <ostream>
#include <cstring>
#include <string>
#include "globals.h"
#include "mugen_sprite.h"
#include "util/bitmap.h"

using namespace std;

static int calculateTile( int length, int width ){
    int loc = 0;
    for( int i = 1; ; ++i ){
	if( loc > length )return i;
	loc+=width;
    }
}

static void doParallax(Bitmap &bmp, Bitmap &work, int xscroll, int y1, float z1, int y2, float z2){
   if(y2 <= y1) return;

   // trade down the centre of the screen
   float z = 1.0 / z1;
   float z_add = ((1.0 / z2) - z) / (y2 - y1);
   float src_y = 0;
   float src_y_add = ((float)bmp.getHeight() / z2) / (y2 - y1);

   while(y1 < y2)
   {
      float y = src_y / z;
      int start_x = (work.getWidth() >> 1) - z*((bmp.getWidth() >> 1) + xscroll);
      int width = bmp.getWidth()*z;

      //stretch_blit(source, dest, 0, y, source->w, 1, start_x, y1, width, 1);
      bmp.Stretch( work, 0, y, bmp.getWidth(), 1, start_x, y1, width, 1 );

      y1++;
      z +=  z_add;
      src_y += src_y_add;
   }
}

static int idCounter = -9999999;

BgController::BgController( ControlType ctrl, std::vector<int>ids ):
type(ctrl),
timestart(0),
endtime(0),
looptime(0),
ctrlID(ids){
}
BgController::~BgController(){
}
void BgController::act( std::map<int, MugenBackground *> &bgs ){
    // nothing
}

MugenBgController::MugenBgController( std::string &n, std::vector<int>ids ):
name(n),
looptime(0),
ctrlID(ids){
}
MugenBgController::~MugenBgController(){
}
void MugenBgController::addControl( BgController *ctrl ){
    controls.push_back(ctrl);
}
void MugenBgController::act( std::map<int, MugenBackground *> &bgs ){
}

// mugen background
MugenBackground::MugenBackground():
type(Normal),
groupNumber(-1),
imageNumber(-1),
actionno(-1),
id(++idCounter),
layerno(0),
startx(0),
starty(0),
deltax(0),
deltay(0),
trans(None),
alphalow(0),
alphahigh(0),
mask(true),
tilex(0),
tiley(0),
tilespacingx(0),
tilespacingy(0),
windowdeltax(0),
windowdeltay(0),
xscaletop(0),
xscalebot(0),
yscalestart(0),
yscaledelta(0),
positionlink(false),
velocityx(0),
velocityy(0),
sinx_amp(0),
sinx_period(0),
sinx_offset(0),
siny_amp(0),
siny_period(0),
siny_offset(0),
sin_angle(0),
xoffset(0),
yoffset(0),
movex(0),
movey(0),
velx(0),
vely(0),
ticks(0),
sprite(0),
spriteBmp(0),
action(0){
}
MugenBackground::MugenBackground( const MugenBackground &copy ){
}
MugenBackground::~MugenBackground(){
    // Kill the bmp
    if( spriteBmp )delete spriteBmp;
}
MugenBackground & MugenBackground::operator=( const MugenBackground &copy ){

    return *this;
}

void MugenBackground::logic( const int &x, const int &y ){
    movex = movey = 0;
    movex += x * deltax;
    movey += y * deltay;
    velx += velocityx;
    vely += velocityy;
    /* how much should sin_angle be incremented by each frame? */
    sin_angle += 0.00005;
    //whatvar = sinx_amp * sin(whatvar*sinx_period + sinx_offset);
    //whatvar = siny_amp * sin(whatvar*siny_period + siny_offset);
    ticks++;
    if( ticks >= 1 ){
	// Do frame or whatever movement etc
	// Reset
	ticks = 0;
    }
    if( type == Anim ) action->logic();
    Global::debug(1) << "x move: " << x << " | y move: " << y << endl;
}

void MugenBackground::render( const int &totalLength, const int &totalHeight, Bitmap *work ){
    const int x = (int)(xoffset + movex + velx + sinx_amp * sin(sin_angle*sinx_period + sinx_offset));
    const int y = (int)(yoffset + movey + vely + siny_amp * sin(sin_angle*siny_period + siny_offset));
    switch( type ){
	case Normal:{
	    // Normal is a sprite
	    // see if we need to tile this beyatch
	    int tilexloc = x;
	    const int width = spriteBmp->getWidth();
	    const int height = spriteBmp->getHeight();
	    bool dirx = false, diry = false;
	    // Figure out total we need to tile (this crap doesn't work needs fix)
	    int repeath = (tilex > 0 ? (tilex > 1 ? tilex : ( calculateTile( totalLength, width ) ) ) : 1 );
	    int repeatv = ( tiley > 0 ? (tiley > 1 ? tiley : ( calculateTile( totalLength, height ) ) ) : 1 );
	    // We need to repeat and wrap
	    for( int h = 0; h < repeath; h++ ){
		int tileyloc = y;
		for( int v = 0; v < repeatv; v++ ){
		    draw( tilexloc, tileyloc, *work );
		    if( !diry )tileyloc += height + tilespacingy;
		    else tileyloc -= height + tilespacingy;
		    if( tileyloc >= work->getHeight() ){
			diry = true;
			tileyloc = y - height + tilespacingy;
		    }
		}
		if( !dirx )tilexloc += width + tilespacingx;
		else tilexloc -= width + tilespacingx;
		if( tilexloc >= work->getWidth() ){
		    dirx = true;
		    tilexloc = x - width + tilespacingx;
		}
	    }
	    break;
	}
	case Parallax:{
	    // This is also a sprite but we must parallax it across the top and bottom to give the illusion of depth
	    doParallax( *spriteBmp, *work, x + 160, y - (((yscalestart + yscaledelta)/100)*movey), xscaletop * 1 , y + spriteBmp->getHeight() + (((yscalestart + yscaledelta)/100)*movey), xscaletop * 1.75);
	    break;
	}
	case Anim:{
	    // there is no sprite use our action!
	    action->render( x, y, *work );
	    break;
	}
	case Dummy:
	    // Do nothing
	default:
	    break;
    }

}

void MugenBackground::preload( const int &xaxis, const int &yaxis ){
    // Lets load our sprite
    if(sprite){
	spriteBmp = new Bitmap(Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength));
	// Set our initial offsets
	xoffset = 160 + (xaxis - sprite->x) + startx;
	yoffset = (yaxis - sprite->y) + starty;
	velx = vely = 0;
    }
    else{
	// Set our initial offsets
	xoffset = 160 + (xaxis) + startx;
	yoffset = (yaxis) + starty;
	velx = vely = 0;
    }
}

void MugenBackground::draw( const int &x, const int &y, Bitmap &work ){
    // This needs to be a switch trans = None, Add, Add1, Sub1, Addalpha
    switch( trans ){
	case Addalpha:{
	    // Need to figure out blend correctly addalpha is given to two locations low and high ?
	    Bitmap::transBlender( 0, 0, 0, alphalow );
            Bitmap::drawingMode( Bitmap::MODE_TRANS );
	    spriteBmp->drawTrans( x, y, work);
            Bitmap::drawingMode( Bitmap::MODE_SOLID );
	    break;
	}
	case Add:
	case Add1:
	case Sub:
	case None:
	default:{
	    if( mask )spriteBmp->draw( x,y, work );
	    else spriteBmp->Blit( x, y, work );
	    break;
	}
    }
}
<commit_msg>add comment about sin motion<commit_after>#include "mugen_background.h"

#include <math.h>
#include <ostream>
#include <cstring>
#include <string>
#include "globals.h"
#include "mugen_sprite.h"
#include "util/bitmap.h"

using namespace std;

static int calculateTile( int length, int width ){
    int loc = 0;
    for( int i = 1; ; ++i ){
	if( loc > length )return i;
	loc+=width;
    }
}

static void doParallax(Bitmap &bmp, Bitmap &work, int xscroll, int y1, float z1, int y2, float z2){
   if(y2 <= y1) return;

   // trade down the centre of the screen
   float z = 1.0 / z1;
   float z_add = ((1.0 / z2) - z) / (y2 - y1);
   float src_y = 0;
   float src_y_add = ((float)bmp.getHeight() / z2) / (y2 - y1);

   while(y1 < y2)
   {
      float y = src_y / z;
      int start_x = (work.getWidth() >> 1) - z*((bmp.getWidth() >> 1) + xscroll);
      int width = bmp.getWidth()*z;

      //stretch_blit(source, dest, 0, y, source->w, 1, start_x, y1, width, 1);
      bmp.Stretch( work, 0, y, bmp.getWidth(), 1, start_x, y1, width, 1 );

      y1++;
      z +=  z_add;
      src_y += src_y_add;
   }
}

static int idCounter = -9999999;

BgController::BgController( ControlType ctrl, std::vector<int>ids ):
type(ctrl),
timestart(0),
endtime(0),
looptime(0),
ctrlID(ids){
}
BgController::~BgController(){
}
void BgController::act( std::map<int, MugenBackground *> &bgs ){
    // nothing
}

MugenBgController::MugenBgController( std::string &n, std::vector<int>ids ):
name(n),
looptime(0),
ctrlID(ids){
}
MugenBgController::~MugenBgController(){
}
void MugenBgController::addControl( BgController *ctrl ){
    controls.push_back(ctrl);
}
void MugenBgController::act( std::map<int, MugenBackground *> &bgs ){
}

// mugen background
MugenBackground::MugenBackground():
type(Normal),
groupNumber(-1),
imageNumber(-1),
actionno(-1),
id(++idCounter),
layerno(0),
startx(0),
starty(0),
deltax(0),
deltay(0),
trans(None),
alphalow(0),
alphahigh(0),
mask(true),
tilex(0),
tiley(0),
tilespacingx(0),
tilespacingy(0),
windowdeltax(0),
windowdeltay(0),
xscaletop(0),
xscalebot(0),
yscalestart(0),
yscaledelta(0),
positionlink(false),
velocityx(0),
velocityy(0),
sinx_amp(0),
sinx_period(0),
sinx_offset(0),
siny_amp(0),
siny_period(0),
siny_offset(0),
sin_angle(0),
xoffset(0),
yoffset(0),
movex(0),
movey(0),
velx(0),
vely(0),
ticks(0),
sprite(0),
spriteBmp(0),
action(0){
}
MugenBackground::MugenBackground( const MugenBackground &copy ){
}
MugenBackground::~MugenBackground(){
    // Kill the bmp
    if( spriteBmp )delete spriteBmp;
}
MugenBackground & MugenBackground::operator=( const MugenBackground &copy ){

    return *this;
}

void MugenBackground::logic( const int &x, const int &y ){
    movex = movey = 0;
    movex += x * deltax;
    movey += y * deltay;
    velx += velocityx;
    vely += velocityy;
    /* how much should sin_angle be incremented by each frame?
     * I think the total angle should be (ticks % sin_period) * 2pi / sin_period
     */
    sin_angle += 0.00005;
    //whatvar = sinx_amp * sin(whatvar*sinx_period + sinx_offset);
    //whatvar = siny_amp * sin(whatvar*siny_period + siny_offset);
    ticks++;
    if( ticks >= 1 ){
	// Do frame or whatever movement etc
	// Reset
	ticks = 0;
    }
    if( type == Anim ) action->logic();
    Global::debug(1) << "x move: " << x << " | y move: " << y << endl;
}

void MugenBackground::render( const int &totalLength, const int &totalHeight, Bitmap *work ){
    const int x = (int)(xoffset + movex + velx + sinx_amp * sin(sin_angle*sinx_period + sinx_offset));
    const int y = (int)(yoffset + movey + vely + siny_amp * sin(sin_angle*siny_period + siny_offset));
    switch( type ){
	case Normal:{
	    // Normal is a sprite
	    // see if we need to tile this beyatch
	    int tilexloc = x;
	    const int width = spriteBmp->getWidth();
	    const int height = spriteBmp->getHeight();
	    bool dirx = false, diry = false;
	    // Figure out total we need to tile (this crap doesn't work needs fix)
	    int repeath = (tilex > 0 ? (tilex > 1 ? tilex : ( calculateTile( totalLength, width ) ) ) : 1 );
	    int repeatv = ( tiley > 0 ? (tiley > 1 ? tiley : ( calculateTile( totalLength, height ) ) ) : 1 );
	    // We need to repeat and wrap
	    for( int h = 0; h < repeath; h++ ){
		int tileyloc = y;
		for( int v = 0; v < repeatv; v++ ){
		    draw( tilexloc, tileyloc, *work );
		    if( !diry )tileyloc += height + tilespacingy;
		    else tileyloc -= height + tilespacingy;
		    if( tileyloc >= work->getHeight() ){
			diry = true;
			tileyloc = y - height + tilespacingy;
		    }
		}
		if( !dirx )tilexloc += width + tilespacingx;
		else tilexloc -= width + tilespacingx;
		if( tilexloc >= work->getWidth() ){
		    dirx = true;
		    tilexloc = x - width + tilespacingx;
		}
	    }
	    break;
	}
	case Parallax:{
	    // This is also a sprite but we must parallax it across the top and bottom to give the illusion of depth
	    doParallax( *spriteBmp, *work, x + 160, y - (((yscalestart + yscaledelta)/100)*movey), xscaletop * 1 , y + spriteBmp->getHeight() + (((yscalestart + yscaledelta)/100)*movey), xscaletop * 1.75);
	    break;
	}
	case Anim:{
	    // there is no sprite use our action!
	    action->render( x, y, *work );
	    break;
	}
	case Dummy:
	    // Do nothing
	default:
	    break;
    }

}

void MugenBackground::preload( const int &xaxis, const int &yaxis ){
    // Lets load our sprite
    if(sprite){
	spriteBmp = new Bitmap(Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength));
	// Set our initial offsets
	xoffset = 160 + (xaxis - sprite->x) + startx;
	yoffset = (yaxis - sprite->y) + starty;
	velx = vely = 0;
    }
    else{
	// Set our initial offsets
	xoffset = 160 + (xaxis) + startx;
	yoffset = (yaxis) + starty;
	velx = vely = 0;
    }
}

void MugenBackground::draw( const int &x, const int &y, Bitmap &work ){
    // This needs to be a switch trans = None, Add, Add1, Sub1, Addalpha
    switch( trans ){
	case Addalpha:{
	    // Need to figure out blend correctly addalpha is given to two locations low and high ?
	    Bitmap::transBlender( 0, 0, 0, alphalow );
            Bitmap::drawingMode( Bitmap::MODE_TRANS );
	    spriteBmp->drawTrans( x, y, work);
            Bitmap::drawingMode( Bitmap::MODE_SOLID );
	    break;
	}
	case Add:
	case Add1:
	case Sub:
	case None:
	default:{
	    if( mask )spriteBmp->draw( x,y, work );
	    else spriteBmp->Blit( x, y, work );
	    break;
	}
    }
}
<|endoftext|>


<commit_before>#include "subscribe.h"
#include <cassert>
#include <algorithm>

using namespace dariadb::storage;

SubscribeInfo::SubscribeInfo(const IdArray &i,const Flag& f, const ReaderClb_ptr &c):
    ids(i),flag(f),clbk(c){

}

bool SubscribeInfo::isYours(const dariadb::Meas&m) const {
	if ((ids.size() == 0) || (std::find(ids.cbegin(), ids.cend(), m.id) != ids.cend())) {
		if ((flag == 0) || (flag == m.flag)) {
			return true;
		}
	}
	return false;
}

SubscribeNotificator::~SubscribeNotificator() {
	if (!is_stoped) {
		this->stop();
	}
}

void SubscribeNotificator::start() {
	std::lock_guard<std::mutex> lg(_mutex);
	is_stoped = false;
}

void SubscribeNotificator::stop() {
	std::lock_guard<std::mutex> lg(_mutex);
	is_stoped = true;
}

void SubscribeNotificator::add(const SubscribeInfo_ptr&n) {
	std::lock_guard<std::mutex> lg(_mutex);
	assert(!is_stoped);
	_subscribes.push_back(n);
}

void SubscribeNotificator::on_append(const dariadb::Meas&m)const {
	for (auto si : _subscribes) {
		assert(si->clbk != nullptr);
		if (si->isYours(m)) {
			si->clbk->call(m);
		}
	}
}
<commit_msg>msvc build.<commit_after>#include "subscribe.h"
#include <cassert>
#include <algorithm>

using namespace dariadb::storage;
using namespace dariadb;

SubscribeInfo::SubscribeInfo(const IdArray &i,const Flag& f, const ReaderClb_ptr &c):
    ids(i),flag(f),clbk(c){

}

bool SubscribeInfo::isYours(const dariadb::Meas&m) const {
	if ((ids.size() == 0) || (std::find(ids.cbegin(), ids.cend(), m.id) != ids.cend())) {
		if ((flag == 0) || (flag == m.flag)) {
			return true;
		}
	}
	return false;
}

SubscribeNotificator::~SubscribeNotificator() {
	if (!is_stoped) {
		this->stop();
	}
}

void SubscribeNotificator::start() {
	std::lock_guard<std::mutex> lg(_mutex);
	is_stoped = false;
}

void SubscribeNotificator::stop() {
	std::lock_guard<std::mutex> lg(_mutex);
	is_stoped = true;
}

void SubscribeNotificator::add(const SubscribeInfo_ptr&n) {
	std::lock_guard<std::mutex> lg(_mutex);
	assert(!is_stoped);
	_subscribes.push_back(n);
}

void SubscribeNotificator::on_append(const dariadb::Meas&m)const {
	for (auto si : _subscribes) {
		assert(si->clbk != nullptr);
		if (si->isYours(m)) {
			si->clbk->call(m);
		}
	}
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file BlockInfo.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include <libethcore/CommonEth.h>
#include "ProofOfWork.h"
#include "Exceptions.h"
#include "BlockInfo.h"
using namespace std;
using namespace dev;
using namespace dev::eth;

u256 dev::eth::c_genesisDifficulty = (u256)1 << 11;

BlockInfo::BlockInfo(): timestamp(Invalid256)
{
}

BlockInfo::BlockInfo(bytesConstRef _block, bool _checkNonce)
{
	populate(_block, _checkNonce);
}

void BlockInfo::setEmpty()
{
	parentHash = h256();
	sha3Uncles = EmptyListSHA3;
	coinbaseAddress = Address();
	stateRoot = EmptyTrie;
	transactionsRoot = EmptyTrie;
	receiptsRoot = EmptyTrie;
	logBloom = LogBloom();
	difficulty = 0;
	number = 0;
	gasLimit = 0;
	gasUsed = 0;
	timestamp = 0;
	extraData.clear();
	seedHash = h256();
	mixBytes = h256();
	nonce = Nonce();
	hash = headerHash(WithNonce);
}

BlockInfo BlockInfo::fromHeader(bytesConstRef _block)
{
	BlockInfo ret;
	ret.populateFromHeader(RLP(_block));
	return ret;
}

h256 BlockInfo::headerHash(IncludeNonce _n) const
{
	RLPStream s;
	streamRLP(s, _n);
	return sha3(s.out());
}

void BlockInfo::streamRLP(RLPStream& _s, IncludeNonce _n) const
{
	_s.appendList(_n == WithNonce ? 16 : 14)
		<< parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot << receiptsRoot << logBloom
		<< difficulty << number << gasLimit << gasUsed << timestamp << extraData << seedHash;
	if (_n == WithNonce)
		_s << mixBytes << nonce;
}

h256 BlockInfo::headerHash(bytesConstRef _block)
{
	return sha3(RLP(_block)[0].data());
}

void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
{
	hash = dev::sha3(_header.data());

	int field = 0;
	try
	{
		parentHash = _header[field = 0].toHash<h256>();
		sha3Uncles = _header[field = 1].toHash<h256>();
		coinbaseAddress = _header[field = 2].toHash<Address>();
		stateRoot = _header[field = 3].toHash<h256>();
		transactionsRoot = _header[field = 4].toHash<h256>();
		receiptsRoot = _header[field = 5].toHash<h256>();
		logBloom = _header[field = 6].toHash<LogBloom>();
		difficulty = _header[field = 7].toInt<u256>();
		number = _header[field = 8].toInt<u256>();
		gasLimit = _header[field = 9].toInt<u256>();
		gasUsed = _header[field = 10].toInt<u256>();
		timestamp = _header[field = 11].toInt<u256>();
		extraData = _header[field = 12].toBytes();
		seedHash = _header[field = 13].toHash<h256>();
		mixBytes = _header[field = 14].toHash<h256>();
		nonce = _header[field = 15].toHash<Nonce>();
	}

	catch (Exception const& _e)
	{
		_e << errinfo_name("invalid block header format") << BadFieldError(field, toHex(_header[field].data().toBytes()));
		throw;
	}

	// check it hashes according to proof of work or that it's the genesis block.
	if (_checkNonce && parentHash && !ProofOfWork::verify(*this))
		BOOST_THROW_EXCEPTION(InvalidBlockNonce(headerHash(WithoutNonce), nonce, difficulty));

	if (gasUsed > gasLimit)
		BOOST_THROW_EXCEPTION(TooMuchGasUsed());

	if (number && extraData.size() > 1024)
		BOOST_THROW_EXCEPTION(ExtraDataTooBig());
}

void BlockInfo::populate(bytesConstRef _block, bool _checkNonce)
{
	RLP root(_block);
	RLP header = root[0];

	if (!header.isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(0, header.data()) << errinfo_comment("block header needs to be a list"));
	populateFromHeader(header, _checkNonce);

	if (!root[1].isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(1, root[1].data()));
	if (!root[2].isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(2, root[2].data()));
}

void BlockInfo::verifyInternals(bytesConstRef _block) const
{
	RLP root(_block);

	u256 mgp = (u256)-1;

	OverlayDB db;
	GenericTrieDB<OverlayDB> t(&db);
	t.init();
	unsigned i = 0;
	for (auto const& tr: root[1])
	{
		bytes k = rlp(i);
		t.insert(&k, tr.data());
		u256 gasprice = tr[1].toInt<u256>();
		mgp = min(mgp, gasprice); // the minimum gas price is not used for anything //TODO delete?
		++i;
	}
	if (transactionsRoot != t.root())
		BOOST_THROW_EXCEPTION(InvalidTransactionsHash(t.root(), transactionsRoot));

	if (sha3Uncles != sha3(root[2].data()))
		BOOST_THROW_EXCEPTION(InvalidUnclesHash());
}

void BlockInfo::populateFromParent(BlockInfo const& _parent)
{
	stateRoot = _parent.stateRoot;
	parentHash = _parent.hash;
	number = _parent.number + 1;
	gasLimit = calculateGasLimit(_parent);
	gasUsed = 0;
	difficulty = calculateDifficulty(_parent);
	seedHash = number % 30 == 0 ? sha3(_parent.seedHash.asBytes() /*+ _parent.hash.asBytes()*/) : _parent.seedHash;
}

u256 BlockInfo::calculateGasLimit(BlockInfo const& _parent) const
{
	if (!parentHash)
		return 1000000;
	else
		return max<u256>(125000, (_parent.gasLimit * (1024 - 1) + (_parent.gasUsed * 6 / 5)) / 1024);
}

u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const
{
	if (!parentHash)
		return c_genesisDifficulty;
	else
		return max<u256>(2048, timestamp >= _parent.timestamp + (c_protocolVersion == 49 ? 5 : 8) ? _parent.difficulty - (_parent.difficulty / 2048) : (_parent.difficulty + (_parent.difficulty / 2048)));
}

template <class N> inline N diff(N const& _a, N const& _b) { return max(_a, _b) - min(_a, _b); }

void BlockInfo::verifyParent(BlockInfo const& _parent) const
{	// Check difficulty is correct given the two timestamps.
	if (difficulty != calculateDifficulty(_parent))
		BOOST_THROW_EXCEPTION(InvalidDifficulty());

	if (diff(gasLimit, _parent.gasLimit) <= _parent.gasLimit / 1024)
		BOOST_THROW_EXCEPTION(InvalidGasLimit(gasLimit, calculateGasLimit(_parent), diff(gasLimit, _parent.gasLimit), _parent.gasLimit / 1024));

	// Check timestamp is after previous timestamp.
	if (parentHash)
	{
		if (parentHash != _parent.hash)
			BOOST_THROW_EXCEPTION(InvalidParentHash());

		if (timestamp <= _parent.timestamp)
			BOOST_THROW_EXCEPTION(InvalidTimestamp());

		if (number != _parent.number + 1)
			BOOST_THROW_EXCEPTION(InvalidNumber());
	}
}
<commit_msg>fix blockGasLimit bug : 1024 -> 2048<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file BlockInfo.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include <libethcore/CommonEth.h>
#include "ProofOfWork.h"
#include "Exceptions.h"
#include "BlockInfo.h"
using namespace std;
using namespace dev;
using namespace dev::eth;

u256 dev::eth::c_genesisDifficulty = (u256)1 << 11;

BlockInfo::BlockInfo(): timestamp(Invalid256)
{
}

BlockInfo::BlockInfo(bytesConstRef _block, bool _checkNonce)
{
	populate(_block, _checkNonce);
}

void BlockInfo::setEmpty()
{
	parentHash = h256();
	sha3Uncles = EmptyListSHA3;
	coinbaseAddress = Address();
	stateRoot = EmptyTrie;
	transactionsRoot = EmptyTrie;
	receiptsRoot = EmptyTrie;
	logBloom = LogBloom();
	difficulty = 0;
	number = 0;
	gasLimit = 0;
	gasUsed = 0;
	timestamp = 0;
	extraData.clear();
	seedHash = h256();
	mixBytes = h256();
	nonce = Nonce();
	hash = headerHash(WithNonce);
}

BlockInfo BlockInfo::fromHeader(bytesConstRef _block)
{
	BlockInfo ret;
	ret.populateFromHeader(RLP(_block));
	return ret;
}

h256 BlockInfo::headerHash(IncludeNonce _n) const
{
	RLPStream s;
	streamRLP(s, _n);
	return sha3(s.out());
}

void BlockInfo::streamRLP(RLPStream& _s, IncludeNonce _n) const
{
	_s.appendList(_n == WithNonce ? 16 : 14)
		<< parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot << receiptsRoot << logBloom
		<< difficulty << number << gasLimit << gasUsed << timestamp << extraData << seedHash;
	if (_n == WithNonce)
		_s << mixBytes << nonce;
}

h256 BlockInfo::headerHash(bytesConstRef _block)
{
	return sha3(RLP(_block)[0].data());
}

void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
{
	hash = dev::sha3(_header.data());

	int field = 0;
	try
	{
		parentHash = _header[field = 0].toHash<h256>();
		sha3Uncles = _header[field = 1].toHash<h256>();
		coinbaseAddress = _header[field = 2].toHash<Address>();
		stateRoot = _header[field = 3].toHash<h256>();
		transactionsRoot = _header[field = 4].toHash<h256>();
		receiptsRoot = _header[field = 5].toHash<h256>();
		logBloom = _header[field = 6].toHash<LogBloom>();
		difficulty = _header[field = 7].toInt<u256>();
		number = _header[field = 8].toInt<u256>();
		gasLimit = _header[field = 9].toInt<u256>();
		gasUsed = _header[field = 10].toInt<u256>();
		timestamp = _header[field = 11].toInt<u256>();
		extraData = _header[field = 12].toBytes();
		seedHash = _header[field = 13].toHash<h256>();
		mixBytes = _header[field = 14].toHash<h256>();
		nonce = _header[field = 15].toHash<Nonce>();
	}

	catch (Exception const& _e)
	{
		_e << errinfo_name("invalid block header format") << BadFieldError(field, toHex(_header[field].data().toBytes()));
		throw;
	}

	// check it hashes according to proof of work or that it's the genesis block.
	if (_checkNonce && parentHash && !ProofOfWork::verify(*this))
		BOOST_THROW_EXCEPTION(InvalidBlockNonce(headerHash(WithoutNonce), nonce, difficulty));

	if (gasUsed > gasLimit)
		BOOST_THROW_EXCEPTION(TooMuchGasUsed());

	if (number && extraData.size() > 1024)
		BOOST_THROW_EXCEPTION(ExtraDataTooBig());
}

void BlockInfo::populate(bytesConstRef _block, bool _checkNonce)
{
	RLP root(_block);
	RLP header = root[0];

	if (!header.isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(0, header.data()) << errinfo_comment("block header needs to be a list"));
	populateFromHeader(header, _checkNonce);

	if (!root[1].isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(1, root[1].data()));
	if (!root[2].isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(2, root[2].data()));
}

void BlockInfo::verifyInternals(bytesConstRef _block) const
{
	RLP root(_block);

	u256 mgp = (u256)-1;

	OverlayDB db;
	GenericTrieDB<OverlayDB> t(&db);
	t.init();
	unsigned i = 0;
	for (auto const& tr: root[1])
	{
		bytes k = rlp(i);
		t.insert(&k, tr.data());
		u256 gasprice = tr[1].toInt<u256>();
		mgp = min(mgp, gasprice); // the minimum gas price is not used for anything //TODO delete?
		++i;
	}
	if (transactionsRoot != t.root())
		BOOST_THROW_EXCEPTION(InvalidTransactionsHash(t.root(), transactionsRoot));

	if (sha3Uncles != sha3(root[2].data()))
		BOOST_THROW_EXCEPTION(InvalidUnclesHash());
}

void BlockInfo::populateFromParent(BlockInfo const& _parent)
{
	stateRoot = _parent.stateRoot;
	parentHash = _parent.hash;
	number = _parent.number + 1;
	gasLimit = calculateGasLimit(_parent);
	gasUsed = 0;
	difficulty = calculateDifficulty(_parent);
	seedHash = number % 30 == 0 ? sha3(_parent.seedHash.asBytes() /*+ _parent.hash.asBytes()*/) : _parent.seedHash;
}

u256 BlockInfo::calculateGasLimit(BlockInfo const& _parent) const
{
	if (!parentHash)
		return 1000000;
	else
		return max<u256>(125000, (_parent.gasLimit * (1024 - 1) + (_parent.gasUsed * 6 / 5)) / 1024);
}

u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const
{
	if (!parentHash)
		return c_genesisDifficulty;
	else
		return max<u256>(2048, timestamp >= _parent.timestamp + (c_protocolVersion == 49 ? 5 : 8) ? _parent.difficulty - (_parent.difficulty / 2048) : (_parent.difficulty + (_parent.difficulty / 2048)));
}

template <class N> inline N diff(N const& _a, N const& _b) { return max(_a, _b) - min(_a, _b); }

void BlockInfo::verifyParent(BlockInfo const& _parent) const
{	// Check difficulty is correct given the two timestamps.
	if (difficulty != calculateDifficulty(_parent))
		BOOST_THROW_EXCEPTION(InvalidDifficulty());

	if (diff(gasLimit, _parent.gasLimit) <= _parent.gasLimit / 2048)
		BOOST_THROW_EXCEPTION(InvalidGasLimit(gasLimit, calculateGasLimit(_parent), diff(gasLimit, _parent.gasLimit), _parent.gasLimit / 2048));

	// Check timestamp is after previous timestamp.
	if (parentHash)
	{
		if (parentHash != _parent.hash)
			BOOST_THROW_EXCEPTION(InvalidParentHash());

		if (timestamp <= _parent.timestamp)
			BOOST_THROW_EXCEPTION(InvalidTimestamp());

		if (number != _parent.number + 1)
			BOOST_THROW_EXCEPTION(InvalidNumber());
	}
}
<|endoftext|>