<commit_before>#include <stdio.h>

#include "tostring.hpp"
#include "gui/deploywindow.hpp"
#include "gui/texturemanager.hpp"
#include "gui/guihandler.hpp"
#include "gui/cursor.hpp"

namespace qrw
{
	DeployWindow::DeployWindow(Engine* engine, GuiHandler* guihandler,
		IngameWindow* ingamewindow)
	: visible(false),
	  engine(engine),
	  ingamewindow(ingamewindow),
	  buttongroup(new ButtonGroup()),
	  startbutton(new Button(guihandler->getRenderWindow())),
	  defaultfont(new sf::Font()),
	  title(new sf::Text())
	{
		defaultfont->loadFromFile("./res/font/Knigqst.ttf");
		title->setFont(*defaultfont);
		title->setString("Deployment");
		title->setPosition(630, 0);

		TextureManager* texturemgr = TextureManager::getInstance();
		for(int i = 0; i < BUTTONCOUNT; ++i)
		{
			radiobuttons[i] = new RadioToggleButton(
				guihandler->getRenderWindow(), buttongroup);
			radiobuttons[i]->setScale(1.5, 1.5);

			// Set positions
			float x = 650;
			float y = 35 + i * 50;
			radiobuttons[i]->setPosition(x, y);
		}
		radiobuttons[0]->setTextures(texturemgr->getTexture("p1swordman"),
			texturemgr->getTexture("p1swordman"),
			texturemgr->getTexture("p1swordman"));
		radiobuttons[1]->setTextures(texturemgr->getTexture("p1archer"),
			texturemgr->getTexture("p1archer"),
			texturemgr->getTexture("p1archer"));
		radiobuttons[2]->setTextures(texturemgr->getTexture("p1spearman"),
			texturemgr->getTexture("p1spearman"),
			texturemgr->getTexture("p1spearman"));
		radiobuttons[3]->setTextures(texturemgr->getTexture("p2swordman"),
			texturemgr->getTexture("p2swordman"),
			texturemgr->getTexture("p2swordman"));
		radiobuttons[4]->setTextures(texturemgr->getTexture("p2archer"),
			texturemgr->getTexture("p2archer"),
			texturemgr->getTexture("p2archer"));
		radiobuttons[5]->setTextures(texturemgr->getTexture("p2spearman"),
			texturemgr->getTexture("p2spearman"),
			texturemgr->getTexture("p2spearman"));
		radiobuttons[6]->setTextures(texturemgr->getTexture("wood"),
			texturemgr->getTexture("wood"),
			texturemgr->getTexture("wood"));
		radiobuttons[6]->setText("Wood");
		radiobuttons[7]->setTextures(texturemgr->getTexture("hill"),
			texturemgr->getTexture("hill"),
			texturemgr->getTexture("hill"));
		radiobuttons[7]->setText("Hill");
		radiobuttons[8]->setTextures(texturemgr->getTexture("wall"),
			texturemgr->getTexture("wall"),
			texturemgr->getTexture("wall"));
		radiobuttons[8]->setText("Tower");

		startbutton->setTextures(texturemgr->getTexture("startbutton"),
			texturemgr->getTexture("startbutton"),
			texturemgr->getTexture("startbutton"));
		startbutton->setPosition(sf::Vector2f(650, 560));
		startbutton->signalclicked.connect(
			std::bind(&DeployWindow::startbuttonClicked, this));
	}

	DeployWindow::~DeployWindow()
	{
		delete startbutton;
		delete defaultfont;
		delete title;
	}

	void DeployWindow::setVisible(bool visible)
	{
		this->visible = visible;
		for(int i = 0; i < BUTTONCOUNT; ++i)
			radiobuttons[i]->updateSprite();
		startbutton->updateSprite();
	}

	void DeployWindow::draw(sf::RenderTarget& target,
		sf::RenderStates states) const
	{
		if(visible == false)
			return;

		for(int i = 0; i < BUTTONCOUNT; ++i)
			radiobuttons[i]->renderTo(target);

		target.draw(*title);
		target.draw(*startbutton);
	}

	void DeployWindow::update()
	{
		// Set player info text
		std::string text;
		for(int i = 0; i < 2 * EUT_NUMBEROFUNITTYPES; ++i)
		{
			text = "(" + intToString(
				engine->getPlayer(i / EUT_NUMBEROFUNITTYPES)
				->getNumberOfUnits()[i % EUT_NUMBEROFUNITTYPES])
			+ " / " + intToString(playerunits[i]) + ")";
			radiobuttons[i]->setText(text);
		}
	}

	void DeployWindow::setPlayerUnits(int playerunits[])
	{
		for(int i = 0; i < 2 * EUT_NUMBEROFUNITTYPES; ++i)
		{
			this->playerunits[i] = playerunits[i];
		}
	}

	void DeployWindow::handleEvent(const sf::Event& event)
	{
		if(visible == false)
			return;

		if(event.type == sf::Event::KeyPressed)
		{
			if(event.key.code == sf::Keyboard::Return)
			{
				placeEntity();
			}
			return;
		}
		for(int i = 0; i < BUTTONCOUNT; ++i)
			radiobuttons[i]->handleEvent(event);
		startbutton->handleEvent(event);
	}

	void DeployWindow::startbuttonClicked()
	{
		if(engine->getStatus() == EES_PREPARE)
		{
			engine->startGame();
			ingamewindow->setVisible(true);
			setVisible(false);
		}
	}

	void DeployWindow::placeEntity()
	{
		printf("place entity\n");
		// get active button
		int activebuttonid = 0;
		for(activebuttonid = 0;
			activebuttonid < BUTTONCOUNT;
			 ++activebuttonid)
		{
			if(radiobuttons[activebuttonid]->getState() == Button::ES_ACTIVE)
				break;
		}

		// Get cursor position
		Cursor* cursor = Cursor::getCursor();
		int x = cursor->getPosition().x;
		int y = cursor->getPosition().y;

		// Place unit
		if(activebuttonid >= 0 && activebuttonid < 2 * EUT_NUMBEROFUNITTYPES)
		{
			int playerid = activebuttonid / EUT_NUMBEROFUNITTYPES;
			Player* player = engine->getPlayer(playerid);
			UNITTYPES unittype = (UNITTYPES)(activebuttonid % EUT_NUMBEROFUNITTYPES);

			// Check if all units have been placed
			if(player->getNumberOfUnits()[unittype] >= playerunits[activebuttonid])
				return;

			engine->placeUnit(x, y, playerid, unittype);
			update();
		}
		// Place terrain
		else
		{
			TERRAINTYPES terraintype = (TERRAINTYPES)(activebuttonid
				- (2 * EUT_NUMBEROFUNITTYPES));
			engine->placeTerrain(x, y, terraintype);
		}
	}

	void DeployWindow::moveUnit()
	{
		printf("move unit\n");
	}
}<commit_msg>DeployWindow now handles user input to move units. moveUnit not implemented yet!<commit_after>#include <stdio.h>

#include "tostring.hpp"
#include "gui/deploywindow.hpp"
#include "gui/texturemanager.hpp"
#include "gui/guihandler.hpp"
#include "gui/cursor.hpp"

namespace qrw
{
	DeployWindow::DeployWindow(Engine* engine, GuiHandler* guihandler,
		IngameWindow* ingamewindow)
	: visible(false),
	  engine(engine),
	  ingamewindow(ingamewindow),
	  buttongroup(new ButtonGroup()),
	  startbutton(new Button(guihandler->getRenderWindow())),
	  defaultfont(new sf::Font()),
	  title(new sf::Text())
	{
		defaultfont->loadFromFile("./res/font/Knigqst.ttf");
		title->setFont(*defaultfont);
		title->setString("Deployment");
		title->setPosition(630, 0);

		TextureManager* texturemgr = TextureManager::getInstance();
		for(int i = 0; i < BUTTONCOUNT; ++i)
		{
			radiobuttons[i] = new RadioToggleButton(
				guihandler->getRenderWindow(), buttongroup);
			radiobuttons[i]->setScale(1.5, 1.5);

			// Set positions
			float x = 650;
			float y = 35 + i * 50;
			radiobuttons[i]->setPosition(x, y);
		}
		radiobuttons[0]->setTextures(texturemgr->getTexture("p1swordman"),
			texturemgr->getTexture("p1swordman"),
			texturemgr->getTexture("p1swordman"));
		radiobuttons[1]->setTextures(texturemgr->getTexture("p1archer"),
			texturemgr->getTexture("p1archer"),
			texturemgr->getTexture("p1archer"));
		radiobuttons[2]->setTextures(texturemgr->getTexture("p1spearman"),
			texturemgr->getTexture("p1spearman"),
			texturemgr->getTexture("p1spearman"));
		radiobuttons[3]->setTextures(texturemgr->getTexture("p2swordman"),
			texturemgr->getTexture("p2swordman"),
			texturemgr->getTexture("p2swordman"));
		radiobuttons[4]->setTextures(texturemgr->getTexture("p2archer"),
			texturemgr->getTexture("p2archer"),
			texturemgr->getTexture("p2archer"));
		radiobuttons[5]->setTextures(texturemgr->getTexture("p2spearman"),
			texturemgr->getTexture("p2spearman"),
			texturemgr->getTexture("p2spearman"));
		radiobuttons[6]->setTextures(texturemgr->getTexture("wood"),
			texturemgr->getTexture("wood"),
			texturemgr->getTexture("wood"));
		radiobuttons[6]->setText("Wood");
		radiobuttons[7]->setTextures(texturemgr->getTexture("hill"),
			texturemgr->getTexture("hill"),
			texturemgr->getTexture("hill"));
		radiobuttons[7]->setText("Hill");
		radiobuttons[8]->setTextures(texturemgr->getTexture("wall"),
			texturemgr->getTexture("wall"),
			texturemgr->getTexture("wall"));
		radiobuttons[8]->setText("Tower");

		startbutton->setTextures(texturemgr->getTexture("startbutton"),
			texturemgr->getTexture("startbutton"),
			texturemgr->getTexture("startbutton"));
		startbutton->setPosition(sf::Vector2f(650, 560));
		startbutton->signalclicked.connect(
			std::bind(&DeployWindow::startbuttonClicked, this));
	}

	DeployWindow::~DeployWindow()
	{
		delete startbutton;
		delete defaultfont;
		delete title;
	}

	void DeployWindow::setVisible(bool visible)
	{
		this->visible = visible;
		for(int i = 0; i < BUTTONCOUNT; ++i)
			radiobuttons[i]->updateSprite();
		startbutton->updateSprite();
	}

	void DeployWindow::draw(sf::RenderTarget& target,
		sf::RenderStates states) const
	{
		if(visible == false)
			return;

		for(int i = 0; i < BUTTONCOUNT; ++i)
			radiobuttons[i]->renderTo(target);

		target.draw(*title);
		target.draw(*startbutton);
	}

	void DeployWindow::update()
	{
		// Set player info text
		std::string text;
		for(int i = 0; i < 2 * EUT_NUMBEROFUNITTYPES; ++i)
		{
			text = "(" + intToString(
				engine->getPlayer(i / EUT_NUMBEROFUNITTYPES)
				->getNumberOfUnits()[i % EUT_NUMBEROFUNITTYPES])
			+ " / " + intToString(playerunits[i]) + ")";
			radiobuttons[i]->setText(text);
		}
	}

	void DeployWindow::setPlayerUnits(int playerunits[])
	{
		for(int i = 0; i < 2 * EUT_NUMBEROFUNITTYPES; ++i)
		{
			this->playerunits[i] = playerunits[i];
		}
	}

	void DeployWindow::handleEvent(const sf::Event& event)
	{
		if(visible == false)
			return;

		if(event.type == sf::Event::KeyPressed)
		{
			if(event.key.code == sf::Keyboard::Return)
			{
				Cursor* cursor = Cursor::getCursor();

				// Check if a new unit is placed or a unit is moved.
				// A unit is moved if cursor has a child (to point to destination)
				// or there is a unit under cursor.
				Square* cursorsquare = engine->getBoard()->getSquare(cursor->getPosition().x,
						cursor->getPosition().y);
				if (cursor->getChild() != NULL)
				{
					moveUnit();
				}
				else if(cursorsquare->getUnit() != NULL)
				{
					cursor->spawnChild();
				}
				else
				{
					placeEntity();
				}
			}
			return;
		}
		for(int i = 0; i < BUTTONCOUNT; ++i)
			radiobuttons[i]->handleEvent(event);
		startbutton->handleEvent(event);
	}

	void DeployWindow::startbuttonClicked()
	{
		if(engine->getStatus() == EES_PREPARE)
		{
			engine->startGame();
			ingamewindow->setVisible(true);
			setVisible(false);
		}
	}

	void DeployWindow::placeEntity()
	{
		printf("place entity\n");
		// get active button
		int activebuttonid = 0;
		for(activebuttonid = 0;
			activebuttonid < BUTTONCOUNT;
			 ++activebuttonid)
		{
			if(radiobuttons[activebuttonid]->getState() == Button::ES_ACTIVE)
				break;
		}

		// Get cursor position
		Cursor* cursor = Cursor::getCursor();
		int x = cursor->getPosition().x;
		int y = cursor->getPosition().y;

		// Place unit
		if(activebuttonid >= 0 && activebuttonid < 2 * EUT_NUMBEROFUNITTYPES)
		{
			int playerid = activebuttonid / EUT_NUMBEROFUNITTYPES;
			Player* player = engine->getPlayer(playerid);
			UNITTYPES unittype = (UNITTYPES)(activebuttonid % EUT_NUMBEROFUNITTYPES);

			// Check if all units have been placed
			if(player->getNumberOfUnits()[unittype] >= playerunits[activebuttonid])
				return;

			engine->placeUnit(x, y, playerid, unittype);
			update();
		}
		// Place terrain
		else
		{
			TERRAINTYPES terraintype = (TERRAINTYPES)(activebuttonid
				- (2 * EUT_NUMBEROFUNITTYPES));
			engine->placeTerrain(x, y, terraintype);
		}
	}

	void DeployWindow::moveUnit()
	{
		printf("move unit\n");
	}
}<|endoftext|>


<commit_before><commit_msg>gtk3: fix colors for menubar and menu items<commit_after><|endoftext|>


<commit_before>#include "config.h"

#include <iostream>
#include <string>
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
#include <pybind11/stl.h>
#include <c2py/c2py.hpp>

#include "module.hpp"
#include "generated_functions.h"

#include "iTapTradeAPI.h"
#include "TapQuoteAPI.h"
#include "TapAPIError.h"
#include "iTapAPIError.h"
#include "custom/custom_wrappers.hpp"

c2py::cross_assign module_vntap::cross;
c2py::object_store module_vntap::objects;

void additional_init(pybind11::module &m)
{
    c2py::additional_init<tag_vntap>::init(m);
}

void init_dispatcher(pybind11::module &m)
{
    m.def("set_async_callback_exception_handler", &c2py::async_callback_exception_handler::set_handler);

    // maybe module_local is unnecessary
    pybind11::class_<c2py::async_dispatch_exception> c(m, "AsyncDispatchException", pybind11::module_local());
    c.def_property_readonly("what", &c2py::async_dispatch_exception::what_mutable);
    c.def_readonly("instance", &c2py::async_dispatch_exception::instance);
    c.def_readonly("function_name", &c2py::async_dispatch_exception::function_name);

    c2py::dispatcher::instance().start();
}

PYBIND11_MODULE(vntap, m)
{
    generate_vntap(m);

    module_vntap::process_post_assign();

    additional_init(m);
    init_dispatcher(m);
}
<commit_msg>Delete module.cpp<commit_after><|endoftext|>


<commit_before>#pragma once

#include <agency/future.hpp>
#include <agency/detail/type_traits.hpp>
#include <agency/detail/bind.hpp>
#include <agency/execution_categories.hpp>
#include <agency/detail/tuple.hpp>
#include <agency/detail/shape_cast.hpp>
#include <agency/new_executor_traits.hpp>

namespace agency
{
namespace detail
{

__DEFINE_HAS_NESTED_TYPE(has_index_type, index_type);
__DEFINE_HAS_NESTED_TYPE(has_shape_type, shape_type);
__DEFINE_HAS_NESTED_TYPE(has_execution_category, execution_category);
__DEFINE_HAS_NESTED_CLASS_TEMPLATE(has_future_template, future);

template<class T>
struct nested_index_type
{
  using type = typename T::index_type;
};

template<class T, class Default = size_t>
struct nested_index_type_with_default
  : agency::detail::lazy_conditional<
      agency::detail::has_index_type<T>::value,
      nested_index_type<T>,
      agency::detail::identity<Default>
    >
{};

template<class T>
struct nested_shape_type
{
  using type = typename T::shape_type;
};

template<class T, class Default = size_t>
struct nested_shape_type_with_default
  : agency::detail::lazy_conditional<
      agency::detail::has_shape_type<T>::value,
      nested_shape_type<T>,
      agency::detail::identity<Default>
    >
{};

template<class T>
struct nested_future_template
{
  template<class U>
  using type_template = typename T::template future<U>;
};

template<bool condition, class Then, class Else>
struct lazy_conditional_template
{
  template<class T>
  using type_template = typename Then::template type_template<T>;
};

template<class Then, class Else>
struct lazy_conditional_template<false, Then, Else>
{
  template<class T>
  using type_template = typename Else::template type_template<T>;
};

template<template<class> class T>
struct identity_template
{
  template<class U>
  using type_template = T<U>;
};

template<class T, template<class> class Default = std::future>
struct nested_future_with_default
  : agency::detail::lazy_conditional_template<
      agency::detail::has_future_template<T,void>::value,
      nested_future_template<T>,
      identity_template<Default>
    >
{};

template<class Executor, class T, class TypeList>
struct has_then_execute_impl;

template<class Executor, class T, class... Types>
struct has_then_execute_impl<Executor, T, type_list<Types...>>
{
  using index_type = typename nested_index_type_with_default<
    Executor
  >::type;

  using shape_type = typename nested_shape_type_with_default<
    Executor
  >::type;

  template<class U>
  using future = typename nested_future_with_default<
    Executor
  >::template type_template<U>;

  struct dummy_functor
  {
    void operator()(const index_type&, T&, Types&...) {}

    // overload for void past parameter
    void operator()(const index_type&, Types&...) {}
  };

  template<class Executor1,
           class = decltype(
             std::declval<Executor1>().then_execute(
               std::declval<dummy_functor>(),
               std::declval<shape_type>(),
               *std::declval<future<T>*>(),
               *std::declval<Types*>()...
             )
           )>
  static std::true_type test(int);

  template<class>
  static std::false_type test(...);

  using type = decltype(test<Executor>(0));
};

template<class T, bool = has_execution_category<T>::value>
struct has_then_execute : std::false_type {};

template<class T>
struct has_then_execute<T,true>
  : has_then_execute_impl<
      T,
      int,
      repeat_type<
        int, execution_depth<typename T::execution_category>::value
      >
    >::type
{};

template<class Executor, class T, class... Args>
struct has_make_ready_future_impl
{
  template<
    class Executor2,
    typename = decltype(
      std::declval<Executor2*>()->template make_ready_future<T>(
        std::declval<Args>()...
      )
    )
  >
  static std::true_type test(int);

  template<class>
  static std::false_type test(...);

  using type = decltype(test<Executor>(0));
};

template<class Executor, class T, class... Args>
using has_make_ready_future = typename has_make_ready_future_impl<Executor,T,Args...>::type;

} // end detail

template<class T>
struct is_executor
  : std::integral_constant<
      bool,
      detail::has_execution_category<T>::value &&
      detail::has_then_execute<T>::value
    >
{};

template<class Executor>
struct executor_traits
{
  private:
    template<class T>
    struct executor_index
    {
      using type = typename T::index_type;
    };

    template<class T>
    struct executor_shape
    {
      using type = typename T::shape_type;
    };

  public:
    using executor_type = Executor;

    using execution_category = typename Executor::execution_category;

    using index_type = typename detail::nested_index_type_with_default<
      executor_type,
      size_t
    >::type;

    using shape_type = typename detail::lazy_conditional<
      detail::has_shape_type<executor_type>::value,
      executor_shape<executor_type>,
      detail::identity<index_type>
    >::type;

  private:
    template<class T, class U>
    struct has_future_impl
    {
      template<class> static std::false_type test(...);
      template<class X> static std::true_type  test(typename X::template future<U>* = 0);

      using type = decltype(test<T>(0));
    };

    template<class T, class U>
    struct has_future : has_future_impl<T,U>::type {};

    template<class T, class U, bool = has_future<T,U>::value>
    struct executor_future
    {
      using type = typename T::template future<U>;
    };

    template<class T, class U>
    struct executor_future<T,U,false>
    {
      using type = std::future<U>;
    };

  public:
    template<class T>
    using future = typename executor_future<executor_type,T>::type;

  private:
    static future<void> make_ready_future_impl(executor_type& ex, std::true_type)
    {
      return ex.make_ready_future();
    }

    static future<void> make_ready_future_impl(executor_type&, std::false_type)
    {
      return future_traits<future<void>>::make_ready();
    }

    template<class T, class... Args>
    static future<T> make_ready_future_impl(std::true_type, executor_type& ex, Args&&... args)
    {
      return ex.template make_ready_future<T>(std::forward<Args>(args)...);
    }

    template<class T, class... Args>
    static future<T> make_ready_future_impl(std::false_type, executor_type&, Args&&... args)
    {
      return future_traits<future<T>>::template make_ready<T>(std::forward<Args>(args)...);
    }

    template<class T>
    struct is_future : detail::is_instance_of_future<T,future> {};

  public:
    template<class T, class... Args>
    static future<T> make_ready_future(executor_type& ex, Args&&... args)
    {
      return make_ready_future_impl<T>(detail::has_make_ready_future<executor_type,T,Args&&...>(), ex, std::forward<Args>(args)...);
    }

    template<class T, class Future>
    static future<T> future_cast(executor_type& ex, Future& from)
    {
      return new_executor_traits<executor_type>::template future_cast<T>(ex, from);
    }

    // XXX generalize this to interoperate with other Futures
    // XXX we can use async_execute & call fut.get() when depending on foreign Futures
    template<class Function, class Future, class T1, class... Types,
             class = typename std::enable_if<
               is_future<Future>::value
             >::type>
    static future<void> then_execute(executor_type& ex, Function f, shape_type shape, Future& fut, T1&& outer_shared_init, Types&&... inner_shared_inits)
    {
      return new_executor_traits<executor_type>::then_execute(ex, f, shape, fut, std::forward<T1>(outer_shared_init), std::forward<Types>(inner_shared_inits)...);
    }

    template<class Function, class Future,
             class = typename std::enable_if<
               is_future<Future>::value
             >::type>
    static future<void> then_execute(executor_type& ex, Function f, shape_type shape, Future& fut)
    {
      return new_executor_traits<executor_type>::then_execute(ex, f, shape, fut);
    }

    template<class Function, class T, class... Types>
    static future<void> async_execute(executor_type& ex, Function f, shape_type shape, T&& outer_shared_init, Types&&... inner_shared_inits)
    {
      return new_executor_traits<executor_type>::async_execute(ex, f, shape, std::forward<T>(outer_shared_init), std::forward<Types>(inner_shared_inits)...);
    }

    template<class Function>
    static future<void> async_execute(executor_type& ex, Function f, shape_type shape)
    {
      return new_executor_traits<executor_type>::async_execute(ex, f, shape);
    }

    template<class Function, class T, class... Types>
    static void execute(executor_type& ex, Function f, shape_type shape, T&& outer_shared_init, Types&&... inner_shared_inits)
    {
      new_executor_traits<executor_type>::execute(ex, f, shape, std::forward<T>(outer_shared_init), std::forward<Types>(inner_shared_inits)...);
    }

    template<class Function>
    static void execute(executor_type& ex, Function f, shape_type shape)
    {
      new_executor_traits<executor_type>::execute(ex, f, shape);
    }
};

namespace detail
{

template<class Executor, class Enable = void>
struct executor_index {};

template<class Executor>
struct executor_index<Executor, typename std::enable_if<is_executor<Executor>::value>::type>
{
  using type = typename executor_traits<Executor>::index_type;
};

template<class Executor>
using executor_index_t = typename executor_index<Executor>::type;

template<class Executor, class Enable = void>
struct executor_shape {};

template<class Executor>
struct executor_shape<Executor, typename std::enable_if<is_executor<Executor>::value>::type>
{
  using type = typename executor_traits<Executor>::shape_type;
};

template<class Executor>
using executor_shape_t = typename executor_shape<Executor>::type;

template<class Executor, class T, class Enable = void>
struct executor_future {};

template<class Executor, class T>
struct executor_future<Executor, T, typename std::enable_if<is_executor<Executor>::value>::type>
{
  using type = typename executor_traits<Executor>::template future<T>;
};

template<class Executor, class T>
using executor_future_t = typename executor_future<Executor,T>::type;

} // end detail

} // end agency

<commit_msg>Implement executor_traits::make_ready_future with new_executor_traits<commit_after>#pragma once

#include <agency/future.hpp>
#include <agency/detail/type_traits.hpp>
#include <agency/detail/bind.hpp>
#include <agency/execution_categories.hpp>
#include <agency/detail/tuple.hpp>
#include <agency/detail/shape_cast.hpp>
#include <agency/new_executor_traits.hpp>

namespace agency
{
namespace detail
{

__DEFINE_HAS_NESTED_TYPE(has_index_type, index_type);
__DEFINE_HAS_NESTED_TYPE(has_shape_type, shape_type);
__DEFINE_HAS_NESTED_TYPE(has_execution_category, execution_category);
__DEFINE_HAS_NESTED_CLASS_TEMPLATE(has_future_template, future);

template<class T>
struct nested_index_type
{
  using type = typename T::index_type;
};

template<class T, class Default = size_t>
struct nested_index_type_with_default
  : agency::detail::lazy_conditional<
      agency::detail::has_index_type<T>::value,
      nested_index_type<T>,
      agency::detail::identity<Default>
    >
{};

template<class T>
struct nested_shape_type
{
  using type = typename T::shape_type;
};

template<class T, class Default = size_t>
struct nested_shape_type_with_default
  : agency::detail::lazy_conditional<
      agency::detail::has_shape_type<T>::value,
      nested_shape_type<T>,
      agency::detail::identity<Default>
    >
{};

template<class T>
struct nested_future_template
{
  template<class U>
  using type_template = typename T::template future<U>;
};

template<bool condition, class Then, class Else>
struct lazy_conditional_template
{
  template<class T>
  using type_template = typename Then::template type_template<T>;
};

template<class Then, class Else>
struct lazy_conditional_template<false, Then, Else>
{
  template<class T>
  using type_template = typename Else::template type_template<T>;
};

template<template<class> class T>
struct identity_template
{
  template<class U>
  using type_template = T<U>;
};

template<class T, template<class> class Default = std::future>
struct nested_future_with_default
  : agency::detail::lazy_conditional_template<
      agency::detail::has_future_template<T,void>::value,
      nested_future_template<T>,
      identity_template<Default>
    >
{};

template<class Executor, class T, class TypeList>
struct has_then_execute_impl;

template<class Executor, class T, class... Types>
struct has_then_execute_impl<Executor, T, type_list<Types...>>
{
  using index_type = typename nested_index_type_with_default<
    Executor
  >::type;

  using shape_type = typename nested_shape_type_with_default<
    Executor
  >::type;

  template<class U>
  using future = typename nested_future_with_default<
    Executor
  >::template type_template<U>;

  struct dummy_functor
  {
    void operator()(const index_type&, T&, Types&...) {}

    // overload for void past parameter
    void operator()(const index_type&, Types&...) {}
  };

  template<class Executor1,
           class = decltype(
             std::declval<Executor1>().then_execute(
               std::declval<dummy_functor>(),
               std::declval<shape_type>(),
               *std::declval<future<T>*>(),
               *std::declval<Types*>()...
             )
           )>
  static std::true_type test(int);

  template<class>
  static std::false_type test(...);

  using type = decltype(test<Executor>(0));
};

template<class T, bool = has_execution_category<T>::value>
struct has_then_execute : std::false_type {};

template<class T>
struct has_then_execute<T,true>
  : has_then_execute_impl<
      T,
      int,
      repeat_type<
        int, execution_depth<typename T::execution_category>::value
      >
    >::type
{};

template<class Executor, class T, class... Args>
struct has_make_ready_future_impl
{
  template<
    class Executor2,
    typename = decltype(
      std::declval<Executor2*>()->template make_ready_future<T>(
        std::declval<Args>()...
      )
    )
  >
  static std::true_type test(int);

  template<class>
  static std::false_type test(...);

  using type = decltype(test<Executor>(0));
};

template<class Executor, class T, class... Args>
using has_make_ready_future = typename has_make_ready_future_impl<Executor,T,Args...>::type;

} // end detail

template<class T>
struct is_executor
  : std::integral_constant<
      bool,
      detail::has_execution_category<T>::value &&
      detail::has_then_execute<T>::value
    >
{};

template<class Executor>
struct executor_traits
{
  private:
    template<class T>
    struct executor_index
    {
      using type = typename T::index_type;
    };

    template<class T>
    struct executor_shape
    {
      using type = typename T::shape_type;
    };

  public:
    using executor_type = Executor;

    using execution_category = typename Executor::execution_category;

    using index_type = typename detail::nested_index_type_with_default<
      executor_type,
      size_t
    >::type;

    using shape_type = typename detail::lazy_conditional<
      detail::has_shape_type<executor_type>::value,
      executor_shape<executor_type>,
      detail::identity<index_type>
    >::type;

  private:
    template<class T, class U>
    struct has_future_impl
    {
      template<class> static std::false_type test(...);
      template<class X> static std::true_type  test(typename X::template future<U>* = 0);

      using type = decltype(test<T>(0));
    };

    template<class T, class U>
    struct has_future : has_future_impl<T,U>::type {};

    template<class T, class U, bool = has_future<T,U>::value>
    struct executor_future
    {
      using type = typename T::template future<U>;
    };

    template<class T, class U>
    struct executor_future<T,U,false>
    {
      using type = std::future<U>;
    };

  public:
    template<class T>
    using future = typename executor_future<executor_type,T>::type;

    template<class T, class... Args>
    static future<T> make_ready_future(executor_type& ex, Args&&... args)
    {
      return new_executor_traits<executor_type>::template make_ready_future<T>(ex, std::forward<Args>(args)...);
    }

    template<class T, class Future>
    static future<T> future_cast(executor_type& ex, Future& from)
    {
      return new_executor_traits<executor_type>::template future_cast<T>(ex, from);
    }

  private:
    template<class T>
    struct is_future : detail::is_instance_of_future<T,future> {};

  public:
    // XXX generalize this to interoperate with other Futures
    // XXX we can use async_execute & call fut.get() when depending on foreign Futures
    template<class Function, class Future, class T1, class... Types,
             class = typename std::enable_if<
               is_future<Future>::value
             >::type>
    static future<void> then_execute(executor_type& ex, Function f, shape_type shape, Future& fut, T1&& outer_shared_init, Types&&... inner_shared_inits)
    {
      return new_executor_traits<executor_type>::then_execute(ex, f, shape, fut, std::forward<T1>(outer_shared_init), std::forward<Types>(inner_shared_inits)...);
    }

    template<class Function, class Future,
             class = typename std::enable_if<
               is_future<Future>::value
             >::type>
    static future<void> then_execute(executor_type& ex, Function f, shape_type shape, Future& fut)
    {
      return new_executor_traits<executor_type>::then_execute(ex, f, shape, fut);
    }

    template<class Function, class T, class... Types>
    static future<void> async_execute(executor_type& ex, Function f, shape_type shape, T&& outer_shared_init, Types&&... inner_shared_inits)
    {
      return new_executor_traits<executor_type>::async_execute(ex, f, shape, std::forward<T>(outer_shared_init), std::forward<Types>(inner_shared_inits)...);
    }

    template<class Function>
    static future<void> async_execute(executor_type& ex, Function f, shape_type shape)
    {
      return new_executor_traits<executor_type>::async_execute(ex, f, shape);
    }

    template<class Function, class T, class... Types>
    static void execute(executor_type& ex, Function f, shape_type shape, T&& outer_shared_init, Types&&... inner_shared_inits)
    {
      new_executor_traits<executor_type>::execute(ex, f, shape, std::forward<T>(outer_shared_init), std::forward<Types>(inner_shared_inits)...);
    }

    template<class Function>
    static void execute(executor_type& ex, Function f, shape_type shape)
    {
      new_executor_traits<executor_type>::execute(ex, f, shape);
    }
};

namespace detail
{

template<class Executor, class Enable = void>
struct executor_index {};

template<class Executor>
struct executor_index<Executor, typename std::enable_if<is_executor<Executor>::value>::type>
{
  using type = typename executor_traits<Executor>::index_type;
};

template<class Executor>
using executor_index_t = typename executor_index<Executor>::type;

template<class Executor, class Enable = void>
struct executor_shape {};

template<class Executor>
struct executor_shape<Executor, typename std::enable_if<is_executor<Executor>::value>::type>
{
  using type = typename executor_traits<Executor>::shape_type;
};

template<class Executor>
using executor_shape_t = typename executor_shape<Executor>::type;

template<class Executor, class T, class Enable = void>
struct executor_future {};

template<class Executor, class T>
struct executor_future<Executor, T, typename std::enable_if<is_executor<Executor>::value>::type>
{
  using type = typename executor_traits<Executor>::template future<T>;
};

template<class Executor, class T>
using executor_future_t = typename executor_future<Executor,T>::type;

} // end detail

} // end agency

<|endoftext|>


<commit_before>// This Source Code Form is licensed MPLv2: http://mozilla.org/MPL/2.0
#include <stdio.h>
#include "components-a1-server.hh"
#include "components-a1-client.hh"

using namespace Rapicorn;

// == data samples ==
enum Plain {
  P0 = 0,
  P88 = 88
};

struct Simple {
  int   i1;
  Plain p2;
  Simple (int i, Plain p) : i1 (i), p2 (p) {}
  template<class Visitor> void
  __accept__ (Visitor _visitor_)
  {
    _visitor_ (i1, "int1");
    _visitor_ (p2, "enum2");
  }
};

static void
fill_simple_data_pack (A1::SimpleDataPack &simple)
{
  simple.vbool = true;
  simple.vi32 = 32;
  simple.vi64t = 64;
  simple.vf64 = 123456789e-11;
  simple.vstr = "donkeykong";
  simple.count = A1::THREE;
  simple.location.x = -3;
  simple.location.y = -3;
  simple.strings.push_back ("ABCDEFGHI");
  simple.strings.push_back ("jklmnopqr");
  simple.strings.push_back ("STUVWXYZ");
}

static void
fill_big_data_pack (A1::BigDataPack &big)
{
  const double TstNAN = 0 ? NAN : 909.909; // "NAN" is useful to test but breaks assert (in == out)
  fill_simple_data_pack (big.simple_pack);
  std::vector<bool> bools = { false, false, false, true, true, true, false, false, false };
  bools.swap (big.bools);
  std::vector<int32_t> ints32 = { -3, -2, -1, 0, 1, 2, 3 };
  ints32.swap (big.ints32);
  std::vector<int64_t> ints64 = { -1, 0x11111111deadbeefLL, -2 };
  ints64.swap (big.ints64);
  std::vector<double> floats = { -TstNAN, -INFINITY, -5.5, -0.75, -0, +0, +0.25, +1.25, +INFINITY, +TstNAN };
  floats.swap (big.floats);
  std::vector<A1::CountEnum> counts = { A1::THREE, A1::TWO, A1::ONE };
  counts.swap (big.counts);
  A1::Location l;
  l.x = -3; l.y = -5; big.locations.push_back (l);
  l.x = -1; l.y = -2; big.locations.push_back (l);
  l.x =  0; l.y =  0; big.locations.push_back (l);
  l.x = +1; l.y = +1; big.locations.push_back (l);
  l.x = +9; l.y = +2; big.locations.push_back (l);
  // any1;
  // anys;
  // objects;
  // other;
  // derived;
}

// == struct utilities ==
template<class Struct>
static String
struct_to_ini (Struct &s, const String &name)
{
  IniWriter iniwriter;
  ToIniVisitor writer_visitor (iniwriter, name + ".");
  s.__accept__ (writer_visitor);
  return iniwriter.output();
}

template<class Struct>
static bool
struct_from_ini (Struct &s, const String &name, const String &inidata)
{
  IniFile inifile ("-", inidata);
  if (!inifile.has_sections())
    return false;
  FromIniVisitor fromini_visitor (inifile, name + ".");
  s.__accept__ (fromini_visitor);
  return true;
}

template<class Struct>
static String
struct_to_xml (Struct &s, const String &name)
{
  XmlNodeP xnode = XmlNode::create_parent (name, 0, 0, "");
  ToXmlVisitor toxml_visitor (xnode);
  s.__accept__ (toxml_visitor);
  return xnode->xml_string (0, true);
}

template<class Struct>
static bool
struct_from_xml (Struct &s, const String &xmldata)
{
  MarkupParser::Error xerror;
  if (xerror.code != MarkupParser::NONE)
    return false;
  XmlNodeP xroot = XmlNode::parse_xml ("-", xmldata.c_str(), xmldata.size(), &xerror, "");
  if (xerror.code != MarkupParser::NONE)
    return false;
  FromXmlVisitor fromxml_visitor (xroot);
  s.__accept__ (fromxml_visitor);
  return true;
}

// == main ==
int
main (int   argc,
      char *argv[])
{
  bool ok;

  // rich data type test setup
  A1::BigDataPack big;
  fill_big_data_pack (big);
  switch (0)
    {
    case 1: printout ("%s\n", struct_to_xml (big, "BigDataPack")); break;
    case 2: printout ("%s", struct_to_ini (big, "BigDataPack")); break;
    case 0: ;
    }

  // test rich data type conversion to and from INI
  {
    String iniout = struct_to_ini (big, "BigDataPack");
    A1::BigDataPack b2;
    assert (big != b2);
    ok = struct_from_ini (b2, "BigDataPack", iniout);
    assert (ok);
    assert (big == b2);
  }

  // test rich data type conversion to and from XML
  {
    String xmlout = struct_to_xml (big, "BigDataPack");
    A1::BigDataPack b2;
    assert (big != b2);
    ok = struct_from_xml (b2, xmlout);
    assert (ok);
    assert (big == b2);
  }

  {
    Any any = big.__aida_to_any__();
    A1::BigDataPack buck;
    buck.__aida_from_any__ (any);
    assert (big == buck);
    printerr ("Big->Buck via Any:\n%s\n", struct_to_xml (buck, "BigDataPack"));
  }

  // test non-introspectible enums
  Simple s1 (111, P88);
  {
    Simple s2 (0, P0);
    assert (s1.i1 != s2.i1 && s1.p2 != s2.p2);
    ok = struct_from_xml (s2, struct_to_xml (s1, "Simple"));
    assert (ok);
    assert (s1.i1 == s2.i1 && s1.p2 == s2.p2);
  }
  {
    Simple s2 (0, P0);
    assert (s1.i1 != s2.i1 && s1.p2 != s2.p2);
    ok = struct_from_ini (s2, "Simple", struct_to_ini (s1, "Simple"));
    assert (ok);
    assert (s1.i1 == s2.i1 && s1.p2 == s2.p2);
  }

  printout ("  %-8s %-60s  %s\n", "TEST", argv[0], "OK");
  return 0;
}

#include "components-a1-client.cc"
#include "components-a1-server.cc"
<commit_msg>AIDACC: tests: silence debugging output<commit_after>// This Source Code Form is licensed MPLv2: http://mozilla.org/MPL/2.0
#include <stdio.h>
#include "components-a1-server.hh"
#include "components-a1-client.hh"

using namespace Rapicorn;

// == data samples ==
enum Plain {
  P0 = 0,
  P88 = 88
};

struct Simple {
  int   i1;
  Plain p2;
  Simple (int i, Plain p) : i1 (i), p2 (p) {}
  template<class Visitor> void
  __accept__ (Visitor _visitor_)
  {
    _visitor_ (i1, "int1");
    _visitor_ (p2, "enum2");
  }
};

static void
fill_simple_data_pack (A1::SimpleDataPack &simple)
{
  simple.vbool = true;
  simple.vi32 = 32;
  simple.vi64t = 64;
  simple.vf64 = 123456789e-11;
  simple.vstr = "donkeykong";
  simple.count = A1::THREE;
  simple.location.x = -3;
  simple.location.y = -3;
  simple.strings.push_back ("ABCDEFGHI");
  simple.strings.push_back ("jklmnopqr");
  simple.strings.push_back ("STUVWXYZ");
}

static void
fill_big_data_pack (A1::BigDataPack &big)
{
  const double TstNAN = 0 ? NAN : 909.909; // "NAN" is useful to test but breaks assert (in == out)
  fill_simple_data_pack (big.simple_pack);
  std::vector<bool> bools = { false, false, false, true, true, true, false, false, false };
  bools.swap (big.bools);
  std::vector<int32_t> ints32 = { -3, -2, -1, 0, 1, 2, 3 };
  ints32.swap (big.ints32);
  std::vector<int64_t> ints64 = { -1, 0x11111111deadbeefLL, -2 };
  ints64.swap (big.ints64);
  std::vector<double> floats = { -TstNAN, -INFINITY, -5.5, -0.75, -0, +0, +0.25, +1.25, +INFINITY, +TstNAN };
  floats.swap (big.floats);
  std::vector<A1::CountEnum> counts = { A1::THREE, A1::TWO, A1::ONE };
  counts.swap (big.counts);
  A1::Location l;
  l.x = -3; l.y = -5; big.locations.push_back (l);
  l.x = -1; l.y = -2; big.locations.push_back (l);
  l.x =  0; l.y =  0; big.locations.push_back (l);
  l.x = +1; l.y = +1; big.locations.push_back (l);
  l.x = +9; l.y = +2; big.locations.push_back (l);
  // any1;
  // anys;
  // objects;
  // other;
  // derived;
}

// == struct utilities ==
template<class Struct>
static String
struct_to_ini (Struct &s, const String &name)
{
  IniWriter iniwriter;
  ToIniVisitor writer_visitor (iniwriter, name + ".");
  s.__accept__ (writer_visitor);
  return iniwriter.output();
}

template<class Struct>
static bool
struct_from_ini (Struct &s, const String &name, const String &inidata)
{
  IniFile inifile ("-", inidata);
  if (!inifile.has_sections())
    return false;
  FromIniVisitor fromini_visitor (inifile, name + ".");
  s.__accept__ (fromini_visitor);
  return true;
}

template<class Struct>
static String
struct_to_xml (Struct &s, const String &name)
{
  XmlNodeP xnode = XmlNode::create_parent (name, 0, 0, "");
  ToXmlVisitor toxml_visitor (xnode);
  s.__accept__ (toxml_visitor);
  return xnode->xml_string (0, true);
}

template<class Struct>
static bool
struct_from_xml (Struct &s, const String &xmldata)
{
  MarkupParser::Error xerror;
  if (xerror.code != MarkupParser::NONE)
    return false;
  XmlNodeP xroot = XmlNode::parse_xml ("-", xmldata.c_str(), xmldata.size(), &xerror, "");
  if (xerror.code != MarkupParser::NONE)
    return false;
  FromXmlVisitor fromxml_visitor (xroot);
  s.__accept__ (fromxml_visitor);
  return true;
}

// == main ==
int
main (int   argc,
      char *argv[])
{
  bool ok;

  // rich data type test setup
  A1::BigDataPack big;
  fill_big_data_pack (big);
  switch (0)
    {
    case 1: printout ("%s\n", struct_to_xml (big, "BigDataPack")); break;
    case 2: printout ("%s", struct_to_ini (big, "BigDataPack")); break;
    case 0: ;
    }

  // test rich data type conversion to and from INI
  {
    String iniout = struct_to_ini (big, "BigDataPack");
    A1::BigDataPack b2;
    assert (big != b2);
    ok = struct_from_ini (b2, "BigDataPack", iniout);
    assert (ok);
    assert (big == b2);
  }

  // test rich data type conversion to and from XML
  {
    String xmlout = struct_to_xml (big, "BigDataPack");
    A1::BigDataPack b2;
    assert (big != b2);
    ok = struct_from_xml (b2, xmlout);
    assert (ok);
    assert (big == b2);
  }

  {
    Any any = big.__aida_to_any__();
    A1::BigDataPack buck;
    buck.__aida_from_any__ (any);
    assert (big == buck);
    if (0)
      printerr ("Big->Buck via Any:\n%s\n", struct_to_xml (buck, "BigDataPack"));
  }

  // test non-introspectible enums
  Simple s1 (111, P88);
  {
    Simple s2 (0, P0);
    assert (s1.i1 != s2.i1 && s1.p2 != s2.p2);
    ok = struct_from_xml (s2, struct_to_xml (s1, "Simple"));
    assert (ok);
    assert (s1.i1 == s2.i1 && s1.p2 == s2.p2);
  }
  {
    Simple s2 (0, P0);
    assert (s1.i1 != s2.i1 && s1.p2 != s2.p2);
    ok = struct_from_ini (s2, "Simple", struct_to_ini (s1, "Simple"));
    assert (ok);
    assert (s1.i1 == s2.i1 && s1.p2 == s2.p2);
  }

  printout ("  %-8s %-60s  %s\n", "TEST", argv[0], "OK");
  return 0;
}

#include "components-a1-client.cc"
#include "components-a1-server.cc"
<|endoftext|>


<commit_before>#ifndef AMGCL_VALUE_TYPE_EIGEN_HPP
#define AMGCL_VALUE_TYPE_EIGEN_HPP

/*
The MIT License

Copyright (c) 2012-2020 Denis Demidov <dennis.demidov@gmail.com>

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.
*/

/**
 * \file   amgcl/value_type/eigen.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Enable statically sized eigen matrices as value types.
 */

#include <Eigen/Dense>

#include <amgcl/backend/builtin.hpp>
#include <amgcl/value_type/interface.hpp>

namespace amgcl {
namespace backend {

/// Enable Eigen matrix as a value-type.
template <typename T, int N, int M>
struct is_builtin_vector< std::vector<Eigen::Matrix<T, N, M> > > : std::true_type {};

} // namespace backend

namespace math {

/// Scalar type of a non-scalar type.
template <class T, int N, int M>
struct scalar_of< Eigen::Matrix<T, N, M> > {
    typedef typename math::scalar_of<T>::type type;
};

/// Replace scalar type in the static matrix
template <class T, int N, int M, class S>
struct replace_scalar< Eigen::Matrix<T, N, M>, S> {
    typedef Eigen::Matrix<S, N, M> type;
};

/// RHS type corresponding to a non-scalar type.
template <class T, int N>
struct rhs_of< Eigen::Matrix<T, N, N> > {
    typedef Eigen::Matrix<T, N, 1> type;
};

/// Whether the value type is a statically sized matrix.
template <class T, int N, int M>
struct is_static_matrix< Eigen::Matrix<T, N, M> > : std::true_type {};

/// Number of rows for statically sized matrix types.
template <class T, int N, int M>
struct static_rows< Eigen::Matrix<T, N, M> > : std::integral_constant<int, N> {};

/// Number of columns for statically sized matrix types.
template <class T, int N, int M>
struct static_cols< Eigen::Matrix<T, N, M> > : std::integral_constant<int, M> {};

/// Specialization of conjugate transpose for eigen matrices.
template <typename T, int N, int M>
struct adjoint_impl< Eigen::Matrix<T, N, M> >
{
    typedef typename Eigen::Matrix<T, N, M>::AdjointReturnType return_type;

    static return_type get(const Eigen::Matrix<T, N, M> &x) {
        return x.adjoint();
    }
};

/// Inner-product result of two Eigen vectors.
template <class T, int N>
struct inner_product_impl< Eigen::Matrix<T, N, 1> >
{
    typedef T return_type;
    static T get(const Eigen::Matrix<T, N, 1> &x, const Eigen::Matrix<T, N, 1> &y) {
        return x.adjoint() * y;
    }
};

/// Inner-product result of two Eigen matrices.
template <class T, int N, int M>
struct inner_product_impl< Eigen::Matrix<T, N, M> >
{
    typedef Eigen::Matrix<T, M, M> return_type;

    static return_type get(const Eigen::Matrix<T, N, M> &x, const Eigen::Matrix<T, N, M> &y) {
        return x.adjoint() * y;
    }
};

/// Specialization of element norm for eigen matrices.
template <typename T, int N, int M>
struct norm_impl< Eigen::Matrix<T, N, M> >
{
    static typename math::scalar_of<T>::type get(const Eigen::Matrix<T, N, M> &x) {
        return x.norm();
    }
};

/// Specialization of zero element for eigen matrices.
template <typename T, int N, int M>
struct zero_impl< Eigen::Matrix<T, N, M> >
{
    static Eigen::Matrix<T, N, M> get() {
        return Eigen::Matrix<T, N, M>::Zero();
    }
};

/// Specialization of zero element for eigen matrices.
template <typename T, int N, int M>
struct is_zero_impl< Eigen::Matrix<T, N, M> >
{
    static bool get(const Eigen::Matrix<T, N, M> &x) {
        return x.isZero();
    }
};

/// Specialization of identity for eigen matrices.
template <typename T, int N>
struct identity_impl< Eigen::Matrix<T, N, N> >
{
    static Eigen::Matrix<T, N, N> get() {
        return Eigen::Matrix<T, N, N>::Identity();
    }
};

/// Specialization of constant for eigen matrices.
template <typename T, int N, int M>
struct constant_impl< Eigen::Matrix<T, N, M> >
{
    static Eigen::Matrix<T, N, M> get(T c) {
        return Eigen::Matrix<T, N, M>::Constant(c);
    }
};

/// Specialization of inversion for eigen matrices.
template <typename T, int N>
struct inverse_impl< Eigen::Matrix<T, N, N> >
{
    static Eigen::Matrix<T, N, N> get(const Eigen::Matrix<T, N, N> &x) {
        return x.inverse();
    }
};

} // namespace math

namespace relaxation {
template <class Backend> struct spai1;
} //namespace relaxation

namespace backend {

template <class Backend>
struct relaxation_is_supported<
    Backend, relaxation::spai1,
    typename std::enable_if<
        std::is_base_of<
            Eigen::MatrixBase<typename Backend::value_type>,
            typename Backend::value_type
            >::value
        >::type
    > : std::false_type
{};

} // namespace backend
} // namespace amgcl

namespace Eigen {

template <class A, class B>
bool operator<(const MatrixBase<A> &a, const MatrixBase<B> &b) {
    return a.trace() < b.trace();
}

} // namespace Eigen

#endif
<commit_msg>Remove unnecessary check from value_type/eigen<commit_after>#ifndef AMGCL_VALUE_TYPE_EIGEN_HPP
#define AMGCL_VALUE_TYPE_EIGEN_HPP

/*
The MIT License

Copyright (c) 2012-2020 Denis Demidov <dennis.demidov@gmail.com>

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.
*/

/**
 * \file   amgcl/value_type/eigen.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Enable statically sized eigen matrices as value types.
 */

#include <Eigen/Dense>

#include <amgcl/backend/builtin.hpp>
#include <amgcl/value_type/interface.hpp>

namespace amgcl {
namespace backend {

/// Enable Eigen matrix as a value-type.
template <typename T, int N, int M>
struct is_builtin_vector< std::vector<Eigen::Matrix<T, N, M> > > : std::true_type {};

} // namespace backend

namespace math {

/// Scalar type of a non-scalar type.
template <class T, int N, int M>
struct scalar_of< Eigen::Matrix<T, N, M> > {
    typedef typename math::scalar_of<T>::type type;
};

/// Replace scalar type in the static matrix
template <class T, int N, int M, class S>
struct replace_scalar< Eigen::Matrix<T, N, M>, S> {
    typedef Eigen::Matrix<S, N, M> type;
};

/// RHS type corresponding to a non-scalar type.
template <class T, int N>
struct rhs_of< Eigen::Matrix<T, N, N> > {
    typedef Eigen::Matrix<T, N, 1> type;
};

/// Whether the value type is a statically sized matrix.
template <class T, int N, int M>
struct is_static_matrix< Eigen::Matrix<T, N, M> > : std::true_type {};

/// Number of rows for statically sized matrix types.
template <class T, int N, int M>
struct static_rows< Eigen::Matrix<T, N, M> > : std::integral_constant<int, N> {};

/// Number of columns for statically sized matrix types.
template <class T, int N, int M>
struct static_cols< Eigen::Matrix<T, N, M> > : std::integral_constant<int, M> {};

/// Specialization of conjugate transpose for eigen matrices.
template <typename T, int N, int M>
struct adjoint_impl< Eigen::Matrix<T, N, M> >
{
    typedef typename Eigen::Matrix<T, N, M>::AdjointReturnType return_type;

    static return_type get(const Eigen::Matrix<T, N, M> &x) {
        return x.adjoint();
    }
};

/// Inner-product result of two Eigen vectors.
template <class T, int N>
struct inner_product_impl< Eigen::Matrix<T, N, 1> >
{
    typedef T return_type;
    static T get(const Eigen::Matrix<T, N, 1> &x, const Eigen::Matrix<T, N, 1> &y) {
        return x.adjoint() * y;
    }
};

/// Inner-product result of two Eigen matrices.
template <class T, int N, int M>
struct inner_product_impl< Eigen::Matrix<T, N, M> >
{
    typedef Eigen::Matrix<T, M, M> return_type;

    static return_type get(const Eigen::Matrix<T, N, M> &x, const Eigen::Matrix<T, N, M> &y) {
        return x.adjoint() * y;
    }
};

/// Specialization of element norm for eigen matrices.
template <typename T, int N, int M>
struct norm_impl< Eigen::Matrix<T, N, M> >
{
    static typename math::scalar_of<T>::type get(const Eigen::Matrix<T, N, M> &x) {
        return x.norm();
    }
};

/// Specialization of zero element for eigen matrices.
template <typename T, int N, int M>
struct zero_impl< Eigen::Matrix<T, N, M> >
{
    static Eigen::Matrix<T, N, M> get() {
        return Eigen::Matrix<T, N, M>::Zero();
    }
};

/// Specialization of zero element for eigen matrices.
template <typename T, int N, int M>
struct is_zero_impl< Eigen::Matrix<T, N, M> >
{
    static bool get(const Eigen::Matrix<T, N, M> &x) {
        return x.isZero();
    }
};

/// Specialization of identity for eigen matrices.
template <typename T, int N>
struct identity_impl< Eigen::Matrix<T, N, N> >
{
    static Eigen::Matrix<T, N, N> get() {
        return Eigen::Matrix<T, N, N>::Identity();
    }
};

/// Specialization of constant for eigen matrices.
template <typename T, int N, int M>
struct constant_impl< Eigen::Matrix<T, N, M> >
{
    static Eigen::Matrix<T, N, M> get(T c) {
        return Eigen::Matrix<T, N, M>::Constant(c);
    }
};

/// Specialization of inversion for eigen matrices.
template <typename T, int N>
struct inverse_impl< Eigen::Matrix<T, N, N> >
{
    static Eigen::Matrix<T, N, N> get(const Eigen::Matrix<T, N, N> &x) {
        return x.inverse();
    }
};

} // namespace math
} // namespace amgcl

namespace Eigen {

template <class A, class B>
bool operator<(const MatrixBase<A> &a, const MatrixBase<B> &b) {
    return a.trace() < b.trace();
}

} // namespace Eigen

#endif
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
//      https://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 "experimental/ModelBuilder/ModelBuilder.h"

#include "mlir/Dialect/Affine/EDSC/Builders.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/GPU/GPUDialect.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/Linalg/IR/LinalgOps.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/Dialect/SCF/SCF.h"
#include "mlir/Dialect/SPIRV/SPIRVDialect.h"
#include "mlir/Dialect/SPIRV/TargetAndABI.h"
#include "mlir/Dialect/Shape/IR/Shape.h"
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/Dialect/Vector/VectorOps.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/StandardTypes.h"
#include "mlir/IR/TypeUtilities.h"

using namespace mlir;
using namespace mlir::edsc;
using namespace mlir::edsc::ops;
using namespace mlir::edsc::intrinsics;

thread_local MLIRContext mlir::ModelBuilder::ctx;

void ModelBuilder::registerAllDialects() {
  // TODO: remove.
}

mlir::ModelBuilder::ModelBuilder()
    : OpBuilder(&ctx),
      module(mlir::ModuleOp::create(mlir::UnknownLoc::get(&ctx))),
      symbolTable(*module),
      loc(module->getLoc()),
      i8(IntegerType::get(8, &ctx)),
      f32(FloatType::getF32(&ctx)),
      f64(FloatType::getF64(&ctx)) {
  ctx.getOrLoadDialect<AffineDialect>();
  ctx.getOrLoadDialect<gpu::GPUDialect>();
  ctx.getOrLoadDialect<LLVM::LLVMDialect>();
  ctx.getOrLoadDialect<linalg::LinalgDialect>();
  ctx.getOrLoadDialect<scf::SCFDialect>();
  ctx.getOrLoadDialect<omp::OpenMPDialect>();
  ctx.getOrLoadDialect<spirv::SPIRVDialect>();
  ctx.getOrLoadDialect<StandardOpsDialect>();
  ctx.getOrLoadDialect<vector::VectorDialect>();
}

Value mlir::ModelBuilder::constant_f32(float v) {
  return std_constant_float(llvm::APFloat(v),
                            FloatType::getF32(ScopedContext::getContext()));
}

Value mlir::ModelBuilder::constant_f64(double v) {
  return std_constant_float(llvm::APFloat(v),
                            FloatType::getF64(ScopedContext::getContext()));
}

Value mlir::ModelBuilder::constant_index(int64_t v) {
  return std_constant_index(v);
}

FuncOp mlir::ModelBuilder::makeFunction(StringRef name, ArrayRef<Type> results,
                                        ArrayRef<Type> args,
                                        MLIRFuncOpConfig config) {
  FunctionType ft = FunctionType::get(args, results, &ctx);
  auto function = FuncOp::create(loc, name, ft);
  config.apply(function);
  module->push_back(function);
  return function;
}
FuncOp mlir::ModelBuilder::makeFunction(
    std::function<std::string(FunctionType)> nameBuilder,
    ArrayRef<Type> results, ArrayRef<Type> args, MLIRFuncOpConfig config) {
  FunctionType ft = FunctionType::get(args, results, &ctx);
  return makeFunction(nameBuilder(ft), results, args, config);
}

static spirv::TargetEnvAttr getTargetEnv(MLIRContext *context) {
  auto triple = spirv::VerCapExtAttr::get(
      spirv::Version::V_1_0,
      {spirv::Capability::Shader, spirv::Capability::CooperativeMatrixNV,
       spirv::Capability::Int8, spirv::Capability::Float16,
       spirv::Capability::StorageUniform16,
       spirv::Capability::StorageBuffer8BitAccess,
       spirv::Capability::Float16Buffer},
      {spirv::Extension::SPV_KHR_storage_buffer_storage_class,
       spirv::Extension::SPV_NV_cooperative_matrix,
       spirv::Extension::SPV_KHR_8bit_storage,
       spirv::Extension::SPV_KHR_16bit_storage},
      context);
  return spirv::TargetEnvAttr::get(triple, spirv::Vendor::Unknown,
                                   spirv::DeviceType::Unknown,
                                   spirv::TargetEnvAttr::kUnknownDeviceID,
                                   spirv::getDefaultResourceLimits(context));
}

gpu::GPUModuleOp mlir::ModelBuilder::makeGPUModule(StringRef name) {
  // Add module attributes required first.
  addGPUAttr();
  OpBuilder b(&module->getBodyRegion());
  auto kernelModule = b.create<gpu::GPUModuleOp>(loc, name);
  return kernelModule;
}

void mlir::ModelBuilder::addGPUAttr() {
  // Add module attributes required first.
  module->setAttr(gpu::GPUDialect::getContainerModuleAttrName(),
                  UnitAttr::get(module->getContext()));
  spirv::TargetEnvAttr targetEnv = getTargetEnv(module->getContext());
  module->setAttr(spirv::getTargetEnvAttrName(), targetEnv);
}

gpu::GPUFuncOp mlir::ModelBuilder::makeGPUKernel(
    StringRef name, gpu::GPUModuleOp GPUModule, ArrayRef<int32_t> workgroupSize,
    ArrayRef<Type> args, ArrayRef<Type> results) {
  auto fnType = FunctionType::get(args, results, module->getContext());
  OpBuilder b(&GPUModule.body());
  auto kernelFunc = b.create<gpu::GPUFuncOp>(loc, name, fnType);
  kernelFunc.setAttr(gpu::GPUDialect::getKernelFuncAttrName(), b.getUnitAttr());
  kernelFunc.setAttr(
      spirv::getEntryPointABIAttrName(),
      spirv::getEntryPointABIAttr(workgroupSize, module->getContext()));
  return kernelFunc;
}

VectorType mlir::ModelBuilder::getVectorType(ArrayRef<int64_t> shape,
                                             Type elementalType) {
  return VectorType::get(shape, elementalType);
}

MemRefType mlir::ModelBuilder::getMemRefType(ArrayRef<int64_t> shape,
                                             Type elementType,
                                             unsigned addressSpace) {
  return MemRefType::get(shape, elementType, {}, addressSpace);
}

RankedTensorType mlir::ModelBuilder::getRankedTensorType(
    ArrayRef<int64_t> shape, Type elementType) {
  return RankedTensorType::get(shape, elementType);
}

Value mlir::ModelBuilder::fusedBiasTanh(Value x, Value bias) {
  using edsc::op::operator+;
  using edsc::op::operator*;
  using edsc::intrinsics::std_call;
  assert(x.getType().isF32() && bias.getType().isF32() && "f32 expected");
  Value half = constant_f32(0.5f);
  return x + half * call_tanhf((x + bias) * half) + half;
}

Value mlir::ModelBuilder::FCBiasTanh(std::array<Value, 3> fcArgs,
                                     Value biasValueArg) {
  //==========================================================================//
  // Layer 1: FC
  //==========================================================================//
  Value I = fcArgs[0], W = fcArgs[1], O = fcArgs[2];
  // Emit a linalg.generic op that implements matmul:
  linalg_generic_matmul(I, W, O);

  //==========================================================================//
  // Layer 2: BiasAddTanh Block
  //==========================================================================//
  // Build and capture AffineExpr i and j for building index expressions.
  AffineExpr i, j;
  bindDims(&ctx, i, j);

  // Emit a linalg.generic op that implements pointwise with `opBuilder` for:
  //   `0.5f * tanh(0.5f * (x + bias)) + 0.5f`
  //
  // This performs the (inplace) computation:
  //   `o[i, j] <- pointwise(bias[j], o[i, j])`
  //
  // in which bias is broadcast along `i`.
  StructuredIndexed o(O), bias(biasValueArg);
  linalg_generic_pointwise(fusedBiasTanh, o({i, j}), bias({j}), o({i, j}));

  return O;
}

Value ModelBuilder::FCBiasTanhTensors(RankedTensorType outputTensorType,
                                      std::array<Value, 2> fcArgs,
                                      Value fcInitTensor, Value biasValueArg) {
  //==========================================================================//
  // Layer 1: FC
  //==========================================================================//
  Value I = fcArgs[0], W = fcArgs[1];
  Value O2 =
      linalg_generic_matmul(I, W, fcInitTensor, outputTensorType)->getResult(0);

  //==========================================================================//
  // Layer 2: BiasAddTanh Block
  //==========================================================================//
  AffineExpr i, j;
  bindDims(&ctx, i, j);
  // in-place with explicit bias broacast
  StructuredIndexed o2(O2), bias(biasValueArg), o3Type(outputTensorType);
  return linalg_generic_pointwise(fusedBiasTanh, o2({i, j}), bias({j}),
                                  o3Type({i, j}))
      ->getResult(0);
}

Value ModelBuilder::call_tanhf(Value v) {
  assert(v.getType().isF32() && "f32 expected");
  return emitCallToRegisteredSymbol("tanhf", v.getType(), v)->getResult(0);
}

void ModelBuilder::call_print_memref_f32(Value v) {
  auto &builder = ScopedContext::getBuilderRef();
  auto loc = builder.getInsertionBlock()
                 ->getParent()
                 ->getParentOfType<FuncOp>()
                 .getLoc();
  auto elementType = v.getType().cast<MemRefType>().getElementType();
  auto unrankedType = UnrankedMemRefType::get(elementType, 0);
  auto castMemRef = builder.create<MemRefCastOp>(loc, v, unrankedType);
  if (elementType.isF32())
    emitCallToRegisteredSymbol("print_memref_f32", {}, {castMemRef});
  else
    llvm_unreachable("Incorrect argument type for print_memref_f32");
}

Operation *ModelBuilder::emitCallToRegisteredSymbol(StringRef functionName,
                                                    ArrayRef<Type> returnTypes,
                                                    ValueRange values) {
  auto &builder = ScopedContext::getBuilderRef();
  auto callerFunc =
      builder.getInsertionBlock()->getParent()->getParentOfType<FuncOp>();
  FuncOp calleeFunc =
      SymbolTable::lookupNearestSymbolFrom<FuncOp>(callerFunc, functionName);
  if (!calleeFunc) {
    OpBuilder::InsertionGuard insertGuard(builder);
    auto module = callerFunc.getParentOfType<ModuleOp>();
    builder.setInsertionPointToStart(module.getBody());
    calleeFunc = builder.create<FuncOp>(
        module.getLoc(), functionName,
        FunctionType::get(SmallVector<Type, 4>(values.getTypes()), returnTypes,
                          builder.getContext()));
    calleeFunc.setPrivate();
  }
  return std_call(calleeFunc, values);
}

MLIRFuncOpConfig &MLIRFuncOpConfig::setNoInline(bool v) {
  noInline = v;
  return *this;
}
MLIRFuncOpConfig &MLIRFuncOpConfig::setPreferAvx512(bool v) {
  preferAvx512 = v;
  return *this;
}
MLIRFuncOpConfig &MLIRFuncOpConfig::setTargetCpu(StringRef s) {
  targetCpu = std::string(s);
  return *this;
}
MLIRFuncOpConfig &MLIRFuncOpConfig::setDeclOnly(bool v) {
  declOnly = v;
  return *this;
}
MLIRFuncOpConfig &MLIRFuncOpConfig::setEmitCInterface(bool v) {
  emitCInterface = v;
  return *this;
}

void MLIRFuncOpConfig::apply(FuncOp &f) {
  MLIRContext *ctx = f.getContext();
  SmallVector<Attribute, 8> attrs;
  if (noInline) attrs.push_back(StringAttr::get("noinline", ctx));
  if (preferAvx512)
    attrs.push_back(ArrayAttr::get({StringAttr::get("prefer-vector-width", ctx),
                                    StringAttr::get("512", ctx)},
                                   ctx));
  if (!targetCpu.empty())
    attrs.push_back(ArrayAttr::get(
        {StringAttr::get("target-cpu", ctx), StringAttr::get(targetCpu, ctx)},
        ctx));
  if (!attrs.empty()) f.setAttr("passthrough", ArrayAttr::get(attrs, ctx));

  if (emitCInterface)
    f.setAttr("llvm.emit_c_interface", mlir::UnitAttr::get(ctx));

  if (!declOnly)
    f.addEntryBlock();
  else
    f.setPrivate();
}

// -----------------------------------------------------------------------------
// EDSC extensions.
// -----------------------------------------------------------------------------
template <typename Lambda>
static SmallVector<Value, 4> valueRangeOperatorImpl(Lambda fun, ValueRange a,
                                                    ValueRange b) {
  SmallVector<Value, 4> res;
  res.reserve(std::min(a.size(), b.size()));
  for (auto it : llvm::zip(a, b))
    res.push_back(fun(std::get<0>(it), std::get<1>(it)));
  return res;
}
SmallVector<Value, 4> mlir::edsc::extensions::operator-(ValueRange a,
                                                        ValueRange b) {
  return valueRangeOperatorImpl(edsc::op::operator-, a, b);
}
SmallVector<Value, 4> mlir::edsc::extensions::operator+(ValueRange a,
                                                        ValueRange b) {
  return valueRangeOperatorImpl(edsc::op::operator+, a, b);
}
SmallVector<Value, 4> mlir::edsc::extensions::std_max(ValueRange a,
                                                      ValueRange b) {
  using edsc::op::slt;
  auto fun = [](Value va, Value vb) { return slt(va, vb) ? vb : va; };
  return valueRangeOperatorImpl(fun, a, b);
}
SmallVector<Value, 4> mlir::edsc::extensions::std_min(ValueRange a,
                                                      ValueRange b) {
  using edsc::op::slt;
  auto fun = [](Value va, Value vb) { return slt(va, vb) ? va : vb; };
  return valueRangeOperatorImpl(fun, a, b);
}
SmallVector<Value, 4> mlir::edsc::extensions::affine_max(ValueRange a,
                                                         ValueRange b) {
  // TODO(ntv): cleanup when affine_max accepts has more idiomatic builders.
  MLIRContext *ctx = ScopedContext::getContext();
  auto map = AffineMap::get(
      2, 0, {getAffineDimExpr(0, ctx), getAffineDimExpr(1, ctx)}, ctx);
  auto fun = [&](Value va, Value vb) {
    return intrinsics::affine_max(map, ValueRange{va, vb});
  };
  return valueRangeOperatorImpl(fun, a, b);
}
SmallVector<Value, 4> mlir::edsc::extensions::affine_min(ValueRange a,
                                                         ValueRange b) {
  // TODO(ntv): cleanup when affine_min accepts has more idiomatic builders.
  MLIRContext *ctx = ScopedContext::getContext();
  auto map = AffineMap::get(
      2, 0, {getAffineDimExpr(0, ctx), getAffineDimExpr(1, ctx)}, ctx);
  auto fun = [&](Value va, Value vb) {
    return intrinsics::affine_min(map, ValueRange{va, vb});
  };
  return valueRangeOperatorImpl(fun, a, b);
}
<commit_msg>Use OpState::operator->() to get to member functions in Operation so we can remove the corresponding methods from OpState.<commit_after>// Copyright 2020 Google LLC
//
// 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
//
//      https://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 "experimental/ModelBuilder/ModelBuilder.h"

#include "mlir/Dialect/Affine/EDSC/Builders.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/GPU/GPUDialect.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/Linalg/IR/LinalgOps.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/Dialect/SCF/SCF.h"
#include "mlir/Dialect/SPIRV/SPIRVDialect.h"
#include "mlir/Dialect/SPIRV/TargetAndABI.h"
#include "mlir/Dialect/Shape/IR/Shape.h"
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/Dialect/Vector/VectorOps.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/StandardTypes.h"
#include "mlir/IR/TypeUtilities.h"

using namespace mlir;
using namespace mlir::edsc;
using namespace mlir::edsc::ops;
using namespace mlir::edsc::intrinsics;

thread_local MLIRContext mlir::ModelBuilder::ctx;

void ModelBuilder::registerAllDialects() {
  // TODO: remove.
}

mlir::ModelBuilder::ModelBuilder()
    : OpBuilder(&ctx),
      module(mlir::ModuleOp::create(mlir::UnknownLoc::get(&ctx))),
      symbolTable(*module),
      loc(module->getLoc()),
      i8(IntegerType::get(8, &ctx)),
      f32(FloatType::getF32(&ctx)),
      f64(FloatType::getF64(&ctx)) {
  ctx.getOrLoadDialect<AffineDialect>();
  ctx.getOrLoadDialect<gpu::GPUDialect>();
  ctx.getOrLoadDialect<LLVM::LLVMDialect>();
  ctx.getOrLoadDialect<linalg::LinalgDialect>();
  ctx.getOrLoadDialect<scf::SCFDialect>();
  ctx.getOrLoadDialect<omp::OpenMPDialect>();
  ctx.getOrLoadDialect<spirv::SPIRVDialect>();
  ctx.getOrLoadDialect<StandardOpsDialect>();
  ctx.getOrLoadDialect<vector::VectorDialect>();
}

Value mlir::ModelBuilder::constant_f32(float v) {
  return std_constant_float(llvm::APFloat(v),
                            FloatType::getF32(ScopedContext::getContext()));
}

Value mlir::ModelBuilder::constant_f64(double v) {
  return std_constant_float(llvm::APFloat(v),
                            FloatType::getF64(ScopedContext::getContext()));
}

Value mlir::ModelBuilder::constant_index(int64_t v) {
  return std_constant_index(v);
}

FuncOp mlir::ModelBuilder::makeFunction(StringRef name, ArrayRef<Type> results,
                                        ArrayRef<Type> args,
                                        MLIRFuncOpConfig config) {
  FunctionType ft = FunctionType::get(args, results, &ctx);
  auto function = FuncOp::create(loc, name, ft);
  config.apply(function);
  module->push_back(function);
  return function;
}
FuncOp mlir::ModelBuilder::makeFunction(
    std::function<std::string(FunctionType)> nameBuilder,
    ArrayRef<Type> results, ArrayRef<Type> args, MLIRFuncOpConfig config) {
  FunctionType ft = FunctionType::get(args, results, &ctx);
  return makeFunction(nameBuilder(ft), results, args, config);
}

static spirv::TargetEnvAttr getTargetEnv(MLIRContext *context) {
  auto triple = spirv::VerCapExtAttr::get(
      spirv::Version::V_1_0,
      {spirv::Capability::Shader, spirv::Capability::CooperativeMatrixNV,
       spirv::Capability::Int8, spirv::Capability::Float16,
       spirv::Capability::StorageUniform16,
       spirv::Capability::StorageBuffer8BitAccess,
       spirv::Capability::Float16Buffer},
      {spirv::Extension::SPV_KHR_storage_buffer_storage_class,
       spirv::Extension::SPV_NV_cooperative_matrix,
       spirv::Extension::SPV_KHR_8bit_storage,
       spirv::Extension::SPV_KHR_16bit_storage},
      context);
  return spirv::TargetEnvAttr::get(triple, spirv::Vendor::Unknown,
                                   spirv::DeviceType::Unknown,
                                   spirv::TargetEnvAttr::kUnknownDeviceID,
                                   spirv::getDefaultResourceLimits(context));
}

gpu::GPUModuleOp mlir::ModelBuilder::makeGPUModule(StringRef name) {
  // Add module attributes required first.
  addGPUAttr();
  OpBuilder b(&module->getBodyRegion());
  auto kernelModule = b.create<gpu::GPUModuleOp>(loc, name);
  return kernelModule;
}

void mlir::ModelBuilder::addGPUAttr() {
  // Add module attributes required first.
  module->setAttr(gpu::GPUDialect::getContainerModuleAttrName(),
                  UnitAttr::get(module->getContext()));
  spirv::TargetEnvAttr targetEnv = getTargetEnv(module->getContext());
  module->setAttr(spirv::getTargetEnvAttrName(), targetEnv);
}

gpu::GPUFuncOp mlir::ModelBuilder::makeGPUKernel(
    StringRef name, gpu::GPUModuleOp GPUModule, ArrayRef<int32_t> workgroupSize,
    ArrayRef<Type> args, ArrayRef<Type> results) {
  auto fnType = FunctionType::get(args, results, module->getContext());
  OpBuilder b(&GPUModule.body());
  auto kernelFunc = b.create<gpu::GPUFuncOp>(loc, name, fnType);
  kernelFunc.setAttr(gpu::GPUDialect::getKernelFuncAttrName(), b.getUnitAttr());
  kernelFunc.setAttr(
      spirv::getEntryPointABIAttrName(),
      spirv::getEntryPointABIAttr(workgroupSize, module->getContext()));
  return kernelFunc;
}

VectorType mlir::ModelBuilder::getVectorType(ArrayRef<int64_t> shape,
                                             Type elementalType) {
  return VectorType::get(shape, elementalType);
}

MemRefType mlir::ModelBuilder::getMemRefType(ArrayRef<int64_t> shape,
                                             Type elementType,
                                             unsigned addressSpace) {
  return MemRefType::get(shape, elementType, {}, addressSpace);
}

RankedTensorType mlir::ModelBuilder::getRankedTensorType(
    ArrayRef<int64_t> shape, Type elementType) {
  return RankedTensorType::get(shape, elementType);
}

Value mlir::ModelBuilder::fusedBiasTanh(Value x, Value bias) {
  using edsc::op::operator+;
  using edsc::op::operator*;
  using edsc::intrinsics::std_call;
  assert(x.getType().isF32() && bias.getType().isF32() && "f32 expected");
  Value half = constant_f32(0.5f);
  return x + half * call_tanhf((x + bias) * half) + half;
}

Value mlir::ModelBuilder::FCBiasTanh(std::array<Value, 3> fcArgs,
                                     Value biasValueArg) {
  //==========================================================================//
  // Layer 1: FC
  //==========================================================================//
  Value I = fcArgs[0], W = fcArgs[1], O = fcArgs[2];
  // Emit a linalg.generic op that implements matmul:
  linalg_generic_matmul(I, W, O);

  //==========================================================================//
  // Layer 2: BiasAddTanh Block
  //==========================================================================//
  // Build and capture AffineExpr i and j for building index expressions.
  AffineExpr i, j;
  bindDims(&ctx, i, j);

  // Emit a linalg.generic op that implements pointwise with `opBuilder` for:
  //   `0.5f * tanh(0.5f * (x + bias)) + 0.5f`
  //
  // This performs the (inplace) computation:
  //   `o[i, j] <- pointwise(bias[j], o[i, j])`
  //
  // in which bias is broadcast along `i`.
  StructuredIndexed o(O), bias(biasValueArg);
  linalg_generic_pointwise(fusedBiasTanh, o({i, j}), bias({j}), o({i, j}));

  return O;
}

Value ModelBuilder::FCBiasTanhTensors(RankedTensorType outputTensorType,
                                      std::array<Value, 2> fcArgs,
                                      Value fcInitTensor, Value biasValueArg) {
  //==========================================================================//
  // Layer 1: FC
  //==========================================================================//
  Value I = fcArgs[0], W = fcArgs[1];
  Value O2 =
      linalg_generic_matmul(I, W, fcInitTensor, outputTensorType)->getResult(0);

  //==========================================================================//
  // Layer 2: BiasAddTanh Block
  //==========================================================================//
  AffineExpr i, j;
  bindDims(&ctx, i, j);
  // in-place with explicit bias broacast
  StructuredIndexed o2(O2), bias(biasValueArg), o3Type(outputTensorType);
  return linalg_generic_pointwise(fusedBiasTanh, o2({i, j}), bias({j}),
                                  o3Type({i, j}))
      ->getResult(0);
}

Value ModelBuilder::call_tanhf(Value v) {
  assert(v.getType().isF32() && "f32 expected");
  return emitCallToRegisteredSymbol("tanhf", v.getType(), v)->getResult(0);
}

void ModelBuilder::call_print_memref_f32(Value v) {
  auto &builder = ScopedContext::getBuilderRef();
  auto loc = builder.getInsertionBlock()
                 ->getParent()
                 ->getParentOfType<FuncOp>()
                 .getLoc();
  auto elementType = v.getType().cast<MemRefType>().getElementType();
  auto unrankedType = UnrankedMemRefType::get(elementType, 0);
  auto castMemRef = builder.create<MemRefCastOp>(loc, v, unrankedType);
  if (elementType.isF32())
    emitCallToRegisteredSymbol("print_memref_f32", {}, {castMemRef});
  else
    llvm_unreachable("Incorrect argument type for print_memref_f32");
}

Operation *ModelBuilder::emitCallToRegisteredSymbol(StringRef functionName,
                                                    ArrayRef<Type> returnTypes,
                                                    ValueRange values) {
  auto &builder = ScopedContext::getBuilderRef();
  auto callerFunc =
      builder.getInsertionBlock()->getParent()->getParentOfType<FuncOp>();
  FuncOp calleeFunc =
      SymbolTable::lookupNearestSymbolFrom<FuncOp>(callerFunc, functionName);
  if (!calleeFunc) {
    OpBuilder::InsertionGuard insertGuard(builder);
    auto module = callerFunc->getParentOfType<ModuleOp>();
    builder.setInsertionPointToStart(module.getBody());
    calleeFunc = builder.create<FuncOp>(
        module.getLoc(), functionName,
        FunctionType::get(SmallVector<Type, 4>(values.getTypes()), returnTypes,
                          builder.getContext()));
    calleeFunc.setPrivate();
  }
  return std_call(calleeFunc, values);
}

MLIRFuncOpConfig &MLIRFuncOpConfig::setNoInline(bool v) {
  noInline = v;
  return *this;
}
MLIRFuncOpConfig &MLIRFuncOpConfig::setPreferAvx512(bool v) {
  preferAvx512 = v;
  return *this;
}
MLIRFuncOpConfig &MLIRFuncOpConfig::setTargetCpu(StringRef s) {
  targetCpu = std::string(s);
  return *this;
}
MLIRFuncOpConfig &MLIRFuncOpConfig::setDeclOnly(bool v) {
  declOnly = v;
  return *this;
}
MLIRFuncOpConfig &MLIRFuncOpConfig::setEmitCInterface(bool v) {
  emitCInterface = v;
  return *this;
}

void MLIRFuncOpConfig::apply(FuncOp &f) {
  MLIRContext *ctx = f.getContext();
  SmallVector<Attribute, 8> attrs;
  if (noInline) attrs.push_back(StringAttr::get("noinline", ctx));
  if (preferAvx512)
    attrs.push_back(ArrayAttr::get({StringAttr::get("prefer-vector-width", ctx),
                                    StringAttr::get("512", ctx)},
                                   ctx));
  if (!targetCpu.empty())
    attrs.push_back(ArrayAttr::get(
        {StringAttr::get("target-cpu", ctx), StringAttr::get(targetCpu, ctx)},
        ctx));
  if (!attrs.empty()) f.setAttr("passthrough", ArrayAttr::get(attrs, ctx));

  if (emitCInterface)
    f.setAttr("llvm.emit_c_interface", mlir::UnitAttr::get(ctx));

  if (!declOnly)
    f.addEntryBlock();
  else
    f.setPrivate();
}

// -----------------------------------------------------------------------------
// EDSC extensions.
// -----------------------------------------------------------------------------
template <typename Lambda>
static SmallVector<Value, 4> valueRangeOperatorImpl(Lambda fun, ValueRange a,
                                                    ValueRange b) {
  SmallVector<Value, 4> res;
  res.reserve(std::min(a.size(), b.size()));
  for (auto it : llvm::zip(a, b))
    res.push_back(fun(std::get<0>(it), std::get<1>(it)));
  return res;
}
SmallVector<Value, 4> mlir::edsc::extensions::operator-(ValueRange a,
                                                        ValueRange b) {
  return valueRangeOperatorImpl(edsc::op::operator-, a, b);
}
SmallVector<Value, 4> mlir::edsc::extensions::operator+(ValueRange a,
                                                        ValueRange b) {
  return valueRangeOperatorImpl(edsc::op::operator+, a, b);
}
SmallVector<Value, 4> mlir::edsc::extensions::std_max(ValueRange a,
                                                      ValueRange b) {
  using edsc::op::slt;
  auto fun = [](Value va, Value vb) { return slt(va, vb) ? vb : va; };
  return valueRangeOperatorImpl(fun, a, b);
}
SmallVector<Value, 4> mlir::edsc::extensions::std_min(ValueRange a,
                                                      ValueRange b) {
  using edsc::op::slt;
  auto fun = [](Value va, Value vb) { return slt(va, vb) ? va : vb; };
  return valueRangeOperatorImpl(fun, a, b);
}
SmallVector<Value, 4> mlir::edsc::extensions::affine_max(ValueRange a,
                                                         ValueRange b) {
  // TODO(ntv): cleanup when affine_max accepts has more idiomatic builders.
  MLIRContext *ctx = ScopedContext::getContext();
  auto map = AffineMap::get(
      2, 0, {getAffineDimExpr(0, ctx), getAffineDimExpr(1, ctx)}, ctx);
  auto fun = [&](Value va, Value vb) {
    return intrinsics::affine_max(map, ValueRange{va, vb});
  };
  return valueRangeOperatorImpl(fun, a, b);
}
SmallVector<Value, 4> mlir::edsc::extensions::affine_min(ValueRange a,
                                                         ValueRange b) {
  // TODO(ntv): cleanup when affine_min accepts has more idiomatic builders.
  MLIRContext *ctx = ScopedContext::getContext();
  auto map = AffineMap::get(
      2, 0, {getAffineDimExpr(0, ctx), getAffineDimExpr(1, ctx)}, ctx);
  auto fun = [&](Value va, Value vb) {
    return intrinsics::affine_min(map, ValueRange{va, vb});
  };
  return valueRangeOperatorImpl(fun, a, b);
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include <algorithm>
#include <array>
#include <atomic>
#include <string>
#include <utility>

#include <actionlib/server/simple_action_server.h>
#include <controller_manager/controller_manager.h>
#include <franka/exception.h>
#include <franka/robot.h>
#include <franka_hw/franka_hw.h>
#include <franka_hw/services.h>
#include <franka_msgs/ErrorRecoveryAction.h>
#include <ros/ros.h>

using franka_hw::ServiceContainer;

int main(int argc, char** argv) {
  ros::init(argc, argv, "franka_control_node");

  ros::NodeHandle public_node_handle;
  ros::NodeHandle node_handle("~");

  franka_hw::FrankaHW franka_control;
  if (!franka_control.init(public_node_handle, node_handle)) {
    ROS_ERROR("franka_control_node: Failed to initialize FrankaHW class. Shutting down!");
    return 1;
  }

  franka::Robot& robot = franka_control.robot();

  std::string realtime_config_param = node_handle.param("realtime_config", std::string("enforce"));
  franka::RealtimeConfig realtime_config;
  if (realtime_config_param == "enforce") {
    realtime_config = franka::RealtimeConfig::kEnforce;
  } else if (realtime_config_param == "ignore") {
    realtime_config = franka::RealtimeConfig::kIgnore;
  } else {
    ROS_ERROR("Invalid realtime_config parameter provided. Valid values are 'enforce', 'ignore'.");
    return 1;
  }

  std::atomic_bool has_error(false);

  ServiceContainer services;
  franka_hw::setupServices(robot, node_handle, services);

  actionlib::SimpleActionServer<franka_msgs::ErrorRecoveryAction> recovery_action_server(
      node_handle, "error_recovery",
      [&](const franka_msgs::ErrorRecoveryGoalConstPtr&) {
        try {
          robot.automaticErrorRecovery();
          has_error = false;
          recovery_action_server.setSucceeded();
          ROS_INFO("Recovered from error");
        } catch (const franka::Exception& ex) {
          recovery_action_server.setAborted(franka_msgs::ErrorRecoveryResult(), ex.what());
        }
      },
      false);

  // Initialize robot state before loading any controller
  franka_control.update(robot.readOnce());

  controller_manager::ControllerManager control_manager(&franka_control, public_node_handle);

  recovery_action_server.start();

  // Start background threads for message handling
  ros::AsyncSpinner spinner(4);
  spinner.start();

  while (ros::ok()) {
    ros::Time last_time = ros::Time::now();

    // Wait until controller has been activated or error has been recovered
    while (!franka_control.controllerActive() || has_error) {
      franka_control.update(robot.readOnce());

      ros::Time now = ros::Time::now();
      control_manager.update(now, now - last_time);
      franka_control.checkJointLimits();
      last_time = now;

      if (!ros::ok()) {
        return 0;
      }
    }

    try {
      // Run control loop. Will exit if the controller is switched.
      franka_control.control([&](const ros::Time& now, const ros::Duration& period) {
        if (period.toSec() == 0.0) {
          // Reset controllers before starting a motion
          control_manager.update(now, period, true);
          franka_control.checkJointLimits();
          franka_control.reset();
        } else {
          control_manager.update(now, period);
          franka_control.checkJointLimits();
          franka_control.enforceLimits(period);
        }
        return ros::ok();
      });
    } catch (const franka::ControlException& e) {
      ROS_ERROR("%s", e.what());
      has_error = true;
    }
  }

  return 0;
}
<commit_msg>removes rt config param parsing from hw node<commit_after>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include <algorithm>
#include <array>
#include <atomic>
#include <string>
#include <utility>

#include <actionlib/server/simple_action_server.h>
#include <controller_manager/controller_manager.h>
#include <franka/exception.h>
#include <franka/robot.h>
#include <franka_hw/franka_hw.h>
#include <franka_hw/services.h>
#include <franka_msgs/ErrorRecoveryAction.h>
#include <ros/ros.h>

using franka_hw::ServiceContainer;

int main(int argc, char** argv) {
  ros::init(argc, argv, "franka_control_node");

  ros::NodeHandle public_node_handle;
  ros::NodeHandle node_handle("~");

  franka_hw::FrankaHW franka_control;
  if (!franka_control.init(public_node_handle, node_handle)) {
    ROS_ERROR("franka_control_node: Failed to initialize FrankaHW class. Shutting down!");
    return 1;
  }

  franka::Robot& robot = franka_control.robot();

  std::atomic_bool has_error(false);

  ServiceContainer services;
  franka_hw::setupServices(robot, node_handle, services);

  actionlib::SimpleActionServer<franka_msgs::ErrorRecoveryAction> recovery_action_server(
      node_handle, "error_recovery",
      [&](const franka_msgs::ErrorRecoveryGoalConstPtr&) {
        try {
          robot.automaticErrorRecovery();
          has_error = false;
          recovery_action_server.setSucceeded();
          ROS_INFO("Recovered from error");
        } catch (const franka::Exception& ex) {
          recovery_action_server.setAborted(franka_msgs::ErrorRecoveryResult(), ex.what());
        }
      },
      false);

  // Initialize robot state before loading any controller
  franka_control.update(robot.readOnce());

  controller_manager::ControllerManager control_manager(&franka_control, public_node_handle);

  recovery_action_server.start();

  // Start background threads for message handling
  ros::AsyncSpinner spinner(4);
  spinner.start();

  while (ros::ok()) {
    ros::Time last_time = ros::Time::now();

    // Wait until controller has been activated or error has been recovered
    while (!franka_control.controllerActive() || has_error) {
      franka_control.update(robot.readOnce());

      ros::Time now = ros::Time::now();
      control_manager.update(now, now - last_time);
      franka_control.checkJointLimits();
      last_time = now;

      if (!ros::ok()) {
        return 0;
      }
    }

    try {
      // Run control loop. Will exit if the controller is switched.
      franka_control.control([&](const ros::Time& now, const ros::Duration& period) {
        if (period.toSec() == 0.0) {
          // Reset controllers before starting a motion
          control_manager.update(now, period, true);
          franka_control.checkJointLimits();
          franka_control.reset();
        } else {
          control_manager.update(now, period);
          franka_control.checkJointLimits();
          franka_control.enforceLimits(period);
        }
        return ros::ok();
      });
    } catch (const franka::ControlException& e) {
      ROS_ERROR("%s", e.what());
      has_error = true;
    }
  }

  return 0;
}
<|endoftext|>