dsimcha wrote:
On 3/22/2011 1:25 AM, Don wrote:
There are a few approaches we can take from here. One is to define
certain traits that differentiate BigInt from other integrals (e.g.
preferAdditionToMultiplication or whatnot), and then design Rational to
use those traits. Another is of course to specialize the entire
Rational on BigInt. Third would be to specialize certain core routines
(gcd and friends) for BigInt and keep Rational agnostic.

You're missing something important here. Rational big integers are a
very well defined area of research, with its own set of algorithms.
Although you can pretend a BigInt behaves as an int, and make a rational
type, the performance will be pathetic, and everyone will laugh at you.

I fully understand this based on your previous posts. I therefore agree that Rational doesn't belong in Phobos exactly as-is. I'm trying to understand which of the following scenarios is true, though:

Scenario A: Making BigInt efficient would require changes only in a few small places, like GCD. If we provide hooks for arbitrary precision types to specialize these, and provide specializations for std.bigint.BigInt, all will be well.

Scenario B: Making BigInt efficient would have ripple effects all over the implementation, require rethinking of every operation, etc., but in a way that wouldn't bleed out into the interface. It might make sense to get the interface and a generic implementation right first, then specialize it to improve performance later.

Scenario C: Making BigInt efficient would have ripple effects for both the interface and the implementation. In this case, we probably shouldn't provide a generic implementation because the arbitrary precision one is much more generally useful and the fixed width one would mostly add clutter.

From the BigInt side, the only real change is the addition of gcd and gcdExtended.
(gcdExtended returns x, y such that a*x + b*y = gcd(a, b) ).

I believe that is the only low-level algorithm which is missing; pretty much everything else remains unchanged.

However, the other case which is interesting is when BigInt is replaced with FixedInt!n (maybe someone can come up with a better name for this?) -- an integer with a length of a fixed number of ints. Unlike BigInt, this has basically the same semantics as built-in integer types. In fact, FixedInt!1 == int, FixedInt!2 == long, FixedInt!4 == cent. This is possibly even more relevant for Rational. I haven't thought much about the implications though.

BTW, does BigInt over-allocate initially to allow certain operations (like +=) to be done in-place more frequently?

No, it doesn't. As long as it uses copy-on-write, there's no benefit to doing so. Reference counting would clearly be superior for FixedInt, but I'm not at all sure that it would be a win for BigInt. But of course FixedInt wouldn't need to over-allocate.

Using TempAlloc would have a far greater effect on performance.

Reply via email to