diff --git a/include/boost/move/algo/detail/set_difference.hpp b/include/boost/move/algo/detail/set_difference.hpp new file mode 100644 index 0000000..51d0475 --- /dev/null +++ b/include/boost/move/algo/detail/set_difference.hpp @@ -0,0 +1,207 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2017-2017. +// 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) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_MOVE_SET_DIFFERENCE_HPP +#define BOOST_MOVE_SET_DIFFERENCE_HPP + +#include +#include +#include + +namespace boost { + +namespace move_detail{ + +template +OutputIt copy(InputIt first, InputIt last, OutputIt result) +{ + while (first != last) { + *result++ = *first; + ++result; + ++first; + } + return result; +} + +} //namespace move_detail{ + +namespace movelib { + +//Moves the elements from the sorted range [first1, last1) which are not found in the sorted +//range [first2, last2) to the range beginning at result. +//The resulting range is also sorted. Equivalent elements are treated individually, +//that is, if some element is found m times in [first1, last1) and n times in [first2, last2), +//it will be moved to result exactly max(m-n, 0) times. +//The resulting range cannot overlap with either of the input ranges. +template +OutputIt set_difference + (InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt result, Compare comp) +{ + while (first1 != last1) { + if (first2 == last2) + return boost::move_detail::copy(first1, last1, result); + + if (comp(*first1, *first2)) { + *result = *first1; + ++result; + ++first1; + } + else { + if (!comp(*first2, *first1)) { + ++first1; + } + ++first2; + } + } + return result; +} + +//Moves the elements from the sorted range [first1, last1) which are not found in the sorted +//range [first2, last2) to the range beginning at first1 (in place operation in range1). +//The resulting range is also sorted. Equivalent elements are treated individually, +//that is, if some element is found m times in [first1, last1) and n times in [first2, last2), +//it will be moved to result exactly max(m-n, 0) times. +template +InputOutputIt1 inplace_set_difference + (InputOutputIt1 first1, InputOutputIt1 last1, InputIt2 first2, InputIt2 last2, Compare comp ) +{ + while (first1 != last1) { + //Skip copying from range 1 if no element has to be skipped + if (first2 == last2){ + return last1; + } + else if (comp(*first1, *first2)){ + ++first1; + } + else{ + if (!comp(*first2, *first1)) { + InputOutputIt1 result = first1; + //An element from range 1 must be skipped, no longer an inplace operation + return boost::movelib::set_difference + ( boost::make_move_iterator(++first1) + , boost::make_move_iterator(last1) + , ++first2, last2, result, comp); + } + ++first2; + } + } + return first1; +} + +//Moves the elements from the sorted range [first1, last1) which are not found in the sorted +//range [first2, last2) to the range beginning at first1. +//The resulting range is also sorted. Equivalent elements from range 1 are moved past to end +//of the result, +//that is, if some element is found m times in [first1, last1) and n times in [first2, last2), +//it will be moved to result exactly max(m-n, 0) times. +//The resulting range cannot overlap with either of the input ranges. +template +OutputIt set_unique_difference + (ForwardIt1 first1, ForwardIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt result, Compare comp) +{ + while (first1 != last1) { + if (first2 == last2){ + //unique_copy-like sequence with forward iterators but don't write i + //to result before comparing as moving *i could alter the value in i. + ForwardIt1 i = first1; + while (++first1 != last1) { + if (comp(*i, *first1)) { + *result = *i; + ++result; + i = first1; + } + } + *result = *i; + ++result; + break; + } + + if (comp(*first1, *first2)) { + //Skip equivalent elements in range1 but don't write i + //to result before comparing as moving *i could alter the value in i. + ForwardIt1 i = first1; + while (++first1 != last1) { + if (comp(*i, *first1)) { + break; + } + } + *result = *i; + ++result; + } + else { + if (comp(*first2, *first1)) { + ++first2; + } + else{ + ++first1; + } + } + } + return result; +} + +//Moves the elements from the sorted range [first1, last1) which are not found in the sorted +//range [first2, last2) to the range beginning at first1 (in place operation in range1). +//The resulting range is also sorted. Equivalent elements are treated individually, +//that is, if some element is found m times in [first1, last1) and n times in [first2, last2), +//it will be moved to result exactly max(m-n, 0) times. +template +ForwardOutputIt1 inplace_set_unique_difference + (ForwardOutputIt1 first1, ForwardOutputIt1 last1, ForwardIt2 first2, ForwardIt2 last2, Compare comp ) +{ + while (first1 != last1) { + //Skip copying from range 1 if no element has to be skipped + if (first2 == last2){ + //unique-like algorithm for the remaining range 1 + ForwardOutputIt1 result = first1; + while (++first1 != last1) { + if (comp(*result, *first1) && ++result != first1) { + *result = boost::move(*first1); + } + } + return ++result; + } + else if (comp(*first2, *first1)) { + ++first2; + } + else if (comp(*first1, *first2)){ + //skip any adjacent equivalent elementin range 1 + ForwardOutputIt1 result = first1; + if (++first1 != last1 && !comp(*result, *first1)) { + //Some elements from range 1 must be skipped, no longer an inplace operation + while (++first1 != last1 && !comp(*result, *first1)){} + return boost::movelib::set_unique_difference + ( boost::make_move_iterator(first1) + , boost::make_move_iterator(last1) + , first2, last2, ++result, comp); + } + } + else{ + ForwardOutputIt1 result = first1; + //Some elements from range 1 must be skipped, no longer an inplace operation + while (++first1 != last1 && !comp(*result, *first1)){} + //An element from range 1 must be skipped, no longer an inplace operation + return boost::movelib::set_unique_difference + ( boost::make_move_iterator(first1) + , boost::make_move_iterator(last1) + , first2, last2, result, comp); + } + } + return first1; +} + + + +} //namespace movelib { +} //namespace boost { + +#endif //#define BOOST_MOVE_SET_DIFFERENCE_HPP diff --git a/proj/vc7ide/algo_test.vcproj b/proj/vc7ide/algo_test.vcproj new file mode 100644 index 0000000..e228f8f --- /dev/null +++ b/proj/vc7ide/algo_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/algo_test.cpp b/test/algo_test.cpp new file mode 100644 index 0000000..d4652e2 --- /dev/null +++ b/test/algo_test.cpp @@ -0,0 +1,953 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2017. +// 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) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include "order_type.hpp" +#include +#include +/* +/////////////////////////////////// +// +// set_difference +// +/////////////////////////////////// +void test_set_difference_normal() +{ + order_perf_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_perf_type range1[4]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 1u; + range1[1].val = 1u; + range1[2].key = 3u; + range1[2].val = 1u; + range1[3].key = 4u; + range1[3].val = 1u; + + order_perf_type out[20]; + out[2].key = 998; + out[2].val = 999; + boost::movelib::set_difference(range1, range1+4, range2, range2+10, out, order_type_less()); + BOOST_TEST(out[0].key == 1u); + BOOST_TEST(out[0].val == 1u); + BOOST_TEST(out[1].key == 3u); + BOOST_TEST(out[1].val == 1u); + BOOST_TEST(out[2].key == 998); + BOOST_TEST(out[2].val == 999); +} + +void test_set_difference_range1_repeated() +{ + order_perf_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_perf_type range1[4]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 2u; + range1[1].val = 1u; + range1[2].key = 4u; + range1[2].val = 1u; + range1[3].key = 6u; + range1[3].val = 1u; + + order_perf_type out[20]; + out[0].key = 998; + out[0].val = 999; + boost::movelib::set_difference(range1, range1+4, range2, range2+10, out, order_type_less()); + BOOST_TEST(out[0].key == 998); + BOOST_TEST(out[0].val == 999); +} + +void test_set_difference_range1_unique() +{ + order_perf_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_perf_type range1[4]; + range1[0].key = 1u; + range1[0].val = 1u; + range1[1].key = 3u; + range1[1].val = 1u; + range1[2].key = 5u; + range1[2].val = 1u; + range1[3].key = 7u; + range1[3].val = 1u; + + order_perf_type out[20]; + out[4].key = 998; + out[4].val = 999; + boost::movelib::set_difference(range1, range1+4, range2, range2+10, out, order_type_less()); + BOOST_TEST(out[0].key == 1u); + BOOST_TEST(out[0].val == 1u); + BOOST_TEST(out[1].key == 3u); + BOOST_TEST(out[1].val == 1u); + BOOST_TEST(out[2].key == 5u); + BOOST_TEST(out[3].val == 1u); + BOOST_TEST(out[3].key == 7u); + BOOST_TEST(out[3].val == 1u); + BOOST_TEST(out[4].key == 998); + BOOST_TEST(out[4].val == 999); +} +*/ + +/////////////////////////////////// +// +// set_difference +// +/////////////////////////////////// +void test_set_difference_normal() +{ + order_perf_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_perf_type range1[5]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 1u; + range1[1].val = 1u; + range1[2].key = 1u; + range1[2].val = 2u; + range1[3].key = 3u; + range1[3].val = 1u; + range1[4].key = 4u; + range1[4].val = 1u; + + order_perf_type out[20]; + out[3].key = 998; + out[3].val = 999; + order_perf_type *r = + boost::movelib::set_difference(range1, range1+5, range2, range2+10, out, order_type_less()); + BOOST_TEST(&out[3] == r); + BOOST_TEST(out[0].key == 1u); + BOOST_TEST(out[0].val == 1u); + BOOST_TEST(out[1].key == 1u); + BOOST_TEST(out[1].val == 2u); + BOOST_TEST(out[2].key == 3u); + BOOST_TEST(out[2].val == 1u); + BOOST_TEST(out[3].key == 998); + BOOST_TEST(out[3].val == 999); +} + +void test_set_difference_range1_repeated() +{ + order_perf_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_perf_type range1[5]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 2u; + range1[1].val = 1u; + range1[2].key = 2u; + range1[2].val = 2u; + range1[3].key = 4u; + range1[3].val = 1u; + range1[4].key = 6u; + range1[4].val = 1u; + + order_perf_type out[20]; + out[0].key = 998; + out[0].val = 999; + order_perf_type *r = + boost::movelib::set_difference(range1, range1+5, range2, range2+10, out, order_type_less()); + BOOST_TEST(&out[1] == r); + BOOST_TEST(out[0].key == 2); + BOOST_TEST(out[0].val == 2); +} + +void test_set_difference_range1_unique() +{ + order_perf_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_perf_type range1[5]; + range1[0].key = 1u; + range1[0].val = 1u; + range1[1].key = 3u; + range1[1].val = 1u; + range1[2].key = 5u; + range1[2].val = 1u; + range1[3].key = 7u; + range1[3].val = 1u; + range1[4].key = 7u; + range1[4].val = 2u; + + order_perf_type out[20]; + out[5].key = 998; + out[5].val = 999; + order_perf_type *r = + boost::movelib::set_difference(range1, range1+5, range2, range2+10, out, order_type_less()); + BOOST_TEST(&out[5] == r); + BOOST_TEST(out[0].key == 1u); + BOOST_TEST(out[0].val == 1u); + BOOST_TEST(out[1].key == 3u); + BOOST_TEST(out[1].val == 1u); + BOOST_TEST(out[2].key == 5u); + BOOST_TEST(out[2].val == 1u); + BOOST_TEST(out[3].key == 7u); + BOOST_TEST(out[3].val == 1u); + BOOST_TEST(out[4].key == 7u); + BOOST_TEST(out[4].val == 2u); + BOOST_TEST(out[5].key == 998); + BOOST_TEST(out[5].val == 999); +} + +/* +/////////////////////////////////// +// +// inplace_set_difference +// +/////////////////////////////////// +void test_inplace_set_difference_normal() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[4]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 1u; + range1[1].val = 1u; + range1[2].key = 3u; + range1[2].val = 1u; + range1[3].key = 4u; + range1[3].val = 1u; + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+2); + BOOST_TEST(range1[0].key == 1u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 3u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == order_move_type::moved_assign_mark); + BOOST_TEST(range1[2].val == order_move_type::moved_assign_mark); +} + +void test_inplace_set_difference_range1_repeated() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[5]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 2u; + range1[1].val = 1u; + range1[2].key = 4u; + range1[2].val = 1u; + range1[3].key = 6u; + range1[3].val = 1u; + range1[4].key = order_move_type::moved_assign_mark; + range1[4].val = order_move_type::moved_assign_mark; + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+0); + BOOST_TEST(range1[0].key == 0u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 2u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == 4u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[3].key == 6u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark); + BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark); +} + +void test_inplace_set_difference_range1_unique() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[5]; + range1[0].key = 1u; + range1[0].val = 1u; + range1[1].key = 3u; + range1[1].val = 1u; + range1[2].key = 5u; + range1[2].val = 1u; + range1[3].key = 7u; + range1[3].val = 1u; + range1[4].key = order_move_type::moved_assign_mark; + range1[4].val = order_move_type::moved_assign_mark; + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+4); + BOOST_TEST(range1[0].key == 1u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 3u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == 5u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[3].key == 7u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark); + BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark); +} + +void test_inplace_set_difference_range1_unique_long() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[11]; + for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){ + range1[i].key = i*2+1; + range1[i].val = 1u; + } + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+11, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+11); + for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){ + BOOST_TEST(range1[i].key == i*2+1); + BOOST_TEST(range1[i].val == 1u); + } +} + +void test_inplace_set_difference_range1_same_start() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[5]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 2u; + range1[1].val = 1u; + range1[2].key = 4u; + range1[2].val = 1u; + range1[3].key = 5u; + range1[3].val = 1u; + range1[4].key = 7u; + range1[4].val = 1u; + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+2); + BOOST_TEST(range1[0].key == 5u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 7u); + BOOST_TEST(range1[1].val == 1u); +} + +void test_inplace_set_difference_range1_same_end() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[5]; + range1[0].key = 1u; + range1[0].val = 1u; + range1[1].key = 3u; + range1[1].val = 1u; + range1[2].key = 4u; + range1[2].val = 1u; + range1[3].key = 6u; + range1[3].val = 1u; + range1[4].key = 8u; + range1[4].val = 1u; + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+2); + BOOST_TEST(range1[0].key == 1u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 3u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == 4u); + BOOST_TEST(range1[2].val == 1u); + BOOST_TEST(range1[3].key == 6u); + BOOST_TEST(range1[3].val == 1u); +} +*/ + +/////////////////////////////////// +// +// inplace_set_difference +// +/////////////////////////////////// +void test_inplace_set_difference_normal() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[4]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 1u; + range1[1].val = 1u; + range1[2].key = 3u; + range1[2].val = 1u; + range1[3].key = 4u; + range1[3].val = 1u; + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+2); + BOOST_TEST(range1[0].key == 1u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 3u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == order_move_type::moved_assign_mark); + BOOST_TEST(range1[2].val == order_move_type::moved_assign_mark); +} + +void test_inplace_set_difference_range1_repeated() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[5]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 2u; + range1[1].val = 1u; + range1[2].key = 4u; + range1[2].val = 1u; + range1[3].key = 6u; + range1[3].val = 1u; + range1[4].key = order_move_type::moved_assign_mark; + range1[4].val = order_move_type::moved_assign_mark; + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+0); + BOOST_TEST(range1[0].key == 0u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 2u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == 4u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[3].key == 6u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark); + BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark); +} + +void test_inplace_set_difference_range1_unique() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[5]; + range1[0].key = 1u; + range1[0].val = 1u; + range1[1].key = 3u; + range1[1].val = 1u; + range1[2].key = 5u; + range1[2].val = 1u; + range1[3].key = 7u; + range1[3].val = 1u; + range1[4].key = order_move_type::moved_assign_mark; + range1[4].val = order_move_type::moved_assign_mark; + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+4); + BOOST_TEST(range1[0].key == 1u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 3u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == 5u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[3].key == 7u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark); + BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark); +} + +void test_inplace_set_difference_range1_unique_long() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[11]; + for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){ + range1[i].key = i*2+1; + range1[i].val = 1u; + } + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+11, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+11); + for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){ + BOOST_TEST(range1[i].key == i*2+1); + BOOST_TEST(range1[i].val == 1u); + } +} + +void test_inplace_set_difference_range1_same_start() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[5]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 2u; + range1[1].val = 1u; + range1[2].key = 4u; + range1[2].val = 1u; + range1[3].key = 5u; + range1[3].val = 1u; + range1[4].key = 7u; + range1[4].val = 1u; + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+2); + BOOST_TEST(range1[0].key == 5u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 7u); + BOOST_TEST(range1[1].val == 1u); +} + +void test_inplace_set_difference_range1_same_end() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[5]; + range1[0].key = 1u; + range1[0].val = 1u; + range1[1].key = 3u; + range1[1].val = 1u; + range1[2].key = 4u; + range1[2].val = 1u; + range1[3].key = 6u; + range1[3].val = 1u; + range1[4].key = 8u; + range1[4].val = 1u; + + order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+2); + BOOST_TEST(range1[0].key == 1u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 3u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == 4u); + BOOST_TEST(range1[2].val == 1u); + BOOST_TEST(range1[3].key == 6u); + BOOST_TEST(range1[3].val == 1u); +} + + +/////////////////////////////////// +// +// set_unique_difference +// +/////////////////////////////////// +void test_set_unique_difference_normal() +{ + order_perf_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_perf_type range1[10]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 1u; + range1[1].val = 1u; + range1[2].key = 1u; + range1[2].val = 2u; + range1[3].key = 3u; + range1[3].val = 1u; + range1[4].key = 4u; + range1[4].val = 1u; + range1[5].key = 4u; + range1[5].val = 2u; + range1[6].key = 21u; + range1[6].val = 1u; + range1[7].key = 21u; + range1[7].val = 2u; + range1[8].key = 23u; + range1[8].val = 1u; + range1[9].key = 23u; + range1[9].val = 2u; + + order_perf_type out[20]; + out[4].key = 998; + out[4].val = 999; + order_perf_type * r = + boost::movelib::set_unique_difference(range1, range1+10, range2, range2+10, out, order_type_less()); + BOOST_TEST(&out[4] == r); + BOOST_TEST(out[0].key == 1u); + BOOST_TEST(out[0].val == 1u); + BOOST_TEST(out[1].key == 3u); + BOOST_TEST(out[1].val == 1u); + BOOST_TEST(out[2].key == 21u); + BOOST_TEST(out[2].val == 1u); + BOOST_TEST(out[3].key == 23u); + BOOST_TEST(out[3].val == 1u); + BOOST_TEST(out[4].key == 998); + BOOST_TEST(out[4].val == 999); +} + +void test_set_unique_difference_range1_repeated() +{ + order_perf_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_perf_type range1[11]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 0u; + range1[1].val = 2u; + range1[2].key = 0u; + range1[2].val = 2u; + range1[3].key = 2u; + range1[3].val = 1u; + range1[4].key = 2u; + range1[4].val = 2u; + range1[5].key = 4u; + range1[5].val = 1u; + range1[6].key = 6u; + range1[6].val = 1u; + range1[7].key = 6u; + range1[7].val = 2u; + range1[8].key = 6u; + range1[8].val = 3u; + range1[9].key = 6u; + range1[9].val = 4u; + range1[10].key = 6u; + range1[10].val = 5u; + + order_perf_type out[20]; + out[0].key = 998; + out[0].val = 999; + order_perf_type * r = + boost::movelib::set_unique_difference(range1, range1+11, range2, range2+10, out, order_type_less()); + BOOST_TEST(&out[0] == r); + BOOST_TEST(out[0].key == 998); + BOOST_TEST(out[0].val == 999); +} + +void test_set_unique_difference_range1_unique() +{ + order_perf_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_perf_type range1[7]; + range1[0].key = 1u; + range1[0].val = 1u; + range1[1].key = 3u; + range1[1].val = 1u; + range1[2].key = 3u; + range1[2].val = 2u; + range1[3].key = 5u; + range1[3].val = 1u; + range1[4].key = 7u; + range1[4].val = 1u; + range1[5].key = 7u; + range1[5].val = 2u; + range1[6].key = 7u; + range1[6].val = 3u; + + order_perf_type out[20]; + out[4].key = 998; + out[4].val = 999; + order_perf_type * r = + boost::movelib::set_unique_difference(range1, range1+7, range2, range2+10, out, order_type_less()); + BOOST_TEST(&out[4] == r); + BOOST_TEST(out[0].key == 1u); + BOOST_TEST(out[0].val == 1u); + BOOST_TEST(out[1].key == 3u); + BOOST_TEST(out[1].val == 1u); + BOOST_TEST(out[2].key == 5u); + BOOST_TEST(out[2].val == 1u); + BOOST_TEST(out[3].key == 7u); + BOOST_TEST(out[3].val == 1u); + BOOST_TEST(out[4].key == 998); + BOOST_TEST(out[4].val == 999); +} + +/////////////////////////////////// +// +// inplace_set_unique_difference +// +/////////////////////////////////// +void test_inplace_set_unique_difference_normal() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[4]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 1u; + range1[1].val = 1u; + range1[2].key = 3u; + range1[2].val = 1u; + range1[3].key = 4u; + range1[3].val = 1u; + + order_move_type *ret = boost::movelib::inplace_set_unique_difference(range1, range1+4, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+2); + BOOST_TEST(range1[0].key == 1u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 3u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == order_move_type::moved_assign_mark); + BOOST_TEST(range1[2].val == order_move_type::moved_assign_mark); +} + +void test_inplace_set_unique_difference_range1_repeated() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[5]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 2u; + range1[1].val = 1u; + range1[2].key = 4u; + range1[2].val = 1u; + range1[3].key = 6u; + range1[3].val = 1u; + range1[4].key = order_move_type::moved_assign_mark; + range1[4].val = order_move_type::moved_assign_mark; + + order_move_type *ret = boost::movelib::inplace_set_unique_difference(range1, range1+4, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+0); + BOOST_TEST(range1[0].key == 0u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 2u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == 4u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[3].key == 6u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark); + BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark); +} + +void test_inplace_set_unique_difference_range1_unique() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[9]; + range1[0].key = 1u; + range1[0].val = 1u; + range1[1].key = 1u; + range1[1].val = 2u; + range1[2].key = 3u; + range1[2].val = 1u; + range1[3].key = 3u; + range1[3].val = 2u; + range1[4].key = 5u; + range1[4].val = 1u; + range1[5].key = 7u; + range1[5].val = 1u; + range1[6].key = 7u; + range1[6].val = 2u; + range1[7].key = 7u; + range1[7].val = 3u; + range1[8].val = 3u; + range1[8].key = order_move_type::moved_assign_mark; + range1[8].val = order_move_type::moved_assign_mark; + + order_move_type *ret = + boost::movelib::inplace_set_unique_difference(range1, range1+8, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+4); + BOOST_TEST(range1[0].key == 1u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 3u); + BOOST_TEST(range1[1].val == 1u); + BOOST_TEST(range1[2].key == 5u); + BOOST_TEST(range1[3].val == 1u); + BOOST_TEST(range1[3].key == 7u); + BOOST_TEST(range1[3].val == 1u); +} + +void test_inplace_set_unique_difference_range1_unique_long() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[22]; + for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){ + range1[i].key = (i/2)*2+1; + range1[i].val = i%2; + } + + order_move_type *ret = + boost::movelib::inplace_set_unique_difference(range1, range1+22, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+11); + for(std::size_t i = 0; i != 11; ++i){ + BOOST_TEST(range1[i].key == i*2+1); + BOOST_TEST(range1[i].val == 0u); + } +} + +void test_inplace_set_unique_difference_range1_same_start() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[6]; + range1[0].key = 0u; + range1[0].val = 1u; + range1[1].key = 2u; + range1[1].val = 1u; + range1[2].key = 4u; + range1[2].val = 1u; + range1[3].key = 4u; + range1[3].val = 2u; + range1[4].key = 5u; + range1[4].val = 1u; + range1[5].key = 7u; + range1[5].val = 1u; + + order_move_type *ret = + boost::movelib::inplace_set_unique_difference(range1, range1+6, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+2); + BOOST_TEST(range1[0].key == 5u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 7u); + BOOST_TEST(range1[1].val == 1u); +} + +void test_inplace_set_unique_difference_range1_same_end() +{ + order_move_type range2[10]; + for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){ + range2[i].key = i*2; + range2[i].val = 0u; + } + + order_move_type range1[8]; + range1[0].key = 1u; + range1[0].val = 1u; + range1[1].key = 3u; + range1[1].val = 1u; + range1[2].key = 4u; + range1[2].val = 1u; + range1[3].key = 4u; + range1[3].val = 2u; + range1[4].key = 6u; + range1[4].val = 1u; + range1[5].key = 8u; + range1[5].val = 1u; + range1[6].key = 8u; + range1[6].val = 2u; + range1[7].key = 8u; + range1[7].val = 3u; + + order_move_type *ret = + boost::movelib::inplace_set_unique_difference(range1, range1+8, range2, range2+10, order_type_less()); + BOOST_TEST(ret == range1+2); + BOOST_TEST(range1[0].key == 1u); + BOOST_TEST(range1[0].val == 1u); + BOOST_TEST(range1[1].key == 3u); + BOOST_TEST(range1[1].val == 1u); +} + +int main() +{ + //set_difference + test_set_difference_normal(); + test_set_difference_range1_repeated(); + test_set_difference_range1_unique(); + //inplace_set_difference + test_inplace_set_difference_normal(); + test_inplace_set_difference_range1_repeated(); + test_inplace_set_difference_range1_unique(); + test_inplace_set_difference_range1_unique_long(); + test_inplace_set_difference_range1_same_start(); + test_inplace_set_difference_range1_same_end(); + //set_unique_difference + test_set_unique_difference_normal(); + test_set_unique_difference_range1_repeated(); + test_set_unique_difference_range1_unique(); + //inplace_set_unique_difference + test_inplace_set_unique_difference_normal(); + test_inplace_set_unique_difference_range1_repeated(); + test_inplace_set_unique_difference_range1_unique(); + test_inplace_set_unique_difference_range1_unique_long(); + test_inplace_set_unique_difference_range1_same_start(); + test_inplace_set_unique_difference_range1_same_end(); + + return boost::report_errors(); +} diff --git a/test/order_type.hpp b/test/order_type.hpp index 350312f..da4a90a 100644 --- a/test/order_type.hpp +++ b/test/order_type.hpp @@ -75,6 +75,9 @@ struct order_move_type std::size_t key; std::size_t val; + static const std::size_t moved_constr_mark = std::size_t(-1); + static const std::size_t moved_assign_mark = std::size_t(-2); + order_move_type() : key(0u), val(0u) {} @@ -104,8 +107,8 @@ struct order_move_type struct order_type_less { - template - bool operator()(const T &a, T const &b) const + template + bool operator()(const T &a, U const &b) const { return a < b; } };