-
Notifications
You must be signed in to change notification settings - Fork 68
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
base: master
Are you sure you want to change the base?
Numeric ranges #312
Commits on Jun 26, 2019
-
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.
Configuration menu - View commit details
-
Copy full SHA for 1ace59c - Browse repository at this point
Copy the full SHA 1ace59cView commit details -
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.
Configuration menu - View commit details
-
Copy full SHA for 9d54dfd - Browse repository at this point
Copy the full SHA 9d54dfdView commit details -
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.
Configuration menu - View commit details
-
Copy full SHA for b0498f0 - Browse repository at this point
Copy the full SHA b0498f0View commit details -
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.
Configuration menu - View commit details
-
Copy full SHA for e0fe9af - Browse repository at this point
Copy the full SHA e0fe9afView commit details -
removes right_identity<modulus>
The given modulus right-identity was not actually an identity element.
Configuration menu - View commit details
-
Copy full SHA for f6a4292 - Browse repository at this point
Copy the full SHA f6a4292View commit details -
Configuration menu - View commit details
-
Copy full SHA for fb829d1 - Browse repository at this point
Copy the full SHA fb829d1View commit details -
adds ranges::adjacent_difference
This is a direct port of std::adjacent_difference, in the image of ranges::partial_sum.
Configuration menu - View commit details
-
Copy full SHA for 2b5331f - Browse repository at this point
Copy the full SHA 2b5331fView commit details -
Configuration menu - View commit details
-
Copy full SHA for fba4255 - Browse repository at this point
Copy the full SHA fba4255View commit details
Commits on Jun 29, 2019
-
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.
Configuration menu - View commit details
-
Copy full SHA for 6e7c3a3 - Browse repository at this point
Copy the full SHA 6e7c3a3View commit details