Browse Source

BigRational: fix pow to support negative integer exponents

provider
Christoph Ruegg 13 years ago
parent
commit
fa67ff3ab4
  1. 13
      src/FSharp/BigRational.fs
  2. 21
      src/FSharpUnitTests/BigRationalTests.fs

13
src/FSharp/BigRational.fs

@ -115,7 +115,8 @@ type BigRationalLarge (p : BigInteger, q : BigInteger) =
//
static member Pow (num : BigRationalLarge, n : int) =
// p,q powers still coprime
BigRationalLarge (BigInteger.Pow (num.Numerator, n), BigInteger.Pow (num.Denominator, n))
if n < 0 then BigRationalLarge.Normalize (BigInteger.Pow (num.Denominator, -n), BigInteger.Pow (num.Numerator, -n))
else BigRationalLarge (BigInteger.Pow (num.Numerator, n), BigInteger.Pow (num.Denominator, n))
//
static member FromBigInteger z =
@ -414,14 +415,18 @@ type BigRational =
/// Returns the multiplicative inverse of a rational number
static member Reciprocal (n) =
match n with
| Z z -> Q (BigRationalLarge.Create (BigInteger.One, z))
| Q q -> Q (BigRationalLarge.Reciprocal q)
| Z z ->
Q (BigRationalLarge.Create (BigInteger.One, z))
| Q q ->
Q (BigRationalLarge.Reciprocal q)
/// Return the result of raising the given rational number to the given power
static member Pow (n, i : int) =
match n with
| Z z ->
| Z z when i > 0 ->
Z (BigInteger.Pow (z, i))
| Z z ->
Q (BigRationalLarge.Pow (BigRationalLarge.FromBigInteger z, i))
| Q q ->
Q (BigRationalLarge.Pow (q, i))

21
src/FSharpUnitTests/BigRationalTests.fs

@ -286,10 +286,15 @@ type public BigRationalTests() =
test1All "Abs" (BigRational.Abs) (fun (p,q) -> (abs p,abs q)) vector1s
testR1All "Sign" (fun (x:BigRational) -> x.Sign) (fun (p,q) -> check "NonZeroDenom" (sign q <> 0I) true; (sign p * sign q) |> int32) vector1s
// Test: PowN
test1All "PowN(x,2)" (fun x -> BigRational.PowN(x,2)) (fun (p,q) -> (p*p,q*q)) vector1s
test1All "PowN(x,1)" (fun x -> BigRational.PowN(x,1)) (fun (p,q) -> (p,q)) vector1s
test1All "PowN(x,0)" (fun x -> BigRational.PowN(x,0)) (fun (p,q) -> (1I,1I)) vector1s
// Test: Pow
test1All "Pow(x,2)" (fun x -> BigRational.Pow(x,2)) (fun (p,q) -> (p*p,q*q)) vector1s
test1All "Pow(x,1)" (fun x -> BigRational.Pow(x,1)) (fun (p,q) -> (p,q)) vector1s
test1All "Pow(x,0)" (fun x -> BigRational.Pow(x,0)) (fun (p,q) -> (1I,1I)) vector1s
test1All "Pow(x,-1)" (fun x -> BigRational.Pow(x,-1)) (fun (p,q) -> (q,p)) (vector1s |> List.filter (fun (p,_) -> p <> 0I))
test1All "Pow(x,-2)" (fun x -> BigRational.Pow(x,-2)) (fun (p,q) -> (q*q,p*p)) (vector1s |> List.filter (fun (p,_) -> p <> 0I))
testR1One "Pow(0,-1)" (fun x -> throws (fun () -> BigRational.PowN(x,-1))) (fun (p,q) -> true) (0I, -1I)
testR1One "Pow(0,-2)" (fun x -> throws (fun () -> BigRational.PowN(x,-2))) (fun (p,q) -> true) (0I, -2I)
// MatteoT: moved to numbersVS2008\test.ml
//test1All "PowN(x,200)" (fun x -> BigRational.PowN(x,200)) (fun (p,q) -> (BigInteger.Pow(p,200I),BigInteger.Pow(q,200I))) vector1s
@ -298,10 +303,6 @@ type public BigRationalTests() =
//let powers = [0I .. 100I]
//powers |> List.iter (fun i -> test1All "PowN(x,i)" (fun x -> BigRational.PowN(x,int i)) (fun (p,q) -> (BigInteger.Pow(p,i),BigInteger.Pow(q,i))) vector1s)
// Test: PowN with negative powers - expect exception
testR1All "PowN(x,-1)" (fun x -> throws (fun () -> BigRational.PowN(x,-1))) (fun (p,q) -> true) vector1s
testR1All "PowN(x,-4)" (fun x -> throws (fun () -> BigRational.PowN(x,-4))) (fun (p,q) -> true) vector1s
[<TestFixture>]
@ -387,8 +388,10 @@ type BigNumType() =
member this.Pow() =
Assert.AreEqual(bignum.Pow(100N,2), 10000N)
Assert.AreEqual(bignum.Pow(-3N,3), -27N)
Assert.AreEqual(bignum.Pow(2N,-2), 1N/4N)
Assert.AreEqual(bignum.Pow(2N/3N,-2), 9N/4N)
Assert.AreEqual(bignum.Pow(g_zero,2147483647), 0N)
Assert.AreEqual(bignum.Pow(g_normal,0), 1N)
Assert.AreEqual(bignum.Pow(g_normal,0), 1N)
()
[<Test>]

Loading…
Cancel
Save