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

Numeric ranges #312

wants to merge 9 commits into from

Commits on Jun 26, 2019

  1. establishes the basis for numeric ranges

    This commit does all the necessary groundwork to get a basis for
    accumulate to be a ranges citizen. We achieve this by introducing:
    
    * the concept Magma
    * the concept IndirectMagma
    * a new set of arithmetic operation function objects
    * an accumulate niebloid
    * accumulate tests
    
    == Notes
    
    std::multiplies and std::divides have been renamed to `product` and
    `quotient`, respectively.
    
    Each arithmetic operation has its own detail concept that effectively
    check things like "has plus". Care was taken to ensure that the
    requirements for each operator were as complete as possible. For
    example, since subtraction is the inverse of addition, anything that
    supports ranges::ext::minus should also support ranges::ext::plus.
    
    == Known issues
    
    It's believed that each of the detail concepts are ill-specified with
    respect to references. For example, most expressions are checked à la
    `{ std::forward<T>(t) + std::forward<T>(t) } -> Common<T>;`, but the
    type of `t` is `__uncvref(t)` due to difficulties getting some
    expressions to compile. Reviewers should note this problem when
    evaluating the design of the detail concepts.
    cjdb committed Jun 26, 2019
    Configuration menu
    Copy the full SHA
    1ace59c View commit details
    Browse the repository at this point in the history
  2. adds algebraic concepts, identity numeric trait, and accumulate overl…

    …oads
    
    == change-log
    
    * shuffles around entities to remove circular dependencies introduced by
      this commit.
    * adds identity numeric traits
    * adds identities for all arithmetic operations
    * adds Semigroup concept
    * adds Monoid concept
    * adds IndirectSemigroup concept
    * adds IndirectMonoid concept
    * adds monoid overload subset for accumulate
    
    == left_identity, right_identity, and two_sided_identity
    
    The library needs to support two-sided identities in order to facilitate
    monoids and loops. Similarly to common_type, a user is allowed to
    specialise both left_identity and right_identity (they are in fact
    required to do so for an identity to exist). A user may not specialise
    the two_sided_identity template.
    
    A well-formed left_identity and right_identity specialisation has an
    explicit constructor taking a binary operation, a T, and a U. The
    constructor should also require that the binary operation is a magma
    over T and U. The identity specialisations also have a const-qualified
    value member function that returns the value of the identity.
    
    A well-formed two_sided_identity is only possible if the left_identity
    and the right_identity return the same type and value.
    
    All the arithmeric operations except for modulus added in ac25864 have
    been given either a left_identiy or a right_identity, but only plus and
    product have both.
    
    === Known issues
    
    left_identity and right_identity currently permit specialisations to
    also take a reference-to-const T or U. It is likely that this will cause
    lifetime issues, and the author is considering changing this from a
    reference to an object.
    
    == accumulate overload subset for monoid operations over T and U
    
    std::accumulate requires -- as input -- an initial value to determine
    the return type of the function. This was somewhat mitigated by the
    introduction of std::reduce, which has an overload only taking an
    iterator-pair. This is not a complete solution, as that overload is
    equivalent to calling the overload taking iter_value_t<I>{} and
    std::plus{}. In other words, `reduce(first, last)` is only possible
    if your reduction is an addition operation. The standard library
    prevents other operations from working because different operations
    treat values differently. For example, anything multiplied by zero is
    also zero, and it would have been flawed for the specification to
    permit this. The only safe option was to have the interface be a
    convenience for addition.
    
    The niebloid-equivalent accumulate has been designed so that there are
    two overload subsets: the magma overload subset and the monoid overload
    subset. The magma overload subset is the rangified equivalent of
    std::accumulate, requires only that the binary operation models a Magma
    over T and U, and was commit in ac25864. The monoid overload subset
    refines the requirements by requiring the binary operation model a
    Monoid over T and U. Because a monoid requires that the operation have a
    two-sided identity, we're able to provide a pair of overloads that don't
    need an initial value for any operation: a user can simply specialise
    the left_identity and right_identity numeric-traits, and accumulate will
    take care of the rest.
    
    === Known issues
    
    The decision for this overload subset to require a monoid instead of
    just a left_identity is because accumulate perfoms a left-fold
    operation, and C++ does not have a right-fold operation. To get a
    right-fold, one must iterate over the range in reverse, and so requiring
    only a left_identity is too weak. A monoid is perhaps over-constraining,
    as the monoid subset will reject a subtractive fold, even though
    associativity isn't required. It's unclear to the author how to proceed
    in this manner.
    cjdb committed Jun 26, 2019
    Configuration menu
    Copy the full SHA
    9d54dfd View commit details
    Browse the repository at this point in the history
  3. adds negate function object, fixes minus requirements, adjusts whit…

    …espace
    
    The ranges-equivalent of std::negate was forgotten in the previous
    commit. This commit is to rectify that mistake.
    
    The requirement for a type to have a unary operator- is now under the
    jurisdiction of the implementation-detail concept __negatable, which is
    refined by __differenceable_with. A slight bug was identified: -t should
    not be required to return the same type as T, but rather a type in
    common with T.
    
    Finally, there were a few whitespace issues that were noticed. They've
    been cleaned up.
    cjdb committed Jun 26, 2019
    Configuration menu
    Copy the full SHA
    b0498f0 View commit details
    Browse the repository at this point in the history
  4. adds ranges::ext::partial_sum

    The design of this algorithm is slightly different to the one found in
    range-v3, as it has a slightly weaker requirement. The range-v3 cousin
    requires the binary operation to be a semigroup over the projection of
    I; but the author couldn't see a reason for partial_sum to require
    associativity. As such, the implementation here only requires that the
    binary operation model a magma over the projection of I.
    cjdb committed Jun 26, 2019
    Configuration menu
    Copy the full SHA
    e0fe9af View commit details
    Browse the repository at this point in the history
  5. removes right_identity<modulus>

    The given modulus right-identity was not actually an identity element.
    cjdb committed Jun 26, 2019
    Configuration menu
    Copy the full SHA
    f6a4292 View commit details
    Browse the repository at this point in the history
  6. changes copyright and licencing

    cjdb committed Jun 26, 2019
    Configuration menu
    Copy the full SHA
    fb829d1 View commit details
    Browse the repository at this point in the history
  7. adds ranges::adjacent_difference

    This is a direct port of std::adjacent_difference, in the image of
    ranges::partial_sum.
    cjdb committed Jun 26, 2019
    Configuration menu
    Copy the full SHA
    2b5331f View commit details
    Browse the repository at this point in the history
  8. updates to spacing

    cjdb committed Jun 26, 2019
    Configuration menu
    Copy the full SHA
    fba4255 View commit details
    Browse the repository at this point in the history

Commits on Jun 29, 2019

  1. adds a test for numeric concepts and applies patches

    This is probably some of the most questionable code that I've written,
    but is necessary because C++20 doesn't support concept templates. The
    test attached demonstrates that Magma, Semigroup, and Monoid work as
    expected for lvalues, rvalues, and references. It's likely incomplete.
    
    The tests identified that there were a few errors embedded into the
    design of `two_sided_identity`, and promted a small patch to some code
    that GCC permits, but the IS does not.
    cjdb committed Jun 29, 2019
    Configuration menu
    Copy the full SHA
    6e7c3a3 View commit details
    Browse the repository at this point in the history