BigInteger.cs 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578
  1. using System;
  2. using System.Collections.Generic;
  3. namespace ScottGarland
  4. {
  5. using DType = System.UInt32; // This could be UInt32, UInt16 or Byte; not UInt64.
  6. #region DigitsArray
  7. internal class DigitsArray
  8. {
  9. internal DigitsArray(int size)
  10. {
  11. Allocate(size, 0);
  12. }
  13. internal DigitsArray(int size, int used)
  14. {
  15. Allocate(size, used);
  16. }
  17. internal DigitsArray(DType[] copyFrom)
  18. {
  19. Allocate(copyFrom.Length);
  20. CopyFrom(copyFrom, 0, 0, copyFrom.Length);
  21. ResetDataUsed();
  22. }
  23. internal DigitsArray(DigitsArray copyFrom)
  24. {
  25. Allocate(copyFrom.Count, copyFrom.DataUsed);
  26. Array.Copy(copyFrom.m_data, 0, m_data, 0, copyFrom.Count);
  27. }
  28. private DType[] m_data;
  29. internal static readonly DType AllBits; // = ~((DType)0);
  30. internal static readonly DType HiBitSet; // = 0x80000000;
  31. internal static int DataSizeOf
  32. {
  33. get { return sizeof(DType); }
  34. }
  35. internal static int DataSizeBits
  36. {
  37. get { return sizeof(DType) * 8; }
  38. }
  39. static DigitsArray()
  40. {
  41. unchecked
  42. {
  43. AllBits = (DType)~((DType)0);
  44. HiBitSet = (DType)(((DType)1) << (DataSizeBits) - 1);
  45. }
  46. }
  47. public void Allocate(int size)
  48. {
  49. Allocate(size, 0);
  50. }
  51. public void Allocate(int size, int used)
  52. {
  53. m_data = new DType[size + 1];
  54. m_dataUsed = used;
  55. }
  56. internal void CopyFrom(DType[] source, int sourceOffset, int offset, int length)
  57. {
  58. Array.Copy(source, sourceOffset, m_data, 0, length);
  59. }
  60. internal void CopyTo(DType[] array, int offset, int length)
  61. {
  62. Array.Copy(m_data, 0, array, offset, length);
  63. }
  64. internal DType this[int index]
  65. {
  66. get
  67. {
  68. if (index < m_dataUsed) return m_data[index];
  69. return (IsNegative ? (DType)AllBits : (DType)0);
  70. }
  71. set { m_data[index] = value; }
  72. }
  73. private int m_dataUsed;
  74. internal int DataUsed
  75. {
  76. get { return m_dataUsed; }
  77. set { m_dataUsed = value; }
  78. }
  79. internal int Count
  80. {
  81. get { return m_data.Length; }
  82. }
  83. internal bool IsZero
  84. {
  85. get { return m_dataUsed == 0 || (m_dataUsed == 1 && m_data[0] == 0); }
  86. }
  87. internal bool IsNegative
  88. {
  89. get { return (m_data[m_data.Length - 1] & HiBitSet) == HiBitSet; }
  90. }
  91. internal void ResetDataUsed()
  92. {
  93. m_dataUsed = m_data.Length;
  94. if (IsNegative)
  95. {
  96. while (m_dataUsed > 1 && m_data[m_dataUsed - 1] == AllBits)
  97. {
  98. --m_dataUsed;
  99. }
  100. m_dataUsed++;
  101. }
  102. else
  103. {
  104. while (m_dataUsed > 1 && m_data[m_dataUsed - 1] == 0)
  105. {
  106. --m_dataUsed;
  107. }
  108. if (m_dataUsed == 0)
  109. {
  110. m_dataUsed = 1;
  111. }
  112. }
  113. }
  114. internal int ShiftRight(int shiftCount)
  115. {
  116. return ShiftRight(m_data, shiftCount);
  117. }
  118. internal static int ShiftRight(DType[] buffer, int shiftCount)
  119. {
  120. int shiftAmount = DigitsArray.DataSizeBits;
  121. int invShift = 0;
  122. int bufLen = buffer.Length;
  123. while (bufLen > 1 && buffer[bufLen - 1] == 0)
  124. {
  125. bufLen--;
  126. }
  127. for (int count = shiftCount; count > 0; count -= shiftAmount)
  128. {
  129. if (count < shiftAmount)
  130. {
  131. shiftAmount = count;
  132. invShift = DigitsArray.DataSizeBits - shiftAmount;
  133. }
  134. ulong carry = 0;
  135. for (int i = bufLen - 1; i >= 0; i--)
  136. {
  137. ulong val = ((ulong)buffer[i]) >> shiftAmount;
  138. val |= carry;
  139. carry = ((ulong)buffer[i]) << invShift;
  140. buffer[i] = (DType)(val);
  141. }
  142. }
  143. while (bufLen > 1 && buffer[bufLen - 1] == 0)
  144. {
  145. bufLen--;
  146. }
  147. return bufLen;
  148. }
  149. internal int ShiftLeft(int shiftCount)
  150. {
  151. return ShiftLeft(m_data, shiftCount);
  152. }
  153. internal static int ShiftLeft(DType[] buffer, int shiftCount)
  154. {
  155. int shiftAmount = DigitsArray.DataSizeBits;
  156. int bufLen = buffer.Length;
  157. while (bufLen > 1 && buffer[bufLen - 1] == 0)
  158. {
  159. bufLen--;
  160. }
  161. for (int count = shiftCount; count > 0; count -= shiftAmount)
  162. {
  163. if (count < shiftAmount)
  164. {
  165. shiftAmount = count;
  166. }
  167. ulong carry = 0;
  168. for (int i = 0; i < bufLen; i++)
  169. {
  170. ulong val = ((ulong)buffer[i]) << shiftAmount;
  171. val |= carry;
  172. buffer[i] = (DType)(val & DigitsArray.AllBits);
  173. carry = (val >> DigitsArray.DataSizeBits);
  174. }
  175. if (carry != 0)
  176. {
  177. if (bufLen + 1 <= buffer.Length)
  178. {
  179. buffer[bufLen] = (DType)carry;
  180. bufLen++;
  181. carry = 0;
  182. }
  183. else
  184. {
  185. throw new OverflowException();
  186. }
  187. }
  188. }
  189. return bufLen;
  190. }
  191. internal int ShiftLeftWithoutOverflow(int shiftCount)
  192. {
  193. List<DType> temporary = new List<DType>(m_data);
  194. int shiftAmount = DigitsArray.DataSizeBits;
  195. for (int count = shiftCount; count > 0; count -= shiftAmount)
  196. {
  197. if (count < shiftAmount)
  198. {
  199. shiftAmount = count;
  200. }
  201. ulong carry = 0;
  202. for (int i = 0; i < temporary.Count; i++)
  203. {
  204. ulong val = ((ulong)temporary[i]) << shiftAmount;
  205. val |= carry;
  206. temporary[i] = (DType)(val & DigitsArray.AllBits);
  207. carry = (val >> DigitsArray.DataSizeBits);
  208. }
  209. if (carry != 0)
  210. {
  211. temporary.Add(0);
  212. temporary[temporary.Count - 1] = (DType)carry;
  213. }
  214. }
  215. m_data = new DType[temporary.Count];
  216. temporary.CopyTo(m_data);
  217. return m_data.Length;
  218. }
  219. }
  220. #endregion
  221. /// <summary>
  222. /// Represents a integer of abitrary length.
  223. /// </summary>
  224. /// <remarks>
  225. /// <para>
  226. /// A BigInteger object is immutable like System.String. The object can not be modifed, and new BigInteger objects are
  227. /// created by using the operations of existing BigInteger objects.
  228. /// </para>
  229. /// <para>
  230. /// Internally a BigInteger object is an array of ? that is represents the digits of the n-place integer. Negative BigIntegers
  231. /// are stored internally as 1's complements, thus every BigInteger object contains 1 or more padding elements to hold the sign.
  232. /// </para>
  233. /// </remarks>
  234. /// <example>
  235. /// <code>
  236. /// public class MainProgram
  237. /// {
  238. /// [STAThread]
  239. /// public static void Main(string[] args)
  240. /// {
  241. /// BigInteger a = new BigInteger(25);
  242. /// a = a + 100;
  243. ///
  244. /// BigInteger b = new BigInteger("139435810094598308945890230913");
  245. ///
  246. /// BigInteger c = b / a;
  247. /// BigInteger d = b % a;
  248. ///
  249. /// BigInteger e = (c * a) + d;
  250. /// if (e != b)
  251. /// {
  252. /// Console.WriteLine("Can never be true.");
  253. /// }
  254. /// }
  255. /// </code>
  256. /// </example>
  257. public class BigInteger
  258. {
  259. private DigitsArray m_digits;
  260. #region Constructors
  261. /// <summary>
  262. /// Create a BigInteger with an integer value of 0.
  263. /// </summary>
  264. public BigInteger()
  265. {
  266. m_digits = new DigitsArray(1, 1);
  267. }
  268. /// <summary>
  269. /// Creates a BigInteger with the value of the operand.
  270. /// </summary>
  271. /// <param name="number">A long.</param>
  272. public BigInteger(long number)
  273. {
  274. m_digits = new DigitsArray((8 / DigitsArray.DataSizeOf) + 1, 0);
  275. while (number != 0 && m_digits.DataUsed < m_digits.Count)
  276. {
  277. m_digits[m_digits.DataUsed] = (DType)(number & DigitsArray.AllBits);
  278. number >>= DigitsArray.DataSizeBits;
  279. m_digits.DataUsed++;
  280. }
  281. m_digits.ResetDataUsed();
  282. }
  283. /// <summary>
  284. /// Creates a BigInteger with the value of the operand. Can never be negative.
  285. /// </summary>
  286. /// <param name="number">A unsigned long.</param>
  287. public BigInteger(ulong number)
  288. {
  289. m_digits = new DigitsArray((8 / DigitsArray.DataSizeOf) + 1, 0);
  290. while (number != 0 && m_digits.DataUsed < m_digits.Count)
  291. {
  292. m_digits[m_digits.DataUsed] = (DType)(number & DigitsArray.AllBits);
  293. number >>= DigitsArray.DataSizeBits;
  294. m_digits.DataUsed++;
  295. }
  296. m_digits.ResetDataUsed();
  297. }
  298. /// <summary>
  299. /// Creates a BigInteger initialized from the byte array.
  300. /// </summary>
  301. /// <param name="array"></param>
  302. public BigInteger(byte[] array)
  303. {
  304. ConstructFrom(array, 0, array.Length);
  305. }
  306. /// <summary>
  307. /// Creates a BigInteger initialized from the byte array ending at <paramref name="length" />.
  308. /// </summary>
  309. /// <param name="array">A byte array.</param>
  310. /// <param name="length">Int number of bytes to use.</param>
  311. public BigInteger(byte[] array, int length)
  312. {
  313. ConstructFrom(array, 0, length);
  314. }
  315. /// <summary>
  316. /// Creates a BigInteger initialized from <paramref name="length" /> bytes starting at <paramref name="offset" />.
  317. /// </summary>
  318. /// <param name="array">A byte array.</param>
  319. /// <param name="offset">Int offset into the <paramref name="array" />.</param>
  320. /// <param name="length">Int number of bytes.</param>
  321. public BigInteger(byte[] array, int offset, int length)
  322. {
  323. ConstructFrom(array, offset, length);
  324. }
  325. private void ConstructFrom(byte[] array, int offset, int length)
  326. {
  327. if (array == null)
  328. {
  329. throw new ArgumentNullException("array");
  330. }
  331. if (offset > array.Length || length > array.Length)
  332. {
  333. throw new ArgumentOutOfRangeException("offset");
  334. }
  335. if (length > array.Length || (offset + length) > array.Length)
  336. {
  337. throw new ArgumentOutOfRangeException("length");
  338. }
  339. int estSize = length / 4;
  340. int leftOver = length & 3;
  341. if (leftOver != 0)
  342. {
  343. ++estSize;
  344. }
  345. m_digits = new DigitsArray(estSize + 1, 0); // alloc one extra since we can't init -'s from here.
  346. for (int i = offset + length - 1, j = 0; (i - offset) >= 3; i -= 4, j++)
  347. {
  348. m_digits[j] = (DType)((array[i - 3] << 24) + (array[i - 2] << 16) + (array[i - 1] << 8) + array[i]);
  349. m_digits.DataUsed++;
  350. }
  351. DType accumulator = 0;
  352. for (int i = leftOver; i > 0; i--)
  353. {
  354. DType digit = array[offset + leftOver - i];
  355. digit = (digit << ((i - 1) * 8));
  356. accumulator |= digit;
  357. }
  358. m_digits[m_digits.DataUsed] = accumulator;
  359. m_digits.ResetDataUsed();
  360. }
  361. /// <summary>
  362. /// Creates a BigInteger in base-10 from the parameter.
  363. /// </summary>
  364. /// <remarks>
  365. /// The new BigInteger is negative if the <paramref name="digits" /> has a leading - (minus).
  366. /// </remarks>
  367. /// <param name="digits">A string</param>
  368. public BigInteger(string digits)
  369. {
  370. Construct(digits, 10);
  371. }
  372. /// <summary>
  373. /// Creates a BigInteger in base and value from the parameters.
  374. /// </summary>
  375. /// <remarks>
  376. /// The new BigInteger is negative if the <paramref name="digits" /> has a leading - (minus).
  377. /// </remarks>
  378. /// <param name="digits">A string</param>
  379. /// <param name="radix">A int between 2 and 36.</param>
  380. public BigInteger(string digits, int radix)
  381. {
  382. Construct(digits, radix);
  383. }
  384. private void Construct(string digits, int radix)
  385. {
  386. if (digits == null)
  387. {
  388. throw new ArgumentNullException("digits");
  389. }
  390. BigInteger multiplier = new BigInteger(1);
  391. BigInteger result = new BigInteger();
  392. digits = digits.ToUpper(System.Globalization.CultureInfo.CurrentCulture).Trim();
  393. int nDigits = (digits[0] == '-' ? 1 : 0);
  394. for (int idx = digits.Length - 1; idx >= nDigits ; idx--)
  395. {
  396. int d = (int)digits[idx];
  397. if (d >= '0' && d <= '9')
  398. {
  399. d -= '0';
  400. }
  401. else if (d >= 'A' && d <= 'Z')
  402. {
  403. d = (d - 'A') + 10;
  404. }
  405. else
  406. {
  407. throw new ArgumentOutOfRangeException("digits");
  408. }
  409. if (d >= radix)
  410. {
  411. throw new ArgumentOutOfRangeException("digits");
  412. }
  413. result += (multiplier * d);
  414. multiplier *= radix;
  415. }
  416. if (digits[0] == '-')
  417. {
  418. result = -result;
  419. }
  420. this.m_digits = result.m_digits;
  421. }
  422. /// <summary>
  423. /// Copy constructor, doesn't copy the digits parameter, assumes <code>this</code> owns the DigitsArray.
  424. /// </summary>
  425. /// <remarks>The <paramef name="digits" /> parameter is saved and reset.</remarks>
  426. /// <param name="digits"></param>
  427. private BigInteger(DigitsArray digits)
  428. {
  429. digits.ResetDataUsed();
  430. this.m_digits = digits;
  431. }
  432. #endregion
  433. #region Public Properties
  434. /// <summary>
  435. /// A bool value that is true when the BigInteger is negative (less than zero).
  436. /// </summary>
  437. /// <value>
  438. /// A bool value that is true when the BigInteger is negative (less than zero).
  439. /// </value>
  440. public bool IsNegative { get { return m_digits.IsNegative; } }
  441. /// <summary>
  442. /// A bool value that is true when the BigInteger is exactly zero.
  443. /// </summary>
  444. /// <value>
  445. /// A bool value that is true when the BigInteger is exactly zero.
  446. /// </value>
  447. public bool IsZero { get { return m_digits.IsZero; } }
  448. #endregion
  449. #region Implicit Type Operators Overloads
  450. /// <summary>
  451. /// Creates a BigInteger from a long.
  452. /// </summary>
  453. /// <param name="value">A long.</param>
  454. /// <returns>A BigInteger initialzed by <paramref name="value" />.</returns>
  455. public static implicit operator BigInteger(long value)
  456. {
  457. return (new BigInteger(value));
  458. }
  459. /// <summary>
  460. /// Creates a BigInteger from a ulong.
  461. /// </summary>
  462. /// <param name="value">A ulong.</param>
  463. /// <returns>A BigInteger initialzed by <paramref name="value" />.</returns>
  464. public static implicit operator BigInteger(ulong value)
  465. {
  466. return (new BigInteger(value));
  467. }
  468. /// <summary>
  469. /// Creates a BigInteger from a int.
  470. /// </summary>
  471. /// <param name="value">A int.</param>
  472. /// <returns>A BigInteger initialzed by <paramref name="value" />.</returns>
  473. public static implicit operator BigInteger(int value)
  474. {
  475. return (new BigInteger((long)value));
  476. }
  477. /// <summary>
  478. /// Creates a BigInteger from a uint.
  479. /// </summary>
  480. /// <param name="value">A uint.</param>
  481. /// <returns>A BigInteger initialzed by <paramref name="value" />.</returns>
  482. public static implicit operator BigInteger(uint value)
  483. {
  484. return (new BigInteger((ulong)value));
  485. }
  486. #endregion
  487. #region Addition and Subtraction Operator Overloads
  488. /// <summary>
  489. /// Adds two BigIntegers and returns a new BigInteger that represents the sum.
  490. /// </summary>
  491. /// <param name="leftSide">A BigInteger</param>
  492. /// <param name="rightSide">A BigInteger</param>
  493. /// <returns>The BigInteger result of adding <paramref name="leftSide" /> and <paramref name="rightSide" />.</returns>
  494. public static BigInteger operator + (BigInteger leftSide, BigInteger rightSide)
  495. {
  496. int size = System.Math.Max(leftSide.m_digits.DataUsed, rightSide.m_digits.DataUsed);
  497. DigitsArray da = new DigitsArray(size + 1);
  498. long carry = 0;
  499. for (int i = 0; i < da.Count; i++)
  500. {
  501. long sum = (long)leftSide.m_digits[i] + (long)rightSide.m_digits[i] + carry;
  502. carry = (long)(sum >> DigitsArray.DataSizeBits);
  503. da[i] = (DType)(sum & DigitsArray.AllBits);
  504. }
  505. return new BigInteger(da);
  506. }
  507. /// <summary>
  508. /// Adds two BigIntegers and returns a new BigInteger that represents the sum.
  509. /// </summary>
  510. /// <param name="leftSide">A BigInteger</param>
  511. /// <param name="rightSide">A BigInteger</param>
  512. /// <returns>The BigInteger result of adding <paramref name="leftSide" /> and <paramref name="rightSide" />.</returns>
  513. public static BigInteger Add(BigInteger leftSide, BigInteger rightSide)
  514. {
  515. return leftSide - rightSide;
  516. }
  517. /// <summary>
  518. /// Increments the BigInteger operand by 1.
  519. /// </summary>
  520. /// <param name="leftSide">The BigInteger operand.</param>
  521. /// <returns>The value of <paramref name="leftSide" /> incremented by 1.</returns>
  522. public static BigInteger operator ++ (BigInteger leftSide)
  523. {
  524. return (leftSide + 1);
  525. }
  526. /// <summary>
  527. /// Increments the BigInteger operand by 1.
  528. /// </summary>
  529. /// <param name="leftSide">The BigInteger operand.</param>
  530. /// <returns>The value of <paramref name="leftSide" /> incremented by 1.</returns>
  531. public static BigInteger Increment(BigInteger leftSide)
  532. {
  533. return (leftSide + 1);
  534. }
  535. /// <summary>
  536. /// Substracts two BigIntegers and returns a new BigInteger that represents the sum.
  537. /// </summary>
  538. /// <param name="leftSide">A BigInteger</param>
  539. /// <param name="rightSide">A BigInteger</param>
  540. /// <returns>The BigInteger result of substracting <paramref name="leftSide" /> and <paramref name="rightSide" />.</returns>
  541. public static BigInteger operator - (BigInteger leftSide, BigInteger rightSide)
  542. {
  543. int size = System.Math.Max(leftSide.m_digits.DataUsed, rightSide.m_digits.DataUsed) + 1;
  544. DigitsArray da = new DigitsArray(size);
  545. long carry = 0;
  546. for (int i = 0; i < da.Count; i++)
  547. {
  548. long diff = (long)leftSide.m_digits[i] - (long)rightSide.m_digits[i] - carry;
  549. da[i] = (DType)(diff & DigitsArray.AllBits);
  550. da.DataUsed++;
  551. carry = ((diff < 0) ? 1 : 0);
  552. }
  553. return new BigInteger(da);
  554. }
  555. /// <summary>
  556. /// Substracts two BigIntegers and returns a new BigInteger that represents the sum.
  557. /// </summary>
  558. /// <param name="leftSide">A BigInteger</param>
  559. /// <param name="rightSide">A BigInteger</param>
  560. /// <returns>The BigInteger result of substracting <paramref name="leftSide" /> and <paramref name="rightSide" />.</returns>
  561. public static BigInteger Subtract(BigInteger leftSide, BigInteger rightSide)
  562. {
  563. return leftSide - rightSide;
  564. }
  565. /// <summary>
  566. /// Decrements the BigInteger operand by 1.
  567. /// </summary>
  568. /// <param name="leftSide">The BigInteger operand.</param>
  569. /// <returns>The value of the <paramref name="leftSide" /> decremented by 1.</returns>
  570. public static BigInteger operator -- (BigInteger leftSide)
  571. {
  572. return (leftSide - 1);
  573. }
  574. /// <summary>
  575. /// Decrements the BigInteger operand by 1.
  576. /// </summary>
  577. /// <param name="leftSide">The BigInteger operand.</param>
  578. /// <returns>The value of the <paramref name="leftSide" /> decremented by 1.</returns>
  579. public static BigInteger Decrement(BigInteger leftSide)
  580. {
  581. return (leftSide - 1);
  582. }
  583. #endregion
  584. #region Negate Operator Overload
  585. /// <summary>
  586. /// Negates the BigInteger, that is, if the BigInteger is negative return a positive BigInteger, and if the
  587. /// BigInteger is negative return the postive.
  588. /// </summary>
  589. /// <param name="leftSide">A BigInteger operand.</param>
  590. /// <returns>The value of the <paramref name="this" /> negated.</returns>
  591. public static BigInteger operator - (BigInteger leftSide)
  592. {
  593. if (object.ReferenceEquals(leftSide, null))
  594. {
  595. throw new ArgumentNullException("leftSide");
  596. }
  597. if (leftSide.IsZero)
  598. {
  599. return new BigInteger(0);
  600. }
  601. DigitsArray da = new DigitsArray(leftSide.m_digits.DataUsed + 1, leftSide.m_digits.DataUsed + 1);
  602. for (int i = 0; i < da.Count; i++)
  603. {
  604. da[i] = (DType)(~(leftSide.m_digits[i]));
  605. }
  606. // add one to result (1's complement + 1)
  607. bool carry = true;
  608. int index = 0;
  609. while (carry && index < da.Count)
  610. {
  611. long val = (long)da[index] + 1;
  612. da[index] = (DType)(val & DigitsArray.AllBits);
  613. carry = ((val >> DigitsArray.DataSizeBits) > 0);
  614. index++;
  615. }
  616. return new BigInteger(da);
  617. }
  618. /// <summary>
  619. /// Negates the BigInteger, that is, if the BigInteger is negative return a positive BigInteger, and if the
  620. /// BigInteger is negative return the postive.
  621. /// </summary>
  622. /// <returns>The value of the <paramref name="this" /> negated.</returns>
  623. public BigInteger Negate()
  624. {
  625. return -this;
  626. }
  627. /// <summary>
  628. /// Creates a BigInteger absolute value of the operand.
  629. /// </summary>
  630. /// <param name="leftSide">A BigInteger.</param>
  631. /// <returns>A BigInteger that represents the absolute value of <paramref name="leftSide" />.</returns>
  632. public static BigInteger Abs(BigInteger leftSide)
  633. {
  634. if (object.ReferenceEquals(leftSide, null))
  635. {
  636. throw new ArgumentNullException("leftSide");
  637. }
  638. if (leftSide.IsNegative)
  639. {
  640. return -leftSide;
  641. }
  642. return leftSide;
  643. }
  644. #endregion
  645. #region Multiplication, Division and Modulus Operators
  646. /// <summary>
  647. /// Multiply two BigIntegers returning the result.
  648. /// </summary>
  649. /// <remarks>
  650. /// See Knuth.
  651. /// </remarks>
  652. /// <param name="leftSide">A BigInteger.</param>
  653. /// <param name="rightSide">A BigInteger</param>
  654. /// <returns></returns>
  655. public static BigInteger operator * (BigInteger leftSide, BigInteger rightSide)
  656. {
  657. if (object.ReferenceEquals(leftSide, null))
  658. {
  659. throw new ArgumentNullException("leftSide");
  660. }
  661. if (object.ReferenceEquals(rightSide, null))
  662. {
  663. throw new ArgumentNullException("rightSide");
  664. }
  665. bool leftSideNeg = leftSide.IsNegative;
  666. bool rightSideNeg = rightSide.IsNegative;
  667. leftSide = Abs(leftSide);
  668. rightSide = Abs(rightSide);
  669. DigitsArray da = new DigitsArray(leftSide.m_digits.DataUsed + rightSide.m_digits.DataUsed);
  670. da.DataUsed = da.Count;
  671. for (int i = 0; i < leftSide.m_digits.DataUsed; i++)
  672. {
  673. ulong carry = 0;
  674. for (int j = 0, k = i; j < rightSide.m_digits.DataUsed; j++, k++)
  675. {
  676. ulong val = ((ulong)leftSide.m_digits[i] * (ulong)rightSide.m_digits[j]) + (ulong)da[k] + carry;
  677. da[k] = (DType)(val & DigitsArray.AllBits);
  678. carry = (val >> DigitsArray.DataSizeBits);
  679. }
  680. if (carry != 0)
  681. {
  682. da[i + rightSide.m_digits.DataUsed] = (DType)carry;
  683. }
  684. }
  685. //da.ResetDataUsed();
  686. BigInteger result = new BigInteger(da);
  687. return (leftSideNeg != rightSideNeg ? -result : result);
  688. }
  689. /// <summary>
  690. /// Multiply two BigIntegers returning the result.
  691. /// </summary>
  692. /// <param name="leftSide">A BigInteger.</param>
  693. /// <param name="rightSide">A BigInteger</param>
  694. /// <returns></returns>
  695. public static BigInteger Multiply(BigInteger leftSide, BigInteger rightSide)
  696. {
  697. return leftSide * rightSide;
  698. }
  699. /// <summary>
  700. /// Divide a BigInteger by another BigInteger and returning the result.
  701. /// </summary>
  702. /// <param name="leftSide">A BigInteger divisor.</param>
  703. /// <param name="rightSide">A BigInteger dividend.</param>
  704. /// <returns>The BigInteger result.</returns>
  705. public static BigInteger operator / (BigInteger leftSide, BigInteger rightSide)
  706. {
  707. if (leftSide == null)
  708. {
  709. throw new ArgumentNullException("leftSide");
  710. }
  711. if (rightSide == null)
  712. {
  713. throw new ArgumentNullException("rightSide");
  714. }
  715. if (rightSide.IsZero)
  716. {
  717. throw new DivideByZeroException();
  718. }
  719. bool divisorNeg = rightSide.IsNegative;
  720. bool dividendNeg = leftSide.IsNegative;
  721. leftSide = Abs(leftSide);
  722. rightSide = Abs(rightSide);
  723. if (leftSide < rightSide)
  724. {
  725. return new BigInteger(0);
  726. }
  727. BigInteger quotient;
  728. BigInteger remainder;
  729. Divide(leftSide, rightSide, out quotient, out remainder);
  730. return (dividendNeg != divisorNeg ? -quotient : quotient);
  731. }
  732. /// <summary>
  733. /// Divide a BigInteger by another BigInteger and returning the result.
  734. /// </summary>
  735. /// <param name="leftSide">A BigInteger divisor.</param>
  736. /// <param name="rightSide">A BigInteger dividend.</param>
  737. /// <returns>The BigInteger result.</returns>
  738. public static BigInteger Divide(BigInteger leftSide, BigInteger rightSide)
  739. {
  740. return leftSide / rightSide;
  741. }
  742. private static void Divide(BigInteger leftSide, BigInteger rightSide, out BigInteger quotient, out BigInteger remainder)
  743. {
  744. if (leftSide.IsZero)
  745. {
  746. quotient = new BigInteger();
  747. remainder = new BigInteger();
  748. return;
  749. }
  750. if (rightSide.m_digits.DataUsed == 1)
  751. {
  752. SingleDivide(leftSide, rightSide, out quotient, out remainder);
  753. }
  754. else
  755. {
  756. MultiDivide(leftSide, rightSide, out quotient, out remainder);
  757. }
  758. }
  759. private static void MultiDivide(BigInteger leftSide, BigInteger rightSide, out BigInteger quotient, out BigInteger remainder)
  760. {
  761. if (rightSide.IsZero)
  762. {
  763. throw new DivideByZeroException();
  764. }
  765. DType val = rightSide.m_digits[rightSide.m_digits.DataUsed - 1];
  766. int d = 0;
  767. for (uint mask = DigitsArray.HiBitSet; mask != 0 && (val & mask) == 0; mask >>= 1)
  768. {
  769. d++;
  770. }
  771. int remainderLen = leftSide.m_digits.DataUsed + 1;
  772. DType[] remainderDat = new DType[remainderLen];
  773. leftSide.m_digits.CopyTo(remainderDat, 0, leftSide.m_digits.DataUsed);
  774. DigitsArray.ShiftLeft(remainderDat, d);
  775. rightSide = rightSide << d;
  776. ulong firstDivisor = rightSide.m_digits[rightSide.m_digits.DataUsed - 1];
  777. ulong secondDivisor = (rightSide.m_digits.DataUsed < 2 ? (DType)0 : rightSide.m_digits[rightSide.m_digits.DataUsed - 2]);
  778. int divisorLen = rightSide.m_digits.DataUsed + 1;
  779. DigitsArray dividendPart = new DigitsArray(divisorLen, divisorLen);
  780. DType[] result = new DType[leftSide.m_digits.Count + 1];
  781. int resultPos = 0;
  782. ulong carryBit = (ulong)0x1 << DigitsArray.DataSizeBits; // 0x100000000
  783. for (int j = remainderLen - rightSide.m_digits.DataUsed, pos = remainderLen - 1; j > 0; j--, pos--)
  784. {
  785. ulong dividend = ((ulong)remainderDat[pos] << DigitsArray.DataSizeBits) + (ulong)remainderDat[pos - 1];
  786. ulong qHat = (dividend / firstDivisor);
  787. ulong rHat = (dividend % firstDivisor);
  788. while (pos >= 2)
  789. {
  790. if (qHat == carryBit || (qHat * secondDivisor) > ((rHat << DigitsArray.DataSizeBits) + remainderDat[pos - 2]))
  791. {
  792. qHat--;
  793. rHat += firstDivisor;
  794. if (rHat < carryBit)
  795. {
  796. continue;
  797. }
  798. }
  799. break;
  800. }
  801. for (int h = 0; h < divisorLen; h++)
  802. {
  803. dividendPart[divisorLen - h - 1] = remainderDat[pos - h];
  804. }
  805. BigInteger dTemp = new BigInteger(dividendPart);
  806. BigInteger rTemp = rightSide * (long)qHat;
  807. while (rTemp > dTemp)
  808. {
  809. qHat--;
  810. rTemp -= rightSide;
  811. }
  812. rTemp = dTemp - rTemp;
  813. for (int h = 0; h < divisorLen; h++)
  814. {
  815. remainderDat[pos - h] = rTemp.m_digits[rightSide.m_digits.DataUsed - h];
  816. }
  817. result[resultPos++] = (DType)qHat;
  818. }
  819. Array.Reverse(result, 0, resultPos);
  820. quotient = new BigInteger(new DigitsArray(result));
  821. int n = DigitsArray.ShiftRight(remainderDat, d);
  822. DigitsArray rDA = new DigitsArray(n, n);
  823. rDA.CopyFrom(remainderDat, 0, 0, rDA.DataUsed);
  824. remainder = new BigInteger(rDA);
  825. }
  826. private static void SingleDivide(BigInteger leftSide, BigInteger rightSide, out BigInteger quotient, out BigInteger remainder)
  827. {
  828. if (rightSide.IsZero)
  829. {
  830. throw new DivideByZeroException();
  831. }
  832. DigitsArray remainderDigits = new DigitsArray(leftSide.m_digits);
  833. remainderDigits.ResetDataUsed();
  834. int pos = remainderDigits.DataUsed - 1;
  835. ulong divisor = (ulong)rightSide.m_digits[0];
  836. ulong dividend = (ulong)remainderDigits[pos];
  837. DType[] result = new DType[leftSide.m_digits.Count];
  838. leftSide.m_digits.CopyTo(result, 0, result.Length);
  839. int resultPos = 0;
  840. if (dividend >= divisor)
  841. {
  842. result[resultPos++] = (DType)(dividend / divisor);
  843. remainderDigits[pos] = (DType)(dividend % divisor);
  844. }
  845. pos--;
  846. while (pos >= 0)
  847. {
  848. dividend = ((ulong)(remainderDigits[pos + 1]) << DigitsArray.DataSizeBits) + (ulong)remainderDigits[pos];
  849. result[resultPos++] = (DType)(dividend / divisor);
  850. remainderDigits[pos + 1] = 0;
  851. remainderDigits[pos--] = (DType)(dividend % divisor);
  852. }
  853. remainder = new BigInteger(remainderDigits);
  854. DigitsArray quotientDigits = new DigitsArray(resultPos + 1, resultPos);
  855. int j = 0;
  856. for (int i = quotientDigits.DataUsed - 1; i >= 0; i--, j++)
  857. {
  858. quotientDigits[j] = result[i];
  859. }
  860. quotient = new BigInteger(quotientDigits);
  861. }
  862. /// <summary>
  863. /// Perform the modulus of a BigInteger with another BigInteger and return the result.
  864. /// </summary>
  865. /// <param name="leftSide">A BigInteger divisor.</param>
  866. /// <param name="rightSide">A BigInteger dividend.</param>
  867. /// <returns>The BigInteger result.</returns>
  868. public static BigInteger operator % (BigInteger leftSide, BigInteger rightSide)
  869. {
  870. if (leftSide == null)
  871. {
  872. throw new ArgumentNullException("leftSide");
  873. }
  874. if (rightSide == null)
  875. {
  876. throw new ArgumentNullException("rightSide");
  877. }
  878. if (rightSide.IsZero)
  879. {
  880. throw new DivideByZeroException();
  881. }
  882. BigInteger quotient;
  883. BigInteger remainder;
  884. bool dividendNeg = leftSide.IsNegative;
  885. leftSide = Abs(leftSide);
  886. rightSide = Abs(rightSide);
  887. if (leftSide < rightSide)
  888. {
  889. return leftSide;
  890. }
  891. Divide(leftSide, rightSide, out quotient, out remainder);
  892. return (dividendNeg ? -remainder : remainder);
  893. }
  894. /// <summary>
  895. /// Perform the modulus of a BigInteger with another BigInteger and return the result.
  896. /// </summary>
  897. /// <param name="leftSide">A BigInteger divisor.</param>
  898. /// <param name="rightSide">A BigInteger dividend.</param>
  899. /// <returns>The BigInteger result.</returns>
  900. public static BigInteger Modulus(BigInteger leftSide, BigInteger rightSide)
  901. {
  902. return leftSide % rightSide;
  903. }
  904. #endregion
  905. #region Bitwise Operator Overloads
  906. public static BigInteger operator & (BigInteger leftSide, BigInteger rightSide)
  907. {
  908. int len = System.Math.Max(leftSide.m_digits.DataUsed, rightSide.m_digits.DataUsed);
  909. DigitsArray da = new DigitsArray(len, len);
  910. for (int idx = 0; idx < len; idx++)
  911. {
  912. da[idx] = (DType)(leftSide.m_digits[idx] & rightSide.m_digits[idx]);
  913. }
  914. return new BigInteger(da);
  915. }
  916. public static BigInteger BitwiseAnd(BigInteger leftSide, BigInteger rightSide)
  917. {
  918. return leftSide & rightSide;
  919. }
  920. public static BigInteger operator | (BigInteger leftSide, BigInteger rightSide)
  921. {
  922. int len = System.Math.Max(leftSide.m_digits.DataUsed, rightSide.m_digits.DataUsed);
  923. DigitsArray da = new DigitsArray(len, len);
  924. for (int idx = 0; idx < len; idx++)
  925. {
  926. da[idx] = (DType)(leftSide.m_digits[idx] | rightSide.m_digits[idx]);
  927. }
  928. return new BigInteger(da);
  929. }
  930. public static BigInteger BitwiseOr(BigInteger leftSide, BigInteger rightSide)
  931. {
  932. return leftSide | rightSide;
  933. }
  934. public static BigInteger operator ^ (BigInteger leftSide, BigInteger rightSide)
  935. {
  936. int len = System.Math.Max(leftSide.m_digits.DataUsed, rightSide.m_digits.DataUsed);
  937. DigitsArray da = new DigitsArray(len, len);
  938. for (int idx = 0; idx < len; idx++)
  939. {
  940. da[idx] = (DType)(leftSide.m_digits[idx] ^ rightSide.m_digits[idx]);
  941. }
  942. return new BigInteger(da);
  943. }
  944. public static BigInteger Xor(BigInteger leftSide, BigInteger rightSide)
  945. {
  946. return leftSide ^ rightSide;
  947. }
  948. public static BigInteger operator ~ (BigInteger leftSide)
  949. {
  950. DigitsArray da = new DigitsArray(leftSide.m_digits.Count);
  951. for(int idx = 0; idx < da.Count; idx++)
  952. {
  953. da[idx] = (DType)(~(leftSide.m_digits[idx]));
  954. }
  955. return new BigInteger(da);
  956. }
  957. public static BigInteger OnesComplement(BigInteger leftSide)
  958. {
  959. return ~leftSide;
  960. }
  961. #endregion
  962. #region Left and Right Shift Operator Overloads
  963. public static BigInteger operator << (BigInteger leftSide, int shiftCount)
  964. {
  965. if (leftSide == null)
  966. {
  967. throw new ArgumentNullException("leftSide");
  968. }
  969. DigitsArray da = new DigitsArray(leftSide.m_digits);
  970. da.DataUsed = da.ShiftLeftWithoutOverflow(shiftCount);
  971. return new BigInteger(da);
  972. }
  973. public static BigInteger LeftShift(BigInteger leftSide, int shiftCount)
  974. {
  975. return leftSide << shiftCount;
  976. }
  977. public static BigInteger operator >> (BigInteger leftSide, int shiftCount)
  978. {
  979. if (leftSide == null)
  980. {
  981. throw new ArgumentNullException("leftSide");
  982. }
  983. DigitsArray da = new DigitsArray(leftSide.m_digits);
  984. da.DataUsed = da.ShiftRight(shiftCount);
  985. if (leftSide.IsNegative)
  986. {
  987. for (int i = da.Count - 1; i >= da.DataUsed; i--)
  988. {
  989. da[i] = DigitsArray.AllBits;
  990. }
  991. DType mask = DigitsArray.HiBitSet;
  992. for (int i = 0; i < DigitsArray.DataSizeBits; i++)
  993. {
  994. if ((da[da.DataUsed - 1] & mask) == DigitsArray.HiBitSet)
  995. {
  996. break;
  997. }
  998. da[da.DataUsed - 1] |= mask;
  999. mask >>= 1;
  1000. }
  1001. da.DataUsed = da.Count;
  1002. }
  1003. return new BigInteger(da);
  1004. }
  1005. public static BigInteger RightShift(BigInteger leftSide, int shiftCount)
  1006. {
  1007. if (leftSide == null)
  1008. {
  1009. throw new ArgumentNullException("leftSide");
  1010. }
  1011. return leftSide >> shiftCount;
  1012. }
  1013. #endregion
  1014. #region Relational Operator Overloads
  1015. /// <summary>
  1016. /// Compare this instance to a specified object and returns indication of their relative value.
  1017. /// </summary>
  1018. /// <param name="value">An object to compare, or a null reference (<b>Nothing</b> in Visual Basic).</param>
  1019. /// <returns>A signed number indicating the relative value of this instance and <i>value</i>.
  1020. /// <list type="table">
  1021. /// <listheader>
  1022. /// <term>Return Value</term>
  1023. /// <description>Description</description>
  1024. /// </listheader>
  1025. /// <item>
  1026. /// <term>Less than zero</term>
  1027. /// <description>This instance is less than <i>value</i>.</description>
  1028. /// </item>
  1029. /// <item>
  1030. /// <term>Zero</term>
  1031. /// <description>This instance is equal to <i>value</i>.</description>
  1032. /// </item>
  1033. /// <item>
  1034. /// <term>Greater than zero</term>
  1035. /// <description>
  1036. /// This instance is greater than <i>value</i>.
  1037. /// <para>-or-</para>
  1038. /// <i>value</i> is a null reference (<b>Nothing</b> in Visual Basic).
  1039. /// </description>
  1040. /// </item>
  1041. /// </list>
  1042. /// </returns>
  1043. public int CompareTo(BigInteger value)
  1044. {
  1045. return Compare(this, value);
  1046. }
  1047. /// <summary>
  1048. /// Compare two objects and return an indication of their relative value.
  1049. /// </summary>
  1050. /// <param name="leftSide">An object to compare, or a null reference (<b>Nothing</b> in Visual Basic).</param>
  1051. /// <param name="rightSide">An object to compare, or a null reference (<b>Nothing</b> in Visual Basic).</param>
  1052. /// <returns>A signed number indicating the relative value of this instance and <i>value</i>.
  1053. /// <list type="table">
  1054. /// <listheader>
  1055. /// <term>Return Value</term>
  1056. /// <description>Description</description>
  1057. /// </listheader>
  1058. /// <item>
  1059. /// <term>Less than zero</term>
  1060. /// <description>This instance is less than <i>value</i>.</description>
  1061. /// </item>
  1062. /// <item>
  1063. /// <term>Zero</term>
  1064. /// <description>This instance is equal to <i>value</i>.</description>
  1065. /// </item>
  1066. /// <item>
  1067. /// <term>Greater than zero</term>
  1068. /// <description>
  1069. /// This instance is greater than <i>value</i>.
  1070. /// <para>-or-</para>
  1071. /// <i>value</i> is a null reference (<b>Nothing</b> in Visual Basic).
  1072. /// </description>
  1073. /// </item>
  1074. /// </list>
  1075. /// </returns>
  1076. public static int Compare(BigInteger leftSide, BigInteger rightSide)
  1077. {
  1078. if (object.ReferenceEquals(leftSide, rightSide))
  1079. {
  1080. return 0;
  1081. }
  1082. if (object.ReferenceEquals(leftSide, null))
  1083. {
  1084. throw new ArgumentNullException("leftSide");
  1085. }
  1086. if (object.ReferenceEquals(rightSide, null))
  1087. {
  1088. throw new ArgumentNullException("rightSide");
  1089. }
  1090. if (leftSide > rightSide) return 1;
  1091. if (leftSide == rightSide) return 0;
  1092. return -1;
  1093. }
  1094. public static bool operator == (BigInteger leftSide, BigInteger rightSide)
  1095. {
  1096. if (object.ReferenceEquals(leftSide, rightSide))
  1097. {
  1098. return true;
  1099. }
  1100. if (object.ReferenceEquals(leftSide, null ) || object.ReferenceEquals(rightSide, null ))
  1101. {
  1102. return false;
  1103. }
  1104. if (leftSide.IsNegative != rightSide.IsNegative)
  1105. {
  1106. return false;
  1107. }
  1108. return leftSide.Equals(rightSide);
  1109. }
  1110. public static bool operator != (BigInteger leftSide, BigInteger rightSide)
  1111. {
  1112. return !(leftSide == rightSide);
  1113. }
  1114. public static bool operator > (BigInteger leftSide, BigInteger rightSide)
  1115. {
  1116. if (object.ReferenceEquals(leftSide, null))
  1117. {
  1118. throw new ArgumentNullException("leftSide");
  1119. }
  1120. if (object.ReferenceEquals(rightSide, null))
  1121. {
  1122. throw new ArgumentNullException("rightSide");
  1123. }
  1124. if (leftSide.IsNegative != rightSide.IsNegative)
  1125. {
  1126. return rightSide.IsNegative;
  1127. }
  1128. if (leftSide.m_digits.DataUsed != rightSide.m_digits.DataUsed)
  1129. {
  1130. return leftSide.m_digits.DataUsed > rightSide.m_digits.DataUsed;
  1131. }
  1132. for (int idx = leftSide.m_digits.DataUsed - 1; idx >= 0; idx--)
  1133. {
  1134. if (leftSide.m_digits[idx] != rightSide.m_digits[idx])
  1135. {
  1136. return (leftSide.m_digits[idx] > rightSide.m_digits[idx]);
  1137. }
  1138. }
  1139. return false;
  1140. }
  1141. public static bool operator < (BigInteger leftSide, BigInteger rightSide)
  1142. {
  1143. if (object.ReferenceEquals(leftSide, null))
  1144. {
  1145. throw new ArgumentNullException("leftSide");
  1146. }
  1147. if (object.ReferenceEquals(rightSide, null))
  1148. {
  1149. throw new ArgumentNullException("rightSide");
  1150. }
  1151. if (leftSide.IsNegative != rightSide.IsNegative)
  1152. {
  1153. return leftSide.IsNegative;
  1154. }
  1155. if (leftSide.m_digits.DataUsed != rightSide.m_digits.DataUsed)
  1156. {
  1157. return leftSide.m_digits.DataUsed < rightSide.m_digits.DataUsed;
  1158. }
  1159. for (int idx = leftSide.m_digits.DataUsed - 1; idx >= 0; idx--)
  1160. {
  1161. if (leftSide.m_digits[idx] != rightSide.m_digits[idx])
  1162. {
  1163. return (leftSide.m_digits[idx] < rightSide.m_digits[idx]);
  1164. }
  1165. }
  1166. return false;
  1167. }
  1168. public static bool operator >= (BigInteger leftSide, BigInteger rightSide)
  1169. {
  1170. return Compare(leftSide, rightSide) >= 0;
  1171. }
  1172. public static bool operator <= (BigInteger leftSide, BigInteger rightSide)
  1173. {
  1174. return Compare(leftSide, rightSide) <= 0;
  1175. }
  1176. #endregion
  1177. #region Object Overrides
  1178. /// <summary>
  1179. /// Determines whether two Object instances are equal.
  1180. /// </summary>
  1181. /// <param name="obj">An <see cref="System.Object">Object</see> to compare with this instance.</param>
  1182. /// <returns></returns>
  1183. /// <seealso cref="System.Object">System.Object</seealso>
  1184. public override bool Equals(object obj)
  1185. {
  1186. if (object.ReferenceEquals(obj, null))
  1187. {
  1188. return false;
  1189. }
  1190. if (object.ReferenceEquals(this, obj))
  1191. {
  1192. return true;
  1193. }
  1194. BigInteger c = (BigInteger)obj;
  1195. if (this.m_digits.DataUsed != c.m_digits.DataUsed)
  1196. {
  1197. return false;
  1198. }
  1199. for (int idx = 0; idx < this.m_digits.DataUsed; idx++)
  1200. {
  1201. if (this.m_digits[idx] != c.m_digits[idx])
  1202. {
  1203. return false;
  1204. }
  1205. }
  1206. return true;
  1207. }
  1208. /// <summary>
  1209. /// Returns the hash code for this instance.
  1210. /// </summary>
  1211. /// <returns>A 32-bit signed integer has code.</returns>
  1212. /// <seealso cref="System.Object">System.Object</seealso>
  1213. public override int GetHashCode()
  1214. {
  1215. return this.m_digits.GetHashCode();
  1216. }
  1217. /// <summary>
  1218. /// Converts the numeric value of this instance to its equivalent base 10 string representation.
  1219. /// </summary>
  1220. /// <returns>A <see cref="System.String">String</see> in base 10.</returns>
  1221. /// <seealso cref="System.Object">System.Object</seealso>
  1222. public override string ToString()
  1223. {
  1224. return ToString(10);
  1225. }
  1226. #endregion
  1227. #region Type Conversion Methods
  1228. /// <summary>
  1229. /// Converts the numeric value of this instance to its equivalent string representation in specified base.
  1230. /// </summary>
  1231. /// <param name="radix">Int radix between 2 and 36</param>
  1232. /// <returns>A string.</returns>
  1233. public string ToString(int radix)
  1234. {
  1235. if (radix < 2 || radix > 36)
  1236. {
  1237. throw new ArgumentOutOfRangeException("radix");
  1238. }
  1239. if (IsZero)
  1240. {
  1241. return "0";
  1242. }
  1243. BigInteger a = this;
  1244. bool negative = a.IsNegative;
  1245. a = Abs(this);
  1246. BigInteger quotient;
  1247. BigInteger remainder;
  1248. BigInteger biRadix = new BigInteger(radix);
  1249. const string charSet = "0123456789abcdefghijklmnopqrstuvwxyz";
  1250. System.Collections.ArrayList al = new System.Collections.ArrayList();
  1251. while (a.m_digits.DataUsed > 1 || (a.m_digits.DataUsed == 1 && a.m_digits[0] != 0))
  1252. {
  1253. Divide(a, biRadix, out quotient, out remainder);
  1254. al.Insert(0, charSet[(int)remainder.m_digits[0]]);
  1255. a = quotient;
  1256. }
  1257. string result = new String((char[])al.ToArray(typeof(char)));
  1258. if (radix == 10 && negative)
  1259. {
  1260. return "-" + result;
  1261. }
  1262. return result;
  1263. }
  1264. /// <summary>
  1265. /// Returns string in hexidecimal of the internal digit representation.
  1266. /// </summary>
  1267. /// <remarks>
  1268. /// This is not the same as ToString(16). This method does not return the sign, but instead
  1269. /// dumps the digits array into a string representation in base 16.
  1270. /// </remarks>
  1271. /// <returns>A string in base 16.</returns>
  1272. public string ToHexString()
  1273. {
  1274. System.Text.StringBuilder sb = new System.Text.StringBuilder();
  1275. sb.AppendFormat("{0:X}", m_digits[m_digits.DataUsed - 1]);
  1276. string f = "{0:X" + (2 * DigitsArray.DataSizeOf) + "}";
  1277. for (int i = m_digits.DataUsed - 2; i >= 0; i--)
  1278. {
  1279. sb.AppendFormat(f, m_digits[i]);
  1280. }
  1281. return sb.ToString();
  1282. }
  1283. /// <summary>
  1284. /// Returns BigInteger as System.Int16 if possible.
  1285. /// </summary>
  1286. /// <param name="value"></param>
  1287. /// <returns>Int value of BigInteger</returns>
  1288. /// <exception cref="System.Exception">When BigInteger is too large to fit into System.Int16</exception>
  1289. public static int ToInt16(BigInteger value)
  1290. {
  1291. if (object.ReferenceEquals(value, null))
  1292. {
  1293. throw new ArgumentNullException("value");
  1294. }
  1295. return System.Int16.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);
  1296. }
  1297. /// <summary>
  1298. /// Returns BigInteger as System.UInt16 if possible.
  1299. /// </summary>
  1300. /// <param name="value"></param>
  1301. /// <returns></returns>
  1302. /// <exception cref="System.Exception">When BigInteger is too large to fit into System.UInt16</exception>
  1303. public static uint ToUInt16(BigInteger value)
  1304. {
  1305. if (object.ReferenceEquals(value, null))
  1306. {
  1307. throw new ArgumentNullException("value");
  1308. }
  1309. return System.UInt16.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);
  1310. }
  1311. /// <summary>
  1312. /// Returns BigInteger as System.Int32 if possible.
  1313. /// </summary>
  1314. /// <param name="value"></param>
  1315. /// <returns></returns>
  1316. /// <exception cref="System.Exception">When BigInteger is too large to fit into System.Int32</exception>
  1317. public static int ToInt32(BigInteger value)
  1318. {
  1319. if (object.ReferenceEquals(value, null))
  1320. {
  1321. throw new ArgumentNullException("value");
  1322. }
  1323. return System.Int32.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);
  1324. }
  1325. /// <summary>
  1326. /// Returns BigInteger as System.UInt32 if possible.
  1327. /// </summary>
  1328. /// <param name="value"></param>
  1329. /// <returns></returns>
  1330. /// <exception cref="System.Exception">When BigInteger is too large to fit into System.UInt32</exception>
  1331. public static uint ToUInt32(BigInteger value)
  1332. {
  1333. if (object.ReferenceEquals(value, null))
  1334. {
  1335. throw new ArgumentNullException("value");
  1336. }
  1337. return System.UInt32.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);
  1338. }
  1339. /// <summary>
  1340. /// Returns BigInteger as System.Int64 if possible.
  1341. /// </summary>
  1342. /// <param name="value"></param>
  1343. /// <returns></returns>
  1344. /// <exception cref="System.Exception">When BigInteger is too large to fit into System.Int64</exception>
  1345. public static long ToInt64(BigInteger value)
  1346. {
  1347. if (object.ReferenceEquals(value, null))
  1348. {
  1349. throw new ArgumentNullException("value");
  1350. }
  1351. return System.Int64.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);
  1352. }
  1353. /// <summary>
  1354. /// Returns BigInteger as System.UInt64 if possible.
  1355. /// </summary>
  1356. /// <param name="value"></param>
  1357. /// <returns></returns>
  1358. /// <exception cref="System.Exception">When BigInteger is too large to fit into System.UInt64</exception>
  1359. public static ulong ToUInt64(BigInteger value)
  1360. {
  1361. if (object.ReferenceEquals(value, null))
  1362. {
  1363. throw new ArgumentNullException("value");
  1364. }
  1365. return System.UInt64.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);
  1366. }
  1367. internal object ToString(string v)
  1368. {
  1369. throw new NotImplementedException();
  1370. }
  1371. #endregion
  1372. }
  1373. }