<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include <sstream>

#include "otbCoordinateToName.h"
#include "otbMacro.h"
#include "otbUtils.h"

#include "tinyxml.h"
#include "otbCurlHelper.h"

#include "itkMersenneTwisterRandomVariateGenerator.h"

namespace otb
{

/**
 * Constructor
 */
CoordinateToName::CoordinateToName() :
  m_Lon(-1000.0), m_Lat(-1000.0), m_Multithread(false), m_IsValid(false),
  m_PlaceName(""), m_CountryName("")
{
  /*
  //Avoid collision between different instance of the class
  typedef itk::Statistics::MersenneTwisterRandomVariateGenerator RandomGenType;
  RandomGenType::Pointer randomGen = RandomGenType::GetInstance();
  randomGen->SetSeed(reinterpret_cast<long int>(this)); //make sure the seed is unique for this class
  unsigned int randomNum = randomGen->GetIntegerVariate();

  std::stringstream filename;
  filename << "tmp-coordinateToName-SignayriUt1-";
  filename << randomNum;
  filename << ".xml";
  m_TempFileName = filename.str();
  */

  m_Curl = CurlHelper::New();

  m_Threader = itk::MultiThreader::New();

  m_UpdateDistance = 0.01; //about 1km at equator

}

/**
 * PrintSelf
 */
void
CoordinateToName
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << " m_Lon "  << m_Lon << std::endl;
  os << indent << " m_Lat "  << m_Lat << std::endl;
  os << indent << " m_PlaceName "  << m_PlaceName << std::endl;
}

bool CoordinateToName::Evaluate()
{
  if (m_Multithread)
    {
    m_Threader->SpawnThread(ThreadFunction, this);
    }
  else
    {
    DoEvaluate();
    }
  return true;
}

ITK_THREAD_RETURN_TYPE
CoordinateToName::ThreadFunction(void *arg)
{
  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (itk::MultiThreader::ThreadInfoStruct *) (arg);
  CoordinateToName::Pointer  lThis = (CoordinateToName*) (pInfo->UserData);
  lThis->DoEvaluate();
  return 0;
}

void CoordinateToName::DoEvaluate()
{
  if (Utils::IsLonLatValid(m_Lon, m_Lat))
    {
    std::ostringstream urlStream;
    urlStream << "http://ws.geonames.org/findNearbyPlaceName?lat=";
    urlStream << m_Lat;
    urlStream << "&lng=";
    urlStream << m_Lon;
    otbMsgDevMacro("CoordinateToName: retrieve url " << urlStream.str());

    m_Curl->RetrieveUrlInMemory(urlStream.str(), m_CurlOutput);

    std::string placeName = "";
    std::string countryName = "";
    ParseXMLGeonames(placeName, countryName);
    m_PlaceName = placeName;
    m_CountryName = countryName;
    m_IsValid = true;
    }
  else
    {
    m_PlaceName = "";
    m_CountryName = "";
    m_IsValid = false;
    }
}

void CoordinateToName::ParseXMLGeonames(std::string& placeName, std::string& countryName) const
{
  TiXmlDocument doc;
  doc.Parse(m_CurlOutput.c_str());

  if (!doc.Error())
    {
    TiXmlHandle docHandle(&doc);

    TiXmlElement* childName = docHandle.FirstChild("geonames").FirstChild("geoname").
                              FirstChild("name").Element();
    if (childName)
      {
      placeName = childName->GetText();
      }
    TiXmlElement* childCountryName = docHandle.FirstChild("geonames").FirstChild("geoname").
                                     FirstChild("countryName").Element();
    if (childCountryName)
      {
      countryName = childCountryName->GetText();
      }
    otbMsgDevMacro(<< "Near " << placeName << " in " << countryName);
    }
}

} // namespace otb
<commit_msg>ENH : make the exception raised in the class otbCoordinateToName to avoid crash in Monteverdi modules<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include <sstream>

#include "otbCoordinateToName.h"
#include "otbMacro.h"
#include "otbUtils.h"

#include "tinyxml.h"
#include "otbCurlHelper.h"

#include "itkMersenneTwisterRandomVariateGenerator.h"

namespace otb
{

/**
 * Constructor
 */
CoordinateToName::CoordinateToName() :
  m_Lon(-1000.0), m_Lat(-1000.0), m_Multithread(false), m_IsValid(false),
  m_PlaceName(""), m_CountryName("")
{
  /*
  //Avoid collision between different instance of the class
  typedef itk::Statistics::MersenneTwisterRandomVariateGenerator RandomGenType;
  RandomGenType::Pointer randomGen = RandomGenType::GetInstance();
  randomGen->SetSeed(reinterpret_cast<long int>(this)); //make sure the seed is unique for this class
  unsigned int randomNum = randomGen->GetIntegerVariate();

  std::stringstream filename;
  filename << "tmp-coordinateToName-SignayriUt1-";
  filename << randomNum;
  filename << ".xml";
  m_TempFileName = filename.str();
  */

  m_Curl = CurlHelper::New();

  m_Threader = itk::MultiThreader::New();

  m_UpdateDistance = 0.01; //about 1km at equator

}

/**
 * PrintSelf
 */
void
CoordinateToName
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << " m_Lon "  << m_Lon << std::endl;
  os << indent << " m_Lat "  << m_Lat << std::endl;
  os << indent << " m_PlaceName "  << m_PlaceName << std::endl;
}

bool CoordinateToName::Evaluate()
{
  if (m_Multithread)
    {
    m_Threader->SpawnThread(ThreadFunction, this);
    }
  else
    {
    DoEvaluate();
    }
  return true;
}

ITK_THREAD_RETURN_TYPE
CoordinateToName::ThreadFunction(void *arg)
{
  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (itk::MultiThreader::ThreadInfoStruct *) (arg);
  CoordinateToName::Pointer  lThis = (CoordinateToName*) (pInfo->UserData);
  lThis->DoEvaluate();
  return 0;
}

void CoordinateToName::DoEvaluate()
{
    m_PlaceName = "";
    m_CountryName = "";
    m_IsValid = false;

  if (Utils::IsLonLatValid(m_Lon, m_Lat))
    {
    std::ostringstream urlStream;
    urlStream << "http://ws.geonames.org/findNearbyPlaceName?lat=";
    urlStream << m_Lat;
    urlStream << "&lng=";
    urlStream << m_Lon;
    otbMsgDevMacro("CoordinateToName: retrieve url " << urlStream.str());

    try
      {
      m_Curl->RetrieveUrlInMemory(urlStream.str(), m_CurlOutput);
      m_IsValid = true;
      }
    catch(itk::ExceptionObject& e)
      {
      m_IsValid = false;
      }

    if(m_IsValid)
      {
      std::string placeName = "";
      std::string countryName = "";
      ParseXMLGeonames(placeName, countryName);
      m_PlaceName = placeName;
      m_CountryName = countryName;
      }
    }
}

void CoordinateToName::ParseXMLGeonames(std::string& placeName, std::string& countryName) const
{
  TiXmlDocument doc;
  doc.Parse(m_CurlOutput.c_str());

  if (!doc.Error())
    {
    TiXmlHandle docHandle(&doc);

    TiXmlElement* childName = docHandle.FirstChild("geonames").FirstChild("geoname").
                              FirstChild("name").Element();
    if (childName)
      {
      placeName = childName->GetText();
      }
    TiXmlElement* childCountryName = docHandle.FirstChild("geonames").FirstChild("geoname").
                                     FirstChild("countryName").Element();
    if (childCountryName)
      {
      countryName = childCountryName->GetText();
      }
    otbMsgDevMacro(<< "Near " << placeName << " in " << countryName);
    }
}

} // namespace otb
<|endoftext|>


<commit_before>//
// Created by dar on 1/23/16.
//

#include "Application.h"
#include "window/Game.h"
#include "render/RenderManager.h"
#include "logging.h"

Application::Application() {
    this->renderer = new RenderManager();
    this->window = new Game();
    this->timer = new Timer();
    this->inputManager = new InputManager();
    this->reinit();
    this->resize(1366,750);
}

void Application::reinit() {
    this->renderer->init();
    this->renderer->initWindow(this->window); //TODO
    timer->GetDelta(); //if not called right now, first call in game loop would return a very huge value
    this->inputManager->reload();
}

void Application::update(bool dynamic) {
    if (dynamic) {
        double deltaTime = timer->GetDelta();
        this->accumulator += deltaTime;
        while (accumulator > TIME_STEP) {
            this->getCurrentWindow()->tick(TIME_STEP);
            this->accumulator -= TIME_STEP;
        }
    } else {
        this->getCurrentWindow()->tick(TIME_STEP);
    }
    this->renderer->render(this->getCurrentWindow());
    if (!MOBILE) this->handleEvents();
    this->inputManager->tick(this->getCurrentWindow());
}

Application::~Application() {
    delete this->window;
}

#ifdef __ANDROID__

#include <jni.h>

Application *application = nullptr;

extern "C" {
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_init(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_resize(JNIEnv *env, jobject obj, jint width, jint height);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_tick(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_handleTouch(JNIEnv *env, jobject obj, jint i, jint action, jfloat x, jfloat y);
};

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_init(JNIEnv *env, jobject obj) {
    LOGD("C++ init");
    if (application == nullptr || application->getCurrentWindow() == nullptr) {
        application =  new Application();
    } else {
        application->reinit();
    }
    jclass cls = env->GetObjectClass(obj);
    jmethodID mid = env->GetMethodID(cls, "loadTexture", "()V");
    if (mid == 0) {
        return;
    }
    env->CallVoidMethod(obj, mid);
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_resize(JNIEnv *env, jobject obj, jint width, jint height) {
    LOGD("C++ resize(%d, %d)", width, height);
    application->resize(width, height);
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_tick(JNIEnv *env, jobject obj) {
    application->update(false);
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_handleTouch(JNIEnv *env, jobject obj, jint i,  jint action, jfloat x, jfloat y) {
    LOGD("C++ touch. i:%d, action:%d, x:%f, y:%f", i, action, x, y);
    application->handleClick(i, action, x, y);
}

#endif //__ANDROID__

void Application::resize(int width, int height) {
    this->getCurrentWindow()->reload(width, height);
    this->renderer->resize(this->getCurrentWindow(), width, height);
}

void Application::handleClick(int i, int action, float x, float y) {
    this->inputManager->handleClick(i, action, x, y);
}

void Application::handleEvents() {
#ifndef __ANDROID__
    while (SDL_PollEvent(&e) != 0) {
        switch (e.type) {
            case SDL_QUIT:
                this->running = false;
                break;
            case SDL_WINDOWEVENT:
                if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                    this->resize((unsigned int) e.window.data1, (unsigned int) e.window.data2);
                }
                break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
                this->inputManager->handleKeypress(&e);
                break;
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEMOTION:
            case SDL_MOUSEBUTTONUP: {
                int x, y;
                SDL_GetMouseState(&x, &y);
                this->inputManager->handleClick(e.button.button, e.type == SDL_MOUSEBUTTONDOWN ? 0 : (e.type == SDL_MOUSEBUTTONUP ? 1 : 2), x, y);
                break;
            }
        }
    }
#else //__ANDROID__
    LOGW("SDL is not supported on this platform\n");
#endif //__ANDROID__

}
<commit_msg>Changed fixed time step (for static updates)<commit_after>//
// Created by dar on 1/23/16.
//

#include "Application.h"
#include "window/Game.h"
#include "render/RenderManager.h"
#include "logging.h"

Application::Application() {
    this->renderer = new RenderManager();
    this->window = new Game();
    this->timer = new Timer();
    this->inputManager = new InputManager();
    this->reinit();
    this->resize(1366,750);
}

void Application::reinit() {
    this->renderer->init();
    this->renderer->initWindow(this->window); //TODO
    timer->GetDelta(); //if not called right now, first call in game loop would return a very huge value
    this->inputManager->reload();
}

void Application::update(bool dynamic) {
    if (dynamic) {
        double deltaTime = timer->GetDelta();
        this->accumulator += deltaTime;
        while (accumulator > TIME_STEP) {
            this->getCurrentWindow()->tick(TIME_STEP);
            this->accumulator -= TIME_STEP;
        }
    } else {
        this->getCurrentWindow()->tick(1.0/30);
    }
    this->renderer->render(this->getCurrentWindow());
    if (!MOBILE) this->handleEvents();
    this->inputManager->tick(this->getCurrentWindow());
}

Application::~Application() {
    delete this->window;
}

#ifdef __ANDROID__

#include <jni.h>

Application *application = nullptr;

extern "C" {
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_init(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_resize(JNIEnv *env, jobject obj, jint width, jint height);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_tick(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_handleTouch(JNIEnv *env, jobject obj, jint i, jint action, jfloat x, jfloat y);
};

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_init(JNIEnv *env, jobject obj) {
    LOGD("C++ init");
    if (application == nullptr || application->getCurrentWindow() == nullptr) {
        application =  new Application();
    } else {
        application->reinit();
    }
    jclass cls = env->GetObjectClass(obj);
    jmethodID mid = env->GetMethodID(cls, "loadTexture", "()V");
    if (mid == 0) {
        return;
    }
    env->CallVoidMethod(obj, mid);
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_resize(JNIEnv *env, jobject obj, jint width, jint height) {
    LOGD("C++ resize(%d, %d)", width, height);
    application->resize(width, height);
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_tick(JNIEnv *env, jobject obj) {
    application->update(false);
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_handleTouch(JNIEnv *env, jobject obj, jint i,  jint action, jfloat x, jfloat y) {
    LOGD("C++ touch. i:%d, action:%d, x:%f, y:%f", i, action, x, y);
    application->handleClick(i, action, x, y);
}

#endif //__ANDROID__

void Application::resize(int width, int height) {
    this->getCurrentWindow()->reload(width, height);
    this->renderer->resize(this->getCurrentWindow(), width, height);
}

void Application::handleClick(int i, int action, float x, float y) {
    this->inputManager->handleClick(i, action, x, y);
}

void Application::handleEvents() {
#ifndef __ANDROID__
    while (SDL_PollEvent(&e) != 0) {
        switch (e.type) {
            case SDL_QUIT:
                this->running = false;
                break;
            case SDL_WINDOWEVENT:
                if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                    this->resize((unsigned int) e.window.data1, (unsigned int) e.window.data2);
                }
                break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
                this->inputManager->handleKeypress(&e);
                break;
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEMOTION:
            case SDL_MOUSEBUTTONUP: {
                int x, y;
                SDL_GetMouseState(&x, &y);
                this->inputManager->handleClick(e.button.button, e.type == SDL_MOUSEBUTTONDOWN ? 0 : (e.type == SDL_MOUSEBUTTONUP ? 1 : 2), x, y);
                break;
            }
        }
    }
#else //__ANDROID__
    LOGW("SDL is not supported on this platform\n");
#endif //__ANDROID__

}
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 *
 * transaction.cpp
 * file description
 *
 * Copyright(c) 2015, CMU
 *
 *-------------------------------------------------------------------------
 */

#include "backend/concurrency/transaction.h"

#include "backend/common/synch.h"
#include "backend/common/logger.h"

#include <chrono>
#include <thread>
#include <iomanip>

namespace peloton {
namespace concurrency {

void Transaction::RecordInsert(ItemPointer location) {
    auto& manager = catalog::Manager::GetInstance();
    storage::TileGroup *tile_group = static_cast<storage::TileGroup *>(manager.locator[location.block]);
    inserted_tuples[tile_group].push_back(location.offset);
}

void Transaction::RecordDelete(ItemPointer location) {
    auto& manager = catalog::Manager::GetInstance();
    storage::TileGroup *tile_group = static_cast<storage::TileGroup *>(manager.locator[location.block]);
    deleted_tuples[tile_group].push_back(location.offset);
}

bool Transaction::HasInsertedTuples(storage::TileGroup* tile_group) const {
    auto tile_group_itr = inserted_tuples.find(tile_group);
    if(tile_group_itr != inserted_tuples.end() && !tile_group_itr->second.empty())
        return true;

    return false;
}

bool Transaction::HasDeletedTuples(storage::TileGroup* tile_group) const {
    auto tile_group_itr = deleted_tuples.find(tile_group);
    if(tile_group_itr != deleted_tuples.end() && !tile_group_itr->second.empty())
        return true;

    return false;
}

const std::map<storage::TileGroup*, std::vector<oid_t> >& Transaction::GetInsertedTuples() {
    return inserted_tuples;
}

const std::map<storage::TileGroup*, std::vector<oid_t> >& Transaction::GetDeletedTuples() {
    return deleted_tuples;
}

void Transaction::IncrementRefCount() {
    ++ref_count;
}

void Transaction::DecrementRefCount() {
    assert(ref_count > 0);

    // DROP transaction when ref count reaches 1
    if (ref_count.fetch_sub(1) == 1) {
        delete this;
    }
}

void Transaction::SetResult(Result result) {
  result_ = result;
}

Result Transaction::GetResult() const {
  return result_;
}

std::ostream& operator<<(std::ostream& os, const Transaction& txn) {

    os << "\tTxn :: @" <<  &txn << " ID : " << std::setw(4) << txn.txn_id
       << " Commit ID : " << std::setw(4) << txn.cid
       << " Last Commit ID : " << std::setw(4) << txn.last_cid
       << " Result : " << txn.result_;

    if(txn.next == nullptr) {
        os << " Next : " << std::setw(4) << txn.next;
    }
    else {
        os << " Next : " << std::setw(4) << txn.next->txn_id;
    }

    os << " Ref count : " << std::setw(4) << txn.ref_count <<  "\n";
    return os;
}

} // End concurrency namespace
} // End peloton namespace
<commit_msg>Disable check.<commit_after>/*-------------------------------------------------------------------------
 *
 * transaction.cpp
 * file description
 *
 * Copyright(c) 2015, CMU
 *
 *-------------------------------------------------------------------------
 */

#include "backend/concurrency/transaction.h"

#include "backend/common/synch.h"
#include "backend/common/logger.h"

#include <chrono>
#include <thread>
#include <iomanip>

namespace peloton {
namespace concurrency {

void Transaction::RecordInsert(ItemPointer location) {
    auto& manager = catalog::Manager::GetInstance();
    storage::TileGroup *tile_group = static_cast<storage::TileGroup *>(manager.locator[location.block]);
    inserted_tuples[tile_group].push_back(location.offset);
}

void Transaction::RecordDelete(ItemPointer location) {
    auto& manager = catalog::Manager::GetInstance();
    storage::TileGroup *tile_group = static_cast<storage::TileGroup *>(manager.locator[location.block]);
    deleted_tuples[tile_group].push_back(location.offset);
}

bool Transaction::HasInsertedTuples(storage::TileGroup* tile_group) const {
    auto tile_group_itr = inserted_tuples.find(tile_group);
    if(tile_group_itr != inserted_tuples.end() && !tile_group_itr->second.empty())
        return true;

    return false;
}

bool Transaction::HasDeletedTuples(storage::TileGroup* tile_group) const {
    auto tile_group_itr = deleted_tuples.find(tile_group);
    if(tile_group_itr != deleted_tuples.end() && !tile_group_itr->second.empty())
        return true;

    return false;
}

const std::map<storage::TileGroup*, std::vector<oid_t> >& Transaction::GetInsertedTuples() {
    return inserted_tuples;
}

const std::map<storage::TileGroup*, std::vector<oid_t> >& Transaction::GetDeletedTuples() {
    return deleted_tuples;
}

void Transaction::IncrementRefCount() {
    ++ref_count;
}

void Transaction::DecrementRefCount() {
    // DROP transaction when ref count reaches 1
    if (ref_count.fetch_sub(1) == 1) {
        delete this;
    }
}

void Transaction::SetResult(Result result) {
  result_ = result;
}

Result Transaction::GetResult() const {
  return result_;
}

std::ostream& operator<<(std::ostream& os, const Transaction& txn) {

    os << "\tTxn :: @" <<  &txn << " ID : " << std::setw(4) << txn.txn_id
       << " Commit ID : " << std::setw(4) << txn.cid
       << " Last Commit ID : " << std::setw(4) << txn.last_cid
       << " Result : " << txn.result_;

    if(txn.next == nullptr) {
        os << " Next : " << std::setw(4) << txn.next;
    }
    else {
        os << " Next : " << std::setw(4) << txn.next->txn_id;
    }

    os << " Ref count : " << std::setw(4) << txn.ref_count <<  "\n";
    return os;
}

} // End concurrency namespace
} // End peloton namespace
<|endoftext|>


<commit_before>#include <cstdlib>
#include <cassert>
#include <cstring>
#include <cstdio> // debug
#include "utilities.h"
#include "Column.h"
#include "ArrayString.h"

// Pre-declare local functions
size_t round_up(size_t len);

size_t round_up(size_t len) {
	size_t width = 0;
	if (len == 0)     width = 0;
	else if (len < 3) width = 4;
	else {
		width = len;
		width |= width >> 1;
		width |= width >> 2;
		width |= width >> 4;
		++width;
	}
	return width;
}

ArrayString::ArrayString(Array* parent, size_t pndx, Allocator& alloc) : Array(COLUMN_NORMAL, parent, pndx, alloc) {
}

ArrayString::ArrayString(size_t ref, const Array* parent, size_t pndx, Allocator& alloc) : Array(ref, parent, pndx, alloc) {
}

// Creates new array (but invalid, call UpdateRef to init)
ArrayString::ArrayString(Allocator& alloc) : Array(alloc) {
}

ArrayString::~ArrayString() {
}

const char* ArrayString::Get(size_t ndx) const {
	assert(ndx < m_len);

	if (m_width == 0) return "";
	else return (const char*)(m_data + (ndx * m_width));
}

bool ArrayString::Set(size_t ndx, const char* value) {
	assert(ndx < m_len);
	assert(value);

	return Set(ndx, value, strlen(value));
}

bool ArrayString::Set(size_t ndx, const char* value, size_t len) {
	assert(ndx < m_len);
	assert(value);
	assert(len < 64); // otherwise we have to use another column type

	// Check if we need to copy before modifying
	if (!CopyOnWrite()) return false;

	// Calc min column width (incl trailing zero-byte)
	size_t width = round_up(len);

	// Make room for the new value
	if (width > m_width) {
		const size_t oldwidth = m_width;
		if (!Alloc(m_len, width)) return false;
		m_width = width;

		// Expand the old values
		int k = (int)m_len;
		while (--k >= 0) {
			const char* v = (const char*)m_data + (k * oldwidth);

			// Move the value
			char* data = (char*)m_data + (k * m_width);
			char* const end = data + m_width;
			memmove(data, v, oldwidth);
			for (data += oldwidth; data < end; ++data) {
				*data = '\0'; // pad with zeroes
			}
		}
	}

	// Set the value
	char* data = (char*)m_data + (ndx * m_width);
	char* const end = data + m_width;
	memmove(data, value, len);
	for (data += len; data < end; ++data) {
		*data = '\0'; // pad with zeroes
	}

	return true;
}

bool ArrayString::Add() {
	return Insert(m_len, "", 0);
}

bool ArrayString::Add(const char* value) {
	return Insert(m_len, value, strlen(value));
}

bool ArrayString::Insert(size_t ndx, const char* value) {
	return Insert(ndx, value, strlen(value));
}

bool ArrayString::Insert(size_t ndx, const char* value, size_t len) {
	assert(ndx <= m_len);
	assert(value);
	assert(len < 64); // otherwise we have to use another column type

	// Check if we need to copy before modifying
	if (!CopyOnWrite()) return false;

	// Calc min column width (incl trailing zero-byte)
	size_t width = round_up(len);

	const bool doExpand = width > m_width;

	// Make room for the new value
	const size_t oldwidth = m_width;
	if (!Alloc(m_len+1, doExpand ? width : m_width)) return false;
	if (doExpand) m_width = width;

	// Move values below insertion (may expand)
	if (doExpand) {
		// Expand the old values
		int k = (int)m_len;
		while (--k >= (int)ndx) {
			const char* v = (const char*)m_data + (k * oldwidth);

			// Move the value
			char* data = (char*)m_data + ((k+1) * m_width);
			char* const end = data + m_width;
			memmove(data, v, oldwidth);
			for (data += oldwidth; data < end; ++data) {
				*data = '\0'; // pad with zeroes
			}
		}
	}
	else if (ndx != m_len) {
		// when no expansion, use memmove
		unsigned char* src = m_data + (ndx * m_width);
		unsigned char* dst = src + m_width;
		const size_t count = (m_len - ndx) * m_width;
		memmove(dst, src, count);
	}

	// Set the value
	char* data = (char*)m_data + (ndx * m_width);
	memcpy(data, value, len);

	// Pad with zeroes
	char* const end = data + m_width;
	for (data += len; data < end; ++data) {
		*data = '\0';
	}

	// Expand values above insertion
	if (doExpand) {
		int k = (int)ndx;
		while (--k >= 0) {
			const char* v = (const char*)m_data + (k * oldwidth);

			// Move the value
			char* data = (char*)m_data + (k * m_width);
			char* const end = data + m_width;
			memmove(data, v, oldwidth);
			for (data += oldwidth; data < end; ++data) {
				*data = '\0'; // pad with zeroes
			}
		}
	}

	++m_len;
	return true;
}

void ArrayString::Delete(size_t ndx) {
	assert(ndx < m_len);

	// Check if we need to copy before modifying
	CopyOnWrite();

	--m_len;

	// move data under deletion up
	if (ndx < m_len) {
		char* src = (char*)m_data + ((ndx+1) * m_width);
		char* dst = (char*)m_data + (ndx * m_width);
		const size_t len = (m_len - ndx) * m_width;
		memmove(dst, src, len);
	}

	// Update length in header
	set_header_len(m_len);
}

size_t ArrayString::CalcByteLen(size_t count, size_t width) const {
	return 8 + (count * width);
}

size_t ArrayString::CalcItemCount(size_t bytes, size_t width) const {
	if (width == 0) return (size_t)-1; // zero-width gives infinite space

	const size_t bytes_without_header = bytes - 8;
	return bytes_without_header / width;
}

size_t ArrayString::Find(const char* value, size_t start, size_t end) const {
	assert(value);
	return FindWithLen(value, strlen(value), start, end);
}

void ArrayString::FindAll(Array& result, const char* value, size_t add_offset, size_t start, size_t end) {
	assert(value);

	const size_t len = strlen(value);

	size_t first = start - 1;
	for (;;) {
		first = FindWithLen(value, len, first + 1, end);
		if (first != (size_t)-1)
			result.Add(first + add_offset);
		else break;
	}
}

size_t ArrayString::FindWithLen(const char* value, size_t len, size_t start, size_t end) const {
	assert(value);

	if (end == (size_t)-1) end = m_len;
	if (start == end) return (size_t)-1;
	assert(start < m_len && end <= m_len && start < end);
	if (m_len == 0) return (size_t)-1; // empty list
	if (len >= m_width) return (size_t)-1; // A string can never be wider than the column width

	// todo, ensure behaves as expected when m_width = 0

	for (size_t i = start; i < end; ++i) {
		if (value[0] == m_data[i * m_width] && value[len] == m_data[i * m_width + len]) {
			const char* const v = (const char *)m_data + i * m_width;
			if (strncmp(value, v, len) == 0) return i;
		}
	}

	return (size_t)-1; // not found
}

#ifdef _DEBUG
#include "stdio.h"

bool ArrayString::Compare(const ArrayString& c) const {
	if (c.Size() != Size()) return false;

	for (size_t i = 0; i < Size(); ++i) {
		if (strcmp(Get(i), c.Get(i)) != 0) return false;
	}

	return true;
}

void ArrayString::StringStats() const {
	size_t total = 0;
	size_t longest = 0;

	for (size_t i = 0; i < m_len; ++i) {
		const char* str = Get(i);
		const size_t len = strlen(str)+1;

		total += len;
		if (len > longest) longest = len;
	}

	const size_t size = m_len * m_width;
	const size_t zeroes = size - total;
	const size_t zavg = zeroes / m_len;

	printf("Count: %zu\n", m_len);
	printf("Width: %zu\n", m_width);
	printf("Total: %zu\n", size);
	printf("Capacity: %zu\n\n", m_capacity);
	printf("Bytes string: %zu\n", total);
	printf("     longest: %zu\n", longest);
	printf("Bytes zeroes: %zu\n", zeroes);
	printf("         avg: %zu\n", zavg);
}

void ArrayString::ToDot(FILE* f) const {
	const size_t ref = GetRef();

	fprintf(f, "n%zx [label=\"", ref);

	for (size_t i = 0; i < m_len; ++i) {
		if (i > 0) fprintf(f, " | ");

		fprintf(f, "%s", Get(i));
	}

	fprintf(f, "\"];\n");
}

#endif //_DEBUG<commit_msg>Fixed memory overwrite error related to virtual functions<commit_after>#include <cstdlib>
#include <cassert>
#include <cstring>
#include <cstdio> // debug
#include "utilities.h"
#include "Column.h"
#include "ArrayString.h"

// Pre-declare local functions
size_t round_up(size_t len);

size_t round_up(size_t len) {
	size_t width = 0;
	if (len == 0)     width = 0;
	else if (len < 3) width = 4;
	else {
		width = len;
		width |= width >> 1;
		width |= width >> 2;
		width |= width >> 4;
		++width;
	}
	return width;
}

ArrayString::ArrayString(Array* parent, size_t pndx, Allocator& alloc) : Array(COLUMN_NORMAL, parent, pndx, alloc) {
}

ArrayString::ArrayString(size_t ref, const Array* parent, size_t pndx, Allocator& alloc) : Array(alloc) {
	// Manually create array as doing it in initializer list
	// will not be able to call correct virtual functions
	Create(ref);
	SetParent((Array*)parent, pndx);
}

// Creates new array (but invalid, call UpdateRef to init)
ArrayString::ArrayString(Allocator& alloc) : Array(alloc) {
}

ArrayString::~ArrayString() {
}

const char* ArrayString::Get(size_t ndx) const {
	assert(ndx < m_len);

	if (m_width == 0) return "";
	else return (const char*)(m_data + (ndx * m_width));
}

bool ArrayString::Set(size_t ndx, const char* value) {
	assert(ndx < m_len);
	assert(value);

	return Set(ndx, value, strlen(value));
}

bool ArrayString::Set(size_t ndx, const char* value, size_t len) {
	assert(ndx < m_len);
	assert(value);
	assert(len < 64); // otherwise we have to use another column type

	// Check if we need to copy before modifying
	if (!CopyOnWrite()) return false;

	// Calc min column width (incl trailing zero-byte)
	size_t width = round_up(len);

	// Make room for the new value
	if (width > m_width) {
		const size_t oldwidth = m_width;
		if (!Alloc(m_len, width)) return false;
		m_width = width;

		// Expand the old values
		int k = (int)m_len;
		while (--k >= 0) {
			const char* v = (const char*)m_data + (k * oldwidth);

			// Move the value
			char* data = (char*)m_data + (k * m_width);
			char* const end = data + m_width;
			memmove(data, v, oldwidth);
			for (data += oldwidth; data < end; ++data) {
				*data = '\0'; // pad with zeroes
			}
		}
	}

	// Set the value
	char* data = (char*)m_data + (ndx * m_width);
	char* const end = data + m_width;
	memmove(data, value, len);
	for (data += len; data < end; ++data) {
		*data = '\0'; // pad with zeroes
	}

	return true;
}

bool ArrayString::Add() {
	return Insert(m_len, "", 0);
}

bool ArrayString::Add(const char* value) {
	return Insert(m_len, value, strlen(value));
}

bool ArrayString::Insert(size_t ndx, const char* value) {
	return Insert(ndx, value, strlen(value));
}

bool ArrayString::Insert(size_t ndx, const char* value, size_t len) {
	assert(ndx <= m_len);
	assert(value);
	assert(len < 64); // otherwise we have to use another column type

	// Check if we need to copy before modifying
	if (!CopyOnWrite()) return false;

	// Calc min column width (incl trailing zero-byte)
	size_t width = round_up(len);

	const bool doExpand = width > m_width;

	// Make room for the new value
	const size_t oldwidth = m_width;
	if (!Alloc(m_len+1, doExpand ? width : m_width)) return false;
	if (doExpand) m_width = width;

	// Move values below insertion (may expand)
	if (doExpand) {
		// Expand the old values
		int k = (int)m_len;
		while (--k >= (int)ndx) {
			const char* v = (const char*)m_data + (k * oldwidth);

			// Move the value
			char* data = (char*)m_data + ((k+1) * m_width);
			char* const end = data + m_width;
			memmove(data, v, oldwidth);
			for (data += oldwidth; data < end; ++data) {
				*data = '\0'; // pad with zeroes
			}
		}
	}
	else if (ndx != m_len) {
		// when no expansion, use memmove
		unsigned char* src = m_data + (ndx * m_width);
		unsigned char* dst = src + m_width;
		const size_t count = (m_len - ndx) * m_width;
		memmove(dst, src, count);
	}

	// Set the value
	char* data = (char*)m_data + (ndx * m_width);
	memcpy(data, value, len);

	// Pad with zeroes
	char* const end = data + m_width;
	for (data += len; data < end; ++data) {
		*data = '\0';
	}

	// Expand values above insertion
	if (doExpand) {
		int k = (int)ndx;
		while (--k >= 0) {
			const char* v = (const char*)m_data + (k * oldwidth);

			// Move the value
			char* data = (char*)m_data + (k * m_width);
			char* const end = data + m_width;
			memmove(data, v, oldwidth);
			for (data += oldwidth; data < end; ++data) {
				*data = '\0'; // pad with zeroes
			}
		}
	}

	++m_len;
	return true;
}

void ArrayString::Delete(size_t ndx) {
	assert(ndx < m_len);

	// Check if we need to copy before modifying
	CopyOnWrite();

	--m_len;

	// move data under deletion up
	if (ndx < m_len) {
		char* src = (char*)m_data + ((ndx+1) * m_width);
		char* dst = (char*)m_data + (ndx * m_width);
		const size_t len = (m_len - ndx) * m_width;
		memmove(dst, src, len);
	}

	// Update length in header
	set_header_len(m_len);
}

size_t ArrayString::CalcByteLen(size_t count, size_t width) const {
	return 8 + (count * width);
}

size_t ArrayString::CalcItemCount(size_t bytes, size_t width) const {
	if (width == 0) return (size_t)-1; // zero-width gives infinite space

	const size_t bytes_without_header = bytes - 8;
	return bytes_without_header / width;
}

size_t ArrayString::Find(const char* value, size_t start, size_t end) const {
	assert(value);
	return FindWithLen(value, strlen(value), start, end);
}

void ArrayString::FindAll(Array& result, const char* value, size_t add_offset, size_t start, size_t end) {
	assert(value);

	const size_t len = strlen(value);

	size_t first = start - 1;
	for (;;) {
		first = FindWithLen(value, len, first + 1, end);
		if (first != (size_t)-1)
			result.Add(first + add_offset);
		else break;
	}
}

size_t ArrayString::FindWithLen(const char* value, size_t len, size_t start, size_t end) const {
	assert(value);

	if (end == (size_t)-1) end = m_len;
	if (start == end) return (size_t)-1;
	assert(start < m_len && end <= m_len && start < end);
	if (m_len == 0) return (size_t)-1; // empty list
	if (len >= m_width) return (size_t)-1; // A string can never be wider than the column width

	// todo, ensure behaves as expected when m_width = 0

	for (size_t i = start; i < end; ++i) {
		if (value[0] == m_data[i * m_width] && value[len] == m_data[i * m_width + len]) {
			const char* const v = (const char *)m_data + i * m_width;
			if (strncmp(value, v, len) == 0) return i;
		}
	}

	return (size_t)-1; // not found
}

#ifdef _DEBUG
#include "stdio.h"

bool ArrayString::Compare(const ArrayString& c) const {
	if (c.Size() != Size()) return false;

	for (size_t i = 0; i < Size(); ++i) {
		if (strcmp(Get(i), c.Get(i)) != 0) return false;
	}

	return true;
}

void ArrayString::StringStats() const {
	size_t total = 0;
	size_t longest = 0;

	for (size_t i = 0; i < m_len; ++i) {
		const char* str = Get(i);
		const size_t len = strlen(str)+1;

		total += len;
		if (len > longest) longest = len;
	}

	const size_t size = m_len * m_width;
	const size_t zeroes = size - total;
	const size_t zavg = zeroes / m_len;

	printf("Count: %zu\n", m_len);
	printf("Width: %zu\n", m_width);
	printf("Total: %zu\n", size);
	printf("Capacity: %zu\n\n", m_capacity);
	printf("Bytes string: %zu\n", total);
	printf("     longest: %zu\n", longest);
	printf("Bytes zeroes: %zu\n", zeroes);
	printf("         avg: %zu\n", zavg);
}

void ArrayString::ToDot(FILE* f) const {
	const size_t ref = GetRef();

	fprintf(f, "n%zx [label=\"", ref);

	for (size_t i = 0; i < m_len; ++i) {
		if (i > 0) fprintf(f, " | ");

		fprintf(f, "%s", Get(i));
	}

	fprintf(f, "\"];\n");
}

#endif //_DEBUG<|endoftext|>


<commit_before>#ifndef AMGCL_MPI_DIRECT_SOLVER_SOLVER_BASE_HPP
#define AMGCL_MPI_DIRECT_SOLVER_SOLVER_BASE_HPP

/*
The MIT License

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

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
\file   amgcl/mpi/direct_solver/solver_base.hpp
\author Denis Demidov <dennis.demidov@gmail.com>
\brief  Basic functionality for distributed direct solvers.
*/

#include <amgcl/mpi/util.hpp>

namespace amgcl {
namespace mpi {
namespace direct {

template <class value_type, class Solver>
class solver_base {
    public:
        typedef backend::crs<value_type> build_matrix;

        solver_base() {}

        void init(communicator comm, const build_matrix &Astrip) {
            this->comm = comm;
            n = Astrip.nrows;

            std::vector<int> domain = mpi::exclusive_sum(comm, n);
            uniform_n = true;
            for(int i = 0; i < comm.size; ++i) {
                if (domain[i+1] - domain[i] != n) {
                    uniform_n = false;
                    break;
                }
            }

            // Consolidate the matrix on a fewer processes.
            int nmasters = std::min(comm.size, solver().comm_size(domain.back()));
            int slaves_per_master = (comm.size + nmasters - 1) / nmasters;
            int group_beg = (comm.rank / slaves_per_master) * slaves_per_master;
            int group_end = std::min(group_beg + slaves_per_master, comm.size);
            int group_size = group_end - group_beg;

            group_master = group_beg;

            // Communicator for masters (used to solve the coarse problem):
            MPI_Comm_split(comm,
                    comm.rank == group_master ? 0 : MPI_UNDEFINED,
                    comm.rank, &masters_comm
                    );

            // Communicator for slaves (used to send/recv coarse data):
            MPI_Comm_split(comm, group_master, comm.rank, &slaves_comm);

            // Count rows in local chunk of the consolidated matrix.
            int nloc;
            MPI_Reduce(&n, &nloc, 1, MPI_INT, MPI_SUM, 0, slaves_comm);

            // Shift from row pointers to row widths:
            std::vector<ptrdiff_t> widths(n);
            for(ptrdiff_t i = 0; i < n; ++i)
                widths[i] = Astrip.ptr[i+1] - Astrip.ptr[i];

            // Consolidate the matrix on group masters
            if (comm.rank == group_master) {
                build_matrix A;
                A.set_size(nloc, domain.back(), false);
                A.ptr[0] = 0;
                cons_f.resize(A.nrows);
                cons_x.resize(A.nrows);

                count.resize(group_size);
                displ.resize(group_size);

                if (uniform_n) {
                    MPI_Gather(&widths[0], n, datatype<ptrdiff_t>(),
                            &A.ptr[1], n, datatype<ptrdiff_t>(), 0, slaves_comm);
                } else {

                    for(int i = 0, j = group_beg; j < group_end; ++i, ++j) {
                        count[i] = domain[j+1] - domain[j];
                        displ[i] = i ? displ[i-1] + count[i] : 0;
                    }

                    MPI_Gatherv(&widths[0], n, datatype<ptrdiff_t>(),
                            &A.ptr[1], &count[0], &displ[0], datatype<ptrdiff_t>(),
                            0, slaves_comm);
                }

                A.set_nonzeros(A.scan_row_sizes());

                std::vector<int> nnz_count(group_size);
                std::vector<int> nnz_displ(group_size);

                for(int i = 0, j = group_beg, d0 = domain[group_beg]; j < group_end; ++i, ++j) {
                    nnz_count[i] = A.ptr[domain[j+1] - d0] - A.ptr[domain[j] - d0];
                    nnz_displ[i] = i ? nnz_displ[i-1] + nnz_count[i] : 0;
                }

                MPI_Gatherv(&Astrip.col[0], Astrip.nnz, datatype<ptrdiff_t>(),
                        &A.col[0], &nnz_count[0], &nnz_displ[0], datatype<ptrdiff_t>(),
                        0, slaves_comm);

                MPI_Gatherv(&Astrip.val[0], Astrip.nnz, datatype<value_type>(),
                        &A.val[0], &nnz_count[0], &nnz_displ[0], datatype<value_type>(),
                        0, slaves_comm);

                solver().init(masters_comm, A);
            } else {
                if (uniform_n) {
                    MPI_Gather(&widths[0], n, datatype<ptrdiff_t>(),
                            NULL, n, datatype<ptrdiff_t>(), 0, slaves_comm);
                } else {
                    MPI_Gatherv(&widths[0], n, datatype<ptrdiff_t>(),
                            NULL, NULL, NULL, datatype<ptrdiff_t>(),
                            0, slaves_comm);
                }

                MPI_Gatherv(&Astrip.col[0], Astrip.nnz, datatype<ptrdiff_t>(),
                        NULL, NULL, NULL, datatype<ptrdiff_t>(),
                        0, slaves_comm);

                MPI_Gatherv(&Astrip.val[0], Astrip.nnz, datatype<value_type>(),
                        NULL, NULL, NULL, datatype<value_type>(),
                        0, slaves_comm);
            }
        }

        virtual ~solver_base() {
            if (masters_comm != MPI_COMM_NULL) MPI_Comm_free(&masters_comm);
            if (slaves_comm  != MPI_COMM_NULL) MPI_Comm_free(&slaves_comm);
        }

        Solver& solver() {
            return *static_cast<Solver*>(this);
        }

        const Solver& solver() const {
            return *static_cast<const Solver*>(this);
        }

        template <class VecF, class VecX>
        void operator()(const VecF &f, VecX &x) const {
            static const MPI_Datatype T = datatype<value_type>();

            if (comm.rank == group_master) {
                if (uniform_n) {
                    MPI_Gather(&f[0], n, T, &cons_f[0], n, T, 0, slaves_comm);
                } else {
                    MPI_Gatherv(&f[0], n, T, &cons_f[0],
                            const_cast<int*>(&count[0]), const_cast<int*>(&displ[0]),
                            T, 0, slaves_comm);
                }

                solver().solve(cons_f, cons_x);

                if (uniform_n) {
                    MPI_Scatter(&cons_x[0], n, T, &x[0], n, T, 0, slaves_comm);
                } else {
                    MPI_Scatterv(&cons_x[0],
                            const_cast<int*>(&count[0]), const_cast<int*>(&displ[0]),
                            T, &x[0], n, T, 0, slaves_comm);
                }
            } else {
                if (uniform_n) {
                    MPI_Gather(&f[0], n, T, NULL, n, T, 0, slaves_comm);
                    MPI_Scatter(NULL, n, T, &x[0], n, T, 0, slaves_comm);
                } else {
                    MPI_Gatherv(&f[0], n, T, NULL, NULL, NULL, T, 0, slaves_comm);
                    MPI_Scatterv(NULL, NULL, NULL, T, &x[0], n, T, 0, slaves_comm);
                }
            }
        }
    private:

        communicator comm;
        int          n;
        bool         uniform_n;
        int          group_master;
        MPI_Comm     masters_comm, slaves_comm;
        std::vector<int> count, displ;
        mutable std::vector<value_type> cons_f, cons_x;
};

} // namespace direct
} // namespace mpi
} // namespace amgcl

#endif
<commit_msg>Fixing const-correctness issues with some MPI implementations<commit_after>#ifndef AMGCL_MPI_DIRECT_SOLVER_SOLVER_BASE_HPP
#define AMGCL_MPI_DIRECT_SOLVER_SOLVER_BASE_HPP

/*
The MIT License

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

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
\file   amgcl/mpi/direct_solver/solver_base.hpp
\author Denis Demidov <dennis.demidov@gmail.com>
\brief  Basic functionality for distributed direct solvers.
*/

#include <amgcl/mpi/util.hpp>

namespace amgcl {
namespace mpi {
namespace direct {

template <class value_type, class Solver>
class solver_base {
    public:
        typedef backend::crs<value_type> build_matrix;

        solver_base() {}

        void init(communicator comm, const build_matrix &Astrip) {
            this->comm = comm;
            n = Astrip.nrows;

            std::vector<int> domain = mpi::exclusive_sum(comm, n);
            uniform_n = true;
            for(int i = 0; i < comm.size; ++i) {
                if (domain[i+1] - domain[i] != n) {
                    uniform_n = false;
                    break;
                }
            }

            // Consolidate the matrix on a fewer processes.
            int nmasters = std::min(comm.size, solver().comm_size(domain.back()));
            int slaves_per_master = (comm.size + nmasters - 1) / nmasters;
            int group_beg = (comm.rank / slaves_per_master) * slaves_per_master;
            int group_end = std::min(group_beg + slaves_per_master, comm.size);
            int group_size = group_end - group_beg;

            group_master = group_beg;

            // Communicator for masters (used to solve the coarse problem):
            MPI_Comm_split(comm,
                    comm.rank == group_master ? 0 : MPI_UNDEFINED,
                    comm.rank, &masters_comm
                    );

            // Communicator for slaves (used to send/recv coarse data):
            MPI_Comm_split(comm, group_master, comm.rank, &slaves_comm);

            // Count rows in local chunk of the consolidated matrix.
            int nloc;
            MPI_Reduce(&n, &nloc, 1, MPI_INT, MPI_SUM, 0, slaves_comm);

            // Shift from row pointers to row widths:
            std::vector<ptrdiff_t> widths(n);
            for(ptrdiff_t i = 0; i < n; ++i)
                widths[i] = Astrip.ptr[i+1] - Astrip.ptr[i];

            // Consolidate the matrix on group masters
            if (comm.rank == group_master) {
                build_matrix A;
                A.set_size(nloc, domain.back(), false);
                A.ptr[0] = 0;
                cons_f.resize(A.nrows);
                cons_x.resize(A.nrows);

                count.resize(group_size);
                displ.resize(group_size);

                if (uniform_n) {
                    MPI_Gather(&widths[0], n, datatype<ptrdiff_t>(),
                            &A.ptr[1], n, datatype<ptrdiff_t>(), 0, slaves_comm);
                } else {

                    for(int i = 0, j = group_beg; j < group_end; ++i, ++j) {
                        count[i] = domain[j+1] - domain[j];
                        displ[i] = i ? displ[i-1] + count[i] : 0;
                    }

                    MPI_Gatherv(&widths[0], n, datatype<ptrdiff_t>(),
                            &A.ptr[1], &count[0], &displ[0], datatype<ptrdiff_t>(),
                            0, slaves_comm);
                }

                A.set_nonzeros(A.scan_row_sizes());

                std::vector<int> nnz_count(group_size);
                std::vector<int> nnz_displ(group_size);

                for(int i = 0, j = group_beg, d0 = domain[group_beg]; j < group_end; ++i, ++j) {
                    nnz_count[i] = A.ptr[domain[j+1] - d0] - A.ptr[domain[j] - d0];
                    nnz_displ[i] = i ? nnz_displ[i-1] + nnz_count[i] : 0;
                }

                MPI_Gatherv(&Astrip.col[0], Astrip.nnz, datatype<ptrdiff_t>(),
                        &A.col[0], &nnz_count[0], &nnz_displ[0], datatype<ptrdiff_t>(),
                        0, slaves_comm);

                MPI_Gatherv(&Astrip.val[0], Astrip.nnz, datatype<value_type>(),
                        &A.val[0], &nnz_count[0], &nnz_displ[0], datatype<value_type>(),
                        0, slaves_comm);

                solver().init(masters_comm, A);
            } else {
                if (uniform_n) {
                    MPI_Gather(&widths[0], n, datatype<ptrdiff_t>(),
                            NULL, n, datatype<ptrdiff_t>(), 0, slaves_comm);
                } else {
                    MPI_Gatherv(&widths[0], n, datatype<ptrdiff_t>(),
                            NULL, NULL, NULL, datatype<ptrdiff_t>(),
                            0, slaves_comm);
                }

                MPI_Gatherv(&Astrip.col[0], Astrip.nnz, datatype<ptrdiff_t>(),
                        NULL, NULL, NULL, datatype<ptrdiff_t>(),
                        0, slaves_comm);

                MPI_Gatherv(&Astrip.val[0], Astrip.nnz, datatype<value_type>(),
                        NULL, NULL, NULL, datatype<value_type>(),
                        0, slaves_comm);
            }
        }

        virtual ~solver_base() {
            if (masters_comm != MPI_COMM_NULL) MPI_Comm_free(&masters_comm);
            if (slaves_comm  != MPI_COMM_NULL) MPI_Comm_free(&slaves_comm);
        }

        Solver& solver() {
            return *static_cast<Solver*>(this);
        }

        const Solver& solver() const {
            return *static_cast<const Solver*>(this);
        }

        template <class VecF, class VecX>
        void operator()(const VecF &f, VecX &x) const {
            static const MPI_Datatype T = datatype<value_type>();

            if (comm.rank == group_master) {
                if (uniform_n) {
                    MPI_Gather(const_cast<value_type*>(&f[0]), n, T,
                            &cons_f[0], n, T, 0, slaves_comm);
                } else {
                    MPI_Gatherv(const_cast<value_type*>(&f[0]), n, T, &cons_f[0],
                            const_cast<int*>(&count[0]), const_cast<int*>(&displ[0]),
                            T, 0, slaves_comm);
                }

                solver().solve(cons_f, cons_x);

                if (uniform_n) {
                    MPI_Scatter(&cons_x[0], n, T, &x[0], n, T, 0, slaves_comm);
                } else {
                    MPI_Scatterv(&cons_x[0],
                            const_cast<int*>(&count[0]), const_cast<int*>(&displ[0]),
                            T, &x[0], n, T, 0, slaves_comm);
                }
            } else {
                if (uniform_n) {
                    MPI_Gather(const_cast<value_type*>(&f[0]), n, T, NULL, n, T, 0, slaves_comm);
                    MPI_Scatter(NULL, n, T, &x[0], n, T, 0, slaves_comm);
                } else {
                    MPI_Gatherv(const_cast<value_type*>(&f[0]), n, T, NULL, NULL, NULL, T, 0, slaves_comm);
                    MPI_Scatterv(NULL, NULL, NULL, T, &x[0], n, T, 0, slaves_comm);
                }
            }
        }
    private:

        communicator comm;
        int          n;
        bool         uniform_n;
        int          group_master;
        MPI_Comm     masters_comm, slaves_comm;
        std::vector<int> count, displ;
        mutable std::vector<value_type> cons_f, cons_x;
};

} // namespace direct
} // namespace mpi
} // namespace amgcl

#endif
<|endoftext|>


<commit_before>#ifndef _SDD_DD_TOOLS_DOT_SDD_HH_
#define _SDD_DD_TOOLS_DOT_SDD_HH_

#include <unordered_map>

#include "sdd/dd/definition.hh"

namespace sdd { namespace tools {

/*------------------------------------------------------------------------------------------------*/

/// @internal
template <typename C>
struct to_dot_visitor
{
  /// @brief Required by mem::variant visitor mechanism.
  using result_type = unsigned int;

  /// @brief How to identify a node.
  using node_id_type = typename flat_node<C>::id_type;

  /// @brief A cache is necessary to to know if a node has already been encountered.
  mutable std::unordered_map<node_id_type, unsigned int> cache_;

  mutable unsigned int last_id_;

  /// @brief The stream to export to.
  std::ostream& os_;

  /// @brief Constructor.
  to_dot_visitor(std::ostream& os)
    : cache_(), last_id_(1), os_(os)
  {}

  /// @brief |0|.
  result_type
  operator()(const zero_terminal<C>& n)
  const
  {
    assert(false);
  }

  /// @brief |1|.
  result_type
  operator()(const one_terminal<C>& n)
  const
  {
    return 1;
  }

  /// @brief Flat SDD.
  result_type
  operator()(const flat_node<C>& n)
  const
  {
    auto insertion = cache_.emplace(n.id(), 0);
    if (insertion.second)
    {
      const auto id = ++last_id_;
      insertion.first->second = id;
      os_ << "node_" << id << " [label=\"" << +n.variable() << "|" << (void*)(&*n.id().env) << "|" << (void*)n.id().node << "\"];" << std::endl;
      for (const auto& arc : n)
      {
        const auto succ = visit(*this, arc.successor());
        os_ << "node_" << id << " -> " << "node_" << succ
            << " [label=\"" << arc.valuation() << "\"];"
            << std::endl;
      }
    }
    return insertion.first->second;
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
template <typename C>
struct to_dot
{
  const SDD<C> x_;

  to_dot(const SDD<C>& x)
    : x_(x)
  {}

  friend
  std::ostream&
  operator<<(std::ostream& out, const to_dot& manip)
  {
    out << "digraph sdd {" << std::endl;
    if (manip.x_.empty())
    {
      out << "node_0 [shape=square,label=\"0\"];" << std::endl;
    }
    else
    {
      out << "node_1 [shape=square,label=\"1\"];" << std::endl;
      visit(to_dot_visitor<C>(out), manip.x_);
    }
    return out << "}" << std::endl;
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @brief Export an SDD to the DOT format.
template <typename C>
to_dot<C>
dot(const SDD<C>& x)
{
  return to_dot<C>(x);
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::tools

#endif // _SDD_DD_TOOLS_DOT_SDD_HH_
<commit_msg>Avoid warning.<commit_after>#ifndef _SDD_DD_TOOLS_DOT_SDD_HH_
#define _SDD_DD_TOOLS_DOT_SDD_HH_

#include <unordered_map>

#include "sdd/dd/definition.hh"

namespace sdd { namespace tools {

/*------------------------------------------------------------------------------------------------*/

/// @internal
template <typename C>
struct to_dot_visitor
{
  /// @brief Required by mem::variant visitor mechanism.
  using result_type = unsigned int;

  /// @brief How to identify a node.
  using node_id_type = typename flat_node<C>::id_type;

  /// @brief A cache is necessary to to know if a node has already been encountered.
  mutable std::unordered_map<node_id_type, unsigned int> cache_;

  mutable unsigned int last_id_;

  /// @brief The stream to export to.
  std::ostream& os_;

  /// @brief Constructor.
  to_dot_visitor(std::ostream& os)
    : cache_(), last_id_(1), os_(os)
  {}

  /// @brief |0|.
  result_type
  operator()(const zero_terminal<C>& n)
  const
  {
    assert(false);
    return 0;
  }

  /// @brief |1|.
  result_type
  operator()(const one_terminal<C>& n)
  const
  {
    return 1;
  }

  /// @brief Flat SDD.
  result_type
  operator()(const flat_node<C>& n)
  const
  {
    auto insertion = cache_.emplace(n.id(), 0);
    if (insertion.second)
    {
      const auto id = ++last_id_;
      insertion.first->second = id;
      os_ << "node_" << id << " [label=\"" << +n.variable() << "|" << (void*)(&*n.id().env) << "|" << (void*)n.id().node << "\"];" << std::endl;
      for (const auto& arc : n)
      {
        const auto succ = visit(*this, arc.successor());
        os_ << "node_" << id << " -> " << "node_" << succ
            << " [label=\"" << arc.valuation() << "\"];"
            << std::endl;
      }
    }
    return insertion.first->second;
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
template <typename C>
struct to_dot
{
  const SDD<C> x_;

  to_dot(const SDD<C>& x)
    : x_(x)
  {}

  friend
  std::ostream&
  operator<<(std::ostream& out, const to_dot& manip)
  {
    out << "digraph sdd {" << std::endl;
    if (manip.x_.empty())
    {
      out << "node_0 [shape=square,label=\"0\"];" << std::endl;
    }
    else
    {
      out << "node_1 [shape=square,label=\"1\"];" << std::endl;
      visit(to_dot_visitor<C>(out), manip.x_);
    }
    return out << "}" << std::endl;
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @brief Export an SDD to the DOT format.
template <typename C>
to_dot<C>
dot(const SDD<C>& x)
{
  return to_dot<C>(x);
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::tools

#endif // _SDD_DD_TOOLS_DOT_SDD_HH_
<|endoftext|>


<commit_before>/*
 * Copyright 2010, 2011 Esrille Inc.
 *
 * 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 "U16InputStream.h"

#include <assert.h>
#include <string.h>

#include <unicode/ucnv.h>

#include <algorithm>

const char* U16InputStream::DefaultEncoding = "windows-1252";

namespace {

struct Override
{
    const char* input;
    const char* replacement;
};

Override overrides[] = {
    { "euc-kr", "windows-949" },
    { "gb2312", "gbk" },
    { "gb_2312-80", "gbk" },
    { "iso-8859-1", "windows-1252" },
    { "iso-8859-9", "windows-1254" },
    { "iso-8859-11", "windows-874" },
    { "ks_c_5601-1987", "windows-949" },
    { "shift_jis", "windows-31j" },
    { "tis-620", "windows-874" },
    { "us-ascii", "windows-1252" }
};

}  // namespace

U16InputStream::U16InputStream(std::istream& stream, const std::string optionalEncoding) :
    confidence(Certain),
    stream(stream)
{
    initializeConverter();
    encoding = checkEncoding(optionalEncoding);
}

U16InputStream::~U16InputStream()
{
    if (converter)
        ucnv_close(converter);
}

const char* U16InputStream::skipSpace(const char* p)
{
    while (*p) {
        if (strchr(" \t\r\n\f", *p) == 0)
            return p;
        ++p;
    }
    return p;
};

const char* U16InputStream::skipOver(const char* p, const char* target, size_t length)
{
    while (*p) {
        if (strncmp(p, target, length) == 0)
            return p + length;
        ++p;
    }
    return p;
};

void U16InputStream::detect(const char* p)
{
    if (strncmp(p, "\xfe\xff", 2) == 0) {
        encoding = "utf-16be";
        return;
    }
    if (strncmp(p, "\xff\xfe", 2) == 0) {
        encoding = "utf-16le";
        return;
    }
    if (strncmp(p, "\xef\xbb\xbf", 3) == 0) {
        encoding = "utf-8";
        return;
    }
    encoding = "";
}

std::string U16InputStream::checkEncoding(std::string value)
{
    // Remove any leading or trailing space characters
    std::string::iterator i = value.begin();
    while (i < value.end() && strchr("\t\n\f\r ", *i))
        ++i;
    value.erase(value.begin(), i);
    int j;
    for (j = value.length(); 0 < j && strchr("\t\n\f\r ", value[j - 1]); --j)
        ;
    value.erase(j, value.length());

    if (value.empty())
        return "";

    // Override character encoding
    for (Override* override = overrides;
         override < &overrides[sizeof overrides / sizeof overrides[0]];
         ++override) {
        if (!strcasecmp(value.c_str(), override->input)) {
            value = override->replacement;
            break;
        }
    }
    return value;
}

void U16InputStream::setEncoding(std::string value)
{
    value = checkEncoding(value);
    if (value.empty())
        value = DefaultEncoding;

    // Re-check encoding with ICU for conversion
    UErrorCode error = U_ZERO_ERROR;
    converter = ucnv_open(value.c_str(), &error);
    if (!converter) {
        value = DefaultEncoding;
        converter = ucnv_open(value.c_str(), &error);
        if (!converter)
            eof = true;
    }
    encoding = value;
}

void U16InputStream::initializeConverter()
{
    flush = false;
    eof = !stream;
    converter = 0;
    source = sourceLimit = sourceBuffer;
    target = targetBuffer;
    nextChar = target;
    lastChar = 0;
}

void U16InputStream::updateSource()
{
    assert(!flush);
    size_t count = sourceLimit - source;
    if (0 < count && sourceBuffer != source)
        memmove(sourceBuffer, source, count);
    source = sourceBuffer;
    sourceLimit = sourceBuffer + count;
    count = ChunkSize - count;
    if (0 < count) {
        stream.read(sourceLimit, count);
        count = stream.gcount();
        if (!converter) {
            if (encoding.empty()) {
                sourceLimit[count] = '\0';
                detect(sourceLimit);
            }
            setEncoding(encoding);
        }
        sourceLimit += count;
        if (count == 0)
            flush = true;
    }
}

void U16InputStream::readChunk()
{
    nextChar = target = targetBuffer;
    updateSource();
    UErrorCode err = U_ZERO_ERROR;
    ucnv_toUnicode(converter,
                   reinterpret_cast<UChar**>(&target),
                   reinterpret_cast<UChar*>(targetBuffer) + ChunkSize,
                   const_cast<const char**>(&source),
                   sourceLimit, 0, flush, &err);
}

U16InputStream::operator std::u16string()
{
    std::u16string text;
    char16_t c;
    while (getChar(c))
        text += c;
    return text;
}<commit_msg>(overrides) : Update the list.<commit_after>/*
 * Copyright 2010, 2011 Esrille Inc.
 *
 * 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 "U16InputStream.h"

#include <assert.h>
#include <string.h>

#include <unicode/ucnv.h>

#include <algorithm>

const char* U16InputStream::DefaultEncoding = "windows-1252";

namespace {

struct Override
{
    const char* input;
    const char* replacement;
};

// cf. HTML Living Standard 13.2.2.2 Character encodings
Override overrides[] = {
    { "euc-kr", "windows-949" },
    { "euc-jp", "cp51932" },
    { "gb2312", "gbk" },
    { "gb_2312-80", "gbk" },
    { "iso-2022-jp", "cp50220" },
    { "iso-8859-1", "windows-1252" },
    { "iso-8859-9", "windows-1254" },
    { "iso-8859-11", "windows-874" },
    { "ks_c_5601-1987", "windows-949" },
    { "shift_jis", "windows-31j" },
    { "tis-620", "windows-874" },
    { "us-ascii", "windows-1252" }
};

}  // namespace

U16InputStream::U16InputStream(std::istream& stream, const std::string optionalEncoding) :
    confidence(Certain),
    stream(stream)
{
    initializeConverter();
    encoding = checkEncoding(optionalEncoding);
}

U16InputStream::~U16InputStream()
{
    if (converter)
        ucnv_close(converter);
}

const char* U16InputStream::skipSpace(const char* p)
{
    while (*p) {
        if (strchr(" \t\r\n\f", *p) == 0)
            return p;
        ++p;
    }
    return p;
};

const char* U16InputStream::skipOver(const char* p, const char* target, size_t length)
{
    while (*p) {
        if (strncmp(p, target, length) == 0)
            return p + length;
        ++p;
    }
    return p;
};

void U16InputStream::detect(const char* p)
{
    if (strncmp(p, "\xfe\xff", 2) == 0) {
        encoding = "utf-16be";
        return;
    }
    if (strncmp(p, "\xff\xfe", 2) == 0) {
        encoding = "utf-16le";
        return;
    }
    if (strncmp(p, "\xef\xbb\xbf", 3) == 0) {
        encoding = "utf-8";
        return;
    }
    encoding = "";
}

std::string U16InputStream::checkEncoding(std::string value)
{
    // Remove any leading or trailing space characters
    std::string::iterator i = value.begin();
    while (i < value.end() && strchr("\t\n\f\r ", *i))
        ++i;
    value.erase(value.begin(), i);
    int j;
    for (j = value.length(); 0 < j && strchr("\t\n\f\r ", value[j - 1]); --j)
        ;
    value.erase(j, value.length());

    if (value.empty())
        return "";

    // Override character encoding
    for (Override* override = overrides;
         override < &overrides[sizeof overrides / sizeof overrides[0]];
         ++override) {
        if (!strcasecmp(value.c_str(), override->input)) {
            value = override->replacement;
            break;
        }
    }
    return value;
}

void U16InputStream::setEncoding(std::string value)
{
    value = checkEncoding(value);
    if (value.empty())
        value = DefaultEncoding;

    // Re-check encoding with ICU for conversion
    UErrorCode error = U_ZERO_ERROR;
    converter = ucnv_open(value.c_str(), &error);
    if (!converter) {
        value = DefaultEncoding;
        converter = ucnv_open(value.c_str(), &error);
        if (!converter)
            eof = true;
    }
    encoding = value;
}

void U16InputStream::initializeConverter()
{
    flush = false;
    eof = !stream;
    converter = 0;
    source = sourceLimit = sourceBuffer;
    target = targetBuffer;
    nextChar = target;
    lastChar = 0;
}

void U16InputStream::updateSource()
{
    assert(!flush);
    size_t count = sourceLimit - source;
    if (0 < count && sourceBuffer != source)
        memmove(sourceBuffer, source, count);
    source = sourceBuffer;
    sourceLimit = sourceBuffer + count;
    count = ChunkSize - count;
    if (0 < count) {
        stream.read(sourceLimit, count);
        count = stream.gcount();
        if (!converter) {
            if (encoding.empty()) {
                sourceLimit[count] = '\0';
                detect(sourceLimit);
            }
            setEncoding(encoding);
        }
        sourceLimit += count;
        if (count == 0)
            flush = true;
    }
}

void U16InputStream::readChunk()
{
    nextChar = target = targetBuffer;
    updateSource();
    UErrorCode err = U_ZERO_ERROR;
    ucnv_toUnicode(converter,
                   reinterpret_cast<UChar**>(&target),
                   reinterpret_cast<UChar*>(targetBuffer) + ChunkSize,
                   const_cast<const char**>(&source),
                   sourceLimit, 0, flush, &err);
}

U16InputStream::operator std::u16string()
{
    std::u16string text;
    char16_t c;
    while (getChar(c))
        text += c;
    return text;
}<|endoftext|>


<commit_before>#include "ItemUtils.h"
#include <Items/ItemComponent.h>
#include <Scene/SceneComponent.h>
#include <Game/ECS/Components/RigidBodyComponent.h>

namespace DEM::RPG
{

bool AddItemsIntoContainer(Game::CGameWorld& World, Game::HEntity Container, Game::HEntity ItemStackEntity)
{
	auto pItemStack = World.FindComponent<CItemStackComponent>(ItemStackEntity);
	if (!pItemStack) return false;

	//!!!only if container entity has a container component with limits!
	// Collect weight and volume already occupied in a container
	float Weight = 0.f;
	float Volume = 0.f;
	World.ForEachComponent<const CItemStackComponent>(
		[&Weight, &Volume, &World, Container](auto EntityID, const CItemStackComponent& Stack)
	{
		if (Stack.Container != Container) return;

		if (const CItemComponent* pItem = FindItemComponent<const CItemComponent>(World, EntityID, &Stack))
		{
			Weight += Stack.Count * pItem->Weight;
			Volume += Stack.Count * pItem->Volume;
		}
	});

	if (const CItemComponent* pItem = FindItemComponent<const CItemComponent>(World, ItemStackEntity, pItemStack))
	{
		//NewItemWeight = pItemStack->Count * pItem->Weight;
		//NewItemVolume = pItemStack->Count * pItem->Volume;

		// if Weight + NewItemWeight > ContainerWeightLimit, fail
		// if Volume + NewItemVolume > ContainerVolumeLimit, fail
	}

	World.RemoveComponent<Game::CSceneComponent>(ItemStackEntity);
	World.RemoveComponent<Game::CRigidBodyComponent>(ItemStackEntity);

	pItemStack->Container = Container;

	return true;
}
//---------------------------------------------------------------------

//!!!check dropping near another item stack or pile! bool flag 'allow merging'?
bool DropItemsToLocation(Game::CGameWorld& World, Game::HEntity ItemStackEntity, const Math::CTransformSRT& Tfm)
{
	auto pItemStack = World.FindComponent<CItemStackComponent>(ItemStackEntity);
	if (!pItemStack) return false;

	const CItemComponent* pItem = FindItemComponent<const CItemComponent>(World, ItemStackEntity, pItemStack);
	if (!pItem) return false;

	if (pItem->InLocationModelID)
	{
		auto pSceneComponent = World.AddComponent<Game::CSceneComponent>(ItemStackEntity);
		pSceneComponent->RootNode->RemoveFromParent();
		pSceneComponent->AssetID = pItem->InLocationModelID;
		pSceneComponent->SetLocalTransform(Tfm);
	}

	if (pItem->InLocationPhysicsID)
	{
		auto pPhysicsComponent = World.AddComponent<Game::CRigidBodyComponent>(ItemStackEntity);
		pPhysicsComponent->ShapeAssetID = pItem->InLocationPhysicsID;
		pPhysicsComponent->Mass = pItemStack->Count * pItem->Weight;
		// TODO: physics material, collision group & flags
	}

	return true;
}
//---------------------------------------------------------------------

}
<commit_msg>TODO notes<commit_after>#include "ItemUtils.h"
#include <Items/ItemComponent.h>
#include <Scene/SceneComponent.h>
#include <Game/ECS/Components/RigidBodyComponent.h>

namespace DEM::RPG
{

bool AddItemsIntoContainer(Game::CGameWorld& World, Game::HEntity Container, Game::HEntity ItemStackEntity)
{
	auto pItemStack = World.FindComponent<CItemStackComponent>(ItemStackEntity);
	if (!pItemStack) return false;

	//!!!only if container entity has a container component with limits!
	// Collect weight and volume already occupied in a container
	float Weight = 0.f;
	float Volume = 0.f;
	World.ForEachComponent<const CItemStackComponent>(
		[&Weight, &Volume, &World, Container](auto EntityID, const CItemStackComponent& Stack)
	{
		if (Stack.Container != Container) return;

		if (const CItemComponent* pItem = FindItemComponent<const CItemComponent>(World, EntityID, &Stack))
		{
			Weight += Stack.Count * pItem->Weight;
			Volume += Stack.Count * pItem->Volume;
		}
	});

	if (const CItemComponent* pItem = FindItemComponent<const CItemComponent>(World, ItemStackEntity, pItemStack))
	{
		//NewItemWeight = pItemStack->Count * pItem->Weight;
		//NewItemVolume = pItemStack->Count * pItem->Volume;

		// if Weight + NewItemWeight > ContainerWeightLimit, fail
		// if Volume + NewItemVolume > ContainerVolumeLimit, fail
	}

	//!!!if bool AllowMerge, try to merge with existing stack inside this container!
	//first pass - same prototype, zero modifications
	//second pass - same prototype, deep comparison?

	World.RemoveComponent<Game::CSceneComponent>(ItemStackEntity);
	World.RemoveComponent<Game::CRigidBodyComponent>(ItemStackEntity);

	pItemStack->Container = Container;

	return true;
}
//---------------------------------------------------------------------

//!!!check dropping near another item stack or pile! bool flag 'allow merging'?
bool DropItemsToLocation(Game::CGameWorld& World, Game::HEntity ItemStackEntity, const Math::CTransformSRT& Tfm)
{
	auto pItemStack = World.FindComponent<CItemStackComponent>(ItemStackEntity);
	if (!pItemStack) return false;

	const CItemComponent* pItem = FindItemComponent<const CItemComponent>(World, ItemStackEntity, pItemStack);
	if (!pItem) return false;

	if (pItem->InLocationModelID)
	{
		auto pSceneComponent = World.AddComponent<Game::CSceneComponent>(ItemStackEntity);
		pSceneComponent->RootNode->RemoveFromParent();
		pSceneComponent->AssetID = pItem->InLocationModelID;
		pSceneComponent->SetLocalTransform(Tfm);
	}

	if (pItem->InLocationPhysicsID)
	{
		auto pPhysicsComponent = World.AddComponent<Game::CRigidBodyComponent>(ItemStackEntity);
		pPhysicsComponent->ShapeAssetID = pItem->InLocationPhysicsID;
		pPhysicsComponent->Mass = pItemStack->Count * pItem->Weight;
		// TODO: physics material, collision group & flags
	}

	return true;
}
//---------------------------------------------------------------------

}
<|endoftext|>


<commit_before>#include <cstdlib>

#include "Application/Parameters/ApplicationParameters.h"
#include "Application/Parameters/ApplicationParametersBuilder.h"
#include "Application/Parameters/ApplicationParametersManager.h"
#include "Application/Parameters/ApplicationParametersReader.h"
#include "FileSystem/Entities/Executable.h"
#include "FileSystem/Factories/EntityFactory.h"
#include "FileSystem/Entities/Exceptions/InvalidExecutablePathException.h"
#include <memory>
#include <iostream>

using namespace clt::filesystem;
using namespace clt::filesystem::factories;
using namespace clt::filesystem::entities;
using namespace clt::filesystem::entities::exceptions;
using namespace application::parameters;

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

	if (argc < 2)
	{
		// TODO: real arguments management
		printf("not enough argument, need the path of your executable");
		return EXIT_FAILURE;
	}

	ApplicationParametersManager parametersManager(std::make_unique<ApplicationParametersBuilder>(), std::make_unique<ApplicationParametersReader>());
	parametersManager.start(argc, argv);
	ApplicationParameters parameters = parametersManager.getParameters();

	EntityFactory entityFactory;

	try
	{
		Executable executable = entityFactory.createExecutable(parameters.getExecutablePath());
		executable.execute();
	}
	catch (InvalidExecutablePathException exception) {
		std::cout << "Invalid executable path : " << std::endl << "\t - " << exception.getDescription() << std::endl;
	}

	return EXIT_SUCCESS;
}
<commit_msg>Remove test that have not to be here<commit_after>#include <cstdlib>

#include "Application/Parameters/ApplicationParameters.h"
#include "Application/Parameters/ApplicationParametersBuilder.h"
#include "Application/Parameters/ApplicationParametersManager.h"
#include "Application/Parameters/ApplicationParametersReader.h"
#include "FileSystem/Entities/Executable.h"
#include "FileSystem/Factories/EntityFactory.h"
#include "FileSystem/Entities/Exceptions/InvalidExecutablePathException.h"
#include <memory>
#include <iostream>

using namespace clt::filesystem;
using namespace clt::filesystem::factories;
using namespace clt::filesystem::entities;
using namespace clt::filesystem::entities::exceptions;
using namespace application::parameters;

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

	ApplicationParametersManager parametersManager(std::make_unique<ApplicationParametersBuilder>(), std::make_unique<ApplicationParametersReader>());
	parametersManager.start(argc, argv);
	ApplicationParameters parameters = parametersManager.getParameters();

	EntityFactory entityFactory;

	try
	{
		Executable executable = entityFactory.createExecutable(parameters.getExecutablePath());
		executable.execute();
	}
	catch (InvalidExecutablePathException exception) {
		std::cout << "Invalid executable path : " << std::endl << "\t - " << exception.getDescription() << std::endl;
	}

	return EXIT_SUCCESS;
}
<|endoftext|>