<commit_before>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

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 the author 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.

*/

#ifndef ROUTING_TABLE_HPP
#define ROUTING_TABLE_HPP

#include <vector>
#include <boost/cstdint.hpp>

#include <boost/utility.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/array.hpp>
#include <set>

#include <libtorrent/kademlia/logging.hpp>

#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/node_entry.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/size_type.hpp>
#include <libtorrent/assert.hpp>
#include <libtorrent/ptime.hpp>

namespace libtorrent
{
	struct session_status;
}

namespace libtorrent { namespace dht
{

#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(table);
#endif

typedef std::vector<node_entry> bucket_t;

struct routing_table_node
{
	bucket_t replacements;
	bucket_t live_nodes;
	ptime last_active;
};

// differences in the implementation from the description in
// the paper:
//
// * Nodes are not marked as being stale, they keep a counter
// 	that tells how many times in a row they have failed. When
// 	a new node is to be inserted, the node that has failed
// 	the most times is replaced. If none of the nodes in the
// 	bucket has failed, then it is put in the replacement
// 	cache (just like in the paper).

class TORRENT_EXPORT routing_table
{
public:
	routing_table(node_id const& id, int bucket_size
		, dht_settings const& settings);

	void status(session_status& s) const;

	void node_failed(node_id const& id);

	// adds an endpoint that will never be added to
	// the routing table
	void add_router_node(udp::endpoint router);

	// iterates over the router nodes added
	typedef std::set<udp::endpoint>::const_iterator router_iterator;
	router_iterator router_begin() const { return m_router_nodes.begin(); }
	router_iterator router_end() const { return m_router_nodes.end(); }

	bool add_node(node_entry const& e);

	// this function is called every time the node sees
	// a sign of a node being alive. This node will either
	// be inserted in the k-buckets or be moved to the top
	// of its bucket.
	bool node_seen(node_id const& id, udp::endpoint ep);

	// this may add a node to the routing table and mark it as
	// not pinged. If the bucket the node falls into is full,
	// the node will be ignored.
	void heard_about(node_id const& id, udp::endpoint const& ep);

	// if any bucket in the routing table needs to be refreshed
	// this function will return true and set the target to an
	// appropriate target inside that bucket
	bool need_refresh(node_id& target) const;

	enum
	{
		include_failed = 1
	};
	// fills the vector with the count nodes from our buckets that
	// are nearest to the given id.
	void find_node(node_id const& id, std::vector<node_entry>& l
		, int options, int count = 0);

	int bucket_size(int bucket)
	{
		int num_buckets = m_buckets.size();
		if (bucket < num_buckets) bucket = num_buckets - 1;
		table_t::iterator i = m_buckets.begin();
		std::advance(i, bucket);
		return (int)i->live_nodes.size();
	}

	void for_each_node(void (*)(void*, node_entry const&)
		, void (*)(void*, node_entry const&), void* userdata) const;

	int bucket_size() const { return m_bucket_size; }

	boost::tuple<int, int> size() const;
	size_type num_global_nodes() const;

	// returns true if there are no working nodes
	// in the routing table
	bool need_bootstrap() const;
	int num_active_buckets() const { return m_buckets.size(); }

	void replacement_cache(bucket_t& nodes) const;

#if defined TORRENT_DHT_VERBOSE_LOGGING || defined TORRENT_DEBUG
	// used for debug and monitoring purposes. This will print out
	// the state of the routing table to the given stream
	void print_state(std::ostream& os) const;
#endif

	void touch_bucket(node_id const& target);

private:

	typedef std::list<routing_table_node> table_t;

	table_t::iterator find_bucket(node_id const& id);

	// constant called k in paper
	int m_bucket_size;

	dht_settings const& m_settings;

	// (k-bucket, replacement cache) pairs
	// the first entry is the bucket the furthest
	// away from our own ID. Each time the bucket
	// closest to us (m_buckets.back()) has more than
	// bucket size nodes in it, another bucket is
	// added to the end and it's split up between them
	table_t m_buckets;

	node_id m_id; // our own node id

	// the last time need_bootstrap() returned true
	mutable ptime m_last_bootstrap;

	// this is a set of all the endpoints that have
	// been identified as router nodes. They will
	// be used in searches, but they will never
	// be added to the routing table.
	std::set<udp::endpoint> m_router_nodes;
};

} } // namespace libtorrent::dht

#endif // ROUTING_TABLE_HPP

<commit_msg>added missing include<commit_after>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

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 the author 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.

*/

#ifndef ROUTING_TABLE_HPP
#define ROUTING_TABLE_HPP

#include <vector>
#include <boost/cstdint.hpp>

#include <boost/utility.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/array.hpp>
#include <set>
#include <list>

#include <libtorrent/kademlia/logging.hpp>

#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/node_entry.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/size_type.hpp>
#include <libtorrent/assert.hpp>
#include <libtorrent/ptime.hpp>

namespace libtorrent
{
	struct session_status;
}

namespace libtorrent { namespace dht
{

#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(table);
#endif

typedef std::vector<node_entry> bucket_t;

struct routing_table_node
{
	bucket_t replacements;
	bucket_t live_nodes;
	ptime last_active;
};

// differences in the implementation from the description in
// the paper:
//
// * Nodes are not marked as being stale, they keep a counter
// 	that tells how many times in a row they have failed. When
// 	a new node is to be inserted, the node that has failed
// 	the most times is replaced. If none of the nodes in the
// 	bucket has failed, then it is put in the replacement
// 	cache (just like in the paper).

class TORRENT_EXPORT routing_table
{
public:
	routing_table(node_id const& id, int bucket_size
		, dht_settings const& settings);

	void status(session_status& s) const;

	void node_failed(node_id const& id);

	// adds an endpoint that will never be added to
	// the routing table
	void add_router_node(udp::endpoint router);

	// iterates over the router nodes added
	typedef std::set<udp::endpoint>::const_iterator router_iterator;
	router_iterator router_begin() const { return m_router_nodes.begin(); }
	router_iterator router_end() const { return m_router_nodes.end(); }

	bool add_node(node_entry const& e);

	// this function is called every time the node sees
	// a sign of a node being alive. This node will either
	// be inserted in the k-buckets or be moved to the top
	// of its bucket.
	bool node_seen(node_id const& id, udp::endpoint ep);

	// this may add a node to the routing table and mark it as
	// not pinged. If the bucket the node falls into is full,
	// the node will be ignored.
	void heard_about(node_id const& id, udp::endpoint const& ep);

	// if any bucket in the routing table needs to be refreshed
	// this function will return true and set the target to an
	// appropriate target inside that bucket
	bool need_refresh(node_id& target) const;

	enum
	{
		include_failed = 1
	};
	// fills the vector with the count nodes from our buckets that
	// are nearest to the given id.
	void find_node(node_id const& id, std::vector<node_entry>& l
		, int options, int count = 0);

	int bucket_size(int bucket)
	{
		int num_buckets = m_buckets.size();
		if (bucket < num_buckets) bucket = num_buckets - 1;
		table_t::iterator i = m_buckets.begin();
		std::advance(i, bucket);
		return (int)i->live_nodes.size();
	}

	void for_each_node(void (*)(void*, node_entry const&)
		, void (*)(void*, node_entry const&), void* userdata) const;

	int bucket_size() const { return m_bucket_size; }

	boost::tuple<int, int> size() const;
	size_type num_global_nodes() const;

	// returns true if there are no working nodes
	// in the routing table
	bool need_bootstrap() const;
	int num_active_buckets() const { return m_buckets.size(); }

	void replacement_cache(bucket_t& nodes) const;

#if defined TORRENT_DHT_VERBOSE_LOGGING || defined TORRENT_DEBUG
	// used for debug and monitoring purposes. This will print out
	// the state of the routing table to the given stream
	void print_state(std::ostream& os) const;
#endif

	void touch_bucket(node_id const& target);

private:

	typedef std::list<routing_table_node> table_t;

	table_t::iterator find_bucket(node_id const& id);

	// constant called k in paper
	int m_bucket_size;

	dht_settings const& m_settings;

	// (k-bucket, replacement cache) pairs
	// the first entry is the bucket the furthest
	// away from our own ID. Each time the bucket
	// closest to us (m_buckets.back()) has more than
	// bucket size nodes in it, another bucket is
	// added to the end and it's split up between them
	table_t m_buckets;

	node_id m_id; // our own node id

	// the last time need_bootstrap() returned true
	mutable ptime m_last_bootstrap;

	// this is a set of all the endpoints that have
	// been identified as router nodes. They will
	// be used in searches, but they will never
	// be added to the routing table.
	std::set<udp::endpoint> m_router_nodes;
};

} } // namespace libtorrent::dht

#endif // ROUTING_TABLE_HPP

<|endoftext|>


<commit_before>#include <iostream>
int main(int argc ,char *argv[]) {
	std::cout << "Hello World" << std::endl;
	return 0;
}
<commit_msg>Change hello_world.cxx<commit_after>#include <iostream>
int main(int argc ,char *argv[]) {
	std::cout << "Hello World" << std::endl;

	return 0;
}
<|endoftext|>


<commit_before>#include <taichi/visualization/image_buffer.h>
#include <taichi/math/linalg.h>

#define STB_IMAGE_IMPLEMENTATION
#define STBI_FAILURE_USERMSG
#include <stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
#define STB_TRUETYPE_IMPLEMENTATION
#include <stb_truetype.h>

TC_NAMESPACE_BEGIN

template<typename T>
void Array2D<T>::load(const std::string &filename) {
    int channels;
    FILE *f = fopen(filename.c_str(), "rb");
    assert_info(f != nullptr, "Image file not found: " + filename);
    real *data = stbi_loadf(filename.c_str(), &this->width, &this->height, &channels, 0);
    P(stbi_is_hdr(filename.c_str()));
    assert_info(data != nullptr, "Image file load failed: " + filename + " # Msg: " + std::string(stbi_failure_reason()));
    assert_info(channels == 3 || channels == 4, "Image must have channel 3 or 4: " + filename);
    this->initialize(this->width, this->height);
    for (int i = 0; i < this->width; i++) {
        for (int j = 0; j < this->height; j++) {
            real *pixel = data + ((this->height - 1 - j) * this->width + i) * channels;
            (*this)[i][j][0] = pixel[0];
            (*this)[i][j][1] = pixel[1];
            (*this)[i][j][2] = pixel[2];
            if (channels == 4 && same_type<T, Vector4>())
                (*this)[i][j][3] = pixel[3];
        }
    }
    stbi_image_free(data);
}

template<typename T>
void Array2D<T>::write(const std::string &filename)
{
    int comp = 3;
    std::vector<unsigned char> data(this->width * this->height * comp);
    for (int i = 0; i < this->width; i++) {
        for (int j = 0; j < this->height; j++) {
            for (int k = 0; k < comp; k++) {
                data[j * this->width * comp + i * comp + k] =
                        (unsigned char)(255.0f * clamp(this->data[i * this->height + (this->height - j - 1)][k], 0.0f, 1.0f));
            }
        }
    }
    int write_result = stbi_write_png(filename.c_str(), this->width, this->height, comp, &data[0], comp * this->width);
    // assert_info((bool)write_result, "Can not write image file");
}

template<typename T>
void Array2D<T>::write_text(const std::string &font_fn, const std::string &content_, real size,
                                      int dx, int dy) {
    std::vector<unsigned char> buffer(24 << 20, (unsigned char)0);
    std::vector<unsigned char> screen_buffer((size_t)(this->width * this->height), (unsigned char)0);

    static stbtt_fontinfo font;
    int i, j, ascent, baseline, ch = 0;
    float xpos = 2; // leave a little padding in case the character extends left
    static float scale;
    // TODO: cache loaded fonts?
    FILE *font_file = fopen(font_fn.c_str(), "rb");
    assert_info(font_file != nullptr, "Font file not found: " + std::string(font_fn));
    fread(&buffer[0], 1, 24 << 20, font_file);
    stbtt_InitFont(&font, &buffer[0], 0);

    scale = stbtt_ScaleForPixelHeight(&font, size);

    stbtt_GetFontVMetrics(&font, &ascent, 0, 0);
    baseline = (int)(ascent*scale);
    const std::string c_content = content_;
    const char *content = c_content.c_str();
    while (content[ch]) {
        int advance, lsb, x0, y0, x1, y1;
        float x_shift = xpos - (float)floor(xpos);
        stbtt_GetCodepointHMetrics(&font, content[ch], &advance, &lsb);
        stbtt_GetCodepointBitmapBoxSubpixel(&font, content[ch], scale, scale, x_shift, 0, &x0, &y0, &x1, &y1);
        stbtt_MakeCodepointBitmapSubpixel(&font, &screen_buffer[0] + this->width * (baseline + y0) + (int)xpos + x0,
                                          x1 - x0, y1 - y0, 200, scale, scale, x_shift, 0, content[ch]);
        // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
        // because this API is really for baking character bitmaps into textures. if you want to render
        // a sequence of characters, you really need to render each bitmap to a temp buffer, then
        // "alpha blend" that into the working buffer
        xpos += (advance * scale);
        if (content[ch + 1])
            xpos += scale * stbtt_GetCodepointKernAdvance(&font, content[ch], content[ch + 1]);
        ++ch;
    }
    if (dy < 0) {
        dy = this->height + dy - 1;
    }
    for (j = 0; j < this->height; ++j) {
        for (i = 0; i < this->width; ++i) {
            int x = dx + i, y = dy + j;
            float alpha = screen_buffer[(this->height - j - 1) * this->width + i] / 255.0f;
            (*this)[x][y] = lerp(alpha, this->get(x, y), T(1.0f));
        }
    }
}

template
void Array2D<Vector3>::write_text(const std::string &font_fn, const std::string &content_, real size,
                                      int dx, int dy);
template
void Array2D<Vector4>::write_text(const std::string &font_fn, const std::string &content_, real size,
                                      int dx, int dy);

template void Array2D<Vector3>::load(const std::string &filename);
template void Array2D<Vector4>::load(const std::string &filename);
template void Array2D<Vector3>::write(const std::string &filename);
template void Array2D<Vector4>::write(const std::string &filename);

TC_NAMESPACE_END
<commit_msg>Remove debugging statement<commit_after>#include <taichi/visualization/image_buffer.h>
#include <taichi/math/linalg.h>

#define STB_IMAGE_IMPLEMENTATION
#define STBI_FAILURE_USERMSG
#include <stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
#define STB_TRUETYPE_IMPLEMENTATION
#include <stb_truetype.h>

TC_NAMESPACE_BEGIN

template<typename T>
void Array2D<T>::load(const std::string &filename) {
    int channels;
    FILE *f = fopen(filename.c_str(), "rb");
    assert_info(f != nullptr, "Image file not found: " + filename);
    real *data = stbi_loadf(filename.c_str(), &this->width, &this->height, &channels, 0);
    assert_info(data != nullptr, "Image file load failed: " + filename + " # Msg: " + std::string(stbi_failure_reason()));
    assert_info(channels == 3 || channels == 4, "Image must have channel 3 or 4: " + filename);
    this->initialize(this->width, this->height);
    for (int i = 0; i < this->width; i++) {
        for (int j = 0; j < this->height; j++) {
            real *pixel = data + ((this->height - 1 - j) * this->width + i) * channels;
            (*this)[i][j][0] = pixel[0];
            (*this)[i][j][1] = pixel[1];
            (*this)[i][j][2] = pixel[2];
            if (channels == 4 && same_type<T, Vector4>())
                (*this)[i][j][3] = pixel[3];
        }
    }
    stbi_image_free(data);
}

template<typename T>
void Array2D<T>::write(const std::string &filename)
{
    int comp = 3;
    std::vector<unsigned char> data(this->width * this->height * comp);
    for (int i = 0; i < this->width; i++) {
        for (int j = 0; j < this->height; j++) {
            for (int k = 0; k < comp; k++) {
                data[j * this->width * comp + i * comp + k] =
                        (unsigned char)(255.0f * clamp(this->data[i * this->height + (this->height - j - 1)][k], 0.0f, 1.0f));
            }
        }
    }
    int write_result = stbi_write_png(filename.c_str(), this->width, this->height, comp, &data[0], comp * this->width);
    // assert_info((bool)write_result, "Can not write image file");
}

template<typename T>
void Array2D<T>::write_text(const std::string &font_fn, const std::string &content_, real size,
                                      int dx, int dy) {
    std::vector<unsigned char> buffer(24 << 20, (unsigned char)0);
    std::vector<unsigned char> screen_buffer((size_t)(this->width * this->height), (unsigned char)0);

    static stbtt_fontinfo font;
    int i, j, ascent, baseline, ch = 0;
    float xpos = 2; // leave a little padding in case the character extends left
    static float scale;
    // TODO: cache loaded fonts?
    FILE *font_file = fopen(font_fn.c_str(), "rb");
    assert_info(font_file != nullptr, "Font file not found: " + std::string(font_fn));
    fread(&buffer[0], 1, 24 << 20, font_file);
    stbtt_InitFont(&font, &buffer[0], 0);

    scale = stbtt_ScaleForPixelHeight(&font, size);

    stbtt_GetFontVMetrics(&font, &ascent, 0, 0);
    baseline = (int)(ascent*scale);
    const std::string c_content = content_;
    const char *content = c_content.c_str();
    while (content[ch]) {
        int advance, lsb, x0, y0, x1, y1;
        float x_shift = xpos - (float)floor(xpos);
        stbtt_GetCodepointHMetrics(&font, content[ch], &advance, &lsb);
        stbtt_GetCodepointBitmapBoxSubpixel(&font, content[ch], scale, scale, x_shift, 0, &x0, &y0, &x1, &y1);
        stbtt_MakeCodepointBitmapSubpixel(&font, &screen_buffer[0] + this->width * (baseline + y0) + (int)xpos + x0,
                                          x1 - x0, y1 - y0, 200, scale, scale, x_shift, 0, content[ch]);
        // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
        // because this API is really for baking character bitmaps into textures. if you want to render
        // a sequence of characters, you really need to render each bitmap to a temp buffer, then
        // "alpha blend" that into the working buffer
        xpos += (advance * scale);
        if (content[ch + 1])
            xpos += scale * stbtt_GetCodepointKernAdvance(&font, content[ch], content[ch + 1]);
        ++ch;
    }
    if (dy < 0) {
        dy = this->height + dy - 1;
    }
    for (j = 0; j < this->height; ++j) {
        for (i = 0; i < this->width; ++i) {
            int x = dx + i, y = dy + j;
            float alpha = screen_buffer[(this->height - j - 1) * this->width + i] / 255.0f;
            (*this)[x][y] = lerp(alpha, this->get(x, y), T(1.0f));
        }
    }
}

template
void Array2D<Vector3>::write_text(const std::string &font_fn, const std::string &content_, real size,
                                      int dx, int dy);
template
void Array2D<Vector4>::write_text(const std::string &font_fn, const std::string &content_, real size,
                                      int dx, int dy);

template void Array2D<Vector3>::load(const std::string &filename);
template void Array2D<Vector4>::load(const std::string &filename);
template void Array2D<Vector3>::write(const std::string &filename);
template void Array2D<Vector4>::write(const std::string &filename);

TC_NAMESPACE_END
<|endoftext|>


<commit_before>#ifndef GP_NODE_CONST_NODE
#define GP_NODE_CONST_NODE

#include "node_base.hpp"
#include <sstream>

namespace gp::node {
    namespace const_node {
        constexpr const char* nameHeader = "Const[";
        constexpr char nameDelimiter = ']';
        constexpr char propertySeparator = ',';
    }

    template <typename T>
    class ConstNode: public NodeBase<T(void)> {
    private:
        using ThisType = ConstNode;
        using node_instance_type = NodeInterface::node_instance_type;
        T data;
    private:
        T evaluationDefinition(utility::EvaluationContext& evaluationContext)const override {
            return data;
        }
    public:
        std::string getNodeName()const override {
            std::stringstream sstream;
            sstream << const_node::propertySeparator << data;
            return std::string(const_node::nameHeader) + utility::typeInfo<T>().name() + sstream.str() + std::string(1, const_node::nameDelimiter);
        }
        node_instance_type clone()const override {return NodeInterface::createInstance<ThisType>(data);}
        NodeType getNodeType()const noexcept override final {return NodeType::Const;}
        void setNodePropertyByNodeName(const std::string& name) override {
            auto beg = name.find('[');
            auto end = name.find(']');
            if(beg == std::string::npos || end == std::string::npos || end < beg) throw std::invalid_argument("invalid node name of const node");
            auto sep = name.find(',', beg);
            if(sep == std::string::npos || end < sep) throw std::invalid_argument("invalid node name of const node");
            std::stringstream sstream;
            sstream << name.substr(sep + 1, end - sep - 1);
            sstream >> data;
        }
        void setNodePropertyByAny(const std::any& prop) override {
            assert(prop.type() == typeid(T));
            data = std::any_cast<T>(prop);
        }
        std::any getNodePropertyByAny()const override {return data;}
    public:
        ConstNode(T&& val): data(std::move(val)){}
        ConstNode(const T& val): data(val){}
        ConstNode() = default;
        ConstNode(const ConstNode&) = default;
        ConstNode(ConstNode&&) = default;
        ConstNode& operator=(const ConstNode&) = default;
        ConstNode& operator=(ConstNode&&) = default;
        ~ConstNode() = default;
    };
}

#endif
<commit_msg>add static_assertion<commit_after>#ifndef GP_NODE_CONST_NODE
#define GP_NODE_CONST_NODE

#include "node_base.hpp"
#include <gp/utility/is_match_template.hpp>
#include <sstream>

namespace gp::node {
    namespace const_node {
        constexpr const char* nameHeader = "Const[";
        constexpr char nameDelimiter = ']';
        constexpr char propertySeparator = ',';
    }

    template <typename T>
    class ConstNode: public NodeBase<T(void)> {
        static_assert(!utility::is_match_template_v<utility::LeftHandValue, T>
                      && !utility::is_match_template_v<utility::Reference, T>);
    private:
        using ThisType = ConstNode;
        using node_instance_type = NodeInterface::node_instance_type;
        T data;
    private:
        T evaluationDefinition(utility::EvaluationContext& evaluationContext)const override {
            return data;
        }
    public:
        std::string getNodeName()const override {
            std::stringstream sstream;
            sstream << const_node::propertySeparator << data;
            return std::string(const_node::nameHeader) + utility::typeInfo<T>().name() + sstream.str() + std::string(1, const_node::nameDelimiter);
        }
        node_instance_type clone()const override {return NodeInterface::createInstance<ThisType>(data);}
        NodeType getNodeType()const noexcept override final {return NodeType::Const;}
        void setNodePropertyByNodeName(const std::string& name) override {
            auto beg = name.find('[');
            auto end = name.find(']');
            if(beg == std::string::npos || end == std::string::npos || end < beg) throw std::invalid_argument("invalid node name of const node");
            auto sep = name.find(',', beg);
            if(sep == std::string::npos || end < sep) throw std::invalid_argument("invalid node name of const node");
            std::stringstream sstream;
            sstream << name.substr(sep + 1, end - sep - 1);
            sstream >> data;
        }
        void setNodePropertyByAny(const std::any& prop) override {
            assert(prop.type() == typeid(T));
            data = std::any_cast<T>(prop);
        }
        std::any getNodePropertyByAny()const override {return data;}
    public:
        ConstNode(T&& val): data(std::move(val)){}
        ConstNode(const T& val): data(val){}
        ConstNode() = default;
        ConstNode(const ConstNode&) = default;
        ConstNode(ConstNode&&) = default;
        ConstNode& operator=(const ConstNode&) = default;
        ConstNode& operator=(ConstNode&&) = default;
        ~ConstNode() = default;
    };
}

#endif
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/tf2tensorrt/convert/trt_optimization_pass.h"

#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "tensorflow/compiler/tf2tensorrt/convert/convert_graph.h"
#include "tensorflow/compiler/tf2tensorrt/convert/utils.h"
#include "tensorflow/core/grappler/clusters/cluster.h"
#include "tensorflow/core/grappler/grappler_item.h"
#include "tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.h"
#include "tensorflow/core/lib/strings/numbers.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/lib/strings/strcat.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/stacktrace.h"

#if GOOGLE_CUDA && GOOGLE_TENSORRT
namespace tensorflow {
namespace tensorrt {
namespace convert {
// TODO(sami): Remove VLOG messages once the code matures
using absl::AsciiStrToUpper;
using absl::StrAppend;
using absl::StrCat;

Status TRTOptimizationPass::Init(
    const RewriterConfig_CustomGraphOptimizer* config) {
  VLOG(1) << "Called INIT for " << name_ << " with config = " << config;
  if (config == nullptr) {
    return Status::OK();
  }
  VLOG(1) << "config = " << config->DebugString();
  const auto params = config->parameter_map();
  if (params.count("minimum_segment_size")) {
    minimum_segment_size_ = params.at("minimum_segment_size").i();
  }
  if (params.count("max_batch_size")) {
    maximum_batch_size_ = params.at("max_batch_size").i();
  }
  if (params.count("is_dynamic_op")) {
    is_dynamic_op_ = params.at("is_dynamic_op").b();
  }
  if (params.count("maximum_cached_engines")) {
    max_cached_batches_ = params.at("maximum_cached_engines").i();
  }
  if (params.count("max_workspace_size_bytes")) {
    max_workspace_size_bytes_ = params.at("max_workspace_size_bytes").i();
  }
  if (params.count("precision_mode")) {
    TF_RETURN_IF_ERROR(TrtPrecisionModeFromName(
        AsciiStrToUpper(params.at("precision_mode").s()), &precision_mode_));
  }
  if (params.count("use_calibration")) {
    use_calibration_ = params.at("use_calibration").b();
  }
  if (params.count("trt_logger")) {
    trt_logger_name_ = params.at("trt_logger").s();
  }
  if (params.count("allow_build_at_runtime")) {
    allow_build_at_runtime_ = params.at("allow_build_at_runtime").b();
  }
  if (params.count("use_implicit_batch")) {
    use_implicit_batch_ = params.at("use_implicit_batch").b();
  }
  return Status::OK();
}

void TRTOptimizationPass::PrintDebugInfo(grappler::Cluster* cluster,
                                         const grappler::GrapplerItem& item) {
  LOG(INFO) << "Cluster = " << cluster;
  string offset("  ");
  string offset2 = StrCat(offset, offset);
  string offset3 = StrCat(offset2, offset);
  string offset4 = StrCat(offset2, offset2);
  if (cluster) {
    LOG(INFO) << offset << "type             = " << cluster->type();
    LOG(INFO) << offset << "num warmup steps = " << cluster->NumWarmupSteps();
    const auto dev_names = cluster->GetDeviceNames();
    if (!dev_names.empty()) {
      LOG(INFO) << offset << " Device names:";
      for (const auto& s : dev_names) {
        LOG(INFO) << offset2 << s;
      }
    }
    std::unordered_map<string, uint64> peak_mem;
    auto status = cluster->GetPeakMemoryUsage(&peak_mem);
    if (status == Status::OK()) {
      LOG(INFO) << offset << "Peak Memory Usage :";
      for (const auto& s : peak_mem) {
        LOG(INFO) << offset2 << s.first << " = " << s.second;
      }
    }

    const auto dev_props = cluster->GetDevices();
    if (!dev_props.empty()) {
      LOG(INFO) << offset << "Device properties:";
      for (const auto& k : dev_props) {
        LOG(INFO) << offset2 << k.first;
        const auto& dt = k.second;
        LOG(INFO) << offset3 << "type          = " << dt.type();
        LOG(INFO) << offset3 << "vendor        = " << dt.vendor();
        LOG(INFO) << offset3 << "model         = " << dt.model();
        LOG(INFO) << offset3 << "frequency     = " << dt.frequency();
        LOG(INFO) << offset3 << "num cores     = " << dt.num_cores();
        LOG(INFO) << offset3 << "num registers = " << dt.num_registers();
        LOG(INFO) << offset3 << "L1 cache size = " << dt.l1_cache_size();
        LOG(INFO) << offset3 << "L2 cache size = " << dt.l2_cache_size();
        LOG(INFO) << offset3 << "L3 cache size = " << dt.l3_cache_size();
        LOG(INFO) << offset3 << "SHMem per SMP = "
                  << dt.shared_memory_size_per_multiprocessor();
        LOG(INFO) << offset3 << "memory size   = " << dt.memory_size();
        LOG(INFO) << offset3 << "bandwidth     = " << dt.bandwidth();
        if (dt.environment_size()) {
          LOG(INFO) << offset3 << "environment   :";
          for (const auto& e : dt.environment()) {
            LOG(INFO) << offset4 << e.first << " = " << e.second;
          }
        }
      }
    }
  }
  LOG(INFO) << "item: " << item.id;
  if (!item.feed.empty()) {
    LOG(INFO) << offset << "Feeds  :";
    for (const auto& f : item.feed) {
      const auto& shape = f.second.shape();
      LOG(INFO) << offset2 << f.first << " = shaped " << shape.DebugString();
    }
  } else {
    LOG(INFO) << offset << "No Feeds";
  }
  if (!item.fetch.empty()) {
    LOG(INFO) << offset << "Fetches  :";
    for (const auto& f : item.fetch) {
      LOG(INFO) << offset2 << f;
    }
  } else {
    LOG(INFO) << offset << "No Fetches";
  }

  if (!item.init_ops.empty()) {
    LOG(INFO) << offset << "init ops  :";
    for (const auto& f : item.init_ops) {
      LOG(INFO) << offset2 << f;
    }
  } else {
    LOG(INFO) << offset << "No init ops";
  }
  LOG(INFO) << "Save Op = " << item.save_op;
  LOG(INFO) << "Restore Op = " << item.restore_op;
  LOG(INFO) << "save_restore_loc_tensor = " << item.save_restore_loc_tensor;
  if (!item.keep_ops.empty()) {
    LOG(INFO) << offset << "keep ops  :";
    for (const auto& f : item.keep_ops) {
      LOG(INFO) << offset2 << f;
    }
  } else {
    LOG(INFO) << offset << "No keep ops";
  }
  for (const auto dev : cluster->GetDeviceSet()->devices()) {
    const auto& pname = dev->parsed_name();
    LOG(INFO) << "Device name= " << dev->name()
              << " parsedname job= " << pname.job << " id= " << pname.id
              << " has_id: " << pname.has_id << " has_job: " << pname.has_job
              << "has_type: " << pname.has_type << " type =" << pname.type;
  }
}

Status TRTOptimizationPass::Optimize(grappler::Cluster* cluster,
                                     const grappler::GrapplerItem& item,
                                     GraphDef* optimized_graph) {
  VLOG(1) << "Called TRTOptimization Pass " << name_;
  // This is a hack to workaround optimizer issue. MetaOptimizer calls
  // optimization passes on function objects as well, we should not modify
  // generated funcdefs! This is fragile but we don't have any other option
  // until framework fixes it.
  if (item.id != "tf_graph") {
    VLOG(1) << "Called TRTOptimization Pass " << name_
            << " on a grappler item with id=" << item.id
            << ", which is probably a function object (funcdef). "
            << "Skipping optimization because TensorRTOptimizer "
            << "should not be called on function objects.";
    *optimized_graph = item.graph;
    return Status::OK();
  }
  if (VLOG_IS_ON(3)) {
    LOG(INFO) << CurrentStackTrace();
    PrintDebugInfo(cluster, item);
  }
  if (!is_dynamic_op_) {
    int max_batch_dim = -1;
    if (!item.feed.empty()) {
      for (const auto& f : item.feed) {
        const auto& shape = f.second.shape();
        if (shape.dims() > 0) {
          if (shape.dim_size(0) > max_batch_dim)
            max_batch_dim = shape.dim_size(0);
          VLOG(2) << "Setting max_batch_dim to " << max_batch_dim
                  << " using batch dimension of " << f.first << " with shape "
                  << shape;
        }
      }
    }
    if (max_batch_dim > maximum_batch_size_) {
      return errors::InvalidArgument(
          "Specified max_batch_size=", maximum_batch_size_,
          " is less than maximum batch dimension of inputs (", max_batch_dim,
          "). ", "To continue, set max_batch_size to >= ", max_batch_dim);
    } else if (max_batch_dim < maximum_batch_size_) {
      LOG(INFO) << "Specified max_batch_size=" << maximum_batch_size_
                << " is larger than maximum batch dimension of inputs ("
                << max_batch_dim << "). "
                << "This can result in poor performance.";
    }
  }

  if (use_calibration_ && precision_mode_ != TrtPrecisionMode::INT8) {
    VLOG(1) << "Calibration with FP32 or FP16 is not implemented. "
            << "Falling back to use_calibration = False."
            << "Note that the default value of use_calibration is True.";
    use_calibration_ = false;
  }

  std::vector<string> nodes_to_preserve;
  for (const auto& n : item.NodesToPreserve()) {
    auto tokens = str_util::Split(n, ":");
    string s = tokens.at(0);
    for (int i = 1; i < tokens.size() - 1; ++i) {
      StrAppend(&s, ":", tokens.at(i));
    }
    int dumm_port = -1;
    // If the last token is not an integer, it must be part of the name.
    // Otherwise it is port number.
    if (tokens.size() > 1 &&
        !strings::safe_strto32(tokens.back(), &dumm_port)) {  // non-absl ok
      StrAppend(&s, ":", tokens.back());
    }
    nodes_to_preserve.push_back(s);
  }

  ConversionParams cp;
  cp.grappler_item = &item;
  cp.output_names = &nodes_to_preserve;
  cp.trt_logger_name = trt_logger_name_;
  cp.max_batch_size = maximum_batch_size_;
  cp.max_workspace_size_bytes = max_workspace_size_bytes_;
  cp.output_graph_def = optimized_graph;
  cp.precision_mode = precision_mode_;
  cp.minimum_segment_size = minimum_segment_size_;
  cp.cluster = cluster;
  cp.is_dyn_op = is_dynamic_op_;
  cp.max_cached_engines = max_cached_batches_;
  cp.use_calibration = use_calibration_;
  cp.use_implicit_batch = use_implicit_batch_;
  cp.allow_build_at_runtime = allow_build_at_runtime_;
  auto status = ConvertAfterShapes(cp);
  VLOG(1) << "Returning from " << name_;
  return status;
}

void TRTOptimizationPass::Feedback(grappler::Cluster* cluster,
                                   const grappler::GrapplerItem& item,
                                   const GraphDef& optimized_graph,
                                   double result) {}

class VerboseCustomGraphOptimizerRegistrar
    : public grappler::CustomGraphOptimizerRegistrar {
 public:
  VerboseCustomGraphOptimizerRegistrar(
      const grappler::CustomGraphOptimizerRegistry::Creator& cr,
      const string& name)
      : grappler::CustomGraphOptimizerRegistrar(cr, name) {
    VLOG(1) << "Constructing a CustomOptimizationPass registration object for "
            << name;
  }
};

static VerboseCustomGraphOptimizerRegistrar TRTOptimizationPass_Registrar(
    []() {
      VLOG(1)
          << "Instantiating CustomOptimizationPass object TensorRTOptimizer";
      return new TRTOptimizationPass("TensorRTOptimizer");
    },
    ("TensorRTOptimizer"));

}  // namespace convert
}  // namespace tensorrt
}  // namespace tensorflow

#endif  // GOOGLE_CUDA && GOOGLE_TENSORRT
<commit_msg>[TF:TRT] Avoid null pointer accesses in TRTOptimizationPass::PrintDebugInfo.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/tf2tensorrt/convert/trt_optimization_pass.h"

#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "tensorflow/compiler/tf2tensorrt/convert/convert_graph.h"
#include "tensorflow/compiler/tf2tensorrt/convert/utils.h"
#include "tensorflow/core/grappler/clusters/cluster.h"
#include "tensorflow/core/grappler/grappler_item.h"
#include "tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.h"
#include "tensorflow/core/lib/strings/numbers.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/lib/strings/strcat.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/stacktrace.h"

#if GOOGLE_CUDA && GOOGLE_TENSORRT
namespace tensorflow {
namespace tensorrt {
namespace convert {
// TODO(sami): Remove VLOG messages once the code matures
using absl::AsciiStrToUpper;
using absl::StrAppend;
using absl::StrCat;

Status TRTOptimizationPass::Init(
    const RewriterConfig_CustomGraphOptimizer* config) {
  VLOG(1) << "Called INIT for " << name_ << " with config = " << config;
  if (config == nullptr) {
    return Status::OK();
  }
  VLOG(1) << "config = " << config->DebugString();
  const auto params = config->parameter_map();
  if (params.count("minimum_segment_size")) {
    minimum_segment_size_ = params.at("minimum_segment_size").i();
  }
  if (params.count("max_batch_size")) {
    maximum_batch_size_ = params.at("max_batch_size").i();
  }
  if (params.count("is_dynamic_op")) {
    is_dynamic_op_ = params.at("is_dynamic_op").b();
  }
  if (params.count("maximum_cached_engines")) {
    max_cached_batches_ = params.at("maximum_cached_engines").i();
  }
  if (params.count("max_workspace_size_bytes")) {
    max_workspace_size_bytes_ = params.at("max_workspace_size_bytes").i();
  }
  if (params.count("precision_mode")) {
    TF_RETURN_IF_ERROR(TrtPrecisionModeFromName(
        AsciiStrToUpper(params.at("precision_mode").s()), &precision_mode_));
  }
  if (params.count("use_calibration")) {
    use_calibration_ = params.at("use_calibration").b();
  }
  if (params.count("trt_logger")) {
    trt_logger_name_ = params.at("trt_logger").s();
  }
  if (params.count("allow_build_at_runtime")) {
    allow_build_at_runtime_ = params.at("allow_build_at_runtime").b();
  }
  if (params.count("use_implicit_batch")) {
    use_implicit_batch_ = params.at("use_implicit_batch").b();
  }
  return Status::OK();
}

void TRTOptimizationPass::PrintDebugInfo(grappler::Cluster* cluster,
                                         const grappler::GrapplerItem& item) {
  LOG(INFO) << "Cluster = " << cluster;
  string offset("  ");
  string offset2 = StrCat(offset, offset);
  string offset3 = StrCat(offset2, offset);
  string offset4 = StrCat(offset2, offset2);

  if (cluster) {
    LOG(INFO) << offset << "type             = " << cluster->type();
    LOG(INFO) << offset << "num warmup steps = " << cluster->NumWarmupSteps();
    const auto dev_names = cluster->GetDeviceNames();
    if (!dev_names.empty()) {
      LOG(INFO) << offset << " Device names:";
      for (const auto& s : dev_names) {
        LOG(INFO) << offset2 << s;
      }
    }
    std::unordered_map<string, uint64> peak_mem;
    auto status = cluster->GetPeakMemoryUsage(&peak_mem);
    if (status == Status::OK()) {
      LOG(INFO) << offset << "Peak Memory Usage :";
      for (const auto& s : peak_mem) {
        LOG(INFO) << offset2 << s.first << " = " << s.second;
      }
    }

    const auto dev_props = cluster->GetDevices();
    if (!dev_props.empty()) {
      LOG(INFO) << offset << "Device properties:";
      for (const auto& k : dev_props) {
        LOG(INFO) << offset2 << k.first;
        const auto& dt = k.second;
        LOG(INFO) << offset3 << "type          = " << dt.type();
        LOG(INFO) << offset3 << "vendor        = " << dt.vendor();
        LOG(INFO) << offset3 << "model         = " << dt.model();
        LOG(INFO) << offset3 << "frequency     = " << dt.frequency();
        LOG(INFO) << offset3 << "num cores     = " << dt.num_cores();
        LOG(INFO) << offset3 << "num registers = " << dt.num_registers();
        LOG(INFO) << offset3 << "L1 cache size = " << dt.l1_cache_size();
        LOG(INFO) << offset3 << "L2 cache size = " << dt.l2_cache_size();
        LOG(INFO) << offset3 << "L3 cache size = " << dt.l3_cache_size();
        LOG(INFO) << offset3 << "SHMem per SMP = "
                  << dt.shared_memory_size_per_multiprocessor();
        LOG(INFO) << offset3 << "memory size   = " << dt.memory_size();
        LOG(INFO) << offset3 << "bandwidth     = " << dt.bandwidth();
        if (dt.environment_size()) {
          LOG(INFO) << offset3 << "environment   :";
          for (const auto& e : dt.environment()) {
            LOG(INFO) << offset4 << e.first << " = " << e.second;
          }
        }
      }
    }

    if (cluster->GetDeviceSet()) {
      for (const auto dev : cluster->GetDeviceSet()->devices()) {
        LOG(INFO) << "Device name= " << dev->name() << "Pased name= "
                  << DeviceNameUtils::ParsedNameToString(dev->parsed_name());
      }
    }
  }

  LOG(INFO) << "item: " << item.id;
  if (!item.feed.empty()) {
    LOG(INFO) << offset << "Feeds  :";
    for (const auto& f : item.feed) {
      const auto& shape = f.second.shape();
      LOG(INFO) << offset2 << f.first << " = shaped " << shape.DebugString();
    }
  } else {
    LOG(INFO) << offset << "No Feeds";
  }
  if (!item.fetch.empty()) {
    LOG(INFO) << offset << "Fetches  :";
    for (const auto& f : item.fetch) {
      LOG(INFO) << offset2 << f;
    }
  } else {
    LOG(INFO) << offset << "No Fetches";
  }

  if (!item.init_ops.empty()) {
    LOG(INFO) << offset << "init ops  :";
    for (const auto& f : item.init_ops) {
      LOG(INFO) << offset2 << f;
    }
  } else {
    LOG(INFO) << offset << "No init ops";
  }
  LOG(INFO) << "Save Op = " << item.save_op;
  LOG(INFO) << "Restore Op = " << item.restore_op;
  LOG(INFO) << "save_restore_loc_tensor = " << item.save_restore_loc_tensor;
  if (!item.keep_ops.empty()) {
    LOG(INFO) << offset << "keep ops  :";
    for (const auto& f : item.keep_ops) {
      LOG(INFO) << offset2 << f;
    }
  } else {
    LOG(INFO) << offset << "No keep ops";
  }
}

Status TRTOptimizationPass::Optimize(grappler::Cluster* cluster,
                                     const grappler::GrapplerItem& item,
                                     GraphDef* optimized_graph) {
  VLOG(1) << "Called TRTOptimization Pass " << name_;
  // This is a hack to workaround optimizer issue. MetaOptimizer calls
  // optimization passes on function objects as well, we should not modify
  // generated funcdefs! This is fragile but we don't have any other option
  // until framework fixes it.
  if (item.id != "tf_graph") {
    VLOG(1) << "Called TRTOptimization Pass " << name_
            << " on a grappler item with id=" << item.id
            << ", which is probably a function object (funcdef). "
            << "Skipping optimization because TensorRTOptimizer "
            << "should not be called on function objects.";
    *optimized_graph = item.graph;
    return Status::OK();
  }
  if (VLOG_IS_ON(3)) {
    LOG(INFO) << CurrentStackTrace();
    PrintDebugInfo(cluster, item);
  }
  if (!is_dynamic_op_) {
    int max_batch_dim = -1;
    if (!item.feed.empty()) {
      for (const auto& f : item.feed) {
        const auto& shape = f.second.shape();
        if (shape.dims() > 0) {
          if (shape.dim_size(0) > max_batch_dim)
            max_batch_dim = shape.dim_size(0);
          VLOG(2) << "Setting max_batch_dim to " << max_batch_dim
                  << " using batch dimension of " << f.first << " with shape "
                  << shape;
        }
      }
    }
    if (max_batch_dim > maximum_batch_size_) {
      return errors::InvalidArgument(
          "Specified max_batch_size=", maximum_batch_size_,
          " is less than maximum batch dimension of inputs (", max_batch_dim,
          "). ", "To continue, set max_batch_size to >= ", max_batch_dim);
    } else if (max_batch_dim < maximum_batch_size_) {
      LOG(INFO) << "Specified max_batch_size=" << maximum_batch_size_
                << " is larger than maximum batch dimension of inputs ("
                << max_batch_dim << "). "
                << "This can result in poor performance.";
    }
  }

  if (use_calibration_ && precision_mode_ != TrtPrecisionMode::INT8) {
    VLOG(1) << "Calibration with FP32 or FP16 is not implemented. "
            << "Falling back to use_calibration = False."
            << "Note that the default value of use_calibration is True.";
    use_calibration_ = false;
  }

  std::vector<string> nodes_to_preserve;
  for (const auto& n : item.NodesToPreserve()) {
    auto tokens = str_util::Split(n, ":");
    string s = tokens.at(0);
    for (int i = 1; i < tokens.size() - 1; ++i) {
      StrAppend(&s, ":", tokens.at(i));
    }
    int dumm_port = -1;
    // If the last token is not an integer, it must be part of the name.
    // Otherwise it is port number.
    if (tokens.size() > 1 &&
        !strings::safe_strto32(tokens.back(), &dumm_port)) {  // non-absl ok
      StrAppend(&s, ":", tokens.back());
    }
    nodes_to_preserve.push_back(s);
  }

  ConversionParams cp;
  cp.grappler_item = &item;
  cp.output_names = &nodes_to_preserve;
  cp.trt_logger_name = trt_logger_name_;
  cp.max_batch_size = maximum_batch_size_;
  cp.max_workspace_size_bytes = max_workspace_size_bytes_;
  cp.output_graph_def = optimized_graph;
  cp.precision_mode = precision_mode_;
  cp.minimum_segment_size = minimum_segment_size_;
  cp.cluster = cluster;
  cp.is_dyn_op = is_dynamic_op_;
  cp.max_cached_engines = max_cached_batches_;
  cp.use_calibration = use_calibration_;
  cp.use_implicit_batch = use_implicit_batch_;
  cp.allow_build_at_runtime = allow_build_at_runtime_;
  auto status = ConvertAfterShapes(cp);
  VLOG(1) << "Returning from " << name_;
  return status;
}

void TRTOptimizationPass::Feedback(grappler::Cluster* cluster,
                                   const grappler::GrapplerItem& item,
                                   const GraphDef& optimized_graph,
                                   double result) {}

class VerboseCustomGraphOptimizerRegistrar
    : public grappler::CustomGraphOptimizerRegistrar {
 public:
  VerboseCustomGraphOptimizerRegistrar(
      const grappler::CustomGraphOptimizerRegistry::Creator& cr,
      const string& name)
      : grappler::CustomGraphOptimizerRegistrar(cr, name) {
    VLOG(1) << "Constructing a CustomOptimizationPass registration object for "
            << name;
  }
};

static VerboseCustomGraphOptimizerRegistrar TRTOptimizationPass_Registrar(
    []() {
      VLOG(1)
          << "Instantiating CustomOptimizationPass object TensorRTOptimizer";
      return new TRTOptimizationPass("TensorRTOptimizer");
    },
    ("TensorRTOptimizer"));

}  // namespace convert
}  // namespace tensorrt
}  // namespace tensorflow

#endif  // GOOGLE_CUDA && GOOGLE_TENSORRT
<|endoftext|>


<commit_before>//
// frame_selector.cpp
// Projectname: amos-ss16-proj5
//
// Created on 21.05.2016.
// Copyright (c) 2016 de.fau.cs.osr.amos2016.gruppe5
//
// This file is part of the AMOS Project 2016 @ FAU
// (Friedrich-Alexander University Erlangen-Nürnberg)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//

#include <sstream>

#include "frame_selector.h"

namespace patch{

    template < typename T > std::string to_string( const T& n ){

        std::ostringstream stm ;
        stm << n ;
        return stm.str() ;

    }
}

FrameSelector::FrameSelector(std::string file){

    file_name_ = file;

    hdf_reader_ = new HDFReader(file);

    // read hdf5 file
    hdf_reader_->ReadFile();

}

FrameSelector::~FrameSelector(){

    delete hdf_reader_;

}

Image FrameSelector::ReadImage(unsigned int frame_index){

    // get the protobuf payload from hdf5 reader
    std::vector<int64_t> protobuf_file_buffer = hdf_reader_->ReadOneProtobufFile(frame_index);
    int protobuf_file_size = protobuf_file_buffer.size();

    // convert to char array
    unsigned char* file = ConvertProtobufFileToArray(protobuf_file_buffer);

    //convert protobuf file buffer to msgCameraImage and read image from protobuf file
    ProtobufImageWrapper protobuf_image;
    protobuf_image.ParseFromArray(file, protobuf_file_size);

    // create an Image from msgCameraImage
    Image result_image(protobuf_image.GetImagePayload(), protobuf_image.GetImageWidth(), protobuf_image.GetImageHeight());

    std::cout << "Protobuf file: WIDTH: " << result_image.GetImageWidth() << " HEIGHT: " << result_image.GetImageHeight() << std::endl;
    std::cout << " Size of payload: " << result_image.GetImagePayload().size() << std::endl;
    std::cout << " Hash of payload: " << std::hash<std::string>()(result_image.GetImagePayload()) << std::endl;

    return result_image;

}

int FrameSelector::GetImageCount(){
    return hdf_reader_->GetNumberOfProtobufFiles();
}

std::vector<Image> FrameSelector::ReadAllImages(){

    std::vector<std::vector<int64_t> > all_protobuf_files = hdf_reader_->ReadAllProtobufFiles();

    //all result images
    std::vector<Image> result_images;

    for(int i = 0; i < all_protobuf_files.size(); i++){

        // convert current image
        unsigned char* file = ConvertProtobufFileToArray(all_protobuf_files.at(i));

        ProtobufImageWrapper protobuf_image;
        protobuf_image.ParseFromArray(file, all_protobuf_files.at(i).size());

        Image current_image(protobuf_image.GetImagePayload(), protobuf_image.GetImageWidth(), protobuf_image.GetImageHeight());

        result_images.push_back(current_image);

    }

    return result_images;

}

unsigned char* FrameSelector::ConvertProtobufFileToArray(std::vector<int64_t> file){

    int size = file.size();
    unsigned char *file_array = new unsigned char[size];

    for(int i = 0; i < size; i++){

        file_array[i] = static_cast<unsigned char>(file.at(i));

    }

    return file_array;

}
<commit_msg>removed hash because the travis compiler does not support it<commit_after>//
// frame_selector.cpp
// Projectname: amos-ss16-proj5
//
// Created on 21.05.2016.
// Copyright (c) 2016 de.fau.cs.osr.amos2016.gruppe5
//
// This file is part of the AMOS Project 2016 @ FAU
// (Friedrich-Alexander University Erlangen-Nürnberg)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//

#include <sstream>

#include "frame_selector.h"

namespace patch{

    template < typename T > std::string to_string( const T& n ){

        std::ostringstream stm ;
        stm << n ;
        return stm.str() ;

    }
}

FrameSelector::FrameSelector(std::string file){

    file_name_ = file;

    hdf_reader_ = new HDFReader(file);

    // read hdf5 file
    hdf_reader_->ReadFile();

}

FrameSelector::~FrameSelector(){

    delete hdf_reader_;

}

Image FrameSelector::ReadImage(unsigned int frame_index){

    // get the protobuf payload from hdf5 reader
    std::vector<int64_t> protobuf_file_buffer = hdf_reader_->ReadOneProtobufFile(frame_index);
    int protobuf_file_size = protobuf_file_buffer.size();

    // convert to char array
    unsigned char* file = ConvertProtobufFileToArray(protobuf_file_buffer);

    //convert protobuf file buffer to msgCameraImage and read image from protobuf file
    ProtobufImageWrapper protobuf_image;
    protobuf_image.ParseFromArray(file, protobuf_file_size);

    // create an Image from msgCameraImage
    Image result_image(protobuf_image.GetImagePayload(), protobuf_image.GetImageWidth(), protobuf_image.GetImageHeight());

    std::cout << "Protobuf file: WIDTH: " << result_image.GetImageWidth() << " HEIGHT: " << result_image.GetImageHeight() << std::endl;
    std::cout << " Size of payload: " << result_image.GetImagePayload().size() << std::endl;

    return result_image;

}

int FrameSelector::GetImageCount(){
    return hdf_reader_->GetNumberOfProtobufFiles();
}

std::vector<Image> FrameSelector::ReadAllImages(){

    std::vector<std::vector<int64_t> > all_protobuf_files = hdf_reader_->ReadAllProtobufFiles();

    //all result images
    std::vector<Image> result_images;

    for(int i = 0; i < all_protobuf_files.size(); i++){

        // convert current image
        unsigned char* file = ConvertProtobufFileToArray(all_protobuf_files.at(i));

        ProtobufImageWrapper protobuf_image;
        protobuf_image.ParseFromArray(file, all_protobuf_files.at(i).size());

        Image current_image(protobuf_image.GetImagePayload(), protobuf_image.GetImageWidth(), protobuf_image.GetImageHeight());

        result_images.push_back(current_image);

    }

    return result_images;

}

unsigned char* FrameSelector::ConvertProtobufFileToArray(std::vector<int64_t> file){

    int size = file.size();
    unsigned char *file_array = new unsigned char[size];

    for(int i = 0; i < size; i++){

        file_array[i] = static_cast<unsigned char>(file.at(i));

    }

    return file_array;

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/event/Observable.h"

using namespace std;
using namespace db::event;
using namespace db::modest;
using namespace db::rt;

Observable::Observable()
{
   // no events to dispatch yet
   mDispatch = false;
}

Observable::~Observable()
{
   // ensure event dispatching is stopped
   stop();
}

void Observable::dispatchEvent(
   Event& e, EventId id, OperationList& opList)
{
   // go through the list of EventId taps
   EventIdMap::iterator ti = mTaps.find(id);
   if(ti != mTaps.end())
   {
      EventIdMap::iterator end = mTaps.upper_bound(id);
      for(; ti != end; ti++)
      {
         // dispatch event if the tap is the EventId itself
         if(ti->second == id)
         {
            // go through the list of observers for the EventId tap
            ObserverMap::iterator oi = mObservers.find(id);
            if(oi != mObservers.end())
            {
               ObserverMap::iterator oend = mObservers.upper_bound(id);
               for(; oi != oend; oi++)
               {
                  // create and run event dispatcher for each observable
                  CollectableRunnable ed = new EventDispatcher(oi->second, &e);
                  Operation op(ed);
                  mOpRunner->runOperation(op);
                  opList.add(op);
               }
            }
         }
         else
         {
            // dispatch event to tap
            dispatchEvent(e, ti->second, opList);
         }
      }
   }
}

void Observable::dispatchEvent(Event& e)
{
   // create an operation list
   OperationList opList;

   // get the EventId for the event and dispatch it
   EventId id = e["id"]->getUInt64();
   dispatchEvent(e, id, opList);

   if(!opList.isEmpty())
   {
      // unlock, wait for dispatch operations to complete, relock
      unlock();
      opList.waitFor();
      opList.prune();
      lock();
   }
}

void Observable::dispatchEvents()
{
   lock();
   {
      while(!mEventQueue.empty())
      {
         // dispatch the next event
         Event e = mEventQueue.front();
         mEventQueue.pop_front();
         dispatchEvent(e);
      }

      // turn off dispatching
      mDispatch = false;
   }
   unlock();
}

void Observable::registerObserver(Observer* observer, EventId id)
{
   lock();
   {
      // add tap to self if EventId doesn't exist yet
      EventIdMap::iterator i = mTaps.find(id);
      if(i == mTaps.end())
      {
         mTaps.insert(make_pair(id, id));
      }

      // add observer
      mObservers.insert(make_pair(id, observer));
   }
   unlock();
}

void Observable::unregisterObserver(Observer* observer, EventId id)
{
   lock();
   {
      ObserverMap::iterator i = mObservers.find(id);
      if(i != mObservers.end())
      {
         ObserverMap::iterator end = mObservers.upper_bound(id);
         for(; i != end; i++)
         {
            if(i->second == observer)
            {
               // remove observer and break
               mObservers.erase(i);
               break;
            }
         }
      }
   }
   unlock();
}

void Observable::addTap(EventId id, EventId tap)
{
   lock();
   {
      // add tap to id-self if EventId doesn't exist yet
      EventIdMap::iterator i = mTaps.find(id);
      if(i == mTaps.end())
      {
         mTaps.insert(make_pair(id, id));
      }

      // insert tap for id
      mTaps.insert(make_pair(id, tap));

      // add tap to tap-self if EventId doesn't exist yet
      i = mTaps.find(tap);
      if(i == mTaps.end())
      {
         mTaps.insert(make_pair(tap, tap));
      }
   }
   unlock();
}

void Observable::removeTap(EventId id, EventId tap)
{
   lock();
   {
      // look for tap in the range of taps
      EventIdMap::iterator i = mTaps.find(id);
      if(i != mTaps.end())
      {
         EventIdMap::iterator end = mTaps.upper_bound(id);
         for(; i != end; i++)
         {
            if(i->second == tap)
            {
               // remove tap and break
               mTaps.erase(i);
               break;
            }
         }
      }
   }
   unlock();
}

void Observable::schedule(Event e, EventId id, bool async)
{
   lock();
   {
      // set the event's ID
      e["id"] = id;

      if(async)
      {
         // lock to set dispatch condition
         mDispatchLock.lock();
         mDispatch = true;

         // add event to event queue
         mEventQueue.push_back(e);

         // notify on dispatch lock and release
         mDispatchLock.notifyAll();
         mDispatchLock.unlock();
      }
      else
      {
         // dispatch the event immediately
         dispatchEvent(e);
      }
   }
   unlock();
}

void Observable::start(OperationRunner* opRunner)
{
   lock();
   {
      if(mOperation.isNull())
      {
         // store operation runner, create and run operation
         mOpRunner = opRunner;
         mOperation = *this;
         opRunner->runOperation(mOperation);
      }
   }
   unlock();
}

void Observable::stop()
{
   lock();
   {
      if(!mOperation.isNull())
      {
         // interrupt and clean up operation
         mOperation->interrupt();
         mOperation->waitFor();
         mOperation = NULL;
      }
   }
   unlock();
}

void Observable::run()
{
   // keep dispatching until interrupted
   while(!mOperation->isInterrupted())
   {
      // lock dispatch lock and check to see if we can dispatch
      mDispatchLock.lock();
      if(mDispatch)
      {
         mDispatchLock.unlock();
         dispatchEvents();
      }
      else
      {
         // wait until dispatch condition is marked true and we are notified
         mDispatchLock.wait();
         mDispatchLock.unlock();
      }
   }
}
<commit_msg>Fixed deadlock bug in Observable and cleaned up a couple of other superfluous calls.<commit_after>/*
 * Copyright (c) 2007 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/event/Observable.h"

using namespace std;
using namespace db::event;
using namespace db::modest;
using namespace db::rt;

Observable::Observable()
{
   // no events to dispatch yet
   mDispatch = false;
}

Observable::~Observable()
{
   // ensure event dispatching is stopped
   stop();
}

void Observable::dispatchEvent(
   Event& e, EventId id, OperationList& opList)
{
   // go through the list of EventId taps
   EventIdMap::iterator ti = mTaps.find(id);
   if(ti != mTaps.end())
   {
      EventIdMap::iterator end = mTaps.upper_bound(id);
      for(; ti != end; ti++)
      {
         // dispatch event if the tap is the EventId itself
         if(ti->second == id)
         {
            // go through the list of observers for the EventId tap
            ObserverMap::iterator oi = mObservers.find(id);
            if(oi != mObservers.end())
            {
               ObserverMap::iterator oend = mObservers.upper_bound(id);
               for(; oi != oend; oi++)
               {
                  // create and run event dispatcher for each observable
                  CollectableRunnable ed = new EventDispatcher(oi->second, &e);
                  Operation op(ed);
                  mOpRunner->runOperation(op);
                  opList.add(op);
               }
            }
         }
         else
         {
            // dispatch event to tap
            dispatchEvent(e, ti->second, opList);
         }
      }
   }
}

void Observable::dispatchEvent(Event& e)
{
   // create an operation list
   OperationList opList;

   // get the EventId for the event and dispatch it
   EventId id = e["id"]->getUInt64();
   dispatchEvent(e, id, opList);

   if(!opList.isEmpty())
   {
      // unlock, wait for dispatch operations to complete, relock
      unlock();
      if(!opList.waitFor())
      {
         // dispatch thread interrupted, so interrupt all
         // event dispatches and wait for them to complete
         opList.interrupt();
         opList.waitFor(false);
      }
      lock();
   }
}

void Observable::dispatchEvents()
{
   // lock while dispatching
   lock();
   {
      // dispatch
      while(!mEventQueue.empty() && !mOperation->isInterrupted())
      {
         // dispatch the next event
         Event e = mEventQueue.front();
         mEventQueue.pop_front();
         dispatchEvent(e);
      }

      // turn off dispatching
      mDispatch = false;
   }
   unlock();
}

void Observable::registerObserver(Observer* observer, EventId id)
{
   lock();
   {
      // add tap to self if EventId doesn't exist yet
      EventIdMap::iterator i = mTaps.find(id);
      if(i == mTaps.end())
      {
         mTaps.insert(make_pair(id, id));
      }

      // add observer
      mObservers.insert(make_pair(id, observer));
   }
   unlock();
}

void Observable::unregisterObserver(Observer* observer, EventId id)
{
   lock();
   {
      ObserverMap::iterator i = mObservers.find(id);
      if(i != mObservers.end())
      {
         ObserverMap::iterator end = mObservers.upper_bound(id);
         for(; i != end; i++)
         {
            if(i->second == observer)
            {
               // remove observer and break
               mObservers.erase(i);
               break;
            }
         }
      }
   }
   unlock();
}

void Observable::addTap(EventId id, EventId tap)
{
   lock();
   {
      // add tap to id-self if EventId doesn't exist yet
      EventIdMap::iterator i = mTaps.find(id);
      if(i == mTaps.end())
      {
         mTaps.insert(make_pair(id, id));
      }

      // insert tap for id
      mTaps.insert(make_pair(id, tap));

      // add tap to tap-self if EventId doesn't exist yet
      i = mTaps.find(tap);
      if(i == mTaps.end())
      {
         mTaps.insert(make_pair(tap, tap));
      }
   }
   unlock();
}

void Observable::removeTap(EventId id, EventId tap)
{
   lock();
   {
      // look for tap in the range of taps
      EventIdMap::iterator i = mTaps.find(id);
      if(i != mTaps.end())
      {
         EventIdMap::iterator end = mTaps.upper_bound(id);
         for(; i != end; i++)
         {
            if(i->second == tap)
            {
               // remove tap and break
               mTaps.erase(i);
               break;
            }
         }
      }
   }
   unlock();
}

void Observable::schedule(Event e, EventId id, bool async)
{
   lock();
   {
      // set the event's ID
      e["id"] = id;

      if(async)
      {
         // lock to set dispatch condition
         mDispatchLock.lock();
         mDispatch = true;

         // add event to event queue
         mEventQueue.push_back(e);

         // notify on dispatch lock and release
         mDispatchLock.notifyAll();
         mDispatchLock.unlock();
      }
      else
      {
         // dispatch the event immediately
         dispatchEvent(e);
      }
   }
   unlock();
}

void Observable::start(OperationRunner* opRunner)
{
   lock();
   {
      if(mOperation.isNull())
      {
         // store operation runner, activate dispatching,
         // create and run operation
         mOpRunner = opRunner;
         mDispatch = true;
         mOperation = *this;
         opRunner->runOperation(mOperation);
      }
   }
   unlock();
}

void Observable::stop()
{
   lock();
   {
      if(!mOperation.isNull())
      {
         // interrupt dispatch operation
         mOperation->interrupt();

         // Note: We only care about locking in this method to prevent
         // start() from running while we are shutting down -- we don't
         // care if more events are scheduled because that won't cause
         // any conflicts. Since this is the case, and start() will
         // check mOperation.isNull() before starting anything, then
         // we don't need to worry about it starting here since mOperation
         // can't be NULL until we relock and clear it below.
         //
         // We need to unlock() while we wait for the dispatch operation
         // to complete because it needs to lock after dispatching each
         // event and won't finish if we are holding the lock here waiting
         // for it to finish.

         // unlock, wait for dispatch operation to finish, relock
         unlock();
         mOperation->waitFor();
         lock();

         // clean up operation
         mOperation.setNull();
      }
   }
   unlock();
}

void Observable::run()
{
   // keep dispatching until interrupted
   while(!mOperation->isInterrupted())
   {
      // lock dispatch lock and check to see if we can dispatch
      mDispatchLock.lock();
      if(mDispatch)
      {
         mDispatchLock.unlock();
         dispatchEvents();
      }
      else
      {
         // wait until dispatch condition is marked true and we are notified
         mDispatchLock.wait();
         mDispatchLock.unlock();
      }
   }
}
<|endoftext|>


<commit_before>#ifndef CPPMATH_AABB_INL
#define CPPMATH_AABB_INL

#include "AABB.hpp"

namespace math
{
    template <typename T>
    AABB<T>::AABB() :
        pos(),
        size()
    {};

    template <typename T>
    AABB<T>::AABB(T x, T y, T w, T h) :
        AABB(Point2<T>(x, y), Vec2<T>(w, h))
    {};

    template <typename T>
    AABB<T>::AABB(const Point2<T>& pos_, const Vec2<T>& size_) :
        pos(pos_.asVector()),
        size(size_)
    {};

    template <typename T>
    AABB<T>::AABB(const AABB<T>& a, const AABB<T>& b) :
        AABB(a)
    {
        combine(b);
    }

    template <typename T>
    AABB<T> fromPoints(const Point2<T>& a, const Point2<T>& b)
    {
        return AABB<T>(
                std::min(a.x, b.x),
                std::min(a.y, b.y),
                std::abs(a.x - b.x),
                std::abs(a.y - b.y)
            );
    }

    template <typename T>
    void AABB<T>::combine(const AABB<T>& other)
    {
        if (isEmpty())
        {
            *this = other;
            return;
        }
        else if (other.isEmpty())
            return;

        Vec2<T> newpos = mins(pos, other.pos);
        size = maxs(pos + size, other.pos + other.size) - newpos;
        pos = newpos;
    }

    template <typename T>
    void AABB<T>::extend(const AABB<T>& other, bool center)
    {
        extend(other.size, center);
    }

    template <typename T>
    void AABB<T>::extend(const Vec2<T>& othersize, bool center)
    {
        if (center)
            pos -= othersize / 2.f;
        size += othersize;
    }

    template <typename T>
    bool AABB<T>::isEmpty() const
    {
        return size.x == 0 && size.y == 0;
    }

    template <typename T>
    void AABB<T>::center(T x, T y)
    {
        pos.fill(x, y);
        pos -= size / 2;
    }

    template <typename T>
    void AABB<T>::center(const Point2<T>& p)
    {
        center(p.x, p.y);
    }

    template <typename T>
    Point2<T> AABB<T>::getCenter() const
    {
        return pos.asPoint() + size / 2;
    }

    template <typename T>
    bool AABB<T>::operator!=(const AABB<T>& r) const
    {
        return pos != r.pos || size != r.size;
    }

    template <typename T>
    bool AABB<T>::operator==(const AABB<T>& r) const
    {
        return pos == r.pos && size == r.size;
    }

    template <typename T>
    template <typename T2>
    AABB<T>::operator AABB<T2>() const
    {
        return AABB<T2>(pos, size);
    }
}

#endif
<commit_msg>Fix wrong function signature<commit_after>#ifndef CPPMATH_AABB_INL
#define CPPMATH_AABB_INL

#include "AABB.hpp"

namespace math
{
    template <typename T>
    AABB<T>::AABB() :
        pos(),
        size()
    {};

    template <typename T>
    AABB<T>::AABB(T x, T y, T w, T h) :
        AABB(Point2<T>(x, y), Vec2<T>(w, h))
    {};

    template <typename T>
    AABB<T>::AABB(const Point2<T>& pos_, const Vec2<T>& size_) :
        pos(pos_.asVector()),
        size(size_)
    {};

    template <typename T>
    AABB<T>::AABB(const AABB<T>& a, const AABB<T>& b) :
        AABB(a)
    {
        combine(b);
    }

    template <typename T>
    AABB<T> AABB<T>::fromPoints(const Point2<T>& a, const Point2<T>& b)
    {
        return AABB<T>(
                std::min(a.x, b.x),
                std::min(a.y, b.y),
                std::abs(a.x - b.x),
                std::abs(a.y - b.y)
            );
    }

    template <typename T>
    void AABB<T>::combine(const AABB<T>& other)
    {
        if (isEmpty())
        {
            *this = other;
            return;
        }
        else if (other.isEmpty())
            return;

        Vec2<T> newpos = mins(pos, other.pos);
        size = maxs(pos + size, other.pos + other.size) - newpos;
        pos = newpos;
    }

    template <typename T>
    void AABB<T>::extend(const AABB<T>& other, bool center)
    {
        extend(other.size, center);
    }

    template <typename T>
    void AABB<T>::extend(const Vec2<T>& othersize, bool center)
    {
        if (center)
            pos -= othersize / 2.f;
        size += othersize;
    }

    template <typename T>
    bool AABB<T>::isEmpty() const
    {
        return size.x == 0 && size.y == 0;
    }

    template <typename T>
    void AABB<T>::center(T x, T y)
    {
        pos.fill(x, y);
        pos -= size / 2;
    }

    template <typename T>
    void AABB<T>::center(const Point2<T>& p)
    {
        center(p.x, p.y);
    }

    template <typename T>
    Point2<T> AABB<T>::getCenter() const
    {
        return pos.asPoint() + size / 2;
    }

    template <typename T>
    bool AABB<T>::operator!=(const AABB<T>& r) const
    {
        return pos != r.pos || size != r.size;
    }

    template <typename T>
    bool AABB<T>::operator==(const AABB<T>& r) const
    {
        return pos == r.pos && size == r.size;
    }

    template <typename T>
    template <typename T2>
    AABB<T>::operator AABB<T2>() const
    {
        return AABB<T2>(pos, size);
    }
}

#endif
<|endoftext|>


<commit_before>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2012  Sandro Santilli <strk@kbt.io>
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * NOTE: this is not in JTS. JTS has a snapround/GeometryNoder though
 *
 **********************************************************************/

#include <geos/noding/GeometryNoder.h>
#include <geos/noding/SegmentString.h>
#include <geos/noding/NodedSegmentString.h>
#include <geos/noding/OrientedCoordinateArray.h>
#include <geos/noding/Noder.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/CoordinateSequence.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/LineString.h>

#include <geos/noding/IteratedNoder.h>

#include <geos/algorithm/LineIntersector.h>
#include <geos/noding/IntersectionAdder.h>
#include <geos/noding/MCIndexNoder.h>

#include <geos/noding/snapround/SimpleSnapRounder.h>
#include <geos/noding/snapround/MCIndexSnapRounder.h>

#include <memory> // for unique_ptr
#include <iostream>

namespace geos {
namespace noding { // geos.noding

namespace {

/**
 * Add every linear element in a geometry into SegmentString vector
 */
class SegmentStringExtractor: public geom::GeometryComponentFilter {
public:
  SegmentStringExtractor(SegmentString::NonConstVect& to)
    : _to(to)
  {}

  void filter_ro(const geom::Geometry * g) override {
    const geom::LineString *ls = dynamic_cast<const geom::LineString *>(g);
    if ( ls ) {
      geom::CoordinateSequence* coord = ls->getCoordinates();
      // coord ownership transferred to SegmentString
      SegmentString *ss = new NodedSegmentString(coord, nullptr);
      _to.push_back(ss);
    }
  }
private:
  SegmentString::NonConstVect& _to;

  SegmentStringExtractor(SegmentStringExtractor const&); /*= delete*/
  SegmentStringExtractor& operator=(SegmentStringExtractor const&); /*= delete*/
};

}

/* public static */
std::unique_ptr<geom::Geometry>
GeometryNoder::node(const geom::Geometry& geom)
{
  GeometryNoder noder(geom);
  return noder.getNoded();
}

/* public */
GeometryNoder::GeometryNoder(const geom::Geometry& g)
  :
  argGeom(g)
{
}

/* private */
std::unique_ptr<geom::Geometry>
GeometryNoder::toGeometry(SegmentString::NonConstVect& nodedEdges)
{
  const geom::GeometryFactory *geomFact = argGeom.getFactory();

  std::set< OrientedCoordinateArray > ocas;

  // Create a geometry out of the noded substrings.
  std::vector< geom::Geometry* >* lines = new std::vector< geom::Geometry * >();
  lines->reserve(nodedEdges.size());
  for (auto &ss :  nodedEdges)
  {
    const geom::CoordinateSequence* coords = ss->getCoordinates();

    // Check if an equivalent edge is known
    OrientedCoordinateArray oca1( *coords );
    if ( ocas.insert(oca1).second ) {
      geom::Geometry* tmp = geomFact->createLineString( coords->clone() );
      lines->push_back( tmp );
    }
  }

  std::unique_ptr<geom::Geometry> noded ( geomFact->createMultiLineString( lines ) );

  return noded;
}

/* public */
std::unique_ptr<geom::Geometry>
GeometryNoder::getNoded()
{
  SegmentString::NonConstVect p_lineList;
  extractSegmentStrings(argGeom, p_lineList);

  Noder& p_noder = getNoder();
  SegmentString::NonConstVect* nodedEdges = nullptr;

  try {
    p_noder.computeNodes( &p_lineList );
    nodedEdges = p_noder.getNodedSubstrings();
  }
  catch (const std::exception& ex)
  {
    for (size_t i=0, n=p_lineList.size(); i<n; ++i)
      delete p_lineList[i];
    throw;
  }

  std::unique_ptr<geom::Geometry> noded = toGeometry(*nodedEdges);

  for (auto &elem : (*nodedEdges))
    delete elem;
  delete nodedEdges;

  for (auto &elem : lineList)
    delete elem;

  return noded;
}

/* private static */
void
GeometryNoder::extractSegmentStrings(const geom::Geometry& g,
                                     SegmentString::NonConstVect& to)
{
  SegmentStringExtractor ex(to);
	g.apply_ro(&ex);
}

/* private */
Noder&
GeometryNoder::getNoder()
{
  if ( ! noder.get() )
  {
    const geom::PrecisionModel *pm = argGeom.getFactory()->getPrecisionModel();
#if 0
    using algorithm::LineIntersector;
		LineIntersector li;
		IntersectionAdder intersectionAdder(li);
    noder.reset( new MCIndexNoder(&intersectionAdder) );
#else

    IteratedNoder* in = new IteratedNoder(pm);
    //in->setMaximumIterations(0);
    noder.reset( in );

    //using snapround::SimpleSnapRounder;
    //noder.reset( new SimpleSnapRounder(*pm) );

    //using snapround::MCIndexSnapRounder;
    //noder.reset( new MCIndexSnapRounder(*pm) );
#endif
  }
  return *noder;

}

} // namespace geos.noding
} // namespace geos
<commit_msg>Fix memory leak in getNoded<commit_after>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2012  Sandro Santilli <strk@kbt.io>
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * NOTE: this is not in JTS. JTS has a snapround/GeometryNoder though
 *
 **********************************************************************/

#include <geos/noding/GeometryNoder.h>
#include <geos/noding/SegmentString.h>
#include <geos/noding/NodedSegmentString.h>
#include <geos/noding/OrientedCoordinateArray.h>
#include <geos/noding/Noder.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/CoordinateSequence.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/LineString.h>

#include <geos/noding/IteratedNoder.h>

#include <geos/algorithm/LineIntersector.h>
#include <geos/noding/IntersectionAdder.h>
#include <geos/noding/MCIndexNoder.h>

#include <geos/noding/snapround/SimpleSnapRounder.h>
#include <geos/noding/snapround/MCIndexSnapRounder.h>

#include <memory> // for unique_ptr
#include <iostream>

namespace geos {
namespace noding { // geos.noding

namespace {

/**
 * Add every linear element in a geometry into SegmentString vector
 */
class SegmentStringExtractor: public geom::GeometryComponentFilter {
public:
  SegmentStringExtractor(SegmentString::NonConstVect& to)
    : _to(to)
  {}

  void filter_ro(const geom::Geometry * g) override {
    const geom::LineString *ls = dynamic_cast<const geom::LineString *>(g);
    if ( ls ) {
      geom::CoordinateSequence* coord = ls->getCoordinates();
      // coord ownership transferred to SegmentString
      SegmentString *ss = new NodedSegmentString(coord, nullptr);
      _to.push_back(ss);
    }
  }
private:
  SegmentString::NonConstVect& _to;

  SegmentStringExtractor(SegmentStringExtractor const&); /*= delete*/
  SegmentStringExtractor& operator=(SegmentStringExtractor const&); /*= delete*/
};

}

/* public static */
std::unique_ptr<geom::Geometry>
GeometryNoder::node(const geom::Geometry& geom)
{
  GeometryNoder noder(geom);
  return noder.getNoded();
}

/* public */
GeometryNoder::GeometryNoder(const geom::Geometry& g)
  :
  argGeom(g)
{
}

/* private */
std::unique_ptr<geom::Geometry>
GeometryNoder::toGeometry(SegmentString::NonConstVect& nodedEdges)
{
  const geom::GeometryFactory *geomFact = argGeom.getFactory();

  std::set< OrientedCoordinateArray > ocas;

  // Create a geometry out of the noded substrings.
  std::vector< geom::Geometry* >* lines = new std::vector< geom::Geometry * >();
  lines->reserve(nodedEdges.size());
  for (auto &ss :  nodedEdges)
  {
    const geom::CoordinateSequence* coords = ss->getCoordinates();

    // Check if an equivalent edge is known
    OrientedCoordinateArray oca1( *coords );
    if ( ocas.insert(oca1).second ) {
      geom::Geometry* tmp = geomFact->createLineString( coords->clone() );
      lines->push_back( tmp );
    }
  }

  std::unique_ptr<geom::Geometry> noded ( geomFact->createMultiLineString( lines ) );

  return noded;
}

/* public */
std::unique_ptr<geom::Geometry>
GeometryNoder::getNoded()
{
  SegmentString::NonConstVect p_lineList;
  extractSegmentStrings(argGeom, p_lineList);

  Noder& p_noder = getNoder();
  SegmentString::NonConstVect* nodedEdges = nullptr;

  try {
    p_noder.computeNodes( &p_lineList );
    nodedEdges = p_noder.getNodedSubstrings();
  }
  catch (const std::exception& ex)
  {
    for (size_t i=0, n=p_lineList.size(); i<n; ++i)
      delete p_lineList[i];
    throw;
  }

  std::unique_ptr<geom::Geometry> noded = toGeometry(*nodedEdges);

  for (auto &elem : (*nodedEdges))
    delete elem;
  delete nodedEdges;

  for (auto &elem : p_lineList)
    delete elem;

  return noded;
}

/* private static */
void
GeometryNoder::extractSegmentStrings(const geom::Geometry& g,
                                     SegmentString::NonConstVect& to)
{
  SegmentStringExtractor ex(to);
	g.apply_ro(&ex);
}

/* private */
Noder&
GeometryNoder::getNoder()
{
  if ( ! noder.get() )
  {
    const geom::PrecisionModel *pm = argGeom.getFactory()->getPrecisionModel();
#if 0
    using algorithm::LineIntersector;
		LineIntersector li;
		IntersectionAdder intersectionAdder(li);
    noder.reset( new MCIndexNoder(&intersectionAdder) );
#else

    IteratedNoder* in = new IteratedNoder(pm);
    //in->setMaximumIterations(0);
    noder.reset( in );

    //using snapround::SimpleSnapRounder;
    //noder.reset( new SimpleSnapRounder(*pm) );

    //using snapround::MCIndexSnapRounder;
    //noder.reset( new MCIndexSnapRounder(*pm) );
#endif
  }
  return *noder;

}

} // namespace geos.noding
} // namespace geos
<|endoftext|>


<commit_before><commit_msg>better extract page type<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/download/download_shelf.h"

#include "app/l10n_util.h"
#include "base/file_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/dom_ui/downloads_ui.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/download/download_util.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"

// DownloadShelfContextMenu ----------------------------------------------------

DownloadShelfContextMenu::DownloadShelfContextMenu(
    BaseDownloadItemModel* download_model)
    : download_(download_model->download()),
      model_(download_model) {
}

DownloadShelfContextMenu::~DownloadShelfContextMenu() {
}

bool DownloadShelfContextMenu::ItemIsChecked(int id) const {
  switch (id) {
    case OPEN_WHEN_COMPLETE:
      return download_->open_when_complete();
    case ALWAYS_OPEN_TYPE: {
      const FilePath::StringType extension =
          file_util::GetFileExtensionFromPath(download_->full_path());
      return download_->manager()->ShouldOpenFileExtension(extension);
    }
  }
  return false;
}

bool DownloadShelfContextMenu::ItemIsDefault(int id) const {
  return id == OPEN_WHEN_COMPLETE;
}

std::wstring DownloadShelfContextMenu::GetItemLabel(int id) const {
  switch (id) {
    case SHOW_IN_FOLDER:
      return l10n_util::GetString(IDS_DOWNLOAD_LINK_SHOW);
    case OPEN_WHEN_COMPLETE:
      if (download_->state() == DownloadItem::IN_PROGRESS)
        return l10n_util::GetString(IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE);
      return l10n_util::GetString(IDS_DOWNLOAD_MENU_OPEN);
    case ALWAYS_OPEN_TYPE:
      return l10n_util::GetString(IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE);
    case CANCEL:
      return l10n_util::GetString(IDS_DOWNLOAD_MENU_CANCEL);
    case REMOVE_ITEM:
      return l10n_util::GetString(IDS_DOWNLOAD_MENU_REMOVE_ITEM);
    default:
      NOTREACHED();
  }
  return std::wstring();
}

bool DownloadShelfContextMenu::IsItemCommandEnabled(int id) const {
  switch (id) {
    case SHOW_IN_FOLDER:
    case OPEN_WHEN_COMPLETE:
      return download_->state() != DownloadItem::CANCELLED;
    case ALWAYS_OPEN_TYPE:
      return download_util::CanOpenDownload(download_);
    case CANCEL:
      return download_->state() == DownloadItem::IN_PROGRESS;
    case REMOVE_ITEM:
      return download_->state() == DownloadItem::COMPLETE;
    default:
      return id > 0 && id < MENU_LAST;
  }
}

void DownloadShelfContextMenu::ExecuteItemCommand(int id) {
  switch (id) {
    case SHOW_IN_FOLDER:
      download_->manager()->ShowDownloadInShell(download_);
      break;
    case OPEN_WHEN_COMPLETE:
      download_util::OpenDownload(download_);
      break;
    case ALWAYS_OPEN_TYPE: {
      const FilePath::StringType extension =
          file_util::GetFileExtensionFromPath(download_->full_path());
      download_->manager()->OpenFilesOfExtension(
          extension, !ItemIsChecked(ALWAYS_OPEN_TYPE));
      break;
    }
    case CANCEL:
      model_->CancelTask();
      break;
    case REMOVE_ITEM:
      download_->Remove(false);
      break;
    default:
      NOTREACHED();
  }
}
<commit_msg>Allow cancellable download items to be removable from download shelf.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/download/download_shelf.h"

#include "app/l10n_util.h"
#include "base/file_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/dom_ui/downloads_ui.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/download/download_util.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"

// DownloadShelfContextMenu ----------------------------------------------------

DownloadShelfContextMenu::DownloadShelfContextMenu(
    BaseDownloadItemModel* download_model)
    : download_(download_model->download()),
      model_(download_model) {
}

DownloadShelfContextMenu::~DownloadShelfContextMenu() {
}

bool DownloadShelfContextMenu::ItemIsChecked(int id) const {
  switch (id) {
    case OPEN_WHEN_COMPLETE:
      return download_->open_when_complete();
    case ALWAYS_OPEN_TYPE: {
      const FilePath::StringType extension =
          file_util::GetFileExtensionFromPath(download_->full_path());
      return download_->manager()->ShouldOpenFileExtension(extension);
    }
  }
  return false;
}

bool DownloadShelfContextMenu::ItemIsDefault(int id) const {
  return id == OPEN_WHEN_COMPLETE;
}

std::wstring DownloadShelfContextMenu::GetItemLabel(int id) const {
  switch (id) {
    case SHOW_IN_FOLDER:
      return l10n_util::GetString(IDS_DOWNLOAD_LINK_SHOW);
    case OPEN_WHEN_COMPLETE:
      if (download_->state() == DownloadItem::IN_PROGRESS)
        return l10n_util::GetString(IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE);
      return l10n_util::GetString(IDS_DOWNLOAD_MENU_OPEN);
    case ALWAYS_OPEN_TYPE:
      return l10n_util::GetString(IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE);
    case CANCEL:
      return l10n_util::GetString(IDS_DOWNLOAD_MENU_CANCEL);
    case REMOVE_ITEM:
      return l10n_util::GetString(IDS_DOWNLOAD_MENU_REMOVE_ITEM);
    default:
      NOTREACHED();
  }
  return std::wstring();
}

bool DownloadShelfContextMenu::IsItemCommandEnabled(int id) const {
  switch (id) {
    case SHOW_IN_FOLDER:
    case OPEN_WHEN_COMPLETE:
      return download_->state() != DownloadItem::CANCELLED;
    case ALWAYS_OPEN_TYPE:
      return download_util::CanOpenDownload(download_);
    case CANCEL:
      return download_->state() == DownloadItem::IN_PROGRESS;
    case REMOVE_ITEM:
      return download_->state() == DownloadItem::COMPLETE ||
          download_->state() == DownloadItem::CANCELLED;
    default:
      return id > 0 && id < MENU_LAST;
  }
}

void DownloadShelfContextMenu::ExecuteItemCommand(int id) {
  switch (id) {
    case SHOW_IN_FOLDER:
      download_->manager()->ShowDownloadInShell(download_);
      break;
    case OPEN_WHEN_COMPLETE:
      download_util::OpenDownload(download_);
      break;
    case ALWAYS_OPEN_TYPE: {
      const FilePath::StringType extension =
          file_util::GetFileExtensionFromPath(download_->full_path());
      download_->manager()->OpenFilesOfExtension(
          extension, !ItemIsChecked(ALWAYS_OPEN_TYPE));
      break;
    }
    case CANCEL:
      model_->CancelTask();
      break;
    case REMOVE_ITEM:
      download_->Remove(false);
      break;
    default:
      NOTREACHED();
  }
}
<|endoftext|>


<commit_before>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2/9/2019, 9:16:48 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int L;
ll A[200010];
ll B[200010]; // even
ll C[200010]; // odd
ll sum[3][200010];

ll calc(int a, int b, int c, int d)
{
  ll ans = 0;
  ans += sum[0][a] - sum[0][0];
  ans += sum[1][b] - sum[1][a];
  ans += sum[2][c] - sum[2][b];
  ans += sum[1][d] - sum[1][c];
  ans += sum[0][L] - sum[0][d];
  return ans;
}

int main()
{
  cin >> L;
  ll mini = 0;
  for (auto i = 0; i < L; i++)
  {
    cin >> A[i];
    mini += A[i];
  }
  bool zero = true;
  for (auto i = 0; i < L; i++)
  {
    if (A[i] > 0)
    {
      zero = false;
      break;
    }
  }
  if (zero)
  {
    cout << 0 << endl;
    return 0;
  }
  for (auto i = 0; i < L; i++)
  {
    if (A[i] == 0)
    {
      B[i] = 2;
    }
    else if (A[i] % 2 == 0)
    {
      B[i] = 0;
    }
    else
    {
      B[i] = 1;
    }
  }
  for (auto i = 0; i < L; i++)
  {
    if (A[i] % 2 == 1)
    {
      C[i] = 0;
    }
    else
    {
      C[i] = 1;
    }
  }
  sum[0][0] = sum[0][1] = sum[0][2] = 0;
  for (auto i = 0; i < L; i++)
  {
    sum[0][i + 1] = sum[0][i] + A[i];
    sum[1][i + 1] = sum[1][i] + B[i];
    sum[2][i + 1] = sum[2][i] + C[i];
  }
  for (auto a = 0; a <= L; a++)
  {
    for (auto b = a; b <= L; b++)
    {
      for (auto c = b; c <= L; c++)
      {
        for (auto d = c; d <= L; d++)
        {
          ll t = calc(a, b, c, d);
          mini = min(mini, t);
          cerr << "calc(" << a << ", " << b << ", " << c << ", " << d << ") = " << t << endl;
        }
      }
    }
  }
  cerr << mini << endl;
}<commit_msg>submit D.cpp to 'D - Ears' (yahoo-procon2019-qual) [C++14 (GCC 5.4.1)]<commit_after>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2/9/2019, 9:16:48 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int L;
ll A[200010];
ll B[200010]; // even
ll C[200010]; // odd
ll sum[3][200010];

// TLE

ll calc(int a, int b, int c, int d)
{
  ll ans = 0;
  ans += sum[0][a] - sum[0][0];
  ans += sum[1][b] - sum[1][a];
  ans += sum[2][c] - sum[2][b];
  ans += sum[1][d] - sum[1][c];
  ans += sum[0][L] - sum[0][d];
  return ans;
}

int main()
{
  cin >> L;
  ll mini = 0;
  for (auto i = 0; i < L; i++)
  {
    cin >> A[i];
    mini += A[i];
  }
  bool zero = true;
  for (auto i = 0; i < L; i++)
  {
    if (A[i] > 0)
    {
      zero = false;
      break;
    }
  }
  if (zero)
  {
    cout << 0 << endl;
    return 0;
  }
  for (auto i = 0; i < L; i++)
  {
    if (A[i] == 0)
    {
      B[i] = 2;
    }
    else if (A[i] % 2 == 0)
    {
      B[i] = 0;
    }
    else
    {
      B[i] = 1;
    }
  }
  for (auto i = 0; i < L; i++)
  {
    if (A[i] % 2 == 1)
    {
      C[i] = 0;
    }
    else
    {
      C[i] = 1;
    }
  }
  sum[0][0] = sum[0][1] = sum[0][2] = 0;
  for (auto i = 0; i < L; i++)
  {
    sum[0][i + 1] = sum[0][i] + A[i];
    sum[1][i + 1] = sum[1][i] + B[i];
    sum[2][i + 1] = sum[2][i] + C[i];
  }
  for (auto a = 0; a <= L; a++)
  {
    for (auto b = a; b <= L; b++)
    {
      for (auto c = b; c <= L; c++)
      {
        for (auto d = c; d <= L; d++)
        {
          ll t = calc(a, b, c, d);
          mini = min(mini, t);
          // cerr << "calc(" << a << ", " << b << ", " << c << ", " << d << ") = " << t << endl;
        }
      }
    }
  }
  cout << mini << endl;
}<|endoftext|>