void interval_set_intersects_4_bicremental_types()
{
    typedef IntervalSet<T> IntervalSetT;
    typedef typename IntervalSetT::interval_type IntervalT;
    typedef typename IntervalSetT::key_type      KeyT;

    IntervalT between = I_D(3,5);

    IntervalSetT set_a;
    set_a.add(C_D(1,3)).add(I_I(6,11));
    //         (1   3)         [6    11]
    BOOST_CHECK( icl::intersects(set_a, MK_v(2)) );
    BOOST_CHECK( icl::intersects(set_a, MK_v(11)) );
    BOOST_CHECK( icl::disjoint(set_a, MK_v(3)) );
    BOOST_CHECK( icl::disjoint(set_a, MK_v(5)) );

    BOOST_CHECK( icl::intersects(set_a, C_D(1,3)) );
    BOOST_CHECK( icl::intersects(set_a, I_D(8,10)) );
    BOOST_CHECK( icl::disjoint(set_a, between) );
    BOOST_CHECK( icl::disjoint(set_a, I_I(0,1)) );

    IntervalSetT to_12 = IntervalSetT(I_D(0, 13));
    IntervalSetT complement_a = to_12 - set_a;
    BOOST_CHECK( icl::disjoint(set_a, complement_a) );
    BOOST_CHECK( icl::intersects(to_12, set_a) );

    BOOST_CHECK_EQUAL( icl::lower(set_a), icl::lower(*(set_a.begin())) );
    BOOST_CHECK_EQUAL( icl::lower(set_a), MK_v(1) );
    BOOST_CHECK_EQUAL( icl::upper(set_a), icl::upper(*(set_a.rbegin())) );
    BOOST_CHECK_EQUAL( icl::upper(set_a), MK_v(11) );
}
void interval_bitset_find_4_integral_types()
{
    typedef IntervalSet<T> IntervalSetT;
    typedef typename IntervalSetT::interval_type IntervalT;
    typedef typename IntervalSetT::bitset_type BitsT;

    IntervalT itv = I_D(3,5);

    IntervalSetT set_a;
    set_a.add(C_D(1,3)).add(I_I(6,11));

    typename IntervalSetT::const_iterator found = set_a.find(MK_v(6));

    BOOST_CHECK( (found->second).contains(6) );

    found = set_a.find(MK_v(5));
    BOOST_CHECK( found == set_a.end() );

    set_a.add(MK_v(64));
    found = set_a.find(MK_v(64));
    BOOST_CHECK( (found->second).contains(0) );

    set_a.add(MK_v(65));
    found = set_a.find(MK_v(65));
    BOOST_CHECK( (found->second).contains(1) );

    found = set_a.find(MK_v(66));
    BOOST_CHECK( found == set_a.end() );
}
void interval_set_mixed_contains_4_bicremental_types()
{
    typedef interval_set<T> IntervalSetT;
    typedef typename IntervalSetT::interval_type IntervalT;

    split_interval_set<T> split_set;
    split_set.add(I_D(0,4)).add(I_D(4,8));
    BOOST_CHECK_EQUAL( icl::contains(split_set, MK_v(4)), true );
    BOOST_CHECK_EQUAL( icl::contains(split_set, C_D(2,5)), true );

    interval_set<T> join_set_gap4(split_set.erase(MK_v(4)));
    BOOST_CHECK_EQUAL( icl::contains(join_set_gap4, MK_v(4)), false );
    BOOST_CHECK_EQUAL( icl::contains(join_set_gap4, C_D(2,5)), false );

    BOOST_CHECK_EQUAL( icl::contains(split_set, split_set), true );
    BOOST_CHECK_EQUAL( icl::contains(split_set, join_set_gap4), true );
    
}
void discrete_dynamic_interval_bounds_4_bicremental_types()
{
    typedef typename icl::interval<T>::type IntervalT;

    BOOST_CHECK( icl::bounds(I_I(2,4)) == interval_bounds::closed()     );
    BOOST_CHECK( icl::bounds(I_D(2,5)) == interval_bounds::right_open() );
    BOOST_CHECK( icl::bounds(C_I(1,4)) == interval_bounds::left_open()  );
    BOOST_CHECK( icl::bounds(C_D(1,5)) == interval_bounds::open()       );

}
void interval_set_infix_plus_overload_4_bicremental_types()
{
    typedef IntervalSet<T> IntervalSetT;
    typedef typename IntervalSetT::interval_type IntervalT;
    IntervalT itv = I_D(3,5);

    IntervalSetT set_a, set_b;
    set_a.add(C_D(1,3)).add(I_D(8,9)).add(I_I(6,11));
    set_b.add(I_D(0,9)).add(I_I(3,6)).add(I_D(5,7));

    BOOST_CHECK_EQUAL(set_a + set_b, set_b + set_a);
    // This checks all cases of is_interval_set_derivative<T>
    BOOST_CHECK_EQUAL(set_a + itv, itv + set_a);
    BOOST_CHECK_EQUAL(set_b + MK_v(4), MK_v(4) + set_b);
}
void interval_set_check_partial_invertive_monoid_plus_4_bicremental_types()
{
    typedef IntervalSet<T> IntervalSetT;

    IntervalSetT set_a, set_b, set_c;
    set_a.add(I_D(3,6)).add(I_I(5,7));
    set_b.add(C_D(1,3)).add(I_D(8,9));
    set_c.add(I_D(0,9)).add(I_I(3,6)).add(I_D(5,7));

    typename IntervalSetT::segment_type segm = I_D(6,9);
    T elem = make<T>(5);

    CHECK_PARTIAL_INVERTIVE_MONOID_INSTANCE_WRT(plus) (set_a, set_b, set_c, segm, elem);
    CHECK_PARTIAL_INVERTIVE_MONOID_INSTANCE_WRT(pipe) (set_a, set_b, set_c, segm, elem);
}
void interval_set_check_abelian_monoid_et_4_bicremental_types()
{
    typedef IntervalSet<T> IntervalSetT;

    IntervalSetT set_a, set_b, set_c;
    set_a.add(I_D(3,6)).add(I_I(5,7));
    set_b.add(C_D(1,3)).add(I_D(8,9));
    set_c.add(I_D(0,9)).add(I_I(3,6)).add(I_D(5,7));

    typename IntervalSetT::segment_type segm = I_D(6,9);
    T elem = make<T>(5);

    CHECK_ABELIAN_MONOID_INSTANCE_WRT(et)   (set_a, set_b, set_c, segm, elem);
    CHECK_ABELIAN_MONOID_INSTANCE_WRT(caret)(set_a, set_b, set_c, segm, elem);
}
void interval_set_check_abelian_group_plus_4_bicremental_types()
{
    typedef IntervalSet<T> IntervalSetT;

    IntervalSetT set_a, set_b, set_c;
    set_a.add(I_D(3,6)).add(I_I(5,7));
    set_b.add(C_D(1,3)).add(I_D(8,9));
    set_c.add(I_D(0,9)).add(I_I(3,6)).add(I_D(5,7));

    typename IntervalSetT::segment_type segm = I_D(6,9);
    T elem = make<T>(5);

    CHECK_ABELIAN_GROUP_INSTANCE_WRT(plus) (set_a, set_b, set_c, segm, elem);
    CHECK_ABELIAN_GROUP_INSTANCE_WRT(pipe) (set_a, set_b, set_c, segm, elem);
}
void interval_set_check_abelian_monoid_plus_4_bicremental_types()
{
    typedef IntervalSet<T> IntervalSetT;

    IntervalSetT set_a, set_b, set_c;
    set_a.add(I_D(3,6)).add(I_I(5,7));
    set_b.add(C_D(1,3)).add(I_D(8,9));
    set_c.add(I_D(0,9)).add(I_I(3,6)).add(I_D(5,7));

    typename IntervalSetT::segment_type inter_val1 = I_D(6,9);
    typename IntervalSetT::segment_type inter_val2 = I_I(5,5);

    CHECK_ABELIAN_MONOID_INSTANCE_WRT(plus) (set_a, set_b, set_c, inter_val1, inter_val2);
    CHECK_ABELIAN_MONOID_INSTANCE_WRT(pipe) (set_a, set_b, set_c, inter_val1, inter_val2);
}
void interval_set_range_4_discrete_types()
{
    typedef IntervalSet<T> IntervalSetT;
    typedef typename IntervalSetT::interval_type IntervalT;
    typedef typename IntervalSetT::key_type      KeyT;

    IntervalT between = I_D(3,5);

    IntervalSetT set_a;
    set_a.add(C_D(1,3)).add(I_I(6,11));
    //         (1   3)         [6    11]
    BOOST_CHECK_EQUAL( icl::first(set_a), icl::first(*(set_a.begin())) );
    BOOST_CHECK_EQUAL( icl::first(set_a), MK_v(2) );
    BOOST_CHECK_EQUAL( icl::last(set_a), icl::last(*(set_a.rbegin())) );
    BOOST_CHECK_EQUAL( icl::last(set_a), MK_v(11) );
}
void interval_set_find_4_bicremental_types()
{
    typedef IntervalSet<T> IntervalSetT;
    typedef typename IntervalSetT::interval_type IntervalT;
    typedef typename IntervalSetT::const_iterator c_iterator;

    IntervalT itv = I_D(3,5);

    IntervalSetT set_a;
    set_a.add(C_D(1,3)).add(I_I(6,11));

    typename IntervalSetT::const_iterator found = set_a.find(MK_v(6));

    BOOST_CHECK_EQUAL( *found, I_I(6,11) );

    found = set_a.find(MK_v(5));

    BOOST_CHECK_EQUAL( found == set_a.end(), true );

    c_iterator found1 = set_a.find(MK_v(6));
    c_iterator found2 = icl::find(set_a, MK_v(6));

    BOOST_CHECK      ( found1 == found2 );
    BOOST_CHECK_EQUAL( *found1, *found2 );
    BOOST_CHECK_EQUAL( *found1, I_I(6,11) );

    found1 = set_a.find(MK_v(5));

    BOOST_CHECK_EQUAL( found1 == set_a.end(), true );

    //LAW map c; key k: k in dom(c) => contains(c, *find(c, k))
    BOOST_CHECK( icl::contains(set_a, *icl::find(set_a, MK_v(2))) );
    BOOST_CHECK( icl::contains(set_a, *set_a.find(MK_v(11))) );

    BOOST_CHECK(  icl::contains(set_a, MK_v(2)) );
    BOOST_CHECK(  icl::contains(set_a, MK_v(10)) );
    BOOST_CHECK( !icl::contains(set_a, MK_v(1)) );
    BOOST_CHECK( !icl::contains(set_a, MK_v(3)) );

    BOOST_CHECK(  icl::intersects(set_a, MK_v(2)) );
    BOOST_CHECK(  icl::intersects(set_a, MK_v(10)) );
    BOOST_CHECK( !icl::intersects(set_a, MK_v(1)) );
    BOOST_CHECK( !icl::intersects(set_a, MK_v(3)) );
}
void interval_set_check_abelian_group_plus_prot_inv_4_bicremental_types()
{
    typedef IntervalSet<T> IntervalSetT;

    IntervalSetT set_a, set_b, set_c;
    set_a.add(I_D(3,6)).add(I_I(5,7));
    set_b.add(C_D(1,3)).add(I_D(8,9));
    set_c.add(I_D(0,9)).add(I_I(3,6)).add(I_D(5,7));

    typename IntervalSetT::segment_type segm = I_D(6,9);
    T elem = make<T>(5);

    CHECK_ABELIAN_MONOID_INSTANCE_WRT(plus) (set_a, set_b, set_c, segm, elem);
    CHECK_ABELIAN_MONOID_INSTANCE_WRT(pipe) (set_a, set_b, set_c, segm, elem);

#if !defined(_MSC_VER) || (_MSC_VER >= 1400) // 1310==MSVC-7.1  1400 ==MSVC-8.0
    CHECK_ABELIAN_GROUP_INSTANCE_WRT_EQUAL(plus) (is_distinct_equal, set_a, set_b, set_c, segm, elem);
    CHECK_ABELIAN_GROUP_INSTANCE_WRT_EQUAL(pipe) (is_distinct_equal, set_a, set_b, set_c, segm, elem);
#endif
}
void interval_set_move_4_discrete_types()
{
    typedef IntervalSet<T> IntervalSetT;
    typedef typename IntervalSetT::interval_type IntervalT;
    typedef std::vector<T> VectorT;

    //JODO static_cast fails for gcc compilers
    //IntervalSetT set_A(boost::move(static_cast<IntervalSetT&>(IntervalSetT(I_D(0,4)))));
    IntervalSetT set_A(boost::move(static_cast<IntervalSetT&>(IntervalSetT(I_D(0,4)).add(I_D(0,0)) )));
    IntervalSetT set_B(boost::move(static_cast<IntervalSetT&>(IntervalSetT(I_D(0,2)).add(I_D(2,4)).add(I_D(0,4)))));

    BOOST_CHECK( icl::is_element_equal(set_A, set_B) );
    BOOST_CHECK_EQUAL( set_A, join(set_B) );

    //JODO static_cast fails for gcc compilers
    //set_A = boost::move(static_cast<IntervalSetT&>(IntervalSetT(I_I(1,4))));
    set_A = boost::move(static_cast<IntervalSetT&>(IntervalSetT(I_I(1,4)).add(I_D(0,0))));
    set_B = boost::move(static_cast<IntervalSetT&>(IntervalSetT(C_I(0,2)).insert(I_D(3,5)).add(C_D(0,5))));

    BOOST_CHECK( icl::is_element_equal(set_A, set_B) );
    BOOST_CHECK_EQUAL( set_A, join(set_B) );
}
void distant_intervals_4_numeric_continuous_types()
{
    typedef  right_open_interval<T,Compare> L__D; // L__D for [..)
    typedef   left_open_interval<T,Compare> C__I; // C__I for (..]
    typedef  typename  icl::interval<T,Compare>::type IntervalT;

    BOOST_CHECK( is_interval<L__D>::value ); 
    BOOST_CHECK( has_difference<typename interval_traits<L__D>::domain_type>::value ); 
    BOOST_CHECK( is_continuous<typename interval_traits<L__D>::domain_type>::value  ); 
    BOOST_CHECK( (boost::is_same<typename interval_traits<L__D>::domain_type, T>::value)   ); 

    typedef typename difference_type_of<T>::type DiffT;

    test_inner_complement<T,Compare,L__D>(MK_I(L__D,0,4), MK_I(L__D,8,9));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,7,8), MK_I(L__D,2,3));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,2,4), MK_I(L__D,4,6));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,3,7), MK_I(L__D,5,8));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,7,9), MK_I(L__D,0,4));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,0,0), MK_I(L__D,0,0));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,1,0), MK_I(L__D,2,0));

    test_inner_complement<T,Compare,C__I>(MK_I(C__I,1,5), MK_I(C__I,4,9));
    test_inner_complement<T,Compare,C__I>(MK_I(C__I,4,6), MK_I(C__I,1,3));
    test_inner_complement<T,Compare,C__I>(MK_I(C__I,0,2), MK_I(C__I,4,6));
    test_inner_complement<T,Compare,C__I>(MK_I(C__I,0,2), MK_I(C__I,0,6));

    //--------------------------------------------------------------------------
#ifndef BOOST_ICL_USE_STATIC_BOUNDED_INTERVALS
    test_inner_complement<T,Compare,IntervalT>(I_D(0,4), I_D(8,9));
    test_inner_complement<T,Compare,IntervalT>(I_D(7,8), I_D(2,3));
    test_inner_complement<T,Compare,IntervalT>(I_D(2,4), I_D(4,6));
    test_inner_complement<T,Compare,IntervalT>(I_D(3,7), I_D(5,8));
    test_inner_complement<T,Compare,IntervalT>(I_D(7,9), I_D(0,4));
    test_inner_complement<T,Compare,IntervalT>(I_D(0,0), I_D(0,0));
    test_inner_complement<T,Compare,IntervalT>(I_D(1,0), I_D(2,0));

    test_inner_complement<T,Compare,IntervalT>(C_I(1,5), C_I(4,9));
    test_inner_complement<T,Compare,IntervalT>(C_I(4,6), C_I(1,3));
    test_inner_complement<T,Compare,IntervalT>(C_I(0,2), C_I(4,6));
    test_inner_complement<T,Compare,IntervalT>(C_I(0,2), C_I(0,6));

    test_inner_complement<T,Compare,IntervalT>(I_I(7,9), I_I(0,5));
    test_inner_complement<T,Compare,IntervalT>(I_I(0,9), I_I(2,5));

    test_inner_complement<T,Compare,IntervalT>(C_D(6,9), C_D(1,4));
    test_inner_complement<T,Compare,IntervalT>(C_D(1,3), C_D(1,4));
    test_inner_complement<T,Compare,IntervalT>(C_D(1,3), C_D(6,8));
    test_inner_complement<T,Compare,IntervalT>(C_D(1,7), C_D(1,6));
    test_inner_complement<T,Compare,IntervalT>(C_D(1,1), C_D(1,1));
    test_inner_complement<T,Compare,IntervalT>(C_D(3,0), C_D(4,0));
    test_inner_complement<T,Compare,IntervalT>(C_D(0,2), C_D(4,6));
    test_inner_complement<T,Compare,IntervalT>(C_D(0,2), C_D(0,6));
#endif //BOOST_ICL_USE_STATIC_BOUNDED_INTERVALS
}
void distant_intervals_4_discrete_types()
{
    typedef right_open_interval<T,Compare> L__D; // L__D for [..)
    typedef  left_open_interval<T,Compare> C__I; // C__I for (..]
    typedef    closed_interval<T,Compare> L__I; // L__I for [..]
    typedef      open_interval<T,Compare> C__D; // C__D for (..)
    typedef typename icl::interval<T,Compare>::type IntervalT;

    BOOST_CHECK( is_interval<L__D>::value ); 
    BOOST_CHECK( has_difference<typename interval_traits<L__D>::domain_type>::value ); 
    BOOST_CHECK( is_discrete<typename interval_traits<L__D>::domain_type>::value    ); 
    BOOST_CHECK( (boost::is_same<typename interval_traits<L__D>::domain_type, T>::value)   ); 

    typedef typename difference_type_of<T>::type DiffT;

    test_inner_complement<T,Compare,L__D>(MK_I(L__D,0,4), MK_I(L__D,8,9));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,7,8), MK_I(L__D,2,3));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,2,4), MK_I(L__D,4,6));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,3,7), MK_I(L__D,5,8));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,7,9), MK_I(L__D,0,4));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,0,0), MK_I(L__D,0,0));
    test_inner_complement<T,Compare,L__D>(MK_I(L__D,1,0), MK_I(L__D,2,0));

    test_inner_complement<T,Compare,C__I>(MK_I(C__I,1,5), MK_I(C__I,4,9));
    test_inner_complement<T,Compare,C__I>(MK_I(C__I,4,6), MK_I(C__I,1,3));
    test_inner_complement<T,Compare,C__I>(MK_I(C__I,0,2), MK_I(C__I,4,6));
    test_inner_complement<T,Compare,C__I>(MK_I(C__I,0,2), MK_I(C__I,0,6));

    test_inner_complement<T,Compare,L__I>(MK_I(L__I,7,9), MK_I(L__I,0,5));
    test_inner_complement<T,Compare,L__I>(MK_I(L__I,0,9), MK_I(L__I,2,5));

    test_inner_complement<T,Compare,C__D>(MK_I(C__D,6,9), MK_I(C__D,1,4));
    test_inner_complement<T,Compare,C__D>(MK_I(C__D,1,3), MK_I(C__D,1,4));
    test_inner_complement<T,Compare,C__D>(MK_I(C__D,1,3), MK_I(C__D,6,8));
    test_inner_complement<T,Compare,C__D>(MK_I(C__D,1,7), MK_I(C__D,1,6));
    test_inner_complement<T,Compare,C__D>(MK_I(C__D,1,1), MK_I(C__D,1,1));
    test_inner_complement<T,Compare,C__D>(MK_I(C__D,3,0), MK_I(C__D,4,0));
    test_inner_complement<T,Compare,C__D>(MK_I(C__D,0,2), MK_I(C__D,4,6));
    test_inner_complement<T,Compare,C__D>(MK_I(C__D,0,2), MK_I(C__D,0,6));

    //--------------------------------------------------------------------------
    test_inner_complement<T,Compare,IntervalT>(I_D(0,4), I_D(8,9));
    test_inner_complement<T,Compare,IntervalT>(I_D(7,8), I_D(2,3));
    test_inner_complement<T,Compare,IntervalT>(I_D(2,4), I_D(4,6));
    test_inner_complement<T,Compare,IntervalT>(I_D(3,7), I_D(5,8));
    test_inner_complement<T,Compare,IntervalT>(I_D(7,9), I_D(0,4));
    test_inner_complement<T,Compare,IntervalT>(I_D(0,0), I_D(0,0));
    test_inner_complement<T,Compare,IntervalT>(I_D(1,0), I_D(2,0));

    test_inner_complement<T,Compare,IntervalT>(C_I(1,5), C_I(4,9));
    test_inner_complement<T,Compare,IntervalT>(C_I(4,6), C_I(1,3));
    test_inner_complement<T,Compare,IntervalT>(C_I(0,2), C_I(4,6));
    test_inner_complement<T,Compare,IntervalT>(C_I(0,2), C_I(0,6));

    test_inner_complement<T,Compare,IntervalT>(I_I(7,9), I_I(0,5));
    test_inner_complement<T,Compare,IntervalT>(I_I(0,9), I_I(2,5));

    test_inner_complement<T,Compare,IntervalT>(C_D(6,9), C_D(1,4));
    test_inner_complement<T,Compare,IntervalT>(C_D(1,3), C_D(1,4));
    test_inner_complement<T,Compare,IntervalT>(C_D(1,3), C_D(6,8));
    test_inner_complement<T,Compare,IntervalT>(C_D(1,7), C_D(1,6));
    test_inner_complement<T,Compare,IntervalT>(C_D(1,1), C_D(1,1));
    test_inner_complement<T,Compare,IntervalT>(C_D(3,0), C_D(4,0));
    test_inner_complement<T,Compare,IntervalT>(C_D(0,2), C_D(4,6));
    test_inner_complement<T,Compare,IntervalT>(C_D(0,2), C_D(0,6));

}