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

// mapnik
#include <mapnik/renderer_common/process_group_symbolizer.hpp>
#include <mapnik/renderer_common/process_point_symbolizer.hpp>
#include <mapnik/renderer_common/process_markers_symbolizer.hpp>
#include <mapnik/text/glyph_info.hpp>
#include <mapnik/make_unique.hpp>

namespace mapnik {

vector_marker_render_thunk::vector_marker_render_thunk(svg_path_ptr const& src,
                                                       svg_attribute_type const& attrs,
                                                       agg::trans_affine const& marker_trans,
                                                       double opacity,
                                                       composite_mode_e comp_op,
                                                       bool snap_to_pixels)
    : src_(src), attrs_(attrs), tr_(marker_trans), opacity_(opacity),
      comp_op_(comp_op), snap_to_pixels_(snap_to_pixels)
{}

raster_marker_render_thunk::raster_marker_render_thunk(image_rgba8 const& src,
                                                       agg::trans_affine const& marker_trans,
                                                       double opacity,
                                                       composite_mode_e comp_op,
                                                       bool snap_to_pixels)
    : src_(src), tr_(marker_trans), opacity_(opacity), comp_op_(comp_op),
      snap_to_pixels_(snap_to_pixels)
{}

text_render_thunk::text_render_thunk(helper_ptr && helper,
                                     double opacity, composite_mode_e comp_op,
                                     halo_rasterizer_enum halo_rasterizer)
    : helper_(std::move(helper)),
      placements_(helper_->get()),
      opacity_(opacity),
      comp_op_(comp_op),
      halo_rasterizer_(halo_rasterizer)
{}

namespace detail {

template <typename Detector, typename RendererContext>
struct vector_marker_thunk_dispatch : public vector_markers_dispatch<Detector>
{
    vector_marker_thunk_dispatch(svg_path_ptr const& src,
                                 svg_path_adapter & path,
                                 svg_attribute_type const& attrs,
                                 agg::trans_affine const& marker_trans,
                                 symbolizer_base const& sym,
                                 Detector & detector,
                                 double scale_factor,
                                 feature_impl & feature,
                                 attributes const& vars,
                                 bool snap_to_pixels,
                                 RendererContext const& renderer_context)
        : vector_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
          attrs_(attrs), comp_op_(get<composite_mode_e, keys::comp_op>(sym, feature, vars)),
          snap_to_pixels_(snap_to_pixels), thunks_(std::get<0>(renderer_context))
    {}

    ~vector_marker_thunk_dispatch() {}

    void render_marker(agg::trans_affine const& marker_tr, double opacity)
    {
        vector_marker_render_thunk thunk(this->src_, this->attrs_, marker_tr, opacity, comp_op_, snap_to_pixels_);
        thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
    }

private:
    svg_attribute_type const& attrs_;
    composite_mode_e comp_op_;
    bool snap_to_pixels_;
    render_thunk_list & thunks_;
};

template <typename Detector, typename RendererContext>
struct raster_marker_thunk_dispatch : public raster_markers_dispatch<Detector>
{
    raster_marker_thunk_dispatch(image_rgba8 const& src,
                                 agg::trans_affine const& marker_trans,
                                 symbolizer_base const& sym,
                                 Detector & detector,
                                 double scale_factor,
                                 feature_impl & feature,
                                 attributes const& vars,
                                 RendererContext const& renderer_context,
                                 bool snap_to_pixels = false)
        : raster_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
          comp_op_(get<composite_mode_e, keys::comp_op>(sym, feature, vars)),
          snap_to_pixels_(snap_to_pixels), thunks_(std::get<0>(renderer_context))
    {}

    ~raster_marker_thunk_dispatch() {}

    void render_marker(agg::trans_affine const& marker_tr, double opacity)
    {
        raster_marker_render_thunk thunk(this->src_, marker_tr, opacity, comp_op_, snap_to_pixels_);
        thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
    }

private:
    composite_mode_e comp_op_;
    bool snap_to_pixels_;
    render_thunk_list & thunks_;
};

} // end detail ns

render_thunk_extractor::render_thunk_extractor(box2d<double> & box,
                                               render_thunk_list & thunks,
                                               feature_impl & feature,
                                               attributes const& vars,
                                               proj_transform const& prj_trans,
                                               virtual_renderer_common & common,
                                               box2d<double> const& clipping_extent)
    : box_(box), thunks_(thunks), feature_(feature), vars_(vars), prj_trans_(prj_trans),
      common_(common), clipping_extent_(clipping_extent)
{}

void render_thunk_extractor::operator()(markers_symbolizer const& sym) const
{
    auto renderer_context = std::tie(thunks_);
    using context_type = decltype(renderer_context);
    using vector_dispatch_type = detail::vector_marker_thunk_dispatch<label_collision_detector4, context_type>;
    using raster_dispatch_type = detail::raster_marker_thunk_dispatch<label_collision_detector4, context_type>;

    render_markers_symbolizer<vector_dispatch_type, raster_dispatch_type>(
            sym, feature_, prj_trans_, common_, clipping_extent_, renderer_context);

    update_box();
}

void render_thunk_extractor::operator()(text_symbolizer const& sym) const
{
    box2d<double> clip_box = clipping_extent_;
    helper_ptr helper = std::make_unique<text_symbolizer_helper>(
        sym, feature_, vars_, prj_trans_,
        common_.width_, common_.height_,
        common_.scale_factor_,
        common_.t_, common_.font_manager_, *common_.detector_,
        clip_box, agg::trans_affine());

    extract_text_thunk(std::move(helper), sym);
}

void render_thunk_extractor::operator()(shield_symbolizer const& sym) const
{
    box2d<double> clip_box = clipping_extent_;
    helper_ptr helper = std::make_unique<text_symbolizer_helper>(
        sym, feature_, vars_, prj_trans_,
        common_.width_, common_.height_,
        common_.scale_factor_,
        common_.t_, common_.font_manager_, *common_.detector_,
        clip_box, agg::trans_affine());

    extract_text_thunk(std::move(helper), sym);
}

void render_thunk_extractor::extract_text_thunk(helper_ptr && helper, text_symbolizer const& sym) const
{
    double opacity = get<double>(sym, keys::opacity, feature_, common_.vars_, 1.0);
    composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature_, common_.vars_, src_over);
    halo_rasterizer_enum halo_rasterizer = get<halo_rasterizer_enum>(sym, keys::halo_rasterizer, feature_, common_.vars_, HALO_RASTERIZER_FULL);

    text_render_thunk thunk(std::move(helper), opacity, comp_op, halo_rasterizer);
    thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));

    update_box();
}

void render_thunk_extractor::update_box() const
{
    label_collision_detector4 & detector = *common_.detector_;

    for (auto const& label : detector)
    {
        if (box_.width() > 0 && box_.height() > 0)
        {
            box_.expand_to_include(label.box);
        }
        else
        {
            box_ = label.box;
        }
    }

    detector.clear();
}

} // namespace mapnik
<commit_msg>remove unused includes<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/renderer_common/process_group_symbolizer.hpp>
#include <mapnik/renderer_common/process_markers_symbolizer.hpp>
#include <mapnik/make_unique.hpp>

namespace mapnik {

vector_marker_render_thunk::vector_marker_render_thunk(svg_path_ptr const& src,
                                                       svg_attribute_type const& attrs,
                                                       agg::trans_affine const& marker_trans,
                                                       double opacity,
                                                       composite_mode_e comp_op,
                                                       bool snap_to_pixels)
    : src_(src), attrs_(attrs), tr_(marker_trans), opacity_(opacity),
      comp_op_(comp_op), snap_to_pixels_(snap_to_pixels)
{}

raster_marker_render_thunk::raster_marker_render_thunk(image_rgba8 const& src,
                                                       agg::trans_affine const& marker_trans,
                                                       double opacity,
                                                       composite_mode_e comp_op,
                                                       bool snap_to_pixels)
    : src_(src), tr_(marker_trans), opacity_(opacity), comp_op_(comp_op),
      snap_to_pixels_(snap_to_pixels)
{}

text_render_thunk::text_render_thunk(helper_ptr && helper,
                                     double opacity, composite_mode_e comp_op,
                                     halo_rasterizer_enum halo_rasterizer)
    : helper_(std::move(helper)),
      placements_(helper_->get()),
      opacity_(opacity),
      comp_op_(comp_op),
      halo_rasterizer_(halo_rasterizer)
{}

namespace detail {

template <typename Detector, typename RendererContext>
struct vector_marker_thunk_dispatch : public vector_markers_dispatch<Detector>
{
    vector_marker_thunk_dispatch(svg_path_ptr const& src,
                                 svg_path_adapter & path,
                                 svg_attribute_type const& attrs,
                                 agg::trans_affine const& marker_trans,
                                 symbolizer_base const& sym,
                                 Detector & detector,
                                 double scale_factor,
                                 feature_impl & feature,
                                 attributes const& vars,
                                 bool snap_to_pixels,
                                 RendererContext const& renderer_context)
        : vector_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
          attrs_(attrs), comp_op_(get<composite_mode_e, keys::comp_op>(sym, feature, vars)),
          snap_to_pixels_(snap_to_pixels), thunks_(std::get<0>(renderer_context))
    {}

    ~vector_marker_thunk_dispatch() {}

    void render_marker(agg::trans_affine const& marker_tr, double opacity)
    {
        vector_marker_render_thunk thunk(this->src_, this->attrs_, marker_tr, opacity, comp_op_, snap_to_pixels_);
        thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
    }

private:
    svg_attribute_type const& attrs_;
    composite_mode_e comp_op_;
    bool snap_to_pixels_;
    render_thunk_list & thunks_;
};

template <typename Detector, typename RendererContext>
struct raster_marker_thunk_dispatch : public raster_markers_dispatch<Detector>
{
    raster_marker_thunk_dispatch(image_rgba8 const& src,
                                 agg::trans_affine const& marker_trans,
                                 symbolizer_base const& sym,
                                 Detector & detector,
                                 double scale_factor,
                                 feature_impl & feature,
                                 attributes const& vars,
                                 RendererContext const& renderer_context,
                                 bool snap_to_pixels = false)
        : raster_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
          comp_op_(get<composite_mode_e, keys::comp_op>(sym, feature, vars)),
          snap_to_pixels_(snap_to_pixels), thunks_(std::get<0>(renderer_context))
    {}

    ~raster_marker_thunk_dispatch() {}

    void render_marker(agg::trans_affine const& marker_tr, double opacity)
    {
        raster_marker_render_thunk thunk(this->src_, marker_tr, opacity, comp_op_, snap_to_pixels_);
        thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
    }

private:
    composite_mode_e comp_op_;
    bool snap_to_pixels_;
    render_thunk_list & thunks_;
};

} // end detail ns

render_thunk_extractor::render_thunk_extractor(box2d<double> & box,
                                               render_thunk_list & thunks,
                                               feature_impl & feature,
                                               attributes const& vars,
                                               proj_transform const& prj_trans,
                                               virtual_renderer_common & common,
                                               box2d<double> const& clipping_extent)
    : box_(box), thunks_(thunks), feature_(feature), vars_(vars), prj_trans_(prj_trans),
      common_(common), clipping_extent_(clipping_extent)
{}

void render_thunk_extractor::operator()(markers_symbolizer const& sym) const
{
    auto renderer_context = std::tie(thunks_);
    using context_type = decltype(renderer_context);
    using vector_dispatch_type = detail::vector_marker_thunk_dispatch<label_collision_detector4, context_type>;
    using raster_dispatch_type = detail::raster_marker_thunk_dispatch<label_collision_detector4, context_type>;

    render_markers_symbolizer<vector_dispatch_type, raster_dispatch_type>(
            sym, feature_, prj_trans_, common_, clipping_extent_, renderer_context);

    update_box();
}

void render_thunk_extractor::operator()(text_symbolizer const& sym) const
{
    box2d<double> clip_box = clipping_extent_;
    helper_ptr helper = std::make_unique<text_symbolizer_helper>(
        sym, feature_, vars_, prj_trans_,
        common_.width_, common_.height_,
        common_.scale_factor_,
        common_.t_, common_.font_manager_, *common_.detector_,
        clip_box, agg::trans_affine());

    extract_text_thunk(std::move(helper), sym);
}

void render_thunk_extractor::operator()(shield_symbolizer const& sym) const
{
    box2d<double> clip_box = clipping_extent_;
    helper_ptr helper = std::make_unique<text_symbolizer_helper>(
        sym, feature_, vars_, prj_trans_,
        common_.width_, common_.height_,
        common_.scale_factor_,
        common_.t_, common_.font_manager_, *common_.detector_,
        clip_box, agg::trans_affine());

    extract_text_thunk(std::move(helper), sym);
}

void render_thunk_extractor::extract_text_thunk(helper_ptr && helper, text_symbolizer const& sym) const
{
    double opacity = get<double>(sym, keys::opacity, feature_, common_.vars_, 1.0);
    composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature_, common_.vars_, src_over);
    halo_rasterizer_enum halo_rasterizer = get<halo_rasterizer_enum>(sym, keys::halo_rasterizer, feature_, common_.vars_, HALO_RASTERIZER_FULL);

    text_render_thunk thunk(std::move(helper), opacity, comp_op, halo_rasterizer);
    thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));

    update_box();
}

void render_thunk_extractor::update_box() const
{
    label_collision_detector4 & detector = *common_.detector_;

    for (auto const& label : detector)
    {
        if (box_.width() > 0 && box_.height() > 0)
        {
            box_.expand_to_include(label.box);
        }
        else
        {
            box_ = label.box;
        }
    }

    detector.clear();
}

} // namespace mapnik
<|endoftext|>


<commit_before>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */

#if !defined(XALANMAP_HEADER_GUARD_1357924680)
#define XALANMAP_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>

#include <cstddef>
#include <algorithm>
#include <functional>
#include <utility>

#include <xalanc/Include/XalanMemoryManagement.hpp>

#include <xalanc/Include/XalanVector.hpp>
#include <xalanc/Include/XalanList.hpp>

XALAN_CPP_NAMESPACE_BEGIN

typedef size_t	size_type;

template <class Key>
class XalanHasher : public XALAN_STD_QUALIFIER unary_function<Key, size_type>
{
public:
	size_type operator()(const Key& key) const
	{
		const char *byteArray = reinterpret_cast<const char*>(&key);

		size_type result = 0;

		for (size_type i = 0; i < sizeof(Key); ++i)
		{
			result = (result << 1) ^ byteArray[i];
		}

		return result;
	}
};

template <class Key>
struct XalanMapKeyTraits
{
	typedef XalanHasher<Key>					Hasher;
	typedef XALAN_STD_QUALIFIER equal_to<Key>	Comparator;
};

template <class Key>
struct XalanHashMemberPointer
{

	size_type operator() (const Key * key) const
	{
		assert (key != 0);
		return key->hash();
	}
};

template <class Key>
struct XalanHashMemberReference
{

	size_type operator() (const Key& key) const
	{
		return key.hash();
	}
};

/**
 * Xalan map entry pair of a key and data
 */
template <class KeyType,  class DataType>
struct XalanMapEntry
{
    typedef KeyType     first_type;
    typedef DataType    second_type;

	typedef size_t	size_type;

    XalanMapEntry(
            const first_type & theFirst,
            const second_type& theSecond,
            size_type index = 0) :
		first(theFirst),
        second(theSecond),
        bucketIndex(index)
	{
	}

	XalanMapEntry() :
		first(),
        second(),
        bucketIndex(size_type())
	{
	}

    first_type      first;
    second_type     second;
    size_type       bucketIndex;
};

template <class Value>
struct XalanMapIteratorTraits
{
	typedef Value	        value_type;
	typedef Value&	        reference;
	typedef Value*	        pointer;
};

template <class Value>
struct XalanMapConstIteratorTraits
{
	typedef Value	        value_type;
	typedef const Value&	reference;
	typedef const Value*	pointer;
};

template <class XalanMapTraits, class BaseIterator>
struct XalanMapIterator : public BaseIterator
{
    typedef typename XalanMapTraits::value_type         value_type;
    typedef typename XalanMapTraits::reference          reference;
    typedef typename XalanMapTraits::pointer            pointer;

	typedef ptrdiff_t		                    difference_type;
	typedef XALAN_STD_QUALIFIER bidirectional_iterator_tag iterator_category;

    typedef typename BaseIterator::iterator             Iterator;

    XalanMapIterator() :
            BaseIterator()
    {
    }

    XalanMapIterator(const BaseIterator & theRhs) :
            BaseIterator(theRhs)
    {
    }

    reference operator*() const
    {
        return *(BaseIterator::operator*());
    }

    pointer operator->() const
    {
        return (BaseIterator::operator*());
    }
};

/**
  * Xalan implementation of a hashtable.
  *
  */
template <
		class Key,
		class Value,
		class KeyTraits = XalanMapKeyTraits<Key> >
class XalanMap
{
public:
	/**
	 * Each map entry is stored in a linked list.
	 * The hash buckets are a vector of pointers into the entry list
	 * An empty bucket will point to the end of the list,
	 * A non-empty bucket will point to its first entry.  Remaining
	 * entries in the chain follow the first and have the same index value.
	 */

	typedef Key					key_type;
	typedef Value				data_type;
	typedef size_t				size_type;

	typedef XalanMapEntry<const key_type, data_type>   value_type;
    typedef value_type  Entry;

	typedef XalanList<Entry*>									EntryListType;

    typedef XalanMapIterator<XalanMapIteratorTraits<Entry>, typename EntryListType::iterator>            iterator;
    typedef XalanMapIterator<XalanMapConstIteratorTraits<Entry>, typename EntryListType::const_iterator> const_iterator;

	typedef XalanVector<iterator>		EntryPosVectorType;

    typedef typename MemoryManagedConstructionTraits<key_type>::Constructor  FirstConstructor;
    typedef typename MemoryManagedConstructionTraits<data_type>::Constructor SecondConstructor;

	XalanMap(
			MemoryManagerType* theMemoryManager = 0,
			float loadFactor = 0.75,
			size_type minBuckets = 10) :
		m_memoryManager(theMemoryManager),
		m_loadFactor(loadFactor),
		m_minBuckets(minBuckets),
		m_size(0),
		m_entries(m_memoryManager),
		m_buckets(m_memoryManager)
	{
	}

	XalanMap(
			const XalanMap &theRhs,
			MemoryManagerType*  theManager = 0) :
        m_memoryManager(theManager != 0 ? theManager : theRhs.m_memoryManager),
		m_loadFactor(theRhs.m_loadFactor),
		m_minBuckets(10),
		m_size(0),
		m_entries(m_memoryManager),
		m_buckets(size_type(m_loadFactor * theRhs.size())+ 1, m_entries.end(), m_memoryManager)
	{
		const_iterator entry = theRhs.begin();
		while(entry != theRhs.end())
		{
			insert(*entry);
			++entry;
		}

		assert(m_size == theRhs.m_size);
	}

	~XalanMap()
	{
	}

	XalanMap & operator=(const XalanMap& theRhs)
	{
		XalanMap theTemp(theRhs);
		swap(theTemp);
		return *this;
	}

	size_type size() const
	{
		return m_size;
	}

	bool empty() const {
		return m_size == 0;
	}

	iterator begin()
	{
		return m_entries.begin();
	}

	const_iterator begin() const
	{
		return m_entries.begin();
	}

	iterator end()
	{
		return m_entries.end();
	}

	const_iterator end() const
	{
		return m_entries.end();
	}

	iterator find(const key_type& key)
	{
		if (!m_buckets.empty())
		{
			const size_type     index = doHash(key);
            assert(index < m_buckets.size());

			iterator bucketPos = m_buckets[index];

			while (bucketPos != m_entries.end() &&
				   bucketPos->bucketIndex == index)
			{
				if (m_equals(key,bucketPos->first))
				{
					return bucketPos;
				}
				++bucketPos;
			}
		}

		return end();
	}

	const_iterator find(const key_type& key) const
	{
		return const_cast<XalanMap *>(this)->find(key);
	}

	data_type & operator[](const key_type& key)
	{
		iterator pos = find(key);

		if (pos == end())
		{
			pos = doCreateEntry(key);
		}

		return (*pos).second;
	}

	void insert(const value_type& value)
	{
		const key_type& key = value.first;
		const data_type& data = value.second;

		insert(key, data);
	}

    void insert(const key_type& key, const data_type& data)
	{
		const const_iterator    pos = find(key);

		if (pos == end())
		{
			doCreateEntry(key, &data);
		}
	}

	void erase(iterator pos)
	{
		if (pos != end())
		{
			doRemoveEntry(pos);
		}
	}

	size_type erase(const key_type& key)
	{
		const iterator  pos = find(key);

        if (pos != end())
        {
		    erase(pos);
            return 1;
        }
        else
        {
            return 0;
        }
	}

	void clear()
	{
		m_size = 0;

		XALAN_STD_QUALIFIER fill(
            m_buckets.begin(),
            m_buckets.end(),
            m_entries.end());

		m_entries.clear();
	}

	void swap(XalanMap& theRhs)
	{
		size_type tempSize = m_size;
		m_size = theRhs.m_size;
		theRhs.m_size = tempSize;

		MemoryManagerType* tempMemoryManager = m_memoryManager;
		m_memoryManager = theRhs.m_memoryManager;
		theRhs.m_memoryManager = tempMemoryManager;

		m_entries.swap(theRhs.m_entries);
		m_buckets.swap(theRhs.m_buckets);
	}

	protected:

	iterator doCreateEntry(const key_type & key, const data_type*  data = 0)
	{
		// if there are no buckets, create initial minimum set of buckets
		if (m_buckets.empty())
		{
			m_buckets.insert(m_buckets.begin(), m_minBuckets, m_entries.end());
		}

		// if the load factor has been reached, rehash
		if (size_type(m_loadFactor * size()) > m_buckets.size())
		{
			rehash();
		}

		size_type index = doHash(key);

		iterator & bucketStartPos = m_buckets[index];

		// insert a new entry as the first position in the bucket
        Entry * newEntry = allocate(1);
        FirstConstructor::construct((key_type*)&newEntry->first, key, *m_memoryManager);
        if (data != 0)
        {
            SecondConstructor::construct(&newEntry->second, *data, *m_memoryManager);
        }
        else
        {
             SecondConstructor::construct(&newEntry->second, *m_memoryManager);
        }

        new (&newEntry->bucketIndex) size_type(index);
		bucketStartPos = m_entries.insert(bucketStartPos, newEntry);

		++m_size;
		return bucketStartPos;
	}

	void doRemoveEntry(iterator & toRemovePos)
	{
		size_type index = toRemovePos->bucketIndex;
		iterator nextPos = ++(iterator(toRemovePos));

		// if the entry to remove is the first in the bucket
		// set the next entry as the first or,
		// if there are no more entries set it to the end
		if (m_buckets[index] == toRemovePos)
		{
			if (nextPos != m_entries.end() &&
                nextPos->bucketIndex == index)
			{
				m_buckets[index] = nextPos;
			}
			else
			{
				m_buckets[index] = m_entries.end();
			}
		}

        value_type& toRemove = *toRemovePos;
        toRemove.~value_type();
        deallocate(&toRemove);
		m_entries.erase(toRemovePos);
		--m_size;
	}

	size_type doHash(const Key & key) const
	{
		return m_hash(key) % m_buckets.size();
	}

	void rehash()
	{
		// grow the number of buckets by 60%
		EntryPosVectorType temp(size_type(1.6 * size()), m_entries.end(), m_memoryManager);
		m_buckets.swap(temp);

		// move current entries into a temporary list
		EntryListType tempEntryList;
		tempEntryList.splice(tempEntryList.begin(),m_entries, m_entries.begin(), m_entries.end());

		// rehash each entry assign to bucket and insert into list
		while (tempEntryList.begin() != tempEntryList.end())
		{
			iterator entry = tempEntryList.begin();

			entry->bucketIndex = doHash(entry->first);
			iterator & bucketStartPos = m_buckets[entry->bucketIndex];

			// if the bucket is empty assign to the entry and insert
			// into the list, otherwise insert into front of the
			// current first entry
			if (bucketStartPos == m_entries.end())
			{
				bucketStartPos = entry;
				m_entries.splice(m_entries.begin(), tempEntryList, entry);
			}
			else
			{
				m_entries.splice(bucketStartPos, tempEntryList, entry);
				--bucketStartPos;
			}
		}
	}

    value_type*
    allocate(size_type  size)
    {
        const size_type     theBytesNeeded = size * sizeof(value_type);

        void*   pointer = m_memoryManager == 0 ?
            ::operator new (theBytesNeeded) :
            m_memoryManager->allocate(theBytesNeeded);

        assert(pointer != 0);

        return (value_type*) pointer;
    }

    void
    deallocate(value_type*  pointer)
    {
        if (m_memoryManager == 0)
        {
            ::operator delete(pointer);
        }
        else
        {
            m_memoryManager->deallocate(pointer);
        }
    }

	// Data members...
	typename KeyTraits::Hasher					m_hash;

	typename KeyTraits::Comparator				m_equals;

    MemoryManagerType*					m_memoryManager;

	float								m_loadFactor;

	size_type							m_minBuckets;

	size_type							m_size;

	EntryListType						m_entries;

    EntryPosVectorType					m_buckets;

};

XALAN_CPP_NAMESPACE_END

#endif  // XALANMAP_HEADER_GUARD_1357924680

<commit_msg>Fix copy constructors<commit_after>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */

#if !defined(XALANMAP_HEADER_GUARD_1357924680)
#define XALANMAP_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>

#include <cstddef>
#include <algorithm>
#include <functional>
#include <utility>

#include <xalanc/Include/XalanMemoryManagement.hpp>

#include <xalanc/Include/XalanVector.hpp>
#include <xalanc/Include/XalanList.hpp>

XALAN_CPP_NAMESPACE_BEGIN

typedef size_t	size_type;

template <class Key>
class XalanHasher : public XALAN_STD_QUALIFIER unary_function<Key, size_type>
{
public:
	size_type operator()(const Key& key) const
	{
		const char *byteArray = reinterpret_cast<const char*>(&key);

		size_type result = 0;

		for (size_type i = 0; i < sizeof(Key); ++i)
		{
			result = (result << 1) ^ byteArray[i];
		}

		return result;
	}
};

template <class Key>
struct XalanMapKeyTraits
{
	typedef XalanHasher<Key>					Hasher;
	typedef XALAN_STD_QUALIFIER equal_to<Key>	Comparator;
};

template <class Key>
struct XalanHashMemberPointer
{

	size_type operator() (const Key * key) const
	{
		assert (key != 0);
		return key->hash();
	}
};

template <class Key>
struct XalanHashMemberReference
{

	size_type operator() (const Key& key) const
	{
		return key.hash();
	}
};

/**
 * Xalan map entry pair of a key and data
 */
template <class KeyType,  class DataType>
struct XalanMapEntry
{
    typedef KeyType     first_type;
    typedef DataType    second_type;

	typedef size_t	size_type;

    XalanMapEntry(
            const first_type & theFirst,
            const second_type& theSecond,
            size_type index = 0) :
		first(theFirst),
        second(theSecond),
        bucketIndex(index)
	{
	}

	XalanMapEntry() :
		first(),
        second(),
        bucketIndex(size_type())
	{
	}

    first_type      first;
    second_type     second;
    size_type       bucketIndex;
};

template <class Value>
struct XalanMapIteratorTraits
{
	typedef Value	        value_type;
	typedef Value&	        reference;
	typedef Value*	        pointer;
};

template <class Value>
struct XalanMapConstIteratorTraits
{
	typedef Value	        value_type;
	typedef const Value&	reference;
	typedef const Value*	pointer;
};

template <class XalanMapTraits, class BaseIterator>
struct XalanMapIterator : public BaseIterator
{
    typedef typename XalanMapTraits::value_type         value_type;
    typedef typename XalanMapTraits::reference          reference;
    typedef typename XalanMapTraits::pointer            pointer;

	typedef ptrdiff_t		                    difference_type;
	typedef XALAN_STD_QUALIFIER bidirectional_iterator_tag iterator_category;

    typedef XalanMapIterator<
		XalanMapIteratorTraits<value_type>,
  		typename BaseIterator::iterator>	Iterator;

    XalanMapIterator() :
            BaseIterator()
    {
    }

    XalanMapIterator(const Iterator & theRhs) :
            BaseIterator(theRhs)
    {
    }

    XalanMapIterator(const BaseIterator& theRhs) :
            BaseIterator(theRhs)
    {
    }

    reference operator*() const
    {
        return *(BaseIterator::operator*());
    }

    pointer operator->() const
    {
        return (BaseIterator::operator*());
    }
};

/**
  * Xalan implementation of a hashtable.
  *
  */
template <
		class Key,
		class Value,
		class KeyTraits = XalanMapKeyTraits<Key> >
class XalanMap
{
public:
	/**
	 * Each map entry is stored in a linked list.
	 * The hash buckets are a vector of pointers into the entry list
	 * An empty bucket will point to the end of the list,
	 * A non-empty bucket will point to its first entry.  Remaining
	 * entries in the chain follow the first and have the same index value.
	 */

	typedef Key					key_type;
	typedef Value				data_type;
	typedef size_t				size_type;

	typedef XalanMapEntry<const key_type, data_type>   value_type;
    typedef value_type  Entry;

	typedef XalanList<Entry*>									EntryListType;

    typedef XalanMapIterator<XalanMapIteratorTraits<Entry>, typename EntryListType::iterator>            iterator;
    typedef XalanMapIterator<XalanMapConstIteratorTraits<Entry>, typename EntryListType::const_iterator> const_iterator;

	typedef XalanVector<iterator>		EntryPosVectorType;

    typedef typename MemoryManagedConstructionTraits<key_type>::Constructor  FirstConstructor;
    typedef typename MemoryManagedConstructionTraits<data_type>::Constructor SecondConstructor;

	XalanMap(
			MemoryManagerType* theMemoryManager = 0,
			float loadFactor = 0.75,
			size_type minBuckets = 10) :
		m_memoryManager(theMemoryManager),
		m_loadFactor(loadFactor),
		m_minBuckets(minBuckets),
		m_size(0),
		m_entries(m_memoryManager),
		m_buckets(m_memoryManager)
	{
	}

	XalanMap(
			const XalanMap &theRhs,
			MemoryManagerType*  theManager = 0) :
        m_memoryManager(theManager != 0 ? theManager : theRhs.m_memoryManager),
		m_loadFactor(theRhs.m_loadFactor),
		m_minBuckets(10),
		m_size(0),
		m_entries(m_memoryManager),
		m_buckets(size_type(m_loadFactor * theRhs.size())+ 1, m_entries.end(), m_memoryManager)
	{
		const_iterator entry = theRhs.begin();
		while(entry != theRhs.end())
		{
			insert(*entry);
			++entry;
		}

		assert(m_size == theRhs.m_size);
	}

	~XalanMap()
	{
	}

	XalanMap & operator=(const XalanMap& theRhs)
	{
		XalanMap theTemp(theRhs);
		swap(theTemp);
		return *this;
	}

	size_type size() const
	{
		return m_size;
	}

	bool empty() const {
		return m_size == 0;
	}

	iterator begin()
	{
		return m_entries.begin();
	}

	const_iterator begin() const
	{
		return m_entries.begin();
	}

	iterator end()
	{
		return m_entries.end();
	}

	const_iterator end() const
	{
		return m_entries.end();
	}

	iterator find(const key_type& key)
	{
		if (!m_buckets.empty())
		{
			const size_type     index = doHash(key);
            assert(index < m_buckets.size());

			iterator bucketPos = m_buckets[index];

			while (bucketPos != m_entries.end() &&
				   bucketPos->bucketIndex == index)
			{
				if (m_equals(key,bucketPos->first))
				{
					return bucketPos;
				}
				++bucketPos;
			}
		}

		return end();
	}

	const_iterator find(const key_type& key) const
	{
		return const_cast<XalanMap *>(this)->find(key);
	}

	data_type & operator[](const key_type& key)
	{
		iterator pos = find(key);

		if (pos == end())
		{
			pos = doCreateEntry(key);
		}

		return (*pos).second;
	}

	void insert(const value_type& value)
	{
		const key_type& key = value.first;
		const data_type& data = value.second;

		insert(key, data);
	}

    void insert(const key_type& key, const data_type& data)
	{
		const const_iterator    pos = find(key);

		if (pos == end())
		{
			doCreateEntry(key, &data);
		}
	}

	void erase(iterator pos)
	{
		if (pos != end())
		{
			doRemoveEntry(pos);
		}
	}

	size_type erase(const key_type& key)
	{
		const iterator  pos = find(key);

        if (pos != end())
        {
		    erase(pos);
            return 1;
        }
        else
        {
            return 0;
        }
	}

	void clear()
	{
		m_size = 0;

		XALAN_STD_QUALIFIER fill(
            m_buckets.begin(),
            m_buckets.end(),
            m_entries.end());

		m_entries.clear();
	}

	void swap(XalanMap& theRhs)
	{
		size_type tempSize = m_size;
		m_size = theRhs.m_size;
		theRhs.m_size = tempSize;

		MemoryManagerType* tempMemoryManager = m_memoryManager;
		m_memoryManager = theRhs.m_memoryManager;
		theRhs.m_memoryManager = tempMemoryManager;

		m_entries.swap(theRhs.m_entries);
		m_buckets.swap(theRhs.m_buckets);
	}

	protected:

	iterator doCreateEntry(const key_type & key, const data_type*  data = 0)
	{
		// if there are no buckets, create initial minimum set of buckets
		if (m_buckets.empty())
		{
			m_buckets.insert(m_buckets.begin(), m_minBuckets, m_entries.end());
		}

		// if the load factor has been reached, rehash
		if (size_type(m_loadFactor * size()) > m_buckets.size())
		{
			rehash();
		}

		size_type index = doHash(key);

		iterator & bucketStartPos = m_buckets[index];

		// insert a new entry as the first position in the bucket
        Entry * newEntry = allocate(1);
        FirstConstructor::construct((key_type*)&newEntry->first, key, *m_memoryManager);
        if (data != 0)
        {
            SecondConstructor::construct(&newEntry->second, *data, *m_memoryManager);
        }
        else
        {
             SecondConstructor::construct(&newEntry->second, *m_memoryManager);
        }

        new (&newEntry->bucketIndex) size_type(index);
		bucketStartPos = m_entries.insert(bucketStartPos, newEntry);

		++m_size;
		return bucketStartPos;
	}

	void doRemoveEntry(iterator & toRemovePos)
	{
		size_type index = toRemovePos->bucketIndex;
		iterator nextPos = ++(iterator(toRemovePos));

		// if the entry to remove is the first in the bucket
		// set the next entry as the first or,
		// if there are no more entries set it to the end
		if (m_buckets[index] == toRemovePos)
		{
			if (nextPos != m_entries.end() &&
                nextPos->bucketIndex == index)
			{
				m_buckets[index] = nextPos;
			}
			else
			{
				m_buckets[index] = m_entries.end();
			}
		}

        value_type& toRemove = *toRemovePos;
        toRemove.~value_type();
        deallocate(&toRemove);
		m_entries.erase(toRemovePos);
		--m_size;
	}

	size_type doHash(const Key & key) const
	{
		return m_hash(key) % m_buckets.size();
	}

	void rehash()
	{
		// grow the number of buckets by 60%
		EntryPosVectorType temp(size_type(1.6 * size()), m_entries.end(), m_memoryManager);
		m_buckets.swap(temp);

		// move current entries into a temporary list
		EntryListType tempEntryList;
		tempEntryList.splice(tempEntryList.begin(),m_entries, m_entries.begin(), m_entries.end());

		// rehash each entry assign to bucket and insert into list
		while (tempEntryList.begin() != tempEntryList.end())
		{
			iterator entry = tempEntryList.begin();

			entry->bucketIndex = doHash(entry->first);
			iterator & bucketStartPos = m_buckets[entry->bucketIndex];

			// if the bucket is empty assign to the entry and insert
			// into the list, otherwise insert into front of the
			// current first entry
			if (bucketStartPos == m_entries.end())
			{
				bucketStartPos = entry;
				m_entries.splice(m_entries.begin(), tempEntryList, entry);
			}
			else
			{
				m_entries.splice(bucketStartPos, tempEntryList, entry);
				--bucketStartPos;
			}
		}
	}

    value_type*
    allocate(size_type  size)
    {
        const size_type     theBytesNeeded = size * sizeof(value_type);

        void*   pointer = m_memoryManager == 0 ?
            ::operator new (theBytesNeeded) :
            m_memoryManager->allocate(theBytesNeeded);

        assert(pointer != 0);

        return (value_type*) pointer;
    }

    void
    deallocate(value_type*  pointer)
    {
        if (m_memoryManager == 0)
        {
            ::operator delete(pointer);
        }
        else
        {
            m_memoryManager->deallocate(pointer);
        }
    }

	// Data members...
	typename KeyTraits::Hasher					m_hash;

	typename KeyTraits::Comparator				m_equals;

    MemoryManagerType*					m_memoryManager;

	float								m_loadFactor;

	size_type							m_minBuckets;

	size_type							m_size;

	EntryListType						m_entries;

    EntryPosVectorType					m_buckets;

};

XALAN_CPP_NAMESPACE_END

#endif  // XALANMAP_HEADER_GUARD_1357924680

<|endoftext|>


<commit_before>// irview : simple viewer for adding false colour to IR or thermal images
//          / video / camera feed
// usage: prog {image/video file}

// Author : Toby Breckon, toby.breckon@durham.ac.uk

// Copyright (c) 2008 School of Engineering, Cranfield University
// Copyright (c) 2017 School of Engineering and Computing Sciences, Durham University
// License : GPL - http://www.gnu.org/licenses/gpl.html

/******************************************************************************/

#define BUILD_FOR_OPENCV_3 1

#if (BUILD_FOR_OPENCV_3)

#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

#include <iostream>		// standard C++ I/O
#include <string>		// standard C++ I/O
#include <algorithm>    // includes max()

using namespace cv; // OpenCV API is in the C++ "cv" namespace
using namespace std;

#else

#include "cv.h"       // open cv general include file
#include "highgui.h"  // open cv GUI include file

#include <stdio.h>
#include <ctype.h>

#endif

/******************************************************************************/
// setup the camera index properly based on OS platform

// 0 in linux gives first camera for v4l
//-1 in windows gives first device or user dialog selection

#ifdef linux
	#define CAMERA_INDEX 0
#else
	#define CAMERA_INDEX -1
#endif
/******************************************************************************/

#define PROG_ID_STRING "IrView v0.2- (c) Toby Breckon, 2008-2017+"
#define LICENSE_STRING "GPL - http://www.gnu.org/licenses/gpl.html"

static void print_help(char **name){
	printf("\n%s\n", PROG_ID_STRING);
	printf ("\t with OpenCV version %s (%d.%d.%d)\n",
					CV_VERSION,
					CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
	printf("%s\n\n", LICENSE_STRING);

	printf("Usage :%s [image/video file]\n", name[0]);
	printf("Camera interface: run with no file agrument for direct camera use\n");
	printf("\nKeyboard commands\n");
	printf("\t a - automatic scaling (default: on)\n");
	printf("\t b - show both false colour and original (default: off)\n");
	printf("\t c - toggle false colour (default: on)\n");
	printf("\t x - exit\n\n");
}

/******************************************************************************/

// concatenate 2 OpenCV Mat Objects side-by-side (in general)

Mat concatImages(Mat img1, Mat img2)
{
		Mat out = Mat(img1.rows, img1.cols + img2.cols, img1.type());
		Mat roi = out(Rect(0, 0, img1.cols, img1.rows));
		Mat roi2 = out(Rect(img1.cols, 0, img2.cols, img2.rows));

		img1.copyTo(roi);

		// depth of img1 is master, depth of img2 is slave
		// so convert if needed

		if (img1.depth() != img2.depth())
		{
				// e.g. if img2 is 8-bit and img1 32-bit - scale to range 0->1 (32-bit)
				// otherwise img2 is 32-bit and img1 is 8-bit - scale to 0->255 (8-bit)

				img2.convertTo(roi2, img1.depth(), (img2.depth() < img1.depth()) ? 1.0 / 255.0 : 255);
		} else {
				img2.copyTo(roi2);
		}
		return out;
}

/******************************************************************************/

int main( int argc, char** argv )
{

	IplImage* img = NULL;      // image object
	CvCapture* capture = NULL; // capture object

	const char* windowNameHSV = PROG_ID_STRING; // window name

 	IplImage* HSV = NULL;					// HSV image
 	IplImage* singleChannelH = NULL;		// Hue plain (from input image)
 	IplImage* singleChannelPlain = NULL; 	// constant plane for S & V

	bool keepProcessing = true;		// loop control flag
	char key = '\0';				// user input
	int  EVENT_LOOP_DELAY = 40;     // 40ms equates to 1000ms/25fps =
									// 40ms per frame

	bool useFalseColour = true;     // process flag - false colour
	bool useNormalisation = true;   // process flag - normalisation
	bool useConcatImage = false; 		// process flag - show concatenated images

  // if command line arguments are provided try to read image/video_name
  // otherwise default to capture from attached H/W camera

    if(
	  ( argc == 2 && (img = cvLoadImage( argv[1], 1)) != 0 ) ||
	  ( argc == 2 && (capture = cvCreateFileCapture( argv[1] )) != 0 ) ||
	  ( argc != 2 && (capture = cvCreateCameraCapture( CAMERA_INDEX )) != 0 )
	  )
    {
      // print help

	  print_help(argv);

	  // create window object (use flag=0 to allow resize, 1 to auto fix size)

	  cvNamedWindow(windowNameHSV, 0);
	  cvResizeWindow(windowNameHSV, 640, 480);

	  // if capture object in use (i.e. video/camera)
	  // get initial image from capture object

	  if (capture) {

		  // cvQueryFrame s just a combination of cvGrabFrame
		  // and cvRetrieveFrame in one call.

		  img = cvQueryFrame(capture);
		  if(!img){
			if (argc == 2){
				printf("End of video file reached\n");
			} else {
				printf("ERROR: cannot get next frame from camera\n");
			}
			exit(0);
		  }

	  }

	  // setup output image in HSV

	  HSV = cvCloneImage(img);
	  singleChannelH =
	  			cvCreateImage(cvSize(img->width,img->height), IPL_DEPTH_8U, 1);
	  singleChannelH->origin = img->origin;
	  IplImage* singleChannelV =
	  			cvCreateImage(cvSize(img->width,img->height), IPL_DEPTH_8U, 1);
	  singleChannelV->origin = img->origin;

	  // set single channel up for Saturation / Variance

	  singleChannelPlain =
	  			cvCreateImage(cvSize(img->width,img->height), IPL_DEPTH_8U, 1);
	  singleChannelPlain->origin = img->origin;
	  cvSet(singleChannelPlain, cvScalar(255));

	  // start main loop

	  while (keepProcessing) {

		  // if capture object in use (i.e. video/camera)
		  // get image from capture object

		  if (capture) {

			  // cvQueryFrame is just a combination of cvGrabFrame
			  // and cvRetrieveFrame in one call.

			  img = cvQueryFrame(capture);

			  // cvQueryFrame s just a combination of cvGrabFrame
			  // and cvRetrieveFrame in one call.

			  if(!img){
					if (argc == 2){
						printf("End of video file reached\n");
					} else {
						printf("ERROR: cannot get next frame from camera\n");
					}
					exit(0);
			  }

		  }

		  // extract first (or only input image channel)

		  if (img->nChannels > 1) {
		  		cvSetImageCOI(img, 1); // select channel 1, 0 means all channels
		  }

		  // we will use this for the Hue and Variance channels

		  cvCopy(img, singleChannelH);
		  cvCopy(img, singleChannelV);
		  cvSetImageCOI(img, 0);

		  // do colour normalisation (makes it look more impressive)

		  if (useNormalisation){
		  	cvNormalize(singleChannelH, singleChannelH, 0, 255,
			  												CV_MINMAX, NULL);
				cvNormalize(singleChannelV, singleChannelV, 0, 255,
			  												CV_MINMAX, NULL);
		  }

		  // do scaling to avoid Hue space wrap around (i.e. dark == bright!)
		  // N.B. changing the scaling factor and addition will vary the colour
		  // effect - OpenCV 8-bit Hue in range 0->120 => 0.5 * Hue + 90 maps
		  // all values to (wrap-around) 180->60 range in Hue.

		  cvConvertScale(singleChannelH, singleChannelH, 0.5, 90);

      // put it all back together in RGB

		  cvMerge(singleChannelH, singleChannelPlain,
		  										singleChannelV, NULL, HSV);
		  cvCvtColor(HSV, HSV, CV_HSV2BGR);

		  // display image in window

			if (useConcatImage){
				imshow(windowNameHSV, concatImages(cv::cvarrToMat(img), cv::cvarrToMat(HSV)));
			} else {
				if (useFalseColour){
			  	cvShowImage(windowNameHSV, HSV);
				} else {
			    cvShowImage(windowNameHSV, img);
			  }
			}

		  // start event processing loop

		  key = cvWaitKey(EVENT_LOOP_DELAY);

		  // process any keyboard input

		  switch (tolower(key))
			{
				case  'x':

					// if user presses "x" then exit

	   				keepProcessing = false;
					;
					break;
				case  'a':

					// toggle automatic scaling

					useNormalisation = (!useNormalisation);

					;
					break;
			 	case  'b':

						// toggle concatenated images

						useConcatImage = (!useConcatImage);

						;
						break;
				case  'c':

					// toggle false colour

					useFalseColour = (!useFalseColour);

					;
					break;
			}

	  }

    // destroy window objects

	  cvDestroyAllWindows();

    // destroy image object (if it does not originate from a capture object)

    if (!capture){
		  cvReleaseImage( &img );
    }
	  cvReleaseImage( &HSV );
	  cvReleaseImage( &singleChannelH );
	  cvReleaseImage( &singleChannelPlain );

      // all OK : main returns 0

      return 0;
    }

    // not OK : main returns -1

	print_help(argv);
    return -1;
}
/******************************************************************************/
<commit_msg>code layout<commit_after>// irview : simple viewer for adding false colour to IR or thermal images
//          / video / camera feed
// usage: prog {image/video file}

// Author : Toby Breckon, toby.breckon@durham.ac.uk

// Copyright (c) 2008 School of Engineering, Cranfield University
// Copyright (c) 2017 School of Engineering and Computing Sciences, Durham University
// License : GPL - http://www.gnu.org/licenses/gpl.html

/******************************************************************************/

#define BUILD_FOR_OPENCV_3 1

#if (BUILD_FOR_OPENCV_3)

#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

#include <iostream>		// standard C++ I/O
#include <string>		// standard C++ I/O
#include <algorithm>    // includes max()

using namespace cv; // OpenCV API is in the C++ "cv" namespace
using namespace std;

#else

#include "cv.h"       // open cv general include file
#include "highgui.h"  // open cv GUI include file

#include <stdio.h>
#include <ctype.h>

#endif

/******************************************************************************/
// setup the camera index properly based on OS platform

// 0 in linux gives first camera for v4l
//-1 in windows gives first device or user dialog selection

#ifdef linux
	#define CAMERA_INDEX 0
#else
	#define CAMERA_INDEX -1
#endif
/******************************************************************************/

#define PROG_ID_STRING "IrView v0.2- (c) Toby Breckon, 2008-2017+"
#define LICENSE_STRING "GPL - http://www.gnu.org/licenses/gpl.html"

static void print_help(char **name){
	printf("\n%s\n", PROG_ID_STRING);
	printf ("\t with OpenCV version %s (%d.%d.%d)\n",
					CV_VERSION,
					CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
	printf("%s\n\n", LICENSE_STRING);

	printf("Usage :%s [image/video file]\n", name[0]);
	printf("Camera interface: run with no file agrument for direct camera use\n");
	printf("\nKeyboard commands\n");
	printf("\t a - automatic scaling (default: on)\n");
	printf("\t b - show both false colour and original (default: off)\n");
	printf("\t c - toggle false colour (default: on)\n");
	printf("\t x - exit\n\n");
}

/******************************************************************************/

// concatenate 2 OpenCV Mat Objects side-by-side (in general)

Mat concatImages(Mat img1, Mat img2)
{
		Mat out = Mat(img1.rows, img1.cols + img2.cols, img1.type());
		Mat roi = out(Rect(0, 0, img1.cols, img1.rows));
		Mat roi2 = out(Rect(img1.cols, 0, img2.cols, img2.rows));

		img1.copyTo(roi);

		// depth of img1 is master, depth of img2 is slave
		// so convert if needed

		if (img1.depth() != img2.depth())
		{
				// e.g. if img2 is 8-bit and img1 32-bit - scale to range 0->1 (32-bit)
				// otherwise img2 is 32-bit and img1 is 8-bit - scale to 0->255 (8-bit)

				img2.convertTo(roi2, img1.depth(), (img2.depth() < img1.depth()) ? 1.0 / 255.0 : 255);
		} else {
				img2.copyTo(roi2);
		}
		return out;
}

/******************************************************************************/

int main( int argc, char** argv )
{

	IplImage* img = NULL;      // image object
	CvCapture* capture = NULL; // capture object

	const char* windowNameHSV = PROG_ID_STRING; // window name

 	IplImage* HSV = NULL;					// HSV image
 	IplImage* singleChannelH = NULL;		// Hue plain (from input image)
 	IplImage* singleChannelPlain = NULL; 	// constant plane for S & V

	bool keepProcessing = true;		// loop control flag
	char key = '\0';				// user input
	int  EVENT_LOOP_DELAY = 40;     // 40ms equates to 1000ms/25fps =
									// 40ms per frame

	bool useFalseColour = true;     // process flag - false colour
	bool useNormalisation = true;   // process flag - normalisation
	bool useConcatImage = false; 		// process flag - show concatenated images

  // if command line arguments are provided try to read image/video_name
  // otherwise default to capture from attached H/W camera

    if(
	  ( argc == 2 && (img = cvLoadImage( argv[1], 1)) != 0 ) ||
	  ( argc == 2 && (capture = cvCreateFileCapture( argv[1] )) != 0 ) ||
	  ( argc != 2 && (capture = cvCreateCameraCapture( CAMERA_INDEX )) != 0 )
	  )
    {
      // print help

	  print_help(argv);

	  // create window object (use flag=0 to allow resize, 1 to auto fix size)

	  cvNamedWindow(windowNameHSV, 0);
	  cvResizeWindow(windowNameHSV, 640, 480);

	  // if capture object in use (i.e. video/camera)
	  // get initial image from capture object

	  if (capture) {

		  // cvQueryFrame s just a combination of cvGrabFrame
		  // and cvRetrieveFrame in one call.

		  img = cvQueryFrame(capture);
		  if(!img){
			if (argc == 2){
				printf("End of video file reached\n");
			} else {
				printf("ERROR: cannot get next frame from camera\n");
			}
			exit(0);
		  }

	  }

	  // setup output image in HSV

	  HSV = cvCloneImage(img);
	  singleChannelH =
	  			cvCreateImage(cvSize(img->width,img->height), IPL_DEPTH_8U, 1);
	  singleChannelH->origin = img->origin;
	  IplImage* singleChannelV =
	  			cvCreateImage(cvSize(img->width,img->height), IPL_DEPTH_8U, 1);
	  singleChannelV->origin = img->origin;

	  // set single channel up for Saturation / Variance

	  singleChannelPlain =
	  			cvCreateImage(cvSize(img->width,img->height), IPL_DEPTH_8U, 1);
	  singleChannelPlain->origin = img->origin;
	  cvSet(singleChannelPlain, cvScalar(255));

	  // start main loop

	  while (keepProcessing) {

		  // if capture object in use (i.e. video/camera)
		  // get image from capture object

		  if (capture) {

			  // cvQueryFrame is just a combination of cvGrabFrame
			  // and cvRetrieveFrame in one call.

			  img = cvQueryFrame(capture);

			  // cvQueryFrame s just a combination of cvGrabFrame
			  // and cvRetrieveFrame in one call.

			  if(!img){
					if (argc == 2){
						printf("End of video file reached\n");
					} else {
						printf("ERROR: cannot get next frame from camera\n");
					}
					exit(0);
			  }

		  }

		  // extract first (or only input image channel)

		  if (img->nChannels > 1) {
		  		cvSetImageCOI(img, 1); // select channel 1, 0 means all channels
		  }

		  // we will use this for the Hue and Variance channels

		  cvCopy(img, singleChannelH);
		  cvCopy(img, singleChannelV);
		  cvSetImageCOI(img, 0);

		  // do colour normalisation (makes it look more impressive)

		  if (useNormalisation){
		  	cvNormalize(singleChannelH, singleChannelH, 0, 255,
			  												CV_MINMAX, NULL);
				cvNormalize(singleChannelV, singleChannelV, 0, 255,
			  												CV_MINMAX, NULL);
		  }

		  // do scaling to avoid Hue space wrap around (i.e. dark == bright!)
		  // N.B. changing the scaling factor and addition will vary the colour
		  // effect - OpenCV 8-bit Hue in range 0->120 => 0.5 * Hue + 90 maps
		  // all values to (wrap-around) 180->60 range in Hue.

		  cvConvertScale(singleChannelH, singleChannelH, 0.5, 90);

			// put it all back together in RGB

		  cvMerge(singleChannelH, singleChannelPlain,	singleChannelV, NULL, HSV);
		  cvCvtColor(HSV, HSV, CV_HSV2BGR);

		  // display image in window

			if (useConcatImage){
				imshow(windowNameHSV, concatImages(cv::cvarrToMat(img), cv::cvarrToMat(HSV)));
			} else {
				if (useFalseColour){
			  	cvShowImage(windowNameHSV, HSV);
				} else {
			    cvShowImage(windowNameHSV, img);
			  }
			}

		  // start event processing loop

		  key = cvWaitKey(EVENT_LOOP_DELAY);

		  // process any keyboard input

		  switch (tolower(key))
			{
				case  'x':

					// if user presses "x" then exit

	   				keepProcessing = false;
					;
					break;
				case  'a':

					// toggle automatic scaling

					useNormalisation = (!useNormalisation);

					;
					break;
			 	case  'b':

					// toggle concatenated images

					useConcatImage = (!useConcatImage);

						;
						break;
				case  'c':

					// toggle false colour

					useFalseColour = (!useFalseColour);

					;
					break;
			}

	  }

    // destroy window objects

	  cvDestroyAllWindows();

    // destroy image object (if it does not originate from a capture object)

    if (!capture){
		  cvReleaseImage( &img );
    }
	  cvReleaseImage( &HSV );
	  cvReleaseImage( &singleChannelH );
	  cvReleaseImage( &singleChannelPlain );

      // all OK : main returns 0

      return 0;
    }

    // not OK : main returns -1

	print_help(argv);
    return -1;
}
/******************************************************************************/
<|endoftext|>


<commit_before>#include <list>

#include <Poco/AtomicCounter.h>
#include <Poco/Mutex.h>
#include <Poco/Runnable.h>
#include <Poco/Thread.h>
#include <Poco/Timestamp.h>

#include <cppunit/extensions/HelperMacros.h>

#include "cppunit/BetterAssert.h"

#include "work/BasicProcessor.h"
#include "work/Work.h"
#include "work/WorkExecutor.h"
#include "work/WorkLockManager.h"

using namespace Poco;

namespace BeeeOn {

class TestableBasicProcessor;

class BasicProcessorTest : public CppUnit::TestFixture {
	CPPUNIT_TEST_SUITE(BasicProcessorTest);
	CPPUNIT_TEST(testNoMoreThreads);
	CPPUNIT_TEST(testDispatchInterruptible);
	CPPUNIT_TEST(testDispatchFinishedWork);
	CPPUNIT_TEST(testNoMatchingExecutor);
	CPPUNIT_TEST_SUITE_END();
public:
	void setUp();
	void tearDown();

	void testNoMoreThreads();
	void testDispatchInterruptible();
	void testDispatchFinishedWork();
	void testNoMatchingExecutor();

private:
	TestableBasicProcessor *m_processor;
	WorkLockManager *m_lockManager;
};

CPPUNIT_TEST_SUITE_REGISTRATION(BasicProcessorTest);

class TestableBasicProcessor : public BasicProcessor {
public:
	using BasicProcessor::dispatch;
	using BasicProcessor::executeInThread;
	using BasicProcessor::pool;
};

class YieldingRunnable : public Poco::Runnable {
public:
	void run() override {
		while (!m_done)
			Thread::yield();
	}

	AtomicCounter m_done;
};

class NotAcceptingExecutor : public WorkExecutor {
public:
	bool accepts(const Work::Ptr) const override
	{
		return false;
	}

	void execute(Work::Ptr) override
	{
		throw Poco::AssertionViolationException("this must never be called");
	}
};

void BasicProcessorTest::setUp()
{
	m_lockManager = new WorkLockManager(31, 63);
	m_processor = new TestableBasicProcessor();
	m_processor->setLockManager(m_lockManager);
}

void BasicProcessorTest::tearDown()
{
	delete m_processor;
	delete m_lockManager;
}

/**
 * Test executeInThread returns false when no more threads
 * are available.
 */
void BasicProcessorTest::testNoMoreThreads()
{
	m_processor->setMinThreads(1);
	m_processor->setMaxThreads(1);

	YieldingRunnable runnable0;
	YieldingRunnable runnable1;

	CPPUNIT_ASSERT(m_processor->executeInThread(runnable0, "test0"));
	CPPUNIT_ASSERT(!m_processor->executeInThread(runnable1, "test1"));

	runnable0.m_done = 1;
	m_processor->pool().joinAll();
}

/**
 * Test that when the dispatch() method starts blocking due to an empty
 * queue, it can be interrupted by calling notify().
 */
void BasicProcessorTest::testDispatchInterruptible()
{
	NotAcceptingExecutor executor;
	m_processor->registerExecutor(&executor);

	Timestamp now;

	Thread t;
	t.startFunc(
		[&]() {
			Thread::sleep(100);
			m_processor->notify();
		}
	);

	CPPUNIT_ASSERT(now.elapsed() < 100000);
	m_processor->dispatch();
	CPPUNIT_ASSERT(now.elapsed() >= 100000);

	t.join();
}

/**
 * Assure there is no unexpected behaviour when
 * a finished work is encountered in the queue.
 */
void BasicProcessorTest::testDispatchFinishedWork()
{
	Work::Ptr work(new Work);

	m_processor->schedule(work);

	work->setFinished(work->created());
	CPPUNIT_ASSERT(Work::timestampValid(work->finished()));
	work->setState(Work::STATE_FINISHED);

	m_processor->dispatch();
}

void BasicProcessorTest::testNoMatchingExecutor()
{
	NotAcceptingExecutor executor;

	m_processor->registerExecutor(&executor);

	Work::Ptr work(new Work(WorkID::parse("8028bf15-51f7-4e12-af11-fc8cafc18917")));

	CPPUNIT_ASSERT(work->state() == Work::STATE_IDLE);

	m_processor->schedule(work);
	m_processor->dispatch();

	CPPUNIT_ASSERT(work->state() == Work::STATE_FAILED);
}

}
<commit_msg>BasicProcessorTest: fix destruction of WorkLockManager<commit_after>#include <list>

#include <Poco/AtomicCounter.h>
#include <Poco/Mutex.h>
#include <Poco/Runnable.h>
#include <Poco/Thread.h>
#include <Poco/Timestamp.h>

#include <cppunit/extensions/HelperMacros.h>

#include "cppunit/BetterAssert.h"

#include "work/BasicProcessor.h"
#include "work/Work.h"
#include "work/WorkExecutor.h"
#include "work/WorkLockManager.h"

using namespace Poco;

namespace BeeeOn {

class TestableBasicProcessor;

class BasicProcessorTest : public CppUnit::TestFixture {
	CPPUNIT_TEST_SUITE(BasicProcessorTest);
	CPPUNIT_TEST(testNoMoreThreads);
	CPPUNIT_TEST(testDispatchInterruptible);
	CPPUNIT_TEST(testDispatchFinishedWork);
	CPPUNIT_TEST(testNoMatchingExecutor);
	CPPUNIT_TEST_SUITE_END();
public:
	void setUp();
	void tearDown();

	void testNoMoreThreads();
	void testDispatchInterruptible();
	void testDispatchFinishedWork();
	void testNoMatchingExecutor();

private:
	TestableBasicProcessor *m_processor;
	WorkLockManager::Ptr m_lockManager;
};

CPPUNIT_TEST_SUITE_REGISTRATION(BasicProcessorTest);

class TestableBasicProcessor : public BasicProcessor {
public:
	using BasicProcessor::dispatch;
	using BasicProcessor::executeInThread;
	using BasicProcessor::pool;
};

class YieldingRunnable : public Poco::Runnable {
public:
	void run() override {
		while (!m_done)
			Thread::yield();
	}

	AtomicCounter m_done;
};

class NotAcceptingExecutor : public WorkExecutor {
public:
	bool accepts(const Work::Ptr) const override
	{
		return false;
	}

	void execute(Work::Ptr) override
	{
		throw Poco::AssertionViolationException("this must never be called");
	}
};

void BasicProcessorTest::setUp()
{
	m_lockManager = new WorkLockManager(31, 63);
	m_processor = new TestableBasicProcessor();
	m_processor->setLockManager(m_lockManager);
}

void BasicProcessorTest::tearDown()
{
	delete m_processor;
}

/**
 * Test executeInThread returns false when no more threads
 * are available.
 */
void BasicProcessorTest::testNoMoreThreads()
{
	m_processor->setMinThreads(1);
	m_processor->setMaxThreads(1);

	YieldingRunnable runnable0;
	YieldingRunnable runnable1;

	CPPUNIT_ASSERT(m_processor->executeInThread(runnable0, "test0"));
	CPPUNIT_ASSERT(!m_processor->executeInThread(runnable1, "test1"));

	runnable0.m_done = 1;
	m_processor->pool().joinAll();
}

/**
 * Test that when the dispatch() method starts blocking due to an empty
 * queue, it can be interrupted by calling notify().
 */
void BasicProcessorTest::testDispatchInterruptible()
{
	NotAcceptingExecutor executor;
	m_processor->registerExecutor(&executor);

	Timestamp now;

	Thread t;
	t.startFunc(
		[&]() {
			Thread::sleep(100);
			m_processor->notify();
		}
	);

	CPPUNIT_ASSERT(now.elapsed() < 100000);
	m_processor->dispatch();
	CPPUNIT_ASSERT(now.elapsed() >= 100000);

	t.join();
}

/**
 * Assure there is no unexpected behaviour when
 * a finished work is encountered in the queue.
 */
void BasicProcessorTest::testDispatchFinishedWork()
{
	Work::Ptr work(new Work);

	m_processor->schedule(work);

	work->setFinished(work->created());
	CPPUNIT_ASSERT(Work::timestampValid(work->finished()));
	work->setState(Work::STATE_FINISHED);

	m_processor->dispatch();
}

void BasicProcessorTest::testNoMatchingExecutor()
{
	NotAcceptingExecutor executor;

	m_processor->registerExecutor(&executor);

	Work::Ptr work(new Work(WorkID::parse("8028bf15-51f7-4e12-af11-fc8cafc18917")));

	CPPUNIT_ASSERT(work->state() == Work::STATE_IDLE);

	m_processor->schedule(work);
	m_processor->dispatch();

	CPPUNIT_ASSERT(work->state() == Work::STATE_FAILED);
}

}
<|endoftext|>


<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2019 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#include <miopen/conv/invokers/impl_gemm.hpp>
#include <miopen/conv/data_invoke_params.hpp>
#include <miopen/solver.hpp>
#include <miopen/handle.hpp>
#include <miopen/generic_search.hpp>
#include <miopen/solver/ck_utility_common.hpp>
#include <cstddef>

#include "../composable_kernel/host/solver/include/conv_igemm_fwd_v6r1_dlops_nchw_kcyx_nkhw.hpp"

MIOPEN_DECLARE_ENV_VAR(MIOPEN_DEBUG_CONV_CK_IGEMM_FWD_V6R1_DLOPS_NCHW)

namespace miopen {
namespace solver {
namespace ck_utility {

static inline auto get_ck_tunable_conv_igemm_fwd_v6r1_dlops_nchw_kcyx_nkhw(
    const PerformanceConvCkIgemmFwdV6r1DlopsNchw& config)
{
    return ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetTunableList()[config
                                                                               .ck_tunable_list_id];
}

} // namespace ck_utility

bool PerformanceConvCkIgemmFwdV6r1DlopsNchw::SetNextValue(const ConvolutionContext&)
{
    if(ck_tunable_list_id <
       ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetTunableList().size() - 1)
    {
        ck_tunable_list_id++;
        return true;
    }
    else
    {
        return false;
    }
}

bool PerformanceConvCkIgemmFwdV6r1DlopsNchw::IsValid(const ConvolutionContext& ctx) const
{
    auto compile_param = ck::driver::CompileParameterConvIgemmFwdV6r1DlopsNchwKcyxNkhw{};
    bool found         = false;

    std::tie(compile_param, found) =
        ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::CalculateCompileParameterBasedOnTunable(
            ck_utility::get_ck_convolution_problem_descriptor(ctx),
            ck_utility::get_ck_tunable_conv_igemm_fwd_v6r1_dlops_nchw_kcyx_nkhw(*this));

    if(!found)
        return false;

    return ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::IsValidCompileParameter(
        ck_utility::get_ck_convolution_problem_descriptor(ctx), compile_param);
}

bool ConvCkIgemmFwdV6r1DlopsNchw::IsApplicable(const ConvolutionContext& ctx) const
{
    if(miopen::IsDisabled(MIOPEN_DEBUG_CONV_CK_IGEMM_FWD_V6R1_DLOPS_NCHW{}))
        return false;
    if(!ctx.use_hip_kernels)
        return false;
    if(!ck_utility::is_ck_supported_hardware(ctx.GetStream()))
        return false;
    if(!ctx.IsLayoutDefault())
        return false;
    if(!ctx.direction.IsForward())
        return false;
    if(!ctx.Is2d())
        return false;
    if(!(ctx.IsFp32() or ctx.IsFp16()))
        return false;
    if(ctx.group_counts != 1)
        return false;

    {
        // this kernel use int32_t for memory offset, which covers 2GB of memory maximum
        const std::size_t max_index_range = std::size_t(2) * 1024 * 1024 * 1024;

        if(!(ctx.bot_sz < max_index_range && ctx.weights_sz < max_index_range &&
             ctx.top_sz < max_index_range))
            return false;
    }

    return ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::IsApplicable(
        ck_utility::get_ck_convolution_problem_descriptor(ctx));
}

PerformanceConvCkIgemmFwdV6r1DlopsNchw
ConvCkIgemmFwdV6r1DlopsNchw::GetPerformanceConfig(const ConvolutionContext& ctx) const
{
    for(int i = 0; i < ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetTunableList().size(); ++i)
    {
        if(IsValidPerformanceConfig(ctx, i))
        {
            return {i};
        }
    }

    MIOPEN_LOG_E("cannot find a valid performance config");

    return {-1};
}

bool ConvCkIgemmFwdV6r1DlopsNchw::IsValidPerformanceConfig(
    const ConvolutionContext& ctx, const PerformanceConvCkIgemmFwdV6r1DlopsNchw& config) const
{
    return config.IsValid(ctx);
}

ConvSolution ConvCkIgemmFwdV6r1DlopsNchw::GetSolution(
    const ConvolutionContext& ctx, const PerformanceConvCkIgemmFwdV6r1DlopsNchw& config, bool) const
{
    ConvSolution sol;
    KernelInfo kernel0_info, kernel1_info;

    const auto ck_conv_problem_desc = ck_utility::get_ck_convolution_problem_descriptor(ctx);

    auto ck_compile_param = ck::driver::CompileParameterConvIgemmFwdV6r1DlopsNchwKcyxNkhw{};

    std::tie(ck_compile_param, std::ignore) =
        ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::CalculateCompileParameterBasedOnTunable(
            ck_conv_problem_desc,
            ck_utility::get_ck_tunable_conv_igemm_fwd_v6r1_dlops_nchw_kcyx_nkhw(config));

    // kernel0: prepare
    {
        kernel0_info.kernel_file =
            "convolution_forward_implicit_gemm_v6r1_dlops_nchw_kcyx_nkhw.cpp";

        kernel0_info.kernel_name =
            "convolution_forward_implicit_gemm_v6r1_dlops_nchw_kcyx_nkhw_prepare";

        kernel0_info.l_wk = {1, 1, 1};
        kernel0_info.g_wk = {1, 1, 1};

        kernel0_info.comp_options = ck_compile_param.GetCompileParameterString() +
                                    ck_utility::get_ck_common_compiler_flag(ctx.GetStream());
    }

    // kernel1: compute
    {
        kernel1_info.kernel_file =
            "convolution_forward_implicit_gemm_v6r1_dlops_nchw_kcyx_nkhw.cpp";

        kernel1_info.kernel_name = "convolution_forward_implicit_gemm_v6r1_dlops_nchw_kcyx_nkhw";

        const auto block_size =
            std::size_t(ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetBlockSize(
                ck_conv_problem_desc, ck_compile_param));

        const auto grid_size =
            std::size_t(ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetGridSize(
                ck_conv_problem_desc, ck_compile_param));

        kernel1_info.l_wk = {block_size, 1, 1};
        kernel1_info.g_wk = {block_size * grid_size, 1, 1};

        kernel1_info.comp_options = ck_compile_param.GetCompileParameterString() +
                                    ck_utility::get_ck_common_compiler_flag(ctx.GetStream());
    }

    sol.construction_params.push_back(kernel0_info);
    sol.construction_params.push_back(kernel1_info);

    // workspace is used to save transformed tensor descriptors
    sol.workspce_sz = GetWorkspaceSize(ctx);

    sol.invoker_factory = [=](const std::vector<Kernel>& kernels) {
        return [=](const Handle& handle, const AnyInvokeParams& primitive_params) {
            const auto& data_ctx = primitive_params.CastTo<conv::DataInvokeParams>();
            const auto& tensors  = data_ctx.tensors;
            auto kernel0         = handle.Run(kernels[0]);
            auto kernel1         = handle.Run(kernels[1]);

            float elapsed = 0;

            // kernel for transforming tensor descriptors
            kernel0(ck_conv_problem_desc.N,
                    ck_conv_problem_desc.C,
                    ck_conv_problem_desc.Hi,
                    ck_conv_problem_desc.Wi,
                    ck_conv_problem_desc.K,
                    ck_conv_problem_desc.Y,
                    ck_conv_problem_desc.X,
                    ck_conv_problem_desc.ConvStrideH,
                    ck_conv_problem_desc.ConvStrideW,
                    ck_conv_problem_desc.ConvDilationH,
                    ck_conv_problem_desc.ConvDilationW,
                    ck_conv_problem_desc.InLeftPadH,
                    ck_conv_problem_desc.InLeftPadW,
                    ck_conv_problem_desc.InRightPadH,
                    ck_conv_problem_desc.InRightPadW,
                    data_ctx.workSpace);

            if(handle.IsProfilingEnabled())
            {
                elapsed += handle.GetKernelTime();
            }

            // kernel for computation
            kernel1(tensors.w, tensors.in, tensors.out, data_ctx.workSpace);

            if(handle.IsProfilingEnabled())
            {
                elapsed += handle.GetKernelTime();
                handle.ResetKernelTime();
                handle.AccumKernelTime(elapsed);
            }
        };
    };

    return sol;
}

std::size_t ConvCkIgemmFwdV6r1DlopsNchw::GetWorkspaceSize(const ConvolutionContext& ctx) const
{
    return ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetMaxWorkSpaceSize(
        ck_utility::get_ck_convolution_problem_descriptor(ctx));
}

PerformanceConvCkIgemmFwdV6r1DlopsNchw
ConvCkIgemmFwdV6r1DlopsNchw::Search(const ConvolutionContext& ctx,
                                    const AnyInvokeParams& invoke_ctx) const
{
    return GenericSearch(*this, ctx, invoke_ctx);
}

} // namespace solver
} // namespace miopen
<commit_msg>[HOTFIX][gfx90a][FP16] Disable ConvCkIgemmFwdV6r1DlopsNchw when "ALT FP16" kernel is required (#1320)<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2019 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#include <miopen/conv/invokers/impl_gemm.hpp>
#include <miopen/conv/data_invoke_params.hpp>
#include <miopen/solver.hpp>
#include <miopen/handle.hpp>
#include <miopen/generic_search.hpp>
#include <miopen/solver/ck_utility_common.hpp>
#include <cstddef>

#include "../composable_kernel/host/solver/include/conv_igemm_fwd_v6r1_dlops_nchw_kcyx_nkhw.hpp"

MIOPEN_DECLARE_ENV_VAR(MIOPEN_DEBUG_CONV_CK_IGEMM_FWD_V6R1_DLOPS_NCHW)

namespace miopen {
namespace solver {
namespace ck_utility {

static inline auto get_ck_tunable_conv_igemm_fwd_v6r1_dlops_nchw_kcyx_nkhw(
    const PerformanceConvCkIgemmFwdV6r1DlopsNchw& config)
{
    return ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetTunableList()[config
                                                                               .ck_tunable_list_id];
}

} // namespace ck_utility

bool PerformanceConvCkIgemmFwdV6r1DlopsNchw::SetNextValue(const ConvolutionContext&)
{
    if(ck_tunable_list_id <
       ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetTunableList().size() - 1)
    {
        ck_tunable_list_id++;
        return true;
    }
    else
    {
        return false;
    }
}

bool PerformanceConvCkIgemmFwdV6r1DlopsNchw::IsValid(const ConvolutionContext& ctx) const
{
    auto compile_param = ck::driver::CompileParameterConvIgemmFwdV6r1DlopsNchwKcyxNkhw{};
    bool found         = false;

    std::tie(compile_param, found) =
        ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::CalculateCompileParameterBasedOnTunable(
            ck_utility::get_ck_convolution_problem_descriptor(ctx),
            ck_utility::get_ck_tunable_conv_igemm_fwd_v6r1_dlops_nchw_kcyx_nkhw(*this));

    if(!found)
        return false;

    return ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::IsValidCompileParameter(
        ck_utility::get_ck_convolution_problem_descriptor(ctx), compile_param);
}

bool ConvCkIgemmFwdV6r1DlopsNchw::IsApplicable(const ConvolutionContext& ctx) const
{
    if(miopen::IsDisabled(MIOPEN_DEBUG_CONV_CK_IGEMM_FWD_V6R1_DLOPS_NCHW{}))
        return false;
    if(!ctx.use_hip_kernels)
        return false;
    if(!ck_utility::is_ck_supported_hardware(ctx.GetStream()))
        return false;
    if(!ctx.IsLayoutDefault())
        return false;
    if(!ctx.direction.IsForward())
        return false;
    if(!ctx.Is2d())
        return false;
    if(!(ctx.IsFp32() or ctx.IsFp16()))
        return false;
    if(ctx.group_counts != 1)
        return false;
    if(ctx.GetStream().GetTargetProperties().Name() == "gfx90a" &&
       ctx.conv_problem.IsGfx90aFp16altRequired())
        return false;

    {
        // this kernel use int32_t for memory offset, which covers 2GB of memory maximum
        const std::size_t max_index_range = std::size_t(2) * 1024 * 1024 * 1024;

        if(!(ctx.bot_sz < max_index_range && ctx.weights_sz < max_index_range &&
             ctx.top_sz < max_index_range))
            return false;
    }

    return ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::IsApplicable(
        ck_utility::get_ck_convolution_problem_descriptor(ctx));
}

PerformanceConvCkIgemmFwdV6r1DlopsNchw
ConvCkIgemmFwdV6r1DlopsNchw::GetPerformanceConfig(const ConvolutionContext& ctx) const
{
    for(int i = 0; i < ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetTunableList().size(); ++i)
    {
        if(IsValidPerformanceConfig(ctx, i))
        {
            return {i};
        }
    }

    MIOPEN_LOG_E("cannot find a valid performance config");

    return {-1};
}

bool ConvCkIgemmFwdV6r1DlopsNchw::IsValidPerformanceConfig(
    const ConvolutionContext& ctx, const PerformanceConvCkIgemmFwdV6r1DlopsNchw& config) const
{
    return config.IsValid(ctx);
}

ConvSolution ConvCkIgemmFwdV6r1DlopsNchw::GetSolution(
    const ConvolutionContext& ctx, const PerformanceConvCkIgemmFwdV6r1DlopsNchw& config, bool) const
{
    ConvSolution sol;
    KernelInfo kernel0_info, kernel1_info;

    const auto ck_conv_problem_desc = ck_utility::get_ck_convolution_problem_descriptor(ctx);

    auto ck_compile_param = ck::driver::CompileParameterConvIgemmFwdV6r1DlopsNchwKcyxNkhw{};

    std::tie(ck_compile_param, std::ignore) =
        ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::CalculateCompileParameterBasedOnTunable(
            ck_conv_problem_desc,
            ck_utility::get_ck_tunable_conv_igemm_fwd_v6r1_dlops_nchw_kcyx_nkhw(config));

    // kernel0: prepare
    {
        kernel0_info.kernel_file =
            "convolution_forward_implicit_gemm_v6r1_dlops_nchw_kcyx_nkhw.cpp";

        kernel0_info.kernel_name =
            "convolution_forward_implicit_gemm_v6r1_dlops_nchw_kcyx_nkhw_prepare";

        kernel0_info.l_wk = {1, 1, 1};
        kernel0_info.g_wk = {1, 1, 1};

        kernel0_info.comp_options = ck_compile_param.GetCompileParameterString() +
                                    ck_utility::get_ck_common_compiler_flag(ctx.GetStream());
    }

    // kernel1: compute
    {
        kernel1_info.kernel_file =
            "convolution_forward_implicit_gemm_v6r1_dlops_nchw_kcyx_nkhw.cpp";

        kernel1_info.kernel_name = "convolution_forward_implicit_gemm_v6r1_dlops_nchw_kcyx_nkhw";

        const auto block_size =
            std::size_t(ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetBlockSize(
                ck_conv_problem_desc, ck_compile_param));

        const auto grid_size =
            std::size_t(ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetGridSize(
                ck_conv_problem_desc, ck_compile_param));

        kernel1_info.l_wk = {block_size, 1, 1};
        kernel1_info.g_wk = {block_size * grid_size, 1, 1};

        kernel1_info.comp_options = ck_compile_param.GetCompileParameterString() +
                                    ck_utility::get_ck_common_compiler_flag(ctx.GetStream());
    }

    sol.construction_params.push_back(kernel0_info);
    sol.construction_params.push_back(kernel1_info);

    // workspace is used to save transformed tensor descriptors
    sol.workspce_sz = GetWorkspaceSize(ctx);

    sol.invoker_factory = [=](const std::vector<Kernel>& kernels) {
        return [=](const Handle& handle, const AnyInvokeParams& primitive_params) {
            const auto& data_ctx = primitive_params.CastTo<conv::DataInvokeParams>();
            const auto& tensors  = data_ctx.tensors;
            auto kernel0         = handle.Run(kernels[0]);
            auto kernel1         = handle.Run(kernels[1]);

            float elapsed = 0;

            // kernel for transforming tensor descriptors
            kernel0(ck_conv_problem_desc.N,
                    ck_conv_problem_desc.C,
                    ck_conv_problem_desc.Hi,
                    ck_conv_problem_desc.Wi,
                    ck_conv_problem_desc.K,
                    ck_conv_problem_desc.Y,
                    ck_conv_problem_desc.X,
                    ck_conv_problem_desc.ConvStrideH,
                    ck_conv_problem_desc.ConvStrideW,
                    ck_conv_problem_desc.ConvDilationH,
                    ck_conv_problem_desc.ConvDilationW,
                    ck_conv_problem_desc.InLeftPadH,
                    ck_conv_problem_desc.InLeftPadW,
                    ck_conv_problem_desc.InRightPadH,
                    ck_conv_problem_desc.InRightPadW,
                    data_ctx.workSpace);

            if(handle.IsProfilingEnabled())
            {
                elapsed += handle.GetKernelTime();
            }

            // kernel for computation
            kernel1(tensors.w, tensors.in, tensors.out, data_ctx.workSpace);

            if(handle.IsProfilingEnabled())
            {
                elapsed += handle.GetKernelTime();
                handle.ResetKernelTime();
                handle.AccumKernelTime(elapsed);
            }
        };
    };

    return sol;
}

std::size_t ConvCkIgemmFwdV6r1DlopsNchw::GetWorkspaceSize(const ConvolutionContext& ctx) const
{
    return ck::driver::ConvIgemmFwdV6r1DlopsNchwKcyxNkhw::GetMaxWorkSpaceSize(
        ck_utility::get_ck_convolution_problem_descriptor(ctx));
}

PerformanceConvCkIgemmFwdV6r1DlopsNchw
ConvCkIgemmFwdV6r1DlopsNchw::Search(const ConvolutionContext& ctx,
                                    const AnyInvokeParams& invoke_ctx) const
{
    return GenericSearch(*this, ctx, invoke_ctx);
}

} // namespace solver
} // namespace miopen
<|endoftext|>


<commit_before>// 湍流游戏

#include "BuildingScene.h"
#include "uiconf.h"
#include "EditState.h"
#include "format.h"
#include "Msg.h"
#include "../rapidjson/rapidjson.h"
#include "../rapidjson/document.h"
#include "../rapidjson/writer.h"
#include "../rapidjson/stringbuffer.h"
#include "../rapidjson/filereadstream.h"

#include <cstdio>
#include <vector>

#include <sys/stat.h> //mkdir

USING_NS_CC;

class StateInfoLayer: public McdLayer
{
public:
    virtual bool init() override {
        assert(McdLayer::init());

        _lbUnitFile = Label::createWithTTF(EditState::s()->getExtraUnitFilePath(), uic::font_zh, 14);
        _lbUnitFile->setPosition(genPos({0.5f, 0.95f}));
        this->addChild(_lbUnitFile);

        schedule(schedule_selector(StateInfoLayer::onUpdateState), 0.33f, kRepeatForever, 0);

        return true;
    }
    CREATE_FUNC(StateInfoLayer);

private:
    Label* _lbUnitFile;

    void onUpdateState(float dt) {
        _lbUnitFile->setString(EditState::s()->getExtraUnitFilePath());
    }

};

bool BuildingScene::init()
{
    assert(TRBaseScene::init());

    this->addChild(StateInfoLayer::create());

    reloadMetaCubes();

    return true;
}

void BuildingScene::reloadMetaCubes()
{
    FILE* fp = fopen(EditState::s()->getCubeMetaFilePath().c_str(), "r"); // TODO if Windows using "rb"

    if (fp == NULL) {
        CCLOG("Metacubes not exists, copy template workspace there.");
        copyTemplateWorkspace();
        // reopen
        fp = fopen(EditState::s()->getCubeMetaFilePath().c_str(), "r");
    }

    assert(fp != NULL);

    char readBuffer[65536];
    rjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer));

    rjson::Document doc;
    doc.ParseStream(is);
    fclose(fp);

    //
}

void BuildingScene::copyTemplateWorkspace()
{
    auto fileListString = FileUtils::getInstance()->getStringFromFile("MicroCube/filelist.json");
    CCLOG(fileListString.c_str());
    rjson::Document doc;
    doc.Parse(fileListString.c_str());
    std::vector<std::string> dirs;
    std::vector<std::string> files;
    auto& dirlist = doc["directories"];
    for (auto iter = dirlist.Begin(); iter != dirlist.End(); iter++) {
        std::string str = iter->GetString();
        CCLOG(str.c_str());
        dirs.push_back(str);
    }
    auto& filelist = doc["files"];
    for (auto iter = filelist.Begin(); iter != filelist.End(); iter++) {
        std::string str = iter->GetString();
        CCLOG(str.c_str());
        files.push_back(str);
    }
    // create base dir
    mkdir(EditState::s()->getBasePath().c_str(), 0777);
    for (int i = 0; i < dirs.size(); i++) {
        std::string dst = EditState::s()->getBasePath()+dirs[i];
        mkdir(dst.c_str(), 0777);
    }
    for (int i = 0; i < files.size(); i++) {
        auto data = FileUtils::getInstance()->getDataFromFile("MicroCube/" + files[i]);
        std::string dst = EditState::s()->getBasePath()+files[i];
        CCLOG(dst.c_str());
        FILE* fp = fopen((EditState::s()->getBasePath()+files[i]).c_str(), "w");
        assert(fp != NULL);
        fwrite(data.getBytes(), sizeof(unsigned char), data.getSize(), fp);
        fclose(fp);
    }
}

<commit_msg>fix warnings<commit_after>// 湍流游戏

#include "BuildingScene.h"
#include "uiconf.h"
#include "EditState.h"
#include "format.h"
#include "Msg.h"
#include "../rapidjson/rapidjson.h"
#include "../rapidjson/document.h"
#include "../rapidjson/writer.h"
#include "../rapidjson/stringbuffer.h"
#include "../rapidjson/filereadstream.h"

#include <cstdio>
#include <vector>

#include <sys/stat.h> //mkdir

USING_NS_CC;

class StateInfoLayer: public McdLayer
{
public:
    virtual bool init() override {
        assert(McdLayer::init());

        _lbUnitFile = Label::createWithTTF(EditState::s()->getExtraUnitFilePath(), uic::font_zh, 14);
        _lbUnitFile->setPosition(genPos({0.5f, 0.95f}));
        this->addChild(_lbUnitFile);

        schedule(schedule_selector(StateInfoLayer::onUpdateState), 0.33f, kRepeatForever, 0);

        return true;
    }
    CREATE_FUNC(StateInfoLayer);

private:
    Label* _lbUnitFile;

    void onUpdateState(float dt) {
        _lbUnitFile->setString(EditState::s()->getExtraUnitFilePath());
    }

};

bool BuildingScene::init()
{
    assert(TRBaseScene::init());

    this->addChild(StateInfoLayer::create());

    reloadMetaCubes();

    return true;
}

void BuildingScene::reloadMetaCubes()
{
    FILE* fp = fopen(EditState::s()->getCubeMetaFilePath().c_str(), "r"); // TODO if Windows using "rb"

    if (fp == NULL) {
        CCLOG("Metacubes not exists, copy template workspace there.");
        copyTemplateWorkspace();
        // reopen
        fp = fopen(EditState::s()->getCubeMetaFilePath().c_str(), "r");
    }

    assert(fp != NULL);

    char readBuffer[65536];
    rjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer));

    rjson::Document doc;
    doc.ParseStream(is);
    fclose(fp);

    //
}

void BuildingScene::copyTemplateWorkspace()
{
    auto fileListString = FileUtils::getInstance()->getStringFromFile("MicroCube/filelist.json");
    CCLOG("%s", fileListString.c_str());
    rjson::Document doc;
    doc.Parse(fileListString.c_str());
    std::vector<std::string> dirs;
    std::vector<std::string> files;
    auto& dirlist = doc["directories"];
    for (auto iter = dirlist.Begin(); iter != dirlist.End(); iter++) {
        std::string str = iter->GetString();
        CCLOG("%s", str.c_str());
        dirs.push_back(str);
    }
    auto& filelist = doc["files"];
    for (auto iter = filelist.Begin(); iter != filelist.End(); iter++) {
        std::string str = iter->GetString();
        CCLOG("%s", str.c_str());
        files.push_back(str);
    }
    // create base dir
    mkdir(EditState::s()->getBasePath().c_str(), 0777);
    for (int i = 0; i < dirs.size(); i++) {
        std::string dst = EditState::s()->getBasePath()+dirs[i];
        mkdir(dst.c_str(), 0777);
    }
    for (int i = 0; i < files.size(); i++) {
        auto data = FileUtils::getInstance()->getDataFromFile("MicroCube/" + files[i]);
        std::string dst = EditState::s()->getBasePath()+files[i];
        CCLOG("%s", dst.c_str());
        FILE* fp = fopen((EditState::s()->getBasePath()+files[i]).c_str(), "w");
        assert(fp != NULL);
        fwrite(data.getBytes(), sizeof(unsigned char), data.getSize(), fp);
        fclose(fp);
    }
}

<|endoftext|>