<commit_before>// Copyright (c) 2015, Matthew Malensek.
// Distributed under the BSD 2-Clause License (see LICENSE.txt for details)

#include "Dialog.h"

#include "../../3RVX/Logger.h"
#include "Control.h"

Dialog::Dialog(LPCWSTR className, LPCWSTR dlgTemplate) :
Window(className) {
    _dlgHwnd = CreateDialogParam(
        Window::InstanceHandle(),
        dlgTemplate,
        Window::Handle(),
        StaticDialogProc,
        (LPARAM) this);
}

void Dialog::AddControl(Control *control) {
    if (control == nullptr) {
        return;
    }

    CLOG(L"Adding control id: %d", control->ID());
    int id = control->ID();
    _controlMap[id] = control;
}

HWND Dialog::DialogHandle() {
    return _dlgHwnd;
}

INT_PTR Dialog::StaticDialogProc(HWND hwndDlg, UINT uMsg,
        WPARAM wParam, LPARAM lParam) {
    Dialog *dlg;

    if (uMsg == WM_INITDIALOG) {
        dlg = (Dialog *) lParam;
        SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) dlg);
    } else {
        dlg = (Dialog *) GetWindowLongPtr(hwndDlg, DWLP_USER);
        if (!dlg) {
            return FALSE;
        }
    }

    return dlg->DialogProc(hwndDlg, uMsg, wParam, lParam);
}

INT_PTR Dialog::DialogProc(HWND hwndDlg, UINT uMsg,
        WPARAM wParam, LPARAM lParam) {

    unsigned short nCode, ctrlId;

    switch (uMsg) {
    case WM_INITDIALOG:
        return FALSE;

    case WM_COMMAND:
        nCode = HIWORD(wParam);
        ctrlId = LOWORD(wParam);
        if (_controlMap.count(ctrlId) > 0) {
            return _controlMap[ctrlId]->Command(nCode);
        } else {
            return FALSE;
        }

    case WM_NOTIFY:
        NMHDR *nHdr = (NMHDR *) lParam;
        ctrlId = nHdr->idFrom;
        if (_controlMap.count(ctrlId) > 0) {
            return _controlMap[ctrlId]->Notification(nHdr);
        } else {
            return FALSE;
        }
    }

    return FALSE;
}
<commit_msg>Translate download dialog text<commit_after>// Copyright (c) 2015, Matthew Malensek.
// Distributed under the BSD 2-Clause License (see LICENSE.txt for details)

#include "Dialog.h"

#include "../../3RVX/Logger.h"
#include "../UITranslator.h"
#include "Control.h"

Dialog::Dialog(LPCWSTR className, LPCWSTR dlgTemplate) :
Window(className) {
    _dlgHwnd = CreateDialogParam(
        Window::InstanceHandle(),
        dlgTemplate,
        Window::Handle(),
        StaticDialogProc,
        (LPARAM) this);

    UITranslator::TranslateWindowText(_dlgHwnd);
}

void Dialog::AddControl(Control *control) {
    if (control == nullptr) {
        return;
    }

    CLOG(L"Adding control id: %d", control->ID());
    int id = control->ID();
    _controlMap[id] = control;
}

HWND Dialog::DialogHandle() {
    return _dlgHwnd;
}

INT_PTR Dialog::StaticDialogProc(HWND hwndDlg, UINT uMsg,
        WPARAM wParam, LPARAM lParam) {
    Dialog *dlg;

    if (uMsg == WM_INITDIALOG) {
        dlg = (Dialog *) lParam;
        SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) dlg);
    } else {
        dlg = (Dialog *) GetWindowLongPtr(hwndDlg, DWLP_USER);
        if (!dlg) {
            return FALSE;
        }
    }

    return dlg->DialogProc(hwndDlg, uMsg, wParam, lParam);
}

INT_PTR Dialog::DialogProc(HWND hwndDlg, UINT uMsg,
        WPARAM wParam, LPARAM lParam) {

    unsigned short nCode, ctrlId;

    switch (uMsg) {
    case WM_INITDIALOG:
        return FALSE;

    case WM_COMMAND:
        nCode = HIWORD(wParam);
        ctrlId = LOWORD(wParam);
        if (_controlMap.count(ctrlId) > 0) {
            return _controlMap[ctrlId]->Command(nCode);
        } else {
            return FALSE;
        }

    case WM_NOTIFY:
        NMHDR *nHdr = (NMHDR *) lParam;
        ctrlId = nHdr->idFrom;
        if (_controlMap.count(ctrlId) > 0) {
            return _controlMap[ctrlId]->Notification(nHdr);
        } else {
            return FALSE;
        }
    }

    return FALSE;
}
<|endoftext|>


<commit_before>#include "SpriteRenderer.hpp"
#include "ShaderManager.hpp"

#include <iostream>

SpriteRenderer::SpriteRenderer()
{

}

void SpriteRenderer::init()
{
	m_VertexBuffer.init();
	m_TexCoordBuffer.init();
}

void SpriteRenderer::render(std::vector<Sprite>& sprites, Texture& texture)
{
	clearVectors();

	for (auto& sprite : sprites)
	{
		addVertices(sprite.getPosition(), sprite.getSize(), sprite.getRotationRads());
		addTexCoords(sprite.getTextureBounds(), glm::vec2(texture.width, texture.height));
	}

	texture.bind();
	glActiveTexture(GL_TEXTURE0 + texture.getId());

	passDataToBuffers();

	m_VertexBuffer.bind();
	ShaderManager::getInstance().getShader("Texture")->bind();
	ShaderManager::getInstance().getShader("Texture")->setupVertexAttribPointer("in_Position");
	m_TexCoordBuffer.bind();
	ShaderManager::getInstance().getShader("Texture")->setupVertexAttribPointer("in_TexCoords");
	ShaderManager::getInstance().getShader("Texture")->setUniform("in_Texture", texture.getId());
	glDrawArrays(GL_TRIANGLES, 0, m_VertexBuffer.getDataSize());
}

void SpriteRenderer::passDataToBuffers()
{
	m_VertexBuffer.setData(m_Vertices);
	m_TexCoordBuffer.setData(m_TexCoords);
}

void SpriteRenderer::addTexCoords(const TextureBounds& textureBounds, const glm::vec2& textureSize)
{
	// Bottom Left
	m_TexCoords.push_back(textureBounds.bottomLeft.x / textureSize.x);
	m_TexCoords.push_back((textureSize.y - textureBounds.bottomLeft.y) / textureSize.y);

	// Bottom Right
	m_TexCoords.push_back((textureBounds.bottomLeft.x + textureBounds.size.x) / textureSize.x);
	m_TexCoords.push_back((textureSize.y - textureBounds.bottomLeft.y) / textureSize.y);

	// Top Right
	m_TexCoords.push_back((textureBounds.bottomLeft.x + textureBounds.size.x) / textureSize.x);
	m_TexCoords.push_back((textureSize.y - (textureBounds.bottomLeft.y + textureBounds.size.y)) / textureSize.y);

	// Top Right (2)
	m_TexCoords.push_back((textureBounds.bottomLeft.x + textureBounds.size.x) / textureSize.x);
	m_TexCoords.push_back((textureSize.y - (textureBounds.bottomLeft.y + textureBounds.size.y)) / textureSize.y);

	// Top Left
	m_TexCoords.push_back(textureBounds.bottomLeft.x / textureSize.x);
	m_TexCoords.push_back((textureSize.y - (textureBounds.bottomLeft.y + textureBounds.size.y)) / textureSize.y);

	// Bottom Left (2)
	m_TexCoords.push_back(textureBounds.bottomLeft.x / textureSize.x);
	m_TexCoords.push_back((textureSize.y - textureBounds.bottomLeft.y) / textureSize.y);
}

void SpriteRenderer::addVertices(const glm::vec2& position, const glm::vec2& size, float rotationRads)
{
	auto sinAngle = glm::sin(rotationRads);
	auto cosAngle = glm::cos(rotationRads);

	auto offsetFromCenter = glm::vec2(-size.x / 2.f, -size.y / 2.f);
	auto bottomLeft = glm::vec2(position.x + (offsetFromCenter.x * cosAngle - offsetFromCenter.y * sinAngle),
								position.y - (-offsetFromCenter.y * cosAngle - offsetFromCenter.x * sinAngle));

	offsetFromCenter = glm::vec2(size.x / 2.f, -size.y / 2.f);
	auto bottomRight = glm::vec2(position.x + (offsetFromCenter.x * cosAngle - offsetFromCenter.y * sinAngle),
								 position.y - (-offsetFromCenter.y * cosAngle - offsetFromCenter.x * sinAngle));

	offsetFromCenter = glm::vec2(size.x / 2.f, size.y / 2.f);
	auto topRight = glm::vec2(position.x + (offsetFromCenter.x * cosAngle - offsetFromCenter.y * sinAngle),
							  position.y - (-offsetFromCenter.y * cosAngle - offsetFromCenter.x * sinAngle));

	offsetFromCenter = glm::vec2(-size.x / 2.f, size.y / 2.f);
	auto topLeft = glm::vec2(position.x + (offsetFromCenter.x * cosAngle - offsetFromCenter.y * sinAngle),
							 position.y - (-offsetFromCenter.y * cosAngle - offsetFromCenter.x * sinAngle));

	// Bottom Left
	m_Vertices.push_back(bottomLeft.x);
	m_Vertices.push_back(bottomLeft.y);

	// Bottom Right
	m_Vertices.push_back(bottomRight.x);
	m_Vertices.push_back(bottomRight.y);

	// Top Right
	m_Vertices.push_back(topRight.x);
	m_Vertices.push_back(topRight.y);

	// Top Right (2)
	m_Vertices.push_back(topRight.x);
	m_Vertices.push_back(topRight.y);

	// Top Left
	m_Vertices.push_back(topLeft.x);
	m_Vertices.push_back(topLeft.y);

	// Bottom Left (2)
	m_Vertices.push_back(bottomLeft.x);
	m_Vertices.push_back(bottomLeft.y);
}

void SpriteRenderer::clearVectors()
{
	m_Vertices.clear();
	m_TexCoords.clear();
}<commit_msg>Fixed bug which was rendering the wrong textures (they were switched)<commit_after>#include "SpriteRenderer.hpp"
#include "ShaderManager.hpp"

#include <iostream>

SpriteRenderer::SpriteRenderer()
{

}

void SpriteRenderer::init()
{
	m_VertexBuffer.init();
	m_TexCoordBuffer.init();
}

void SpriteRenderer::render(std::vector<Sprite>& sprites, Texture& texture)
{
	clearVectors();

	for (auto& sprite : sprites)
	{
		addVertices(sprite.getPosition(), sprite.getSize(), sprite.getRotationRads());
		addTexCoords(sprite.getTextureBounds(), glm::vec2(texture.width, texture.height));
	}

	texture.bind();

	passDataToBuffers();

	m_VertexBuffer.bind();
	ShaderManager::getInstance().getShader("Texture")->bind();
	ShaderManager::getInstance().getShader("Texture")->setupVertexAttribPointer("in_Position");
	m_TexCoordBuffer.bind();
	ShaderManager::getInstance().getShader("Texture")->setupVertexAttribPointer("in_TexCoords");
	ShaderManager::getInstance().getShader("Texture")->setUniform("in_Texture", texture.getId());
	glDrawArrays(GL_TRIANGLES, 0, m_VertexBuffer.getDataSize());
}

void SpriteRenderer::passDataToBuffers()
{
	m_VertexBuffer.setData(m_Vertices);
	m_TexCoordBuffer.setData(m_TexCoords);
}

void SpriteRenderer::addTexCoords(const TextureBounds& textureBounds, const glm::vec2& textureSize)
{
	// Bottom Left
	m_TexCoords.push_back(textureBounds.bottomLeft.x / textureSize.x);
	m_TexCoords.push_back((textureSize.y - textureBounds.bottomLeft.y) / textureSize.y);

	// Bottom Right
	m_TexCoords.push_back((textureBounds.bottomLeft.x + textureBounds.size.x) / textureSize.x);
	m_TexCoords.push_back((textureSize.y - textureBounds.bottomLeft.y) / textureSize.y);

	// Top Right
	m_TexCoords.push_back((textureBounds.bottomLeft.x + textureBounds.size.x) / textureSize.x);
	m_TexCoords.push_back((textureSize.y - (textureBounds.bottomLeft.y + textureBounds.size.y)) / textureSize.y);

	// Top Right (2)
	m_TexCoords.push_back((textureBounds.bottomLeft.x + textureBounds.size.x) / textureSize.x);
	m_TexCoords.push_back((textureSize.y - (textureBounds.bottomLeft.y + textureBounds.size.y)) / textureSize.y);

	// Top Left
	m_TexCoords.push_back(textureBounds.bottomLeft.x / textureSize.x);
	m_TexCoords.push_back((textureSize.y - (textureBounds.bottomLeft.y + textureBounds.size.y)) / textureSize.y);

	// Bottom Left (2)
	m_TexCoords.push_back(textureBounds.bottomLeft.x / textureSize.x);
	m_TexCoords.push_back((textureSize.y - textureBounds.bottomLeft.y) / textureSize.y);
}

void SpriteRenderer::addVertices(const glm::vec2& position, const glm::vec2& size, float rotationRads)
{
	auto sinAngle = glm::sin(rotationRads);
	auto cosAngle = glm::cos(rotationRads);

	auto offsetFromCenter = glm::vec2(-size.x / 2.f, -size.y / 2.f);
	auto bottomLeft = glm::vec2(position.x + (offsetFromCenter.x * cosAngle - offsetFromCenter.y * sinAngle),
								position.y - (-offsetFromCenter.y * cosAngle - offsetFromCenter.x * sinAngle));

	offsetFromCenter = glm::vec2(size.x / 2.f, -size.y / 2.f);
	auto bottomRight = glm::vec2(position.x + (offsetFromCenter.x * cosAngle - offsetFromCenter.y * sinAngle),
								 position.y - (-offsetFromCenter.y * cosAngle - offsetFromCenter.x * sinAngle));

	offsetFromCenter = glm::vec2(size.x / 2.f, size.y / 2.f);
	auto topRight = glm::vec2(position.x + (offsetFromCenter.x * cosAngle - offsetFromCenter.y * sinAngle),
							  position.y - (-offsetFromCenter.y * cosAngle - offsetFromCenter.x * sinAngle));

	offsetFromCenter = glm::vec2(-size.x / 2.f, size.y / 2.f);
	auto topLeft = glm::vec2(position.x + (offsetFromCenter.x * cosAngle - offsetFromCenter.y * sinAngle),
							 position.y - (-offsetFromCenter.y * cosAngle - offsetFromCenter.x * sinAngle));

	// Bottom Left
	m_Vertices.push_back(bottomLeft.x);
	m_Vertices.push_back(bottomLeft.y);

	// Bottom Right
	m_Vertices.push_back(bottomRight.x);
	m_Vertices.push_back(bottomRight.y);

	// Top Right
	m_Vertices.push_back(topRight.x);
	m_Vertices.push_back(topRight.y);

	// Top Right (2)
	m_Vertices.push_back(topRight.x);
	m_Vertices.push_back(topRight.y);

	// Top Left
	m_Vertices.push_back(topLeft.x);
	m_Vertices.push_back(topLeft.y);

	// Bottom Left (2)
	m_Vertices.push_back(bottomLeft.x);
	m_Vertices.push_back(bottomLeft.y);
}

void SpriteRenderer::clearVectors()
{
	m_Vertices.clear();
	m_TexCoords.clear();
}<|endoftext|>


<commit_before>// Copyright 2019 The TCMalloc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "tcmalloc/parameters.h"

#include "absl/time/time.h"
#include "tcmalloc/common.h"
#include "tcmalloc/experiment.h"
#include "tcmalloc/experiment_config.h"
#include "tcmalloc/huge_page_aware_allocator.h"
#include "tcmalloc/lifetime_based_allocator.h"
#include "tcmalloc/malloc_extension.h"
#include "tcmalloc/static_vars.h"
#include "tcmalloc/thread_cache.h"

GOOGLE_MALLOC_SECTION_BEGIN
namespace tcmalloc {
namespace tcmalloc_internal {

// As decide_subrelease() is determined at runtime, we cannot require constant
// initialization for the atomic.  This avoids an initialization order fiasco.
static std::atomic<bool>* hpaa_subrelease_ptr() {
  static std::atomic<bool> v(decide_subrelease());
  return &v;
}

// As skip_subrelease_interval_ns() is determined at runtime, we cannot require
// constant initialization for the atomic.  This avoids an initialization order
// fiasco.
static std::atomic<int64_t>& skip_subrelease_interval_ns() {
  static std::atomic<int64_t> v(absl::ToInt64Nanoseconds(
#if defined(TCMALLOC_SMALL_BUT_SLOW)
      absl::ZeroDuration()
#else
      absl::Seconds(60)
#endif
          ));
  return v;
}

uint64_t Parameters::heap_size_hard_limit() {
  size_t amount;
  bool is_hard;
  std::tie(amount, is_hard) = Static::page_allocator().limit();
  if (!is_hard) {
    amount = 0;
  }
  return amount;
}

void Parameters::set_heap_size_hard_limit(uint64_t value) {
  TCMalloc_Internal_SetHeapSizeHardLimit(value);
}

bool Parameters::hpaa_subrelease() {
  return hpaa_subrelease_ptr()->load(std::memory_order_relaxed);
}

void Parameters::set_hpaa_subrelease(bool value) {
  TCMalloc_Internal_SetHPAASubrelease(value);
}

ABSL_CONST_INIT std::atomic<MallocExtension::BytesPerSecond>
    Parameters::background_release_rate_(MallocExtension::BytesPerSecond{
        0
    });
ABSL_CONST_INIT std::atomic<int64_t> Parameters::guarded_sampling_rate_(
    50 * kDefaultProfileSamplingRate);
ABSL_CONST_INIT std::atomic<bool> Parameters::shuffle_per_cpu_caches_enabled_(
    true);
ABSL_CONST_INIT std::atomic<int32_t> Parameters::max_per_cpu_cache_size_(
    kMaxCpuCacheSize);
ABSL_CONST_INIT std::atomic<bool> Parameters::prioritize_spans_enabled_(false);
ABSL_CONST_INIT std::atomic<int64_t> Parameters::max_total_thread_cache_bytes_(
    kDefaultOverallThreadCacheSize);
ABSL_CONST_INIT std::atomic<double>
    Parameters::peak_sampling_heap_growth_fraction_(1.1);
ABSL_CONST_INIT std::atomic<bool> Parameters::per_cpu_caches_enabled_(
#if defined(TCMALLOC_DEPRECATED_PERTHREAD)
    false
#else
    true
#endif
);
ABSL_CONST_INIT std::atomic<bool>
    Parameters::per_cpu_caches_dynamic_slab_enabled_(false);
ABSL_CONST_INIT std::atomic<double>
    Parameters::per_cpu_caches_dynamic_slab_grow_threshold_(0.9);
ABSL_CONST_INIT std::atomic<double>
    Parameters::per_cpu_caches_dynamic_slab_shrink_threshold_(0.5);

ABSL_CONST_INIT std::atomic<int64_t> Parameters::profile_sampling_rate_(
    kDefaultProfileSamplingRate);

absl::Duration Parameters::filler_skip_subrelease_interval() {
  return absl::Nanoseconds(
      skip_subrelease_interval_ns().load(std::memory_order_relaxed));
}

bool Parameters::pass_span_object_count_to_pageheap() {
  static bool v([]() {
    return IsExperimentActive(
        Experiment::TEST_ONLY_TCMALLOC_PASS_SPAN_OBJECT_COUNT_TO_PAGEHEAP);
  }());
  return v;
}

}  // namespace tcmalloc_internal
}  // namespace tcmalloc
GOOGLE_MALLOC_SECTION_END

using tcmalloc::tcmalloc_internal::kLog;
using tcmalloc::tcmalloc_internal::Log;
using tcmalloc::tcmalloc_internal::Parameters;
using tcmalloc::tcmalloc_internal::Static;

extern "C" {

int64_t MallocExtension_Internal_GetProfileSamplingRate() {
  return Parameters::profile_sampling_rate();
}

void MallocExtension_Internal_SetProfileSamplingRate(int64_t value) {
  Parameters::set_profile_sampling_rate(value);
}

int64_t MallocExtension_Internal_GetGuardedSamplingRate() {
  return Parameters::guarded_sampling_rate();
}

void MallocExtension_Internal_SetGuardedSamplingRate(int64_t value) {
  Parameters::set_guarded_sampling_rate(value);
}

int64_t MallocExtension_Internal_GetMaxTotalThreadCacheBytes() {
  return Parameters::max_total_thread_cache_bytes();
}

void MallocExtension_Internal_SetMaxTotalThreadCacheBytes(int64_t value) {
  Parameters::set_max_total_thread_cache_bytes(value);
}

void MallocExtension_Internal_GetSkipSubreleaseInterval(absl::Duration* ret) {
  *ret = Parameters::filler_skip_subrelease_interval();
}

void MallocExtension_Internal_SetSkipSubreleaseInterval(absl::Duration value) {
  Parameters::set_filler_skip_subrelease_interval(value);
}

tcmalloc::MallocExtension::BytesPerSecond
MallocExtension_Internal_GetBackgroundReleaseRate() {
  return Parameters::background_release_rate();
}

void MallocExtension_Internal_SetBackgroundReleaseRate(
    tcmalloc::MallocExtension::BytesPerSecond rate) {
  Parameters::set_background_release_rate(rate);
}

void TCMalloc_Internal_SetBackgroundReleaseRate(size_t value) {
  Parameters::background_release_rate_.store(
      static_cast<tcmalloc::MallocExtension::BytesPerSecond>(value));
}

uint64_t TCMalloc_Internal_GetHeapSizeHardLimit() {
  return Parameters::heap_size_hard_limit();
}

bool TCMalloc_Internal_GetHPAASubrelease() {
  return Parameters::hpaa_subrelease();
}

bool TCMalloc_Internal_GetShufflePerCpuCachesEnabled() {
  return Parameters::shuffle_per_cpu_caches();
}

bool TCMalloc_Internal_GetPrioritizeSpansEnabled() {
  return Parameters::prioritize_spans();
}

double TCMalloc_Internal_GetPeakSamplingHeapGrowthFraction() {
  return Parameters::peak_sampling_heap_growth_fraction();
}

bool TCMalloc_Internal_GetPerCpuCachesEnabled() {
  return Parameters::per_cpu_caches();
}

void TCMalloc_Internal_SetGuardedSamplingRate(int64_t v) {
  Parameters::guarded_sampling_rate_.store(v, std::memory_order_relaxed);
}

// update_lock guards changes via SetHeapSizeHardLimit.
ABSL_CONST_INIT static absl::base_internal::SpinLock update_lock(
    absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);

void TCMalloc_Internal_SetHeapSizeHardLimit(uint64_t value) {
  // Ensure that page allocator is set up.
  Static::InitIfNecessary();

  absl::base_internal::SpinLockHolder l(&update_lock);

  size_t limit = std::numeric_limits<size_t>::max();
  bool active = false;
  if (value > 0) {
    limit = value;
    active = true;
  }

  bool currently_hard = Static::page_allocator().limit().second;
  if (active || currently_hard) {
    // Avoid resetting limit when current limit is soft.
    Static::page_allocator().set_limit(limit, active /* is_hard */);
    Log(kLog, __FILE__, __LINE__, "[tcmalloc] set page heap hard limit to",
        limit, "bytes");
  }
}

void TCMalloc_Internal_SetHPAASubrelease(bool v) {
  tcmalloc::tcmalloc_internal::hpaa_subrelease_ptr()->store(
      v, std::memory_order_relaxed);
}

void TCMalloc_Internal_SetShufflePerCpuCachesEnabled(bool v) {
  Parameters::shuffle_per_cpu_caches_enabled_.store(v,
                                                    std::memory_order_relaxed);
}

void TCMalloc_Internal_SetPrioritizeSpansEnabled(bool v) {
  Parameters::prioritize_spans_enabled_.store(v, std::memory_order_relaxed);
}

void TCMalloc_Internal_SetMaxPerCpuCacheSize(int32_t v) {
  Parameters::max_per_cpu_cache_size_.store(v, std::memory_order_relaxed);
}

void TCMalloc_Internal_SetMaxTotalThreadCacheBytes(int64_t v) {
  Parameters::max_total_thread_cache_bytes_.store(v, std::memory_order_relaxed);

  absl::base_internal::SpinLockHolder l(
      &tcmalloc::tcmalloc_internal::pageheap_lock);
  tcmalloc::tcmalloc_internal::ThreadCache::set_overall_thread_cache_size(v);
}

void TCMalloc_Internal_SetPeakSamplingHeapGrowthFraction(double v) {
  Parameters::peak_sampling_heap_growth_fraction_.store(
      v, std::memory_order_relaxed);
}

void TCMalloc_Internal_SetPerCpuCachesEnabled(bool v) {
  Parameters::per_cpu_caches_enabled_.store(v, std::memory_order_relaxed);
}

void TCMalloc_Internal_SetProfileSamplingRate(int64_t v) {
  Parameters::profile_sampling_rate_.store(v, std::memory_order_relaxed);
}

void TCMalloc_Internal_GetHugePageFillerSkipSubreleaseInterval(
    absl::Duration* v) {
  *v = Parameters::filler_skip_subrelease_interval();
}

void TCMalloc_Internal_SetHugePageFillerSkipSubreleaseInterval(
    absl::Duration v) {
  tcmalloc::tcmalloc_internal::skip_subrelease_interval_ns().store(
      absl::ToInt64Nanoseconds(v), std::memory_order_relaxed);
}

void TCMalloc_Internal_SetLifetimeAllocatorOptions(absl::string_view s) {
  absl::base_internal::SpinLockHolder l(
      &tcmalloc::tcmalloc_internal::pageheap_lock);
  tcmalloc::tcmalloc_internal::HugePageAwareAllocator* hpaa =
      Static::page_allocator().default_hpaa();
  if (hpaa != nullptr) {
    hpaa->lifetime_based_allocator().Enable(
        tcmalloc::tcmalloc_internal::LifetimePredictionOptions::FromFlag(s));
  }
}

bool TCMalloc_Internal_GetPerCpuCachesDynamicSlabEnabled() {
  return Parameters::per_cpu_caches_dynamic_slab_enabled();
}

void TCMalloc_Internal_SetPerCpuCachesDynamicSlabEnabled(bool v) {
  Parameters::per_cpu_caches_dynamic_slab_enabled_.store(
      v, std::memory_order_relaxed);
}

double TCMalloc_Internal_GetPerCpuCachesDynamicSlabGrowThreshold() {
  return Parameters::per_cpu_caches_dynamic_slab_grow_threshold();
}

void TCMalloc_Internal_SetPerCpuCachesDynamicSlabGrowThreshold(double v) {
  Parameters::per_cpu_caches_dynamic_slab_grow_threshold_.store(
      v, std::memory_order_relaxed);
}

double TCMalloc_Internal_GetPerCpuCachesDynamicSlabShrinkThreshold() {
  return Parameters::per_cpu_caches_dynamic_slab_shrink_threshold();
}

void TCMalloc_Internal_SetPerCpuCachesDynamicSlabShrinkThreshold(double v) {
  Parameters::per_cpu_caches_dynamic_slab_shrink_threshold_.store(
      v, std::memory_order_relaxed);
}

}  // extern "C"
<commit_msg>Enable span prioritization by default in the central freelist.<commit_after>// Copyright 2019 The TCMalloc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "tcmalloc/parameters.h"

#include "absl/time/time.h"
#include "tcmalloc/common.h"
#include "tcmalloc/experiment.h"
#include "tcmalloc/experiment_config.h"
#include "tcmalloc/huge_page_aware_allocator.h"
#include "tcmalloc/lifetime_based_allocator.h"
#include "tcmalloc/malloc_extension.h"
#include "tcmalloc/static_vars.h"
#include "tcmalloc/thread_cache.h"

GOOGLE_MALLOC_SECTION_BEGIN
namespace tcmalloc {
namespace tcmalloc_internal {

// As decide_subrelease() is determined at runtime, we cannot require constant
// initialization for the atomic.  This avoids an initialization order fiasco.
static std::atomic<bool>* hpaa_subrelease_ptr() {
  static std::atomic<bool> v(decide_subrelease());
  return &v;
}

// As skip_subrelease_interval_ns() is determined at runtime, we cannot require
// constant initialization for the atomic.  This avoids an initialization order
// fiasco.
static std::atomic<int64_t>& skip_subrelease_interval_ns() {
  static std::atomic<int64_t> v(absl::ToInt64Nanoseconds(
#if defined(TCMALLOC_SMALL_BUT_SLOW)
      absl::ZeroDuration()
#else
      absl::Seconds(60)
#endif
          ));
  return v;
}

uint64_t Parameters::heap_size_hard_limit() {
  size_t amount;
  bool is_hard;
  std::tie(amount, is_hard) = Static::page_allocator().limit();
  if (!is_hard) {
    amount = 0;
  }
  return amount;
}

void Parameters::set_heap_size_hard_limit(uint64_t value) {
  TCMalloc_Internal_SetHeapSizeHardLimit(value);
}

bool Parameters::hpaa_subrelease() {
  return hpaa_subrelease_ptr()->load(std::memory_order_relaxed);
}

void Parameters::set_hpaa_subrelease(bool value) {
  TCMalloc_Internal_SetHPAASubrelease(value);
}

ABSL_CONST_INIT std::atomic<MallocExtension::BytesPerSecond>
    Parameters::background_release_rate_(MallocExtension::BytesPerSecond{
        0
    });
ABSL_CONST_INIT std::atomic<int64_t> Parameters::guarded_sampling_rate_(
    50 * kDefaultProfileSamplingRate);
ABSL_CONST_INIT std::atomic<bool> Parameters::shuffle_per_cpu_caches_enabled_(
    true);
ABSL_CONST_INIT std::atomic<int32_t> Parameters::max_per_cpu_cache_size_(
    kMaxCpuCacheSize);
ABSL_CONST_INIT std::atomic<bool> Parameters::prioritize_spans_enabled_(true);
ABSL_CONST_INIT std::atomic<int64_t> Parameters::max_total_thread_cache_bytes_(
    kDefaultOverallThreadCacheSize);
ABSL_CONST_INIT std::atomic<double>
    Parameters::peak_sampling_heap_growth_fraction_(1.1);
ABSL_CONST_INIT std::atomic<bool> Parameters::per_cpu_caches_enabled_(
#if defined(TCMALLOC_DEPRECATED_PERTHREAD)
    false
#else
    true
#endif
);
ABSL_CONST_INIT std::atomic<bool>
    Parameters::per_cpu_caches_dynamic_slab_enabled_(false);
ABSL_CONST_INIT std::atomic<double>
    Parameters::per_cpu_caches_dynamic_slab_grow_threshold_(0.9);
ABSL_CONST_INIT std::atomic<double>
    Parameters::per_cpu_caches_dynamic_slab_shrink_threshold_(0.5);

ABSL_CONST_INIT std::atomic<int64_t> Parameters::profile_sampling_rate_(
    kDefaultProfileSamplingRate);

absl::Duration Parameters::filler_skip_subrelease_interval() {
  return absl::Nanoseconds(
      skip_subrelease_interval_ns().load(std::memory_order_relaxed));
}

bool Parameters::pass_span_object_count_to_pageheap() {
  static bool v([]() {
    return IsExperimentActive(
        Experiment::TEST_ONLY_TCMALLOC_PASS_SPAN_OBJECT_COUNT_TO_PAGEHEAP);
  }());
  return v;
}

}  // namespace tcmalloc_internal
}  // namespace tcmalloc
GOOGLE_MALLOC_SECTION_END

using tcmalloc::tcmalloc_internal::kLog;
using tcmalloc::tcmalloc_internal::Log;
using tcmalloc::tcmalloc_internal::Parameters;
using tcmalloc::tcmalloc_internal::Static;

extern "C" {

int64_t MallocExtension_Internal_GetProfileSamplingRate() {
  return Parameters::profile_sampling_rate();
}

void MallocExtension_Internal_SetProfileSamplingRate(int64_t value) {
  Parameters::set_profile_sampling_rate(value);
}

int64_t MallocExtension_Internal_GetGuardedSamplingRate() {
  return Parameters::guarded_sampling_rate();
}

void MallocExtension_Internal_SetGuardedSamplingRate(int64_t value) {
  Parameters::set_guarded_sampling_rate(value);
}

int64_t MallocExtension_Internal_GetMaxTotalThreadCacheBytes() {
  return Parameters::max_total_thread_cache_bytes();
}

void MallocExtension_Internal_SetMaxTotalThreadCacheBytes(int64_t value) {
  Parameters::set_max_total_thread_cache_bytes(value);
}

void MallocExtension_Internal_GetSkipSubreleaseInterval(absl::Duration* ret) {
  *ret = Parameters::filler_skip_subrelease_interval();
}

void MallocExtension_Internal_SetSkipSubreleaseInterval(absl::Duration value) {
  Parameters::set_filler_skip_subrelease_interval(value);
}

tcmalloc::MallocExtension::BytesPerSecond
MallocExtension_Internal_GetBackgroundReleaseRate() {
  return Parameters::background_release_rate();
}

void MallocExtension_Internal_SetBackgroundReleaseRate(
    tcmalloc::MallocExtension::BytesPerSecond rate) {
  Parameters::set_background_release_rate(rate);
}

void TCMalloc_Internal_SetBackgroundReleaseRate(size_t value) {
  Parameters::background_release_rate_.store(
      static_cast<tcmalloc::MallocExtension::BytesPerSecond>(value));
}

uint64_t TCMalloc_Internal_GetHeapSizeHardLimit() {
  return Parameters::heap_size_hard_limit();
}

bool TCMalloc_Internal_GetHPAASubrelease() {
  return Parameters::hpaa_subrelease();
}

bool TCMalloc_Internal_GetShufflePerCpuCachesEnabled() {
  return Parameters::shuffle_per_cpu_caches();
}

bool TCMalloc_Internal_GetPrioritizeSpansEnabled() {
  return Parameters::prioritize_spans();
}

double TCMalloc_Internal_GetPeakSamplingHeapGrowthFraction() {
  return Parameters::peak_sampling_heap_growth_fraction();
}

bool TCMalloc_Internal_GetPerCpuCachesEnabled() {
  return Parameters::per_cpu_caches();
}

void TCMalloc_Internal_SetGuardedSamplingRate(int64_t v) {
  Parameters::guarded_sampling_rate_.store(v, std::memory_order_relaxed);
}

// update_lock guards changes via SetHeapSizeHardLimit.
ABSL_CONST_INIT static absl::base_internal::SpinLock update_lock(
    absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);

void TCMalloc_Internal_SetHeapSizeHardLimit(uint64_t value) {
  // Ensure that page allocator is set up.
  Static::InitIfNecessary();

  absl::base_internal::SpinLockHolder l(&update_lock);

  size_t limit = std::numeric_limits<size_t>::max();
  bool active = false;
  if (value > 0) {
    limit = value;
    active = true;
  }

  bool currently_hard = Static::page_allocator().limit().second;
  if (active || currently_hard) {
    // Avoid resetting limit when current limit is soft.
    Static::page_allocator().set_limit(limit, active /* is_hard */);
    Log(kLog, __FILE__, __LINE__, "[tcmalloc] set page heap hard limit to",
        limit, "bytes");
  }
}

void TCMalloc_Internal_SetHPAASubrelease(bool v) {
  tcmalloc::tcmalloc_internal::hpaa_subrelease_ptr()->store(
      v, std::memory_order_relaxed);
}

void TCMalloc_Internal_SetShufflePerCpuCachesEnabled(bool v) {
  Parameters::shuffle_per_cpu_caches_enabled_.store(v,
                                                    std::memory_order_relaxed);
}

void TCMalloc_Internal_SetPrioritizeSpansEnabled(bool v) {
  Parameters::prioritize_spans_enabled_.store(v, std::memory_order_relaxed);
}

void TCMalloc_Internal_SetMaxPerCpuCacheSize(int32_t v) {
  Parameters::max_per_cpu_cache_size_.store(v, std::memory_order_relaxed);
}

void TCMalloc_Internal_SetMaxTotalThreadCacheBytes(int64_t v) {
  Parameters::max_total_thread_cache_bytes_.store(v, std::memory_order_relaxed);

  absl::base_internal::SpinLockHolder l(
      &tcmalloc::tcmalloc_internal::pageheap_lock);
  tcmalloc::tcmalloc_internal::ThreadCache::set_overall_thread_cache_size(v);
}

void TCMalloc_Internal_SetPeakSamplingHeapGrowthFraction(double v) {
  Parameters::peak_sampling_heap_growth_fraction_.store(
      v, std::memory_order_relaxed);
}

void TCMalloc_Internal_SetPerCpuCachesEnabled(bool v) {
  Parameters::per_cpu_caches_enabled_.store(v, std::memory_order_relaxed);
}

void TCMalloc_Internal_SetProfileSamplingRate(int64_t v) {
  Parameters::profile_sampling_rate_.store(v, std::memory_order_relaxed);
}

void TCMalloc_Internal_GetHugePageFillerSkipSubreleaseInterval(
    absl::Duration* v) {
  *v = Parameters::filler_skip_subrelease_interval();
}

void TCMalloc_Internal_SetHugePageFillerSkipSubreleaseInterval(
    absl::Duration v) {
  tcmalloc::tcmalloc_internal::skip_subrelease_interval_ns().store(
      absl::ToInt64Nanoseconds(v), std::memory_order_relaxed);
}

void TCMalloc_Internal_SetLifetimeAllocatorOptions(absl::string_view s) {
  absl::base_internal::SpinLockHolder l(
      &tcmalloc::tcmalloc_internal::pageheap_lock);
  tcmalloc::tcmalloc_internal::HugePageAwareAllocator* hpaa =
      Static::page_allocator().default_hpaa();
  if (hpaa != nullptr) {
    hpaa->lifetime_based_allocator().Enable(
        tcmalloc::tcmalloc_internal::LifetimePredictionOptions::FromFlag(s));
  }
}

bool TCMalloc_Internal_GetPerCpuCachesDynamicSlabEnabled() {
  return Parameters::per_cpu_caches_dynamic_slab_enabled();
}

void TCMalloc_Internal_SetPerCpuCachesDynamicSlabEnabled(bool v) {
  Parameters::per_cpu_caches_dynamic_slab_enabled_.store(
      v, std::memory_order_relaxed);
}

double TCMalloc_Internal_GetPerCpuCachesDynamicSlabGrowThreshold() {
  return Parameters::per_cpu_caches_dynamic_slab_grow_threshold();
}

void TCMalloc_Internal_SetPerCpuCachesDynamicSlabGrowThreshold(double v) {
  Parameters::per_cpu_caches_dynamic_slab_grow_threshold_.store(
      v, std::memory_order_relaxed);
}

double TCMalloc_Internal_GetPerCpuCachesDynamicSlabShrinkThreshold() {
  return Parameters::per_cpu_caches_dynamic_slab_shrink_threshold();
}

void TCMalloc_Internal_SetPerCpuCachesDynamicSlabShrinkThreshold(double v) {
  Parameters::per_cpu_caches_dynamic_slab_shrink_threshold_.store(
      v, std::memory_order_relaxed);
}

}  // extern "C"
<|endoftext|>


<commit_before>// ComplexCi.cpp : ̨Ӧóڵ㡣
//

//#include "stdafx.h"

#include <iostream>
#include <vector>
#include <set>
#include <fstream>
#include <string>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <sstream>
#include <iterator>
#include <queue>
#include <algorithm>
#include <chrono>
#include <bitset>

using namespace std;
using namespace std::chrono;

template<typename Out>
void split(const std::string &s, char delim, Out result) {
	std::stringstream ss;
	ss.str(s);
	std::string item;
	while (std::getline(ss, item, delim)) {
		*(result++) = item;
	}
}

std::vector<std::string> split(const std::string &s, char delim) {
	std::vector<std::string> elems;
	split(s, delim, std::back_inserter(elems));
	return elems;
}

/*void getNeighbourFrontierAndScope(const vector<vector<int> > &adjListGraph, int scope, int currentNode, unordered_set<int> &currentSet, unordered_set<int>& alreadyAccess)
{
//alreadyAccess.reserve(100000);

currentSet.insert(currentNode);
alreadyAccess.insert(currentNode);

for (int i = 0; i < scope; i++)
{
unordered_set<int> nextSet;
//nextSet.reserve(30000);

for (const auto& node : currentSet)
{
const vector<int>& neighbourNodeList = adjListGraph[node];

for (const auto& eachNeighbour : neighbourNodeList)
{
if (alreadyAccess.find(eachNeighbour) == alreadyAccess.end())
{
nextSet.insert(eachNeighbour);
alreadyAccess.insert(eachNeighbour);
}
}

}

currentSet = move(nextSet);
}
}*/

bitset<2000000> alreadyAccessBool;

void getNeighbourFrontierAndScope(const vector<vector<int> > &adjListGraph, int scope, int currentNode, vector<int> &currentSet, vector<int>& alreadyAccess)
{
	//alreadyAccessBool.reset();

	currentSet.push_back(currentNode);
	alreadyAccess.push_back(currentNode);
	alreadyAccessBool[currentNode] = 1;

	for (int i = 0; i < scope; i++)
	{
		vector<int> nextSet;

		for (const auto& node : currentSet)
		{
			const vector<int>& neighbourNodeList = adjListGraph[node];

			for (const auto& eachNeighbour : neighbourNodeList)
			{
				if (alreadyAccessBool[eachNeighbour] == 0)
				{
					nextSet.push_back(eachNeighbour);
					alreadyAccess.push_back(eachNeighbour);

					alreadyAccessBool[eachNeighbour] = 1;
				}
			}

		}

		currentSet = move(nextSet);
	}

	for (int node: alreadyAccess)
	{
		alreadyAccessBool.reset(node);
	}

}

long long basicCi(const vector<vector<int> > &adjListGraph, int ballRadius, int currentNode)
{
	if (adjListGraph[currentNode].size() == 0)
	{
		return -1;
	}

	vector<int> currentFrontier;
	vector<int> dummyValue;

	getNeighbourFrontierAndScope(adjListGraph, ballRadius, currentNode, currentFrontier, dummyValue);

	long long ci = 0;

	for (auto node : currentFrontier)
	{
		ci += (adjListGraph[node].size() - 1);
	}

	ci *= (adjListGraph[currentNode].size() - 1);

	/*
	if (currentNode % 500 == 0)
	{
	cout << currentNode << " currentFrontier size :" << currentFrontier.size() << endl;
	}
	*/

	/*
	if (currentNode == 1715132 && (ci == 0 || ci == 2))
	{
	cout << "currentNode: " << currentNode << " adjListGraph[currentNode].size(): " << adjListGraph[currentNode].size() << "/ ";

	for (auto node : adjListGraph[currentNode])
	{
	cout << node << " " ;
	}

	cout << endl;

	cout << "ci: " << ci << endl;

	cout << "currentFrontier: " << endl;

	for (auto node : currentFrontier)
	{
	cout << node << " " << adjListGraph[node].size() << endl;
	}

	cout << "dummyValue: " << endl;

	for (auto node : dummyValue)
	{
	cout << node << " node1: ";

	for (auto node1 : adjListGraph[node])
	{
	cout <<  node1 << " ";
	}
	cout << endl;
	}
	cout << endl;

	}
	*/

	return ci;
}

void deleteNode(vector<vector<int> > &adjListGraph, int node)
{
	/*
	if (adjListGraph[node].size() == 0)
	{
	return;
	} // not must here
	*/

	for (auto neighbour : adjListGraph[node])
	{
		adjListGraph[neighbour].erase(remove(adjListGraph[neighbour].begin(), adjListGraph[neighbour].end(), node), adjListGraph[neighbour].end());
	}

	adjListGraph[node].clear();

}

int main(int argc, char* argv[])
{
	unsigned int ballRadius = 1;
	unsigned int updateBatch = 1;
	unsigned int outputNumBatch = 1;

	string path = "";
	string output = "";

	if (argc > 4)
	{
		path = argv[1];
		output = path + "_out";

		ballRadius = stoi(argv[2]);
		updateBatch = stoi(argv[3]);
		outputNumBatch = stoi(argv[4]);

	}
	else
	{
		cout << "at least 3 parameters for csv path" << endl;
		cout << "e.g. 'C:/Users/zhfkt/Documents/Visual Studio 2013/Projects/ComplexCi/Release/karate.txt' 2 500 500" << endl;
		return 0;
	}

	high_resolution_clock::time_point t1 = high_resolution_clock::now();

	string modelID = "";

	{
		vector<string> fileName = split(path, '/');
		modelID = split(fileName[fileName.size() - 1], '.')[0];
	}

	std::cout << "path: " << path << endl;
	std::cout << "output: " << output << endl;
	std::cout << "modelID: " << modelID << endl;

	std::cout << "ballRadius: " << ballRadius << endl;
	std::cout << "updateBatch: " << updateBatch << endl;
	std::cout << "outputNumBatch: " << outputNumBatch << endl;

	std::cout << "First Read Start" << endl;

	unordered_set<int> allVex;
	string eachLine;
	ifstream is;
	is.open(path);

	while (is >> eachLine)
	{
		vector<string> csvEachLine = split(eachLine, ',');

		allVex.insert(stoi(csvEachLine[0]));
		allVex.insert(stoi(csvEachLine[1]));

	}
	is.close();
	int totalSize = allVex.size();

	std::cout << "First Read End/Second Read Start" << endl;

	vector<vector<int> > adjListGraph(totalSize);
	is.open(path);
	while (is >> eachLine)
	{
		vector<string> csvEachLine = split(eachLine, ',');

		adjListGraph[stoi(csvEachLine[0])].push_back(stoi(csvEachLine[1]));
		adjListGraph[stoi(csvEachLine[1])].push_back(stoi(csvEachLine[0]));
	}

	std::cout << "Second Read End" << endl;

	//--------------

	set<pair<long long, int> > allPQ; //ci/currentNode --- long is 32 bit on the win and long long is 64 bit / and long long can be multiple
	vector<long long> revereseLoopUpAllPQ(totalSize);
	cout << "modelID: " << modelID << " First Cal CI" << endl;

	for (int i = 0; i < adjListGraph.size(); i++)
	{
		int currentNode = i;
		// core_ci
		long long ci = basicCi(adjListGraph, ballRadius, currentNode);

		allPQ.insert(make_pair(ci, currentNode));
		revereseLoopUpAllPQ[currentNode] = ci;
	}

	vector<int> finalOutput;
	int loopCount = 0;
	while (true)
	{
		cout << "modelID: " << modelID << " loopCount: " << loopCount << " totalSize: " << totalSize << " maxCi: " << allPQ.rbegin()->first << " node: " << allPQ.rbegin()->second << endl;
		loopCount += updateBatch;

		vector<int> batchList;
		unsigned int batchLimiti = 0;

		pair<long long, int> debugPreviousMax = *(allPQ.rbegin());

		for (auto rit = allPQ.rbegin(); batchLimiti < updateBatch && (rit != allPQ.rend()); rit++, batchLimiti++)
		{
			batchList.push_back(rit->second);
			finalOutput.push_back(rit->second);
			allVex.erase(rit->second);  //remove key

			if (rit->first <= 0)
			{
				// ci algorithm ends
				goto CIEND;
			}
		}

		/*
		if (loopCount == 600000)
		{
		cout << " revereseLoopUpAllPQ[1715132] " << revereseLoopUpAllPQ[1715132] << endl;
		}
		*/

		//cout << "monitor 1" << endl;

		//int debugCount = 0;

		unordered_set<int> candidateUpdateNodes;
		for (int i : batchList)
		{
			vector<int> allScopeInBallRadiusPlusOne;
			vector<int> dummyValue;
			getNeighbourFrontierAndScope(adjListGraph, ballRadius + 1, i, dummyValue, allScopeInBallRadiusPlusOne);
			candidateUpdateNodes.insert(allScopeInBallRadiusPlusOne.begin(), allScopeInBallRadiusPlusOne.end());

			//cout << "monitor 1_2: " << debugCount++ << " " << batchList.size() << " " << candidateUpdateNodes.size() << endl;

		}

		//cout << "monitor 2" << endl;

		for (int i : batchList)
		{
			deleteNode(adjListGraph, i);
			//candidateUpdateNodesWithCi.insert(make_pair(i, -1));// no need to because self will be included in the candidateUpdateNodes and updated in the below
		}

		//cout << "monitor 3" << endl;
		//debugCount = 0;

		for (int i : candidateUpdateNodes)
		{
			long long updatedCi = basicCi(adjListGraph, ballRadius, i);

			long long olderCi = revereseLoopUpAllPQ[i];

			allPQ.erase(make_pair(olderCi, i));
			allPQ.insert(make_pair(updatedCi, i));

			revereseLoopUpAllPQ[i] = updatedCi;

			//cout << "monitor 3_4: " << debugCount++ << " " << candidateUpdateNodes.size() << endl;
		}
		//cout << "monitor 4" << endl;

		/*if ((debugPreviousMax.first) < (allPQ.rbegin()->first))
		{
		cout << "monitor 5: " << debugPreviousMax.first << " " << allPQ.rbegin()->first << endl;;
		}
		*/

	}

CIEND:

	//add left random

	cout << "Before Random adding the left CI equals zero: " << finalOutput.size() << endl;
	for (auto leftVex : allVex)
	{
		finalOutput.push_back(leftVex);
	}
	cout << "After Random adding the left CI equals zero: " << finalOutput.size() << endl;

	while (true)
	{
		if (finalOutput.size() % outputNumBatch == 0)
		{
			break;
		}
		else
		{
			finalOutput.push_back(-1);
		}
	}

	//--------------

	std::cout << "Outputing Start.." << endl;

	ofstream os(output);

	string output500 = "";
	for (unsigned int i = 0; i < finalOutput.size(); i++)
	{
		if (i % outputNumBatch == 0)
		{
			output500 = modelID;
		}

		if (finalOutput[i] != -1)
		{
			output500 += (',' + std::to_string(finalOutput[i]));
		}
		else
		{
			output500 += ',';
		}

		if (i % outputNumBatch == (outputNumBatch - 1) || i == (finalOutput.size() - 1))
		{
			os << output500 << endl;
			//std::cout << "output500: " << output500 << endl;
			output500.clear();
		}

	}

	os.close();

	std::cout << "Outputing End.." << endl;

	high_resolution_clock::time_point t2 = high_resolution_clock::now();
	auto duration = duration_cast<seconds>(t2 - t1).count();

	cout << "duration: " << duration << "s" << endl;

	system("pause");
	return 0;
}

<commit_msg>Rewrite the BFS process to boost<commit_after>// ComplexCi.cpp : ̨Ӧóڵ㡣
//

//#include "stdafx.h"

#include <iostream>
#include <vector>
#include <set>
#include <fstream>
#include <string>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <sstream>
#include <iterator>
#include <queue>
#include <algorithm>
#include <chrono>
#include <bitset>

using namespace std;
using namespace std::chrono;

template<typename Out>
void split(const std::string &s, char delim, Out result) {
	std::stringstream ss;
	ss.str(s);
	std::string item;
	while (std::getline(ss, item, delim)) {
		*(result++) = item;
	}
}

std::vector<std::string> split(const std::string &s, char delim) {
	std::vector<std::string> elems;
	split(s, delim, std::back_inserter(elems));
	return elems;
}

/*void getNeighbourFrontierAndScope(const vector<vector<int> > &adjListGraph, int scope, int currentNode, unordered_set<int> &currentSet, unordered_set<int>& alreadyAccess)
{
//alreadyAccess.reserve(100000);

currentSet.insert(currentNode);
alreadyAccess.insert(currentNode);

for (int i = 0; i < scope; i++)
{
unordered_set<int> nextSet;
//nextSet.reserve(30000);

for (const auto& node : currentSet)
{
const vector<int>& neighbourNodeList = adjListGraph[node];

for (const auto& eachNeighbour : neighbourNodeList)
{
if (alreadyAccess.find(eachNeighbour) == alreadyAccess.end())
{
nextSet.insert(eachNeighbour);
alreadyAccess.insert(eachNeighbour);
}
}

}

currentSet = move(nextSet);
}
}*/

bitset<2000000> alreadyAccessBool;
vector<int> bfsQueue;
int startIt = 0;
int endIt = 1;

void getNeighbourFrontierAndScope(const vector<vector<int> > &adjListGraph, int scope, int currentNode)
{
	startIt = 0;
	endIt = 1;

	//startIt and endIt will never execeed bfsQueue.size();
	//alreadyAccess is between 0 and endIt
	//fontier is between startIt and endIt

	bfsQueue[0] = currentNode;
	alreadyAccessBool[currentNode] = 1;

	for (int i = 0; i < scope; i++)
	{
		int lastEndIt = endIt;
		while (startIt != lastEndIt)
		{
			const vector<int>& neighbourNodeList = adjListGraph[bfsQueue[startIt++]];

			for (const auto& eachNeighbour : neighbourNodeList)
			{
				if (alreadyAccessBool[eachNeighbour] == 0)
				{
					bfsQueue[endIt++] = eachNeighbour;
					alreadyAccessBool[eachNeighbour] = 1;
				}
			}
		}
	}

	for (int i = 0; i < endIt; i++)
	{
		alreadyAccessBool.reset(bfsQueue[i]);
	}

}

long long basicCi(const vector<vector<int> > &adjListGraph, int ballRadius, int currentNode)
{
	if (adjListGraph[currentNode].size() == 0)
	{
		return -1;
	}

	getNeighbourFrontierAndScope(adjListGraph, ballRadius, currentNode);

	long long ci = 0;

	for (int i = startIt; i < endIt; i++)
	{
		ci += (adjListGraph[bfsQueue[i]].size() - 1);
	}

	ci *= (adjListGraph[currentNode].size() - 1);

	/*
	if (currentNode % 500 == 0)
	{
	cout << currentNode << " currentFrontier size :" << currentFrontier.size() << endl;
	}
	*/

	/*
	if (currentNode == 1715132 && (ci == 0 || ci == 2))
	{
	cout << "currentNode: " << currentNode << " adjListGraph[currentNode].size(): " << adjListGraph[currentNode].size() << "/ ";

	for (auto node : adjListGraph[currentNode])
	{
	cout << node << " " ;
	}

	cout << endl;

	cout << "ci: " << ci << endl;

	cout << "currentFrontier: " << endl;

	for (auto node : currentFrontier)
	{
	cout << node << " " << adjListGraph[node].size() << endl;
	}

	cout << "dummyValue: " << endl;

	for (auto node : dummyValue)
	{
	cout << node << " node1: ";

	for (auto node1 : adjListGraph[node])
	{
	cout <<  node1 << " ";
	}
	cout << endl;
	}
	cout << endl;

	}
	*/

	return ci;
}

void deleteNode(vector<vector<int> > &adjListGraph, int node)
{
	/*
	if (adjListGraph[node].size() == 0)
	{
	return;
	} // not must here
	*/

	for (auto neighbour : adjListGraph[node])
	{
		adjListGraph[neighbour].erase(remove(adjListGraph[neighbour].begin(), adjListGraph[neighbour].end(), node), adjListGraph[neighbour].end());
	}

	adjListGraph[node].clear();

}

int main(int argc, char* argv[])
{
	unsigned int ballRadius = 1;
	unsigned int updateBatch = 1;
	unsigned int outputNumBatch = 1;

	string path = "";
	string output = "";

	if (argc > 4)
	{
		path = argv[1];
		output = path + "_out";

		ballRadius = stoi(argv[2]);
		updateBatch = stoi(argv[3]);
		outputNumBatch = stoi(argv[4]);

	}
	else
	{
		cout << "at least 3 parameters for csv path" << endl;
		cout << "e.g. 'C:/Users/zhfkt/Documents/Visual Studio 2013/Projects/ComplexCi/Release/karate.txt' 2 500 500" << endl;
		return 0;
	}

	high_resolution_clock::time_point t1 = high_resolution_clock::now();

	string modelID = "";

	{
		vector<string> fileName = split(path, '/');
		modelID = split(fileName[fileName.size() - 1], '.')[0];
	}

	std::cout << "path: " << path << endl;
	std::cout << "output: " << output << endl;
	std::cout << "modelID: " << modelID << endl;

	std::cout << "ballRadius: " << ballRadius << endl;
	std::cout << "updateBatch: " << updateBatch << endl;
	std::cout << "outputNumBatch: " << outputNumBatch << endl;

	std::cout << "First Read Start" << endl;

	unordered_set<int> allVex;
	string eachLine;
	ifstream is;
	is.open(path);

	while (is >> eachLine)
	{
		vector<string> csvEachLine = split(eachLine, ',');

		allVex.insert(stoi(csvEachLine[0]));
		allVex.insert(stoi(csvEachLine[1]));

	}
	is.close();
	int totalSize = allVex.size();

	std::cout << "First Read End/Second Read Start" << endl;

	vector<vector<int> > adjListGraph(totalSize);
	is.open(path);
	while (is >> eachLine)
	{
		vector<string> csvEachLine = split(eachLine, ',');

		adjListGraph[stoi(csvEachLine[0])].push_back(stoi(csvEachLine[1]));
		adjListGraph[stoi(csvEachLine[1])].push_back(stoi(csvEachLine[0]));
	}

	std::cout << "Second Read End" << endl;

	bfsQueue.resize(totalSize, -1);

	//--------------

	set<pair<long long, int> > allPQ; //ci/currentNode --- long is 32 bit on the win and long long is 64 bit / and long long can be multiple
	vector<long long> revereseLoopUpAllPQ(totalSize);
	cout << "modelID: " << modelID << " First Cal CI" << endl;

	for (int i = 0; i < adjListGraph.size(); i++)
	{
		int currentNode = i;
		// core_ci
		long long ci = basicCi(adjListGraph, ballRadius, currentNode);

		allPQ.insert(make_pair(ci, currentNode));
		revereseLoopUpAllPQ[currentNode] = ci;
	}

	vector<int> finalOutput;
	int loopCount = 0;
	while (true)
	{
		cout << "modelID: " << modelID << " loopCount: " << loopCount << " totalSize: " << totalSize << " maxCi: " << allPQ.rbegin()->first << " node: " << allPQ.rbegin()->second << endl;
		loopCount += updateBatch;

		vector<int> batchList;
		unsigned int batchLimiti = 0;

		pair<long long, int> debugPreviousMax = *(allPQ.rbegin());

		for (auto rit = allPQ.rbegin(); batchLimiti < updateBatch && (rit != allPQ.rend()); rit++, batchLimiti++)
		{
			batchList.push_back(rit->second);
			finalOutput.push_back(rit->second);
			allVex.erase(rit->second);  //remove key

			if (rit->first <= 0)
			{
				// ci algorithm ends
				goto CIEND;
			}
		}

		/*
		if (loopCount == 600000)
		{
		cout << " revereseLoopUpAllPQ[1715132] " << revereseLoopUpAllPQ[1715132] << endl;
		}
		*/

		//cout << "monitor 1" << endl;

		//int debugCount = 0;

		unordered_set<int> candidateUpdateNodes;
		for (int i : batchList)
		{
			getNeighbourFrontierAndScope(adjListGraph, ballRadius + 1, i);
			candidateUpdateNodes.insert(bfsQueue.begin(), bfsQueue.begin() + endIt);

			//cout << "monitor 1_2: " << debugCount++ << " " << batchList.size() << " " << candidateUpdateNodes.size() << endl;

		}

		//cout << "monitor 2" << endl;

		for (int i : batchList)
		{
			deleteNode(adjListGraph, i);
			//candidateUpdateNodesWithCi.insert(make_pair(i, -1));// no need to because self will be included in the candidateUpdateNodes and updated in the below
		}

		//cout << "monitor 3" << endl;
		//debugCount = 0;

		for (int i : candidateUpdateNodes)
		{
			long long updatedCi = basicCi(adjListGraph, ballRadius, i);

			long long olderCi = revereseLoopUpAllPQ[i];

			allPQ.erase(make_pair(olderCi, i));
			allPQ.insert(make_pair(updatedCi, i));

			revereseLoopUpAllPQ[i] = updatedCi;

			//cout << "monitor 3_4: " << debugCount++ << " " << candidateUpdateNodes.size() << endl;
		}
		//cout << "monitor 4" << endl;

		/*if ((debugPreviousMax.first) < (allPQ.rbegin()->first))
		{
		cout << "monitor 5: " << debugPreviousMax.first << " " << allPQ.rbegin()->first << endl;;
		}
		*/

	}

CIEND:

	//add left random

	cout << "Before Random adding the left CI equals zero: " << finalOutput.size() << endl;
	for (auto leftVex : allVex)
	{
		finalOutput.push_back(leftVex);
	}
	cout << "After Random adding the left CI equals zero: " << finalOutput.size() << endl;

	while (true)
	{
		if (finalOutput.size() % outputNumBatch == 0)
		{
			break;
		}
		else
		{
			finalOutput.push_back(-1);
		}
	}

	//--------------

	std::cout << "Outputing Start.." << endl;

	ofstream os(output);

	string output500 = "";
	for (unsigned int i = 0; i < finalOutput.size(); i++)
	{
		if (i % outputNumBatch == 0)
		{
			output500 = modelID;
		}

		if (finalOutput[i] != -1)
		{
			output500 += (',' + std::to_string(finalOutput[i]));
		}
		else
		{
			output500 += ',';
		}

		if (i % outputNumBatch == (outputNumBatch - 1) || i == (finalOutput.size() - 1))
		{
			os << output500 << endl;
			//std::cout << "output500: " << output500 << endl;
			output500.clear();
		}

	}

	os.close();

	std::cout << "Outputing End.." << endl;

	high_resolution_clock::time_point t2 = high_resolution_clock::now();
	auto duration = duration_cast<seconds>(t2 - t1).count();

	cout << "duration: " << duration << "s" << endl;

	system("pause");
	return 0;
}

<|endoftext|>


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

  Library:   CTK

  Copyright (c) 2010  Kitware 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.commontk.org/LICENSE

  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.

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

#ifndef __ctkAbstractFactory_tpp
#define __ctkAbstractFactory_tpp

// QT includes
#include <QDebug>

// CTK includes
#include "ctkAbstractFactory.h"

//----------------------------------------------------------------------------
// ctkAbstractFactoryItem methods

//----------------------------------------------------------------------------
template<typename BaseClassType>
ctkAbstractFactoryItem<BaseClassType>::ctkAbstractFactoryItem()
  :Instance()
{
  this->Verbose = false;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
QString ctkAbstractFactoryItem<BaseClassType>::loadErrorString()const
{
  return QString();
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
BaseClassType* ctkAbstractFactoryItem<BaseClassType>::instantiate()
{
  if (this->Instance)
    {
    return this->Instance;
    }
  this->Instance = this->instanciator();
  return this->Instance;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
bool ctkAbstractFactoryItem<BaseClassType>::instantiated()const
{
  return (this->Instance != 0);
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
void ctkAbstractFactoryItem<BaseClassType>::uninstantiate()
{
  if (!this->Instance)
    {
    return;
    }
  delete this->Instance;
  // Make sure the pointer is set to 0. Doing so, Will prevent attempt to
  // delete unextising object if uninstantiate() methods is called multiple times.
  this->Instance = 0;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
void ctkAbstractFactoryItem<BaseClassType>::setVerbose(bool value)
{
  this->Verbose = value;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
bool ctkAbstractFactoryItem<BaseClassType>::verbose()const
{
  return this->Verbose;
}

//----------------------------------------------------------------------------
// ctkAbstractFactory methods

//----------------------------------------------------------------------------
template<typename BaseClassType>
ctkAbstractFactory<BaseClassType>::ctkAbstractFactory()
{
  this->Verbose = false;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
ctkAbstractFactory<BaseClassType>::~ctkAbstractFactory()
{
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
void ctkAbstractFactory<BaseClassType>::printAdditionalInfo()
{
  qDebug() << "ctkAbstractFactory<BaseClassType> (" << this << ")";
  // TODO
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
BaseClassType* ctkAbstractFactory<BaseClassType>::instantiate(const QString& itemKey)
{
  ctkAbstractFactoryItem<BaseClassType>* _item = this->item(itemKey);
  return (_item ? _item->instantiate() : 0);
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
void ctkAbstractFactory<BaseClassType>::uninstantiate(const QString& itemKey)
{
  ctkAbstractFactoryItem<BaseClassType> * _item = this->item(itemKey);
  if (!_item)
    {
    return;
    }
  _item->uninstantiate();
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
QStringList ctkAbstractFactory<BaseClassType>::keys() const
{
  // Since by construction, we checked if a name was already in the QHash,
  // there is no need to call 'uniqueKeys'
  return this->RegisteredItemMap.keys();
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
bool ctkAbstractFactory<BaseClassType>::registerItem(const QString& key,
  const QSharedPointer<ctkAbstractFactoryItem<BaseClassType> > & _item)
{
  // Sanity checks
  if (!_item || key.isEmpty() || this->item(key))
    {
    return false;
    }

  // Attempt to load it
  if (!_item->load())
    {
    QString errorStr;
    if (!_item->loadErrorString().isEmpty())
      {
      errorStr = " - " + _item->loadErrorString();
      }
    if (this->verbose())
      {
      qCritical() << "Failed to load object:" << key << errorStr ;
      }
    return false;
    }

  // Store its reference using a QSharedPointer
  this->RegisteredItemMap[key] = _item;
  return true;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
ctkAbstractFactoryItem<BaseClassType> * ctkAbstractFactory<BaseClassType>::item(const QString& itemKey)const
{
  ConstIterator iter = this->RegisteredItemMap.find(itemKey);
  if ( iter == this->RegisteredItemMap.constEnd())
    {
    return 0;
    }
  return iter.value().data();
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
void ctkAbstractFactory<BaseClassType>::setVerbose(bool value)
{
  this->Verbose = value;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
bool ctkAbstractFactory<BaseClassType>::verbose()const
{
  return this->Verbose;
}

#endif
<commit_msg>ENH: Add verbose to ctkAbstractFactory::registerItem<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) 2010  Kitware 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.commontk.org/LICENSE

  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.

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

#ifndef __ctkAbstractFactory_tpp
#define __ctkAbstractFactory_tpp

// QT includes
#include <QDebug>

// CTK includes
#include "ctkAbstractFactory.h"

//----------------------------------------------------------------------------
// ctkAbstractFactoryItem methods

//----------------------------------------------------------------------------
template<typename BaseClassType>
ctkAbstractFactoryItem<BaseClassType>::ctkAbstractFactoryItem()
  :Instance()
{
  this->Verbose = false;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
QString ctkAbstractFactoryItem<BaseClassType>::loadErrorString()const
{
  return QString();
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
BaseClassType* ctkAbstractFactoryItem<BaseClassType>::instantiate()
{
  if (this->Instance)
    {
    return this->Instance;
    }
  this->Instance = this->instanciator();
  return this->Instance;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
bool ctkAbstractFactoryItem<BaseClassType>::instantiated()const
{
  return (this->Instance != 0);
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
void ctkAbstractFactoryItem<BaseClassType>::uninstantiate()
{
  if (!this->Instance)
    {
    return;
    }
  delete this->Instance;
  // Make sure the pointer is set to 0. Doing so, Will prevent attempt to
  // delete unextising object if uninstantiate() methods is called multiple times.
  this->Instance = 0;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
void ctkAbstractFactoryItem<BaseClassType>::setVerbose(bool value)
{
  this->Verbose = value;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
bool ctkAbstractFactoryItem<BaseClassType>::verbose()const
{
  return this->Verbose;
}

//----------------------------------------------------------------------------
// ctkAbstractFactory methods

//----------------------------------------------------------------------------
template<typename BaseClassType>
ctkAbstractFactory<BaseClassType>::ctkAbstractFactory()
{
  this->Verbose = false;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
ctkAbstractFactory<BaseClassType>::~ctkAbstractFactory()
{
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
void ctkAbstractFactory<BaseClassType>::printAdditionalInfo()
{
  qDebug() << "ctkAbstractFactory<BaseClassType> (" << this << ")";
  // TODO
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
BaseClassType* ctkAbstractFactory<BaseClassType>::instantiate(const QString& itemKey)
{
  ctkAbstractFactoryItem<BaseClassType>* _item = this->item(itemKey);
  return (_item ? _item->instantiate() : 0);
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
void ctkAbstractFactory<BaseClassType>::uninstantiate(const QString& itemKey)
{
  ctkAbstractFactoryItem<BaseClassType> * _item = this->item(itemKey);
  if (!_item)
    {
    return;
    }
  _item->uninstantiate();
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
QStringList ctkAbstractFactory<BaseClassType>::keys() const
{
  // Since by construction, we checked if a name was already in the QHash,
  // there is no need to call 'uniqueKeys'
  return this->RegisteredItemMap.keys();
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
bool ctkAbstractFactory<BaseClassType>::registerItem(const QString& key,
  const QSharedPointer<ctkAbstractFactoryItem<BaseClassType> > & _item)
{
  // Sanity checks
  if (!_item || key.isEmpty() || this->item(key))
    {
    if (this->verbose())
      {
      qDebug() << __FUNCTION__ << "key is empty or already exists:"
               << key << "; item: " << _item;
      }
    return false;
    }

  // Attempt to load it
  if (!_item->load())
    {
    QString errorStr;
    if (!_item->loadErrorString().isEmpty())
      {
      errorStr = " - " + _item->loadErrorString();
      }
    if (this->verbose())
      {
      qCritical() << "Failed to load object:" << key << errorStr ;
      }
    return false;
    }

  // Store its reference using a QSharedPointer
  this->RegisteredItemMap[key] = _item;
  return true;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
ctkAbstractFactoryItem<BaseClassType> * ctkAbstractFactory<BaseClassType>::item(const QString& itemKey)const
{
  ConstIterator iter = this->RegisteredItemMap.find(itemKey);
  if ( iter == this->RegisteredItemMap.constEnd())
    {
    return 0;
    }
  return iter.value().data();
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
void ctkAbstractFactory<BaseClassType>::setVerbose(bool value)
{
  this->Verbose = value;
}

//----------------------------------------------------------------------------
template<typename BaseClassType>
bool ctkAbstractFactory<BaseClassType>::verbose()const
{
  return this->Verbose;
}

#endif
<|endoftext|>


<commit_before>// This may look like C code, but it is really -*- C++ -*-
//
// Copyright Bob Friesenhahn, 1999, 2000, 2002, 2003
//
// Test STL montageImages function
//

#include <Magick++.h>
#include <string>
#include <iostream>
#include <list>
#include <vector>

using namespace std;

using namespace Magick;

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

  // Initialize ImageMagick install location for Windows
  // InitializeMagick(*argv);
  InitializeMagick("");

  int failures=0;

  try {

    string srcdir("");
    if(getenv("SRCDIR") != 0)
      srcdir = getenv("SRCDIR");

    //
    // Test montageImages
    //

    list<Image> imageList;
    readImages( &imageList, srcdir + "test_image_anim.miff" );

    vector<Image> montage;
    MontageFramed montageOpts;

    // Default montage
    montageImages( &montage, imageList.begin(), imageList.end(), montageOpts );

    {
      Geometry targetGeometry(128, 126 );
      if ( montage[0].montageGeometry() != targetGeometry )
        {
          ++failures;
          cout << "Line: " << __LINE__
               << "  Montage geometry ("
               << string(montage[0].montageGeometry())
               << ") is incorrect (expected "
               << string(targetGeometry)
               << ")"
               << endl;
        }
    }

    if ( montage[0].columns() != 768 || montage[0].rows() != 504 )
      {
	++failures;
	cout << "Line: " << __LINE__
	     << "  Montage columns/rows ("
	     << montage[0].columns() << "x"
	     << montage[0].rows()
	     << ") incorrect. (expected 768x504)" << endl;
      }

    // Montage with options set
    montage.clear();
    montageOpts.borderColor( "green" );
    montageOpts.borderWidth( 1 );
    montageOpts.compose( OverCompositeOp );
    montageOpts.fileName( "Montage" );
    montageOpts.frameGeometry( "6x6+3+3" );
    montageOpts.geometry("50x50+2+2>");
    montageOpts.gravity( CenterGravity );
    montageOpts.strokeColor( "yellow" );
    montageOpts.shadow( true );
    montageOpts.texture( "granite:" );
    montageOpts.tile("2x1");
    montageImages( &montage, imageList.begin(), imageList.end(), montageOpts );

    if ( montage.size() != 3 )
      {
	++failures;
	cout << "Line: " << __LINE__
	     << "  Montage images failed, number of montage frames is "
	     << montage.size()
	     << " rather than 3 as expected." << endl;
      }

    {
      Geometry targetGeometry( 66, 70 );
      if ( montage[0].montageGeometry() != targetGeometry )
        {
          ++failures;
          cout << "Line: " << __LINE__
               << "  Montage geometry ("
               << string(montage[0].montageGeometry())
               << ") is incorrect (expected "
               << string(targetGeometry)
               << ")."
               << endl;
        }
    }

    if ( montage[0].columns() != 136 || montage[0].rows() != 70 )
      {
	++failures;
	cout << "Line: " << __LINE__
	     << "  Montage columns/rows ("
	     << montage[0].columns() << "x"
	     << montage[0].rows()
	     << ") incorrect. (expected 136x70)" << endl;
      }
  }

  catch( Exception &error_ )
    {
      cout << "Caught exception: " << error_.what() << endl;
      return 1;
    }
  catch( exception &error_ )
    {
      cout << "Caught exception: " << error_.what() << endl;
      return 1;
    }

  if ( failures )
    {
      cout << failures << " failures" << endl;
      return 1;
    }

  return 0;
}

<commit_msg>Build fix.<commit_after>// This may look like C code, but it is really -*- C++ -*-
//
// Copyright Bob Friesenhahn, 1999, 2000, 2002, 2003
//
// Test STL montageImages function
//

#include <Magick++.h>
#include <string>
#include <iostream>
#include <list>
#include <vector>

using namespace std;

using namespace Magick;

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

  // Initialize ImageMagick install location for Windows
  // InitializeMagick(*argv);
  InitializeMagick("");

  int failures=0;

  try {

    string srcdir("");
    if(getenv("SRCDIR") != 0)
      srcdir = getenv("SRCDIR");

    //
    // Test montageImages
    //

    list<Image> imageList;
    readImages( &imageList, srcdir + "test_image_anim.miff" );

    vector<Image> montage;
    MontageFramed montageOpts;

    // Default montage
    montageImages( &montage, imageList.begin(), imageList.end(), montageOpts );

    {
      Geometry targetGeometry(128, 126 );
      if ( montage[0].montageGeometry() != targetGeometry )
        {
          ++failures;
          cout << "Line: " << __LINE__
               << "  Montage geometry ("
               << string(montage[0].montageGeometry())
               << ") is incorrect (expected "
               << string(targetGeometry)
               << ")"
               << endl;
        }
    }

    if ( montage[0].columns() != 768 || montage[0].rows() != 504 )
      {
	++failures;
	cout << "Line: " << __LINE__
	     << "  Montage columns/rows ("
	     << montage[0].columns() << "x"
	     << montage[0].rows()
	     << ") incorrect. (expected 768x504)" << endl;
      }

    // Montage with options set
    montage.clear();
    montageOpts.borderColor( "green" );
    montageOpts.borderWidth( 1 );
    montageOpts.fileName( "Montage" );
    montageOpts.frameGeometry( "6x6+3+3" );
    montageOpts.geometry("50x50+2+2>");
    montageOpts.gravity( CenterGravity );
    montageOpts.strokeColor( "yellow" );
    montageOpts.shadow( true );
    montageOpts.texture( "granite:" );
    montageOpts.tile("2x1");
    montageImages( &montage, imageList.begin(), imageList.end(), montageOpts );

    if ( montage.size() != 3 )
      {
	++failures;
	cout << "Line: " << __LINE__
	     << "  Montage images failed, number of montage frames is "
	     << montage.size()
	     << " rather than 3 as expected." << endl;
      }

    {
      Geometry targetGeometry( 66, 70 );
      if ( montage[0].montageGeometry() != targetGeometry )
        {
          ++failures;
          cout << "Line: " << __LINE__
               << "  Montage geometry ("
               << string(montage[0].montageGeometry())
               << ") is incorrect (expected "
               << string(targetGeometry)
               << ")."
               << endl;
        }
    }

    if ( montage[0].columns() != 136 || montage[0].rows() != 70 )
      {
	++failures;
	cout << "Line: " << __LINE__
	     << "  Montage columns/rows ("
	     << montage[0].columns() << "x"
	     << montage[0].rows()
	     << ") incorrect. (expected 136x70)" << endl;
      }
  }

  catch( Exception &error_ )
    {
      cout << "Caught exception: " << error_.what() << endl;
      return 1;
    }
  catch( exception &error_ )
    {
      cout << "Caught exception: " << error_.what() << endl;
      return 1;
    }

  if ( failures )
    {
      cout << failures << " failures" << endl;
      return 1;
    }

  return 0;
}

<|endoftext|>


<commit_before>/**
*  Copyright (C) 2016 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program 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 Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
* Allows Export functionality from 3D Repo World to asset bundle
*/

#include "repo_model_export_asset.h"
#include "../../../core/model/bson/repo_bson_factory.h"
#include "../../../lib/repo_log.h"

using namespace repo::manipulator::modelconvertor;
const static size_t SRC_MAX_VERTEX_LIMIT = 65535;
//Labels for multipart JSON descriptor files
const static std::string MP_LABEL_APPEARANCE = "appearance";
const static std::string MP_LABEL_MAT_DIFFUSE = "diffuseColor";
const static std::string MP_LABEL_MAT_EMISSIVE = "emissiveColor";
const static std::string MP_LABEL_MATERIAL = "material";
const static std::string MP_LABEL_MAPPING = "mapping";
const static std::string MP_LABEL_MAT_SHININESS = "shininess";
const static std::string MP_LABEL_MAT_SPECULAR = "specularColor";
const static std::string MP_LABEL_MAT_TRANSPARENCY = "transparency";
const static std::string MP_LABEL_MAX = "max";
const static std::string MP_LABEL_MAX_GEO_COUNT = "maxGeoCount";
const static std::string MP_LABEL_MIN = "min";
const static std::string MP_LABEL_NAME = "name";
const static std::string MP_LABEL_NUM_IDs = "numberOfIDs";
const static std::string MP_LABEL_USAGE = "usage";

const static std::string MP_LABEL_ASSETS = "assets";
const static std::string MP_LABEL_SHARED = "sharedID";
const static std::string MP_LABEL_JSONS = "jsonFiles";
const static std::string MP_LABEL_OFFSET = "offset";
const static std::string MP_LABEL_DATABASE = "database";
const static std::string MP_LABEL_PROJECT = "project";

AssetModelExport::AssetModelExport(
	const repo::core::model::RepoScene *scene
	) : WebModelExport(scene)
{
	//Considering all newly imported models should have a stash graph, we only need to support stash graph?
	if (convertSuccess)
	{
		if (gType == repo::core::model::RepoScene::GraphType::OPTIMIZED)
		{
			convertSuccess = generateTreeRepresentation();
		}
		else  if (!(convertSuccess = !scene->getAllMeshes(repo::core::model::RepoScene::GraphType::DEFAULT).size()))
		{
			repoError << "Scene has no optimised graph and it is not a federation graph. SRC Exporter relies on this.";
		}
	}
	else
	{
		repoError << "Unable to export to SRC : Empty scene graph!";
	}
}

AssetModelExport::~AssetModelExport()
{
}

repo_web_buffers_t AssetModelExport::getAllFilesExportedAsBuffer() const
{
	return{ std::unordered_map<std::string, std::vector<uint8_t>>(), getJSONFilesAsBuffer() };
}

bool AssetModelExport::generateJSONMapping(
	const repo::core::model::MeshNode  *mesh,
	const repo::core::model::RepoScene *scene,
	const std::unordered_map<repo::lib::RepoUUID, std::vector<uint32_t>, repo::lib::RepoUUIDHasher> &splitMapping)
{
	bool success;
	if (success = mesh)
	{
		repo::lib::PropertyTree jsonTree;
		std::vector<repo_mesh_mapping_t> mappings = mesh->getMeshMapping();
		std::sort(mappings.begin(), mappings.end(),
			[](repo_mesh_mapping_t const& a, repo_mesh_mapping_t const& b) { return a.vertFrom < b.vertFrom; });

		size_t mappingLength = mappings.size();

		jsonTree.addToTree(MP_LABEL_NUM_IDs, mappingLength);
		jsonTree.addToTree(MP_LABEL_MAX_GEO_COUNT, mappingLength);

		std::vector<repo::lib::PropertyTree> mappingTrees;
		std::string meshUID = mesh->getUniqueID().toString();
		//Could get the mesh split function to pass a mapping out so we don't do this again.
		for (size_t i = 0; i < mappingLength; ++i)
		{
			auto mapIt = splitMapping.find(mappings[i].mesh_id);
			if (mapIt != splitMapping.end())
			{
				for (const uint32_t &subMeshID : mapIt->second)
				{
					repo::lib::PropertyTree mappingTree;

					mappingTree.addToTree(MP_LABEL_NAME, mappings[i].mesh_id.toString());

					repo::lib::RepoUUID id(mappings[i].mesh_id.toString());
					auto mesh = scene->getNodeByUniqueID(repo::core::model::RepoScene::GraphType::DEFAULT, id);
					if (mesh)
						mappingTree.addToTree(MP_LABEL_SHARED, mesh->getSharedID().toString());
					mappingTree.addToTree(MP_LABEL_MIN, mappings[i].min);
					mappingTree.addToTree(MP_LABEL_MAX, mappings[i].max);
					std::vector<std::string> usageArr = { meshUID + "_" + std::to_string(subMeshID) };
					mappingTree.addToTree(MP_LABEL_USAGE, usageArr);
					mappingTrees.push_back(mappingTree);
				}
			}
			else
			{
				repoError << "Failed to find split mapping for id: " << mappings[i].mesh_id;
			}
		}

		jsonTree.addArrayObjects(MP_LABEL_MAPPING, mappingTrees);

		std::string jsonFileName = "/" + scene->getDatabaseName() + "/" + scene->getProjectName() + "/" + mesh->getUniqueID().toString() + "_unity.json.mpc";

		jsonTrees[jsonFileName] = jsonTree;
	}
	else
	{
		repoError << "Unable to generate JSON file mapping : null pointer to mesh!";
	}

	return success;
}

bool AssetModelExport::generateTreeRepresentation(
	)
{
	bool success;
	if (success = scene->hasRoot(gType))
	{
		auto meshes = scene->getAllMeshes(gType);

		std::vector<std::string> assetFiles, jsons;
		for (const repo::core::model::RepoNode* node : meshes)
		{
			auto mesh = dynamic_cast<const repo::core::model::MeshNode*>(node);
			if (!mesh)
			{
				repoError << "Failed to cast a Repo Node of type mesh into a MeshNode(" << node->getUniqueID() << "). Skipping...";
			}
			std::string textureID = scene->getTextureIDForMesh(gType, mesh->getSharedID());

			repo::manipulator::modelutility::MeshMapReorganiser *reSplitter =
				new repo::manipulator::modelutility::MeshMapReorganiser(mesh, SRC_MAX_VERTEX_LIMIT);
			reorganisedMeshes.push_back(std::make_shared<repo::core::model::MeshNode>(reSplitter->getRemappedMesh()));

			if (success = !(reorganisedMeshes.back()->isEmpty()))
			{
				serialisedFaceBuf.push_back(reSplitter->getSerialisedFaces());
				idMapBuf.push_back(reSplitter->getIDMapArrays());
				meshMappings.push_back(reSplitter->getMappingsPerSubMesh());
				std::unordered_map<repo::lib::RepoUUID, std::vector<uint32_t>, repo::lib::RepoUUIDHasher> splitMapping = reSplitter->getSplitMapping();

				std::string fNamePrefix = "/" + scene->getDatabaseName() + "/" + scene->getProjectName() + "/" + mesh->getUniqueID().toString();
				assetFiles.push_back(fNamePrefix + ".unity3d");
				jsons.push_back(fNamePrefix + "_unity.json.mpc");

				success &= generateJSONMapping(mesh, scene, reSplitter->getSplitMapping());
				delete reSplitter;
			}
			else
			{
				repoError << "Failed to generate a remapped mesh for mesh with ID : " << mesh->getUniqueID();
				break;
			}
		}

		std::string assetListFile = "/" + scene->getDatabaseName() + "/" + scene->getProjectName() + "/revision/" + scene->getRevisionID().toString() + "/unityAssets.json";
		repo::lib::PropertyTree assetListTree;
		assetListTree.addToTree(MP_LABEL_ASSETS, assetFiles);
		assetListTree.addToTree(MP_LABEL_JSONS, jsons);
		assetListTree.addToTree(MP_LABEL_OFFSET, scene->getWorldOffset());
		assetListTree.addToTree(MP_LABEL_DATABASE, scene->getDatabaseName());
		assetListTree.addToTree(MP_LABEL_PROJECT, scene->getProjectName());
		jsonTrees[assetListFile] = assetListTree;
	}

	return success;
}<commit_msg>ISSUE #189 write min/max as arrays<commit_after>/**
*  Copyright (C) 2016 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program 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 Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
* Allows Export functionality from 3D Repo World to asset bundle
*/

#include "repo_model_export_asset.h"
#include "../../../core/model/bson/repo_bson_factory.h"
#include "../../../lib/repo_log.h"

using namespace repo::manipulator::modelconvertor;
const static size_t SRC_MAX_VERTEX_LIMIT = 65535;
//Labels for multipart JSON descriptor files
const static std::string MP_LABEL_APPEARANCE = "appearance";
const static std::string MP_LABEL_MAT_DIFFUSE = "diffuseColor";
const static std::string MP_LABEL_MAT_EMISSIVE = "emissiveColor";
const static std::string MP_LABEL_MATERIAL = "material";
const static std::string MP_LABEL_MAPPING = "mapping";
const static std::string MP_LABEL_MAT_SHININESS = "shininess";
const static std::string MP_LABEL_MAT_SPECULAR = "specularColor";
const static std::string MP_LABEL_MAT_TRANSPARENCY = "transparency";
const static std::string MP_LABEL_MAX = "max";
const static std::string MP_LABEL_MAX_GEO_COUNT = "maxGeoCount";
const static std::string MP_LABEL_MIN = "min";
const static std::string MP_LABEL_NAME = "name";
const static std::string MP_LABEL_NUM_IDs = "numberOfIDs";
const static std::string MP_LABEL_USAGE = "usage";

const static std::string MP_LABEL_ASSETS = "assets";
const static std::string MP_LABEL_SHARED = "sharedID";
const static std::string MP_LABEL_JSONS = "jsonFiles";
const static std::string MP_LABEL_OFFSET = "offset";
const static std::string MP_LABEL_DATABASE = "database";
const static std::string MP_LABEL_PROJECT = "project";

AssetModelExport::AssetModelExport(
	const repo::core::model::RepoScene *scene
	) : WebModelExport(scene)
{
	//Considering all newly imported models should have a stash graph, we only need to support stash graph?
	if (convertSuccess)
	{
		if (gType == repo::core::model::RepoScene::GraphType::OPTIMIZED)
		{
			convertSuccess = generateTreeRepresentation();
		}
		else  if (!(convertSuccess = !scene->getAllMeshes(repo::core::model::RepoScene::GraphType::DEFAULT).size()))
		{
			repoError << "Scene has no optimised graph and it is not a federation graph. SRC Exporter relies on this.";
		}
	}
	else
	{
		repoError << "Unable to export to SRC : Empty scene graph!";
	}
}

AssetModelExport::~AssetModelExport()
{
}

repo_web_buffers_t AssetModelExport::getAllFilesExportedAsBuffer() const
{
	return{ std::unordered_map<std::string, std::vector<uint8_t>>(), getJSONFilesAsBuffer() };
}

bool AssetModelExport::generateJSONMapping(
	const repo::core::model::MeshNode  *mesh,
	const repo::core::model::RepoScene *scene,
	const std::unordered_map<repo::lib::RepoUUID, std::vector<uint32_t>, repo::lib::RepoUUIDHasher> &splitMapping)
{
	bool success;
	if (success = mesh)
	{
		repo::lib::PropertyTree jsonTree;
		std::vector<repo_mesh_mapping_t> mappings = mesh->getMeshMapping();
		std::sort(mappings.begin(), mappings.end(),
			[](repo_mesh_mapping_t const& a, repo_mesh_mapping_t const& b) { return a.vertFrom < b.vertFrom; });

		size_t mappingLength = mappings.size();

		jsonTree.addToTree(MP_LABEL_NUM_IDs, mappingLength);
		jsonTree.addToTree(MP_LABEL_MAX_GEO_COUNT, mappingLength);

		std::vector<repo::lib::PropertyTree> mappingTrees;
		std::string meshUID = mesh->getUniqueID().toString();
		//Could get the mesh split function to pass a mapping out so we don't do this again.
		for (size_t i = 0; i < mappingLength; ++i)
		{
			auto mapIt = splitMapping.find(mappings[i].mesh_id);
			if (mapIt != splitMapping.end())
			{
				for (const uint32_t &subMeshID : mapIt->second)
				{
					repo::lib::PropertyTree mappingTree;

					mappingTree.addToTree(MP_LABEL_NAME, mappings[i].mesh_id.toString());

					repo::lib::RepoUUID id(mappings[i].mesh_id.toString());
					auto mesh = scene->getNodeByUniqueID(repo::core::model::RepoScene::GraphType::DEFAULT, id);
					if (mesh)
						mappingTree.addToTree(MP_LABEL_SHARED, mesh->getSharedID().toString());
					mappingTree.addToTree(MP_LABEL_MIN, mappings[i].min.toStdVector());
					mappingTree.addToTree(MP_LABEL_MAX, mappings[i].max.toStdVector());
					std::vector<std::string> usageArr = { meshUID + "_" + std::to_string(subMeshID) };
					mappingTree.addToTree(MP_LABEL_USAGE, usageArr);
					mappingTrees.push_back(mappingTree);
				}
			}
			else
			{
				repoError << "Failed to find split mapping for id: " << mappings[i].mesh_id;
			}
		}

		jsonTree.addArrayObjects(MP_LABEL_MAPPING, mappingTrees);

		std::string jsonFileName = "/" + scene->getDatabaseName() + "/" + scene->getProjectName() + "/" + mesh->getUniqueID().toString() + "_unity.json.mpc";

		jsonTrees[jsonFileName] = jsonTree;
	}
	else
	{
		repoError << "Unable to generate JSON file mapping : null pointer to mesh!";
	}

	return success;
}

bool AssetModelExport::generateTreeRepresentation(
	)
{
	bool success;
	if (success = scene->hasRoot(gType))
	{
		auto meshes = scene->getAllMeshes(gType);

		std::vector<std::string> assetFiles, jsons;
		for (const repo::core::model::RepoNode* node : meshes)
		{
			auto mesh = dynamic_cast<const repo::core::model::MeshNode*>(node);
			if (!mesh)
			{
				repoError << "Failed to cast a Repo Node of type mesh into a MeshNode(" << node->getUniqueID() << "). Skipping...";
			}
			std::string textureID = scene->getTextureIDForMesh(gType, mesh->getSharedID());

			repo::manipulator::modelutility::MeshMapReorganiser *reSplitter =
				new repo::manipulator::modelutility::MeshMapReorganiser(mesh, SRC_MAX_VERTEX_LIMIT);
			reorganisedMeshes.push_back(std::make_shared<repo::core::model::MeshNode>(reSplitter->getRemappedMesh()));

			if (success = !(reorganisedMeshes.back()->isEmpty()))
			{
				serialisedFaceBuf.push_back(reSplitter->getSerialisedFaces());
				idMapBuf.push_back(reSplitter->getIDMapArrays());
				meshMappings.push_back(reSplitter->getMappingsPerSubMesh());
				std::unordered_map<repo::lib::RepoUUID, std::vector<uint32_t>, repo::lib::RepoUUIDHasher> splitMapping = reSplitter->getSplitMapping();

				std::string fNamePrefix = "/" + scene->getDatabaseName() + "/" + scene->getProjectName() + "/" + mesh->getUniqueID().toString();
				assetFiles.push_back(fNamePrefix + ".unity3d");
				jsons.push_back(fNamePrefix + "_unity.json.mpc");

				success &= generateJSONMapping(mesh, scene, reSplitter->getSplitMapping());
				delete reSplitter;
			}
			else
			{
				repoError << "Failed to generate a remapped mesh for mesh with ID : " << mesh->getUniqueID();
				break;
			}
		}

		std::string assetListFile = "/" + scene->getDatabaseName() + "/" + scene->getProjectName() + "/revision/" + scene->getRevisionID().toString() + "/unityAssets.json";
		repo::lib::PropertyTree assetListTree;
		assetListTree.addToTree(MP_LABEL_ASSETS, assetFiles);
		assetListTree.addToTree(MP_LABEL_JSONS, jsons);
		assetListTree.addToTree(MP_LABEL_OFFSET, scene->getWorldOffset());
		assetListTree.addToTree(MP_LABEL_DATABASE, scene->getDatabaseName());
		assetListTree.addToTree(MP_LABEL_PROJECT, scene->getProjectName());
		jsonTrees[assetListFile] = assetListTree;
	}

	return success;
}<|endoftext|>