<commit_before>/*!
    \file record.inl
    \brief Logging record inline implementation
    \author Ivan Shynkarenka
    \date 08.07.2016
    \copyright MIT License
*/

namespace CppLogging {

//! @cond INTERNALS
namespace Internals {

template <typename Char, typename T>
std::size_t CalculateExtraSize(const fmt::internal::Arg& arg)
{
    std::size_t result = 0;

    if (arg.type == fmt::internal::Arg::CSTRING)
        result = sizeof(std::size_t) + (std::strlen(arg.string.value) + 1) * sizeof(char);
    else if (arg.type == fmt::internal::Arg::STRING)
        result = sizeof(std::size_t) + arg.string.size * sizeof(char);
    else if (arg.type == fmt::internal::Arg::WSTRING)
        result = sizeof(std::size_t) + arg.wstring.size * sizeof(wchar_t);
    else if (arg.type == fmt::internal::Arg::CUSTOM)
        result = sizeof(T);

    return result;
}

template <typename Char>
unsigned CalculateBufferSize(std::size_t&)
{
    return 0;
}

template <typename Char, typename T>
unsigned CalculateBufferSize(std::size_t& extra_size, const T& argument)
{
    fmt::internal::MakeArg<fmt::BasicFormatter<Char>> arg(argument);
    extra_size += CalculateExtraSize<Char, T>(arg);
    return 1;
}

template <typename Char, typename T>
unsigned CalculateBufferSize(std::size_t& extra_size, const fmt::internal::NamedArgWithType<Char, T>& argument)
{
    extra_size += sizeof(fmt::internal::NamedArgWithType<Char, T>) + sizeof(std::size_t) + argument.name.size() * sizeof(Char) + CalculateExtraSize<Char, fmt::internal::NamedArgWithType<Char, T>>(argument);
    return 1;
}

template <typename Char, typename T, typename... Args>
unsigned CalculateBufferSize(std::size_t& extra_size, const T& argument, const Args&... args)
{
    unsigned count = 0;
    count += CalculateBufferSize<Char>(extra_size, argument);
    count += CalculateBufferSize<Char>(extra_size, args...);
    return count;
}

template <typename Char, typename T>
void SerializeExtraData(uint8_t*& data_buffer, fmt::internal::Arg::Type type, const fmt::internal::Value& value)
{
    // Serialize extra data
    if (type == fmt::internal::Arg::CSTRING)
    {
        std::size_t size = (std::strlen(value.string.value) + 1) * sizeof(char);
        std::memcpy(data_buffer, &size, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        std::memcpy(data_buffer, value.string.value, size);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::STRING)
    {
        std::size_t size = value.string.size * sizeof(char);
        std::memcpy(data_buffer, &size, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        std::memcpy(data_buffer, value.string.value, size);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::WSTRING)
    {
        std::size_t size = value.wstring.size * sizeof(wchar_t);
        std::memcpy(data_buffer, &size, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        std::memcpy(data_buffer, value.wstring.value, size);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::CUSTOM)
    {
        std::size_t size = sizeof(T);
        std::memcpy(data_buffer, &size, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        std::memcpy(data_buffer, value.custom.value, size);
        data_buffer += size;
    }
}

template <typename Char, typename T>
void SerializeExtraData(uint8_t*& data_buffer, const fmt::internal::NamedArgWithType<Char, T>& named)
{
    std::memcpy(data_buffer, &named, sizeof(fmt::internal::NamedArgWithType<Char, T>));
    data_buffer += sizeof(fmt::internal::NamedArgWithType<Char, T>);
    std::size_t size = named.name.size() * sizeof(Char);
    std::memcpy(data_buffer, &size, sizeof(std::size_t));
    data_buffer += sizeof(std::size_t);
    std::memcpy(data_buffer, named.name.data(), size);
    data_buffer += size;
    SerializeExtraData<Char, T>(data_buffer, named.type, named);
}

template <typename Char>
void SerializeArguments(std::size_t, uint8_t*&, uint8_t*&)
{
}

template <typename Char, typename T>
void SerializeArguments(std::size_t item_size, uint8_t*& base_buffer, uint8_t*& data_buffer, const T& argument)
{
    // Serialize argument
    fmt::internal::MakeArg<fmt::BasicFormatter<Char>> arg(argument);
    std::memcpy(base_buffer, &arg, item_size);
    base_buffer += item_size;
    // Serialize extra data
    SerializeExtraData<Char, T>(data_buffer, arg.type, arg);
}

template <typename Char, typename T>
void SerializeArguments(std::size_t item_size, uint8_t*& base_buffer, uint8_t*& data_buffer, const fmt::internal::NamedArgWithType<Char, T>& argument)
{
    // Serialize argument
    const fmt::internal::Arg& arg = argument;
    std::memcpy(base_buffer, &arg, item_size);
    base_buffer += item_size;
    // Serialize extra data
    SerializeExtraData<Char, T>(data_buffer, argument);
}

template <typename Char, typename T, typename... Args>
void SerializeArguments(std::size_t item_size, uint8_t*& base_buffer, uint8_t*& data_buffer, const T& argument, const Args&... args)
{
    SerializeArguments<Char>(item_size, base_buffer, data_buffer, argument);
    SerializeArguments<Char>(item_size, base_buffer, data_buffer, args...);
}

template <typename Char, typename... Args>
void Serialize(std::vector<uint8_t>& buffer, const Args&... args)
{
    std::size_t extra_size = 0;
    unsigned count = CalculateBufferSize<Char>(extra_size, args...);

    // Special check for none format arguments
    if (count == 0)
        return;

    // Caclulate base & full buffer sizes
    std::size_t item_size = (count > fmt::ArgList::MAX_PACKED_ARGS) ? sizeof(fmt::internal::Arg) : sizeof(fmt::internal::Value);
    std::size_t base_size = sizeof(unsigned) + sizeof(std::size_t) + sizeof(fmt::ULongLong) + count * item_size;
    std::size_t full_size = base_size + extra_size;

    // Resize buffer to fit all format arguments
    buffer.resize(full_size);

    uint8_t* base_buffer = buffer.data();
    uint8_t* data_buffer = base_buffer + base_size;

    // Serialize the count of format arguments
    std::memcpy(base_buffer, &count, sizeof(unsigned));
    base_buffer += sizeof(unsigned);

    // Serialize the base buffer size
    std::memcpy(base_buffer, &base_size, sizeof(std::size_t));
    base_buffer += sizeof(std::size_t);

    // Serialize types of format arguments
    fmt::ULongLong types = fmt::internal::make_type(args...);
    std::memcpy(base_buffer, &types, sizeof(fmt::ULongLong));
    base_buffer += sizeof(fmt::ULongLong);

    // Serialize values of format arguments
    SerializeArguments<Char>(item_size, base_buffer, data_buffer, args...);
}

template <typename Char>
void DeserializeExtraData(uint8_t*& data_buffer, fmt::internal::Arg::Type type, fmt::internal::Value& value)
{
    // Deserialize extra data
    if (type == fmt::internal::Arg::NAMED_ARG)
    {
        fmt::internal::NamedArg<Char>* named = reinterpret_cast<fmt::internal::NamedArg<Char>*>(data_buffer);
        value.pointer = named;
        data_buffer += sizeof(fmt::internal::NamedArg<Char>);
        std::size_t size;
        std::memcpy(&size, data_buffer, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        named->name = fmt::BasicStringRef<Char>(reinterpret_cast<const Char*>(data_buffer), size);
        data_buffer += size;
        DeserializeExtraData<Char>(data_buffer, named->type, *named);
    }
    else if (type == fmt::internal::Arg::CSTRING)
    {
        std::size_t size;
        std::memcpy(&size, data_buffer, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        value.string.value = reinterpret_cast<const char*>(data_buffer);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::STRING)
    {
        std::size_t size;
        std::memcpy(&size, data_buffer, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        value.string.value = reinterpret_cast<const char*>(data_buffer);
        value.string.size = size / sizeof(char);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::WSTRING)
    {
        std::size_t size;
        std::memcpy(&size, data_buffer, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        value.wstring.value = reinterpret_cast<const wchar_t*>(data_buffer);
        value.wstring.size = size / sizeof(wchar_t);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::CUSTOM)
    {
        std::size_t size;
        std::memcpy(&size, data_buffer, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        value.custom.value = data_buffer;
        data_buffer += size;
    }
}

template <typename Char>
fmt::ArgList Deserialize(std::vector<uint8_t>& buffer)
{
    // Special check for empty format arguments list
    if (buffer.empty())
        return fmt::ArgList();

    uint8_t* base_buffer = buffer.data();
    uint8_t* data_buffer = base_buffer;

    // Deserialize the count of format arguments
    unsigned count;
    std::memcpy(&count, base_buffer, sizeof(unsigned));
    base_buffer += sizeof(unsigned);

    // Deserialize the base buffer size
    std::size_t base_size;
    std::memcpy(&base_size, base_buffer, sizeof(std::size_t));
    base_buffer += sizeof(std::size_t);

    // Update the data buffer offset
    data_buffer += base_size;

    // Deserialize types of format arguments
    fmt::ULongLong types;
    std::memcpy(&types, base_buffer, sizeof(fmt::ULongLong));
    base_buffer += sizeof(fmt::ULongLong);

    // Calculate the item size
    std::size_t item_size = (count > fmt::ArgList::MAX_PACKED_ARGS) ? sizeof(fmt::internal::Arg) : sizeof(fmt::internal::Value);

    // Deserialize values of format arguments
    uint8_t* local_buffer = base_buffer;
    for (unsigned i = 0; i < count; ++i)
    {
        // Deserialize argument
        fmt::internal::Value* value = reinterpret_cast<fmt::internal::Value*>(local_buffer);
        local_buffer += item_size;
        // Deserialize extra data
        DeserializeExtraData<Char>(data_buffer, fmt::ArgList::type(types, i), *value);
    }

    // Prepare and return arguments list stored in the provided buffer
    return (count > fmt::ArgList::MAX_PACKED_ARGS) ?
        fmt::ArgList(types, reinterpret_cast<const fmt::internal::Arg*>(base_buffer)) :
        fmt::ArgList(types, reinterpret_cast<const fmt::internal::Value*>(base_buffer));
}

} // namespace Internals
//! @endcond

inline Record::Record()
    : timestamp(CppCommon::Timestamp::utc()),
      thread(CppCommon::Thread::CurrentThreadId()),
      level(Level::INFO)
{
    logger.reserve(32);
    message.reserve(512);
    buffer.reserve(1024);
    format.reserve(128);
    raw.reserve(512);
}

template <typename... Args>
inline void Record::FormatSerialize(const char* pattern, const Args&... args)
{
    // Save the format pattern
    message = pattern;

    // Serialize arguments list
    Internals::Serialize<char>(format, args...);
}

inline void Record::FormatDeserialize()
{
    // Special check for empty format arguments list
    if (format.empty())
        return;

    // Format the message filed of the logging record
    fmt::ArgList args = Internals::Deserialize<char>(format);
    message = fmt::format(message.c_str(), args);

    // Clear format buffer
    format.clear();
}

inline void Record::Clear()
{
    timestamp = 0;
    thread = 0;
    level = Level::NONE;
    logger.clear();
    message.clear();
    buffer.clear();
    format.clear();
    raw.clear();
}

inline void Record::swap(Record& record) noexcept
{
    using std::swap;
    swap(timestamp, record.timestamp);
    swap(thread, record.thread);
    swap(level, record.level);
    swap(logger, record.logger);
    swap(message, record.message);
    swap(buffer, record.buffer);
    swap(format, record.format);
    swap(raw, record.raw);
}

inline void swap(Record& record1, Record& record2) noexcept
{
    record1.swap(record2);
}

} // namespace CppLogging
<commit_msg>build<commit_after>/*!
    \file record.inl
    \brief Logging record inline implementation
    \author Ivan Shynkarenka
    \date 08.07.2016
    \copyright MIT License
*/

namespace CppLogging {

//! @cond INTERNALS
namespace Internals {

template <typename Char, typename T>
std::size_t CalculateExtraSize(const fmt::internal::Arg& arg)
{
    std::size_t result = 0;

    if (arg.type == fmt::internal::Arg::CSTRING)
        result = sizeof(std::size_t) + (std::strlen(arg.string.value) + 1) * sizeof(char);
    else if (arg.type == fmt::internal::Arg::STRING)
        result = sizeof(std::size_t) + arg.string.size * sizeof(char);
    else if (arg.type == fmt::internal::Arg::WSTRING)
        result = sizeof(std::size_t) + arg.wstring.size * sizeof(wchar_t);
    else if (arg.type == fmt::internal::Arg::CUSTOM)
        result = sizeof(T);

    return result;
}

template <typename Char>
unsigned CalculateBufferSize(std::size_t&)
{
    return 0;
}

template <typename Char, typename T>
unsigned CalculateBufferSize(std::size_t& extra_size, const T& argument)
{
    fmt::internal::MakeArg<fmt::BasicFormatter<Char>> arg(argument);
    extra_size += CalculateExtraSize<Char, T>(arg);
    return 1;
}

template <typename Char, typename T>
unsigned CalculateBufferSize(std::size_t& extra_size, const fmt::internal::NamedArgWithType<Char, T>& argument)
{
    extra_size += sizeof(fmt::internal::NamedArgWithType<Char, T>) + sizeof(std::size_t) + argument.name.size() * sizeof(Char) + CalculateExtraSize<Char, fmt::internal::NamedArgWithType<Char, T>>(argument);
    return 1;
}

template <typename Char, typename T, typename... Args>
unsigned CalculateBufferSize(std::size_t& extra_size, const T& argument, const Args&... args)
{
    unsigned count = 0;
    count += CalculateBufferSize<Char>(extra_size, argument);
    count += CalculateBufferSize<Char>(extra_size, args...);
    return count;
}

template <typename Char, typename T>
void SerializeExtraData(uint8_t*& data_buffer, fmt::internal::Arg::Type type, const fmt::internal::Value& value)
{
    // Serialize extra data
    if (type == fmt::internal::Arg::CSTRING)
    {
        std::size_t size = (std::strlen(value.string.value) + 1) * sizeof(char);
        std::memcpy(data_buffer, &size, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        std::memcpy(data_buffer, value.string.value, size);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::STRING)
    {
        std::size_t size = value.string.size * sizeof(char);
        std::memcpy(data_buffer, &size, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        std::memcpy(data_buffer, value.string.value, size);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::WSTRING)
    {
        std::size_t size = value.wstring.size * sizeof(wchar_t);
        std::memcpy(data_buffer, &size, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        std::memcpy(data_buffer, value.wstring.value, size);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::CUSTOM)
    {
        std::size_t size = sizeof(T);
        std::memcpy(data_buffer, &size, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        std::memcpy(data_buffer, value.custom.value, size);
        data_buffer += size;
    }
}

template <typename Char, typename T>
void SerializeExtraData(uint8_t*& data_buffer, const fmt::internal::NamedArgWithType<Char, T>& named)
{
    std::memcpy(data_buffer, &named, sizeof(fmt::internal::NamedArgWithType<Char, T>));
    data_buffer += sizeof(fmt::internal::NamedArgWithType<Char, T>);
    std::size_t size = named.name.size() * sizeof(Char);
    std::memcpy(data_buffer, &size, sizeof(std::size_t));
    data_buffer += sizeof(std::size_t);
    std::memcpy(data_buffer, named.name.data(), size);
    data_buffer += size;
    SerializeExtraData<Char, T>(data_buffer, named.type, named);
}

template <typename Char>
void SerializeArguments(std::size_t, uint8_t*&, uint8_t*&)
{
}

template <typename Char, typename T>
void SerializeArguments(std::size_t item_size, uint8_t*& base_buffer, uint8_t*& data_buffer, const T& argument)
{
    // Serialize argument
    fmt::internal::MakeArg<fmt::BasicFormatter<Char>> arg(argument);
    std::memcpy(base_buffer, &arg, item_size);
    base_buffer += item_size;
    // Serialize extra data
    SerializeExtraData<Char, T>(data_buffer, arg.type, arg);
}

template <typename Char, typename T>
void SerializeArguments(std::size_t item_size, uint8_t*& base_buffer, uint8_t*& data_buffer, const fmt::internal::NamedArgWithType<Char, T>& argument)
{
    // Serialize argument
    const fmt::internal::Arg& arg = argument;
    std::memcpy(base_buffer, &arg, item_size);
    base_buffer += item_size;
    // Serialize extra data
    SerializeExtraData<Char, T>(data_buffer, argument);
}

template <typename Char, typename T, typename... Args>
void SerializeArguments(std::size_t item_size, uint8_t*& base_buffer, uint8_t*& data_buffer, const T& argument, const Args&... args)
{
    SerializeArguments<Char>(item_size, base_buffer, data_buffer, argument);
    SerializeArguments<Char>(item_size, base_buffer, data_buffer, args...);
}

template <typename Char, typename... Args>
void Serialize(std::vector<uint8_t>& buffer, const Args&... args)
{
    std::size_t extra_size = 0;
    unsigned count = CalculateBufferSize<Char>(extra_size, args...);

    // Special check for none format arguments
    if (count == 0)
        return;

    // Caclulate base & full buffer sizes
    std::size_t item_size = (count > fmt::ArgList::MAX_PACKED_ARGS) ? sizeof(fmt::internal::Arg) : sizeof(fmt::internal::Value);
    std::size_t base_size = sizeof(unsigned) + sizeof(std::size_t) + sizeof(fmt::ULongLong) + count * item_size;
    std::size_t full_size = base_size + extra_size;

    // Resize buffer to fit all format arguments
    buffer.resize(full_size);

    uint8_t* base_buffer = buffer.data();
    uint8_t* data_buffer = base_buffer + base_size;

    // Serialize the count of format arguments
    std::memcpy(base_buffer, &count, sizeof(unsigned));
    base_buffer += sizeof(unsigned);

    // Serialize the base buffer size
    std::memcpy(base_buffer, &base_size, sizeof(std::size_t));
    base_buffer += sizeof(std::size_t);

    // Serialize types of format arguments
    fmt::ULongLong types = fmt::internal::make_type(args...);
    std::memcpy(base_buffer, &types, sizeof(fmt::ULongLong));
    base_buffer += sizeof(fmt::ULongLong);

    // Serialize values of format arguments
    SerializeArguments<Char>(item_size, base_buffer, data_buffer, args...);
}

template <typename Char>
void DeserializeExtraData(uint8_t*& data_buffer, fmt::internal::Arg::Type type, fmt::internal::Value& value)
{
    // Deserialize extra data
    if (type == fmt::internal::Arg::NAMED_ARG)
    {
        fmt::internal::NamedArg<Char>* named = (fmt::internal::NamedArg<Char>*)data_buffer;
        value.pointer = named;
        data_buffer += sizeof(fmt::internal::NamedArg<Char>);
        std::size_t size;
        std::memcpy(&size, data_buffer, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        named->name = fmt::BasicStringRef<Char>((const Char*)data_buffer, size);
        data_buffer += size;
        DeserializeExtraData<Char>(data_buffer, named->type, *named);
    }
    else if (type == fmt::internal::Arg::CSTRING)
    {
        std::size_t size;
        std::memcpy(&size, data_buffer, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        value.string.value = (const char*)data_buffer;
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::STRING)
    {
        std::size_t size;
        std::memcpy(&size, data_buffer, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        value.string.value = (const char*)data_buffer;
        value.string.size = size / sizeof(char);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::WSTRING)
    {
        std::size_t size;
        std::memcpy(&size, data_buffer, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        value.wstring.value = (const wchar_t*)data_buffer;
        value.wstring.size = size / sizeof(wchar_t);
        data_buffer += size;
    }
    else if (type == fmt::internal::Arg::CUSTOM)
    {
        std::size_t size;
        std::memcpy(&size, data_buffer, sizeof(std::size_t));
        data_buffer += sizeof(std::size_t);
        value.custom.value = data_buffer;
        data_buffer += size;
    }
}

template <typename Char>
fmt::ArgList Deserialize(std::vector<uint8_t>& buffer)
{
    // Special check for empty format arguments list
    if (buffer.empty())
        return fmt::ArgList();

    uint8_t* base_buffer = buffer.data();
    uint8_t* data_buffer = base_buffer;

    // Deserialize the count of format arguments
    unsigned count;
    std::memcpy(&count, base_buffer, sizeof(unsigned));
    base_buffer += sizeof(unsigned);

    // Deserialize the base buffer size
    std::size_t base_size;
    std::memcpy(&base_size, base_buffer, sizeof(std::size_t));
    base_buffer += sizeof(std::size_t);

    // Update the data buffer offset
    data_buffer += base_size;

    // Deserialize types of format arguments
    fmt::ULongLong types;
    std::memcpy(&types, base_buffer, sizeof(fmt::ULongLong));
    base_buffer += sizeof(fmt::ULongLong);

    // Calculate the item size
    std::size_t item_size = (count > fmt::ArgList::MAX_PACKED_ARGS) ? sizeof(fmt::internal::Arg) : sizeof(fmt::internal::Value);

    // Deserialize values of format arguments
    uint8_t* local_buffer = base_buffer;
    for (unsigned i = 0; i < count; ++i)
    {
        // Deserialize argument
        fmt::internal::Value* value = (fmt::internal::Value*)local_buffer;
        local_buffer += item_size;
        // Deserialize extra data
        DeserializeExtraData<Char>(data_buffer, fmt::ArgList::type(types, i), *value);
    }

    // Prepare and return arguments list stored in the provided buffer
    return (count > fmt::ArgList::MAX_PACKED_ARGS) ?
        fmt::ArgList(types, (const fmt::internal::Arg*)base_buffer) :
        fmt::ArgList(types, (const fmt::internal::Value*)base_buffer);
}

} // namespace Internals
//! @endcond

inline Record::Record()
    : timestamp(CppCommon::Timestamp::utc()),
      thread(CppCommon::Thread::CurrentThreadId()),
      level(Level::INFO)
{
    logger.reserve(32);
    message.reserve(512);
    buffer.reserve(1024);
    format.reserve(128);
    raw.reserve(512);
}

template <typename... Args>
inline void Record::FormatSerialize(const char* pattern, const Args&... args)
{
    // Save the format pattern
    message = pattern;

    // Serialize arguments list
    Internals::Serialize<char>(format, args...);
}

inline void Record::FormatDeserialize()
{
    // Special check for empty format arguments list
    if (format.empty())
        return;

    // Format the message filed of the logging record
    fmt::ArgList args = Internals::Deserialize<char>(format);
    message = fmt::format(message.c_str(), args);

    // Clear format buffer
    format.clear();
}

inline void Record::Clear()
{
    timestamp = 0;
    thread = 0;
    level = Level::NONE;
    logger.clear();
    message.clear();
    buffer.clear();
    format.clear();
    raw.clear();
}

inline void Record::swap(Record& record) noexcept
{
    using std::swap;
    swap(timestamp, record.timestamp);
    swap(thread, record.thread);
    swap(level, record.level);
    swap(logger, record.logger);
    swap(message, record.message);
    swap(buffer, record.buffer);
    swap(format, record.format);
    swap(raw, record.raw);
}

inline void swap(Record& record1, Record& record2) noexcept
{
    record1.swap(record2);
}

} // namespace CppLogging
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: feature.hpp 40 2005-04-13 20:20:46Z pavlenko $

#ifndef FEATURE_HPP
#define FEATURE_HPP
// mapnik
#include <mapnik/value.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/raster.hpp>
// boost
#include <boost/property_map.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
// stl
#include <map>

namespace mapnik {
   typedef boost::shared_ptr<raster> raster_ptr;
   typedef boost::associative_property_map<
      std::map<std::string,value
               > > properties;

   template <typename T1,typename T2>
   struct feature : public properties,
                    private boost::noncopyable
   {
      public:
         typedef T1 geometry_type;
         typedef T2 raster_type;
         typedef std::map<std::string,value>::value_type value_type;
         typedef std::map<std::string,value>::size_type size_type;

      private:
         int id_;
         boost::ptr_vector<geometry_type> geom_cont_;
         raster_type   raster_;
         std::map<std::string,value> props_;
      public:
         typedef std::map<std::string,value>::iterator iterator;
         explicit feature(int id)
            : properties(props_),
              id_(id),
              geom_cont_(),
              raster_() {}

         //feature(int id,const geometry_type& geom)
         //  : properties(props_),
         //   id_(id),
         //   geom_(geom),
         //   raster_() {}

         int id() const
         {
            return id_;
         }

         void add_geometry(geometry_type * geom)
         {
            geom_cont_.push_back(geom);
         }

         unsigned num_geometries() const
         {
            return geom_cont_.size();
         }

         geometry_type const& get_geometry(unsigned index) const
         {
            return geom_cont_[index];
         }

         geometry_type& get_geometry(unsigned index)
         {
            return geom_cont_[index];
         }

         Envelope<double> envelope() const
         {
             Envelope<double> result;
             for (unsigned i=0;i<num_geometries();++i)
             {
                geometry2d const& geom = get_geometry(i);
                if (i==0)
                {
                    Envelope<double> box = geom.envelope();
                    result.init(box.minx(),box.miny(),box.maxx(),box.maxy());
                }
                else
                {
                    result.expand_to_include(geom.envelope());
                }
             }
             return result;
         }

         const raster_type& get_raster() const
         {
            return raster_;
         }

         void set_raster(raster_type const& raster)
         {
            raster_=raster;
         }

         std::map<std::string,value> const& props() const
         {
            return props_;
         }

         iterator begin() const
         {
            return props_.begin();
         }

         iterator end() const
         {
            return props_.end();
         }

         std::string to_string() const
         {
            std::stringstream ss;
            ss << "feature (" << std::endl;
            for (std::map<std::string,value>::const_iterator itr=props_.begin();
                 itr != props_.end();++itr)
            {
               ss << "  " << itr->first  << ":" <<  itr->second << std::endl;
            }
            ss << ")" << std::endl;
            return ss.str();
         }
   };

   typedef feature<geometry2d,raster_ptr> Feature;

   inline std::ostream& operator<< (std::ostream & out,Feature const& f)
   {
      out << f.to_string();
      return out;
   }
}

#endif //FEATURE_HPP
<commit_msg>avoid deprecation warnings with boost 1_40 related to location of property_map.hpp<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: feature.hpp 40 2005-04-13 20:20:46Z pavlenko $

#ifndef FEATURE_HPP
#define FEATURE_HPP
// mapnik
#include <mapnik/value.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/raster.hpp>

// boost
#include <boost/version.hpp>
#if BOOST_VERSION >= 104000
#include <boost/property_map/property_map.hpp>
#else
#include <boost/property_map.hpp>
#endif

#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
// stl
#include <map>

namespace mapnik {
   typedef boost::shared_ptr<raster> raster_ptr;
   typedef boost::associative_property_map<
      std::map<std::string,value
               > > properties;

   template <typename T1,typename T2>
   struct feature : public properties,
                    private boost::noncopyable
   {
      public:
         typedef T1 geometry_type;
         typedef T2 raster_type;
         typedef std::map<std::string,value>::value_type value_type;
         typedef std::map<std::string,value>::size_type size_type;

      private:
         int id_;
         boost::ptr_vector<geometry_type> geom_cont_;
         raster_type   raster_;
         std::map<std::string,value> props_;
      public:
         typedef std::map<std::string,value>::iterator iterator;
         explicit feature(int id)
            : properties(props_),
              id_(id),
              geom_cont_(),
              raster_() {}

         //feature(int id,const geometry_type& geom)
         //  : properties(props_),
         //   id_(id),
         //   geom_(geom),
         //   raster_() {}

         int id() const
         {
            return id_;
         }

         void add_geometry(geometry_type * geom)
         {
            geom_cont_.push_back(geom);
         }

         unsigned num_geometries() const
         {
            return geom_cont_.size();
         }

         geometry_type const& get_geometry(unsigned index) const
         {
            return geom_cont_[index];
         }

         geometry_type& get_geometry(unsigned index)
         {
            return geom_cont_[index];
         }

         Envelope<double> envelope() const
         {
             Envelope<double> result;
             for (unsigned i=0;i<num_geometries();++i)
             {
                geometry2d const& geom = get_geometry(i);
                if (i==0)
                {
                    Envelope<double> box = geom.envelope();
                    result.init(box.minx(),box.miny(),box.maxx(),box.maxy());
                }
                else
                {
                    result.expand_to_include(geom.envelope());
                }
             }
             return result;
         }

         const raster_type& get_raster() const
         {
            return raster_;
         }

         void set_raster(raster_type const& raster)
         {
            raster_=raster;
         }

         std::map<std::string,value> const& props() const
         {
            return props_;
         }

         iterator begin() const
         {
            return props_.begin();
         }

         iterator end() const
         {
            return props_.end();
         }

         std::string to_string() const
         {
            std::stringstream ss;
            ss << "feature (" << std::endl;
            for (std::map<std::string,value>::const_iterator itr=props_.begin();
                 itr != props_.end();++itr)
            {
               ss << "  " << itr->first  << ":" <<  itr->second << std::endl;
            }
            ss << ")" << std::endl;
            return ss.str();
         }
   };

   typedef feature<geometry2d,raster_ptr> Feature;

   inline std::ostream& operator<< (std::ostream & out,Feature const& f)
   {
      out << f.to_string();
      return out;
   }
}

#endif //FEATURE_HPP
<|endoftext|>


<commit_before>#pragma once

#include <glm/glm.hpp>
#include <array>
#include <map>

namespace mos {
namespace gfx {

/** Rendering camera view. */
class Camera final {
public:
  Camera();
  Camera(const glm::vec3 &position,
               const glm::vec3 &center,
               const glm::mat4 &projection,
               const glm::vec3 &up = glm::vec3(0.0f, 0.0f, 1.0f));
  ~Camera() = default;

  glm::vec3 up() const;

  /** Set up vector. */
  void up(const glm::vec3 &up);

  glm::vec3 position() const;

  /** Set position. */
  void position(const glm::vec3 &position);

  glm::vec3 center() const;

  /** Set center/focus point. */
  void center(const glm::vec3 &center);

  glm::vec3 direction() const;

  /** Set direction. */
  void direction(const glm::vec3 &direction);

  float aspect_ratio() const;

  bool in_frustum(const glm::vec3 & point, const float radius) const;

  glm::mat4 projection;
  glm::mat4 view;

private:
  void calculate_view();
  void calculate_frustum();
  std::array<glm::vec4, 6> frustum_planes_;
  glm::vec3 up_;
  glm::vec3 center_;
  glm::vec3 position_;
};
}
}<commit_msg>check<commit_after>#pragma once

#include <glm/glm.hpp>
#include <array>
#include <map>

namespace mos {
namespace gfx {

/** Rendering camera view. */
class Camera final {
public:
  Camera(const glm::vec3 &position = glm::vec3(0.0f),
               const glm::vec3 &center = glm::vec3(0.0f),
               const glm::mat4 &projection = glm::mat4(1.0f),
               const glm::vec3 &up = glm::vec3(0.0f, 0.0f, 1.0f));
  ~Camera() = default;

  glm::vec3 up() const;

  /** Set up vector. */
  void up(const glm::vec3 &up);

  glm::vec3 position() const;

  /** Set position. */
  void position(const glm::vec3 &position);

  glm::vec3 center() const;

  /** Set center/focus point. */
  void center(const glm::vec3 &center);

  glm::vec3 direction() const;

  /** Set direction. */
  void direction(const glm::vec3 &direction);

  float aspect_ratio() const;

  bool in_frustum(const glm::vec3 & point, const float radius) const;

  glm::mat4 projection;
  glm::mat4 view;

private:
  void calculate_view();
  void calculate_frustum();
  std::array<glm::vec4, 6> frustum_planes_;
  glm::vec3 up_;
  glm::vec3 center_;
  glm::vec3 position_;
};
}
}
<|endoftext|>


<commit_before>#ifndef LIBTEN_SHARED_POOL_HH
#define LIBTEN_SHARED_POOL_HH

#include "task/rendez.hh"
#include "ten/logging.hh"
#include "ten/optional.hh"

#include <deque>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <chrono>
#include <type_traits>

namespace ten {

namespace detail {
template <typename T> class scoped_resource;
}

//! thread and task safe pool of shared resources
//! useful for connection pools and other types of shared resources
template <typename ResourceT, typename ScopeT = detail::scoped_resource<ResourceT>>
class shared_pool {
    friend class detail::scoped_resource<ResourceT>;

public:
    using resource_type = ResourceT;
    using scoped_resource = ScopeT;  // use this type to RAII resources from the pool

protected:
    using res_ptr = std::shared_ptr<resource_type>;
    using creator_type = std::function<res_ptr ()>;

    struct pool_impl {
        using queue_type = std::deque<res_ptr>;
        using set_type = std::unordered_set<res_ptr>;

        qutex mut;
        rendez not_empty;
        queue_type avail;
        set_type set;
        std::string name;
        creator_type new_resource;
        optional<size_t> max_resources;

        size_t size() const {
            std::lock_guard<qutex> lk(mut);
            return set.size();
        }

        bool has_avail() const {
            std::lock_guard<qutex> lk(mut);
            return !avail.empty();
        }

        void clear() {
            std::lock_guard<qutex> lk(mut);
            avail.clear();
            set.clear();
        }

        res_ptr acquire() {
            std::unique_lock<qutex> lk(mut);
            while (avail.empty()) {
                if (!max_resources || set.size() < *max_resources) {
                    // need to create a new resource
                    return new_with_lock(lk);
                }
                // can't create anymore we're at max, try waiting
                // we don't use a predicate here because
                // we might be woken up from destroy()
                // in which case we might not be at max anymore
                not_empty.sleep(lk);
            }

            CHECK(!avail.empty());
            // pop resource from front of queue
            res_ptr c{std::move(avail.front())};
            avail.pop_front();
            CHECK(c) << "acquire shared resource failed in pool: " << name;
            return c;
        }

        res_ptr new_with_lock(std::unique_lock<qutex> &lk) {
            if (lk)
                lk.unlock(); // unlock while newing resource
            res_ptr c;
            try {
                c = new_resource();
            } catch (std::exception &e) {
                LOG(ERROR) << "exception creating new resource for pool: " << name << " " << e.what();
                throw;
            }
            CHECK(c) << "new_resource failed for pool: " << name;
            DVLOG(4) << "inserting to shared_pool(" << name << "): " << c;
            lk.lock(); // re-lock before inserting to set
            set.insert(c);
            return c;
        }

        void destroy(res_ptr &c) { discard(c, false); }
        void release(res_ptr &c) { discard(c, true); }

        void discard(res_ptr &c, bool can_keep) {
            if (!c)
                return;

            std::unique_lock<qutex> lk(mut);

            if (!can_keep)
                set.erase(c);
            else if (!set.count(c))
                can_keep = false; // it must have exceeded lifetime

            const auto i = std::find(begin(avail), end(avail), c);
            if (i != end(avail))  // should never happen
                avail.erase(i);
            if (can_keep)
                avail.push_front(c);

            // give waiting threads a chance to reuse or create resource
            not_empty.wakeup();
            lk.unlock();

            c.reset();
            if (!can_keep)
                LOG(WARNING) << "destroyed shared resource from pool " << name;
        }
    };

    // this thread safety supports possible swapping of impl objects someday
    std::shared_ptr<pool_impl> _impl() const {
        std::lock_guard<std::mutex> lock(_im_mutex);
        return _im;
    }
    void _impl(std::shared_ptr<pool_impl> im) {
        std::lock_guard<std::mutex> lock(_im_mutex);
        _im = std::move(im);
    }

private:
    std::shared_ptr<pool_impl> _im;
    mutable std::mutex _im_mutex;

public:
    shared_pool(const std::string &name_,
                const creator_type &alloc_,
                decltype((_im->max_resources)) max_ = {})
    {
        auto m = std::make_shared<pool_impl>();
        m->name = name_;
        m->new_resource = alloc_;
        m->max_resources = max_;
        _im = std::move(m);
    }

    //! no copy
    shared_pool(const shared_pool &) = delete;
    shared_pool &operator =(const shared_pool &) = delete;

    //! yes move
    shared_pool(shared_pool &&) = default;
    shared_pool &operator =(shared_pool &&) = default;

    //! accessors
    const std::string &name() const { return _impl()->name; }
    size_t size() const             { return _impl()->size(); }
    void clear()                    { _impl()->clear(); }
};

namespace detail {

// do not use this class directly, instead use your shared_pool<>::scoped_resource
template <typename T>
class scoped_resource {
protected:
    using pool_type = shared_pool<T>;
    using pool_ref = typename std::add_lvalue_reference<pool_type>::type;
    using pool_impl = typename pool_type::pool_impl;
    using res_ptr = typename pool_type::res_ptr;

    std::shared_ptr<pool_impl> _pm; // no mutex here <- no contention
    res_ptr _c;
    bool _success;

public:
    //! RAII
    explicit scoped_resource(pool_ref p)
        : _pm{p._impl()},
          _c{_pm->acquire()},
          _success{}
    {}

    //! do not copy
    scoped_resource(const scoped_resource &) = delete;
    scoped_resource & operator =(const scoped_resource &) = delete;

    //! move is ok
    scoped_resource(scoped_resource &&) = default;
    scoped_resource & operator =(scoped_resource &&) = default;

    //! must call done() to return the resource to the pool
    //! otherwise we destroy it because a timeout or other exception
    //! could have occured causing the resource state to be in transition
    ~scoped_resource() {
        _pm->discard(_c, _success);
    }

    //! call this to allow resource reuse
    void done() {
        DCHECK(!_success);
        _success = true;
    }

    //! access resource
    T *get() const {
        if (!_c) throw std::runtime_error("null pointer");
        return _c.get();
    }
    T * operator -> () const { return get(); }
    T & operator * () const  { return *get(); }
};

} // end detail namespace

} // end namespace ten

#endif // LIBTEN_SHARED_POOL_HH
<commit_msg>tweak logging in shared_pool<commit_after>#ifndef LIBTEN_SHARED_POOL_HH
#define LIBTEN_SHARED_POOL_HH

#include "task/rendez.hh"
#include "ten/logging.hh"
#include "ten/optional.hh"

#include <deque>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <chrono>
#include <type_traits>

namespace ten {

namespace detail {
template <typename T> class scoped_resource;
}

//! thread and task safe pool of shared resources
//! useful for connection pools and other types of shared resources
template <typename ResourceT, typename ScopeT = detail::scoped_resource<ResourceT>>
class shared_pool {
    friend class detail::scoped_resource<ResourceT>;

public:
    using resource_type = ResourceT;
    using scoped_resource = ScopeT;  // use this type to RAII resources from the pool

protected:
    using res_ptr = std::shared_ptr<resource_type>;
    using creator_type = std::function<res_ptr ()>;

    struct pool_impl {
        using queue_type = std::deque<res_ptr>;
        using set_type = std::unordered_set<res_ptr>;

        qutex mut;
        rendez not_empty;
        queue_type avail;
        set_type set;
        std::string name;
        creator_type new_resource;
        optional<size_t> max_resources;

        size_t size() const {
            std::lock_guard<qutex> lk(mut);
            return set.size();
        }

        bool has_avail() const {
            std::lock_guard<qutex> lk(mut);
            return !avail.empty();
        }

        void clear() {
            std::lock_guard<qutex> lk(mut);
            avail.clear();
            set.clear();
        }

        res_ptr acquire() {
            std::unique_lock<qutex> lk(mut);
            while (avail.empty()) {
                if (!max_resources || set.size() < *max_resources) {
                    // need to create a new resource
                    return new_with_lock(lk);
                }
                // can't create anymore we're at max, try waiting
                // we don't use a predicate here because
                // we might be woken up from destroy()
                // in which case we might not be at max anymore
                not_empty.sleep(lk);
            }

            CHECK(!avail.empty());
            // pop resource from front of queue
            res_ptr c{std::move(avail.front())};
            avail.pop_front();
            CHECK(c) << "acquire shared resource failed in pool " << name;
            return c;
        }

        res_ptr new_with_lock(std::unique_lock<qutex> &lk) {
            if (lk)
                lk.unlock(); // unlock while newing resource
            res_ptr c;
            try {
                c = new_resource();
            } catch (std::exception &e) {
                LOG(ERROR) << "exception creating new resource for pool " << name << ": " << e.what();
                throw;
            }
            CHECK(c) << "new_resource failed for pool " << name;
            VLOG(3) << "adding shared resource to pool " << name << ": " << c;
            lk.lock(); // re-lock before inserting to set
            set.insert(c);
            return c;
        }

        void destroy(res_ptr &c) { discard(c, false); }
        void release(res_ptr &c) { discard(c, true); }

        void discard(res_ptr &c, bool can_keep) {
            if (!c)
                return;

            std::unique_lock<qutex> lk(mut);

            if (!can_keep)
                set.erase(c);
            else if (!set.count(c))
                can_keep = false; // it must have exceeded lifetime

            const auto i = std::find(begin(avail), end(avail), c);
            if (i != end(avail))  // should never happen
                avail.erase(i);
            if (can_keep)
                avail.push_front(c);

            // give waiting threads a chance to reuse or create resource
            not_empty.wakeup();
            lk.unlock();

            const void * const addr = c.get();
            c.reset();
            if (!can_keep)
                VLOG(3) << "destroyed shared resource from pool " << name << ": " << addr;
        }
    };

    // this thread safety supports possible swapping of impl objects someday
    std::shared_ptr<pool_impl> _impl() const {
        std::lock_guard<std::mutex> lock(_im_mutex);
        return _im;
    }
    void _impl(std::shared_ptr<pool_impl> im) {
        std::lock_guard<std::mutex> lock(_im_mutex);
        _im = std::move(im);
    }

private:
    std::shared_ptr<pool_impl> _im;
    mutable std::mutex _im_mutex;

public:
    shared_pool(const std::string &name_,
                const creator_type &alloc_,
                decltype((_im->max_resources)) max_ = {})
    {
        auto m = std::make_shared<pool_impl>();
        m->name = name_;
        m->new_resource = alloc_;
        m->max_resources = max_;
        _im = std::move(m);
    }

    //! no copy
    shared_pool(const shared_pool &) = delete;
    shared_pool &operator =(const shared_pool &) = delete;

    //! yes move
    shared_pool(shared_pool &&) = default;
    shared_pool &operator =(shared_pool &&) = default;

    //! accessors
    const std::string &name() const { return _impl()->name; }
    size_t size() const             { return _impl()->size(); }
    void clear()                    { _impl()->clear(); }
};

namespace detail {

// do not use this class directly, instead use your shared_pool<>::scoped_resource
template <typename T>
class scoped_resource {
protected:
    using pool_type = shared_pool<T>;
    using pool_ref = typename std::add_lvalue_reference<pool_type>::type;
    using pool_impl = typename pool_type::pool_impl;
    using res_ptr = typename pool_type::res_ptr;

    std::shared_ptr<pool_impl> _pm; // no mutex here <- no contention
    res_ptr _c;
    bool _success;

public:
    //! RAII
    explicit scoped_resource(pool_ref p)
        : _pm{p._impl()},
          _c{_pm->acquire()},
          _success{}
    {}

    //! do not copy
    scoped_resource(const scoped_resource &) = delete;
    scoped_resource & operator =(const scoped_resource &) = delete;

    //! move is ok
    scoped_resource(scoped_resource &&) = default;
    scoped_resource & operator =(scoped_resource &&) = default;

    //! must call done() to return the resource to the pool
    //! otherwise we destroy it because a timeout or other exception
    //! could have occured causing the resource state to be in transition
    ~scoped_resource() {
        _pm->discard(_c, _success);
    }

    //! call this to allow resource reuse
    void done() {
        DCHECK(!_success);
        _success = true;
    }

    //! access resource
    T *get() const {
        if (!_c) throw std::runtime_error("null pointer");
        return _c.get();
    }
    T * operator -> () const { return get(); }
    T & operator * () const  { return *get(); }
};

} // end detail namespace

} // end namespace ten

#endif // LIBTEN_SHARED_POOL_HH
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XARRAY_HPP
#define XARRAY_HPP

#include <initializer_list>
#include <utility>
#include <vector>
#include <algorithm>

#include "xcontainer.hpp"
#include "xsemantic.hpp"

namespace xt
{

    /**********************
     * xarray declaration *
     **********************/

    template <class T>
    class xarray;

    template <class T>
    struct xcontainer_inner_types<xarray<T>>
    {
        using container_type = std::vector<T>;
        using shape_type = std::vector<typename container_type::size_type>;
        using strides_type = shape_type;
        using temporary_type = xarray<T>;
    };

    /**
     * @class xarray
     * @brief Dense multidimensional container with tensor
     * semantic.
     *
     * The xarray class implements a dense multidimensional container
     * with tensor semantic.
     *
     * @tparam T The type of objects stored in the container.
     */
    template <class T>
    class xarray : public xcontainer<xarray<T>>,
                   public xcontainer_semantic<xarray<T>>
    {

    public:

        using self_type = xarray<T>;
        using base_type = xcontainer<self_type>;
        using semantic_base = xcontainer_semantic<self_type>;
        using container_type = typename base_type::container_type;
        using value_type = typename base_type::value_type;
        using reference = typename base_type::reference;
        using const_reference = typename base_type::const_reference;
        using pointer = typename base_type::pointer;
        using const_pointer = typename base_type::const_pointer;
        using shape_type = typename base_type::shape_type;
        using strides_type = typename base_type::strides_type;

        using closure_type = const self_type&;

        xarray();
        explicit xarray(const shape_type& shape, layout l = layout::row_major);
        explicit xarray(const shape_type& shape, const_reference value, layout l = layout::row_major);
        explicit xarray(const shape_type& shape, const strides_type& strides);
        explicit xarray(const shape_type& shape, const strides_type& strides, const_reference value);

        xarray(const value_type& t);
        xarray(std::initializer_list<T> t);
        xarray(std::initializer_list<std::initializer_list<T>> t);
        xarray(std::initializer_list<std::initializer_list<std::initializer_list<T>>> t);
        xarray(std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<T>>>> t);
        xarray(std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<T>>>>> t);

        ~xarray() = default;

        xarray(const xarray&) = default;
        xarray& operator=(const xarray&) = default;

        xarray(xarray&&) = default;
        xarray& operator=(xarray&&) = default;

        template <class E>
        xarray(const xexpression<E>& e);

        template <class E>
        xarray& operator=(const xexpression<E>& e);

    private:

        container_type m_data;

        container_type& data_impl() noexcept;
        const container_type& data_impl() const noexcept;

        friend class xcontainer<xarray<T>>;
    };

    /******************************
     * xarray_adaptor declaration *
     ******************************/

    template <class C>
    class xarray_adaptor;

    template <class C>
    struct xcontainer_inner_types<xarray_adaptor<C>>
    {
        using container_type = C;
        using shape_type = std::vector<typename container_type::size_type>;
        using strides_type = shape_type;
        using temporary_type = xarray<typename C::value_type>;
    };

    /**
     * @class xarray_adaptor
     * @brief Dense multidimensional container adaptor with
     * tensor semantic.
     *
     * The xarray_adaptor class implements a dense multidimensional
     * container adaptor with tensor semantic. It is used to provide
     * a multidimensional container semantic and a tensor semantic to
     * stl-like containers.
     *
     * @tparam C The container type to adapt.
     */
    template <class C>
    class xarray_adaptor : public xcontainer<xarray_adaptor<C>>,
                           public xadaptor_semantic<xarray_adaptor<C>>
    {

    public:

        using self_type = xarray_adaptor<C>;
        using base_type = xcontainer<self_type>;
        using semantic_base = xadaptor_semantic<self_type>;
        using container_type = typename base_type::container_type;
        using shape_type = typename base_type::shape_type;
        using strides_type = typename base_type::strides_type;

        using closure_type = const self_type&;

        xarray_adaptor(container_type& data);
        xarray_adaptor(container_type& data, const shape_type& shape, layout l = layout::row_major);
        xarray_adaptor(container_type& data, const shape_type& shape, const strides_type& strides);

        ~xarray_adaptor() = default;

        xarray_adaptor(const xarray_adaptor&) = default;
        xarray_adaptor& operator=(const xarray_adaptor&);

        xarray_adaptor(xarray_adaptor&&) = default;
        xarray_adaptor& operator=(xarray_adaptor&&);

        template <class E>
        xarray_adaptor& operator=(const xexpression<E>& e);

    private:

        container_type& m_data;

        container_type& data_impl() noexcept;
        const container_type& data_impl() const noexcept;

        using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
        void assign_temporary_impl(temporary_type& tmp);

        friend class xcontainer<xarray_adaptor<C>>;
        friend class xadaptor_semantic<xarray_adaptor<C>>;
    };

    /*************************
     * xarray implementation *
     *************************/

    /**
     * @name Constructors
     */
    //@{
    /**
     * Allocates an uninitialized xarray that holds 0 element.
     */
    template <class T>
    inline xarray<T>::xarray()
        : base_type(), m_data(1, value_type())
    {
    }

    /**
     * Allocates an uninitialized xarray with the specified shape and
     * layout.
     * @param shape the shape of the xarray
     * @param l the layout of the xarray
     */
    template <class T>
    inline xarray<T>::xarray(const shape_type& shape, layout l)
        : base_type()
    {
        base_type::reshape(shape, l);
    }

    /**
     * Allocates an xarray with the specified shape and layout. Elements
     * are initialized to the specified value.
     * @param shape the shape of the xarray
     * @param value the value of the elements
     * @param l the layout of the xarray
     */
    template <class T>
    inline xarray<T>::xarray(const shape_type& shape, const_reference value, layout l)
        : base_type()
    {
        base_type::reshape(shape, l);
        std::fill(m_data.begin(), m_data.end(), value);
    }

    /**
     * Allocates an uninitialized xarray with the specified shape and strides.
     * @param shape the shape of the xarray
     * @param strides the strides of the xarray
     */
    template <class T>
    inline xarray<T>::xarray(const shape_type& shape, const strides_type& strides)
        : base_type()
    {
        base_type::reshape(shape, strides);
    }

    /**
     * Allocates an uninitialized xarray with the specified shape and strides.
     * Elements are initialized to the specified value.
     * @param shape the shape of the xarray
     * @param strides the strides of the xarray
     * @param value the value of the elements
     */
    template <class T>
    inline xarray<T>::xarray(const shape_type& shape, const strides_type& strides, const_reference value)
        : base_type()
    {
        base_type::reshape(shape, strides);
        std::fill(m_data.begin(), m_data.end(), value);
    }

    /**
     * Allocates an xarray that holds a single element initialized to the
     * specified value.
     * @param t the value of the element
     */
    template <class T>
    inline xarray<T>::xarray(const value_type& t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }
    //@}

    /**
     * @name Constructors from initializer list
     */
    //@{
    /**
     * Allocates a one-dimensional xarray.
     * @param t the elements of the xarray
     */
    template <class T>
    inline xarray<T>::xarray(std::initializer_list<T> t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }

    /**
     * Allocates a two-dimensional xarray.
     * @param t the elements of the xarray
     */
    template <class T>
    inline xarray<T>::xarray(std::initializer_list<std::initializer_list<T>> t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }

    /**
     * Allocates a three-dimensional xarray.
     * @param t the elements of the xarray
     */
    template <class T>
    inline xarray<T>::xarray(std::initializer_list<std::initializer_list<std::initializer_list<T>>> t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }

    /**
     * Allocates a four-dimensional xarray.
     * @param t the elements of the xarray
     */
    template <class T>
    inline xarray<T>::xarray(std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<T>>>> t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }

    /**
     * Allocates a five-dimensional xarray.
     * @param t the elements of the xarray
     */
    template <class T>
    inline xarray<T>::xarray(std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<T>>>>> t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }
    //@}

    /**
     * @name Extended copy semantic
     */
    //@{
    /**
     * The extended copy constructor.
     */
    template <class T>
    template <class E>
    inline xarray<T>::xarray(const xexpression<E>& e)
        : base_type()
    {
        semantic_base::assign(e);
    }

    /**
     * The extended assignment operator.
     */
    template <class T>
    template <class E>
    inline auto xarray<T>::operator=(const xexpression<E>& e) -> self_type&
    {
        return semantic_base::operator=(e);
    }
    //@}

    template <class T>
    inline auto xarray<T>::data_impl() noexcept -> container_type&
    {
        return m_data;
    }

    template <class T>
    inline auto xarray<T>::data_impl() const noexcept -> const container_type&
    {
        return m_data;
    }

    /******************
     * xarray_adaptor *
     ******************/

    /**
     * @name Constructors
     */
    //@{
    /**
     * Constructs an xarray_adaptor of the given stl-like container.
     * @param data the container to adapt
     */
    template <class C>
    inline xarray_adaptor<C>::xarray_adaptor(container_type& data)
        : base_type(), m_data(data)
    {
    }

    /**
     * Constructs an xarray_adaptor of the given stl-like container,
     * with the specified shape and layout.
     * @param data the container to adapt
     * @param shape the shape of the xarray_adaptor
     * @param l the layout of the xarray_adaptor
     */
    template <class C>
    inline xarray_adaptor<C>::xarray_adaptor(container_type& data, const shape_type& shape, layout l)
        : base_type(), m_data(data)
    {
        base_type::reshape(shape, l);
    }

    /**
     * Constructs an xarray_adaptor of the given stl-like container,
     * with the specified shape and strides.
     * @param data the container to adapt
     * @param shape the shape of the xarray_adaptor
     * @param strides the strides of the xarray_adaptor
     */
    template <class C>
    inline xarray_adaptor<C>::xarray_adaptor(container_type& data, const shape_type& shape, const strides_type& strides)
        : base_type(), m_data(data)
    {
        base_type::reshape(shape, strides);
    }
    //@}

    template <class C>
    inline xarray_adaptor<C>& xarray_adaptor<C>::operator=(const xarray_adaptor& rhs)
    {
        base_type::operator=(rhs);
        m_data = rhs.m_data;
        return *this;
    }

    template <class C>
    inline xarray_adaptor<C>& xarray_adaptor<C>::operator=(xarray_adaptor&& rhs)
    {
        base_type::operator=(std::move(rhs));
        m_data = rhs.m_data;
        return *this;
    }

    /**
     * @name Extended copy semantic
     */
    //@{
    /**
     * The extended assignment operator.
     */
    template <class C>
    template <class E>
    inline auto xarray_adaptor<C>::operator=(const xexpression<E>& e) -> self_type&
    {
        return semantic_base::operator=(e);
    }
    //@}

    template <class C>
    inline auto xarray_adaptor<C>::data_impl() noexcept -> container_type&
    {
        return m_data;
    }

    template <class C>
    inline auto xarray_adaptor<C>::data_impl() const noexcept -> const container_type&
    {
        return m_data;
    }

    template <class C>
    inline void xarray_adaptor<C>::assign_temporary_impl(temporary_type& tmp)
    {
        // TODO (performance improvement) : consider moving tmps
        // shape and strides
        base_type::get_shape() = tmp.shape();
        base_type::get_strides() = tmp.strides();
        base_type::get_backstrides() = tmp.backstrides();
        m_data.resize(tmp.size());
        std::copy(tmp.data().cbegin(), tmp.data().cend(), m_data.begin());
    }
}

#endif

<commit_msg>support custom allocators for xarrays<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XARRAY_HPP
#define XARRAY_HPP

#include <initializer_list>
#include <utility>
#include <vector>
#include <algorithm>
#include <memory>

#include "xcontainer.hpp"
#include "xsemantic.hpp"

namespace xt
{

    /**********************
     * xarray declaration *
     **********************/

    template <class T, class EA = std::allocator<T>, class SA = std::allocator<typename std::vector<T, EA>::size_type>>
    class xarray;

    template <class T, class EA, class SA>
    struct xcontainer_inner_types<xarray<T, EA, SA>>
    {
        using container_type = std::vector<T, EA>;
        using shape_type = std::vector<typename container_type::size_type, SA>;
        using strides_type = shape_type;
        using temporary_type = xarray<T, EA, SA>;
    };

    /**
     * @class xarray
     * @brief Dense multidimensional container with tensor
     * semantic.
     *
     * The xarray class implements a dense multidimensional container
     * with tensor semantic.
     *
     * @tparam T The type of objects stored in the container.
     */
    template <class T, class EA, class SA>
    class xarray : public xcontainer<xarray<T, EA, SA>>,
                   public xcontainer_semantic<xarray<T, EA, SA>>
    {

    public:

        using self_type = xarray<T, EA, SA>;
        using base_type = xcontainer<self_type>;
        using semantic_base = xcontainer_semantic<self_type>;
        using container_type = typename base_type::container_type;
        using value_type = typename base_type::value_type;
        using reference = typename base_type::reference;
        using const_reference = typename base_type::const_reference;
        using pointer = typename base_type::pointer;
        using const_pointer = typename base_type::const_pointer;
        using shape_type = typename base_type::shape_type;
        using strides_type = typename base_type::strides_type;

        using closure_type = const self_type&;

        xarray();
        explicit xarray(const shape_type& shape, layout l = layout::row_major);
        explicit xarray(const shape_type& shape, const_reference value, layout l = layout::row_major);
        explicit xarray(const shape_type& shape, const strides_type& strides);
        explicit xarray(const shape_type& shape, const strides_type& strides, const_reference value);

        xarray(const value_type& t);
        xarray(std::initializer_list<T> t);
        xarray(std::initializer_list<std::initializer_list<T>> t);
        xarray(std::initializer_list<std::initializer_list<std::initializer_list<T>>> t);
        xarray(std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<T>>>> t);
        xarray(std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<T>>>>> t);

        ~xarray() = default;

        xarray(const xarray&) = default;
        xarray& operator=(const xarray&) = default;

        xarray(xarray&&) = default;
        xarray& operator=(xarray&&) = default;

        template <class E>
        xarray(const xexpression<E>& e);

        template <class E>
        xarray& operator=(const xexpression<E>& e);

    private:

        container_type m_data;

        container_type& data_impl() noexcept;
        const container_type& data_impl() const noexcept;

        friend class xcontainer<xarray<T, EA, SA>>;
    };

    /******************************
     * xarray_adaptor declaration *
     ******************************/

    template <class C, class EA = std::allocator<typename C::value_type>, class SA = std::allocator<typename C::size_type>>
    class xarray_adaptor;

    template <class C, class EA, class SA>
    struct xcontainer_inner_types<xarray_adaptor<C, EA, SA>>
    {
        using container_type = C;
        using shape_type = std::vector<typename container_type::size_type, SA>;
        using strides_type = shape_type;
        using temporary_type = xarray<typename C::value_type, EA, SA>;
    };

    /**
     * @class xarray_adaptor
     * @brief Dense multidimensional container adaptor with
     * tensor semantic.
     *
     * The xarray_adaptor class implements a dense multidimensional
     * container adaptor with tensor semantic. It is used to provide
     * a multidimensional container semantic and a tensor semantic to
     * stl-like containers.
     *
     * @tparam C The container type to adapt.
     */
    template <class C, class EA, class SA>
    class xarray_adaptor : public xcontainer<xarray_adaptor<C, EA, SA>>,
                           public xadaptor_semantic<xarray_adaptor<C, EA, SA>>
    {

    public:

        using self_type = xarray_adaptor<C, EA, SA>;
        using base_type = xcontainer<self_type>;
        using semantic_base = xadaptor_semantic<self_type>;
        using container_type = typename base_type::container_type;
        using shape_type = typename base_type::shape_type;
        using strides_type = typename base_type::strides_type;

        using closure_type = const self_type&;

        xarray_adaptor(container_type& data);
        xarray_adaptor(container_type& data, const shape_type& shape, layout l = layout::row_major);
        xarray_adaptor(container_type& data, const shape_type& shape, const strides_type& strides);

        ~xarray_adaptor() = default;

        xarray_adaptor(const xarray_adaptor&) = default;
        xarray_adaptor& operator=(const xarray_adaptor&);

        xarray_adaptor(xarray_adaptor&&) = default;
        xarray_adaptor& operator=(xarray_adaptor&&);

        template <class E>
        xarray_adaptor& operator=(const xexpression<E>& e);

    private:

        container_type& m_data;

        container_type& data_impl() noexcept;
        const container_type& data_impl() const noexcept;

        using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
        void assign_temporary_impl(temporary_type& tmp);

        friend class xcontainer<xarray_adaptor<C, EA, SA>>;
        friend class xadaptor_semantic<xarray_adaptor<C, EA, SA>>;
    };

    /*************************
     * xarray implementation *
     *************************/

    /**
     * @name Constructors
     */
    //@{
    /**
     * Allocates an uninitialized xarray that holds 0 element.
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray()
        : base_type(), m_data(1, value_type())
    {
    }

    /**
     * Allocates an uninitialized xarray with the specified shape and
     * layout.
     * @param shape the shape of the xarray
     * @param l the layout of the xarray
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray(const shape_type& shape, layout l)
        : base_type()
    {
        base_type::reshape(shape, l);
    }

    /**
     * Allocates an xarray with the specified shape and layout. Elements
     * are initialized to the specified value.
     * @param shape the shape of the xarray
     * @param value the value of the elements
     * @param l the layout of the xarray
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray(const shape_type& shape, const_reference value, layout l)
        : base_type()
    {
        base_type::reshape(shape, l);
        std::fill(m_data.begin(), m_data.end(), value);
    }

    /**
     * Allocates an uninitialized xarray with the specified shape and strides.
     * @param shape the shape of the xarray
     * @param strides the strides of the xarray
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray(const shape_type& shape, const strides_type& strides)
        : base_type()
    {
        base_type::reshape(shape, strides);
    }

    /**
     * Allocates an uninitialized xarray with the specified shape and strides.
     * Elements are initialized to the specified value.
     * @param shape the shape of the xarray
     * @param strides the strides of the xarray
     * @param value the value of the elements
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray(const shape_type& shape, const strides_type& strides, const_reference value)
        : base_type()
    {
        base_type::reshape(shape, strides);
        std::fill(m_data.begin(), m_data.end(), value);
    }

    /**
     * Allocates an xarray that holds a single element initialized to the
     * specified value.
     * @param t the value of the element
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray(const value_type& t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }
    //@}

    /**
     * @name Constructors from initializer list
     */
    //@{
    /**
     * Allocates a one-dimensional xarray.
     * @param t the elements of the xarray
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray(std::initializer_list<T> t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }

    /**
     * Allocates a two-dimensional xarray.
     * @param t the elements of the xarray
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray(std::initializer_list<std::initializer_list<T>> t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }

    /**
     * Allocates a three-dimensional xarray.
     * @param t the elements of the xarray
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray(std::initializer_list<std::initializer_list<std::initializer_list<T>>> t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }

    /**
     * Allocates a four-dimensional xarray.
     * @param t the elements of the xarray
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray(std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<T>>>> t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }

    /**
     * Allocates a five-dimensional xarray.
     * @param t the elements of the xarray
     */
    template <class T, class EA, class SA>
    inline xarray<T, EA, SA>::xarray(std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<T>>>>> t)
        : base_type()
    {
        base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
        nested_copy(m_data.begin(), t);
    }
    //@}

    /**
     * @name Extended copy semantic
     */
    //@{
    /**
     * The extended copy constructor.
     */
    template <class T, class EA, class SA>
    template <class E>
    inline xarray<T, EA, SA>::xarray(const xexpression<E>& e)
        : base_type()
    {
        semantic_base::assign(e);
    }

    /**
     * The extended assignment operator.
     */
    template <class T, class EA, class SA>
    template <class E>
    inline auto xarray<T, EA, SA>::operator=(const xexpression<E>& e) -> self_type&
    {
        return semantic_base::operator=(e);
    }
    //@}

    template <class T, class EA, class SA>
    inline auto xarray<T, EA, SA>::data_impl() noexcept -> container_type&
    {
        return m_data;
    }

    template <class T, class EA, class SA>
    inline auto xarray<T, EA, SA>::data_impl() const noexcept -> const container_type&
    {
        return m_data;
    }

    /******************
     * xarray_adaptor *
     ******************/

    /**
     * @name Constructors
     */
    //@{
    /**
     * Constructs an xarray_adaptor of the given stl-like container.
     * @param data the container to adapt
     */
    template <class C, class EA, class SA>
    inline xarray_adaptor<C, EA, SA>::xarray_adaptor(container_type& data)
        : base_type(), m_data(data)
    {
    }

    /**
     * Constructs an xarray_adaptor of the given stl-like container,
     * with the specified shape and layout.
     * @param data the container to adapt
     * @param shape the shape of the xarray_adaptor
     * @param l the layout of the xarray_adaptor
     */
    template <class C, class EA, class SA>
    inline xarray_adaptor<C, EA, SA>::xarray_adaptor(container_type& data, const shape_type& shape, layout l)
        : base_type(), m_data(data)
    {
        base_type::reshape(shape, l);
    }

    /**
     * Constructs an xarray_adaptor of the given stl-like container,
     * with the specified shape and strides.
     * @param data the container to adapt
     * @param shape the shape of the xarray_adaptor
     * @param strides the strides of the xarray_adaptor
     */
    template <class C, class EA, class SA>
    inline xarray_adaptor<C, EA, SA>::xarray_adaptor(container_type& data, const shape_type& shape, const strides_type& strides)
        : base_type(), m_data(data)
    {
        base_type::reshape(shape, strides);
    }
    //@}

    template <class C, class EA, class SA>
    inline xarray_adaptor<C, EA, SA>& xarray_adaptor<C, EA, SA>::operator=(const xarray_adaptor& rhs)
    {
        base_type::operator=(rhs);
        m_data = rhs.m_data;
        return *this;
    }

    template <class C, class EA, class SA>
    inline xarray_adaptor<C, EA, SA>& xarray_adaptor<C, EA, SA>::operator=(xarray_adaptor&& rhs)
    {
        base_type::operator=(std::move(rhs));
        m_data = rhs.m_data;
        return *this;
    }

    /**
     * @name Extended copy semantic
     */
    //@{
    /**
     * The extended assignment operator.
     */
    template <class C, class EA, class SA>
    template <class E>
    inline auto xarray_adaptor<C, EA, SA>::operator=(const xexpression<E>& e) -> self_type&
    {
        return semantic_base::operator=(e);
    }
    //@}

    template <class C, class EA, class SA>
    inline auto xarray_adaptor<C, EA, SA>::data_impl() noexcept -> container_type&
    {
        return m_data;
    }

    template <class C, class EA, class SA>
    inline auto xarray_adaptor<C, EA, SA>::data_impl() const noexcept -> const container_type&
    {
        return m_data;
    }

    template <class C, class EA, class SA>
    inline void xarray_adaptor<C, EA, SA>::assign_temporary_impl(temporary_type& tmp)
    {
        // TODO (performance improvement) : consider moving tmps
        // shape and strides
        base_type::get_shape() = tmp.shape();
        base_type::get_strides() = tmp.strides();
        base_type::get_backstrides() = tmp.backstrides();
        m_data.resize(tmp.size());
        std::copy(tmp.data().cbegin(), tmp.data().cend(), m_data.begin());
    }
}

#endif
<|endoftext|>


<commit_before>// example of TGraphTime
//Author: Rene Brun 14/07/2009

#include "TCanvas.h"
#include "TRandom3.h"
#include "TMath.h"
#include "TText.h"
#include "TArrow.h"
#include "TGraphTime.h"
#include "TROOT.h"

void gtime(Int_t nsteps = 500, Int_t np=100) {
   if (np > 1000) np = 1000;
   Int_t color[1000];
   Double_t rr[1000], phi[1000], dr[1000], size[1000];
   TRandom3 r;
   Double_t xmin = -10, xmax = 10, ymin = -10, ymax = 10;
   TGraphTime *g = new TGraphTime(nsteps,xmin,ymin,xmax,ymax);
   Int_t i,s;
   for (i=0;i<np;i++) { //calculate some object parameters
      rr[i]  = r.Uniform(0.1*xmax,0.2*xmax);
      phi[i] = r.Uniform(0,2*TMath::Pi());
      dr[i]  = r.Uniform(0,1)*0.9*xmax/Double_t(nsteps);
      Double_t rc = r.Rndm();
      color[i] = kRed;
      if (rc > 0.3) color[i] = kBlue;
      if (rc > 0.7) color[i] = kYellow;
      size[i] = r.Uniform(0.5,6);
   }
   for (s=0;s<nsteps;s++) { //fill the TGraphTime step by step
      for (i=0;i<np;i++) {
         Double_t newr = rr[i]+dr[i]*s;
         Double_t newsize = 0.2+size[i]*TMath::Abs(TMath::Sin(newr+10));
         Double_t newphi = phi[i] + 0.01*s;
         Double_t xx = newr*TMath::Cos(newphi);
         Double_t yy = newr*TMath::Sin(newphi);
         TMarker *m = new TMarker(xx,yy,20);
         m->SetMarkerColor(color[i]);
         m->SetMarkerSize(newsize);
         g->Add(m,s);
         if (i==np-1) g->Add(new TArrow(xmin,ymax,xx,yy,0.02,"-|>"), s);
      }
   }
   g->Draw("time");

   //save object to a file
   TFile f("gtime.root","recreate");
   g->Write("g");
   //to view this object in another session do
   //  TFile f("gtime.root");
   //  g.Draw("time");
}

<commit_msg>Add a TPaveLabel in the list of objects . The label shows the time step number.<commit_after>// example of TGraphTime
//Author: Rene Brun 14/07/2009

#include "TCanvas.h"
#include "TRandom3.h"
#include "TMath.h"
#include "TText.h"
#include "TArrow.h"
#include "TGraphTime.h"
#include "TROOT.h"

void gtime(Int_t nsteps = 500, Int_t np=100) {
   if (np > 1000) np = 1000;
   Int_t color[1000];
   Double_t rr[1000], phi[1000], dr[1000], size[1000];
   TRandom3 r;
   Double_t xmin = -10, xmax = 10, ymin = -10, ymax = 10;
   TGraphTime *g = new TGraphTime(nsteps,xmin,ymin,xmax,ymax);
   Int_t i,s;
   for (i=0;i<np;i++) { //calculate some object parameters
      rr[i]  = r.Uniform(0.1*xmax,0.2*xmax);
      phi[i] = r.Uniform(0,2*TMath::Pi());
      dr[i]  = r.Uniform(0,1)*0.9*xmax/Double_t(nsteps);
      Double_t rc = r.Rndm();
      color[i] = kRed;
      if (rc > 0.3) color[i] = kBlue;
      if (rc > 0.7) color[i] = kYellow;
      size[i] = r.Uniform(0.5,6);
   }
   for (s=0;s<nsteps;s++) { //fill the TGraphTime step by step
      for (i=0;i<np;i++) {
         Double_t newr = rr[i]+dr[i]*s;
         Double_t newsize = 0.2+size[i]*TMath::Abs(TMath::Sin(newr+10));
         Double_t newphi = phi[i] + 0.01*s;
         Double_t xx = newr*TMath::Cos(newphi);
         Double_t yy = newr*TMath::Sin(newphi);
         TMarker *m = new TMarker(xx,yy,20);
         m->SetMarkerColor(color[i]);
         m->SetMarkerSize(newsize);
         g->Add(m,s);
         if (i==np-1) g->Add(new TArrow(xmin,ymax,xx,yy,0.02,"-|>"), s);
      }
      g->Add(new TPaveLabel(.90,.92,.98,.97,Form("%d",s+1),"brNDC"),s);
   }
   g->Draw();

   //save object to a file
   TFile f("gtime.root","recreate");
   g->Write("g");
   //to view this object in another session do
   //  TFile f("gtime.root");
   //  g.Draw("time");
}

<|endoftext|>


<commit_before>// tutorial illustrating the use of TMath::Permute
//  can be run with:
// root > .x permute.C
// root > .x permute.C+ with ACLIC
//Author: Federico Carminati

#include <TMath.h>

int permuteSimple1 ()
{
  printf("\nTMath::Permute simple test\n");
  printf("==========================\n");
  char aa='a';
  Int_t a[4];
  Int_t i;
  Int_t icount=0;
  for(i=0; i<4; i++) a[i]=i;
  do {
    icount++;
    for(Int_t i=0;i<4;printf("%c",static_cast<char>(aa+a[i++])))
       ;
    printf("\n");

  } while(TMath::Permute(4,a));
  printf("Found %d permutations = 4!\n",icount);
  return 0;
}

int permuteSimple2 ()
{
  printf("\nTMath::Permute simple test with repetition\n");
  printf("==========================================\n");
  char aa='a'-1;
  Int_t a[6];
  Int_t i;
  Int_t icount=0;
  for(i=0; i<6; i++) a[i]=(i+2)/2;
  do {
     icount++;
     for(Int_t i=0;i<5;printf("%c",static_cast<char>(aa+a[i++])))
        ;
     printf("\n");

  } while(TMath::Permute(5,a));
  printf("Found %d permutations = 5!/(2! 2!)\n",icount);
  return 0;
}

Int_t permuteFancy()
{
  Int_t a[10];
  Int_t &n=a[0], &i=a[1];
  Int_t &e=a[2], &t=a[3];
  Int_t &h=a[4], &r=a[5];
  Int_t &f=a[6], &o=a[7];
  Int_t &s=a[8], &u=a[9];
  Int_t nine, three, neuf, trois;

  printf("\nTMath::Permute fancy test\n");
  printf("=========================\n");
  printf("This is a program to calculate the solution to the following problem\n");
  printf("Find the equivalence between letters and numbers so that\n\n");
  printf("              NINE*THREE = NEUF*TROIS\n\n");
  for(Int_t ii=0; ii<10; ii++) a[ii]=ii;
  do {
     nine=((n*10+i)*10+n)*10+e;
     neuf=((n*10+e)*10+u)*10+f;
     three=(((t*10+h)*10+r)*10+e)*10+e;
     trois=(((t*10+r)*10+o)*10+i)*10+s;
     if(nine*three==neuf*trois) {
        printf("Solution found!\n\n");
        printf("T=%d N=%d E=%d S=%d F=%d H=%d R=%d I=%d O=%d U=%d\n",t,n,e,s,f,h,r,i,o,u);
        printf("NINE=%d THREE=%d NEUF=%d TROIS=%d\n",nine,three,neuf,trois);
        printf("NINE*THREE = NEUF*TROIS = %d\n",neuf*trois);
        return 0;
     }
  } while(TMath::Permute(10,a));
  printf("No solutions found -- something is wrong here!\n");
  return 0;
}

void permute() {
   permuteSimple1();
   permuteSimple2();
   permuteFancy();
}
<commit_msg>Hm, not so funny actually :)<commit_after>// tutorial illustrating the use of TMath::Permute
//  can be run with:
// root > .x permute.C
// root > .x permute.C+ with ACLIC
//Author: Federico Carminati

#include <TMath.h>

int permuteSimple1 ()
{
  printf("\nTMath::Permute simple test\n");
  printf("==========================\n");
  char aa='a';
  Int_t a[4];
  Int_t i;
  Int_t icount=0;
  for(i=0; i<4; i++) a[i]=i;
  do {
    icount++;
    for(Int_t i=0;i<4;printf("%c",static_cast<char>(aa+a[i++])));
    printf("\n");

  } while(TMath::Permute(4,a));
  printf("Found %d permutations = 4!\n",icount);
  return 0;
}

int permuteSimple2 ()
{
  printf("\nTMath::Permute simple test with repetition\n");
  printf("==========================================\n");
  char aa='a'-1;
  Int_t a[6];
  Int_t i;
  Int_t icount=0;
  for(i=0; i<6; i++) a[i]=(i+2)/2;
  do {
     icount++;
     for(Int_t i=0;i<5;printf("%c",static_cast<char>(aa+a[i++])));
     printf("\n");

  } while(TMath::Permute(5,a));
  printf("Found %d permutations = 5!/(2! 2!)\n",icount);
  return 0;
}

Int_t permuteFancy()
{
  Int_t a[10];
  Int_t &n=a[0], &i=a[1];
  Int_t &e=a[2], &t=a[3];
  Int_t &h=a[4], &r=a[5];
  Int_t &f=a[6], &o=a[7];
  Int_t &s=a[8], &u=a[9];
  Int_t nine, three, neuf, trois;

  printf("\nTMath::Permute fancy test\n");
  printf("=========================\n");
  printf("This is a program to calculate the solution to the following problem\n");
  printf("Find the equivalence between letters and numbers so that\n\n");
  printf("              NINE*THREE = NEUF*TROIS\n\n");
  for(Int_t ii=0; ii<10; ii++) a[ii]=ii;
  do {
     nine=((n*10+i)*10+n)*10+e;
     neuf=((n*10+e)*10+u)*10+f;
     three=(((t*10+h)*10+r)*10+e)*10+e;
     trois=(((t*10+r)*10+o)*10+i)*10+s;
     if(nine*three==neuf*trois) {
        printf("Solution found!\n\n");
        printf("T=%d N=%d E=%d S=%d F=%d H=%d R=%d I=%d O=%d U=%d\n",t,n,e,s,f,h,r,i,o,u);
        printf("NINE=%d THREE=%d NEUF=%d TROIS=%d\n",nine,three,neuf,trois);
        printf("NINE*THREE = NEUF*TROIS = %d\n",neuf*trois);
        return 0;
     }
  } while(TMath::Permute(10,a));
  printf("No solutions found -- something is wrong here!\n");
  return 0;
}

void permute() {
   permuteSimple1();
   permuteSimple2();
   permuteFancy();
}
<|endoftext|>