| | | 1 | | #pragma warning disable SA1028 // Code should not contain trailing whitespace |
| | | 2 | | #pragma warning disable SA1515 // Single-line comment should be preceded by blank line |
| | | 3 | | // |
| | | 4 | | // System.Numerics.BigInteger |
| | | 5 | | // |
| | | 6 | | // Authors: |
| | | 7 | | // Rodrigo Kumpera (rkumpera@novell.com) |
| | | 8 | | // Marek Safar <marek.safar@gmail.com> |
| | | 9 | | // |
| | | 10 | | // Copyright (C) 2010 Novell, Inc (http://www.novell.com) |
| | | 11 | | // Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com) |
| | | 12 | | // |
| | | 13 | | // Permission is hereby granted, free of charge, to any person obtaining |
| | | 14 | | // a copy of this software and associated documentation files (the |
| | | 15 | | // "Software"), to deal in the Software without restriction, including |
| | | 16 | | // without limitation the rights to use, copy, modify, merge, publish, |
| | | 17 | | // distribute, sublicense, and/or sell copies of the Software, and to |
| | | 18 | | // permit persons to whom the Software is furnished to do so, subject to |
| | | 19 | | // the following conditions: |
| | | 20 | | // |
| | | 21 | | // The above copyright notice and this permission notice shall be |
| | | 22 | | // included in all copies or substantial portions of the Software. |
| | | 23 | | // |
| | | 24 | | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| | | 25 | | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| | | 26 | | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| | | 27 | | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| | | 28 | | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| | | 29 | | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| | | 30 | | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| | | 31 | | // |
| | | 32 | | // A big chuck of code comes the DLR (as hosted in http://ironpython.codeplex.com), |
| | | 33 | | // which has the following License: |
| | | 34 | | // |
| | | 35 | | /* **************************************************************************** |
| | | 36 | | * |
| | | 37 | | * Copyright (c) Microsoft Corporation. |
| | | 38 | | * |
| | | 39 | | * This source code is subject to terms and conditions of the Microsoft Public License. A |
| | | 40 | | * copy of the license can be found in the License.html file at the root of this distribution. If |
| | | 41 | | * you cannot locate the Microsoft Public License, please send an email to |
| | | 42 | | * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound |
| | | 43 | | * by the terms of the Microsoft Public License. |
| | | 44 | | * |
| | | 45 | | * You must not remove this notice, or any other, from this software. |
| | | 46 | | * |
| | | 47 | | * |
| | | 48 | | * ***************************************************************************/ |
| | | 49 | | #pragma warning restore SA1515 // Single-line comment should be preceded by blank line |
| | | 50 | | #pragma warning restore SA1028 // Code should not contain trailing whitespace |
| | | 51 | | |
| | | 52 | | using System; |
| | | 53 | | using System.Collections.Generic; |
| | | 54 | | using System.Globalization; |
| | | 55 | | |
| | | 56 | | using Renci.SshNet.Abstractions; |
| | | 57 | | |
| | | 58 | | /* |
| | | 59 | | * Optimization: |
| | | 60 | | * - Have proper popcount function for IsPowerOfTwo |
| | | 61 | | * - Use unsafe ops to avoid bounds check |
| | | 62 | | * - CoreAdd could avoid some resizes by checking for equal sized array that top overflow |
| | | 63 | | * - For bitwise operators, hoist the conditionals out of their main loop |
| | | 64 | | * - Optimize BitScanBackward |
| | | 65 | | * - Use a carry variable to make shift opts do half the number of array ops. |
| | | 66 | | * -Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers |
| | | 67 | | */ |
| | | 68 | | namespace Renci.SshNet.Common |
| | | 69 | | { |
| | | 70 | | /// <summary> |
| | | 71 | | /// Represents an arbitrarily large signed integer. |
| | | 72 | | /// </summary> |
| | | 73 | | public struct BigInteger : IComparable, IFormattable, IComparable<BigInteger>, IEquatable<BigInteger> |
| | | 74 | | { |
| | | 75 | | private const ulong Base = 0x100000000; |
| | | 76 | | private const int Bias = 1075; |
| | | 77 | | private const int DecimalSignMask = unchecked((int)0x80000000); |
| | | 78 | | |
| | 4 | 79 | | private static readonly BigInteger ZeroSingleton = new BigInteger(0); |
| | 4 | 80 | | private static readonly BigInteger OneSingleton = new BigInteger(1); |
| | 4 | 81 | | private static readonly BigInteger MinusOneSingleton = new BigInteger(-1); |
| | | 82 | | |
| | | 83 | | // LSB on [0] |
| | | 84 | | private readonly uint[] _data; |
| | | 85 | | private readonly short _sign; |
| | | 86 | | |
| | | 87 | | #region SSH.NET additions |
| | | 88 | | |
| | | 89 | | /// <summary> |
| | | 90 | | /// Gets number of bits used by the number. |
| | | 91 | | /// </summary> |
| | | 92 | | /// <value> |
| | | 93 | | /// The number of the bit used. |
| | | 94 | | /// </value> |
| | | 95 | | public readonly int BitLength |
| | | 96 | | { |
| | | 97 | | get |
| | 2619 | 98 | | { |
| | 2619 | 99 | | if (_sign == 0) |
| | 0 | 100 | | { |
| | 0 | 101 | | return 0; |
| | | 102 | | } |
| | | 103 | | |
| | 2619 | 104 | | var msbIndex = _data.Length - 1; |
| | | 105 | | |
| | 2619 | 106 | | while (_data[msbIndex] == 0) |
| | 0 | 107 | | { |
| | 0 | 108 | | msbIndex--; |
| | 0 | 109 | | } |
| | | 110 | | |
| | 2619 | 111 | | var msbBitCount = BitScanBackward(_data[msbIndex]) + 1; |
| | | 112 | | |
| | 2619 | 113 | | return (msbIndex * 4 * 8) + msbBitCount + ((_sign > 0) ? 0 : 1); |
| | 2619 | 114 | | } |
| | | 115 | | } |
| | | 116 | | |
| | | 117 | | /// <summary> |
| | | 118 | | /// Mods the inverse. |
| | | 119 | | /// </summary> |
| | | 120 | | /// <param name="bi">The bi.</param> |
| | | 121 | | /// <param name="modulus">The modulus.</param> |
| | | 122 | | /// <returns> |
| | | 123 | | /// Modulus inverted number. |
| | | 124 | | /// </returns> |
| | | 125 | | public static BigInteger ModInverse(BigInteger bi, BigInteger modulus) |
| | 700 | 126 | | { |
| | 1400 | 127 | | BigInteger a = modulus, b = bi % modulus; |
| | 1400 | 128 | | BigInteger p0 = 0, p1 = 1; |
| | | 129 | | |
| | 416538 | 130 | | while (!b.IsZero) |
| | 416538 | 131 | | { |
| | 416538 | 132 | | if (b.IsOne) |
| | 373 | 133 | | { |
| | 373 | 134 | | return p1; |
| | | 135 | | } |
| | | 136 | | |
| | 416165 | 137 | | p0 += (a / b) * p1; |
| | 416165 | 138 | | a %= b; |
| | | 139 | | |
| | 416165 | 140 | | if (a.IsZero) |
| | 0 | 141 | | { |
| | 0 | 142 | | break; |
| | | 143 | | } |
| | | 144 | | |
| | 416165 | 145 | | if (a.IsOne) |
| | 327 | 146 | | { |
| | 327 | 147 | | return modulus - p0; |
| | | 148 | | } |
| | | 149 | | |
| | 415838 | 150 | | p1 += (b / a) * p0; |
| | 415838 | 151 | | b %= a; |
| | 415838 | 152 | | } |
| | | 153 | | |
| | 0 | 154 | | return 0; |
| | 700 | 155 | | } |
| | | 156 | | |
| | | 157 | | /// <summary> |
| | | 158 | | /// Returns positive remainder that results from division with two specified <see cref="BigInteger"/> values. |
| | | 159 | | /// </summary> |
| | | 160 | | /// <param name="dividend">The value to be divided.</param> |
| | | 161 | | /// <param name="divisor">The value to divide by.</param> |
| | | 162 | | /// <returns> |
| | | 163 | | /// Positive remainder that results from the division. |
| | | 164 | | /// </returns> |
| | | 165 | | public static BigInteger PositiveMod(BigInteger dividend, BigInteger divisor) |
| | 2088 | 166 | | { |
| | 2088 | 167 | | var result = dividend % divisor; |
| | | 168 | | |
| | 2088 | 169 | | if (result < 0) |
| | 291 | 170 | | { |
| | 291 | 171 | | result += divisor; |
| | 291 | 172 | | } |
| | | 173 | | |
| | 2088 | 174 | | return result; |
| | 2088 | 175 | | } |
| | | 176 | | |
| | | 177 | | /// <summary> |
| | | 178 | | /// Generates a new, random <see cref="BigInteger"/> of the specified length. |
| | | 179 | | /// </summary> |
| | | 180 | | /// <param name="bitLength">The number of bits for the new number.</param> |
| | | 181 | | /// <returns>A random number of the specified length.</returns> |
| | | 182 | | public static BigInteger Random(int bitLength) |
| | 727 | 183 | | { |
| | 727 | 184 | | var bytesArray = new byte[(bitLength / 8) + (((bitLength % 8) > 0) ? 1 : 0)]; |
| | 727 | 185 | | CryptoAbstraction.GenerateRandom(bytesArray); |
| | 727 | 186 | | bytesArray[bytesArray.Length - 1] = (byte) (bytesArray[bytesArray.Length - 1] & 0x7F); // Ensure not a negat |
| | 727 | 187 | | return new BigInteger(bytesArray); |
| | 727 | 188 | | } |
| | | 189 | | |
| | | 190 | | #endregion SSH.NET additions |
| | | 191 | | |
| | | 192 | | private BigInteger(short sign, uint[] data) |
| | 9009700 | 193 | | { |
| | 9009700 | 194 | | _sign = sign; |
| | 9009700 | 195 | | _data = data; |
| | 9009700 | 196 | | } |
| | | 197 | | |
| | | 198 | | /// <summary> |
| | | 199 | | /// Initializes a new instance of the <see cref="BigInteger"/> structure using a 32-bit signed integer value. |
| | | 200 | | /// </summary> |
| | | 201 | | /// <param name="value">A 32-bit signed integer.</param> |
| | | 202 | | public BigInteger(int value) |
| | 27644 | 203 | | { |
| | 27644 | 204 | | if (value == 0) |
| | 1874 | 205 | | { |
| | 1874 | 206 | | _sign = 0; |
| | 1874 | 207 | | _data = null; |
| | 1874 | 208 | | } |
| | 25770 | 209 | | else if (value > 0) |
| | 25616 | 210 | | { |
| | 25616 | 211 | | _sign = 1; |
| | 25616 | 212 | | _data = new[] { (uint) value }; |
| | 25616 | 213 | | } |
| | | 214 | | else |
| | 154 | 215 | | { |
| | 154 | 216 | | _sign = -1; |
| | | 217 | | #pragma warning disable SA1021 // Negative signs should be spaced correctly |
| | 154 | 218 | | _data = new[] { (uint) -value }; |
| | | 219 | | #pragma warning restore SA1021 // Negative signs should be spaced correctly |
| | 154 | 220 | | } |
| | 27644 | 221 | | } |
| | | 222 | | |
| | | 223 | | /// <summary> |
| | | 224 | | /// Initializes a new instance of the <see cref="BigInteger"/> structure using an unsigned 32-bit integer value. |
| | | 225 | | /// </summary> |
| | | 226 | | /// <param name="value">An unsigned 32-bit integer value.</param> |
| | | 227 | | [CLSCompliant(false)] |
| | | 228 | | public BigInteger(uint value) |
| | 18201 | 229 | | { |
| | 18201 | 230 | | if (value == 0) |
| | 0 | 231 | | { |
| | 0 | 232 | | _sign = 0; |
| | 0 | 233 | | _data = null; |
| | 0 | 234 | | } |
| | | 235 | | else |
| | 18201 | 236 | | { |
| | 18201 | 237 | | _sign = 1; |
| | 18201 | 238 | | _data = new[] { value }; |
| | 18201 | 239 | | } |
| | 18201 | 240 | | } |
| | | 241 | | |
| | | 242 | | /// <summary> |
| | | 243 | | /// Initializes a new instance of the <see cref="BigInteger"/> structure using a 64-bit signed integer value. |
| | | 244 | | /// </summary> |
| | | 245 | | /// <param name="value">A 64-bit signed integer.</param> |
| | | 246 | | public BigInteger(long value) |
| | 3645 | 247 | | { |
| | 3645 | 248 | | if (value == 0) |
| | 426 | 249 | | { |
| | 426 | 250 | | _sign = 0; |
| | 426 | 251 | | _data = null; |
| | 426 | 252 | | } |
| | 3219 | 253 | | else if (value > 0) |
| | 1737 | 254 | | { |
| | 1737 | 255 | | _sign = 1; |
| | 1737 | 256 | | var low = (uint)value; |
| | 1737 | 257 | | var high = (uint)(value >> 32); |
| | | 258 | | |
| | 1737 | 259 | | _data = new uint[high != 0 ? 2 : 1]; |
| | 1737 | 260 | | _data[0] = low; |
| | 1737 | 261 | | if (high != 0) |
| | 657 | 262 | | { |
| | 657 | 263 | | _data[1] = high; |
| | 657 | 264 | | } |
| | 1737 | 265 | | } |
| | | 266 | | else |
| | 1482 | 267 | | { |
| | 1482 | 268 | | _sign = -1; |
| | 1482 | 269 | | value = -value; |
| | 1482 | 270 | | var low = (uint)value; |
| | 1482 | 271 | | var high = (uint)((ulong)value >> 32); |
| | | 272 | | |
| | 1482 | 273 | | _data = new uint[high != 0 ? 2 : 1]; |
| | 1482 | 274 | | _data[0] = low; |
| | 1482 | 275 | | if (high != 0) |
| | 507 | 276 | | { |
| | 507 | 277 | | _data[1] = high; |
| | 507 | 278 | | } |
| | 1482 | 279 | | } |
| | 3645 | 280 | | } |
| | | 281 | | |
| | | 282 | | /// <summary> |
| | | 283 | | /// Initializes a new instance of the <see cref="BigInteger"/> structure with an unsigned 64-bit integer value. |
| | | 284 | | /// </summary> |
| | | 285 | | /// <param name="value">An unsigned 64-bit integer.</param> |
| | | 286 | | [CLSCompliant(false)] |
| | | 287 | | public BigInteger(ulong value) |
| | 210 | 288 | | { |
| | 210 | 289 | | if (value == 0) |
| | 24 | 290 | | { |
| | 24 | 291 | | _sign = 0; |
| | 24 | 292 | | _data = null; |
| | 24 | 293 | | } |
| | | 294 | | else |
| | 186 | 295 | | { |
| | 186 | 296 | | _sign = 1; |
| | 186 | 297 | | var low = (uint) value; |
| | 186 | 298 | | var high = (uint) (value >> 32); |
| | | 299 | | |
| | 186 | 300 | | _data = new uint[high != 0 ? 2 : 1]; |
| | 186 | 301 | | _data[0] = low; |
| | 186 | 302 | | if (high != 0) |
| | 114 | 303 | | { |
| | 114 | 304 | | _data[1] = high; |
| | 114 | 305 | | } |
| | 186 | 306 | | } |
| | 210 | 307 | | } |
| | | 308 | | |
| | | 309 | | /// <summary> |
| | | 310 | | /// Initializes a new instance of the <see cref="BigInteger"/> structure using a double-precision floating-point |
| | | 311 | | /// </summary> |
| | | 312 | | /// <param name="value">A double-precision floating-point value.</param> |
| | | 313 | | public BigInteger(double value) |
| | 24 | 314 | | { |
| | 24 | 315 | | if (double.IsNaN(value) || double.IsInfinity(value)) |
| | 9 | 316 | | { |
| | 9 | 317 | | throw new OverflowException(); |
| | | 318 | | } |
| | | 319 | | |
| | 15 | 320 | | var bytes = BitConverter.GetBytes(value); |
| | 15 | 321 | | var mantissa = Mantissa(bytes); |
| | 15 | 322 | | if (mantissa == 0) |
| | 0 | 323 | | { |
| | | 324 | | // 1.0 * 2**exp, we have a power of 2 |
| | 0 | 325 | | int exponent = Exponent(bytes); |
| | 0 | 326 | | if (exponent == 0) |
| | 0 | 327 | | { |
| | 0 | 328 | | _sign = 0; |
| | 0 | 329 | | _data = null; |
| | 0 | 330 | | return; |
| | | 331 | | } |
| | | 332 | | |
| | 0 | 333 | | var res = Negative(bytes) ? MinusOne : One; |
| | 0 | 334 | | res <<= exponent - 0x3ff; |
| | 0 | 335 | | _sign = res._sign; |
| | 0 | 336 | | _data = res._data; |
| | 0 | 337 | | } |
| | | 338 | | else |
| | 15 | 339 | | { |
| | | 340 | | // 1.mantissa * 2**exp |
| | 15 | 341 | | int exponent = Exponent(bytes); |
| | 15 | 342 | | mantissa |= 0x10000000000000ul; |
| | 15 | 343 | | BigInteger res = mantissa; |
| | 15 | 344 | | res = exponent > Bias ? res << (exponent - Bias) : res >> (Bias - exponent); |
| | | 345 | | |
| | 15 | 346 | | _sign = (short) (Negative(bytes) ? -1 : 1); |
| | 15 | 347 | | _data = res._data; |
| | 15 | 348 | | } |
| | 15 | 349 | | } |
| | | 350 | | |
| | | 351 | | /// <summary> |
| | | 352 | | /// Initializes a new instance of the <see cref="BigInteger"/> structure using a single-precision floating-point |
| | | 353 | | /// </summary> |
| | | 354 | | /// <param name="value">A single-precision floating-point value.</param> |
| | | 355 | | public BigInteger(float value) |
| | 0 | 356 | | : this((double) value) |
| | 0 | 357 | | { |
| | 0 | 358 | | } |
| | | 359 | | |
| | | 360 | | /// <summary> |
| | | 361 | | /// Initializes a new instance of the <see cref="BigInteger"/> structure using a <see cref="decimal"/> value. |
| | | 362 | | /// </summary> |
| | | 363 | | /// <param name="value">A decimal number.</param> |
| | | 364 | | public BigInteger(decimal value) |
| | 12 | 365 | | { |
| | | 366 | | // First truncate to get scale to 0 and extract bits |
| | 12 | 367 | | var bits = decimal.GetBits(decimal.Truncate(value)); |
| | | 368 | | |
| | 12 | 369 | | var size = 3; |
| | 33 | 370 | | while (size > 0 && bits[size - 1] == 0) |
| | 21 | 371 | | { |
| | 21 | 372 | | size--; |
| | 21 | 373 | | } |
| | | 374 | | |
| | 12 | 375 | | if (size == 0) |
| | 3 | 376 | | { |
| | 3 | 377 | | _sign = 0; |
| | 3 | 378 | | _data = null; |
| | 3 | 379 | | return; |
| | | 380 | | } |
| | | 381 | | |
| | 9 | 382 | | _sign = (short) ((bits[3] & DecimalSignMask) != 0 ? -1 : 1); |
| | | 383 | | |
| | 9 | 384 | | _data = new uint[size]; |
| | 9 | 385 | | _data[0] = (uint) bits[0]; |
| | 9 | 386 | | if (size > 1) |
| | 3 | 387 | | { |
| | 3 | 388 | | _data[1] = (uint) bits[1]; |
| | 3 | 389 | | } |
| | | 390 | | |
| | 9 | 391 | | if (size > 2) |
| | 3 | 392 | | { |
| | 3 | 393 | | _data[2] = (uint) bits[2]; |
| | 3 | 394 | | } |
| | 12 | 395 | | } |
| | | 396 | | |
| | | 397 | | /// <summary> |
| | | 398 | | /// Initializes a new instance of the <see cref="BigInteger"/> structure using the values in a byte array. |
| | | 399 | | /// </summary> |
| | | 400 | | /// <param name="value">An array of <see cref="byte"/> values in little-endian order.</param> |
| | | 401 | | /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception> |
| | | 402 | | [CLSCompliant(false)] |
| | | 403 | | public BigInteger(byte[] value) |
| | 11224 | 404 | | { |
| | 11224 | 405 | | if (value is null) |
| | 3 | 406 | | { |
| | 3 | 407 | | throw new ArgumentNullException(nameof(value)); |
| | | 408 | | } |
| | | 409 | | |
| | 11221 | 410 | | var len = value.Length; |
| | | 411 | | |
| | 11221 | 412 | | if (len == 0 || (len == 1 && value[0] == 0)) |
| | 517 | 413 | | { |
| | 517 | 414 | | _sign = 0; |
| | 517 | 415 | | _data = null; |
| | 517 | 416 | | return; |
| | | 417 | | } |
| | | 418 | | |
| | 10704 | 419 | | if ((value[len - 1] & 0x80) != 0) |
| | 90 | 420 | | { |
| | 90 | 421 | | _sign = -1; |
| | 90 | 422 | | } |
| | | 423 | | else |
| | 10614 | 424 | | { |
| | 10614 | 425 | | _sign = 1; |
| | 10614 | 426 | | } |
| | | 427 | | |
| | | 428 | | #pragma warning disable CA1508 // Avoid dead conditional code | this is the following bug in the analyzer rule: https:// |
| | 10704 | 429 | | if (_sign == 1) |
| | | 430 | | #pragma warning restore CA1508 // Avoid dead conditional code |
| | 10614 | 431 | | { |
| | 16623 | 432 | | while (value[len - 1] == 0) |
| | 6012 | 433 | | { |
| | 6012 | 434 | | if (--len == 0) |
| | 3 | 435 | | { |
| | 3 | 436 | | _sign = 0; |
| | 3 | 437 | | _data = null; |
| | 3 | 438 | | return; |
| | | 439 | | } |
| | 6009 | 440 | | } |
| | | 441 | | |
| | | 442 | | int size; |
| | 10611 | 443 | | var fullWords = size = len / 4; |
| | 10611 | 444 | | if ((len & 0x3) != 0) |
| | 2579 | 445 | | { |
| | 2579 | 446 | | ++size; |
| | 2579 | 447 | | } |
| | | 448 | | |
| | 10611 | 449 | | _data = new uint[size]; |
| | 10611 | 450 | | var j = 0; |
| | 985608 | 451 | | for (var i = 0; i < fullWords; ++i) |
| | 482193 | 452 | | { |
| | 482193 | 453 | | _data[i] = (uint) value[j++] | |
| | 482193 | 454 | | (uint) (value[j++] << 8) | |
| | 482193 | 455 | | (uint) (value[j++] << 16) | |
| | 482193 | 456 | | (uint) (value[j++] << 24); |
| | 482193 | 457 | | } |
| | | 458 | | |
| | 10611 | 459 | | size = len & 0x3; |
| | 10611 | 460 | | if (size > 0) |
| | 2579 | 461 | | { |
| | 2579 | 462 | | var idx = _data.Length - 1; |
| | 18300 | 463 | | for (var i = 0; i < size; ++i) |
| | 6571 | 464 | | { |
| | 6571 | 465 | | _data[idx] |= (uint) (value[j++] << (i * 8)); |
| | 6571 | 466 | | } |
| | 2579 | 467 | | } |
| | 10611 | 468 | | } |
| | | 469 | | else |
| | 90 | 470 | | { |
| | | 471 | | int size; |
| | 90 | 472 | | var fullWords = size = len / 4; |
| | 90 | 473 | | if ((len & 0x3) != 0) |
| | 60 | 474 | | { |
| | 60 | 475 | | ++size; |
| | 60 | 476 | | } |
| | | 477 | | |
| | 90 | 478 | | _data = new uint[size]; |
| | | 479 | | |
| | 90 | 480 | | uint word, borrow = 1; |
| | | 481 | | ulong sub; |
| | 90 | 482 | | var j = 0; |
| | | 483 | | |
| | 1362 | 484 | | for (var i = 0; i < fullWords; ++i) |
| | 591 | 485 | | { |
| | 591 | 486 | | word = (uint) value[j++] | |
| | 591 | 487 | | (uint) (value[j++] << 8) | |
| | 591 | 488 | | (uint) (value[j++] << 16) | |
| | 591 | 489 | | (uint) (value[j++] << 24); |
| | | 490 | | |
| | 591 | 491 | | sub = (ulong) word - borrow; |
| | 591 | 492 | | word = (uint) sub; |
| | 591 | 493 | | borrow = (uint) (sub >> 32) & 0x1u; |
| | 591 | 494 | | _data[i] = ~word; |
| | 591 | 495 | | } |
| | | 496 | | |
| | 90 | 497 | | size = len & 0x3; |
| | | 498 | | |
| | 90 | 499 | | if (size > 0) |
| | 60 | 500 | | { |
| | 60 | 501 | | word = 0; |
| | 60 | 502 | | uint storeMask = 0; |
| | 336 | 503 | | for (var i = 0; i < size; ++i) |
| | 108 | 504 | | { |
| | 108 | 505 | | word |= (uint) (value[j++] << (i * 8)); |
| | 108 | 506 | | storeMask = (storeMask << 8) | 0xFF; |
| | 108 | 507 | | } |
| | | 508 | | |
| | 60 | 509 | | sub = word - borrow; |
| | 60 | 510 | | word = (uint) sub; |
| | 60 | 511 | | borrow = (uint) (sub >> 32) & 0x1u; |
| | | 512 | | |
| | 60 | 513 | | if ((~word & storeMask) == 0) |
| | 12 | 514 | | { |
| | 12 | 515 | | Array.Resize(ref _data, _data.Length - 1); |
| | 12 | 516 | | } |
| | | 517 | | else |
| | 48 | 518 | | { |
| | 48 | 519 | | _data[_data.Length - 1] = ~word & storeMask; |
| | 48 | 520 | | } |
| | 60 | 521 | | } |
| | | 522 | | |
| | 90 | 523 | | if (borrow != 0) |
| | 0 | 524 | | { |
| | | 525 | | #pragma warning disable CA2201 // Do not raise reserved exception types |
| | 0 | 526 | | throw new Exception("non zero final carry"); |
| | | 527 | | #pragma warning restore CA2201 // Do not raise reserved exception types |
| | | 528 | | } |
| | 90 | 529 | | } |
| | 11221 | 530 | | } |
| | | 531 | | |
| | | 532 | | private static bool Negative(byte[] v) |
| | 15 | 533 | | { |
| | 15 | 534 | | return (v[7] & 0x80) != 0; |
| | 15 | 535 | | } |
| | | 536 | | |
| | | 537 | | private static ushort Exponent(byte[] v) |
| | 15 | 538 | | { |
| | 15 | 539 | | return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4)); |
| | 15 | 540 | | } |
| | | 541 | | |
| | | 542 | | private static ulong Mantissa(byte[] v) |
| | 15 | 543 | | { |
| | 15 | 544 | | var i1 = (uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24); |
| | 15 | 545 | | var i2 = (uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16); |
| | | 546 | | |
| | 15 | 547 | | return (ulong) i1 | ((ulong) i2 << 32); |
| | 15 | 548 | | } |
| | | 549 | | |
| | | 550 | | /// <summary> |
| | | 551 | | /// Gets a value indicating whether the value of the current <see cref="BigInteger"/> object is an even number. |
| | | 552 | | /// </summary> |
| | | 553 | | /// <value> |
| | | 554 | | /// <see langword="true"/> if the value of the <see cref="BigInteger"/> object is an even number; otherwise, <se |
| | | 555 | | /// </value> |
| | | 556 | | public readonly bool IsEven |
| | | 557 | | { |
| | 4453422 | 558 | | get { return _sign == 0 || (_data[0] & 0x1) == 0; } |
| | | 559 | | } |
| | | 560 | | |
| | | 561 | | /// <summary> |
| | | 562 | | /// Gets a value indicating whether the value of the current <see cref="BigInteger"/> object is <see cref="One"/ |
| | | 563 | | /// </summary> |
| | | 564 | | /// <value> |
| | | 565 | | /// <see langword="true"/> if the value of the <see cref="BigInteger"/> object is <see cref="One"/>; |
| | | 566 | | /// otherwise, <see langword="false"/>. |
| | | 567 | | /// </value> |
| | | 568 | | public readonly bool IsOne |
| | | 569 | | { |
| | 6951558 | 570 | | get { return _sign == 1 && _data.Length == 1 && _data[0] == 1; } |
| | | 571 | | } |
| | | 572 | | |
| | | 573 | | // Gem from Hacker's Delight |
| | | 574 | | // Returns the number of bits set in @x |
| | | 575 | | private static int PopulationCount(uint x) |
| | 51 | 576 | | { |
| | 51 | 577 | | x -= (x >> 1) & 0x55555555; |
| | 51 | 578 | | x = (x & 0x33333333) + ((x >> 2) & 0x33333333); |
| | 51 | 579 | | x = (x + (x >> 4)) & 0x0F0F0F0F; |
| | 51 | 580 | | x += x >> 8; |
| | 51 | 581 | | x += x >> 16; |
| | 51 | 582 | | return (int) (x & 0x0000003F); |
| | 51 | 583 | | } |
| | | 584 | | |
| | | 585 | | /// <summary> |
| | | 586 | | /// Returns the number of bits set in <paramref name="x"/>. |
| | | 587 | | /// </summary> |
| | | 588 | | /// <returns> |
| | | 589 | | /// The number of bits set in <paramref name="x"/>. |
| | | 590 | | /// </returns> |
| | | 591 | | /// <remarks> |
| | | 592 | | /// Based on code by Zilong Tan on Ulib released under MIT license. |
| | | 593 | | /// </remarks> |
| | | 594 | | private static int PopulationCount(ulong x) |
| | 54 | 595 | | { |
| | 54 | 596 | | x -= (x >> 1) & 0x5555555555555555UL; |
| | 54 | 597 | | x = (x & 0x3333333333333333UL) + ((x >> 2) & 0x3333333333333333UL); |
| | 54 | 598 | | x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fUL; |
| | 54 | 599 | | return (int)((x * 0x0101010101010101UL) >> 56); |
| | 54 | 600 | | } |
| | | 601 | | |
| | | 602 | | private static int LeadingZeroCount(uint value) |
| | 39 | 603 | | { |
| | 39 | 604 | | value |= value >> 1; |
| | 39 | 605 | | value |= value >> 2; |
| | 39 | 606 | | value |= value >> 4; |
| | 39 | 607 | | value |= value >> 8; |
| | 39 | 608 | | value |= value >> 16; |
| | 39 | 609 | | return 32 - PopulationCount(value); // 32 = bits in uint |
| | 39 | 610 | | } |
| | | 611 | | |
| | | 612 | | private static int LeadingZeroCount(ulong value) |
| | 54 | 613 | | { |
| | 54 | 614 | | value |= value >> 1; |
| | 54 | 615 | | value |= value >> 2; |
| | 54 | 616 | | value |= value >> 4; |
| | 54 | 617 | | value |= value >> 8; |
| | 54 | 618 | | value |= value >> 16; |
| | 54 | 619 | | value |= value >> 32; |
| | 54 | 620 | | return 64 - PopulationCount(value); // 64 = bits in ulong |
| | 54 | 621 | | } |
| | | 622 | | |
| | | 623 | | private static double BuildDouble(int sign, ulong mantissa, int exponent) |
| | 54 | 624 | | { |
| | | 625 | | const int exponentBias = 1023; |
| | | 626 | | const int mantissaLength = 52; |
| | | 627 | | const int exponentLength = 11; |
| | | 628 | | const int maxExponent = 2046; |
| | | 629 | | const long mantissaMask = 0xfffffffffffffL; |
| | | 630 | | const long exponentMask = 0x7ffL; |
| | | 631 | | const ulong negativeMark = 0x8000000000000000uL; |
| | | 632 | | |
| | 54 | 633 | | if (sign == 0 || mantissa == 0) |
| | 0 | 634 | | { |
| | 0 | 635 | | return 0.0; |
| | | 636 | | } |
| | | 637 | | |
| | 54 | 638 | | exponent += exponentBias + mantissaLength; |
| | 54 | 639 | | var offset = LeadingZeroCount(mantissa) - exponentLength; |
| | 54 | 640 | | if (exponent - offset > maxExponent) |
| | 9 | 641 | | { |
| | 9 | 642 | | return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity; |
| | | 643 | | } |
| | | 644 | | |
| | 45 | 645 | | if (offset < 0) |
| | 6 | 646 | | { |
| | 6 | 647 | | mantissa >>= -offset; |
| | 6 | 648 | | exponent += -offset; |
| | 6 | 649 | | } |
| | 39 | 650 | | else if (offset >= exponent) |
| | 0 | 651 | | { |
| | 0 | 652 | | mantissa <<= exponent - 1; |
| | 0 | 653 | | exponent = 0; |
| | 0 | 654 | | } |
| | | 655 | | else |
| | 39 | 656 | | { |
| | 39 | 657 | | mantissa <<= offset; |
| | 39 | 658 | | exponent -= offset; |
| | 39 | 659 | | } |
| | | 660 | | |
| | 45 | 661 | | mantissa &= mantissaMask; |
| | | 662 | | |
| | 45 | 663 | | if ((exponent & exponentMask) == exponent) |
| | 45 | 664 | | { |
| | | 665 | | unchecked |
| | 45 | 666 | | { |
| | 45 | 667 | | var bits = mantissa | ((ulong)exponent << mantissaLength); |
| | 45 | 668 | | if (sign < 0) |
| | 12 | 669 | | { |
| | 12 | 670 | | bits |= negativeMark; |
| | 12 | 671 | | } |
| | | 672 | | |
| | 45 | 673 | | return BitConverter.Int64BitsToDouble((long)bits); |
| | | 674 | | } |
| | | 675 | | } |
| | | 676 | | |
| | 0 | 677 | | return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity; |
| | 54 | 678 | | } |
| | | 679 | | |
| | | 680 | | /// <summary> |
| | | 681 | | /// Gets a value Indicating whether the value of the current <see cref="BigInteger"/> object is a power of two. |
| | | 682 | | /// </summary> |
| | | 683 | | /// <value> |
| | | 684 | | /// <see langword="true"/> if the value of the <see cref="BigInteger"/> object is a power of two; |
| | | 685 | | /// otherwise, <see langword="false"/>. |
| | | 686 | | /// </value> |
| | | 687 | | public readonly bool IsPowerOfTwo |
| | | 688 | | { |
| | | 689 | | get |
| | 27 | 690 | | { |
| | 27 | 691 | | if (_sign != 1) |
| | 15 | 692 | | { |
| | 15 | 693 | | return false; |
| | | 694 | | } |
| | | 695 | | |
| | 12 | 696 | | var foundBit = false; |
| | | 697 | | |
| | | 698 | | // This function is pop count == 1 for positive numbers |
| | 57 | 699 | | foreach (var bit in _data) |
| | 12 | 700 | | { |
| | 12 | 701 | | var p = PopulationCount(bit); |
| | 12 | 702 | | if (p > 0) |
| | 12 | 703 | | { |
| | 12 | 704 | | if (p > 1 || foundBit) |
| | 3 | 705 | | { |
| | 3 | 706 | | return false; |
| | | 707 | | } |
| | | 708 | | |
| | 9 | 709 | | foundBit = true; |
| | 9 | 710 | | } |
| | 9 | 711 | | } |
| | | 712 | | |
| | 9 | 713 | | return foundBit; |
| | 27 | 714 | | } |
| | | 715 | | } |
| | | 716 | | |
| | | 717 | | /// <summary> |
| | | 718 | | /// Gets a value indicating whether the value of the current <see cref="BigInteger"/> object is <see cref="Zero" |
| | | 719 | | /// </summary> |
| | | 720 | | /// <value> |
| | | 721 | | /// <see langword="true"/> if the value of the <see cref="BigInteger"/> object is <see cref="Zero"/>; |
| | | 722 | | /// otherwise, <see langword="false"/>. |
| | | 723 | | /// </value> |
| | | 724 | | public readonly bool IsZero |
| | | 725 | | { |
| | 2504220 | 726 | | get { return _sign == 0; } |
| | | 727 | | } |
| | | 728 | | |
| | | 729 | | /// <summary> |
| | | 730 | | /// Gets a number that indicates the sign (negative, positive, or zero) of the current <see cref="BigInteger"/> |
| | | 731 | | /// </summary> |
| | | 732 | | /// <value> |
| | | 733 | | /// A number that indicates the sign of the <see cref="BigInteger"/> object. |
| | | 734 | | /// </value> |
| | | 735 | | public readonly int Sign |
| | | 736 | | { |
| | 54 | 737 | | get { return _sign; } |
| | | 738 | | } |
| | | 739 | | |
| | | 740 | | /// <summary> |
| | | 741 | | /// Gets a value that represents the number negative one (-1). |
| | | 742 | | /// </summary> |
| | | 743 | | /// <value> |
| | | 744 | | /// An integer whose value is negative one (-1). |
| | | 745 | | /// </value> |
| | | 746 | | public static BigInteger MinusOne |
| | | 747 | | { |
| | 144 | 748 | | get { return MinusOneSingleton; } |
| | | 749 | | } |
| | | 750 | | |
| | | 751 | | /// <summary> |
| | | 752 | | /// Gets a value that represents the number one (1). |
| | | 753 | | /// </summary> |
| | | 754 | | /// <value> |
| | | 755 | | /// An object whose value is one (1). |
| | | 756 | | /// </value> |
| | | 757 | | public static BigInteger One |
| | | 758 | | { |
| | 18771 | 759 | | get { return OneSingleton; } |
| | | 760 | | } |
| | | 761 | | |
| | | 762 | | /// <summary> |
| | | 763 | | /// Gets a value that represents the number 0 (zero). |
| | | 764 | | /// </summary> |
| | | 765 | | /// <value> |
| | | 766 | | /// An integer whose value is 0 (zero). |
| | | 767 | | /// </value> |
| | | 768 | | public static BigInteger Zero |
| | | 769 | | { |
| | 14625 | 770 | | get { return ZeroSingleton; } |
| | | 771 | | } |
| | | 772 | | |
| | | 773 | | /// <summary> |
| | | 774 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 32-bit signed integer value. |
| | | 775 | | /// </summary> |
| | | 776 | | /// <param name="value">The value to convert to a 32-bit signed integer.</param> |
| | | 777 | | /// <returns> |
| | | 778 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 779 | | /// </returns> |
| | | 780 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 781 | | public static explicit operator int(BigInteger value) |
| | | 782 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 18462 | 783 | | { |
| | 18462 | 784 | | if (value._data is null) |
| | 2187 | 785 | | { |
| | 2187 | 786 | | return 0; |
| | | 787 | | } |
| | | 788 | | |
| | 16275 | 789 | | if (value._data.Length > 1) |
| | 3 | 790 | | { |
| | 3 | 791 | | throw new OverflowException(); |
| | | 792 | | } |
| | | 793 | | |
| | 16272 | 794 | | var data = value._data[0]; |
| | | 795 | | |
| | 16272 | 796 | | if (value._sign == 1) |
| | 16194 | 797 | | { |
| | 16194 | 798 | | if (data > (uint) int.MaxValue) |
| | 3 | 799 | | { |
| | 3 | 800 | | throw new OverflowException(); |
| | | 801 | | } |
| | | 802 | | |
| | 16191 | 803 | | return (int)data; |
| | | 804 | | } |
| | | 805 | | |
| | 78 | 806 | | if (value._sign == -1) |
| | 78 | 807 | | { |
| | 78 | 808 | | if (data > 0x80000000u) |
| | 3 | 809 | | { |
| | 3 | 810 | | throw new OverflowException(); |
| | | 811 | | } |
| | | 812 | | |
| | 75 | 813 | | return -(int)data; |
| | | 814 | | } |
| | | 815 | | |
| | 0 | 816 | | return 0; |
| | 18453 | 817 | | } |
| | | 818 | | |
| | | 819 | | /// <summary> |
| | | 820 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned 32-bit integer value. |
| | | 821 | | /// </summary> |
| | | 822 | | /// <param name="value">The value to convert to an unsigned 32-bit integer.</param> |
| | | 823 | | /// <returns> |
| | | 824 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 825 | | /// </returns> |
| | | 826 | | [CLSCompliant(false)] |
| | | 827 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 828 | | public static explicit operator uint(BigInteger value) |
| | | 829 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 18 | 830 | | { |
| | 18 | 831 | | if (value._data is null) |
| | 3 | 832 | | { |
| | 3 | 833 | | return 0; |
| | | 834 | | } |
| | | 835 | | |
| | 15 | 836 | | if (value._data.Length > 1 || value._sign == -1) |
| | 0 | 837 | | { |
| | 0 | 838 | | throw new OverflowException(); |
| | | 839 | | } |
| | | 840 | | |
| | 15 | 841 | | return value._data[0]; |
| | 18 | 842 | | } |
| | | 843 | | |
| | | 844 | | /// <summary> |
| | | 845 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 16-bit signed integer value. |
| | | 846 | | /// </summary> |
| | | 847 | | /// <param name="value">The value to convert to a 16-bit signed integer.</param> |
| | | 848 | | /// <returns> |
| | | 849 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 850 | | /// </returns> |
| | | 851 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 852 | | public static explicit operator short(BigInteger value) |
| | | 853 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 6 | 854 | | { |
| | 6 | 855 | | var val = (int) value; |
| | 6 | 856 | | if (val is < short.MinValue or > short.MaxValue) |
| | 6 | 857 | | { |
| | 6 | 858 | | throw new OverflowException(); |
| | | 859 | | } |
| | | 860 | | |
| | 0 | 861 | | return (short) val; |
| | 0 | 862 | | } |
| | | 863 | | |
| | | 864 | | /// <summary> |
| | | 865 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 16-bit unsigned integer value. |
| | | 866 | | /// </summary> |
| | | 867 | | /// <param name="value">The value to convert to a 16-bit unsigned integer.</param> |
| | | 868 | | /// <returns> |
| | | 869 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 870 | | /// </returns> |
| | | 871 | | [CLSCompliant(false)] |
| | | 872 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 873 | | public static explicit operator ushort(BigInteger value) |
| | | 874 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 875 | | { |
| | 0 | 876 | | var val = (uint) value; |
| | 0 | 877 | | if (val > ushort.MaxValue) |
| | 0 | 878 | | { |
| | 0 | 879 | | throw new OverflowException(); |
| | | 880 | | } |
| | | 881 | | |
| | 0 | 882 | | return (ushort) val; |
| | 0 | 883 | | } |
| | | 884 | | |
| | | 885 | | /// <summary> |
| | | 886 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned byte value. |
| | | 887 | | /// </summary> |
| | | 888 | | /// <param name="value">The value to convert to a <see cref="byte"/>.</param> |
| | | 889 | | /// <returns> |
| | | 890 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 891 | | /// </returns> |
| | | 892 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 893 | | public static explicit operator byte(BigInteger value) |
| | | 894 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 895 | | { |
| | 0 | 896 | | var val = (uint) value; |
| | 0 | 897 | | if (val > byte.MaxValue) |
| | 0 | 898 | | { |
| | 0 | 899 | | throw new OverflowException(); |
| | | 900 | | } |
| | | 901 | | |
| | 0 | 902 | | return (byte) val; |
| | 0 | 903 | | } |
| | | 904 | | |
| | | 905 | | /// <summary> |
| | | 906 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a signed 8-bit value. |
| | | 907 | | /// </summary> |
| | | 908 | | /// <param name="value">The value to convert to a signed 8-bit value.</param> |
| | | 909 | | /// <returns> |
| | | 910 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 911 | | /// </returns> |
| | | 912 | | [CLSCompliant(false)] |
| | | 913 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 914 | | public static explicit operator sbyte(BigInteger value) |
| | | 915 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 916 | | { |
| | 0 | 917 | | var val = (int) value; |
| | 0 | 918 | | if (val is < sbyte.MinValue or > sbyte.MaxValue) |
| | 0 | 919 | | { |
| | 0 | 920 | | throw new OverflowException(); |
| | | 921 | | } |
| | | 922 | | |
| | 0 | 923 | | return (sbyte) val; |
| | 0 | 924 | | } |
| | | 925 | | |
| | | 926 | | /// <summary> |
| | | 927 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 64-bit signed integer value. |
| | | 928 | | /// </summary> |
| | | 929 | | /// <param name="value">The value to convert to a 64-bit signed integer.</param> |
| | | 930 | | /// <returns> |
| | | 931 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 932 | | /// </returns> |
| | | 933 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 934 | | public static explicit operator long(BigInteger value) |
| | | 935 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 2238 | 936 | | { |
| | 2238 | 937 | | if (value._data is null) |
| | 471 | 938 | | { |
| | 471 | 939 | | return 0; |
| | | 940 | | } |
| | | 941 | | |
| | 1767 | 942 | | if (value._data.Length > 2) |
| | 3 | 943 | | { |
| | 3 | 944 | | throw new OverflowException(); |
| | | 945 | | } |
| | | 946 | | |
| | 1764 | 947 | | var low = value._data[0]; |
| | | 948 | | |
| | 1764 | 949 | | if (value._data.Length == 1) |
| | 1023 | 950 | | { |
| | 1023 | 951 | | if (value._sign == 1) |
| | 474 | 952 | | { |
| | 474 | 953 | | return (long) low; |
| | | 954 | | } |
| | | 955 | | |
| | 549 | 956 | | var res = (long)low; |
| | 549 | 957 | | return -res; |
| | | 958 | | } |
| | | 959 | | |
| | 741 | 960 | | var high = value._data[1]; |
| | | 961 | | |
| | 741 | 962 | | if (value._sign == 1) |
| | 390 | 963 | | { |
| | 390 | 964 | | if (high >= 0x80000000u) |
| | 3 | 965 | | { |
| | 3 | 966 | | throw new OverflowException(); |
| | | 967 | | } |
| | | 968 | | |
| | 387 | 969 | | return (((long)high) << 32) | low; |
| | | 970 | | } |
| | | 971 | | |
| | | 972 | | /* |
| | | 973 | | We cannot represent negative numbers smaller than long.MinValue. |
| | | 974 | | Those values are encoded into what look negative numbers, so negating |
| | | 975 | | them produces a positive value, that's why it's safe to check for that |
| | | 976 | | condition. |
| | | 977 | | |
| | | 978 | | long.MinValue works fine since it's bigint encoding looks like a negative |
| | | 979 | | number, but since long.MinValue == -long.MinValue, we're good. |
| | | 980 | | */ |
| | | 981 | | |
| | 351 | 982 | | var result = -((((long)high) << 32) | (long)low); |
| | 351 | 983 | | if (result > 0) |
| | 6 | 984 | | { |
| | 6 | 985 | | throw new OverflowException(); |
| | | 986 | | } |
| | | 987 | | |
| | 345 | 988 | | return result; |
| | 2226 | 989 | | } |
| | | 990 | | |
| | | 991 | | /// <summary> |
| | | 992 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned 64-bit integer value. |
| | | 993 | | /// </summary> |
| | | 994 | | /// <param name="value">The value to convert to an unsigned 64-bit integer.</param> |
| | | 995 | | /// <returns> |
| | | 996 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 997 | | /// </returns> |
| | | 998 | | [CLSCompliant(false)] |
| | | 999 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1000 | | public static explicit operator ulong(BigInteger value) |
| | | 1001 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 3 | 1002 | | { |
| | 3 | 1003 | | if (value._data is null) |
| | 3 | 1004 | | { |
| | 3 | 1005 | | return 0; |
| | | 1006 | | } |
| | | 1007 | | |
| | 0 | 1008 | | if (value._data.Length > 2 || value._sign == -1) |
| | 0 | 1009 | | { |
| | 0 | 1010 | | throw new OverflowException(); |
| | | 1011 | | } |
| | | 1012 | | |
| | 0 | 1013 | | var low = value._data[0]; |
| | 0 | 1014 | | if (value._data.Length == 1) |
| | 0 | 1015 | | { |
| | 0 | 1016 | | return low; |
| | | 1017 | | } |
| | | 1018 | | |
| | 0 | 1019 | | var high = value._data[1]; |
| | 0 | 1020 | | return (((ulong)high) << 32) | low; |
| | 3 | 1021 | | } |
| | | 1022 | | |
| | | 1023 | | /// <summary> |
| | | 1024 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a <see cref="double"/> value. |
| | | 1025 | | /// </summary> |
| | | 1026 | | /// <param name="value">The value to convert to a <see cref="double"/>.</param> |
| | | 1027 | | /// <returns> |
| | | 1028 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1029 | | /// </returns> |
| | | 1030 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1031 | | public static explicit operator double(BigInteger value) |
| | | 1032 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 57 | 1033 | | { |
| | 57 | 1034 | | if (value._data is null) |
| | 3 | 1035 | | { |
| | 3 | 1036 | | return 0.0; |
| | | 1037 | | } |
| | | 1038 | | |
| | 54 | 1039 | | switch (value._data.Length) |
| | | 1040 | | { |
| | | 1041 | | case 1: |
| | 9 | 1042 | | return BuildDouble(value._sign, value._data[0], 0); |
| | | 1043 | | case 2: |
| | 6 | 1044 | | return BuildDouble(value._sign, (ulong) value._data[1] << 32 | (ulong) value._data[0], 0); |
| | | 1045 | | default: |
| | 39 | 1046 | | var index = value._data.Length - 1; |
| | 39 | 1047 | | var word = value._data[index]; |
| | 39 | 1048 | | var mantissa = ((ulong)word << 32) | value._data[index - 1]; |
| | 39 | 1049 | | var missing = LeadingZeroCount(word) - 11; // 11 = bits in exponent |
| | 39 | 1050 | | if (missing > 0) |
| | 9 | 1051 | | { |
| | | 1052 | | // add the missing bits from the next word |
| | 9 | 1053 | | mantissa = (mantissa << missing) | (value._data[index - 2] >> (32 - missing)); |
| | 9 | 1054 | | } |
| | | 1055 | | else |
| | 30 | 1056 | | { |
| | 30 | 1057 | | mantissa >>= -missing; |
| | 30 | 1058 | | } |
| | | 1059 | | |
| | 39 | 1060 | | return BuildDouble(value._sign, mantissa, ((value._data.Length - 2) * 32) - missing); |
| | | 1061 | | } |
| | 57 | 1062 | | } |
| | | 1063 | | |
| | | 1064 | | /// <summary> |
| | | 1065 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a single-precision floating-point val |
| | | 1066 | | /// </summary> |
| | | 1067 | | /// <param name="value">The value to convert to a single-precision floating-point value.</param> |
| | | 1068 | | /// <returns> |
| | | 1069 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1070 | | /// </returns> |
| | | 1071 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1072 | | public static explicit operator float(BigInteger value) |
| | | 1073 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 1074 | | { |
| | 0 | 1075 | | return (float) (double) value; |
| | 0 | 1076 | | } |
| | | 1077 | | |
| | | 1078 | | /// <summary> |
| | | 1079 | | /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a <see cref="decimal"/> value. |
| | | 1080 | | /// </summary> |
| | | 1081 | | /// <param name="value">The value to convert to a <see cref="decimal"/>.</param> |
| | | 1082 | | /// <returns> |
| | | 1083 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1084 | | /// </returns> |
| | | 1085 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1086 | | public static explicit operator decimal(BigInteger value) |
| | | 1087 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 24 | 1088 | | { |
| | 24 | 1089 | | if (value._data is null) |
| | 6 | 1090 | | { |
| | 6 | 1091 | | return decimal.Zero; |
| | | 1092 | | } |
| | | 1093 | | |
| | 18 | 1094 | | var data = value._data; |
| | 18 | 1095 | | if (data.Length > 3) |
| | 6 | 1096 | | { |
| | 6 | 1097 | | throw new OverflowException(); |
| | | 1098 | | } |
| | | 1099 | | |
| | 36 | 1100 | | int lo = 0, mi = 0, hi = 0; |
| | 12 | 1101 | | if (data.Length > 2) |
| | 3 | 1102 | | { |
| | 3 | 1103 | | hi = (int) data[2]; |
| | 3 | 1104 | | } |
| | | 1105 | | |
| | 12 | 1106 | | if (data.Length > 1) |
| | 3 | 1107 | | { |
| | 3 | 1108 | | mi = (int) data[1]; |
| | 3 | 1109 | | } |
| | | 1110 | | |
| | 12 | 1111 | | if (data.Length > 0) |
| | 12 | 1112 | | { |
| | 12 | 1113 | | lo = (int) data[0]; |
| | 12 | 1114 | | } |
| | | 1115 | | |
| | 12 | 1116 | | return new decimal(lo, mi, hi, value._sign < 0, 0); |
| | 18 | 1117 | | } |
| | | 1118 | | |
| | | 1119 | | /// <summary> |
| | | 1120 | | /// Defines an implicit conversion of a signed 32-bit integer to a <see cref="BigInteger"/> value. |
| | | 1121 | | /// </summary> |
| | | 1122 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1123 | | /// <returns> |
| | | 1124 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1125 | | /// </returns> |
| | | 1126 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1127 | | public static implicit operator BigInteger(int value) |
| | | 1128 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 14951 | 1129 | | { |
| | 14951 | 1130 | | return new BigInteger(value); |
| | 14951 | 1131 | | } |
| | | 1132 | | |
| | | 1133 | | /// <summary> |
| | | 1134 | | /// Defines an implicit conversion of a 32-bit unsigned integer to a <see cref="BigInteger"/> value. |
| | | 1135 | | /// </summary> |
| | | 1136 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1137 | | /// <returns> |
| | | 1138 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1139 | | /// </returns> |
| | | 1140 | | [CLSCompliant(false)] |
| | | 1141 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1142 | | public static implicit operator BigInteger(uint value) |
| | | 1143 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 18201 | 1144 | | { |
| | 18201 | 1145 | | return new BigInteger(value); |
| | 18201 | 1146 | | } |
| | | 1147 | | |
| | | 1148 | | /// <summary> |
| | | 1149 | | /// Defines an implicit conversion of a signed 16-bit integer to a BigInteger value. |
| | | 1150 | | /// </summary> |
| | | 1151 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1152 | | /// <returns> |
| | | 1153 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1154 | | /// </returns> |
| | | 1155 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1156 | | public static implicit operator BigInteger(short value) |
| | | 1157 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 1158 | | { |
| | 0 | 1159 | | return new BigInteger(value); |
| | 0 | 1160 | | } |
| | | 1161 | | |
| | | 1162 | | /// <summary> |
| | | 1163 | | /// Defines an implicit conversion of a 16-bit unsigned integer to a <see cref="BigInteger"/> value. |
| | | 1164 | | /// </summary> |
| | | 1165 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1166 | | /// <returns> |
| | | 1167 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1168 | | /// </returns> |
| | | 1169 | | [CLSCompliant(false)] |
| | | 1170 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1171 | | public static implicit operator BigInteger(ushort value) |
| | | 1172 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 1173 | | { |
| | 0 | 1174 | | return new BigInteger(value); |
| | 0 | 1175 | | } |
| | | 1176 | | |
| | | 1177 | | /// <summary> |
| | | 1178 | | /// Defines an implicit conversion of an unsigned byte to a <see cref="BigInteger"/> value. |
| | | 1179 | | /// </summary> |
| | | 1180 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1181 | | /// <returns> |
| | | 1182 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1183 | | /// </returns> |
| | | 1184 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1185 | | public static implicit operator BigInteger(byte value) |
| | | 1186 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 12405 | 1187 | | { |
| | 12405 | 1188 | | return new BigInteger(value); |
| | 12405 | 1189 | | } |
| | | 1190 | | |
| | | 1191 | | /// <summary> |
| | | 1192 | | /// Defines an implicit conversion of a signed byte to a <see cref="BigInteger"/> value. |
| | | 1193 | | /// </summary> |
| | | 1194 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1195 | | /// <returns> |
| | | 1196 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1197 | | /// </returns> |
| | | 1198 | | [CLSCompliant(false)] |
| | | 1199 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1200 | | public static implicit operator BigInteger(sbyte value) |
| | | 1201 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 1202 | | { |
| | 0 | 1203 | | return new BigInteger(value); |
| | 0 | 1204 | | } |
| | | 1205 | | |
| | | 1206 | | /// <summary> |
| | | 1207 | | /// Defines an implicit conversion of a signed 64-bit integer to a <see cref="BigInteger"/> value. |
| | | 1208 | | /// </summary> |
| | | 1209 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1210 | | /// <returns> |
| | | 1211 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1212 | | /// </returns> |
| | | 1213 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1214 | | public static implicit operator BigInteger(long value) |
| | | 1215 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 6 | 1216 | | { |
| | 6 | 1217 | | return new BigInteger(value); |
| | 6 | 1218 | | } |
| | | 1219 | | |
| | | 1220 | | /// <summary> |
| | | 1221 | | /// Defines an implicit conversion of a 64-bit unsigned integer to a <see cref="BigInteger"/> value. |
| | | 1222 | | /// </summary> |
| | | 1223 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1224 | | /// <returns> |
| | | 1225 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1226 | | /// </returns> |
| | | 1227 | | [CLSCompliant(false)] |
| | | 1228 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1229 | | public static implicit operator BigInteger(ulong value) |
| | | 1230 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 15 | 1231 | | { |
| | 15 | 1232 | | return new BigInteger(value); |
| | 15 | 1233 | | } |
| | | 1234 | | |
| | | 1235 | | /// <summary> |
| | | 1236 | | /// Defines an explicit conversion of a <see cref="double"/> value to a <see cref="BigInteger"/> value. |
| | | 1237 | | /// </summary> |
| | | 1238 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1239 | | /// <returns> |
| | | 1240 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1241 | | /// </returns> |
| | | 1242 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1243 | | public static explicit operator BigInteger(double value) |
| | | 1244 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 1245 | | { |
| | 0 | 1246 | | return new BigInteger(value); |
| | 0 | 1247 | | } |
| | | 1248 | | |
| | | 1249 | | /// <summary> |
| | | 1250 | | /// Defines an explicit conversion of a <see cref="float"/> object to a <see cref="BigInteger"/> value. |
| | | 1251 | | /// </summary> |
| | | 1252 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1253 | | /// <returns> |
| | | 1254 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1255 | | /// </returns> |
| | | 1256 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1257 | | public static explicit operator BigInteger(float value) |
| | | 1258 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 1259 | | { |
| | 0 | 1260 | | return new BigInteger(value); |
| | 0 | 1261 | | } |
| | | 1262 | | |
| | | 1263 | | /// <summary> |
| | | 1264 | | /// Defines an explicit conversion of a <see cref="decimal"/> object to a <see cref="BigInteger"/> value. |
| | | 1265 | | /// </summary> |
| | | 1266 | | /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param> |
| | | 1267 | | /// <returns> |
| | | 1268 | | /// An object that contains the value of the <paramref name="value"/> parameter. |
| | | 1269 | | /// </returns> |
| | | 1270 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1271 | | public static explicit operator BigInteger(decimal value) |
| | | 1272 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 1273 | | { |
| | 0 | 1274 | | return new BigInteger(value); |
| | 0 | 1275 | | } |
| | | 1276 | | |
| | | 1277 | | /// <summary> |
| | | 1278 | | /// Adds the values of two specified <see cref="BigInteger"/> objects. |
| | | 1279 | | /// </summary> |
| | | 1280 | | /// <param name="left">The first value to add.</param> |
| | | 1281 | | /// <param name="right">The second value to add.</param> |
| | | 1282 | | /// <returns> |
| | | 1283 | | /// The sum of <paramref name="left"/> and <paramref name="right"/>. |
| | | 1284 | | /// </returns> |
| | | 1285 | | public static BigInteger operator +(BigInteger left, BigInteger right) |
| | 845636 | 1286 | | { |
| | 845636 | 1287 | | if (left._sign == 0) |
| | 880 | 1288 | | { |
| | 880 | 1289 | | return right; |
| | | 1290 | | } |
| | | 1291 | | |
| | 844756 | 1292 | | if (right._sign == 0) |
| | 1107 | 1293 | | { |
| | 1107 | 1294 | | return left; |
| | | 1295 | | } |
| | | 1296 | | |
| | 843649 | 1297 | | if (left._sign == right._sign) |
| | 843292 | 1298 | | { |
| | 843292 | 1299 | | return new BigInteger(left._sign, CoreAdd(left._data, right._data)); |
| | | 1300 | | } |
| | | 1301 | | |
| | 357 | 1302 | | var r = CoreCompare(left._data, right._data); |
| | | 1303 | | |
| | 357 | 1304 | | if (r == 0) |
| | 30 | 1305 | | { |
| | 30 | 1306 | | return Zero; |
| | | 1307 | | } |
| | | 1308 | | |
| | 327 | 1309 | | if (r > 0) |
| | 18 | 1310 | | { |
| | | 1311 | | // left > right |
| | 18 | 1312 | | return new BigInteger(left._sign, CoreSub(left._data, right._data)); |
| | | 1313 | | } |
| | | 1314 | | |
| | 309 | 1315 | | return new BigInteger(right._sign, CoreSub(right._data, left._data)); |
| | 845636 | 1316 | | } |
| | | 1317 | | |
| | | 1318 | | /// <summary> |
| | | 1319 | | /// Subtracts a <see cref="BigInteger"/> value from another <see cref="BigInteger"/> value. |
| | | 1320 | | /// </summary> |
| | | 1321 | | /// <param name="left">The value to subtract from (the minuend).</param> |
| | | 1322 | | /// <param name="right">The value to subtract (the subtrahend).</param> |
| | | 1323 | | /// <returns> |
| | | 1324 | | /// The result of subtracting <paramref name="right"/> from <paramref name="left"/>. |
| | | 1325 | | /// </returns> |
| | | 1326 | | public static BigInteger operator -(BigInteger left, BigInteger right) |
| | 2082 | 1327 | | { |
| | 2082 | 1328 | | if (right._sign == 0) |
| | 42 | 1329 | | { |
| | 42 | 1330 | | return left; |
| | | 1331 | | } |
| | | 1332 | | |
| | 2040 | 1333 | | if (left._sign == 0) |
| | 36 | 1334 | | { |
| | | 1335 | | #pragma warning disable SA1021 // Negative signs should be spaced correctly |
| | 36 | 1336 | | return new BigInteger((short) -right._sign, right._data); |
| | | 1337 | | #pragma warning restore SA1021 // Negative signs should be spaced correctly |
| | | 1338 | | } |
| | | 1339 | | |
| | 2004 | 1340 | | if (left._sign == right._sign) |
| | 1893 | 1341 | | { |
| | 1893 | 1342 | | var r = CoreCompare(left._data, right._data); |
| | | 1343 | | |
| | 1893 | 1344 | | if (r == 0) |
| | 36 | 1345 | | { |
| | 36 | 1346 | | return Zero; |
| | | 1347 | | } |
| | | 1348 | | |
| | 1857 | 1349 | | if (r > 0) |
| | 1527 | 1350 | | { |
| | | 1351 | | // left > right |
| | 1527 | 1352 | | return new BigInteger(left._sign, CoreSub(left._data, right._data)); |
| | | 1353 | | } |
| | | 1354 | | |
| | 330 | 1355 | | return new BigInteger((short)-right._sign, CoreSub(right._data, left._data)); |
| | | 1356 | | } |
| | | 1357 | | |
| | 111 | 1358 | | return new BigInteger(left._sign, CoreAdd(left._data, right._data)); |
| | 2082 | 1359 | | } |
| | | 1360 | | |
| | | 1361 | | /// <summary> |
| | | 1362 | | /// Multiplies two specified <see cref="BigInteger"/> values. |
| | | 1363 | | /// </summary> |
| | | 1364 | | /// <param name="left">The first value to multiply.</param> |
| | | 1365 | | /// <param name="right">The second value to multiply.</param> |
| | | 1366 | | /// <returns> |
| | | 1367 | | /// The product of left and right. |
| | | 1368 | | /// </returns> |
| | | 1369 | | public static BigInteger operator *(BigInteger left, BigInteger right) |
| | 3086902 | 1370 | | { |
| | 3086902 | 1371 | | if (left._sign == 0 || right._sign == 0) |
| | 192 | 1372 | | { |
| | 192 | 1373 | | return Zero; |
| | | 1374 | | } |
| | | 1375 | | |
| | 3086710 | 1376 | | if (left._data[0] == 1 && left._data.Length == 1) |
| | 349063 | 1377 | | { |
| | 349063 | 1378 | | if (left._sign == 1) |
| | 349045 | 1379 | | { |
| | 349045 | 1380 | | return right; |
| | | 1381 | | } |
| | | 1382 | | |
| | 18 | 1383 | | return new BigInteger((short)-right._sign, right._data); |
| | | 1384 | | } |
| | | 1385 | | |
| | 2737647 | 1386 | | if (right._data[0] == 1 && right._data.Length == 1) |
| | 578 | 1387 | | { |
| | 578 | 1388 | | if (right._sign == 1) |
| | 563 | 1389 | | { |
| | 563 | 1390 | | return left; |
| | | 1391 | | } |
| | | 1392 | | |
| | 15 | 1393 | | return new BigInteger((short)-left._sign, left._data); |
| | | 1394 | | } |
| | | 1395 | | |
| | 2737069 | 1396 | | var a = left._data; |
| | 2737069 | 1397 | | var b = right._data; |
| | | 1398 | | |
| | 2737069 | 1399 | | var res = new uint[a.Length + b.Length]; |
| | | 1400 | | |
| | 159032098 | 1401 | | for (var i = 0; i < a.Length; ++i) |
| | 76778980 | 1402 | | { |
| | 76778980 | 1403 | | var ai = a[i]; |
| | 76778980 | 1404 | | var k = i; |
| | | 1405 | | |
| | 76778980 | 1406 | | ulong carry = 0; |
| | 96823624 | 1407 | | for (var j = 0; j < b.Length; ++j) |
| | 46284714 | 1408 | | { |
| | 46284714 | 1409 | | carry = carry + (((ulong) ai) * b[j]) + res[k]; |
| | 46284714 | 1410 | | res[k++] = (uint)carry; |
| | 46284714 | 1411 | | carry >>= 32; |
| | 46284714 | 1412 | | } |
| | | 1413 | | |
| | 152990388 | 1414 | | while (carry != 0) |
| | 76211408 | 1415 | | { |
| | 76211408 | 1416 | | carry += res[k]; |
| | 76211408 | 1417 | | res[k++] = (uint)carry; |
| | 76211408 | 1418 | | carry >>= 32; |
| | 76211408 | 1419 | | } |
| | 76778980 | 1420 | | } |
| | | 1421 | | |
| | | 1422 | | int m; |
| | 6396186 | 1423 | | for (m = res.Length - 1; m >= 0 && res[m] == 0; --m) |
| | 461024 | 1424 | | { |
| | | 1425 | | // Intentionally empty block |
| | 461024 | 1426 | | } |
| | | 1427 | | |
| | 2737069 | 1428 | | if (m < res.Length - 1) |
| | 461024 | 1429 | | { |
| | 461024 | 1430 | | Array.Resize(ref res, m + 1); |
| | 461024 | 1431 | | } |
| | | 1432 | | |
| | 2737069 | 1433 | | return new BigInteger((short) (left._sign*right._sign), res); |
| | 3086902 | 1434 | | } |
| | | 1435 | | |
| | | 1436 | | /// <summary> |
| | | 1437 | | /// Divides a specified <see cref="BigInteger"/> value by another specified <see cref="BigInteger"/> value by us |
| | | 1438 | | /// integer division. |
| | | 1439 | | /// </summary> |
| | | 1440 | | /// <param name="dividend">The value to be divided.</param> |
| | | 1441 | | /// <param name="divisor">The value to divide by.</param> |
| | | 1442 | | /// <returns> |
| | | 1443 | | /// The integral result of the division. |
| | | 1444 | | /// </returns> |
| | | 1445 | | public static BigInteger operator /(BigInteger dividend, BigInteger divisor) |
| | 832006 | 1446 | | { |
| | 832006 | 1447 | | if (divisor._sign == 0) |
| | 0 | 1448 | | { |
| | 0 | 1449 | | throw new DivideByZeroException(); |
| | | 1450 | | } |
| | | 1451 | | |
| | 832006 | 1452 | | if (dividend._sign == 0) |
| | 0 | 1453 | | { |
| | 0 | 1454 | | return dividend; |
| | | 1455 | | } |
| | | 1456 | | |
| | 832006 | 1457 | | DivModUnsigned(dividend._data, divisor._data, out var quotient, out _); |
| | | 1458 | | |
| | | 1459 | | int i; |
| | 1751740 | 1460 | | for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) |
| | 43864 | 1461 | | { |
| | | 1462 | | // Intentionally empty block |
| | 43864 | 1463 | | } |
| | | 1464 | | |
| | 832006 | 1465 | | if (i == -1) |
| | 0 | 1466 | | { |
| | 0 | 1467 | | return Zero; |
| | | 1468 | | } |
| | | 1469 | | |
| | 832006 | 1470 | | if (i < quotient.Length - 1) |
| | 43864 | 1471 | | { |
| | 43864 | 1472 | | Array.Resize(ref quotient, i + 1); |
| | 43864 | 1473 | | } |
| | | 1474 | | |
| | 832006 | 1475 | | return new BigInteger((short)(dividend._sign * divisor._sign), quotient); |
| | 832006 | 1476 | | } |
| | | 1477 | | |
| | | 1478 | | /// <summary> |
| | | 1479 | | /// Returns the remainder that results from division with two specified <see cref="BigInteger"/> values. |
| | | 1480 | | /// </summary> |
| | | 1481 | | /// <param name="dividend">The value to be divided.</param> |
| | | 1482 | | /// <param name="divisor">The value to divide by.</param> |
| | | 1483 | | /// <returns> |
| | | 1484 | | /// The remainder that results from the division. |
| | | 1485 | | /// </returns> |
| | | 1486 | | public static BigInteger operator %(BigInteger dividend, BigInteger divisor) |
| | 3078625 | 1487 | | { |
| | 3078625 | 1488 | | if (divisor._sign == 0) |
| | 0 | 1489 | | { |
| | 0 | 1490 | | throw new DivideByZeroException(); |
| | | 1491 | | } |
| | | 1492 | | |
| | 3078625 | 1493 | | if (dividend._sign == 0) |
| | 0 | 1494 | | { |
| | 0 | 1495 | | return dividend; |
| | | 1496 | | } |
| | | 1497 | | |
| | 3078625 | 1498 | | DivModUnsigned(dividend._data, divisor._data, out _, out var remainderValue); |
| | | 1499 | | |
| | | 1500 | | int i; |
| | 162933758 | 1501 | | for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) |
| | 78388254 | 1502 | | { |
| | | 1503 | | // Intentionally empty block |
| | 78388254 | 1504 | | } |
| | | 1505 | | |
| | 3078625 | 1506 | | if (i == -1) |
| | 0 | 1507 | | { |
| | 0 | 1508 | | return Zero; |
| | | 1509 | | } |
| | | 1510 | | |
| | 3078625 | 1511 | | if (i < remainderValue.Length - 1) |
| | 3062106 | 1512 | | { |
| | 3062106 | 1513 | | Array.Resize(ref remainderValue, i + 1); |
| | 3062106 | 1514 | | } |
| | | 1515 | | |
| | 3078625 | 1516 | | return new BigInteger(dividend._sign, remainderValue); |
| | 3078625 | 1517 | | } |
| | | 1518 | | |
| | | 1519 | | /// <summary> |
| | | 1520 | | /// Negates a specified <see cref="BigInteger"/> value. |
| | | 1521 | | /// </summary> |
| | | 1522 | | /// <param name="value">The value to negate.</param> |
| | | 1523 | | /// <returns> |
| | | 1524 | | /// The result of the <paramref name="value"/> parameter multiplied by negative one (-1). |
| | | 1525 | | /// </returns> |
| | | 1526 | | public static BigInteger operator -(BigInteger value) |
| | 42 | 1527 | | { |
| | 42 | 1528 | | if (value._data is null) |
| | 6 | 1529 | | { |
| | 6 | 1530 | | return value; |
| | | 1531 | | } |
| | | 1532 | | |
| | | 1533 | | #pragma warning disable SA1021 // Negative signs should be spaced correctly |
| | 36 | 1534 | | return new BigInteger((short) -value._sign, value._data); |
| | | 1535 | | #pragma warning restore SA1021 // Negative signs should be spaced correctly |
| | 42 | 1536 | | } |
| | | 1537 | | |
| | | 1538 | | /// <summary> |
| | | 1539 | | /// Returns the value of the <see cref="BigInteger"/> operand. |
| | | 1540 | | /// </summary> |
| | | 1541 | | /// <param name="value">An integer value.</param> |
| | | 1542 | | /// <returns> |
| | | 1543 | | /// The value of the <paramref name="value"/> operand. |
| | | 1544 | | /// </returns> |
| | | 1545 | | /// <remarks> |
| | | 1546 | | /// The sign of the operand is unchanged. |
| | | 1547 | | /// </remarks> |
| | | 1548 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1549 | | public static BigInteger operator +(BigInteger value) |
| | | 1550 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 0 | 1551 | | { |
| | 0 | 1552 | | return value; |
| | 0 | 1553 | | } |
| | | 1554 | | |
| | | 1555 | | /// <summary> |
| | | 1556 | | /// Increments a <see cref="BigInteger"/> value by 1. |
| | | 1557 | | /// </summary> |
| | | 1558 | | /// <param name="value">The value to increment.</param> |
| | | 1559 | | /// <returns> |
| | | 1560 | | /// The value of the <paramref name="value"/> parameter incremented by 1. |
| | | 1561 | | /// </returns> |
| | | 1562 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1563 | | public static BigInteger operator ++(BigInteger value) |
| | | 1564 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 24 | 1565 | | { |
| | 24 | 1566 | | if (value._data is null) |
| | 6 | 1567 | | { |
| | 6 | 1568 | | return One; |
| | | 1569 | | } |
| | | 1570 | | |
| | 18 | 1571 | | var sign = value._sign; |
| | 18 | 1572 | | var data = value._data; |
| | 18 | 1573 | | if (data.Length == 1) |
| | 12 | 1574 | | { |
| | 12 | 1575 | | if (sign == -1 && data[0] == 1) |
| | 3 | 1576 | | { |
| | 3 | 1577 | | return Zero; |
| | | 1578 | | } |
| | | 1579 | | |
| | 9 | 1580 | | if (sign == 0) |
| | 0 | 1581 | | { |
| | 0 | 1582 | | return One; |
| | | 1583 | | } |
| | 9 | 1584 | | } |
| | | 1585 | | |
| | 15 | 1586 | | data = sign == -1 ? CoreSub(data, 1) : CoreAdd(data, 1); |
| | | 1587 | | |
| | 15 | 1588 | | return new BigInteger(sign, data); |
| | 24 | 1589 | | } |
| | | 1590 | | |
| | | 1591 | | /// <summary> |
| | | 1592 | | /// Decrements a <see cref="BigInteger"/> value by 1. |
| | | 1593 | | /// </summary> |
| | | 1594 | | /// <param name="value">The value to decrement.</param> |
| | | 1595 | | /// <returns> |
| | | 1596 | | /// The value of the <paramref name="value"/> parameter decremented by 1. |
| | | 1597 | | /// </returns> |
| | | 1598 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1599 | | public static BigInteger operator --(BigInteger value) |
| | | 1600 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 33 | 1601 | | { |
| | 33 | 1602 | | if (value._data is null) |
| | 6 | 1603 | | { |
| | 6 | 1604 | | return MinusOne; |
| | | 1605 | | } |
| | | 1606 | | |
| | 27 | 1607 | | var sign = value._sign; |
| | 27 | 1608 | | var data = value._data; |
| | 27 | 1609 | | if (data.Length == 1) |
| | 21 | 1610 | | { |
| | 21 | 1611 | | if (sign == 1 && data[0] == 1) |
| | 3 | 1612 | | { |
| | 3 | 1613 | | return Zero; |
| | | 1614 | | } |
| | | 1615 | | |
| | 18 | 1616 | | if (sign == 0) |
| | 0 | 1617 | | { |
| | 0 | 1618 | | return MinusOne; |
| | | 1619 | | } |
| | 18 | 1620 | | } |
| | | 1621 | | |
| | 24 | 1622 | | data = sign == -1 ? CoreAdd(data, 1) : CoreSub(data, 1); |
| | | 1623 | | |
| | 24 | 1624 | | return new BigInteger(sign, data); |
| | 33 | 1625 | | } |
| | | 1626 | | |
| | | 1627 | | /// <summary> |
| | | 1628 | | /// Performs a bitwise <c>And</c> operation on two <see cref="BigInteger"/> values. |
| | | 1629 | | /// </summary> |
| | | 1630 | | /// <param name="left">The first value.</param> |
| | | 1631 | | /// <param name="right">The second value.</param> |
| | | 1632 | | /// <returns> |
| | | 1633 | | /// The result of the bitwise <c>And</c> operation. |
| | | 1634 | | /// </returns> |
| | | 1635 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1636 | | public static BigInteger operator &(BigInteger left, BigInteger right) |
| | | 1637 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 249 | 1638 | | { |
| | 249 | 1639 | | if (left._sign == 0) |
| | 24 | 1640 | | { |
| | 24 | 1641 | | return left; |
| | | 1642 | | } |
| | | 1643 | | |
| | 225 | 1644 | | if (right._sign == 0) |
| | 21 | 1645 | | { |
| | 21 | 1646 | | return right; |
| | | 1647 | | } |
| | | 1648 | | |
| | 204 | 1649 | | var a = left._data; |
| | 204 | 1650 | | var b = right._data; |
| | 204 | 1651 | | int ls = left._sign; |
| | 204 | 1652 | | int rs = right._sign; |
| | | 1653 | | |
| | 204 | 1654 | | var negRes = (ls == rs) && (ls == -1); |
| | | 1655 | | |
| | 204 | 1656 | | var result = new uint[Math.Max(a.Length, b.Length)]; |
| | | 1657 | | |
| | 612 | 1658 | | ulong ac = 1, bc = 1, borrow = 1; |
| | | 1659 | | |
| | | 1660 | | int i; |
| | 1014 | 1661 | | for (i = 0; i < result.Length; ++i) |
| | 303 | 1662 | | { |
| | 303 | 1663 | | uint va = 0; |
| | 303 | 1664 | | if (i < a.Length) |
| | 267 | 1665 | | { |
| | 267 | 1666 | | va = a[i]; |
| | 267 | 1667 | | } |
| | | 1668 | | |
| | 303 | 1669 | | if (ls == -1) |
| | 102 | 1670 | | { |
| | 102 | 1671 | | ac = ~va + ac; |
| | 102 | 1672 | | va = (uint)ac; |
| | 102 | 1673 | | ac = (uint)(ac >> 32); |
| | 102 | 1674 | | } |
| | | 1675 | | |
| | 303 | 1676 | | uint vb = 0; |
| | 303 | 1677 | | if (i < b.Length) |
| | 267 | 1678 | | { |
| | 267 | 1679 | | vb = b[i]; |
| | 267 | 1680 | | } |
| | | 1681 | | |
| | 303 | 1682 | | if (rs == -1) |
| | 102 | 1683 | | { |
| | 102 | 1684 | | bc = ~vb + bc; |
| | 102 | 1685 | | vb = (uint)bc; |
| | 102 | 1686 | | bc = (uint)(bc >> 32); |
| | 102 | 1687 | | } |
| | | 1688 | | |
| | 303 | 1689 | | var word = va & vb; |
| | | 1690 | | |
| | 303 | 1691 | | if (negRes) |
| | 42 | 1692 | | { |
| | 42 | 1693 | | borrow = word - borrow; |
| | 42 | 1694 | | word = ~(uint)borrow; |
| | 42 | 1695 | | borrow = (uint)(borrow >> 32) & 0x1u; |
| | 42 | 1696 | | } |
| | | 1697 | | |
| | 303 | 1698 | | result[i] = word; |
| | 303 | 1699 | | } |
| | | 1700 | | |
| | 636 | 1701 | | for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) |
| | 114 | 1702 | | { |
| | | 1703 | | // Intentionally empty block |
| | 114 | 1704 | | } |
| | | 1705 | | |
| | 204 | 1706 | | if (i == -1) |
| | 72 | 1707 | | { |
| | 72 | 1708 | | return Zero; |
| | | 1709 | | } |
| | | 1710 | | |
| | 132 | 1711 | | if (i < result.Length - 1) |
| | 6 | 1712 | | { |
| | 6 | 1713 | | Array.Resize(ref result, i + 1); |
| | 6 | 1714 | | } |
| | | 1715 | | |
| | 132 | 1716 | | return new BigInteger(negRes ? (short)-1 : (short)1, result); |
| | 249 | 1717 | | } |
| | | 1718 | | |
| | | 1719 | | /// <summary> |
| | | 1720 | | /// Performs a bitwise <c>Or</c> operation on two <see cref="BigInteger"/> values. |
| | | 1721 | | /// </summary> |
| | | 1722 | | /// <param name="left">The first value.</param> |
| | | 1723 | | /// <param name="right">The second value.</param> |
| | | 1724 | | /// <returns> |
| | | 1725 | | /// The result of the bitwise <c>Or</c> operation. |
| | | 1726 | | /// </returns> |
| | | 1727 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1728 | | public static BigInteger operator |(BigInteger left, BigInteger right) |
| | | 1729 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 192 | 1730 | | { |
| | 192 | 1731 | | if (left._sign == 0) |
| | 24 | 1732 | | { |
| | 24 | 1733 | | return right; |
| | | 1734 | | } |
| | | 1735 | | |
| | 168 | 1736 | | if (right._sign == 0) |
| | 21 | 1737 | | { |
| | 21 | 1738 | | return left; |
| | | 1739 | | } |
| | | 1740 | | |
| | 147 | 1741 | | var a = left._data; |
| | 147 | 1742 | | var b = right._data; |
| | 147 | 1743 | | int ls = left._sign; |
| | 147 | 1744 | | int rs = right._sign; |
| | | 1745 | | |
| | 147 | 1746 | | var negRes = (ls == -1) || (rs == -1); |
| | | 1747 | | |
| | 147 | 1748 | | var result = new uint[Math.Max(a.Length, b.Length)]; |
| | | 1749 | | |
| | 441 | 1750 | | ulong ac = 1, bc = 1, borrow = 1; |
| | | 1751 | | |
| | | 1752 | | int i; |
| | 786 | 1753 | | for (i = 0; i < result.Length; ++i) |
| | 246 | 1754 | | { |
| | 246 | 1755 | | uint va = 0; |
| | 246 | 1756 | | if (i < a.Length) |
| | 210 | 1757 | | { |
| | 210 | 1758 | | va = a[i]; |
| | 210 | 1759 | | } |
| | | 1760 | | |
| | 246 | 1761 | | if (ls == -1) |
| | 102 | 1762 | | { |
| | 102 | 1763 | | ac = ~va + ac; |
| | 102 | 1764 | | va = (uint)ac; |
| | 102 | 1765 | | ac = (uint)(ac >> 32); |
| | 102 | 1766 | | } |
| | | 1767 | | |
| | 246 | 1768 | | uint vb = 0; |
| | 246 | 1769 | | if (i < b.Length) |
| | 210 | 1770 | | { |
| | 210 | 1771 | | vb = b[i]; |
| | 210 | 1772 | | } |
| | | 1773 | | |
| | 246 | 1774 | | if (rs == -1) |
| | 102 | 1775 | | { |
| | 102 | 1776 | | bc = ~vb + bc; |
| | 102 | 1777 | | vb = (uint)bc; |
| | 102 | 1778 | | bc = (uint)(bc >> 32); |
| | 102 | 1779 | | } |
| | | 1780 | | |
| | 246 | 1781 | | var word = va | vb; |
| | | 1782 | | |
| | 246 | 1783 | | if (negRes) |
| | 162 | 1784 | | { |
| | 162 | 1785 | | borrow = word - borrow; |
| | 162 | 1786 | | word = ~(uint)borrow; |
| | 162 | 1787 | | borrow = (uint)(borrow >> 32) & 0x1u; |
| | 162 | 1788 | | } |
| | | 1789 | | |
| | 246 | 1790 | | result[i] = word; |
| | 246 | 1791 | | } |
| | | 1792 | | |
| | 390 | 1793 | | for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) |
| | 48 | 1794 | | { |
| | | 1795 | | // Intentionally empty block |
| | 48 | 1796 | | } |
| | | 1797 | | |
| | 147 | 1798 | | if (i == -1) |
| | 0 | 1799 | | { |
| | 0 | 1800 | | return Zero; |
| | | 1801 | | } |
| | | 1802 | | |
| | 147 | 1803 | | if (i < result.Length - 1) |
| | 48 | 1804 | | { |
| | 48 | 1805 | | Array.Resize(ref result, i + 1); |
| | 48 | 1806 | | } |
| | | 1807 | | |
| | 147 | 1808 | | return new BigInteger(negRes ? (short)-1 : (short)1, result); |
| | 192 | 1809 | | } |
| | | 1810 | | |
| | | 1811 | | /// <summary> |
| | | 1812 | | /// Performs a bitwise exclusive <c>Or</c> (<c>XOr</c>) operation on two <see cref="BigInteger"/> values. |
| | | 1813 | | /// </summary> |
| | | 1814 | | /// <param name="left">The first value.</param> |
| | | 1815 | | /// <param name="right">The second value.</param> |
| | | 1816 | | /// <returns> |
| | | 1817 | | /// The result of the bitwise <c>Or</c> operation. |
| | | 1818 | | /// </returns> |
| | | 1819 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1820 | | public static BigInteger operator ^(BigInteger left, BigInteger right) |
| | | 1821 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 210 | 1822 | | { |
| | 210 | 1823 | | if (left._sign == 0) |
| | 24 | 1824 | | { |
| | 24 | 1825 | | return right; |
| | | 1826 | | } |
| | | 1827 | | |
| | 186 | 1828 | | if (right._sign == 0) |
| | 21 | 1829 | | { |
| | 21 | 1830 | | return left; |
| | | 1831 | | } |
| | | 1832 | | |
| | 165 | 1833 | | var a = left._data; |
| | 165 | 1834 | | var b = right._data; |
| | 165 | 1835 | | int ls = left._sign; |
| | 165 | 1836 | | int rs = right._sign; |
| | | 1837 | | |
| | 165 | 1838 | | var negRes = (ls == -1) ^ (rs == -1); |
| | | 1839 | | |
| | 165 | 1840 | | var result = new uint[Math.Max(a.Length, b.Length)]; |
| | | 1841 | | |
| | 495 | 1842 | | ulong ac = 1, bc = 1, borrow = 1; |
| | | 1843 | | |
| | | 1844 | | int i; |
| | 2952 | 1845 | | for (i = 0; i < result.Length; ++i) |
| | 1311 | 1846 | | { |
| | 1311 | 1847 | | uint va = 0; |
| | 1311 | 1848 | | if (i < a.Length) |
| | 228 | 1849 | | { |
| | 228 | 1850 | | va = a[i]; |
| | 228 | 1851 | | } |
| | | 1852 | | |
| | 1311 | 1853 | | if (ls == -1) |
| | 102 | 1854 | | { |
| | 102 | 1855 | | ac = ~va + ac; |
| | 102 | 1856 | | va = (uint)ac; |
| | 102 | 1857 | | ac = (uint)(ac >> 32); |
| | 102 | 1858 | | } |
| | | 1859 | | |
| | 1311 | 1860 | | uint vb = 0; |
| | 1311 | 1861 | | if (i < b.Length) |
| | 1275 | 1862 | | { |
| | 1275 | 1863 | | vb = b[i]; |
| | 1275 | 1864 | | } |
| | | 1865 | | |
| | 1311 | 1866 | | if (rs == -1) |
| | 102 | 1867 | | { |
| | 102 | 1868 | | bc = ~vb + bc; |
| | 102 | 1869 | | vb = (uint)bc; |
| | 102 | 1870 | | bc = (uint)(bc >> 32); |
| | 102 | 1871 | | } |
| | | 1872 | | |
| | 1311 | 1873 | | var word = va ^ vb; |
| | | 1874 | | |
| | 1311 | 1875 | | if (negRes) |
| | 120 | 1876 | | { |
| | 120 | 1877 | | borrow = word - borrow; |
| | 120 | 1878 | | word = ~(uint)borrow; |
| | 120 | 1879 | | borrow = (uint)(borrow >> 32) & 0x1u; |
| | 120 | 1880 | | } |
| | | 1881 | | |
| | 1311 | 1882 | | result[i] = word; |
| | 1311 | 1883 | | } |
| | | 1884 | | |
| | 414 | 1885 | | for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) |
| | 42 | 1886 | | { |
| | | 1887 | | // Intentionally empty block |
| | 42 | 1888 | | } |
| | | 1889 | | |
| | 165 | 1890 | | if (i == -1) |
| | 27 | 1891 | | { |
| | 27 | 1892 | | return Zero; |
| | | 1893 | | } |
| | | 1894 | | |
| | 138 | 1895 | | if (i < result.Length - 1) |
| | 6 | 1896 | | { |
| | 6 | 1897 | | Array.Resize(ref result, i + 1); |
| | 6 | 1898 | | } |
| | | 1899 | | |
| | 138 | 1900 | | return new BigInteger(negRes ? (short)-1 : (short)1, result); |
| | 210 | 1901 | | } |
| | | 1902 | | |
| | | 1903 | | /// <summary> |
| | | 1904 | | /// Returns the bitwise one's complement of a <see cref="BigInteger"/> value. |
| | | 1905 | | /// </summary> |
| | | 1906 | | /// <param name="value">An integer value.</param> |
| | | 1907 | | /// <returns> |
| | | 1908 | | /// The bitwise one's complement of <paramref name="value"/>. |
| | | 1909 | | /// </returns> |
| | | 1910 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1911 | | public static BigInteger operator ~(BigInteger value) |
| | | 1912 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 195 | 1913 | | { |
| | 195 | 1914 | | if (value._data is null) |
| | 27 | 1915 | | { |
| | 27 | 1916 | | return MinusOne; |
| | | 1917 | | } |
| | | 1918 | | |
| | 168 | 1919 | | var data = value._data; |
| | 168 | 1920 | | int sign = value._sign; |
| | | 1921 | | |
| | 168 | 1922 | | var negRes = sign == 1; |
| | | 1923 | | |
| | 168 | 1924 | | var result = new uint[data.Length]; |
| | | 1925 | | |
| | 336 | 1926 | | ulong carry = 1, borrow = 1; |
| | | 1927 | | |
| | | 1928 | | int i; |
| | 816 | 1929 | | for (i = 0; i < result.Length; ++i) |
| | 240 | 1930 | | { |
| | 240 | 1931 | | var word = data[i]; |
| | 240 | 1932 | | if (sign == -1) |
| | 96 | 1933 | | { |
| | 96 | 1934 | | carry = ~word + carry; |
| | 96 | 1935 | | word = (uint)carry; |
| | 96 | 1936 | | carry = (uint)(carry >> 32); |
| | 96 | 1937 | | } |
| | | 1938 | | |
| | 240 | 1939 | | word = ~word; |
| | | 1940 | | |
| | 240 | 1941 | | if (negRes) |
| | 144 | 1942 | | { |
| | 144 | 1943 | | borrow = word - borrow; |
| | 144 | 1944 | | word = ~(uint)borrow; |
| | 144 | 1945 | | borrow = (uint)(borrow >> 32) & 0x1u; |
| | 144 | 1946 | | } |
| | | 1947 | | |
| | 240 | 1948 | | result[i] = word; |
| | 240 | 1949 | | } |
| | | 1950 | | |
| | 384 | 1951 | | for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) |
| | 24 | 1952 | | { |
| | | 1953 | | // Intentionally empty block |
| | 24 | 1954 | | } |
| | | 1955 | | |
| | 168 | 1956 | | if (i == -1) |
| | 24 | 1957 | | { |
| | 24 | 1958 | | return Zero; |
| | | 1959 | | } |
| | | 1960 | | |
| | 144 | 1961 | | if (i < result.Length - 1) |
| | 0 | 1962 | | { |
| | 0 | 1963 | | Array.Resize(ref result, i + 1); |
| | 0 | 1964 | | } |
| | | 1965 | | |
| | 144 | 1966 | | return new BigInteger(negRes ? (short)-1 : (short)1, result); |
| | 195 | 1967 | | } |
| | | 1968 | | |
| | | 1969 | | /// <summary> |
| | | 1970 | | /// Returns the zero-based index of the most significant set bit. |
| | | 1971 | | /// </summary> |
| | | 1972 | | /// <param name="word">The value to scan.</param> |
| | | 1973 | | /// <returns> |
| | | 1974 | | /// The zero-based index of the most significant set bit, or zero if no bit is set. |
| | | 1975 | | /// </returns> |
| | | 1976 | | private static int BitScanBackward(uint word) |
| | 1484277 | 1977 | | { |
| | 49327574 | 1978 | | for (var i = 31; i >= 0; --i) |
| | 24663787 | 1979 | | { |
| | 24663787 | 1980 | | var mask = 1u << i; |
| | 24663787 | 1981 | | if ((word & mask) == mask) |
| | 1484277 | 1982 | | { |
| | 1484277 | 1983 | | return i; |
| | | 1984 | | } |
| | 23179510 | 1985 | | } |
| | | 1986 | | |
| | 0 | 1987 | | return 0; |
| | 1484277 | 1988 | | } |
| | | 1989 | | |
| | | 1990 | | /// <summary> |
| | | 1991 | | /// Shifts a <see cref="BigInteger"/> value a specified number of bits to the left. |
| | | 1992 | | /// </summary> |
| | | 1993 | | /// <param name="value">The value whose bits are to be shifted.</param> |
| | | 1994 | | /// <param name="shift">The number of bits to shift value to the left.</param> |
| | | 1995 | | /// <returns> |
| | | 1996 | | /// A value that has been shifted to the left by the specified number of bits. |
| | | 1997 | | /// </returns> |
| | | 1998 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 1999 | | public static BigInteger operator <<(BigInteger value, int shift) |
| | | 2000 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 255 | 2001 | | { |
| | 255 | 2002 | | if (shift == 0 || value._data is null) |
| | 6 | 2003 | | { |
| | 6 | 2004 | | return value; |
| | | 2005 | | } |
| | | 2006 | | |
| | 249 | 2007 | | if (shift < 0) |
| | 3 | 2008 | | { |
| | 3 | 2009 | | return value >> -shift; |
| | | 2010 | | } |
| | | 2011 | | |
| | 246 | 2012 | | var data = value._data; |
| | 246 | 2013 | | int sign = value._sign; |
| | | 2014 | | |
| | 246 | 2015 | | var topMostIdx = BitScanBackward(data[data.Length - 1]); |
| | 246 | 2016 | | var bits = shift - (31 - topMostIdx); |
| | 246 | 2017 | | var extraWords = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0); |
| | | 2018 | | |
| | 246 | 2019 | | var res = new uint[data.Length + extraWords]; |
| | | 2020 | | |
| | 246 | 2021 | | var idxShift = shift >> 5; |
| | 246 | 2022 | | var bitShift = shift & 0x1F; |
| | 246 | 2023 | | var carryShift = 32 - bitShift; |
| | | 2024 | | |
| | 246 | 2025 | | if (carryShift == 32) |
| | 9 | 2026 | | { |
| | 90 | 2027 | | for (var i = 0; i < data.Length; ++i) |
| | 36 | 2028 | | { |
| | 36 | 2029 | | var word = data[i]; |
| | 36 | 2030 | | res[i + idxShift] |= word << bitShift; |
| | 36 | 2031 | | } |
| | 9 | 2032 | | } |
| | | 2033 | | else |
| | 237 | 2034 | | { |
| | 2154 | 2035 | | for (var i = 0; i < data.Length; ++i) |
| | 840 | 2036 | | { |
| | 840 | 2037 | | var word = data[i]; |
| | 840 | 2038 | | res[i + idxShift] |= word << bitShift; |
| | 840 | 2039 | | if (i + idxShift + 1 < res.Length) |
| | 609 | 2040 | | { |
| | 609 | 2041 | | res[i + idxShift + 1] = word >> carryShift; |
| | 609 | 2042 | | } |
| | 840 | 2043 | | } |
| | 237 | 2044 | | } |
| | | 2045 | | |
| | 246 | 2046 | | return new BigInteger((short)sign, res); |
| | 255 | 2047 | | } |
| | | 2048 | | |
| | | 2049 | | /// <summary> |
| | | 2050 | | /// Shifts a <see cref="BigInteger"/> value a specified number of bits to the right. |
| | | 2051 | | /// </summary> |
| | | 2052 | | /// <param name="value">The value whose bits are to be shifted.</param> |
| | | 2053 | | /// <param name="shift">The number of bits to shift value to the right.</param> |
| | | 2054 | | /// <returns> |
| | | 2055 | | /// A value that has been shifted to the right by the specified number of bits. |
| | | 2056 | | /// </returns> |
| | | 2057 | | #pragma warning disable CA2225 // Operator overloads have named alternates |
| | | 2058 | | public static BigInteger operator >>(BigInteger value, int shift) |
| | | 2059 | | #pragma warning restore CA2225 // Operator overloads have named alternates |
| | 1481418 | 2060 | | { |
| | 1481418 | 2061 | | if (shift == 0 || value._sign == 0) |
| | 3 | 2062 | | { |
| | 3 | 2063 | | return value; |
| | | 2064 | | } |
| | | 2065 | | |
| | 1481415 | 2066 | | if (shift < 0) |
| | 3 | 2067 | | { |
| | 3 | 2068 | | return value << -shift; |
| | | 2069 | | } |
| | | 2070 | | |
| | 1481412 | 2071 | | var data = value._data; |
| | 1481412 | 2072 | | int sign = value._sign; |
| | | 2073 | | |
| | 1481412 | 2074 | | var topMostIdx = BitScanBackward(data[data.Length - 1]); |
| | 1481412 | 2075 | | var idxShift = shift >> 5; |
| | 1481412 | 2076 | | var bitShift = shift & 0x1F; |
| | | 2077 | | |
| | 1481412 | 2078 | | var extraWords = idxShift; |
| | 1481412 | 2079 | | if (bitShift > topMostIdx) |
| | 44458 | 2080 | | { |
| | 44458 | 2081 | | ++extraWords; |
| | 44458 | 2082 | | } |
| | | 2083 | | |
| | 1481412 | 2084 | | var size = data.Length - extraWords; |
| | | 2085 | | |
| | 1481412 | 2086 | | if (size <= 0) |
| | 21 | 2087 | | { |
| | 21 | 2088 | | return sign == 1 ? Zero : MinusOne; |
| | | 2089 | | } |
| | | 2090 | | |
| | 1481391 | 2091 | | var res = new uint[size]; |
| | 1481391 | 2092 | | var carryShift = 32 - bitShift; |
| | | 2093 | | |
| | 1481391 | 2094 | | if (carryShift == 32) |
| | 9 | 2095 | | { |
| | 96 | 2096 | | for (var i = data.Length - 1; i >= idxShift; --i) |
| | 39 | 2097 | | { |
| | 39 | 2098 | | var word = data[i]; |
| | | 2099 | | |
| | 39 | 2100 | | if (i - idxShift < res.Length) |
| | 39 | 2101 | | { |
| | 39 | 2102 | | res[i - idxShift] |= word >> bitShift; |
| | 39 | 2103 | | } |
| | 39 | 2104 | | } |
| | 9 | 2105 | | } |
| | | 2106 | | else |
| | 1481382 | 2107 | | { |
| | 51043510 | 2108 | | for (var i = data.Length - 1; i >= idxShift; --i) |
| | 24040373 | 2109 | | { |
| | 24040373 | 2110 | | var word = data[i]; |
| | | 2111 | | |
| | 24040373 | 2112 | | if (i - idxShift < res.Length) |
| | 23995933 | 2113 | | { |
| | 23995933 | 2114 | | res[i - idxShift] |= word >> bitShift; |
| | 23995933 | 2115 | | } |
| | | 2116 | | |
| | 24040373 | 2117 | | if (i - idxShift - 1 >= 0) |
| | 22558991 | 2118 | | { |
| | 22558991 | 2119 | | res[i - idxShift - 1] = word << carryShift; |
| | 22558991 | 2120 | | } |
| | 24040373 | 2121 | | } |
| | 1481382 | 2122 | | } |
| | | 2123 | | |
| | | 2124 | | // Round down instead of toward zero |
| | 1481391 | 2125 | | if (sign == -1) |
| | 9 | 2126 | | { |
| | 18 | 2127 | | for (var i = 0; i < idxShift; i++) |
| | 3 | 2128 | | { |
| | 3 | 2129 | | if (data[i] != 0u) |
| | 3 | 2130 | | { |
| | 3 | 2131 | | var tmp = new BigInteger((short)sign, res); |
| | 3 | 2132 | | --tmp; |
| | 3 | 2133 | | return tmp; |
| | | 2134 | | } |
| | 0 | 2135 | | } |
| | | 2136 | | |
| | 6 | 2137 | | if (bitShift > 0 && (data[idxShift] << carryShift) != 0u) |
| | 6 | 2138 | | { |
| | 6 | 2139 | | var tmp = new BigInteger((short)sign, res); |
| | 6 | 2140 | | --tmp; |
| | 6 | 2141 | | return tmp; |
| | | 2142 | | } |
| | 0 | 2143 | | } |
| | | 2144 | | |
| | 1481382 | 2145 | | return new BigInteger((short)sign, res); |
| | 1481418 | 2146 | | } |
| | | 2147 | | |
| | | 2148 | | /// <summary> |
| | | 2149 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than another |
| | | 2150 | | /// <see cref="BigInteger"/> value. |
| | | 2151 | | /// </summary> |
| | | 2152 | | /// <param name="left">The first value to compare.</param> |
| | | 2153 | | /// <param name="right">The second value to compare.</param> |
| | | 2154 | | /// <returns> |
| | | 2155 | | /// <see langword="true"/> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <see lan |
| | | 2156 | | /// </returns> |
| | | 2157 | | public static bool operator <(BigInteger left, BigInteger right) |
| | 1960 | 2158 | | { |
| | 1960 | 2159 | | return Compare(left, right) < 0; |
| | 1960 | 2160 | | } |
| | | 2161 | | |
| | | 2162 | | /// <summary> |
| | | 2163 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than a 64-bit signed integer |
| | | 2164 | | /// </summary> |
| | | 2165 | | /// <param name="left">The first value to compare.</param> |
| | | 2166 | | /// <param name="right">The second value to compare.</param> |
| | | 2167 | | /// <returns> |
| | | 2168 | | /// <see langword="true"/> if left is <paramref name="left"/> than <paramref name="right"/>; otherwise, <see lan |
| | | 2169 | | /// </returns> |
| | | 2170 | | public static bool operator <(BigInteger left, long right) |
| | 2481 | 2171 | | { |
| | 2481 | 2172 | | return left.CompareTo(right) < 0; |
| | 2481 | 2173 | | } |
| | | 2174 | | |
| | | 2175 | | /// <summary> |
| | | 2176 | | /// Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="BigInteger"/> value |
| | | 2177 | | /// </summary> |
| | | 2178 | | /// <param name="left">The first value to compare.</param> |
| | | 2179 | | /// <param name="right">The second value to compare.</param> |
| | | 2180 | | /// <returns> |
| | | 2181 | | /// <see langword="true"/> if <paramref name="left"/> is less than <paramref name="right"/>; |
| | | 2182 | | /// otherwise, <see langword="false"/>. |
| | | 2183 | | /// </returns> |
| | | 2184 | | public static bool operator <(long left, BigInteger right) |
| | 363 | 2185 | | { |
| | 363 | 2186 | | return right.CompareTo(left) > 0; |
| | 363 | 2187 | | } |
| | | 2188 | | |
| | | 2189 | | /// <summary> |
| | | 2190 | | /// Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="BigInteger"/> value |
| | | 2191 | | /// </summary> |
| | | 2192 | | /// <param name="left">The first value to compare.</param> |
| | | 2193 | | /// <param name="right">The second value to compare.</param> |
| | | 2194 | | /// <returns> |
| | | 2195 | | /// <see langword="true"/> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <see lan |
| | | 2196 | | /// </returns> |
| | | 2197 | | [CLSCompliant(false)] |
| | | 2198 | | public static bool operator <(BigInteger left, ulong right) |
| | 192 | 2199 | | { |
| | 192 | 2200 | | return left.CompareTo(right) < 0; |
| | 192 | 2201 | | } |
| | | 2202 | | |
| | | 2203 | | /// <summary> |
| | | 2204 | | /// Returns a value that indicates whether a 64-bit unsigned integer is less than a <see cref="BigInteger"/> val |
| | | 2205 | | /// </summary> |
| | | 2206 | | /// <param name="left">The first value to compare.</param> |
| | | 2207 | | /// <param name="right">The second value to compare.</param> |
| | | 2208 | | /// <returns> |
| | | 2209 | | /// <see langword="true"/> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <see lan |
| | | 2210 | | /// </returns> |
| | | 2211 | | [CLSCompliant(false)] |
| | | 2212 | | public static bool operator <(ulong left, BigInteger right) |
| | 192 | 2213 | | { |
| | 192 | 2214 | | return right.CompareTo(left) > 0; |
| | 192 | 2215 | | } |
| | | 2216 | | |
| | | 2217 | | /// <summary> |
| | | 2218 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal |
| | | 2219 | | /// to another <see cref="BigInteger"/> value. |
| | | 2220 | | /// </summary> |
| | | 2221 | | /// <param name="left">The first value to compare.</param> |
| | | 2222 | | /// <param name="right">The second value to compare.</param> |
| | | 2223 | | /// <returns> |
| | | 2224 | | /// <see langword="true"/> if <paramref name="left"/> is less than or equal to <paramref name="right"/>; |
| | | 2225 | | /// otherwise, <see langword="false"/>. |
| | | 2226 | | /// </returns> |
| | | 2227 | | public static bool operator <=(BigInteger left, BigInteger right) |
| | 2658 | 2228 | | { |
| | 2658 | 2229 | | return Compare(left, right) <= 0; |
| | 2658 | 2230 | | } |
| | | 2231 | | |
| | | 2232 | | /// <summary> |
| | | 2233 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal |
| | | 2234 | | /// to a 64-bit signed integer. |
| | | 2235 | | /// </summary> |
| | | 2236 | | /// <param name="left">The first value to compare.</param> |
| | | 2237 | | /// <param name="right">The second value to compare.</param> |
| | | 2238 | | /// <returns> |
| | | 2239 | | /// <see langword="true"/> if <paramref name="left"/> is less than or equal to <paramref name="right"/>; |
| | | 2240 | | /// otherwise, <see langword="false"/>. |
| | | 2241 | | /// </returns> |
| | | 2242 | | public static bool operator <=(BigInteger left, long right) |
| | 371 | 2243 | | { |
| | 371 | 2244 | | return left.CompareTo(right) <= 0; |
| | 371 | 2245 | | } |
| | | 2246 | | |
| | | 2247 | | /// <summary> |
| | | 2248 | | /// Returns a value that indicates whether a 64-bit signed integer is less than or equal to a <see cref="BigInte |
| | | 2249 | | /// </summary> |
| | | 2250 | | /// <param name="left">The first value to compare.</param> |
| | | 2251 | | /// <param name="right">The second value to compare.</param> |
| | | 2252 | | /// <returns> |
| | | 2253 | | /// <see langword="true"/> if <paramref name="left"/> is less than or equal to <paramref name="right"/>; |
| | | 2254 | | /// otherwise, <see langword="false"/>. |
| | | 2255 | | /// </returns> |
| | | 2256 | | public static bool operator <=(long left, BigInteger right) |
| | 363 | 2257 | | { |
| | 363 | 2258 | | return right.CompareTo(left) >= 0; |
| | 363 | 2259 | | } |
| | | 2260 | | |
| | | 2261 | | /// <summary> |
| | | 2262 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal to |
| | | 2263 | | /// a 64-bit unsigned integer. |
| | | 2264 | | /// </summary> |
| | | 2265 | | /// <param name="left">The first value to compare.</param> |
| | | 2266 | | /// <param name="right">The second value to compare.</param> |
| | | 2267 | | /// <returns> |
| | | 2268 | | /// <see langword="true"/> if <paramref name="left"/> is less than or equal to <paramref name="right"/>; |
| | | 2269 | | /// otherwise, <see langword="false"/>. |
| | | 2270 | | /// </returns> |
| | | 2271 | | [CLSCompliant(false)] |
| | | 2272 | | public static bool operator <=(BigInteger left, ulong right) |
| | 192 | 2273 | | { |
| | 192 | 2274 | | return left.CompareTo(right) <= 0; |
| | 192 | 2275 | | } |
| | | 2276 | | |
| | | 2277 | | /// <summary> |
| | | 2278 | | /// Returns a value that indicates whether a 64-bit unsigned integer is less than or equal to a |
| | | 2279 | | /// <see cref="BigInteger"/> value. |
| | | 2280 | | /// </summary> |
| | | 2281 | | /// <param name="left">The first value to compare.</param> |
| | | 2282 | | /// <param name="right">The second value to compare.</param> |
| | | 2283 | | /// <returns> |
| | | 2284 | | /// <see langword="true"/> if <paramref name="left"/> is less than or equal to <paramref name="right"/>; |
| | | 2285 | | /// otherwise, <see langword="false"/>. |
| | | 2286 | | /// </returns> |
| | | 2287 | | [CLSCompliant(false)] |
| | | 2288 | | public static bool operator <=(ulong left, BigInteger right) |
| | 192 | 2289 | | { |
| | 192 | 2290 | | return right.CompareTo(left) >= 0; |
| | 192 | 2291 | | } |
| | | 2292 | | |
| | | 2293 | | /// <summary> |
| | | 2294 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than another |
| | | 2295 | | /// <see cref="BigInteger"/> value. |
| | | 2296 | | /// </summary> |
| | | 2297 | | /// <param name="left">The first value to compare.</param> |
| | | 2298 | | /// <param name="right">The second value to compare.</param> |
| | | 2299 | | /// <returns> |
| | | 2300 | | /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>; |
| | | 2301 | | /// otherwise, <see langword="false"/>. |
| | | 2302 | | /// </returns> |
| | | 2303 | | public static bool operator >(BigInteger left, BigInteger right) |
| | 1284 | 2304 | | { |
| | 1284 | 2305 | | return Compare(left, right) > 0; |
| | 1284 | 2306 | | } |
| | | 2307 | | |
| | | 2308 | | /// <summary> |
| | | 2309 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> is greater than a 64-bit signed integer va |
| | | 2310 | | /// </summary> |
| | | 2311 | | /// <param name="left">The first value to compare.</param> |
| | | 2312 | | /// <param name="right">The second value to compare.</param> |
| | | 2313 | | /// <returns> |
| | | 2314 | | /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>; |
| | | 2315 | | /// otherwise, <see langword="false"/>. |
| | | 2316 | | /// </returns> |
| | | 2317 | | public static bool operator >(BigInteger left, long right) |
| | 363 | 2318 | | { |
| | 363 | 2319 | | return left.CompareTo(right) > 0; |
| | 363 | 2320 | | } |
| | | 2321 | | |
| | | 2322 | | /// <summary> |
| | | 2323 | | /// Returns a value that indicates whether a 64-bit signed integer is greater than a <see cref="BigInteger"/> va |
| | | 2324 | | /// </summary> |
| | | 2325 | | /// <param name="left">The first value to compare.</param> |
| | | 2326 | | /// <param name="right">The second value to compare.</param> |
| | | 2327 | | /// <returns> |
| | | 2328 | | /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>; |
| | | 2329 | | /// otherwise, <see langword="false"/>. |
| | | 2330 | | /// </returns> |
| | | 2331 | | public static bool operator >(long left, BigInteger right) |
| | 363 | 2332 | | { |
| | 363 | 2333 | | return right.CompareTo(left) < 0; |
| | 363 | 2334 | | } |
| | | 2335 | | |
| | | 2336 | | /// <summary> |
| | | 2337 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than a 64-bit unsigned in |
| | | 2338 | | /// </summary> |
| | | 2339 | | /// <param name="left">The first value to compare.</param> |
| | | 2340 | | /// <param name="right">The second value to compare.</param> |
| | | 2341 | | /// <returns> |
| | | 2342 | | /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>; |
| | | 2343 | | /// otherwise, <see langword="false"/>. |
| | | 2344 | | /// </returns> |
| | | 2345 | | [CLSCompliant(false)] |
| | | 2346 | | public static bool operator >(BigInteger left, ulong right) |
| | 192 | 2347 | | { |
| | 192 | 2348 | | return left.CompareTo(right) > 0; |
| | 192 | 2349 | | } |
| | | 2350 | | |
| | | 2351 | | /// <summary> |
| | | 2352 | | /// Returns a value that indicates whether a 64-bit unsigned integer is greater than a <see cref="BigInteger"/> |
| | | 2353 | | /// </summary> |
| | | 2354 | | /// <param name="left">The first value to compare.</param> |
| | | 2355 | | /// <param name="right">The second value to compare.</param> |
| | | 2356 | | /// <returns> |
| | | 2357 | | /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>; |
| | | 2358 | | /// otherwise, <see langword="false"/>. |
| | | 2359 | | /// </returns> |
| | | 2360 | | [CLSCompliant(false)] |
| | | 2361 | | public static bool operator >(ulong left, BigInteger right) |
| | 192 | 2362 | | { |
| | 192 | 2363 | | return right.CompareTo(left) < 0; |
| | 192 | 2364 | | } |
| | | 2365 | | |
| | | 2366 | | /// <summary> |
| | | 2367 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal |
| | | 2368 | | /// to another <see cref="BigInteger"/> value. |
| | | 2369 | | /// </summary> |
| | | 2370 | | /// <param name="left">The first value to compare.</param> |
| | | 2371 | | /// <param name="right">The second value to compare.</param> |
| | | 2372 | | /// <returns> |
| | | 2373 | | /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>; |
| | | 2374 | | /// otherwise, <see langword="false"/>. |
| | | 2375 | | /// </returns> |
| | | 2376 | | public static bool operator >=(BigInteger left, BigInteger right) |
| | 1969 | 2377 | | { |
| | 1969 | 2378 | | return Compare(left, right) >= 0; |
| | 1969 | 2379 | | } |
| | | 2380 | | |
| | | 2381 | | /// <summary> |
| | | 2382 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal |
| | | 2383 | | /// to a 64-bit signed integer value. |
| | | 2384 | | /// </summary> |
| | | 2385 | | /// <param name="left">The first value to compare.</param> |
| | | 2386 | | /// <param name="right">The second value to compare.</param> |
| | | 2387 | | /// <returns> |
| | | 2388 | | /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>; |
| | | 2389 | | /// otherwise, <see langword="false"/>. |
| | | 2390 | | /// </returns> |
| | | 2391 | | public static bool operator >=(BigInteger left, long right) |
| | 363 | 2392 | | { |
| | 363 | 2393 | | return left.CompareTo(right) >= 0; |
| | 363 | 2394 | | } |
| | | 2395 | | |
| | | 2396 | | /// <summary> |
| | | 2397 | | /// Returns a value that indicates whether a 64-bit signed integer is greater than or equal to a |
| | | 2398 | | /// <see cref="BigInteger"/> value. |
| | | 2399 | | /// </summary> |
| | | 2400 | | /// <param name="left">The first value to compare.</param> |
| | | 2401 | | /// <param name="right">The second value to compare.</param> |
| | | 2402 | | /// <returns> |
| | | 2403 | | /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>; |
| | | 2404 | | /// otherwise, <see langword="false"/>. |
| | | 2405 | | /// </returns> |
| | | 2406 | | public static bool operator >=(long left, BigInteger right) |
| | 363 | 2407 | | { |
| | 363 | 2408 | | return right.CompareTo(left) <= 0; |
| | 363 | 2409 | | } |
| | | 2410 | | |
| | | 2411 | | /// <summary> |
| | | 2412 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal to a |
| | | 2413 | | /// 64-bit unsigned integer value. |
| | | 2414 | | /// </summary> |
| | | 2415 | | /// <param name="left">The first value to compare.</param> |
| | | 2416 | | /// <param name="right">The second value to compare.</param> |
| | | 2417 | | /// <returns> |
| | | 2418 | | /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>; |
| | | 2419 | | /// otherwise, <see langword="false"/>. |
| | | 2420 | | /// </returns> |
| | | 2421 | | [CLSCompliant(false)] |
| | | 2422 | | public static bool operator >=(BigInteger left, ulong right) |
| | 192 | 2423 | | { |
| | 192 | 2424 | | return left.CompareTo(right) >= 0; |
| | 192 | 2425 | | } |
| | | 2426 | | |
| | | 2427 | | /// <summary> |
| | | 2428 | | /// Returns a value that indicates whether a 64-bit unsigned integer is greater than or equal to a |
| | | 2429 | | /// <see cref="BigInteger"/> value. |
| | | 2430 | | /// </summary> |
| | | 2431 | | /// <param name="left">The first value to compare.</param> |
| | | 2432 | | /// <param name="right">The second value to compare.</param> |
| | | 2433 | | /// <returns> |
| | | 2434 | | /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>; |
| | | 2435 | | /// otherwise, <see langword="false"/>. |
| | | 2436 | | /// </returns> |
| | | 2437 | | [CLSCompliant(false)] |
| | | 2438 | | public static bool operator >=(ulong left, BigInteger right) |
| | 192 | 2439 | | { |
| | 192 | 2440 | | return right.CompareTo(left) <= 0; |
| | 192 | 2441 | | } |
| | | 2442 | | |
| | | 2443 | | /// <summary> |
| | | 2444 | | /// Returns a value that indicates whether the values of two <see cref="BigInteger"/> objects are equal. |
| | | 2445 | | /// </summary> |
| | | 2446 | | /// <param name="left">The first value to compare.</param> |
| | | 2447 | | /// <param name="right">The second value to compare.</param> |
| | | 2448 | | /// <returns> |
| | | 2449 | | /// <see langword="true"/> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same |
| | | 2450 | | /// otherwise, <see langword="false"/>. |
| | | 2451 | | /// </returns> |
| | | 2452 | | public static bool operator ==(BigInteger left, BigInteger right) |
| | 1263 | 2453 | | { |
| | 1263 | 2454 | | return Compare(left, right) == 0; |
| | 1263 | 2455 | | } |
| | | 2456 | | |
| | | 2457 | | /// <summary> |
| | | 2458 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a signed long integer value are |
| | | 2459 | | /// </summary> |
| | | 2460 | | /// <param name="left">The first value to compare.</param> |
| | | 2461 | | /// <param name="right">The second value to compare.</param> |
| | | 2462 | | /// <returns> |
| | | 2463 | | /// <see langword="true"/> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same |
| | | 2464 | | /// otherwise, <see langword="false"/>. |
| | | 2465 | | /// </returns> |
| | | 2466 | | public static bool operator ==(BigInteger left, long right) |
| | 363 | 2467 | | { |
| | 363 | 2468 | | return left.CompareTo(right) == 0; |
| | 363 | 2469 | | } |
| | | 2470 | | |
| | | 2471 | | /// <summary> |
| | | 2472 | | /// Returns a value that indicates whether a signed long integer value and a <see cref="BigInteger"/> value are |
| | | 2473 | | /// </summary> |
| | | 2474 | | /// <param name="left">The first value to compare.</param> |
| | | 2475 | | /// <param name="right">The second value to compare.</param> |
| | | 2476 | | /// <returns> |
| | | 2477 | | /// <see langword="true"/> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same |
| | | 2478 | | /// otherwise, <see langword="false"/>. |
| | | 2479 | | /// </returns> |
| | | 2480 | | public static bool operator ==(long left, BigInteger right) |
| | 363 | 2481 | | { |
| | 363 | 2482 | | return right.CompareTo(left) == 0; |
| | 363 | 2483 | | } |
| | | 2484 | | |
| | | 2485 | | /// <summary> |
| | | 2486 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value and an unsigned long integer value a |
| | | 2487 | | /// </summary> |
| | | 2488 | | /// <param name="left">The first value to compare.</param> |
| | | 2489 | | /// <param name="right">The second value to compare.</param> |
| | | 2490 | | /// <returns> |
| | | 2491 | | /// <see langword="true"/> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same |
| | | 2492 | | /// otherwise, <see langword="false"/>. |
| | | 2493 | | /// </returns> |
| | | 2494 | | [CLSCompliant(false)] |
| | | 2495 | | public static bool operator ==(BigInteger left, ulong right) |
| | 192 | 2496 | | { |
| | 192 | 2497 | | return left.CompareTo(right) == 0; |
| | 192 | 2498 | | } |
| | | 2499 | | |
| | | 2500 | | /// <summary> |
| | | 2501 | | /// Returns a value that indicates whether an unsigned long integer value and a <see cref="BigInteger"/> value a |
| | | 2502 | | /// </summary> |
| | | 2503 | | /// <param name="left">The first value to compare.</param> |
| | | 2504 | | /// <param name="right">The second value to compare.</param> |
| | | 2505 | | /// <returns> |
| | | 2506 | | /// <see langword="true"/> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same |
| | | 2507 | | /// otherwise, <see langword="false"/>. |
| | | 2508 | | /// </returns> |
| | | 2509 | | [CLSCompliant(false)] |
| | | 2510 | | public static bool operator ==(ulong left, BigInteger right) |
| | 192 | 2511 | | { |
| | 192 | 2512 | | return right.CompareTo(left) == 0; |
| | 192 | 2513 | | } |
| | | 2514 | | |
| | | 2515 | | /// <summary> |
| | | 2516 | | /// Returns a value that indicates whether two <see cref="BigInteger"/> objects have different values. |
| | | 2517 | | /// </summary> |
| | | 2518 | | /// <param name="left">The first value to compare.</param> |
| | | 2519 | | /// <param name="right">The second value to compare.</param> |
| | | 2520 | | /// <returns> |
| | | 2521 | | /// <see langword="true"/> if <paramref name="left"/> and <paramref name="right"/> are not equal; |
| | | 2522 | | /// otherwise, <see langword="false"/>. |
| | | 2523 | | /// </returns> |
| | | 2524 | | public static bool operator !=(BigInteger left, BigInteger right) |
| | 1257 | 2525 | | { |
| | 1257 | 2526 | | return Compare(left, right) != 0; |
| | 1257 | 2527 | | } |
| | | 2528 | | |
| | | 2529 | | /// <summary> |
| | | 2530 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a 64-bit signed integer are not |
| | | 2531 | | /// </summary> |
| | | 2532 | | /// <param name="left">The first value to compare.</param> |
| | | 2533 | | /// <param name="right">The second value to compare.</param> |
| | | 2534 | | /// <returns> |
| | | 2535 | | /// <see langword="true"/> if <paramref name="left"/> and <paramref name="right"/> are not equal; |
| | | 2536 | | /// otherwise, <see langword="false"/>. |
| | | 2537 | | /// </returns> |
| | | 2538 | | public static bool operator !=(BigInteger left, long right) |
| | 19044 | 2539 | | { |
| | 19044 | 2540 | | return left.CompareTo(right) != 0; |
| | 19044 | 2541 | | } |
| | | 2542 | | |
| | | 2543 | | /// <summary> |
| | | 2544 | | /// Returns a value that indicates whether a 64-bit signed integer and a <see cref="BigInteger"/> value are not |
| | | 2545 | | /// </summary> |
| | | 2546 | | /// <param name="left">The first value to compare.</param> |
| | | 2547 | | /// <param name="right">The second value to compare.</param> |
| | | 2548 | | /// <returns> |
| | | 2549 | | /// <see langword="true"/> if <paramref name="left"/> and <paramref name="right"/> are not equal; |
| | | 2550 | | /// otherwise, <see langword="false"/>. |
| | | 2551 | | /// </returns> |
| | | 2552 | | public static bool operator !=(long left, BigInteger right) |
| | 363 | 2553 | | { |
| | 363 | 2554 | | return right.CompareTo(left) != 0; |
| | 363 | 2555 | | } |
| | | 2556 | | |
| | | 2557 | | /// <summary> |
| | | 2558 | | /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a 64-bit unsigned integer are no |
| | | 2559 | | /// </summary> |
| | | 2560 | | /// <param name="left">The first value to compare.</param> |
| | | 2561 | | /// <param name="right">The second value to compare.</param> |
| | | 2562 | | /// <returns> |
| | | 2563 | | /// <see langword="true"/> if <paramref name="left"/> and <paramref name="right"/> are not equal; |
| | | 2564 | | /// otherwise, <see langword="false"/>. |
| | | 2565 | | /// </returns> |
| | | 2566 | | [CLSCompliant(false)] |
| | | 2567 | | public static bool operator !=(BigInteger left, ulong right) |
| | 192 | 2568 | | { |
| | 192 | 2569 | | return left.CompareTo(right) != 0; |
| | 192 | 2570 | | } |
| | | 2571 | | |
| | | 2572 | | /// <summary> |
| | | 2573 | | /// Returns a value that indicates whether a 64-bit unsigned integer and a <see cref="BigInteger"/> value are no |
| | | 2574 | | /// </summary> |
| | | 2575 | | /// <param name="left">The first value to compare.</param> |
| | | 2576 | | /// <param name="right">The second value to compare.</param> |
| | | 2577 | | /// <returns> |
| | | 2578 | | /// <see langword="true"/> if <paramref name="left"/> and <paramref name="right"/> are not equal; |
| | | 2579 | | /// otherwise, <see langword="false"/>. |
| | | 2580 | | /// </returns> |
| | | 2581 | | [CLSCompliant(false)] |
| | | 2582 | | public static bool operator !=(ulong left, BigInteger right) |
| | 192 | 2583 | | { |
| | 192 | 2584 | | return right.CompareTo(left) != 0; |
| | 192 | 2585 | | } |
| | | 2586 | | |
| | | 2587 | | /// <summary> |
| | | 2588 | | /// Returns a value that indicates whether the current instance and a specified object have the same value. |
| | | 2589 | | /// </summary> |
| | | 2590 | | /// <param name="obj">The object to compare.</param> |
| | | 2591 | | /// <returns> |
| | | 2592 | | /// <see langword="true"/> if the <paramref name="obj"/> parameter is a <see cref="BigInteger"/> object or a typ |
| | | 2593 | | /// of implicit conversion to a <see cref="BigInteger"/> value, and its value is equal to the value of the |
| | | 2594 | | /// current <see cref="BigInteger"/> object; otherwise, <see langword="false"/>. |
| | | 2595 | | /// </returns> |
| | | 2596 | | public override readonly bool Equals(object obj) |
| | 0 | 2597 | | { |
| | 0 | 2598 | | if (obj is not BigInteger other) |
| | 0 | 2599 | | { |
| | 0 | 2600 | | return false; |
| | | 2601 | | } |
| | | 2602 | | |
| | 0 | 2603 | | return Equals(other); |
| | 0 | 2604 | | } |
| | | 2605 | | |
| | | 2606 | | /// <summary> |
| | | 2607 | | /// Returns a value that indicates whether the current instance and a specified <see cref="BigInteger"/> object |
| | | 2608 | | /// have the same value. |
| | | 2609 | | /// </summary> |
| | | 2610 | | /// <param name="other">The object to compare.</param> |
| | | 2611 | | /// <returns> |
| | | 2612 | | /// <see langword="true"/> if this <see cref="BigInteger"/> object and <paramref name="other"/> have the same va |
| | | 2613 | | /// otherwise, <see langword="false"/>. |
| | | 2614 | | /// </returns> |
| | | 2615 | | public readonly bool Equals(BigInteger other) |
| | 165 | 2616 | | { |
| | 165 | 2617 | | if (_sign != other._sign) |
| | 3 | 2618 | | { |
| | 3 | 2619 | | return false; |
| | | 2620 | | } |
| | | 2621 | | |
| | 162 | 2622 | | var alen = _data != null ? _data.Length : 0; |
| | 162 | 2623 | | var blen = other._data != null ? other._data.Length : 0; |
| | | 2624 | | |
| | 162 | 2625 | | if (alen != blen) |
| | 0 | 2626 | | { |
| | 0 | 2627 | | return false; |
| | | 2628 | | } |
| | | 2629 | | |
| | 828 | 2630 | | for (var i = 0; i < alen; ++i) |
| | 252 | 2631 | | { |
| | 252 | 2632 | | if (_data[i] != other._data[i]) |
| | 0 | 2633 | | { |
| | 0 | 2634 | | return false; |
| | | 2635 | | } |
| | 252 | 2636 | | } |
| | | 2637 | | |
| | 162 | 2638 | | return true; |
| | 165 | 2639 | | } |
| | | 2640 | | |
| | | 2641 | | /// <summary> |
| | | 2642 | | /// Returns a value that indicates whether the current instance and a signed 64-bit integer have the same value. |
| | | 2643 | | /// </summary> |
| | | 2644 | | /// <param name="other">The signed 64-bit integer value to compare.</param> |
| | | 2645 | | /// <returns> |
| | | 2646 | | /// <see langword="true"/> if the signed 64-bit integer and the current instance have the same value; otherwise, |
| | | 2647 | | /// </returns> |
| | | 2648 | | public readonly bool Equals(long other) |
| | 0 | 2649 | | { |
| | 0 | 2650 | | return CompareTo(other) == 0; |
| | 0 | 2651 | | } |
| | | 2652 | | |
| | | 2653 | | /// <summary> |
| | | 2654 | | /// Returns a value that indicates whether the current instance and an unsigned 64-bit integer have the same val |
| | | 2655 | | /// </summary> |
| | | 2656 | | /// <param name="other">The unsigned 64-bit integer to compare.</param> |
| | | 2657 | | /// <returns> |
| | | 2658 | | /// <see langword="true"/> if the current instance and the unsigned 64-bit integer have the same value; otherwis |
| | | 2659 | | /// </returns> |
| | | 2660 | | [CLSCompliant(false)] |
| | | 2661 | | public readonly bool Equals(ulong other) |
| | 0 | 2662 | | { |
| | 0 | 2663 | | return CompareTo(other) == 0; |
| | 0 | 2664 | | } |
| | | 2665 | | |
| | | 2666 | | /// <summary> |
| | | 2667 | | /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string represent |
| | | 2668 | | /// </summary> |
| | | 2669 | | /// <returns> |
| | | 2670 | | /// The string representation of the current <see cref="BigInteger"/> value. |
| | | 2671 | | /// </returns> |
| | | 2672 | | public override readonly string ToString() |
| | 447 | 2673 | | { |
| | 447 | 2674 | | return ToString(10, provider: null); |
| | 447 | 2675 | | } |
| | | 2676 | | |
| | | 2677 | | /// <summary> |
| | | 2678 | | /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string represent |
| | | 2679 | | /// by using the specified format. |
| | | 2680 | | /// </summary> |
| | | 2681 | | /// <param name="format">A standard or custom numeric format string.</param> |
| | | 2682 | | /// <returns> |
| | | 2683 | | /// The string representation of the current <see cref="BigInteger"/> value in the format specified by the |
| | | 2684 | | /// <paramref name="format"/> parameter. |
| | | 2685 | | /// </returns> |
| | | 2686 | | /// <exception cref="FormatException"><paramref name="format"/> is not a valid format string.</exception> |
| | | 2687 | | public readonly string ToString(string format) |
| | 36 | 2688 | | { |
| | 36 | 2689 | | return ToString(format, formatProvider: null); |
| | 36 | 2690 | | } |
| | | 2691 | | |
| | | 2692 | | /// <summary> |
| | | 2693 | | /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string represent |
| | | 2694 | | /// by using the specified culture-specific formatting information. |
| | | 2695 | | /// </summary> |
| | | 2696 | | /// <param name="provider">An object that supplies culture-specific formatting information.</param> |
| | | 2697 | | /// <returns> |
| | | 2698 | | /// The string representation of the current <see cref="BigInteger"/> value in the format specified by the |
| | | 2699 | | /// <paramref name="provider"/> parameter. |
| | | 2700 | | /// </returns> |
| | | 2701 | | public readonly string ToString(IFormatProvider provider) |
| | 12 | 2702 | | { |
| | 12 | 2703 | | return ToString(format: null, provider); |
| | 12 | 2704 | | } |
| | | 2705 | | |
| | | 2706 | | /// <summary> |
| | | 2707 | | /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string represent |
| | | 2708 | | /// by using the specified format and culture-specific format information. |
| | | 2709 | | /// </summary> |
| | | 2710 | | /// <param name="format">A standard or custom numeric format string.</param> |
| | | 2711 | | /// <param name="formatProvider">An object that supplies culture-specific formatting information.</param> |
| | | 2712 | | /// <returns> |
| | | 2713 | | /// The string representation of the current <see cref="BigInteger"/> value as specified by the <paramref name=" |
| | | 2714 | | /// and <paramref name="formatProvider"/> parameters. |
| | | 2715 | | /// </returns> |
| | | 2716 | | public readonly string ToString(string format, IFormatProvider formatProvider) |
| | 75 | 2717 | | { |
| | 75 | 2718 | | if (string.IsNullOrEmpty(format)) |
| | 15 | 2719 | | { |
| | 15 | 2720 | | return ToString(10, formatProvider); |
| | | 2721 | | } |
| | | 2722 | | |
| | 60 | 2723 | | switch (format[0]) |
| | | 2724 | | { |
| | | 2725 | | case 'd': |
| | | 2726 | | case 'D': |
| | | 2727 | | case 'g': |
| | | 2728 | | case 'G': |
| | | 2729 | | case 'r': |
| | | 2730 | | case 'R': |
| | 33 | 2731 | | return ToStringWithPadding(format, 10, formatProvider); |
| | | 2732 | | case 'x': |
| | | 2733 | | case 'X': |
| | 27 | 2734 | | return ToStringWithPadding(format, 16, provider: null); |
| | | 2735 | | default: |
| | 0 | 2736 | | throw new FormatException(string.Format("format '{0}' not implemented", format)); |
| | | 2737 | | } |
| | 75 | 2738 | | } |
| | | 2739 | | |
| | | 2740 | | private readonly string ToStringWithPadding(string format, uint radix, IFormatProvider provider) |
| | 60 | 2741 | | { |
| | 60 | 2742 | | if (format.Length > 1) |
| | 12 | 2743 | | { |
| | 12 | 2744 | | var precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat); |
| | 12 | 2745 | | var baseStr = ToString(radix, provider); |
| | 12 | 2746 | | if (baseStr.Length < precision) |
| | 9 | 2747 | | { |
| | 9 | 2748 | | var additional = new string('0', precision - baseStr.Length); |
| | 9 | 2749 | | if (baseStr[0] != '-') |
| | 9 | 2750 | | { |
| | 9 | 2751 | | return additional + baseStr; |
| | | 2752 | | } |
| | | 2753 | | |
| | | 2754 | | #if NET |
| | 0 | 2755 | | return string.Concat("-", additional, baseStr.AsSpan(1)); |
| | | 2756 | | #else |
| | 0 | 2757 | | return "-" + additional + baseStr.Substring(1); |
| | | 2758 | | #endif // NET |
| | | 2759 | | } |
| | | 2760 | | |
| | 3 | 2761 | | return baseStr; |
| | | 2762 | | } |
| | | 2763 | | |
| | 48 | 2764 | | return ToString(radix, provider); |
| | 60 | 2765 | | } |
| | | 2766 | | |
| | | 2767 | | private static uint[] MakeTwoComplement(uint[] v) |
| | 6 | 2768 | | { |
| | 6 | 2769 | | var res = new uint[v.Length]; |
| | | 2770 | | |
| | 6 | 2771 | | ulong carry = 1; |
| | 24 | 2772 | | for (var i = 0; i < v.Length; ++i) |
| | 6 | 2773 | | { |
| | 6 | 2774 | | var word = v[i]; |
| | 6 | 2775 | | carry = (ulong) ~word + carry; |
| | 6 | 2776 | | word = (uint) carry; |
| | 6 | 2777 | | carry = (uint) (carry >> 32); |
| | 6 | 2778 | | res[i] = word; |
| | 6 | 2779 | | } |
| | | 2780 | | |
| | 6 | 2781 | | var last = res[res.Length - 1]; |
| | 6 | 2782 | | var idx = FirstNonFfByte(last); |
| | 6 | 2783 | | uint mask = 0xFF; |
| | 12 | 2784 | | for (var i = 1; i < idx; ++i) |
| | 0 | 2785 | | { |
| | 0 | 2786 | | mask = (mask << 8) | 0xFF; |
| | 0 | 2787 | | } |
| | | 2788 | | |
| | 6 | 2789 | | res[res.Length - 1] = last & mask; |
| | 6 | 2790 | | return res; |
| | 6 | 2791 | | } |
| | | 2792 | | |
| | | 2793 | | private readonly string ToString(uint radix, IFormatProvider provider) |
| | 522 | 2794 | | { |
| | | 2795 | | const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
| | | 2796 | | |
| | 522 | 2797 | | if (characterSet.Length < radix) |
| | 0 | 2798 | | { |
| | 0 | 2799 | | throw new ArgumentException("charSet length less than radix", nameof(radix)); |
| | | 2800 | | } |
| | | 2801 | | |
| | 522 | 2802 | | if (radix == 1) |
| | 0 | 2803 | | { |
| | 0 | 2804 | | throw new ArgumentException("There is no such thing as radix one notation", nameof(radix)); |
| | | 2805 | | } |
| | | 2806 | | |
| | 522 | 2807 | | if (_sign == 0) |
| | 9 | 2808 | | { |
| | 9 | 2809 | | return "0"; |
| | | 2810 | | } |
| | | 2811 | | |
| | 513 | 2812 | | if (_data.Length == 1 && _data[0] == 1) |
| | 3 | 2813 | | { |
| | 3 | 2814 | | return _sign == 1 ? "1" : "-1"; |
| | | 2815 | | } |
| | | 2816 | | |
| | 510 | 2817 | | var digits = new List<char>(1 + ((_data.Length * 3) / 10)); |
| | | 2818 | | |
| | | 2819 | | BigInteger a; |
| | 510 | 2820 | | if (_sign == 1) |
| | 477 | 2821 | | { |
| | 477 | 2822 | | a = this; |
| | 477 | 2823 | | } |
| | | 2824 | | else |
| | 33 | 2825 | | { |
| | 33 | 2826 | | var dt = _data; |
| | 33 | 2827 | | if (radix > 10) |
| | 6 | 2828 | | { |
| | 6 | 2829 | | dt = MakeTwoComplement(dt); |
| | 6 | 2830 | | } |
| | | 2831 | | |
| | 33 | 2832 | | a = new BigInteger(1, dt); |
| | 33 | 2833 | | } |
| | | 2834 | | |
| | 18681 | 2835 | | while (a != 0) |
| | 18171 | 2836 | | { |
| | 18171 | 2837 | | a = DivRem(a, radix, out var rem); |
| | 18171 | 2838 | | digits.Add(characterSet[(int) rem]); |
| | 18171 | 2839 | | } |
| | | 2840 | | |
| | 510 | 2841 | | if (_sign == -1 && radix == 10) |
| | 27 | 2842 | | { |
| | 27 | 2843 | | NumberFormatInfo info = null; |
| | 27 | 2844 | | if (provider != null) |
| | 21 | 2845 | | { |
| | 21 | 2846 | | info = provider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo; |
| | 21 | 2847 | | } |
| | | 2848 | | |
| | 27 | 2849 | | if (info != null) |
| | 21 | 2850 | | { |
| | 21 | 2851 | | var str = info.NegativeSign; |
| | 108 | 2852 | | for (var i = str.Length - 1; i >= 0; --i) |
| | 33 | 2853 | | { |
| | 33 | 2854 | | digits.Add(str[i]); |
| | 33 | 2855 | | } |
| | 21 | 2856 | | } |
| | | 2857 | | else |
| | 6 | 2858 | | { |
| | 6 | 2859 | | digits.Add('-'); |
| | 6 | 2860 | | } |
| | 27 | 2861 | | } |
| | | 2862 | | |
| | 510 | 2863 | | var last = digits[digits.Count - 1]; |
| | 510 | 2864 | | if (_sign == 1 && radix > 10 && (last < '0' || last > '9')) |
| | 12 | 2865 | | { |
| | 12 | 2866 | | digits.Add('0'); |
| | 12 | 2867 | | } |
| | | 2868 | | |
| | 510 | 2869 | | digits.Reverse(); |
| | | 2870 | | |
| | 510 | 2871 | | return new string(digits.ToArray()); |
| | 522 | 2872 | | } |
| | | 2873 | | |
| | | 2874 | | /// <summary> |
| | | 2875 | | /// Converts the string representation of a number to its <see cref="BigInteger"/> equivalent. |
| | | 2876 | | /// </summary> |
| | | 2877 | | /// <param name="value">A string that contains the number to convert.</param> |
| | | 2878 | | /// <returns> |
| | | 2879 | | /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter. |
| | | 2880 | | /// </returns> |
| | | 2881 | | /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception> |
| | | 2882 | | /// <exception cref="FormatException"><paramref name="value"/> is not in the correct format.</exception> |
| | | 2883 | | public static BigInteger Parse(string value) |
| | 48 | 2884 | | { |
| | 48 | 2885 | | if (!Parse(value, tryParse: false, out var result, out var ex)) |
| | 18 | 2886 | | { |
| | 18 | 2887 | | throw ex; |
| | | 2888 | | } |
| | | 2889 | | |
| | 30 | 2890 | | return result; |
| | 30 | 2891 | | } |
| | | 2892 | | |
| | | 2893 | | /// <summary> |
| | | 2894 | | /// Converts the string representation of a number in a specified style to its <see cref="BigInteger"/> equivale |
| | | 2895 | | /// </summary> |
| | | 2896 | | /// <param name="value">A string that contains a number to convert.</param> |
| | | 2897 | | /// <param name="style">A bitwise combination of the enumeration values that specify the permitted format of <pa |
| | | 2898 | | /// <returns> |
| | | 2899 | | /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter. |
| | | 2900 | | /// </returns> |
| | | 2901 | | /// <exception cref="ArgumentException"> |
| | | 2902 | | /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para> |
| | | 2903 | | /// <para>-or-</para> |
| | | 2904 | | /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="Numbe |
| | | 2905 | | /// </exception> |
| | | 2906 | | /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception> |
| | | 2907 | | /// <exception cref="FormatException"><paramref name="value"/> does not comply with the input pattern specified |
| | | 2908 | | public static BigInteger Parse(string value, NumberStyles style) |
| | 39 | 2909 | | { |
| | 39 | 2910 | | return Parse(value, style, provider: null); |
| | 36 | 2911 | | } |
| | | 2912 | | |
| | | 2913 | | /// <summary> |
| | | 2914 | | /// Converts the string representation of a number in a specified style to its <see cref="BigInteger"/> equivale |
| | | 2915 | | /// </summary> |
| | | 2916 | | /// <param name="value">A string that contains a number to convert.</param> |
| | | 2917 | | /// <param name="provider">An object that provides culture-specific formatting information about <paramref name= |
| | | 2918 | | /// <returns> |
| | | 2919 | | /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter. |
| | | 2920 | | /// </returns> |
| | | 2921 | | /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception> |
| | | 2922 | | /// <exception cref="FormatException"><paramref name="value"/> is not in the correct format.</exception> |
| | | 2923 | | public static BigInteger Parse(string value, IFormatProvider provider) |
| | 0 | 2924 | | { |
| | 0 | 2925 | | return Parse(value, NumberStyles.Integer, provider); |
| | 0 | 2926 | | } |
| | | 2927 | | |
| | | 2928 | | /// <summary> |
| | | 2929 | | /// Converts the string representation of a number in a specified style and culture-specific format to its <see |
| | | 2930 | | /// </summary> |
| | | 2931 | | /// <param name="value">A string that contains a number to convert.</param> |
| | | 2932 | | /// <param name="style">A bitwise combination of the enumeration values that specify the permitted format of <pa |
| | | 2933 | | /// <param name="provider">An object that provides culture-specific formatting information about <paramref name= |
| | | 2934 | | /// <returns> |
| | | 2935 | | /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter. |
| | | 2936 | | /// </returns> |
| | | 2937 | | /// <exception cref="ArgumentException"> |
| | | 2938 | | /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para> |
| | | 2939 | | /// <para>-or-</para> |
| | | 2940 | | /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="Numbe |
| | | 2941 | | /// </exception> |
| | | 2942 | | /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception> |
| | | 2943 | | /// <exception cref="FormatException"><paramref name="value"/> does not comply with the input pattern specified |
| | | 2944 | | public static BigInteger Parse(string value, NumberStyles style, IFormatProvider provider) |
| | 45 | 2945 | | { |
| | 45 | 2946 | | if (!Parse(value, style, provider, tryParse: false, out var res, out var exc)) |
| | 3 | 2947 | | { |
| | 3 | 2948 | | throw exc; |
| | | 2949 | | } |
| | | 2950 | | |
| | 42 | 2951 | | return res; |
| | 42 | 2952 | | } |
| | | 2953 | | |
| | | 2954 | | /// <summary> |
| | | 2955 | | /// Tries to convert the string representation of a number to its <see cref="BigInteger"/> equivalent, and |
| | | 2956 | | /// returns a value that indicates whether the conversion succeeded. |
| | | 2957 | | /// </summary> |
| | | 2958 | | /// <param name="value">The string representation of a number.</param> |
| | | 2959 | | /// <param name="result">When this method returns, contains the <see cref="BigInteger"/> equivalent to the numbe |
| | | 2960 | | /// <returns> |
| | | 2961 | | /// <see langword="true"/> if <paramref name="value"/> was converted successfully; otherwise, <see langword="fal |
| | | 2962 | | /// </returns> |
| | | 2963 | | /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception> |
| | | 2964 | | public static bool TryParse(string value, out BigInteger result) |
| | 33 | 2965 | | { |
| | 33 | 2966 | | return Parse(value, tryParse: true, out result, out _); |
| | 33 | 2967 | | } |
| | | 2968 | | |
| | | 2969 | | /// <summary> |
| | | 2970 | | /// Tries to convert the string representation of a number in a specified style and culture-specific format to i |
| | | 2971 | | /// <see cref="BigInteger"/> equivalent, and returns a value that indicates whether the conversion succeeded. |
| | | 2972 | | /// </summary> |
| | | 2973 | | /// <param name="value">The string representation of a number.</param> |
| | | 2974 | | /// <param name="style">A bitwise combination of enumeration values that indicates the style elements that can b |
| | | 2975 | | /// <param name="provider">An object that supplies culture-specific formatting information about <paramref name= |
| | | 2976 | | /// <param name="result">When this method returns, contains the <see cref="BigInteger"/> equivalent to the numbe |
| | | 2977 | | /// <returns> |
| | | 2978 | | /// <see langword="true"/> if <paramref name="value"/> was converted successfully; otherwise, <see langword="fal |
| | | 2979 | | /// </returns> |
| | | 2980 | | /// <exception cref="ArgumentException"> |
| | | 2981 | | /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para> |
| | | 2982 | | /// <para>-or-</para> |
| | | 2983 | | /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="Numbe |
| | | 2984 | | /// </exception> |
| | | 2985 | | public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out BigInteger result) |
| | 63 | 2986 | | { |
| | 63 | 2987 | | if (!Parse(value, style, provider, tryParse: true, out result, out _)) |
| | 33 | 2988 | | { |
| | 33 | 2989 | | result = Zero; |
| | 33 | 2990 | | return false; |
| | | 2991 | | } |
| | | 2992 | | |
| | 30 | 2993 | | return true; |
| | 63 | 2994 | | } |
| | | 2995 | | |
| | | 2996 | | #pragma warning disable S4136 // Method overloads should be grouped together |
| | | 2997 | | private static bool Parse(string value, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger re |
| | | 2998 | | #pragma warning restore S4136 // Method overloads should be grouped together |
| | 108 | 2999 | | { |
| | 108 | 3000 | | result = Zero; |
| | 108 | 3001 | | exc = null; |
| | | 3002 | | |
| | 108 | 3003 | | if (value is null) |
| | 3 | 3004 | | { |
| | 3 | 3005 | | if (!tryParse) |
| | 0 | 3006 | | { |
| | 0 | 3007 | | exc = new ArgumentNullException(nameof(value)); |
| | 0 | 3008 | | } |
| | | 3009 | | |
| | 3 | 3010 | | return false; |
| | | 3011 | | } |
| | | 3012 | | |
| | 105 | 3013 | | if (value.Length == 0) |
| | 0 | 3014 | | { |
| | 0 | 3015 | | if (!tryParse) |
| | 0 | 3016 | | { |
| | 0 | 3017 | | exc = GetFormatException(); |
| | 0 | 3018 | | } |
| | | 3019 | | |
| | 0 | 3020 | | return false; |
| | | 3021 | | } |
| | | 3022 | | |
| | 105 | 3023 | | NumberFormatInfo nfi = null; |
| | 105 | 3024 | | if (fp != null) |
| | 30 | 3025 | | { |
| | 30 | 3026 | | var typeNfi = typeof(NumberFormatInfo); |
| | 30 | 3027 | | nfi = (NumberFormatInfo) fp.GetFormat(typeNfi); |
| | 30 | 3028 | | } |
| | | 3029 | | |
| | 105 | 3030 | | nfi ??= NumberFormatInfo.CurrentInfo; |
| | | 3031 | | |
| | 105 | 3032 | | if (!CheckStyle(style, tryParse, ref exc)) |
| | 0 | 3033 | | { |
| | 0 | 3034 | | return false; |
| | | 3035 | | } |
| | | 3036 | | |
| | 105 | 3037 | | var allowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) == NumberStyles.AllowCurrencySymbol; |
| | 105 | 3038 | | var allowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier; |
| | 105 | 3039 | | var allowThousands = (style & NumberStyles.AllowThousands) == NumberStyles.AllowThousands; |
| | 105 | 3040 | | var allowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) == NumberStyles.AllowDecimalPoint; |
| | 105 | 3041 | | var allowParentheses = (style & NumberStyles.AllowParentheses) == NumberStyles.AllowParentheses; |
| | 105 | 3042 | | var allowTrailingSign = (style & NumberStyles.AllowTrailingSign) == NumberStyles.AllowTrailingSign; |
| | 105 | 3043 | | var allowLeadingSign = (style & NumberStyles.AllowLeadingSign) == NumberStyles.AllowLeadingSign; |
| | 105 | 3044 | | var allowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) == NumberStyles.AllowTrailingWhite; |
| | 105 | 3045 | | var allowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) == NumberStyles.AllowLeadingWhite; |
| | 105 | 3046 | | var allowExponent = (style & NumberStyles.AllowExponent) == NumberStyles.AllowExponent; |
| | | 3047 | | |
| | 105 | 3048 | | var pos = 0; |
| | | 3049 | | |
| | 105 | 3050 | | if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) |
| | 0 | 3051 | | { |
| | 0 | 3052 | | return false; |
| | | 3053 | | } |
| | | 3054 | | |
| | 105 | 3055 | | var foundOpenParentheses = false; |
| | 105 | 3056 | | var negative = false; |
| | 105 | 3057 | | var foundSign = false; |
| | 105 | 3058 | | var foundCurrency = false; |
| | | 3059 | | |
| | | 3060 | | // Pre-number stuff |
| | 105 | 3061 | | if (allowParentheses && value[pos] == '(') |
| | 6 | 3062 | | { |
| | 6 | 3063 | | foundOpenParentheses = true; |
| | 6 | 3064 | | foundSign = true; |
| | 6 | 3065 | | negative = true; // MS always make the number negative when there parentheses, even when NumberFormatInf |
| | 6 | 3066 | | pos++; |
| | | 3067 | | |
| | 6 | 3068 | | if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) |
| | 0 | 3069 | | { |
| | 0 | 3070 | | return false; |
| | | 3071 | | } |
| | | 3072 | | |
| | 6 | 3073 | | if (value.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign) |
| | 0 | 3074 | | { |
| | 0 | 3075 | | if (!tryParse) |
| | 0 | 3076 | | { |
| | 0 | 3077 | | exc = GetFormatException(); |
| | 0 | 3078 | | } |
| | | 3079 | | |
| | 0 | 3080 | | return false; |
| | | 3081 | | } |
| | | 3082 | | |
| | 6 | 3083 | | if (value.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign) |
| | 0 | 3084 | | { |
| | 0 | 3085 | | if (!tryParse) |
| | 0 | 3086 | | { |
| | 0 | 3087 | | exc = GetFormatException(); |
| | 0 | 3088 | | } |
| | | 3089 | | |
| | 0 | 3090 | | return false; |
| | | 3091 | | } |
| | 6 | 3092 | | } |
| | | 3093 | | |
| | 105 | 3094 | | if (allowLeadingSign && !foundSign) |
| | 18 | 3095 | | { |
| | | 3096 | | // Sign + Currency |
| | 18 | 3097 | | FindSign(ref pos, value, nfi, ref foundSign, ref negative); |
| | 18 | 3098 | | if (foundSign) |
| | 6 | 3099 | | { |
| | 6 | 3100 | | if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) |
| | 0 | 3101 | | { |
| | 0 | 3102 | | return false; |
| | | 3103 | | } |
| | | 3104 | | |
| | 6 | 3105 | | if (allowCurrencySymbol) |
| | 0 | 3106 | | { |
| | 0 | 3107 | | FindCurrency(ref pos, value, nfi, ref foundCurrency); |
| | 0 | 3108 | | if (foundCurrency && allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, |
| | 0 | 3109 | | { |
| | 0 | 3110 | | return false; |
| | | 3111 | | } |
| | 0 | 3112 | | } |
| | 6 | 3113 | | } |
| | 18 | 3114 | | } |
| | | 3115 | | |
| | 105 | 3116 | | if (allowCurrencySymbol && !foundCurrency) |
| | 12 | 3117 | | { |
| | | 3118 | | // Currency + sign |
| | 12 | 3119 | | FindCurrency(ref pos, value, nfi, ref foundCurrency); |
| | 12 | 3120 | | if (foundCurrency) |
| | 3 | 3121 | | { |
| | 3 | 3122 | | if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) |
| | 0 | 3123 | | { |
| | 0 | 3124 | | return false; |
| | | 3125 | | } |
| | | 3126 | | |
| | 3 | 3127 | | if (foundCurrency) |
| | 3 | 3128 | | { |
| | 3 | 3129 | | if (!foundSign && allowLeadingSign) |
| | 0 | 3130 | | { |
| | 0 | 3131 | | FindSign(ref pos, value, nfi, ref foundSign, ref negative); |
| | 0 | 3132 | | if (foundSign && allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, |
| | 0 | 3133 | | { |
| | 0 | 3134 | | return false; |
| | | 3135 | | } |
| | 0 | 3136 | | } |
| | 3 | 3137 | | } |
| | 3 | 3138 | | } |
| | 12 | 3139 | | } |
| | | 3140 | | |
| | 105 | 3141 | | var number = Zero; |
| | 105 | 3142 | | var nDigits = 0; |
| | 105 | 3143 | | var decimalPointPos = -1; |
| | 105 | 3144 | | var firstHexDigit = true; |
| | | 3145 | | |
| | | 3146 | | // Number stuff |
| | 12024 | 3147 | | while (pos < value.Length) |
| | 11979 | 3148 | | { |
| | 11979 | 3149 | | if (!ValidDigit(value[pos], allowHexSpecifier)) |
| | 81 | 3150 | | { |
| | 81 | 3151 | | if (allowThousands && |
| | 81 | 3152 | | (FindOther(ref pos, value, nfi.NumberGroupSeparator) |
| | 81 | 3153 | | || FindOther(ref pos, value, nfi.CurrencyGroupSeparator))) |
| | 12 | 3154 | | { |
| | 12 | 3155 | | continue; |
| | | 3156 | | } |
| | | 3157 | | |
| | 69 | 3158 | | if (allowDecimalPoint && decimalPointPos < 0 && |
| | 69 | 3159 | | (FindOther(ref pos, value, nfi.NumberDecimalSeparator) |
| | 69 | 3160 | | || FindOther(ref pos, value, nfi.CurrencyDecimalSeparator))) |
| | 9 | 3161 | | { |
| | 9 | 3162 | | decimalPointPos = nDigits; |
| | 9 | 3163 | | continue; |
| | | 3164 | | } |
| | | 3165 | | |
| | 60 | 3166 | | break; |
| | | 3167 | | } |
| | | 3168 | | |
| | 11898 | 3169 | | nDigits++; |
| | | 3170 | | |
| | 11898 | 3171 | | if (allowHexSpecifier) |
| | 2349 | 3172 | | { |
| | 2349 | 3173 | | var hexDigit = value[pos++]; |
| | | 3174 | | byte digitValue; |
| | 2349 | 3175 | | if (char.IsDigit(hexDigit)) |
| | 1383 | 3176 | | { |
| | 1383 | 3177 | | digitValue = (byte) (hexDigit - '0'); |
| | 1383 | 3178 | | } |
| | 966 | 3179 | | else if (char.IsLower(hexDigit)) |
| | 0 | 3180 | | { |
| | 0 | 3181 | | digitValue = (byte) (hexDigit - 'a' + 10); |
| | 0 | 3182 | | } |
| | | 3183 | | else |
| | 966 | 3184 | | { |
| | 966 | 3185 | | digitValue = (byte) (hexDigit - 'A' + 10); |
| | 966 | 3186 | | } |
| | | 3187 | | |
| | 2349 | 3188 | | if (firstHexDigit && digitValue >= 8) |
| | 9 | 3189 | | { |
| | 9 | 3190 | | negative = true; |
| | 9 | 3191 | | } |
| | | 3192 | | |
| | 2349 | 3193 | | number = (number * 16) + digitValue; |
| | 2349 | 3194 | | firstHexDigit = false; |
| | 2349 | 3195 | | continue; |
| | | 3196 | | } |
| | | 3197 | | |
| | 9549 | 3198 | | number = (number * 10) + (byte)(value[pos++] - '0'); |
| | 9549 | 3199 | | } |
| | | 3200 | | |
| | | 3201 | | // Post number stuff |
| | 105 | 3202 | | if (nDigits == 0) |
| | 24 | 3203 | | { |
| | 24 | 3204 | | if (!tryParse) |
| | 0 | 3205 | | { |
| | 0 | 3206 | | exc = GetFormatException(); |
| | 0 | 3207 | | } |
| | | 3208 | | |
| | 24 | 3209 | | return false; |
| | | 3210 | | } |
| | | 3211 | | |
| | | 3212 | | // Signed hex value (Two's Complement) |
| | 81 | 3213 | | if (allowHexSpecifier && negative) |
| | 9 | 3214 | | { |
| | 9 | 3215 | | var mask = Pow(16, nDigits) - 1; |
| | 9 | 3216 | | number = (number ^ mask) + 1; |
| | 9 | 3217 | | } |
| | | 3218 | | |
| | 81 | 3219 | | var exponent = 0; |
| | 81 | 3220 | | if (allowExponent) |
| | 12 | 3221 | | { |
| | 12 | 3222 | | if (FindExponent(ref pos, value, ref exponent, tryParse, ref exc) && exc != null) |
| | 3 | 3223 | | { |
| | 3 | 3224 | | return false; |
| | | 3225 | | } |
| | 9 | 3226 | | } |
| | | 3227 | | |
| | 78 | 3228 | | if (allowTrailingSign && !foundSign) |
| | 12 | 3229 | | { |
| | | 3230 | | // Sign + Currency |
| | 12 | 3231 | | FindSign(ref pos, value, nfi, ref foundSign, ref negative); |
| | 12 | 3232 | | if (foundSign && pos < value.Length) |
| | 0 | 3233 | | { |
| | 0 | 3234 | | if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) |
| | 0 | 3235 | | { |
| | 0 | 3236 | | return false; |
| | | 3237 | | } |
| | 0 | 3238 | | } |
| | 12 | 3239 | | } |
| | | 3240 | | |
| | 78 | 3241 | | if (allowCurrencySymbol && !foundCurrency) |
| | 6 | 3242 | | { |
| | 6 | 3243 | | if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, |
| | 0 | 3244 | | { |
| | 0 | 3245 | | return false; |
| | | 3246 | | } |
| | | 3247 | | |
| | | 3248 | | // Currency + sign |
| | 6 | 3249 | | FindCurrency(ref pos, value, nfi, ref foundCurrency); |
| | 6 | 3250 | | if (foundCurrency && pos < value.Length) |
| | 3 | 3251 | | { |
| | 3 | 3252 | | if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) |
| | 0 | 3253 | | { |
| | 0 | 3254 | | return false; |
| | | 3255 | | } |
| | | 3256 | | |
| | 3 | 3257 | | if (!foundSign && allowTrailingSign) |
| | 3 | 3258 | | { |
| | 3 | 3259 | | FindSign(ref pos, value, nfi, ref foundSign, ref negative); |
| | 3 | 3260 | | } |
| | 3 | 3261 | | } |
| | 6 | 3262 | | } |
| | | 3263 | | |
| | 78 | 3264 | | if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, tryP |
| | 0 | 3265 | | { |
| | 0 | 3266 | | return false; |
| | | 3267 | | } |
| | | 3268 | | |
| | 78 | 3269 | | if (foundOpenParentheses) |
| | 6 | 3270 | | { |
| | 6 | 3271 | | if (pos >= value.Length || value[pos++] != ')') |
| | 0 | 3272 | | { |
| | 0 | 3273 | | if (!tryParse) |
| | 0 | 3274 | | { |
| | 0 | 3275 | | exc = GetFormatException(); |
| | 0 | 3276 | | } |
| | | 3277 | | |
| | 0 | 3278 | | return false; |
| | | 3279 | | } |
| | | 3280 | | |
| | 6 | 3281 | | if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, |
| | 0 | 3282 | | { |
| | 0 | 3283 | | return false; |
| | | 3284 | | } |
| | 6 | 3285 | | } |
| | | 3286 | | |
| | 78 | 3287 | | if (pos < value.Length && value[pos] != '\u0000') |
| | 6 | 3288 | | { |
| | 6 | 3289 | | if (!tryParse) |
| | 0 | 3290 | | { |
| | 0 | 3291 | | exc = GetFormatException(); |
| | 0 | 3292 | | } |
| | | 3293 | | |
| | 6 | 3294 | | return false; |
| | | 3295 | | } |
| | | 3296 | | |
| | 72 | 3297 | | if (decimalPointPos >= 0) |
| | 9 | 3298 | | { |
| | 9 | 3299 | | exponent = exponent - nDigits + decimalPointPos; |
| | 9 | 3300 | | } |
| | | 3301 | | |
| | 72 | 3302 | | if (exponent < 0) |
| | 9 | 3303 | | { |
| | | 3304 | | // Any non-zero values after decimal point are not allowed |
| | 9 | 3305 | | number = DivRem(number, Pow(10, -exponent), out var remainder); |
| | | 3306 | | |
| | 9 | 3307 | | if (!remainder.IsZero) |
| | 0 | 3308 | | { |
| | 0 | 3309 | | if (!tryParse) |
| | 0 | 3310 | | { |
| | 0 | 3311 | | exc = new OverflowException(string.Format(CultureInfo.InvariantCulture, |
| | 0 | 3312 | | "Value too large or too small. exp= {0} rem = {1} pow |
| | 0 | 3313 | | exponent, |
| | 0 | 3314 | | remainder, |
| | 0 | 3315 | | Pow(10, -exponent))); |
| | 0 | 3316 | | } |
| | | 3317 | | |
| | 0 | 3318 | | return false; |
| | | 3319 | | } |
| | 9 | 3320 | | } |
| | 63 | 3321 | | else if (exponent > 0) |
| | 6 | 3322 | | { |
| | 6 | 3323 | | number = Pow(10, exponent) * number; |
| | 6 | 3324 | | } |
| | | 3325 | | |
| | 72 | 3326 | | if (number._sign == 0) |
| | 0 | 3327 | | { |
| | 0 | 3328 | | result = number; |
| | 0 | 3329 | | } |
| | 72 | 3330 | | else if (negative) |
| | 24 | 3331 | | { |
| | 24 | 3332 | | result = new BigInteger(-1, number._data); |
| | 24 | 3333 | | } |
| | | 3334 | | else |
| | 48 | 3335 | | { |
| | 48 | 3336 | | result = new BigInteger(1, number._data); |
| | 48 | 3337 | | } |
| | | 3338 | | |
| | 72 | 3339 | | return true; |
| | 108 | 3340 | | } |
| | | 3341 | | |
| | | 3342 | | private static bool CheckStyle(NumberStyles style, bool tryParse, ref Exception exc) |
| | 105 | 3343 | | { |
| | 105 | 3344 | | if ((style & NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier) |
| | 24 | 3345 | | { |
| | 24 | 3346 | | var ne = style ^ NumberStyles.AllowHexSpecifier; |
| | 24 | 3347 | | if ((ne & NumberStyles.AllowLeadingWhite) == NumberStyles.AllowLeadingWhite) |
| | 0 | 3348 | | { |
| | 0 | 3349 | | ne ^= NumberStyles.AllowLeadingWhite; |
| | 0 | 3350 | | } |
| | | 3351 | | |
| | 24 | 3352 | | if ((ne & NumberStyles.AllowTrailingWhite) == NumberStyles.AllowTrailingWhite) |
| | 0 | 3353 | | { |
| | 0 | 3354 | | ne ^= NumberStyles.AllowTrailingWhite; |
| | 0 | 3355 | | } |
| | | 3356 | | |
| | 24 | 3357 | | if (ne != NumberStyles.None) |
| | 0 | 3358 | | { |
| | 0 | 3359 | | if (!tryParse) |
| | 0 | 3360 | | { |
| | 0 | 3361 | | exc = new ArgumentException("With AllowHexSpecifier only " + |
| | 0 | 3362 | | "AllowLeadingWhite and AllowTrailingWhite " + |
| | 0 | 3363 | | "are permitted."); |
| | 0 | 3364 | | } |
| | | 3365 | | |
| | 0 | 3366 | | return false; |
| | | 3367 | | } |
| | 24 | 3368 | | } |
| | 81 | 3369 | | else if ((uint)style > (uint)NumberStyles.Any) |
| | 0 | 3370 | | { |
| | 0 | 3371 | | if (!tryParse) |
| | 0 | 3372 | | { |
| | 0 | 3373 | | exc = new ArgumentException("Not a valid number style"); |
| | 0 | 3374 | | } |
| | | 3375 | | |
| | 0 | 3376 | | return false; |
| | | 3377 | | } |
| | | 3378 | | |
| | 105 | 3379 | | return true; |
| | 105 | 3380 | | } |
| | | 3381 | | |
| | | 3382 | | private static bool JumpOverWhitespace(ref int pos, string s, bool reportError, bool tryParse, ref Exception exc |
| | 48 | 3383 | | { |
| | 96 | 3384 | | while (pos < s.Length && char.IsWhiteSpace(s[pos])) |
| | 48 | 3385 | | { |
| | 48 | 3386 | | pos++; |
| | 48 | 3387 | | } |
| | | 3388 | | |
| | 48 | 3389 | | if (reportError && pos >= s.Length) |
| | 0 | 3390 | | { |
| | 0 | 3391 | | if (!tryParse) |
| | 0 | 3392 | | { |
| | 0 | 3393 | | exc = GetFormatException(); |
| | 0 | 3394 | | } |
| | | 3395 | | |
| | 0 | 3396 | | return false; |
| | | 3397 | | } |
| | | 3398 | | |
| | 48 | 3399 | | return true; |
| | 48 | 3400 | | } |
| | | 3401 | | |
| | | 3402 | | private static void FindSign(ref int pos, string s, NumberFormatInfo nfi, ref bool foundSign, ref bool negative) |
| | 33 | 3403 | | { |
| | 33 | 3404 | | if ((pos + nfi.NegativeSign.Length) <= s.Length && |
| | 33 | 3405 | | string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0) |
| | 9 | 3406 | | { |
| | 9 | 3407 | | negative = true; |
| | 9 | 3408 | | foundSign = true; |
| | 9 | 3409 | | pos += nfi.NegativeSign.Length; |
| | 9 | 3410 | | } |
| | 24 | 3411 | | else if ((pos + nfi.PositiveSign.Length) <= s.Length && |
| | 24 | 3412 | | string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0) |
| | 0 | 3413 | | { |
| | 0 | 3414 | | negative = false; |
| | 0 | 3415 | | pos += nfi.PositiveSign.Length; |
| | 0 | 3416 | | foundSign = true; |
| | 0 | 3417 | | } |
| | 33 | 3418 | | } |
| | | 3419 | | |
| | | 3420 | | private static void FindCurrency(ref int pos, string s, NumberFormatInfo nfi, ref bool foundCurrency) |
| | 18 | 3421 | | { |
| | 18 | 3422 | | if ((pos + nfi.CurrencySymbol.Length) <= s.Length && |
| | 18 | 3423 | | s.Substring(pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) |
| | 9 | 3424 | | { |
| | 9 | 3425 | | foundCurrency = true; |
| | 9 | 3426 | | pos += nfi.CurrencySymbol.Length; |
| | 9 | 3427 | | } |
| | 18 | 3428 | | } |
| | | 3429 | | |
| | | 3430 | | private static bool FindExponent(ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc) |
| | 12 | 3431 | | { |
| | 12 | 3432 | | exponent = 0; |
| | | 3433 | | |
| | 12 | 3434 | | if (pos >= s.Length || (s[pos] != 'e' && s[pos] != 'E')) |
| | 0 | 3435 | | { |
| | 0 | 3436 | | exc = null; |
| | 0 | 3437 | | return false; |
| | | 3438 | | } |
| | | 3439 | | |
| | 12 | 3440 | | var i = pos + 1; |
| | 12 | 3441 | | if (i == s.Length) |
| | 0 | 3442 | | { |
| | 0 | 3443 | | exc = tryParse ? null : GetFormatException(); |
| | 0 | 3444 | | return true; |
| | | 3445 | | } |
| | | 3446 | | |
| | 12 | 3447 | | var negative = false; |
| | 12 | 3448 | | if (s[i] == '-') |
| | 3 | 3449 | | { |
| | 3 | 3450 | | negative = true; |
| | 3 | 3451 | | if (++i == s.Length) |
| | 0 | 3452 | | { |
| | 0 | 3453 | | exc = tryParse ? null : GetFormatException(); |
| | 0 | 3454 | | return true; |
| | | 3455 | | } |
| | 3 | 3456 | | } |
| | | 3457 | | |
| | 12 | 3458 | | if (s[i] == '+' && ++i == s.Length) |
| | 0 | 3459 | | { |
| | 0 | 3460 | | exc = tryParse ? null : GetFormatException(); |
| | 0 | 3461 | | return true; |
| | | 3462 | | } |
| | | 3463 | | |
| | 12 | 3464 | | long exp = 0; // temp long value |
| | 36 | 3465 | | for (; i < s.Length; i++) |
| | 15 | 3466 | | { |
| | 15 | 3467 | | if (!char.IsDigit(s[i])) |
| | 3 | 3468 | | { |
| | 3 | 3469 | | exc = tryParse ? null : GetFormatException(); |
| | 3 | 3470 | | return true; |
| | | 3471 | | } |
| | | 3472 | | |
| | | 3473 | | // Reduce the risk of throwing an overflow exc |
| | 12 | 3474 | | exp = checked((exp * 10) - (s[i] - '0')); |
| | 12 | 3475 | | if (exp is < int.MinValue or > int.MaxValue) |
| | 0 | 3476 | | { |
| | 0 | 3477 | | exc = tryParse ? null : new OverflowException("Value too large or too small."); |
| | 0 | 3478 | | return true; |
| | | 3479 | | } |
| | 12 | 3480 | | } |
| | | 3481 | | |
| | | 3482 | | // exp value saved as negative |
| | 9 | 3483 | | if (!negative) |
| | 6 | 3484 | | { |
| | 6 | 3485 | | exp = -exp; |
| | 6 | 3486 | | } |
| | | 3487 | | |
| | 9 | 3488 | | exc = null; |
| | 9 | 3489 | | exponent = (int) exp; |
| | 9 | 3490 | | pos = i; |
| | 9 | 3491 | | return true; |
| | 12 | 3492 | | } |
| | | 3493 | | |
| | | 3494 | | private static bool FindOther(ref int pos, string s, string other) |
| | 63 | 3495 | | { |
| | 63 | 3496 | | if ((pos + other.Length) <= s.Length && |
| | 63 | 3497 | | s.Substring(pos, other.Length) == other) |
| | 21 | 3498 | | { |
| | 21 | 3499 | | pos += other.Length; |
| | 21 | 3500 | | return true; |
| | | 3501 | | } |
| | | 3502 | | |
| | 42 | 3503 | | return false; |
| | 63 | 3504 | | } |
| | | 3505 | | |
| | | 3506 | | private static bool ValidDigit(char e, bool allowHex) |
| | 11979 | 3507 | | { |
| | 11979 | 3508 | | if (allowHex) |
| | 2349 | 3509 | | { |
| | 2349 | 3510 | | return char.IsDigit(e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f'); |
| | | 3511 | | } |
| | | 3512 | | |
| | 9630 | 3513 | | return char.IsDigit(e); |
| | 11979 | 3514 | | } |
| | | 3515 | | |
| | | 3516 | | private static FormatException GetFormatException() |
| | 18 | 3517 | | { |
| | 18 | 3518 | | return new FormatException("Input string was not in the correct format"); |
| | 18 | 3519 | | } |
| | | 3520 | | |
| | | 3521 | | private static bool ProcessTrailingWhitespace(bool tryParse, string s, int position, ref Exception exc) |
| | 21 | 3522 | | { |
| | 21 | 3523 | | var len = s.Length; |
| | | 3524 | | |
| | 66 | 3525 | | for (var i = position; i < len; i++) |
| | 21 | 3526 | | { |
| | 21 | 3527 | | var c = s[i]; |
| | | 3528 | | |
| | 21 | 3529 | | if (c != 0 && !char.IsWhiteSpace(c)) |
| | 9 | 3530 | | { |
| | 9 | 3531 | | if (!tryParse) |
| | 6 | 3532 | | { |
| | 6 | 3533 | | exc = GetFormatException(); |
| | 6 | 3534 | | } |
| | | 3535 | | |
| | 9 | 3536 | | return false; |
| | | 3537 | | } |
| | 12 | 3538 | | } |
| | | 3539 | | |
| | 12 | 3540 | | return true; |
| | 21 | 3541 | | } |
| | | 3542 | | |
| | | 3543 | | private static bool Parse(string value, bool tryParse, out BigInteger result, out Exception exc) |
| | 81 | 3544 | | { |
| | 81 | 3545 | | int i, sign = 1; |
| | 81 | 3546 | | var digitsSeen = false; |
| | | 3547 | | |
| | 81 | 3548 | | result = Zero; |
| | 81 | 3549 | | exc = null; |
| | | 3550 | | |
| | 81 | 3551 | | if (value is null) |
| | 6 | 3552 | | { |
| | 6 | 3553 | | if (!tryParse) |
| | 3 | 3554 | | { |
| | 3 | 3555 | | exc = new ArgumentNullException(nameof(value)); |
| | 3 | 3556 | | } |
| | | 3557 | | |
| | 6 | 3558 | | return false; |
| | | 3559 | | } |
| | | 3560 | | |
| | 75 | 3561 | | var len = value.Length; |
| | | 3562 | | |
| | | 3563 | | char c; |
| | 228 | 3564 | | for (i = 0; i < len; i++) |
| | 102 | 3565 | | { |
| | 102 | 3566 | | c = value[i]; |
| | 102 | 3567 | | if (!char.IsWhiteSpace(c)) |
| | 63 | 3568 | | { |
| | 63 | 3569 | | break; |
| | | 3570 | | } |
| | 39 | 3571 | | } |
| | | 3572 | | |
| | 75 | 3573 | | if (i == len) |
| | 12 | 3574 | | { |
| | 12 | 3575 | | if (!tryParse) |
| | 6 | 3576 | | { |
| | 6 | 3577 | | exc = GetFormatException(); |
| | 6 | 3578 | | } |
| | | 3579 | | |
| | 12 | 3580 | | return false; |
| | | 3581 | | } |
| | | 3582 | | |
| | 63 | 3583 | | var info = NumberFormatInfo.CurrentInfo; |
| | | 3584 | | |
| | 63 | 3585 | | var negative = info.NegativeSign; |
| | 63 | 3586 | | var positive = info.PositiveSign; |
| | | 3587 | | |
| | 63 | 3588 | | if (string.CompareOrdinal(value, i, positive, 0, positive.Length) == 0) |
| | 12 | 3589 | | { |
| | 12 | 3590 | | i += positive.Length; |
| | 12 | 3591 | | } |
| | 51 | 3592 | | else if (string.CompareOrdinal(value, i, negative, 0, negative.Length) == 0) |
| | 24 | 3593 | | { |
| | 24 | 3594 | | sign = -1; |
| | 24 | 3595 | | i += negative.Length; |
| | 24 | 3596 | | } |
| | | 3597 | | |
| | 63 | 3598 | | var val = Zero; |
| | 1101 | 3599 | | for (; i < len; i++) |
| | 528 | 3600 | | { |
| | 528 | 3601 | | c = value[i]; |
| | | 3602 | | |
| | 528 | 3603 | | if (c == '\0') |
| | 0 | 3604 | | { |
| | 0 | 3605 | | i = len; |
| | 0 | 3606 | | continue; |
| | | 3607 | | } |
| | | 3608 | | |
| | 528 | 3609 | | if (c is >= '0' and <= '9') |
| | 507 | 3610 | | { |
| | 507 | 3611 | | var d = (byte) (c - '0'); |
| | | 3612 | | |
| | 507 | 3613 | | val = (val * 10) + d; |
| | | 3614 | | |
| | 507 | 3615 | | digitsSeen = true; |
| | 507 | 3616 | | } |
| | 21 | 3617 | | else if (!ProcessTrailingWhitespace(tryParse, value, i, ref exc)) |
| | 9 | 3618 | | { |
| | 9 | 3619 | | return false; |
| | | 3620 | | } |
| | 519 | 3621 | | } |
| | | 3622 | | |
| | 54 | 3623 | | if (!digitsSeen) |
| | 9 | 3624 | | { |
| | 9 | 3625 | | if (!tryParse) |
| | 3 | 3626 | | { |
| | 3 | 3627 | | exc = GetFormatException(); |
| | 3 | 3628 | | } |
| | | 3629 | | |
| | 9 | 3630 | | return false; |
| | | 3631 | | } |
| | | 3632 | | |
| | 45 | 3633 | | if (val._sign == 0) |
| | 0 | 3634 | | { |
| | 0 | 3635 | | result = val; |
| | 0 | 3636 | | } |
| | | 3637 | | #pragma warning disable CA1508 // Avoid dead conditional code | this is the following bug in the analyzer rule: https:// |
| | 45 | 3638 | | else if (sign == -1) |
| | | 3639 | | #pragma warning restore CA1508 // Avoid dead conditional code |
| | 15 | 3640 | | { |
| | 15 | 3641 | | result = new BigInteger(-1, val._data); |
| | 15 | 3642 | | } |
| | | 3643 | | else |
| | 30 | 3644 | | { |
| | 30 | 3645 | | result = new BigInteger(1, val._data); |
| | 30 | 3646 | | } |
| | | 3647 | | |
| | 45 | 3648 | | return true; |
| | 81 | 3649 | | } |
| | | 3650 | | |
| | | 3651 | | /// <summary> |
| | | 3652 | | /// Returns the smaller of two <see cref="BigInteger"/> values. |
| | | 3653 | | /// </summary> |
| | | 3654 | | /// <param name="left">The first value to compare.</param> |
| | | 3655 | | /// <param name="right">The second value to compare.</param> |
| | | 3656 | | /// <returns> |
| | | 3657 | | /// The <paramref name="left"/> or <paramref name="right"/> parameter, whichever is smaller. |
| | | 3658 | | /// </returns> |
| | | 3659 | | public static BigInteger Min(BigInteger left, BigInteger right) |
| | 150 | 3660 | | { |
| | 150 | 3661 | | int ls = left._sign; |
| | 150 | 3662 | | int rs = right._sign; |
| | | 3663 | | |
| | 150 | 3664 | | if (ls < rs) |
| | 45 | 3665 | | { |
| | 45 | 3666 | | return left; |
| | | 3667 | | } |
| | | 3668 | | |
| | 105 | 3669 | | if (rs < ls) |
| | 45 | 3670 | | { |
| | 45 | 3671 | | return right; |
| | | 3672 | | } |
| | | 3673 | | |
| | 60 | 3674 | | var r = CoreCompare(left._data, right._data); |
| | 60 | 3675 | | if (ls == -1) |
| | 27 | 3676 | | { |
| | 27 | 3677 | | r = -r; |
| | 27 | 3678 | | } |
| | | 3679 | | |
| | 60 | 3680 | | if (r <= 0) |
| | 42 | 3681 | | { |
| | 42 | 3682 | | return left; |
| | | 3683 | | } |
| | | 3684 | | |
| | 18 | 3685 | | return right; |
| | 150 | 3686 | | } |
| | | 3687 | | |
| | | 3688 | | /// <summary> |
| | | 3689 | | /// Returns the larger of two <see cref="BigInteger"/> values. |
| | | 3690 | | /// </summary> |
| | | 3691 | | /// <param name="left">The first value to compare.</param> |
| | | 3692 | | /// <param name="right">The second value to compare.</param> |
| | | 3693 | | /// <returns> |
| | | 3694 | | /// The <paramref name="left"/> or <paramref name="right"/> parameter, whichever is larger. |
| | | 3695 | | /// </returns> |
| | | 3696 | | public static BigInteger Max(BigInteger left, BigInteger right) |
| | 147 | 3697 | | { |
| | 147 | 3698 | | int ls = left._sign; |
| | 147 | 3699 | | int rs = right._sign; |
| | | 3700 | | |
| | 147 | 3701 | | if (ls > rs) |
| | 45 | 3702 | | { |
| | 45 | 3703 | | return left; |
| | | 3704 | | } |
| | | 3705 | | |
| | 102 | 3706 | | if (rs > ls) |
| | 45 | 3707 | | { |
| | 45 | 3708 | | return right; |
| | | 3709 | | } |
| | | 3710 | | |
| | 57 | 3711 | | var r = CoreCompare(left._data, right._data); |
| | 57 | 3712 | | if (ls == -1) |
| | 27 | 3713 | | { |
| | 27 | 3714 | | r = -r; |
| | 27 | 3715 | | } |
| | | 3716 | | |
| | 57 | 3717 | | if (r >= 0) |
| | 39 | 3718 | | { |
| | 39 | 3719 | | return left; |
| | | 3720 | | } |
| | | 3721 | | |
| | 18 | 3722 | | return right; |
| | 147 | 3723 | | } |
| | | 3724 | | |
| | | 3725 | | /// <summary> |
| | | 3726 | | /// Gets the absolute value of a <see cref="BigInteger"/> object. |
| | | 3727 | | /// </summary> |
| | | 3728 | | /// <param name="value">A number.</param> |
| | | 3729 | | /// <returns> |
| | | 3730 | | /// The absolute value of <paramref name="value"/>. |
| | | 3731 | | /// </returns> |
| | | 3732 | | public static BigInteger Abs(BigInteger value) |
| | 36 | 3733 | | { |
| | 36 | 3734 | | return new BigInteger(Math.Abs(value._sign), value._data); |
| | 36 | 3735 | | } |
| | | 3736 | | |
| | | 3737 | | /// <summary> |
| | | 3738 | | /// Divides one <see cref="BigInteger"/> value by another, returns the result, and returns the remainder in |
| | | 3739 | | /// an output parameter. |
| | | 3740 | | /// </summary> |
| | | 3741 | | /// <param name="dividend">The value to be divided.</param> |
| | | 3742 | | /// <param name="divisor">The value to divide by.</param> |
| | | 3743 | | /// <param name="remainder">When this method returns, contains a <see cref="BigInteger"/> value that represents |
| | | 3744 | | /// <returns> |
| | | 3745 | | /// The quotient of the division. |
| | | 3746 | | /// </returns> |
| | | 3747 | | public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder) |
| | 18354 | 3748 | | { |
| | 18354 | 3749 | | if (divisor._sign == 0) |
| | 3 | 3750 | | { |
| | 3 | 3751 | | throw new DivideByZeroException(); |
| | | 3752 | | } |
| | | 3753 | | |
| | 18351 | 3754 | | if (dividend._sign == 0) |
| | 21 | 3755 | | { |
| | 21 | 3756 | | remainder = dividend; |
| | 21 | 3757 | | return dividend; |
| | | 3758 | | } |
| | | 3759 | | |
| | 18330 | 3760 | | DivModUnsigned(dividend._data, divisor._data, out var quotient, out var remainderValue); |
| | | 3761 | | |
| | | 3762 | | int i; |
| | 41166 | 3763 | | for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) |
| | 2253 | 3764 | | { |
| | | 3765 | | // Intentionally empty block |
| | 2253 | 3766 | | } |
| | | 3767 | | |
| | 18330 | 3768 | | if (i == -1) |
| | 2232 | 3769 | | { |
| | 2232 | 3770 | | remainder = Zero; |
| | 2232 | 3771 | | } |
| | | 3772 | | else |
| | 16098 | 3773 | | { |
| | 16098 | 3774 | | if (i < remainderValue.Length - 1) |
| | 6 | 3775 | | { |
| | 6 | 3776 | | Array.Resize(ref remainderValue, i + 1); |
| | 6 | 3777 | | } |
| | | 3778 | | |
| | 16098 | 3779 | | remainder = new BigInteger(dividend._sign, remainderValue); |
| | 16098 | 3780 | | } |
| | | 3781 | | |
| | 41112 | 3782 | | for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) |
| | 2226 | 3783 | | { |
| | | 3784 | | // Intentionally empty block |
| | 2226 | 3785 | | } |
| | | 3786 | | |
| | 18330 | 3787 | | if (i == -1) |
| | 573 | 3788 | | { |
| | 573 | 3789 | | return Zero; |
| | | 3790 | | } |
| | | 3791 | | |
| | 17757 | 3792 | | if (i < quotient.Length - 1) |
| | 1653 | 3793 | | { |
| | 1653 | 3794 | | Array.Resize(ref quotient, i + 1); |
| | 1653 | 3795 | | } |
| | | 3796 | | |
| | 17757 | 3797 | | return new BigInteger((short)(dividend._sign * divisor._sign), quotient); |
| | 18351 | 3798 | | } |
| | | 3799 | | |
| | | 3800 | | /// <summary> |
| | | 3801 | | /// Raises a <see cref="BigInteger"/> value to the power of a specified value. |
| | | 3802 | | /// </summary> |
| | | 3803 | | /// <param name="value">The number to raise to the <paramref name="exponent"/> power.</param> |
| | | 3804 | | /// <param name="exponent">The exponent to raise <paramref name="value"/> by.</param> |
| | | 3805 | | /// <returns> |
| | | 3806 | | /// The result of raising <paramref name="value"/> to the <paramref name="exponent"/> power. |
| | | 3807 | | /// </returns> |
| | | 3808 | | public static BigInteger Pow(BigInteger value, int exponent) |
| | 75 | 3809 | | { |
| | 75 | 3810 | | if (exponent < 0) |
| | 3 | 3811 | | { |
| | 3 | 3812 | | throw new ArgumentOutOfRangeException(nameof(exponent), "exp must be >= 0"); |
| | | 3813 | | } |
| | | 3814 | | |
| | 72 | 3815 | | if (exponent == 0) |
| | 3 | 3816 | | { |
| | 3 | 3817 | | return One; |
| | | 3818 | | } |
| | | 3819 | | |
| | 69 | 3820 | | if (exponent == 1) |
| | 12 | 3821 | | { |
| | 12 | 3822 | | return value; |
| | | 3823 | | } |
| | | 3824 | | |
| | 57 | 3825 | | var result = One; |
| | 351 | 3826 | | while (exponent != 0) |
| | 351 | 3827 | | { |
| | 351 | 3828 | | if ((exponent & 1) != 0) |
| | 159 | 3829 | | { |
| | 159 | 3830 | | result *= value; |
| | 159 | 3831 | | } |
| | | 3832 | | |
| | 351 | 3833 | | if (exponent == 1) |
| | 57 | 3834 | | { |
| | 57 | 3835 | | break; |
| | | 3836 | | } |
| | | 3837 | | |
| | 294 | 3838 | | value *= value; |
| | 294 | 3839 | | exponent >>= 1; |
| | 294 | 3840 | | } |
| | | 3841 | | |
| | 57 | 3842 | | return result; |
| | 72 | 3843 | | } |
| | | 3844 | | |
| | | 3845 | | /// <summary> |
| | | 3846 | | /// Performs modulus division on a number raised to the power of another number. |
| | | 3847 | | /// </summary> |
| | | 3848 | | /// <param name="value">The number to raise to the <paramref name="exponent"/> power.</param> |
| | | 3849 | | /// <param name="exponent">The exponent to raise <paramref name="value"/> by.</param> |
| | | 3850 | | /// <param name="modulus">The number by which to divide <paramref name="value"/> raised to the <paramref name="e |
| | | 3851 | | /// <returns> |
| | | 3852 | | /// The remainder after dividing <paramref name="value"/> raised by <paramref name="exponent"/> by |
| | | 3853 | | /// <paramref name="modulus"/>. |
| | | 3854 | | /// </returns> |
| | | 3855 | | /// <exception cref="ArgumentOutOfRangeException"><paramref name="exponent"/> is negative.</exception> |
| | | 3856 | | public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus) |
| | 3359 | 3857 | | { |
| | 3359 | 3858 | | if (exponent._sign == -1) |
| | 3 | 3859 | | { |
| | 3 | 3860 | | throw new ArgumentOutOfRangeException(nameof(exponent), "power must be >= 0"); |
| | | 3861 | | } |
| | | 3862 | | |
| | 3356 | 3863 | | if (modulus._sign == 0) |
| | 3 | 3864 | | { |
| | 3 | 3865 | | throw new DivideByZeroException(); |
| | | 3866 | | } |
| | | 3867 | | |
| | 3353 | 3868 | | var result = One % modulus; |
| | 1484456 | 3869 | | while (exponent._sign != 0) |
| | 1484456 | 3870 | | { |
| | 1484456 | 3871 | | if (!exponent.IsEven) |
| | 757924 | 3872 | | { |
| | 757924 | 3873 | | result *= value; |
| | 757924 | 3874 | | result %= modulus; |
| | 757924 | 3875 | | } |
| | | 3876 | | |
| | 1484456 | 3877 | | if (exponent.IsOne) |
| | 3353 | 3878 | | { |
| | 3353 | 3879 | | break; |
| | | 3880 | | } |
| | | 3881 | | |
| | 1481103 | 3882 | | value *= value; |
| | 1481103 | 3883 | | value %= modulus; |
| | 1481103 | 3884 | | exponent >>= 1; |
| | 1481103 | 3885 | | } |
| | | 3886 | | |
| | 3353 | 3887 | | return result; |
| | 3353 | 3888 | | } |
| | | 3889 | | |
| | | 3890 | | /// <summary> |
| | | 3891 | | /// Finds the greatest common divisor of two <see cref="BigInteger"/> values. |
| | | 3892 | | /// </summary> |
| | | 3893 | | /// <param name="left">The first value.</param> |
| | | 3894 | | /// <param name="right">The second value.</param> |
| | | 3895 | | /// <returns> |
| | | 3896 | | /// The greatest common divisor of <paramref name="left"/> and <paramref name="right"/>. |
| | | 3897 | | /// </returns> |
| | | 3898 | | public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right) |
| | 54 | 3899 | | { |
| | 54 | 3900 | | if (left._sign != 0 && left._data.Length == 1 && left._data[0] == 1) |
| | 12 | 3901 | | { |
| | 12 | 3902 | | return One; |
| | | 3903 | | } |
| | | 3904 | | |
| | 42 | 3905 | | if (right._sign != 0 && right._data.Length == 1 && right._data[0] == 1) |
| | 12 | 3906 | | { |
| | 12 | 3907 | | return One; |
| | | 3908 | | } |
| | | 3909 | | |
| | 30 | 3910 | | if (left.IsZero) |
| | 9 | 3911 | | { |
| | 9 | 3912 | | return Abs(right); |
| | | 3913 | | } |
| | | 3914 | | |
| | 21 | 3915 | | if (right.IsZero) |
| | 6 | 3916 | | { |
| | 6 | 3917 | | return Abs(left); |
| | | 3918 | | } |
| | | 3919 | | |
| | 15 | 3920 | | var x = new BigInteger(1, left._data); |
| | 15 | 3921 | | var y = new BigInteger(1, right._data); |
| | | 3922 | | |
| | 15 | 3923 | | var g = y; |
| | | 3924 | | |
| | 15 | 3925 | | while (x._data.Length > 1) |
| | 0 | 3926 | | { |
| | 0 | 3927 | | g = x; |
| | 0 | 3928 | | x = y % x; |
| | 0 | 3929 | | y = g; |
| | 0 | 3930 | | } |
| | | 3931 | | |
| | 15 | 3932 | | if (x.IsZero) |
| | 0 | 3933 | | { |
| | 0 | 3934 | | return g; |
| | | 3935 | | } |
| | | 3936 | | |
| | | 3937 | | // TODO: should we have something here if we can convert to long? |
| | | 3938 | | |
| | | 3939 | | /* |
| | | 3940 | | * Now we can just do it with single precision. I am using the binary gcd method, |
| | | 3941 | | * as it should be faster. |
| | | 3942 | | */ |
| | | 3943 | | |
| | 15 | 3944 | | var yy = x._data[0]; |
| | 15 | 3945 | | var xx = (uint)(y % yy); |
| | | 3946 | | |
| | 15 | 3947 | | var t = 0; |
| | | 3948 | | |
| | 36 | 3949 | | while (((xx | yy) & 1) == 0) |
| | 21 | 3950 | | { |
| | 21 | 3951 | | xx >>= 1; |
| | 21 | 3952 | | yy >>= 1; |
| | 21 | 3953 | | t++; |
| | 21 | 3954 | | } |
| | | 3955 | | |
| | 216 | 3956 | | while (xx != 0) |
| | 201 | 3957 | | { |
| | 342 | 3958 | | while ((xx & 1) == 0) |
| | 141 | 3959 | | { |
| | 141 | 3960 | | xx >>= 1; |
| | 141 | 3961 | | } |
| | | 3962 | | |
| | 351 | 3963 | | while ((yy & 1) == 0) |
| | 150 | 3964 | | { |
| | 150 | 3965 | | yy >>= 1; |
| | 150 | 3966 | | } |
| | | 3967 | | |
| | 201 | 3968 | | if (xx >= yy) |
| | 96 | 3969 | | { |
| | 96 | 3970 | | xx = (xx - yy) >> 1; |
| | 96 | 3971 | | } |
| | | 3972 | | else |
| | 105 | 3973 | | { |
| | 105 | 3974 | | yy = (yy - xx) >> 1; |
| | 105 | 3975 | | } |
| | 201 | 3976 | | } |
| | | 3977 | | |
| | 15 | 3978 | | return yy << t; |
| | 54 | 3979 | | } |
| | | 3980 | | |
| | | 3981 | | /* |
| | | 3982 | | * LAMESPEC Log doesn't specify to how many ulp is has to be precise |
| | | 3983 | | * We are equilavent to MS with about 2 ULP |
| | | 3984 | | */ |
| | | 3985 | | |
| | | 3986 | | /// <summary> |
| | | 3987 | | /// Returns the logarithm of a specified number in a specified base. |
| | | 3988 | | /// </summary> |
| | | 3989 | | /// <param name="value">A number whose logarithm is to be found.</param> |
| | | 3990 | | /// <param name="baseValue">The base of the logarithm.</param> |
| | | 3991 | | /// <returns> |
| | | 3992 | | /// The base <paramref name="baseValue"/> logarithm of value. |
| | | 3993 | | /// </returns> |
| | | 3994 | | /// <exception cref="ArgumentOutOfRangeException">The log of <paramref name="value"/> is out of range of the <se |
| | | 3995 | | public static double Log(BigInteger value, double baseValue) |
| | 51 | 3996 | | { |
| | 51 | 3997 | | if (value._sign == -1 || baseValue == 1.0d || baseValue == -1.0d || |
| | 51 | 3998 | | baseValue == double.NegativeInfinity || double.IsNaN(baseValue)) |
| | 24 | 3999 | | { |
| | 24 | 4000 | | return double.NaN; |
| | | 4001 | | } |
| | | 4002 | | |
| | 27 | 4003 | | if (baseValue is 0.0d or double.PositiveInfinity) |
| | 12 | 4004 | | { |
| | 12 | 4005 | | return value.IsOne ? 0 : double.NaN; |
| | | 4006 | | } |
| | | 4007 | | |
| | 15 | 4008 | | if (value._data is null) |
| | 3 | 4009 | | { |
| | 3 | 4010 | | return double.NegativeInfinity; |
| | | 4011 | | } |
| | | 4012 | | |
| | 12 | 4013 | | var length = value._data.Length - 1; |
| | 12 | 4014 | | var bitCount = -1; |
| | 678 | 4015 | | for (var curBit = 31; curBit >= 0; curBit--) |
| | 339 | 4016 | | { |
| | 339 | 4017 | | if ((value._data[length] & (1 << curBit)) != 0) |
| | 12 | 4018 | | { |
| | 12 | 4019 | | bitCount = curBit + (length * 32); |
| | 12 | 4020 | | break; |
| | | 4021 | | } |
| | 327 | 4022 | | } |
| | | 4023 | | |
| | 12 | 4024 | | long bitlen = bitCount; |
| | 24 | 4025 | | double c = 0, d = 1; |
| | | 4026 | | |
| | 12 | 4027 | | var testBit = One; |
| | 12 | 4028 | | var tempBitlen = bitlen; |
| | 12 | 4029 | | while (tempBitlen > int.MaxValue) |
| | 0 | 4030 | | { |
| | 0 | 4031 | | testBit <<= int.MaxValue; |
| | 0 | 4032 | | tempBitlen -= int.MaxValue; |
| | 0 | 4033 | | } |
| | | 4034 | | |
| | 12 | 4035 | | testBit <<= (int)tempBitlen; |
| | | 4036 | | |
| | 138 | 4037 | | for (var curbit = bitlen; curbit >= 0; --curbit) |
| | 57 | 4038 | | { |
| | 57 | 4039 | | if ((value & testBit)._sign != 0) |
| | 33 | 4040 | | { |
| | 33 | 4041 | | c += d; |
| | 33 | 4042 | | } |
| | | 4043 | | |
| | 57 | 4044 | | d *= 0.5; |
| | 57 | 4045 | | testBit >>= 1; |
| | 57 | 4046 | | } |
| | | 4047 | | |
| | 12 | 4048 | | return (Math.Log(c) + (Math.Log(2) * bitlen)) / Math.Log(baseValue); |
| | 51 | 4049 | | } |
| | | 4050 | | |
| | | 4051 | | /// <summary> |
| | | 4052 | | /// Returns the natural (base <c>e</c>) logarithm of a specified number. |
| | | 4053 | | /// </summary> |
| | | 4054 | | /// <param name="value">The number whose logarithm is to be found.</param> |
| | | 4055 | | /// <returns> |
| | | 4056 | | /// The natural (base <c>e</c>) logarithm of <paramref name="value"/>. |
| | | 4057 | | /// </returns> |
| | | 4058 | | /// <exception cref="ArgumentOutOfRangeException">The base 10 log of value is out of range of the <see cref="dou |
| | | 4059 | | public static double Log(BigInteger value) |
| | 18 | 4060 | | { |
| | 18 | 4061 | | return Log(value, Math.E); |
| | 18 | 4062 | | } |
| | | 4063 | | |
| | | 4064 | | /// <summary> |
| | | 4065 | | /// Returns the base 10 logarithm of a specified number. |
| | | 4066 | | /// </summary> |
| | | 4067 | | /// <param name="value">A number whose logarithm is to be found.</param> |
| | | 4068 | | /// <returns> |
| | | 4069 | | /// The base 10 logarithm of <paramref name="value"/>. |
| | | 4070 | | /// </returns> |
| | | 4071 | | /// <exception cref="ArgumentOutOfRangeException">The base 10 log of value is out of range of the <see cref="dou |
| | | 4072 | | public static double Log10(BigInteger value) |
| | 0 | 4073 | | { |
| | 0 | 4074 | | return Log(value, 10); |
| | 0 | 4075 | | } |
| | | 4076 | | |
| | | 4077 | | /// <summary> |
| | | 4078 | | /// Returns the hash code for the current <see cref="BigInteger"/> object. |
| | | 4079 | | /// </summary> |
| | | 4080 | | /// <returns> |
| | | 4081 | | /// A 32-bit signed integer hash code. |
| | | 4082 | | /// </returns> |
| | | 4083 | | public override readonly int GetHashCode() |
| | 6 | 4084 | | { |
| | 6 | 4085 | | var hash = (uint) (_sign * 0x01010101u); |
| | 6 | 4086 | | if (_data != null) |
| | 0 | 4087 | | { |
| | 0 | 4088 | | foreach (var bit in _data) |
| | 0 | 4089 | | { |
| | 0 | 4090 | | hash ^= bit; |
| | 0 | 4091 | | } |
| | 0 | 4092 | | } |
| | | 4093 | | |
| | 6 | 4094 | | return (int) hash; |
| | 6 | 4095 | | } |
| | | 4096 | | |
| | | 4097 | | /// <summary> |
| | | 4098 | | /// Adds two <see cref="BigInteger"/> values and returns the result. |
| | | 4099 | | /// </summary> |
| | | 4100 | | /// <param name="left">The first value to add.</param> |
| | | 4101 | | /// <param name="right">The second value to add.</param> |
| | | 4102 | | /// <returns> |
| | | 4103 | | /// The sum of <paramref name="left"/> and <paramref name="right"/>. |
| | | 4104 | | /// </returns> |
| | | 4105 | | public static BigInteger Add(BigInteger left, BigInteger right) |
| | 9 | 4106 | | { |
| | 9 | 4107 | | return left + right; |
| | 9 | 4108 | | } |
| | | 4109 | | |
| | | 4110 | | /// <summary> |
| | | 4111 | | /// Subtracts one <see cref="BigInteger"/> value from another and returns the result. |
| | | 4112 | | /// </summary> |
| | | 4113 | | /// <param name="left">The value to subtract from (the minuend).</param> |
| | | 4114 | | /// <param name="right">The value to subtract (the subtrahend).</param> |
| | | 4115 | | /// <returns> |
| | | 4116 | | /// The result of subtracting <paramref name="right"/> from <paramref name="left"/>. |
| | | 4117 | | /// </returns> |
| | | 4118 | | public static BigInteger Subtract(BigInteger left, BigInteger right) |
| | 147 | 4119 | | { |
| | 147 | 4120 | | return left - right; |
| | 147 | 4121 | | } |
| | | 4122 | | |
| | | 4123 | | /// <summary> |
| | | 4124 | | /// Returns the product of two <see cref="BigInteger"/> values. |
| | | 4125 | | /// </summary> |
| | | 4126 | | /// <param name="left">The first number to multiply.</param> |
| | | 4127 | | /// <param name="right">The second number to multiply.</param> |
| | | 4128 | | /// <returns> |
| | | 4129 | | /// The product of the <paramref name="left"/> and <paramref name="right"/> parameters. |
| | | 4130 | | /// </returns> |
| | | 4131 | | public static BigInteger Multiply(BigInteger left, BigInteger right) |
| | 0 | 4132 | | { |
| | 0 | 4133 | | return left * right; |
| | 0 | 4134 | | } |
| | | 4135 | | |
| | | 4136 | | /// <summary> |
| | | 4137 | | /// Divides one <see cref="BigInteger"/> value by another and returns the result. |
| | | 4138 | | /// </summary> |
| | | 4139 | | /// <param name="dividend">The value to be divided.</param> |
| | | 4140 | | /// <param name="divisor">The value to divide by.</param> |
| | | 4141 | | /// <returns> |
| | | 4142 | | /// The quotient of the division. |
| | | 4143 | | /// </returns> |
| | | 4144 | | public static BigInteger Divide(BigInteger dividend, BigInteger divisor) |
| | 0 | 4145 | | { |
| | 0 | 4146 | | return dividend / divisor; |
| | 0 | 4147 | | } |
| | | 4148 | | |
| | | 4149 | | /// <summary> |
| | | 4150 | | /// Performs integer division on two <see cref="BigInteger"/> values and returns the remainder. |
| | | 4151 | | /// </summary> |
| | | 4152 | | /// <param name="dividend">The value to be divided.</param> |
| | | 4153 | | /// <param name="divisor">The value to divide by.</param> |
| | | 4154 | | /// <returns> |
| | | 4155 | | /// The remainder after dividing <paramref name="dividend"/> by <paramref name="divisor"/>. |
| | | 4156 | | /// </returns> |
| | | 4157 | | public static BigInteger Remainder(BigInteger dividend, BigInteger divisor) |
| | 0 | 4158 | | { |
| | 0 | 4159 | | return dividend % divisor; |
| | 0 | 4160 | | } |
| | | 4161 | | |
| | | 4162 | | /// <summary> |
| | | 4163 | | /// Negates a specified <see cref="BigInteger"/> value. |
| | | 4164 | | /// </summary> |
| | | 4165 | | /// <param name="value">The value to negate.</param> |
| | | 4166 | | /// <returns> |
| | | 4167 | | /// The result of the <paramref name="value"/> parameter multiplied by negative one (-1). |
| | | 4168 | | /// </returns> |
| | | 4169 | | public static BigInteger Negate(BigInteger value) |
| | 21 | 4170 | | { |
| | 21 | 4171 | | return -value; |
| | 21 | 4172 | | } |
| | | 4173 | | |
| | | 4174 | | /// <summary> |
| | | 4175 | | /// Compares this instance to a specified object and returns an integer that indicates whether the value of |
| | | 4176 | | /// this instance is less than, equal to, or greater than the value of the specified object. |
| | | 4177 | | /// </summary> |
| | | 4178 | | /// <param name="obj">The object to compare.</param> |
| | | 4179 | | /// <returns> |
| | | 4180 | | /// A signed integer that indicates the relationship of the current instance to the <paramref name="obj"/> param |
| | | 4181 | | /// as shown in the following table. |
| | | 4182 | | /// <list type="table"> |
| | | 4183 | | /// <listheader> |
| | | 4184 | | /// <term>Value</term> |
| | | 4185 | | /// <description>Condition</description> |
| | | 4186 | | /// </listheader> |
| | | 4187 | | /// <item> |
| | | 4188 | | /// <term>Less than zero</term> |
| | | 4189 | | /// <description>The current instance is less than <paramref name="obj"/>.</description> |
| | | 4190 | | /// </item> |
| | | 4191 | | /// <item> |
| | | 4192 | | /// <term>Zero</term> |
| | | 4193 | | /// <description>The current instance equals <paramref name="obj"/>.</description> |
| | | 4194 | | /// </item> |
| | | 4195 | | /// <item> |
| | | 4196 | | /// <term>Greater than zero</term> |
| | | 4197 | | /// <description>The current instance is greater than <paramref name="obj"/>.</description> |
| | | 4198 | | /// </item> |
| | | 4199 | | /// </list> |
| | | 4200 | | /// </returns> |
| | | 4201 | | /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="BigInteger"/>.</exception> |
| | | 4202 | | public readonly int CompareTo(object obj) |
| | 3 | 4203 | | { |
| | 3 | 4204 | | if (obj is null) |
| | 3 | 4205 | | { |
| | 3 | 4206 | | return 1; |
| | | 4207 | | } |
| | | 4208 | | |
| | 0 | 4209 | | if (obj is not BigInteger other) |
| | 0 | 4210 | | { |
| | 0 | 4211 | | return -1; |
| | | 4212 | | } |
| | | 4213 | | |
| | 0 | 4214 | | return Compare(this, other); |
| | 3 | 4215 | | } |
| | | 4216 | | |
| | | 4217 | | /// <summary> |
| | | 4218 | | /// Compares this instance to a second <see cref="BigInteger"/> and returns an integer that indicates whether th |
| | | 4219 | | /// value of this instance is less than, equal to, or greater than the value of the specified object. |
| | | 4220 | | /// </summary> |
| | | 4221 | | /// <param name="other">The object to compare.</param> |
| | | 4222 | | /// <returns> |
| | | 4223 | | /// A signed integer value that indicates the relationship of this instance to <paramref name="other"/>, as |
| | | 4224 | | /// shown in the following table. |
| | | 4225 | | /// <list type="table"> |
| | | 4226 | | /// <listheader> |
| | | 4227 | | /// <term>Value</term> |
| | | 4228 | | /// <description>Condition</description> |
| | | 4229 | | /// </listheader> |
| | | 4230 | | /// <item> |
| | | 4231 | | /// <term>Less than zero</term> |
| | | 4232 | | /// <description>The current instance is less than <paramref name="other"/>.</description> |
| | | 4233 | | /// </item> |
| | | 4234 | | /// <item> |
| | | 4235 | | /// <term>Zero</term> |
| | | 4236 | | /// <description>The current instance equals <paramref name="other"/>.</description> |
| | | 4237 | | /// </item> |
| | | 4238 | | /// <item> |
| | | 4239 | | /// <term>Greater than zero</term> |
| | | 4240 | | /// <description>The current instance is greater than <paramref name="other"/>.</description> |
| | | 4241 | | /// </item> |
| | | 4242 | | /// </list> |
| | | 4243 | | /// </returns> |
| | | 4244 | | public readonly int CompareTo(BigInteger other) |
| | 705 | 4245 | | { |
| | 705 | 4246 | | return Compare(this, other); |
| | 705 | 4247 | | } |
| | | 4248 | | |
| | | 4249 | | /// <summary> |
| | | 4250 | | /// Compares this instance to an unsigned 64-bit integer and returns an integer that indicates whether the value |
| | | 4251 | | /// instance is less than, equal to, or greater than the value of the unsigned 64-bit integer. |
| | | 4252 | | /// </summary> |
| | | 4253 | | /// <param name="other">The unsigned 64-bit integer to compare.</param> |
| | | 4254 | | /// <returns> |
| | | 4255 | | /// A signed integer that indicates the relative value of this instance and <paramref name="other"/>, as shown |
| | | 4256 | | /// in the following table. |
| | | 4257 | | /// <list type="table"> |
| | | 4258 | | /// <listheader> |
| | | 4259 | | /// <term>Value</term> |
| | | 4260 | | /// <description>Condition</description> |
| | | 4261 | | /// </listheader> |
| | | 4262 | | /// <item> |
| | | 4263 | | /// <term>Less than zero</term> |
| | | 4264 | | /// <description>The current instance is less than <paramref name="other"/>.</description> |
| | | 4265 | | /// </item> |
| | | 4266 | | /// <item> |
| | | 4267 | | /// <term>Zero</term> |
| | | 4268 | | /// <description>The current instance equals <paramref name="other"/>.</description> |
| | | 4269 | | /// </item> |
| | | 4270 | | /// <item> |
| | | 4271 | | /// <term>Greater than zero</term> |
| | | 4272 | | /// <description>The current instance is greater than <paramref name="other"/>.</description> |
| | | 4273 | | /// </item> |
| | | 4274 | | /// </list> |
| | | 4275 | | /// </returns> |
| | | 4276 | | [CLSCompliant(false)] |
| | | 4277 | | public readonly int CompareTo(ulong other) |
| | 2496 | 4278 | | { |
| | 2496 | 4279 | | if (_sign < 0) |
| | 936 | 4280 | | { |
| | 936 | 4281 | | return -1; |
| | | 4282 | | } |
| | | 4283 | | |
| | 1560 | 4284 | | if (_sign == 0) |
| | 312 | 4285 | | { |
| | 312 | 4286 | | return other == 0 ? 0 : -1; |
| | | 4287 | | } |
| | | 4288 | | |
| | 1248 | 4289 | | if (_data.Length > 2) |
| | 0 | 4290 | | { |
| | 0 | 4291 | | return 1; |
| | | 4292 | | } |
| | | 4293 | | |
| | 1248 | 4294 | | var high = (uint)(other >> 32); |
| | 1248 | 4295 | | var low = (uint)other; |
| | | 4296 | | |
| | 1248 | 4297 | | return LongCompare(low, high); |
| | 2496 | 4298 | | } |
| | | 4299 | | |
| | | 4300 | | /// <summary> |
| | | 4301 | | /// Compares this instance to a signed 64-bit integer and returns an integer that indicates whether the value of |
| | | 4302 | | /// instance is less than, equal to, or greater than the value of the signed 64-bit integer. |
| | | 4303 | | /// </summary> |
| | | 4304 | | /// <param name="other">The signed 64-bit integer to compare.</param> |
| | | 4305 | | /// <returns> |
| | | 4306 | | /// A signed integer that indicates the relative value of this instance and <paramref name="other"/>, as shown |
| | | 4307 | | /// in the following table. |
| | | 4308 | | /// <list type="table"> |
| | | 4309 | | /// <listheader> |
| | | 4310 | | /// <term>Value</term> |
| | | 4311 | | /// <description>Condition</description> |
| | | 4312 | | /// </listheader> |
| | | 4313 | | /// <item> |
| | | 4314 | | /// <term>Less than zero</term> |
| | | 4315 | | /// <description>The current instance is less than <paramref name="other"/>.</description> |
| | | 4316 | | /// </item> |
| | | 4317 | | /// <item> |
| | | 4318 | | /// <term>Zero</term> |
| | | 4319 | | /// <description>The current instance equals <paramref name="other"/>.</description> |
| | | 4320 | | /// </item> |
| | | 4321 | | /// <item> |
| | | 4322 | | /// <term>Greater than zero</term> |
| | | 4323 | | /// <description>The current instance is greater than <paramref name="other"/>.</description> |
| | | 4324 | | /// </item> |
| | | 4325 | | /// </list> |
| | | 4326 | | /// </returns> |
| | | 4327 | | public readonly int CompareTo(long other) |
| | 25541 | 4328 | | { |
| | 25541 | 4329 | | int ls = _sign; |
| | 25541 | 4330 | | var rs = Math.Sign(other); |
| | | 4331 | | |
| | 25541 | 4332 | | if (ls != rs) |
| | 22927 | 4333 | | { |
| | 22927 | 4334 | | return ls > rs ? 1 : -1; |
| | | 4335 | | } |
| | | 4336 | | |
| | 2614 | 4337 | | if (ls == 0) |
| | 550 | 4338 | | { |
| | 550 | 4339 | | return 0; |
| | | 4340 | | } |
| | | 4341 | | |
| | 2064 | 4342 | | if (_data.Length > 2) |
| | 27 | 4343 | | { |
| | 27 | 4344 | | return _sign; |
| | | 4345 | | } |
| | | 4346 | | |
| | 2037 | 4347 | | if (other < 0) |
| | 627 | 4348 | | { |
| | 627 | 4349 | | other = -other; |
| | 627 | 4350 | | } |
| | | 4351 | | |
| | 2037 | 4352 | | var low = (uint) other; |
| | 2037 | 4353 | | var high = (uint) ((ulong) other >> 32); |
| | | 4354 | | |
| | 2037 | 4355 | | var r = LongCompare(low, high); |
| | 2037 | 4356 | | if (ls == -1) |
| | 627 | 4357 | | { |
| | 627 | 4358 | | r = -r; |
| | 627 | 4359 | | } |
| | | 4360 | | |
| | 2037 | 4361 | | return r; |
| | 25541 | 4362 | | } |
| | | 4363 | | |
| | | 4364 | | private readonly int LongCompare(uint low, uint high) |
| | 3285 | 4365 | | { |
| | 3285 | 4366 | | uint h = 0; |
| | | 4367 | | |
| | 3285 | 4368 | | if (_data.Length > 1) |
| | 1644 | 4369 | | { |
| | 1644 | 4370 | | h = _data[1]; |
| | 1644 | 4371 | | } |
| | | 4372 | | |
| | 3285 | 4373 | | if (h > high) |
| | 1098 | 4374 | | { |
| | 1098 | 4375 | | return 1; |
| | | 4376 | | } |
| | | 4377 | | |
| | 2187 | 4378 | | if (h < high) |
| | 1092 | 4379 | | { |
| | 1092 | 4380 | | return -1; |
| | | 4381 | | } |
| | | 4382 | | |
| | 1095 | 4383 | | var l = _data[0]; |
| | | 4384 | | |
| | 1095 | 4385 | | if (l > low) |
| | 273 | 4386 | | { |
| | 273 | 4387 | | return 1; |
| | | 4388 | | } |
| | | 4389 | | |
| | 822 | 4390 | | if (l < low) |
| | 276 | 4391 | | { |
| | 276 | 4392 | | return -1; |
| | | 4393 | | } |
| | | 4394 | | |
| | 546 | 4395 | | return 0; |
| | 3285 | 4396 | | } |
| | | 4397 | | |
| | | 4398 | | /// <summary> |
| | | 4399 | | /// Compares two <see cref="BigInteger"/> values and returns an integer that indicates whether the first value i |
| | | 4400 | | /// </summary> |
| | | 4401 | | /// <param name="left">The first value to compare.</param> |
| | | 4402 | | /// <param name="right">The second value to compare.</param> |
| | | 4403 | | /// <returns> |
| | | 4404 | | /// A signed integer that indicates the relative values of left and right, as shown in the following table. |
| | | 4405 | | /// <list type="table"> |
| | | 4406 | | /// <listheader> |
| | | 4407 | | /// <term>Value</term> |
| | | 4408 | | /// <description>Condition</description> |
| | | 4409 | | /// </listheader> |
| | | 4410 | | /// <item> |
| | | 4411 | | /// <term>Less than zero</term> |
| | | 4412 | | /// <description><paramref name="left"/> is less than <paramref name="right"/>.</description> |
| | | 4413 | | /// </item> |
| | | 4414 | | /// <item> |
| | | 4415 | | /// <term>Zero</term> |
| | | 4416 | | /// <description><paramref name="left"/> equals <paramref name="right"/>.</description> |
| | | 4417 | | /// </item> |
| | | 4418 | | /// <item> |
| | | 4419 | | /// <term>Greater than zero</term> |
| | | 4420 | | /// <description><paramref name="left"/> is greater than <paramref name="right"/>.</description> |
| | | 4421 | | /// </item> |
| | | 4422 | | /// </list> |
| | | 4423 | | /// </returns> |
| | | 4424 | | public static int Compare(BigInteger left, BigInteger right) |
| | 11243 | 4425 | | { |
| | 11243 | 4426 | | int ls = left._sign; |
| | 11243 | 4427 | | int rs = right._sign; |
| | | 4428 | | |
| | 11243 | 4429 | | if (ls != rs) |
| | 4738 | 4430 | | { |
| | 4738 | 4431 | | return ls > rs ? 1 : -1; |
| | | 4432 | | } |
| | | 4433 | | |
| | 6505 | 4434 | | var r = CoreCompare(left._data, right._data); |
| | 6505 | 4435 | | if (ls < 0) |
| | 840 | 4436 | | { |
| | 840 | 4437 | | r = -r; |
| | 840 | 4438 | | } |
| | | 4439 | | |
| | 6505 | 4440 | | return r; |
| | 11243 | 4441 | | } |
| | | 4442 | | |
| | | 4443 | | private static int TopByte(uint x) |
| | 8654 | 4444 | | { |
| | 8654 | 4445 | | if ((x & 0xFFFF0000u) != 0) |
| | 7110 | 4446 | | { |
| | 7110 | 4447 | | if ((x & 0xFF000000u) != 0) |
| | 4622 | 4448 | | { |
| | 4622 | 4449 | | return 4; |
| | | 4450 | | } |
| | | 4451 | | |
| | 2488 | 4452 | | return 3; |
| | | 4453 | | } |
| | | 4454 | | |
| | 1544 | 4455 | | if ((x & 0xFF00u) != 0) |
| | 59 | 4456 | | { |
| | 59 | 4457 | | return 2; |
| | | 4458 | | } |
| | | 4459 | | |
| | 1485 | 4460 | | return 1; |
| | 8654 | 4461 | | } |
| | | 4462 | | |
| | | 4463 | | private static int FirstNonFfByte(uint word) |
| | 129 | 4464 | | { |
| | 129 | 4465 | | if ((word & 0xFF000000u) != 0xFF000000u) |
| | 39 | 4466 | | { |
| | 39 | 4467 | | return 4; |
| | | 4468 | | } |
| | | 4469 | | |
| | 90 | 4470 | | if ((word & 0xFF0000u) != 0xFF0000u) |
| | 27 | 4471 | | { |
| | 27 | 4472 | | return 3; |
| | | 4473 | | } |
| | | 4474 | | |
| | 63 | 4475 | | if ((word & 0xFF00u) != 0xFF00u) |
| | 27 | 4476 | | { |
| | 27 | 4477 | | return 2; |
| | | 4478 | | } |
| | | 4479 | | |
| | 36 | 4480 | | return 1; |
| | 129 | 4481 | | } |
| | | 4482 | | |
| | | 4483 | | /// <summary> |
| | | 4484 | | /// Converts a <see cref="BigInteger"/> value to a byte array. |
| | | 4485 | | /// </summary> |
| | | 4486 | | /// <returns> |
| | | 4487 | | /// The value of the current <see cref="BigInteger"/> object converted to an array of bytes. |
| | | 4488 | | /// </returns> |
| | | 4489 | | public readonly byte[] ToByteArray() |
| | 8678 | 4490 | | { |
| | 8678 | 4491 | | if (_sign == 0) |
| | 24 | 4492 | | { |
| | 24 | 4493 | | return new byte[1]; |
| | | 4494 | | } |
| | | 4495 | | |
| | | 4496 | | // number of bytes not counting upper word |
| | 8654 | 4497 | | var bytes = (_data.Length - 1) * 4; |
| | 8654 | 4498 | | var needExtraZero = false; |
| | | 4499 | | |
| | 8654 | 4500 | | var topWord = _data[_data.Length - 1]; |
| | | 4501 | | int extra; |
| | | 4502 | | |
| | | 4503 | | // if the topmost bit is set we need an extra |
| | 8654 | 4504 | | if (_sign == 1) |
| | 8531 | 4505 | | { |
| | 8531 | 4506 | | extra = TopByte(topWord); |
| | 8531 | 4507 | | var mask = 0x80u << ((extra - 1) * 8); |
| | 8531 | 4508 | | if ((topWord & mask) != 0) |
| | 3517 | 4509 | | { |
| | 3517 | 4510 | | needExtraZero = true; |
| | 3517 | 4511 | | } |
| | 8531 | 4512 | | } |
| | | 4513 | | else |
| | 123 | 4514 | | { |
| | 123 | 4515 | | extra = TopByte(topWord); |
| | 123 | 4516 | | } |
| | | 4517 | | |
| | 8654 | 4518 | | var res = new byte[bytes + extra + (needExtraZero ? 1 : 0)]; |
| | 8654 | 4519 | | if (_sign == 1) |
| | 8531 | 4520 | | { |
| | 8531 | 4521 | | var j = 0; |
| | 8531 | 4522 | | var end = _data.Length - 1; |
| | 761840 | 4523 | | for (var i = 0; i < end; ++i) |
| | 372389 | 4524 | | { |
| | 372389 | 4525 | | var word = _data[i]; |
| | | 4526 | | |
| | 372389 | 4527 | | res[j++] = (byte)word; |
| | 372389 | 4528 | | res[j++] = (byte)(word >> 8); |
| | 372389 | 4529 | | res[j++] = (byte)(word >> 16); |
| | 372389 | 4530 | | res[j++] = (byte)(word >> 24); |
| | 372389 | 4531 | | } |
| | | 4532 | | |
| | 35759 | 4533 | | while (extra-- > 0) |
| | 27228 | 4534 | | { |
| | 27228 | 4535 | | res[j++] = (byte)topWord; |
| | 27228 | 4536 | | topWord >>= 8; |
| | 27228 | 4537 | | } |
| | 8531 | 4538 | | } |
| | | 4539 | | else |
| | 123 | 4540 | | { |
| | 123 | 4541 | | var j = 0; |
| | 123 | 4542 | | var end = _data.Length - 1; |
| | | 4543 | | |
| | 123 | 4544 | | uint carry = 1, word; |
| | | 4545 | | ulong add; |
| | 606 | 4546 | | for (var i = 0; i < end; ++i) |
| | 180 | 4547 | | { |
| | 180 | 4548 | | word = _data[i]; |
| | 180 | 4549 | | add = (ulong)~word + carry; |
| | 180 | 4550 | | word = (uint)add; |
| | 180 | 4551 | | carry = (uint)(add >> 32); |
| | | 4552 | | |
| | 180 | 4553 | | res[j++] = (byte)word; |
| | 180 | 4554 | | res[j++] = (byte)(word >> 8); |
| | 180 | 4555 | | res[j++] = (byte)(word >> 16); |
| | 180 | 4556 | | res[j++] = (byte)(word >> 24); |
| | 180 | 4557 | | } |
| | | 4558 | | |
| | 123 | 4559 | | add = (ulong)~topWord + carry; |
| | 123 | 4560 | | word = (uint)add; |
| | 123 | 4561 | | carry = (uint)(add >> 32); |
| | 123 | 4562 | | if (carry == 0) |
| | 123 | 4563 | | { |
| | 123 | 4564 | | var ex = FirstNonFfByte(word); |
| | 123 | 4565 | | var needExtra = (word & (1 << ((ex * 8) - 1))) == 0; |
| | 123 | 4566 | | var to = ex + (needExtra ? 1 : 0); |
| | | 4567 | | |
| | 123 | 4568 | | if (to != extra) |
| | 15 | 4569 | | { |
| | 15 | 4570 | | Array.Resize(ref res, bytes + to); |
| | 15 | 4571 | | } |
| | | 4572 | | |
| | 444 | 4573 | | while (ex-- > 0) |
| | 321 | 4574 | | { |
| | 321 | 4575 | | res[j++] = (byte)word; |
| | 321 | 4576 | | word >>= 8; |
| | 321 | 4577 | | } |
| | | 4578 | | |
| | 123 | 4579 | | if (needExtra) |
| | 21 | 4580 | | { |
| | | 4581 | | #pragma warning disable S1854 // Unused assignments should be removed |
| | 21 | 4582 | | res[j++] = 0xFF; |
| | | 4583 | | #pragma warning restore S1854 // Unused assignments should be removed |
| | 21 | 4584 | | } |
| | 123 | 4585 | | } |
| | | 4586 | | else |
| | 0 | 4587 | | { |
| | 0 | 4588 | | Array.Resize(ref res, bytes + 5); |
| | 0 | 4589 | | res[j++] = (byte)word; |
| | 0 | 4590 | | res[j++] = (byte)(word >> 8); |
| | 0 | 4591 | | res[j++] = (byte)(word >> 16); |
| | 0 | 4592 | | res[j++] = (byte)(word >> 24); |
| | | 4593 | | #pragma warning disable S1854 // Unused assignments should be removed |
| | 0 | 4594 | | res[j++] = 0xFF; |
| | | 4595 | | #pragma warning restore S1854 // Unused assignments should be removed |
| | 0 | 4596 | | } |
| | 123 | 4597 | | } |
| | | 4598 | | |
| | 8654 | 4599 | | return res; |
| | 8678 | 4600 | | } |
| | | 4601 | | |
| | | 4602 | | private static uint[] CoreAdd(uint[] a, uint[] b) |
| | 843403 | 4603 | | { |
| | 843403 | 4604 | | if (a.Length < b.Length) |
| | 80439 | 4605 | | { |
| | 80439 | 4606 | | var tmp = a; |
| | 80439 | 4607 | | a = b; |
| | 80439 | 4608 | | b = tmp; |
| | 80439 | 4609 | | } |
| | | 4610 | | |
| | 843403 | 4611 | | var bl = a.Length; |
| | 843403 | 4612 | | var sl = b.Length; |
| | | 4613 | | |
| | 843403 | 4614 | | var res = new uint[bl]; |
| | | 4615 | | |
| | 843403 | 4616 | | ulong sum = 0; |
| | | 4617 | | |
| | 843403 | 4618 | | var i = 0; |
| | 54764497 | 4619 | | for (; i < sl; i++) |
| | 26960547 | 4620 | | { |
| | 26960547 | 4621 | | sum = sum + a[i] + b[i]; |
| | 26960547 | 4622 | | res[i] = (uint)sum; |
| | 26960547 | 4623 | | sum >>= 32; |
| | 26960547 | 4624 | | } |
| | | 4625 | | |
| | 2974365 | 4626 | | for (; i < bl; i++) |
| | 1065481 | 4627 | | { |
| | 1065481 | 4628 | | sum += a[i]; |
| | 1065481 | 4629 | | res[i] = (uint)sum; |
| | 1065481 | 4630 | | sum >>= 32; |
| | 1065481 | 4631 | | } |
| | | 4632 | | |
| | 843403 | 4633 | | if (sum != 0) |
| | 7335 | 4634 | | { |
| | 7335 | 4635 | | Array.Resize(ref res, bl + 1); |
| | 7335 | 4636 | | res[i] = (uint)sum; |
| | 7335 | 4637 | | } |
| | | 4638 | | |
| | 843403 | 4639 | | return res; |
| | 843403 | 4640 | | } |
| | | 4641 | | |
| | | 4642 | | private static uint[] CoreAdd(uint[] a, uint b) |
| | 27 | 4643 | | { |
| | 27 | 4644 | | var len = a.Length; |
| | 27 | 4645 | | var res = new uint[len]; |
| | | 4646 | | |
| | 27 | 4647 | | ulong sum = b; |
| | | 4648 | | int i; |
| | 120 | 4649 | | for (i = 0; i < len; i++) |
| | 33 | 4650 | | { |
| | 33 | 4651 | | sum += a[i]; |
| | 33 | 4652 | | res[i] = (uint) sum; |
| | 33 | 4653 | | sum >>= 32; |
| | 33 | 4654 | | } |
| | | 4655 | | |
| | 27 | 4656 | | if (sum != 0) |
| | 0 | 4657 | | { |
| | 0 | 4658 | | Array.Resize(ref res, len + 1); |
| | 0 | 4659 | | res[i] = (uint) sum; |
| | 0 | 4660 | | } |
| | | 4661 | | |
| | 27 | 4662 | | return res; |
| | 27 | 4663 | | } |
| | | 4664 | | |
| | | 4665 | | /*invariant a > b*/ |
| | | 4666 | | private static uint[] CoreSub(uint[] a, uint[] b) |
| | 2184 | 4667 | | { |
| | 2184 | 4668 | | var bl = a.Length; |
| | 2184 | 4669 | | var sl = b.Length; |
| | | 4670 | | |
| | 2184 | 4671 | | var res = new uint[bl]; |
| | | 4672 | | |
| | 2184 | 4673 | | ulong borrow = 0; |
| | | 4674 | | int i; |
| | 111040 | 4675 | | for (i = 0; i < sl; ++i) |
| | 53336 | 4676 | | { |
| | 53336 | 4677 | | borrow = (ulong)a[i] - b[i] - borrow; |
| | | 4678 | | |
| | 53336 | 4679 | | res[i] = (uint)borrow; |
| | 53336 | 4680 | | borrow = (borrow >> 32) & 0x1; |
| | 53336 | 4681 | | } |
| | | 4682 | | |
| | 96102 | 4683 | | for (; i < bl; i++) |
| | 46959 | 4684 | | { |
| | 46959 | 4685 | | borrow = (ulong)a[i] - borrow; |
| | 46959 | 4686 | | res[i] = (uint)borrow; |
| | 46959 | 4687 | | borrow = (borrow >> 32) & 0x1; |
| | 46959 | 4688 | | } |
| | | 4689 | | |
| | | 4690 | | // remove extra zeroes |
| | 4368 | 4691 | | for (i = bl - 1; i >= 0 && res[i] == 0; --i) |
| | 0 | 4692 | | { |
| | | 4693 | | // Intentionally empty block |
| | 0 | 4694 | | } |
| | | 4695 | | |
| | 2184 | 4696 | | if (i < bl - 1) |
| | 0 | 4697 | | { |
| | 0 | 4698 | | Array.Resize(ref res, i + 1); |
| | 0 | 4699 | | } |
| | | 4700 | | |
| | 2184 | 4701 | | return res; |
| | 2184 | 4702 | | } |
| | | 4703 | | |
| | | 4704 | | private static uint[] CoreSub(uint[] a, uint b) |
| | 12 | 4705 | | { |
| | 12 | 4706 | | var len = a.Length; |
| | 12 | 4707 | | var res = new uint[len]; |
| | | 4708 | | |
| | 12 | 4709 | | ulong borrow = b; |
| | | 4710 | | int i; |
| | 60 | 4711 | | for (i = 0; i < len; i++) |
| | 18 | 4712 | | { |
| | 18 | 4713 | | borrow = (ulong)a[i] - borrow; |
| | 18 | 4714 | | res[i] = (uint)borrow; |
| | 18 | 4715 | | borrow = (borrow >> 32) & 0x1; |
| | 18 | 4716 | | } |
| | | 4717 | | |
| | | 4718 | | // Remove extra zeroes |
| | 24 | 4719 | | for (i = len - 1; i >= 0 && res[i] == 0; --i) |
| | 0 | 4720 | | { |
| | | 4721 | | // Intentionally empty block |
| | 0 | 4722 | | } |
| | | 4723 | | |
| | 12 | 4724 | | if (i < len - 1) |
| | 0 | 4725 | | { |
| | 0 | 4726 | | Array.Resize(ref res, i + 1); |
| | 0 | 4727 | | } |
| | | 4728 | | |
| | 12 | 4729 | | return res; |
| | 12 | 4730 | | } |
| | | 4731 | | |
| | | 4732 | | private static int CoreCompare(uint[] a, uint[] b) |
| | 8872 | 4733 | | { |
| | 8872 | 4734 | | var al = a != null ? a.Length : 0; |
| | 8872 | 4735 | | var bl = b != null ? b.Length : 0; |
| | | 4736 | | |
| | 8872 | 4737 | | if (al > bl) |
| | 3078 | 4738 | | { |
| | 3078 | 4739 | | return 1; |
| | | 4740 | | } |
| | | 4741 | | |
| | 5794 | 4742 | | if (bl > al) |
| | 942 | 4743 | | { |
| | 942 | 4744 | | return -1; |
| | | 4745 | | } |
| | | 4746 | | |
| | 13418 | 4747 | | for (var i = al - 1; i >= 0; --i) |
| | 5098 | 4748 | | { |
| | 5098 | 4749 | | var ai = a[i]; |
| | 5098 | 4750 | | var bi = b[i]; |
| | 5098 | 4751 | | if (ai > bi) |
| | 1338 | 4752 | | { |
| | 1338 | 4753 | | return 1; |
| | | 4754 | | } |
| | | 4755 | | |
| | 3760 | 4756 | | if (ai < bi) |
| | 1903 | 4757 | | { |
| | 1903 | 4758 | | return -1; |
| | | 4759 | | } |
| | 1857 | 4760 | | } |
| | | 4761 | | |
| | 1611 | 4762 | | return 0; |
| | 8872 | 4763 | | } |
| | | 4764 | | |
| | | 4765 | | private static int GetNormalizeShift(uint value) |
| | 3881309 | 4766 | | { |
| | 3881309 | 4767 | | var shift = 0; |
| | | 4768 | | |
| | 3881309 | 4769 | | if ((value & 0xFFFF0000) == 0) |
| | 819933 | 4770 | | { |
| | 819933 | 4771 | | value <<= 16; |
| | 819933 | 4772 | | shift += 16; |
| | 819933 | 4773 | | } |
| | | 4774 | | |
| | 3881309 | 4775 | | if ((value & 0xFF000000) == 0) |
| | 817981 | 4776 | | { |
| | 817981 | 4777 | | value <<= 8; |
| | 817981 | 4778 | | shift += 8; |
| | 817981 | 4779 | | } |
| | | 4780 | | |
| | 3881309 | 4781 | | if ((value & 0xF0000000) == 0) |
| | 819361 | 4782 | | { |
| | 819361 | 4783 | | value <<= 4; |
| | 819361 | 4784 | | shift += 4; |
| | 819361 | 4785 | | } |
| | | 4786 | | |
| | 3881309 | 4787 | | if ((value & 0xC0000000) == 0) |
| | 820097 | 4788 | | { |
| | 820097 | 4789 | | value <<= 2; |
| | 820097 | 4790 | | shift += 2; |
| | 820097 | 4791 | | } |
| | | 4792 | | |
| | 3881309 | 4793 | | if ((value & 0x80000000) == 0) |
| | 817759 | 4794 | | { |
| | | 4795 | | #pragma warning disable IDE0059 // Unnecessary assignment of a value |
| | 817759 | 4796 | | value <<= 1; |
| | | 4797 | | #pragma warning restore IDE0059 // Unnecessary assignment of a value |
| | 817759 | 4798 | | shift += 1; |
| | 817759 | 4799 | | } |
| | | 4800 | | |
| | 3881309 | 4801 | | return shift; |
| | 3881309 | 4802 | | } |
| | | 4803 | | |
| | | 4804 | | private static void Normalize(uint[] u, int l, uint[] un, int shift) |
| | 7762618 | 4805 | | { |
| | 7762618 | 4806 | | uint carry = 0; |
| | | 4807 | | int i; |
| | 7762618 | 4808 | | if (shift > 0) |
| | 3175714 | 4809 | | { |
| | 3175714 | 4810 | | var rshift = 32 - shift; |
| | 215982214 | 4811 | | for (i = 0; i < l; i++) |
| | 104815393 | 4812 | | { |
| | 104815393 | 4813 | | var ui = u[i]; |
| | 104815393 | 4814 | | un[i] = (ui << shift) | carry; |
| | 104815393 | 4815 | | carry = ui >> rshift; |
| | 104815393 | 4816 | | } |
| | 3175714 | 4817 | | } |
| | | 4818 | | else |
| | 4586904 | 4819 | | { |
| | 468257532 | 4820 | | for (i = 0; i < l; i++) |
| | 229541862 | 4821 | | { |
| | 229541862 | 4822 | | un[i] = u[i]; |
| | 229541862 | 4823 | | } |
| | 4586904 | 4824 | | } |
| | | 4825 | | |
| | 11643927 | 4826 | | while (i < un.Length) |
| | 3881309 | 4827 | | { |
| | 3881309 | 4828 | | un[i++] = 0; |
| | 3881309 | 4829 | | } |
| | | 4830 | | |
| | 7762618 | 4831 | | if (carry != 0) |
| | 1188497 | 4832 | | { |
| | 1188497 | 4833 | | un[l] = carry; |
| | 1188497 | 4834 | | } |
| | 7762618 | 4835 | | } |
| | | 4836 | | |
| | | 4837 | | private static void Unnormalize(uint[] un, out uint[] r, int shift) |
| | 3881309 | 4838 | | { |
| | 3881309 | 4839 | | var length = un.Length; |
| | 3881309 | 4840 | | r = new uint[length]; |
| | | 4841 | | |
| | 3881309 | 4842 | | if (shift > 0) |
| | 1587857 | 4843 | | { |
| | 1587857 | 4844 | | var lshift = 32 - shift; |
| | 1587857 | 4845 | | uint carry = 0; |
| | 111213998 | 4846 | | for (var i = length - 1; i >= 0; i--) |
| | 54019142 | 4847 | | { |
| | 54019142 | 4848 | | var uni = un[i]; |
| | 54019142 | 4849 | | r[i] = (uni >> shift) | carry; |
| | 54019142 | 4850 | | carry = uni << lshift; |
| | 54019142 | 4851 | | } |
| | 1587857 | 4852 | | } |
| | | 4853 | | else |
| | 2293452 | 4854 | | { |
| | 313993926 | 4855 | | for (var i = 0; i < length; i++) |
| | 154703511 | 4856 | | { |
| | 154703511 | 4857 | | r[i] = un[i]; |
| | 154703511 | 4858 | | } |
| | 2293452 | 4859 | | } |
| | 3881309 | 4860 | | } |
| | | 4861 | | |
| | | 4862 | | private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r) |
| | 3928961 | 4863 | | { |
| | 3928961 | 4864 | | var m = u.Length; |
| | 3928961 | 4865 | | var n = v.Length; |
| | | 4866 | | |
| | 3928961 | 4867 | | if (n <= 1) |
| | 43996 | 4868 | | { |
| | | 4869 | | // Divide by single digit |
| | 43996 | 4870 | | ulong rem = 0; |
| | 43996 | 4871 | | var v0 = v[0]; |
| | 43996 | 4872 | | q = new uint[m]; |
| | 43996 | 4873 | | r = new uint[1]; |
| | | 4874 | | |
| | 239234 | 4875 | | for (var j = m - 1; j >= 0; j--) |
| | 75621 | 4876 | | { |
| | 75621 | 4877 | | rem *= Base; |
| | 75621 | 4878 | | rem += u[j]; |
| | | 4879 | | |
| | 75621 | 4880 | | var div = rem / v0; |
| | 75621 | 4881 | | rem -= div * v0; |
| | 75621 | 4882 | | q[j] = (uint)div; |
| | 75621 | 4883 | | } |
| | | 4884 | | |
| | 43996 | 4885 | | r[0] = (uint) rem; |
| | 43996 | 4886 | | } |
| | 3884965 | 4887 | | else if (m >= n) |
| | 3881309 | 4888 | | { |
| | 3881309 | 4889 | | var shift = GetNormalizeShift(v[n - 1]); |
| | | 4890 | | |
| | 3881309 | 4891 | | var un = new uint[m + 1]; |
| | 3881309 | 4892 | | var vn = new uint[n]; |
| | | 4893 | | |
| | 3881309 | 4894 | | Normalize(u, m, un, shift); |
| | 3881309 | 4895 | | Normalize(v, n, vn, shift); |
| | | 4896 | | |
| | 3881309 | 4897 | | q = new uint[m - n + 1]; |
| | | 4898 | | |
| | | 4899 | | // Main division loop |
| | 166176102 | 4900 | | for (var j = m - n; j >= 0; j--) |
| | 79206742 | 4901 | | { |
| | | 4902 | | int i; |
| | | 4903 | | |
| | 79206742 | 4904 | | var rr = (Base * un[j + n]) + un[j + n - 1]; |
| | 79206742 | 4905 | | var qq = rr / vn[n - 1]; |
| | 79206742 | 4906 | | rr -= qq * vn[n - 1]; |
| | | 4907 | | |
| | | 4908 | | for (; ; ) |
| | 90728928 | 4909 | | { |
| | | 4910 | | // Estimate too big ? |
| | 90728928 | 4911 | | if ((qq >= Base) || (qq * vn[n - 2] > ((rr * Base) + un[j + n - 2]))) |
| | 35931863 | 4912 | | { |
| | 35931863 | 4913 | | qq--; |
| | 35931863 | 4914 | | rr += (ulong)vn[n - 1]; |
| | 35931863 | 4915 | | if (rr < Base) |
| | 11522186 | 4916 | | { |
| | 11522186 | 4917 | | continue; |
| | | 4918 | | } |
| | 24409677 | 4919 | | } |
| | | 4920 | | |
| | 79206742 | 4921 | | break; |
| | | 4922 | | } |
| | | 4923 | | |
| | | 4924 | | // Multiply and subtract |
| | 79206742 | 4925 | | long b = 0; |
| | | 4926 | | long t; |
| | 98631280 | 4927 | | for (i = 0; i < n; i++) |
| | 47835590 | 4928 | | { |
| | 47835590 | 4929 | | var p = vn[i] * qq; |
| | 47835590 | 4930 | | t = (long)un[i + j] - (long)(uint)p - b; |
| | 47835590 | 4931 | | un[i + j] = (uint)t; |
| | 47835590 | 4932 | | p >>= 32; |
| | 47835590 | 4933 | | t >>= 32; |
| | 47835590 | 4934 | | b = (long)p - t; |
| | 47835590 | 4935 | | } |
| | | 4936 | | |
| | 79206742 | 4937 | | t = (long)un[j + n] - b; |
| | 79206742 | 4938 | | un[j + n] = (uint)t; |
| | | 4939 | | |
| | | 4940 | | // Store the calculated value |
| | 79206742 | 4941 | | q[j] = (uint)qq; |
| | | 4942 | | |
| | | 4943 | | // Add back vn[0..n] to un[j..j+n] |
| | 79206742 | 4944 | | if (t < 0) |
| | 0 | 4945 | | { |
| | 0 | 4946 | | q[j]--; |
| | 0 | 4947 | | ulong c = 0; |
| | 0 | 4948 | | for (i = 0; i < n; i++) |
| | 0 | 4949 | | { |
| | 0 | 4950 | | c = (ulong)vn[i] + un[j + i] + c; |
| | 0 | 4951 | | un[j + i] = (uint)c; |
| | 0 | 4952 | | c >>= 32; |
| | 0 | 4953 | | } |
| | | 4954 | | |
| | 0 | 4955 | | c += (ulong)un[j + n]; |
| | 0 | 4956 | | un[j + n] = (uint)c; |
| | 0 | 4957 | | } |
| | 79206742 | 4958 | | } |
| | | 4959 | | |
| | 3881309 | 4960 | | Unnormalize(un, out r, shift); |
| | 3881309 | 4961 | | } |
| | | 4962 | | else |
| | 3656 | 4963 | | { |
| | 3656 | 4964 | | q = new uint[] { 0 }; |
| | 3656 | 4965 | | r = u; |
| | 3656 | 4966 | | } |
| | 3928961 | 4967 | | } |
| | | 4968 | | } |
| | | 4969 | | } |