JeffreySarnoff/FastRationals.jl

Generic implementation

Closed this issue · 7 comments

I don't understand the close-to-equal implementation files FastQ32/64.
It would be easy to have a single file, which defines everything in a generic manner.

That would also enable Int128 and BigInt base types.

The base type T in struct FastRational should be restricted to <:Signed.

Int32/Int64 could be replaced by generic T/widen(T) in all methods.

Int128 and BigInt cannot be fast because they do not widen() to a fast integer type.
Other functions can be unified -- they are not now just to make sure everything worked, I developed for one type and then replicated the file after some subtle issue with one of the generic defs occured.

Int128 and BigInt cannot be fast

my impression was, that your implementation is faster than Rational because the number of calls to gcd is reduced. That would also count for Int128 and BigInt.

I developed for one type and then replicated the file after some subtle issue with one of the generic defs occured

You know, that code duplication is not state of the art :-). Maybe I could help investigating the subtle issues.

Thanks. I will reintegrate tonight on a dev branch and see if it work now.

Re Int128 and BigInt, yes .. however .. that would qualify as FasterRationals and not FastRationals because they widen to BigInt. My earlier implementation would be appropriate for them. That's the one where you found the inv issue. I think this is a two stage process. Get this implementation as clean as can be (no dup code, and whatever else). Then use the two-state type that knows if its reduced.
The fast comes from from fewer gcd's in two ways .. the current implementation uses one of them, as it does not know whether the rational is in reduced form or not.

@KlausC ok .. master is now generic. Note that the 128bit type is faster than the default -- 1.5x..2x only.
please give it a once-over.

I get

        relative speeds
         (32)    (64)    (128)

mul:     25.5    22.8    2.4
muladd:  21.7    18.8    1.9
add:     18.5    16.5    1.6
poly:    14.3    23.9    2.0
matmul:  11.9    15.0    1.8
matlu:   5.7     6.3     1.7
matinv:  3.7     2.7     1.1

Int128 and BigInt, yes .. however .. that would qualify as FasterRationals and not FastRationals

Playing around, it was difficult to find examples, which don't overflow FastQR64 . That is the same for Rational{Int64} . There is a tendency for the components of rational numbers to blow up after quite a few elementary operations. So I don't see the important use cases, except for BigInt as the base type.

For example:
A = rand(-1:1, 20,20); AR = Rational.(A); AF = FastQ64.(A); @btime inv(AR); @btime inv(AF)

That gives a time factor of 2.
But for 30x30 you get overflow for Int64 and time factor 0.32 for Int128.

yes -- its always that way with Rationals.
In light of this, the current master supports FastQbig (FastRational{BigInt}) and they do outperform Rational{BigInt} 2x..4x on a few different tasks.
Your help has been good to have. Thanks again.