<commit_before>//============================================================================
// vSMC/include/vsmc/utility/aligned_memory.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013-2016, Yan Zhou
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
//   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.
//
// 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.
//============================================================================

#ifndef VSMC_UTILITY_ALIGNED_MEMORY
#define VSMC_UTILITY_ALIGNED_MEMORY

#include <vsmc/internal/assert.hpp>
#include <vsmc/internal/config.h>

#include <cstddef>
#include <cstdlib>
#include <memory>
#include <vector>

#if VSMC_HAS_POSIX
#include <stdlib.h>
#elif defined(VSMC_MSVC)
#include <malloc.h>
#endif

#if VSMC_HAS_TBB_MALLOC
#include <tbb/scalable_allocator.h>
#endif

#if VSMC_HAS_MKL
#include <mkl_service.h>
#endif

/// \brief Default AlignedMemory type
/// \ingroup Config
#ifndef VSMC_ALIGNED_MEMORY_TYPE
#if VSMC_HAS_TBB_MALLOC
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryTBB
#elif VSMC_HAS_MKL
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryMKL
#elif VSMC_HAS_POSIX || defined(VSMC_MSVC)
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySYS
#else
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySTD
#endif
#endif

/// \brief Defualt alignment
/// \ingroup Config
#ifndef VSMC_ALIGNMENT
#define VSMC_ALIGNMENT 32
#endif

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment)    \
    VSMC_RUNTIME_ASSERT(                                                      \
        (alignment != 0 && (alignment & (alignment - 1)) == 0),               \
        "**aligned_malloc** USED WITH ALIGNMENT NOT A POWER OF TWO")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignemnt)     \
    VSMC_RUNTIME_ASSERT((alignment >= sizeof(void *)),                        \
        "**aligned_malloc** USED WITH ALIGNMENT LESS THAN sizeof(void *)")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY                            \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment);       \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignment);

namespace vsmc
{

/// \brief Aligned memory using `std::malloc` and `std::free`
/// \ingroup AlignedMemory
///
/// \details
/// Memory allocated through this class is aligned but some bytes might be
/// wasted in each allocation.
class AlignedMemorySTD
{
    public:
    static void *aligned_malloc(std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return nullptr;

        void *orig_ptr = std::malloc(n + alignment + sizeof(void *));
        if (orig_ptr == nullptr)
            throw std::bad_alloc();

        uintptr_t address = reinterpret_cast<uintptr_t>(orig_ptr);
        uintptr_t offset = alignment - (address + sizeof(void *)) % alignment;
        void *ptr =
            reinterpret_cast<void *>(address + offset + sizeof(void *));
        void **orig = reinterpret_cast<void **>(address + offset);
        *orig = orig_ptr;

        return ptr;
    }

    static void aligned_free(void *ptr)
    {
        std::free(*reinterpret_cast<void **>(
            reinterpret_cast<uintptr_t>(ptr) - sizeof(void *)));
    }
}; // class AlignedMemmorySTD

#if VSMC_HAS_POSIX

/// \brief Aligned memory using native system aligned memory allocation
/// \ingroup AlignedMemory
///
/// \details
/// This class use `posix_memalign` and `free` on POSIX systems (Mac OS X,
/// Linux, etc.) and `_aligned_malloc` and `_aligned_free` on Windows.
class AlignedMemorySYS
{
    public:
    static void *aligned_malloc(std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return nullptr;

        void *ptr;
        if (posix_memalign(&ptr, alignment, n) != 0)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free(void *ptr) { free(ptr); }
}; // class AlignedMallocSYS

#elif defined(VSMC_MSVC)

class AlignedMemorySYS
{
    public:
    static void *aligned_malloc(std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return nullptr;

        void *ptr = _aligned_malloc(n, alignment);
        if (ptr == nullptr)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free(void *ptr) { _aligned_free(ptr); }
}; // class AlignedMemorySYS

#endif // VSMC_HAS_POSIX

#if VSMC_HAS_TBB_MALLOC

/// \brief Aligned memory using Intel TBB `scalable_aligned_malloc` and
/// `scalable_aligned_free`.
/// \ingroup AlignedMemory
class AlignedMemoryTBB
{
    public:
    static void *aligned_malloc(std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return nullptr;

        void *ptr = scalable_aligned_malloc(n, alignment);
        if (ptr == nullptr)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free(void *ptr) { scalable_aligned_free(ptr); }
}; // class AlignedMemoryTBB

#endif // VSMC_HAS_TBB_MALLOC

#if VSMC_HAS_MKL

/// \brief Aligned memory using Intel MKL `mkl_malloc` and `mkl_free`
/// \ingroup AlignedMemory
class AlignedMemoryMKL
{
    public:
    static void *aligned_malloc(std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return nullptr;

        void *ptr = mkl_malloc(n, static_cast<int>(alignment));
        if (ptr == nullptr)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free(void *ptr) { mkl_free(ptr); }
}; // class AlignedMemoryMKL

#endif // VSMC_HAS_MKL

/// \brief Default AlignedMemory type
/// \ingroup AlignedMemory
using AlignedMemory = VSMC_ALIGNED_MEMORY_TYPE;

/// \brief Aligned allocator
/// \ingroup AlignedMemory
///
/// \tparam T The value type
/// \tparam Alignment The alignment requirement of memory, must be a power of
/// two and no less than `sizeof(void *)`.
/// \tparam Memory The memory management class. Must provides two static member
/// functions, `aligned_malloc` and `aligned_free`. The member function
/// `aligned_malloc` shall behave similar to `std::malloc` but take an
/// additional arguments for alignment. The member function `aligned_free`
/// shall behave just like `std::free`.
template <typename T, std::size_t Alignment = VSMC_ALIGNMENT,
    typename Memory = AlignedMemory>
class AlignedAllocator
{
    static_assert(Alignment != 0 && (Alignment & (Alignment - 1)) == 0,
        "**AlignedAllocator** USED WITH Alignment OTHER THAN A POWER OF TWO "
        "POSITIVE INTEGER");

    static_assert(Alignment >= sizeof(void *),
        "**AlignedAllocator** USED WITH Alignment LESS THAN sizeof(void *)");

    public:
    using value_type = T;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using pointer = T *;
    using const_pointer = const T *;
    using reference = typename std::add_lvalue_reference<T>::type;
    using const_reference = typename std::add_lvalue_reference<const T>::type;
    using is_always_equal = std::true_type;

    template <typename U>
    class rebind
    {
        public:
        using other = AlignedAllocator<U, Alignment, AlignedMemory>;
    }; // class rebind

    AlignedAllocator() noexcept {}

    AlignedAllocator(const AlignedAllocator<T, Alignment, Memory> &) noexcept
    {
    }

    template <typename U>
    AlignedAllocator(const AlignedAllocator<U, Alignment, Memory> &) noexcept
    {
    }

    ~AlignedAllocator() noexcept {}

    static pointer address(reference x) noexcept { return std::addressof(x); }

    static const_pointer address(const_reference x) noexcept
    {
        return std::addressof(x);
    }

    static pointer allocate(size_type n, const void * = nullptr)
    {
        if (n == 0)
            return nullptr;

        return static_cast<pointer>(
            Memory::aligned_malloc(sizeof(T) * n, Alignment));
    }

    static void deallocate(pointer ptr, size_type)
    {
        if (ptr != nullptr)
            Memory::aligned_free(ptr);
    }

    static constexpr size_type max_size() noexcept
    {
        return std::numeric_limits<size_type>::max();
    }

    template <typename U, typename... Args>
    static void construct(U *ptr, Args &&... args)
    {
        construct(std::integral_constant<bool, std::is_scalar<U>::value>(),
            ptr, std::forward<Args>(args)...);
    }

    template <typename U>
    static void destroy(U *ptr)
    {
        std::allocator<U> alloc;
        alloc.destroy(ptr);
    }

    template <typename T1, typename T2>
    friend bool operator==(const AlignedAllocator<T1, Alignment, Memory> &,
        const AlignedAllocator<T2, Alignment, Memory> &) noexcept
    {
        return true;
    }

    template <typename T1, typename T2>
    friend bool operator!=(const AlignedAllocator<T1, Alignment, Memory> &,
        const AlignedAllocator<T2, Alignment, Memory> &) noexcept
    {
        return false;
    }

    private:
    template <typename U, typename... Args>
    static void construct(std::true_type, U *, Args &&...)
    {
    }

    template <typename U, typename... Args>
    static void construct(std::false_type, U *ptr, Args &&... args)
    {
        std::allocator<U> alloc;
        alloc.construct(ptr, std::forward<Args>(args)...);
    }
}; // class AlignedAllocator

template <std::size_t Alignment, typename Memory>
class AlignedAllocator<void, Alignment, Memory>
{
    using value_type = void;
    using pointer = void *;
    using const_pointer = const void *;

    template <class U>
    struct rebind {
        using other = AlignedAllocator<U, Alignment, Memory>;
    };
}; // class AlignedAllocator

template <std::size_t Alignment, typename Memory>
class AlignedAllocator<const void, Alignment, Memory>
{
    using value_type = const void;
    using pointer = const void *;
    using const_pointer = const void *;

    template <class U>
    struct rebind {
        using other = AlignedAllocator<U, Alignment, Memory>;
    };
}; // class AlignedAllocator

/// \brief AlignedAllocator for scalar type and `std::allocator` for others
/// \ingroup AlignedMemory
template <typename T>
using Allocator = typename std::conditional<std::is_scalar<T>::value,
    AlignedAllocator<T>, std::allocator<T>>::type;

/// \brief Vector type using AlignedAllocator
/// \ingroup AlignedMemory
template <typename T>
using AlignedVector = std::vector<T, AlignedAllocator<T>>;

/// \brief AlignedVector for scalar type and `std::vector` for others
/// \ingroup AlignedMemory
template <typename T>
using Vector = typename std::conditional<std::is_scalar<T>::value,
    AlignedVector<T>, std::vector<T>>::type;

} // namespace vsmc

#endif // VSMC_UTILITY_ALIGNED_MEMORY
<commit_msg>fix AlignedMemory::rebind<commit_after>//============================================================================
// vSMC/include/vsmc/utility/aligned_memory.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013-2016, Yan Zhou
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
//   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.
//
// 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.
//============================================================================

#ifndef VSMC_UTILITY_ALIGNED_MEMORY
#define VSMC_UTILITY_ALIGNED_MEMORY

#include <vsmc/internal/assert.hpp>
#include <vsmc/internal/config.h>

#include <cstddef>
#include <cstdlib>
#include <memory>
#include <vector>

#if VSMC_HAS_POSIX
#include <stdlib.h>
#elif defined(VSMC_MSVC)
#include <malloc.h>
#endif

#if VSMC_HAS_TBB_MALLOC
#include <tbb/scalable_allocator.h>
#endif

#if VSMC_HAS_MKL
#include <mkl_service.h>
#endif

/// \brief Default AlignedMemory type
/// \ingroup Config
#ifndef VSMC_ALIGNED_MEMORY_TYPE
#if VSMC_HAS_TBB_MALLOC
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryTBB
#elif VSMC_HAS_MKL
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryMKL
#elif VSMC_HAS_POSIX || defined(VSMC_MSVC)
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySYS
#else
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySTD
#endif
#endif

/// \brief Defualt alignment
/// \ingroup Config
#ifndef VSMC_ALIGNMENT
#define VSMC_ALIGNMENT 32
#endif

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment)    \
    VSMC_RUNTIME_ASSERT(                                                      \
        (alignment != 0 && (alignment & (alignment - 1)) == 0),               \
        "**aligned_malloc** USED WITH ALIGNMENT NOT A POWER OF TWO")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignemnt)     \
    VSMC_RUNTIME_ASSERT((alignment >= sizeof(void *)),                        \
        "**aligned_malloc** USED WITH ALIGNMENT LESS THAN sizeof(void *)")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY                            \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment);       \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignment);

namespace vsmc
{

/// \brief Aligned memory using `std::malloc` and `std::free`
/// \ingroup AlignedMemory
///
/// \details
/// Memory allocated through this class is aligned but some bytes might be
/// wasted in each allocation.
class AlignedMemorySTD
{
    public:
    static void *aligned_malloc(std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return nullptr;

        void *orig_ptr = std::malloc(n + alignment + sizeof(void *));
        if (orig_ptr == nullptr)
            throw std::bad_alloc();

        uintptr_t address = reinterpret_cast<uintptr_t>(orig_ptr);
        uintptr_t offset = alignment - (address + sizeof(void *)) % alignment;
        void *ptr =
            reinterpret_cast<void *>(address + offset + sizeof(void *));
        void **orig = reinterpret_cast<void **>(address + offset);
        *orig = orig_ptr;

        return ptr;
    }

    static void aligned_free(void *ptr)
    {
        std::free(*reinterpret_cast<void **>(
            reinterpret_cast<uintptr_t>(ptr) - sizeof(void *)));
    }
}; // class AlignedMemmorySTD

#if VSMC_HAS_POSIX

/// \brief Aligned memory using native system aligned memory allocation
/// \ingroup AlignedMemory
///
/// \details
/// This class use `posix_memalign` and `free` on POSIX systems (Mac OS X,
/// Linux, etc.) and `_aligned_malloc` and `_aligned_free` on Windows.
class AlignedMemorySYS
{
    public:
    static void *aligned_malloc(std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return nullptr;

        void *ptr;
        if (posix_memalign(&ptr, alignment, n) != 0)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free(void *ptr) { free(ptr); }
}; // class AlignedMallocSYS

#elif defined(VSMC_MSVC)

class AlignedMemorySYS
{
    public:
    static void *aligned_malloc(std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return nullptr;

        void *ptr = _aligned_malloc(n, alignment);
        if (ptr == nullptr)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free(void *ptr) { _aligned_free(ptr); }
}; // class AlignedMemorySYS

#endif // VSMC_HAS_POSIX

#if VSMC_HAS_TBB_MALLOC

/// \brief Aligned memory using Intel TBB `scalable_aligned_malloc` and
/// `scalable_aligned_free`.
/// \ingroup AlignedMemory
class AlignedMemoryTBB
{
    public:
    static void *aligned_malloc(std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return nullptr;

        void *ptr = scalable_aligned_malloc(n, alignment);
        if (ptr == nullptr)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free(void *ptr) { scalable_aligned_free(ptr); }
}; // class AlignedMemoryTBB

#endif // VSMC_HAS_TBB_MALLOC

#if VSMC_HAS_MKL

/// \brief Aligned memory using Intel MKL `mkl_malloc` and `mkl_free`
/// \ingroup AlignedMemory
class AlignedMemoryMKL
{
    public:
    static void *aligned_malloc(std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return nullptr;

        void *ptr = mkl_malloc(n, static_cast<int>(alignment));
        if (ptr == nullptr)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free(void *ptr) { mkl_free(ptr); }
}; // class AlignedMemoryMKL

#endif // VSMC_HAS_MKL

/// \brief Default AlignedMemory type
/// \ingroup AlignedMemory
using AlignedMemory = VSMC_ALIGNED_MEMORY_TYPE;

/// \brief Aligned allocator
/// \ingroup AlignedMemory
///
/// \tparam T The value type
/// \tparam Alignment The alignment requirement of memory, must be a power of
/// two and no less than `sizeof(void *)`.
/// \tparam Memory The memory management class. Must provides two static member
/// functions, `aligned_malloc` and `aligned_free`. The member function
/// `aligned_malloc` shall behave similar to `std::malloc` but take an
/// additional arguments for alignment. The member function `aligned_free`
/// shall behave just like `std::free`.
template <typename T, std::size_t Alignment = VSMC_ALIGNMENT,
    typename Memory = AlignedMemory>
class AlignedAllocator
{
    static_assert(Alignment != 0 && (Alignment & (Alignment - 1)) == 0,
        "**AlignedAllocator** USED WITH Alignment OTHER THAN A POWER OF TWO "
        "POSITIVE INTEGER");

    static_assert(Alignment >= sizeof(void *),
        "**AlignedAllocator** USED WITH Alignment LESS THAN sizeof(void *)");

    public:
    using value_type = T;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using pointer = T *;
    using const_pointer = const T *;
    using reference = typename std::add_lvalue_reference<T>::type;
    using const_reference = typename std::add_lvalue_reference<const T>::type;
    using is_always_equal = std::true_type;

    template <typename U>
    class rebind
    {
        public:
        using other = AlignedAllocator<U, Alignment, Memory>;
    }; // class rebind

    AlignedAllocator() noexcept {}

    AlignedAllocator(const AlignedAllocator<T, Alignment, Memory> &) noexcept
    {
    }

    template <typename U>
    AlignedAllocator(const AlignedAllocator<U, Alignment, Memory> &) noexcept
    {
    }

    ~AlignedAllocator() noexcept {}

    static pointer address(reference x) noexcept { return std::addressof(x); }

    static const_pointer address(const_reference x) noexcept
    {
        return std::addressof(x);
    }

    static pointer allocate(size_type n, const void * = nullptr)
    {
        if (n == 0)
            return nullptr;

        return static_cast<pointer>(
            Memory::aligned_malloc(sizeof(T) * n, Alignment));
    }

    static void deallocate(pointer ptr, size_type)
    {
        if (ptr != nullptr)
            Memory::aligned_free(ptr);
    }

    static constexpr size_type max_size() noexcept
    {
        return std::numeric_limits<size_type>::max();
    }

    template <typename U, typename... Args>
    static void construct(U *ptr, Args &&... args)
    {
        construct(std::integral_constant<bool, std::is_scalar<U>::value>(),
            ptr, std::forward<Args>(args)...);
    }

    template <typename U>
    static void destroy(U *ptr)
    {
        std::allocator<U> alloc;
        alloc.destroy(ptr);
    }

    template <typename T1, typename T2>
    friend bool operator==(const AlignedAllocator<T1, Alignment, Memory> &,
        const AlignedAllocator<T2, Alignment, Memory> &) noexcept
    {
        return true;
    }

    template <typename T1, typename T2>
    friend bool operator!=(const AlignedAllocator<T1, Alignment, Memory> &,
        const AlignedAllocator<T2, Alignment, Memory> &) noexcept
    {
        return false;
    }

    private:
    template <typename U, typename... Args>
    static void construct(std::true_type, U *, Args &&...)
    {
    }

    template <typename U, typename... Args>
    static void construct(std::false_type, U *ptr, Args &&... args)
    {
        std::allocator<U> alloc;
        alloc.construct(ptr, std::forward<Args>(args)...);
    }
}; // class AlignedAllocator

template <std::size_t Alignment, typename Memory>
class AlignedAllocator<void, Alignment, Memory>
{
    using value_type = void;
    using pointer = void *;
    using const_pointer = const void *;

    template <class U>
    struct rebind {
        using other = AlignedAllocator<U, Alignment, Memory>;
    };
}; // class AlignedAllocator

template <std::size_t Alignment, typename Memory>
class AlignedAllocator<const void, Alignment, Memory>
{
    using value_type = const void;
    using pointer = const void *;
    using const_pointer = const void *;

    template <class U>
    struct rebind {
        using other = AlignedAllocator<U, Alignment, Memory>;
    };
}; // class AlignedAllocator

/// \brief AlignedAllocator for scalar type and `std::allocator` for others
/// \ingroup AlignedMemory
template <typename T>
using Allocator = typename std::conditional<std::is_scalar<T>::value,
    AlignedAllocator<T>, std::allocator<T>>::type;

/// \brief Vector type using AlignedAllocator
/// \ingroup AlignedMemory
template <typename T>
using AlignedVector = std::vector<T, AlignedAllocator<T>>;

/// \brief AlignedVector for scalar type and `std::vector` for others
/// \ingroup AlignedMemory
template <typename T>
using Vector = typename std::conditional<std::is_scalar<T>::value,
    AlignedVector<T>, std::vector<T>>::type;

} // namespace vsmc

#endif // VSMC_UTILITY_ALIGNED_MEMORY
<|endoftext|>


<commit_before>//https://code.google.com/p/nya-engine/

#include "resources.h"
#include "file_resources_provider.h"
//#include "system/system.h"
#include <string.h>

#if defined(_WIN32)
    #define strncasecmp _strnicmp
#endif

namespace
{
    nya_resources::resources_provider *res_provider=0;
    nya_log::log_base *resources_log=0;
}

namespace nya_resources
{

void set_resources_provider(resources_provider *provider)
{
    res_provider = provider;
}

resources_provider &get_resources_provider()
{
    if(!res_provider)
    {
        static nya_resources::file_resources_provider fprov;
        //fprov.set_folder(nya_system::get_app_path(),true);
        res_provider= &fprov;
    }

    return *res_provider;
}

void set_log(nya_log::log_base *l)
{
    resources_log=l;
}

nya_log::log_base &log()
{
    static const char *resources_log_tag="resources";
    if(!resources_log)
    {
        return nya_log::log(resources_log_tag);
    }

    resources_log->set_tag(resources_log_tag);
    return *resources_log;
}

bool check_extension(const char *name,const char *ext)
{
    if(!name || !ext)
        return false;

    const size_t name_len=strlen(name),ext_len=strlen(ext);
    if(ext_len>name_len)
        return false;

    return strcasecmp(name+name_len-ext_len-1,ext);
}

}
<commit_msg>wwww sorry<commit_after>//https://code.google.com/p/nya-engine/

#include "resources.h"
#include "file_resources_provider.h"
//#include "system/system.h"
#include <string.h>

#if defined(_WIN32)
    #define strcasecmp _stricmp
#endif

namespace
{
    nya_resources::resources_provider *res_provider=0;
    nya_log::log_base *resources_log=0;
}

namespace nya_resources
{

void set_resources_provider(resources_provider *provider)
{
    res_provider = provider;
}

resources_provider &get_resources_provider()
{
    if(!res_provider)
    {
        static nya_resources::file_resources_provider fprov;
        //fprov.set_folder(nya_system::get_app_path(),true);
        res_provider= &fprov;
    }

    return *res_provider;
}

void set_log(nya_log::log_base *l)
{
    resources_log=l;
}

nya_log::log_base &log()
{
    static const char *resources_log_tag="resources";
    if(!resources_log)
    {
        return nya_log::log(resources_log_tag);
    }

    resources_log->set_tag(resources_log_tag);
    return *resources_log;
}

bool check_extension(const char *name,const char *ext)
{
    if(!name || !ext)
        return false;

    const size_t name_len=strlen(name),ext_len=strlen(ext);
    if(ext_len>name_len)
        return false;

    return strcasecmp(name+name_len-ext_len,ext)==0;
}

}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      link.cpp
// Purpose:   Implementation of class wxExLink
// Author:    Anton van Wezenbeek
// Copyright: (c) 2011 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <regex>
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/tokenzr.h>
#include <wx/extension/link.h>
#include <wx/extension/lexer.h>
#include <wx/extension/stc.h>
#include <wx/extension/util.h>

wxExLink::wxExLink(wxExSTC* stc)
  : m_STC(stc)
{
}

bool wxExLink::AddBasePath()
{
  // Find the base path, if this is not yet on the list, add it.
  const wxString basepath_text = "Basepath: ";
  const int find = m_STC->FindText(
    0,
    1000, // the max pos to look for, this seems enough
    basepath_text);

  if (find == -1)
  {
    return false;
  }

  const int line = m_STC->LineFromPosition(find);

  m_PathList.Add(m_STC->GetTextRange(
    find + basepath_text.length(),
    m_STC->GetLineEndPosition(line) - 3));

  return true;
}

const wxString wxExLink::FindPath(const wxString& text) const
{
  if (
    text.empty() ||
    // wxPathList cannot handle links over several lines.
    wxExGetNumberOfLines(text) > 1)
  {
    return wxEmptyString;
  }

  // Better first try to find "...", then <...>, as in next example.
  // scintilla component.

  // So, first get text between " signs.
  size_t pos_char1 = text.find("\"");
  size_t pos_char2 = text.rfind("\"");

  // If that did not succeed, then get text between < and >.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    pos_char1 = text.find("<");
    pos_char2 = text.rfind(">");
  }

  // If that did not succeed, then get text between : and : (in .po files).
  if (m_STC->GetLexer().GetScintillaLexer() == "po" &&
      (pos_char1 == wxString::npos ||
       pos_char2 == wxString::npos ||
       pos_char2 <= pos_char1))
  {
    pos_char1 = text.find(": ");
    pos_char2 = text.rfind(":");
  }

  // If that did not succeed, then get text between ' and '.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    pos_char1 = text.find("'");
    pos_char2 = text.rfind("'");
  }

  wxString out;

  // If we did not find anything.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    // Filter out a possible line number, or ending with : and whitespace.
    try {
      std::match_results<std::string::const_iterator> res;
      std::regex rx("(.+):(([0-9]+)|( *))");
      std::string str(text.c_str());
      std::regex_search(str, res, rx);

      if (res.size() > 0)
      {
        out = wxString(res[1]);
      }
      else
      {
        out = text;
      }
      }
      catch(std::exception& e) {
        wxLogMessage(e.what());
      }
  }
  else
  {
    // Okay, get everything inbetween.
    out = text.substr(pos_char1 + 1, pos_char2 - pos_char1 - 1);
  }

  // And make sure we skip white space.
  out.Trim(true);
  out.Trim(false);

  return out;
}

int wxExLink::GetLineNo(const wxString& text) const
{
  return wxExGetLineNumber(text);
}

const wxString wxExLink::GetPath(const wxString& text) const
{
  const wxString link(FindPath(text));

  if (
    link.empty() ||
    // Otherwise, if you happen to select text that
    // ends with a separator, wx asserts.
    wxFileName::IsPathSeparator(link.Last()))
  {
    return wxEmptyString;
  }

  wxFileName file(link);
  wxString fullpath;

  if (file.FileExists())
  {
    file.MakeAbsolute();
    fullpath = file.GetFullPath();
  }
  else
  {
    if (file.IsRelative())
    {
      if (file.MakeAbsolute(m_STC->GetFileName().GetPath()))
      {
        if (file.FileExists())
        {
          fullpath = file.GetFullPath();
        }
      }
    }

    if (fullpath.empty())
    {
      fullpath = m_PathList.FindAbsoluteValidPath(link);
    }
  }

  return fullpath;
}

void wxExLink::SetFromConfig()
{
  wxStringTokenizer tkz(
    wxConfigBase::Get()->Read(_("Include directory")),
    "\r\n");

  m_PathList.Empty();

  while (tkz.HasMoreTokens())
  {
    m_PathList.Add(tkz.GetNextToken());
  }
}
<commit_msg>fix for mac (no stl regex)<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      link.cpp
// Purpose:   Implementation of class wxExLink
// Author:    Anton van Wezenbeek
// Copyright: (c) 2011 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#ifdef wxExUSE_CPP0X
#include <regex>
#else
#include <wx/regex.h>
#endif
#include <wx/config.h>
#include <wx/tokenzr.h>
#include <wx/extension/link.h>
#include <wx/extension/lexer.h>
#include <wx/extension/stc.h>
#include <wx/extension/util.h>

wxExLink::wxExLink(wxExSTC* stc)
  : m_STC(stc)
{
}

bool wxExLink::AddBasePath()
{
  // Find the base path, if this is not yet on the list, add it.
  const wxString basepath_text = "Basepath: ";
  const int find = m_STC->FindText(
    0,
    1000, // the max pos to look for, this seems enough
    basepath_text);

  if (find == -1)
  {
    return false;
  }

  const int line = m_STC->LineFromPosition(find);

  m_PathList.Add(m_STC->GetTextRange(
    find + basepath_text.length(),
    m_STC->GetLineEndPosition(line) - 3));

  return true;
}

const wxString wxExLink::FindPath(const wxString& text) const
{
  if (
    text.empty() ||
    // wxPathList cannot handle links over several lines.
    wxExGetNumberOfLines(text) > 1)
  {
    return wxEmptyString;
  }

  // Better first try to find "...", then <...>, as in next example.
  // scintilla component.

  // So, first get text between " signs.
  size_t pos_char1 = text.find("\"");
  size_t pos_char2 = text.rfind("\"");

  // If that did not succeed, then get text between < and >.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    pos_char1 = text.find("<");
    pos_char2 = text.rfind(">");
  }

  // If that did not succeed, then get text between : and : (in .po files).
  if (m_STC->GetLexer().GetScintillaLexer() == "po" &&
      (pos_char1 == wxString::npos ||
       pos_char2 == wxString::npos ||
       pos_char2 <= pos_char1))
  {
    pos_char1 = text.find(": ");
    pos_char2 = text.rfind(":");
  }

  // If that did not succeed, then get text between ' and '.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    pos_char1 = text.find("'");
    pos_char2 = text.rfind("'");
  }

  wxString out;

  // If we did not find anything.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    // Filter out a possible line number, or ending with : and whitespace.
#ifdef wxExUSE_CPP0X
    try {
      std::match_results<std::string::const_iterator> res;
      std::regex rx("(.+):(([0-9]+)|( *))");
      std::string str(text.c_str());
      std::regex_search(str, res, rx);

      if (res.size() > 0)
      {
        out = wxString(res[1]);
      }
      else
      {
        out = text;
      }
      }
      catch(std::exception& e) {
        wxLogMessage(e.what());
      }
#else
    wxRegEx regex("(.*):[0-9]*");

    if (regex.Matches(text))
    {
      size_t start, len;

      if (regex.GetMatch(&start, &len, 1))
      {
        out = text.substr(start, len);
      }
      else
      {
        out = text;
      }
    }
    else
    {
      out = text;
    }
#endif
  }
  else
  {
    // Okay, get everything inbetween.
    out = text.substr(pos_char1 + 1, pos_char2 - pos_char1 - 1);
  }

  // And make sure we skip white space.
  out.Trim(true);
  out.Trim(false);

  return out;
}

int wxExLink::GetLineNo(const wxString& text) const
{
  return wxExGetLineNumber(text);
}

const wxString wxExLink::GetPath(const wxString& text) const
{
  const wxString link(FindPath(text));

  if (
    link.empty() ||
    // Otherwise, if you happen to select text that
    // ends with a separator, wx asserts.
    wxFileName::IsPathSeparator(link.Last()))
  {
    return wxEmptyString;
  }

  wxFileName file(link);
  wxString fullpath;

  if (file.FileExists())
  {
    file.MakeAbsolute();
    fullpath = file.GetFullPath();
  }
  else
  {
    if (file.IsRelative())
    {
      if (file.MakeAbsolute(m_STC->GetFileName().GetPath()))
      {
        if (file.FileExists())
        {
          fullpath = file.GetFullPath();
        }
      }
    }

    if (fullpath.empty())
    {
      fullpath = m_PathList.FindAbsoluteValidPath(link);
    }
  }

  return fullpath;
}

void wxExLink::SetFromConfig()
{
  wxStringTokenizer tkz(
    wxConfigBase::Get()->Read(_("Include directory")),
    "\r\n");

  m_PathList.Empty();

  while (tkz.HasMoreTokens())
  {
    m_PathList.Add(tkz.GetNextToken());
  }
}
<|endoftext|>


<commit_before>/// \file ROOT/TFitPanel.cxx
/// \ingroup WebGui ROOT7
/// \author Sergey Linev <S.Linev@gsi.de>
/// \date 2017-10-24
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "ROOT/TFitPanel.hxx"

#include <ROOT/TWebWindowsManager.hxx>
#include <ROOT/TLogger.hxx>
#include "ROOT/TDirectory.hxx"

#include "TString.h"
#include "TROOT.h"
#include "TBufferJSON.h"

std::shared_ptr<ROOT::Experimental::TWebWindow> ROOT::Experimental::TFitPanel::GetWindow()
{
   if (!fWindow) {
      fWindow = TWebWindowsManager::Instance()->CreateWindow(false);

      fWindow->SetPanelName("FitPanel");

      fWindow->SetDataCallBack(std::bind(&TFitPanel::ProcessData, this, std::placeholders::_1, std::placeholders::_2));
   }

   return fWindow;
}

void ROOT::Experimental::TFitPanel::Show(const std::string &where)
{
   GetWindow()->Show(where);
}

void ROOT::Experimental::TFitPanel::Hide()
{
   if (!fWindow) return;

   fWindow->CloseConnections();
}

void ROOT::Experimental::TFitPanel::ProcessData(unsigned connid, const std::string &arg)
{
   if (arg == "CONN_READY") {
      fConnId = connid;
      printf("Connection established %u\n", fConnId);
      fWindow->Send("INITDONE", fConnId);

      TFitPanelModel model;
      model.fDataNames.push_back(ComboBoxItem("1","RootData1"));
      model.fDataNames.push_back(ComboBoxItem("2","RootData2"));
      model.fDataNames.push_back(ComboBoxItem("3","RootData3"));
      model.fSelectDataId = "1";

      model.fModelNames.push_back(ComboBoxItem("1","RootModel1"));
      model.fModelNames.push_back(ComboBoxItem("2","RootModel2"));
      model.fModelNames.push_back(ComboBoxItem("3","RootModel3"));
      model.fSelectModelId = "3";

      TString json = TBufferJSON::ConvertToJSON(&model, gROOT->GetClass("ROOT::Experimental::TFitPanelModel"));

      fWindow->Send(std::string("MODEL:") + json.Data(), fConnId);

      return;
   }

   if (arg == "CONN_CLOSED") {
      printf("Connection closed\n");
      fConnId = 0;
      return;
   }

   if (arg.find("DOFIT:")==0) {
      TString exec;
      exec.Form("((ROOT::Experimental::TFitPanel *) %p)->DoFit(%s);", this, arg.c_str()+6);
      printf("Execute %s\n", exec.Data());
      gROOT->ProcessLine(exec.Data());
      return;
   }
}

void ROOT::Experimental::TFitPanel::UseCanvas(std::shared_ptr<TCanvas> &canv)
{
   if (fCanvas) {
      R__ERROR_HERE("ShowIn") << "FitPanel already bound to the canvas - change is not yet supported";
      return;
   }

   fCanvas = canv;
}

/// method called from the UI
void ROOT::Experimental::TFitPanel::DoFit(const std::string &dname, const std::string &mname)
{
   printf("DoFit %s %s\n", dname.c_str(), mname.c_str());

   bool first_time = false;

   if (!fCanvas) {
      fCanvas = Experimental::TCanvas::Create("FitPanel Canvas");
      first_time = true;
   }

   if (!fFitHist) {

      // Create the histogram.
      auto xaxis = std::make_shared<ROOT::Experimental::TAxisConfig>(10, 0., 10.);

      fFitHist = std::make_shared<ROOT::Experimental::TH1D>(*xaxis.get());

      // Fill a few points.
      fFitHist->Fill(5);
      fFitHist->Fill(6);
      fFitHist->Fill(6);
      fFitHist->Fill(7);

      fCanvas->Draw(fFitHist).SetLineColor(Experimental::TColor::kBlue);

      // workaround to keep histogram in the lists
      ROOT::Experimental::TDirectory::Heap().Add("fitaxis", xaxis);

      if (first_time) {
         fCanvas->Show("opera");
         fCanvas->Update();
      } else {
         printf("Call modified\n");
         fCanvas->Modified();
         printf("Call Update\n");
         fCanvas->Update();
         printf("Done Update\n");
      }
   }
}
<commit_msg>webgui: show new canvas when press fit in fit panel<commit_after>/// \file ROOT/TFitPanel.cxx
/// \ingroup WebGui ROOT7
/// \author Sergey Linev <S.Linev@gsi.de>
/// \date 2017-10-24
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "ROOT/TFitPanel.hxx"

#include <ROOT/TWebWindowsManager.hxx>
#include <ROOT/TLogger.hxx>
#include "ROOT/TDirectory.hxx"

#include "TString.h"
#include "TROOT.h"
#include "TBufferJSON.h"

std::shared_ptr<ROOT::Experimental::TWebWindow> ROOT::Experimental::TFitPanel::GetWindow()
{
   if (!fWindow) {
      fWindow = TWebWindowsManager::Instance()->CreateWindow(false);

      fWindow->SetPanelName("FitPanel");

      fWindow->SetDataCallBack(std::bind(&TFitPanel::ProcessData, this, std::placeholders::_1, std::placeholders::_2));
   }

   return fWindow;
}

void ROOT::Experimental::TFitPanel::Show(const std::string &where)
{
   GetWindow()->Show(where);
}

void ROOT::Experimental::TFitPanel::Hide()
{
   if (!fWindow) return;

   fWindow->CloseConnections();
}

void ROOT::Experimental::TFitPanel::ProcessData(unsigned connid, const std::string &arg)
{
   if (arg == "CONN_READY") {
      fConnId = connid;
      printf("Connection established %u\n", fConnId);
      fWindow->Send("INITDONE", fConnId);

      TFitPanelModel model;
      model.fDataNames.push_back(ComboBoxItem("1","RootData1"));
      model.fDataNames.push_back(ComboBoxItem("2","RootData2"));
      model.fDataNames.push_back(ComboBoxItem("3","RootData3"));
      model.fSelectDataId = "1";

      model.fModelNames.push_back(ComboBoxItem("1","RootModel1"));
      model.fModelNames.push_back(ComboBoxItem("2","RootModel2"));
      model.fModelNames.push_back(ComboBoxItem("3","RootModel3"));
      model.fSelectModelId = "3";

      TString json = TBufferJSON::ConvertToJSON(&model, gROOT->GetClass("ROOT::Experimental::TFitPanelModel"));

      fWindow->Send(std::string("MODEL:") + json.Data(), fConnId);

      return;
   }

   if (arg == "CONN_CLOSED") {
      printf("Connection closed\n");
      fConnId = 0;
      return;
   }

   if (arg.find("DOFIT:")==0) {
      TString exec;
      exec.Form("((ROOT::Experimental::TFitPanel *) %p)->DoFit(%s);", this, arg.c_str()+6);
      printf("Execute %s\n", exec.Data());
      gROOT->ProcessLine(exec.Data());
      return;
   }
}

void ROOT::Experimental::TFitPanel::UseCanvas(std::shared_ptr<TCanvas> &canv)
{
   if (fCanvas) {
      R__ERROR_HERE("ShowIn") << "FitPanel already bound to the canvas - change is not yet supported";
      return;
   }

   fCanvas = canv;
}

/// method called from the UI
void ROOT::Experimental::TFitPanel::DoFit(const std::string &dname, const std::string &mname)
{
   printf("DoFit %s %s\n", dname.c_str(), mname.c_str());

   bool first_time = false;

   if (!fCanvas) {
      fCanvas = Experimental::TCanvas::Create("FitPanel Canvas");
      first_time = true;
   }

   if (!fFitHist) {

      // Create the histogram.
      auto xaxis = std::make_shared<ROOT::Experimental::TAxisConfig>(10, 0., 10.);

      fFitHist = std::make_shared<ROOT::Experimental::TH1D>(*xaxis.get());

      // Fill a few points.
      fFitHist->Fill(5);
      fFitHist->Fill(6);
      fFitHist->Fill(6);
      fFitHist->Fill(7);

      fCanvas->Draw(fFitHist).SetLineColor(Experimental::TColor::kBlue);

      // workaround to keep histogram in the lists
      ROOT::Experimental::TDirectory::Heap().Add("fitaxis", xaxis);

      if (first_time) {
         fCanvas->Show();
         //fCanvas->Update();
      } else {
         fCanvas->Modified();
         //fCanvas->Update();
      }
   }
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All rights reserved.
//
// 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 "timers.h"
#include "internal_macros.h"

#ifdef BENCHMARK_OS_WINDOWS
#include <shlwapi.h>
#undef StrCat  // Don't let StrCat in string_util.h be renamed to lstrcatA
#include <versionhelpers.h>
#include <windows.h>
#else
#include <fcntl.h>
#ifndef BENCHMARK_OS_FUCHSIA
#include <sys/resource.h>
#endif
#include <sys/time.h>
#include <sys/types.h>  // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
#include <unistd.h>
#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX
#include <sys/sysctl.h>
#endif
#if defined(BENCHMARK_OS_MACOSX)
#include <mach/mach_init.h>
#include <mach/mach_port.h>
#include <mach/thread_act.h>
#endif
#endif

#ifdef BENCHMARK_OS_EMSCRIPTEN
#include <emscripten.h>
#endif

#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <limits>
#include <mutex>

#include "check.h"
#include "log.h"
#include "sleep.h"
#include "string_util.h"

namespace benchmark {

// Suppress unused warnings on helper functions.
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wunused-function"
#endif

namespace {
#if defined(BENCHMARK_OS_WINDOWS)
double MakeTime(FILETIME const& kernel_time, FILETIME const& user_time) {
  ULARGE_INTEGER kernel;
  ULARGE_INTEGER user;
  kernel.HighPart = kernel_time.dwHighDateTime;
  kernel.LowPart = kernel_time.dwLowDateTime;
  user.HighPart = user_time.dwHighDateTime;
  user.LowPart = user_time.dwLowDateTime;
  return (static_cast<double>(kernel.QuadPart) +
          static_cast<double>(user.QuadPart)) *
         1e-7;
}
#elif !defined(BENCHMARK_OS_FUCHSIA)
double MakeTime(struct rusage const& ru) {
  return (static_cast<double>(ru.ru_utime.tv_sec) +
          static_cast<double>(ru.ru_utime.tv_usec) * 1e-6 +
          static_cast<double>(ru.ru_stime.tv_sec) +
          static_cast<double>(ru.ru_stime.tv_usec) * 1e-6);
}
#endif
#if defined(BENCHMARK_OS_MACOSX)
double MakeTime(thread_basic_info_data_t const& info) {
  return (static_cast<double>(info.user_time.seconds) +
          static_cast<double>(info.user_time.microseconds) * 1e-6 +
          static_cast<double>(info.system_time.seconds) +
          static_cast<double>(info.system_time.microseconds) * 1e-6);
}
#endif
#if defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_THREAD_CPUTIME_ID)
double MakeTime(struct timespec const& ts) {
  return ts.tv_sec + (static_cast<double>(ts.tv_nsec) * 1e-9);
}
#endif

BENCHMARK_NORETURN static void DiagnoseAndExit(const char* msg) {
  std::cerr << "ERROR: " << msg << std::endl;
  std::exit(EXIT_FAILURE);
}

}  // end namespace

double ProcessCPUUsage() {
#if defined(BENCHMARK_OS_WINDOWS)
  HANDLE proc = GetCurrentProcess();
  FILETIME creation_time;
  FILETIME exit_time;
  FILETIME kernel_time;
  FILETIME user_time;
  if (GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time,
                      &user_time))
    return MakeTime(kernel_time, user_time);
  DiagnoseAndExit("GetProccessTimes() failed");
#elif defined(BENCHMARK_OS_EMSCRIPTEN)
  // clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) returns 0 on Emscripten.
  // Use Emscripten-specific API. Reported CPU time would be exactly the
  // same as total time, but this is ok because there aren't long-latency
  // syncronous system calls in Emscripten.
  return emscripten_get_now() * 1e-3;
#elif defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
  // FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See
  // https://github.com/google/benchmark/pull/292
  struct timespec spec;
  if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &spec) == 0)
    return MakeTime(spec);
  DiagnoseAndExit("clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) failed");
#else
  struct rusage ru;
  if (getrusage(RUSAGE_SELF, &ru) == 0) return MakeTime(ru);
  DiagnoseAndExit("getrusage(RUSAGE_SELF, ...) failed");
#endif
}

double ThreadCPUUsage() {
#if defined(BENCHMARK_OS_WINDOWS)
  HANDLE this_thread = GetCurrentThread();
  FILETIME creation_time;
  FILETIME exit_time;
  FILETIME kernel_time;
  FILETIME user_time;
  GetThreadTimes(this_thread, &creation_time, &exit_time, &kernel_time,
                 &user_time);
  return MakeTime(kernel_time, user_time);
#elif defined(BENCHMARK_OS_MACOSX)
  // FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See
  // https://github.com/google/benchmark/pull/292
  mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
  thread_basic_info_data_t info;
  mach_port_t thread = pthread_mach_thread_np(pthread_self());
  if (thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&info, &count) ==
      KERN_SUCCESS) {
    return MakeTime(info);
  }
  DiagnoseAndExit("ThreadCPUUsage() failed when evaluating thread_info");
#elif defined(BENCHMARK_OS_EMSCRIPTEN)
  // Emscripten doesn't support traditional threads
  return ProcessCPUUsage();
#elif defined(BENCHMARK_OS_RTEMS)
  // RTEMS doesn't support CLOCK_THREAD_CPUTIME_ID. See
  // https://github.com/RTEMS/rtems/blob/master/cpukit/posix/src/clockgettime.c
  return ProcessCPUUsage();
#elif defined(BENCHMARK_OS_SOLARIS)
  struct rusage ru;
  if (getrusage(RUSAGE_LWP, &ru) == 0) return MakeTime(ru);
  DiagnoseAndExit("getrusage(RUSAGE_LWP, ...) failed");
#elif defined(CLOCK_THREAD_CPUTIME_ID)
  struct timespec ts;
  if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) return MakeTime(ts);
  DiagnoseAndExit("clock_gettime(CLOCK_THREAD_CPUTIME_ID, ...) failed");
#else
#error Per-thread timing is not available on your system.
#endif
}

std::string LocalDateTimeString() {
  // Write the local time in RFC3339 format yyyy-mm-ddTHH:MM:SS+/-HH:MM.
  typedef std::chrono::system_clock Clock;
  std::time_t now = Clock::to_time_t(Clock::now());
  const std::size_t kTzOffsetLen = 6;
  const std::size_t kTimestampLen = 19;

  std::size_t tz_len;
  std::size_t timestamp_len;
  long int offset_minutes;
  char tz_offset_sign = '+';
  char tz_offset[kTzOffsetLen + 1];
  char storage[kTimestampLen + kTzOffsetLen + 1];

#if defined(BENCHMARK_OS_WINDOWS)
  std::tm *timeinfo_p = ::localtime(&now);
#else
  std::tm timeinfo;
  std::tm *timeinfo_p = &timeinfo;
  ::localtime_r(&now, &timeinfo);
#endif

  tz_len = std::strftime(tz_offset, sizeof(tz_offset), "%z", timeinfo_p);

  if (tz_len < kTzOffsetLen && tz_len > 1) {
    // Timezone offset was written. strftime writes offset as +HHMM or -HHMM,
    // RFC3339 specifies an offset as +HH:MM or -HH:MM. To convert, we parse
    // the offset as an integer, then reprint it to a string.

    offset_minutes = ::strtol(tz_offset, NULL, 10);
    if (offset_minutes < 0) {
      offset_minutes *= -1;
      tz_offset_sign = '-';
    }
    tz_len = ::sprintf(tz_offset, "%c%02li:%02li", tz_offset_sign,
        offset_minutes / 100, offset_minutes % 100);
    CHECK(tz_len == 6);
    ((void)tz_len); // Prevent unused variable warning in optimized build.
  } else {
    // Unknown offset. RFC3339 specifies that unknown local offsets should be
    // written as UTC time with -00:00 timezone.
#if defined(BENCHMARK_OS_WINDOWS)
    // Potential race condition if another thread calls localtime or gmtime.
    timeinfo_p = ::gmtime(&now);
#else
    ::gmtime_r(&now, &timeinfo);
#endif

    strncpy(tz_offset, "-00:00", kTzOffsetLen + 1);
  }

  timestamp_len = std::strftime(storage, sizeof(storage), "%Y-%m-%dT%H:%M:%S",
      timeinfo_p);
  CHECK(timestamp_len == kTimestampLen);
  ((void)timestamp_len); // Prevent unused variable warning in optimized build.

  std::strncat(storage, tz_offset, kTzOffsetLen + 1);
  return std::string(storage);
}

}  // end namespace benchmark
<commit_msg>timers: silence format overflow warning<commit_after>// Copyright 2015 Google Inc. All rights reserved.
//
// 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 "timers.h"
#include "internal_macros.h"

#ifdef BENCHMARK_OS_WINDOWS
#include <shlwapi.h>
#undef StrCat  // Don't let StrCat in string_util.h be renamed to lstrcatA
#include <versionhelpers.h>
#include <windows.h>
#else
#include <fcntl.h>
#ifndef BENCHMARK_OS_FUCHSIA
#include <sys/resource.h>
#endif
#include <sys/time.h>
#include <sys/types.h>  // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
#include <unistd.h>
#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX
#include <sys/sysctl.h>
#endif
#if defined(BENCHMARK_OS_MACOSX)
#include <mach/mach_init.h>
#include <mach/mach_port.h>
#include <mach/thread_act.h>
#endif
#endif

#ifdef BENCHMARK_OS_EMSCRIPTEN
#include <emscripten.h>
#endif

#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <limits>
#include <mutex>

#include "check.h"
#include "log.h"
#include "sleep.h"
#include "string_util.h"

namespace benchmark {

// Suppress unused warnings on helper functions.
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wunused-function"
#endif

namespace {
#if defined(BENCHMARK_OS_WINDOWS)
double MakeTime(FILETIME const& kernel_time, FILETIME const& user_time) {
  ULARGE_INTEGER kernel;
  ULARGE_INTEGER user;
  kernel.HighPart = kernel_time.dwHighDateTime;
  kernel.LowPart = kernel_time.dwLowDateTime;
  user.HighPart = user_time.dwHighDateTime;
  user.LowPart = user_time.dwLowDateTime;
  return (static_cast<double>(kernel.QuadPart) +
          static_cast<double>(user.QuadPart)) *
         1e-7;
}
#elif !defined(BENCHMARK_OS_FUCHSIA)
double MakeTime(struct rusage const& ru) {
  return (static_cast<double>(ru.ru_utime.tv_sec) +
          static_cast<double>(ru.ru_utime.tv_usec) * 1e-6 +
          static_cast<double>(ru.ru_stime.tv_sec) +
          static_cast<double>(ru.ru_stime.tv_usec) * 1e-6);
}
#endif
#if defined(BENCHMARK_OS_MACOSX)
double MakeTime(thread_basic_info_data_t const& info) {
  return (static_cast<double>(info.user_time.seconds) +
          static_cast<double>(info.user_time.microseconds) * 1e-6 +
          static_cast<double>(info.system_time.seconds) +
          static_cast<double>(info.system_time.microseconds) * 1e-6);
}
#endif
#if defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_THREAD_CPUTIME_ID)
double MakeTime(struct timespec const& ts) {
  return ts.tv_sec + (static_cast<double>(ts.tv_nsec) * 1e-9);
}
#endif

BENCHMARK_NORETURN static void DiagnoseAndExit(const char* msg) {
  std::cerr << "ERROR: " << msg << std::endl;
  std::exit(EXIT_FAILURE);
}

}  // end namespace

double ProcessCPUUsage() {
#if defined(BENCHMARK_OS_WINDOWS)
  HANDLE proc = GetCurrentProcess();
  FILETIME creation_time;
  FILETIME exit_time;
  FILETIME kernel_time;
  FILETIME user_time;
  if (GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time,
                      &user_time))
    return MakeTime(kernel_time, user_time);
  DiagnoseAndExit("GetProccessTimes() failed");
#elif defined(BENCHMARK_OS_EMSCRIPTEN)
  // clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) returns 0 on Emscripten.
  // Use Emscripten-specific API. Reported CPU time would be exactly the
  // same as total time, but this is ok because there aren't long-latency
  // syncronous system calls in Emscripten.
  return emscripten_get_now() * 1e-3;
#elif defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
  // FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See
  // https://github.com/google/benchmark/pull/292
  struct timespec spec;
  if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &spec) == 0)
    return MakeTime(spec);
  DiagnoseAndExit("clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) failed");
#else
  struct rusage ru;
  if (getrusage(RUSAGE_SELF, &ru) == 0) return MakeTime(ru);
  DiagnoseAndExit("getrusage(RUSAGE_SELF, ...) failed");
#endif
}

double ThreadCPUUsage() {
#if defined(BENCHMARK_OS_WINDOWS)
  HANDLE this_thread = GetCurrentThread();
  FILETIME creation_time;
  FILETIME exit_time;
  FILETIME kernel_time;
  FILETIME user_time;
  GetThreadTimes(this_thread, &creation_time, &exit_time, &kernel_time,
                 &user_time);
  return MakeTime(kernel_time, user_time);
#elif defined(BENCHMARK_OS_MACOSX)
  // FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See
  // https://github.com/google/benchmark/pull/292
  mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
  thread_basic_info_data_t info;
  mach_port_t thread = pthread_mach_thread_np(pthread_self());
  if (thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&info, &count) ==
      KERN_SUCCESS) {
    return MakeTime(info);
  }
  DiagnoseAndExit("ThreadCPUUsage() failed when evaluating thread_info");
#elif defined(BENCHMARK_OS_EMSCRIPTEN)
  // Emscripten doesn't support traditional threads
  return ProcessCPUUsage();
#elif defined(BENCHMARK_OS_RTEMS)
  // RTEMS doesn't support CLOCK_THREAD_CPUTIME_ID. See
  // https://github.com/RTEMS/rtems/blob/master/cpukit/posix/src/clockgettime.c
  return ProcessCPUUsage();
#elif defined(BENCHMARK_OS_SOLARIS)
  struct rusage ru;
  if (getrusage(RUSAGE_LWP, &ru) == 0) return MakeTime(ru);
  DiagnoseAndExit("getrusage(RUSAGE_LWP, ...) failed");
#elif defined(CLOCK_THREAD_CPUTIME_ID)
  struct timespec ts;
  if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) return MakeTime(ts);
  DiagnoseAndExit("clock_gettime(CLOCK_THREAD_CPUTIME_ID, ...) failed");
#else
#error Per-thread timing is not available on your system.
#endif
}

std::string LocalDateTimeString() {
  // Write the local time in RFC3339 format yyyy-mm-ddTHH:MM:SS+/-HH:MM.
  typedef std::chrono::system_clock Clock;
  std::time_t now = Clock::to_time_t(Clock::now());
  const std::size_t kTzOffsetLen = 6;
  const std::size_t kTimestampLen = 19;

  std::size_t tz_len;
  std::size_t timestamp_len;
  long int offset_minutes;
  char tz_offset_sign = '+';
  char tz_offset[kTzOffsetLen + 1];
  char storage[kTimestampLen + kTzOffsetLen + 1];

#if defined(BENCHMARK_OS_WINDOWS)
  std::tm *timeinfo_p = ::localtime(&now);
#else
  std::tm timeinfo;
  std::tm *timeinfo_p = &timeinfo;
  ::localtime_r(&now, &timeinfo);
#endif

  tz_len = std::strftime(tz_offset, sizeof(tz_offset), "%z", timeinfo_p);

  if (tz_len < kTzOffsetLen && tz_len > 1) {
    // Timezone offset was written. strftime writes offset as +HHMM or -HHMM,
    // RFC3339 specifies an offset as +HH:MM or -HH:MM. To convert, we parse
    // the offset as an integer, then reprint it to a string.

    offset_minutes = ::strtol(tz_offset, NULL, 10);
    if (offset_minutes < 0) {
      offset_minutes *= -1;
      tz_offset_sign = '-';
    }

    // Apply % 100 to hour to guarantee range [0, 99].
    tz_len = ::sprintf(tz_offset, "%c%02li:%02li", tz_offset_sign,
        (offset_minutes / 100) % 100, offset_minutes % 100);
    CHECK(tz_len == 6);
    ((void)tz_len); // Prevent unused variable warning in optimized build.
  } else {
    // Unknown offset. RFC3339 specifies that unknown local offsets should be
    // written as UTC time with -00:00 timezone.
#if defined(BENCHMARK_OS_WINDOWS)
    // Potential race condition if another thread calls localtime or gmtime.
    timeinfo_p = ::gmtime(&now);
#else
    ::gmtime_r(&now, &timeinfo);
#endif

    strncpy(tz_offset, "-00:00", kTzOffsetLen + 1);
  }

  timestamp_len = std::strftime(storage, sizeof(storage), "%Y-%m-%dT%H:%M:%S",
      timeinfo_p);
  CHECK(timestamp_len == kTimestampLen);
  ((void)timestamp_len); // Prevent unused variable warning in optimized build.

  std::strncat(storage, tz_offset, kTzOffsetLen + 1);
  return std::string(storage);
}

}  // end namespace benchmark
<|endoftext|>


<commit_before>#include <iostream>
#include "tools.h"

using Eigen::VectorXd;
using Eigen::MatrixXd;
using std::vector;

Tools::Tools() {}

Tools::~Tools() {}

VectorXd Tools::CalculateRMSE(const vector<VectorXd> &estimations,
                              const vector<VectorXd> &ground_truth) {
  VectorXd rmse(4);
  rmse << 0, 0, 0, 0;

  // check the validity of the following inputs:
  //  * the estimation vector size should not be zero
  //  * the estimation vector size should equal ground truth vector size
  if(estimations.size() == 0 || estimations.size() != ground_truth.size()) {
    std::cout << "calculateRMSE() - Error - Invalid Estimations vector size" << std::endl;
    return rmse;
  }

  //accumulate squared residuals
  VectorXd sum(4);
  sum << 0, 0, 0, 0;

  for(int i = 0; i < estimations.size(); ++i) {
    VectorXd estimated = estimations[i];
    VectorXd actual = ground_truth[i];

    VectorXd diff = (estimated - actual);
    //coefficient-wise multiplication
    diff = diff.array() * diff.array();
    sum = sum + diff;
  }

  //calculate the mean
  Eigen::VectorXd mean = sum / estimations.size();

  //calculate the squared root
  rmse = mean.array().sqrt();

  return rmse;
}

float Tools::NormalizeAngle(float angle_rad) {
  //angle normalization
    while (angle_rad > M_PI)
      angle_rad -= 2.*M_PI;

    while (angle_rad < -M_PI)
      angle_rad += 2. * M_PI;

    return angle_rad;
}
<commit_msg>refactor: Replaced NormalizeAngle() with a better implementation<commit_after>#include <iostream>
#include "tools.h"

using Eigen::VectorXd;
using Eigen::MatrixXd;
using std::vector;

Tools::Tools() {}

Tools::~Tools() {}

VectorXd Tools::CalculateRMSE(const vector<VectorXd> &estimations,
                              const vector<VectorXd> &ground_truth) {
  VectorXd rmse(4);
  rmse << 0, 0, 0, 0;

  // check the validity of the following inputs:
  //  * the estimation vector size should not be zero
  //  * the estimation vector size should equal ground truth vector size
  if(estimations.size() == 0 || estimations.size() != ground_truth.size()) {
    std::cout << "calculateRMSE() - Error - Invalid Estimations vector size" << std::endl;
    return rmse;
  }

  //accumulate squared residuals
  VectorXd sum(4);
  sum << 0, 0, 0, 0;

  for(int i = 0; i < estimations.size(); ++i) {
    VectorXd estimated = estimations[i];
    VectorXd actual = ground_truth[i];

    VectorXd diff = (estimated - actual);
    //coefficient-wise multiplication
    diff = diff.array() * diff.array();
    sum = sum + diff;
  }

  //calculate the mean
  Eigen::VectorXd mean = sum / estimations.size();

  //calculate the squared root
  rmse = mean.array().sqrt();

  return rmse;
}

float Tools::NormalizeAngle(float angle_rad) {
  angle_rad = angle_rad - 2*M_PI*floor((angle_rad+ M_PI)/(2 * M_PI ));
  return angle_rad;
}
//float Tools::NormalizeAngle(float angle_rad) {
//  //angle normalization
//    while (angle_rad > M_PI)
//      angle_rad -= 2.*M_PI;
//
//    while (angle_rad < -M_PI)
//      angle_rad += 2. * M_PI;
//
//    return angle_rad;
//}
<|endoftext|>


<commit_before>#include "ModelEditor.hpp"
#include <Engine/Geometry/Model.hpp>
#include "../FileSelector.hpp"
#include <functional>
#include <Engine/Hymn.hpp>
#include <Engine/Util/FileSystem.hpp>
#include <imgui.h>
#include "Util/AssetMetaData.hpp"
#include <Utility/Log.hpp>
#include "../../Resources.hpp"

using namespace GUI;

ModelEditor::ModelEditor() {
    name[0] = '\0';
}

void ModelEditor::Show() {
    if (ImGui::Begin(("Model: " + model->name + "###" + std::to_string(reinterpret_cast<uintptr_t>(model))).c_str(), &visible, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_ShowBorders)) {
        if (ImGui::InputText("Name", name, 128, ImGuiInputTextFlags_EnterReturnsTrue)) {
            model->name = name;

            // Rename all the files.
            if (FileSystem::FileExists((destination + ".fbx").c_str())) {
                FileSystem::Rename(destination + ".fbx", std::string(name) + ".fbx");

                if (FileSystem::FileExists((destination + ".asset").c_str()))
                    FileSystem::Rename(destination + ".asset", std::string(name) + ".asset");

                if (FileSystem::FileExists((destination + ".asset.meta").c_str()))
                    FileSystem::Rename(destination + ".asset.meta", std::string(name) + ".asset.meta");

                destination = Hymn().GetPath() + FileSystem::DELIMITER + "Models" + FileSystem::DELIMITER + name;
            }
        }

        if (ImGui::Button("Open model")) {
            // Currently only fbx is tested.
            fileSelector.AddExtensions("fbx");

            // Set the initial path to the models directory.
            fileSelector.SetInitialPath((Hymn().GetPath() + FileSystem::DELIMITER + "Models").c_str());
            fileSelector.SetFileSelectedCallback(std::bind(&ModelEditor::FileSelected, this, std::placeholders::_1));
            fileSelector.SetVisible(true);
        }

        if (hasSourceFile) {
            ImGui::Text("Mesh Data");
            ImGui::Checkbox("Uniform Scaling", &uniformScaling);

            if (uniformScaling) {
                float uniScale = scale.x;
                ImGui::DragFloat("Scale", &uniScale, 0.01f);
                scale = glm::vec3(uniScale);
            } else
                ImGui::DragFloat3("Scale", &scale[0], 0.01f);

            ImGui::Checkbox("Triangulate", &triangulate);
            ImGui::Checkbox("Import Normals", &importNormals);
            ImGui::Checkbox("Import Tangents", &importTangents);
            ImGui::Checkbox("Import Textures", &importTextures);
            ImGui::Checkbox("Import Tangents", &importTangents);
            ImGui::Checkbox("Flip UVs", &flipUVs);

            std::string button = isImported ? "Re-import" : "Import";

            if (ImGui::Button(button.c_str())) {
                // Convert to .asset format.
                AssetConverter asset;
                asset.Convert(source.c_str(), (destination + ".asset").c_str(), scale, triangulate, importNormals, importTangents, importTextures, flipUVs);
                model->Load(destination.c_str());
                msgString = asset.Success() ? "Success\n" : asset.GetErrorString();
                isImported = true;

                // Generate meta data.
                AssetMetaData::MeshImportData * importData = new AssetMetaData::MeshImportData;
                importData->triangulate = triangulate;
                importData->importNormals = importNormals;
                importData->importTangents = importTangents;
                AssetMetaData::GenerateMetaData((destination + ".asset.meta").c_str(), importData);

                delete importData;
                importData = nullptr;
            }

            ImGui::Text("Material Data");
            if (ImGui::Button("Import material")) {

            }

            if (isImported)
                ImGui::Text(msgString.c_str());
        }
    }
    ImGui::End();

    if (fileSelector.IsVisible())
        fileSelector.Show();
}

const Geometry::Model* ModelEditor::GetModel() const {
    return model;
}

void ModelEditor::SetModel(Geometry::Model* model) {
    this->model = model;

    strcpy(name, model->name.c_str());

    destination = Hymn().GetPath() + "/" + model->path + name;

    RefreshImportSettings();
}

bool ModelEditor::IsVisible() const {
    return visible;
}

void ModelEditor::SetVisible(bool visible) {
    this->visible = visible;
}

void ModelEditor::FileSelected(const std::string& file) {
    std::string name = FileSystem::GetName(file).c_str();

    // Checking so that the file isn't imported twice.
    /// @todo Overwrite option?
    /// @todo Reimplement this.
    /*for (int i = 0; i < Resources().models.size(); ++i) {
        if (Resources().models[i]->name == name) {
            Log() << "File " << name << " is already added to project.\n";
            isImported = false;
            hasSourceFile = false;
            return;
        }
    }*/

    source = file;

    // Rename the model to the name of the source file.
    strcpy(this->name, name.c_str());
    model->name = this->name;

    destination = Hymn().GetPath() + "/" + model->path + name;

    // Check if source file is in proper directory, otherwise, copy it.
    if (!FileSystem::FileExists((destination + "." + FileSystem::GetExtension(source)).c_str()))
        FileSystem::Copy(source.c_str(), (destination + "." + FileSystem::GetExtension(source)).c_str());

    hasSourceFile = true;

    RefreshImportSettings();
}

void GUI::ModelEditor::RefreshImportSettings() {
    // Check if the source file exist, currently only .fbx is supported.
    if (!FileSystem::FileExists((destination + ".fbx").c_str())) {
        hasSourceFile = false;
        isImported = false;
        return;
    }

    // Check if meta file already exists. If it does import the metadata.
    std::string filePath(destination + ".asset.meta");
    if (FileSystem::FileExists(filePath.c_str())) {
        AssetMetaData::MeshImportData * importData = AssetMetaData::GetMetaData(filePath.c_str());
        triangulate = importData->triangulate;
        importNormals = importData->importNormals;
        importTangents = importData->importTangents;

        delete importData;
        isImported = true;
    } else {
        isImported = false;
    }
}
<commit_msg>Remove duplicate checkbox<commit_after>#include "ModelEditor.hpp"
#include <Engine/Geometry/Model.hpp>
#include "../FileSelector.hpp"
#include <functional>
#include <Engine/Hymn.hpp>
#include <Engine/Util/FileSystem.hpp>
#include <imgui.h>
#include "Util/AssetMetaData.hpp"
#include <Utility/Log.hpp>
#include "../../Resources.hpp"

using namespace GUI;

ModelEditor::ModelEditor() {
    name[0] = '\0';
}

void ModelEditor::Show() {
    if (ImGui::Begin(("Model: " + model->name + "###" + std::to_string(reinterpret_cast<uintptr_t>(model))).c_str(), &visible, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_ShowBorders)) {
        if (ImGui::InputText("Name", name, 128, ImGuiInputTextFlags_EnterReturnsTrue)) {
            model->name = name;

            // Rename all the files.
            if (FileSystem::FileExists((destination + ".fbx").c_str())) {
                FileSystem::Rename(destination + ".fbx", std::string(name) + ".fbx");

                if (FileSystem::FileExists((destination + ".asset").c_str()))
                    FileSystem::Rename(destination + ".asset", std::string(name) + ".asset");

                if (FileSystem::FileExists((destination + ".asset.meta").c_str()))
                    FileSystem::Rename(destination + ".asset.meta", std::string(name) + ".asset.meta");

                destination = Hymn().GetPath() + FileSystem::DELIMITER + "Models" + FileSystem::DELIMITER + name;
            }
        }

        if (ImGui::Button("Open model")) {
            // Currently only fbx is tested.
            fileSelector.AddExtensions("fbx");

            // Set the initial path to the models directory.
            fileSelector.SetInitialPath((Hymn().GetPath() + FileSystem::DELIMITER + "Models").c_str());
            fileSelector.SetFileSelectedCallback(std::bind(&ModelEditor::FileSelected, this, std::placeholders::_1));
            fileSelector.SetVisible(true);
        }

        if (hasSourceFile) {
            ImGui::Text("Mesh Data");
            ImGui::Checkbox("Uniform Scaling", &uniformScaling);

            if (uniformScaling) {
                float uniScale = scale.x;
                ImGui::DragFloat("Scale", &uniScale, 0.01f);
                scale = glm::vec3(uniScale);
            } else
                ImGui::DragFloat3("Scale", &scale[0], 0.01f);

            ImGui::Checkbox("Triangulate", &triangulate);
            ImGui::Checkbox("Import Normals", &importNormals);
            ImGui::Checkbox("Import Tangents", &importTangents);
            ImGui::Checkbox("Import Textures", &importTextures);
            ImGui::Checkbox("Flip UVs", &flipUVs);

            std::string button = isImported ? "Re-import" : "Import";

            if (ImGui::Button(button.c_str())) {
                // Convert to .asset format.
                AssetConverter asset;
                asset.Convert(source.c_str(), (destination + ".asset").c_str(), scale, triangulate, importNormals, importTangents, importTextures, flipUVs);
                model->Load(destination.c_str());
                msgString = asset.Success() ? "Success\n" : asset.GetErrorString();
                isImported = true;

                // Generate meta data.
                AssetMetaData::MeshImportData * importData = new AssetMetaData::MeshImportData;
                importData->triangulate = triangulate;
                importData->importNormals = importNormals;
                importData->importTangents = importTangents;
                AssetMetaData::GenerateMetaData((destination + ".asset.meta").c_str(), importData);

                delete importData;
                importData = nullptr;
            }

            ImGui::Text("Material Data");
            if (ImGui::Button("Import material")) {

            }

            if (isImported)
                ImGui::Text(msgString.c_str());
        }
    }
    ImGui::End();

    if (fileSelector.IsVisible())
        fileSelector.Show();
}

const Geometry::Model* ModelEditor::GetModel() const {
    return model;
}

void ModelEditor::SetModel(Geometry::Model* model) {
    this->model = model;

    strcpy(name, model->name.c_str());

    destination = Hymn().GetPath() + "/" + model->path + name;

    RefreshImportSettings();
}

bool ModelEditor::IsVisible() const {
    return visible;
}

void ModelEditor::SetVisible(bool visible) {
    this->visible = visible;
}

void ModelEditor::FileSelected(const std::string& file) {
    std::string name = FileSystem::GetName(file).c_str();

    // Checking so that the file isn't imported twice.
    /// @todo Overwrite option?
    /// @todo Reimplement this.
    /*for (int i = 0; i < Resources().models.size(); ++i) {
        if (Resources().models[i]->name == name) {
            Log() << "File " << name << " is already added to project.\n";
            isImported = false;
            hasSourceFile = false;
            return;
        }
    }*/

    source = file;

    // Rename the model to the name of the source file.
    strcpy(this->name, name.c_str());
    model->name = this->name;

    destination = Hymn().GetPath() + "/" + model->path + name;

    // Check if source file is in proper directory, otherwise, copy it.
    if (!FileSystem::FileExists((destination + "." + FileSystem::GetExtension(source)).c_str()))
        FileSystem::Copy(source.c_str(), (destination + "." + FileSystem::GetExtension(source)).c_str());

    hasSourceFile = true;

    RefreshImportSettings();
}

void GUI::ModelEditor::RefreshImportSettings() {
    // Check if the source file exist, currently only .fbx is supported.
    if (!FileSystem::FileExists((destination + ".fbx").c_str())) {
        hasSourceFile = false;
        isImported = false;
        return;
    }

    // Check if meta file already exists. If it does import the metadata.
    std::string filePath(destination + ".asset.meta");
    if (FileSystem::FileExists(filePath.c_str())) {
        AssetMetaData::MeshImportData * importData = AssetMetaData::GetMetaData(filePath.c_str());
        triangulate = importData->triangulate;
        importNormals = importData->importNormals;
        importTangents = importData->importTangents;

        delete importData;
        isImported = true;
    } else {
        isImported = false;
    }
}
<|endoftext|>


<commit_before>#include "SceneEditor.hpp"

#include <Engine/Hymn.hpp>
#include <Engine/Util/FileSystem.hpp>
#include <Engine/Util/Log.hpp>
#include <imgui.h>

using namespace GUI;

void SceneEditor::Show() {
    if (ImGui::Begin(("Scene: " + Hymn().scenes[sceneIndex] + "###Scene").c_str(), &visible)) {
        ImGui::InputText("Name", name, 128);
        Hymn().scenes[sceneIndex] = name;

        // Entities.
        entityPressed = false;
        ShowEntity(Hymn().world.GetRoot());
    }
    ImGui::End();
}

void SceneEditor::SetScene(std::size_t sceneIndex) {
    if (sceneIndex < Hymn().scenes.size()) {
        this->sceneIndex = sceneIndex;
        strcpy(name, Hymn().scenes[sceneIndex].c_str());
    }
}

bool SceneEditor::IsVisible() const {
    return visible;
}

void SceneEditor::SetVisible(bool visible) {
    this->visible = visible;
}

void SceneEditor::Save() const {
    if (sceneIndex < Hymn().scenes.size())
        Hymn().world.Save(Hymn().GetPath() + FileSystem::DELIMITER + "Scenes" + FileSystem::DELIMITER + Hymn().scenes[sceneIndex] + ".json");
}

void SceneEditor::ShowEntity(Entity* entity) {
    if (ImGui::TreeNode(entity->name.c_str())) {
        if (ImGui::Button("Edit")) {
            entityPressed = true;
            entityEditor.SetEntity(entity);
        }

        if (!entity->IsScene()) {
            if (ImGui::Button("Add child"))
                entity->AddChild("Entity #" + std::to_string(Hymn().entityNumber++));

            if (ImGui::Button("Instantiate scene"))
                ImGui::OpenPopup("Select scene");

            if (ImGui::BeginPopup("Select scene")) {
                ImGui::Text("Scenes");
                ImGui::Separator();

                for (const std::string& scene : Hymn().scenes) {
                    if (ImGui::Selectable(scene.c_str()))
                        entity->InstantiateScene(scene);
                }

                ImGui::EndPopup();
            }
        }

        if (entity != Hymn().world.GetRoot())
            if (ImGui::Button("Delete"))
                entity->Kill();

        if (!entity->IsScene()) {
            for (Entity* child : entity->GetChildren()) {
                ShowEntity(child);
            }
        }

        ImGui::TreePop();
    }
}
<commit_msg>Close entity editor when setting scene<commit_after>#include "SceneEditor.hpp"

#include <Engine/Hymn.hpp>
#include <Engine/Util/FileSystem.hpp>
#include <Engine/Util/Log.hpp>
#include <imgui.h>

using namespace GUI;

void SceneEditor::Show() {
    if (ImGui::Begin(("Scene: " + Hymn().scenes[sceneIndex] + "###Scene").c_str(), &visible)) {
        ImGui::InputText("Name", name, 128);
        Hymn().scenes[sceneIndex] = name;

        // Entities.
        entityPressed = false;
        ShowEntity(Hymn().world.GetRoot());
    }
    ImGui::End();
}

void SceneEditor::SetScene(std::size_t sceneIndex) {
    entityEditor.SetVisible(false);

    if (sceneIndex < Hymn().scenes.size()) {
        this->sceneIndex = sceneIndex;
        strcpy(name, Hymn().scenes[sceneIndex].c_str());
    }
}

bool SceneEditor::IsVisible() const {
    return visible;
}

void SceneEditor::SetVisible(bool visible) {
    this->visible = visible;
}

void SceneEditor::Save() const {
    if (sceneIndex < Hymn().scenes.size())
        Hymn().world.Save(Hymn().GetPath() + FileSystem::DELIMITER + "Scenes" + FileSystem::DELIMITER + Hymn().scenes[sceneIndex] + ".json");
}

void SceneEditor::ShowEntity(Entity* entity) {
    if (ImGui::TreeNode(entity->name.c_str())) {
        if (ImGui::Button("Edit")) {
            entityPressed = true;
            entityEditor.SetEntity(entity);
        }

        if (!entity->IsScene()) {
            if (ImGui::Button("Add child"))
                entity->AddChild("Entity #" + std::to_string(Hymn().entityNumber++));

            if (ImGui::Button("Instantiate scene"))
                ImGui::OpenPopup("Select scene");

            if (ImGui::BeginPopup("Select scene")) {
                ImGui::Text("Scenes");
                ImGui::Separator();

                for (const std::string& scene : Hymn().scenes) {
                    if (ImGui::Selectable(scene.c_str()))
                        entity->InstantiateScene(scene);
                }

                ImGui::EndPopup();
            }
        }

        if (entity != Hymn().world.GetRoot())
            if (ImGui::Button("Delete"))
                entity->Kill();

        if (!entity->IsScene()) {
            for (Entity* child : entity->GetChildren()) {
                ShowEntity(child);
            }
        }

        ImGui::TreePop();
    }
}
<|endoftext|>


<commit_before>using namespace std;

#define COUNTOF(x) (sizeof(x)/sizeof(*x))

extern string S;
extern long SA[];

/*
*
*
*/

struct interval_t {
	long start, end;
};

struct triplet_t {
	long index;
	struct interval_t interval;
};

/**
* Returns left bound of interval.
* Searches input string (S) for suffixes having "comparing_character" at "query_offset",
* using suffix array (SA).
*/
long binary_search_left (char comparing_character, long query_offset, long start_interval, long end_interval) {
	if (comparing_character == S[SA[start_interval] + query_offset]) {
		return start_interval;
	}

	long middle;
	while ((end_interval - start_interval) > 1) {
		middle = (end_interval + start_interval) / 2;
		if (comparing_character <= S[SA[middle] + query_offset]) {
			end_interval = middle;
		} else {
			start_interval = middle;
		}
	}

	return end_interval;
}

/**
* Returns right bound of interval.
* Searches input string (S) for suffixes having "comparing_character" at "query_offset",
* using suffix array (SA).
*/
long binary_search_right (char comparing_character, long query_offset, long start_interval, long end_interval) {
	if (comparing_character == S[SA[end_interval] + query_offset]){
		return end_interval;
	}

	long middle;
	while ((end_interval - start_interval) > 1) {
		middle = (end_interval + start_interval) / 2;
		if (comparing_character < S[SA[middle] + query_offset]) {
			end_interval = middle;
		} else {
			start_interval = middle;
		}
	}

	return start_interval;
}

/**
* Returns interval containing "compairing_character" if it exists, else returns not_found
* It uses binary_search to find both boundaries (in suffix array).
*/

triplet_t topdown_search (char comparing_character, long query_offset, long start_interval, long end_interval) {
	triplet_t not_found = {-1, {0, 0}};
	triplet_t interval;

	long lower_bound, upper_bound;

	if (comparing_character < S[SA[start_interval] + query_offset]){
		return not_found;
	}
	if (comparing_character > S[SA[end_interval] + query_offset]){
		return not_found;
	}

	lower_bound = binary_search_left (comparing_character, query_offset, start_interval, end_interval);
	upper_bound = binary_search_right (comparing_character, query_offset, start_interval, end_interval);

	if (lower_bound > upper_bound) {
		return not_found;
	}

	interval = {query_offset + 1, {lower_bound, upper_bound}};
	return interval;
}

interval_t search_string(string query_string) {
	long query_index = 0;
	long start_interval = 0; // TODO: refactor names
	long end_interval = 11; // TODO: use dinamyc information!

	triplet_t triplet;
	interval_t empty_interval = {0, 0};

	while (query_index < query_string.length()) {
		triplet = topdown_search (query_string[query_index],
					query_index,
					start_interval,
					end_interval);
		if (triplet.index == -1) {
			return empty_interval;
		}

		query_index = triplet.index;
		start_interval = triplet.interval.start;
		end_interval = triplet.interval.end;
	}

	return triplet.interval;
}

<commit_msg>sudo-code for serch algorithms<commit_after>using namespace std;

#define COUNTOF(x) (sizeof(x)/sizeof(*x))

extern string S;
extern long SA[];

/*
*
*
*/

struct interval_t {
	long start, end;
};

struct triplet_t {
	long index;
	struct interval_t interval;
};

/**
* Returns left bound of interval.
* Searches input string (S) for suffixes having "comparing_character" at "query_offset",
* using suffix array (SA).
*/
long binary_search_left (char comparing_character, long query_offset, long start_interval, long end_interval) {
	if (comparing_character == S[SA[start_interval] + query_offset]) {
		return start_interval;
	}

	long middle;
	while ((end_interval - start_interval) > 1) {
		middle = (end_interval + start_interval) / 2;
		if (comparing_character <= S[SA[middle] + query_offset]) {
			end_interval = middle;
		} else {
			start_interval = middle;
		}
	}

	return end_interval;
}

/**
* Returns right bound of interval.
* Searches input string (S) for suffixes having "comparing_character" at "query_offset",
* using suffix array (SA).
*/
long binary_search_right (char comparing_character, long query_offset, long start_interval, long end_interval) {
	if (comparing_character == S[SA[end_interval] + query_offset]){
		return end_interval;
	}

	long middle;
	while ((end_interval - start_interval) > 1) {
		middle = (end_interval + start_interval) / 2;
		if (comparing_character < S[SA[middle] + query_offset]) {
			end_interval = middle;
		} else {
			start_interval = middle;
		}
	}

	return start_interval;
}

/**
* Returns interval containing "compairing_character" if it exists, else returns not_found
* It uses binary_search to find both boundaries (in suffix array).
*/

triplet_t topdown_search (char comparing_character, long query_offset, long start_interval, long end_interval) {
	triplet_t not_found = {-1, {0, 0}};
	triplet_t interval;

	long lower_bound, upper_bound;

	if (comparing_character < S[SA[start_interval] + query_offset]){
		return not_found;
	}
	if (comparing_character > S[SA[end_interval] + query_offset]){
		return not_found;
	}

	lower_bound = binary_search_left (comparing_character, query_offset, start_interval, end_interval);
	upper_bound = binary_search_right (comparing_character, query_offset, start_interval, end_interval);

	if (lower_bound > upper_bound) {
		return not_found;
	}

	interval = {query_offset + 1, {lower_bound, upper_bound}};
	return interval;
}

interval_t search_string(string query_string) {
	long query_index = 0;
	long start_interval = 0; // TODO: refactor names
	long end_interval = 11; // TODO: use dinamyc information!

	triplet_t triplet;
	interval_t empty_interval = {0, 0};

	while (query_index < query_string.length()) {
		triplet = topdown_search (query_string[query_index],
					query_index,
					start_interval,
					end_interval);
		if (triplet.index == -1) {
			return empty_interval;
		}

		query_index = triplet.index;
		start_interval = triplet.interval.start;
		end_interval = triplet.interval.end;
	}

	return triplet.interval;
}

/*
triplet_t traverse(p, d:[s..e], M) {
	while (p + d < P.length()){
		d2 : [s2..e2] = topdown(P[p+d], d:[s..e])
		if (d2 == empty_interval)
			return d:[s..e]

		d : [s..e] = d2 : [s2..e2]
		if (d >= M)
			break;
	}

	return d:[s..e];
}

void findL (p, i, q){
	for (k = 0; k < K; k += 1){
		if (p == 0 or i == 0){
			MEM at i in S, p in P, length q;
			return ;
		}

		if (P[p-1] != S[i-1] and q >= L){
			MEM at i in S, p in P, length q;
			return ;
		}

		p -= 1;
		i -= 1;
		q += 1;
	}
}

void collect_MEMs (p, d:[s..e], q:[l..r]){
	for (i = l; i < r; i += 1)
		findL (p, SA[i], q);

	while q >= d
		if r + 1 < n/K
			q = max (LCP[l], LCP[r + 1]);
		else q = LCP[l];

		if q >= d
			while LCP[l] >= q
				l = l-1
				findL (p, SA[l], q)
			while r+1 < n/K and LCP[r + 1] >= q
				r += 1
				findL (p, SA[r], q);

	return ;
}

void find_MEMs(p0) {
	d:[s..e] = q:[l..r] = 0:[0..n / (K-1)]
	p = p0
	while p < (P.length() - (K- p0))
		d:[s..e] = traverse(p, d:[s..e], L - (K - 1))
		q:[l..r] = traverse(p, q:[l..r], P.length())

		if d <= 1
			d:[s..e] = q:[l..r] = 0:[0..n / (K-1)]
			p = p + K
			continue

		if d >= (L - (K - 1))
			collect_MEMS(p, d:[s..e], q:[l..r])

		p += K

		d:[s..e] = suffix_link (d:[s..e])
		q:[l..r] = suffix_link (q:[l..r])

		if d == empty
			d:[s..e] = q:[l..r] = 0:[0..n / (K-1)]
			continue
}

*/

<|endoftext|>