basedOpinionated utility library |
git clone git://git.dimitrijedobrota.com/based.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |
commit | 4d38cd3cb45556a57d4343b9ea5df5938c296477 |
parent | cbb280b1215db7a68f492e9930191a594c40f905 |
author | Dimitrije Dobrota < mail@dimitrijedobrota.com > |
date | Tue, 6 May 2025 13:25:16 +0200 |
Get rid of the algorithms and examples
* No need to reinvent the wheel
M | CMakeLists.txt | | | --------- |
M | HACKING.md | | | ---- |
M | README.md | | | + - |
M | cmake/coverage.cmake | | | - |
M | cmake/lint-targets.cmake | | | - |
M | cmake/lint.cmake | | | + --------- |
D | example/CMakeLists.txt | | | ----------------------------- |
D | example/algorithm.cpp | | | ---------------------------------------------------------- |
D | example/instrumentation.cpp | | | ------------------------------------------------------------ |
D | example/list.cpp | | | ----------------------------------------------------- |
D | example/template.cpp | | | --------------------------------------------- |
D | example/type_traits.cpp | | | --------------------------------------------------------------------------------- |
D | include/based/algorithms/batch/for_each.hpp | | | --------------------------------- |
D | include/based/algorithms/bsearch/lower_bound.hpp | | | -------------------------------------------------- |
D | include/based/algorithms/bsearch/upper_bound.hpp | | | -------------------------------------------------- |
A | include/based/algorithms/max.hpp | | | +++++++++++++++++++++++++++++++++++++++ |
A | include/based/algorithms/min.hpp | | | ++++++++++++++++++++++++++++++++++++++ |
D | include/based/algorithms/minmax/max.hpp | | | --------------------------------------- |
D | include/based/algorithms/minmax/max_element.hpp | | | -------------------------------------- |
D | include/based/algorithms/minmax/min.hpp | | | -------------------------------------- |
D | include/based/algorithms/minmax/min_element.hpp | | | -------------------------------------- |
D | include/based/algorithms/minmax/minmax_element.hpp | | | ---------------------------------------------------------------------- |
D | include/based/algorithms/numeric/accumulate.hpp | | | -------------------------------------------------------------------------- |
D | include/based/algorithms/search/all.hpp | | | ------------------------ |
D | include/based/algorithms/search/count.hpp | | | -------------------------------------------------- |
D | include/based/algorithms/search/count_if.hpp | | | --------------------------------------------------- |
D | include/based/algorithms/search/count_if_not.hpp | | | --------------------------------------------------- |
D | include/based/algorithms/search/count_not.hpp | | | ----------------------------------------------------- |
D | include/based/algorithms/search/find.hpp | | | ------------------------------ |
D | include/based/algorithms/search/find_adjacent_mismatch.hpp | | | -------------------------------------------------------------------- |
D | include/based/algorithms/search/find_if.hpp | | | ----------------------------------------- |
D | include/based/algorithms/search/find_if_not.hpp | | | ----------------------------------------- |
D | include/based/algorithms/search/find_mismatch.hpp | | | --------------------------------------------------------------------------- |
D | include/based/algorithms/search/find_not.hpp | | | ------------------------------ |
D | include/based/algorithms/search/none.hpp | | | ------------------------ |
D | include/based/algorithms/search/not_all.hpp | | | ------------------------ |
D | include/based/algorithms/search/some.hpp | | | ------------------------ |
D | include/based/algorithms/sort/increasing_range.hpp | | | ------------------------------- |
D | include/based/algorithms/sort/partition_point.hpp | | | ---------------------------------------- |
D | include/based/algorithms/sort/partitioned.hpp | | | -------------------------- |
D | include/based/algorithms/sort/relation_preserving_range.hpp | | | -------------------------- |
D | include/based/algorithms/sort/strictly_increasing_range.hpp | | | ------------------------- |
M | test/CMakeLists.txt | | | ----------------------- |
D | test/source/algorithms/all_test.cpp | | | --------------------------------------------------------------- |
D | test/source/algorithms/count_if_not_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/count_if_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/count_not_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/count_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/find_adjacent_mismatch_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/find_if_not_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/find_if_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/find_mismatch_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/find_not_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/find_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/foreach_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/lower_bound_test.cpp | | | ------------------------------------------------ |
D | test/source/algorithms/max_element_test.cpp | | | --------------------------------------------------------------------------------- |
M | test/source/algorithms/max_test.cpp | | | + - |
D | test/source/algorithms/min_element_test.cpp | | | --------------------------------------------------------------------------------- |
M | test/source/algorithms/min_test.cpp | | | + - |
D | test/source/algorithms/minmax_element_test.cpp | | | --------------------------------------------------------------------------------- |
D | test/source/algorithms/none_test.cpp | | | ----------------------------------------------------------------- |
D | test/source/algorithms/not_all_test.cpp | | | ----------------------------------------------------------------- |
D | test/source/algorithms/partition_point_test.cpp | | | ------------------------------------------------ |
D | test/source/algorithms/partitioned_test.cpp | | | ----------------------------------------------------- |
D | test/source/algorithms/reduce_test.cpp | | | --------------------------------------------------------------------- |
D | test/source/algorithms/some_test.cpp | | | ----------------------------------------------------------------- |
D | test/source/algorithms/upper_bound_test.cpp | | | ------------------------------------------------ |
68 files changed, 81 insertions(+), 4510 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
@@ -37,15 +37,6 @@
if(NOT CMAKE_SKIP_INSTALL_RULES)
include(cmake/install-rules.cmake)
endif()
# ---- Examples ----
if(PROJECT_IS_TOP_LEVEL)
option(BUILD_EXAMPLES "Build examples tree." "${based_DEVELOPER_MODE}")
if(BUILD_EXAMPLES)
add_subdirectory(example)
endif()
endif()
# ---- Developer mode ----
if(NOT based_DEVELOPER_MODE)
diff --git a/ HACKING.md b/ HACKING.md
@@ -146,10 +146,6 @@
These targets run the clang-format tool on the codebase to check errors and to
fix them respectively. Customization available using the `FORMAT_PATTERNS` and
`FORMAT_COMMAND` cache variables.
#### `run-examples`
Runs all the examples created by the `add_example` command.
#### `spell-check` and `spell-fix`
These targets run the codespell tool on the codebase to check errors and to fix
diff --git a/ README.md b/ README.md
@@ -27,7 +27,7 @@
See the [`BUILDING`](BUILDING.md) document.
## Usage
> Please reference example folder for relevant usage examples.
> Please reference test folder for relevant usage examples.
## Version History
diff --git a/ cmake/coverage.cmake b/ cmake/coverage.cmake
@@ -11,7 +11,6 @@
set(
-o "${PROJECT_BINARY_DIR}/coverage.info"
-d "${PROJECT_BINARY_DIR}"
--include "${PROJECT_SOURCE_DIR}/*"
--exclude "${PROJECT_SOURCE_DIR}/example"
--capture
--all
CACHE STRING
diff --git a/ cmake/lint-targets.cmake b/ cmake/lint-targets.cmake
@@ -3,7 +3,6 @@
set(
source/*.cpp source/*.hpp
include/*.hpp
test/*.cpp test/*.hpp
example/*.cpp example/*.hpp
CACHE STRING
"; separated patterns relative to the project source dir to format"
)
diff --git a/ cmake/lint.cmake b/ cmake/lint.cmake
@@ -1,18 +1,10 @@
cmake_minimum_required(VERSION 3.14)
macro(default name)
if(NOT DEFINED "${name}")
set("${name}" "${ARGN}")
endif()
endmacro()
default(FORMAT_COMMAND clang-format)
defaul(FORMAT_COMMAND clang-format)
default(
PATTERNS
source/*.cpp source/*.hpp
include/*.hpp
test/*.cpp test/*.hpp
example/*.cpp example/*.hpp
)
default(FIX NO)
diff --git a/ example/CMakeLists.txt b/ example/CMakeLists.txt
@@ -1,29 +0,0 @@
cmake_minimum_required(VERSION 3.14)
project(basedExamples CXX)
include(../cmake/project-is-top-level.cmake)
include(../cmake/folders.cmake)
if(PROJECT_IS_TOP_LEVEL)
find_package(based REQUIRED)
endif()
add_custom_target(run-examples)
function(add_example NAME)
add_executable("${NAME}" "${NAME}.cpp")
target_link_libraries("${NAME}" PRIVATE based::based)
target_compile_features("${NAME}" PRIVATE cxx_std_20)
add_custom_target("run_${NAME}" COMMAND "${NAME}" VERBATIM)
add_dependencies("run_${NAME}" "${NAME}")
add_dependencies(run-examples "run_${NAME}")
endfunction()
add_example(instrumentation)
add_example(algorithm)
add_example(list)
add_example(type_traits)
add_example(template)
add_folders(Example)
diff --git a/ example/algorithm.cpp b/ example/algorithm.cpp
@@ -1,58 +0,0 @@
#include "based/algorithms/minmax/max_element.hpp"
#include "based/algorithms/minmax/min_element.hpp"
#include "based/algorithms/minmax/minmax_element.hpp"
#include "based/instrumentation/instrumented.hpp"
#include "based/instrumentation/timer.hpp"
based::instrumented_base::op::type::array<double>
based::instrumented_base::counts;
int main()
{
static constexpr std::size_t size = 16;
static constexpr std::size_t mega = 1024;
{
const based::timer time;
based::count_operations(
size,
size * mega * mega,
[](const auto& a, const auto& b)
{
based::min_element(a, b);
},
based::normalize_n
);
}
{
const based::timer time;
based::count_operations(
size,
size * mega * mega,
[](const auto& a, const auto& b)
{
based::max_element(a, b);
},
based::normalize_n
);
}
{
const based::timer time;
based::count_operations(
size,
size * mega * mega,
[](const auto& a, const auto& b)
{
based::minmax_element(a, b);
},
based::normalize_n
);
}
return 0;
}
diff --git a/ example/instrumentation.cpp b/ example/instrumentation.cpp
@@ -1,60 +0,0 @@
#include <algorithm>
#include <iostream>
#include "based/instrumentation/instrumented.hpp"
#include "based/instrumentation/registry.hpp"
#include "based/instrumentation/timer.hpp"
based::instrumented_base::op::type::array<double>
based::instrumented_base::counts;
class reg : public based::registry<reg>
{
public:
explicit reg(int val)
: m_val(val)
{
}
int m_val;
};
int main()
{
static constexpr std::size_t size = 16;
static constexpr std::size_t mega = 1024;
{
const based::timer time;
based::count_operations(
size,
size * mega * mega,
[](const auto& a, const auto& b)
{
std::sort(a, b);
},
based::normalize_nlogn
);
}
{
const based::timer time;
based::count_operations(
size,
size * mega * mega,
[](const auto& a, const auto& b)
{
std::stable_sort(a, b);
},
based::normalize_nlogn
);
}
const reg a(0);
const reg b(1);
const reg c(2);
std::cout << based::registry<reg>::count << '\n';
}
diff --git a/ example/list.cpp b/ example/list.cpp
@@ -1,53 +0,0 @@
#include <cstdint>
#include "based/list.hpp"
#include "based/instrumentation/instrumented.hpp"
based::instrumented_base::op::type::array<double>
based::instrumented_base::counts;
int main()
{
using instrumented = based::instrumented<double>;
using list_pool = based::list_pool<instrumented, std::uint8_t>;
using iter = list_pool::iterator;
static constexpr std::size_t iter_count = 0xFF;
auto pool = list_pool();
auto head = pool.node_empty();
for (std::size_t i = 0; i < iter_count; i++) {
head = pool.allocate(static_cast<double>(i), head);
}
for (auto it = iter(pool, head); it != iter(pool); ++it) {
std::cout << *it << " ";
}
std::cout << '\n';
based::free_list(pool, head);
auto queue = pool.queue_empty();
for (std::size_t i = 0; i < iter_count; i++) {
if (i % 2 == 0) {
queue = pool.push_front(queue, static_cast<double>(i));
} else {
queue = pool.push_back(queue, static_cast<double>(i));
}
if (i % 3 == 0) {
queue = pool.pop_front(queue);
}
}
for (auto it = iter(pool, queue.first); it != iter(pool); ++it) {
std::cout << *it << " ";
}
std::cout << '\n';
pool.free(queue);
return 0;
}
diff --git a/ example/template.cpp b/ example/template.cpp
@@ -1,45 +0,0 @@
#include <functional>
#include <iostream>
#include "based/functional/function.hpp"
#include "based/functional/overload.hpp"
int main()
{
{
const auto func = based::overload {
[](const int* integer)
{
std::cout << "i=" << *integer << '\n';
},
[](const double* dbl)
{
std::cout << "d=" << *dbl << '\n';
}
};
const int integer = 5;
func(&integer);
const double dbl = 7.3;
func(&dbl);
}
{
const based::function func = [](int val)
{
return val + 1;
};
std::cout << func(3) << '\n';
}
{
const std::function func = [](int val)
{
return val + 1;
};
std::cout << func(3) << '\n';
}
return 0;
}
diff --git a/ example/type_traits.cpp b/ example/type_traits.cpp
@@ -1,118 +0,0 @@
#include "based/concepts/procedure/function.hpp"
#include "based/concepts/procedure/procedure.hpp"
namespace
{
struct irregular
{
irregular() = default;
irregular(const irregular&) = delete;
irregular(irregular&&) = delete;
irregular& operator=(const irregular&) = delete;
irregular& operator=(irregular&&) = delete;
~irregular() = default;
};
template<typename T>
struct identity
{
T operator()(T val) { return val; }
};
template<typename T, typename U>
struct add
{
T operator()(const T& val1, const U& val2) { return val1 + val2; }
};
template<typename T>
struct mutate
{
T operator()(T* val) { return *val = 1; }
};
template<typename T, typename U>
T sub(T val1, U val2)
{
return val1 - val2;
}
} // namespace
int main()
{
using id = identity<double>;
using ii = identity<irregular>;
static_assert(based::Procedure<id, double, double>);
static_assert(!based::Procedure<ii, irregular>);
static_assert(based::RegularProcedure<id, double, double>);
static_assert(!based::RegularProcedure<ii, irregular>);
static_assert(based::FunctionalProcedure<id, double, double>);
static_assert(!based::FunctionalProcedure<ii, irregular>);
using ad = add<double, double>;
using ai = add<irregular, irregular>;
using aid = add<irregular, double>;
using adi = add<double, irregular>;
static_assert(based::Procedure<ad, double, double, double>);
static_assert(!based::Procedure<ai, irregular, irregular, irregular>);
static_assert(!based::Procedure<aid, irregular, irregular, double>);
static_assert(based::Procedure<adi, double, double, irregular>);
static_assert(based::RegularProcedure<ad, double, double, double>);
static_assert(!based::RegularProcedure<ai, irregular, irregular, irregular>);
static_assert(!based::RegularProcedure<aid, irregular, irregular, double>);
static_assert(!based::RegularProcedure<adi, double, double, irregular>);
static_assert(based::FunctionalProcedure<ad, double, double, double>);
static_assert(!based::
FunctionalProcedure<ai, irregular, irregular, irregular>);
static_assert(!based::FunctionalProcedure<aid, irregular, irregular, double>);
static_assert(!based::FunctionalProcedure<adi, double, double, irregular>);
using md = mutate<double>;
static_assert(based::Procedure<md, double, double*>);
static_assert(based::RegularProcedure<md, double, double*>);
static_assert(!based::FunctionalProcedure<md, double, double*>);
static_assert(based::RegularProcedure<
decltype(sub<double, double>),
double,
double,
double>);
static const auto func1 = [](double /* a */)
{
return 1;
};
static_assert(based::Procedure<decltype(func1), int, double>);
static_assert(based::RegularProcedure<decltype(func1), int, double>);
static_assert(based::FunctionalProcedure<decltype(func1), int, double>);
static const auto func2 = [](irregular /* a */)
{
return 1;
};
static_assert(!based::Procedure<decltype(func2), int, irregular>);
static_assert(!based::RegularProcedure<decltype(func2), int, irregular>);
static_assert(!based::FunctionalProcedure<decltype(func2), int, irregular>);
static const auto func3 = [](const irregular& /* a */)
{
return 1;
};
static_assert(based::Procedure<decltype(func3), int, irregular>);
static_assert(!based::RegularProcedure<decltype(func3), int, irregular>);
static_assert(!based::FunctionalProcedure<decltype(func3), int, irregular>);
return 0;
}
diff --git a/ include/based/algorithms/batch/for_each.hpp b/ include/based/algorithms/batch/for_each.hpp
@@ -1,33 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/procedure_iter.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I, IterUnaryProcedure<void, I> Proc>
Proc for_each(I first, I last, Proc proc)
{
// Precondition: readable_bounded_range(first, last);
while (first != last) {
proc(*first);
first++;
}
return proc;
}
template<ReadableIterator I, IterUnaryProcedure<void, I> Proc>
auto for_each_n(I first, iter_dist_t<I> size, Proc proc)
{
// Precondition: readable_weak_range(first, size);
while (size != 0) {
size--;
proc(*first);
first++;
}
return std::make_pair(proc, first);
}
} // namespace based
diff --git a/ include/based/algorithms/bsearch/lower_bound.hpp b/ include/based/algorithms/bsearch/lower_bound.hpp
@@ -1,50 +0,0 @@
#pragma once
#include <cassert>
#include "based/algorithms/sort/increasing_range.hpp"
#include "based/algorithms/sort/partition_point.hpp"
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
namespace based
{
namespace detail
{
template<typename T, Relation<T> Rel>
auto lower_bound_predicate(const T& goal, Rel rel)
{
return [=](const T& val)
{
return !rel(val, goal);
};
}
} // namespace detail
template<ReadableForwardIterator I, IterRelation<I> Rel>
I lower_bound_n(
I first, iter_dist_t<I> size, const iter_value_t<I>& val, Rel rel
)
{
// Precondition: weak_ordering(rel)
assert(increasing_range_n(first, size, rel));
return partition_point_n(
first, size, detail::lower_bound_predicate(val, rel)
);
}
template<ReadableForwardIterator I, IterRelation<I> Rel>
I lower_bound(I first, I last, const iter_value_t<I>& val, Rel rel)
{
// Precondition: weak_ordering(rel)
assert(increasing_range(first, last, rel));
return based::lower_bound_n(first, last - first, val, rel);
}
} // namespace based
diff --git a/ include/based/algorithms/bsearch/upper_bound.hpp b/ include/based/algorithms/bsearch/upper_bound.hpp
@@ -1,50 +0,0 @@
#pragma once
#include <cassert>
#include "based/algorithms/sort/increasing_range.hpp"
#include "based/algorithms/sort/partition_point.hpp"
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
namespace based
{
namespace detail
{
template<typename T, Relation<T> Rel>
auto upper_bound_predicate(const T& goal, Rel rel)
{
return [=](const T& val)
{
return rel(goal, val);
};
}
} // namespace detail
template<ReadableForwardIterator I, IterRelation<I> Rel>
I upper_bound_n(
I first, iter_dist_t<I> size, const iter_value_t<I>& val, Rel rel
)
{
// Precondition: weak_ordering(rel)
assert(increasing_range_n(first, size, rel));
return partition_point_n(
first, size, detail::upper_bound_predicate(val, rel)
);
}
template<ReadableForwardIterator I, IterRelation<I> Rel>
I upper_bound(I first, I last, const iter_value_t<I>& val, Rel rel)
{
// Precondition: weak_ordering(rel)
assert(increasing_range(first, last, rel));
return based::upper_bound_n(first, last - first, val, rel);
}
} // namespace based
diff --git a/ include/based/algorithms/max.hpp b/ include/based/algorithms/max.hpp
@@ -0,0 +1,39 @@
#pragma once
#include <functional>
#include "based/concepts/is/regular.hpp"
#include "based/concepts/is/same.hpp"
#include "based/concepts/procedure/procedure.hpp"
#include "based/type_traits/remove/cvref.hpp"
namespace based
{
namespace detail
{
template<typename P, typename Arg>
concept NoninputRelation = RegularProcedure<P, bool, Arg, Arg>;
} // namespace detail
// returns max element, second if equal
template<BareRegular T, BareRegular U, detail::NoninputRelation<T> Rel>
requires BareSameAs<T, U>
decltype(auto) max(T&& lhs, U&& rhs, Rel rel)
{
return rel(rhs, lhs) ? std::forward<T>(lhs) : std::forward<U>(rhs);
}
// returns max element, second if equal
template<BareRegular T, BareRegular U>
requires BareSameAs<T, U>
decltype(auto) max(T&& lhs, U&& rhs)
{
return based::max(
std::forward<T>(lhs), std::forward<U>(rhs), std::less<remove_cvref_t<T>>()
);
}
} // namespace based
diff --git a/ include/based/algorithms/min.hpp b/ include/based/algorithms/min.hpp
@@ -0,0 +1,38 @@
#pragma once
#include <functional>
#include "based/concepts/is/regular.hpp"
#include "based/concepts/is/same.hpp"
#include "based/concepts/procedure/procedure.hpp"
#include "based/type_traits/remove/cvref.hpp"
namespace based
{
namespace detail
{
template<typename P, typename Arg>
concept NoninputRelation = RegularProcedure<P, bool, Arg, Arg>;
} // namespace detail
template<BareRegular T, BareRegular U, detail::NoninputRelation<T> Rel>
requires BareSameAs<T, U>
decltype(auto) min(T&& lhs, U&& rhs, Rel rel)
{
return rel(rhs, lhs) ? std::forward<U>(rhs) : std::forward<T>(lhs);
}
// returns min element, first if equal
template<BareRegular T, BareRegular U>
requires BareSameAs<T, U>
decltype(auto) min(T&& lhs, U&& rhs)
{
return based::min(
std::forward<T>(lhs), std::forward<U>(rhs), std::less<remove_cvref_t<T>>()
);
}
} // namespace based
diff --git a/ include/based/algorithms/minmax/max.hpp b/ include/based/algorithms/minmax/max.hpp
@@ -1,39 +0,0 @@
#pragma once
#include <functional>
#include "based/concepts/is/regular.hpp"
#include "based/concepts/is/same.hpp"
#include "based/concepts/procedure/procedure.hpp"
#include "based/type_traits/remove/cvref.hpp"
namespace based
{
namespace detail
{
template<typename P, typename Arg>
concept NoninputRelation = RegularProcedure<P, bool, Arg, Arg>;
} // namespace detail
// returns max element, second if equal
template<BareRegular T, BareRegular U, detail::NoninputRelation<T> Rel>
requires BareSameAs<T, U>
decltype(auto) max(T&& lhs, U&& rhs, Rel rel)
{
return rel(rhs, lhs) ? std::forward<T>(lhs) : std::forward<U>(rhs);
}
// returns max element, second if equal
template<BareRegular T, BareRegular U>
requires BareSameAs<T, U>
decltype(auto) max(T&& lhs, U&& rhs)
{
return based::max(
std::forward<T>(lhs), std::forward<U>(rhs), std::less<remove_cvref_t<T>>()
);
}
} // namespace based
diff --git a/ include/based/algorithms/minmax/max_element.hpp b/ include/based/algorithms/minmax/max_element.hpp
@@ -1,38 +0,0 @@
#pragma once
#include <functional>
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
// return last max element
template<Iterator I, IterRelation<I> Rel>
I max_element(I first, I last, Rel rel)
{
if (first == last) {
return last;
}
I maxi = first;
first++;
while (first != last) {
if (!rel(*first, *maxi)) {
maxi = first;
}
first++;
}
return maxi;
}
// return last max element
template<Iterator I>
I max_element(I first, I last)
{
return based::max_element(first, last, std::less<iter_value_t<I>>());
}
} // namespace based
diff --git a/ include/based/algorithms/minmax/min.hpp b/ include/based/algorithms/minmax/min.hpp
@@ -1,38 +0,0 @@
#pragma once
#include <functional>
#include "based/concepts/is/regular.hpp"
#include "based/concepts/is/same.hpp"
#include "based/concepts/procedure/procedure.hpp"
#include "based/type_traits/remove/cvref.hpp"
namespace based
{
namespace detail
{
template<typename P, typename Arg>
concept NoninputRelation = RegularProcedure<P, bool, Arg, Arg>;
} // namespace detail
template<BareRegular T, BareRegular U, detail::NoninputRelation<T> Rel>
requires BareSameAs<T, U>
decltype(auto) min(T&& lhs, U&& rhs, Rel rel)
{
return rel(rhs, lhs) ? std::forward<U>(rhs) : std::forward<T>(lhs);
}
// returns min element, first if equal
template<BareRegular T, BareRegular U>
requires BareSameAs<T, U>
decltype(auto) min(T&& lhs, U&& rhs)
{
return based::min(
std::forward<T>(lhs), std::forward<U>(rhs), std::less<remove_cvref_t<T>>()
);
}
} // namespace based
diff --git a/ include/based/algorithms/minmax/min_element.hpp b/ include/based/algorithms/minmax/min_element.hpp
@@ -1,38 +0,0 @@
#pragma once
#include <functional>
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
// return first min element
template<Iterator I, IterRelation<I> Rel>
I min_element(I first, I last, Rel rel)
{
if (first == last) {
return last;
}
I mini = first;
first++;
while (first != last) {
if (rel(*first, *mini)) {
mini = first;
}
first++;
}
return mini;
}
// return first min element
template<Iterator I>
I min_element(I first, I last)
{
return based::min_element(first, last, std::less<iter_value_t<I>>());
}
} // namespace based
diff --git a/ include/based/algorithms/minmax/minmax_element.hpp b/ include/based/algorithms/minmax/minmax_element.hpp
@@ -1,70 +0,0 @@
#pragma once
#include <functional>
#include <iterator>
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
// return first min and last max element
template<Iterator I, IterRelation<I> Rel>
std::pair<I, I> minmax_element(I first, I last, Rel rel)
{
if (first == last) {
return {last, last};
}
I mini = first++;
if (first == last) {
return {mini, mini};
}
I maxi = first++;
if (rel(*maxi, *mini)) {
std::swap(mini, maxi);
}
I next = std::next(first);
while (first != last && next != last) {
I pmini = first;
I pmaxi = next;
if (rel(*pmaxi, *pmini)) {
std::swap(pmini, pmaxi);
}
if (rel(*pmini, *mini)) {
mini = pmini;
}
if (!rel(*pmaxi, *maxi)) {
maxi = pmaxi;
}
next++;
first = next;
next++;
}
if (first != last) {
if (rel(*first, *mini)) {
mini = first;
} else if (!rel(*first, *maxi)) {
maxi = first;
}
}
return {mini, maxi};
}
template<Iterator I>
std::pair<I, I> minmax_element(I first, I last)
{
return based::minmax_element(first, last, std::less<iter_value_t<I>>());
}
} // namespace based
diff --git a/ include/based/algorithms/numeric/accumulate.hpp b/ include/based/algorithms/numeric/accumulate.hpp
@@ -1,74 +0,0 @@
#pragma once
#include <cassert>
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/operation.hpp"
namespace based
{
template<Iterator I, UnaryFunction<void, I> F, BinaryOperation<ret_t<F, I>> Op>
auto accumulate_nonempty(I first, I last, Op opr, F fun)
{
assert(first != last);
// Precondition: bounded_range(first, last)
// Precondition: partially_associative(opr)
auto res = fun(first);
first++;
while (first != last) {
res = opr(res, fun(first));
first++;
}
return res;
}
template<Iterator I, UnaryFunction<void, I> F, BinaryOperation<ret_t<F, I>> Op>
auto accumulate(
I first,
I last,
Op opr,
F fun,
const decltype(accumulate_nonempty(first, last, opr, fun))& zero
)
{
// Precondition: bounded_range(first, last)
// Precondition: partially_associative(opr)
if (first == last) {
return zero;
}
return accumulate_nonempty(first, last, opr, fun);
}
template<Iterator I, UnaryFunction<void, I> F, BinaryOperation<ret_t<F, I>> Op>
auto accumulate_nonzero(
I first,
I last,
Op opr,
F fun,
const decltype(accumulate_nonempty(first, last, opr, fun))& zero
)
{
// Precondition: bounded_range(first, last)
// Precondition: partially_associative(opr)
ret_t<F, I> res;
do {
if (first == last) {
return zero;
}
res = fun(first);
first++;
} while (res == zero);
while (first != last) {
auto crnt = fun(first);
if (crnt != zero) {
res = opr(res, crnt);
}
first++;
}
return res;
}
} // namespace based
diff --git a/ include/based/algorithms/search/all.hpp b/ include/based/algorithms/search/all.hpp
@@ -1,24 +0,0 @@
#pragma once
#include "based/algorithms/search/find_if_not.hpp"
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
namespace based
{
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
bool all(I first, I last, Pred pred)
{
// Precondition: readable_bounded_range(first, last);
return find_if_not(first, last, pred) == last;
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
bool all_n(I first, iter_dist_t<I> size, Pred pred)
{
// Precondition: readable_weak_range(first, last);
return find_if_not_n(first, size, pred).second == 0;
}
} // namespace based
diff --git a/ include/based/algorithms/search/count.hpp b/ include/based/algorithms/search/count.hpp
@@ -1,50 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I, Iterator J>
J count(I first, I last, const iter_value_t<I>& val, J cnt)
{
// Precondition: readable_bounded_range(first, last);
while (first != last) {
if (*first == val) {
cnt++;
}
first++;
}
return cnt;
}
template<ReadableIterator I>
iter_dist_t<I> count(I first, I last, const iter_value_t<I>& val)
{
// Precondition: readable_bounded_range(first, last);
return count(first, last, val, iter_dist_t<I> {0});
}
template<ReadableIterator I, Iterator J>
auto count_n(I first, iter_dist_t<I> size, const iter_value_t<I>& val, J cnt)
{
// Precondition: readable_weak_range(first, size);
while (size != 0) {
if (*first == val) {
cnt++;
}
size--;
first++;
}
return std::make_pair(first, cnt);
}
template<ReadableIterator I>
auto count_n(I first, iter_dist_t<I> size, const iter_value_t<I>& val)
{
// Precondition: readable_weak_range(first, size);
return count_n(first, size, val, iter_dist_t<I> {0});
}
} // namespace based
diff --git a/ include/based/algorithms/search/count_if.hpp b/ include/based/algorithms/search/count_if.hpp
@@ -1,51 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I, IterUnaryPredicate<I> Pred, Iterator J>
J count_if(I first, I last, Pred pred, J cnt)
{
// Precondition: readable_bounded_range(first, last);
while (first != last) {
if (pred(*first)) {
cnt++;
}
first++;
}
return cnt;
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
iter_dist_t<I> count_if(I first, I last, Pred pred)
{
// Precondition: readable_bounded_range(first, last);
return count_if(first, last, pred, iter_dist_t<I> {0});
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred, Iterator J>
auto count_if_n(I first, iter_dist_t<I> size, Pred pred, J cnt)
{
// Precondition: readable_weak_range(first, size);
while (size != 0) {
if (pred(*first)) {
cnt++;
}
size--;
first++;
}
return std::make_pair(first, cnt);
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
auto count_if_n(I first, iter_dist_t<I> size, Pred pred)
{
// Precondition: readable_weak_range(first, size);
return count_if_n(first, size, pred, iter_dist_t<I> {0});
}
} // namespace based
diff --git a/ include/based/algorithms/search/count_if_not.hpp b/ include/based/algorithms/search/count_if_not.hpp
@@ -1,51 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I, IterUnaryPredicate<I> Pred, Iterator J>
J count_if_not(I first, I last, Pred pred, J cnt)
{
// Precondition: readable_bounded_range(first, last);
while (first != last) {
if (!pred(*first)) {
cnt++;
}
first++;
}
return cnt;
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
iter_dist_t<I> count_if_not(I first, I last, Pred pred)
{
// Precondition: readable_bounded_range(first, last);
return count_if_not(first, last, pred, iter_dist_t<I> {0});
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred, Iterator J>
auto count_if_not_n(I first, iter_dist_t<I> size, Pred pred, J cnt)
{
// Precondition: readable_weak_range(first, size);
while (size != 0) {
if (!pred(*first)) {
cnt++;
}
size--;
first++;
}
return std::make_pair(first, cnt);
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
auto count_if_not_n(I first, iter_dist_t<I> size, Pred pred)
{
// Precondition: readable_weak_range(first, size);
return count_if_not_n(first, size, pred, iter_dist_t<I> {0});
}
} // namespace based
diff --git a/ include/based/algorithms/search/count_not.hpp b/ include/based/algorithms/search/count_not.hpp
@@ -1,53 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I, Iterator J>
J count_not(I first, I last, const iter_value_t<I>& val, J cnt)
{
// Precondition: readable_bounded_range(first, last);
while (first != last) {
if (*first != val) {
cnt++;
}
first++;
}
return cnt;
}
template<ReadableIterator I>
iter_dist_t<I> count_not(I first, I last, const iter_value_t<I>& val)
{
// Precondition: readable_bounded_range(first, last);
return count_not(first, last, val, iter_dist_t<I> {0});
}
template<ReadableIterator I, Iterator J>
auto count_not_n(
I first, iter_dist_t<I> size, const iter_value_t<I>& val, J cnt
)
{
// Precondition: readable_weak_range(first, size);
while (size != 0) {
if (*first != val) {
cnt++;
}
size--;
first++;
}
return std::make_pair(first, cnt);
}
template<ReadableIterator I>
auto count_not_n(I first, iter_dist_t<I> size, const iter_value_t<I>& val)
{
// Precondition: readable_weak_range(first, size);
return count_not_n(first, size, val, iter_dist_t<I> {0});
}
} // namespace based
diff --git a/ include/based/algorithms/search/find.hpp b/ include/based/algorithms/search/find.hpp
@@ -1,30 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I>
I find(I first, I lst, const iter_value_t<I>& val)
{
// Precondition: readable_bounded_range(first, last);
while (first != lst && *first != val) {
first++;
}
return first;
}
template<ReadableIterator I>
auto find_n(I first, iter_dist_t<I> size, const iter_value_t<I>& val)
{
// Precondition: readable_weak_range(first, size);
while (size != 0 && *first != val) {
size--;
first++;
}
return std::make_pair(first, size);
}
} // namespace based
diff --git a/ include/based/algorithms/search/find_adjacent_mismatch.hpp b/ include/based/algorithms/search/find_adjacent_mismatch.hpp
@@ -1,68 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I, IterRelation<I> Rel>
I find_adjacent_mismatch(I first, I last, Rel rel)
{
// Precondition: readable_bounded_range(first, last)
if (first == last) {
return last;
}
auto crnt = *first;
first++;
while (first != last && rel(crnt, *first)) {
crnt = *first;
first++;
}
return first;
}
template<ReadableIterator I, IterRelation<I> Rel>
auto find_adjacent_mismatch_n(I first, iter_dist_t<I> size, Rel rel)
{
// Precondition: readable_bounded_range(first, last)
if (size == 0) {
return std::make_pair(first, size);
}
auto crnt = *first;
first++;
size--;
while (size != 0 && rel(crnt, *first)) {
crnt = *first;
size--;
first++;
}
return std::make_pair(first, size);
}
template<ReadableForwardIterator I, IterRelation<I> Rel>
I find_adjacent_mismatch_forward(I first, I last, Rel rel)
{
// Precondition: readable_bounded_range(first, last)
if (first == last) {
return last;
}
I tmp;
do {
tmp = first;
first++;
} while (first != last && rel(*tmp, *first));
return first;
}
} // namespace based
diff --git a/ include/based/algorithms/search/find_if.hpp b/ include/based/algorithms/search/find_if.hpp
@@ -1,41 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
I find_if(I first, I last, Pred pred)
{
// Precondition: readable_bounded_range(first, last);
while (first != last && !pred(*first)) {
first++;
}
return first;
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
auto find_if_n(I first, iter_dist_t<I> size, Pred pred)
{
// Precondition: readable_weak_range(first, size);
while (size != 0 && !pred(*first)) {
size--;
first++;
}
return std::make_pair(first, size);
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
I find_if_unguarded(I first, Pred pred)
{
// Precondition: readable_bounded_range(first, last) && some(f, d, p);
while (!pred(*first)) {
first++;
}
return first;
}
} // namespace based
diff --git a/ include/based/algorithms/search/find_if_not.hpp b/ include/based/algorithms/search/find_if_not.hpp
@@ -1,41 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
I find_if_not(I first, I last, Pred pred)
{
// Precondition: readable_bounded_range(first, last);
while (first != last && pred(*first)) {
first++;
}
return first;
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
auto find_if_not_n(I first, iter_dist_t<I> size, Pred pred)
{
// Precondition: readable_weak_range(first, size);
while (size != 0 && pred(*first)) {
size--;
first++;
}
return std::make_pair(first, size);
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
I find_if_not_unguarded(I first, Pred pred)
{
// Precondition: readable_bounded_range(first, last) && not_all(f, d, p);
while (pred(*first)) {
first++;
}
return first;
}
} // namespace based
diff --git a/ include/based/algorithms/search/find_mismatch.hpp b/ include/based/algorithms/search/find_mismatch.hpp
@@ -1,75 +0,0 @@
#pragma once
#include <tuple>
#include <utility>
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I0, ReadableIterator I1, IterRelation<I0> Rel>
requires BareSameAs<iter_value_t<I0>, iter_value_t<I1>>
auto find_mismatch(I0 first0, I0 last0, I1 first1, I1 last1, Rel rel)
{
// Precondition: readable_bounded_range(first0, last0)
// Precondition: readable_bounded_range(first1, last1)
while (first0 != last0 && first1 != last1 && rel(*first0, *first1)) {
first0++;
first1++;
}
return std::make_pair(first0, first1);
}
template<ReadableIterator I0, ReadableIterator I1, IterRelation<I0> Rel>
requires BareSameAs<iter_value_t<I0>, iter_value_t<I1>>
auto find_mismatch_n(
I0 first0, iter_dist_t<I0> size0, I1 first1, I1 last1, Rel rel
)
{
// Precondition: readable_weak_range(first0, size0)
// Precondition: readable_bounded_range(first1,last1)
while (size0 != 0 && first1 != last1 && rel(*first0, *first1)) {
first0++;
first1++;
size0--;
}
return std::make_tuple(first0, size0, first1);
}
template<ReadableIterator I0, ReadableIterator I1, IterRelation<I0> Rel>
requires BareSameAs<iter_value_t<I0>, iter_value_t<I1>>
auto find_mismatch_m(
I0 first0, I0 last0, I1 first1, iter_dist_t<I1> size1, Rel rel
)
{
// Precondition: readable_bounded_range(first0,last0)
// Precondition: readable_weak_range(first1, size1)
while (first0 != last0 && size1 != 0 && rel(*first0, *first1)) {
first0++;
first1++;
size1--;
}
return std::make_tuple(first0, first1, size1);
}
template<ReadableIterator I0, ReadableIterator I1, IterRelation<I0> Rel>
requires BareSameAs<iter_value_t<I0>, iter_value_t<I1>>
auto find_mismatch_n_m(
I0 first0, iter_dist_t<I0> size0, I1 first1, iter_dist_t<I1> size1, Rel rel
)
{
// Precondition: readable_weak_range(first0, size0)
// Precondition: readable_weak_range(first1, size1)
while (size0 != 0 && size1 != 0 && rel(*first0, *first1)) {
first0++;
first1++;
size0--;
size1--;
}
return std::make_tuple(first0, size0, first1, size1);
}
} // namespace based
diff --git a/ include/based/algorithms/search/find_not.hpp b/ include/based/algorithms/search/find_not.hpp
@@ -1,30 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/type_traits/iterator.hpp"
namespace based
{
template<ReadableIterator I>
I find_not(I first, I last, const iter_value_t<I>& val)
{
// Precondition: readable_bounded_range(first, last);
while (first != last && *first == val) {
first++;
}
return first;
}
template<ReadableIterator I>
auto find_not_n(I first, iter_dist_t<I> size, const iter_value_t<I>& val)
{
// Precondition: readable_weak_range(first, size);
while (size != 0 && *first == val) {
size--;
first++;
}
return std::make_pair(first, size);
}
} // namespace based
diff --git a/ include/based/algorithms/search/none.hpp b/ include/based/algorithms/search/none.hpp
@@ -1,24 +0,0 @@
#pragma once
#include "based/algorithms/search/find_if.hpp"
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
namespace based
{
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
bool none(I first, I last, Pred pred)
{
// Precondition: readable_bounded_range(first, last);
return find_if(first, last, pred) == last;
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
bool none_n(I first, iter_dist_t<I> size, Pred pred)
{
// Precondition: readable_weak_range(first, size);
return find_if_n(first, size, pred).second == 0;
}
} // namespace based
diff --git a/ include/based/algorithms/search/not_all.hpp b/ include/based/algorithms/search/not_all.hpp
@@ -1,24 +0,0 @@
#pragma once
#include "based/algorithms/search/find_if_not.hpp"
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
namespace based
{
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
bool not_all(I first, I last, Pred pred)
{
// Precondition: readable_bounded_range(first, last);
return first == last || find_if_not(first, last, pred) != last;
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
bool not_all_n(I first, iter_dist_t<I> size, Pred pred)
{
// Precondition: readable_weak_range(first, size);
return size == 0 || find_if_not_n(first, size, pred).second != 0;
}
} // namespace based
diff --git a/ include/based/algorithms/search/some.hpp b/ include/based/algorithms/search/some.hpp
@@ -1,24 +0,0 @@
#pragma once
#include "based/algorithms/search/find_if.hpp"
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
namespace based
{
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
bool some(I first, I last, Pred pred)
{
// Precondition: readable_bounded_range(first, last);
return find_if(first, last, pred) != last;
}
template<ReadableIterator I, IterUnaryPredicate<I> Pred>
bool some_n(I first, iter_dist_t<I> size, Pred pred)
{
// Precondition: readable_weak_range(first, size);
return find_if_n(first, size, pred).second != 0;
}
} // namespace based
diff --git a/ include/based/algorithms/sort/increasing_range.hpp b/ include/based/algorithms/sort/increasing_range.hpp
@@ -1,31 +0,0 @@
#pragma once
#include "based/algorithms/sort/relation_preserving_range.hpp"
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
#include "based/functional/predicate.hpp"
namespace based
{
template<ReadableIterator I, IterRelation<I> Rel>
bool increasing_range(I first, I last, Rel rel)
{
// Precondition: readable_bounded_range(first, last)
// Precondition: weak_ordering(rel);
return relation_preserving_range(
first, last, complement_of_converse<iter_value_t<I>>(rel)
);
}
template<ReadableIterator I, IterRelation<I> Rel>
bool increasing_range_n(I first, iter_dist_t<I> size, Rel rel)
{
// Precondition: readable_bounded_range(first, size)
// Precondition: weak_ordering(rel);
return relation_preserving_range_n(
first, size, complement_of_converse<iter_value_t<I>>(rel)
);
}
} // namespace based
diff --git a/ include/based/algorithms/sort/partition_point.hpp b/ include/based/algorithms/sort/partition_point.hpp
@@ -1,40 +0,0 @@
#pragma once
#include <cassert>
#include "based/algorithms/sort/partitioned.hpp"
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
namespace based
{
template<ReadableForwardIterator I, IterUnaryPredicate<I> Pred>
I partition_point_n(I first, iter_dist_t<I> size, Pred pred)
{
// Precondition: readable_bounded_range(first, size)
assert(partitioned_n(first, size, pred));
while (size != 0) {
const auto hlf = size / 2;
I mid = first + hlf;
if (pred(*mid)) {
size = hlf;
} else {
size -= hlf + 1;
first = mid + 1;
}
}
return first;
}
template<ReadableForwardIterator I, IterUnaryPredicate<I> Pred>
I partition_point(I first, I last, Pred pred)
{
// Precondition: readable_bounded_range(first, last)
assert(partitioned(first, last, pred));
return partition_point_n(first, last - first, pred);
}
} // namespace based
diff --git a/ include/based/algorithms/sort/partitioned.hpp b/ include/based/algorithms/sort/partitioned.hpp
@@ -1,26 +0,0 @@
#pragma once
#include "based/algorithms/search/find_if.hpp"
#include "based/algorithms/search/find_if_not.hpp"
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
namespace based
{
template<ReadableForwardIterator I, IterUnaryPredicate<I> Pred>
bool partitioned_n(I first, iter_dist_t<I> size, Pred pred)
{
// Precondition: readable_bounded_range(first, size)
std::tie(first, size) = find_if_n(first, size, pred);
return find_if_not_n(first, size, pred).second == 0;
}
template<ReadableForwardIterator I, IterUnaryPredicate<I> Pred>
bool partitioned(I first, I last, Pred pred)
{
// Precondition: readable_bounded_range(first, last)
return find_if_not(find_if(first, last, pred), last, pred) == last;
}
} // namespace based
diff --git a/ include/based/algorithms/sort/relation_preserving_range.hpp b/ include/based/algorithms/sort/relation_preserving_range.hpp
@@ -1,26 +0,0 @@
#pragma once
#include "based/algorithms/search/find_adjacent_mismatch.hpp"
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
namespace based
{
template<ReadableIterator I, IterRelation<I> Rel>
bool relation_preserving_range(I first, I last, Rel rel)
{
// Precondition: readable_bounded_range(first, last)
// Precondition: weak_ordering(rel);
return find_adjacent_mismatch(first, last, rel) == last;
}
template<ReadableIterator I, IterRelation<I> Rel>
bool relation_preserving_range_n(I first, iter_dist_t<I> size, Rel rel)
{
// Precondition: readable_bounded_range(first, size)
// Precondition: weak_ordering(rel);
return find_adjacent_mismatch_n(first, size, rel).second == 0;
}
} // namespace based
diff --git a/ include/based/algorithms/sort/strictly_increasing_range.hpp b/ include/based/algorithms/sort/strictly_increasing_range.hpp
@@ -1,25 +0,0 @@
#pragma once
#include "based/concepts/iterator.hpp"
#include "based/concepts/procedure/predicate_iter.hpp"
namespace based
{
template<ReadableIterator I, IterRelation<I> Rel>
bool strictly_increasing_range(I first, I last, Rel rel)
{
// Precondition: readable_bounded_range(first, last)
// Precondition: weak_ordering(rel);
return relation_preserving_range(first, last, rel);
}
template<ReadableIterator I, IterRelation<I> Rel>
bool strictly_increasing_range_n(I first, iter_dist_t<I> size, Rel rel)
{
// Precondition: readable_bounded_range(first, size)
// Precondition: weak_ordering(rel);
return relation_preserving_range_n(first, size, rel);
}
} // namespace based
diff --git a/ test/CMakeLists.txt b/ test/CMakeLists.txt
@@ -42,31 +42,8 @@
add_test(concepts callable_test)
## ----- Algorithm -----
add_test(algorithms all_test)
add_test(algorithms count_if_not_test)
add_test(algorithms count_if_test)
add_test(algorithms count_not_test)
add_test(algorithms count_test)
add_test(algorithms find_adjacent_mismatch_test)
add_test(algorithms find_if_not_test)
add_test(algorithms find_if_test)
add_test(algorithms find_mismatch_test)
add_test(algorithms find_not_test)
add_test(algorithms find_test)
add_test(algorithms foreach_test)
add_test(algorithms lower_bound_test)
add_test(algorithms max_element_test)
add_test(algorithms max_test)
add_test(algorithms min_element_test)
add_test(algorithms minmax_element_test)
add_test(algorithms min_test)
add_test(algorithms none_test)
add_test(algorithms not_all_test)
add_test(algorithms partitioned_test)
add_test(algorithms partition_point_test)
add_test(algorithms reduce_test)
add_test(algorithms some_test)
add_test(algorithms upper_bound_test)
## ----- Utility -----
diff --git a/ test/source/algorithms/all_test.cpp b/ test/source/algorithms/all_test.cpp
@@ -1,63 +0,0 @@
#include <array>
#include "based/algorithms/search/all.hpp"
#include <catch2/catch_test_macros.hpp>
struct predicate
{
int goal;
explicit predicate(int init)
: goal(init)
{
}
auto operator()(int n) const { return n == goal; }
};
TEST_CASE("all(empty)", "[algorithm/all]")
{
const std::array<int, 0> arr = {};
REQUIRE(based::all(std::begin(arr), std::end(arr), predicate {0}));
}
TEST_CASE("all(homogeneous)", "[algorithm/all]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
REQUIRE(based::all(std::begin(arr), std::end(arr), predicate {1}));
REQUIRE(!based::all(std::begin(arr), std::end(arr), predicate {2}));
}
TEST_CASE("all(non homogenous)", "[algorithm/all]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
REQUIRE(!based::all(std::begin(arr), std::end(arr), predicate {1}));
REQUIRE(!based::all(std::begin(arr), std::end(arr), predicate {2}));
}
TEST_CASE("all_n(empty)", "[algorithm/all_n]")
{
const std::array<int, 0> arr = {};
REQUIRE(based::all_n(std::begin(arr), std::size(arr), predicate {0}));
}
TEST_CASE("all_n(homogeneous)", "[algorithm/all_n]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
REQUIRE(based::all_n(std::begin(arr), std::size(arr), predicate {1}));
REQUIRE(!based::all_n(std::begin(arr), std::size(arr), predicate {2}));
}
TEST_CASE("all_n(non homogenous)", "[algorithm/all_n]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
REQUIRE(!based::all_n(std::begin(arr), std::size(arr), predicate {1}));
REQUIRE(!based::all_n(std::begin(arr), std::size(arr), predicate {2}));
}
diff --git a/ test/source/algorithms/count_if_not_test.cpp b/ test/source/algorithms/count_if_not_test.cpp
@@ -1,161 +0,0 @@
#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
#include <array>
#include "based/algorithms/search/count_if_not.hpp"
#include <catch2/catch_test_macros.hpp>
#include "based/concepts/is/same.hpp"
struct predicate
{
int goal;
explicit predicate(int init)
: goal(init)
{
}
auto operator()(int n) const { return n == goal; }
};
TEST_CASE("count_if_not return type", "[algorithm/count_if_not]")
{
const std::array<int, 0> arr = {};
SECTION("auto counter")
{
using res_t = decltype(based::count_if_not(
std::begin(arr), std::end(arr), predicate {0}
));
STATIC_REQUIRE(based::SameAs<
based::iter_dist_t<decltype(arr)::iterator>,
res_t>);
}
SECTION("explicit counter")
{
using res_t = decltype(based::count_if_not(
std::begin(arr), std::end(arr), predicate {0}, based::u8 {0}
));
STATIC_REQUIRE(based::SameAs<based::u8, res_t>);
}
}
TEST_CASE("count_if_not(empty)", "[algorithm/count_if_not]")
{
const std::array<int, 0> arr = {};
const auto count =
based::count_if_not(std::begin(arr), std::end(arr), predicate {0});
REQUIRE(count == 0);
}
TEST_CASE("count_if_not(homogeneous)", "[algorithm/count_if_not]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
const auto count0 =
based::count_if_not(std::begin(arr), std::end(arr), predicate {0});
const auto count1 =
based::count_if_not(std::begin(arr), std::end(arr), predicate {1});
REQUIRE(count0 == 6);
REQUIRE(count1 == 0);
}
TEST_CASE("count_if_not(non homogeneous)", "[algorithm/count_if_not]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
const auto count0 =
based::count_if_not(std::begin(arr), std::end(arr), predicate {0});
const auto count1 =
based::count_if_not(std::begin(arr), std::end(arr), predicate {1});
const auto count2 =
based::count_if_not(std::begin(arr), std::end(arr), predicate {2});
REQUIRE(count0 == 6);
REQUIRE(count1 == 2);
REQUIRE(count2 == 4);
}
TEST_CASE("count_if_not_n return type", "[algorithm/count_if_not_n]")
{
const std::array<int, 0> arr = {};
SECTION("auto counter")
{
using res_t = decltype(based::count_if_not_n(
std::begin(arr), std::size(arr), predicate {0}
));
STATIC_REQUIRE(based::SameAs<
based::iter_dist_t<decltype(arr)::iterator>,
res_t::second_type>);
}
SECTION("explicit counter")
{
using res_t = decltype(based::count_if_not_n(
std::begin(arr), std::size(arr), predicate {0}, based::u8 {0}
));
STATIC_REQUIRE(based::SameAs<based::u8, res_t::second_type>);
}
}
TEST_CASE("count_if_not_n(empty)", "[algorithm/count_if_not_n]")
{
const std::array<int, 0> arr = {};
const auto [itr, count] =
based::count_if_not_n(std::begin(arr), std::size(arr), predicate {0});
REQUIRE(count == 0);
REQUIRE(itr == std::end(arr));
}
TEST_CASE("count_if_not_n(homogeneous)", "[algorithm/count_if_not_n]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
const auto [itr0, count0] =
based::count_if_not_n(std::begin(arr), std::size(arr), predicate {0});
const auto [itr1, count1] =
based::count_if_not_n(std::begin(arr), std::size(arr), predicate {1});
REQUIRE(count0 == 6);
REQUIRE(itr0 == std::end(arr));
REQUIRE(count1 == 0);
REQUIRE(itr1 == std::end(arr));
}
TEST_CASE("count_if_not_n(non homogeneous)", "[algorithm/count_if_not_n]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
const auto [itr0, count0] =
based::count_if_not_n(std::begin(arr), std::size(arr), predicate {0});
const auto [itr1, count1] =
based::count_if_not_n(std::begin(arr), std::size(arr), predicate {1});
const auto [itr2, count2] =
based::count_if_not_n(std::begin(arr), std::size(arr), predicate {2});
REQUIRE(count0 == 6);
REQUIRE(itr0 == std::end(arr));
REQUIRE(count1 == 2);
REQUIRE(itr1 == std::end(arr));
REQUIRE(count2 == 4);
REQUIRE(itr2 == std::end(arr));
}
diff --git a/ test/source/algorithms/count_if_test.cpp b/ test/source/algorithms/count_if_test.cpp
@@ -1,164 +0,0 @@
#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
#include <array>
#include "based/algorithms/search/count_if.hpp"
#include <catch2/catch_test_macros.hpp>
#include "based/concepts/is/same.hpp"
struct predicate
{
int goal;
explicit predicate(int init)
: goal(init)
{
}
auto operator()(int n) const { return n == goal; }
};
TEST_CASE("count_if return type", "[algorithm/count_if]")
{
const std::array<int, 0> arr = {};
SECTION("auto counter")
{
using res_t =
decltype(based::count_if(std::begin(arr), std::end(arr), predicate {0})
);
STATIC_REQUIRE(based::SameAs<
based::iter_dist_t<decltype(arr)::iterator>,
res_t>);
}
SECTION("explicit counter")
{
using res_t = decltype(based::count_if(
std::begin(arr), std::end(arr), predicate {0}, based::u8 {0}
));
STATIC_REQUIRE(based::SameAs<based::u8, res_t>);
}
}
TEST_CASE("count_if(empty)", "[algorithm/count_if]")
{
const std::array<int, 0> arr = {};
const auto count =
based::count_if(std::begin(arr), std::end(arr), predicate {0});
REQUIRE(count == 0);
}
TEST_CASE("count_if(homogeneous)", "[algorithm/count_if]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
const auto count0 =
based::count_if(std::begin(arr), std::end(arr), predicate {0});
const auto count1 =
based::count_if(std::begin(arr), std::end(arr), predicate {1});
REQUIRE(count0 == 0);
REQUIRE(count1 == 6);
}
TEST_CASE("count_if(non homogeneous)", "[algorithm/count_if]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
const auto count0 =
based::count_if(std::begin(arr), std::end(arr), predicate {0});
const auto count1 =
based::count_if(std::begin(arr), std::end(arr), predicate {1});
const auto count2 =
based::count_if(std::begin(arr), std::end(arr), predicate {2});
REQUIRE(count0 == 0);
REQUIRE(count1 == 4);
REQUIRE(count2 == 2);
}
TEST_CASE("count_if_n return type", "[algorithm/count_if_n]")
{
const std::array<int, 0> arr = {};
SECTION("auto counter")
{
using res_t = decltype(based::count_if_n(
std::begin(arr), std::size(arr), predicate {0}
)
.second);
STATIC_REQUIRE(based::SameAs<
based::iter_dist_t<decltype(arr)::iterator>,
res_t>);
}
SECTION("explicit counter")
{
using res_t = decltype(based::count_if_n(
std::begin(arr),
std::size(arr),
predicate {0},
based::u8 {0}
)
.second);
STATIC_REQUIRE(based::SameAs<based::u8, res_t>);
}
}
TEST_CASE("count_if_n(empty)", "[algorithm/count_if_n]")
{
const std::array<int, 0> arr = {};
const auto [itr, count] =
based::count_if_n(std::begin(arr), std::size(arr), predicate {0});
REQUIRE(count == 0);
REQUIRE(itr == std::end(arr));
}
TEST_CASE("count_if_n(homogeneous)", "[algorithm/count_if_n]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
const auto [itr0, count0] =
based::count_if_n(std::begin(arr), std::size(arr), predicate {0});
const auto [itr1, count1] =
based::count_if_n(std::begin(arr), std::size(arr), predicate {1});
REQUIRE(count0 == 0);
REQUIRE(itr0 == std::end(arr));
REQUIRE(count1 == 6);
REQUIRE(itr1 == std::end(arr));
}
TEST_CASE("count_if_n(non homogeneous)", "[algorithm/count_if_n]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
const auto [itr0, count0] =
based::count_if_n(std::begin(arr), std::size(arr), predicate {0});
const auto [itr1, count1] =
based::count_if_n(std::begin(arr), std::size(arr), predicate {1});
const auto [itr2, count2] =
based::count_if_n(std::begin(arr), std::size(arr), predicate {2});
REQUIRE(count0 == 0);
REQUIRE(itr0 == std::end(arr));
REQUIRE(count1 == 4);
REQUIRE(itr1 == std::end(arr));
REQUIRE(count2 == 2);
REQUIRE(itr2 == std::end(arr));
}
diff --git a/ test/source/algorithms/count_not_test.cpp b/ test/source/algorithms/count_not_test.cpp
@@ -1,138 +0,0 @@
#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
#include <array>
#include "based/algorithms/search/count_not.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("count_not return type", "[algorithm/count_not]")
{
const std::array<int, 0> arr = {};
SECTION("auto counter")
{
using res_t = decltype(based::count_not(std::begin(arr), std::end(arr), 0));
STATIC_REQUIRE(based::SameAs<
based::iter_dist_t<decltype(arr)::iterator>,
res_t>);
}
SECTION("explicit counter")
{
using res_t = decltype(based::count_not(
std::begin(arr), std::end(arr), 0, based::u8 {0}
));
STATIC_REQUIRE(based::SameAs<based::u8, res_t>);
}
}
TEST_CASE("count_not(empty)", "[algorithm/count_not]")
{
const std::array<int, 0> arr = {};
const auto count_not = based::count_not(std::begin(arr), std::end(arr), 0);
REQUIRE(count_not == 0);
}
TEST_CASE("count_not(homogeneous)", "[algorithm/count_not]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
const auto count0 = based::count_not(std::begin(arr), std::end(arr), 0);
const auto count1 = based::count_not(std::begin(arr), std::end(arr), 1);
REQUIRE(count0 == 6);
REQUIRE(count1 == 0);
}
TEST_CASE("count_not(non homogeneous)", "[algorithm/count_not]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
const auto count0 = based::count_not(std::begin(arr), std::end(arr), 0);
const auto count1 = based::count_not(std::begin(arr), std::end(arr), 1);
const auto count2 = based::count_not(std::begin(arr), std::end(arr), 2);
REQUIRE(count0 == 6);
REQUIRE(count1 == 2);
REQUIRE(count2 == 4);
}
TEST_CASE("count_not_n return type", "[algorithm/count_not_n]")
{
const std::array<int, 0> arr = {};
SECTION("auto counter")
{
using res_t =
decltype(based::count_not_n(std::begin(arr), std::size(arr), 0));
STATIC_REQUIRE(based::SameAs<
based::iter_dist_t<decltype(arr)::iterator>,
res_t::second_type>);
}
SECTION("explicit counter")
{
using res_t = decltype(based::count_not_n(
std::begin(arr), std::size(arr), 0, based::u8 {0}
));
STATIC_REQUIRE(based::SameAs<based::u8, res_t::second_type>);
}
}
TEST_CASE("count_not_n(empty)", "[algorithm/count_not_n]")
{
const std::array<int, 0> arr = {};
const auto [itr, count] =
based::count_not_n(std::begin(arr), std::size(arr), 0);
REQUIRE(count == 0);
REQUIRE(itr == std::end(arr));
}
TEST_CASE("count_not_n(homogeneous)", "[algorithm/count_not_n]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
const auto [itr0, count0] =
based::count_not_n(std::begin(arr), std::size(arr), 0);
const auto [itr1, count1] =
based::count_not_n(std::begin(arr), std::size(arr), 1);
REQUIRE(count0 == 6);
REQUIRE(itr0 == std::end(arr));
REQUIRE(count1 == 0);
REQUIRE(itr1 == std::end(arr));
}
TEST_CASE("count_not_n(non homogeneous)", "[algorithm/count_not_n]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
const auto [itr0, count0] =
based::count_not_n(std::begin(arr), std::size(arr), 0);
const auto [itr1, count1] =
based::count_not_n(std::begin(arr), std::size(arr), 1);
const auto [itr2, count2] =
based::count_not_n(std::begin(arr), std::size(arr), 2);
REQUIRE(count0 == 6);
REQUIRE(itr0 == std::end(arr));
REQUIRE(count1 == 2);
REQUIRE(itr1 == std::end(arr));
REQUIRE(count2 == 4);
REQUIRE(itr2 == std::end(arr));
}
diff --git a/ test/source/algorithms/count_test.cpp b/ test/source/algorithms/count_test.cpp
@@ -1,137 +0,0 @@
#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
#include <array>
#include "based/algorithms/search/count.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("count return type", "[algorithm/count]")
{
const std::array<int, 0> arr = {};
SECTION("auto counter")
{
using res_t = decltype(based::count(std::begin(arr), std::end(arr), 0));
STATIC_REQUIRE(based::SameAs<
based::iter_dist_t<decltype(arr)::iterator>,
res_t>);
}
SECTION("explicit counter")
{
using res_t =
decltype(based::count(std::begin(arr), std::end(arr), 0, based::u8 {0})
);
STATIC_REQUIRE(based::SameAs<based::u8, res_t>);
}
}
TEST_CASE("count(empty)", "[algorithm/count]")
{
const std::array<int, 0> arr = {};
const auto count = based::count(std::begin(arr), std::end(arr), 0);
REQUIRE(count == 0);
}
TEST_CASE("count(homogeneous)", "[algorithm/count]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
const auto count0 = based::count(std::begin(arr), std::end(arr), 0);
const auto count1 = based::count(std::begin(arr), std::end(arr), 1);
REQUIRE(count0 == 0);
REQUIRE(count1 == 6);
}
TEST_CASE("count(non homogeneous)", "[algorithm/count]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
const auto count0 = based::count(std::begin(arr), std::end(arr), 0);
const auto count1 = based::count(std::begin(arr), std::end(arr), 1);
const auto count2 = based::count(std::begin(arr), std::end(arr), 2);
REQUIRE(count0 == 0);
REQUIRE(count1 == 4);
REQUIRE(count2 == 2);
}
TEST_CASE("count_n return type", "[algorithm/count_n]")
{
const std::array<int, 0> arr = {};
SECTION("auto counter")
{
using res_t =
decltype(based::count_n(std::begin(arr), std::size(arr), 0).second);
STATIC_REQUIRE(based::SameAs<
based::iter_dist_t<decltype(arr)::iterator>,
res_t>);
}
SECTION("explicit counter")
{
using res_t = decltype(based::count_n(
std::begin(arr), std::size(arr), 0, based::u8 {0}
)
.second);
STATIC_REQUIRE(based::SameAs<based::u8, res_t>);
}
}
TEST_CASE("count_n(empty)", "[algorithm/count_n]")
{
const std::array<int, 0> arr = {};
const auto [itr, count] = based::count_n(std::begin(arr), std::size(arr), 0);
REQUIRE(count == 0);
REQUIRE(itr == std::end(arr));
}
TEST_CASE("count_n(homogeneous)", "[algorithm/count_n]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
const auto [itr0, count0] =
based::count_n(std::begin(arr), std::size(arr), 0);
const auto [itr1, count1] =
based::count_n(std::begin(arr), std::size(arr), 1);
REQUIRE(count0 == 0);
REQUIRE(itr0 == std::end(arr));
REQUIRE(count1 == 6);
REQUIRE(itr1 == std::end(arr));
}
TEST_CASE("count_n(non homogeneous)", "[algorithm/count_n]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
const auto [itr0, count0] =
based::count_n(std::begin(arr), std::size(arr), 0);
const auto [itr1, count1] =
based::count_n(std::begin(arr), std::size(arr), 1);
const auto [itr2, count2] =
based::count_n(std::begin(arr), std::size(arr), 2);
REQUIRE(count0 == 0);
REQUIRE(itr0 == std::end(arr));
REQUIRE(count1 == 4);
REQUIRE(itr1 == std::end(arr));
REQUIRE(count2 == 2);
REQUIRE(itr2 == std::end(arr));
}
diff --git a/ test/source/algorithms/find_adjacent_mismatch_test.cpp b/ test/source/algorithms/find_adjacent_mismatch_test.cpp
@@ -1,160 +0,0 @@
#include <array>
#include "based/algorithms/search/find_adjacent_mismatch.hpp"
#include <catch2/catch_test_macros.hpp>
struct equal
{
auto operator()(int a, int b) const { return a == b; }
};
TEST_CASE("find_adjacent_mismatch(empty)", "[algorithm/find_adjacent_mismatch]")
{
std::array<int, 0> arr = {};
const auto* itr =
based::find_adjacent_mismatch(std::begin(arr), std::end(arr), equal {});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("find_adjacent_mismatch(one)", "[algorithm/find_adjacent_mismatch]")
{
std::array arr = {0};
const auto* itr =
based::find_adjacent_mismatch(std::begin(arr), std::end(arr), equal {});
REQUIRE(itr == std::end(arr));
}
TEST_CASE(
"find_adjacent_mismatch(two equal)", "[algorithm/find_adjacent_mismatch]"
)
{
std::array arr = {0, 0};
const auto* itr =
based::find_adjacent_mismatch(std::begin(arr), std::end(arr), equal {});
REQUIRE(itr == std::end(arr));
}
TEST_CASE(
"find_adjacent_mismatch(two nonequal)", "[algorithm/find_adjacent_mismatch]"
)
{
std::array arr = {0, 1};
const auto* itr =
based::find_adjacent_mismatch(std::begin(arr), std::end(arr), equal {});
REQUIRE(itr == std::next(std::begin(arr), 1));
}
TEST_CASE("find_adjacent_mismatch(equal)", "[algorithm/find_adjacent_mismatch]")
{
std::array arr = {0, 0, 0, 0, 0, 0};
const auto* itr =
based::find_adjacent_mismatch(std::begin(arr), std::end(arr), equal {});
REQUIRE(itr == std::end(arr));
}
TEST_CASE(
"find_adjacent_mismatch(nonequal)", "[algorithm/find_adjacent_mismatch]"
)
{
std::array arr = {0, 0, 0, 0, 1, 1, 1, 1};
const auto* itr =
based::find_adjacent_mismatch(std::begin(arr), std::end(arr), equal {});
REQUIRE(itr == std::next(std::begin(arr), 4));
}
TEST_CASE(
"find_adjacent_mismatch_forward(empty)",
"[algorithm/find_adjacent_mismatch_forward]"
)
{
std::array<int, 0> arr = {};
const auto* itr = based::find_adjacent_mismatch_forward(
std::begin(arr), std::end(arr), equal {}
);
REQUIRE(itr == std::end(arr));
}
TEST_CASE(
"find_adjacent_mismatch_forward(one)",
"[algorithm/find_adjacent_mismatch_forward]"
)
{
std::array arr = {0};
const auto* itr = based::find_adjacent_mismatch_forward(
std::begin(arr), std::end(arr), equal {}
);
REQUIRE(itr == std::end(arr));
}
TEST_CASE(
"find_adjacent_mismatch_forward(two equal)",
"[algorithm/find_adjacent_mismatch_forward]"
)
{
std::array arr = {0, 0};
const auto* itr = based::find_adjacent_mismatch_forward(
std::begin(arr), std::end(arr), equal {}
);
REQUIRE(itr == std::end(arr));
}
TEST_CASE(
"find_adjacent_mismatch_forward(two nonequal)",
"[algorithm/find_adjacent_mismatch_forward]"
)
{
std::array arr = {0, 1};
const auto* itr = based::find_adjacent_mismatch_forward(
std::begin(arr), std::end(arr), equal {}
);
REQUIRE(itr == std::next(std::begin(arr), 1));
}
TEST_CASE(
"find_adjacent_mismatch_forward(equal)",
"[algorithm/find_adjacent_mismatch_forward]"
)
{
std::array arr = {0, 0, 0, 0, 0, 0};
const auto* itr = based::find_adjacent_mismatch_forward(
std::begin(arr), std::end(arr), equal {}
);
REQUIRE(itr == std::end(arr));
}
TEST_CASE(
"find_adjacent_mismatch_forward(nonequal)",
"[algorithm/find_adjacent_mismatch_forward]"
)
{
std::array arr = {0, 0, 0, 0, 1, 1, 1, 1};
const auto* itr = based::find_adjacent_mismatch_forward(
std::begin(arr), std::end(arr), equal {}
);
REQUIRE(itr == std::next(std::begin(arr), 4));
}
diff --git a/ test/source/algorithms/find_if_not_test.cpp b/ test/source/algorithms/find_if_not_test.cpp
@@ -1,206 +0,0 @@
#include <array>
#include "based/algorithms/search/find_if_not.hpp"
#include <catch2/catch_test_macros.hpp>
struct predicate
{
int goal;
explicit predicate(int init)
: goal(init)
{
}
auto operator()(int n) const { return n == goal; }
};
TEST_CASE("find_if_not_n(empty)", "[algorithm/find_if_not_n]")
{
const std::array<int, 0> arr = {};
const auto [itr, left] =
based::find_if_not_n(std::begin(arr), std::size(arr), predicate {0});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("find_if_not_n(one)", "[algorithm/find_if_not_n]")
{
const std::array arr = {0};
SECTION("found")
{
const auto [itr, left] =
based::find_if_not_n(std::begin(arr), std::size(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("not found")
{
const auto [itr, left] =
based::find_if_not_n(std::begin(arr), std::size(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
REQUIRE(idx + left == std::size(arr));
}
}
TEST_CASE("find_if_not_n(two)", "[algorithm/find_if_not_n]")
{
const std::array arr = {0, 1};
SECTION("found 1")
{
const auto [itr, left] =
based::find_if_not_n(std::begin(arr), std::size(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("found 2")
{
const auto [itr, left] =
based::find_if_not_n(std::begin(arr), std::size(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
REQUIRE(idx + left == std::size(arr));
}
}
TEST_CASE("find_if_not_n(multiple)", "[algorithm/find_if_not_n]")
{
const std::array arr = {0, 0, 0, 0};
SECTION("found")
{
const auto [itr, left] =
based::find_if_not_n(std::begin(arr), std::size(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("not found")
{
const auto [itr, left] =
based::find_if_not_n(std::begin(arr), std::size(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 4);
REQUIRE(idx + left == std::size(arr));
}
}
TEST_CASE("find_if_not(empty)", "[algorithm/find_if_not]")
{
const std::array<int, 0> arr = {};
const auto* itr =
based::find_if_not(std::begin(arr), std::end(arr), predicate {0});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("find_if_not(one)", "[algorithm/find_if_not]")
{
const std::array arr = {0};
SECTION("found")
{
const auto* itr =
based::find_if_not(std::begin(arr), std::end(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("not found")
{
const auto* itr =
based::find_if_not(std::begin(arr), std::end(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
}
TEST_CASE("find_if_not(two)", "[algorithm/find_if_not]")
{
const std::array arr = {0, 1};
SECTION("found 1")
{
const auto* itr =
based::find_if_not(std::begin(arr), std::end(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("found 2")
{
const auto* itr =
based::find_if_not(std::begin(arr), std::end(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
}
TEST_CASE("find_if_not(multiple)", "[algorithm/find_if_not]")
{
const std::array arr = {0, 0, 0, 0};
SECTION("found")
{
const auto* itr =
based::find_if_not(std::begin(arr), std::end(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("not found")
{
const auto* itr =
based::find_if_not(std::begin(arr), std::end(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 4);
}
}
TEST_CASE("find_if_not_unguarded(one)", "[algorithm/find_if_not_unguarded]")
{
const std::array arr = {0};
const auto* itr =
based::find_if_not_unguarded(std::begin(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("find_if_not_unguarded(two)", "[algorithm/find_if_not_unguarded]")
{
const std::array arr = {0, 1};
const auto* itr =
based::find_if_not_unguarded(std::begin(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
TEST_CASE(
"find_if_not_unguarded(multiple)", "[algorithm/find_if_not_unguarded]"
)
{
const std::array arr = {1, 1, 0, 1};
const auto* itr =
based::find_if_not_unguarded(std::begin(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 2);
}
diff --git a/ test/source/algorithms/find_if_test.cpp b/ test/source/algorithms/find_if_test.cpp
@@ -1,218 +0,0 @@
#include <array>
#include "based/algorithms/search/find_if.hpp"
#include <catch2/catch_test_macros.hpp>
struct predicate
{
int goal;
explicit predicate(int init)
: goal(init)
{
}
auto operator()(int n) const { return n == goal; }
};
TEST_CASE("find_if(empty)", "[algorithm/find_if]")
{
const std::array<int, 0> arr = {};
const auto* itr =
based::find_if(std::begin(arr), std::end(arr), predicate {0});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("find_if(one)", "[algorithm/find_if]")
{
const std::array arr = {0};
SECTION("found")
{
const auto* itr =
based::find_if(std::begin(arr), std::end(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("not found")
{
const auto* itr =
based::find_if(std::begin(arr), std::end(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
}
TEST_CASE("find_if(two)", "[algorithm/find_if]")
{
const std::array arr = {0, 1};
SECTION("found 1")
{
const auto* itr =
based::find_if(std::begin(arr), std::end(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("found 2")
{
const auto* itr =
based::find_if(std::begin(arr), std::end(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
SECTION("not found")
{
const auto* itr =
based::find_if(std::begin(arr), std::end(arr), predicate {2});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 2);
}
}
TEST_CASE("find_if(multiple)", "[algorithm/find_if]")
{
const std::array arr = {0, 0, 0, 0};
SECTION("found")
{
const auto* itr =
based::find_if(std::begin(arr), std::end(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("not found")
{
const auto* itr =
based::find_if(std::begin(arr), std::end(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 4);
}
}
TEST_CASE("find_if_n(empty)", "[algorithm/find_if_n]")
{
const std::array<int, 0> arr = {};
const auto [itr, left] =
based::find_if_n(std::begin(arr), std::size(arr), predicate {0});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("find_if_n(one)", "[algorithm/find_if_n]")
{
const std::array arr = {0};
SECTION("found")
{
const auto [itr, left] =
based::find_if_n(std::begin(arr), std::size(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("not found")
{
const auto [itr, left] =
based::find_if_n(std::begin(arr), std::size(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
REQUIRE(idx + left == std::size(arr));
}
}
TEST_CASE("find_if_n(two)", "[algorithm/find_if_n]")
{
const std::array arr = {0, 1};
SECTION("found 1")
{
const auto [itr, left] =
based::find_if_n(std::begin(arr), std::size(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("found 2")
{
const auto [itr, left] =
based::find_if_n(std::begin(arr), std::size(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
REQUIRE(idx + left == std::size(arr));
}
SECTION("not found")
{
const auto [itr, left] =
based::find_if_n(std::begin(arr), std::size(arr), predicate {2});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 2);
REQUIRE(idx + left == std::size(arr));
}
}
TEST_CASE("find_if_n(multiple)", "[algorithm/find_if_n]")
{
const std::array arr = {0, 0, 0, 0};
SECTION("found")
{
const auto [itr, left] =
based::find_if_n(std::begin(arr), std::size(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("not found")
{
const auto [itr, left] =
based::find_if_n(std::begin(arr), std::size(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 4);
REQUIRE(idx + left == std::size(arr));
}
}
TEST_CASE("find_if_unguarded(one)", "[algorithm/find_if_unguarded]")
{
const std::array arr = {0};
const auto* itr = based::find_if_unguarded(std::begin(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("find_if_unguarded(two)", "[algorithm/find_if_unguarded]")
{
const std::array arr = {0, 1};
const auto* itr = based::find_if_unguarded(std::begin(arr), predicate {1});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
TEST_CASE("find_if_unguarded(multiple)", "[algorithm/find_if_unguarded]")
{
const std::array arr = {0, 0, 0, 0};
const auto* itr = based::find_if_unguarded(std::begin(arr), predicate {0});
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
diff --git a/ test/source/algorithms/find_mismatch_test.cpp b/ test/source/algorithms/find_mismatch_test.cpp
@@ -1,535 +0,0 @@
#include <array>
#include "based/algorithms/search/find_mismatch.hpp"
#include <catch2/catch_test_macros.hpp>
struct equal
{
auto operator()(int lhs, int rhs) const { return lhs == rhs; }
};
TEST_CASE("find_mismatch(empty)", "[algorithm/find_mismatch]")
{
std::array<int, 0> arr0 = {};
std::array<int, 0> arr1 = {};
const auto [itr0, itr1] = based::find_mismatch(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(itr1 == std::end(arr1));
}
TEST_CASE("find_mismatch(empty, nonempty)", "[algorithm/find_mismatch]")
{
std::array<int, 0> arr0 = {};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, itr1] = based::find_mismatch(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(itr1 == std::begin(arr1));
}
TEST_CASE("find_mismatch(nonempty, empty)", "[algorithm/find_mismatch]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array<int, 0> arr1 = {};
const auto [itr0, itr1] = based::find_mismatch(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::begin(arr0));
REQUIRE(itr1 == std::end(arr1));
}
TEST_CASE("find_mismatch(equal)", "[algorithm/find_mismatch]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, itr1] = based::find_mismatch(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(itr1 == std::end(arr1));
}
TEST_CASE("find_mismatch(equal, longer)", "[algorithm/find_mismatch]")
{
std::array arr0 = {0, 1, 2};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, itr1] = based::find_mismatch(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(itr1 == std::next(std::begin(arr1), std::size(arr0)));
}
TEST_CASE("find_mismatch(longer, equal)", "[algorithm/find_mismatch]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array arr1 = {0, 1, 2};
const auto [itr0, itr1] = based::find_mismatch(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::next(std::begin(arr0), std::size(arr1)));
REQUIRE(itr1 == std::end(arr1));
}
TEST_CASE("find_mismatch(mismatch)", "[algorithm/find_mismatch]")
{
std::array arr0 = {0, 1, 4, 3, 2};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, itr1] = based::find_mismatch(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::next(std::begin(arr0), 2));
REQUIRE(itr1 == std::next(std::begin(arr1), 2));
}
TEST_CASE("find_mismatch_n(empty)", "[algorithm/find_mismatch_n]")
{
std::array<int, 0> arr0 = {};
std::array<int, 0> arr1 = {};
const auto [itr0, n0, itr1] = based::find_mismatch_n(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(n0 == 0);
REQUIRE(itr1 == std::end(arr1));
}
TEST_CASE("find_mismatch_n(empty, nonempty)", "[algorithm/find_mismatch_n]")
{
std::array<int, 0> arr0 = {};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, n0, itr1] = based::find_mismatch_n(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(n0 == 0);
REQUIRE(itr1 == std::begin(arr1));
}
TEST_CASE("find_mismatch_n(nonempty, empty)", "[algorithm/find_mismatch_n]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array<int, 0> arr1 = {};
const auto [itr0, n0, itr1] = based::find_mismatch_n(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::begin(arr0));
REQUIRE(n0 == std::size(arr0));
REQUIRE(itr1 == std::end(arr1));
}
TEST_CASE("find_mismatch_n(equal)", "[algorithm/find_mismatch_n]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, n0, itr1] = based::find_mismatch_n(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(n0 == 0);
REQUIRE(itr1 == std::end(arr1));
}
TEST_CASE("find_mismatch_n(equal, longer)", "[algorithm/find_mismatch_n]")
{
std::array arr0 = {0, 1, 2};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, n0, itr1] = based::find_mismatch_n(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(n0 == 0);
REQUIRE(itr1 == std::next(std::begin(arr1), std::size(arr0)));
}
TEST_CASE("find_mismatch_n(longer, equal)", "[algorithm/find_mismatch_n]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array arr1 = {0, 1, 2};
const auto [itr0, n0, itr1] = based::find_mismatch_n(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::next(std::begin(arr0), std::size(arr1)));
REQUIRE(n0 == 2);
REQUIRE(itr1 == std::end(arr1));
}
TEST_CASE("find_mismatch_n(mismatch)", "[algorithm/find_mismatch_n]")
{
std::array arr0 = {0, 1, 4, 3, 2};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, n0, itr1] = based::find_mismatch_n(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::end(arr1),
equal {}
);
REQUIRE(itr0 == std::next(std::begin(arr0), 2));
REQUIRE(n0 == 3);
REQUIRE(itr1 == std::next(std::begin(arr1), 2));
}
TEST_CASE("find_mismatch_m(empty)", "[algorithm/find_mismatch_m]")
{
std::array<int, 0> arr0 = {};
std::array<int, 0> arr1 = {};
const auto [itr0, itr1, n1] = based::find_mismatch_m(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(itr1 == std::end(arr1));
REQUIRE(n1 == 0);
}
TEST_CASE("find_mismatch_m(empty, nonempty)", "[algorithm/find_mismatch_m]")
{
std::array<int, 0> arr0 = {};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, itr1, n1] = based::find_mismatch_m(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(itr1 == std::begin(arr1));
REQUIRE(n1 == std::size(arr1));
}
TEST_CASE("find_mismatch_m(nonempty, empty)", "[algorithm/find_mismatch_m]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array<int, 0> arr1 = {};
const auto [itr0, itr1, n1] = based::find_mismatch_m(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::begin(arr0));
REQUIRE(itr1 == std::end(arr1));
REQUIRE(n1 == 0);
}
TEST_CASE("find_mismatch_m(equal)", "[algorithm/find_mismatch_m]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, itr1, n1] = based::find_mismatch_m(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(itr1 == std::end(arr1));
REQUIRE(n1 == 0);
}
TEST_CASE("find_mismatch_m(equal, longer)", "[algorithm/find_mismatch_m]")
{
std::array arr0 = {0, 1, 2};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, itr1, n1] = based::find_mismatch_m(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(itr1 == std::next(std::begin(arr1), std::size(arr0)));
REQUIRE(n1 == 2);
}
TEST_CASE("find_mismatch_m(longer, equal)", "[algorithm/find_mismatch_m]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array arr1 = {0, 1, 2};
const auto [itr0, itr1, n1] = based::find_mismatch_m(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::next(std::begin(arr0), std::size(arr1)));
REQUIRE(itr1 == std::end(arr1));
REQUIRE(n1 == 0);
}
TEST_CASE("find_mismatch_m(mismatch)", "[algorithm/find_mismatch_m]")
{
std::array arr0 = {0, 1, 4, 3, 2};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, itr1, n1] = based::find_mismatch_m(
std::begin(arr0),
std::end(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::next(std::begin(arr0), 2));
REQUIRE(itr1 == std::next(std::begin(arr1), 2));
REQUIRE(n1 == 3);
}
TEST_CASE("find_mismatch_n_m(empty)", "[algorithm/find_mismatch_n_m]")
{
std::array<int, 0> arr0 = {};
std::array<int, 0> arr1 = {};
const auto [itr0, n0, itr1, n1] = based::find_mismatch_n_m(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(n0 == 0);
REQUIRE(itr1 == std::end(arr1));
REQUIRE(n1 == 0);
}
TEST_CASE("find_mismatch_n_m(empty, nonempty)", "[algorithm/find_mismatch_n_m]")
{
std::array<int, 0> arr0 = {};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, n0, itr1, n1] = based::find_mismatch_n_m(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(n0 == 0);
REQUIRE(itr1 == std::begin(arr1));
REQUIRE(n1 == std::size(arr1));
}
TEST_CASE("find_mismatch_n_m(nonempty, empty)", "[algorithm/find_mismatch_n_m]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array<int, 0> arr1 = {};
const auto [itr0, n0, itr1, n1] = based::find_mismatch_n_m(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::begin(arr0));
REQUIRE(n0 == std::size(arr0));
REQUIRE(itr1 == std::end(arr1));
REQUIRE(n1 == 0);
}
TEST_CASE("find_mismatch_n_m(equal)", "[algorithm/find_mismatch_n_m]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, n0, itr1, n1] = based::find_mismatch_n_m(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(n0 == 0);
REQUIRE(itr1 == std::end(arr1));
REQUIRE(n1 == 0);
}
TEST_CASE("find_mismatch_n_m(equal, longer)", "[algorithm/find_mismatch_n_m]")
{
std::array arr0 = {0, 1, 2};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, n0, itr1, n1] = based::find_mismatch_n_m(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::end(arr0));
REQUIRE(n0 == 0);
REQUIRE(itr1 == std::next(std::begin(arr1), std::size(arr0)));
REQUIRE(n1 == 2);
}
TEST_CASE("find_mismatch_n_m(longer, equal)", "[algorithm/find_mismatch_n_m]")
{
std::array arr0 = {0, 1, 2, 3, 4};
std::array arr1 = {0, 1, 2};
const auto [itr0, n0, itr1, n1] = based::find_mismatch_n_m(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::next(std::begin(arr0), std::size(arr1)));
REQUIRE(n0 == 2);
REQUIRE(itr1 == std::end(arr1));
REQUIRE(n1 == 0);
}
TEST_CASE("find_mismatch_n_m(mismatch)", "[algorithm/find_mismatch_n_m]")
{
std::array arr0 = {0, 1, 4, 3, 2};
std::array arr1 = {0, 1, 2, 3, 4};
const auto [itr0, n0, itr1, n1] = based::find_mismatch_n_m(
std::begin(arr0),
std::size(arr0),
std::begin(arr1),
std::size(arr1),
equal {}
);
REQUIRE(itr0 == std::next(std::begin(arr0), 2));
REQUIRE(n0 == 3);
REQUIRE(itr1 == std::next(std::begin(arr1), 2));
REQUIRE(n1 == 3);
}
diff --git a/ test/source/algorithms/find_not_test.cpp b/ test/source/algorithms/find_not_test.cpp
@@ -1,157 +0,0 @@
#include <array>
#include "based/algorithms/search/find_not.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("find_not(empty)", "[algorithm/find_not]")
{
const std::array<int, 0> arr = {};
const auto* itr = based::find_not(std::begin(arr), std::end(arr), 0);
REQUIRE(itr == std::end(arr));
}
TEST_CASE("find_not(one) = found", "[algorithm/find_not]")
{
const std::array arr = {0};
SECTION("found")
{
const auto* itr = based::find_not(std::begin(arr), std::end(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("not found")
{
const auto* itr = based::find_not(std::begin(arr), std::end(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
}
TEST_CASE("find_not(two) = found", "[algorithm/find_not]")
{
const std::array arr = {0, 1};
SECTION("found 1")
{
const auto* itr = based::find_not(std::begin(arr), std::end(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("found 2")
{
const auto* itr = based::find_not(std::begin(arr), std::end(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
}
TEST_CASE("find_not(multiple) = found", "[algorithm/find_not]")
{
const std::array arr = {0, 0, 0, 0};
SECTION("found")
{
const auto* itr = based::find_not(std::begin(arr), std::end(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("not found")
{
const auto* itr = based::find_not(std::begin(arr), std::end(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 4);
}
}
TEST_CASE("find_not_n(empty)", "[algorithm/find_not_n]")
{
const std::array<int, 0> arr = {};
const auto [itr, left] =
based::find_not_n(std::begin(arr), std::size(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
TEST_CASE("find_not_n(one)", "[algorithm/find_not_n]")
{
const std::array arr = {0};
SECTION("found")
{
const auto [itr, left] =
based::find_not_n(std::begin(arr), std::size(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("not found")
{
const auto [itr, left] =
based::find_not_n(std::begin(arr), std::size(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
REQUIRE(idx + left == std::size(arr));
}
}
TEST_CASE("find_not_n(two)", "[algorithm/find_not_n]")
{
const std::array arr = {0, 1};
SECTION("found 1")
{
const auto [itr, left] =
based::find_not_n(std::begin(arr), std::size(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("found 2")
{
const auto [itr, left] =
based::find_not_n(std::begin(arr), std::size(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
REQUIRE(idx + left == std::size(arr));
}
}
TEST_CASE("find_not_n(multiple)", "[algorithm/find_not_n]")
{
const std::array arr = {0, 0, 0, 0};
SECTION("found")
{
const auto [itr, left] =
based::find_not_n(std::begin(arr), std::size(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("not found")
{
const auto [itr, left] =
based::find_not_n(std::begin(arr), std::size(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 4);
REQUIRE(idx + left == std::size(arr));
}
}
diff --git a/ test/source/algorithms/find_test.cpp b/ test/source/algorithms/find_test.cpp
@@ -1,164 +0,0 @@
#include <array>
#include "based/algorithms/search/find.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("find(empty)", "[algorithm/find]")
{
const std::array<int, 0> arr = {};
const auto* itr = based::find(std::begin(arr), std::end(arr), 0);
REQUIRE(itr == std::end(arr));
}
TEST_CASE("find(one) = found", "[algorithm/find]")
{
const std::array arr = {0};
SECTION("found")
{
const auto* itr = based::find(std::begin(arr), std::end(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("not found")
{
const auto* itr = based::find(std::begin(arr), std::end(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
}
TEST_CASE("find(two) = found", "[algorithm/find]")
{
const std::array arr = {0, 1};
SECTION("found 1")
{
const auto* itr = based::find(std::begin(arr), std::end(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("found 2")
{
const auto* itr = based::find(std::begin(arr), std::end(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
SECTION("not found")
{
const auto* itr = based::find(std::begin(arr), std::end(arr), 2);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 2);
}
}
TEST_CASE("find(multiple) = found", "[algorithm/find]")
{
const std::array arr = {0, 0, 0, 0};
SECTION("found")
{
const auto* itr = based::find(std::begin(arr), std::end(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
SECTION("not found")
{
const auto* itr = based::find(std::begin(arr), std::end(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 4);
}
}
TEST_CASE("find_n(empty)", "[algorithm/find_n]")
{
const std::array<int, 0> arr = {};
const auto [itr, left] = based::find_n(std::begin(arr), std::size(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
TEST_CASE("find_n(one)", "[algorithm/find_n]")
{
const std::array arr = {0};
SECTION("found")
{
const auto [itr, left] = based::find_n(std::begin(arr), std::size(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("not found")
{
const auto [itr, left] = based::find_n(std::begin(arr), std::size(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
REQUIRE(idx + left == std::size(arr));
}
}
TEST_CASE("find_n(two)", "[algorithm/find_n]")
{
const std::array arr = {0, 1};
SECTION("found 1")
{
const auto [itr, left] = based::find_n(std::begin(arr), std::size(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("found 2")
{
const auto [itr, left] = based::find_n(std::begin(arr), std::size(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
REQUIRE(idx + left == std::size(arr));
}
SECTION("not found")
{
const auto [itr, left] = based::find_n(std::begin(arr), std::size(arr), 2);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 2);
REQUIRE(idx + left == std::size(arr));
}
}
TEST_CASE("find_n(multiple)", "[algorithm/find_n]")
{
const std::array arr = {0, 0, 0, 0};
SECTION("found")
{
const auto [itr, left] = based::find_n(std::begin(arr), std::size(arr), 0);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
REQUIRE(idx + left == std::size(arr));
}
SECTION("not found")
{
const auto [itr, left] = based::find_n(std::begin(arr), std::size(arr), 1);
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 4);
REQUIRE(idx + left == std::size(arr));
}
}
diff --git a/ test/source/algorithms/foreach_test.cpp b/ test/source/algorithms/foreach_test.cpp
@@ -1,84 +0,0 @@
#include <array>
#include <catch2/catch_test_macros.hpp>
#include "based/algorithms/batch/for_each.hpp"
struct functor
{
int operator()(int n) { return sum += n; }
int sum = 0;
};
TEST_CASE("for_each(empty)", "[algorithm/for_each]")
{
const std::array<int, 0> arr = {};
const auto func = based::for_each(std::begin(arr), std::end(arr), functor {});
REQUIRE(func.sum == 0);
}
TEST_CASE("for_each(one)", "[algorithm/for_each]")
{
const std::array arr = {1};
const auto func = based::for_each(std::begin(arr), std::end(arr), functor {});
REQUIRE(func.sum == 1);
}
TEST_CASE("for_each(two)", "[algorithm/for_each]")
{
const std::array arr = {1, 2};
const auto func = based::for_each(std::begin(arr), std::end(arr), functor {});
REQUIRE(func.sum == 3);
}
TEST_CASE("for_each(three)", "[algorithm/for_each]")
{
const std::array arr = {1, 2, 3};
const auto func = based::for_each(std::begin(arr), std::end(arr), functor {});
REQUIRE(func.sum == 6);
}
TEST_CASE("for_each_n(empty)", "[algorithm/for_each_n]")
{
const std::array<int, 0> arr = {};
const auto [f, itr] =
based::for_each_n(std::begin(arr), std::size(arr), functor {});
REQUIRE(f.sum == 0);
REQUIRE(itr == std::end(arr));
}
TEST_CASE("for_each_n(one)", "[algorithm/for_each_n]")
{
const std::array arr = {1};
const auto [f, itr] =
based::for_each_n(std::begin(arr), std::size(arr), functor {});
REQUIRE(f.sum == 1);
REQUIRE(itr == std::end(arr));
}
TEST_CASE("for_each_n(two)", "[algorithm/for_each_n]")
{
const std::array arr = {1, 2};
const auto [f, itr] =
based::for_each_n(std::begin(arr), std::size(arr), functor {});
REQUIRE(f.sum == 3);
REQUIRE(itr == std::end(arr));
}
TEST_CASE("for_each_n(three)", "[algorithm/for_each_n]")
{
const std::array arr = {1, 2, 3};
const auto [f, itr] =
based::for_each_n(std::begin(arr), std::size(arr), functor {});
REQUIRE(f.sum == 6);
REQUIRE(itr == std::end(arr));
}
diff --git a/ test/source/algorithms/lower_bound_test.cpp b/ test/source/algorithms/lower_bound_test.cpp
@@ -1,48 +0,0 @@
#include <array>
#include "based/algorithms/bsearch/lower_bound.hpp"
#include <catch2/catch_test_macros.hpp>
struct equal
{
auto operator()(int a) const { return a == goal; }
int goal;
};
TEST_CASE("lower_bound(empty)", "[algorithm/lower_bound]")
{
std::array<int, 0> arr = {};
const auto* itr =
based::lower_bound(std::begin(arr), std::end(arr), 4, std::less<int> {});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("lower_bound(one equal)", "[algorithm/lower_bound]")
{
std::array arr = {4};
const auto* itr =
based::lower_bound(std::begin(arr), std::end(arr), 4, std::less<int> {});
REQUIRE(itr == std::begin(arr));
}
TEST_CASE("lower_bound(one nonequal)", "[algorithm/lower_bound]")
{
std::array arr = {1};
const auto* itr =
based::lower_bound(std::begin(arr), std::end(arr), 4, std::less<int> {});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("lower_bound(sequence)", "[algorithm/lower_bound]")
{
std::array arr = {0, 1, 2, 3, 3, 4};
const auto* itr =
based::lower_bound(std::begin(arr), std::end(arr), 3, std::less<int> {});
REQUIRE(itr == std::next(std::begin(arr), 3));
}
diff --git a/ test/source/algorithms/max_element_test.cpp b/ test/source/algorithms/max_element_test.cpp
@@ -1,92 +0,0 @@
#include <array>
#include "based/algorithms/minmax/max_element.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("max_element(empty)", "[algorithm/max_element]")
{
const std::array<int, 0> arr = {};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
REQUIRE(itr == std::end(arr));
}
TEST_CASE("max_element(1)", "[algorithm/max_element]")
{
const std::array arr = {0};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("max_element(2) = first", "[algorithm/max_element]")
{
const std::array arr = {1, 0};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("max_element(2) = second", "[algorithm/max_element]")
{
const std::array arr = {0, 1};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
TEST_CASE("max_element(2) = stable", "[algorithm/max_element]")
{
const std::array arr = {0, 0};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
TEST_CASE("max_element(3) = first", "[algorithm/max_element]")
{
const std::array arr = {2, 1, 0};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("max_element(3) = second", "[algorithm/max_element]")
{
const std::array arr = {1, 2, 0};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
TEST_CASE("max_element(3) = third", "[algorithm/max_element]")
{
const std::array arr = {0, 1, 2};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 2);
}
TEST_CASE("max_element(3) = stable(1, 2)", "[algorithm/max_element]")
{
const std::array arr = {1, 1, 0};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
TEST_CASE("max_element(3) = stable(1, 3)", "[algorithm/max_element]")
{
const std::array arr = {1, 0, 1};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 2);
}
TEST_CASE("max_element(3) = stable(2, 3)", "[algorithm/max_element]")
{
const std::array arr = {0, 1, 1};
const auto* itr = based::max_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 2);
}
diff --git a/ test/source/algorithms/max_test.cpp b/ test/source/algorithms/max_test.cpp
@@ -1,6 +1,6 @@
#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
#include "based/algorithms/minmax/max.hpp"
#include "based/algorithms/max.hpp"
#include <catch2/catch_test_macros.hpp>
diff --git a/ test/source/algorithms/min_element_test.cpp b/ test/source/algorithms/min_element_test.cpp
@@ -1,92 +0,0 @@
#include <array>
#include "based/algorithms/minmax/min_element.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("min_element(empty)", "[algorithm/min_element]")
{
const std::array<int, 0> arr = {};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
REQUIRE(itr == std::end(arr));
}
TEST_CASE("min_element(1)", "[algorithm/min_element]")
{
const std::array arr = {0};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("min_element(2) = first", "[algorithm/min_element]")
{
const std::array arr = {0, 1};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("min_element(2) = second", "[algorithm/min_element]")
{
const std::array arr = {1, 0};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
TEST_CASE("min_element(2) = stable", "[algorithm/min_element]")
{
const std::array arr = {0, 0};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("min_element(3) = first", "[algorithm/min_element]")
{
const std::array arr = {0, 1, 2};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("min_element(3) = second", "[algorithm/min_element]")
{
const std::array arr = {1, 0, 2};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
TEST_CASE("min_element(3) = third", "[algorithm/min_element]")
{
const std::array arr = {2, 1, 0};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 2);
}
TEST_CASE("min_element(3) = stable(1, 2)", "[algorithm/min_element]")
{
const std::array arr = {0, 0, 1};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("min_element(3) = stable(1, 3)", "[algorithm/min_element]")
{
const std::array arr = {0, 1, 0};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 0);
}
TEST_CASE("min_element(3) = stable(2, 3)", "[algorithm/min_element]")
{
const std::array arr = {1, 0, 0};
const auto* itr = based::min_element(std::begin(arr), std::end(arr));
const auto idx = std::distance(std::cbegin(arr), itr);
REQUIRE(idx == 1);
}
diff --git a/ test/source/algorithms/min_test.cpp b/ test/source/algorithms/min_test.cpp
@@ -1,6 +1,6 @@
#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
#include "based/algorithms/minmax/min.hpp"
#include "based/algorithms/min.hpp"
#include <catch2/catch_test_macros.hpp>
diff --git a/ test/source/algorithms/minmax_element_test.cpp b/ test/source/algorithms/minmax_element_test.cpp
@@ -1,101 +0,0 @@
#include "based/algorithms/minmax/minmax_element.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("minmax_element(empty)", "[algorithm/minmax_element]")
{
const std::array<int, 0> arr = {};
const auto [min, max] = based::minmax_element(std::begin(arr), std::end(arr));
REQUIRE(min == std::end(arr));
REQUIRE(max == std::end(arr));
}
TEST_CASE("minmax_element(1)", "[algorithm/minmax_element]")
{
const std::array arr = {0};
const auto [min, max] = based::minmax_element(std::begin(arr), std::end(arr));
const auto mini = std::distance(std::begin(arr), min);
const auto maxi = std::distance(std::begin(arr), max);
REQUIRE(mini == 0);
REQUIRE(maxi == 0);
}
TEST_CASE("minmax_element(increasing even)", "[algorithm/minmax_element]")
{
const std::array arr = {0, 1, 2, 3};
const auto [min, max] = based::minmax_element(std::begin(arr), std::end(arr));
const auto mini = std::distance(std::begin(arr), min);
const auto maxi = std::distance(std::begin(arr), max);
REQUIRE(mini == 0);
REQUIRE(maxi == std::size(arr) - 1);
}
TEST_CASE("minmax_element(increasing odd)", "[algorithm/minmax_element]")
{
const std::array arr = {0, 1, 2, 3, 4};
const auto [min, max] = based::minmax_element(std::begin(arr), std::end(arr));
const auto mini = std::distance(std::begin(arr), min);
const auto maxi = std::distance(std::begin(arr), max);
REQUIRE(mini == 0);
REQUIRE(maxi == std::size(arr) - 1);
}
TEST_CASE("minmax_element(decreasing even)", "[algorithm/minmax_element]")
{
const std::array arr = {3, 2, 1, 0};
const auto [min, max] = based::minmax_element(std::begin(arr), std::end(arr));
const auto mini = std::distance(std::begin(arr), min);
const auto maxi = std::distance(std::begin(arr), max);
REQUIRE(mini == std::size(arr) - 1);
REQUIRE(maxi == 0);
}
TEST_CASE("minmax_element(decreasing odd)", "[algorithm/minmax_element]")
{
const std::array arr = {4, 3, 2, 1, 0};
const auto [min, max] = based::minmax_element(std::begin(arr), std::end(arr));
const auto mini = std::distance(std::begin(arr), min);
const auto maxi = std::distance(std::begin(arr), max);
REQUIRE(mini == std::size(arr) - 1);
REQUIRE(maxi == 0);
}
TEST_CASE("minmax_element(stable even)", "[algorithm/minmax_element]")
{
const std::array arr = {3, 0, 0, 3};
const auto [min, max] = based::minmax_element(std::begin(arr), std::end(arr));
const auto mini = std::distance(std::begin(arr), min);
const auto maxi = std::distance(std::begin(arr), max);
REQUIRE(mini == 1);
REQUIRE(maxi == std::size(arr) - 1);
}
TEST_CASE("minmax_element(stable odd)", "[algorithm/minmax_element]")
{
const std::array arr = {3, 0, 3, 3, 0};
const auto [min, max] = based::minmax_element(std::begin(arr), std::end(arr));
const auto mini = std::distance(std::begin(arr), min);
const auto maxi = std::distance(std::begin(arr), max);
REQUIRE(mini == 1);
REQUIRE(maxi == std::size(arr) - 2);
}
TEST_CASE("minmax_element(stable increasing)", "[algorithm/minmax_element]")
{
const std::array arr = {0, 0, 1, 2, 3, 4, 4};
const auto [min, max] = based::minmax_element(std::begin(arr), std::end(arr));
const auto mini = std::distance(std::begin(arr), min);
const auto maxi = std::distance(std::begin(arr), max);
REQUIRE(mini == 0);
REQUIRE(maxi == std::size(arr) - 1);
}
TEST_CASE("minmax_element(stable decreasing)", "[algorithm/minmax_element]")
{
const std::array arr = {4, 4, 3, 2, 1, 0, 0};
const auto [min, max] = based::minmax_element(std::begin(arr), std::end(arr));
const auto mini = std::distance(std::begin(arr), min);
const auto maxi = std::distance(std::begin(arr), max);
REQUIRE(mini == std::size(arr) - 2);
REQUIRE(maxi == 1);
}
diff --git a/ test/source/algorithms/none_test.cpp b/ test/source/algorithms/none_test.cpp
@@ -1,65 +0,0 @@
#include <array>
#include "based/algorithms/search/none.hpp"
#include <catch2/catch_test_macros.hpp>
struct predicate
{
int goal;
explicit predicate(int init)
: goal(init)
{
}
auto operator()(int n) const { return n == goal; }
};
TEST_CASE("none(empty)", "[algorithm/none]")
{
const std::array<int, 0> arr = {};
REQUIRE(based::none(std::begin(arr), std::end(arr), predicate {0}));
}
TEST_CASE("none(homogeneous)", "[algorithm/none]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
REQUIRE(based::none(std::begin(arr), std::end(arr), predicate {2}));
REQUIRE(!based::none(std::begin(arr), std::end(arr), predicate {1}));
}
TEST_CASE("none(non homogeneous)", "[algorithm/none]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
REQUIRE(based::none(std::begin(arr), std::end(arr), predicate {0}));
REQUIRE(!based::none(std::begin(arr), std::end(arr), predicate {2}));
REQUIRE(!based::none(std::begin(arr), std::end(arr), predicate {1}));
}
TEST_CASE("none_n(empty)", "[algorithm/none_n]")
{
const std::array<int, 0> arr = {};
REQUIRE(based::none_n(std::begin(arr), std::size(arr), predicate {0}));
}
TEST_CASE("none_n(homogeneous)", "[algorithm/none_n]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
REQUIRE(based::none_n(std::begin(arr), std::size(arr), predicate {2}));
REQUIRE(!based::none_n(std::begin(arr), std::size(arr), predicate {1}));
}
TEST_CASE("none_n(non homogeneous)", "[algorithm/none_n]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
REQUIRE(based::none_n(std::begin(arr), std::size(arr), predicate {0}));
REQUIRE(!based::none_n(std::begin(arr), std::size(arr), predicate {2}));
REQUIRE(!based::none_n(std::begin(arr), std::size(arr), predicate {1}));
}
diff --git a/ test/source/algorithms/not_all_test.cpp b/ test/source/algorithms/not_all_test.cpp
@@ -1,65 +0,0 @@
#include <array>
#include "based/algorithms/search/not_all.hpp"
#include <catch2/catch_test_macros.hpp>
struct predicate
{
int goal;
explicit predicate(int init)
: goal(init)
{
}
auto operator()(int n) const { return n == goal; }
};
TEST_CASE("not_all(empty)", "[algorithm/not_all]")
{
const std::array<int, 0> arr = {};
REQUIRE(based::not_all(std::begin(arr), std::end(arr), predicate {0}));
}
TEST_CASE("not_all(homogeneous)", "[algorithm/not_all]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
REQUIRE(based::not_all(std::begin(arr), std::end(arr), predicate {2}));
REQUIRE(!based::not_all(std::begin(arr), std::end(arr), predicate {1}));
}
TEST_CASE("not_all(non homogeneous)", "[algorithm/not_all]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
REQUIRE(based::not_all(std::begin(arr), std::end(arr), predicate {0}));
REQUIRE(based::not_all(std::begin(arr), std::end(arr), predicate {1}));
REQUIRE(based::not_all(std::begin(arr), std::end(arr), predicate {2}));
}
TEST_CASE("not_all_n(empty)", "[algorithm/not_all_n]")
{
const std::array<int, 0> arr = {};
REQUIRE(based::not_all_n(std::begin(arr), std::size(arr), predicate {0}));
}
TEST_CASE("not_all_n(homogeneous)", "[algorithm/not_all_n]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
REQUIRE(based::not_all_n(std::begin(arr), std::size(arr), predicate {2}));
REQUIRE(!based::not_all_n(std::begin(arr), std::size(arr), predicate {1}));
}
TEST_CASE("not_all_n(non homogeneous)", "[algorithm/not_all_n]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
REQUIRE(based::not_all_n(std::begin(arr), std::size(arr), predicate {0}));
REQUIRE(based::not_all_n(std::begin(arr), std::size(arr), predicate {1}));
REQUIRE(based::not_all_n(std::begin(arr), std::size(arr), predicate {2}));
}
diff --git a/ test/source/algorithms/partition_point_test.cpp b/ test/source/algorithms/partition_point_test.cpp
@@ -1,48 +0,0 @@
#include <array>
#include "based/algorithms/sort/partition_point.hpp"
#include <catch2/catch_test_macros.hpp>
struct equal
{
auto operator()(int a) const { return a == goal; }
int goal;
};
TEST_CASE("partition_point(empty)", "[algorithm/partition_point]")
{
std::array<int, 0> arr = {};
const auto* itr =
based::partition_point(std::begin(arr), std::end(arr), equal {4});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("partition_point(one equal)", "[algorithm/partition_point]")
{
std::array arr = {4};
const auto* itr =
based::partition_point(std::begin(arr), std::end(arr), equal {4});
REQUIRE(itr == std::begin(arr));
}
TEST_CASE("partition_point(one nonequal)", "[algorithm/partition_point]")
{
std::array arr = {1};
const auto* itr =
based::partition_point(std::begin(arr), std::end(arr), equal {4});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("partition_point(sequence)", "[algorithm/partition_point]")
{
std::array arr = {0, 1, 2, 3, 4, 4, 4, 4};
const auto* itr =
based::partition_point(std::begin(arr), std::end(arr), equal {4});
REQUIRE(itr == std::next(std::begin(arr), 4));
}
diff --git a/ test/source/algorithms/partitioned_test.cpp b/ test/source/algorithms/partitioned_test.cpp
@@ -1,53 +0,0 @@
#include <array>
#include "based/algorithms/sort/partitioned.hpp"
#include <catch2/catch_test_macros.hpp>
struct equal
{
auto operator()(int a) const { return a == goal; }
int goal;
};
TEST_CASE("partitioned(empty)", "[algorithm/partitioned]")
{
std::array<int, 0> arr = {};
REQUIRE(based::partitioned(std::begin(arr), std::end(arr), equal {4}));
}
TEST_CASE("partitioned(one equal)", "[algorithm/partitioned]")
{
std::array arr = {4};
REQUIRE(based::partitioned(std::begin(arr), std::end(arr), equal {4}));
}
TEST_CASE("partitioned(one nonequal)", "[algorithm/partitioned]")
{
std::array arr = {1};
REQUIRE(based::partitioned(std::begin(arr), std::end(arr), equal {4}));
}
TEST_CASE("partitioned(partitioned)", "[algorithm/partitioned]")
{
std::array arr = {0, 1, 2, 3, 4, 4, 4, 4};
REQUIRE(based::partitioned(std::begin(arr), std::end(arr), equal {4}));
}
TEST_CASE("partitioned(nonpartitioned equal)", "[algorithm/partitioned]")
{
std::array arr = {4, 0, 1, 2, 3, 4, 4, 4};
REQUIRE(!based::partitioned(std::begin(arr), std::end(arr), equal {4}));
}
TEST_CASE("partitioned(nonpartitioned nonequal)", "[algorithm/partitioned]")
{
std::array arr = {4, 0, 1, 2, 3, 4, 4, 4, 0};
REQUIRE(!based::partitioned(std::begin(arr), std::end(arr), equal {4}));
}
diff --git a/ test/source/algorithms/reduce_test.cpp b/ test/source/algorithms/reduce_test.cpp
@@ -1,69 +0,0 @@
#include <array>
#include <vector>
#include <catch2/catch_test_macros.hpp>
#include "based/algorithms/numeric/accumulate.hpp"
struct op
{
auto operator()(const auto& lhs, const auto& rhs) { return lhs + rhs; }
};
struct fun
{
auto operator()(based::Iterator auto itr) { return *itr; }
};
TEST_CASE("accumulate_nonempty(sequence)", "[algorithm/accumulate_nonempty]")
{
const std::array arr = {0, 1, 2, 3, 4, 5};
const auto count = based::accumulate_nonempty(
std::cbegin(arr), std::cend(arr), op {}, fun {}
);
REQUIRE(count == 15);
}
TEST_CASE("accumulate(empty)", "[algorithm/accumulate]")
{
const std::array<int, 0> arr = {};
const auto count =
based::accumulate(std::cbegin(arr), std::cend(arr), op {}, fun {}, 0);
REQUIRE(count == 0);
}
TEST_CASE("accumulate(sequence)", "[algorithm/accumulate]")
{
const std::array arr = {0, 1, 2, 3, 4, 5};
const auto count =
based::accumulate(std::cbegin(arr), std::cend(arr), op {}, fun {}, 0);
REQUIRE(count == 15);
}
TEST_CASE("accumulate_nonzero(empty)", "[algorithm/accumulate_nonzero]")
{
const std::array<int, 0> arr = {};
const auto count = based::accumulate_nonzero(
std::cbegin(arr), std::cend(arr), op {}, fun {}, 0
);
REQUIRE(count == 0);
}
TEST_CASE("accumulate_nonzero(sequence)", "[algorithm/accumulate_nonzero]")
{
const std::array arr = {0, 1, 2, 3, 4, 5};
const auto count = based::accumulate_nonzero(
std::cbegin(arr), std::cend(arr), op {}, fun {}, 0
);
REQUIRE(count == 15);
}
diff --git a/ test/source/algorithms/some_test.cpp b/ test/source/algorithms/some_test.cpp
@@ -1,65 +0,0 @@
#include <array>
#include "based/algorithms/search/some.hpp"
#include <catch2/catch_test_macros.hpp>
struct predicate
{
int goal;
explicit predicate(int init)
: goal(init)
{
}
auto operator()(int n) const { return n == goal; }
};
TEST_CASE("some(empty)", "[algorithm/some]")
{
const std::array<int, 0> arr = {};
REQUIRE(!based::some(std::begin(arr), std::end(arr), predicate {0}));
}
TEST_CASE("some(homogeneous)", "[algorithm/some]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
REQUIRE(based::some(std::begin(arr), std::end(arr), predicate {1}));
REQUIRE(!based::some(std::begin(arr), std::end(arr), predicate {2}));
}
TEST_CASE("some(non homogeneous)", "[algorithm/some]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
REQUIRE(based::some(std::begin(arr), std::end(arr), predicate {1}));
REQUIRE(based::some(std::begin(arr), std::end(arr), predicate {2}));
REQUIRE(!based::some(std::begin(arr), std::end(arr), predicate {0}));
}
TEST_CASE("some_n(empty)", "[algorithm/some_n]")
{
const std::array<int, 0> arr = {};
REQUIRE(!based::some_n(std::begin(arr), std::size(arr), predicate {0}));
}
TEST_CASE("some_n(homogeneous)", "[algorithm/some_n]")
{
const std::array arr = {1, 1, 1, 1, 1, 1};
REQUIRE(based::some_n(std::begin(arr), std::size(arr), predicate {1}));
REQUIRE(!based::some_n(std::begin(arr), std::size(arr), predicate {2}));
}
TEST_CASE("some_n(non homogeneous)", "[algorithm/some_n]")
{
const std::array arr = {1, 2, 1, 1, 1, 2};
REQUIRE(based::some_n(std::begin(arr), std::size(arr), predicate {1}));
REQUIRE(based::some_n(std::begin(arr), std::size(arr), predicate {2}));
REQUIRE(!based::some_n(std::begin(arr), std::size(arr), predicate {0}));
}
diff --git a/ test/source/algorithms/upper_bound_test.cpp b/ test/source/algorithms/upper_bound_test.cpp
@@ -1,48 +0,0 @@
#include <array>
#include "based/algorithms/bsearch/upper_bound.hpp"
#include <catch2/catch_test_macros.hpp>
struct equal
{
auto operator()(int a) const { return a == goal; }
int goal;
};
TEST_CASE("upper_bound(empty)", "[algorithm/lower_bound]")
{
std::array<int, 0> arr = {};
const auto* itr =
based::upper_bound(std::begin(arr), std::end(arr), 4, std::less<int> {});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("upper_bound(one equal)", "[algorithm/lower_bound]")
{
std::array arr = {4};
const auto* itr =
based::upper_bound(std::begin(arr), std::end(arr), 4, std::less<int> {});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("upper_bound(one nonequal)", "[algorithm/lower_bound]")
{
std::array arr = {1};
const auto* itr =
based::upper_bound(std::begin(arr), std::end(arr), 4, std::less<int> {});
REQUIRE(itr == std::end(arr));
}
TEST_CASE("upper_bound(sequence)", "[algorithm/lower_bound]")
{
std::array arr = {0, 1, 2, 3, 3, 4};
const auto* itr =
based::upper_bound(std::begin(arr), std::end(arr), 3, std::less<int> {});
REQUIRE(itr == std::next(std::begin(arr), 5));
}