Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Numeric ranges #312

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions include/stl2/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <stl2/detail/concepts/core.hpp>
#include <stl2/detail/concepts/function.hpp>
#include <stl2/detail/concepts/fundamental.hpp>
#include <stl2/detail/concepts/numeric.hpp>
#include <stl2/detail/concepts/object.hpp>
#include <stl2/detail/concepts/urng.hpp>
#include <stl2/detail/iostream/concepts.hpp>
Expand Down
18 changes: 18 additions & 0 deletions include/stl2/detail/algorithm/results.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,24 @@
#include <stl2/detail/concepts/core.hpp>

STL2_OPEN_NAMESPACE {
template<class I, class T>
struct __in_value_result {
STL2_NO_UNIQUE_ADDRESS I in;
STL2_NO_UNIQUE_ADDRESS T value;

// Extension: the dangling story actually works.
template<class I2, class T2>
requires ConvertibleTo<const I&, I2> && ConvertibleTo<const T&, T2>
operator __in_value_result<I2, T2>() const& {
return {in, value};
}
template<class I2, class T2>
requires ConvertibleTo<I, I2> && ConvertibleTo<T, T2>
operator __in_value_result<I2, T2>() && {
return {std::move(in), std::move(value)};
}
};

template<class I, class O>
struct __in_out_result {
STL2_NO_UNIQUE_ADDRESS I in;
Expand Down
53 changes: 53 additions & 0 deletions include/stl2/detail/concepts/numeric.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// cmcstl2 - A concept-enabled C++ standard library
//
// Copyright Casey Carter
// Copyright Christopher Di Bella
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/caseycarter/cmcstl2
//
#ifndef STL2_DETAIL_CONCEPTS_NUMERIC_HPP
#define STL2_DETAIL_CONCEPTS_NUMERIC_HPP

#include <stl2/detail/concepts/numeric/magma.hpp>
#include <stl2/detail/concepts/numeric/semigroup.hpp>
#include <stl2/detail/concepts/numeric/monoid.hpp>
#include <stl2/detail/concepts/callable.hpp>
#include <stl2/detail/fwd.hpp>

STL2_OPEN_NAMESPACE {
namespace ext {
template<class BOp, class I1, class I2, class O>
META_CONCEPT IndirectMagma =
Readable<I1> &&
Readable<I2> &&
Writable<O, indirect_result_t<BOp&, I1, I2>> &&
Magma<BOp&, iter_value_t<I1>&, iter_value_t<I2>&> &&
Magma<BOp&, iter_value_t<I1>&, iter_reference_t<I2>&> &&
Magma<BOp&, iter_reference_t<I1>, iter_value_t<I2>&> &&
Magma<BOp&, iter_reference_t<I1>, iter_reference_t<I2>> &&
Magma<BOp&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;

template<class BOp, class I1, class I2, class O>
META_CONCEPT IndirectSemigroup = IndirectMagma<BOp, I1, I2, O> &&
Semigroup<BOp&, iter_value_t<I1>&, iter_value_t<I2>&> &&
Semigroup<BOp&, iter_value_t<I1>&, iter_reference_t<I2>&> &&
Semigroup<BOp&, iter_reference_t<I1>, iter_value_t<I2>&> &&
Semigroup<BOp&, iter_reference_t<I1>, iter_reference_t<I2>> &&
Semigroup<BOp&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;

template<class BOp, class I1, class I2, class O>
META_CONCEPT IndirectMonoid = IndirectSemigroup<BOp, I1, I2, O> &&
Monoid<BOp&, iter_value_t<I1>&, iter_value_t<I2>&> &&
Monoid<BOp&, iter_value_t<I1>&, iter_reference_t<I2>&> &&
Monoid<BOp&, iter_reference_t<I1>, iter_value_t<I2>&> &&
Monoid<BOp&, iter_reference_t<I1>, iter_reference_t<I2>> &&
Monoid<BOp&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;
} // namespace ext
} STL2_CLOSE_NAMESPACE

#endif // STL2_DETAIL_CONCEPTS_NUMERIC_HPP
39 changes: 39 additions & 0 deletions include/stl2/detail/concepts/numeric/magma.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// cmcstl2 - A concept-enabled C++ standard library
//
// Copyright Casey Carter
// Copyright Christopher Di Bella
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/caseycarter/cmcstl2
//
#ifndef STL2_DETAIL_CONCEPTS_NUMERIC_MAGMA_HPP
#define STL2_DETAIL_CONCEPTS_NUMERIC_MAGMA_HPP

#include <stl2/detail/concepts/core.hpp>
#include <stl2/detail/concepts/function.hpp>
#include <stl2/detail/fwd.hpp>

STL2_OPEN_NAMESPACE {
namespace ext {
template<class BOp, class T, class U>
META_CONCEPT Magma =
Common<T, U> &&
RegularInvocable<BOp, T, T> &&
RegularInvocable<BOp, U, U> &&
RegularInvocable<BOp, T, U> &&
RegularInvocable<BOp, U, T> &&
Common<invoke_result_t<BOp&, T, U>, T> &&
Common<invoke_result_t<BOp&, T, U>, U> &&
Same<invoke_result_t<BOp&, T, U>, invoke_result_t<BOp&, U, T>>;
// axiom: Let `bop` be an object of type `BOp`, `t` be an object of type `T`, and `u` be an
// object of type `U`. The expression `invoke(bop, t, u)` must return a result that is
// representable by `common_type_t<T, U>`.
// axiom: The result of `invoke(bop, t, u)` needn't be the same as `invoke(bop, u, t)`.
} // namespace ext
} STL2_CLOSE_NAMESPACE

#endif // STL2_DETAIL_CONCEPTS_NUMERIC_MAGMA_HPP
29 changes: 29 additions & 0 deletions include/stl2/detail/concepts/numeric/monoid.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// cmcstl2 - A concept-enabled C++ standard library
//
// Copyright Casey Carter
// Copyright Christopher Di Bella
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/caseycarter/cmcstl2
//
#ifndef STL2_DETAIL_CONCEPTS_NUMERIC_MONOID_HPP
#define STL2_DETAIL_CONCEPTS_NUMERIC_MONOID_HPP

#include <stl2/detail/concepts/numeric/semigroup.hpp>
#include <stl2/detail/fwd.hpp>
#include <stl2/detail/numeric_traits/identity.hpp>

STL2_OPEN_NAMESPACE {
namespace ext {
template<class BOp, class T, class U>
META_CONCEPT Monoid = Semigroup<BOp, T, U> && requires {
typename two_sided_identity_t<BOp, __uncvref<T>, __uncvref<U>>;
};
} // namespace ext
} STL2_CLOSE_NAMESPACE

#endif // STL2_DETAIL_CONCEPTS_NUMERIC_MONOID_HPP
29 changes: 29 additions & 0 deletions include/stl2/detail/concepts/numeric/semigroup.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// cmcstl2 - A concept-enabled C++ standard library
//
// Copyright Casey Carter
// Copyright Christopher Di Bella
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/caseycarter/cmcstl2
//
#ifndef STL2_DETAIL_CONCEPTS_NUMERIC_SEMIGROUP_HPP
#define STL2_DETAIL_CONCEPTS_NUMERIC_SEMIGROUP_HPP

#include <stl2/detail/concepts/numeric/magma.hpp>
#include <stl2/detail/fwd.hpp>

STL2_OPEN_NAMESPACE {
namespace ext {
template<class BOp, class T, class U>
META_CONCEPT Semigroup = Magma<BOp, T, U>;
// axiom: Let `bop` be an object of type `BOp`, `t` be an object of type `T`, and `u` be an
// object of type `U`. The expression `invoke(bop, t, invoke(bop, t, u))` is
// expression-equivalent to `invoke(bop, invoke(bop, t, u), u)`.
} // namespace ext
} STL2_CLOSE_NAMESPACE

#endif // STL2_DETAIL_CONCEPTS_NUMERIC_SEMIGROUP_HPP
23 changes: 23 additions & 0 deletions include/stl2/detail/functional/arithmetic.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// cmcstl2 - A concept-enabled C++ standard library
//
// Copyright Casey Carter
// Copyright Christopher Di Bella
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/caseycarter/cmcstl2
//
#ifndef STL2_DETAIL_FUNCTIONAL_ARITHMETIC_HPP
#define STL2_DETAIL_FUNCTIONAL_ARITHMETIC_HPP

#include <stl2/detail/functional/arithmetic/plus.hpp>
#include <stl2/detail/functional/arithmetic/minus.hpp>
#include <stl2/detail/functional/arithmetic/negate.hpp>
#include <stl2/detail/functional/arithmetic/product.hpp>
#include <stl2/detail/functional/arithmetic/quotient.hpp>
#include <stl2/detail/functional/arithmetic/modulus.hpp>

#endif // STL2_DETAIL_FUNCTIONAL_ARITHMETIC_HPP
64 changes: 64 additions & 0 deletions include/stl2/detail/functional/arithmetic/minus.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// cmcstl2 - A concept-enabled C++ standard library
//
// Copyright Casey Carter
// Copyright Christopher Di Bella
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/caseycarter/cmcstl2
//
#ifndef STL2_DETAIL_FUNCTIONAL_ARITHMETIC_MINUS_HPP
#define STL2_DETAIL_FUNCTIONAL_ARITHMETIC_MINUS_HPP

#include <stl2/detail/concepts/core.hpp>
#include <stl2/detail/functional/arithmetic/plus.hpp>
#include <stl2/detail/functional/arithmetic/negate.hpp>
#include <stl2/detail/fwd.hpp>
#include <stl2/detail/numeric_traits/identity.hpp>
#include <type_traits>
#include <utility>

STL2_OPEN_NAMESPACE {
namespace ext {
template<class T, class U>
META_CONCEPT __differenceable_with =
__summable_with<T, U> &&
__negatable<T> &&
__negatable<U> &&
requires(__uncvref<T> t, __uncvref<U> u) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that T and U have had their cv- and ref-qualifiers removed, but I can't think of a better way to implement this at the moment.

{ t -= std::forward<U>(u) } -> CommonReference<T&>;
{ u -= std::forward<T>(t) } -> CommonReference<U&>;
{ std::forward<T>(t) - std::forward<T>(t) } -> Common<T>;
{ std::forward<U>(u) - std::forward<U>(u) } -> Common<U>;
{ std::forward<T>(t) - std::forward<U>(u) } -> Common<T>;
{ std::forward<T>(t) - std::forward<U>(u) } -> Common<U>;
requires Same<decltype(std::forward<T>(t) - std::forward<U>(u)),
decltype(std::forward<U>(t) - std::forward<T>(u))>;
};
// axiom: `t - t` is equivalent to `T{}`
// axiom: `t - (-t)` is equivalent to `t + t`
// axiom: `-t - t` is equivalent to `-(t + t)`
// axiom: `t + t - t` is equivalent to `t`

struct minus {
template<class T, __differenceable_with<T> U>
constexpr decltype(auto) operator()(T&& t, U&& u) const {
return std::forward<T>(t) - std::forward<U>(u);
}

using is_transparent = std::true_type;
};

template<class T, class U>
requires Magma<__stl2::ext::minus, T, U>
struct right_identity<__stl2::ext::minus, T, U>
: private right_identity<__stl2::ext::plus, T, U> {
using right_identity<__stl2::ext::plus, T, U>::value;
};
} // namespace ext
} STL2_CLOSE_NAMESPACE

#endif // STL2_DETAIL_FUNCTIONAL_ARITHMETIC_MINUS_HPP
50 changes: 50 additions & 0 deletions include/stl2/detail/functional/arithmetic/modulus.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// cmcstl2 - A concept-enabled C++ standard library
//
// Copyright Casey Carter
// Copyright Christopher Di Bella
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/caseycarter/cmcstl2
//
#ifndef STL2_DETAIL_FUNCTIONAL_ARITHMETIC_MODULUS_HPP
#define STL2_DETAIL_FUNCTIONAL_ARITHMETIC_MODULUS_HPP

#include <stl2/detail/concepts/core.hpp>
#include <stl2/detail/functional/arithmetic/plus.hpp>
#include <stl2/detail/functional/arithmetic/quotient.hpp>
#include <stl2/detail/fwd.hpp>
#include <stl2/detail/numeric_traits/identity.hpp>
#include <type_traits>
#include <utility>

STL2_OPEN_NAMESPACE {
namespace ext {
template<class T, class U>
META_CONCEPT __modulo_with = __summable_with<T, U> && __divisible_with<T, U> &&
requires(__uncvref<T> t, __uncvref<U> u) {
{ t %= std::forward<U>(u) } -> CommonReference<T&>;
{ u %= std::forward<T>(t) } -> CommonReference<U&>;
{ std::forward<T>(t) % std::forward<T>(t) } -> Common<T>;
{ std::forward<U>(u) % std::forward<U>(u) } -> Common<U>;
{ std::forward<T>(t) % std::forward<U>(u) } -> Common<T>;
{ std::forward<T>(t) % std::forward<U>(u) } -> Common<U>;
requires Same<decltype(std::forward<T>(t) / std::forward<U>(u)),
decltype(std::forward<U>(t) / std::forward<T>(u))>;
};
// Let n, q, r, t all be distinct objects of type T.
// axiom: `t % q == q * r + n`

struct modulus {
template<class T, __modulo_with<T> U>
constexpr decltype(auto) operator()(T&& t, U&& u) const {
return std::forward<T>(t) % std::forward<U>(u);
}
};
} // namespace ext
} STL2_CLOSE_NAMESPACE

#endif // STL2_DETAIL_FUNCTIONAL_ARITHMETIC_MODULUS_HPP
39 changes: 39 additions & 0 deletions include/stl2/detail/functional/arithmetic/negate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// cmcstl2 - A concept-enabled C++ standard library
//
// Copyright Casey Carter
// Copyright Christopher Di Bella
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/caseycarter/cmcstl2
//
#ifndef STL2_DETAIL_FUNCTIONAL_ARITHMETIC_NEGATE_HPP
#define STL2_DETAIL_FUNCTIONAL_ARITHMETIC_NEGATE_HPP

#include <stl2/detail/concepts/core.hpp>
#include <stl2/detail/functional/arithmetic/plus.hpp>
#include <stl2/detail/fwd.hpp>
#include <stl2/detail/numeric_traits/identity.hpp>
#include <type_traits>
#include <utility>

STL2_OPEN_NAMESPACE {
template<class T>
META_CONCEPT __negatable = requires(T&& t) {
{ -std::forward<T>(t) } -> Common<T>;
};

struct negate {
template<__negatable T>
constexpr decltype(auto) operator()(T&& t) const {
return -std::forward<T>(t);
}

using is_transparent = std::true_type;
};
} STL2_CLOSE_NAMESPACE

#endif // STL2_DETAIL_FUNCTIONAL_ARITHMETIC_NEGATE_HPP