@@ -19,7 +19,10 @@ namespace System.Numerics
1919// NOTE: 0 has two repns (+1,0) or (-1,0).
2020[<Struct>]
2121[<CustomEquality; CustomComparison>]
22+ #if FX_ ATLEAST_ PORTABLE
23+ #else
2224[<StructuredFormatDisplay( " {StructuredDisplayString}I" ) >]
25+ #endif
2326type BigInteger ( signInt : int , v : BigNat ) =
2427
2528static let smallLim = 4096
@@ -31,13 +34,17 @@ namespace System.Numerics
3134if BigNatModule.isSmall n&& BigNatModule.getSmall n< smallLim
3235then smallPosTab.[ BigNatModule.getSmall n]
3336else n
37+
3438static member internal create ( s , n ) = BigInteger( s, BigInteger.nat n)
39+
3540static member internal posn n = BigInteger( 1 , BigInteger.nat n)
36- static member internal negn n = BigInteger(- 1 , BigInteger.nat n)
3741
42+ static member internal negn n = BigInteger(- 1 , BigInteger.nat n)
3843
3944member x.Sign = if x.IsZerothen 0 else signInt
45+
4046member x.SignInt = signInt
47+
4148member internal x.V = v
4249
4350static member op_Equality ( x : BigInteger , y : BigInteger ) =
@@ -48,7 +55,12 @@ namespace System.Numerics
4855| - 1 , - 1 -> BigNatModule.equal x.V y.V// -1.xv = -1.yv iff xv = yv
4956| 1 ,- 1 -> BigNatModule.isZero x.V&& BigNatModule.isZero y.V// 1.xv = -1.yv iff xv=0 and yv=0
5057| - 1 , 1 -> BigNatModule.isZero x.V&& BigNatModule.isZero y.V// -1.xv = 1.yv iff xv=0 and yv=0
51- | _ -> invalidArg" x" " signs should be +/- 1"
58+ | 0 , 0 -> true
59+ | 0 , 1 -> BigNatModule.isZero y.V
60+ | 0 , - 1 -> BigNatModule.isZero y.V
61+ | 1 , 0 -> BigNatModule.isZero x.V
62+ | - 1 , 0 -> BigNatModule.isZero x.V
63+ | _ -> invalidArg" x" " signs should be +/- 1 or 0"
5264
5365static member op_Inequality ( x : BigInteger , y : BigInteger ) = not ( BigInteger.op_ Equality( x, y)) // CA2226: OperatorsShouldHaveSymmetricalOverloads
5466
@@ -62,27 +74,41 @@ namespace System.Numerics
6274// (a) xv=0 and yv=0, then false
6375// (b) xv<>0, -1.xv < 0 <= 1.yv, so true
6476// (c) yv<>0, -1.xv <= 0 < 1.yv, so true
65- | _ -> invalidArg" x" " signs should be +/- 1"
77+ | 0 , 0 -> false
78+ | 0 , 1 -> not ( BigNatModule.isZero y.V)
79+ | 0 ,- 1 -> false
80+ | 1 , 0 -> false
81+ | - 1 , 0 -> not ( BigNatModule.isZero x.V)
82+ | _ -> invalidArg" x" " signs should be +/- 1 or 0"
6683
6784static member op_GreaterThan ( x : BigInteger , y : BigInteger ) = // Follow lt by +/- symmetry
6885match x.SignInt, y.SignIntwith
6986| 1 , 1 -> BigNatModule.gt x.V y.V
7087| - 1 ,- 1 -> BigNatModule.gt y.V x.V
7188| 1 ,- 1 -> not ( BigNatModule.isZero x.V) || not ( BigNatModule.isZero y.V)
7289| - 1 , 1 -> false
73- | _ -> invalidArg" x" " signs should be +/- 1"
90+ | 0 , 0 -> false
91+ | 0 , 1 -> false
92+ | 0 ,- 1 -> not ( BigNatModule.isZero y.V)
93+ | 1 , 0 -> not ( BigNatModule.isZero x.V)
94+ | - 1 , 0 -> false
95+ | _ -> invalidArg" x" " signs should be +/- 1 or 0"
7496
7597static member internal compare ( n , nn ) = if BigInteger.op_ LessThan( n, nn) then - 1 elif BigInteger.op_ Equality( n, nn) then 0 else 1
76- static member internal hash ( z : BigInteger ) = z.SignInt+ BigNatModule.hash( z.V)
98+
99+ static member internal hash ( z : BigInteger ) =
100+ if z.SignInt= 0 then 1 // 1 is hashcode for initialized BigInteger.Zero
101+ else z.SignInt+ BigNatModule.hash( z.V)
77102
78103override x.ToString () =
79104match x.SignIntwith
80105| 1 -> BigNatModule.toString x.V// positive
81106| - 1 ->
82107if BigNatModule.isZero x.V
83108then " 0" // not negative infact, but zero.
84- else " -" + BigNatModule.toString x.V// negative
85- | _ -> invalidOp" signs should be +/- 1"
109+ else " -" + BigNatModule.toString x.V// negative
110+ | 0 -> " 0"
111+ | _ -> invalidOp" signs should be +/- 1 or 0"
86112
87113member x.StructuredDisplayString = x.ToString()
88114
@@ -99,15 +125,13 @@ namespace System.Numerics
99125
100126override x.GetHashCode () = BigInteger.hash( x)
101127
102-
103128new ( n : int ) =
104129if n>= 0
105130then BigInteger( 1 , BigInteger.nat( BigNatModule.ofInt32 n))
106131elif ( n= System.Int32.MinValue)
107132then BigInteger(- 1 , BigInteger.nat( BigNatModule.ofInt64(-( int64 n))))
108133else BigInteger(- 1 , BigInteger.nat( BigNatModule.ofInt32(- n)))
109134
110-
111135new ( n : int64 ) =
112136if n>= 0 L
113137then BigInteger( 1 , BigInteger.nat( BigNatModule.ofInt64 n))
@@ -116,9 +140,16 @@ namespace System.Numerics
116140else BigInteger(- 1 , BigInteger.nat( BigNatModule.ofInt64(- n)))
117141
118142static member One = one
143+
119144static member Zero = zero
120- static member (~-) ( z : BigInteger ) = BigInteger.create(- 1 * z.SignInt, z.V)
121- static member Scale ( k , z : BigInteger ) =
145+
146+ static member (~-) ( z : BigInteger ) =
147+ match z.SignIntwith
148+ | 0 -> BigInteger.Zero
149+ | i-> BigInteger.create(- i, z.V)
150+
151+ static member Scale ( k , z : BigInteger ) =
152+ if z.SignInt= 0 then BigInteger.Zeroelse
122153if k< 0
123154then BigInteger.create(- z.SignInt, ( BigNatModule.scale(- k) z.V)) // k.zsign.zv = -zsign.(-k.zv)
124155else BigInteger.create( z.SignInt, ( BigNatModule.scale k z.V)) // k.zsign.zv = zsign.k.zv
@@ -132,8 +163,10 @@ namespace System.Numerics
132163static member internal addnn ( nx , ny ) =
133164 BigInteger.posn( BigNatModule.add nx ny) // Compute "nx + ny" to be integer
134165
135- member x.IsZero = BigNatModule.isZero x.V// signx.xv = 0 iff xv=0, since signx is +1,-1
166+ member x.IsZero = x.SignInt= 0 || BigNatModule.isZero x.V
167+
136168member x.IsOne = ( x.SignInt= 1 ) && BigNatModule.isOne x.V// signx.xv = 1 iff signx = +1 and xv = 1
169+
137170static member (+) ( x : BigInteger , y : BigInteger ) =
138171if y.IsZerothen xelse
139172if x.IsZerothen yelse
@@ -146,6 +179,7 @@ namespace System.Numerics
146179
147180static member (-) ( x : BigInteger , y : BigInteger ) =
148181if y.IsZerothen xelse
182+ if x.IsZerothen - yelse
149183match x.SignInt, y.SignIntwith
150184| 1 , 1 -> BigInteger.subnn( x.V, y.V) // 1.xv - 1.yv = (xv - yv)
151185| - 1 ,- 1 -> BigInteger.subnn( y.V, x.V) // -1.xv - -1.yv = (yv - xv)
@@ -162,7 +196,12 @@ namespace System.Numerics
162196let m = ( BigNatModule.mul x.V y.V)
163197 BigInteger.create( x.SignInt* y.SignInt, m) // xsign.xv * ysign.yv = (xsign.ysign).(xv.yv)
164198
165- static member DivRem ( x : BigInteger , y : BigInteger , rem : BigInteger byref ) =
199+ static member DivRem ( x : BigInteger , y : BigInteger , [<System.Runtime.InteropServices.Out>] rem : BigInteger byref ) =
200+ if y.IsZerothen raise( new System.DivideByZeroException())
201+ if x.IsZerothen
202+ rem<- BigInteger.Zero
203+ BigInteger.Zero
204+ else
166205let d , r = BigNatModule.divmod x.V y.V
167206// HAVE: |x| = d.|y| + r and 0 <= r < |y|
168207// HAVE: xv = d.yv + r and 0 <= r < yv
@@ -176,13 +215,22 @@ namespace System.Numerics
176215static member (/) ( x : BigInteger , y : BigInteger ) =
177216let mutable rem = new BigInteger( 0 )
178217 BigInteger.DivRem( x, y,& rem)
218+
179219static member (%) ( x : BigInteger , y : BigInteger ) =
180220let mutable rem = new BigInteger( 0 )
181221 BigInteger.DivRem( x, y,& rem) |> ignore; rem
182- static member GreatestCommonDivisor ( x : BigInteger , y : BigInteger ) = BigInteger.posn( BigNatModule.hcf x.V y.V) // hcf (xsign.xv,ysign.yv) = hcf (xv,yv)
222+
223+ static member GreatestCommonDivisor ( x : BigInteger , y : BigInteger ) =
224+ match x.SignInt, y.SignIntwith
225+ | 0 , 0 -> BigInteger.Zero
226+ | 0 , _ -> BigInteger.posn y.V
227+ | _, 0 -> BigInteger.posn x.V
228+ | _ -> BigInteger.posn( BigNatModule.hcf x.V y.V) // hcf (xsign.xv,ysign.yv) = hcf (xv,yv)
183229
184230member x.IsNegative = x.SignInt= - 1 && not ( x.IsZero) // signx.xv < 0 iff signx = -1 and xv<>0
231+
185232member x.IsPositive = x.SignInt= 1 && not ( x.IsZero) // signx.xv > 0 iff signx = +1 and xv<>0
233+
186234static member Abs ( x : BigInteger ) = if x.SignInt= - 1 then - xelse x
187235
188236static member op_LessThanOrEqual ( x : BigInteger , y : BigInteger ) =
@@ -192,25 +240,39 @@ namespace System.Numerics
192240| 1 ,- 1 -> BigNatModule.isZero x.V&& BigNatModule.isZero y.V// 1.xv <= -1.yv,
193241// (a) if xv=0 and yv=0 then true
194242// (b) otherwise false, only meet at zero.
195-
243+
196244| - 1 , 1 -> true // -1.xv <= 1.yv, true
197- | _ -> invalidArg" x" " signs should be +/- 1"
245+ | 0 , 0 -> true
246+ | 1 , 0 -> BigNatModule.isZero x.V
247+ | - 1 , 0 -> true
248+ | 0 , 1 -> true
249+ | 0 ,- 1 -> BigNatModule.isZero y.V
250+ | _ -> invalidArg" x" " signs should be +/- 1 or 0"
198251
199252static member op_GreaterThanOrEqual ( x : BigInteger , y : BigInteger ) = // Follow lte by +/- symmetry
200253match x.SignInt, y.SignIntwith
201254| 1 , 1 -> BigNatModule.gte x.V y.V
202255| - 1 ,- 1 -> BigNatModule.gte y.V x.V
203256| 1 ,- 1 -> true
204257| - 1 , 1 -> BigNatModule.isZero x.V&& BigNatModule.isZero y.V
205- | _ -> invalidArg" x" " signs should be +/- 1"
206-
258+ | 0 , 0 -> true
259+ | 1 , 0 -> true
260+ | - 1 , 0 -> BigNatModule.isZero x.V
261+ | 0 , 1 -> BigNatModule.isZero y.V
262+ | 0 ,- 1 -> true
263+ | _ -> invalidArg" x" " signs should be +/- 1 or 0"
207264
208265static member Pow ( x : BigInteger , y : int32 ) =
209- if y< 0 then invalidArg" y" ( SR.GetString( SR.inputMustBeNonNegative))
210- let yval = BigInteger( y)
211- BigInteger.create(( if BigNatModule.isZero( BigNatModule.rem yval.V BigNatModule.two) then 1 else x.SignInt), BigNatModule.pow x.V yval.V)
266+ if y< 0 then raise( new System.ArgumentOutOfRangeException( " y" , ( SR.GetString( SR.inputMustBeNonNegative))))
267+ match x.IsZero, ywith
268+ | true , 0 -> BigInteger.One
269+ | true , _ -> BigInteger.Zero
270+ | _ ->
271+ let yval = BigInteger( y)
272+ BigInteger.create(( if BigNatModule.isZero( BigNatModule.rem yval.V BigNatModule.two) then 1 else x.SignInt), BigNatModule.pow x.V yval.V)
212273
213274static member op_Explicit ( x : BigInteger ) =
275+ if x.IsZerothen 0 else
214276let u = BigNatModule.toUInt32 x.V
215277if u<= uint32 System.Int32.MaxValuethen
216278// Handle range [-MaxValue,MaxValue]
@@ -222,7 +284,8 @@ namespace System.Numerics
222284else
223285 raise( System.OverflowException())
224286
225- static member op_Explicit ( x : BigInteger ) =
287+ static member op_Explicit ( x : BigInteger ) =
288+ if x.IsZerothen 0 Lelse
226289let u = BigNatModule.toUInt64 x.V
227290if u<= uint64 System.Int64.MaxValuethen
228291(* Handle range [-MaxValue,MaxValue]*)
@@ -238,17 +301,23 @@ namespace System.Numerics
238301match x.SignIntwith
239302| 1 -> BigNatModule.toFloat x.V// float (1.xv) = float (xv)
240303| - 1 -> - ( BigNatModule.toFloat x.V) // float (-1.xv) = - float (xv)
241- | _ -> invalidArg" x" " signs should be +/- 1"
304+ | 0 -> 0.
305+ | _ -> invalidArg" x" " signs should be +/- 1 or 0"
242306
243307static member Parse ( text : string ) =
308+ if text= null then raise( new ArgumentNullException( " text" ))
309+ let text = text.Trim()
244310let len = text.Length
245- if len= 0 then raise( new System.FormatException( " The value could not be parsed" ))
246- if text.[ 0 .. 0 ] = " -" then
247- BigInteger.negn( BigNatModule.ofString text.[ 1 .. len-1 ])
248- else
249- BigInteger.posn( BigNatModule.ofString text)
250-
251- member internal x.IsSmall = BigNatModule.isSmall( x.V)
311+ if len= 0 then raise( new System.FormatException( SR.GetString( SR.badFormatString)))
312+ match text.[ 0 ], lenwith
313+ | '-' , 1 -> raise( new System.FormatException( SR.GetString( SR.badFormatString)))
314+ | '-' , _ -> BigInteger.negn( BigNatModule.ofString text.[ 1 .. len-1 ])
315+ | '+' , 1 -> raise( new System.FormatException( SR.GetString( SR.badFormatString)))
316+ | '+' , _ -> BigInteger.posn( BigNatModule.ofString text.[ 1 .. len-1 ])
317+ | _ -> BigInteger.posn( BigNatModule.ofString text)
318+
319+ member internal x.IsSmall = x.IsZero|| BigNatModule.isSmall( x.V)
320+
252321static member Factorial ( x : BigInteger ) =
253322if x.IsNegativethen invalidArg" x" ( SR.GetString( SR.inputMustBeNonNegative))
254323if x.IsPositivethen BigInteger.posn( BigNatModule.factorial x.V)
@@ -257,6 +326,7 @@ namespace System.Numerics
257326static member ( ~+ )( n1 : BigInteger ) = n1
258327
259328static member FromInt64 ( x : int64 ) = new BigInteger( x)
329+
260330static member FromInt32 ( x : int32 ) = new BigInteger( x)
261331#endif
262332