<commit_before>/*
* This source file is part of ArkGameFrame
* For the latest info, see https://github.com/ArkGame
*
* Copyright (c) 2013-2017 ArkGame 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
*
*     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.
*
*/

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <assert.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <limits>
#include <algorithm>
#include <utility>
#include <functional>
#include <cctype>
#include <iterator>
#include <unordered_map>
#include <stdint.h>
#include <functional>
#include <memory>
#include <signal.h>
#include <chrono>
#include <sstream>
#include <random>
#include <thread>
#include <mutex>

#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(__WIN64__) || defined(WIN64) || defined(_WIN64)
// only windows include
#include <io.h>
#include <time.h>
#ifndef WIN32_LEAN_AND_MEAN
#include <WinSock2.h>
#include <MSWSock.h>
#define WIN32_LEAN_AND_MEAN
#endif // WIN32_LEAN_AND_MEAN
#include <windows.h>
#define _SCL_SECURE_NO_WARNINGS

#define SIGHUP  1
#define SIGINT  2
#define SIGQUIT 3
#define SIGUSR1 10
#define SIGPIPE 13
#define SIGCHLD 17
#define SIGSYS  32

#else
// only other unix/linux include
#include <sys/socket.h>
#endif

#define ARK_LITTLE_ENDIAN
#define ARK_BIG_ENDIAN

#if !defined(ARK_ENDIAN)
#  if defined(USE_BIG_ENDIAN)
#    define ARK_ENDIAN ARK_BIG_ENDIAN
#  else
#     define ARK_ENDIAN ARK_LITTLE_ENDIAN
#  endif
#endif // !defined(ARK_ENDIAN)

#define PLATFORM_WIN    0
#define PLATFORM_UNIX   1
#define PLATFORM_APPLE  2

#define UNIX_FLAVOUR_LINUX  1
#define UNIX_FLAVOUR_BSD    2
#define UNIX_FLAVOUR_OTHER  3
#define UNIX_FLAVOUR_OSX    4

#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(__WIN64__) || defined(WIN64) || defined(_WIN64)
#  define ARK_PLATFORM PLATFORM_WIN
#elif defined(__APPLE_CC__)
#  define ARK_PLATFORM PLATFORM_APPLE
#else
#  define ARK_PLATFORM PLATFORM_UNIX
#endif

#define COMPILER_MICROSOFT  0
#define COMPILER_GNU        1
#define COMPILER_BORLAND    2
#define COMPILER_INTEL      3
#define COMPILER_CLANG      4

#ifdef _MSC_VER
#  define ARK_COMPILER COMPILER_MICROSOFT
#elif defined(__INTEL_COMPILER)
#  define ARK_COMPILER COMPILER_INTEL
#elif defined(__BORLANDC__)
#  define ARK_COMPILER COMPILER_BORLAND
#elif defined(__GNUC__)
#  define ARK_COMPILER COMPILER_GNU
#elif defined( __clang__ )
#  define ARK_COMPILER COMPILER_CLANG
#else
#  pragma error "FATAL ERROR: Unknown compiler."
#endif

#if ARK_PLATFORM == PLATFORM_UNIX || ARK_PLATFORM == PLATFORM_APPLE
#  if defined(HAVE_DARWIN)
#    define ARK_PLATFORM_NAME "MacOSX"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_OSX
#  elif defined(USE_KQUEUE)
#    define ARK_PLATFORM_NAME "FreeBSD"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_BSD
#  elif defined(USE_KQUEUE_DFLY)
#    define ARK_PLATFORM_NAME "DragonFlyBSD"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_BSD
#  else
#    define ARK_PLATFORM_NAME "Linux"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_LINUX
#  endif
#elif ARK_PLATFORM == PLATFORM_WIN
#  define ARK_PLATFORM_NAME "Windows"
#else
#  pragma error "FATAL ERROR: Unknown platform."
#endif

#define ARK_RUN_MODE_DEBUG      0
#define ARK_RUN_MODE_RELEASE    1

#ifndef ARK_RUN_MODE
#  if defined(DEBUG) || defined(_DEBUG)
#    define ARK_RUN_MODE ARK_RUN_MODE_DEBUG
#    define ARK_RUN_MODE_NAME "Debug"
#  else
#    define ARK_RUN_MODE ARK_RUN_MODE_RELEASE
#    define ARK_RUN_MODE_NAME "Release"
#  endif // DEBUG
#endif

#ifndef X64
#  if defined(_WIN64) || defined(__x86_64__) || defined(__amd64) || defined(__LP64__)
#    define X64
#  endif
#endif

#ifdef X64
#  define ARK_ARCH_NAME "X64"
#else
#  define ARK_ARCH_NAME "X86"
#endif // X64

#define ARK_LITTLE_ENDIAN

#ifndef ARK_DYNAMIC_PLUGIN
#define ARK_DYNAMIC_PLUGIN
#endif

<commit_msg>modify platform<commit_after>/*
* This source file is part of ArkGameFrame
* For the latest info, see https://github.com/ArkGame
*
* Copyright (c) 2013-2017 ArkGame 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
*
*     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.
*
*/

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <assert.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <limits>
#include <algorithm>
#include <utility>
#include <functional>
#include <cctype>
#include <iterator>
#include <unordered_map>
#include <stdint.h>
#include <functional>
#include <memory>
#include <signal.h>
#include <chrono>
#include <sstream>
#include <random>
#include <thread>
#include <mutex>

#define NOMINMAX
#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(__WIN64__) || defined(WIN64) || defined(_WIN64)
// only windows include
#include <io.h>
#include <time.h>
#ifndef WIN32_LEAN_AND_MEAN
#include <WinSock2.h>
#include <MSWSock.h>
#define WIN32_LEAN_AND_MEAN
#endif // WIN32_LEAN_AND_MEAN
#include <windows.h>
#define _SCL_SECURE_NO_WARNINGS

#define SIGHUP  1
#define SIGINT  2
#define SIGQUIT 3
#define SIGUSR1 10
#define SIGPIPE 13
#define SIGCHLD 17
#define SIGSYS  32

#else
// only other unix/linux include
#include <sys/socket.h>
#endif

#define ARK_LITTLE_ENDIAN
#define ARK_BIG_ENDIAN

#if !defined(ARK_ENDIAN)
#  if defined(USE_BIG_ENDIAN)
#    define ARK_ENDIAN ARK_BIG_ENDIAN
#  else
#     define ARK_ENDIAN ARK_LITTLE_ENDIAN
#  endif
#endif // !defined(ARK_ENDIAN)

#define PLATFORM_WIN    0
#define PLATFORM_UNIX   1
#define PLATFORM_APPLE  2

#define UNIX_FLAVOUR_LINUX  1
#define UNIX_FLAVOUR_BSD    2
#define UNIX_FLAVOUR_OTHER  3
#define UNIX_FLAVOUR_OSX    4

#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(__WIN64__) || defined(WIN64) || defined(_WIN64)
#  define ARK_PLATFORM PLATFORM_WIN
#elif defined(__APPLE_CC__)
#  define ARK_PLATFORM PLATFORM_APPLE
#else
#  define ARK_PLATFORM PLATFORM_UNIX
#endif

#define COMPILER_MICROSOFT  0
#define COMPILER_GNU        1
#define COMPILER_BORLAND    2
#define COMPILER_INTEL      3
#define COMPILER_CLANG      4

#ifdef _MSC_VER
#  define ARK_COMPILER COMPILER_MICROSOFT
#elif defined(__INTEL_COMPILER)
#  define ARK_COMPILER COMPILER_INTEL
#elif defined(__BORLANDC__)
#  define ARK_COMPILER COMPILER_BORLAND
#elif defined(__GNUC__)
#  define ARK_COMPILER COMPILER_GNU
#elif defined( __clang__ )
#  define ARK_COMPILER COMPILER_CLANG
#else
#  pragma error "FATAL ERROR: Unknown compiler."
#endif

#if ARK_PLATFORM == PLATFORM_UNIX || ARK_PLATFORM == PLATFORM_APPLE
#  if defined(HAVE_DARWIN)
#    define ARK_PLATFORM_NAME "MacOSX"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_OSX
#  elif defined(USE_KQUEUE)
#    define ARK_PLATFORM_NAME "FreeBSD"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_BSD
#  elif defined(USE_KQUEUE_DFLY)
#    define ARK_PLATFORM_NAME "DragonFlyBSD"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_BSD
#  else
#    define ARK_PLATFORM_NAME "Linux"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_LINUX
#  endif
#elif ARK_PLATFORM == PLATFORM_WIN
#  define ARK_PLATFORM_NAME "Windows"
#else
#  pragma error "FATAL ERROR: Unknown platform."
#endif

#define ARK_RUN_MODE_DEBUG      0
#define ARK_RUN_MODE_RELEASE    1

#ifndef ARK_RUN_MODE
#  if defined(DEBUG) || defined(_DEBUG)
#    define ARK_RUN_MODE ARK_RUN_MODE_DEBUG
#    define ARK_RUN_MODE_NAME "Debug"
#  else
#    define ARK_RUN_MODE ARK_RUN_MODE_RELEASE
#    define ARK_RUN_MODE_NAME "Release"
#  endif // DEBUG
#endif

#ifndef X64
#  if defined(_WIN64) || defined(__x86_64__) || defined(__amd64) || defined(__LP64__)
#    define X64
#  endif
#endif

#ifdef X64
#  define ARK_ARCH_NAME "X64"
#else
#  define ARK_ARCH_NAME "X86"
#endif // X64

#define ARK_LITTLE_ENDIAN

#ifndef ARK_DYNAMIC_PLUGIN
#define ARK_DYNAMIC_PLUGIN
#endif

<|endoftext|>


<commit_before>// Time:  O(n^2 * p), p is max number of the same two sum pairs.
// Space: O(n^2)

class Solution {
public:
    /**
     * @param numbers: Give an array numbersbers of n integer
     * @param target: you need to find four elements that's sum of target
     * @return: Find all unique quadruplets in the array which gives the sum of
     *          zero.
     */
    vector<vector<int> > fourSum(vector<int> nums, int target) {

        sort(nums.begin(), nums.end());
        unordered_map<int, vector<vector<size_t>>> two_sum; // two_sum saves "sum to (i, j) pairs, which i < j."
        for (size_t i = 0; i < nums.size(); ++i) {
            for (size_t j = i + 1; j < nums.size(); ++j) {
                bool have_duplicate = false;
                for (const auto& vec : two_sum[nums[i] + nums[j]]) {
                    if (nums[vec.front()] == nums[i]) { // Duplicated.
                        have_duplicate = true;
                        break;
                    }
                }
                if (!have_duplicate) { // Not duplicated
                    vector<size_t> new_vec = {i, j};
                    two_sum[nums[i] + nums[j]].emplace_back(move(new_vec));
                }
            }
        }

        unordered_set<string> answers; // Use hash to filter duplicated.
        vector<vector<int>> res;
        for (size_t i = 2; i < nums.size(); ++i) {
            for (size_t j = i + 1; j < nums.size(); ++j) {
                auto it = two_sum.find(target - nums[i] - nums[j]);
                if (it != two_sum.end()) {
                    for (const auto& vec : it->second) {
                        if (i > vec.back()) { // {vec.front() < vec.back() < i < j}
                            vector<int> candidate = {nums[vec.front()], nums[vec.back()], nums[i], nums[j]};
                            if (answers.emplace(join_vector(candidate)).second) { // Not duplicated.
                                res.emplace_back(move(candidate)); // Add to answers.
                            }
                        }
                    }
                }
            }
        }
        return res;
    }

    // Hash vector to string.
    string join_vector(const vector<int>& nums) {
        string ret;
        for (int n : nums) {
            ret += to_string(n);
            ret += ' ';
        }
        return ret;
    }
};<commit_msg>Update 4-sum.cpp<commit_after>// Time:  O(n^2 * p), p is max number of the same two sum pairs.
// Space: O(n^2 * p)

class Solution {
public:
    /**
     * @param numbers: Give an array numbersbers of n integer
     * @param target: you need to find four elements that's sum of target
     * @return: Find all unique quadruplets in the array which gives the sum of
     *          zero.
     */
    vector<vector<int> > fourSum(vector<int> nums, int target) {

        sort(nums.begin(), nums.end());
        unordered_map<int, vector<vector<size_t>>> two_sum; // two_sum saves "sum to (i, j) pairs, which i < j."
        for (size_t i = 0; i < nums.size(); ++i) {
            for (size_t j = i + 1; j < nums.size(); ++j) {
                bool have_duplicate = false;
                for (const auto& vec : two_sum[nums[i] + nums[j]]) {
                    if (nums[vec.front()] == nums[i]) { // Duplicated.
                        have_duplicate = true;
                        break;
                    }
                }
                if (!have_duplicate) { // Not duplicated
                    vector<size_t> new_vec = {i, j};
                    two_sum[nums[i] + nums[j]].emplace_back(move(new_vec));
                }
            }
        }

        unordered_set<string> answers; // Use hash to filter duplicated.
        vector<vector<int>> res;
        for (size_t i = 2; i < nums.size(); ++i) {
            for (size_t j = i + 1; j < nums.size(); ++j) {
                auto it = two_sum.find(target - nums[i] - nums[j]);
                if (it != two_sum.end()) {
                    for (const auto& vec : it->second) {
                        if (i > vec.back()) { // {vec.front() < vec.back() < i < j}
                            vector<int> candidate = {nums[vec.front()], nums[vec.back()], nums[i], nums[j]};
                            if (answers.emplace(join_vector(candidate)).second) { // Not duplicated.
                                res.emplace_back(move(candidate)); // Add to answers.
                            }
                        }
                    }
                }
            }
        }
        return res;
    }

    // Hash vector to string.
    string join_vector(const vector<int>& nums) {
        string ret;
        for (int n : nums) {
            ret += to_string(n);
            ret += ' ';
        }
        return ret;
    }
};
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// 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 "config.h"
#include "alloc.h"
#include "intrinsics.h"
#if defined(TASKING_TBB)
#  define TBB_IMPLEMENT_CPP0X 0
#  define __TBB_NO_IMPLICIT_LINKAGE 1
#  define __TBBMALLOC_NO_IMPLICIT_LINKAGE 1
#  include "tbb/scalable_allocator.h"
#endif

////////////////////////////////////////////////////////////////////////////////
/// Windows Platform
////////////////////////////////////////////////////////////////////////////////

#ifdef _WIN32

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <malloc.h>

namespace embree
{
  void* os_malloc(size_t bytes, const int additional_flags)
  {
    int flags = MEM_COMMIT|MEM_RESERVE|additional_flags;
    char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
    if (ptr == nullptr) throw std::bad_alloc();
    return ptr;
  }

  void* os_reserve(size_t bytes)
  {
    char* ptr = (char*) VirtualAlloc(nullptr,bytes,MEM_RESERVE,PAGE_READWRITE);
    if (ptr == nullptr) throw std::bad_alloc();
    return ptr;
  }

  void os_commit (void* ptr, size_t bytes) {
    VirtualAlloc(ptr,bytes,MEM_COMMIT,PAGE_READWRITE);
  }

  size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld)
  {
    size_t pageSize = 4096;
    bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);
    assert(bytesNew <= bytesOld);
    if (bytesNew < bytesOld)
      VirtualFree((char*)ptr+bytesNew,bytesOld-bytesNew,MEM_DECOMMIT);
    return bytesNew;
  }

  void os_free(void* ptr, size_t bytes) {
    if (bytes == 0) return;
    VirtualFree(ptr,0,MEM_RELEASE);
  }
}
#endif

////////////////////////////////////////////////////////////////////////////////
/// Unix Platform
////////////////////////////////////////////////////////////////////////////////

#if defined(__UNIX__)

#include <sys/mman.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

/* hint for transparent huge pages (THP) */
#if defined(__MACOSX__)
#define USE_MADVISE 0
#else
#define USE_MADVISE 1
#endif

#define UPGRADE_TO_2M_PAGE_LIMIT (256*1024)
#define PAGE_SIZE_2M (2*1024*1024)
#define PAGE_SIZE_4K (4*1024)

namespace embree
{

  __forceinline bool isHugePageCandidate(const size_t bytes)
  {
#if defined(__MIC__)
    return true;
#endif

    /* try to use huge pages for large allocations */
    if (bytes >= PAGE_SIZE_2M)
    {
      /* multiple of page size */
      if ((bytes % PAGE_SIZE_2M) == 0)
        return true;
      else if (bytes >= 64 * PAGE_SIZE_2M) /* will only introduce a 3% overhead */
        return true;
    }
    return false;
  }

// ============================================
// ============================================
// ============================================

  static bool tryDirectHugePageAllocation = true;

#if USE_MADVISE
  void os_madvise(void *ptr, size_t bytes)
  {
#ifdef MADV_HUGEPAGE
    int res = madvise(ptr,bytes,MADV_HUGEPAGE);
#if defined(DEBUG)
    if (res) perror("madvise failed: ");
#endif
#endif
  }
#endif

  void* os_malloc(size_t bytes, const int additional_flags)
  {
    int flags = MAP_PRIVATE | MAP_ANON | additional_flags;

    if (isHugePageCandidate(bytes))
    {
#if defined(__MIC__)
      flags |= MAP_POPULATE;
#endif
      bytes = (bytes+PAGE_SIZE_2M-1)&ssize_t(-PAGE_SIZE_2M);

#if !defined(__MACOSX__)
      /* try direct huge page allocation first */
      if (tryDirectHugePageAllocation)
      {
        void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, flags | MAP_HUGETLB, -1, 0);

        if (ptr == nullptr || ptr == MAP_FAILED)
        {
          /* direct huge page allocation failed, disable it for the future */
          tryDirectHugePageAllocation = false;
        }
        else
          return ptr;
      }
#endif
    }
    else
      bytes = (bytes+PAGE_SIZE_4K-1)&ssize_t(-PAGE_SIZE_4K);

    /* standard mmap call */
    void* ptr = (char*) mmap(0, bytes, PROT_READ | PROT_WRITE, flags, -1, 0);
    assert( ptr != MAP_FAILED );
    if (ptr == nullptr || ptr == MAP_FAILED) throw std::bad_alloc();

#if USE_MADVISE
    /* advise huge page hint for THP */
    os_madvise(ptr,bytes);
#endif

    return ptr;
  }

  void* os_reserve(size_t bytes)
  {
    int flags = MAP_PRIVATE | MAP_ANON | MAP_NORESERVE;

    if (isHugePageCandidate(bytes))
    {
#if defined(__MIC__)
      flags |= MAP_POPULATE;
#endif
      bytes = (bytes+PAGE_SIZE_2M-1)&ssize_t(-PAGE_SIZE_2M);

#if !defined(__MACOSX__)
      /* try direct huge page allocation first */
      if (tryDirectHugePageAllocation)
      {
        void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, flags | MAP_HUGETLB, -1, 0);

        if (ptr == nullptr || ptr == MAP_FAILED)
        {
          /* direct huge page allocation failed, disable it for the future */
          tryDirectHugePageAllocation = false;
        }
        else
          return ptr;
      }
#endif
    }
    else
      bytes = (bytes+PAGE_SIZE_4K-1)&ssize_t(-PAGE_SIZE_4K);

    /* standard mmap call */
    char* ptr = (char*) mmap(0, bytes, PROT_READ | PROT_WRITE, flags, -1, 0);
    assert( ptr != MAP_FAILED );
    if (ptr == nullptr || ptr == MAP_FAILED) throw std::bad_alloc();

#if USE_MADVISE
    /* advise huge page hint for THP */
    os_madvise(ptr,bytes);
#endif

    return ptr;
  }

  void os_commit (void* ptr, size_t bytes) {
  }

  size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld)
  {
    size_t pageSize = PAGE_SIZE_4K;
    if (isHugePageCandidate(bytesOld))
      pageSize = PAGE_SIZE_2M;

    bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);

    assert(bytesNew <= bytesOld);
    if (bytesNew >= bytesOld)
      return bytesOld;

    if (munmap((char*)ptr+bytesNew,bytesOld-bytesNew) == -1)
      throw std::bad_alloc();

    return bytesNew;
  }

  void os_free(void* ptr, size_t bytes)
  {
    if (bytes == 0)
      return;

    size_t pageSize = PAGE_SIZE_4K;
    if (isHugePageCandidate(bytes))
      pageSize = PAGE_SIZE_2M;

    bytes = (bytes+pageSize-1)&ssize_t(-pageSize);
    if (munmap(ptr,bytes) == -1)
      throw std::bad_alloc();
  }
}

#endif

////////////////////////////////////////////////////////////////////////////////
/// All Platforms
////////////////////////////////////////////////////////////////////////////////

namespace embree
{
  void* alignedMalloc(size_t size, size_t align)
  {
    assert((align & (align-1)) == 0);
//#if defined(TASKING_TBB) // FIXME: have to disable this for now as the TBB allocator itself seems to access some uninitialized value when using valgrind
//    return scalable_aligned_malloc(size,align);
//#else

// #if USE_MADVISE
//     if (size >= 16*PAGE_SIZE_2M)
//     {
//       align = PAGE_SIZE_2M;
//       void *ptr = _mm_malloc(size,align);
//       os_madvise(ptr,size);
//       return ptr;
//      }
// #endif

    return _mm_malloc(size,align);
//#endif
  }

  void alignedFree(void* ptr)
  {
//#if defined(TASKING_TBB)
//    scalable_aligned_free(ptr);
//#else
    _mm_free(ptr);
//#endif
  }
}
<commit_msg>os_reserve calls now os_malloc under Linux/MacOSX, there was an issue when using the MAP_NORESERVE flag with huge pages, some huge pages got allocated that could not get accessed<commit_after>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// 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 "config.h"
#include "alloc.h"
#include "intrinsics.h"
#if defined(TASKING_TBB)
#  define TBB_IMPLEMENT_CPP0X 0
#  define __TBB_NO_IMPLICIT_LINKAGE 1
#  define __TBBMALLOC_NO_IMPLICIT_LINKAGE 1
#  include "tbb/scalable_allocator.h"
#endif

////////////////////////////////////////////////////////////////////////////////
/// Windows Platform
////////////////////////////////////////////////////////////////////////////////

#ifdef _WIN32

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <malloc.h>

namespace embree
{
  void* os_malloc(size_t bytes, const int additional_flags)
  {
    int flags = MEM_COMMIT|MEM_RESERVE|additional_flags;
    char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
    if (ptr == nullptr) throw std::bad_alloc();
    return ptr;
  }

  void* os_reserve(size_t bytes)
  {
    char* ptr = (char*) VirtualAlloc(nullptr,bytes,MEM_RESERVE,PAGE_READWRITE);
    if (ptr == nullptr) throw std::bad_alloc();
    return ptr;
  }

  void os_commit (void* ptr, size_t bytes) {
    VirtualAlloc(ptr,bytes,MEM_COMMIT,PAGE_READWRITE);
  }

  size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld)
  {
    size_t pageSize = 4096;
    bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);
    assert(bytesNew <= bytesOld);
    if (bytesNew < bytesOld)
      VirtualFree((char*)ptr+bytesNew,bytesOld-bytesNew,MEM_DECOMMIT);
    return bytesNew;
  }

  void os_free(void* ptr, size_t bytes) {
    if (bytes == 0) return;
    VirtualFree(ptr,0,MEM_RELEASE);
  }
}
#endif

////////////////////////////////////////////////////////////////////////////////
/// Unix Platform
////////////////////////////////////////////////////////////////////////////////

#if defined(__UNIX__)

#include <sys/mman.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

/* hint for transparent huge pages (THP) */
#if defined(__MACOSX__)
#define USE_MADVISE 0
#else
#define USE_MADVISE 1
#endif

#define UPGRADE_TO_2M_PAGE_LIMIT (256*1024)
#define PAGE_SIZE_2M (2*1024*1024)
#define PAGE_SIZE_4K (4*1024)

namespace embree
{

  __forceinline bool isHugePageCandidate(const size_t bytes)
  {
#if defined(__MIC__)
    return true;
#endif

    /* try to use huge pages for large allocations */
    if (bytes >= PAGE_SIZE_2M)
    {
      /* multiple of page size */
      if ((bytes % PAGE_SIZE_2M) == 0)
        return true;
      else if (bytes >= 64 * PAGE_SIZE_2M) /* will only introduce a 3% overhead */
        return true;
    }
    return false;
  }

// ============================================
// ============================================
// ============================================

  static bool tryDirectHugePageAllocation = true;

#if USE_MADVISE
  void os_madvise(void *ptr, size_t bytes)
  {
#ifdef MADV_HUGEPAGE
    int res = madvise(ptr,bytes,MADV_HUGEPAGE);
#if defined(DEBUG)
    if (res) perror("madvise failed: ");
#endif
#endif
  }
#endif

  void* os_malloc(size_t bytes, const int additional_flags)
  {
    int flags = MAP_PRIVATE | MAP_ANON | additional_flags;

    if (isHugePageCandidate(bytes))
    {
#if defined(__MIC__)
      flags |= MAP_POPULATE;
#endif
      bytes = (bytes+PAGE_SIZE_2M-1)&ssize_t(-PAGE_SIZE_2M);

#if !defined(__MACOSX__)
      /* try direct huge page allocation first */
      if (tryDirectHugePageAllocation)
      {
        void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, flags | MAP_HUGETLB, -1, 0);

        if (ptr == nullptr || ptr == MAP_FAILED)
        {
          /* direct huge page allocation failed, disable it for the future */
          tryDirectHugePageAllocation = false;
        }
        else
          return ptr;
      }
#endif
    }
    else
      bytes = (bytes+PAGE_SIZE_4K-1)&ssize_t(-PAGE_SIZE_4K);

    /* standard mmap call */
    void* ptr = (char*) mmap(0, bytes, PROT_READ | PROT_WRITE, flags, -1, 0);
    assert( ptr != MAP_FAILED );
    if (ptr == nullptr || ptr == MAP_FAILED) throw std::bad_alloc();

#if USE_MADVISE
    /* advise huge page hint for THP */
    os_madvise(ptr,bytes);
#endif

    return ptr;
  }

  void* os_reserve(size_t bytes)
  {
    /* linux always allocates pages on demand, thus just call allocate */
    return os_malloc(bytes);
  }

  void os_commit (void* ptr, size_t bytes) {
  }

  size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld)
  {
    size_t pageSize = PAGE_SIZE_4K;
    if (isHugePageCandidate(bytesOld))
      pageSize = PAGE_SIZE_2M;

    bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);

    assert(bytesNew <= bytesOld);
    if (bytesNew >= bytesOld)
      return bytesOld;

    if (munmap((char*)ptr+bytesNew,bytesOld-bytesNew) == -1)
      throw std::bad_alloc();

    return bytesNew;
  }

  void os_free(void* ptr, size_t bytes)
  {
    if (bytes == 0)
      return;

    size_t pageSize = PAGE_SIZE_4K;
    if (isHugePageCandidate(bytes))
      pageSize = PAGE_SIZE_2M;

    bytes = (bytes+pageSize-1)&ssize_t(-pageSize);
    if (munmap(ptr,bytes) == -1)
      throw std::bad_alloc();
  }
}

#endif

////////////////////////////////////////////////////////////////////////////////
/// All Platforms
////////////////////////////////////////////////////////////////////////////////

namespace embree
{
  void* alignedMalloc(size_t size, size_t align)
  {
    assert((align & (align-1)) == 0);
//#if defined(TASKING_TBB) // FIXME: have to disable this for now as the TBB allocator itself seems to access some uninitialized value when using valgrind
//    return scalable_aligned_malloc(size,align);
//#else

// #if USE_MADVISE
//     if (size >= 16*PAGE_SIZE_2M)
//     {
//       align = PAGE_SIZE_2M;
//       void *ptr = _mm_malloc(size,align);
//       os_madvise(ptr,size);
//       return ptr;
//      }
// #endif

    return _mm_malloc(size,align);
//#endif
  }

  void alignedFree(void* ptr)
  {
//#if defined(TASKING_TBB)
//    scalable_aligned_free(ptr);
//#else
    _mm_free(ptr);
//#endif
  }
}
<|endoftext|>


<commit_before>#include "kontsevich_graph.hpp"
#include "util/sort_pairs.hpp"
#include "util/cartesian_product.hpp"
#include "util/factorial.hpp"
#include <algorithm>
#include <tuple>
#include <stack>

KontsevichGraph::KontsevichGraph(size_t internal, size_t external, std::vector<KontsevichGraph::VertexPair> targets, int sign, bool normalized)
: d_internal(internal), d_external(external), d_targets(targets), d_sign(sign)
{
    if (!normalized)
        normalize();
}

inline size_t apply_permutation(size_t internal, size_t external, std::vector<KontsevichGraph::VertexPair>& targets, std::vector<KontsevichGraph::Vertex>& permutation)
{
    // Relabel elements of target pairs
    for (size_t i = 0; i != internal; ++i) {
        targets[i].first = permutation[targets[i].first];
        targets[i].second = permutation[targets[i].second];
    }
    // Apply permutation to list of target pairs
    std::vector<KontsevichGraph::VertexPair> permuted(targets.size());
    for (size_t i = 0; i != internal; ++i)
    {
        permuted[permutation[external + i] - external] = targets[i];
    }
    targets.swap(permuted);
    // Sort elements of target pairs
    return sort_pairs(targets.begin(), targets.end());
}

void KontsevichGraph::normalize()
{
    std::vector<KontsevichGraph::VertexPair> global_minimum = d_targets;
    size_t exchanges = sort_pairs(global_minimum.begin(), global_minimum.end());
    std::vector<KontsevichGraph::Vertex> vertices(d_external + d_internal);
    std::iota(vertices.begin(), vertices.end(), 0);
    while (std::next_permutation(vertices.begin() + d_external, vertices.end()))
    {
        std::vector<KontsevichGraph::VertexPair> local_minimum = d_targets;
        size_t local_exchanges = apply_permutation(d_internal, d_external, local_minimum, vertices);
        if (local_minimum < global_minimum) {
            global_minimum = local_minimum;
            exchanges = local_exchanges;
        }
    }
    d_targets = global_minimum;
    d_sign *= (exchanges % 2 == 0) ? 1 : -1;
}

std::vector<KontsevichGraph::Vertex> KontsevichGraph::internal_vertices() const
{
    std::vector<KontsevichGraph::Vertex> vertices(d_internal);
    std::iota(vertices.begin(), vertices.end(), d_external);
    return vertices;
}

std::vector<KontsevichGraph::VertexPair> KontsevichGraph::targets() const
{
    return d_targets;
}

KontsevichGraph::VertexPair KontsevichGraph::targets(KontsevichGraph::Vertex internal_vertex) const
{
    return d_targets[internal_vertex - d_external];
}

int KontsevichGraph::sign() const
{
    return d_sign;
}

int KontsevichGraph::sign(int new_sign)
{
    return d_sign = new_sign;
}

std::pair< size_t, std::vector<KontsevichGraph::VertexPair> > KontsevichGraph::abs() const
{
    return { d_external, d_targets };
}

size_t KontsevichGraph::internal() const
{
    return d_internal;
}

size_t KontsevichGraph::external() const
{
    return d_external;
}

size_t KontsevichGraph::vertices() const
{
    return d_internal + d_external;
}

size_t KontsevichGraph::multiplicity() const
{
    size_t multiplicity = 1;
    std::vector<KontsevichGraph::Vertex> vertices(d_external + d_internal);
    std::iota(vertices.begin(), vertices.end(), 0);
    while (std::next_permutation(vertices.begin() + d_external, vertices.end()))
    {
        std::vector<KontsevichGraph::VertexPair> permuted = d_targets;
        apply_permutation(d_internal, d_external, permuted, vertices);
        if (permuted == d_targets)
            ++multiplicity;
    }
    multiplicity = factorial(d_internal) / multiplicity;
    multiplicity *= pow(2, d_internal);
    return multiplicity;
}

bool KontsevichGraph::is_zero() const
{
    std::vector<KontsevichGraph::Vertex> vertices(d_external + d_internal);
    std::iota(vertices.begin(), vertices.end(), 0);
    while (std::next_permutation(vertices.begin() + d_external, vertices.end()))
    {
        std::vector<KontsevichGraph::VertexPair> permuted = d_targets;
        size_t exchanges = apply_permutation(d_internal, d_external, permuted, vertices);
        if (permuted == d_targets && exchanges % 2 == 1)
            return true;
    }
    return false;
}

std::vector<size_t> KontsevichGraph::in_degrees() const
{
    std::vector<size_t> indegrees(d_external);
    for (auto& target_pair : d_targets)
    {
        if ((size_t)target_pair.first < d_external)
            indegrees[target_pair.first]++;
        if ((size_t)target_pair.second < d_external)
            indegrees[target_pair.second]++;
    }
    return indegrees;
}

std::vector<KontsevichGraph::Vertex> KontsevichGraph::neighbors_in(KontsevichGraph::Vertex vertex) const
{
    std::vector<KontsevichGraph::Vertex> neighbors;
    for (size_t idx = 0; idx < d_internal; ++idx)
    {
        if (d_targets[idx].first == vertex || d_targets[idx].second == vertex)
            neighbors.push_back(d_external + idx);
    }
    return neighbors;
}

bool KontsevichGraph::operator<(const KontsevichGraph& rhs) const
{
    return std::tie(this->d_external, this->d_internal, this->d_targets, this->d_sign) < std::tie(rhs.d_external, rhs.d_internal, rhs.d_targets, rhs.d_sign);
}

KontsevichGraph& KontsevichGraph::operator*=(const KontsevichGraph& rhs)
{
    // TODO: maybe check if d_external == rhs.d_external
    d_targets.reserve(d_targets.size() + rhs.d_targets.size());
    // Concatenate lists of targets
    d_targets.insert(d_targets.end(), rhs.d_targets.begin(), rhs.d_targets.end());
    // Add offsets to RHS' internal targets
    for (size_t i = 0; i != rhs.d_internal; ++i)
    {
        if ((size_t)d_targets[d_internal + i].first >= d_external)
            d_targets[d_internal + i].first += d_internal;
        if ((size_t)d_targets[d_internal + i].second >= d_external)
            d_targets[d_internal + i].second += d_internal;
    }
    d_internal += rhs.d_internal;
    d_sign *= rhs.d_sign;
    normalize();
    return *this;
}

KontsevichGraph operator*(KontsevichGraph lhs, const KontsevichGraph& rhs)
{
    lhs *= rhs;
    return lhs;
}

bool KontsevichGraph::is_prime() const
{
    size_t vertex_count = 0;
    std::set<KontsevichGraph::Vertex> seen;
    // Choose a vertex connected to the ground, if possible
    KontsevichGraph::Vertex start = 0;
    for (size_t i = 0; i != d_internal; ++i)
    {
        if ((size_t)d_targets[i].first < d_external || (size_t)d_targets[i].second < d_external)
        {
            start = d_external + i;
            break;
        }
    }
    // Otherwise, choose the first internal vertex
    if (start == 0)
        start = d_external;
    // Breadth-first search
    std::stack< std::pair<KontsevichGraph::Vertex, int> > vertex_stack;
    vertex_stack.push({ start, 0 });
    while (vertex_stack.size() > 0)
    {
        std::pair<KontsevichGraph::Vertex, int> vertex = vertex_stack.top();
        vertex_stack.pop();
        if (seen.find(vertex.first) == seen.end())
        {
            ++vertex_count;
            seen.insert(vertex.first);
            // Outgoing neighbors
            KontsevichGraph::VertexPair target_pair = d_targets[vertex.first - d_external];
            if ((size_t)target_pair.first >= d_external)
                if (seen.find(target_pair.first) == seen.end())
                    vertex_stack.push({ target_pair.first, vertex.second + 1});
            if ((size_t)target_pair.second >= d_external)
                if (seen.find(target_pair.second) == seen.end())
                    vertex_stack.push({ target_pair.second, vertex.second + 1});
            // Incoming neighbors
            for (auto neighbor : this->neighbors_in(vertex.first))
                if (seen.find(neighbor) == seen.end())
                    vertex_stack.push({ neighbor, vertex.second + 1});
        }
    }
    return vertex_count == d_internal;
}

KontsevichGraph KontsevichGraph::mirror_image() const
{
    std::vector<KontsevichGraph::VertexPair> targets = d_targets;
    // Reverse the ground vertices
    for (auto& target_pair : targets)
    {
        if ((size_t)target_pair.first < d_external)
            target_pair.first = d_external - 1 - target_pair.first;
        if ((size_t)target_pair.second < d_external)
            target_pair.second = d_external - 1 - target_pair.second;
    }
    return KontsevichGraph(d_internal, d_external, targets, d_sign);
}

bool KontsevichGraph::positive_differential_order() const
{
    std::set<KontsevichGraph::Vertex> seen;
    for (auto& target_pair : d_targets)
    {
        if ((size_t)target_pair.first < d_external)
            seen.insert(target_pair.first);
        if ((size_t)target_pair.second < d_external)
            seen.insert(target_pair.second);
    }
    return seen.size() == d_external;
}

std::set<KontsevichGraph> KontsevichGraph::graphs(size_t internal, size_t external, bool modulo_signs, bool modulo_mirror_images, std::function<bool(KontsevichGraph)> const& filter)
{
    std::set<KontsevichGraph> result;
    std::vector<size_t> ends(2*internal);
    for (size_t i = 0; i != 2*internal; ++i)
    {
        ends[i] = internal + external;
    }
    CartesianProduct graph_encodings(ends);
    std::vector<KontsevichGraph::VertexPair> targets(internal);
    for (auto graph_encoding = graph_encodings.begin(); graph_encoding != graph_encodings.end(); ++graph_encoding)
    {
        bool skip = false;
        for (size_t i = 0; i != internal; ++i)
        {
            KontsevichGraph::VertexPair target_pair = { (*graph_encoding)[2*i], (*graph_encoding)[2*i + 1] };
            // Avoid double edges and tadpoles:
            if (target_pair.first == target_pair.second || (size_t)target_pair.first == external + i || (size_t)target_pair.second == external + i)
            {
                skip = true;
                break;
            }
            targets[i] = target_pair;
        }
        if (!skip)
        {
            KontsevichGraph graph(internal, external, targets);
            if (filter && !filter(graph))
                continue;
            if (modulo_mirror_images)
            {
                KontsevichGraph mirror = graph.mirror_image();
                if (mirror < graph)
                    graph = mirror;
            }
            if (modulo_signs)
                graph.sign(1);
            result.insert(graph);
        }
    }
    return result;
}

bool operator==(const KontsevichGraph &lhs, const KontsevichGraph &rhs)
{
    return (lhs.d_external == rhs.d_external) && (lhs.d_sign == rhs.d_sign) && (lhs.d_targets == rhs.d_targets);
}

bool operator!=(const KontsevichGraph &lhs, const KontsevichGraph &rhs)
{
    return !(lhs == rhs);
}

std::ostream& operator<<(std::ostream &os, const KontsevichGraph& g)
{
    return os << "Kontsevich graph with " << g.d_internal << " vertices on " << g.d_external << " ground vertices";
}

std::istream& operator>>(std::istream& is, KontsevichGraph& g)
{
    is >> g.d_external;
    is >> g.d_internal;
    is >> g.d_sign;
    g.d_targets.clear();
    std::string line;
    std::pair<size_t, size_t> target_pair;
    size_t pair_count = 0;
    while (pair_count++ < g.d_internal && is >> target_pair.first >> target_pair.second)
        g.d_targets.push_back(target_pair);
    g.d_internal = g.d_targets.size();
    g.normalize();
    return is;
}

std::ostream& operator<<(std::ostream &os, const KontsevichGraph::Vertex v)
{
    return os << (size_t)v;
}
<commit_msg>Fix KontsevichGraph::multiplicity() and add explanatory comments.<commit_after>#include "kontsevich_graph.hpp"
#include "util/sort_pairs.hpp"
#include "util/cartesian_product.hpp"
#include "util/factorial.hpp"
#include <algorithm>
#include <tuple>
#include <stack>

KontsevichGraph::KontsevichGraph(size_t internal, size_t external, std::vector<KontsevichGraph::VertexPair> targets, int sign, bool normalized)
: d_internal(internal), d_external(external), d_targets(targets), d_sign(sign)
{
    if (!normalized)
        normalize();
}

inline size_t apply_permutation(size_t internal, size_t external, std::vector<KontsevichGraph::VertexPair>& targets, std::vector<KontsevichGraph::Vertex>& permutation)
{
    // Relabel elements of target pairs
    for (size_t i = 0; i != internal; ++i) {
        targets[i].first = permutation[targets[i].first];
        targets[i].second = permutation[targets[i].second];
    }
    // Apply permutation to list of target pairs
    std::vector<KontsevichGraph::VertexPair> permuted(targets.size());
    for (size_t i = 0; i != internal; ++i)
    {
        permuted[permutation[external + i] - external] = targets[i];
    }
    targets.swap(permuted);
    // Sort elements of target pairs
    return sort_pairs(targets.begin(), targets.end());
}

void KontsevichGraph::normalize()
{
    std::vector<KontsevichGraph::VertexPair> global_minimum = d_targets;
    size_t exchanges = sort_pairs(global_minimum.begin(), global_minimum.end());
    std::vector<KontsevichGraph::Vertex> vertices(d_external + d_internal);
    std::iota(vertices.begin(), vertices.end(), 0);
    while (std::next_permutation(vertices.begin() + d_external, vertices.end()))
    {
        std::vector<KontsevichGraph::VertexPair> local_minimum = d_targets;
        size_t local_exchanges = apply_permutation(d_internal, d_external, local_minimum, vertices);
        if (local_minimum < global_minimum) {
            global_minimum = local_minimum;
            exchanges = local_exchanges;
        }
    }
    d_targets = global_minimum;
    d_sign *= (exchanges % 2 == 0) ? 1 : -1;
}

std::vector<KontsevichGraph::Vertex> KontsevichGraph::internal_vertices() const
{
    std::vector<KontsevichGraph::Vertex> vertices(d_internal);
    std::iota(vertices.begin(), vertices.end(), d_external);
    return vertices;
}

std::vector<KontsevichGraph::VertexPair> KontsevichGraph::targets() const
{
    return d_targets;
}

KontsevichGraph::VertexPair KontsevichGraph::targets(KontsevichGraph::Vertex internal_vertex) const
{
    return d_targets[internal_vertex - d_external];
}

int KontsevichGraph::sign() const
{
    return d_sign;
}

int KontsevichGraph::sign(int new_sign)
{
    return d_sign = new_sign;
}

std::pair< size_t, std::vector<KontsevichGraph::VertexPair> > KontsevichGraph::abs() const
{
    return { d_external, d_targets };
}

size_t KontsevichGraph::internal() const
{
    return d_internal;
}

size_t KontsevichGraph::external() const
{
    return d_external;
}

size_t KontsevichGraph::vertices() const
{
    return d_internal + d_external;
}

size_t KontsevichGraph::multiplicity() const
{
    std::set< std::vector<KontsevichGraph::VertexPair> > seen;
    std::vector<KontsevichGraph::Vertex> vertices(d_external + d_internal);
    std::iota(vertices.begin(), vertices.end(), 0);
    do
    {
        std::vector<KontsevichGraph::VertexPair> permuted = d_targets;
        apply_permutation(d_internal, d_external, permuted, vertices); // apply internal vertex permutation
        sort_pairs(permuted.begin(), permuted.end()); // ignore edge labeling
        if (seen.find(permuted) == seen.end())
            seen.insert(permuted);
    }
    while (std::next_permutation(vertices.begin() + d_external, vertices.end()));
    return pow(2, d_internal) * seen.size();
}

bool KontsevichGraph::is_zero() const
{
    std::vector<KontsevichGraph::Vertex> vertices(d_external + d_internal);
    std::iota(vertices.begin(), vertices.end(), 0);
    while (std::next_permutation(vertices.begin() + d_external, vertices.end()))
    {
        std::vector<KontsevichGraph::VertexPair> permuted = d_targets;
        size_t exchanges = apply_permutation(d_internal, d_external, permuted, vertices);
        if (permuted == d_targets && exchanges % 2 == 1)
            return true;
    }
    return false;
}

std::vector<size_t> KontsevichGraph::in_degrees() const
{
    std::vector<size_t> indegrees(d_external);
    for (auto& target_pair : d_targets)
    {
        if ((size_t)target_pair.first < d_external)
            indegrees[target_pair.first]++;
        if ((size_t)target_pair.second < d_external)
            indegrees[target_pair.second]++;
    }
    return indegrees;
}

std::vector<KontsevichGraph::Vertex> KontsevichGraph::neighbors_in(KontsevichGraph::Vertex vertex) const
{
    std::vector<KontsevichGraph::Vertex> neighbors;
    for (size_t idx = 0; idx < d_internal; ++idx)
    {
        if (d_targets[idx].first == vertex || d_targets[idx].second == vertex)
            neighbors.push_back(d_external + idx);
    }
    return neighbors;
}

bool KontsevichGraph::operator<(const KontsevichGraph& rhs) const
{
    return std::tie(this->d_external, this->d_internal, this->d_targets, this->d_sign) < std::tie(rhs.d_external, rhs.d_internal, rhs.d_targets, rhs.d_sign);
}

KontsevichGraph& KontsevichGraph::operator*=(const KontsevichGraph& rhs)
{
    // TODO: maybe check if d_external == rhs.d_external
    d_targets.reserve(d_targets.size() + rhs.d_targets.size());
    // Concatenate lists of targets
    d_targets.insert(d_targets.end(), rhs.d_targets.begin(), rhs.d_targets.end());
    // Add offsets to RHS' internal targets
    for (size_t i = 0; i != rhs.d_internal; ++i)
    {
        if ((size_t)d_targets[d_internal + i].first >= d_external)
            d_targets[d_internal + i].first += d_internal;
        if ((size_t)d_targets[d_internal + i].second >= d_external)
            d_targets[d_internal + i].second += d_internal;
    }
    d_internal += rhs.d_internal;
    d_sign *= rhs.d_sign;
    normalize();
    return *this;
}

KontsevichGraph operator*(KontsevichGraph lhs, const KontsevichGraph& rhs)
{
    lhs *= rhs;
    return lhs;
}

bool KontsevichGraph::is_prime() const
{
    size_t vertex_count = 0;
    std::set<KontsevichGraph::Vertex> seen;
    // Choose a vertex connected to the ground, if possible
    KontsevichGraph::Vertex start = 0;
    for (size_t i = 0; i != d_internal; ++i)
    {
        if ((size_t)d_targets[i].first < d_external || (size_t)d_targets[i].second < d_external)
        {
            start = d_external + i;
            break;
        }
    }
    // Otherwise, choose the first internal vertex
    if (start == 0)
        start = d_external;
    // Breadth-first search
    std::stack< std::pair<KontsevichGraph::Vertex, int> > vertex_stack;
    vertex_stack.push({ start, 0 });
    while (vertex_stack.size() > 0)
    {
        std::pair<KontsevichGraph::Vertex, int> vertex = vertex_stack.top();
        vertex_stack.pop();
        if (seen.find(vertex.first) == seen.end())
        {
            ++vertex_count;
            seen.insert(vertex.first);
            // Outgoing neighbors
            KontsevichGraph::VertexPair target_pair = d_targets[vertex.first - d_external];
            if ((size_t)target_pair.first >= d_external)
                if (seen.find(target_pair.first) == seen.end())
                    vertex_stack.push({ target_pair.first, vertex.second + 1});
            if ((size_t)target_pair.second >= d_external)
                if (seen.find(target_pair.second) == seen.end())
                    vertex_stack.push({ target_pair.second, vertex.second + 1});
            // Incoming neighbors
            for (auto neighbor : this->neighbors_in(vertex.first))
                if (seen.find(neighbor) == seen.end())
                    vertex_stack.push({ neighbor, vertex.second + 1});
        }
    }
    return vertex_count == d_internal;
}

KontsevichGraph KontsevichGraph::mirror_image() const
{
    std::vector<KontsevichGraph::VertexPair> targets = d_targets;
    // Reverse the ground vertices
    for (auto& target_pair : targets)
    {
        if ((size_t)target_pair.first < d_external)
            target_pair.first = d_external - 1 - target_pair.first;
        if ((size_t)target_pair.second < d_external)
            target_pair.second = d_external - 1 - target_pair.second;
    }
    return KontsevichGraph(d_internal, d_external, targets, d_sign);
}

bool KontsevichGraph::positive_differential_order() const
{
    std::set<KontsevichGraph::Vertex> seen;
    for (auto& target_pair : d_targets)
    {
        if ((size_t)target_pair.first < d_external)
            seen.insert(target_pair.first);
        if ((size_t)target_pair.second < d_external)
            seen.insert(target_pair.second);
    }
    return seen.size() == d_external;
}

std::set<KontsevichGraph> KontsevichGraph::graphs(size_t internal, size_t external, bool modulo_signs, bool modulo_mirror_images, std::function<bool(KontsevichGraph)> const& filter)
{
    std::set<KontsevichGraph> result;
    std::vector<size_t> ends(2*internal);
    for (size_t i = 0; i != 2*internal; ++i)
    {
        ends[i] = internal + external;
    }
    CartesianProduct graph_encodings(ends);
    std::vector<KontsevichGraph::VertexPair> targets(internal);
    for (auto graph_encoding = graph_encodings.begin(); graph_encoding != graph_encodings.end(); ++graph_encoding)
    {
        bool skip = false;
        for (size_t i = 0; i != internal; ++i)
        {
            KontsevichGraph::VertexPair target_pair = { (*graph_encoding)[2*i], (*graph_encoding)[2*i + 1] };
            // Avoid double edges and tadpoles:
            if (target_pair.first == target_pair.second || (size_t)target_pair.first == external + i || (size_t)target_pair.second == external + i)
            {
                skip = true;
                break;
            }
            targets[i] = target_pair;
        }
        if (!skip)
        {
            KontsevichGraph graph(internal, external, targets);
            if (filter && !filter(graph))
                continue;
            if (modulo_mirror_images)
            {
                KontsevichGraph mirror = graph.mirror_image();
                if (mirror < graph)
                    graph = mirror;
            }
            if (modulo_signs)
                graph.sign(1);
            result.insert(graph);
        }
    }
    return result;
}

bool operator==(const KontsevichGraph &lhs, const KontsevichGraph &rhs)
{
    return (lhs.d_external == rhs.d_external) && (lhs.d_sign == rhs.d_sign) && (lhs.d_targets == rhs.d_targets);
}

bool operator!=(const KontsevichGraph &lhs, const KontsevichGraph &rhs)
{
    return !(lhs == rhs);
}

std::ostream& operator<<(std::ostream &os, const KontsevichGraph& g)
{
    return os << "Kontsevich graph with " << g.d_internal << " vertices on " << g.d_external << " ground vertices";
}

std::istream& operator>>(std::istream& is, KontsevichGraph& g)
{
    is >> g.d_external;
    is >> g.d_internal;
    is >> g.d_sign;
    g.d_targets.clear();
    std::string line;
    std::pair<size_t, size_t> target_pair;
    size_t pair_count = 0;
    while (pair_count++ < g.d_internal && is >> target_pair.first >> target_pair.second)
        g.d_targets.push_back(target_pair);
    g.d_internal = g.d_targets.size();
    g.normalize();
    return is;
}

std::ostream& operator<<(std::ostream &os, const KontsevichGraph::Vertex v)
{
    return os << (size_t)v;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, The Regents of the University of California (Regents).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *    3. Neither the name of the copyright holder nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Please contact the author(s) of this library if you have any questions.
 * Authors: Erik Nelson            ( eanelson@eecs.berkeley.edu )
 *          David Fridovich-Keil   ( dfk@eecs.berkeley.edu )
 */

#include <geometry/rotation.h>
#include <math/random_generator.h>
#include <sfm/bundle_adjuster.h>
#include <sfm/bundle_adjustment_options.h>
#include <sfm/view.h>
#include <slam/landmark.h>
#include <util/types.h>

#include <Eigen/Core>
#include <gtest/gtest.h>

namespace bsfm {

namespace {
void MakePoints(int num_points, math::RandomGenerator& rng, Point3DList& points) {
  points.clear();

  // Randomly generate cameras will be looking upwards.
  for (int ii = 0; ii < num_points; ++ii) {
    const double x = rng.DoubleUniform(-10.0, 10.0);
    const double y = rng.DoubleUniform(-10.0, 10.0);
    const double z = rng.DoubleUniform(20.0, 30.0);

    points.emplace_back(x, y, z);
  }
}

// Make a camera with a random position that observes all points in 'points'.
Camera RandomCamera(math::RandomGenerator& rng, const Point3DList& points) {

  Camera camera;
  CameraIntrinsics intrinsics;
  intrinsics.SetImageLeft(0);
  intrinsics.SetImageTop(0);
  intrinsics.SetImageWidth(1920);
  intrinsics.SetImageHeight(1080);
  intrinsics.SetVerticalFOV(D2R(90.0));
  intrinsics.SetFU(intrinsics.f_v());
  intrinsics.SetCU(960);
  intrinsics.SetCV(540);
  camera.SetIntrinsics(intrinsics);

  bool sees_all_points = false;
  while (!sees_all_points) {
    // Make a random translation and rotation.
    CameraExtrinsics extrinsics;
    const double x = rng.DoubleUniform(-2.0, 2.0);
    const double y = rng.DoubleUniform(-2.0, 2.0);
    const double z = rng.DoubleUniform(-2.0, 2.0);
    extrinsics.Translate(x, y, z);
    Vector3d euler_angles(Vector3d::Random()*D2R(20.0));
    extrinsics.Rotate(EulerAnglesToMatrix(euler_angles));
    camera.SetExtrinsics(extrinsics);

    // Make sure the camera sees all of the points.
    for (const auto& point : points) {
      double u = 0.0, v = 0.0;
      if (!camera.WorldToImage(point.X(), point.Y(), point.Z(), &u, &v)) {
        sees_all_points = false;
        break;
      }
      sees_all_points = true;
    }
  }

  return camera;
}

}  //\namespace
TEST(BundleAdjuster, TestTwoViewsNoNoise) {
  // Create two views with perfect matches that both view the same set of 3D
  // points. Bundle adjustment shouldn't change a thing.

  // Clean up from other tests.
  Landmark::ResetLandmarks();
  View::ResetViews();

  // Make 3D points.
  math::RandomGenerator rng(0);
  Point3DList points;
  MakePoints(100, rng, points);

  Camera camera1 = RandomCamera(rng, points);
  Camera camera2 = RandomCamera(rng, points);

  // Initialize a view for each camera, a landmark for each point, and an
  // observation for each sighting of each landmark in each camera.
  View::Ptr view1 = View::Create(camera1);
  View::Ptr view2 = View::Create(camera2);

  for (const auto& point : points) {
    Descriptor descriptor(Descriptor::Random(32));

    double u = 0.0, v = 0.0;
    EXPECT_TRUE(camera1.WorldToImage(point.X(), point.Y(), point.Z(), &u, &v));
    Feature feature1(u, v);
    Observation::Ptr observation1 =
        Observation::Create(view1, feature1, descriptor);

    EXPECT_TRUE(camera2.WorldToImage(point.X(), point.Y(), point.Z(), &u, &v));
    Feature feature2(u, v);
    Observation::Ptr observation2 =
        Observation::Create(view2, feature2, descriptor);

    Landmark::Ptr landmark = Landmark::Create();
    view1->AddObservation(observation1);
    view2->AddObservation(observation2);
    EXPECT_TRUE(landmark->IncorporateObservation(observation1));
    EXPECT_TRUE(landmark->IncorporateObservation(observation2));
    EXPECT_NEAR(point.X(), landmark->Position().X(), 1e-8);
    EXPECT_NEAR(point.Y(), landmark->Position().Y(), 1e-8);
    EXPECT_NEAR(point.Z(), landmark->Position().Z(), 1e-8);
  }

  view1->UpdateObservedLandmarks();
  view2->UpdateObservedLandmarks();

  // We now have 100 observations in each view, and 100 corresponding landmarks
  // that are triangulated from the observation positions. Bundle adjustment
  // should have 0 error, and should terminate without altering the positions of
  // any landmarks or cameras.
  BundleAdjuster bundle_adjuster;
  BundleAdjustmentOptions options;

  std::vector<ViewIndex> view_indices = { 0, 1 };
  EXPECT_TRUE(bundle_adjuster.Solve(options, view_indices));

  for (size_t ii = 0; ii < points.size(); ++ii) {
    Landmark::Ptr landmark = Landmark::GetLandmark(ii);
    EXPECT_NEAR(points[ii].X(), landmark->Position().X(), 1e-8);
    EXPECT_NEAR(points[ii].Y(), landmark->Position().Y(), 1e-8);
    EXPECT_NEAR(points[ii].Z(), landmark->Position().Z(), 1e-8);
  }

  EXPECT_TRUE(camera1.Rt().isApprox(view1->Camera().Rt()));
  EXPECT_TRUE(camera2.Rt().isApprox(view2->Camera().Rt()));

  // Clean up.
  Landmark::ResetLandmarks();
  View::ResetViews();
}

}  //\namespace bsfm
<commit_msg>Adding a test with 50 points and 50 cameras.<commit_after>/*
 * Copyright (c) 2015, The Regents of the University of California (Regents).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *    3. Neither the name of the copyright holder nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Please contact the author(s) of this library if you have any questions.
 * Authors: Erik Nelson            ( eanelson@eecs.berkeley.edu )
 *          David Fridovich-Keil   ( dfk@eecs.berkeley.edu )
 */

#include <geometry/rotation.h>
#include <math/random_generator.h>
#include <sfm/bundle_adjuster.h>
#include <sfm/bundle_adjustment_options.h>
#include <sfm/view.h>
#include <slam/landmark.h>
#include <util/types.h>

#include <Eigen/Core>
#include <gtest/gtest.h>

namespace bsfm {

namespace {
void MakePoints(int num_points, math::RandomGenerator& rng, Point3DList& points) {
  points.clear();

  // Randomly generate cameras will be looking upwards.
  for (int ii = 0; ii < num_points; ++ii) {
    const double x = rng.DoubleUniform(-10.0, 10.0);
    const double y = rng.DoubleUniform(-10.0, 10.0);
    const double z = rng.DoubleUniform(20.0, 30.0);

    points.emplace_back(x, y, z);
  }
}

// Make a camera with a random position that observes all points in 'points'.
Camera RandomCamera(math::RandomGenerator& rng, const Point3DList& points) {

  Camera camera;
  CameraIntrinsics intrinsics;
  intrinsics.SetImageLeft(0);
  intrinsics.SetImageTop(0);
  intrinsics.SetImageWidth(1920);
  intrinsics.SetImageHeight(1080);
  intrinsics.SetVerticalFOV(D2R(90.0));
  intrinsics.SetFU(intrinsics.f_v());
  intrinsics.SetCU(960);
  intrinsics.SetCV(540);
  camera.SetIntrinsics(intrinsics);

  bool sees_all_points = false;
  while (!sees_all_points) {
    // Make a random translation and rotation.
    CameraExtrinsics extrinsics;
    const double x = rng.DoubleUniform(-2.0, 2.0);
    const double y = rng.DoubleUniform(-2.0, 2.0);
    const double z = rng.DoubleUniform(-2.0, 2.0);
    extrinsics.Translate(x, y, z);
    Vector3d euler_angles(Vector3d::Random()*D2R(20.0));
    extrinsics.Rotate(EulerAnglesToMatrix(euler_angles));
    camera.SetExtrinsics(extrinsics);

    // Make sure the camera sees all of the points.
    for (const auto& point : points) {
      double u = 0.0, v = 0.0;
      if (!camera.WorldToImage(point.X(), point.Y(), point.Z(), &u, &v)) {
        sees_all_points = false;
        break;
      }
      sees_all_points = true;
    }
  }

  return camera;
}

}  //\namespace

TEST(BundleAdjuster, TestTwoViewsNoNoise) {
  // Create two views with perfect matches that both view the same set of 3D
  // points. Bundle adjustment shouldn't change a thing.

  // Clean up from other tests.
  Landmark::ResetLandmarks();
  View::ResetViews();

  // Make 3D points.
  math::RandomGenerator rng(0);
  Point3DList points;
  MakePoints(100, rng, points);

  Camera camera1 = RandomCamera(rng, points);
  Camera camera2 = RandomCamera(rng, points);

  // Initialize a view for each camera, a landmark for each point, and an
  // observation for each sighting of each landmark in each camera.
  View::Ptr view1 = View::Create(camera1);
  View::Ptr view2 = View::Create(camera2);

  for (const auto& point : points) {
    Descriptor descriptor(Descriptor::Random(32));

    double u = 0.0, v = 0.0;
    EXPECT_TRUE(camera1.WorldToImage(point.X(), point.Y(), point.Z(), &u, &v));
    Feature feature1(u, v);
    Observation::Ptr observation1 =
        Observation::Create(view1, feature1, descriptor);

    EXPECT_TRUE(camera2.WorldToImage(point.X(), point.Y(), point.Z(), &u, &v));
    Feature feature2(u, v);
    Observation::Ptr observation2 =
        Observation::Create(view2, feature2, descriptor);

    Landmark::Ptr landmark = Landmark::Create();
    view1->AddObservation(observation1);
    view2->AddObservation(observation2);
    EXPECT_TRUE(landmark->IncorporateObservation(observation1));
    EXPECT_TRUE(landmark->IncorporateObservation(observation2));
    EXPECT_NEAR(point.X(), landmark->Position().X(), 1e-8);
    EXPECT_NEAR(point.Y(), landmark->Position().Y(), 1e-8);
    EXPECT_NEAR(point.Z(), landmark->Position().Z(), 1e-8);
  }

  view1->UpdateObservedLandmarks();
  view2->UpdateObservedLandmarks();

  // We now have 100 observations in each view, and 100 corresponding landmarks
  // that are triangulated from the observation positions. Bundle adjustment
  // should have 0 error, and should terminate without altering the positions of
  // any landmarks or cameras.
  BundleAdjuster bundle_adjuster;
  BundleAdjustmentOptions options;

  std::vector<ViewIndex> view_indices = { 0, 1 };
  EXPECT_TRUE(bundle_adjuster.Solve(options, view_indices));

  for (size_t ii = 0; ii < points.size(); ++ii) {
    Landmark::Ptr landmark = Landmark::GetLandmark(ii);
    EXPECT_NEAR(points[ii].X(), landmark->Position().X(), 1e-8);
    EXPECT_NEAR(points[ii].Y(), landmark->Position().Y(), 1e-8);
    EXPECT_NEAR(points[ii].Z(), landmark->Position().Z(), 1e-8);
  }

  EXPECT_TRUE(camera1.Rt().isApprox(view1->Camera().Rt()));
  EXPECT_TRUE(camera2.Rt().isApprox(view2->Camera().Rt()));

  // Clean up.
  Landmark::ResetLandmarks();
  View::ResetViews();
}

TEST(BundleAdjuster, TestManyViewsNoNoise) {
  // Create lots of views with perfect matches all view the same set of 3D
  // points. Bundle adjustment shouldn't change a thing.

  // Clean up from other tests.
  Landmark::ResetLandmarks();
  View::ResetViews();

  // Make 3D points.
  math::RandomGenerator rng(0);
  Point3DList points;
  MakePoints(50, rng, points);

  // Make a bunch of random cameras.
  std::vector<Camera> cameras;
  for (int ii = 0; ii < 50; ++ii) {
    cameras.push_back(RandomCamera(rng, points));
    View::Create(cameras.back());
  }

  for (const auto& p : points) {
    Descriptor descriptor(Descriptor::Random(32));
    Landmark::Ptr landmark = Landmark::Create();

    double u = 0.0, v = 0.0;
    for (size_t ii = 0; ii < cameras.size(); ++ii) {
      EXPECT_TRUE(cameras[ii].WorldToImage(p.X(), p.Y(), p.Z(), &u, &v));
      Feature feature(u, v);

      View::Ptr view = View::GetView(ii);
      Observation::Ptr observation =
          Observation::Create(view, feature, descriptor);
      view->AddObservation(observation);
      EXPECT_TRUE(landmark->IncorporateObservation(observation));
    }
    EXPECT_NEAR(p.X(), landmark->Position().X(), 1e-8);
    EXPECT_NEAR(p.Y(), landmark->Position().Y(), 1e-8);
    EXPECT_NEAR(p.Z(), landmark->Position().Z(), 1e-8);
  }

  // Bundle adjust over the views and points that were just created.
  BundleAdjuster bundle_adjuster;
  BundleAdjustmentOptions options;

  std::vector<ViewIndex> view_indices;
  for (ViewIndex ii = 0; ii < View::NumExistingViews(); ++ii)
    view_indices.push_back(ii);

  EXPECT_TRUE(bundle_adjuster.Solve(options, view_indices));

  for (size_t ii = 0; ii < points.size(); ++ii) {
    Landmark::Ptr landmark = Landmark::GetLandmark(ii);
    EXPECT_NEAR(points[ii].X(), landmark->Position().X(), 1e-8);
    EXPECT_NEAR(points[ii].Y(), landmark->Position().Y(), 1e-8);
    EXPECT_NEAR(points[ii].Z(), landmark->Position().Z(), 1e-8);
  }

  for (const auto& view_index : view_indices) {
    View::Ptr view = View::GetView(view_index);
    EXPECT_TRUE(cameras[view_index].Rt().isApprox(view->Camera().Rt()));
  }

  // Clean up.
  Landmark::ResetLandmarks();
  View::ResetViews();
}

}  //\namespace bsfm
<|endoftext|>


<commit_before>// Copyright (c) 2012 Plenluno All rights reserved.

#include <libj/error.h>
#include <libj/detail/status.h>

namespace libj {

#define LIBJ_ERROR_MSG_MAP(GEN) \
    GEN(ANY, "") \
    GEN(TIMEOUT, "Timeout") \
    GEN(ILLEGAL_ARGUMENT, "Illegal Argument") \
    GEN(ILLEGAL_DATA_FORMAT, "Illegal Data Format") \
    GEN(ILLEGAL_REQUEST, "Illegal Request") \
    GEN(ILLEGAL_RESPONSE, "Illegal Response") \
    GEN(ILLEGAL_STATE, "Illegal State") \
    GEN(ILLEGAL_TYPE, "Illegal Type") \
    GEN(INDEX_OUT_OF_BOUNDS, "Index Out Of Bounds") \
    GEN(NO_SUCH_ELEMENT, "No Such Element") \
    GEN(NO_SUCH_FIELD, "No Such Field") \
    GEN(NO_SUCH_METHOD, "No Such Method") \
    GEN(NULL_POINTER, "Null Pointer") \
    GEN(UNSUPPORTED_VERSION, "Unsupported Version") \
    GEN(UNSUPPORTED_OPERATION, "Unsupported Operation")

#define LIBJ_ERROR_MSG_DEF_GEN(NAME, MESSAGE) \
    const String::CPtr MSG_##NAME = String::create(MESSAGE);

#define LIBJ_ERROR_MSG_CASE_GEN(NAME, MESSAGE) \
    case NAME: \
        msg = MSG_##NAME; \
        break;

Error::CPtr Error::create(Error::Code code) {
    LIBJ_ERROR_MSG_MAP(LIBJ_ERROR_MSG_DEF_GEN);

    String::CPtr msg;
    switch (code) {
        LIBJ_ERROR_MSG_MAP(LIBJ_ERROR_MSG_CASE_GEN);
    default:
        return null();
    }
    return CPtr(new detail::Status<Error>(code, msg));
}

Error::CPtr Error::create(Error::Code code, String::CPtr msg) {
    return CPtr(new detail::Status<Error>(code, msg));
}

}  // namespace libj
<commit_msg>set the messages of unknown errors to null<commit_after>// Copyright (c) 2012 Plenluno All rights reserved.

#include <libj/error.h>
#include <libj/detail/status.h>

namespace libj {

#define LIBJ_ERROR_MSG_MAP(GEN) \
    GEN(ANY, "") \
    GEN(TIMEOUT, "Timeout") \
    GEN(ILLEGAL_ARGUMENT, "Illegal Argument") \
    GEN(ILLEGAL_DATA_FORMAT, "Illegal Data Format") \
    GEN(ILLEGAL_REQUEST, "Illegal Request") \
    GEN(ILLEGAL_RESPONSE, "Illegal Response") \
    GEN(ILLEGAL_STATE, "Illegal State") \
    GEN(ILLEGAL_TYPE, "Illegal Type") \
    GEN(INDEX_OUT_OF_BOUNDS, "Index Out Of Bounds") \
    GEN(NO_SUCH_ELEMENT, "No Such Element") \
    GEN(NO_SUCH_FIELD, "No Such Field") \
    GEN(NO_SUCH_METHOD, "No Such Method") \
    GEN(NULL_POINTER, "Null Pointer") \
    GEN(UNSUPPORTED_VERSION, "Unsupported Version") \
    GEN(UNSUPPORTED_OPERATION, "Unsupported Operation")

#define LIBJ_ERROR_MSG_DEF_GEN(NAME, MESSAGE) \
    const String::CPtr MSG_##NAME = String::create(MESSAGE);

#define LIBJ_ERROR_MSG_CASE_GEN(NAME, MESSAGE) \
    case NAME: \
        msg = MSG_##NAME; \
        break;

Error::CPtr Error::create(Error::Code code) {
    LIBJ_ERROR_MSG_MAP(LIBJ_ERROR_MSG_DEF_GEN);

    String::CPtr msg;
    switch (code) {
        LIBJ_ERROR_MSG_MAP(LIBJ_ERROR_MSG_CASE_GEN);
    default:
        msg = String::null();
    }
    return CPtr(new detail::Status<Error>(code, msg));
}

Error::CPtr Error::create(Error::Code code, String::CPtr msg) {
    return CPtr(new detail::Status<Error>(code, msg));
}

}  // namespace libj
<|endoftext|>


<commit_before>/*
Copyright (C) 2017 - Gbor "Razzie" Grzsny
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
*/

#include "Application.hpp"
#include "GameWindow.hpp"
#include "GameWorld.hpp"
#include "Settings.hpp"
#include <ShlObj.h>

/*
 * Source: https://github.com/SFML/SFML/wiki/Source:-Letterbox-effect-using-a-view
 */
static sf::View getLetterboxView(sf::View view, int windowWidth, int windowHeight)
{
	// Compares the aspect ratio of the window to the aspect ratio of the view,
	// and sets the view's viewport accordingly in order to archieve a letterbox effect.
	// A new view (with a new viewport set) is returned.

	float windowRatio = windowWidth / (float)windowHeight;
	float viewRatio = view.getSize().x / (float)view.getSize().y;
	float sizeX = 1;
	float sizeY = 1;
	float posX = 0;
	float posY = 0;

	bool horizontalSpacing = true;
	if (windowRatio < viewRatio)
		horizontalSpacing = false;

	// If horizontalSpacing is true, the black bars will appear on the left and right side.
	// Otherwise, the black bars will appear on the top and bottom.

	if (horizontalSpacing) {
		sizeX = viewRatio / windowRatio;
		posX = (1 - sizeX) / 2.f;
	}

	else {
		sizeY = windowRatio / viewRatio;
		posY = (1 - sizeY) / 2.f;
	}

	view.setViewport(sf::FloatRect(posX, posY, sizeX, sizeY));

	return view;
}

GameWindow::GameWindow(Application* app, uint16_t player_id) :
	m_app(app),
	m_player_id(player_id),
	m_mouse_radius(6.f),
	m_mouse_drag_x(0),
	m_mouse_drag_y(0),
	m_mouse_down(false)
{
	sf::ContextSettings settings;
	settings.antialiasingLevel = 4;

	m_window.create(sf::VideoMode(RESOLUTION_WIDTH, RESOLUTION_HEIGHT), "RazzGravitas", (sf::Style::Resize + sf::Style::Close), settings);
	m_window.setVerticalSyncEnabled(true);
	m_window.setKeyRepeatEnabled(false);
	m_window.clear(sf::Color::White);

	m_view.setSize(RESOLUTION_WIDTH, RESOLUTION_HEIGHT);
	m_view.setCenter(m_view.getSize().x / 2, m_view.getSize().y / 2);
	m_view = getLetterboxView(m_view, RESOLUTION_WIDTH, RESOLUTION_HEIGHT);
	m_window.setView(m_view);

	raz::ColorTable color_table;
	for (int i = 0; i < MAX_PLAYERS; ++i)
		m_player_colors[i] = color_table[i];

	raz::Color player_color = m_player_colors[player_id];

	m_game_object_shape.setOutlineThickness(2.f);

	m_mouse_shape.setRadius(m_mouse_radius);
	m_mouse_shape.setOutlineThickness(2.f);
	m_mouse_shape.setOutlineColor(sf::Color(player_color.r, player_color.g, player_color.b, 6));
	m_mouse_shape.setFillColor(sf::Color::Transparent);

	m_clear_rect.setSize(sf::Vector2f(RESOLUTION_WIDTH, RESOLUTION_HEIGHT));
	m_clear_rect.setFillColor(sf::Color(255, 255, 255, 4));

	PWSTR font_filename;
	SHGetKnownFolderPath(FOLDERID_Fonts, 0, NULL, &font_filename);
	m_font.loadFromFile(sf::String(font_filename) + "/arial.ttf");
	CoTaskMemFree(font_filename);

	m_msg.setFont(m_font);
	m_msg.setOutlineColor(sf::Color::White);
	m_msg.setOutlineThickness(1.f);
	m_msg.setPosition(10, 10);
	m_msg.setCharacterSize(MESSAGE_CHAR_SIZE);

	m_input.setFont(m_font);
	m_input.setOutlineColor(sf::Color::White);
	m_input.setOutlineThickness(1.f);
	m_input.setFillColor(sf::Color(player_color.r, player_color.g, player_color.b));
	m_input.setPosition(10, RESOLUTION_HEIGHT - MESSAGE_CHAR_SIZE - 10);
	m_input.setCharacterSize(MESSAGE_CHAR_SIZE);
}

GameWindow::~GameWindow()
{
}

void GameWindow::drawGameObject(float x, float y, float r, uint16_t player_id)
{
	raz::Color color = m_player_colors[player_id];
	m_game_object_shape.setOutlineColor(sf::Color(color.r, color.g, color.b));
	m_game_object_shape.setFillColor(sf::Color(color.r / 2 + 127, color.g / 2 + 127, color.b / 2 + 127));
	m_game_object_shape.setPosition(x - r + 1.f, y - r + 1.f);
	m_game_object_shape.setRadius(r - 1.f);
	m_window.draw(m_game_object_shape);
}

void GameWindow::operator()()
{
	if (!m_window.isOpen())
		m_app->exit(0);

	sf::Event event;
	while (m_window.pollEvent(event))
	{
		switch (event.type)
		{
		case sf::Event::Closed:
			m_window.close();
			break;

		case sf::Event::Resized:
			m_view = getLetterboxView(m_view, event.size.width, event.size.height);
			m_window.setView(m_view);
			m_window.clear(sf::Color::White);
			break;

		case sf::Event::TextEntered:
			if (event.text.unicode >= 32)
				m_input.setString(m_input.getString() + event.text.unicode);
			break;

		case sf::Event::KeyPressed:
			switch (event.key.code)
			{
			case sf::Keyboard::BackSpace:
				if (!m_input.getString().isEmpty())
				{
					auto msg = m_input.getString();
					msg.erase(m_input.getString().getSize() - 1);
					m_input.setString(msg);
				}
				break;

			case sf::Keyboard::Return:
				{
					Message e;
					e.player_id = m_player_id;
					e.message = m_input.getString().getData();
					m_app->getNetwork()(e);
				}
				m_input.setString({});
				break;
			}
			break;

		case sf::Event::MouseWheelMoved:
			m_mouse_radius += event.mouseWheel.delta * 2;
			if (m_mouse_radius < 2.f)
				m_mouse_radius = 2.f;
			else if (m_mouse_radius > 32.f)
				m_mouse_radius = 32.f;
			m_mouse_shape.setRadius(m_mouse_radius);
			break;

		case sf::Event::MouseButtonPressed:
			if (event.mouseButton.button == sf::Mouse::Left)
			{
				if (m_mouse_down == false)
				{
					m_mouse_drag_x = event.mouseButton.x;
					m_mouse_drag_y = event.mouseButton.y;
				}
				m_mouse_down = true;
			}
			break;

		case sf::Event::MouseButtonReleased:
			m_mouse_down = false;
			auto pos = m_window.mapPixelToCoords(sf::Mouse::getPosition(m_window));
			if (event.mouseButton.button == sf::Mouse::Left)
			{
				auto last_pos = m_window.mapPixelToCoords(sf::Vector2i(m_mouse_drag_x, m_mouse_drag_y));
				AddGameObject e;
				e.position_x = last_pos.x;
				e.position_y = last_pos.y;
				e.radius = m_mouse_radius;
				e.velocity_x = pos.x - last_pos.x;
				e.velocity_y = pos.y - last_pos.y;
				e.player_id = m_player_id;
				m_app->getGameWorld()(e);
				m_app->getNetwork()(e);
			}
			else if (event.mouseButton.button == sf::Mouse::Right)
			{
				RemoveGameObjects e;
				e.position_x = pos.x;
				e.position_y = pos.y;
				e.radius = m_mouse_radius;
				e.player_id = m_player_id;
				m_app->getGameWorld()(e);
				m_app->getNetwork()(e);
			}
			break;
		}
	}

	m_window.draw(m_clear_rect, sf::BlendAdd);

	if (m_mouse_down)
	{
		m_mouse_shape.setPosition(m_window.mapPixelToCoords(sf::Vector2i(m_mouse_drag_x, m_mouse_drag_y)) - sf::Vector2f(m_mouse_radius, m_mouse_radius));

		sf::Vertex line[] =
		{
			sf::Vertex(m_window.mapPixelToCoords(sf::Vector2i(m_mouse_drag_x, m_mouse_drag_y)), m_mouse_shape.getOutlineColor()),
			sf::Vertex(m_window.mapPixelToCoords(sf::Mouse::getPosition(m_window)), m_mouse_shape.getOutlineColor())
		};

		m_window.draw(line, 2, sf::Lines);
	}
	else
	{
		m_mouse_shape.setPosition(m_window.mapPixelToCoords(sf::Mouse::getPosition(m_window)) - sf::Vector2f(m_mouse_radius, m_mouse_radius));
	}
	m_window.draw(m_mouse_shape);

	if (!m_msg_queue.empty())
	{
		if (m_msg_timer.peekElapsed() > MESSAGE_TIMEOUT / m_msg_queue.size())
		{
			m_msg_timer.reset();

			Message msg = m_msg_queue.back();
			m_msg_queue.pop();

			raz::Color color = m_player_colors[msg.player_id];
			m_msg.setFillColor(sf::Color(color.r, color.g, color.b));
			m_msg.setString(msg.message.c_str());
		}
	}
	else if (m_msg_timer.peekElapsed() > MESSAGE_TIMEOUT)
	{
		m_msg.setString({});
	}

	m_window.draw(m_msg);
	m_window.draw(m_input);

	m_window.display();
}

void GameWindow::operator()(GameWorld* world)
{
	world->render(*this);
}

void GameWindow::operator()(Message e)
{
	m_msg_queue.push(e);
}
<commit_msg>Fixed a message queue bug<commit_after>/*
Copyright (C) 2017 - Gbor "Razzie" Grzsny
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
*/

#include "Application.hpp"
#include "GameWindow.hpp"
#include "GameWorld.hpp"
#include "Settings.hpp"
#include <ShlObj.h>

/*
 * Source: https://github.com/SFML/SFML/wiki/Source:-Letterbox-effect-using-a-view
 */
static sf::View getLetterboxView(sf::View view, int windowWidth, int windowHeight)
{
	// Compares the aspect ratio of the window to the aspect ratio of the view,
	// and sets the view's viewport accordingly in order to archieve a letterbox effect.
	// A new view (with a new viewport set) is returned.

	float windowRatio = windowWidth / (float)windowHeight;
	float viewRatio = view.getSize().x / (float)view.getSize().y;
	float sizeX = 1;
	float sizeY = 1;
	float posX = 0;
	float posY = 0;

	bool horizontalSpacing = true;
	if (windowRatio < viewRatio)
		horizontalSpacing = false;

	// If horizontalSpacing is true, the black bars will appear on the left and right side.
	// Otherwise, the black bars will appear on the top and bottom.

	if (horizontalSpacing) {
		sizeX = viewRatio / windowRatio;
		posX = (1 - sizeX) / 2.f;
	}

	else {
		sizeY = windowRatio / viewRatio;
		posY = (1 - sizeY) / 2.f;
	}

	view.setViewport(sf::FloatRect(posX, posY, sizeX, sizeY));

	return view;
}

GameWindow::GameWindow(Application* app, uint16_t player_id) :
	m_app(app),
	m_player_id(player_id),
	m_mouse_radius(6.f),
	m_mouse_drag_x(0),
	m_mouse_drag_y(0),
	m_mouse_down(false)
{
	sf::ContextSettings settings;
	settings.antialiasingLevel = 4;

	m_window.create(sf::VideoMode(RESOLUTION_WIDTH, RESOLUTION_HEIGHT), "RazzGravitas", (sf::Style::Resize + sf::Style::Close), settings);
	m_window.setVerticalSyncEnabled(true);
	m_window.setKeyRepeatEnabled(false);
	m_window.clear(sf::Color::White);

	m_view.setSize(RESOLUTION_WIDTH, RESOLUTION_HEIGHT);
	m_view.setCenter(m_view.getSize().x / 2, m_view.getSize().y / 2);
	m_view = getLetterboxView(m_view, RESOLUTION_WIDTH, RESOLUTION_HEIGHT);
	m_window.setView(m_view);

	raz::ColorTable color_table;
	for (int i = 0; i < MAX_PLAYERS; ++i)
		m_player_colors[i] = color_table[i];

	raz::Color player_color = m_player_colors[player_id];

	m_game_object_shape.setOutlineThickness(2.f);

	m_mouse_shape.setRadius(m_mouse_radius);
	m_mouse_shape.setOutlineThickness(2.f);
	m_mouse_shape.setOutlineColor(sf::Color(player_color.r, player_color.g, player_color.b, 6));
	m_mouse_shape.setFillColor(sf::Color::Transparent);

	m_clear_rect.setSize(sf::Vector2f(RESOLUTION_WIDTH, RESOLUTION_HEIGHT));
	m_clear_rect.setFillColor(sf::Color(255, 255, 255, 4));

	PWSTR font_filename;
	SHGetKnownFolderPath(FOLDERID_Fonts, 0, NULL, &font_filename);
	m_font.loadFromFile(sf::String(font_filename) + "/arial.ttf");
	CoTaskMemFree(font_filename);

	m_msg.setFont(m_font);
	m_msg.setOutlineColor(sf::Color::White);
	m_msg.setOutlineThickness(1.f);
	m_msg.setPosition(10, 10);
	m_msg.setCharacterSize(MESSAGE_CHAR_SIZE);

	m_input.setFont(m_font);
	m_input.setOutlineColor(sf::Color::White);
	m_input.setOutlineThickness(1.f);
	m_input.setFillColor(sf::Color(player_color.r, player_color.g, player_color.b));
	m_input.setPosition(10, RESOLUTION_HEIGHT - MESSAGE_CHAR_SIZE - 10);
	m_input.setCharacterSize(MESSAGE_CHAR_SIZE);
}

GameWindow::~GameWindow()
{
}

void GameWindow::drawGameObject(float x, float y, float r, uint16_t player_id)
{
	raz::Color color = m_player_colors[player_id];
	m_game_object_shape.setOutlineColor(sf::Color(color.r, color.g, color.b));
	m_game_object_shape.setFillColor(sf::Color(color.r / 2 + 127, color.g / 2 + 127, color.b / 2 + 127));
	m_game_object_shape.setPosition(x - r + 1.f, y - r + 1.f);
	m_game_object_shape.setRadius(r - 1.f);
	m_window.draw(m_game_object_shape);
}

void GameWindow::operator()()
{
	if (!m_window.isOpen())
		m_app->exit(0);

	sf::Event event;
	while (m_window.pollEvent(event))
	{
		switch (event.type)
		{
		case sf::Event::Closed:
			m_window.close();
			break;

		case sf::Event::Resized:
			m_view = getLetterboxView(m_view, event.size.width, event.size.height);
			m_window.setView(m_view);
			m_window.clear(sf::Color::White);
			break;

		case sf::Event::TextEntered:
			if (event.text.unicode >= 32)
				m_input.setString(m_input.getString() + event.text.unicode);
			break;

		case sf::Event::KeyPressed:
			switch (event.key.code)
			{
			case sf::Keyboard::BackSpace:
				if (!m_input.getString().isEmpty())
				{
					auto msg = m_input.getString();
					msg.erase(m_input.getString().getSize() - 1);
					m_input.setString(msg);
				}
				break;

			case sf::Keyboard::Return:
				{
					Message e;
					e.player_id = m_player_id;
					e.message = m_input.getString().getData();
					m_app->getNetwork()(e);
				}
				m_input.setString({});
				break;
			}
			break;

		case sf::Event::MouseWheelMoved:
			m_mouse_radius += event.mouseWheel.delta * 2;
			if (m_mouse_radius < 2.f)
				m_mouse_radius = 2.f;
			else if (m_mouse_radius > 32.f)
				m_mouse_radius = 32.f;
			m_mouse_shape.setRadius(m_mouse_radius);
			break;

		case sf::Event::MouseButtonPressed:
			if (event.mouseButton.button == sf::Mouse::Left)
			{
				if (m_mouse_down == false)
				{
					m_mouse_drag_x = event.mouseButton.x;
					m_mouse_drag_y = event.mouseButton.y;
				}
				m_mouse_down = true;
			}
			break;

		case sf::Event::MouseButtonReleased:
			m_mouse_down = false;
			auto pos = m_window.mapPixelToCoords(sf::Mouse::getPosition(m_window));
			if (event.mouseButton.button == sf::Mouse::Left)
			{
				auto last_pos = m_window.mapPixelToCoords(sf::Vector2i(m_mouse_drag_x, m_mouse_drag_y));
				AddGameObject e;
				e.position_x = last_pos.x;
				e.position_y = last_pos.y;
				e.radius = m_mouse_radius;
				e.velocity_x = pos.x - last_pos.x;
				e.velocity_y = pos.y - last_pos.y;
				e.player_id = m_player_id;
				m_app->getGameWorld()(e);
				m_app->getNetwork()(e);
			}
			else if (event.mouseButton.button == sf::Mouse::Right)
			{
				RemoveGameObjects e;
				e.position_x = pos.x;
				e.position_y = pos.y;
				e.radius = m_mouse_radius;
				e.player_id = m_player_id;
				m_app->getGameWorld()(e);
				m_app->getNetwork()(e);
			}
			break;
		}
	}

	m_window.draw(m_clear_rect, sf::BlendAdd);

	if (m_mouse_down)
	{
		m_mouse_shape.setPosition(m_window.mapPixelToCoords(sf::Vector2i(m_mouse_drag_x, m_mouse_drag_y)) - sf::Vector2f(m_mouse_radius, m_mouse_radius));

		sf::Vertex line[] =
		{
			sf::Vertex(m_window.mapPixelToCoords(sf::Vector2i(m_mouse_drag_x, m_mouse_drag_y)), m_mouse_shape.getOutlineColor()),
			sf::Vertex(m_window.mapPixelToCoords(sf::Mouse::getPosition(m_window)), m_mouse_shape.getOutlineColor())
		};

		m_window.draw(line, 2, sf::Lines);
	}
	else
	{
		m_mouse_shape.setPosition(m_window.mapPixelToCoords(sf::Mouse::getPosition(m_window)) - sf::Vector2f(m_mouse_radius, m_mouse_radius));
	}
	m_window.draw(m_mouse_shape);

	if (!m_msg_queue.empty())
	{
		if (m_msg_timer.peekElapsed() > MESSAGE_TIMEOUT / m_msg_queue.size())
		{
			m_msg_timer.reset();

			Message msg = m_msg_queue.front();
			m_msg_queue.pop();

			raz::Color color = m_player_colors[msg.player_id];
			m_msg.setFillColor(sf::Color(color.r, color.g, color.b));
			m_msg.setString(msg.message.c_str());
		}
	}
	else if (m_msg_timer.peekElapsed() > MESSAGE_TIMEOUT)
	{
		m_msg.setString({});
	}

	m_window.draw(m_msg);
	m_window.draw(m_input);

	m_window.display();
}

void GameWindow::operator()(GameWorld* world)
{
	world->render(*this);
}

void GameWindow::operator()(Message e)
{
	m_msg_queue.push(e);
}
<|endoftext|>