1
0
forked from boostorg/move

ADd new set_difference algorithm and tests.

This commit is contained in:
Ion Gaztañaga
2017-12-26 21:55:54 +01:00
parent 5c463507db
commit 67d3dbe41b
4 changed files with 1299 additions and 2 deletions

View File

@ -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 <boost/move/algo/move.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/utility_core.hpp>
namespace boost {
namespace move_detail{
template<class InputIt, class OutputIt>
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<class InputIt1, class InputIt2,
class OutputIt, class Compare>
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<class InputOutputIt1, class InputIt2, class Compare>
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<class ForwardIt1, class InputIt2,
class OutputIt, class Compare>
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<class ForwardOutputIt1, class ForwardIt2, class Compare>
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

View File

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="algo_test"
ProjectGUID="{C8AD2618-79EB-8612-42FE-2A3AC9667A13}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/algo_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
DisableLanguageExtensions="FALSE"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/algo_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/algo_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/algo_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/algo_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{818563C3-6640-0A65-55CB-202E5BAD7FAF}">
<File
RelativePath="..\..\test\algo_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

953
test/algo_test.cpp Normal file
View File

@ -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 <boost/move/algo/detail/set_difference.hpp>
#include "order_type.hpp"
#include <boost/core/lightweight_test.hpp>
#include <cstddef>
/*
///////////////////////////////////
//
// 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();
}

View File

@ -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<class T>
bool operator()(const T &a, T const &b) const
template<class T, class U>
bool operator()(const T &a, U const &b) const
{ return a < b; }
};