std.rational -- update and progress towards review
Joseph Rushton Wakeling
joseph.wakeling at webdrake.net
Wed Oct 2 07:25:53 PDT 2013
Hello all,
I thought I'd ask for some guidance here, since this is the first time I'm
involved in bringing a new Phobos module to review.
If I understand right, "review" means that I present a pull request to Phobos,
rather than just a standalone piece of code as currently available. The
question is how to handle various bits of std.rational that arguably could or
maybe should be implemented elsewhere in Phobos. Is there a preference to
present the module as-is, and have the review process decide what goes where, or
is it better to present the pull request including patches against other modules?
To help with answers to the above, I'll summarize the state of std.rational and
what I've done so far.
* std.rational is designed to allow the construction of rational numbers
based on any of the built-in integer types (it also works with char:-),
std.bigint.BigInt, or arbitrary user-defined "integer-like" types.
* Because it doesn't just want to work with built-in integer types, David
Simcha was forced to define custom versions of various functionality
found elsewhere in Phobos (or in some cases, perhaps at the time the
functionality simply was not there). Some of these have been deleted
in my recent updates as they are no longer necessary: e.g. today it is
fine to use std.math.abs, std.traits.isAssignable. Others remain, and
the question is how to handle these cases.
* David defines an isRational template, which is currently very simple
(it just checks that the type has numerator and denominator properties).
This presumably is fine to keep in std.rational and should not be moved
elsewhere.
* Because std.rational doesn't just want to work with built-in integer types
it can't rely on the existing isIntegral. Instead, David defined a new
template, "isIntegerLike", which checks the operations supported by the
type and whether they work in an integer-like way. Could/should this be
placed in std.traits? Better to do this in the initial pull or let the
decision be part of the review process?
* For similar reasons, CommonType is insufficient and David defined two
new templates, CommonInteger (which works out an appropriate common
type for two "integer-like" types) and CommonRational. The former at
least looks to me like it should be in std.traits. Again, better to
do this in the initial pull request, or make it a decision to take at
review time?
* Several Rational-based overrides for std.math functions are defined:
floor, ceil and round. I believe it's normal for such type-specific
overrides to be in the same module as their type?
* Finally, there are two mathematical functions, gcf (greatest common factor)
and lcm (least common multiple) which again are locally defined because
Phobos' existing std.math.gcd cannot handle BigInts (let alone any other
user-defined integer type). These should presumably be sent over to
std.math but that relies on isIntegerLike being accepted for std.traits,
or else some alternative type check being in place.
* (... actually, there is no lcm in std.math in any case. An oversight:-)
I need to do a careful review of the function attributes (there's a complete
lack of @safe, pure, nothrow, const, ... in the module, only @property is used),
but apart from that I think that the code is now working within the confines of
its design parameters, and in that sense is ready for review. I've squashed the
only overt bug found, added unittests to confirm this and to check other cases
(David's were already very extensive so I haven't needed to do much), updated
and corrected the docs and removed all unnecessary code duplication, and of
course also brought the code style in line with current Phobos standards.
The remaining open issues
<https://github.com/WebDrake/Rational/issues?state=open> are all design-related.
Apart from those raised by my above queries, the major one is how rationals
should relate to floating-point numbers -- e.g. there is currently no opCmp for
floating-point, meaning this:
assert(rational(10, 1) == 10);
... will work, but this:
assert(rational(10, 1) == 10.0);
... will fail to compile. It's not entirely obvious how to resolve this as
floating-point vs. rational comparisons risk accidentally creating huge
temporary BigInt-based rationals ... :-(
Anyway, I'd really value your feedback at this point.
Thanks & best wishes,
-- Joe
More information about the Digitalmars-d
mailing list