Closed non closed 8 years ago
One thing about this is that the actual way we calculate GCD for floating point number is by treating them like rational numbers. I gave a justification in my original PR to Spire:
This makes GCD for rationals match up with Mathematica. The GCD of 2 rational numbers p/q and r/s is gcd(ps, rq) / (q * s). This PR implements this for Rational, Float, Double, and BigDecimal, though being careful to be more efficient.
I wonder if it's worth adding to the docs somewhere, so we can sort of explain the behaviour, since the GCD can basically be anything otherwise for these numbers.
:+1: but we should add an issue to track code coverage and specifically to add tests here. Since this comes from Spire rather than de novo, I'm not as worried.
I can't find any trait with Gcd (I'm on my phone). Am I missing it? Is there no law we have for the expectation of gcd? Or is any law too weak to be a full specification?
@johnynek We have laws for GCD/LCM in spire -- I'll add relevant tests/laws to this PR before we merge it.
There is even a TODO in the laws for EuclideanRing
, so I can also add those while I'm at it.
Oh! It seems like we removed gcd
and lcm
from the type classes at some point, but just hadn't removed all those methods. I'll amend this to remove them (and add tests for quot
and mod
too).
OK -- I think this addresses @johnynek's concerns (we've removed everything GCD-related, added other tests, and removed some unsafe instances we caught with the new tests). It's a bit more of a compatibility break than before but I think it's worth it!
Wait -- I need to do a few more things.
👍 just a minor request for a comment.
👍
Alright, I added the comment for @johnynek and I also made sure to mix the new implicit instances into the AllIntances
trait. Finally, I enabled the law-checking tests for these two new types (in the case of BigDecimal
it's slightly fake, as you'll see, but that's normal in this space).
[info] - [BigDecimal].euclidean ring.distributive *** FAILED ***
[info] GeneratorDrivenPropertyCheckFailedException was thrown during property evaluation.
[info] (algebra-laws-test-fastopt.js:35722)
[info] Falsified after 87 successful property evaluations.
[info] Location: (algebra-laws-test-fastopt.js:35722)
[info] Occurred when passed generated values (
[info] arg0 = -2147483648,
[info] arg1 = -2147483648,
[info] arg2 = -2147483648
[info] )
[info] Label of failing property:
[info] (-9223372036854775808 ?== 9223372036854775808) failed
that's weird. Is this a bug with BigDecimal on scala-js?
@johnynek It sort of looks that way to me. I went ahead and downgraded the test to _.ring
for now, since that is a known-flaky test anyway.
OK, well after finding (and reporting) a Scala.js bug [1] it looks like we're finally green again.
This commit also adds a static method for computing GCDs of BigDecimal values (ported from Spire), and standardizes the methods used in the set instances.