[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