<commit_before>
#include <stddef.h> // Чтобы определить NULL

///////// Включения основного модуля module.h
#include "Module.h"
#include "Function_module.h"

#include <math.h>
#include <iostream>
#include <time.h> // для Рандомайзера

using namespace std;

// Опишу функцию вне класса чтобы можно было применять cout
FunctionResult* MathFunctionModule::executeFunction(regval functionId, regval *args){
	cout << "Func executed" << endl;
	if (!functionId) {
		return NULL;
	}

	// эта конструкция чтобы создать заранее объект указатель на который будем возвращать
	char ch4 = '1'; // имя надо будет поменять  или просто что-то поменять. Но пока символ оставим в покое и буем работать с result.
	rez = new FunctionResult(ch4);

	// Уже не тестовое задание пробуем описать
	switch (functionId) {
		//первая функция pow - квадрат. 1-й аргумент возводимое, второй - степень.
		case 1:
		{
			//C приведением типов
			double arg1,arg2,resOfPow;
			arg1=*args;
			arg2=*(args+1);
			resOfPow=pow(arg1,arg2);
			rez->result = (int) resOfPow;
			// Все сделали и выходим из свича
			break;
		}
		case 2: // ABS модуль числа
		{
		/*C приведением типов*/
			int resOfabs;
			resOfabs = abs(*args);
			rez->result = resOfabs;
			// Все сделали и выходим из свича
			break;
		}
		case 3: // FMOD Остаток от деления
		{
			int resOfmod;
			resOfmod = (int) fmod(*args,*(args +1));
			rez->result = resOfmod;
			// Все сделали и выходим из свича
			break;
		}
		case 4: // DIV Целочисленное деление
			int resOfdiv;
			resOfdiv = ( *args - (int)fmod(*args, *(args + 1)) ) / (*(args+1));
			rez->result = resOfdiv;
			// Все сделали и выходим из свича
			break;

		case 5: // Корень 2-й степени
		{
			int resOfsqrt;
			resOfsqrt = (int) sqrt(*args);
			rez->result = resOfsqrt;
			// Все сделали и выходим из свича
			break;
		}
		case 6: // Рандомное целое число
		{
			int resOfrand;
			resOfrand = rand()%(*args) + (*(args+1)) ;
			rez->result = resOfrand;
			// Все сделали и выходим из свича
			break;
		}
		case 7: // Синус
		{
			int resOfsin;
			resOfsin = (int) (1000 * sin(*args)) ;
			rez->result = resOfsin;
			// Все сделали и выходим из свича
			break;
		}
		case 8: // Косинус
		{
			int resOfcos;
			resOfcos = (int)(1000 * cos(*args));
			rez->result = resOfcos;
			// Все сделали и выходим из свича
			break;
		}
		case 9: // Тангенс
		{
			int resOftan;
			resOftan = (int)(1000 * tan(*args));
			rez->result = resOftan;
			// Все сделали и выходим из свича
			break;
		}
		case 10: // АркСинус
		{
			int resOfasin;
			resOfasin = (int)(1000 * asin(*args));
			rez->result = resOfasin;
			// Все сделали и выходим из свича
			break;
		}
		case 11: // АркКосинус
		{
			int resOfacos;
			resOfacos = (int)(1000 * acos(*args));
			rez->result = resOfacos;
			// Все сделали и выходим из свича
			break;
		}
		case 12: // АркТангенс
		{
			int resOfatan;
			resOfatan = (int)(1000 * atan(*args));
			rez->result = resOfatan;
			// Все сделали и выходим из свича
			break;
		}
		case 13: // Экспонента
		{
			int resOfexp;
			resOfexp = (int) exp(*args);
			rez->result = resOfexp;
			// Все сделали и выходим из свича
			break;
		}
		case 14: // Логарифм Натуральный
		{
			int resOflog;
			resOflog = (int)log(*args);
			rez->result = resOflog;
			// Все сделали и выходим из свича
			break;
		}
		case 15: // Десятичный логарифм
		{
			int resOflog10;
			resOflog10 = (int)log10(*args);
			rez->result = resOflog10;
			// Все сделали и выходим из свича
			break;
		}
    }; // Конец switch
	return rez;
};

int main(){
	int test;
	test = 1;
	cout << test << endl;

	regval *arg1;
	regval x;
	x = 1;
	arg1 = &x;

	regval TwoArgs[] = {2,3};
	regval absTestMas[] = { -14 };
	regval fmodTestMas[] = { 7, 4 };
	regval divTestMas[] = { 9, 4 };
	regval randTestMas[] = { 10, 1 };
	regval SiCoTanTestMas[] = {1};

	MathFunctionModule newObject;

	FunctionResult *FRobject;

	// проверка возведения в степень
	FRobject = newObject.executeFunction(1, TwoArgs); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject << endl;
	cout << FRobject->type << endl;
	cout << FRobject->result << endl;

	// Проверка получения абсолютной величины
	FRobject = newObject.executeFunction(2, absTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject << endl;
	cout << FRobject->type << endl;
	cout << FRobject->result << endl;

	// Проверка остатка от деления
	FRobject = newObject.executeFunction(3, fmodTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject << endl;
	cout << FRobject->type << endl;
	cout << FRobject->result << endl;

	// Проверка целочисленного деления на том же массиве
	FRobject = newObject.executeFunction(4, divTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject << endl;
	cout << FRobject->type << endl;
	cout << FRobject->result << endl;

	cout << "- - - " << newObject.executeFunction(4, divTestMas)->result + newObject.executeFunction(4, divTestMas)->result << endl;

	// Проверка Установка рандомайзера. не важно что передаем в аргументах
	FRobject = newObject.executeFunction(5, divTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject << endl;
	cout << FRobject->type << endl;
	cout << FRobject->result << endl;

	// Проверяем рандомайзер
	FRobject = newObject.executeFunction(6, randTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject->result << endl;
	FRobject = newObject.executeFunction(6, randTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject->result << endl;

	return 0;
}
<commit_msg>update executeFunctions<commit_after>
#include <stddef.h> // Чтобы определить NULL

///////// Включения основного модуля module.h
#include "Module.h"
#include "Function_module.h"

#include <math.h>
#include <iostream>
#include <time.h> // для Рандомайзера

using namespace std;

// Опишу функцию вне класса чтобы можно было применять cout
FunctionResult* MathFunctionModule::executeFunction(regval functionId, regval *args){
	cout << "Func executed" << endl;
	if (!functionId) {
		return NULL;
	}

	// эта конструкция чтобы создать заранее объект указатель на который будем возвращать
	char ch4 = '1'; // имя надо будет поменять  или просто что-то поменять. Но пока символ оставим в покое и буем работать с result.
	rez = new FunctionResult(ch4);

	// Уже не тестовое задание пробуем описать
	switch (functionId) {
		//первая функция pow - квадрат. 1-й аргумент возводимое, второй - степень.
		case 1:  // Тут вопрос про приведение типов
		{
			//C приведением типов
			double arg1,arg2,resOfPow;
			arg1=*args;
			arg2=*(args+1);
			resOfPow=pow(arg1,arg2);
			rez->result = (int) resOfPow;
			// Все сделали и выходим из свича
			break;
		}
		case 2: // ABS модуль числа
		{
		/*C приведением типов*/
			int resOfabs;
			resOfabs = abs(*args);
			rez->result = resOfabs;
			// Все сделали и выходим из свича
			break;
		}
		case 3: // FMOD Остаток от деления
		{
			int resOfmod;
			resOfmod = (int) fmod(*args,*(args +1));
			rez->result = resOfmod;
			// Все сделали и выходим из свича
			break;
		}
		case 4: // DIV Целочисленное деление
			int resOfdiv;
			resOfdiv = ( *args - (int)fmod(*args, *(args + 1)) ) / (*(args+1));
			rez->result = resOfdiv;
			// Все сделали и выходим из свича
			break;

		case 5: // Корень 2-й степени Результат будем выводить умноженным на 1000, потому что растет медленно(меняется медленно)
		{
			int resOfsqrt;
			resOfsqrt = (int) (1000 * sqrt(*args));
			rez->result = resOfsqrt;
			// Все сделали и выходим из свича
			break;
		}
		case 6: // Рандомное целое число
		{
			int resOfrand;
			resOfrand = rand()%(*args) + (*(args+1)) ;
			rez->result = resOfrand;
			// Все сделали и выходим из свича
			break;
		}
		case 7: // Синус Изменяется быстро поэтому ввод просим умножить на 1000 а в вычислениях введенное будем делить на 1000 и выводить будем умножив на 1000, потому что быстро меняется в малых пределах
		{
			int resOfsin;
			resOfsin = (int) (1000 * sin(*args/1000)) ;
			rez->result = resOfsin;
			// Все сделали и выходим из свича
			break;
		}
		case 8: // Косинус Изменяется быстро поэтому ввод просим умножить на 1000 а в вычислениях введенное будем делить на 1000 и выводить будем умножив на 1000, потому что быстро меняется в малых пределах
		{
			int resOfcos;
			resOfcos = (int)(1000 * cos(*args/1000));
			rez->result = resOfcos;
			// Все сделали и выходим из свича
			break;
		}
		case 9: // Тангенс Изменяется быстро поэтому ввод просим умножить на 1000 а в вычислениях введенное будем делить на 1000 и выводить будем умножив на 1000, потому что быстро меняется в малых пределах
		{
			int resOftan;
			resOftan = (int)(1000 * tan(*args / 1000));
			rez->result = resOftan;
			// Все сделали и выходим из свича
			break;
		}
		case 10: // АркСинус Изменяется быстро поэтому ввод просим умножить на 1000 а в вычислениях введенное будем делить на 1000 и выводить будем умножив на 1000, потому что быстро меняется в малых пределах
		{
			int resOfasin;
			resOfasin = (int)(1000 * asin(*args / 1000));
			rez->result = resOfasin;
			// Все сделали и выходим из свича
			break;
		}
		case 11: // АркКосинус Изменяется быстро поэтому ввод просим умножить на 1000 а в вычислениях введенное будем делить на 1000 и выводить будем умножив на 1000, потому что быстро меняется в малых пределах
		{
			int resOfacos;
			resOfacos = (int)(1000 * acos(*args / 1000));
			rez->result = resOfacos;
			// Все сделали и выходим из свича
			break;
		}
		case 12: // АркТангенс Изменяется быстро поэтому ввод просим умножить на 1000 а в вычислениях введенное будем делить на 1000 и выводить будем умножив на 1000, потому что быстро меняется в малых пределах
		{
			int resOfatan;
			resOfatan = (int)(1000 * atan(*args / 1000));
			rez->result = resOfatan;
			// Все сделали и выходим из свича
			break;
		}
		case 13: // Экспонента Растет быстро поэтому ввод просим умножить на 1000 а в вычислениях введенное будем делить на 1000
		{
			int resOfexp;
			resOfexp = (int)exp(*args / 1000);
			rez->result = resOfexp;
			// Все сделали и выходим из свича
			break;
		}
		case 14: // Логарифм Натуральный Растет медленно поэтому вывод умножим на 1000
		{
			int resOflog;
			resOflog = (int)( 1000* log(*args));
			rez->result = resOflog;
			// Все сделали и выходим из свича
			break;
		}
		case 15: // Десятичный логарифм Растет медленно поэтому вывод умножим на 1000
		{
			int resOflog10;
			resOflog10 = (int) (1000 * log10(*args));
			rez->result = resOflog10;
			// Все сделали и выходим из свича
			break;
		}
        }; // Конец switch
	return rez;
};

int main(){
	int test;
	test = 1;
	cout << test << endl;

	regval *arg1;
	regval x;
	x = 1;
	arg1 = &x;

	regval TwoArgs[] = {2,3};
	regval absTestMas[] = { -14 };
	regval fmodTestMas[] = { 7, 4 };
	regval divTestMas[] = { 9, 4 };
	regval randTestMas[] = { 10, 1 };
	regval SiCoTanTestMas[] = {1};

	MathFunctionModule newObject;

	FunctionResult *FRobject;

	// проверка возведения в степень
	FRobject = newObject.executeFunction(1, TwoArgs); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject << endl;
	cout << FRobject->type << endl;
	cout << FRobject->result << endl;

	// Проверка получения абсолютной величины
	FRobject = newObject.executeFunction(2, absTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject << endl;
	cout << FRobject->type << endl;
	cout << FRobject->result << endl;

	// Проверка остатка от деления
	FRobject = newObject.executeFunction(3, fmodTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject << endl;
	cout << FRobject->type << endl;
	cout << FRobject->result << endl;

	// Проверка целочисленного деления на том же массиве
	FRobject = newObject.executeFunction(4, divTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject << endl;
	cout << FRobject->type << endl;
	cout << FRobject->result << endl;

	cout << "- - - " << newObject.executeFunction(4, divTestMas)->result + newObject.executeFunction(4, divTestMas)->result << endl;

	// Проверка Установка рандомайзера. не важно что передаем в аргументах
	FRobject = newObject.executeFunction(5, divTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject << endl;
	cout << FRobject->type << endl;
	cout << FRobject->result << endl;

	// Проверяем рандомайзер
	FRobject = newObject.executeFunction(6, randTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject->result << endl;
	FRobject = newObject.executeFunction(6, randTestMas); // не забываем что этот объект ссылается на свойство newObject.
	cout << FRobject->result << endl;

	return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <boost/format.hpp>

#include "log.h"
#include "common.h"

#include "mem_vec_store.h"
#include "bulk_operate.h"
#include "local_vec_store.h"
#include "mem_matrix_store.h"
#include "NUMA_vector.h"

namespace fm
{

namespace detail
{

mem_vec_store::ptr mem_vec_store::create(size_t length, int num_nodes,
		const scalar_type &type)
{
	if (num_nodes < 0)
		return smp_vec_store::create(length, type);
	else
		return NUMA_vec_store::create(length, num_nodes, type);
}

bool mem_vec_store::copy_from(const char *buf, size_t num_bytes)
{
	if (get_raw_arr() == NULL)
		return false;

	if (num_bytes % get_entry_size() != 0
			|| num_bytes / get_entry_size() != get_length())
		return false;
	memcpy(get_raw_arr(), buf, num_bytes);
	return true;
}

smp_vec_store::smp_vec_store(size_t length, const scalar_type &type): mem_vec_store(
		length, type), data(length * type.get_size())
{
	this->arr = data.get_raw();
}

smp_vec_store::smp_vec_store(const detail::raw_data_array &data,
		const scalar_type &type): mem_vec_store(
			data.get_num_bytes() / type.get_size(), type)
{
	this->data = data;
	this->arr = this->data.get_raw();
}

smp_vec_store::ptr smp_vec_store::create(const detail::raw_data_array &data,
			const scalar_type &type)
{
	if (data.get_num_bytes() % type.get_size() != 0) {
		BOOST_LOG_TRIVIAL(error)
			<< "The data array has a wrong number of bytes";
		return smp_vec_store::ptr();
	}
	return ptr(new smp_vec_store(data, type));
}

smp_vec_store::ptr smp_vec_store::get(const smp_vec_store &idxs) const
{
	if (idxs.get_type() != get_scalar_type<off_t>()) {
		BOOST_LOG_TRIVIAL(error) << "The index vector isn't of the off_t type";
		return smp_vec_store::ptr();
	}

	smp_vec_store::ptr ret = smp_vec_store::create(idxs.get_length(), get_type());
	int num_threads = get_num_omp_threads();
	size_t part_len = ceil(((double) idxs.get_length()) / num_threads);
#pragma omp parallel for
	for (int k = 0; k < num_threads; k++) {
		size_t start = k * part_len;
		size_t end = std::min((k + 1) * part_len, idxs.get_length());
		size_t local_len = end >= start ? end - start : 0;
		if (local_len == 0)
			continue;

		std::vector<const char *> src_locs(local_len);
		for (size_t i = 0; i < local_len; i++) {
			off_t idx = idxs.get<off_t>(i + start);
			// Check if it's out of the range.
			if (idx < 0 && (size_t) idx >= this->get_length()) {
				BOOST_LOG_TRIVIAL(error)
					<< boost::format("%1% is out of range") % idx;
				continue;
			}

			src_locs[i] = this->get(idx);
		}
		get_type().get_sg().gather(src_locs,
				ret->arr + start * ret->get_entry_size());
	}
	return ret;
}

bool smp_vec_store::append(std::vector<vec_store::const_ptr>::const_iterator vec_it,
		std::vector<vec_store::const_ptr>::const_iterator vec_end)
{
	// Get the total size of the result vector.
	size_t tot_res_size = this->get_length();
	for (auto it = vec_it; it != vec_end; it++) {
		tot_res_size += (*it)->get_length();
		if (!(*it)->is_in_mem()) {
			BOOST_LOG_TRIVIAL(error)
				<< "Not support appending an ext-mem vector to an in-mem vector";
			return false;
		}
		if (get_type() != (*it)->get_type()) {
			BOOST_LOG_TRIVIAL(error) << "The two vectors don't have the same type";
			return false;
		}
	}

	// Merge all results to a single vector.
	off_t loc = this->get_length() + get_sub_start();
	this->resize(tot_res_size);
	for (auto it = vec_it; it != vec_end; it++) {
		assert(loc + (*it)->get_length() <= this->get_length());
		assert((*it)->is_in_mem());
		const mem_vec_store &mem_vec = static_cast<const mem_vec_store &>(**it);
		bool ret = data.set_sub_arr(loc * get_entry_size(),
				mem_vec.get_raw_arr(), mem_vec.get_length() * get_entry_size());
		assert(ret);
		loc += (*it)->get_length();
	}
	return true;
}

bool smp_vec_store::append(const vec_store &vec)
{
	if (!vec.is_in_mem()) {
		BOOST_LOG_TRIVIAL(error) << "The input vector isn't in memory";
		return false;
	}
	if (get_type() != vec.get_type()) {
		BOOST_LOG_TRIVIAL(error) << "The two vectors don't have the same type";
		return false;
	}
	// TODO We might want to over expand a little, so we don't need to copy
	// the memory again and again.
	// TODO if this is a sub_vector, what should we do?
	assert(get_sub_start() == 0);
	off_t loc = this->get_length() + get_sub_start();
	this->resize(vec.get_length() + get_length());
	assert(loc + vec.get_length() <= this->get_length());
	const mem_vec_store &mem_vec = static_cast<const mem_vec_store &>(vec);
	assert(mem_vec.get_raw_arr());
	return data.set_sub_arr(loc * get_entry_size(), mem_vec.get_raw_arr(),
			mem_vec.get_length() * get_entry_size());
}

bool smp_vec_store::resize(size_t new_length)
{
	if (new_length == get_length())
		return true;

	size_t tot_len = data.get_num_bytes() / get_type().get_size();
	// We don't want to reallocate memory when shrinking the vector.
	if (new_length < tot_len) {
		return vec_store::resize(new_length);
	}

	// Keep the old information of the vector.
	detail::raw_data_array old_data = data;
	char *old_arr = arr;
	size_t old_length = get_length();

	size_t real_length = old_length;
	if (real_length == 0)
		real_length = 1;
	for (; real_length < new_length; real_length *= 2);
	this->data = detail::raw_data_array(real_length * get_type().get_size());
	this->arr = this->data.get_raw();
	memcpy(arr, old_arr, std::min(old_length, new_length) * get_entry_size());
	return vec_store::resize(new_length);
}

bool smp_vec_store::expose_sub_vec(off_t start, size_t length)
{
	size_t tot_len = data.get_num_bytes() / get_type().get_size();
	if (start + length > tot_len) {
		exit(1);
		BOOST_LOG_TRIVIAL(error) << "expose_sub_vec: out of range";
		return false;
	}

	resize(length);
	arr = data.get_raw() + start * get_entry_size();
	return true;
}

vec_store::ptr smp_vec_store::deep_copy() const
{
	assert(get_raw_arr() == data.get_raw());
	detail::raw_data_array data = this->data.deep_copy();
	return smp_vec_store::create(data, get_type());
}

vec_store::ptr smp_vec_store::sort_with_index()
{
	smp_vec_store::ptr indexes = smp_vec_store::create(get_length(),
			get_scalar_type<off_t>());
	get_type().get_sorter().sort_with_index(arr,
			(off_t *) indexes->arr, get_length(), false);
	return indexes;
}

void smp_vec_store::set_data(const set_vec_operate &op)
{
	// I assume this is column-wise matrix.
	// TODO parallel.
	op.set(arr, get_length(), 0);
}

void smp_vec_store::set(const std::vector<const char *> &locs)
{
	assert(locs.size() <= get_length());
	get_type().get_sg().gather(locs, arr);
}

local_vec_store::ptr smp_vec_store::get_portion(off_t loc, size_t size)
{
	if (loc + size > get_length()) {
		BOOST_LOG_TRIVIAL(error) << "the portion is out of boundary";
		return local_vec_store::ptr();
	}

	return local_vec_store::ptr(new local_ref_vec_store(get(loc),
				loc, size, get_type(), -1));
}

local_vec_store::const_ptr smp_vec_store::get_portion(off_t loc,
			size_t size) const
{
	if (loc + size > get_length()) {
		BOOST_LOG_TRIVIAL(error) << "the portion is out of boundary";
		return local_vec_store::ptr();
	}

	return local_vec_store::ptr(new local_cref_vec_store(get(loc),
				loc, size, get_type(), -1));
}

size_t smp_vec_store::get_portion_size() const
{
	return 64 * 1024;
}

matrix_store::const_ptr smp_vec_store::conv2mat(size_t nrow, size_t ncol,
			bool byrow) const
{
	assert(arr == data.get_raw());
	if (get_length() < nrow * ncol) {
		BOOST_LOG_TRIVIAL(error)
			<< "The vector doesn't have enough elements";
		return matrix_store::ptr();
	}
	if (byrow)
		return mem_row_matrix_store::create(data, nrow, ncol, get_type());
	else
		return mem_col_matrix_store::create(data, nrow, ncol, get_type());
}

template<>
vec_store::ptr create_vec_store<double>(double start, double end,
		double stride)
{
	// The result of division may generate a real number slightly smaller than
	// what we want because of the representation precision in the machine.
	// When we convert the real number to an integer, we may find the number
	// is smaller than exepcted. We need to add a very small number to
	// the real number to correct the problem.
	// TODO is it the right way to correct the problem?
	long n = (end - start) / stride + 1e-9;
	if (n < 0) {
		BOOST_LOG_TRIVIAL(error) <<"wrong sign in 'by' argument";
		return vec_store::ptr();
	}
	// We need to count the start element.
	n++;

	detail::smp_vec_store::ptr v = detail::smp_vec_store::create(n,
			get_scalar_type<double>());
	v->set_data(seq_set_vec_operate<double>(n, start, stride));
	return v;
}

}

}
<commit_msg>[Matrix]: fix a bug in deep copy a mem vectore store.<commit_after>/*
 * Copyright 2015 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <boost/format.hpp>

#include "log.h"
#include "common.h"

#include "mem_vec_store.h"
#include "bulk_operate.h"
#include "local_vec_store.h"
#include "mem_matrix_store.h"
#include "NUMA_vector.h"

namespace fm
{

namespace detail
{

mem_vec_store::ptr mem_vec_store::create(size_t length, int num_nodes,
		const scalar_type &type)
{
	if (num_nodes < 0)
		return smp_vec_store::create(length, type);
	else
		return NUMA_vec_store::create(length, num_nodes, type);
}

bool mem_vec_store::copy_from(const char *buf, size_t num_bytes)
{
	if (get_raw_arr() == NULL)
		return false;

	if (num_bytes % get_entry_size() != 0
			|| num_bytes / get_entry_size() != get_length())
		return false;
	memcpy(get_raw_arr(), buf, num_bytes);
	return true;
}

smp_vec_store::smp_vec_store(size_t length, const scalar_type &type): mem_vec_store(
		length, type), data(length * type.get_size())
{
	this->arr = data.get_raw();
}

smp_vec_store::smp_vec_store(const detail::raw_data_array &data,
		const scalar_type &type): mem_vec_store(
			data.get_num_bytes() / type.get_size(), type)
{
	assert(data.get_num_bytes() % type.get_size() == 0);
	this->data = data;
	this->arr = this->data.get_raw();
}

smp_vec_store::ptr smp_vec_store::create(const detail::raw_data_array &data,
			const scalar_type &type)
{
	if (data.get_num_bytes() % type.get_size() != 0) {
		BOOST_LOG_TRIVIAL(error)
			<< "The data array has a wrong number of bytes";
		return smp_vec_store::ptr();
	}
	return ptr(new smp_vec_store(data, type));
}

smp_vec_store::ptr smp_vec_store::get(const smp_vec_store &idxs) const
{
	if (idxs.get_type() != get_scalar_type<off_t>()) {
		BOOST_LOG_TRIVIAL(error) << "The index vector isn't of the off_t type";
		return smp_vec_store::ptr();
	}

	smp_vec_store::ptr ret = smp_vec_store::create(idxs.get_length(), get_type());
	int num_threads = get_num_omp_threads();
	size_t part_len = ceil(((double) idxs.get_length()) / num_threads);
#pragma omp parallel for
	for (int k = 0; k < num_threads; k++) {
		size_t start = k * part_len;
		size_t end = std::min((k + 1) * part_len, idxs.get_length());
		size_t local_len = end >= start ? end - start : 0;
		if (local_len == 0)
			continue;

		std::vector<const char *> src_locs(local_len);
		for (size_t i = 0; i < local_len; i++) {
			off_t idx = idxs.get<off_t>(i + start);
			// Check if it's out of the range.
			if (idx < 0 && (size_t) idx >= this->get_length()) {
				BOOST_LOG_TRIVIAL(error)
					<< boost::format("%1% is out of range") % idx;
				continue;
			}

			src_locs[i] = this->get(idx);
		}
		get_type().get_sg().gather(src_locs,
				ret->arr + start * ret->get_entry_size());
	}
	return ret;
}

bool smp_vec_store::append(std::vector<vec_store::const_ptr>::const_iterator vec_it,
		std::vector<vec_store::const_ptr>::const_iterator vec_end)
{
	// Get the total size of the result vector.
	size_t tot_res_size = this->get_length();
	for (auto it = vec_it; it != vec_end; it++) {
		tot_res_size += (*it)->get_length();
		if (!(*it)->is_in_mem()) {
			BOOST_LOG_TRIVIAL(error)
				<< "Not support appending an ext-mem vector to an in-mem vector";
			return false;
		}
		if (get_type() != (*it)->get_type()) {
			BOOST_LOG_TRIVIAL(error) << "The two vectors don't have the same type";
			return false;
		}
	}

	// Merge all results to a single vector.
	off_t loc = this->get_length() + get_sub_start();
	this->resize(tot_res_size);
	for (auto it = vec_it; it != vec_end; it++) {
		assert(loc + (*it)->get_length() <= this->get_length());
		assert((*it)->is_in_mem());
		const mem_vec_store &mem_vec = static_cast<const mem_vec_store &>(**it);
		bool ret = data.set_sub_arr(loc * get_entry_size(),
				mem_vec.get_raw_arr(), mem_vec.get_length() * get_entry_size());
		assert(ret);
		loc += (*it)->get_length();
	}
	return true;
}

bool smp_vec_store::append(const vec_store &vec)
{
	if (!vec.is_in_mem()) {
		BOOST_LOG_TRIVIAL(error) << "The input vector isn't in memory";
		return false;
	}
	if (get_type() != vec.get_type()) {
		BOOST_LOG_TRIVIAL(error) << "The two vectors don't have the same type";
		return false;
	}
	// TODO We might want to over expand a little, so we don't need to copy
	// the memory again and again.
	// TODO if this is a sub_vector, what should we do?
	assert(get_sub_start() == 0);
	off_t loc = this->get_length() + get_sub_start();
	this->resize(vec.get_length() + get_length());
	assert(loc + vec.get_length() <= this->get_length());
	const mem_vec_store &mem_vec = static_cast<const mem_vec_store &>(vec);
	assert(mem_vec.get_raw_arr());
	return data.set_sub_arr(loc * get_entry_size(), mem_vec.get_raw_arr(),
			mem_vec.get_length() * get_entry_size());
}

bool smp_vec_store::resize(size_t new_length)
{
	if (new_length == get_length())
		return true;

	size_t tot_len = data.get_num_bytes() / get_type().get_size();
	// We don't want to reallocate memory when shrinking the vector.
	if (new_length < tot_len) {
		return vec_store::resize(new_length);
	}

	// Keep the old information of the vector.
	detail::raw_data_array old_data = data;
	char *old_arr = arr;
	size_t old_length = get_length();

	size_t real_length = old_length;
	if (real_length == 0)
		real_length = 1;
	for (; real_length < new_length; real_length *= 2);
	this->data = detail::raw_data_array(real_length * get_type().get_size());
	this->arr = this->data.get_raw();
	memcpy(arr, old_arr, std::min(old_length, new_length) * get_entry_size());
	return vec_store::resize(new_length);
}

bool smp_vec_store::expose_sub_vec(off_t start, size_t length)
{
	size_t tot_len = data.get_num_bytes() / get_type().get_size();
	if (start + length > tot_len) {
		exit(1);
		BOOST_LOG_TRIVIAL(error) << "expose_sub_vec: out of range";
		return false;
	}

	resize(length);
	arr = data.get_raw() + start * get_entry_size();
	return true;
}

vec_store::ptr smp_vec_store::deep_copy() const
{
	assert(get_raw_arr() == data.get_raw());
	detail::raw_data_array copy = this->data.deep_copy();
	smp_vec_store::ptr ret = smp_vec_store::create(copy, get_type());
	ret->resize(this->get_length());
	return ret;
}

vec_store::ptr smp_vec_store::sort_with_index()
{
	smp_vec_store::ptr indexes = smp_vec_store::create(get_length(),
			get_scalar_type<off_t>());
	get_type().get_sorter().sort_with_index(arr,
			(off_t *) indexes->arr, get_length(), false);
	return indexes;
}

void smp_vec_store::set_data(const set_vec_operate &op)
{
	// I assume this is column-wise matrix.
	// TODO parallel.
	op.set(arr, get_length(), 0);
}

void smp_vec_store::set(const std::vector<const char *> &locs)
{
	assert(locs.size() <= get_length());
	get_type().get_sg().gather(locs, arr);
}

local_vec_store::ptr smp_vec_store::get_portion(off_t loc, size_t size)
{
	if (loc + size > get_length()) {
		BOOST_LOG_TRIVIAL(error) << "the portion is out of boundary";
		return local_vec_store::ptr();
	}

	return local_vec_store::ptr(new local_ref_vec_store(get(loc),
				loc, size, get_type(), -1));
}

local_vec_store::const_ptr smp_vec_store::get_portion(off_t loc,
			size_t size) const
{
	if (loc + size > get_length()) {
		BOOST_LOG_TRIVIAL(error) << "the portion is out of boundary";
		return local_vec_store::ptr();
	}

	return local_vec_store::ptr(new local_cref_vec_store(get(loc),
				loc, size, get_type(), -1));
}

size_t smp_vec_store::get_portion_size() const
{
	return 64 * 1024;
}

matrix_store::const_ptr smp_vec_store::conv2mat(size_t nrow, size_t ncol,
			bool byrow) const
{
	assert(arr == data.get_raw());
	if (get_length() < nrow * ncol) {
		BOOST_LOG_TRIVIAL(error)
			<< "The vector doesn't have enough elements";
		return matrix_store::ptr();
	}
	if (byrow)
		return mem_row_matrix_store::create(data, nrow, ncol, get_type());
	else
		return mem_col_matrix_store::create(data, nrow, ncol, get_type());
}

template<>
vec_store::ptr create_vec_store<double>(double start, double end,
		double stride)
{
	// The result of division may generate a real number slightly smaller than
	// what we want because of the representation precision in the machine.
	// When we convert the real number to an integer, we may find the number
	// is smaller than exepcted. We need to add a very small number to
	// the real number to correct the problem.
	// TODO is it the right way to correct the problem?
	long n = (end - start) / stride + 1e-9;
	if (n < 0) {
		BOOST_LOG_TRIVIAL(error) <<"wrong sign in 'by' argument";
		return vec_store::ptr();
	}
	// We need to count the start element.
	n++;

	detail::smp_vec_store::ptr v = detail::smp_vec_store::create(n,
			get_scalar_type<double>());
	v->set_data(seq_set_vec_operate<double>(n, start, stride));
	return v;
}

}

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: shapetransitionfactory.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 08:41:10 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_slideshow.hxx"

#include <basegfx/numeric/ftools.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <canvas/debug.hxx>
#include <transitionfactory.hxx>
#include <transitiontools.hxx>
#include <parametricpolypolygonfactory.hxx>
#include <animationfactory.hxx>
#include <clippingfunctor.hxx>
#include <com/sun/star/animations/TransitionType.hpp>
#include <com/sun/star/animations/TransitionSubType.hpp>

#ifndef BOOST_BIND_HPP_INCLUDED
#include <boost/bind.hpp>
#endif

using namespace ::com::sun::star;

namespace presentation {
namespace internal {

/***************************************************
 ***                                             ***
 ***          Shape Transition Effects           ***
 ***                                             ***
 ***************************************************/

namespace {

class ClippingAnimation : public NumberAnimation
{
public:
    ClippingAnimation(
        const ParametricPolyPolygonSharedPtr&   rPolygon,
        const LayerManagerSharedPtr&            rLayerManager,
        const TransitionInfo&                   rTransitionInfo,
        bool                                    bDirectionForward,
        bool                                    bModeIn );

    ~ClippingAnimation();

    // Animation interface
    // -------------------
    virtual void start( const AnimatableShapeSharedPtr&     rShape,
                        const ShapeAttributeLayerSharedPtr& rAttrLayer );
    virtual void end();

    // NumberAnimation interface
    // -----------------------
    virtual bool operator()( double nValue );
    virtual double getUnderlyingValue() const;

private:
    void end_();

    AnimatableShapeSharedPtr           mpShape;
    ShapeAttributeLayerSharedPtr       mpAttrLayer;
    LayerManagerSharedPtr              mpLayerManager;
    ClippingFunctor                    maClippingFunctor;
    bool                               mbSpriteActive;
};

ClippingAnimation::ClippingAnimation(
    const ParametricPolyPolygonSharedPtr&   rPolygon,
    const LayerManagerSharedPtr&            rLayerManager,
    const TransitionInfo&                   rTransitionInfo,
    bool                                    bDirectionForward,
    bool                                    bModeIn ) :
        mpShape(),
        mpAttrLayer(),
        mpLayerManager( rLayerManager ),
        maClippingFunctor( rPolygon,
                           rTransitionInfo,
                           bDirectionForward,
                           bModeIn ),
        mbSpriteActive(false)
{
    ENSURE_AND_THROW(
        rLayerManager.get(),
        "ClippingAnimation::ClippingAnimation(): Invalid LayerManager" );
}

ClippingAnimation::~ClippingAnimation()
{
    end_();
}

void ClippingAnimation::start( const AnimatableShapeSharedPtr&      rShape,
                               const ShapeAttributeLayerSharedPtr&  rAttrLayer )
{
    OSL_ENSURE( !mpShape.get(),
                "ClippingAnimation::start(): Shape already set" );
    OSL_ENSURE( !mpAttrLayer.get(),
                "ClippingAnimation::start(): Attribute layer already set" );

    mpShape = rShape;
    mpAttrLayer = rAttrLayer;

    ENSURE_AND_THROW( rShape.get(),
                      "ClippingAnimation::start(): Invalid shape" );
    ENSURE_AND_THROW( rAttrLayer.get(),
                      "ClippingAnimation::start(): Invalid attribute layer" );

    mpShape = rShape;
    mpAttrLayer = rAttrLayer;

    if( !mbSpriteActive )
    {
        mpLayerManager->enterAnimationMode( mpShape );
        mbSpriteActive = true;
    }
}

void ClippingAnimation::end()
{
    end_();
}

void ClippingAnimation::end_()
{
    if( mbSpriteActive )
    {
        mbSpriteActive = false;
        mpLayerManager->leaveAnimationMode( mpShape );

        if( mpShape->isUpdateNecessary() )
            mpLayerManager->notifyShapeUpdate( mpShape );
    }
}

bool ClippingAnimation::operator()( double nValue )
{
    ENSURE_AND_RETURN(
        mpAttrLayer.get() && mpShape.get(),
        "ClippingAnimation::operator(): Invalid ShapeAttributeLayer" );

    // set new clip
    mpAttrLayer->setClip( maClippingFunctor( nValue,
                                             mpShape->getDOMBounds().getRange() ) );

    if( mpShape->isUpdateNecessary() )
        mpLayerManager->notifyShapeUpdate( mpShape );

    return true;
}

double ClippingAnimation::getUnderlyingValue() const
{
    ENSURE_AND_THROW(
        mpAttrLayer.get(),
        "ClippingAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );

    return 0.0;     // though this should be used in concert with
                    // ActivitiesFactory::createSimpleActivity, better
                    // explicitely name our start value.
                    // Permissible range for operator() above is [0,1]
}

} // anon namespace

AnimationActivitySharedPtr TransitionFactory::createShapeTransition(
    const ActivitiesFactory::CommonParameters&          rParms,
    const AnimatableShapeSharedPtr&                     rShape,
    const LayerManagerSharedPtr&                        rLayerManager,
    uno::Reference< animations::XTransitionFilter > const& xTransition )
{
    return createShapeTransition( rParms,
                                  rShape,
                                  rLayerManager,
                                  xTransition,
                                  xTransition->getTransition(),
                                  xTransition->getSubtype() );
}

AnimationActivitySharedPtr TransitionFactory::createShapeTransition(
    const ActivitiesFactory::CommonParameters&              rParms,
    const AnimatableShapeSharedPtr&                         rShape,
    const LayerManagerSharedPtr&                            rLayerManager,
    ::com::sun::star::uno::Reference<
        ::com::sun::star::animations::XTransitionFilter > const& xTransition,
    sal_Int16                                               nType,
    sal_Int16                                               nSubType )
{
    ENSURE_AND_THROW(
        xTransition.is(),
        "TransitionFactory::createShapeTransition(): Invalid XTransition" );

    const TransitionInfo* pTransitionInfo(
        getTransitionInfo( nType, nSubType ) );

    AnimationActivitySharedPtr pGeneratedActivity;
    if( pTransitionInfo != NULL )
    {
        switch( pTransitionInfo->meTransitionClass )
        {
            default:
            case TransitionInfo::TRANSITION_INVALID:
                OSL_ENSURE( false,
                            "TransitionFactory::createShapeTransition(): Invalid transition type. "
                            "Don't ask me for a 0 TransitionType, have no XTransitionFilter node instead!" );
                return AnimationActivitySharedPtr();

            case TransitionInfo::TRANSITION_CLIP_POLYPOLYGON:
            {
                // generate parametric poly-polygon
                ParametricPolyPolygonSharedPtr pPoly(
                    ParametricPolyPolygonFactory::createClipPolyPolygon(
                        nType, nSubType ) );

                // create a clip activity from that
                pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
                    rParms,
                    NumberAnimationSharedPtr(
                        new ClippingAnimation(
                            pPoly,
                            rLayerManager,
                            *pTransitionInfo,
                            xTransition->getDirection(),
                            xTransition->getMode() ) ),
                    true );
            }
            break;

            case TransitionInfo::TRANSITION_SPECIAL:
            {
                switch( nType )
                {
                    case animations::TransitionType::RANDOM:
                    {
                        // select randomly one of the effects from the
                        // TransitionFactoryTable

                        const TransitionInfo* pRandomTransitionInfo( getRandomTransitionInfo() );

                        ENSURE_AND_THROW( pRandomTransitionInfo != NULL,
                                          "TransitionFactory::createShapeTransition(): Got invalid random transition info" );

                        ENSURE_AND_THROW( pRandomTransitionInfo->mnTransitionType != animations::TransitionType::RANDOM,
                                          "TransitionFactory::createShapeTransition(): Got random again for random input!" );

                        // and recurse
                        pGeneratedActivity = createShapeTransition( rParms,
                                                                    rShape,
                                                                    rLayerManager,
                                                                    xTransition,
                                                                    pRandomTransitionInfo->mnTransitionType,
                                                                    pRandomTransitionInfo->mnTransitionSubType );
                    }
                    break;

                    // TODO(F3): Implement slidewipe for shape
                    case animations::TransitionType::SLIDEWIPE:
                    {
                        sal_Int16 nBarWipeSubType(0);
                        bool      bDirectionForward(true);

                        // map slidewipe to BARWIPE, for now
                        switch( nSubType )
                        {
                            case animations::TransitionSubType::FROMLEFT:
                                nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT;
                                bDirectionForward = true;
                                break;

                            case animations::TransitionSubType::FROMRIGHT:
                                nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT;
                                bDirectionForward = false;
                                break;

                            case animations::TransitionSubType::FROMTOP:
                                nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM;
                                bDirectionForward = true;
                                break;

                            case animations::TransitionSubType::FROMBOTTOM:
                                nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM;
                                bDirectionForward = false;
                                break;

                            default:
                                ENSURE_AND_THROW( false,
                                                  "TransitionFactory::createShapeTransition(): Unexpected subtype for SLIDEWIPE" );
                                break;
                        }

                        // generate parametric poly-polygon
                        ParametricPolyPolygonSharedPtr pPoly(
                            ParametricPolyPolygonFactory::createClipPolyPolygon(
                                animations::TransitionType::BARWIPE,
                                nBarWipeSubType ) );

                        // create a clip activity from that
                        pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
                            rParms,
                            NumberAnimationSharedPtr(
                                new ClippingAnimation(
                                    pPoly,
                                    rLayerManager,
                                    *getTransitionInfo( animations::TransitionType::BARWIPE,
                                                        nBarWipeSubType ),
                                    bDirectionForward,
                                    xTransition->getMode() ) ),
                            true );
                    }
                    break;

                    default:
                    {
                        // TODO(F1): Check whether there's anything left, anyway,
                        // for _shape_ transitions. AFAIK, there are no special
                        // effects for shapes...

                        // for now, map all to fade effect
                        pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
                            rParms,
                            AnimationFactory::createNumberPropertyAnimation(
                                ::rtl::OUString(
                                    RTL_CONSTASCII_USTRINGPARAM("Opacity") ),
                                rShape,
                                rLayerManager ),
                            xTransition->getMode() );
                    }
                    break;
                }
            }
            break;
        }
    }

    if( !pGeneratedActivity.get() )
    {
        // No animation generated, maybe no table entry for given
        // transition?
        OSL_TRACE(
            "TransitionFactory::createShapeTransition(): Unknown type/subtype (%d/%d) "
            "combination encountered",
            xTransition->getTransition(),
            xTransition->getSubtype() );
        OSL_ENSURE(
            false,
            "TransitionFactory::createShapeTransition(): Unknown type/subtype "
            "combination encountered" );
    }

    return pGeneratedActivity;
}

}
}
<commit_msg>INTEGRATION: CWS presfixes09 (1.5.10); FILE MERGED 2006/10/18 19:59:09 thb 1.5.10.5: RESYNC: (1.5-1.6); FILE MERGED 2006/04/24 13:25:33 thb 1.5.10.4: #i53194# Unified include statements (local headers always have double quotes; external headers angle brackets); reverted EventMultiplexer pause events to shared_ptr; removed EventMultiplexer::removeViewHandler(), since the handler is held weakly, anyway. 2006/04/12 20:40:08 thb 1.5.10.3: #i37778# Replaced all shared_ptr.get() != NULL places with the more elegant automatic-conversion-to-bool version (at least where the compiler tolerated that) 2006/03/24 18:23:25 thb 1.5.10.2: #i37778# Moved whole slideshow engine from namespace presentation (which conflicts with one of the UNO subnamespaces) to slideshow 2006/03/06 22:14:32 thb 1.5.10.1: #i53194# #i55294# #i59324# Overhauled IntrinsicAnimationActivity; fixes GIF animation import; corrected rehearse timings sprite size; several cosmetic changes (removed external header guards); prepared scene for sprite prio<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: shapetransitionfactory.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 15:45:03 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_slideshow.hxx"

#include <canvas/debug.hxx>

#include <comphelper/anytostring.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>

#include <com/sun/star/animations/TransitionType.hpp>
#include <com/sun/star/animations/TransitionSubType.hpp>

#include "transitionfactory.hxx"
#include "transitiontools.hxx"
#include "parametricpolypolygonfactory.hxx"
#include "animationfactory.hxx"
#include "clippingfunctor.hxx"

#include <boost/bind.hpp>

using namespace ::com::sun::star;

namespace slideshow {
namespace internal {

/***************************************************
 ***                                             ***
 ***          Shape Transition Effects           ***
 ***                                             ***
 ***************************************************/

namespace {

class ClippingAnimation : public NumberAnimation
{
public:
    ClippingAnimation(
        const ParametricPolyPolygonSharedPtr&   rPolygon,
        const LayerManagerSharedPtr&            rLayerManager,
        const TransitionInfo&                   rTransitionInfo,
        bool                                    bDirectionForward,
        bool                                    bModeIn );

    ~ClippingAnimation();

    // Animation interface
    // -------------------
    virtual void start( const AnimatableShapeSharedPtr&     rShape,
                        const ShapeAttributeLayerSharedPtr& rAttrLayer );
    virtual void end();

    // NumberAnimation interface
    // -----------------------
    virtual bool operator()( double nValue );
    virtual double getUnderlyingValue() const;

private:
    void end_();

    AnimatableShapeSharedPtr           mpShape;
    ShapeAttributeLayerSharedPtr       mpAttrLayer;
    LayerManagerSharedPtr              mpLayerManager;
    ClippingFunctor                    maClippingFunctor;
    bool                               mbSpriteActive;
};

ClippingAnimation::ClippingAnimation(
    const ParametricPolyPolygonSharedPtr&   rPolygon,
    const LayerManagerSharedPtr&            rLayerManager,
    const TransitionInfo&                   rTransitionInfo,
    bool                                    bDirectionForward,
    bool                                    bModeIn ) :
        mpShape(),
        mpAttrLayer(),
        mpLayerManager( rLayerManager ),
        maClippingFunctor( rPolygon,
                           rTransitionInfo,
                           bDirectionForward,
                           bModeIn ),
        mbSpriteActive(false)
{
    ENSURE_AND_THROW(
        rLayerManager,
        "ClippingAnimation::ClippingAnimation(): Invalid LayerManager" );
}

ClippingAnimation::~ClippingAnimation()
{
    try
    {
        end_();
    }
    catch (uno::Exception &) {
        OSL_ENSURE( false, rtl::OUStringToOString(
                        comphelper::anyToString(
                            cppu::getCaughtException() ),
                        RTL_TEXTENCODING_UTF8 ).getStr() );
    }
}

void ClippingAnimation::start( const AnimatableShapeSharedPtr&      rShape,
                               const ShapeAttributeLayerSharedPtr&  rAttrLayer )
{
    OSL_ENSURE( !mpShape,
                "ClippingAnimation::start(): Shape already set" );
    OSL_ENSURE( !mpAttrLayer,
                "ClippingAnimation::start(): Attribute layer already set" );

    mpShape = rShape;
    mpAttrLayer = rAttrLayer;

    ENSURE_AND_THROW( rShape,
                      "ClippingAnimation::start(): Invalid shape" );
    ENSURE_AND_THROW( rAttrLayer,
                      "ClippingAnimation::start(): Invalid attribute layer" );

    mpShape = rShape;
    mpAttrLayer = rAttrLayer;

    if( !mbSpriteActive )
    {
        mpLayerManager->enterAnimationMode( mpShape );
        mbSpriteActive = true;
    }
}

void ClippingAnimation::end()
{
    end_();
}

void ClippingAnimation::end_()
{
    if( mbSpriteActive )
    {
        mbSpriteActive = false;
        mpLayerManager->leaveAnimationMode( mpShape );

        if( mpShape->isUpdateNecessary() )
            mpLayerManager->notifyShapeUpdate( mpShape );
    }
}

bool ClippingAnimation::operator()( double nValue )
{
    ENSURE_AND_RETURN(
        mpAttrLayer && mpShape,
        "ClippingAnimation::operator(): Invalid ShapeAttributeLayer" );

    // set new clip
    mpAttrLayer->setClip( maClippingFunctor( nValue,
                                             mpShape->getDOMBounds().getRange() ) );

    if( mpShape->isUpdateNecessary() )
        mpLayerManager->notifyShapeUpdate( mpShape );

    return true;
}

double ClippingAnimation::getUnderlyingValue() const
{
    ENSURE_AND_THROW(
        mpAttrLayer,
        "ClippingAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );

    return 0.0;     // though this should be used in concert with
                    // ActivitiesFactory::createSimpleActivity, better
                    // explicitely name our start value.
                    // Permissible range for operator() above is [0,1]
}

} // anon namespace

AnimationActivitySharedPtr TransitionFactory::createShapeTransition(
    const ActivitiesFactory::CommonParameters&          rParms,
    const AnimatableShapeSharedPtr&                     rShape,
    const LayerManagerSharedPtr&                        rLayerManager,
    uno::Reference< animations::XTransitionFilter > const& xTransition )
{
    return createShapeTransition( rParms,
                                  rShape,
                                  rLayerManager,
                                  xTransition,
                                  xTransition->getTransition(),
                                  xTransition->getSubtype() );
}

AnimationActivitySharedPtr TransitionFactory::createShapeTransition(
    const ActivitiesFactory::CommonParameters&              rParms,
    const AnimatableShapeSharedPtr&                         rShape,
    const LayerManagerSharedPtr&                            rLayerManager,
    ::com::sun::star::uno::Reference<
        ::com::sun::star::animations::XTransitionFilter > const& xTransition,
    sal_Int16                                               nType,
    sal_Int16                                               nSubType )
{
    ENSURE_AND_THROW(
        xTransition.is(),
        "TransitionFactory::createShapeTransition(): Invalid XTransition" );

    const TransitionInfo* pTransitionInfo(
        getTransitionInfo( nType, nSubType ) );

    AnimationActivitySharedPtr pGeneratedActivity;
    if( pTransitionInfo != NULL )
    {
        switch( pTransitionInfo->meTransitionClass )
        {
            default:
            case TransitionInfo::TRANSITION_INVALID:
                OSL_ENSURE( false,
                            "TransitionFactory::createShapeTransition(): Invalid transition type. "
                            "Don't ask me for a 0 TransitionType, have no XTransitionFilter node instead!" );
                return AnimationActivitySharedPtr();

            case TransitionInfo::TRANSITION_CLIP_POLYPOLYGON:
            {
                // generate parametric poly-polygon
                ParametricPolyPolygonSharedPtr pPoly(
                    ParametricPolyPolygonFactory::createClipPolyPolygon(
                        nType, nSubType ) );

                // create a clip activity from that
                pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
                    rParms,
                    NumberAnimationSharedPtr(
                        new ClippingAnimation(
                            pPoly,
                            rLayerManager,
                            *pTransitionInfo,
                            xTransition->getDirection(),
                            xTransition->getMode() ) ),
                    true );
            }
            break;

            case TransitionInfo::TRANSITION_SPECIAL:
            {
                switch( nType )
                {
                    case animations::TransitionType::RANDOM:
                    {
                        // select randomly one of the effects from the
                        // TransitionFactoryTable

                        const TransitionInfo* pRandomTransitionInfo( getRandomTransitionInfo() );

                        ENSURE_AND_THROW( pRandomTransitionInfo != NULL,
                                          "TransitionFactory::createShapeTransition(): Got invalid random transition info" );

                        ENSURE_AND_THROW( pRandomTransitionInfo->mnTransitionType != animations::TransitionType::RANDOM,
                                          "TransitionFactory::createShapeTransition(): Got random again for random input!" );

                        // and recurse
                        pGeneratedActivity = createShapeTransition( rParms,
                                                                    rShape,
                                                                    rLayerManager,
                                                                    xTransition,
                                                                    pRandomTransitionInfo->mnTransitionType,
                                                                    pRandomTransitionInfo->mnTransitionSubType );
                    }
                    break;

                    // TODO(F3): Implement slidewipe for shape
                    case animations::TransitionType::SLIDEWIPE:
                    {
                        sal_Int16 nBarWipeSubType(0);
                        bool      bDirectionForward(true);

                        // map slidewipe to BARWIPE, for now
                        switch( nSubType )
                        {
                            case animations::TransitionSubType::FROMLEFT:
                                nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT;
                                bDirectionForward = true;
                                break;

                            case animations::TransitionSubType::FROMRIGHT:
                                nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT;
                                bDirectionForward = false;
                                break;

                            case animations::TransitionSubType::FROMTOP:
                                nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM;
                                bDirectionForward = true;
                                break;

                            case animations::TransitionSubType::FROMBOTTOM:
                                nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM;
                                bDirectionForward = false;
                                break;

                            default:
                                ENSURE_AND_THROW( false,
                                                  "TransitionFactory::createShapeTransition(): Unexpected subtype for SLIDEWIPE" );
                                break;
                        }

                        // generate parametric poly-polygon
                        ParametricPolyPolygonSharedPtr pPoly(
                            ParametricPolyPolygonFactory::createClipPolyPolygon(
                                animations::TransitionType::BARWIPE,
                                nBarWipeSubType ) );

                        // create a clip activity from that
                        pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
                            rParms,
                            NumberAnimationSharedPtr(
                                new ClippingAnimation(
                                    pPoly,
                                    rLayerManager,
                                    *getTransitionInfo( animations::TransitionType::BARWIPE,
                                                        nBarWipeSubType ),
                                    bDirectionForward,
                                    xTransition->getMode() ) ),
                            true );
                    }
                    break;

                    default:
                    {
                        // TODO(F1): Check whether there's anything left, anyway,
                        // for _shape_ transitions. AFAIK, there are no special
                        // effects for shapes...

                        // for now, map all to fade effect
                        pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
                            rParms,
                            AnimationFactory::createNumberPropertyAnimation(
                                ::rtl::OUString(
                                    RTL_CONSTASCII_USTRINGPARAM("Opacity") ),
                                rShape,
                                rLayerManager ),
                            xTransition->getMode() );
                    }
                    break;
                }
            }
            break;
        }
    }

    if( !pGeneratedActivity )
    {
        // No animation generated, maybe no table entry for given
        // transition?
        OSL_TRACE(
            "TransitionFactory::createShapeTransition(): Unknown type/subtype (%d/%d) "
            "combination encountered",
            xTransition->getTransition(),
            xTransition->getSubtype() );
        OSL_ENSURE(
            false,
            "TransitionFactory::createShapeTransition(): Unknown type/subtype "
            "combination encountered" );
    }

    return pGeneratedActivity;
}

}
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright 2014 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

#ifndef CQL3_FUNCTION_NAME_HH
#define CQL3_FUNCTION_NAME_HH

#include "core/sstring.hh"
#include "db/system_keyspace.hh"
#include <iostream>
#include <functional>

namespace cql3 {

namespace functions {

class function_name final {
public:
    const sstring keyspace;
    const sstring name;

    static function_name native_function(sstring name) {
        return function_name(db::system_keyspace::NAME, name);
    }

    function_name(sstring keyspace, sstring name)
            : keyspace(std::move(keyspace)), name(std::move(name)) {
    }

    function_name as_native_function() const {
        return native_function(name);
    }

    bool has_keyspace() const {
        return !keyspace.empty();
    }

    bool operator==(const function_name& x) const {
        return keyspace == x.keyspace && name == x.name;
    }
};

inline
std::ostream& operator<<(std::ostream& os, const function_name& fn) {
    if (!fn.keyspace.empty()) {
        os << fn.keyspace << ".";
    }
    return os << fn.name;
}

}
}

namespace std {

template <>
struct hash<cql3::functions::function_name> {
    size_t operator()(const cql3::functions::function_name& x) const {
        return std::hash<sstring>()(x.keyspace) ^ std::hash<sstring>()(x.name);
    }
};

}

#endif
<commit_msg>cql3: make function_name friendlier to ANTLR<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright 2014 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

#ifndef CQL3_FUNCTION_NAME_HH
#define CQL3_FUNCTION_NAME_HH

#include "core/sstring.hh"
#include "db/system_keyspace.hh"
#include <iostream>
#include <functional>

namespace cql3 {

namespace functions {

class function_name final {
public:
    sstring keyspace;
    sstring name;

    static function_name native_function(sstring name) {
        return function_name(db::system_keyspace::NAME, name);
    }

    function_name() = default; // for ANTLR
    function_name(sstring keyspace, sstring name)
            : keyspace(std::move(keyspace)), name(std::move(name)) {
    }

    function_name as_native_function() const {
        return native_function(name);
    }

    bool has_keyspace() const {
        return !keyspace.empty();
    }

    bool operator==(const function_name& x) const {
        return keyspace == x.keyspace && name == x.name;
    }
};

inline
std::ostream& operator<<(std::ostream& os, const function_name& fn) {
    if (!fn.keyspace.empty()) {
        os << fn.keyspace << ".";
    }
    return os << fn.name;
}

}
}

namespace std {

template <>
struct hash<cql3::functions::function_name> {
    size_t operator()(const cql3::functions::function_name& x) const {
        return std::hash<sstring>()(x.keyspace) ^ std::hash<sstring>()(x.name);
    }
};

}

#endif
<|endoftext|>


<commit_before>#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "highlevel_feature_extractor.h"
#include <rcsc/common/server_param.h>

using namespace rcsc;

HighLevelFeatureExtractor::HighLevelFeatureExtractor(int num_teammates,
                                                     int num_opponents,
                                                     bool playing_offense) :
  FeatureExtractor(num_teammates, num_opponents, playing_offense)
{
  assert(numTeammates >= 0);
  assert(numOpponents >= 0);
  numFeatures = num_basic_features + features_per_teammate * numTeammates
      + features_per_opponent * numOpponents;
  numFeatures+=2; // action status, stamina
  feature_vec.resize(numFeatures);
}

HighLevelFeatureExtractor::~HighLevelFeatureExtractor() {}

const std::vector<float>&
HighLevelFeatureExtractor::ExtractFeatures(const rcsc::WorldModel& wm,
					   bool last_action_status) {
  featIndx = 0;
  const ServerParam& SP = ServerParam::i();
  const SelfObject& self = wm.self();
  const Vector2D& self_pos = self.pos();
  const float self_ang = self.body().radian();
  const PlayerPtrCont& teammates = wm.teammatesFromSelf();
  const PlayerPtrCont& opponents = wm.opponentsFromSelf();
  float maxR = sqrtf(SP.pitchHalfLength() * SP.pitchHalfLength()
                     + SP.pitchHalfWidth() * SP.pitchHalfWidth());
  // features about self pos
  // Allow the agent to go 10% over the playfield in any direction
  float tolerance_x = .1 * SP.pitchHalfLength();
  float tolerance_y = .1 * SP.pitchHalfWidth();
  // Feature[0]: X-postion
  if (playingOffense) {
    addNormFeature(self_pos.x, -tolerance_x, SP.pitchHalfLength() + tolerance_x);
  } else {
    addNormFeature(self_pos.x, -SP.pitchHalfLength()-tolerance_x, tolerance_x);
  }

  // Feature[1]: Y-Position
  addNormFeature(self_pos.y, -SP.pitchHalfWidth() - tolerance_y,
                 SP.pitchHalfWidth() + tolerance_y);

  // Feature[2]: Self Angle
  addNormFeature(self_ang, -M_PI, M_PI);

  float r;
  float th;
  // Features about the ball
  Vector2D ball_pos = wm.ball().pos();
  angleDistToPoint(self_pos, ball_pos, th, r);
  // Feature[3] and [4]: (x,y) postition of the ball
  if (playingOffense) {
    addNormFeature(ball_pos.x, -tolerance_x, SP.pitchHalfLength() + tolerance_x);
  } else {
    addNormFeature(ball_pos.x, -SP.pitchHalfLength()-tolerance_x, tolerance_x);
  }
  addNormFeature(ball_pos.y, -SP.pitchHalfWidth() - tolerance_y, SP.pitchHalfWidth() + tolerance_y);
  // Feature[5]: Able to kick
  addNormFeature(self.isKickable(), false, true);

  // Features about distance to goal center
  Vector2D goalCenter(SP.pitchHalfLength(), 0);
  if (!playingOffense) {
    goalCenter.assign(-SP.pitchHalfLength(), 0);
  }
  angleDistToPoint(self_pos, goalCenter, th, r);
  // Feature[6]: Goal Center Distance
  addNormFeature(r, 0, maxR);
  // Feature[7]: Angle to goal center
  addNormFeature(th, -M_PI, M_PI);
  // Feature[8]: largest open goal angle
  addNormFeature(calcLargestGoalAngle(wm, self_pos), 0, M_PI);
  // Feature[9]: Dist to our closest opp
  if (numOpponents > 0) {
    calcClosestOpp(wm, self_pos, th, r);
    addNormFeature(r, 0, maxR);
  } else {
    addFeature(FEAT_INVALID);
  }

  // Features[9 - 9+T]: teammate's open angle to goal
  int detected_teammates = 0;
  for (PlayerPtrCont::const_iterator it=teammates.begin(); it != teammates.end(); ++it) {
    const PlayerObject* teammate = *it;
    if (valid(teammate) && teammate->unum() > 0 && detected_teammates < numTeammates) {
      addNormFeature(calcLargestGoalAngle(wm, teammate->pos()), 0, M_PI);
      detected_teammates++;
    }
  }
  // Add zero features for any missing teammates
  for (int i=detected_teammates; i<numTeammates; ++i) {
    addFeature(FEAT_INVALID);
  }

  // Features[9+T - 9+2T]: teammates' dists to closest opps
  if (numOpponents > 0) {
    detected_teammates = 0;
    for (PlayerPtrCont::const_iterator it=teammates.begin(); it != teammates.end(); ++it) {
      const PlayerObject* teammate = *it;
      if (valid(teammate) && teammate->unum() > 0 && detected_teammates < numTeammates) {
        calcClosestOpp(wm, teammate->pos(), th, r);
        addNormFeature(r, 0, maxR);
        detected_teammates++;
      }
    }
    // Add zero features for any missing teammates
    for (int i=detected_teammates; i<numTeammates; ++i) {
      addFeature(FEAT_INVALID);
    }
  } else { // If no opponents, add invalid features
    for (int i=0; i<numTeammates; ++i) {
      addFeature(FEAT_INVALID);
    }
  }

  // Features [9+2T - 9+3T]: open angle to teammates
  detected_teammates = 0;
  for (PlayerPtrCont::const_iterator it=teammates.begin(); it != teammates.end(); ++it) {
    const PlayerObject* teammate = *it;
    if (valid(teammate) && teammate->unum() > 0 && detected_teammates < numTeammates) {
      addNormFeature(calcLargestTeammateAngle(wm, self_pos, teammate->pos()),0,M_PI);
      detected_teammates++;
    }
  }
  // Add zero features for any missing teammates
  for (int i=detected_teammates; i<numTeammates; ++i) {
    addFeature(FEAT_INVALID);
  }

  // Features [9+3T - 9+6T]: x, y, unum of teammates
  detected_teammates = 0;
  for (PlayerPtrCont::const_iterator it=teammates.begin(); it != teammates.end(); ++it) {
    const PlayerObject* teammate = *it;
    if (valid(teammate) && teammate->unum() > 0 && detected_teammates < numTeammates) {
      if (playingOffense) {
        addNormFeature(teammate->pos().x, -tolerance_x, SP.pitchHalfLength() + tolerance_x);
      } else {
        addNormFeature(teammate->pos().x, -SP.pitchHalfLength()-tolerance_x, tolerance_x);
      }
      addNormFeature(teammate->pos().y, -tolerance_y - SP.pitchHalfWidth(), SP.pitchHalfWidth() + tolerance_y);
      addFeature(teammate->unum());
      detected_teammates++;
    }
  }
  // Add zero features for any missing teammates
  for (int i=detected_teammates; i<numTeammates; ++i) {
    addFeature(FEAT_INVALID);
    addFeature(FEAT_INVALID);
    addFeature(FEAT_INVALID);
  }

  // Features [9+6T - 9+6T+3O]: x, y, unum of opponents
  int detected_opponents = 0;
  for (PlayerPtrCont::const_iterator it = opponents.begin(); it != opponents.end(); ++it) {
    const PlayerObject* opponent = *it;
    if (valid(opponent) && opponent->unum() > 0 && detected_opponents < numOpponents) {
      if (playingOffense) {
        addNormFeature(opponent->pos().x, -tolerance_x, SP.pitchHalfLength() + tolerance_x);
      } else {
        addNormFeature(opponent->pos().x, -SP.pitchHalfLength()-tolerance_x, tolerance_x);
      }
      addNormFeature(opponent->pos().y, -tolerance_y - SP.pitchHalfWidth(), SP.pitchHalfWidth() + tolerance_y);
      addFeature(opponent->unum());
      detected_opponents++;
    }
  }
  // Add zero features for any missing opponents
  for (int i=detected_opponents; i<numOpponents; ++i) {
    addFeature(FEAT_INVALID);
    addFeature(FEAT_INVALID);
    addFeature(FEAT_INVALID);
  }

  if (last_action_status) {
    addFeature(FEAT_MAX);
  } else {
    addFeature(FEAT_MIN);
  }
  addNormFeature(self.stamina(), 0., observedStaminaMax);

  assert(featIndx == numFeatures);
  // checkFeatures();
  return feature_vec;
}

bool HighLevelFeatureExtractor::valid(const rcsc::PlayerObject* player) {
  if (!player) {return false;} //avoid segfaults
  const rcsc::Vector2D& pos = player->pos();
  if (!player->posValid()) {
    return false;
  }
  return pos.isValid();
}

<commit_msg>Update highlevel_feature_extractor.cpp<commit_after>#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "highlevel_feature_extractor.h"
#include <rcsc/common/server_param.h>

using namespace rcsc;

HighLevelFeatureExtractor::HighLevelFeatureExtractor(int num_teammates,
                                                     int num_opponents,
                                                     bool playing_offense) :
  FeatureExtractor(num_teammates, num_opponents, playing_offense)
{
  assert(numTeammates >= 0);
  assert(numOpponents >= 0);
  numFeatures = num_basic_features + features_per_teammate * numTeammates
      + features_per_opponent * numOpponents;
  numFeatures+=2; // action status, stamina
  feature_vec.resize(numFeatures);
}

HighLevelFeatureExtractor::~HighLevelFeatureExtractor() {}

const std::vector<float>&
HighLevelFeatureExtractor::ExtractFeatures(const rcsc::WorldModel& wm,
					   bool last_action_status) {
  featIndx = 0;
  const ServerParam& SP = ServerParam::i();
  const SelfObject& self = wm.self();
  const Vector2D& self_pos = self.pos();
  const float self_ang = self.body().radian();
  const PlayerPtrCont& teammates = wm.teammatesFromSelf();
  const PlayerPtrCont& opponents = wm.opponentsFromSelf();
  float maxR = sqrtf(SP.pitchHalfLength() * SP.pitchHalfLength()
                     + SP.pitchWidth() * SP.pitchWidth());
  // features about self pos
  // Allow the agent to go 10% over the playfield in any direction
  float tolerance_x = .1 * SP.pitchHalfLength();
  float tolerance_y = .1 * SP.pitchHalfWidth();
  // Feature[0]: X-postion
  if (playingOffense) {
    addNormFeature(self_pos.x, -tolerance_x, SP.pitchHalfLength() + tolerance_x);
  } else {
    addNormFeature(self_pos.x, -SP.pitchHalfLength()-tolerance_x, tolerance_x);
  }

  // Feature[1]: Y-Position
  addNormFeature(self_pos.y, -SP.pitchHalfWidth() - tolerance_y,
                 SP.pitchHalfWidth() + tolerance_y);

  // Feature[2]: Self Angle
  addNormFeature(self_ang, -M_PI, M_PI);

  float r;
  float th;
  // Features about the ball
  Vector2D ball_pos = wm.ball().pos();
  angleDistToPoint(self_pos, ball_pos, th, r);
  // Feature[3] and [4]: (x,y) postition of the ball
  if (playingOffense) {
    addNormFeature(ball_pos.x, -tolerance_x, SP.pitchHalfLength() + tolerance_x);
  } else {
    addNormFeature(ball_pos.x, -SP.pitchHalfLength()-tolerance_x, tolerance_x);
  }
  addNormFeature(ball_pos.y, -SP.pitchHalfWidth() - tolerance_y, SP.pitchHalfWidth() + tolerance_y);
  // Feature[5]: Able to kick
  addNormFeature(self.isKickable(), false, true);

  // Features about distance to goal center
  Vector2D goalCenter(SP.pitchHalfLength(), 0);
  if (!playingOffense) {
    goalCenter.assign(-SP.pitchHalfLength(), 0);
  }
  angleDistToPoint(self_pos, goalCenter, th, r);
  // Feature[6]: Goal Center Distance
  addNormFeature(r, 0, maxR);
  // Feature[7]: Angle to goal center
  addNormFeature(th, -M_PI, M_PI);
  // Feature[8]: largest open goal angle
  addNormFeature(calcLargestGoalAngle(wm, self_pos), 0, M_PI);
  // Feature[9]: Dist to our closest opp
  if (numOpponents > 0) {
    calcClosestOpp(wm, self_pos, th, r);
    addNormFeature(r, 0, maxR);
  } else {
    addFeature(FEAT_INVALID);
  }

  // Features[9 - 9+T]: teammate's open angle to goal
  int detected_teammates = 0;
  for (PlayerPtrCont::const_iterator it=teammates.begin(); it != teammates.end(); ++it) {
    const PlayerObject* teammate = *it;
    if (valid(teammate) && teammate->unum() > 0 && detected_teammates < numTeammates) {
      addNormFeature(calcLargestGoalAngle(wm, teammate->pos()), 0, M_PI);
      detected_teammates++;
    }
  }
  // Add zero features for any missing teammates
  for (int i=detected_teammates; i<numTeammates; ++i) {
    addFeature(FEAT_INVALID);
  }

  // Features[9+T - 9+2T]: teammates' dists to closest opps
  if (numOpponents > 0) {
    detected_teammates = 0;
    for (PlayerPtrCont::const_iterator it=teammates.begin(); it != teammates.end(); ++it) {
      const PlayerObject* teammate = *it;
      if (valid(teammate) && teammate->unum() > 0 && detected_teammates < numTeammates) {
        calcClosestOpp(wm, teammate->pos(), th, r);
        addNormFeature(r, 0, maxR);
        detected_teammates++;
      }
    }
    // Add zero features for any missing teammates
    for (int i=detected_teammates; i<numTeammates; ++i) {
      addFeature(FEAT_INVALID);
    }
  } else { // If no opponents, add invalid features
    for (int i=0; i<numTeammates; ++i) {
      addFeature(FEAT_INVALID);
    }
  }

  // Features [9+2T - 9+3T]: open angle to teammates
  detected_teammates = 0;
  for (PlayerPtrCont::const_iterator it=teammates.begin(); it != teammates.end(); ++it) {
    const PlayerObject* teammate = *it;
    if (valid(teammate) && teammate->unum() > 0 && detected_teammates < numTeammates) {
      addNormFeature(calcLargestTeammateAngle(wm, self_pos, teammate->pos()),0,M_PI);
      detected_teammates++;
    }
  }
  // Add zero features for any missing teammates
  for (int i=detected_teammates; i<numTeammates; ++i) {
    addFeature(FEAT_INVALID);
  }

  // Features [9+3T - 9+6T]: x, y, unum of teammates
  detected_teammates = 0;
  for (PlayerPtrCont::const_iterator it=teammates.begin(); it != teammates.end(); ++it) {
    const PlayerObject* teammate = *it;
    if (valid(teammate) && teammate->unum() > 0 && detected_teammates < numTeammates) {
      if (playingOffense) {
        addNormFeature(teammate->pos().x, -tolerance_x, SP.pitchHalfLength() + tolerance_x);
      } else {
        addNormFeature(teammate->pos().x, -SP.pitchHalfLength()-tolerance_x, tolerance_x);
      }
      addNormFeature(teammate->pos().y, -tolerance_y - SP.pitchHalfWidth(), SP.pitchHalfWidth() + tolerance_y);
      addFeature(teammate->unum());
      detected_teammates++;
    }
  }
  // Add zero features for any missing teammates
  for (int i=detected_teammates; i<numTeammates; ++i) {
    addFeature(FEAT_INVALID);
    addFeature(FEAT_INVALID);
    addFeature(FEAT_INVALID);
  }

  // Features [9+6T - 9+6T+3O]: x, y, unum of opponents
  int detected_opponents = 0;
  for (PlayerPtrCont::const_iterator it = opponents.begin(); it != opponents.end(); ++it) {
    const PlayerObject* opponent = *it;
    if (valid(opponent) && opponent->unum() > 0 && detected_opponents < numOpponents) {
      if (playingOffense) {
        addNormFeature(opponent->pos().x, -tolerance_x, SP.pitchHalfLength() + tolerance_x);
      } else {
        addNormFeature(opponent->pos().x, -SP.pitchHalfLength()-tolerance_x, tolerance_x);
      }
      addNormFeature(opponent->pos().y, -tolerance_y - SP.pitchHalfWidth(), SP.pitchHalfWidth() + tolerance_y);
      addFeature(opponent->unum());
      detected_opponents++;
    }
  }
  // Add zero features for any missing opponents
  for (int i=detected_opponents; i<numOpponents; ++i) {
    addFeature(FEAT_INVALID);
    addFeature(FEAT_INVALID);
    addFeature(FEAT_INVALID);
  }

  if (last_action_status) {
    addFeature(FEAT_MAX);
  } else {
    addFeature(FEAT_MIN);
  }
  addNormFeature(self.stamina(), 0., observedStaminaMax);

  assert(featIndx == numFeatures);
  // checkFeatures();
  return feature_vec;
}

bool HighLevelFeatureExtractor::valid(const rcsc::PlayerObject* player) {
  if (!player) {return false;} //avoid segfaults
  const rcsc::Vector2D& pos = player->pos();
  if (!player->posValid()) {
    return false;
  }
  return pos.isValid();
}

<|endoftext|>