<commit_before>//============================================================================
// MCKL/include/mckl/random/threefry.hpp
//----------------------------------------------------------------------------
// MCKL: Monte Carlo Kernel Library
//----------------------------------------------------------------------------
// 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 MCKL_RANDOM_THREEFRY_HPP
#define MCKL_RANDOM_THREEFRY_HPP

#include <mckl/random/internal/common.hpp>
#include <mckl/random/internal/threefry_constants.hpp>
#include <mckl/random/internal/threefry_generic.hpp>
#include <mckl/random/counter.hpp>
#include <mckl/random/increment.hpp>

#if MCKL_HAS_SSE2
#include <mckl/random/internal/threefry_sse2.hpp>
#endif

#if MCKL_HAS_AVX2
#include <mckl/random/internal/threefry_avx2.hpp>
#endif

/// \brief ThreefryGenerator default rounds
/// \ingroup Config
#ifndef MCKL_THREEFRY_ROUNDS
#define MCKL_THREEFRY_ROUNDS 20
#endif

namespace mckl
{

namespace internal
{

#if MCKL_USE_AVX2
template <typename T, std::size_t K, std::size_t Rounds, typename Constants>
using ThreefryGeneratorImpl =
    ThreefryGeneratorAVX2Impl<T, K, Rounds, Constants>;
#elif MCKL_USE_SSE2
template <typename T, std::size_t K, std::size_t Rounds, typename Constants>
using ThreefryGeneratorImpl =
    ThreefryGeneratorSSE2Impl<T, K, Rounds, Constants>;
#else  // MCKL_USE_AVX2
template <typename T, std::size_t K, std::size_t Rounds, typename Constants>
using ThreefryGeneratorImpl =
    ThreefryGeneratorGeneric2Impl<T, K, Rounds, Constants>;
#endif // MCKL_USE_AVX2

} // namespace mckl::internal

/// \brief Threefry RNG generator
/// \ingroup Threefry
///
/// \tparam T State vector value type
/// \tparam K State vector length
/// \tparam Rounds The number of rounds
/// \tparam Constants A trait class that defines algorithm constants
template <typename T, std::size_t K, std::size_t Rounds = MCKL_THREEFRY_ROUNDS,
    typename Constants = ThreefryConstants<T, K>>
class ThreefryGenerator
{
    static_assert(std::is_unsigned<T>::value,
        "**ThreefryGenerator** used with T other than unsigned integer types");

    static_assert(K != 0 && K % 2 == 0,
        "**ThreefryGenerator** used with K other than multiples of 2");

    static_assert(
        Rounds != 0, "**ThreefryGenerator** used with rounds equal to zero");

    public:
    using ctr_type = Counter<T, K>;
    using key_type = std::array<T, K>;

    static constexpr std::size_t size() { return sizeof(T) * K; }

    key_type key() const
    {
        key_type key;
        std::memcpy(key.data(), par_.data(), sizeof(T) * K);

        return key;
    }

    void reset(const key_type &key)
    {
        constexpr T p = Constants::parity::value;

        std::memcpy(par_.data(), key.data(), sizeof(T) * K);
        std::get<K>(par_) = p;
        for (std::size_t i = 0; i != key.size(); ++i)
            std::get<K>(par_) ^= par_[i];
        std::get<K + 1>(par_) = 0;
        std::get<K + 2>(par_) = 0;
        std::get<K + 3>(par_) = 0;
    }

    std::pair<T, T> tweak() const
    {
        return std::make_pair(std::get<K + 1>(par_), std::get<K + 2>(par_));
    }

    void tweak(T t0, T t1)
    {
        std::get<K + 1>(par_) = t0;
        std::get<K + 2>(par_) = t1;
        std::get<K + 3>(par_) = t0 ^ t1;
    }

    void operator()(const void *plain, void *cipher) const
    {
        internal::ThreefryGeneratorImpl<T, K, Rounds, Constants>::eval(
            plain, cipher, par_);
    }

    template <typename ResultType>
    void operator()(ctr_type &ctr, ResultType *r) const
    {
        internal::ThreefryGeneratorImpl<T, K, Rounds, Constants>::eval(
            ctr, r, par_);
    }

    template <typename ResultType>
    void operator()(ctr_type &ctr, std::size_t n, ResultType *r) const
    {
        internal::ThreefryGeneratorImpl<T, K, Rounds, Constants>::eval(
            ctr, n, r, par_);
    }

    friend bool operator==(
        const ThreefryGenerator<T, K, Rounds, Constants> &gen1,
        const ThreefryGenerator<T, K, Rounds, Constants> &gen2)
    {
        return gen1.par_ == gen2.par_;
    }

    friend bool operator!=(
        const ThreefryGenerator<T, K, Rounds, Constants> &gen1,
        const ThreefryGenerator<T, K, Rounds, Constants> &gen2)
    {
        return !(gen1 == gen2);
    }

    template <typename CharT, typename Traits>
    friend std::basic_ostream<CharT, Traits> &operator<<(
        std::basic_ostream<CharT, Traits> &os,
        const ThreefryGenerator<T, K, Rounds, Constants> &gen)
    {
        if (!os)
            return os;

        os << gen.par_;

        return os;
    }

    template <typename CharT, typename Traits>
    friend std::basic_istream<CharT, Traits> &operator>>(
        std::basic_istream<CharT, Traits> &is,
        ThreefryGenerator<T, K, Rounds, Constants> &gen)
    {
        if (!is)
            return is;

        ThreefryGenerator<T, K, Rounds, Constants> gen_tmp;
        gen_tmp.par_.fill(0);
        is >> std::ws >> gen_tmp.par_;

        if (is)
            gen = std::move(gen_tmp);

        return is;
    }

    private:
    std::array<T, K + 4> par_;
}; // class ThreefryGenerator

/// \brief Threefry RNG engine
/// \ingroup Threefry
template <typename ResultType, typename T, std::size_t K,
    std::size_t Rounds = MCKL_THREEFRY_ROUNDS,
    typename Constants = ThreefryConstants<T, K>>
using ThreefryEngine =
    CounterEngine<ResultType, ThreefryGenerator<T, K, Rounds, Constants>>;

/// \brief Threefry2x32 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry2x32Engine = ThreefryEngine<ResultType, std::uint32_t, 2>;

/// \brief Threefry4x32 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry4x32Engine = ThreefryEngine<ResultType, std::uint32_t, 4>;

/// \brief Threefry2x64 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry2x64Engine = ThreefryEngine<ResultType, std::uint64_t, 2>;

/// \brief Threefry4x64 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry4x64Engine = ThreefryEngine<ResultType, std::uint64_t, 4>;

/// \brief Threefry8x64 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry8x64Engine = ThreefryEngine<ResultType, std::uint64_t, 8>;

/// \brief Threefry16x64 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry16x64Engine = ThreefryEngine<ResultType, std::uint64_t, 16>;

/// \brief Threefish-256 RNG engine
template <typename ResultType>
using Threefish256Engine = ThreefryEngine<ResultType, std::uint64_t, 4, 72>;

/// \brief Threefish-512 RNG engine
template <typename ResultType>
using Threefish512Engine = ThreefryEngine<ResultType, std::uint64_t, 8, 72>;

/// \brief Threefish-1024 RNG engine
template <typename ResultType>
using Threefish1024Engine = ThreefryEngine<ResultType, std::uint64_t, 16, 80>;

/// \brief Threefry2x32 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry2x32 = Threefry2x32Engine<std::uint32_t>;

/// \brief Threefry4x32 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry4x32 = Threefry4x32Engine<std::uint32_t>;

/// \brief Threefry2x64 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry2x64 = Threefry2x64Engine<std::uint32_t>;

/// \brief Threefry4x64 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry4x64 = Threefry4x64Engine<std::uint32_t>;

/// \brief Threefry8x64 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry8x64 = Threefry8x64Engine<std::uint32_t>;

/// \brief Threefry16x64 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry16x64 = Threefry16x64Engine<std::uint32_t>;

/// \brief Threefish-256 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefish256 = Threefish256Engine<std::uint32_t>;

/// \brief Threefish-512 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefish512 = Threefish512Engine<std::uint32_t>;

/// \brief Threefish-1024 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefish1024 = Threefish1024Engine<std::uint32_t>;

/// \brief Threefry2x32 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry2x32_64 = Threefry2x32Engine<std::uint64_t>;

/// \brief Threefry4x32 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry4x32_64 = Threefry4x32Engine<std::uint64_t>;

/// \brief Threefry2x64 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry2x64_64 = Threefry2x64Engine<std::uint64_t>;

/// \brief Threefry4x64 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry4x64_64 = Threefry4x64Engine<std::uint64_t>;

/// \brief Threefry8x64 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry8x64_64 = Threefry8x64Engine<std::uint64_t>;

/// \brief Threefry16x64 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry16x64_64 = Threefry16x64Engine<std::uint64_t>;

/// \brief Threefish-256 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefish256_64 = Threefish256Engine<std::uint64_t>;

/// \brief Threefish-512 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefish512_64 = Threefish512Engine<std::uint64_t>;

/// \brief Threefish-1024 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefish1024_64 = Threefish1024Engine<std::uint64_t>;

} // namespace mckl

#endif // MCKL_RANDOM_THREEFRY_HPP
<commit_msg>fix generic threefry<commit_after>//============================================================================
// MCKL/include/mckl/random/threefry.hpp
//----------------------------------------------------------------------------
// MCKL: Monte Carlo Kernel Library
//----------------------------------------------------------------------------
// 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 MCKL_RANDOM_THREEFRY_HPP
#define MCKL_RANDOM_THREEFRY_HPP

#include <mckl/random/internal/common.hpp>
#include <mckl/random/internal/threefry_constants.hpp>
#include <mckl/random/internal/threefry_generic.hpp>
#include <mckl/random/counter.hpp>
#include <mckl/random/increment.hpp>

#if MCKL_HAS_SSE2
#include <mckl/random/internal/threefry_sse2.hpp>
#endif

#if MCKL_HAS_AVX2
#include <mckl/random/internal/threefry_avx2.hpp>
#endif

/// \brief ThreefryGenerator default rounds
/// \ingroup Config
#ifndef MCKL_THREEFRY_ROUNDS
#define MCKL_THREEFRY_ROUNDS 20
#endif

namespace mckl
{

namespace internal
{

#if MCKL_USE_AVX2
template <typename T, std::size_t K, std::size_t Rounds, typename Constants>
using ThreefryGeneratorImpl =
    ThreefryGeneratorAVX2Impl<T, K, Rounds, Constants>;
#elif MCKL_USE_SSE2
template <typename T, std::size_t K, std::size_t Rounds, typename Constants>
using ThreefryGeneratorImpl =
    ThreefryGeneratorSSE2Impl<T, K, Rounds, Constants>;
#else  // MCKL_USE_AVX2
template <typename T, std::size_t K, std::size_t Rounds, typename Constants>
using ThreefryGeneratorImpl =
    ThreefryGeneratorGenericImpl<T, K, Rounds, Constants>;
#endif // MCKL_USE_AVX2

} // namespace mckl::internal

/// \brief Threefry RNG generator
/// \ingroup Threefry
///
/// \tparam T State vector value type
/// \tparam K State vector length
/// \tparam Rounds The number of rounds
/// \tparam Constants A trait class that defines algorithm constants
template <typename T, std::size_t K, std::size_t Rounds = MCKL_THREEFRY_ROUNDS,
    typename Constants = ThreefryConstants<T, K>>
class ThreefryGenerator
{
    static_assert(std::is_unsigned<T>::value,
        "**ThreefryGenerator** used with T other than unsigned integer types");

    static_assert(K != 0 && K % 2 == 0,
        "**ThreefryGenerator** used with K other than multiples of 2");

    static_assert(
        Rounds != 0, "**ThreefryGenerator** used with rounds equal to zero");

    public:
    using ctr_type = Counter<T, K>;
    using key_type = std::array<T, K>;

    static constexpr std::size_t size() { return sizeof(T) * K; }

    key_type key() const
    {
        key_type key;
        std::memcpy(key.data(), par_.data(), sizeof(T) * K);

        return key;
    }

    void reset(const key_type &key)
    {
        constexpr T p = Constants::parity::value;

        std::memcpy(par_.data(), key.data(), sizeof(T) * K);
        std::get<K>(par_) = p;
        for (std::size_t i = 0; i != key.size(); ++i)
            std::get<K>(par_) ^= par_[i];
        std::get<K + 1>(par_) = 0;
        std::get<K + 2>(par_) = 0;
        std::get<K + 3>(par_) = 0;
    }

    std::pair<T, T> tweak() const
    {
        return std::make_pair(std::get<K + 1>(par_), std::get<K + 2>(par_));
    }

    void tweak(T t0, T t1)
    {
        std::get<K + 1>(par_) = t0;
        std::get<K + 2>(par_) = t1;
        std::get<K + 3>(par_) = t0 ^ t1;
    }

    void operator()(const void *plain, void *cipher) const
    {
        internal::ThreefryGeneratorImpl<T, K, Rounds, Constants>::eval(
            plain, cipher, par_);
    }

    template <typename ResultType>
    void operator()(ctr_type &ctr, ResultType *r) const
    {
        internal::ThreefryGeneratorImpl<T, K, Rounds, Constants>::eval(
            ctr, r, par_);
    }

    template <typename ResultType>
    void operator()(ctr_type &ctr, std::size_t n, ResultType *r) const
    {
        internal::ThreefryGeneratorImpl<T, K, Rounds, Constants>::eval(
            ctr, n, r, par_);
    }

    friend bool operator==(
        const ThreefryGenerator<T, K, Rounds, Constants> &gen1,
        const ThreefryGenerator<T, K, Rounds, Constants> &gen2)
    {
        return gen1.par_ == gen2.par_;
    }

    friend bool operator!=(
        const ThreefryGenerator<T, K, Rounds, Constants> &gen1,
        const ThreefryGenerator<T, K, Rounds, Constants> &gen2)
    {
        return !(gen1 == gen2);
    }

    template <typename CharT, typename Traits>
    friend std::basic_ostream<CharT, Traits> &operator<<(
        std::basic_ostream<CharT, Traits> &os,
        const ThreefryGenerator<T, K, Rounds, Constants> &gen)
    {
        if (!os)
            return os;

        os << gen.par_;

        return os;
    }

    template <typename CharT, typename Traits>
    friend std::basic_istream<CharT, Traits> &operator>>(
        std::basic_istream<CharT, Traits> &is,
        ThreefryGenerator<T, K, Rounds, Constants> &gen)
    {
        if (!is)
            return is;

        ThreefryGenerator<T, K, Rounds, Constants> gen_tmp;
        gen_tmp.par_.fill(0);
        is >> std::ws >> gen_tmp.par_;

        if (is)
            gen = std::move(gen_tmp);

        return is;
    }

    private:
    std::array<T, K + 4> par_;
}; // class ThreefryGenerator

/// \brief Threefry RNG engine
/// \ingroup Threefry
template <typename ResultType, typename T, std::size_t K,
    std::size_t Rounds = MCKL_THREEFRY_ROUNDS,
    typename Constants = ThreefryConstants<T, K>>
using ThreefryEngine =
    CounterEngine<ResultType, ThreefryGenerator<T, K, Rounds, Constants>>;

/// \brief Threefry2x32 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry2x32Engine = ThreefryEngine<ResultType, std::uint32_t, 2>;

/// \brief Threefry4x32 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry4x32Engine = ThreefryEngine<ResultType, std::uint32_t, 4>;

/// \brief Threefry2x64 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry2x64Engine = ThreefryEngine<ResultType, std::uint64_t, 2>;

/// \brief Threefry4x64 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry4x64Engine = ThreefryEngine<ResultType, std::uint64_t, 4>;

/// \brief Threefry8x64 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry8x64Engine = ThreefryEngine<ResultType, std::uint64_t, 8>;

/// \brief Threefry16x64 RNG engine
/// \ingroup Threefry
template <typename ResultType>
using Threefry16x64Engine = ThreefryEngine<ResultType, std::uint64_t, 16>;

/// \brief Threefish-256 RNG engine
template <typename ResultType>
using Threefish256Engine = ThreefryEngine<ResultType, std::uint64_t, 4, 72>;

/// \brief Threefish-512 RNG engine
template <typename ResultType>
using Threefish512Engine = ThreefryEngine<ResultType, std::uint64_t, 8, 72>;

/// \brief Threefish-1024 RNG engine
template <typename ResultType>
using Threefish1024Engine = ThreefryEngine<ResultType, std::uint64_t, 16, 80>;

/// \brief Threefry2x32 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry2x32 = Threefry2x32Engine<std::uint32_t>;

/// \brief Threefry4x32 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry4x32 = Threefry4x32Engine<std::uint32_t>;

/// \brief Threefry2x64 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry2x64 = Threefry2x64Engine<std::uint32_t>;

/// \brief Threefry4x64 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry4x64 = Threefry4x64Engine<std::uint32_t>;

/// \brief Threefry8x64 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry8x64 = Threefry8x64Engine<std::uint32_t>;

/// \brief Threefry16x64 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefry16x64 = Threefry16x64Engine<std::uint32_t>;

/// \brief Threefish-256 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefish256 = Threefish256Engine<std::uint32_t>;

/// \brief Threefish-512 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefish512 = Threefish512Engine<std::uint32_t>;

/// \brief Threefish-1024 RNG engine with 32-bit integer output
/// \ingroup Threefry
using Threefish1024 = Threefish1024Engine<std::uint32_t>;

/// \brief Threefry2x32 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry2x32_64 = Threefry2x32Engine<std::uint64_t>;

/// \brief Threefry4x32 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry4x32_64 = Threefry4x32Engine<std::uint64_t>;

/// \brief Threefry2x64 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry2x64_64 = Threefry2x64Engine<std::uint64_t>;

/// \brief Threefry4x64 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry4x64_64 = Threefry4x64Engine<std::uint64_t>;

/// \brief Threefry8x64 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry8x64_64 = Threefry8x64Engine<std::uint64_t>;

/// \brief Threefry16x64 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefry16x64_64 = Threefry16x64Engine<std::uint64_t>;

/// \brief Threefish-256 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefish256_64 = Threefish256Engine<std::uint64_t>;

/// \brief Threefish-512 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefish512_64 = Threefish512Engine<std::uint64_t>;

/// \brief Threefish-1024 RNG engine with 64-bit integer output
/// \ingroup Threefry
using Threefish1024_64 = Threefish1024Engine<std::uint64_t>;

} // namespace mckl

#endif // MCKL_RANDOM_THREEFRY_HPP
<|endoftext|>


<commit_before>#ifndef PROTOCOL_MESSAGES_HPP_
#define PROTOCOL_MESSAGES_HPP_

#include <cstdint>

namespace protocol {
namespace message {

struct heartbeat_message_t {
  enum { ID = 0x00 };

  std::uint8_t seq;
} __attribute__((packed));

struct log_message_t {
  enum { ID = 0x01 };

  uint32_t time;
  char data[100];
} __attribute__((packed));

struct attitude_message_t {
  enum { ID = 0x02 };

  uint32_t time;
  float dcm[9];
} __attribute__((packed));

struct set_arm_state_message_t {
  enum { ID = 0x03 };

  bool armed;
} __attribute__((packed));

struct set_control_mode_message_t {
  enum { ID = 0x04 };

  enum class ControlMode {
    MANUAL,
    OFFBOARD
  };

  ControlMode mode;
} __attribute__((packed));

struct offboard_attitude_control_message_t {
  enum { ID = 0x05 };

  float roll;
  float pitch;
  float yaw;
  float throttle;
  uint16_t buttons;   // Bitfield of buttons
  uint8_t mode;
} __attribute__((packed));

struct motor_throttle_message_t {
  enum { ID = 0x06 };

  uint32_t time;
  float throttles[4];
} __attribute__((packed));

struct sensor_calibration_request_message_t {
  enum { ID = 0x07 };
} __attribute__((packed));

struct sensor_calibration_response_message_t {
  enum { ID = 0x08 };

  enum class SensorType {
    ACCEL,
    GYRO,
    MAG
  };

  SensorType type;
  float offsets[3];
} __attribute__((packed));

struct location_message_t {
  enum { ID = 0x09 };

  uint32_t time;
  float lat;
  float lon;
  float alt;
} __attribute__((packed));

struct imu_message_t {
  enum { ID = 0x0a };
  uint32_t time;
  float gyro[3];     // Gyroscope
  float accel[3];    // Accelerometer
} __attribute__((packed));

struct system_message_t {
  enum { ID = 0x0b };

  uint32_t time;
  uint8_t state;
  float motorDC;   // TODO(yoos): Hack for esra test launch
} __attribute__((packed));

struct raw_1000_message_t {
  enum { ID = 0x0c };
  uint32_t time;
  float accel[3];    // Accelerometer
  float accelH[3];   // High-g accel
  float gyro[3];     // Gyroscope
} __attribute__((packed));

struct raw_50_message_t {
  enum { ID = 0x0d };
  uint32_t time;
  float bar;   // Barometric pressure
  float temp;   // Temperature
  float mag[3];   // Magnetometer
} __attribute((packed));

struct raw_10_message_t {
  enum { ID = 0x0e };
  uint32_t time;
  bool gps_valid;
  float lat;
  float lon;
  float utc;   // UTC time
  uint16_t geigerCount;   // Number of blips counted since last report
} __attribute((packed));

struct fs_info_message_t {
  enum { ID = 0x0f };
  uint32_t time;
  char fname[32];
  uint32_t fsize;
} __attribute((packed));

inline std::uint16_t length(int id) {
  // TODO(kyle): sizeof(empty struct) is 1 in C++...
  switch(id) {
    case heartbeat_message_t::ID:
      return sizeof(heartbeat_message_t);
    case log_message_t::ID:
      return sizeof(log_message_t);
    case attitude_message_t::ID:
      return sizeof(attitude_message_t);
    case set_arm_state_message_t::ID:
      return sizeof(set_arm_state_message_t);
    case set_control_mode_message_t::ID:
      return sizeof(set_control_mode_message_t);
    case offboard_attitude_control_message_t::ID:
      return sizeof(offboard_attitude_control_message_t);
    case motor_throttle_message_t::ID:
      return sizeof(motor_throttle_message_t);
    case sensor_calibration_request_message_t::ID:
      return sizeof(sensor_calibration_request_message_t);
    case sensor_calibration_response_message_t::ID:
      return sizeof(sensor_calibration_response_message_t);
    case location_message_t::ID:
      return sizeof(location_message_t);
    case imu_message_t::ID:
      return sizeof(imu_message_t);
    case system_message_t::ID:
      return sizeof(system_message_t);
    case raw_1000_message_t::ID:
      return sizeof(raw_1000_message_t);
    case raw_50_message_t::ID:
      return sizeof(raw_50_message_t);
    case raw_10_message_t::ID:
      return sizeof(raw_10_message_t);
    case fs_info_message_t::ID:
      return sizeof(fs_info_message_t);
  }

  return 0; // TODO(kyle): Return something more meaningful?
}

}
}

#endif // MESSAGES_HPP_

<commit_msg>Comment message types.<commit_after>#ifndef PROTOCOL_MESSAGES_HPP_
#define PROTOCOL_MESSAGES_HPP_

#include <cstdint>

namespace protocol {
namespace message {

// NOTE: message types indicated with downlink/uplink use

// Heartbeat (down)
struct heartbeat_message_t {
  enum { ID = 0x00 };

  std::uint8_t seq;
} __attribute__((packed));

// Log (up)
// TODO(syoo): this is unused
struct log_message_t {
  enum { ID = 0x01 };

  uint32_t time;
  char data[100];
} __attribute__((packed));

// Attitude in DCM (down)
struct attitude_message_t {
  enum { ID = 0x02 };

  uint32_t time;
  float dcm[9];
} __attribute__((packed));

// Set arm state (up)
struct set_arm_state_message_t {
  enum { ID = 0x03 };

  bool armed;
} __attribute__((packed));

// Set control mode (up)
struct set_control_mode_message_t {
  enum { ID = 0x04 };

  enum class ControlMode {
    MANUAL,
    OFFBOARD
  };

  ControlMode mode;
} __attribute__((packed));

// Joystick input (up)
struct offboard_attitude_control_message_t {
  enum { ID = 0x05 };

  float roll;
  float pitch;
  float yaw;
  float throttle;
  uint16_t buttons;   // Bitfield of buttons
  uint8_t mode;
} __attribute__((packed));

// Throttle (down)
struct motor_throttle_message_t {
  enum { ID = 0x06 };

  uint32_t time;
  float throttles[4];
} __attribute__((packed));

// Sensor calibration request (up)
struct sensor_calibration_request_message_t {
  enum { ID = 0x07 };
} __attribute__((packed));

// Sensor calibration response (down)
struct sensor_calibration_response_message_t {
  enum { ID = 0x08 };

  enum class SensorType {
    ACCEL,
    GYRO,
    MAG
  };

  SensorType type;
  float offsets[3];
} __attribute__((packed));

// Location (down)
struct location_message_t {
  enum { ID = 0x09 };

  uint32_t time;
  float lat;
  float lon;
  float alt;
} __attribute__((packed));

// IMU (down)
struct imu_message_t {
  enum { ID = 0x0a };
  uint32_t time;
  float gyro[3];     // Gyroscope
  float accel[3];    // Accelerometer
} __attribute__((packed));

// System (down)
struct system_message_t {
  enum { ID = 0x0b };

  uint32_t time;
  uint8_t state;
  float motorDC;   // TODO(yoos): Hack for esra test launch
} __attribute__((packed));

// 1000 Hz stream (down)
struct raw_1000_message_t {
  enum { ID = 0x0c };
  uint32_t time;
  float accel[3];    // Accelerometer
  float accelH[3];   // High-g accel
  float gyro[3];     // Gyroscope
} __attribute__((packed));

// 50 Hz stream (down)
struct raw_50_message_t {
  enum { ID = 0x0d };
  uint32_t time;
  float bar;   // Barometric pressure
  float temp;   // Temperature
  float mag[3];   // Magnetometer
} __attribute((packed));

// 10 Hz stream (down)
struct raw_10_message_t {
  enum { ID = 0x0e };
  uint32_t time;
  bool gps_valid;
  float lat;
  float lon;
  float utc;   // UTC time
  uint16_t geigerCount;   // Number of blips counted since last report
} __attribute((packed));

// Filesystem (down)
struct fs_info_message_t {
  enum { ID = 0x0f };
  uint32_t time;
  char fname[32];
  uint32_t fsize;
} __attribute((packed));

inline std::uint16_t length(int id) {
  // TODO(kyle): sizeof(empty struct) is 1 in C++...
  switch(id) {
    case heartbeat_message_t::ID:
      return sizeof(heartbeat_message_t);
    case log_message_t::ID:
      return sizeof(log_message_t);
    case attitude_message_t::ID:
      return sizeof(attitude_message_t);
    case set_arm_state_message_t::ID:
      return sizeof(set_arm_state_message_t);
    case set_control_mode_message_t::ID:
      return sizeof(set_control_mode_message_t);
    case offboard_attitude_control_message_t::ID:
      return sizeof(offboard_attitude_control_message_t);
    case motor_throttle_message_t::ID:
      return sizeof(motor_throttle_message_t);
    case sensor_calibration_request_message_t::ID:
      return sizeof(sensor_calibration_request_message_t);
    case sensor_calibration_response_message_t::ID:
      return sizeof(sensor_calibration_response_message_t);
    case location_message_t::ID:
      return sizeof(location_message_t);
    case imu_message_t::ID:
      return sizeof(imu_message_t);
    case system_message_t::ID:
      return sizeof(system_message_t);
    case raw_1000_message_t::ID:
      return sizeof(raw_1000_message_t);
    case raw_50_message_t::ID:
      return sizeof(raw_50_message_t);
    case raw_10_message_t::ID:
      return sizeof(raw_10_message_t);
    case fs_info_message_t::ID:
      return sizeof(fs_info_message_t);
  }

  return 0; // TODO(kyle): Return something more meaningful?
}

}
}

#endif // MESSAGES_HPP_

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * Copyright (c) 2011-2012 Kohei Yoshida
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************/

#ifndef __MDDS_GRID_MAP_COLUMN_HPP__
#define __MDDS_GRID_MAP_COLUMN_HPP__

#include "mdds/default_deleter.hpp"
#include "mdds/compat/unique_ptr.hpp"

#include <vector>
#include <algorithm>
#include <cassert>

#include <boost/noncopyable.hpp>

namespace mdds { namespace __gridmap {

/**
 * Each column consists of a series of blocks, and each block stores a
 * series of non-empty cells of identical type.
 */
template<typename _Trait>
class column
{
public:
    typedef typename _Trait::cell_type cell_type;
    typedef typename _Trait::cell_category_type cell_category_type;
    typedef typename _Trait::row_key_type row_key_type;

private:
    typedef typename _Trait::cell_delete_handler cell_delete_handler;

    /**
     * Data for non-empty block.  Cells are stored here.
     */
    struct block_data : boost::noncopyable
    {
        cell_category_type m_type;
        std::vector<cell_type*> m_cells;

        block_data(cell_category_type _type, size_t _init_size = 0);
        ~block_data();
    };

    /**
     * Empty or non-empty block.
     */
    struct block : boost::noncopyable
    {
        row_key_type m_size;
        block_data* mp_data;
        bool m_empty;

        block();
        block(row_key_type _size);
        ~block();
    };

    column(); // disabled
public:
    column(row_key_type max_row);
    ~column();

    void set_cell(row_key_type row, cell_category_type cat, cell_type* cell);
    const cell_type* get_cell(row_key_type row) const;

private:
    std::vector<block*> m_blocks;
    row_key_type m_max_row;
};

template<typename _Trait>
column<_Trait>::block_data::block_data(cell_category_type _type, size_t _init_size) :
    m_type(_type), m_cells(_init_size, NULL) {}

template<typename _Trait>
column<_Trait>::block_data::~block_data()
{
    std::for_each(m_cells.begin(), m_cells.end(), cell_delete_handler());
}

template<typename _Trait>
column<_Trait>::block::block() : m_size(0), m_empty(true), mp_data(NULL) {}

template<typename _Trait>
column<_Trait>::block::block(row_key_type _size) : m_size(_size), mp_data(NULL), m_empty(true) {}

template<typename _Trait>
column<_Trait>::block::~block()
{
    delete mp_data;
}

template<typename _Trait>
column<_Trait>::column(row_key_type max_row) : m_max_row(max_row)
{
    // Initialize with an empty block that spans from 0 to max.
    m_blocks.push_back(new block(max_row));
}

template<typename _Trait>
column<_Trait>::~column()
{
    std::for_each(m_blocks.begin(), m_blocks.end(), default_deleter<block>());
}

template<typename _Trait>
void column<_Trait>::set_cell(row_key_type row, cell_category_type cat, cell_type* cell)
{
    unique_ptr<cell_type, cell_delete_handler> p(cell);

    // Find the right block ID from the row ID.
    row_key_type start_row = 0; // row ID of the first cell in a block.
    row_key_type block_index = 0;
    for (size_t i = 0, n = m_blocks.size(); i < n; ++i)
    {
        const block& blk = *m_blocks[i];
        if (row < start_row + blk.m_size)
        {
            // Row is in this block.
            block_index = i;
            break;
        }

        // Specified row is not in this block.
        start_row += blk.m_size;
    }

    block& blk = *m_blocks[block_index];
    assert(blk.m_size > 0); // block size should never be zero at any time.

    if (blk.m_empty)
    {
        // This is an empty block.
    }
    else if (blk.mp_data->m_type == cat)
    {
        // This block is of the same type as the cell being inserted.
    }
    else if (row == start_row)
    {
        // Insertion point is at the start of the block.
    }
    else if (row == (start_row + blk.m_size - 1))
    {
        // Insertion point is at the end of the block.
    }
    else
    {
        // Insertion point is somewhere in the middle of the block.
    }
}

template<typename _Trait>
const typename column<_Trait>::cell_type*
column<_Trait>::get_cell(row_key_type row) const
{
    row_key_type start_row = 0;
    for (size_t i = 0, n = m_blocks.size(); i < n; ++i)
    {
        const block& blk = *m_blocks[i];
        if (row >= start_row + blk.m_size)
        {
            // Specified row is not in this block.
            start_row += blk.m_size;
            continue;
        }

        if (blk.m_empty)
            // empty cell block.
            return NULL;

        assert(row >= start_row);
        assert(blk.mp_data); // data for non-empty blocks should never be NULL.
        assert(blk.m_size == static_cast<row_key_type>(blk.mp_data->m_cells.size()));
        row_key_type idx = row - start_row;
        return blk.mp_data->m_cells[idx];
    }
    return NULL;
}

}}

#endif
<commit_msg>Insertion into a blcok of identical type.<commit_after>/*************************************************************************
 *
 * Copyright (c) 2011-2012 Kohei Yoshida
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************/

#ifndef __MDDS_GRID_MAP_COLUMN_HPP__
#define __MDDS_GRID_MAP_COLUMN_HPP__

#include "mdds/default_deleter.hpp"
#include "mdds/compat/unique_ptr.hpp"

#include <vector>
#include <algorithm>
#include <cassert>

#include <boost/noncopyable.hpp>

namespace mdds { namespace __gridmap {

/**
 * Each column consists of a series of blocks, and each block stores a
 * series of non-empty cells of identical type.
 */
template<typename _Trait>
class column
{
public:
    typedef typename _Trait::cell_type cell_type;
    typedef typename _Trait::cell_category_type cell_category_type;
    typedef typename _Trait::row_key_type row_key_type;

private:
    typedef typename _Trait::cell_delete_handler cell_delete_handler;

    /**
     * Data for non-empty block.  Cells are stored here.
     */
    struct block_data : boost::noncopyable
    {
        cell_category_type m_type;
        std::vector<cell_type*> m_cells;

        block_data(cell_category_type _type, size_t _init_size = 0);
        ~block_data();
    };

    /**
     * Empty or non-empty block.
     */
    struct block : boost::noncopyable
    {
        row_key_type m_size;
        block_data* mp_data;
        bool m_empty;

        block();
        block(row_key_type _size);
        ~block();
    };

    column(); // disabled
public:
    column(row_key_type max_row);
    ~column();

    void set_cell(row_key_type row, cell_category_type cat, cell_type* cell);
    const cell_type* get_cell(row_key_type row) const;

private:
    std::vector<block*> m_blocks;
    row_key_type m_max_row;
};

template<typename _Trait>
column<_Trait>::block_data::block_data(cell_category_type _type, size_t _init_size) :
    m_type(_type), m_cells(_init_size, NULL) {}

template<typename _Trait>
column<_Trait>::block_data::~block_data()
{
    std::for_each(m_cells.begin(), m_cells.end(), cell_delete_handler());
}

template<typename _Trait>
column<_Trait>::block::block() : m_size(0), m_empty(true), mp_data(NULL) {}

template<typename _Trait>
column<_Trait>::block::block(row_key_type _size) : m_size(_size), mp_data(NULL), m_empty(true) {}

template<typename _Trait>
column<_Trait>::block::~block()
{
    delete mp_data;
}

template<typename _Trait>
column<_Trait>::column(row_key_type max_row) : m_max_row(max_row)
{
    // Initialize with an empty block that spans from 0 to max.
    m_blocks.push_back(new block(max_row));
}

template<typename _Trait>
column<_Trait>::~column()
{
    std::for_each(m_blocks.begin(), m_blocks.end(), default_deleter<block>());
}

template<typename _Trait>
void column<_Trait>::set_cell(row_key_type row, cell_category_type cat, cell_type* cell)
{
    unique_ptr<cell_type, cell_delete_handler> p(cell);

    // Find the right block ID from the row ID.
    row_key_type start_row = 0; // row ID of the first cell in a block.
    row_key_type block_index = 0;
    for (size_t i = 0, n = m_blocks.size(); i < n; ++i)
    {
        const block& blk = *m_blocks[i];
        if (row < start_row + blk.m_size)
        {
            // Row is in this block.
            block_index = i;
            break;
        }

        // Specified row is not in this block.
        start_row += blk.m_size;
    }

    block& blk = *m_blocks[block_index];
    assert(blk.m_size > 0); // block size should never be zero at any time.

    if (blk.m_empty)
    {
        // This is an empty block.
    }
    else if (blk.mp_data->m_type == cat)
    {
        // This block is of the same type as the cell being inserted.
        assert(blk.mp_data);
        block_data& data = *blk.mp_data;
        row_key_type i = row - start_row;
        assert(data.m_cells.size() > static_cast<size_t>(i));
        delete data.m_cells[i];
        data.m_cells[i] = p.release();
    }
    else if (row == start_row)
    {
        // Insertion point is at the start of the block.
    }
    else if (row == (start_row + blk.m_size - 1))
    {
        // Insertion point is at the end of the block.
    }
    else
    {
        // Insertion point is somewhere in the middle of the block.
    }
}

template<typename _Trait>
const typename column<_Trait>::cell_type*
column<_Trait>::get_cell(row_key_type row) const
{
    row_key_type start_row = 0;
    for (size_t i = 0, n = m_blocks.size(); i < n; ++i)
    {
        const block& blk = *m_blocks[i];
        if (row >= start_row + blk.m_size)
        {
            // Specified row is not in this block.
            start_row += blk.m_size;
            continue;
        }

        if (blk.m_empty)
            // empty cell block.
            return NULL;

        assert(row >= start_row);
        assert(blk.mp_data); // data for non-empty blocks should never be NULL.
        assert(blk.m_size == static_cast<row_key_type>(blk.mp_data->m_cells.size()));
        row_key_type idx = row - start_row;
        return blk.mp_data->m_cells[idx];
    }
    return NULL;
}

}}

#endif
<|endoftext|>


<commit_before>#ifndef _INCLUDED_INPUT_HPP
#define _INCLUDED_INPUT_HPP

#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

#include <boost/utility/string_ref.hpp>
#include <boost/variant.hpp>

#include <tudocomp/util.h>

#include <tudocomp/io/IOUtil.hpp>
#include <tudocomp/io/ViewStream.hpp>

namespace tudocomp {
namespace io {

    struct InputView;
    struct InputStream;

    /// Represents the input of an algorithm.
    ///
    /// Can be used as either a istream or a memory buffer
    /// with the as_stream or as_view methods.
    class Input {
        struct Memory {
            const uint8_t* ptr;
            size_t size;
        };
        struct File {
            std::string path;
            size_t offset;
        };

        friend class InputStream;
        friend class InputView;

        using Variant = boost::variant<Memory, File>;
        std::unique_ptr<Variant> m_data;

    public:
        struct Path { std::string path; };

        /// An empty Input
        inline Input():
            m_data(std::make_unique<Variant>(Memory { nullptr, 0 })) {}

        /// Create an copy of the Input, with internal cursors
        /// set to the current position
        inline Input(const Input& other):
            m_data(std::make_unique<Variant>(*other.m_data)) {}

        /// Move constructor
        inline Input(Input&& other):
            m_data(std::move(other.m_data)) {}

        /// An Input referring to the contents of a file
        Input(Input::Path&& path):
            m_data(std::make_unique<Variant>(File { std::move(path.path), 0 })) {}

        /// An Input referring to the contents of an vector
        Input(const std::vector<uint8_t>& buf):
            m_data(std::make_unique<Variant>(Memory { &buf[0], buf.size() })) {}

        /// An Input referring to the contents of an string
        Input(const boost::string_ref buf):
            m_data(std::make_unique<Variant>(
                    Memory { (const uint8_t*) &buf[0], buf.size() })) {}

        Input& operator=(Input&& other) {
            m_data = std::move(other.m_data);
            return *this;
        }

        /// DEPRECATED
        static Input from_path(std::string path) {
            return Input(Path { path });
        }

        /// DEPRECATED
        static Input from_memory(const std::vector<uint8_t>& buf) {
            return Input(buf);
        }

        /// DEPRECATED
        static Input from_memory(const boost::string_ref buf) {
            return Input(buf);
        }

        inline InputView as_view();
        inline InputStream as_stream();

        inline size_t size();
    };

    struct InputView {
        struct Memory {
            const uint8_t* ptr;
            const size_t size;
        };
        struct File {
            std::vector<uint8_t> buffer;
        };

        boost::variant<Memory, File> data;

        boost::string_ref operator* () {
            struct visitor: public boost::static_visitor<boost::string_ref> {
                boost::string_ref operator()(InputView::Memory& mem) const {
                    return boost::string_ref {
                        (char*) mem.ptr, mem.size
                    };
                }
                boost::string_ref operator()(InputView::File& mem) const {
                    return boost::string_ref {
                        (char*) mem.buffer.data(), mem.buffer.size()
                    };
                }
            };
            return boost::apply_visitor(visitor(), data);
        }

        const uint8_t* mem_ptr() {
            struct visitor: public boost::static_visitor<const uint8_t*> {
                const uint8_t* operator()(InputView::Memory& mem) const {
                    return mem.ptr;
                }
                const uint8_t* operator()(InputView::File& mem) const {
                    return mem.buffer.data();
                }
            };
            return boost::apply_visitor(visitor(), data);
        }

        size_t size() {
            struct visitor: public boost::static_visitor<size_t> {
                size_t operator()(InputView::Memory& mem) const {
                    return mem.size;
                }
                size_t operator()(InputView::File& mem) const {
                    return mem.buffer.size();
                }
            };
            return boost::apply_visitor(visitor(), data);
        }

        InputView(const InputView* other) = delete;
        InputView() = delete;

        InputView(InputView::Memory&& mem): data(std::move(mem)) {}
        InputView(InputView::File&& s): data(std::move(s)) {}

    };

    inline InputView Input::as_view() {
        struct visitor: public boost::static_visitor<InputView> {
            InputView operator()(Input::Memory& mem) const {
                Input::Memory mem2 = mem;

                // advance view into memory by its whole length
                mem.ptr += mem.size;
                mem.size = 0;

                return InputView {
                    InputView::Memory { mem2.ptr, mem2.size }
                };
            }
            InputView operator()(Input::File& mem) const {
                // read file into buffer starting at current offset
                auto buf = read_file_to_stl_byte_container<
                    std::vector<uint8_t>>(mem.path, mem.offset);

                // We read the whole file, so skip it on next read.
                mem.offset += buf.size();

                return InputView {
                    InputView::File {
                        std::move(buf)
                    }
                };
            }
        };

        return boost::apply_visitor(visitor(), *m_data);
    };

    struct InputStream {
        class Memory {
            ViewStream m_stream;

            Input::Memory* m_offset_back_ref;
            size_t m_start_pos;

            friend class InputStream;
        public:
            Memory(ViewStream&& stream, Input::Memory* offset_back_ref):
                m_stream(std::move(stream))
            {
                m_offset_back_ref = offset_back_ref;
                m_start_pos = m_stream.stream().tellg();
            }
            ~Memory() {
                size_t len = size_t(m_stream.stream().tellg()) - m_start_pos;
                m_offset_back_ref->ptr += len;
                m_offset_back_ref->size -= len;
            }
        };
        class File {
            std::string m_path;
            std::unique_ptr<std::ifstream> stream;

            Input::File* m_offset_back_ref;
            size_t m_start_pos;

            File(const File& other) = delete;
            File() = delete;

            friend class InputStream;
        public:
            File(std::string&& path,
                 Input::File* offset_back_ref,
                 size_t offset)
            {
                m_path = path;
                stream = std::make_unique<std::ifstream>(
                    m_path, std::ios::in | std::ios::binary);
                stream->seekg(offset, std::ios::beg);
                m_start_pos = stream->tellg();
                m_offset_back_ref = offset_back_ref;
            }

            File(File&& other) {
                stream = std::move(other.stream);
                m_offset_back_ref = other.m_offset_back_ref;
                m_path = other.m_path;
                m_start_pos = other.m_start_pos;
            }

            ~File() {
                if (stream != nullptr) {
                    auto len = size_t(stream->tellg()) - m_start_pos;
                    m_offset_back_ref->offset += len;
                }
            }
        };

        boost::variant<Memory, File> data;

        std::istream& operator* () {
            struct visitor: public boost::static_visitor<std::istream&> {
                std::istream& operator()(InputStream::Memory& m) const {
                    return m.m_stream.stream();
                }
                std::istream& operator()(InputStream::File& m) const {
                    return *m.stream;
                }
            };
            return boost::apply_visitor(visitor(), data);
        }

        InputStream(const InputStream* other) = delete;
        InputStream() = delete;

        InputStream(InputStream::Memory&& mem): data(std::move(mem)) {}
        InputStream(InputStream::File&& f): data(std::move(f)) {}
    };

    inline InputStream Input::as_stream() {
        struct visitor: public boost::static_visitor<InputStream> {
            InputStream operator()(Input::Memory& mem) const {
                return InputStream {
                    InputStream::Memory {
                        ViewStream {
                            (char*)mem.ptr,
                            mem.size
                        },
                        &mem
                    }
                };
            }
            InputStream operator()(Input::File& f) const {
                return InputStream {
                    InputStream::File {
                        std::string(f.path),
                        &f,
                        f.offset,
                    }
                };
            }
        };
        return boost::apply_visitor(visitor(), *m_data);
    };

    inline size_t Input::size() {
        struct visitor: public boost::static_visitor<size_t> {
            size_t operator()(Input::Memory& mem) const {
                return mem.size;
            }
            size_t operator()(Input::File& f) const {
                return read_file_size(f.path) - f.offset;
            }
        };
        return boost::apply_visitor(visitor(), *m_data);
    };

}}

#endif

<commit_msg>Try to fix possible error of move constructor not being picked<commit_after>#ifndef _INCLUDED_INPUT_HPP
#define _INCLUDED_INPUT_HPP

#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

#include <boost/utility/string_ref.hpp>
#include <boost/variant.hpp>

#include <tudocomp/util.h>

#include <tudocomp/io/IOUtil.hpp>
#include <tudocomp/io/ViewStream.hpp>

namespace tudocomp {
namespace io {

    struct InputView;
    struct InputStream;

    /// Represents the input of an algorithm.
    ///
    /// Can be used as either a istream or a memory buffer
    /// with the as_stream or as_view methods.
    class Input {
        struct Memory {
            const uint8_t* ptr;
            size_t size;
        };
        struct File {
            std::string path;
            size_t offset;
        };

        friend class InputStream;
        friend class InputView;

        using Variant = boost::variant<Memory, File>;
        std::unique_ptr<Variant> m_data;

    public:
        struct Path { std::string path; };

        /// An empty Input
        inline Input():
            m_data(std::make_unique<Variant>(Memory { nullptr, 0 })) {}

        /// Create an copy of the Input, with internal cursors
        /// set to the current position
        inline Input(const Input& other):
            m_data(std::make_unique<Variant>(*other.m_data)) {}

        /// Move constructor
        inline Input(Input&& other):
            m_data(std::move(other.m_data)) {}

        /// An Input referring to the contents of a file
        Input(Input::Path&& path):
            m_data(std::make_unique<Variant>(File { std::move(path.path), 0 })) {}

        /// An Input referring to the contents of an vector
        Input(const std::vector<uint8_t>& buf):
            m_data(std::make_unique<Variant>(Memory { &buf[0], buf.size() })) {}

        /// An Input referring to the contents of an string
        Input(const boost::string_ref buf):
            m_data(std::make_unique<Variant>(
                    Memory { (const uint8_t*) &buf[0], buf.size() })) {}

        Input& operator=(Input&& other) {
            m_data = std::move(other.m_data);
            return *this;
        }

        /// DEPRECATED
        static Input from_path(std::string path) {
            return Input(Path { path });
        }

        /// DEPRECATED
        static Input from_memory(const std::vector<uint8_t>& buf) {
            return Input(buf);
        }

        /// DEPRECATED
        static Input from_memory(const boost::string_ref buf) {
            return Input(buf);
        }

        inline InputView as_view();
        inline InputStream as_stream();

        inline size_t size();
    };

    struct InputView {
        struct Memory {
            const uint8_t* ptr;
            const size_t size;
        };
        struct File {
            std::vector<uint8_t> buffer;
        };

        boost::variant<Memory, File> data;

        boost::string_ref operator* () {
            struct visitor: public boost::static_visitor<boost::string_ref> {
                boost::string_ref operator()(InputView::Memory& mem) const {
                    return boost::string_ref {
                        (char*) mem.ptr, mem.size
                    };
                }
                boost::string_ref operator()(InputView::File& mem) const {
                    return boost::string_ref {
                        (char*) mem.buffer.data(), mem.buffer.size()
                    };
                }
            };
            return boost::apply_visitor(visitor(), data);
        }

        const uint8_t* mem_ptr() {
            struct visitor: public boost::static_visitor<const uint8_t*> {
                const uint8_t* operator()(InputView::Memory& mem) const {
                    return mem.ptr;
                }
                const uint8_t* operator()(InputView::File& mem) const {
                    return mem.buffer.data();
                }
            };
            return boost::apply_visitor(visitor(), data);
        }

        size_t size() {
            struct visitor: public boost::static_visitor<size_t> {
                size_t operator()(InputView::Memory& mem) const {
                    return mem.size;
                }
                size_t operator()(InputView::File& mem) const {
                    return mem.buffer.size();
                }
            };
            return boost::apply_visitor(visitor(), data);
        }

        InputView(const InputView* other) = delete;
        InputView() = delete;

        InputView(InputView::Memory&& mem): data(std::move(mem)) {}
        InputView(InputView::File&& s): data(std::move(s)) {}

    };

    inline InputView Input::as_view() {
        struct visitor: public boost::static_visitor<InputView> {
            InputView operator()(Input::Memory& mem) const {
                Input::Memory mem2 = mem;

                // advance view into memory by its whole length
                mem.ptr += mem.size;
                mem.size = 0;

                return InputView {
                    InputView::Memory { mem2.ptr, mem2.size }
                };
            }
            InputView operator()(Input::File& mem) const {
                // read file into buffer starting at current offset
                auto buf = read_file_to_stl_byte_container<
                    std::vector<uint8_t>>(mem.path, mem.offset);

                // We read the whole file, so skip it on next read.
                mem.offset += buf.size();

                return InputView {
                    InputView::File {
                        std::move(buf)
                    }
                };
            }
        };

        return boost::apply_visitor(visitor(), *m_data);
    };

    struct InputStream {
        class Memory {
            ViewStream m_stream;

            Input::Memory* m_offset_back_ref;
            size_t m_start_pos;

            friend class InputStream;
        public:
            Memory(ViewStream&& stream, Input::Memory* offset_back_ref):
                m_stream(std::move(stream))
            {
                m_offset_back_ref = offset_back_ref;
                m_start_pos = m_stream.stream().tellg();
            }
            ~Memory() {
                size_t len = size_t(m_stream.stream().tellg()) - m_start_pos;
                m_offset_back_ref->ptr += len;
                m_offset_back_ref->size -= len;
            }
        };
        class File {
            std::string m_path;
            std::unique_ptr<std::ifstream> stream;

            Input::File* m_offset_back_ref;
            size_t m_start_pos;

            File(const File& other) = delete;
            File() = delete;

            friend class InputStream;
        public:
            File(std::string&& path,
                 Input::File* offset_back_ref,
                 size_t offset)
            {
                m_path = path;
                stream = std::make_unique<std::ifstream>(
                    m_path, std::ios::in | std::ios::binary);
                stream->seekg(offset, std::ios::beg);
                m_start_pos = stream->tellg();
                m_offset_back_ref = offset_back_ref;
            }

            File(File&& other) {
                stream = std::move(other.stream);
                m_offset_back_ref = other.m_offset_back_ref;
                m_path = other.m_path;
                m_start_pos = other.m_start_pos;
            }

            ~File() {
                if (stream != nullptr) {
                    auto len = size_t(stream->tellg()) - m_start_pos;
                    m_offset_back_ref->offset += len;
                }
            }
        };

        boost::variant<Memory, File> data;

        std::istream& operator* () {
            struct visitor: public boost::static_visitor<std::istream&> {
                std::istream& operator()(InputStream::Memory& m) const {
                    return m.m_stream.stream();
                }
                std::istream& operator()(InputStream::File& m) const {
                    return *m.stream;
                }
            };
            return boost::apply_visitor(visitor(), data);
        }

        InputStream(const InputStream* other) = delete;
        InputStream() = delete;

        InputStream(InputStream::Memory&& mem): data(std::move(mem)) {}
        InputStream(InputStream::File&& f): data(std::move(f)) {}
    };

    inline InputStream Input::as_stream() {
        struct visitor: public boost::static_visitor<InputStream> {
            InputStream operator()(Input::Memory& mem) const {
                return InputStream {
                    InputStream::Memory {
                        ViewStream {
                            (char*)mem.ptr,
                            mem.size
                        },
                        &mem
                    }
                };
            }
            InputStream operator()(Input::File& f) const {
                return InputStream {
                    std::move(InputStream::File {
                        std::string(f.path),
                        &f,
                        f.offset,
                    })
                };
            }
        };
        return boost::apply_visitor(visitor(), *m_data);
    };

    inline size_t Input::size() {
        struct visitor: public boost::static_visitor<size_t> {
            size_t operator()(Input::Memory& mem) const {
                return mem.size;
            }
            size_t operator()(Input::File& f) const {
                return read_file_size(f.path) - f.offset;
            }
        };
        return boost::apply_visitor(visitor(), *m_data);
    };

}}

#endif

<|endoftext|>


<commit_before><commit_msg>Work around missing std::underlying_type in GCC 4.6<commit_after><|endoftext|>


<commit_before>#ifndef _INCLUDED_DS_LCP_ARRAY_HPP
#define _INCLUDED_DS_LCP_ARRAY_HPP

#include <tudocomp/util.h>
#include <sdsl/rank_support.hpp> // for the rank data structure
#include "forward.hh"

namespace tudocomp {

constexpr int bits = 0;
typedef size_t len_t;

template<class T>
class LCPArray {
    typedef sdsl::int_vector<bits> iv_t;

public:

private:
    iv_t m_lcp;
	len_t m_max;

    template <typename sa_t, int U = bits, typename std::enable_if<U == 0,int>::type = 0>
	inline void construct_lcp_array(const iv_t& plcp, const sa_t& sa) {
        const auto& n = sa.size();
		m_max = *std::max_element(plcp.begin(),plcp.end());
		m_lcp = iv_t(n, 0, bits_for(m_max));
		for(len_t i = 0; i < n; i++) {
			DCHECK_LT(sa[i], n);
			m_lcp[i] = plcp[sa[i]];
		}
		for(size_t i = 0; i < m_lcp.size(); ++i) {
			DCHECK_EQ(m_lcp[i], plcp[sa[i]]);
		}
	}

    template <typename sa_t, int U = bits, typename std::enable_if<U != 0,int>::type = 0>
	inline void construct_lcp_array(const iv_t& plcp, const sa_t& sa) {
        const auto& n = sa.size();
		m_max = bits_for(*std::max_element(plcp.begin(),plcp.end()));
        m_lcp = iv_t(n);
		for(len_t i = 0; i < n; i++) {
			m_lcp[i] = plcp[sa[i]];
		}
	}

public:
	/**
	 * Returns the maximum value of the LCP array
	 */
	inline len_t max_lcp() const {
		return m_max;
	}

    inline iv_t& data() {
        return m_lcp;
    }

    inline const iv_t& data() const {
        return m_lcp;
    }

    inline iv_t::value_type operator[](iv_t::size_type i) const {
        return m_lcp[i];
    }

    inline iv_t::size_type size() const {
        return m_lcp.size();
    }

    inline void construct(T& t);
};

template<
typename T,
typename sa_t,
typename select_t = sdsl::select_support_mcl<1,1>>
class lcp_sada {
    typedef sdsl::int_vector<bits> iv_t;
	sa_t* sa;
	sdsl::bit_vector bv;
	select_t s;
	public:
	inline len_t operator[](len_t i) const;
    inline void construct(T& t);

    inline len_t size() const;
	/**
	 * Returns the maximum value of the LCP array
	 */
	inline len_t max_lcp() const {
		len_t max = (*this)[0];
		for(len_t i = 1; i < sa->size(); ++i) {
			max = std::max(max, (*this)[i]);
		}
		return max;
	}

};

}//ns
#include <tudocomp/ds/SuffixArray.hpp>
#include <tudocomp/ds/PhiArray.hpp>
namespace tudocomp {

namespace LCP {
    typedef sdsl::int_vector<bits> iv_t;
	inline static sdsl::bit_vector construct_lcp_sada(const iv_t& plcp) {
		const len_t n = plcp.size();
		len_t len = 0;
		for(len_t i = 0; i+1 < n; i++) {
			DCHECK_GE(plcp[i+1]+1, plcp[i]);
			len += plcp[i+1]-plcp[i]+1;
		}
		sdsl::bit_vector bv(len+2*n,0);
		bv[0]=1;
		len=0;
		for(len_t i = 0; i+1 < n; i++) {
			len += plcp[i+1]-plcp[i]+2;
			DCHECK_LT(len, bv.size());
			bv[len] = 1;
		}
		return bv;
	}
	template<typename T>
	inline static iv_t phi_algorithm(T& t) {
		auto& sa = t.require_sa();
		const auto n = sa.size();
        t.require_phi();
		std::unique_ptr<PhiArray<T>> phi(std::move(t.release_phi()));
		iv_t plcp(std::move(phi->data()));
		for(len_t i = 0, l = 0; i < n - 1; ++i) {
			const len_t phii = plcp[i];
            DCHECK_LT(i+l, n);
            DCHECK_LT(phii+l, n);
            DCHECK_NE(i, phii);
			while(t[i+l] == t[phii+l]) {
				l++;
                DCHECK_LT(i+l, n);
                DCHECK_LT(phii+l, n);
			}
			plcp[i] = l;
			if(l) {
				--l;
			}
		}
		return plcp;
	}
}

template<typename T, typename sa_t, typename select_t>
inline len_t lcp_sada<T,sa_t,select_t>::operator[](len_t i) const {
	const len_t idx = (*sa)[i];
	return s.select(idx+1) - 2*idx;
}

template<typename T, typename sa_t, typename select_t>
inline void lcp_sada<T,sa_t,select_t>::construct(T& t) {
	iv_t plcp(LCP::phi_algorithm(t));
	bv(LCP::construct_lcp_sada(plcp));
	s.set_vector(&bv);
}

template<typename T, typename sa_t, typename select_t>
inline len_t lcp_sada<T,sa_t,select_t>::size() const {
	return sa->size();
}

template<class T>
inline void LCPArray<T>::construct(T& t) {
	iv_t plcp(LCP::phi_algorithm(t));
	construct_lcp_array(plcp, t.require_sa());
}

}

#endif

<commit_msg>Hotfix for undefined behaviour - Input needs to be *actually* extended by a \0 character, not only for SA generation<commit_after>#ifndef _INCLUDED_DS_LCP_ARRAY_HPP
#define _INCLUDED_DS_LCP_ARRAY_HPP

#include <tudocomp/util.h>
#include <sdsl/rank_support.hpp> // for the rank data structure
#include "forward.hh"

namespace tudocomp {

constexpr int bits = 0;
typedef size_t len_t;

template<class T>
class LCPArray {
    typedef sdsl::int_vector<bits> iv_t;

public:

private:
    iv_t m_lcp;
	len_t m_max;

    template <typename sa_t, int U = bits, typename std::enable_if<U == 0,int>::type = 0>
	inline void construct_lcp_array(const iv_t& plcp, const sa_t& sa) {
        const auto& n = sa.size();
		m_max = *std::max_element(plcp.begin(),plcp.end());
		m_lcp = iv_t(n, 0, bits_for(m_max));
		for(len_t i = 1; i < n; i++) { //TODO: start at 0, see line 149
			DCHECK_LT(sa[i], n);
			m_lcp[i] = plcp[sa[i]];
		}
		for(size_t i = 1; i < m_lcp.size(); ++i) { //TODO: start at 0, see line 149
			DCHECK_EQ(m_lcp[i], plcp[sa[i]]);
		}
	}

    template <typename sa_t, int U = bits, typename std::enable_if<U != 0,int>::type = 0>
	inline void construct_lcp_array(const iv_t& plcp, const sa_t& sa) {
        const auto& n = sa.size();
		m_max = bits_for(*std::max_element(plcp.begin(),plcp.end()));
        m_lcp = iv_t(n);
		for(len_t i = 1; i < n; i++) { //TODO: start at 0, see line 149
			m_lcp[i] = plcp[sa[i]];
		}
	}

public:
	/**
	 * Returns the maximum value of the LCP array
	 */
	inline len_t max_lcp() const {
		return m_max;
	}

    inline iv_t& data() {
        return m_lcp;
    }

    inline const iv_t& data() const {
        return m_lcp;
    }

    inline iv_t::value_type operator[](iv_t::size_type i) const {
        return m_lcp[i];
    }

    inline iv_t::size_type size() const {
        return m_lcp.size();
    }

    inline void construct(T& t);
};

template<
typename T,
typename sa_t,
typename select_t = sdsl::select_support_mcl<1,1>>
class lcp_sada {
    typedef sdsl::int_vector<bits> iv_t;
	sa_t* sa;
	sdsl::bit_vector bv;
	select_t s;
	public:
	inline len_t operator[](len_t i) const;
    inline void construct(T& t);

    inline len_t size() const;
	/**
	 * Returns the maximum value of the LCP array
	 */
	inline len_t max_lcp() const {
		len_t max = (*this)[0];
		for(len_t i = 1; i < sa->size(); ++i) {
			max = std::max(max, (*this)[i]);
		}
		return max;
	}

};

}//ns
#include <tudocomp/ds/SuffixArray.hpp>
#include <tudocomp/ds/PhiArray.hpp>
namespace tudocomp {

namespace LCP {
    typedef sdsl::int_vector<bits> iv_t;
	inline static sdsl::bit_vector construct_lcp_sada(const iv_t& plcp) {
		const len_t n = plcp.size();
		len_t len = 0;
		for(len_t i = 0; i+1 < n; i++) {
			DCHECK_GE(plcp[i+1]+1, plcp[i]);
			len += plcp[i+1]-plcp[i]+1;
		}
		sdsl::bit_vector bv(len+2*n,0);
		bv[0]=1;
		len=0;
		for(len_t i = 0; i+1 < n; i++) {
			len += plcp[i+1]-plcp[i]+2;
			DCHECK_LT(len, bv.size());
			bv[len] = 1;
		}
		return bv;
	}
	template<typename T>
	inline static iv_t phi_algorithm(T& t) {
        t.require_phi();
		std::unique_ptr<PhiArray<T>> phi(std::move(t.release_phi()));
        size_t n = phi->size();

		iv_t plcp(std::move(phi->data()));
		for(len_t i = 0, l = 0; i < n - 1; ++i) {
			const len_t phii = plcp[i];
            DCHECK_LT(i+l, n);
            DCHECK_LT(phii+l, n);
            DCHECK_NE(i, phii);
			while(t[i+l] == t[phii+l]) { // !!! UNDEFINED BEHAVIOUR, t[phi.size()-1] is not defined -> InputView needs to be checked
				l++;
                DCHECK_LT(i+l, n);
                DCHECK_LT(phii+l, n);
			}
			plcp[i] = l;
			if(l) {
				--l;
			}
		}
		return plcp;
	}
}

template<typename T, typename sa_t, typename select_t>
inline len_t lcp_sada<T,sa_t,select_t>::operator[](len_t i) const {
	const len_t idx = (*sa)[i];
	return s.select(idx+1) - 2*idx;
}

template<typename T, typename sa_t, typename select_t>
inline void lcp_sada<T,sa_t,select_t>::construct(T& t) {
	iv_t plcp(LCP::phi_algorithm(t));
	bv(LCP::construct_lcp_sada(plcp));
	s.set_vector(&bv);
}

template<typename T, typename sa_t, typename select_t>
inline len_t lcp_sada<T,sa_t,select_t>::size() const {
	return sa->size();
}

template<class T>
inline void LCPArray<T>::construct(T& t) {
	iv_t plcp(LCP::phi_algorithm(t));
	construct_lcp_array(plcp, t.require_sa());
}

}

#endif

<|endoftext|>


<commit_before>/************************************************************************/
/*                                                                      */
/*               Copyright 1998-2002 by Ullrich Koethe                  */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/
#ifndef VIGRA_ITERATORFACADE_HXX
#define VIGRA_ITERATORFACADE_HXX

/*std*/
#include <iterator>

/*vigra*/
#include "metaprogramming.hxx"

namespace vigra {

// facade needs to make this class
// a friend class
class IteratorFacadeCoreAccess{
public:
    template<class F>
    static bool equal(const F & fa,const F & fb){
        return fa.equal(fb);
    }

    template<class F,class REFERENCE>
    static REFERENCE dereference(const F & f){
        return f.dereference();
    }

    template<class F>
    static void increment(F & f){
        f.increment();
    }
};

// see boost iterator facade
template<class FACADE,class VALUE_TYPE,bool IS_CONST = true>
class ForwardIteratorFacade{
private:

public:

    typedef std::forward_iterator_tag iterator_category;
    typedef typename UnqualifiedType<VALUE_TYPE>::type value_type;
    typedef typename IfBool<IS_CONST, value_type const * , value_type *>::type  pointer;
    typedef typename IfBool<IS_CONST, const value_type  & , value_type &>::type  reference;
    typedef std::ptrdiff_t difference_type;

    FACADE & operator++()
    {
        IteratorFacadeCoreAccess::increment(getF());
        return getF();
    }

    FACADE operator++(int)
    {
        FACADE res(getF());
        IteratorFacadeCoreAccess::increment(getF());
        return res;
    }

    bool operator ==(const FACADE & f)const{
        return IteratorFacadeCoreAccess::equal(getF(),f);
    }
    bool operator !=(const FACADE & f)const{
        return !IteratorFacadeCoreAccess::equal(getF(),f);
    }

    reference operator*()const{
        return IteratorFacadeCoreAccess:: template dereference<FACADE,reference>(getF());
    }

    pointer operator->()const{
        return &IteratorFacadeCoreAccess:: template dereference<FACADE,reference>(getF());
    }

private:

    const FACADE & getF()const{
        return *static_cast<FACADE const *>(this);
    }
    FACADE & getF(){
        return *static_cast<FACADE *>(this);
    }
};

} // namespace vigra

#endif /* VIGRA_ITERATORFACADE_HXX */
<commit_msg>added key_begin() and key_end() to iterate over the keys of a std::map (similar to Python's iterkeys)<commit_after>/************************************************************************/
/*                                                                      */
/*               Copyright 1998-2002 by Ullrich Koethe                  */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/
#ifndef VIGRA_ITERATORFACADE_HXX
#define VIGRA_ITERATORFACADE_HXX

/*std*/
#include <iterator>

/*vigra*/
#include "metaprogramming.hxx"

namespace vigra {

// facade needs to make this class
// a friend class
class IteratorFacadeCoreAccess{
public:
    template<class F>
    static bool equal(const F & fa,const F & fb){
        return fa.equal(fb);
    }

    template<class F,class REFERENCE>
    static REFERENCE dereference(const F & f){
        return f.dereference();
    }

    template<class F>
    static void increment(F & f){
        f.increment();
    }
};

// see boost iterator facade
template<class FACADE,class VALUE_TYPE,bool IS_CONST = true>
class ForwardIteratorFacade{
private:

public:

    typedef std::forward_iterator_tag iterator_category;
    typedef typename UnqualifiedType<VALUE_TYPE>::type value_type;
    typedef typename IfBool<IS_CONST, value_type const * , value_type *>::type  pointer;
    typedef typename IfBool<IS_CONST, const value_type  & , value_type &>::type  reference;
    typedef std::ptrdiff_t difference_type;

    FACADE & operator++()
    {
        IteratorFacadeCoreAccess::increment(getF());
        return getF();
    }

    FACADE operator++(int)
    {
        FACADE res(getF());
        IteratorFacadeCoreAccess::increment(getF());
        return res;
    }

    bool operator ==(const FACADE & f)const{
        return IteratorFacadeCoreAccess::equal(getF(),f);
    }
    bool operator !=(const FACADE & f)const{
        return !IteratorFacadeCoreAccess::equal(getF(),f);
    }

    reference operator*()const{
        return IteratorFacadeCoreAccess:: template dereference<FACADE,reference>(getF());
    }

    pointer operator->()const{
        return &IteratorFacadeCoreAccess:: template dereference<FACADE,reference>(getF());
    }

private:

    const FACADE & getF()const{
        return *static_cast<FACADE const *>(this);
    }
    FACADE & getF(){
        return *static_cast<FACADE *>(this);
    }
};

template<class MAP>
class MapKeyIterator
 : public ForwardIteratorFacade<MapKeyIterator<MAP>,typename MAP::key_type,true>
{

public:
    typedef ForwardIteratorFacade<MapKeyIterator<MAP>,typename MAP::key_type,true> BaseType;
    typedef typename MAP::const_iterator InternalIterator;
    typedef typename BaseType::value_type value_type;
    typedef typename BaseType::reference reference;
    typedef typename BaseType::pointer pointer;

    MapKeyIterator(InternalIterator i)
    : iter_(i)
    {}

  private:

    friend class IteratorFacadeCoreAccess;

    bool equal(const MapKeyIterator & other) const{
        return iter_ == other.iter_;
    }

    void increment(){
        ++iter_;
    }

    reference dereference()const{
        return iter_->first;
    }

    InternalIterator iter_;
};

template <class MAP>
inline MapKeyIterator<MAP>
key_begin(MAP const & m)
{
    return MapKeyIterator<MAP>(m.begin());

}

template <class MAP>
inline MapKeyIterator<MAP>
key_end(MAP const & m)
{
    return MapKeyIterator<MAP>(m.end());

}

} // namespace vigra

#endif /* VIGRA_ITERATORFACADE_HXX */
<|endoftext|>


<commit_before>#include "Python.h"

#include "DippyDecompAlgo.h"
#include "DippyDecompApp.h"
#include "DippyPythonUtils.h"

/**
 * Perform branching
 *
 * This function should populate the (down|up)Branch(LB|UB) vectors with (indices, bound-value) pairs
 * which define the branch.
 */
bool DippyAlgoMixin::chooseBranchSet(DecompAlgo *algo, std::vector< std::pair<int, double> > &downBranchLB,
        std::vector< std::pair<int, double> > &downBranchUB,
        std::vector< std::pair<int, double> > &upBranchLB,
        std::vector< std::pair<int, double> > &upBranchUB){

	bool ret_val;

	if (!m_utilParam->GetSetting("pyBranchMethod", true))
        return algo->DecompAlgo::chooseBranchSet(downBranchLB, downBranchUB, upBranchLB, upBranchUB);

	DippyDecompApp * app = (DippyDecompApp *)algo->getDecompApp();

    // copy the current solution into a Python list
    const double *xhat = algo->getXhat();
    PyObject *pSolutionList = pyTupleList_FromDoubleArray(xhat, app->m_colList);

    // try to call chooseBranchSet on the DipProblem python object
    PyObject* pResult = PyObject_CallMethod(m_pProb, "chooseBranchSet", "O", pSolutionList);

    if (pResult == NULL) {
        //something's gone wrong with the function call, a Python exception has been set
        throw UtilException("Error calling method prob.chooseBranchSet()", "chooseBranchSet", "DippyDecompAlgo");
    }

    // need more error checking/assertion setting here
    if (pResult == Py_None) {
        // if chooseBranchSet returns None, do default branching for this algo
        ret_val = algo->DecompAlgo::chooseBranchSet(downBranchLB, downBranchUB, upBranchLB, upBranchUB);
		if (downBranchUB.size() > 0){
			PyObject * downBranchVar, * upBranchVar;
			pDownUB = PyDict_New();
			downBranchVar = PyList_GetItem(app->m_colList, downBranchUB[0].first);
			PyDict_SetItem(pDownUB, downBranchVar, PyInt_FromLong(static_cast<int>(round(downBranchUB[0].second))));
			pUpLB = PyDict_New();
			upBranchVar = PyList_GetItem(app->m_colList, upBranchLB[0].first);
			PyDict_SetItem(pUpLB, upBranchVar, PyInt_FromLong(static_cast<int>(round(upBranchLB[0].second))));
			assert(downBranchVar == upBranchVar);
		}
		return ret_val;
    }else{
        // or else, the function should have returned 4 lists of (name, value) tuples
        pDownLB = PyTuple_GetItem(pResult, 0);
        pDownUB = PyTuple_GetItem(pResult, 1);
        pUpLB = PyTuple_GetItem(pResult, 2);
        pUpUB = PyTuple_GetItem(pResult, 3);

	    // copy the python dictionaries into the result vectors
		pyColDict_AsPairedVector(pDownLB, downBranchLB, app->m_colIndices);
		pyColDict_AsPairedVector(pDownUB, downBranchUB, app->m_colIndices);
		pyColDict_AsPairedVector(pUpLB, upBranchLB, app->m_colIndices);
		pyColDict_AsPairedVector(pUpUB, upBranchUB, app->m_colIndices);

		return true;
	}
}

void DippyAlgoMixin::postProcessBranch(DecompAlgo *algo, DecompStatus decompStatus){

	PyObject * pOutput = PyList_New(0);

	if (!m_utilParam->GetSetting("pyPostProcessBranch", true))
		return;

	AlpsDecompTreeNode * node = (AlpsDecompTreeNode *)algo->getCurrentNode();
	double quality = node->getQuality();
	if (pDownLB != NULL)
		addTupleToPyList(pOutput, PyString_FromString("pDownLB"), pDownLB);
	if (pDownUB != NULL)
		addTupleToPyList(pOutput, PyString_FromString("pDownUB"), pDownUB);
	if (pUpLB != NULL)
		addTupleToPyList(pOutput, PyString_FromString("pUpLB"), pUpLB);
	if (pUpUB != NULL)
		addTupleToPyList(pOutput, PyString_FromString("pUpUB"), pUpUB);
	addTupleToPyList(pOutput, PyString_FromString("nodeIndex"), PyInt_FromLong(algo->getNodeIndex()));
	addTupleToPyList(pOutput, PyString_FromString("nodeQuality"), PyFloat_FromDouble(quality));

	PyObject* pResult = PyObject_CallMethod(m_pProb, "postProcessBranch", "O", pOutput);
}

void DippyAlgoMixin::postProcessNode(DecompAlgo * algo, DecompStatus decompStatus) {

	if (!m_utilParam->GetSetting("pyPostProcessNode", true))
		return;

	PyObject * pOutput = pyTupleList_FromNode(algo, decompStatus);

	PyObject* pResult = PyObject_CallMethod(m_pProb, "postProcessNode", "O", pOutput);
}

<commit_msg>Fixed bug that left old node bounds "hanging around" when default branch used in Dippy.<commit_after>#include "Python.h"

#include "DippyDecompAlgo.h"
#include "DippyDecompApp.h"
#include "DippyPythonUtils.h"

/**
 * Perform branching
 *
 * This function should populate the (down|up)Branch(LB|UB) vectors with (indices, bound-value) pairs
 * which define the branch.
 */
bool DippyAlgoMixin::chooseBranchSet(DecompAlgo *algo, std::vector< std::pair<int, double> > &downBranchLB,
        std::vector< std::pair<int, double> > &downBranchUB,
        std::vector< std::pair<int, double> > &upBranchLB,
        std::vector< std::pair<int, double> > &upBranchUB){

	bool ret_val;

	if (!m_utilParam->GetSetting("pyBranchMethod", true))
        return algo->DecompAlgo::chooseBranchSet(downBranchLB, downBranchUB, upBranchLB, upBranchUB);

	DippyDecompApp * app = (DippyDecompApp *)algo->getDecompApp();

    // copy the current solution into a Python list
    const double *xhat = algo->getXhat();
    PyObject *pSolutionList = pyTupleList_FromDoubleArray(xhat, app->m_colList);

    // try to call chooseBranchSet on the DipProblem python object
    PyObject* pResult = PyObject_CallMethod(m_pProb, "chooseBranchSet", "O", pSolutionList);

    if (pResult == NULL) {
        //something's gone wrong with the function call, a Python exception has been set
        throw UtilException("Error calling method prob.chooseBranchSet()", "chooseBranchSet", "DippyDecompAlgo");
    }

    // need more error checking/assertion setting here
    if (pResult == Py_None) {
        // if chooseBranchSet returns None, do default branching for this algo
        ret_val = algo->DecompAlgo::chooseBranchSet(downBranchLB, downBranchUB, upBranchLB, upBranchUB);
		if (downBranchUB.size() > 0){
			PyObject * downBranchVar, * upBranchVar;
			pDownLB = PyDict_New(); // Down branch LBs is an empty dictionary
			pDownUB = PyDict_New();
			downBranchVar = PyList_GetItem(app->m_colList, downBranchUB[0].first);
			PyDict_SetItem(pDownUB, downBranchVar, PyInt_FromLong(static_cast<int>(round(downBranchUB[0].second))));
			pUpLB = PyDict_New();
			upBranchVar = PyList_GetItem(app->m_colList, upBranchLB[0].first);
			PyDict_SetItem(pUpLB, upBranchVar, PyInt_FromLong(static_cast<int>(round(upBranchLB[0].second))));
			pUpUB = PyDict_New(); // Up branch UBs is an empty dictionary
			assert(downBranchVar == upBranchVar);
		}
		return ret_val;
    }else{
        // or else, the function should have returned 4 lists of (name, value) tuples
        pDownLB = PyTuple_GetItem(pResult, 0);
        pDownUB = PyTuple_GetItem(pResult, 1);
        pUpLB = PyTuple_GetItem(pResult, 2);
        pUpUB = PyTuple_GetItem(pResult, 3);

	    // copy the python dictionaries into the result vectors
		pyColDict_AsPairedVector(pDownLB, downBranchLB, app->m_colIndices);
		pyColDict_AsPairedVector(pDownUB, downBranchUB, app->m_colIndices);
		pyColDict_AsPairedVector(pUpLB, upBranchLB, app->m_colIndices);
		pyColDict_AsPairedVector(pUpUB, upBranchUB, app->m_colIndices);

		return true;
	}
}

void DippyAlgoMixin::postProcessBranch(DecompAlgo *algo, DecompStatus decompStatus){

	PyObject * pOutput = PyList_New(0);

	if (!m_utilParam->GetSetting("pyPostProcessBranch", true))
		return;

	AlpsDecompTreeNode * node = (AlpsDecompTreeNode *)algo->getCurrentNode();
	double quality = node->getQuality();
	if (pDownLB != NULL)
		addTupleToPyList(pOutput, PyString_FromString("pDownLB"), pDownLB);
	if (pDownUB != NULL)
		addTupleToPyList(pOutput, PyString_FromString("pDownUB"), pDownUB);
	if (pUpLB != NULL)
		addTupleToPyList(pOutput, PyString_FromString("pUpLB"), pUpLB);
	if (pUpUB != NULL)
		addTupleToPyList(pOutput, PyString_FromString("pUpUB"), pUpUB);
	addTupleToPyList(pOutput, PyString_FromString("nodeIndex"), PyInt_FromLong(algo->getNodeIndex()));
	addTupleToPyList(pOutput, PyString_FromString("nodeQuality"), PyFloat_FromDouble(quality));

	PyObject* pResult = PyObject_CallMethod(m_pProb, "postProcessBranch", "O", pOutput);
}

void DippyAlgoMixin::postProcessNode(DecompAlgo * algo, DecompStatus decompStatus) {

	if (!m_utilParam->GetSetting("pyPostProcessNode", true))
		return;

	PyObject * pOutput = pyTupleList_FromNode(algo, decompStatus);

	PyObject* pResult = PyObject_CallMethod(m_pProb, "postProcessNode", "O", pOutput);
}

<|endoftext|>