<commit_before>#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <cmath>
#include <vector>
#include <chrono>
#include <SDL/SDL.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <OpenCL/opencl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>

SDL_Surface *surface;
bool done = false;
bool is_active = true;

void
init_sdl ()
{
	const SDL_VideoInfo *video_info;

	if (SDL_Init( SDL_INIT_VIDEO ) < 0)
	{
		fprintf(stderr, "Video initialization failed: %s", SDL_GetError());
		exit(1);
	}

	video_info = SDL_GetVideoInfo();
	if (!video_info)
	{
		fprintf(stderr, "Video info query failed: %s",
		SDL_GetError());
		exit(1);
	}

	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0);

	surface = SDL_SetVideoMode(600, 600, 32, SDL_OPENGL | SDL_GL_DOUBLEBUFFER);
	if (!surface)
	{
		fprintf(stderr, "Video mode set failed: %s", SDL_GetError());
		exit(1);
	}
}

void
resize_viewport ()
{
  glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, 600, 600, 0, -1, 1);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glDisable(GL_DEPTH_TEST);
}

void
init_opengl ()
{
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(20.0f);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);

	resize_viewport();
}

class Vector2
{
	public:
		Vector2 (float _x = 0.0f, float _y = 0.0f)
		{
			x = _x;
			y = _y;
		}

		float
		length ()
		{
			return sqrtf(x*x + y*y);
		}

		float x;
		float y;
};

class Mosquito
{
	public:
		Vector2 velocity;
		Vector2 position;

		static Mosquito
		random ()
		{
			Mosquito m;

			m.velocity.x = (float)(rand() % 1000) / 1000.0f - 0.5f;
			m.velocity.y = (float)(rand() % 1000) / 1000.0f - 0.5f;

			if (rand() % 2 == 0)
			{
				m.position.x = (float)(rand() % 300);
				m.position.y = (float)(rand() % 300);
			}
			else
			{
				m.position.x = (float)(rand() % 300) + 300;
				m.position.y = (float)(rand() % 300) + 300;
			}

			return m;
		}

		void
		draw ()
		{
			glLoadIdentity();
			glColor3ub(0, 99, 0);

			glTranslatef(position.x, position.y, 0.0f);
			glRotatef(atan2(velocity.y, velocity.x) * 180.0f / M_PI + 90.0f, 0.0f, 0.0f, 1.0f);

			glBegin(GL_QUADS);
				glVertex2f(-2.0f, -6.0f);
				glVertex2f( 2.0f, -6.0f);
				glVertex2f( 2.0f,  6.0f);
				glVertex2f(-2.0f,  6.0f);
			glEnd();
		}

};

class Dragonfly
{
	public:
		Vector2 velocity;
		Vector2 position;

		static Dragonfly
		random ()
		{
			Dragonfly d;

			d.velocity.x = (float)(rand() % 1000) / 1000.0f - 0.5f;
			d.velocity.y = (float)(rand() % 1000) / 1000.0f - 0.5f;
			d.position.x = (float)(rand() % 600);
			d.position.y = (float)(rand() % 600);

			return d;
		}

		void
		draw ()
		{
			glLoadIdentity();
			glColor3ub(111, 0, 0);

			glTranslatef(position.x, position.y, 0.0f);
			glRotatef(atan2(velocity.y, velocity.x) * 180.0f / M_PI + 90.0f, 0.0f, 0.0f, 1.0f);

			glBegin(GL_QUADS);
				glVertex2f(-4.0f, -8.0f);
				glVertex2f( 4.0f, -8.0f);
				glVertex2f( 4.0f,  8.0f);
				glVertex2f(-4.0f,  8.0f);
			glEnd();
		}
};

Vector2
operator+ (Vector2 const& _a, Vector2 const& _b)
{
	Vector2 result;
	result.x = _a.x + _b.x;
	result.y = _a.y + _b.y;

	return result;
}

Vector2
operator- (Vector2 const& _a, Vector2 const& _b)
{
	Vector2 result;
	result.x = _a.x - _b.x;
	result.y = _a.y - _b.y;

	return result;
}

Vector2&
operator/= (Vector2& _v, float _s)
{
  _v.x /= _s;
  _v.y /= _s;

  return _v;
}

Vector2&
operator+= (Vector2 & _a, Vector2 const& _b)
{
  _a.x += _b.x;
  _a.y += _b.y;

  return _a;
}

Vector2&
operator-= (Vector2& _a, Vector2& _b)
{
  _a.x -= _b.x;
  _a.y -= _b.y;

  return _a;
}

Vector2
rule_1 (Mosquito& _m, std::vector<Mosquito> _swarm)
{
	Vector2 mass_centre;

	for (auto& m : _swarm)
	{
		if (&_m != &m)
			mass_centre += m.position;
	}
	mass_centre /= (_swarm.size() - 1);

	Vector2 direction = mass_centre - _m.position;
	direction /= 50.0f;

	return direction;
}

Vector2
rule_2 (Mosquito& _m, std::vector<Mosquito> _swarm)
{
	Vector2 centre;

	for(auto& m : _swarm)
	{
		if (&_m != &m)
		{
			Vector2 difference = m.position - _m.position;
			if (difference.length() < 20.0f)
				centre -= difference;
		}
	}

	return centre;
}

Vector2
rule_3 (Mosquito& _m, std::vector<Mosquito> _swarm)
{
	Vector2 velocity;

	for(auto& m : _swarm)
	{
		if (&_m != &m)
		{
			velocity += m.velocity;
		}
	}
	velocity /= (float)(_swarm.size() - 1);

	Vector2 result;
	result = velocity - _m.velocity;
	result /= 2.0f;

	return result;
}

Vector2
rule_4 (Mosquito& _m)
{
	Vector2 top_velocity;
	Vector2 bottom_velocity;
	Vector2 left_velocity;
	Vector2 right_velocity;

	if (_m.position.x == 0.0f || _m.position.y == 0.0f ||
	    _m.position.x == 600.0f || _m.position.y == 600.0f)
		return Vector2();

	top_velocity.y = fabs(20.0f / _m.position.y);
	bottom_velocity.y = -fabs(20.0f / (_m.position.y - 600.0f));
	left_velocity.x = fabs(20.0f / _m.position.x);
	right_velocity.x = -fabs(20.0f / (_m.position.x - 600.0f));

	Vector2 result = top_velocity + bottom_velocity + left_velocity +
	    right_velocity;

	result /= 0.1f;

	return result;
}

Vector2
rule_5 (Mosquito& _m, Dragonfly& _d)
{
	Vector2 result = _m.position - _d.position;
	result /= 60.0;

	return result;
}

Vector2
hunt (Dragonfly& _d, std::vector<Mosquito>& _swarm)
{
	Vector2 closest = _d.position - _swarm[0].position;

	for (auto& m : _swarm)
		if ((_d.position - m.position).length() < closest.length())
			closest = (_d.position - m.position);

	closest /= -35.0f;

	return closest;
}

void
draw_scene (std::vector<Mosquito>& _swarm, Dragonfly& _dragonfly)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

	for (auto& m : _swarm)
		m.draw();

	_dragonfly.draw();
}

std::vector<Mosquito>
step (std::vector<Mosquito>& _swarm, Dragonfly& _dragonfly)
{
	std::vector<Mosquito> new_swarm;

	for (auto& m : _swarm)
	{
		Vector2 v1 = rule_1(m, _swarm);
		Vector2 v2 = rule_2(m, _swarm);
		Vector2 v3 = rule_3(m, _swarm);
		Vector2 v4 = rule_4(m);
		Vector2 v5 = rule_5(m, _dragonfly);

		Vector2 velocity;
		velocity += v1;
		velocity += v2;
		velocity += v3;
		velocity += v4;
		velocity += v5;

		velocity /= 10000.0f;

		Mosquito new_mosquito;
		new_mosquito.velocity = m.velocity + velocity;
		new_mosquito.position = m.position + new_mosquito.velocity;

		if (new_mosquito.velocity.length() > 0.6)
			new_mosquito.velocity /= 10.0f;

		new_swarm.push_back(new_mosquito);
	}

	return new_swarm;
}

void
main_loop (std::vector<Mosquito>& _swarm, Dragonfly& _dragonfly)
{
	is_active = true;
	SDL_Event event;

	while (!done)
	{
		while (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
				case SDL_ACTIVEEVENT:
					if (event.active.state == SDL_APPACTIVE )
						is_active = (event.active.gain != 0);
				break;

				case SDL_QUIT:
					done = true;
				break;

				default:
				break;
			}
		}

		if (is_active)
		{
			_swarm = step(_swarm, _dragonfly);
			_dragonfly.velocity += hunt(_dragonfly, _swarm);
			if (_dragonfly.velocity.length() > 0.2)
				_dragonfly.velocity /= 10.0f;
			_dragonfly.position += _dragonfly.velocity;

			draw_scene(_swarm, _dragonfly);
			SDL_GL_SwapBuffers();
		}
	}
}

int
main (int argc, char *argv[])
{
	const unsigned int N = 20;
	std::vector<Mosquito> swarm;
	srand(time(NULL));

	for (unsigned int i = 0; i < N; i++)
		swarm.push_back(Mosquito::random());

	Dragonfly dragonfly = Dragonfly::random();

  init_sdl();
	init_opengl();

	main_loop(swarm, dragonfly);

	return EXIT_SUCCESS;
}

<commit_msg>OpenCL variables<commit_after>#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <cmath>
#include <vector>
#include <chrono>
#include <SDL/SDL.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <OpenCL/opencl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>

SDL_Surface *surface;
bool done = false;
bool is_active = true;

cl_context context;
cl_int err;
cl_device_id* devices;
cl_device_id device;
cl_platform_id* platforms;
cl_uint num_devices;
cl_platform_id platform;
cl_uint num_platforms;
cl_command_queue command_queue;
cl_program program;
cl_event event;
cl_kernel rule_1_kernel;
cl_kernel rule_2_kernel;
cl_kernel rule_3_kernel;
cl_kernel rule_4_kernel;
cl_kernel rule_5_kernel;
cl_kernel single_step_kernel;

void
init_sdl ()
{
	const SDL_VideoInfo *video_info;

	if (SDL_Init( SDL_INIT_VIDEO ) < 0)
	{
		fprintf(stderr, "Video initialization failed: %s", SDL_GetError());
		exit(1);
	}

	video_info = SDL_GetVideoInfo();
	if (!video_info)
	{
		fprintf(stderr, "Video info query failed: %s",
		SDL_GetError());
		exit(1);
	}

	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0);

	surface = SDL_SetVideoMode(600, 600, 32, SDL_OPENGL | SDL_GL_DOUBLEBUFFER);
	if (!surface)
	{
		fprintf(stderr, "Video mode set failed: %s", SDL_GetError());
		exit(1);
	}
}

void
resize_viewport ()
{
  glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, 600, 600, 0, -1, 1);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glDisable(GL_DEPTH_TEST);
}

void
init_opengl ()
{
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(20.0f);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);

	resize_viewport();
}

class Vector2
{
	public:
		Vector2 (float _x = 0.0f, float _y = 0.0f)
		{
			x = _x;
			y = _y;
		}

		float
		length ()
		{
			return sqrtf(x*x + y*y);
		}

		float x;
		float y;
};

class Mosquito
{
	public:
		Vector2 velocity;
		Vector2 position;

		static Mosquito
		random ()
		{
			Mosquito m;

			m.velocity.x = (float)(rand() % 1000) / 1000.0f - 0.5f;
			m.velocity.y = (float)(rand() % 1000) / 1000.0f - 0.5f;

			if (rand() % 2 == 0)
			{
				m.position.x = (float)(rand() % 300);
				m.position.y = (float)(rand() % 300);
			}
			else
			{
				m.position.x = (float)(rand() % 300) + 300;
				m.position.y = (float)(rand() % 300) + 300;
			}

			return m;
		}

		void
		draw ()
		{
			glLoadIdentity();
			glColor3ub(0, 99, 0);

			glTranslatef(position.x, position.y, 0.0f);
			glRotatef(atan2(velocity.y, velocity.x) * 180.0f / M_PI + 90.0f, 0.0f, 0.0f, 1.0f);

			glBegin(GL_QUADS);
				glVertex2f(-2.0f, -6.0f);
				glVertex2f( 2.0f, -6.0f);
				glVertex2f( 2.0f,  6.0f);
				glVertex2f(-2.0f,  6.0f);
			glEnd();
		}

};

class Dragonfly
{
	public:
		Vector2 velocity;
		Vector2 position;

		static Dragonfly
		random ()
		{
			Dragonfly d;

			d.velocity.x = (float)(rand() % 1000) / 1000.0f - 0.5f;
			d.velocity.y = (float)(rand() % 1000) / 1000.0f - 0.5f;
			d.position.x = (float)(rand() % 600);
			d.position.y = (float)(rand() % 600);

			return d;
		}

		void
		draw ()
		{
			glLoadIdentity();
			glColor3ub(111, 0, 0);

			glTranslatef(position.x, position.y, 0.0f);
			glRotatef(atan2(velocity.y, velocity.x) * 180.0f / M_PI + 90.0f, 0.0f, 0.0f, 1.0f);

			glBegin(GL_QUADS);
				glVertex2f(-4.0f, -8.0f);
				glVertex2f( 4.0f, -8.0f);
				glVertex2f( 4.0f,  8.0f);
				glVertex2f(-4.0f,  8.0f);
			glEnd();
		}
};

Vector2
operator+ (Vector2 const& _a, Vector2 const& _b)
{
	Vector2 result;
	result.x = _a.x + _b.x;
	result.y = _a.y + _b.y;

	return result;
}

Vector2
operator- (Vector2 const& _a, Vector2 const& _b)
{
	Vector2 result;
	result.x = _a.x - _b.x;
	result.y = _a.y - _b.y;

	return result;
}

Vector2&
operator/= (Vector2& _v, float _s)
{
  _v.x /= _s;
  _v.y /= _s;

  return _v;
}

Vector2&
operator+= (Vector2 & _a, Vector2 const& _b)
{
  _a.x += _b.x;
  _a.y += _b.y;

  return _a;
}

Vector2&
operator-= (Vector2& _a, Vector2& _b)
{
  _a.x -= _b.x;
  _a.y -= _b.y;

  return _a;
}

Vector2
rule_1 (Mosquito& _m, std::vector<Mosquito> _swarm)
{
	Vector2 mass_centre;

	for (auto& m : _swarm)
	{
		if (&_m != &m)
			mass_centre += m.position;
	}
	mass_centre /= (_swarm.size() - 1);

	Vector2 direction = mass_centre - _m.position;
	direction /= 50.0f;

	return direction;
}

Vector2
rule_2 (Mosquito& _m, std::vector<Mosquito> _swarm)
{
	Vector2 centre;

	for(auto& m : _swarm)
	{
		if (&_m != &m)
		{
			Vector2 difference = m.position - _m.position;
			if (difference.length() < 20.0f)
				centre -= difference;
		}
	}

	return centre;
}

Vector2
rule_3 (Mosquito& _m, std::vector<Mosquito> _swarm)
{
	Vector2 velocity;

	for(auto& m : _swarm)
	{
		if (&_m != &m)
		{
			velocity += m.velocity;
		}
	}
	velocity /= (float)(_swarm.size() - 1);

	Vector2 result;
	result = velocity - _m.velocity;
	result /= 2.0f;

	return result;
}

Vector2
rule_4 (Mosquito& _m)
{
	Vector2 top_velocity;
	Vector2 bottom_velocity;
	Vector2 left_velocity;
	Vector2 right_velocity;

	if (_m.position.x == 0.0f || _m.position.y == 0.0f ||
	    _m.position.x == 600.0f || _m.position.y == 600.0f)
		return Vector2();

	top_velocity.y = fabs(20.0f / _m.position.y);
	bottom_velocity.y = -fabs(20.0f / (_m.position.y - 600.0f));
	left_velocity.x = fabs(20.0f / _m.position.x);
	right_velocity.x = -fabs(20.0f / (_m.position.x - 600.0f));

	Vector2 result = top_velocity + bottom_velocity + left_velocity +
	    right_velocity;

	result /= 0.1f;

	return result;
}

Vector2
rule_5 (Mosquito& _m, Dragonfly& _d)
{
	Vector2 result = _m.position - _d.position;
	result /= 60.0;

	return result;
}

Vector2
hunt (Dragonfly& _d, std::vector<Mosquito>& _swarm)
{
	Vector2 closest = _d.position - _swarm[0].position;

	for (auto& m : _swarm)
		if ((_d.position - m.position).length() < closest.length())
			closest = (_d.position - m.position);

	closest /= -35.0f;

	return closest;
}

void
draw_scene (std::vector<Mosquito>& _swarm, Dragonfly& _dragonfly)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

	for (auto& m : _swarm)
		m.draw();

	_dragonfly.draw();
}

std::vector<Mosquito>
step (std::vector<Mosquito>& _swarm, Dragonfly& _dragonfly)
{
	std::vector<Mosquito> new_swarm;

	for (auto& m : _swarm)
	{
		Vector2 v1 = rule_1(m, _swarm);
		Vector2 v2 = rule_2(m, _swarm);
		Vector2 v3 = rule_3(m, _swarm);
		Vector2 v4 = rule_4(m);
		Vector2 v5 = rule_5(m, _dragonfly);

		Vector2 velocity;
		velocity += v1;
		velocity += v2;
		velocity += v3;
		velocity += v4;
		velocity += v5;

		velocity /= 10000.0f;

		Mosquito new_mosquito;
		new_mosquito.velocity = m.velocity + velocity;
		new_mosquito.position = m.position + new_mosquito.velocity;

		if (new_mosquito.velocity.length() > 0.6)
			new_mosquito.velocity /= 10.0f;

		new_swarm.push_back(new_mosquito);
	}

	return new_swarm;
}

void
main_loop (std::vector<Mosquito>& _swarm, Dragonfly& _dragonfly)
{
	is_active = true;
	SDL_Event event;

	while (!done)
	{
		while (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
				case SDL_ACTIVEEVENT:
					if (event.active.state == SDL_APPACTIVE )
						is_active = (event.active.gain != 0);
				break;

				case SDL_QUIT:
					done = true;
				break;

				default:
				break;
			}
		}

		if (is_active)
		{
			_swarm = step(_swarm, _dragonfly);
			_dragonfly.velocity += hunt(_dragonfly, _swarm);
			if (_dragonfly.velocity.length() > 0.2)
				_dragonfly.velocity /= 10.0f;
			_dragonfly.position += _dragonfly.velocity;

			draw_scene(_swarm, _dragonfly);
			SDL_GL_SwapBuffers();
		}
	}
}

int
main (int argc, char *argv[])
{
	const unsigned int N = 20;
	std::vector<Mosquito> swarm;
	srand(time(NULL));

	for (unsigned int i = 0; i < N; i++)
		swarm.push_back(Mosquito::random());

	Dragonfly dragonfly = Dragonfly::random();

  init_sdl();
	init_opengl();

	main_loop(swarm, dragonfly);

	return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      rdoparser_rdo.cpp
  \authors
  \authors     (rdo@rk9.bmstu.ru)
  \date
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
#include "simulator/compiler/parser/pch.h"
// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/rdo_activity_i.h"
#include "simulator/compiler/parser/rdoparser_rdo.h"
#include "simulator/compiler/parser/rdoparser_lexer.h"
#include "simulator/compiler/parser/rdoparser.h"
#include "simulator/compiler/parser/rdosmr.h"
#include "simulator/compiler/parser/rdorss.h"
#include "simulator/compiler/parser/rdortp.h"
#include "simulator/compiler/parser/rdofun.h"
#include "simulator/compiler/parser/rdosmr.h"
#include "simulator/compiler/parser/rdopat.h"
#include "simulator/runtime/rdo_pattern.h"
#include "utils/rdostream.h"
#include "kernel/rdokernel.h"
#include "repository/rdorepository.h"
#include "simulator/runtime/calc/std_fun.h"
// --------------------------------------------------------------------------------

OPEN_RDO_PARSER_NAMESPACE

// --------------------------------------------------------------------------------
// -------------------- RDOParserRDOItem
// --------------------------------------------------------------------------------
RDOParserRDOItem::RDOParserRDOItem(rdoModelObjects::RDOFileType type, t_bison_parse_fun parser_fun, t_bison_error_fun error_fun, t_flex_lexer_fun lexer_fun, StreamFrom from)
	: RDOParserItem(type, parser_fun, error_fun, lexer_fun, from)
	, m_pLexer(NULL)
{}

RDOParserRDOItem::~RDOParserRDOItem()
{
	if (m_pLexer)
	{
		delete m_pLexer;
		m_pLexer = NULL;
	}
}

void RDOParserRDOItem::parse(CREF(LPRDOParser) pParser)
{
	ASSERT(pParser);

	rdo::binarystream in_stream;
	switch (m_from)
	{
		case sf_repository:
		{
			rdoRepository::RDOThreadRepository::FileData fileData(m_type, in_stream);
			kernel->sendMessage(kernel->repository(), RDOThread::RT_REPOSITORY_LOAD, &fileData);
			break;
		}
		case sf_editor:
		{
			rdoRepository::RDOThreadRepository::FileData fileData(m_type, in_stream);
			kernel->sendMessage(kernel->studio(), RDOThread::RT_STUDIO_MODEL_GET_TEXT, &fileData);
			break;
		}
	}
	if (in_stream.good())
	{
		parse(pParser, in_stream);
	}
}

void RDOParserRDOItem::parse(CREF(LPRDOParser) pParser, REF(std::istream) in_stream)
{
	ASSERT(pParser);

	if (m_pLexer)
		delete m_pLexer;

	std::ostringstream out_stream;
	m_pLexer = getLexer(pParser, &in_stream, &out_stream);

	if (m_pLexer && m_parser_fun)
		m_parser_fun(m_pLexer);
}

PTR(RDOLexer) RDOParserRDOItem::getLexer(CREF(LPRDOParser) pParser, PTR(std::istream) in_stream, PTR(std::ostream) out_stream)
{
	ASSERT(pParser);
	return new RDOLexer(pParser, in_stream, out_stream);
}

ruint RDOParserRDOItem::lexer_loc_line()
{
	if (m_pLexer)
	{
		return m_pLexer->m_lploc ? m_pLexer->m_lploc->m_first_line : m_pLexer->lineno();
	}
	else
	{
		return ruint(rdoRuntime::RDOSrcInfo::Position::UNDEFINE_LINE);
	}
}

ruint RDOParserRDOItem::lexer_loc_pos()
{
	return m_pLexer && m_pLexer->m_lploc ? m_pLexer->m_lploc->m_first_pos : 0;
}

// --------------------------------------------------------------------------------
// -------------------- RDOParserRSS
// --------------------------------------------------------------------------------
RDOParserRSS::RDOParserRSS(StreamFrom from)
	: RDOParserRDOItem(rdoModelObjects::RSS, rssparse, rsserror, rsslex, from)
{}

void RDOParserRSS::parse(CREF(LPRDOParser) pParser)
{
	ASSERT(pParser);
	pParser->setHaveKWResources   (false);
	pParser->setHaveKWResourcesEnd(false);
	RDOParserRDOItem::parse(pParser);
}

// --------------------------------------------------------------------------------
// -------------------- RDOParserRSSPost
// --------------------------------------------------------------------------------
void RDOParserRSSPost::parse(CREF(LPRDOParser) pParser)
{
	ASSERT(pParser);

	//!            ,        RSS
#ifdef RDOSIM_COMPATIBLE
	STL_FOR_ALL_CONST(pParser->getRTPResType(), rtp_it)
	{
#endif
		STL_FOR_ALL_CONST(pParser->getRSSResources(), rss_it)
		{
#ifdef RDOSIM_COMPATIBLE
			if ((*rss_it)->getType() == *rtp_it)
			{
#endif
				rdoRuntime::LPRDOCalc calc = (*rss_it)->createCalc();
				pParser->runtime()->addInitCalc(calc);
#ifdef RDOSIM_COMPATIBLE
			}
#endif
		}
#ifdef RDOSIM_COMPATIBLE
	}
#endif
}

// --------------------------------------------------------------------------------
// -------------------- RDOParserSMRPost
// --------------------------------------------------------------------------------
RDOParserSMRPost::RDOParserSMRPost()
	: RDOParserItem(rdoModelObjects::SMR, NULL, NULL, NULL)
{}

void RDOParserSMRPost::parse(CREF(LPRDOParser) pParser)
{
	ASSERT(pParser);

	//!  ,   SMR
	STL_FOR_ALL_CONST(pParser->getEvents(), eventIt)
	{
		LPRDOEvent pEvent = *eventIt;
		ASSERT(pEvent);

		rdoRuntime::LPRDOCalc pInitCalc = pEvent->getInitCalc();
		if (pInitCalc)
		{
			pParser->runtime()->addInitCalc(pInitCalc);
		}
	}
}

// --------------------------------------------------------------------------------
// -------------------- RDOParserEVNPost
// --------------------------------------------------------------------------------
void RDOParserEVNPost::parse(CREF(LPRDOParser) pParser)
{
	ASSERT(pParser);

	//!
	STL_FOR_ALL_CONST(pParser->getEvents(), eventIt)
	{
		LPRDOEvent pEvent = *eventIt;

		LPRDOPATPattern pPattern = pParser->findPATPattern(pEvent->name());
		if (!pPattern)
		{
			STL_FOR_ALL_CONST(pEvent->getCalcList(), calcIt)
			{
				pParser->error().push_only((*calcIt)->src_info(), rdo::format(_T("   : %s"), pEvent->name().c_str()));
			}
			pParser->error().push_done();
		}
		if (pPattern->getType() != RDOPATPattern::PT_Event)
		{
			STL_FOR_ALL_CONST(pEvent->getCalcList(), calcIt)
			{
				pParser->error().push_only((*calcIt)->src_info(), rdo::format(_T(" %s   : %s"), pEvent->name().c_str()));
			}
			pParser->error().push_done();
		}

		if (pEvent->getRegular())
		{
			LPIBaseOperation pRuntimeEvent = pPattern->getPatRuntime<rdoRuntime::RDOPatternEvent>()->createActivity(pParser->runtime()->m_pMetaLogic, pParser->runtime(), pEvent->name());
			ASSERT(pRuntimeEvent);
			pEvent->setRuntimeEvent(pRuntimeEvent);

			STL_FOR_ALL(pEvent->getCalcList(), calcIt)
			{
				(*calcIt)->setEvent(pRuntimeEvent);
			}

			LPIActivity pActivity = pRuntimeEvent;
			ASSERT(pActivity);
			STL_FOR_ALL_CONST(pEvent->getParamList()->getContainer(), paramIT)
			{
				LPRDOFUNArithm pParam = *paramIT;
				if (m_currParam < pPattern->m_paramList.size())
				{
					rdoRuntime::LPRDOCalc pSetParamCalc;
					LPRDOParam pPatternParam = pPattern->m_paramList[m_currParam];
					ASSERT(pPatternParam);
					if (pParam->typeInfo()->src_info().src_text() == _T("*"))
					{
						if (!pPatternParam->getDefault()->defined())
						{
							RDOParser::s_parser()->error().push_only(pPatternParam->src_info(), rdo::format(_T("  -   '%s'"), pPatternParam->src_text().c_str()));
							RDOParser::s_parser()->error().push_only(pPatternParam->src_info(), rdo::format(_T(".  '%s',  '%s'"), pPatternParam->src_text().c_str(), pPatternParam->getTypeInfo()->src_info().src_text().c_str()));
							RDOParser::s_parser()->error().push_done();
						}
						rdoRuntime::RDOValue val = pPatternParam->getDefault()->value();
						ASSERT(val);
						pSetParamCalc = rdo::Factory<rdoRuntime::RDOSetPatternParamCalc>::create(
							m_currParam,
							rdo::Factory<rdoRuntime::RDOCalcConst>::create(val)
						);
					}
					else
					{
						LPTypeInfo pTypeInfo = pPatternParam->getTypeInfo();
						ASSERT(pTypeInfo);
						rdoRuntime::LPRDOCalc pParamValueCalc = pParam->createCalc(pTypeInfo);
						ASSERT(pParamValueCalc);
						pSetParamCalc = rdo::Factory<rdoRuntime::RDOSetPatternParamCalc>::create(
							m_currParam,
							pParamValueCalc
						);
					}
					ASSERT(pSetParamCalc);
					pActivity->addParamCalc(pSetParamCalc);
					++m_currParam;
				}
				else
				{
					RDOParser::s_parser()->error().push_only(pParam->src_info(), rdo::format(_T("     '%s'    '%s'"), pEvent->name().c_str(), pEvent->name().c_str()));
					RDOParser::s_parser()->error().push_done();
				}
			}
			m_currParam = 0;
		}
		else
		{
			NEVER_REACH_HERE; //
		}
	}
}

CLOSE_RDO_PARSER_NAMESPACE
<commit_msg> - форматирование<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      rdoparser_rdo.cpp
  \authors
  \authors     (rdo@rk9.bmstu.ru)
  \date
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
#include "simulator/compiler/parser/pch.h"
// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/rdo_activity_i.h"
#include "simulator/compiler/parser/rdoparser_rdo.h"
#include "simulator/compiler/parser/rdoparser_lexer.h"
#include "simulator/compiler/parser/rdoparser.h"
#include "simulator/compiler/parser/rdosmr.h"
#include "simulator/compiler/parser/rdorss.h"
#include "simulator/compiler/parser/rdortp.h"
#include "simulator/compiler/parser/rdofun.h"
#include "simulator/compiler/parser/rdosmr.h"
#include "simulator/compiler/parser/rdopat.h"
#include "simulator/runtime/rdo_pattern.h"
#include "utils/rdostream.h"
#include "kernel/rdokernel.h"
#include "repository/rdorepository.h"
#include "simulator/runtime/calc/std_fun.h"
// --------------------------------------------------------------------------------

OPEN_RDO_PARSER_NAMESPACE

// --------------------------------------------------------------------------------
// -------------------- RDOParserRDOItem
// --------------------------------------------------------------------------------
RDOParserRDOItem::RDOParserRDOItem(rdoModelObjects::RDOFileType type, t_bison_parse_fun parser_fun, t_bison_error_fun error_fun, t_flex_lexer_fun lexer_fun, StreamFrom from)
	: RDOParserItem(type, parser_fun, error_fun, lexer_fun, from)
	, m_pLexer(NULL)
{}

RDOParserRDOItem::~RDOParserRDOItem()
{
	if (m_pLexer)
	{
		delete m_pLexer;
		m_pLexer = NULL;
	}
}

void RDOParserRDOItem::parse(CREF(LPRDOParser) pParser)
{
	ASSERT(pParser);

	rdo::binarystream in_stream;
	switch (m_from)
	{
		case sf_repository:
		{
			rdoRepository::RDOThreadRepository::FileData fileData(m_type, in_stream);
			kernel->sendMessage(kernel->repository(), RDOThread::RT_REPOSITORY_LOAD, &fileData);
			break;
		}
		case sf_editor:
		{
			rdoRepository::RDOThreadRepository::FileData fileData(m_type, in_stream);
			kernel->sendMessage(kernel->studio(), RDOThread::RT_STUDIO_MODEL_GET_TEXT, &fileData);
			break;
		}
	}
	if (in_stream.good())
	{
		parse(pParser, in_stream);
	}
}

void RDOParserRDOItem::parse(CREF(LPRDOParser) pParser, REF(std::istream) in_stream)
{
	ASSERT(pParser);

	if (m_pLexer)
		delete m_pLexer;

	std::ostringstream out_stream;
	m_pLexer = getLexer(pParser, &in_stream, &out_stream);

	if (m_pLexer && m_parser_fun)
		m_parser_fun(m_pLexer);
}

PTR(RDOLexer) RDOParserRDOItem::getLexer(CREF(LPRDOParser) pParser, PTR(std::istream) in_stream, PTR(std::ostream) out_stream)
{
	ASSERT(pParser);
	return new RDOLexer(pParser, in_stream, out_stream);
}

ruint RDOParserRDOItem::lexer_loc_line()
{
	if (m_pLexer)
	{
		return m_pLexer->m_lploc ? m_pLexer->m_lploc->m_first_line : m_pLexer->lineno();
	}
	else
	{
		return ruint(rdoRuntime::RDOSrcInfo::Position::UNDEFINE_LINE);
	}
}

ruint RDOParserRDOItem::lexer_loc_pos()
{
	return m_pLexer && m_pLexer->m_lploc ? m_pLexer->m_lploc->m_first_pos : 0;
}

// --------------------------------------------------------------------------------
// -------------------- RDOParserRSS
// --------------------------------------------------------------------------------
RDOParserRSS::RDOParserRSS(StreamFrom from)
	: RDOParserRDOItem(rdoModelObjects::RSS, rssparse, rsserror, rsslex, from)
{}

void RDOParserRSS::parse(CREF(LPRDOParser) pParser)
{
	ASSERT(pParser);
	pParser->setHaveKWResources   (false);
	pParser->setHaveKWResourcesEnd(false);
	RDOParserRDOItem::parse(pParser);
}

// --------------------------------------------------------------------------------
// -------------------- RDOParserRSSPost
// --------------------------------------------------------------------------------
void RDOParserRSSPost::parse(CREF(LPRDOParser) pParser)
{
	ASSERT(pParser);

	//!            ,        RSS
#ifdef RDOSIM_COMPATIBLE
	STL_FOR_ALL_CONST(pParser->getRTPResType(), rtp_it)
	{
#endif
		STL_FOR_ALL_CONST(pParser->getRSSResources(), rss_it)
		{
#ifdef RDOSIM_COMPATIBLE
			if ((*rss_it)->getType() == *rtp_it)
			{
#endif
				rdoRuntime::LPRDOCalc calc = (*rss_it)->createCalc();
				pParser->runtime()->addInitCalc(calc);
#ifdef RDOSIM_COMPATIBLE
			}
#endif
		}
#ifdef RDOSIM_COMPATIBLE
	}
#endif
}

// --------------------------------------------------------------------------------
// -------------------- RDOParserSMRPost
// --------------------------------------------------------------------------------
RDOParserSMRPost::RDOParserSMRPost()
	: RDOParserItem(rdoModelObjects::SMR, NULL, NULL, NULL)
{}

void RDOParserSMRPost::parse(CREF(LPRDOParser) pParser)
{
	ASSERT(pParser);

	//!  ,   SMR
	STL_FOR_ALL_CONST(pParser->getEvents(), eventIt)
	{
		LPRDOEvent pEvent = *eventIt;
		ASSERT(pEvent);

		rdoRuntime::LPRDOCalc pInitCalc = pEvent->getInitCalc();
		if (pInitCalc)
		{
			pParser->runtime()->addInitCalc(pInitCalc);
		}
	}
}

// --------------------------------------------------------------------------------
// -------------------- RDOParserEVNPost
// --------------------------------------------------------------------------------
void RDOParserEVNPost::parse(CREF(LPRDOParser) pParser)
{
	ASSERT(pParser);

	//!
	STL_FOR_ALL_CONST(pParser->getEvents(), eventIt)
	{
		LPRDOEvent pEvent = *eventIt;

		LPRDOPATPattern pPattern = pParser->findPATPattern(pEvent->name());
		if (!pPattern)
		{
			STL_FOR_ALL_CONST(pEvent->getCalcList(), calcIt)
			{
				pParser->error().push_only((*calcIt)->src_info(), rdo::format(_T("   : %s"), pEvent->name().c_str()));
			}
			pParser->error().push_done();
		}
		if (pPattern->getType() != RDOPATPattern::PT_Event)
		{
			STL_FOR_ALL_CONST(pEvent->getCalcList(), calcIt)
			{
				pParser->error().push_only((*calcIt)->src_info(), rdo::format(_T(" %s   : %s"), pEvent->name().c_str()));
			}
			pParser->error().push_done();
		}

		if (pEvent->getRegular())
		{
			LPIBaseOperation pRuntimeEvent = pPattern->getPatRuntime<rdoRuntime::RDOPatternEvent>()->createActivity(pParser->runtime()->m_pMetaLogic, pParser->runtime(), pEvent->name());
			ASSERT(pRuntimeEvent);
			pEvent->setRuntimeEvent(pRuntimeEvent);

			STL_FOR_ALL(pEvent->getCalcList(), calcIt)
			{
				(*calcIt)->setEvent(pRuntimeEvent);
			}

			LPIActivity pActivity = pRuntimeEvent;
			ASSERT(pActivity);
			STL_FOR_ALL_CONST(pEvent->getParamList()->getContainer(), paramIt)
			{
				LPRDOFUNArithm pParam = *paramIt;
				ASSERT(pParam);
				if (m_currParam < pPattern->m_paramList.size())
				{
					rdoRuntime::LPRDOCalc pSetParamCalc;
					LPRDOParam pPatternParam = pPattern->m_paramList[m_currParam];
					ASSERT(pPatternParam);
					if (pParam->typeInfo()->src_info().src_text() == _T("*"))
					{
						if (!pPatternParam->getDefault()->defined())
						{
							RDOParser::s_parser()->error().push_only(pPatternParam->src_info(), rdo::format(_T("  -   '%s'"), pPatternParam->src_text().c_str()));
							RDOParser::s_parser()->error().push_only(pPatternParam->src_info(), rdo::format(_T(".  '%s',  '%s'"), pPatternParam->src_text().c_str(), pPatternParam->getTypeInfo()->src_info().src_text().c_str()));
							RDOParser::s_parser()->error().push_done();
						}
						rdoRuntime::RDOValue val = pPatternParam->getDefault()->value();
						ASSERT(val);
						pSetParamCalc = rdo::Factory<rdoRuntime::RDOSetPatternParamCalc>::create(
							m_currParam,
							rdo::Factory<rdoRuntime::RDOCalcConst>::create(val)
						);
					}
					else
					{
						LPTypeInfo pTypeInfo = pPatternParam->getTypeInfo();
						ASSERT(pTypeInfo);
						rdoRuntime::LPRDOCalc pParamValueCalc = pParam->createCalc(pTypeInfo);
						ASSERT(pParamValueCalc);
						pSetParamCalc = rdo::Factory<rdoRuntime::RDOSetPatternParamCalc>::create(
							m_currParam,
							pParamValueCalc
						);
					}
					ASSERT(pSetParamCalc);
					pActivity->addParamCalc(pSetParamCalc);
					++m_currParam;
				}
				else
				{
					RDOParser::s_parser()->error().push_only(pParam->src_info(), rdo::format(_T("     '%s'    '%s'"), pEvent->name().c_str(), pEvent->name().c_str()));
					RDOParser::s_parser()->error().push_done();
				}
			}
			m_currParam = 0;
		}
		else
		{
			NEVER_REACH_HERE; //
		}
	}
}

CLOSE_RDO_PARSER_NAMESPACE
<|endoftext|>


<commit_before><% moduleNamespace = api_generator_cpp_MakeNamespace($cur_module.parents) %>

#include "<%= $cur_module.name %>Base.h"
#include "api_generator/js_helpers.h"

#include "logging/RhoLog.h"
#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "<%= $cur_module.name %>"

#include "common/StringConverter.h"

extern "C" void rho_wm_impl_performOnUiThread(rho::common::IRhoRunnable* pTask);

using namespace rho;
using namespace rho::json;
using namespace rho::common;
using namespace rho::apiGenerator;

<% $cur_module.methods.each do |module_method|
   if module_method.generateNativeAPI %>
<%= api_generator_MakeJSMethodDecl($cur_module.name, module_method.native_name, module_method.access == ModuleMethod::ACCESS_STATIC)%>
{
    RAWTRACE3("<%=module_method.native_name%>(strObjID = %s, strCallbackID = %s, strJsVmID = %s)", strObjID.c_str(), strCallbackID.c_str(), strJsVmID.c_str());

    rho::apiGenerator::CMethodResult oRes;

<% if module_method.result != nil
    if module_method.result.sub_param && module_method.result.sub_param.name %>
    oRes.setParamName( "<%= module_method.result.sub_param.name %>" );<%
    end

    result_type = nil
    if MethodParam::BASE_TYPES.include?(module_method.result.type)
      result_type = module_method.result.item_type
    else
      result_type = module_method.result.type;
    end

if api_generator_isSelfModule( $cur_module, result_type) %>
    oRes.setJSObjectClassPath( "<%= api_generator_getJSModuleName(api_generator_getRubyModuleFullName($cur_module))%>" );<%
elsif result_type && result_type.length()>0 && !MethodParam::BASE_TYPES.include?(result_type) %>
    oRes.setJSObjectClassPath( "<%= api_generator_getJSModuleName(result_type) %>" );<%
    if !module_method.linked_entity.nil?%>
    oRes.setResultAsEntity();
<% end
end; end

if module_method.linked_property && module_method.special_behaviour == ModuleMethod::SPECIAL_BEHAVIOUR_GETTER %>
    oRes.setRequestedType(<%= api_generator_cpp_makeMethodResultType(module_method.linked_property.type) %>);<%
elsif module_method.result && module_method.result.type %>
    oRes.setRequestedType(<%= api_generator_cpp_makeMethodResultType(module_method.result.type) %>);<%
end %>

    rho::common::CInstanceClassFunctorBase<rho::apiGenerator::CMethodResult>* pFunctor = 0;
    int argc = argv.getSize();
<% if module_method.access != ModuleMethod::ACCESS_STATIC %>
    <%= moduleNamespace%>I<%= $cur_module.name %>* pObj = <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::getInstance()->getModuleByID(strObjID);
<%end%>

<% functor_params = ""; first_arg = 0;
   module_method.params.each do |param| %>
    <% if !param.can_be_nil %>
    if ( argc == <%= first_arg %> )
    {
        oRes.setArgError( "Wrong number of arguments: " + convertToStringA(argc) + " instead of " + convertToStringA(<%= module_method.params.size() %>) );
        return oRes.toJSON();
    }
    <% end %>

<% if param.type == MethodParam::TYPE_STRING %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %> = "<%= param.default_value ? param.default_value : "" %>";
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isString() )
        {
            arg<%= first_arg %> = argv[<%= first_arg %>].getStringObject();
        }
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError( "Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_INT %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %> = <%= param.default_value ? param.default_value : 0 %>;
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isInteger() )
            arg<%= first_arg %> = argv[<%= first_arg %>].getInt();
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError("Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_BOOL %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %> = <%= param.default_value ? param.default_value : false %>;
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isBoolean() )
            arg<%= first_arg %> = argv[<%= first_arg %>].getBoolean();
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError("Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_DOUBLE %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %> = <%= param.default_value ? param.default_value : 0 %>;
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isFloat() )
            arg<%= first_arg %> = argv[<%= first_arg %>].getDouble();
        else if ( argv[<%= first_arg %>].isInteger() )
            arg<%= first_arg %> = (int64)argv[<%= first_arg %>].getUInt64();
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError("Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_ARRAY %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isArray() )
        {
            CJSONArray arParam(argv[<%= first_arg %>]);
            for( int i = 0; i < arParam.getSize(); i++ )
            {
                arg<%= first_arg %>.addElement( arParam[i].getStringObject() );
            }
        }
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError("Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_HASH %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isObject() )
        {
            CJSONStructIterator objIter(argv[<%= first_arg %>]);

            for( ; !objIter.isEnd(); objIter.next() )
            {
                arg<%= first_arg %>[objIter.getCurKey()] = objIter.getCurString();
            }
        }
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError("Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if !MethodParam::BASE_TYPES.include?(param.type) %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
<% end %>

<% functor_params += "arg#{first_arg}, " %>
<% first_arg = first_arg+1 %>
<% end %>

<% if module_method.has_callback != ModuleMethod::CALLBACK_NONE %>
    oRes.setCallInUIThread(<%= (module_method.run_in_thread == ModuleMethod::RUN_IN_THREAD_UI) ? "true" : "false" %>);
    oRes.setJSCallback( strCallbackID );
    oRes.setCallbackParam( strCallbackParam );
<% end %>

<% numParams = module_method.params.size()+1
if module_method.access != ModuleMethod::ACCESS_STATIC
    nativeInterfaceFunc = "#{moduleNamespace}I#{$cur_module.name}::#{module_method.native_name}"
    functorWar = "pFunctor = rho_makeInstanceClassFunctor#{numParams}( pObj, &#{nativeInterfaceFunc}, #{functor_params} oRes );"
else
    nativeSingleton = "#{moduleNamespace}C#{$cur_module.name}FactoryBase::get#{$cur_module.name}SingletonS()"
    nativeSingletonMethod = "#{moduleNamespace}I#{$cur_module.name}Singleton::#{module_method.native_name}"
    functorWar = "pFunctor = rho_makeInstanceClassFunctor#{numParams}( #{nativeSingleton}, &#{nativeSingletonMethod}, #{functor_params} oRes );"
end

if module_method.run_in_thread == ModuleMethod::RUN_IN_THREAD_UI %>
    <%= functorWar %>
    rho_wm_impl_performOnUiThread( pFunctor );<%
elsif (module_method.run_in_thread == ModuleMethod::RUN_IN_THREAD_MODULE) || (module_method.run_in_thread == ModuleMethod::RUN_IN_THREAD_SEPARATED) %>
    <%= functorWar %>
    <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->addCommandToQueue( pFunctor );<%
else if module_method.run_in_thread != ModuleMethod::RUN_IN_THREAD_NONE %>
    if ( oRes.hasCallback() )
    {
        <%= functorWar %>
        <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->addCommandToQueue( pFunctor );
    }
    else <%
end %>
    {
<% if module_method.access != ModuleMethod::ACCESS_STATIC %>
        pObj-><%= module_method.native_name %>( <%= functor_params %> oRes );<%
else %>
        <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()-><%= module_method.native_name %>( <%= functor_params %> oRes );<%
end %>
    }<% end %>

    return oRes.toJSON();

}
<% end
   end %>

<% if $cur_module.is_template_default_instance %>
<%= api_generator_MakeJSMethodDecl($cur_module.name, "getDefaultID", true)%>
{
    rho::apiGenerator::CMethodResult oRes;
    rho::String strDefaultID = <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->getDefaultID();
    oRes.set(strDefaultID);

    return oRes.toJSON();
}

<%= api_generator_MakeJSMethodDecl($cur_module.name, "getDefault", true)%>
{
    rho::apiGenerator::CMethodResult oRes;
    rho::String strDefaultID = <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->getDefaultID();
    oRes.set(strDefaultID);
    oRes.setJSObjectClassPath("<%= api_generator_getJSModuleName(api_generator_getRubyModuleFullName($cur_module))%>");

    return oRes.toJSON();
}

<%= api_generator_MakeJSMethodDecl($cur_module.name, "setDefaultID", true)%>
{
    rho::apiGenerator::CMethodResult oRes;
    rho::json::CJSONEntry el = argv[0];

    if (el.isString()) {
        <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->setDefaultID(el.getString());
    } else {
        oRes.setError("Method parameter should be defined as string!");
    }

    return oRes.toJSON();
}

<% end %>
<commit_msg>Android: UGLY HACK to init JNIEnv in JS thread.<commit_after><% moduleNamespace = api_generator_cpp_MakeNamespace($cur_module.parents) %>

#include "<%= $cur_module.name %>Base.h"
#include "api_generator/js_helpers.h"

#include "logging/RhoLog.h"
#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "<%= $cur_module.name %>"

#include "common/StringConverter.h"

extern "C" void rho_wm_impl_performOnUiThread(rho::common::IRhoRunnable* pTask);

#ifdef OS_ANDROID
#include <jni.h>
extern "C" void* rho_nativethread_start();
JNIEnv* jnienv();
#endif //OS_ANDROID

using namespace rho;
using namespace rho::json;
using namespace rho::common;
using namespace rho::apiGenerator;

<% $cur_module.methods.each do |module_method|
   if module_method.generateNativeAPI %>
<%= api_generator_MakeJSMethodDecl($cur_module.name, module_method.native_name, module_method.access == ModuleMethod::ACCESS_STATIC)%>
{
    RAWTRACE3("<%=module_method.native_name%>(strObjID = %s, strCallbackID = %s, strJsVmID = %s)", strObjID.c_str(), strCallbackID.c_str(), strJsVmID.c_str());

#ifdef OS_ANDROID
    if ( jnienv() == 0 )
    {
        rho_nativethread_start();
    }
#endif

    rho::apiGenerator::CMethodResult oRes;

<% if module_method.result != nil
    if module_method.result.sub_param && module_method.result.sub_param.name %>
    oRes.setParamName( "<%= module_method.result.sub_param.name %>" );<%
    end

    result_type = nil
    if MethodParam::BASE_TYPES.include?(module_method.result.type)
      result_type = module_method.result.item_type
    else
      result_type = module_method.result.type;
    end

if api_generator_isSelfModule( $cur_module, result_type) %>
    oRes.setJSObjectClassPath( "<%= api_generator_getJSModuleName(api_generator_getRubyModuleFullName($cur_module))%>" );<%
elsif result_type && result_type.length()>0 && !MethodParam::BASE_TYPES.include?(result_type) %>
    oRes.setJSObjectClassPath( "<%= api_generator_getJSModuleName(result_type) %>" );<%
    if !module_method.linked_entity.nil?%>
    oRes.setResultAsEntity();
<% end
end; end

if module_method.linked_property && module_method.special_behaviour == ModuleMethod::SPECIAL_BEHAVIOUR_GETTER %>
    oRes.setRequestedType(<%= api_generator_cpp_makeMethodResultType(module_method.linked_property.type) %>);<%
elsif module_method.result && module_method.result.type %>
    oRes.setRequestedType(<%= api_generator_cpp_makeMethodResultType(module_method.result.type) %>);<%
end %>

    rho::common::CInstanceClassFunctorBase<rho::apiGenerator::CMethodResult>* pFunctor = 0;
    int argc = argv.getSize();
<% if module_method.access != ModuleMethod::ACCESS_STATIC %>
    <%= moduleNamespace%>I<%= $cur_module.name %>* pObj = <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::getInstance()->getModuleByID(strObjID);
<%end%>

<% functor_params = ""; first_arg = 0;
   module_method.params.each do |param| %>
    <% if !param.can_be_nil %>
    if ( argc == <%= first_arg %> )
    {
        oRes.setArgError( "Wrong number of arguments: " + convertToStringA(argc) + " instead of " + convertToStringA(<%= module_method.params.size() %>) );
        return oRes.toJSON();
    }
    <% end %>

<% if param.type == MethodParam::TYPE_STRING %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %> = "<%= param.default_value ? param.default_value : "" %>";
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isString() )
        {
            arg<%= first_arg %> = argv[<%= first_arg %>].getStringObject();
        }
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError( "Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_INT %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %> = <%= param.default_value ? param.default_value : 0 %>;
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isInteger() )
            arg<%= first_arg %> = argv[<%= first_arg %>].getInt();
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError("Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_BOOL %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %> = <%= param.default_value ? param.default_value : false %>;
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isBoolean() )
            arg<%= first_arg %> = argv[<%= first_arg %>].getBoolean();
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError("Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_DOUBLE %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %> = <%= param.default_value ? param.default_value : 0 %>;
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isFloat() )
            arg<%= first_arg %> = argv[<%= first_arg %>].getDouble();
        else if ( argv[<%= first_arg %>].isInteger() )
            arg<%= first_arg %> = (int64)argv[<%= first_arg %>].getUInt64();
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError("Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_ARRAY %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isArray() )
        {
            CJSONArray arParam(argv[<%= first_arg %>]);
            for( int i = 0; i < arParam.getSize(); i++ )
            {
                arg<%= first_arg %>.addElement( arParam[i].getStringObject() );
            }
        }
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError("Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_HASH %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
    if ( argc > <%= first_arg %> )
    {
        if ( argv[<%= first_arg %>].isObject() )
        {
            CJSONStructIterator objIter(argv[<%= first_arg %>]);

            for( ; !objIter.isEnd(); objIter.next() )
            {
                arg<%= first_arg %>[objIter.getCurKey()] = objIter.getCurString();
            }
        }
        else if (!argv[<%= first_arg %>].isNull())
        {
            oRes.setArgError("Type error: argument " <%= "\"#{first_arg}\"" %> " should be " <%= "\"#{param.type.downcase}\"" %> );
            return oRes.toJSON();
        }
    }
<% end %>

<% if !MethodParam::BASE_TYPES.include?(param.type) %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
<% end %>

<% functor_params += "arg#{first_arg}, " %>
<% first_arg = first_arg+1 %>
<% end %>

<% if module_method.has_callback != ModuleMethod::CALLBACK_NONE %>
    oRes.setCallInUIThread(<%= (module_method.run_in_thread == ModuleMethod::RUN_IN_THREAD_UI) ? "true" : "false" %>);
    oRes.setJSCallback( strCallbackID );
    oRes.setCallbackParam( strCallbackParam );
<% end %>

<% numParams = module_method.params.size()+1
if module_method.access != ModuleMethod::ACCESS_STATIC
    nativeInterfaceFunc = "#{moduleNamespace}I#{$cur_module.name}::#{module_method.native_name}"
    functorWar = "pFunctor = rho_makeInstanceClassFunctor#{numParams}( pObj, &#{nativeInterfaceFunc}, #{functor_params} oRes );"
else
    nativeSingleton = "#{moduleNamespace}C#{$cur_module.name}FactoryBase::get#{$cur_module.name}SingletonS()"
    nativeSingletonMethod = "#{moduleNamespace}I#{$cur_module.name}Singleton::#{module_method.native_name}"
    functorWar = "pFunctor = rho_makeInstanceClassFunctor#{numParams}( #{nativeSingleton}, &#{nativeSingletonMethod}, #{functor_params} oRes );"
end

if module_method.run_in_thread == ModuleMethod::RUN_IN_THREAD_UI %>
    <%= functorWar %>
    rho_wm_impl_performOnUiThread( pFunctor );<%
elsif (module_method.run_in_thread == ModuleMethod::RUN_IN_THREAD_MODULE) || (module_method.run_in_thread == ModuleMethod::RUN_IN_THREAD_SEPARATED) %>
    <%= functorWar %>
    <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->addCommandToQueue( pFunctor );<%
else if module_method.run_in_thread != ModuleMethod::RUN_IN_THREAD_NONE %>
    if ( oRes.hasCallback() )
    {
        <%= functorWar %>
        <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->addCommandToQueue( pFunctor );
    }
    else <%
end %>
    {
<% if module_method.access != ModuleMethod::ACCESS_STATIC %>
        pObj-><%= module_method.native_name %>( <%= functor_params %> oRes );<%
else %>
        <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()-><%= module_method.native_name %>( <%= functor_params %> oRes );<%
end %>
    }<% end %>

    return oRes.toJSON();

}
<% end
   end %>

<% if $cur_module.is_template_default_instance %>
<%= api_generator_MakeJSMethodDecl($cur_module.name, "getDefaultID", true)%>
{
    rho::apiGenerator::CMethodResult oRes;
    rho::String strDefaultID = <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->getDefaultID();
    oRes.set(strDefaultID);

    return oRes.toJSON();
}

<%= api_generator_MakeJSMethodDecl($cur_module.name, "getDefault", true)%>
{
    rho::apiGenerator::CMethodResult oRes;
    rho::String strDefaultID = <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->getDefaultID();
    oRes.set(strDefaultID);
    oRes.setJSObjectClassPath("<%= api_generator_getJSModuleName(api_generator_getRubyModuleFullName($cur_module))%>");

    return oRes.toJSON();
}

<%= api_generator_MakeJSMethodDecl($cur_module.name, "setDefaultID", true)%>
{
    rho::apiGenerator::CMethodResult oRes;
    rho::json::CJSONEntry el = argv[0];

    if (el.isString()) {
        <%= moduleNamespace%>C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->setDefaultID(el.getString());
    } else {
        oRes.setError("Method parameter should be defined as string!");
    }

    return oRes.toJSON();
}

<% end %>
<|endoftext|>


<commit_before>#include <cstddef>

#include <tuple>

#include <type_traits>

#include <utility>

namespace generic
{

namespace detail
{

namespace many
{

template <::std::size_t I, typename T>
struct many_holder
{
  ::std::conditional_t<::std::is_reference<T>{},
    ::std::add_pointer_t<::std::remove_reference_t<T>>,
    T
  > value;

  template <typename U = T>
  ::std::enable_if_t<!::std::is_reference<U>{}, U&>
  get() noexcept
  {
    return value;
  }

  template <typename U = T>
  ::std::enable_if_t<!::std::is_reference<U>{}, U const&>
  get() const noexcept
  {
    return value;
  }

  template <typename U = T>
  ::std::enable_if_t<!::std::is_reference<U>{}, U const&&>
  get() const noexcept
  {
    return value;
  }

  template <typename U = T>
  ::std::enable_if_t<::std::is_reference<U>{}, U&>
  get() noexcept
  {
    return *value;
  }

  template <typename U = T>
  ::std::enable_if_t<::std::is_reference<U>{}, U&&>
  get() noexcept
  {
    return *value;
  }

  template <typename U = T>
  ::std::enable_if_t<!::std::is_reference<U>{}>
  set(U const& u) noexcept(noexcept(::std::declval<U&>() = u))
  {
    value = u;
  }

  template <typename U = T>
  ::std::enable_if_t<!::std::is_reference<U>{}>
  set(U&& u) noexcept(noexcept(::std::declval<U&>() = ::std::move(u)))
  {
    value = ::std::move(u);
  }

  template <typename U = T>
  ::std::enable_if_t<::std::is_reference<U>{}>
  set(U u) noexcept
  {
    value = &u;
  }
};

template <typename, typename ...>
struct many_impl;

template <::std::size_t... Is, typename ...Types>
struct many_impl<::std::index_sequence<Is...>, Types...> :
  many_holder<Is, Types>...
{
};

}

}

template <typename ...Types>
struct many : detail::many::many_impl<
  ::std::make_index_sequence<sizeof...(Types)>,
  Types...
>
{
};

namespace detail
{

namespace many
{

template <typename ...Types, ::std::size_t ...Is>
auto make_many_impl(::std::index_sequence<Is...>, Types&& ...a) noexcept(
  noexcept(
    (
      static_cast<
        ::generic::detail::many::many_holder<Is,
          ::std::tuple_element_t<Is, ::generic::many<Types...>>
        >&
      >(::std::declval<::generic::many<Types...>&>()).set(
        ::std::forward<Types>(a)
      ),
      ...
    )
  )
)
{
  ::generic::many<Types...> m;

  (
    static_cast<
      ::generic::detail::many::many_holder<Is,
        ::std::tuple_element_t<Is, ::generic::many<Types...>>
      >&
    >(m).set(::std::forward<Types>(a)),
    ...
  );

  return m;
}

}

}

template <typename ...Types>
auto make_many(Types ...a) noexcept(
  noexcept(
    detail::many::make_many_impl(::std::index_sequence_for<Types...>{}, a...)
  )
)
{
  return detail::many::make_many_impl(::std::index_sequence_for<Types...>{},
    a...);
}

}

namespace std
{

template <typename ...Types>
struct tuple_size<::generic::many<Types...>> :
  ::std::integral_constant<::std::size_t, sizeof...(Types)>
{
};

template <::std::size_t I, class... Types>
struct tuple_element<I, ::generic::many<Types...>>
{
  using type = tuple_element_t<I, ::std::tuple<Types...>>;
};

template<::std::size_t I, typename... Types>
auto& get(::generic::many<Types...>& m) noexcept
{
  return static_cast<
    ::generic::detail::many::many_holder<I,
      ::std::tuple_element_t<I, ::generic::many<Types...>>
    >&
  >(m).get();
}

template<size_t I, typename... Types>
auto& get(::generic::many<Types...> const& m) noexcept
{
  return static_cast<
    ::generic::detail::many::many_holder<I,
      ::std::tuple_element_t<I, ::generic::many<Types...>>
    >const&
  >(m).get();
}

template<::std::size_t I, typename... Types>
auto&& get(::generic::many<Types...>&& m) noexcept
{
  return static_cast<
    ::generic::detail::many::many_holder<I,
      ::std::tuple_element_t<I, ::generic::many<Types...>>
    >&&
  >(m).get();
}

}
<commit_msg>some fixes<commit_after>#include <cstddef>

#include <tuple>

#include <type_traits>

#include <utility>

namespace generic
{

namespace detail
{

namespace many
{

template <::std::size_t I, typename T>
struct many_holder
{
  ::std::conditional_t<::std::is_reference<T>{},
    ::std::add_pointer_t<::std::remove_reference_t<T>>,
    ::std::remove_cv_t<T>
  > value;

  template <typename U = T>
  ::std::enable_if_t<!::std::is_reference<U>{}, U&>
  get() noexcept
  {
    return value;
  }

  template <typename U = T>
  ::std::enable_if_t<!::std::is_reference<U>{}, U const&>
  get() const noexcept
  {
    return value;
  }

  template <typename U = T>
  ::std::enable_if_t<::std::is_reference<U>{}, U>
  get() const noexcept
  {
    return *value;
  }

  template <typename A, typename U = T>
  ::std::enable_if_t<!::std::is_reference<U>{}>
  set(A const& u) noexcept(noexcept(::std::declval<U&>() = u))
  {
    value = u;
  }

  template <typename A, typename U = T>
  ::std::enable_if_t<!::std::is_reference<U>{}>
  set(A&& u) noexcept(noexcept(::std::declval<U&>() = ::std::move(u)))
  {
    value = ::std::move(u);
  }

  template <typename A, typename U = T>
  ::std::enable_if_t<::std::is_reference<U>{}>
  set(A&& u) noexcept
  {
    // convert to a reference to handle reference wrappers
    value = &T(u);
  }
};

template <typename, typename ...>
struct many_impl;

template <::std::size_t... Is, typename ...Types>
struct many_impl<::std::index_sequence<Is...>, Types...> :
  many_holder<Is, Types>...
{
};

}

}

template <typename ...Types>
struct many : detail::many::many_impl<
  ::std::make_index_sequence<sizeof...(Types)>,
  Types...
>
{
};

namespace detail
{

namespace many
{

template <typename ...Types, typename ...A, ::std::size_t ...Is>
auto create_many_impl(::std::index_sequence<Is...>, A&& ...a) noexcept(
  noexcept(
    (
      static_cast<
        ::generic::detail::many::many_holder<Is,
          ::std::tuple_element_t<Is, ::generic::many<Types...>>
        >&
      >(::std::declval<::generic::many<Types...>&>()).set(
        ::std::forward<A>(a)
      ),
      ...
    )
  )
)
{
  ::generic::many<Types...> m;

  (
    static_cast<
      ::generic::detail::many::many_holder<Is,
        ::std::tuple_element_t<Is, ::generic::many<Types...>>
      >&
    >(m).set(::std::forward<A>(a)),
    ...
  );

  return m;
}

}

}

template <typename ...Types, typename ...A>
auto create_many(A&& ...a) noexcept(
  noexcept(
    detail::many::create_many_impl<Types...>(
      ::std::index_sequence_for<Types...>{},
      ::std::forward<A>(a)...
    )
  )
)
{
  return detail::many::create_many_impl<Types...>(
    ::std::index_sequence_for<Types...>{},
    ::std::forward<A>(a)...
  );
}

}

namespace std
{

template <typename ...Types>
struct tuple_size<::generic::many<Types...>> :
  ::std::integral_constant<::std::size_t, sizeof...(Types)>
{
};

template <::std::size_t I, class... Types>
struct tuple_element<I, ::generic::many<Types...>>
{
  using type = tuple_element_t<I, ::std::tuple<Types...>>;
};

template<::std::size_t I, typename... Types>
auto& get(::generic::many<Types...>& m) noexcept
{
  return static_cast<
    ::generic::detail::many::many_holder<I,
      ::std::tuple_element_t<I, ::generic::many<Types...>>
    >&
  >(m).get();
}

template<size_t I, typename... Types>
auto& get(::generic::many<Types...> const& m) noexcept
{
  return static_cast<
    ::generic::detail::many::many_holder<I,
      ::std::tuple_element_t<I, ::generic::many<Types...>>
    >const&
  >(m).get();
}

template<::std::size_t I, typename... Types>
auto&& get(::generic::many<Types...>&& m) noexcept
{
  return static_cast<
    ::generic::detail::many::many_holder<I,
      ::std::tuple_element_t<I, ::generic::many<Types...>>
    >&&
  >(m).get();
}

}
<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <sparse.hpp>
#include <kernel/sparse.hpp>

#include <stdexcept>
#include <string>

#include <arith.hpp>
#include <cast.hpp>
#include <complex.hpp>
#include <err_common.hpp>
#include <lookup.hpp>
#include <math.hpp>
#include <platform.hpp>
#include <queue.hpp>
#include <reduce.hpp>
#include <where.hpp>

namespace cpu
{

using namespace common;

using std::add_const;
using std::add_pointer;
using std::enable_if;
using std::is_floating_point;
using std::remove_const;
using std::conditional;
using std::is_same;

template<typename T, class Enable = void>
struct blas_base {
    using type = T;
};

template<typename T>
struct blas_base <T, typename enable_if<is_complex<T>::value>::type> {
    using type = typename conditional<is_same<T, cdouble>::value,
                                      sp_cdouble, sp_cfloat>
                                     ::type;
};

template<typename T>
using cptr_type     =   typename conditional<   is_complex<T>::value,
                                                const typename blas_base<T>::type *,
                                                const T*>::type;
template<typename T>
using ptr_type     =    typename conditional<   is_complex<T>::value,
                                                typename blas_base<T>::type *,
                                                T*>::type;
template<typename T>
using scale_type   =    typename conditional<   is_complex<T>::value,
                                                const typename blas_base<T>::type *,
                                                const T *>::type;

#ifdef USE_MKL

// void mkl_zdnscsr (const MKL_INT *job ,
//                   const MKL_INT *m , const MKL_INT *n ,
//                   MKL_Complex16 *adns , const MKL_INT *lda ,
//                   MKL_Complex16 *acsr ,
//                   MKL_INT *ja , MKL_INT *ia ,
//                   MKL_INT *info );
template<typename T>
using dnscsr_func_def = void (*)(const int *,
                                 const int *, const int *,
                                 ptr_type<T>, const int *,
                                 ptr_type<T>,
                                 int *, int *,
                                 int *);

//void mkl_zcsrcsc (const MKL_INT *job ,
//                  const MKL_INT *n ,
//                  MKL_Complex16 *acsr ,
//                  MKL_INT *ja , MKL_INT *ia ,
//                  MKL_Complex16 *acsc ,
//                  MKL_INT *ja1 , MKL_INT *ia1 ,
//                  MKL_INT *info );
template<typename T>
using csrcsc_func_def = void (*)(const int *,
                                 const int *,
                                 ptr_type<T>, int *, int *,
                                 ptr_type<T>,
                                 int *, int *,
                                 int *);

#define SPARSE_FUNC_DEF( FUNC )                         \
template<typename T> FUNC##_func_def<T> FUNC##_func();

#define SPARSE_FUNC( FUNC, TYPE, PREFIX )               \
  template<> FUNC##_func_def<TYPE> FUNC##_func<TYPE>()  \
{ return &mkl_##PREFIX##FUNC; }

SPARSE_FUNC_DEF(dnscsr)
SPARSE_FUNC(dnscsr, float,  s)
SPARSE_FUNC(dnscsr, double, d)
SPARSE_FUNC(dnscsr, cfloat, c)
SPARSE_FUNC(dnscsr, cdouble,z)

SPARSE_FUNC_DEF(csrcsc)
SPARSE_FUNC(csrcsc, float,  s)
SPARSE_FUNC(csrcsc, double, d)
SPARSE_FUNC(csrcsc, cfloat, c)
SPARSE_FUNC(csrcsc, cdouble,z)

#undef SPARSE_FUNC
#undef SPARSE_FUNC_DEF

#endif // USE_MKL

////////////////////////////////////////////////////////////////////////////////
// Common to MKL and Not MKL
////////////////////////////////////////////////////////////////////////////////

// Partial template specialization of sparseConvertDenseToStorage for COO
// However, template specialization is not allowed
template<typename T>
SparseArray<T> sparseConvertDenseToCOO(const Array<T> &in)
{
    in.eval();

    Array<uint> nonZeroIdx_ = where<T>(in);
    Array<int> nonZeroIdx = cast<int, uint>(nonZeroIdx_);

    dim_t nNZ = nonZeroIdx.elements();

    Array<int> constNNZ = createValueArray<int>(dim4(nNZ), nNZ);
    constNNZ.eval();

    Array<int> rowIdx = arithOp<int, af_mod_t>(nonZeroIdx, constNNZ, nonZeroIdx.dims());
    Array<int> colIdx = arithOp<int, af_div_t>(nonZeroIdx, constNNZ, nonZeroIdx.dims());
    Array<T>   values = lookup<T, int>(in, nonZeroIdx, 0);

    return createArrayDataSparseArray<T>(in.dims(), values, rowIdx, colIdx, AF_STORAGE_COO);
}

// Partial template specialization of sparseConvertStorageToDense for COO
// However, template specialization is not allowed
template<typename T>
Array<T> sparseConvertCOOToDense(const SparseArray<T> &in)
{
    in.eval();

    Array<T> dense = createValueArray<T>(in.dims(), scalar<T>(0));
    dense.eval();

    const Array<T>   values = in.getValues();
    const Array<int> rowIdx = in.getRowIdx();
    const Array<int> colIdx = in.getColIdx();

    getQueue().enqueue(kernel::coo2dense<T>, dense, values, rowIdx, colIdx);

    return dense;
}

////////////////////////////////////////////////////////////////////////////////
#ifdef USE_MKL // Implementation using MKL
////////////////////////////////////////////////////////////////////////////////

template<typename T, af_storage stype>
SparseArray<T> sparseConvertDenseToStorage(const Array<T> &in_)
{
    in_.eval();

    // MKL only has dns->csr.
    // CSR <-> CSC is only supported if input is square
    uint nNZ = reduce_all<af_notzero_t, T, uint>(in_);

    SparseArray<T> sparse_ = createEmptySparseArray<T>(in_.dims(), nNZ, AF_STORAGE_CSR);
    sparse_.eval();

    auto func = [=] (SparseArray<T> sparse, const Array<T> in) {
        // Read: https://software.intel.com/en-us/node/520848
        // But job description is incorrect with regards to job[1]
        // 0 implies row major and 1 implies column major
        int j1 = 1, j2 = 0;
        const int job[] = {0, j1, j2, 2, (int)sparse.elements(), 1};

        const int M = in.dims()[0];
        const int N = in.dims()[1];

        int ldd = in.strides()[1];

        int info = 0;

        // Have to mess up all const correctness because MKL dnscsr function
        // is bidirectional and has input/output on all pointers
        Array<T  > &values = sparse.getValues();
        Array<int> &rowIdx = sparse.getRowIdx();
        Array<int> &colIdx = sparse.getColIdx();

        dnscsr_func<T>()(
                job, &M, &N,
                reinterpret_cast<ptr_type<T>>(const_cast<T*>(in.get())), &ldd,
                reinterpret_cast<ptr_type<T>>(values.get()),
                colIdx.get(),
                rowIdx.get(),
                &info);
    };

    getQueue().enqueue(func, sparse_, in_);

    if(stype == AF_STORAGE_CSR)
        return sparse_;
    else
        AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    return sparse_;
}

template<typename T, af_storage stype>
Array<T> sparseConvertStorageToDense(const SparseArray<T> &in_)
{
    // MKL only has dns<->csr.
    // CSR <-> CSC is only supported if input is square

    if(stype == AF_STORAGE_CSC)
        AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    in_.eval();

    Array<T> dense_ = createValueArray<T>(in_.dims(), scalar<T>(0));
    dense_.eval();

    auto func = [=] (Array<T> dense, const SparseArray<T> in) {
        // Read: https://software.intel.com/en-us/node/520848
        // But job description is incorrect with regards to job[1]
        // 0 implies row major and 1 implies column major
        int j1 = 1, j2 = 0;
        const int job[] = {1, j1, j2, 2, (int)dense.elements(), 1};

        const int M = dense.dims()[0];
        const int N = dense.dims()[1];

        int ldd = dense.strides()[1];

        int info = 0;

        Array<T  > values = in.getValues();
        Array<int> rowIdx = in.getRowIdx();
        Array<int> colIdx = in.getColIdx();

        // Have to mess up all const correctness because MKL dnscsr function
        // is bidirectional and has input/output on all pointers
        dnscsr_func<T>()(
                job, &M, &N,
                reinterpret_cast<ptr_type<T>>(dense.get()), &ldd,
                reinterpret_cast<ptr_type<T>>(const_cast<T*>(values.get())),
                const_cast<int*>(colIdx.get()),
                const_cast<int*>(rowIdx.get()),
                &info);
    };

    getQueue().enqueue(func, dense_, in_);

    if(stype == AF_STORAGE_CSR)
        return dense_;
    else
        AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    return dense_;
}

////////////////////////////////////////////////////////////////////////////////
#else // Implementation without using MKL
////////////////////////////////////////////////////////////////////////////////

template<typename T, af_storage stype>
SparseArray<T> sparseConvertDenseToStorage(const Array<T> &in_)
{
    // TODO: Make an implementation without MKL
    // Support CSC as well. MKL does not support Dense->CSC. So this will be
    // used as fallback
    in_.eval();

    uint nNZ = reduce_all<af_notzero_t, T, uint>(in_);

    SparseArray<T> sparse_ = createEmptySparseArray<T>(in_.dims(), nNZ, AF_STORAGE_CSR);
    sparse_.eval();

    auto func = [=] (SparseArray<T> sparse, const Array<T> in) {
        Array<T  > values = sparse.getValues();
        Array<int> rowIdx = sparse.getRowIdx();
        Array<int> colIdx = sparse.getColIdx();

        kernel::dns_csr<T>()(values, rowIdx, colIdx, in);
    };

    getQueue().enqueue(func, sparse_, in_);

    if(stype == AF_STORAGE_CSR)
        return sparse_;
    else
        AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    return sparse_;
}

template<typename T, af_storage stype>
Array<T> sparseConvertStorageToDense(const SparseArray<T> &in_)
{
    // TODO: Make an implementation without MKL
    // Support CSC as well. MKL does not support CSC->Dense. So this will be
    // used as fallback
    // Make these implementations like a struct. See approx1
    in_.eval();

    Array<T> dense_ = createValueArray<T>(in_.dims(), scalar<T>(0));
    dense_.eval();

    auto func = [=] (Array<T> dense, const SparseArray<T> in) {
        Array<T  > values = in.getValues();
        Array<int> rowIdx = in.getRowIdx();
        Array<int> colIdx = in.getColIdx();

        kernel::csr_dns<T>()(dense, values, rowIdx, colIdx);
    };

    getQueue().enqueue(func, dense_, in_);

    if(stype == AF_STORAGE_CSR)
        return dense_;
    else
        AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    return dense_;
}

////////////////////////////////////////////////////////////////////////////////
#endif //USE_MKL
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Common to MKL and Not MKL
////////////////////////////////////////////////////////////////////////////////
template<typename T, af_storage src, af_storage dest>
SparseArray<T> sparseConvertStorageToStorage(const SparseArray<T> &in)
{
    // Dummy function
    // TODO finish this function when support is required
    AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    in.eval();

    SparseArray<T> dense = createEmptySparseArray<T>(in.dims(), (int)in.getNNZ(), dest);

    return dense;
}

#define INSTANTIATE_TO_STORAGE(T, S)                                                                        \
    template SparseArray<T> sparseConvertStorageToStorage<T, S, AF_STORAGE_CSR>(const SparseArray<T> &in);  \
    template SparseArray<T> sparseConvertStorageToStorage<T, S, AF_STORAGE_CSC>(const SparseArray<T> &in);  \
    template SparseArray<T> sparseConvertStorageToStorage<T, S, AF_STORAGE_COO>(const SparseArray<T> &in);  \

#define INSTANTIATE_COO_SPECIAL(T)                                                                      \
    template<> SparseArray<T> sparseConvertDenseToStorage<T, AF_STORAGE_COO>(const Array<T> &in)        \
    { return sparseConvertDenseToCOO<T>(in); }                                                          \
    template<> Array<T> sparseConvertStorageToDense<T, AF_STORAGE_COO>(const SparseArray<T> &in)        \
    { return sparseConvertCOOToDense<T>(in); }                                                          \

#define INSTANTIATE_SPARSE(T)                                                                           \
    template SparseArray<T> sparseConvertDenseToStorage<T, AF_STORAGE_CSR>(const Array<T> &in);         \
    template SparseArray<T> sparseConvertDenseToStorage<T, AF_STORAGE_CSC>(const Array<T> &in);         \
                                                                                \
    template Array<T> sparseConvertStorageToDense<T, AF_STORAGE_CSR>(const SparseArray<T> &in);         \
    template Array<T> sparseConvertStorageToDense<T, AF_STORAGE_CSC>(const SparseArray<T> &in);         \
                                                                                \
    INSTANTIATE_COO_SPECIAL(T)                                                                          \
                                                                                \
    INSTANTIATE_TO_STORAGE(T, AF_STORAGE_CSR)                                                           \
    INSTANTIATE_TO_STORAGE(T, AF_STORAGE_CSC)                                                           \
    INSTANTIATE_TO_STORAGE(T, AF_STORAGE_COO)                                                           \

INSTANTIATE_SPARSE(float)
INSTANTIATE_SPARSE(double)
INSTANTIATE_SPARSE(cfloat)
INSTANTIATE_SPARSE(cdouble)

#undef INSTANTIATE_TO_STORAGE
#undef INSTANTIATE_COO_SPECIAL
#undef INSTANTIATE_SPARSE

}
<commit_msg>Removed TODO<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <sparse.hpp>
#include <kernel/sparse.hpp>

#include <stdexcept>
#include <string>

#include <arith.hpp>
#include <cast.hpp>
#include <complex.hpp>
#include <err_common.hpp>
#include <lookup.hpp>
#include <math.hpp>
#include <platform.hpp>
#include <queue.hpp>
#include <reduce.hpp>
#include <where.hpp>

namespace cpu
{

using namespace common;

using std::add_const;
using std::add_pointer;
using std::enable_if;
using std::is_floating_point;
using std::remove_const;
using std::conditional;
using std::is_same;

template<typename T, class Enable = void>
struct blas_base {
    using type = T;
};

template<typename T>
struct blas_base <T, typename enable_if<is_complex<T>::value>::type> {
    using type = typename conditional<is_same<T, cdouble>::value,
                                      sp_cdouble, sp_cfloat>
                                     ::type;
};

template<typename T>
using cptr_type     =   typename conditional<   is_complex<T>::value,
                                                const typename blas_base<T>::type *,
                                                const T*>::type;
template<typename T>
using ptr_type     =    typename conditional<   is_complex<T>::value,
                                                typename blas_base<T>::type *,
                                                T*>::type;
template<typename T>
using scale_type   =    typename conditional<   is_complex<T>::value,
                                                const typename blas_base<T>::type *,
                                                const T *>::type;

#ifdef USE_MKL

// void mkl_zdnscsr (const MKL_INT *job ,
//                   const MKL_INT *m , const MKL_INT *n ,
//                   MKL_Complex16 *adns , const MKL_INT *lda ,
//                   MKL_Complex16 *acsr ,
//                   MKL_INT *ja , MKL_INT *ia ,
//                   MKL_INT *info );
template<typename T>
using dnscsr_func_def = void (*)(const int *,
                                 const int *, const int *,
                                 ptr_type<T>, const int *,
                                 ptr_type<T>,
                                 int *, int *,
                                 int *);

//void mkl_zcsrcsc (const MKL_INT *job ,
//                  const MKL_INT *n ,
//                  MKL_Complex16 *acsr ,
//                  MKL_INT *ja , MKL_INT *ia ,
//                  MKL_Complex16 *acsc ,
//                  MKL_INT *ja1 , MKL_INT *ia1 ,
//                  MKL_INT *info );
template<typename T>
using csrcsc_func_def = void (*)(const int *,
                                 const int *,
                                 ptr_type<T>, int *, int *,
                                 ptr_type<T>,
                                 int *, int *,
                                 int *);

#define SPARSE_FUNC_DEF( FUNC )                         \
template<typename T> FUNC##_func_def<T> FUNC##_func();

#define SPARSE_FUNC( FUNC, TYPE, PREFIX )               \
  template<> FUNC##_func_def<TYPE> FUNC##_func<TYPE>()  \
{ return &mkl_##PREFIX##FUNC; }

SPARSE_FUNC_DEF(dnscsr)
SPARSE_FUNC(dnscsr, float,  s)
SPARSE_FUNC(dnscsr, double, d)
SPARSE_FUNC(dnscsr, cfloat, c)
SPARSE_FUNC(dnscsr, cdouble,z)

SPARSE_FUNC_DEF(csrcsc)
SPARSE_FUNC(csrcsc, float,  s)
SPARSE_FUNC(csrcsc, double, d)
SPARSE_FUNC(csrcsc, cfloat, c)
SPARSE_FUNC(csrcsc, cdouble,z)

#undef SPARSE_FUNC
#undef SPARSE_FUNC_DEF

#endif // USE_MKL

////////////////////////////////////////////////////////////////////////////////
// Common to MKL and Not MKL
////////////////////////////////////////////////////////////////////////////////

// Partial template specialization of sparseConvertDenseToStorage for COO
// However, template specialization is not allowed
template<typename T>
SparseArray<T> sparseConvertDenseToCOO(const Array<T> &in)
{
    in.eval();

    Array<uint> nonZeroIdx_ = where<T>(in);
    Array<int> nonZeroIdx = cast<int, uint>(nonZeroIdx_);

    dim_t nNZ = nonZeroIdx.elements();

    Array<int> constNNZ = createValueArray<int>(dim4(nNZ), nNZ);
    constNNZ.eval();

    Array<int> rowIdx = arithOp<int, af_mod_t>(nonZeroIdx, constNNZ, nonZeroIdx.dims());
    Array<int> colIdx = arithOp<int, af_div_t>(nonZeroIdx, constNNZ, nonZeroIdx.dims());
    Array<T>   values = lookup<T, int>(in, nonZeroIdx, 0);

    return createArrayDataSparseArray<T>(in.dims(), values, rowIdx, colIdx, AF_STORAGE_COO);
}

// Partial template specialization of sparseConvertStorageToDense for COO
// However, template specialization is not allowed
template<typename T>
Array<T> sparseConvertCOOToDense(const SparseArray<T> &in)
{
    in.eval();

    Array<T> dense = createValueArray<T>(in.dims(), scalar<T>(0));
    dense.eval();

    const Array<T>   values = in.getValues();
    const Array<int> rowIdx = in.getRowIdx();
    const Array<int> colIdx = in.getColIdx();

    getQueue().enqueue(kernel::coo2dense<T>, dense, values, rowIdx, colIdx);

    return dense;
}

////////////////////////////////////////////////////////////////////////////////
#ifdef USE_MKL // Implementation using MKL
////////////////////////////////////////////////////////////////////////////////

template<typename T, af_storage stype>
SparseArray<T> sparseConvertDenseToStorage(const Array<T> &in_)
{
    in_.eval();

    // MKL only has dns->csr.
    // CSR <-> CSC is only supported if input is square
    uint nNZ = reduce_all<af_notzero_t, T, uint>(in_);

    SparseArray<T> sparse_ = createEmptySparseArray<T>(in_.dims(), nNZ, AF_STORAGE_CSR);
    sparse_.eval();

    auto func = [=] (SparseArray<T> sparse, const Array<T> in) {
        // Read: https://software.intel.com/en-us/node/520848
        // But job description is incorrect with regards to job[1]
        // 0 implies row major and 1 implies column major
        int j1 = 1, j2 = 0;
        const int job[] = {0, j1, j2, 2, (int)sparse.elements(), 1};

        const int M = in.dims()[0];
        const int N = in.dims()[1];

        int ldd = in.strides()[1];

        int info = 0;

        // Have to mess up all const correctness because MKL dnscsr function
        // is bidirectional and has input/output on all pointers
        Array<T  > &values = sparse.getValues();
        Array<int> &rowIdx = sparse.getRowIdx();
        Array<int> &colIdx = sparse.getColIdx();

        dnscsr_func<T>()(
                job, &M, &N,
                reinterpret_cast<ptr_type<T>>(const_cast<T*>(in.get())), &ldd,
                reinterpret_cast<ptr_type<T>>(values.get()),
                colIdx.get(),
                rowIdx.get(),
                &info);
    };

    getQueue().enqueue(func, sparse_, in_);

    if(stype == AF_STORAGE_CSR)
        return sparse_;
    else
        AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    return sparse_;
}

template<typename T, af_storage stype>
Array<T> sparseConvertStorageToDense(const SparseArray<T> &in_)
{
    // MKL only has dns<->csr.
    // CSR <-> CSC is only supported if input is square

    if(stype == AF_STORAGE_CSC)
        AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    in_.eval();

    Array<T> dense_ = createValueArray<T>(in_.dims(), scalar<T>(0));
    dense_.eval();

    auto func = [=] (Array<T> dense, const SparseArray<T> in) {
        // Read: https://software.intel.com/en-us/node/520848
        // But job description is incorrect with regards to job[1]
        // 0 implies row major and 1 implies column major
        int j1 = 1, j2 = 0;
        const int job[] = {1, j1, j2, 2, (int)dense.elements(), 1};

        const int M = dense.dims()[0];
        const int N = dense.dims()[1];

        int ldd = dense.strides()[1];

        int info = 0;

        Array<T  > values = in.getValues();
        Array<int> rowIdx = in.getRowIdx();
        Array<int> colIdx = in.getColIdx();

        // Have to mess up all const correctness because MKL dnscsr function
        // is bidirectional and has input/output on all pointers
        dnscsr_func<T>()(
                job, &M, &N,
                reinterpret_cast<ptr_type<T>>(dense.get()), &ldd,
                reinterpret_cast<ptr_type<T>>(const_cast<T*>(values.get())),
                const_cast<int*>(colIdx.get()),
                const_cast<int*>(rowIdx.get()),
                &info);
    };

    getQueue().enqueue(func, dense_, in_);

    if(stype == AF_STORAGE_CSR)
        return dense_;
    else
        AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    return dense_;
}

////////////////////////////////////////////////////////////////////////////////
#else // Implementation without using MKL
////////////////////////////////////////////////////////////////////////////////

template<typename T, af_storage stype>
SparseArray<T> sparseConvertDenseToStorage(const Array<T> &in_)
{
    in_.eval();

    uint nNZ = reduce_all<af_notzero_t, T, uint>(in_);

    SparseArray<T> sparse_ = createEmptySparseArray<T>(in_.dims(), nNZ, AF_STORAGE_CSR);
    sparse_.eval();

    auto func = [=] (SparseArray<T> sparse, const Array<T> in) {
        Array<T  > values = sparse.getValues();
        Array<int> rowIdx = sparse.getRowIdx();
        Array<int> colIdx = sparse.getColIdx();

        kernel::dns_csr<T>()(values, rowIdx, colIdx, in);
    };

    getQueue().enqueue(func, sparse_, in_);

    if(stype == AF_STORAGE_CSR)
        return sparse_;
    else
        AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    return sparse_;
}

template<typename T, af_storage stype>
Array<T> sparseConvertStorageToDense(const SparseArray<T> &in_)
{
    in_.eval();

    Array<T> dense_ = createValueArray<T>(in_.dims(), scalar<T>(0));
    dense_.eval();

    auto func = [=] (Array<T> dense, const SparseArray<T> in) {
        Array<T  > values = in.getValues();
        Array<int> rowIdx = in.getRowIdx();
        Array<int> colIdx = in.getColIdx();

        kernel::csr_dns<T>()(dense, values, rowIdx, colIdx);
    };

    getQueue().enqueue(func, dense_, in_);

    if(stype == AF_STORAGE_CSR)
        return dense_;
    else
        AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    return dense_;
}

////////////////////////////////////////////////////////////////////////////////
#endif //USE_MKL
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Common to MKL and Not MKL
////////////////////////////////////////////////////////////////////////////////
template<typename T, af_storage src, af_storage dest>
SparseArray<T> sparseConvertStorageToStorage(const SparseArray<T> &in)
{
    // Dummy function
    // TODO finish this function when support is required
    AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED);

    in.eval();

    SparseArray<T> dense = createEmptySparseArray<T>(in.dims(), (int)in.getNNZ(), dest);

    return dense;
}

#define INSTANTIATE_TO_STORAGE(T, S)                                                                        \
    template SparseArray<T> sparseConvertStorageToStorage<T, S, AF_STORAGE_CSR>(const SparseArray<T> &in);  \
    template SparseArray<T> sparseConvertStorageToStorage<T, S, AF_STORAGE_CSC>(const SparseArray<T> &in);  \
    template SparseArray<T> sparseConvertStorageToStorage<T, S, AF_STORAGE_COO>(const SparseArray<T> &in);  \

#define INSTANTIATE_COO_SPECIAL(T)                                                                      \
    template<> SparseArray<T> sparseConvertDenseToStorage<T, AF_STORAGE_COO>(const Array<T> &in)        \
    { return sparseConvertDenseToCOO<T>(in); }                                                          \
    template<> Array<T> sparseConvertStorageToDense<T, AF_STORAGE_COO>(const SparseArray<T> &in)        \
    { return sparseConvertCOOToDense<T>(in); }                                                          \

#define INSTANTIATE_SPARSE(T)                                                                           \
    template SparseArray<T> sparseConvertDenseToStorage<T, AF_STORAGE_CSR>(const Array<T> &in);         \
    template SparseArray<T> sparseConvertDenseToStorage<T, AF_STORAGE_CSC>(const Array<T> &in);         \
                                                                                \
    template Array<T> sparseConvertStorageToDense<T, AF_STORAGE_CSR>(const SparseArray<T> &in);         \
    template Array<T> sparseConvertStorageToDense<T, AF_STORAGE_CSC>(const SparseArray<T> &in);         \
                                                                                \
    INSTANTIATE_COO_SPECIAL(T)                                                                          \
                                                                                \
    INSTANTIATE_TO_STORAGE(T, AF_STORAGE_CSR)                                                           \
    INSTANTIATE_TO_STORAGE(T, AF_STORAGE_CSC)                                                           \
    INSTANTIATE_TO_STORAGE(T, AF_STORAGE_COO)                                                           \

INSTANTIATE_SPARSE(float)
INSTANTIATE_SPARSE(double)
INSTANTIATE_SPARSE(cfloat)
INSTANTIATE_SPARSE(cdouble)

#undef INSTANTIATE_TO_STORAGE
#undef INSTANTIATE_COO_SPECIAL
#undef INSTANTIATE_SPARSE

}
<|endoftext|>