[Pkg-cli-apps-commits] [fsharp] 23/60: Cleanup and fixes for F# BigInteger to bring it closer to BCL BigInteger behavior. Addresses bugs #105, #106, #107, #108, #109, #111, and #112. (changeset 1304009)
Christopher Halse Rogers
raof-guest at moszumanska.debian.org
Sun Sep 14 08:13:38 UTC 2014
This is an automated email from the git hooks/post-receive script.
raof-guest pushed a commit to branch master
in repository fsharp.
commit 31208c1a238574b415ee1aedd8a7ac80dbef96f4
Author: latkin <latkin at microsoft.com>
Date: Wed Jul 23 11:01:36 2014 -0700
Cleanup and fixes for F# BigInteger to bring it closer to BCL BigInteger behavior. Addresses bugs #105, #106, #107, #108, #109, #111, and #112. (changeset 1304009)
---
src/fsharp/FSharp.Core/math/n.fs | 2 +-
src/fsharp/FSharp.Core/math/z.fs | 130 +++++++++++++++++++++++++++++---------
src/fsharp/FSharp.Core/math/z.fsi | 2 +-
3 files changed, 102 insertions(+), 32 deletions(-)
diff --git a/src/fsharp/FSharp.Core/math/n.fs b/src/fsharp/FSharp.Core/math/n.fs
index 2f1945a..09b779b 100644
--- a/src/fsharp/FSharp.Core/math/n.fs
+++ b/src/fsharp/FSharp.Core/math/n.fs
@@ -1562,7 +1562,7 @@ module internal BigNatModule =
if 0 <= d && d <= 9 then
build (add (mul ten acc) (embed d)) (i+1)
else
- raise (new System.FormatException("The value could not be parsed"))
+ raise (new System.FormatException(SR.GetString(SR.badFormatString)))
build (embed 0) 0
diff --git a/src/fsharp/FSharp.Core/math/z.fs b/src/fsharp/FSharp.Core/math/z.fs
index 590efb1..6cdce31 100644
--- a/src/fsharp/FSharp.Core/math/z.fs
+++ b/src/fsharp/FSharp.Core/math/z.fs
@@ -19,7 +19,10 @@ namespace System.Numerics
// NOTE: 0 has two repns (+1,0) or (-1,0).
[<Struct>]
[<CustomEquality; CustomComparison>]
+#if FX_ATLEAST_PORTABLE
+#else
[<StructuredFormatDisplay("{StructuredDisplayString}I")>]
+#endif
type BigInteger(signInt:int, v : BigNat) =
static let smallLim = 4096
@@ -31,13 +34,17 @@ namespace System.Numerics
if BigNatModule.isSmall n && BigNatModule.getSmall n < smallLim
then smallPosTab.[BigNatModule.getSmall n]
else n
+
static member internal create (s,n) = BigInteger(s,BigInteger.nat n)
+
static member internal posn n = BigInteger(1,BigInteger.nat n)
- static member internal negn n = BigInteger(-1,BigInteger.nat n)
+ static member internal negn n = BigInteger(-1,BigInteger.nat n)
member x.Sign = if x.IsZero then 0 else signInt
+
member x.SignInt = signInt
+
member internal x.V = v
static member op_Equality (x:BigInteger, y:BigInteger) =
@@ -48,7 +55,12 @@ namespace System.Numerics
| -1, -1 -> BigNatModule.equal x.V y.V // -1.xv = -1.yv iff xv = yv
| 1,-1 -> BigNatModule.isZero x.V && BigNatModule.isZero y.V // 1.xv = -1.yv iff xv=0 and yv=0
| -1, 1 -> BigNatModule.isZero x.V && BigNatModule.isZero y.V // -1.xv = 1.yv iff xv=0 and yv=0
- | _ -> invalidArg "x" "signs should be +/- 1"
+ | 0, 0 -> true
+ | 0, 1 -> BigNatModule.isZero y.V
+ | 0, -1 -> BigNatModule.isZero y.V
+ | 1, 0 -> BigNatModule.isZero x.V
+ | -1, 0 -> BigNatModule.isZero x.V
+ | _ -> invalidArg "x" "signs should be +/- 1 or 0"
static member op_Inequality (x:BigInteger, y:BigInteger) = not (BigInteger.op_Equality(x,y)) // CA2226: OperatorsShouldHaveSymmetricalOverloads
@@ -62,7 +74,12 @@ namespace System.Numerics
// (a) xv=0 and yv=0, then false
// (b) xv<>0, -1.xv < 0 <= 1.yv, so true
// (c) yv<>0, -1.xv <= 0 < 1.yv, so true
- | _ -> invalidArg "x" "signs should be +/- 1"
+ | 0, 0 -> false
+ | 0, 1 -> not (BigNatModule.isZero y.V)
+ | 0,-1 -> false
+ | 1, 0 -> false
+ | -1, 0 -> not (BigNatModule.isZero x.V)
+ | _ -> invalidArg "x" "signs should be +/- 1 or 0"
static member op_GreaterThan (x:BigInteger, y:BigInteger) = // Follow lt by +/- symmetry
match x.SignInt,y.SignInt with
@@ -70,10 +87,18 @@ namespace System.Numerics
| -1,-1 -> BigNatModule.gt y.V x.V
| 1,-1 -> not (BigNatModule.isZero x.V) || not (BigNatModule.isZero y.V)
| -1, 1 -> false
- | _ -> invalidArg "x" "signs should be +/- 1"
+ | 0, 0 -> false
+ | 0, 1 -> false
+ | 0,-1 -> not (BigNatModule.isZero y.V)
+ | 1, 0 -> not (BigNatModule.isZero x.V)
+ | -1, 0 -> false
+ | _ -> invalidArg "x" "signs should be +/- 1 or 0"
static member internal compare(n,nn) = if BigInteger.op_LessThan(n,nn) then -1 elif BigInteger.op_Equality(n,nn) then 0 else 1
- static member internal hash (z:BigInteger) = z.SignInt + BigNatModule.hash(z.V)
+
+ static member internal hash (z:BigInteger) =
+ if z.SignInt = 0 then 1 // 1 is hashcode for initialized BigInteger.Zero
+ else z.SignInt + BigNatModule.hash(z.V)
override x.ToString() =
match x.SignInt with
@@ -81,8 +106,9 @@ namespace System.Numerics
| -1 ->
if BigNatModule.isZero x.V
then "0" // not negative infact, but zero.
- else "-" + BigNatModule.toString x.V // negative
- | _ -> invalidOp "signs should be +/- 1"
+ else "-" + BigNatModule.toString x.V // negative
+ | 0 -> "0"
+ | _ -> invalidOp "signs should be +/- 1 or 0"
member x.StructuredDisplayString = x.ToString()
@@ -99,7 +125,6 @@ namespace System.Numerics
override x.GetHashCode() = BigInteger.hash(x)
-
new (n:int) =
if n>=0
then BigInteger (1,BigInteger.nat(BigNatModule.ofInt32 n))
@@ -107,7 +132,6 @@ namespace System.Numerics
then BigInteger(-1,BigInteger.nat(BigNatModule.ofInt64 (-(int64 n))))
else BigInteger(-1,BigInteger.nat(BigNatModule.ofInt32 (-n)))
-
new (n:int64) =
if n>=0L
then BigInteger(1,BigInteger.nat (BigNatModule.ofInt64 n))
@@ -116,9 +140,16 @@ namespace System.Numerics
else BigInteger(-1,BigInteger.nat (BigNatModule.ofInt64 (-n)))
static member One = one
+
static member Zero = zero
- static member (~-) (z:BigInteger) = BigInteger.create(-1 * z.SignInt,z.V)
- static member Scale(k,z:BigInteger) =
+
+ static member (~-) (z:BigInteger) =
+ match z.SignInt with
+ | 0 -> BigInteger.Zero
+ | i -> BigInteger.create(-i, z.V)
+
+ static member Scale(k, z:BigInteger) =
+ if z.SignInt = 0 then BigInteger.Zero else
if k<0
then BigInteger.create(-z.SignInt, (BigNatModule.scale (-k) z.V)) // k.zsign.zv = -zsign.(-k.zv)
else BigInteger.create(z.SignInt, (BigNatModule.scale k z.V)) // k.zsign.zv = zsign.k.zv
@@ -132,8 +163,10 @@ namespace System.Numerics
static member internal addnn (nx,ny) =
BigInteger.posn (BigNatModule.add nx ny) // Compute "nx + ny" to be integer
- member x.IsZero = BigNatModule.isZero x.V // signx.xv = 0 iff xv=0, since signx is +1,-1
+ member x.IsZero = x.SignInt = 0 || BigNatModule.isZero x.V
+
member x.IsOne = (x.SignInt = 1) && BigNatModule.isOne x.V // signx.xv = 1 iff signx = +1 and xv = 1
+
static member (+) (x:BigInteger,y:BigInteger) =
if y.IsZero then x else
if x.IsZero then y else
@@ -146,6 +179,7 @@ namespace System.Numerics
static member (-) (x:BigInteger,y:BigInteger) =
if y.IsZero then x else
+ if x.IsZero then -y else
match x.SignInt,y.SignInt with
| 1, 1 -> BigInteger.subnn(x.V,y.V) // 1.xv - 1.yv = (xv - yv)
| -1,-1 -> BigInteger.subnn(y.V,x.V) // -1.xv - -1.yv = (yv - xv)
@@ -162,7 +196,12 @@ namespace System.Numerics
let m = (BigNatModule.mul x.V y.V)
BigInteger.create (x.SignInt * y.SignInt,m) // xsign.xv * ysign.yv = (xsign.ysign).(xv.yv)
- static member DivRem (x:BigInteger,y:BigInteger,rem:BigInteger byref) =
+ static member DivRem (x:BigInteger, y:BigInteger, [<System.Runtime.InteropServices.Out>]rem:BigInteger byref) =
+ if y.IsZero then raise (new System.DivideByZeroException())
+ if x.IsZero then
+ rem <- BigInteger.Zero
+ BigInteger.Zero
+ else
let d,r = BigNatModule.divmod x.V y.V
// HAVE: |x| = d.|y| + r and 0 <= r < |y|
// HAVE: xv = d.yv + r and 0 <= r < yv
@@ -176,13 +215,22 @@ namespace System.Numerics
static member (/) (x:BigInteger,y:BigInteger) =
let mutable rem = new BigInteger(0)
BigInteger.DivRem(x,y,&rem)
+
static member (%) (x:BigInteger,y:BigInteger) =
let mutable rem = new BigInteger(0)
BigInteger.DivRem(x,y,&rem) |> ignore ; rem
- static member GreatestCommonDivisor (x:BigInteger,y:BigInteger) = BigInteger.posn (BigNatModule.hcf x.V y.V) // hcf (xsign.xv,ysign.yv) = hcf (xv,yv)
+
+ static member GreatestCommonDivisor (x:BigInteger,y:BigInteger) =
+ match x.SignInt,y.SignInt with
+ | 0, 0 -> BigInteger.Zero
+ | 0, _ -> BigInteger.posn y.V
+ | _, 0 -> BigInteger.posn x.V
+ | _ -> BigInteger.posn (BigNatModule.hcf x.V y.V) // hcf (xsign.xv,ysign.yv) = hcf (xv,yv)
member x.IsNegative = x.SignInt = -1 && not (x.IsZero) // signx.xv < 0 iff signx = -1 and xv<>0
+
member x.IsPositive = x.SignInt = 1 && not (x.IsZero) // signx.xv > 0 iff signx = +1 and xv<>0
+
static member Abs (x:BigInteger) = if x.SignInt = -1 then -x else x
static member op_LessThanOrEqual (x:BigInteger,y:BigInteger) =
@@ -192,9 +240,14 @@ namespace System.Numerics
| 1,-1 -> BigNatModule.isZero x.V && BigNatModule.isZero y.V // 1.xv <= -1.yv,
// (a) if xv=0 and yv=0 then true
// (b) otherwise false, only meet at zero.
-
+
| -1, 1 -> true // -1.xv <= 1.yv, true
- | _ -> invalidArg "x" "signs should be +/- 1"
+ | 0, 0 -> true
+ | 1, 0 -> BigNatModule.isZero x.V
+ | -1, 0 -> true
+ | 0, 1 -> true
+ | 0,-1 -> BigNatModule.isZero y.V
+ | _ -> invalidArg "x" "signs should be +/- 1 or 0"
static member op_GreaterThanOrEqual (x:BigInteger,y:BigInteger) = // Follow lte by +/- symmetry
match x.SignInt,y.SignInt with
@@ -202,15 +255,24 @@ namespace System.Numerics
| -1,-1 -> BigNatModule.gte y.V x.V
| 1,-1 -> true
| -1, 1 -> BigNatModule.isZero x.V && BigNatModule.isZero y.V
- | _ -> invalidArg "x" "signs should be +/- 1"
-
+ | 0, 0 -> true
+ | 1, 0 -> true
+ | -1, 0 -> BigNatModule.isZero x.V
+ | 0, 1 -> BigNatModule.isZero y.V
+ | 0,-1 -> true
+ | _ -> invalidArg "x" "signs should be +/- 1 or 0"
static member Pow (x:BigInteger,y:int32) =
- if y < 0 then invalidArg "y" (SR.GetString(SR.inputMustBeNonNegative))
- let yval = BigInteger(y)
- BigInteger.create ((if BigNatModule.isZero (BigNatModule.rem yval.V BigNatModule.two) then 1 else x.SignInt), BigNatModule.pow x.V yval.V)
+ if y < 0 then raise (new System.ArgumentOutOfRangeException("y", (SR.GetString(SR.inputMustBeNonNegative))))
+ match x.IsZero, y with
+ | true, 0 -> BigInteger.One
+ | true, _ -> BigInteger.Zero
+ | _ ->
+ let yval = BigInteger(y)
+ BigInteger.create ((if BigNatModule.isZero (BigNatModule.rem yval.V BigNatModule.two) then 1 else x.SignInt), BigNatModule.pow x.V yval.V)
static member op_Explicit (x:BigInteger) =
+ if x.IsZero then 0 else
let u = BigNatModule.toUInt32 x.V
if u <= uint32 System.Int32.MaxValue then
// Handle range [-MaxValue,MaxValue]
@@ -222,7 +284,8 @@ namespace System.Numerics
else
raise (System.OverflowException())
- static member op_Explicit (x:BigInteger) =
+ static member op_Explicit (x:BigInteger) =
+ if x.IsZero then 0L else
let u = BigNatModule.toUInt64 x.V
if u <= uint64 System.Int64.MaxValue then
(* Handle range [-MaxValue,MaxValue] *)
@@ -238,17 +301,23 @@ namespace System.Numerics
match x.SignInt with
| 1 -> BigNatModule.toFloat x.V // float (1.xv) = float (xv)
| -1 -> - (BigNatModule.toFloat x.V) // float (-1.xv) = - float (xv)
- | _ -> invalidArg "x" "signs should be +/- 1"
+ | 0 -> 0.
+ | _ -> invalidArg "x" "signs should be +/- 1 or 0"
static member Parse(text:string) =
+ if text = null then raise (new ArgumentNullException("text"))
+ let text = text.Trim()
let len = text.Length
- if len = 0 then raise (new System.FormatException("The value could not be parsed"))
- if text.[0..0] = "-" then
- BigInteger.negn (BigNatModule.ofString text.[1..len-1])
- else
- BigInteger.posn (BigNatModule.ofString text)
-
- member internal x.IsSmall = BigNatModule.isSmall (x.V)
+ if len = 0 then raise (new System.FormatException(SR.GetString(SR.badFormatString)))
+ match text.[0], len with
+ | '-', 1 -> raise (new System.FormatException(SR.GetString(SR.badFormatString)))
+ | '-', _ -> BigInteger.negn (BigNatModule.ofString text.[1..len-1])
+ | '+', 1 -> raise (new System.FormatException(SR.GetString(SR.badFormatString)))
+ | '+', _ -> BigInteger.posn (BigNatModule.ofString text.[1..len-1])
+ | _ -> BigInteger.posn (BigNatModule.ofString text)
+
+ member internal x.IsSmall = x.IsZero || BigNatModule.isSmall (x.V)
+
static member Factorial (x:BigInteger) =
if x.IsNegative then invalidArg "x" (SR.GetString(SR.inputMustBeNonNegative))
if x.IsPositive then BigInteger.posn (BigNatModule.factorial x.V)
@@ -257,6 +326,7 @@ namespace System.Numerics
static member ( ~+ )(n1:BigInteger) = n1
static member FromInt64(x:int64) = new BigInteger(x)
+
static member FromInt32(x:int32) = new BigInteger(x)
#endif
diff --git a/src/fsharp/FSharp.Core/math/z.fsi b/src/fsharp/FSharp.Core/math/z.fsi
index 0d2b4d7..a87c2b5 100644
--- a/src/fsharp/FSharp.Core/math/z.fsi
+++ b/src/fsharp/FSharp.Core/math/z.fsi
@@ -36,7 +36,7 @@ namespace System.Numerics
/// Return the sign of a big integer: 0, +1 or -1
member Sign : int
/// Compute the ratio and remainder of two big integers
- static member DivRem : x:BigInteger * y:BigInteger * rem:BigInteger byref -> BigInteger
+ static member DivRem : x:BigInteger * y:BigInteger * [<System.Runtime.InteropServices.Out>]rem:BigInteger byref -> BigInteger
/// This operator is for consistency when this type be used from other CLI languages
static member op_LessThan : x:BigInteger * y:BigInteger -> bool
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-cli-apps/packages/fsharp.git
More information about the Pkg-cli-apps-commits
mailing list