text:
#ifndef __penglei_bitmanip_h__
#define __penglei_bitmanip_h__

#include <assert.h>
#include <limits.h>
//#include <boost/static_assert.hpp>
#include "config.hpp"

#if defined(__GNUC__) && __GNUC__ * 1000 + __GNUC_MINOR__ >= 4005
	#include <immintrin.h>
#endif

#if defined(_MSC_VER) && _MSC_VER >= 1500 || defined(__CYGWIN__)
	#include <intrin.h>
#endif

namespace nark {

// select best popcount implementations
//
#if defined(_MSC_VER) && _MSC_VER >= 1500 // VC 2008
//  different popcount instructions in different headers

	#define fast_popcount64 __popcnt64
	#define fast_clz32  __lzcnt
	#define fast_clz16  __lzcnt16

    #pragma intrinsic(_BitScanForward)
    #define fast_popcount32 __popcnt
    #if defined(_WIN64) || defined(_M_X64) || defined(_M_IA64)
        #pragma intrinsic(_BitScanForward64)
		#define fast_clz64  __lzcnt64
    #else
        inline int fast_clz64(unsigned __int64 x) {
			unsigned long lo32 = (unsigned long)(x & 0xFFFFFFFF);
            unsigned long hi32 = (unsigned long)(x >> 32);
            if (hi32)
				return __lzcnt(hi32);
            else
				return __lzcnt(lo32) + 32;
        }
        inline int fast_popcount64(unsigned __int64 x)
        {
            return
                __popcnt((unsigned)(x      )) +
                __popcnt((unsigned)(x >> 32));
        }
    #endif
        inline int fast_ctz32(unsigned int x) {
            assert(0 != x);
            unsigned long c;
            _BitScanForward(&c, x);
            return c;
        }
        inline int fast_ctz64(unsigned __int64 x) {
            assert(0 != x);
            unsigned long c = 0;
        #if defined(_WIN64) || defined(_M_X64) || defined(_M_IA64)
            _BitScanForward64(&c, x);
        #else
            unsigned long x1 = (unsigned long)(x & 0xFFFFFFFF);
            unsigned long x2 = (unsigned long)(x >> 32);
            if (x1) {
                _BitScanForward(&c, x1);
            } else {
                if (_BitScanForward(&c, x2))
	                c += 32;
				else
					c = 64; // all bits are zero
            }
        #endif
            return c;
        }
#elif defined(__GNUC__) && __GNUC__ >= 4 || \
      defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 900 || \
      defined(__clang__)
    #define fast_popcount32 __builtin_popcount
	#define fast_clz32      __builtin_clz
	#define fast_ctz32      __builtin_ctz

    #ifdef ULONG_MAX
        #if ULONG_MAX == 0xFFFFFFFF
            inline int fast_popcount64(unsigned long long x) {
                return __builtin_popcount((unsigned)(x      )) +
                       __builtin_popcount((unsigned)(x >> 32));
            }
			#define fast_clz64      __builtin_clzll
            #define fast_ctz64      __builtin_ctzll
        #else
            #define fast_popcount64 __builtin_popcountl
			#define fast_clz64      __builtin_clzl
			#define fast_ctz64      __builtin_ctzl
        #endif
    #else
        #error "ULONG_MAX must be defined, use #include <limits.h>"
    #endif
#else // unknow or does not support popcount
  inline int fast_popcount32(unsigned int v) {
    v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
    v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
    return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
  }
  #if NARK_WORD_BITS == 64
    inline long long fast_popcount64(unsigned long long v) {
      v = v - ((v >> 1) & 0x5555555555555555ull);
      v = (v & 0x3333333333333333ull) + ((v >> 2) & 0x3333333333333333ull);
      v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0Full;
      return (v * 0x0101010101010101ull) >> 56;
    }
  #else
    inline int fast_popcount64(unsigned long long v) {
		return fast_popcount32((unsigned)(v))
			 + fast_popcount32((unsigned)(v >> 32));
    }
  #endif
#endif // select best popcount implementations

#if NARK_WORD_BITS >= 64
  #if defined(__INTEL_COMPILER) && !defined(_MSC_VER)
	inline unsigned nark_bsr_u64(unsigned __int64 i) {
		unsigned j;
		__asm
		{
			bsr rax, i
			mov j, rax
		}
		return j;
	}
  #elif defined(_MSC_VER)
	inline int nark_bsr_u64(unsigned __int64 x) {
		unsigned long Index = 0;
		_BitScanReverse64(&Index, x);
		return Index;
	}
  #elif defined(__GNUC__) && __GNUC__ * 1000 + __GNUC_MINOR__ >= 4005
	#define nark_bsr_u64 __bsrq
  #endif
#endif

#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
	inline int nark_bsr_u32(unsigned long x) {
		unsigned long Index = 0;
		_BitScanReverse(&Index, x);
		return Index;
	}
#elif defined(__clang__)
	inline int nark_bsr_u32(unsigned x) { return 31 - __builtin_clz(x); }
#else
    // for gcc/clang/icc
	#define nark_bsr_u32 _bit_scan_reverse
#endif

#if defined(__CYGWIN__) && 0
// cygwin gcc bittest has problems
// other gcc has no bittest
//  #define NARK_BIT_TEST_USE_INTRINSIC
    #if NARK_WORD_BITS == 64
	  BOOST_STATIC_ASSERT(sizeof(long) == 8); // LP model
	  inline bool nark_bit_test(const long* a, long i) { return _bittest64(reinterpret_cast<const __int64*>(a), i) ? 1 : 0; }
	  inline bool nark_bit_test(const long long* a, long i) { return _bittest64(reinterpret_cast<const __int64*>(a), i) ? 1 : 0; }
	  inline bool nark_bit_test(const unsigned long* a, long i) { return _bittest64(reinterpret_cast<const __int64*>(a), i) ? 1 : 0; }
	  inline bool nark_bit_test(const unsigned long long* a, long i) { return _bittest64(reinterpret_cast<const __int64*>(a), i) ? 1 : 0; }

	  inline void nark_bit_set0(long* a, long i) { _bittestandreset64(reinterpret_cast<__int64*>(a), i); }
	  inline void nark_bit_set0(long long* a, long i) { _bittestandreset64(reinterpret_cast<__int64*>(a), i); }
	  inline void nark_bit_set0(unsigned long* a, long i) { _bittestandreset64(reinterpret_cast<__int64*>(a), i); }
	  inline void nark_bit_set0(unsigned long long* a, long i) { _bittestandreset64(reinterpret_cast<__int64*>(a), i); }

	  inline void nark_bit_set1(long* a, long i) { _bittestandset64(reinterpret_cast<__int64*>(a), i); }
	  inline void nark_bit_set1(long long* a, long i) { _bittestandset64(reinterpret_cast<__int64*>(a), i); }
	  inline void nark_bit_set1(unsigned long* a, long i) { _bittestandset64(reinterpret_cast<__int64*>(a), i); }
	  inline void nark_bit_set1(unsigned long long* a, long i) { _bittestandset64(reinterpret_cast<__int64*>(a), i); }
    #else
	  inline bool nark_bit_test(const int* a, long i) { return _bittest(a, i) ? 1 : 0; }
	  inline bool nark_bit_test(const unsigned int* a, long i) { return _bittest(reinterpret_cast<const int*>(a), i) ? 1 : 0; }
	  inline void nark_bit_set0(int* a, long i) { _bittestandreset(a, i); }
	  inline void nark_bit_set0(unsigned int* a, long i) { _bittestandreset(reinterpret_cast<int*>(a), i); }
	  inline void nark_bit_set1(int* a, long i) { _bittestandset(a, i); }
	  inline void nark_bit_set1(unsigned int* a, long i) { _bittestandset(reinterpret_cast<int*>(a), i); }
    #endif
#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
    #define NARK_BIT_TEST_USE_INTRINSIC
    #if NARK_WORD_BITS == 64
	  inline bool nark_bit_test(const __int64* a, __int64 i) { return _bittest64(a, i) ? 1 : 0; }
	  inline bool nark_bit_test(const unsigned __int64* a, __int64 i) { return _bittest64(reinterpret_cast<const __int64*>(a), i) ? 1 : 0; }
	  inline void nark_bit_set0(__int64* a, __int64 i) { _bittestandreset64(a, i); }
	  inline void nark_bit_set0(unsigned __int64* a, __int64 i) { _bittestandreset64(reinterpret_cast<__int64*>(a), i); }
	  inline void nark_bit_set1(__int64* a, __int64 i) { _bittestandset64(a, i); }
	  inline void nark_bit_set1(unsigned __int64* a, __int64 i) { _bittestandset64(reinterpret_cast<__int64*>(a), i); }
    #endif
	inline bool nark_bit_test(const long* a, long i) { return _bittest(a, i) ? 1 : 0; }
	inline bool nark_bit_test(const unsigned long* a, long i) { return _bittest(reinterpret_cast<const long*>(a), i) ? 1 : 0; }
	inline bool nark_bit_test(const int* a, long i) { return _bittest(reinterpret_cast<const long*>(a), i) ? 1 : 0; }
	inline bool nark_bit_test(const unsigned* a, long i) { return _bittest(reinterpret_cast<const long*>(a), i) ? 1 : 0; }

	inline void nark_bit_set0(int* a, long i) { _bittestandreset(reinterpret_cast<long*>(a), i); }
	inline void nark_bit_set0(unsigned* a, long i) { _bittestandreset(reinterpret_cast<long*>(a), i); }
	inline void nark_bit_set1(int* a, long i) { _bittestandset(reinterpret_cast<long*>(a), i); }
	inline void nark_bit_set1(unsigned* a, long i) { _bittestandset(reinterpret_cast<long*>(a), i); }
#endif

#if !defined(NARK_BIT_TEST_USE_INTRINSIC)
template<class Uint>
inline bool nark_bit_test(const Uint* a, size_t i) {
	return a[i/(sizeof(Uint)*8)] & (Uint(1)<<i%(sizeof(Uint)*8)) ? 1 : 0;
}
template<class Uint>
inline void nark_bit_set0(Uint* a, size_t i) {
	a[i/(sizeof(Uint)*8)] &= ~(Uint(1) << i % (sizeof(Uint) * 8));
}
template<class Uint>
inline void nark_bit_set1(Uint* a, size_t i) {
	a[i/(sizeof(Uint)*8)] |= (Uint(1) << i % (sizeof(Uint) * 8));
}
#endif

inline int fast_popcount(unsigned int x) { return fast_popcount32(x); }
inline NARK_IF_WORD_BITS_64(long long, int)
	   fast_popcount(unsigned long long x) { return fast_popcount64(x); }
#if ULONG_MAX > 0xFFFFFFFF
inline long fast_popcount(unsigned long x) { return fast_popcount64(x); }
#else
inline long fast_popcount(unsigned long x) { return fast_popcount32(x); }
#endif

#if defined(__BMI2__)
inline int fast_popcount_trail(unsigned int x, int n) { return fast_popcount32(_bzhi_u32(x, n)); }
#else
inline int fast_popcount_trail(unsigned int x, int n) { return fast_popcount32(x & ~(-1 << n)); }
#endif

#if defined(__BMI2__) && NARK_WORD_BITS >= 64
inline long long fast_popcount_trail(unsigned long long x, int n) { return fast_popcount64(_bzhi_u64(x, n)); }
#else
inline NARK_IF_WORD_BITS_64(long long, int)
fast_popcount_trail(unsigned long long x, int n) { return fast_popcount64(x & ~((unsigned long long)(-1) << n)); }
#endif

#if ULONG_MAX > 0xFFFFFFFF
inline long fast_popcount_trail(unsigned long x, int n) { return fast_popcount_trail((unsigned long long)x, n); }
#else
inline long fast_popcount_trail(unsigned long x, int n) { return fast_popcount_trail((unsigned int)x, n); }
#endif

inline int fast_clz(unsigned int x) { return fast_clz32(x); }
inline NARK_IF_WORD_BITS_64(long long, int)
	   fast_clz(unsigned long long x) { return fast_clz64(x); }
#if ULONG_MAX > 0xFFFFFFFF
inline int fast_clz(unsigned long x) { return fast_clz64(x); }
#else
inline int fast_clz(unsigned long x) { return fast_clz32(x); }
#endif

inline int fast_ctz(unsigned int x) { return fast_ctz32(x); }
inline int fast_ctz(unsigned long long x) { return fast_ctz64(x); }
#if ULONG_MAX > 0xFFFFFFFF
inline long fast_ctz(unsigned long x) { return fast_ctz64(x); }
#else
inline int fast_ctz(unsigned long x) { return fast_ctz32(x); }
#endif

template<class Uint>
static inline void bits_range_set0(Uint* data, size_t i, size_t k) {
	if (i == k) {
		return;
	}
	const static size_t UintBits = sizeof(Uint) * 8;
	size_t j = i / UintBits;
	if (j == (k - 1) / UintBits) {
		data[j] &= ~(Uint(-1) << i%UintBits)
			| (Uint(-2) << (k - 1) % UintBits);
	}
	else {
		if (i % UintBits)
			data[j++] &= ~(Uint(-1) << i%UintBits);
		while (j < k / UintBits)
			data[j++] = 0;
		if (k % UintBits)
			data[j] &= Uint(-1) << k%UintBits;
	}
}

template<class Uint>
static inline void bits_range_set1(Uint* data, size_t i, size_t k) {
	if (i == k) {
		return;
	}
	const static size_t UintBits = sizeof(Uint) * 8;
	size_t j = i / UintBits;
	if (j == (k - 1) / UintBits) {
		data[j] |= (Uint(-1) << i%UintBits)
			& ~(Uint(-2) << (k - 1) % UintBits);
	}
	else {
		if (i % UintBits)
			data[j++] |= (Uint(-1) << i%UintBits);
		while (j < k / UintBits)
			data[j++] = Uint(-1);
		if (k % UintBits)
			data[j] |= ~(Uint(-1) << k%UintBits);
	}
}

template<class Uint>
static inline void bits_range_set(Uint* data, size_t i, size_t k, bool val) {
	if (val)
		bits_range_set1(data, i, k);
	else
		bits_range_set0(data, i, k);
}

template<int Bits> class BitsToUint;
template<> class BitsToUint<32> { typedef unsigned int type; };
template<> class BitsToUint<64> { typedef unsigned long long type; };

} // namespace nark

#endif

max_stars_repo_name: rockeet/nark-bone

max_issues_repo_name: rockeet/nark-bone

max_forks_repo_name: rockeet/nark-bone


text:
// This file is part of MLDB. Copyright 2015 mldb.ai inc. All rights reserved.

/* behavior_domain_valgrid_test.cc
   Jeremy Barnes, 2 July 2013
   Copyright (c) 2013 mldb.ai inc.  All rights reserved.

   Test that the BehaviorDomain valgrinds properly.
*/

#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK

#include <boost/test/unit_test.hpp>
#include "mldb/plugins/behavior/mutable_behavior_domain.h"
#include "mldb/plugins/behavior/mapped_behavior_domain.h"
#include "mldb/plugins/behavior/merged_behavior_domain.h"
#include "mldb/utils/smart_ptr_utils.h"
#include "mldb/utils/string_functions.h"
#include "mldb/utils/vector_utils.h"
#include "mldb/utils/pair_utils.h"
#include "mldb/arch/demangle.h"

using namespace std;
using namespace MLDB;

namespace {

    int nToRecord = 1000;
    int nSubjects = 100;
    int nBehaviors = 100;

} // file scope

#include "behavior_test_utils.h"

#if 1
BOOST_AUTO_TEST_CASE( test_subject_info_sort1 )
{
    SubjectInfo info;
    SubjectBehavior beh;
    beh.behavior = 1;
    beh.count = 1;

    info.behaviors.push_back(beh);
    info.behaviors.push_back(beh);

    info.sort();

    BOOST_CHECK_EQUAL(info.behaviors.size(), 1);
    BOOST_CHECK_EQUAL(info.behaviors[0].count, 2);
    BOOST_CHECK_EQUAL(info.behaviors[0].behavior, 1);
}
#endif

#if 1
BOOST_AUTO_TEST_CASE( test_subject_info_sort2 )
{
    SubjectInfo info;
    SubjectBehavior beh;
    beh.behavior = 1;
    beh.count = 1;

    SubjectBehavior beh2 = beh;
    beh2.timestamp.addSeconds(1);

    info.behaviors.push_back(beh);
    info.behaviors.push_back(beh2);
    info.behaviors.push_back(beh);
    info.behaviors.push_back(beh2);
    info.behaviors.push_back(beh);
    info.behaviors.push_back(beh2);

    info.sort();

    BOOST_CHECK_EQUAL(info.behaviors.size(), 2);
    BOOST_CHECK_EQUAL(info.behaviors[0].count, 3);
    BOOST_CHECK_EQUAL(info.behaviors[0].behavior, 1);
    BOOST_CHECK_EQUAL(info.behaviors[1].count, 3);
    BOOST_CHECK_EQUAL(info.behaviors[1].behavior, 1);
    BOOST_CHECK_LT(info.behaviors[0].timestamp,
                   info.behaviors[1].timestamp);
}
#endif

#if 0 // this test has issues with when we insert the same thing twice
BOOST_AUTO_TEST_CASE( test_mutable_behavior_domain )
{
    MutableBehaviorDomain dom;

    cerr << "size of subject entry = "
         << sizeof(MutableBehaviorDomain::SubjectEntry) << endl;
    cerr << "size of behavior entry = "
         << sizeof(MutableBehaviorDomain::BehaviorEntry) << endl;
    cerr << "size of Id = " << sizeof(Id) << endl;

    vector<tuple<Date, BH, int> > entries;

    Id subject("hello");

    for (unsigned i = 0;  i < 1000;  ++i) {
        Id id(random() % 1000 + 1);
        BH beh(id);
        Date date = Date::fromSecondsSinceEpoch(random() % 1000);
        uint32_t count = i + 1;

        dom.recordId(subject, id, date, count);
        entries.push_back(make_tuple(date, beh, count));

        std::sort(entries.begin(), entries.end());

        vector<tuple<Date, BH, int> > read;

        bool hadError = false;

        int x = 0;
        auto onBeh = [&] (BH beh, Date ts, uint32_t count)
            {
                if (x >= entries.size()
                    || ts != std::get<0>(entries[x])
                    || beh != std::get<1>(entries[x])
                    || count != std::get<2>(entries[x]))
                    hadError = true;

                BOOST_CHECK_LT(x, entries.size());
                BOOST_CHECK_EQUAL(ts, std::get<0>(entries[x]));
                BOOST_CHECK_EQUAL(beh, std::get<1>(entries[x]));
                BOOST_CHECK_EQUAL(count, std::get<2>(entries[x]));

                read.push_back(std::make_tuple(ts, beh, count));

                ++x;
                return true;
            };

        dom.forEachSubjectBehaviorHash(subject, onBeh,
                                        BehaviorDomain::
                                        SubjectBehaviorFilter(),
                                        INORDER);

        if (hadError) {
            auto dump = [&] (const vector<tuple<Date, BH, int> > & read)
                {
                    int i = 0;
                    for (auto e: read) {
                        Date ts;
                        BH beh;
                        uint32_t count;

                        std::tie(ts, beh, count) = e;

                        cerr << i << ": " << ts << " " << beh << " " << count
                             << endl;
                        ++i;
                    }
                };

            cerr << "inserted: " << endl;
            dump(entries);

            cerr << endl << "read: " << endl;
            dump(read);
        }

        BOOST_CHECK_EQUAL(x, entries.size());
    }
}
#endif

#if 1
BOOST_AUTO_TEST_CASE( test_behavior_serialization )
{
    // 1.  Record 1 million behaviors
    auto mut = std::make_shared<MutableBehaviorDomain>();
    createTestBehaviors(mut);

    testIntegrity(*mut);

    mut->save("tmp/behaviorDomainTest.beh");

    MappedBehaviorDomain m;
    m.load("tmp/behaviorDomainTest.beh");

    testIntegrity(m);

    testEquivalent(m, *mut);

    vector<std::shared_ptr<BehaviorDomain> > toMerge;
    toMerge.push_back(make_unowned_sp(m));

    MergedBehaviorDomain m2(toMerge, true);

    testIntegrity(m2);

    testEquivalent(m2, *mut);

    vector<SH> subjs = m.allSubjectHashes();
    int n = subjs.size() / 2;

    vector<SH> subjs1(subjs.begin(), subjs.begin() + n);
    vector<SH> subjs2(subjs.begin() + n, subjs.end());

#if 0
    FilteredBehaviorDomain f1(mut, subjs1);
    FilteredBehaviorDomain f2(make_unowned_sp(m),   subjs2);

    vector<std::shared_ptr<BehaviorDomain> > toMerge2;
    toMerge2.push_back(make_unowned_sp(f1));
    toMerge2.push_back(make_unowned_sp(f2));
    MergedBehaviorDomain m3(toMerge2, true);

    testIntegrity(m3);

    testEquivalent(m3, *mut);
#endif
}
#endif

ext: cc

max_stars_repo_name: kstepanmpmg/mldb

max_issues_repo_name: tomzhang/mldb

max_forks_repo_name: matebestek/mldb


text:
/*
 * Copyright Nick Thompson, 2019
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 */

#include "math_unit_test.hpp"
#include <numeric>
#include <utility>
#include <random>
#include <cmath>
#include <boost/core/demangle.hpp>
#include <boost/math/special_functions/rsqrt.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
#ifdef BOOST_HAS_FLOAT128
#include <boost/multiprecision/float128.hpp>
using boost::multiprecision::float128;
#endif

using boost::math::rsqrt;

template<typename Real>
void test_rsqrt()
{
    std::cout << "Testing rsqrt on type " << boost::core::demangle(typeid(Real).name()) << "\n";
    using std::sqrt;
    Real x = std::numeric_limits<Real>::min();
    while (x < 10000*std::numeric_limits<Real>::epsilon()) {
        Real expected = 1/sqrt(x);
        Real computed = rsqrt(x);
        if(!CHECK_ULP_CLOSE(expected, computed, 2)) {
            std::cerr << "  1/sqrt(" << x << ") is computed incorrectly.\n";
        }
        x += std::numeric_limits<Real>::epsilon();
    }

    // x ~ 1:
    x = 1;
    while (x < 1 + 1000*std::numeric_limits<Real>::epsilon()) {
        Real expected = 1/sqrt(x);
        Real computed = rsqrt(x);
        if(!CHECK_ULP_CLOSE(expected, computed, 2)) {
            std::cerr << "  1/sqrt(" << x << ") is computed incorrectly.\n";
        }
        x += std::numeric_limits<Real>::epsilon();
    }

    // x ~ 1000:
    x = 1000;
    while (x < 1000 + 1000*1000*std::numeric_limits<Real>::epsilon()) {
        Real expected = 1/sqrt(x);
        Real computed = rsqrt(x);
        if(!CHECK_ULP_CLOSE(expected, computed, 2)) {
            std::cerr << "  1/sqrt(" << x << ") is computed incorrectly.\n";
        }
        x += 1000*std::numeric_limits<Real>::epsilon();
    }

    x = std::numeric_limits<Real>::infinity();
    Real expected = 1/sqrt(x);
    Real computed = rsqrt(x);
    if (!CHECK_ULP_CLOSE(expected, computed, 0)) {
        std::cerr << "Reciprocal square root of infinity not correctly computed.\n";
    }

    x = std::numeric_limits<Real>::max();
    expected = 1/sqrt(x);
    computed = rsqrt(x);
    if (!CHECK_EQUAL(expected, computed)) {
        std::cerr << "Reciprocal square root of std::numeric_limits<Real>::max() not correctly computed.\n";
    }

    if (!CHECK_NAN(rsqrt(std::numeric_limits<Real>::quiet_NaN()))) {
        std::cerr << "Reciprocal square root of std::numeric_limits<Real>::quiet_NaN() is not a NaN.\n";
    }
}

int main()
{
    test_rsqrt<float>();
    test_rsqrt<double>();
    test_rsqrt<long double>();
    test_rsqrt<boost::multiprecision::cpp_bin_float_50>();
    test_rsqrt<boost::multiprecision::cpp_bin_float_100>();

    #ifdef BOOST_HAS_FLOAT128
    test_rsqrt<float128>();
    #endif
    return boost::math::test::report_errors();
}

ext: cpp

max_stars_repo_name: anarthal/boost-unix-mirror

max_issues_repo_name: anarthal/boost-unix-mirror


text:
// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#include <boost/hana/tuple.hpp>

#include <utility>
namespace hana = boost::hana;

constexpr int f() {
    // copy-assign
    {
        hana::tuple<int> xs{1};
        hana::tuple<long> ys{1};
        xs = xs;
        ys = xs;
    }

    // move-assign
    {
        hana::tuple<int> xs{1}, xxs{1};
        hana::tuple<long> ys{1};
        xs = std::move(xxs);
        ys = std::move(xs);
    }

    return 0;
}

static_assert(f() == 0, ""); // force f() to be constexpr

int main() { }

max_stars_repo_name: nxplatform/nx-mobile

max_issues_repo_name: nxplatform/nx-mobile

max_forks_repo_name: nxplatform/nx-mobile


text:
/* Boost test/overflow.cpp
 * test if extended precision exponent does not disturb interval computation
 *
 * Copyright 2002-2003 Guillaume Melquiond
 *
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or
 * copy at http://www.boost.org/LICENSE_1_0.txt)
 */

#include <boost/numeric/interval.hpp>
#include <boost/test/minimal.hpp>
#include "bugs.hpp"

template<class I>
void test_one(typename I::base_type x, typename I::base_type f) {
  I y = x;
  typename I::base_type g = 1 / f;
  const int nb = 10000;
  for(int i = 0; i < nb; i++) y *= f;
  for(int i = 0; i < nb; i++) y *= g;
  BOOST_CHECK(in(x, y));
# ifdef BOOST_BORLANDC
  ::detail::ignore_unused_variable_warning(nb);
# endif
}

template<class I>
void test() {
  test_one<I>(1., 25.);
  test_one<I>(1., 0.04);
  test_one<I>(-1., 25.);
  test_one<I>(-1., 0.04);
}

int test_main(int, char *[]) {
  test<boost::numeric::interval<float> >();
  test<boost::numeric::interval<double> >();
  //test<boost::numeric::interval<long double> >();
# ifdef BOOST_BORLANDC
  ::detail::ignore_warnings();
# endif
  return 0;
}


text:
/*
 * Webcam.hpp
 *
 *  Created on: 19 нояб. 2017 г.
 *      Author: snork
 */

#ifndef CAMERA_HPP_
#define CAMERA_HPP_

#include <errno.h>
#include <sys/stat.h>

#include <cstring>
#include <string>
#include <vector>
#include <system_error>
#include <future>

#include <boost/asio/io_service.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>

#include <boost/signals2.hpp>

#include "log.hpp"
#include "MmapBuffer.hpp"

class Camera: private Logable<Camera>
{
public:
	class Frame
	{
	public:
		virtual ~Frame() = default;
		virtual const void * data() = 0;
		virtual size_t dataSize() = 0;
		virtual const struct v4l2_pix_format & pixFmt() = 0;
	};

public:
	Camera(boost::asio::io_service & io): ::Logable<Camera>("Camera"), _strand(io), _fd(io) {}
	~Camera() { close(); }

	void open(const std::string & path);
	void set_fmt(uint32_t xres, uint32_t yres, uint32_t v4l2_fourcc);
	void start(size_t framebuffer_queue_size = 4);
	void stop();
	void close();

	boost::signals2::signal<void(std::shared_ptr<Frame>)> onFrame;

private:
	typedef std::vector<std::shared_ptr<MmapBuffer>> BufferPool;

	void _init_buffers_ws(size_t buffers_count);
	void _reset_buffers_ws();
	void _enqueue_buffer_ws(const MmapBuffer & buffer, bool force = false);
	void _do_read_ws();

	boost::asio::io_service::strand _strand;
	boost::asio::posix::stream_descriptor _fd;

	struct v4l2_format _fmt;
	bool _started = false;
	BufferPool _buffers_pool;
};

#endif /* CAMERA_HPP_ */

ext: hpp


text:
#ifndef TESSERACT_COLLISION_BENCHMARK_UTILS_HPP
#define TESSERACT_COLLISION_BENCHMARK_UTILS_HPP

#include <benchmark/benchmark.h>
#include <Eigen/Eigen>
#include <console_bridge/console.h>

using namespace tesseract_collision;
using namespace test_suite;
using namespace tesseract_geometry;

inline tesseract_geometry::Geometry::Ptr CreateUnitPrimative(const tesseract_geometry::GeometryType type,
                                                             const double scale = 1.0)
{
  tesseract_geometry::Geometry::Ptr geom;
  switch (type)
  {
    case tesseract_geometry::GeometryType::BOX:
      geom = std::make_shared<tesseract_geometry::Box>(scale, scale, scale);
      break;
    case tesseract_geometry::GeometryType::CONE:
      geom = std::make_shared<tesseract_geometry::Cone>(scale, scale);
      break;
    case tesseract_geometry::GeometryType::PLANE:
      geom = std::make_shared<tesseract_geometry::Plane>(scale, scale, scale, scale);
      break;
    case tesseract_geometry::GeometryType::SPHERE:
      geom = std::make_shared<tesseract_geometry::Sphere>(scale);
      break;
    case tesseract_geometry::GeometryType::CAPSULE:
      geom = std::make_shared<tesseract_geometry::Capsule>(scale, scale);
      break;
    case tesseract_geometry::GeometryType::CYLINDER:
      geom = std::make_shared<tesseract_geometry::Cylinder>(scale, scale);
      break;
    default:
      CONSOLE_BRIDGE_logError("Invalid Geometry Type. Can only create primatives");
      break;
  }
  return geom;
};
#endif

max_stars_repo_name: daoran/tesseract

max_issues_repo_name: daoran/tesseract

max_forks_repo_name: daoran/tesseract


text:
//============================================================================
// Name        : Vicon Xbee Communication
// Author      : Britsk Nguyen
// Version     :
// Copyright   : Love me if you use my code
// Description : ros node to communicate with vicon via serial interface
//============================================================================
//#define ROS_MASTER_URI		"http://localhost:11311"
//#define ROS_ROOT		"/opt/ros/indigo/share/ros"
#include <iostream>
#include "stdio.h"
#include <stdlib.h>
#include <sstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <termios.h>
#include <math.h>
#include <cstring>
#include <unistd.h>
#include <sstream>
#include <signal.h>
#include <math.h>
#include <viconxbee/viconPoseMsg.h>
#include <geometry_msgs/TwistWithCovarianceStamped.h>
#include <nav_msgs/Odometry.h>
#include <nav_msgs/Path.h>
#include <sensor_msgs/Imu.h>
#include <tf/transform_broadcaster.h>
#include <boost/assign/list_of.hpp>
#include <errno.h>
#include <serial/serial.h>
#include <tf/transform_broadcaster.h>

//#include <mavros/Imu.h>

#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KYEL  "\x1B[33m"
#define KBLU  "\x1B[34m"
#define KMAG  "\x1B[35m"
#define KCYN  "\x1B[36m"
#define KWHT  "\x1B[37m"
#define RESET "\033[0m"

#define USE_MIT_SERIAL
#define BAUDRATE            57600
#define BAUD_MACRO          B57600
#define DFLT_PORT           "/dev/ttyUSB0"
#define RCV_THRESHOLD       46					//Receive frame's length
#define FPS                 40					//Frames per second
#define DFLT_NODE_RATE      20                  //Update frequency
#define DFLT_COMM_TIMEOUT   250
#define	UP                  0xFF
#define DOWN                0x00
#define HEADER_NAN          0x7FAAAAAA

using namespace std;
serial::Serial fd;

uint8_t		frame32[RCV_THRESHOLD];
uint8_t		rcvdFrame[RCV_THRESHOLD];
uint8_t		backupFrame[RCV_THRESHOLD];
uint8_t		flagIncompleteFrame = 0;
int			rcvdBytesCount = 0;
uint8_t		backupRcvBytesCount = 0;
uint8_t		misAlgnFlag = DOWN;
uint8_t		msgFlag = DOWN;
uint8_t		viconUpdateFlag = DOWN;
uint8_t		publishFlag = DOWN;
uint8_t		headerIndex = 0xFF;
uint32_t	seqCount = 0;
uint32_t viconStartTimestamp;
ros::Time viconRosStartTimestamp;

#define VICON_MSG_HDR       *(uint32_t *)rcvdFrame
#define VICON_MSG_X         *(float *)(rcvdFrame + 4)
#define VICON_MSG_Y         *(float *)(rcvdFrame + 8)
#define VICON_MSG_Z         *(float *)(rcvdFrame + 12)
#define VICON_MSG_XD        *(float *)(rcvdFrame + 16)
#define VICON_MSG_YD        *(float *)(rcvdFrame + 20)
#define VICON_MSG_ZD        *(float *)(rcvdFrame + 24)
#define VICON_MSG_ROLL      *(float *)(rcvdFrame + 28)
#define VICON_MSG_PITCH     *(float *)(rcvdFrame + 32)
#define VICON_MSG_YAW      *(float *)(rcvdFrame + 36)
#define VICON_MSG_STMP      *(uint32_t *)(rcvdFrame + 40)
#define VICON_MSG_CSA       *(uint8_t *)(rcvdFrame + 44)
#define VICON_MSG_CSB       *(uint8_t *)(rcvdFrame + 45)

long validCount = 0;
long faultCount = 0;
long freeCount = 0;
long loopCount = 0;

void signal_handler_IO(int status)
{
    msgFlag = UP;
}

int synchronize(ros::Rate rate, double timeOut);

int main(int argc, char **argv)
{
    //Create ros handler to node
    ros::init(argc, argv, "viconXbeeNode");
    ros::NodeHandle viconXbeeNode("~");

    string serialPortName = string(DFLT_PORT);
    if(viconXbeeNode.getParam("viconSerialPort", serialPortName))
        printf(KBLU"Retrieved value %s for param 'viconSerialPort'!\n"RESET, serialPortName.data());
    else
    {
        printf(KRED "Couldn't retrieve param 'viconSerialPort', program closed!\n"RESET);
        return 0;
    }
    int viconNodeRate = DFLT_NODE_RATE;
    if(viconXbeeNode.getParam("viconNodeRate", viconNodeRate))
        printf(KBLU"Retrieved value %d for param 'viconnNodeRate'\n"RESET, viconNodeRate);
    else
        printf(KYEL "Couldn't retrieve param 'viconnNodeRate', applying default value %dHz\n"RESET, viconNodeRate);

    int viconCommTimeout = DFLT_COMM_TIMEOUT;
    if(viconXbeeNode.getParam("viconCommTimeout", viconCommTimeout))
        printf(KBLU"Retrieved value %d [ms] for param 'viconCommTimeout'\n"RESET, viconCommTimeout);
    else
        printf(KYEL "Couldn't retrieve param 'viconCommTimeout', applying default value %dms\n"RESET, viconCommTimeout);

    //ros Rate object to control the update rate
    ros::Rate rate = ros::Rate(viconNodeRate);

    ros::Publisher viconPosePublisher = viconXbeeNode.advertise<viconxbee::viconPoseMsg>("viconPoseTopic", 1);
    ros::Publisher viconMocapPublisher = viconXbeeNode.advertise<geometry_msgs::PoseStamped>("mocap/pose", 1);
    ros::Publisher viconIMUPublisher = viconXbeeNode.advertise<sensor_msgs::Imu>("mocap/imu", 1);
    ros::Publisher twistPublisher = viconXbeeNode.advertise<geometry_msgs::TwistWithCovarianceStamped>("mocap/twist", 1);
    tf::Quaternion last_quaternion(0,0,0);
    geometry_msgs::PoseStamped poseStamped;
    geometry_msgs::TwistWithCovarianceStamped twist;
    twist.twist.covariance[0*7] = 0.25;
    twist.twist.covariance[1*7] = 0.25;
    twist.twist.covariance[2*7] = 0.25;
    twist.twist.covariance[3*7] = 0.03;
    twist.twist.covariance[4*7] = 0.03;
    twist.twist.covariance[5*7] = 0.03;

    //-------------------Initialize Serial Connection---------------------------------------------------
    fd.setPort(serialPortName);
    fd.setBaudrate(BAUDRATE);
    fd.setTimeout(5, 10, 0, 10, 0);
    fd.open();
    if (fd.isOpen())
    {
        fd.flushInput();
        printf(KBLU "Connection established\n\n" RESET);
    }
    else
    {
        printf(KRED "serialInit: Failed to open port %s\n" RESET, serialPortName.data());
        return 0;
    }
    //-----------------------------------Serial Initialization-------------------------------------
    //Looping to catch the intial of frame
    if( synchronize(rate, viconCommTimeout/1000.0) < 0)
    {
        printf("Timeout synchronizing with stream. Exitting!");
        exit(1);
    }

    viconStartTimestamp = VICON_MSG_STMP;
    viconRosStartTimestamp = ros::Time::now();

    static tf::TransformBroadcaster br;
    tf::Transform transform;

    //start reading and publishing
    poseStamped.header.stamp =  ros::Time::now();
    while(ros::ok())
    {
        uint32_t bytes_avail = fd.available();
        printf("Bytes detected: %lu\n", fd.available());
        //Extract and publish all messages if there are enough bytes in waiting

            if(bytes_avail > RCV_THRESHOLD)
                while(fd.available() >= RCV_THRESHOLD)
                {
                    fd.read(rcvdFrame, RCV_THRESHOLD);
                    //Since intial synchronization, first 4 bytes must be headers otherwise there must have been an error
                    uint32_t headerWord = VICON_MSG_HDR;
                    if(headerWord != HEADER_NAN)
                    {
                        //If there is some error, call the synchronize procedure
                        printf("Lost synchronization. Attempting to synchronize back.\n");
                        if( synchronize(rate, viconCommTimeout/1000.0) < 0)
                        {
                            printf("Timeout synchronizing with stream. Exitting!");
                            exit(1);
                        }
                        printf("Synchronization recovered.\n");

                    }
                    else
                    {
                        //All things are good so far
                        printf(KBLU"Aligned Header found: "RESET);
                        for(int i = 0; i < RCV_THRESHOLD; i++)
                            printf(KGRN"%2x ", rcvdFrame[i]);
                        printf("\n"RESET);

                        //Checksum
                        bool validCRC = false;
                        uint8_t CSA = 0, CSB = 0;
                        for(uint8_t i = sizeof(HEADER_NAN); i < RCV_THRESHOLD - 2; i++)
                        {
                            CSA = CSA + rcvdFrame[i];
                            CSB = CSB + CSA;
                        }

                        if(CSA == VICON_MSG_CSA && CSB == VICON_MSG_CSB)
                        {
                            validCRC = true;
                            printf(KBLU"CRC valid, msg published!!\n"RESET);
                        }
                        else
                            printf(KRED"CRC error, msg discarded!!\n"RESET);

                        if(validCRC)
                        {
                            viconxbee::viconPoseMsg viconPose;
                            double timeDiff = (int32_t)(VICON_MSG_STMP - viconStartTimestamp)/1000.0;
                            if(timeDiff < 0)
                            {
                                printf(KYEL"Vicon time must have reset.\n");
                                viconStartTimestamp = VICON_MSG_STMP;
                                viconRosStartTimestamp = ros::Time::now();
                            }
                            viconPose.time_stamp = viconRosStartTimestamp + ros::Duration((VICON_MSG_STMP - viconStartTimestamp)/1000.0);
                            viconPose.x = VICON_MSG_X;
                            viconPose.y = VICON_MSG_Y;
                            viconPose.z = VICON_MSG_Z;
                            viconPose.dx = VICON_MSG_XD;
                            viconPose.dy = VICON_MSG_YD;
                            viconPose.dz = VICON_MSG_ZD;
                            viconPose.roll = VICON_MSG_ROLL;
                            viconPose.pitch = VICON_MSG_PITCH;
                            viconPose.yaw = VICON_MSG_YAW;
                            viconPosePublisher.publish(viconPose);

                            //publish to mocap/pose topic
                            std_msgs::Header header;
                            header.frame_id = "vicon";
                            header.stamp = ros::Time::now();
                            double dt = poseStamped.header.stamp.toSec()-header.stamp.toSec();
                            poseStamped.header = header;
                            poseStamped.pose.position.x = viconPose.x;
                            poseStamped.pose.position.y = viconPose.y;
                            poseStamped.pose.position.z = viconPose.z;
                            tf::Quaternion q = tf::createQuaternionFromRPY(viconPose.roll, viconPose.pitch, viconPose.yaw);
                            poseStamped.pose.orientation.x = q.x();
                            poseStamped.pose.orientation.y = q.y();
                            poseStamped.pose.orientation.z = q.z();
                            poseStamped.pose.orientation.w = q.w();
                            viconMocapPublisher.publish(poseStamped);
                            seqCount++;

                            twist.header = poseStamped.header;
                            twist.twist.twist.linear.x = viconPose.dx;
                            twist.twist.twist.linear.y = viconPose.dy;
                            twist.twist.twist.linear.z = viconPose.dz;
                            tf::Quaternion quaternion;
                            tf::quaternionMsgToTF(poseStamped.pose.orientation, quaternion);
                            tf::Quaternion d_q = last_quaternion.inverse()*quaternion;
                            tf::Matrix3x3 m(d_q);
                            double roll, pitch, yaw;
                            m.getRPY(roll, pitch, yaw);
                            last_quaternion = quaternion;
                            twist.twist.twist.angular.x = roll/dt;
                            twist.twist.twist.angular.y = pitch/dt;
                            twist.twist.twist.angular.z = yaw/dt;

                            sensor_msgs::Imu imu;
                            imu.header = poseStamped.header;
                            imu.orientation = poseStamped.pose.orientation;
                            imu.linear_acceleration.x = poseStamped.pose.position.x;
                            imu.linear_acceleration.y = poseStamped.pose.position.y;
                            imu.linear_acceleration.z = poseStamped.pose.position.z;
                            viconIMUPublisher.publish(imu);

                            transform.setOrigin(tf::Vector3(viconPose.x, viconPose.y, viconPose.z));
                            transform.setRotation(q);
                            br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "vicon", "robot_base"));
                        }
                    }
                }
        else
            printf(KBLU"No message has arrived...\n"RESET);
        printf("Bytes still buffered: %lu\n\n", fd.available());
        rate.sleep();
    }
    return 0;
}

int synchronize(ros::Rate rate, double timeOut)
{
    ros::Time synchStartTime = ros::Time::now();
    while(ros::ok())
    {
        uint32_t bytes_avail = fd.available();
        printf("Bytes in buffer%d\n", bytes_avail);

        if(bytes_avail < RCV_THRESHOLD*2)
        {
            rate.sleep();
            continue;
        }
        else
        {
            //dummy read to clean up the buffer
            fd.read(rcvdFrame, 4);
            uint32_t headerWord = VICON_MSG_HDR;
            while((headerWord != HEADER_NAN) || (bytes_avail >= RCV_THRESHOLD*2))
            {
                bytes_avail = fd.available();
                headerWord = (headerWord >> 8) & (0x00FFFFFF);
                fd.read(rcvdFrame, 1);
                headerWord = headerWord | (rcvdFrame[0] << 24);
                printf("%x\n", headerWord);
                if(headerWord == HEADER_NAN)
                {
                    VICON_MSG_HDR = HEADER_NAN;
                    fd.read(rcvdFrame + 4, RCV_THRESHOLD - 4);
                    headerWord = HEADER_NAN;
                }
            }
            break;
        }

        if((ros::Time::now() - synchStartTime).toSec() > timeOut)
            return -1;
    }
    return (int)((ros::Time::now() - synchStartTime).toSec()*1000);
}

max_stars_repo_name: khairulislam/phys

max_issues_repo_name: khairulislam/phys

max_forks_repo_name: khairulislam/phys


text: #include <boost/icl/type_traits/codomain_type_of.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text: #include <boost/compute/pipe.hpp>


text:
#pragma once

#include <stdexcept>
#include <vector>

#include <boost/serialization/split_member.hpp>
#include <boost/serialization/vector.hpp>

#include "../Variable.hpp"

namespace mist {
namespace it {

class DistributionOutOfRange : public std::out_of_range
{
public:
  DistributionOutOfRange(std::string const& method, int pos, int size)
    : out_of_range("Distribution::" + method + " : Position " +
                   std::to_string(pos) + " out of range [0," +
                   std::to_string(size))
  {}
};

using DistributionData = double;

/** Joint probability array for N variables
 */
class Distribution
{
private:
  std::vector<DistributionData> data;
  std::vector<int> factors;
  std::size_t size;
  std::size_t nvar;

public:
  using Data = DistributionData;
  using value_type = Data;

  Distribution()
    : data(0)
    , factors(0)
    , size(0)
    , nvar(0)
  {};

  /** Construct directly from dimension strides
   */
  template<class Container>
  Distribution(Container const& strides)
    : Distribution()
  {
    // Dynamically resize factors
    std::size_t next_nvar = strides.size();
    if (this->nvar < next_nvar) {
      this->factors.resize(next_nvar);
    }
    this->nvar = next_nvar;

    // Dynamically resize data
    std::size_t next_size = 1;
    for (std::size_t ii = 0; ii < this->nvar; ii++) {
      this->factors[ii] = next_size;
      next_size *= strides[ii];
    }
    if (this->size < next_size) {
      this->data.resize(next_size);
    }
    this->size = next_size;
    this->data.assign(this->size, 0);
  };

  void
  initialize(Variable::tuple const& vars, Variable::indexes const& indexes)
  {
    // Dynamically resize factors
    std::size_t next_nvar = indexes.size();
    if (this->nvar < next_nvar) {
      this->factors.resize(next_nvar);
    }
    this->nvar = next_nvar;

    // Dynamically resize data
    std::size_t next_size = 1;
    for (size_t ii = 0; ii < nvar; ii++) {
      this->factors[ii] = next_size;
      next_size *= vars[indexes[ii]].bins();
    }
    if (this->size < next_size) {
      this->data.resize(next_size);
    }
    this->size = next_size;
    this->data.assign(this->size, 0); // SEGFAULT
  };

  /** Construct from a Variable tuple
   */
  Distribution(Variable::tuple const& vars)
    : Distribution()
  {
    Variable::indexes indexes(vars.size());
    int ii = 0;
    for (auto& index : indexes) {
      index = ii;
      ii++;
    }
    initialize(vars, indexes);
  }

  Distribution(Variable::tuple const& vars, Variable::indexes const& indexes)
    : Distribution()
  {
    initialize(vars, indexes);
  }

  //
  // accessors
  //
  template<typename Integer>
  Data const& operator[](Integer index) const
  {
    return this->data[index];
  }
  template<typename Integer>
  Data& operator[](Integer index)
  {
    return this->data[index];
  }

  template<typename Iter>
  Data const& operator()(Iter it, Iter end) const
  {
    int index = 0;
    for (int ii = 0; it != end; ++it, ii++)
      index += this->factors[ii] * (*it);
    return this->data[index];
  }
  template<typename Iter>
  Data& operator()(Iter it, Iter end)
  {
    int index = 0;
    for (int ii = 0; it != end; ++it, ii++)
      index += this->factors[ii] * (*it);
    return this->data[index];
  }
  template<typename Container>
  Data const& operator()(Container const& indexes) const
  {
    return this->operator()(indexes.begin(), indexes.end());
  }
  template<typename Container>
  Data& operator()(Container const& indexes)
  {
    return this->operator()(indexes.begin(), indexes.end());
  }

  //
  // at exception throwing accessors
  //
  template<typename Iter>
  Data const& at(Iter it, Iter end) const
  {
    int index = 0;
    for (int ii = 0; it != end; ++it, ii++)
      index += this->factors[ii] * (*it);
    if (index >= this->size)
      throw DistributionOutOfRange("at", index, this->size);
    return this->data[index];
  }
  template<typename Iter>
  Data& at(Iter it, Iter end)
  {
    int index = 0;
    for (int ii = 0; it != end; ++it, ii++)
      index += this->factors[ii] * (*it);
    if (index >= this->size)
      throw DistributionOutOfRange("at", index, this->size);
    return this->data[index];
  }
  template<typename Container>
  Data const& at(Container const& indexes) const
  {
    return this->at(indexes.begin(), indexes.end());
  }
  template<typename Container>
  Data& at(Container const& indexes)
  {
    return this->at(indexes.begin(), indexes.end());
  }

  //
  // Plain data templates
  //
  template<typename Integer>
  Data const& operator()(int d, Integer indices[]) const
  {
    int index = 0;
    for (int ii = 0; ii < d; ii++)
      index += this->factors[ii] * indices[ii];
    return this->data[index];
  };
  template<typename Integer>
  Data& operator()(int d, Integer indices[])
  {
    int index = 0;
    for (int ii = 0; ii < d; ii++)
      index += this->factors[ii] * indices[ii];
    return this->data[index];
  };

  //
  // Peformance critical indexing
  //
  Data const& operator()(int v0, int b0) const { return this->data[v0]; };
  Data& operator()(int v0, int b0) { return this->data[v0]; };
  Data const& operator()(int v0, int v1, int b0, int b1) const
  {
    return this->data[v0 + b0 * v1];
  };
  Data& operator()(int v0, int v1, int b0, int b1)
  {
    return this->data[v0 + b0 * v1];
  };
  Data const& operator()(int v0, int v1, int v2, int b0, int b1, int b2) const
  {
    return this->data[v0 + b0 * v1 + b0 * b1 * v2];
  };
  Data& operator()(int v0, int v1, int v2, int b0, int b1, int b2)
  {
    return this->data[v0 + b0 * v1 + b0 * b1 * v2];
  };
  Data const& operator()(int v0, int v1, int v2, int v3, int b0, int b1, int b2, int b3) const
  {
    return this->data[v0 + b0*v1 + b0*b1*v2 + b0*b1*b2*v3];
  };
  Data& operator()(int v0, int v1, int v2, int v3, int b0, int b1, int b2, int b3)
  {
    return this->data[v0 + b0*v1 + b0*b1*v2 + b0*b1*b2*v3];
  };

  bool operator==(Distribution const& other) const noexcept
  {
    return this->data == other.data && this->factors == other.factors;
  }

  bool empty() { return data.empty(); }

  using iterator = std::vector<Data>::iterator;
  using const_iterator = std::vector<Data>::const_iterator;
  const_iterator begin() const { return this->data.begin(); };
  const_iterator end() const { return this->data.end(); };
  iterator begin() { return this->data.begin(); };
  iterator end() { return this->data.end(); };

  /** Multiply each value in distribution by factor
   */
  void scale(double factor)
  {
    for (std::size_t i = 0; i < this->size; i++) {
      this->data[i] *= factor;
    }
  };

  /** Normalize distribution
   */
  void normalize()
  {
    std::size_t norm = 0;
    for (std::size_t i = 0; i < this->size; i++) {
      norm += this->data[i];
    }
    if (norm)
      this->scale(1.0 / norm);
  };

#if 0
  //
  // Serialization
  //
  friend class boost::serialization::access;

  template<class Archive>
  void load(Archive& ar, const unsigned int version)
  {
    // members
    ar& factors;

    // explicit data
    // since this class specializes std::vector need push/pop each element
    std::size_t size = 0;
    ar& size;
    this->data.resize(size);
    for (std::size_t i = 0; i < size; i++) {
      Data dat;
      ar& dat;
      this->data[i] = dat;
    }
  }
  template<class Archive>
  void save(Archive& ar, const unsigned int version) const
  {
    // members
    ar& factors;

    // explicit data
    // since this class specializes std::vector need push/pop each element
    auto size = this->size;
    ar& size;
    for (std::size_t i = 0; i < size; i++) {
      ar(&this->data[i]);
    }
  }
  BOOST_SERIALIZATION_SPLIT_MEMBER()
#endif
};

} // it
} // mist

max_stars_repo_name: andbanman/mist

max_issues_repo_name: andbanman/mist

max_forks_repo_name: andbanman/mist


text:
/*
Copyright 2017 Glen Joseph Fernandes
(glenjofe@gmail.com)

Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/core/pointer_traits.hpp>
#include <boost/core/is_same.hpp>
#include <boost/core/lightweight_test_trait.hpp>

template<class T>
struct P1 { };

template<class T1, class T2>
struct P2 { };

template<class T1, class T2, class T3>
struct P3 { };

template<class T>
struct E1 {
    typedef bool element_type;
};

template<class T1, class T2>
struct E2 {
    typedef bool element_type;
};

template<class T1, class T2, class T3>
struct E3 {
    typedef bool element_type;
};

#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class... U>
struct P { };

template<class T, class... U>
struct E {
    typedef bool element_type;
};
#endif

int main()
{
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<int,
        boost::pointer_traits<int*>::element_type>));
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<int,
        boost::pointer_traits<P1<int> >::element_type>));
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<int,
        boost::pointer_traits<P2<int, char> >::element_type>));
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<int,
        boost::pointer_traits<P3<int, char, char> >::element_type>));
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<int,
        boost::pointer_traits<P<int, char, char, char> >::element_type>));
#endif
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<bool,
        boost::pointer_traits<E1<int> >::element_type>));
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<bool,
        boost::pointer_traits<E2<int, int> >::element_type>));
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<bool,
        boost::pointer_traits<E3<int, int, int> >::element_type>));
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<bool,
        boost::pointer_traits<E<int, int, int, int> >::element_type>));
#endif
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<void,
        boost::pointer_traits<void*>::element_type>));
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<void,
        boost::pointer_traits<P1<void> >::element_type>));
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<bool,
        boost::pointer_traits<E1<void> >::element_type>));
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<const int,
        boost::pointer_traits<const int*>::element_type>));
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<const int,
        boost::pointer_traits<P1<const int> >::element_type>));
    BOOST_TEST_TRAIT_TRUE((boost::core::is_same<bool,
        boost::pointer_traits<E1<const int> >::element_type>));
    return boost::report_errors();
}


text:
//
// Add --log_level=message to see the messages!
//
#define BOOST_TEST_MODULE "ConvolutionalNetwork Tests"
#include <boost/test/unit_test.hpp>

#include <sstream>

#include "core/types.h"
#include "core/functions.h"
#include "core/utils.h"
#include "core/random.h"
#include "core/updaters.h"
#include "core/training.h"
#include "layers/smaxlayer.h"

#include "networks/cnn.h"

#include "test_utils.h"
#include "timer.h"
#include "mnist_test.h"

using namespace std;
using namespace boost;
using namespace boost::unit_test;
using namespace yann;
using namespace yann::test;

#define MNIST_TEST_FOLDER   "../data/mnist/"

struct CnnTestFixture
{
  MnistTest _mnist_test;

  CnnTestFixture()
  {
    BOOST_TEST_MESSAGE("*** Reading MNIST dataset ...");
    _mnist_test.read(MNIST_TEST_FOLDER);
    BOOST_TEST_MESSAGE(_mnist_test);
  }
  ~CnnTestFixture()
  {
  }

  // Creates CNN with one Conv+Poll layer, FC layer and Softmax layer
  unique_ptr<Network> create_cnn_for_mnist(
      const MatrixSize & conv_filter_size,
      const MatrixSize & polling_size,
      const MatrixSize & frames_num,
      const unique_ptr<CostFunction> & cost)
  {
    // create params
    ConvolutionalNetwork::ConvPollParams params;
    params._output_frames_num = frames_num;
    params._conv_filter_size = conv_filter_size;
    params._conv_activation_funtion = make_unique<SigmoidFunction>();
    params._polling_mode = PollingLayer::PollMode_Max;
    params._polling_filter_size = polling_size;

    // create conv layers
    auto layers = ConvolutionalNetwork::create(
        _mnist_test.get_image_rows(),
        _mnist_test.get_image_cols(),
        params,
        make_unique<IdentityFunction>(),
        _mnist_test.get_label_size());
    YANN_CHECK(layers);

    // add softmaxLayer
    auto smax_layer = make_unique<SoftmaxLayer>(
        layers->get_output_size()
    );
    YANN_CHECK(smax_layer);
    layers->append_layer(std::move(smax_layer));

    // networks
    auto cnn = make_unique<Network>(std::move(layers));
    YANN_CHECK(cnn);
    cnn->set_cost_function(cost);

    // done
    return cnn;
  }
}; // struct CnnTestFixture

BOOST_FIXTURE_TEST_SUITE(CnnTest, CnnTestFixture);

BOOST_AUTO_TEST_CASE(IO_Test)
{
  BOOST_TEST_MESSAGE("*** ConvolutionalNetwork IO test ...");

  const MatrixSize image_size = 32;
  const MatrixSize output_size = 10;

  // create params
  ConvolutionalNetwork::ConvPollParams params;
  params._output_frames_num = 3;
  params._conv_filter_size = 2;
  params._conv_activation_funtion = make_unique<SigmoidFunction>();
  params._polling_mode = PollingLayer::PollMode_Max;
  params._polling_filter_size = 2;

  // create, init and write the network
  auto one_layers = ConvolutionalNetwork::create(
      image_size, // input rows,
      image_size, // input cols
      params,
      make_unique<SigmoidFunction>(), // FC layer activation func
      output_size      // output size
  );
  auto one = make_unique<Network>(std::move(one_layers));
  YANN_CHECK(one);
  one->init(Layer::InitMode_Random);

  // BOOST_TEST_MESSAGE("ConvolutionalNetwork before writing to file: " << (*one));
  ostringstream oss;
  oss << (*one);
  BOOST_CHECK(!oss.fail());

  // read network
  auto two_layers = ConvolutionalNetwork::create(
      image_size, // input rows,
      image_size, // input cols
      params,
      make_unique<SigmoidFunction>(), // FC layer activation func
      output_size      // output size
  );
  auto two = make_unique<Network>(std::move(two_layers));
  YANN_CHECK(two);
  std::istringstream iss(oss.str());
  iss >> (*two);
  BOOST_CHECK(!iss.fail());
  // BOOST_TEST_MESSAGE("ConvolutionalNetwork after loading from file: " << (*two));

  // compare
  BOOST_CHECK(one->is_equal(*two, TEST_TOLERANCE));
}

BOOST_AUTO_TEST_CASE(Training_GradientDescent_Test)
{
  BOOST_TEST_MESSAGE("*** ConvolutionalNetwork training test...");

  const size_t epochs = 300;
  const MatrixSize image_size = 2;
  const MatrixSize filter_size = 2;
  const MatrixSize polling_size = 1;
  const MatrixSize input_size = image_size * image_size;
  const MatrixSize output_size = 2;
  const MatrixSize training_batch_size = 4;
  const MatrixSize testing_batch_size = 2;
  const MatrixSize tests_per_batch = 1;
  VectorBatch training_inputs, training_outputs;
  VectorBatch testing_inputs, testing_outputs;

  resize_batch(training_inputs,  training_batch_size, input_size);
  resize_batch(training_outputs, training_batch_size, output_size);
  resize_batch(testing_inputs,   testing_batch_size,  input_size);
  resize_batch(testing_outputs,  testing_batch_size,  output_size);

  training_inputs  << 0, 0, 0, 1,
                      0, 0, 1, 0,
                      0, 1, 0, 0,
                      1, 0, 0, 0;
  training_outputs << 0, 1,
                      0, 1,
                      1, 0,
                      1, 0;

  testing_inputs   << 0, 0, 1, 1,
                      1, 1, 0, 0;
  testing_outputs  << 0, 1,
                      1, 0;

  ConvolutionalNetwork::ConvPollParams params;
  params._output_frames_num = 1;
  params._conv_filter_size = filter_size;
  params._conv_activation_funtion = make_unique<SigmoidFunction>();
  params._polling_mode = PollingLayer::PollMode_Max;
  params._polling_filter_size = polling_size;
  auto layers = ConvolutionalNetwork::create(
      image_size, // input rows
      image_size, // input cols
      params,
      make_unique<SigmoidFunction>(), // FC layer activation
      output_size
  );
  YANN_CHECK(layers);

  auto cnn = make_unique<Network>(std::move(layers));
  YANN_CHECK(cnn);
  cnn->set_cost_function(make_unique<QuadraticCost>());
  {
    Timer timer("Initializing ConvolutionalNetwork");
    cnn->init(Layer::InitMode_Random, Layer::InitContext(12345));
    BOOST_TEST_MESSAGE(timer);
  }

  // training
  Trainer trainer(make_unique<Updater_GradientDescent>(1.0, 0.0));
  DataSource_Stochastic data_source(
      training_inputs,
      training_outputs,
      DataSource_Stochastic::Sequential,
      tests_per_batch);
  BOOST_TEST_MESSAGE("trainer: " << trainer.get_info());
  {
    Timer timer("Training");
    trainer.train(*cnn, data_source, tests_per_batch, epochs);

    BOOST_TEST_MESSAGE(timer);
  }
  // BOOST_TEST_MESSAGE("After training: " << (*cnn));

  // testing
  VectorBatch res;
  for (MatrixSize ii = 0; ii < testing_batch_size; ii++) {
    VectorBatch in = get_batch(testing_inputs, ii); // copy
    VectorBatch out = get_batch(testing_outputs, ii); // copy
    res.resizeLike(out);

    cnn->calculate(in, res);

    Value cost = cnn->cost(res, out);
    BOOST_TEST_MESSAGE("test " << ii << " input: " << in);
    BOOST_TEST_MESSAGE("test " << ii << " expected: " << out);
    BOOST_TEST_MESSAGE("test " << ii << " actual: " << res);
    BOOST_TEST_MESSAGE("test " << ii << " cost/loss: " << cost);

    BOOST_CHECK_LE(cost, 0.06);
  }
}

BOOST_AUTO_TEST_CASE(Mnist_OneLayer_Two_Labels_Test)
{
  const size_t epochs = 3;

  // reduce the test size to two labels to make it faster
  BOOST_TEST_MESSAGE("*** Filtering test set...");
  _mnist_test.filter(1, 1000, 1000); // only allow 0,1 images; 1000 count
  BOOST_TEST_MESSAGE("*** Filtered test set: " << "\n" << _mnist_test);

  // setup
  auto cnn = create_cnn_for_mnist(
        10, // filter_size
        4, // polling_size,
        2, // frames_num,
        make_unique<QuadraticCost>());
  BOOST_CHECK(cnn);
  cnn->init(Layer::InitMode_Random, Layer::InitContext(12345));

  // create trainer
  auto trainer = make_unique<Trainer>(
      make_unique<Updater_GradientDescent>(1.0, 0.0));
  BOOST_CHECK(trainer);
  trainer->set_batch_progress_callback(batch_progress_callback);

  // print info
  BOOST_TEST_MESSAGE("*** Training against MNIST dataset with ");
  BOOST_TEST_MESSAGE(" ConvolutionalNetwork: " << cnn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);

  // test
  pair<double, Value> res = _mnist_test.train_and_test(
      *cnn,
      *trainer,
      DataSource_Stochastic::Sequential, // want consistency for this test
      10,                  // training_batch_size
      epochs,
      100                  // testing_batch_size
  );
  BOOST_TEST_MESSAGE("*** Success rate: " << (res.first * 100) << "% Loss: " << res.second << " after " << epochs << " epochs");
  BOOST_TEST_MESSAGE(" ConvolutionalNetwork: " << cnn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);

  // check
  BOOST_CHECK_GE(res.first, 0.995); // > 995%%
  BOOST_CHECK_LE(res.second, 0.006); // < 0.006 per test
}

BOOST_AUTO_TEST_CASE(Mnist_OneLayer_Full_Test, * disabled())
{
  const size_t epochs = 30;

  // setup
  auto cnn = create_cnn_for_mnist(
        5, // filter_size
        2, // polling_size,
        3, // frames_num,
        make_unique<QuadraticCost>());
  BOOST_CHECK(cnn);
  cnn->init(Layer::InitMode_Random);

  // trainer
  auto trainer = make_unique<Trainer>(
      make_unique<Updater_GradientDescent>(5.0, 0.0));
  BOOST_CHECK(trainer);
  trainer->set_batch_progress_callback(batch_progress_callback);

  // print info
  BOOST_TEST_MESSAGE("*** Training against MNIST dataset with ");
  BOOST_TEST_MESSAGE(" ConvolutionalNetwork: " << cnn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);

  // test
  pair<double, Value> res = _mnist_test.train_and_test(
      *cnn,
      *trainer,
      DataSource_Stochastic::Random,
      20, // training_batch_size
      epochs,
      100 // testing_batch_size
  );
  BOOST_TEST_MESSAGE("*** Success rate: " << (res.first * 100) << "% Loss: " << res.second << " after " << epochs << " epochs");
  BOOST_TEST_MESSAGE(" ConvolutionalNetwork: " << cnn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);
}

BOOST_AUTO_TEST_CASE(LeNet1_Two_Labels_Test)
{
  // reduce the test size to two labels to make it faster
  BOOST_TEST_MESSAGE("*** Filtering test set...");
  _mnist_test.filter(1, 1000, 1000); // only allow 0,1 images; 1000 count
  BOOST_TEST_MESSAGE("*** Filtered test set: " << "\n" << _mnist_test);

  const double alpha = 0.5;
  const double beta = 0.9;
  const MatrixSize training_batch_size = 10;
  const size_t epochs = 3;

  auto layers = ConvolutionalNetwork::create_lenet1(
      _mnist_test.get_image_rows(), // input_rows
      _mnist_test.get_image_cols(), // input_cols
      PollingLayer::PollMode_Avg,
      20, // fc_size
      _mnist_test.get_label_size(),   // output_size
      make_unique<SigmoidFunction>(), // conv activation
      make_unique<SigmoidFunction>(), // poll activation
      make_unique<SigmoidFunction>()  // fc activation
  );
  YANN_CHECK(layers);
  auto nn = make_unique<Network>(std::move(layers));
  nn->init(Layer::InitMode_Random, Layer::InitContext(12345));
  nn->set_cost_function(make_unique<QuadraticCost>());

  // Trainer
  auto trainer = make_unique<Trainer>(
      make_unique<Updater_GradientDescentWithMomentum>(alpha, beta));
  BOOST_CHECK(trainer);
  trainer->set_batch_progress_callback(batch_progress_callback);

  // print info
  BOOST_TEST_MESSAGE("*** Training against MNIST dataset with ");
  BOOST_TEST_MESSAGE(" CustomlNetwork: " << nn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);

  // train and test
  pair<double, Value> res = _mnist_test.train_and_test(
      *nn,
      *trainer,
      DataSource_Stochastic::Sequential, // want consistency for this test
      training_batch_size,
      epochs,
      100 // testing_batch_size
  );
  BOOST_TEST_MESSAGE("*** Success rate: " << (res.first * 100)
                     << "% Loss: " << res.second
                     << " after " << epochs << " epochs");
  BOOST_TEST_MESSAGE(" CustomlNetwork: " << nn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);

  // save_to_file(*nn, "nn");

  // check
  BOOST_CHECK_GE(res.first, 0.99);  // > 99%%
  BOOST_CHECK_LE(res.second, 0.05); // < 0.05 per test
}

// The best result so far:
//
// Success rate for epoch 100: against training dataset: 98.3633% against test dataset: 98.38%
// Cost/loss per test for epoch 100: against training dataset: 0.122933 against test dataset: 0.122639
// Training time 17385 milliseconds
// Testing against training dataset time 7825.93 milliseconds
// Testing against test dataset time 1340.66 milliseconds
//
//  auto polling_mode = PollingLayer::PollMode_Avg;
//  unique_ptr<ActivationFunction> activation_func = make_unique<SigmoidFunction>();
//  unique_ptr<CostFunction> cost_func = make_unique<CrossEntropyCost>();
//  const MatrixSize fc_size = 100;
//  auto init_mode = Layer::InitMode_Random;
//  const double learning_rate = 0.01;
//  const double regularization = 0.0001;
//  const MatrixSize training_batch_size = 10;
//  const size_t epochs = 100;
//
BOOST_AUTO_TEST_CASE(LeNet1_Full_Test, * disabled())
{
  // reduce the test size to two labels to make it faster
  // BOOST_TEST_MESSAGE("*** Filtering test set...");
  // _mnist_test.filter(9, 10000, 1000); // only allow 0,1 images; 1000 count
  // BOOST_TEST_MESSAGE("*** Filtered test set: " << "\n" << _mnist_test);

  auto polling_mode = PollingLayer::PollMode_Max;
  unique_ptr<ActivationFunction> conv_activation_func = make_unique<SigmoidFunction>();
  unique_ptr<ActivationFunction> poll_activation_func = make_unique<SigmoidFunction>();
  unique_ptr<ActivationFunction> fc_activation_func = make_unique<SigmoidFunction>();
  unique_ptr<CostFunction> cost_func = make_unique<CrossEntropyCost>();
  const MatrixSize fc_size = 120;
  auto init_mode = Layer::InitMode_Random;
  const double learning_rate = 0.05;
  const double regularization = 0.0001;
  const MatrixSize training_batch_size = 10;
  const size_t epochs = 100;

  auto layers = ConvolutionalNetwork::create_lenet1(
      _mnist_test.get_image_rows(), // input_rows
      _mnist_test.get_image_cols(), // input_cols
      polling_mode,
      fc_size,
      _mnist_test.get_label_size(), // output_size
      conv_activation_func,
      poll_activation_func,
      fc_activation_func
  );
  YANN_CHECK(layers);

  auto nn = make_unique<Network>(std::move(layers));
  YANN_CHECK(nn);
  nn->set_cost_function(cost_func);
  nn->init(init_mode);

  // Trainer
  auto trainer = make_unique<Trainer>(
      make_unique<Updater_GradientDescent>(learning_rate, regularization));
  BOOST_CHECK(trainer);
  trainer->set_batch_progress_callback(batch_progress_callback);

  // print info
  BOOST_TEST_MESSAGE("*** Training against MNIST dataset with ");
  BOOST_TEST_MESSAGE(" CustomlNetwork: " << nn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);

  // train and test
  pair<double, Value> res = _mnist_test.train_and_test(
      *nn,
      *trainer,
      DataSource_Stochastic::Random,
      training_batch_size,
      epochs,
      100 // testing_batch_size
  );
  BOOST_TEST_MESSAGE("*** Success rate: " << (res.first * 100)
                     << "% Loss: " << res.second
                     << " after " << epochs << " epochs");
  BOOST_TEST_MESSAGE(" CustomlNetwork: " << nn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);
}

// The best result so far:
//
// Success rate for epoch 93: against training dataset: 96.4867% against test dataset: 96.14%
// Cost/loss per test for epoch 93: against training dataset: 0.229392 against test dataset: 0.256736
//
// Training time 35861.4 milliseconds
// Testing against training dataset time 17260.3 milliseconds
// Testing against test dataset time 2885.71 milliseconds
//
BOOST_AUTO_TEST_CASE(BoostedLeNet1_Full_Test, * disabled())
{
  // reduce the test size to two labels to make it faster
  // BOOST_TEST_MESSAGE("*** Filtering test set...");
  // _mnist_test.filter(9, 10000, 1000); // only allow 0,1 images; 1000 count
  // BOOST_TEST_MESSAGE("*** Filtered test set: " << "\n" << _mnist_test);

  auto polling_mode = PollingLayer::PollMode_Max;
  unique_ptr<ActivationFunction> conv_activation_func = make_unique<SigmoidFunction>();
  unique_ptr<ActivationFunction> poll_activation_func = make_unique<SigmoidFunction>();
  unique_ptr<ActivationFunction> fc_activation_func = make_unique<SigmoidFunction>();
  unique_ptr<CostFunction> cost_func = make_unique<CrossEntropyCost>();
  const MatrixSize paths_num = 2;
  const MatrixSize fc_size = 50;
  const auto init_mode = Layer::InitMode_Random;
  const double alpha = 0.5;
  const double beta = 0.9;
  const MatrixSize training_batch_size = 10;
  const size_t epochs = 100;

  auto layers = ConvolutionalNetwork::create_boosted_lenet1(
      paths_num,
      _mnist_test.get_image_rows(), // input_rows
      _mnist_test.get_image_cols(), // input_cols
      polling_mode,
      fc_size,
      _mnist_test.get_label_size(), // output_size
      conv_activation_func,
      poll_activation_func,
      fc_activation_func
  );
  YANN_CHECK(layers);

  auto nn = make_unique<Network>(std::move(layers));
  YANN_CHECK(nn);
  nn->set_cost_function(cost_func);
  nn->init(init_mode);

  // Trainer
  auto trainer = make_unique<Trainer>(
      make_unique<Updater_GradientDescentWithMomentum>(alpha, beta));
  BOOST_CHECK(trainer);
  trainer->set_batch_progress_callback(batch_progress_callback);

  // print info
  BOOST_TEST_MESSAGE("*** Training against MNIST dataset with ");
  BOOST_TEST_MESSAGE(" CustomlNetwork: " << nn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);

  // train and test
  pair<double, Value> res = _mnist_test.train_and_test(
      *nn,
      *trainer,
      DataSource_Stochastic::Random,
      training_batch_size,
      epochs,
      100 // testing_batch_size
  );
  BOOST_TEST_MESSAGE("*** Success rate: " << (res.first * 100) << "% Loss: " << res.second << " after " << epochs << " epochs");
  BOOST_TEST_MESSAGE(" CustomlNetwork: " << nn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);
}

BOOST_AUTO_TEST_CASE(LeNet5_Two_Labels_Test)
{
  // reduce the test size to two labels to make it faster
  BOOST_TEST_MESSAGE("*** Filtering test set...");
  _mnist_test.filter(1, 2000, 1000); // only allow 0,1 images; 1000 count
  BOOST_TEST_MESSAGE("*** Filtered test set: " << "\n" << _mnist_test);

  const double learning_rate = 0.1;
  const double regularization = 0.0;
  const MatrixSize training_batch_size = 10;
  const size_t epochs = 3;

  auto layers = ConvolutionalNetwork::create_lenet5(
      _mnist_test.get_image_rows(), // input_rows
      _mnist_test.get_image_cols(), // input_cols
      PollingLayer::PollMode_Avg,
      100, // fc1 size
      30, // fc2 size
      _mnist_test.get_label_size(), // output_size
      make_unique<SigmoidFunction>(), // conv activation
      make_unique<SigmoidFunction>(), // poll activation
      make_unique<SigmoidFunction>()  // fc activation
  );
  YANN_CHECK(layers);

  auto nn = make_unique<Network>(std::move(layers));
  YANN_CHECK(nn);
  nn->init(Layer::InitMode_Random, Layer::InitContext(12345));
  nn->set_cost_function(make_unique<CrossEntropyCost>());
  // nn->set_cost_function(make_unique<ExponentialCost>(2.0));

  // Trainer
  auto trainer = make_unique<Trainer>(
      make_unique<Updater_GradientDescent>(learning_rate, regularization));
  BOOST_CHECK(trainer);
  trainer->set_batch_progress_callback(batch_progress_callback);

  // print info
  BOOST_TEST_MESSAGE("*** Training against MNIST dataset with ");
  BOOST_TEST_MESSAGE(" CustomlNetwork: " << nn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);

  // train and test
  pair<double, Value> res = _mnist_test.train_and_test(
      *nn,
      *trainer,
      DataSource_Stochastic::Sequential,
      training_batch_size,
      epochs,
      100  // testing_batch_size
  );
  BOOST_TEST_MESSAGE("*** Success rate: " << (res.first * 100)
                     << "% Loss: " << res.second
                     << " after " << epochs << " epochs");
  BOOST_TEST_MESSAGE(" CustomlNetwork: " << nn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);

  // check
  BOOST_CHECK_GE(res.first, 0.95); // > 95%%
  BOOST_CHECK_LE(res.second, 0.5); // < 0.5 per test
}

// The best result so far:
//
// Success rate for epoch 50: against training dataset: 97.87% against test dataset: 97.61%
// Cost/loss per test for epoch 50: against training dataset: 0.144058 against test dataset: 0.154121
//
// Training time 39157.3 milliseconds
// Testing against training dataset time 17102.2 milliseconds
// Testing against test dataset time 2835.35 milliseconds
//
// unique_ptr<ActivationFunction> activation_func = make_unique<SigmoidFunction>();
// unique_ptr<CostFunction> cost_func = make_unique<CrossEntropyCost>();
// auto polling_mode = PollingLayer::PollMode_Max;
// const MatrixSize fc1_size = 120;
// const MatrixSize fc2_size = 84;
// auto init_mode = Layer::InitMode_Random;
// const double learning_rate = 0.01;
// const double regularization = 0.0001;
// const MatrixSize training_batch_size = 10;
//
BOOST_AUTO_TEST_CASE(LeNet5_Full_Test, * disabled())
{
  unique_ptr<ActivationFunction> conv_activation_func = make_unique<SigmoidFunction>();
  unique_ptr<ActivationFunction> poll_activation_func = make_unique<SigmoidFunction>();
  unique_ptr<ActivationFunction> fc_activation_func = make_unique<SigmoidFunction>();
  unique_ptr<CostFunction> cost_func = make_unique<CrossEntropyCost>();
  auto polling_mode = PollingLayer::PollMode_Max;
  const MatrixSize fc1_size = 120;
  const MatrixSize fc2_size = 84;
  auto init_mode = Layer::InitMode_Random;
  const double alpha = 0.01;
  const double beta = 0.9;
  const MatrixSize training_batch_size = 10;
  const size_t epochs = 50;

  auto layers = ConvolutionalNetwork::create_lenet5(
      _mnist_test.get_image_rows(), // input_rows
      _mnist_test.get_image_cols(), // input_cols
      polling_mode,
      fc1_size,
      fc2_size,
      _mnist_test.get_label_size(), // output_size
      conv_activation_func,
      poll_activation_func,
      fc_activation_func
  );
  YANN_CHECK(layers);

  auto nn = make_unique<Network>(std::move(layers));
  YANN_CHECK(nn);
  nn->init(init_mode);
  nn->set_cost_function(cost_func);

  // Trainer
  auto trainer = make_unique<Trainer>(
      make_unique<Updater_GradientDescentWithMomentum>(alpha, beta));
  BOOST_CHECK(trainer);
  trainer->set_batch_progress_callback(batch_progress_callback);

  // print info
  BOOST_TEST_MESSAGE("*** Training against MNIST dataset with ");
  BOOST_TEST_MESSAGE(" CustomlNetwork: " << nn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);

  // train and test
  pair<double, Value> res = _mnist_test.train_and_test(
      *nn,
      *trainer,
      DataSource_Stochastic::Random,
      training_batch_size,
      epochs,
      100 // testing_batch_size
  );
  BOOST_TEST_MESSAGE("*** Success rate: " << (res.first * 100)
                     << "% Loss: " << res.second
                     << " after " << epochs << " epochs");
  BOOST_TEST_MESSAGE(" CustomlNetwork: " << nn->get_info());
  BOOST_TEST_MESSAGE(" trainer: " << trainer->get_info());
  BOOST_TEST_MESSAGE(" epochs: " << epochs);
}

BOOST_AUTO_TEST_SUITE_END()


text:
/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
#include "unit_test.h"
#include "test_tools.h"
#include "BrokerFixture.h"
#include "qpid/client/QueueOptions.h"
#include "qpid/client/MessageListener.h"
#include "qpid/client/SubscriptionManager.h"
#include "qpid/client/AsyncSession.h"
#include "qpid/sys/Monitor.h"
#include "qpid/sys/Thread.h"
#include "qpid/sys/Runnable.h"
#include "qpid/sys/Time.h"
#include "qpid/client/Session.h"
#include "qpid/client/Message.h"
#include "qpid/framing/reply_exceptions.h"

#include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/format.hpp>

#include <vector>

namespace qpid {
namespace tests {

QPID_AUTO_TEST_SUITE(ClientSessionTest)

using namespace qpid::client;
using namespace qpid::framing;
using namespace qpid;
using qpid::sys::Monitor;
using qpid::sys::Thread;
using qpid::sys::TIME_SEC;
using qpid::broker::BrokerOptions;
using std::string;
using std::cout;
using std::endl;

struct DummyListener : public sys::Runnable, public MessageListener {
    std::vector<Message> messages;
    string name;
    uint expected;
    SubscriptionManager submgr;

    DummyListener(Session& session, const string& n, uint ex) :
        name(n), expected(ex), submgr(session) {}

    void run()
    {
        submgr.subscribe(*this, name);
        submgr.run();
    }

    void received(Message& msg)
    {
        messages.push_back(msg);
        if (--expected == 0) {
            submgr.stop();
        }
    }
};

struct SimpleListener : public MessageListener
{
    Monitor lock;
    std::vector<Message> messages;

    void received(Message& msg)
    {
        Monitor::ScopedLock l(lock);
        messages.push_back(msg);
        lock.notifyAll();
    }

    void waitFor(const uint n)
    {
        Monitor::ScopedLock l(lock);
        while (messages.size() < n) {
            lock.wait();
        }
    }
};

struct ClientSessionFixture : public SessionFixture
{
    ClientSessionFixture(const BrokerOptions& opts = BrokerOptions()) : SessionFixture(opts) {
        session.queueDeclare(arg::queue="my-queue");
    }
};

QPID_AUTO_TEST_CASE(testQueueQuery) {
    ClientSessionFixture fix;
    fix.session = fix.connection.newSession();
    fix.session.queueDeclare(arg::queue="q", arg::alternateExchange="amq.fanout",
                             arg::exclusive=true, arg::autoDelete=true);
    QueueQueryResult result = fix.session.queueQuery("q");
    BOOST_CHECK_EQUAL(false, result.getDurable());
    BOOST_CHECK_EQUAL(true, result.getExclusive());
    BOOST_CHECK_EQUAL("amq.fanout", result.getAlternateExchange());
}

QPID_AUTO_TEST_CASE(testDispatcher)
{
    ClientSessionFixture fix;
    fix.session =fix.connection.newSession();
    size_t count = 100;
    for (size_t i = 0; i < count; ++i)
        fix.session.messageTransfer(arg::content=Message(boost::lexical_cast<string>(i), "my-queue"));
    DummyListener listener(fix.session, "my-queue", count);
    listener.run();
    BOOST_CHECK_EQUAL(count, listener.messages.size());
    for (size_t i = 0; i < count; ++i)
        BOOST_CHECK_EQUAL(boost::lexical_cast<string>(i), listener.messages[i].getData());
}

QPID_AUTO_TEST_CASE(testDispatcherThread)
{
    ClientSessionFixture fix;
    fix.session =fix.connection.newSession();
    size_t count = 10;
    DummyListener listener(fix.session, "my-queue", count);
    sys::Thread t(listener);
    for (size_t i = 0; i < count; ++i) {
        fix.session.messageTransfer(arg::content=Message(boost::lexical_cast<string>(i), "my-queue"));
    }
    t.join();
    BOOST_CHECK_EQUAL(count, listener.messages.size());
    for (size_t i = 0; i < count; ++i)
        BOOST_CHECK_EQUAL(boost::lexical_cast<string>(i), listener.messages[i].getData());
}

QPID_AUTO_TEST_CASE(testUseSuspendedError)
{
    ClientSessionFixture fix;
    fix.session.timeout(60);
    fix.session.suspend();
    try {
        fix.session.exchangeQuery(arg::exchange="amq.fanout");
        BOOST_FAIL("Expected session suspended exception");
    } catch(const NotAttachedException&) {}
}

QPID_AUTO_TEST_CASE(testSendToSelf) {
    ClientSessionFixture fix;
    SimpleListener mylistener;
    fix.session.queueDeclare(arg::queue="myq", arg::exclusive=true, arg::autoDelete=true);
    fix.subs.subscribe(mylistener, "myq");
    sys::Thread runner(fix.subs);//start dispatcher thread
    string data("msg");
    Message msg(data, "myq");
    const uint count=10;
    for (uint i = 0; i < count; ++i) {
        fix.session.messageTransfer(arg::content=msg);
    }
    mylistener.waitFor(count);
    fix.subs.cancel("myq");
    fix.subs.stop();
    runner.join();
    fix.session.close();
    BOOST_CHECK_EQUAL(mylistener.messages.size(), count);
    for (uint j = 0; j < count; ++j) {
        BOOST_CHECK_EQUAL(mylistener.messages[j].getData(), data);
    }
}

QPID_AUTO_TEST_CASE(testLocalQueue) {
    ClientSessionFixture fix;
    fix.session.queueDeclare(arg::queue="lq", arg::exclusive=true, arg::autoDelete=true);
    LocalQueue lq;
    fix.subs.subscribe(lq, "lq", FlowControl(2, FlowControl::UNLIMITED, false));
    fix.session.messageTransfer(arg::content=Message("foo0", "lq"));
    fix.session.messageTransfer(arg::content=Message("foo1", "lq"));
    fix.session.messageTransfer(arg::content=Message("foo2", "lq"));
    BOOST_CHECK_EQUAL("foo0", lq.pop().getData());
    BOOST_CHECK_EQUAL("foo1", lq.pop().getData());
    BOOST_CHECK(lq.empty());    // Credit exhausted.
    fix.subs.getSubscription("lq").setFlowControl(FlowControl::unlimited());
    BOOST_CHECK_EQUAL("foo2", lq.pop().getData());
}

struct DelayedTransfer : sys::Runnable
{
    ClientSessionFixture& fixture;

    DelayedTransfer(ClientSessionFixture& f) : fixture(f) {}

    void run()
    {
        qpid::sys::sleep(1);
        fixture.session.messageTransfer(arg::content=Message("foo2", "getq"));
    }
};

QPID_AUTO_TEST_CASE(testGet) {
    ClientSessionFixture fix;
    fix.session.queueDeclare(arg::queue="getq", arg::exclusive=true, arg::autoDelete=true);
    fix.session.messageTransfer(arg::content=Message("foo0", "getq"));
    fix.session.messageTransfer(arg::content=Message("foo1", "getq"));
    Message got;
    BOOST_CHECK(fix.subs.get(got, "getq", TIME_SEC));
    BOOST_CHECK_EQUAL("foo0", got.getData());
    BOOST_CHECK(fix.subs.get(got, "getq", TIME_SEC));
    BOOST_CHECK_EQUAL("foo1", got.getData());
    BOOST_CHECK(!fix.subs.get(got, "getq"));
    DelayedTransfer sender(fix);
    Thread t(sender);
    //test timed get where message shows up after a short delay
    BOOST_CHECK(fix.subs.get(got, "getq", 5*TIME_SEC));
    BOOST_CHECK_EQUAL("foo2", got.getData());
    t.join();
}

QPID_AUTO_TEST_CASE(testOpenFailure) {
    BrokerFixture b;
    Connection c;
    string host("unknowable-host");
    try {
        c.open(host);
    } catch (const Exception&) {
        BOOST_CHECK(!c.isOpen());
    }
    b.open(c);
    BOOST_CHECK(c.isOpen());
    c.close();
    BOOST_CHECK(!c.isOpen());
}

QPID_AUTO_TEST_CASE(testPeriodicExpiration) {
    BrokerOptions opts;
    opts.queueCleanInterval = 1*TIME_SEC;
    opts.queueFlowStopRatio = 0;
    opts.queueFlowResumeRatio = 0;
    ClientSessionFixture fix(opts);
    FieldTable args;
    args.setInt("qpid.max_count",10);
    fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);

    for (uint i = 0; i < 10; i++) {
        Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue");
        if (i % 2) m.getDeliveryProperties().setTtl(500);
        fix.session.messageTransfer(arg::content=m);
    }

    BOOST_CHECK_EQUAL(fix.session.queueQuery(string("my-queue")).getMessageCount(), 10u);
    qpid::sys::sleep(2);
    BOOST_CHECK_EQUAL(fix.session.queueQuery(string("my-queue")).getMessageCount(), 5u);
    fix.session.messageTransfer(arg::content=Message("Message_11", "my-queue"));//ensure policy is also updated
}

QPID_AUTO_TEST_CASE(testExpirationOnPop) {
    ClientSessionFixture fix;
    fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true);

    for (uint i = 0; i < 10; i++) {
        Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue");
        if (i % 2) m.getDeliveryProperties().setTtl(200);
        fix.session.messageTransfer(arg::content=m);
    }

    qpid::sys::usleep(300* 1000);

    for (uint i = 0; i < 10; i++) {
        if (i % 2) continue;
        Message m;
        BOOST_CHECK(fix.subs.get(m, "my-queue", TIME_SEC));
        BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData());
    }
}

QPID_AUTO_TEST_CASE(testRelease) {
    ClientSessionFixture fix;

    const uint count=10;
    for (uint i = 0; i < count; i++) {
        Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue");
        fix.session.messageTransfer(arg::content=m);
    }

    fix.subs.setAutoStop(false);
    fix.subs.start();
    SubscriptionSettings settings;
    settings.autoAck = 0;

    SimpleListener l1;
    Subscription s1 = fix.subs.subscribe(l1, "my-queue", settings);
    l1.waitFor(count);
    s1.cancel();

    for (uint i = 0; i < count; i++) {
        BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), l1.messages[i].getData());
    }
    s1.release(s1.getUnaccepted());

    //check that released messages are redelivered
    settings.autoAck = 1;
    SimpleListener l2;
    Subscription s2 = fix.subs.subscribe(l2, "my-queue", settings);
    l2.waitFor(count);
    for (uint i = 0; i < count; i++) {
        BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), l2.messages[i].getData());
    }

    fix.subs.stop();
    fix.subs.wait();
    fix.session.close();
}

QPID_AUTO_TEST_CASE(testCompleteOnAccept) {
    ClientSessionFixture fix;
    const uint count = 8;
    const uint chunk = 4;
    for (uint i = 0; i < count; i++) {
        Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue");
        fix.session.messageTransfer(arg::content=m);
    }

    SubscriptionSettings settings;
    settings.autoAck = 0;
    settings.completionMode = COMPLETE_ON_ACCEPT;
    settings.flowControl = FlowControl::messageWindow(chunk);

    LocalQueue q;
    Subscription s = fix.subs.subscribe(q, "my-queue", settings);
    fix.session.messageFlush(arg::destination=s.getName());
    SequenceSet accepted;
    for (uint i = 0; i < chunk; i++) {
        Message m;
        BOOST_CHECK(q.get(m));
        BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData());
        accepted.add(m.getId());
    }
    Message m;
    BOOST_CHECK(!q.get(m));

    s.accept(accepted);
    //need to reallocate credit as we have flushed it all out
    s.setFlowControl(FlowControl::messageWindow(chunk));
    fix.session.messageFlush(arg::destination=s.getName());
    accepted.clear();

    for (uint i = chunk; i < count; i++) {
        Message m;
        BOOST_CHECK(q.get(m));
        BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData());
        accepted.add(m.getId());
    }
    fix.session.messageAccept(accepted);
}

namespace
{
struct Publisher : qpid::sys::Runnable
{
    AsyncSession session;
    Message message;
    uint count;
    Thread thread;

    Publisher(Connection& con, Message m, uint c) : session(con.newSession()), message(m), count(c) {}

    void start()
    {
        thread = Thread(*this);
    }

    void join()
    {
        thread.join();
    }

    void run()
    {
        for (uint i = 0; i < count; i++) {
            session.messageTransfer(arg::content=message);
        }
        session.sync();
        session.close();
    }
};
}

QPID_AUTO_TEST_CASE(testConcurrentSenders)
{
    //Ensure concurrent publishing sessions on a connection don't
    //cause assertions, deadlocks or other undesirables:
    BrokerFixture fix;
    Connection connection;
    ConnectionSettings settings;
    settings.maxFrameSize = 1024;
    settings.port = fix.broker->getPort(qpid::broker::Broker::TCP_TRANSPORT);
    connection.open(settings);
    AsyncSession session = connection.newSession();
    Message message(string(512, 'X'));

    boost::ptr_vector<Publisher> publishers;
    for (size_t i = 0; i < 5; i++) {
        publishers.push_back(new Publisher(connection, message, 100));
    }
    std::for_each(publishers.begin(), publishers.end(), boost::bind(&Publisher::start, _1));
    std::for_each(publishers.begin(), publishers.end(), boost::bind(&Publisher::join, _1));
    connection.close();
}

QPID_AUTO_TEST_CASE(testExclusiveSubscribe)
{
    ClientSessionFixture fix;
    fix.session.queueDeclare(arg::queue="myq", arg::exclusive=true, arg::autoDelete=true);
    SubscriptionSettings settings;
    settings.exclusive = true;
    LocalQueue q;
    fix.subs.subscribe(q, "myq", settings, "first");
    //attempt to create new subscriber should fail
    ScopedSuppressLogging sl;
    BOOST_CHECK_THROW(fix.subs.subscribe(q, "myq", "second"), ResourceLockedException);
    ;

}

QPID_AUTO_TEST_CASE(testExclusiveBinding) {
    FieldTable options;
    options.setString("qpid.exclusive-binding", "anything");
    ClientSessionFixture fix;
    fix.session.queueDeclare(arg::queue="queue-1", arg::exclusive=true, arg::autoDelete=true);
    fix.session.queueDeclare(arg::queue="queue-2", arg::exclusive=true, arg::autoDelete=true);
    fix.session.exchangeBind(arg::exchange="amq.direct", arg::queue="queue-1", arg::bindingKey="my-key", arg::arguments=options);
    fix.session.messageTransfer(arg::destination="amq.direct", arg::content=Message("message1", "my-key"));
    fix.session.exchangeBind(arg::exchange="amq.direct", arg::queue="queue-2", arg::bindingKey="my-key", arg::arguments=options);
    fix.session.messageTransfer(arg::destination="amq.direct", arg::content=Message("message2", "my-key"));

    Message got;
    BOOST_CHECK(fix.subs.get(got, "queue-1"));
    BOOST_CHECK_EQUAL("message1", got.getData());
    BOOST_CHECK(!fix.subs.get(got, "queue-1"));

    BOOST_CHECK(fix.subs.get(got, "queue-2"));
    BOOST_CHECK_EQUAL("message2", got.getData());
    BOOST_CHECK(!fix.subs.get(got, "queue-2"));
}

QPID_AUTO_TEST_CASE(testResubscribeWithLocalQueue) {
    ClientSessionFixture fix;
    fix.session.queueDeclare(arg::queue="some-queue", arg::exclusive=true, arg::autoDelete=true);
    LocalQueue p, q;
    fix.subs.subscribe(p, "some-queue");
    fix.subs.cancel("some-queue");
    fix.subs.subscribe(q, "some-queue");

    fix.session.messageTransfer(arg::content=Message("some-data", "some-queue"));
    fix.session.messageFlush(arg::destination="some-queue");

    Message got;
    BOOST_CHECK(!p.get(got));

    BOOST_CHECK(q.get(got));
    BOOST_CHECK_EQUAL("some-data", got.getData());
    BOOST_CHECK(!q.get(got));
}

QPID_AUTO_TEST_CASE(testReliableDispatch) {
    ClientSessionFixture fix;
    std::string queue("a-queue");
    fix.session.queueDeclare(arg::queue=queue, arg::autoDelete=true);

    ConnectionSettings settings;
    settings.port = fix.broker->getPort(qpid::broker::Broker::TCP_TRANSPORT);

    Connection c1;
    c1.open(settings);
    Session s1 = c1.newSession();
    SubscriptionManager subs1(s1);
    LocalQueue q1;
    subs1.subscribe(q1, queue, FlowControl());//first subscriber has no credit

    Connection c2;
    c2.open(settings);
    Session s2 = c2.newSession();
    SubscriptionManager subs2(s2);
    LocalQueue q2;
    subs2.subscribe(q2, queue);//second subscriber has credit

    fix.session.messageTransfer(arg::content=Message("my-message", queue));

    //check that the second consumer gets the message
    Message got;
    BOOST_CHECK(q2.get(got, 1*TIME_SEC));
    BOOST_CHECK_EQUAL("my-message", got.getData());

    c1.close();
    c2.close();
}

QPID_AUTO_TEST_CASE(testSessionCloseOnInvalidSession) {
    Session session;
    session.close();
}

QPID_AUTO_TEST_CASE(testLVQVariedSize) {
    ClientSessionFixture fix;
    std::string queue("my-lvq");
    QueueOptions args;
    args.setOrdering(LVQ_NO_BROWSE);
    fix.session.queueDeclare(arg::queue=queue, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);

    std::string key;
    args.getLVQKey(key);

    for (size_t i = 0; i < 10; i++) {
        std::ostringstream data;
        size_t size = 100 - ((i % 10) * 10);
        data << std::string(size, 'x');

        Message m(data.str(), queue);
        m.getHeaders().setString(key, "abc");
        fix.session.messageTransfer(arg::content=m);
    }
}

QPID_AUTO_TEST_CASE(testSessionManagerSetFlowControl) {
    ClientSessionFixture fix;
    std::string name("dummy");
    LocalQueue queue;
    SubscriptionSettings settings;
    settings.flowControl = FlowControl();
    fix.session.queueDeclare(arg::queue=name, arg::exclusive=true, arg::autoDelete=true);
    fix.subs.subscribe(queue, name, settings);
    fix.session.messageTransfer(arg::content=Message("my-message", name));
    fix.subs.setFlowControl(name, 1, FlowControl::UNLIMITED, false);
    fix.session.messageFlush(name);
    Message got;
    BOOST_CHECK(queue.get(got, 0));
    BOOST_CHECK_EQUAL("my-message", got.getData());
}

QPID_AUTO_TEST_CASE(testGetThenSubscribe) {
    ClientSessionFixture fix;
    std::string name("myqueue");
    fix.session.queueDeclare(arg::queue=name, arg::exclusive=true, arg::autoDelete=true);
    fix.session.messageTransfer(arg::content=Message("one", name));
    fix.session.messageTransfer(arg::content=Message("two", name));
    Message got;
    BOOST_CHECK(fix.subs.get(got, name));
    BOOST_CHECK_EQUAL("one", got.getData());

    DummyListener listener(fix.session, name, 1);
    listener.run();
    BOOST_CHECK_EQUAL(1u, listener.messages.size());
    if (!listener.messages.empty()) {
        BOOST_CHECK_EQUAL("two", listener.messages[0].getData());
    }
}

QPID_AUTO_TEST_CASE(testSessionIsValid) {
    ClientSessionFixture fix;
    BOOST_CHECK(fix.session.isValid());
    Session session;
    BOOST_CHECK(!session.isValid());
}

QPID_AUTO_TEST_CASE(testExpirationNotAltered) {
    ClientSessionFixture fix;
    fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true);

    Message m("my-message", "my-queue");
    m.getDeliveryProperties().setTtl(60000);
    m.getDeliveryProperties().setExpiration(12345);
    fix.session.messageTransfer(arg::content=m);
    Message got;
    BOOST_CHECK(fix.subs.get(got, "my-queue"));
    BOOST_CHECK_EQUAL("my-message", got.getData());
    BOOST_CHECK_EQUAL(12345u, got.getDeliveryProperties().getExpiration());
}

QPID_AUTO_TEST_CASE(testGetConnectionFromSession) {
    ClientSessionFixture fix;
    FieldTable options;
    options.setInt("no-local", 1);
    fix.session.queueDeclare(arg::queue="a", arg::exclusive=true, arg::autoDelete=true, arg::arguments=options);
    fix.session.queueDeclare(arg::queue="b", arg::exclusive=true, arg::autoDelete=true);

    Connection c = fix.session.getConnection();
    Session s = c.newSession();
    //If this new session was created as expected on the same connection as
    //fix.session, then the no-local behaviour means that queue 'a'
    //will not enqueue messages from this new session but queue 'b'
    //will.
    s.messageTransfer(arg::content=Message("a", "a"));
    s.messageTransfer(arg::content=Message("b", "b"));

    Message got;
    BOOST_CHECK(fix.subs.get(got, "b"));
    BOOST_CHECK_EQUAL("b", got.getData());
    BOOST_CHECK(!fix.subs.get(got, "a"));
}

QPID_AUTO_TEST_CASE(testQueueDeleted)
{
    ClientSessionFixture fix;
    fix.session.queueDeclare(arg::queue="my-queue");
    LocalQueue queue;
    fix.subs.subscribe(queue, "my-queue");

    ScopedSuppressLogging sl;
    fix.session.queueDelete(arg::queue="my-queue");
    BOOST_CHECK_THROW(queue.get(1*qpid::sys::TIME_SEC), qpid::framing::ResourceDeletedException);
}

QPID_AUTO_TEST_CASE(testTtl)
{
    const uint64_t ms = 1000ULL;           // convert sec to ms
    const uint64_t us = 1000ULL * 1000ULL; // convert sec to us

    ClientSessionFixture fix;
    fix.session.queueDeclare(arg::queue="ttl-test", arg::exclusive=true, arg::autoDelete=true);
    Message msg1 = Message("AAA", "ttl-test");
    uint64_t ttl = 2 * ms; // 2 sec
    msg1.getDeliveryProperties().setTtl(ttl);
    Connection c = fix.session.getConnection();
    Session s = c.newSession();
    s.messageTransfer(arg::content=msg1);

    Message msg2 = Message("BBB", "ttl-test");
    ttl = 10 * ms; // 10 sec
    msg2.getDeliveryProperties().setTtl(ttl);
    s.messageTransfer(arg::content=msg2);

    qpid::sys::usleep(5 * us); // 5 sec

    // Message "AAA" should be expired and never be delivered
    // Check "BBB" has ttl somewhere between 1 and 5 secs
    Message got;
    BOOST_CHECK(fix.subs.get(got, "ttl-test"));
    BOOST_CHECK_EQUAL("BBB", got.getData());
    BOOST_CHECK(got.getDeliveryProperties().getTtl() > 1 * ms);
    BOOST_CHECK(got.getDeliveryProperties().getTtl() < ttl - (5 * ms));
}

QPID_AUTO_TEST_SUITE_END()

}} // namespace qpid::tests