PageRenderTime 64ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/NekoKun.Serialization.RubyMarshal/Objects/RubyBignum.cs

https://bitbucket.org/nekokun/nekokun
C# | 2345 lines | 2151 code | 188 blank | 6 comment | 441 complexity | d534b93957d902fce8d6e929b9678ab0 MD5 | raw file
Possible License(s): MIT, CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Globalization;
  5. namespace NekoKun.Serialization.RubyMarshal
  6. {
  7. //disassembled from Microsoft.Scripting.Math.RubyBignum @ Microsoft.Dynamic, Version=1.0.0.0
  8. [Serializable]
  9. public sealed class RubyBignum : RubyObject, IFormattable, IComparable, IConvertible, IEquatable<RubyBignum>
  10. {
  11. // Fields
  12. private const ulong Base = 0x100000000L;
  13. private const int bias = 0x433;
  14. private const int BitsPerDigit = 0x20;
  15. private readonly uint[] data;
  16. private const int DecimalScaleFactorMask = 0xff0000;
  17. private const int DecimalSignMask = -2147483648;
  18. public static readonly RubyBignum One = new RubyBignum(1, new uint[] { 1 });
  19. private readonly short sign;
  20. public static readonly RubyBignum Zero = new RubyBignum(0, new uint[0]);
  21. // Methods
  22. public RubyBignum(RubyBignum copy)
  23. {
  24. if (object.ReferenceEquals(copy, null))
  25. {
  26. throw new ArgumentNullException("copy");
  27. }
  28. this.sign = copy.sign;
  29. this.data = copy.data;
  30. this.ClassName = RubySymbol.GetSymbol("Bignum");
  31. }
  32. public RubyBignum(byte[] bytes)
  33. : this(Create(bytes))
  34. {
  35. }
  36. public RubyBignum(int sign, params uint[] data)
  37. {
  38. ContractUtils.RequiresNotNull(data, "data");
  39. ContractUtils.Requires((sign >= -1) && (sign <= 1), "sign");
  40. int length = GetLength(data);
  41. ContractUtils.Requires((length == 0) || (sign != 0), "sign");
  42. this.data = data;
  43. this.sign = (length == 0) ? ((short)0) : ((short)sign);
  44. this.ClassName = RubySymbol.GetSymbol("Bignum");
  45. }
  46. public RubyBignum Abs()
  47. {
  48. if (this.sign == -1)
  49. {
  50. return -this;
  51. }
  52. return this;
  53. }
  54. public static RubyBignum Add(RubyBignum x, RubyBignum y)
  55. {
  56. return (x + y);
  57. }
  58. private static uint[] add0(uint[] x, int xl, uint[] y, int yl)
  59. {
  60. if (xl >= yl)
  61. {
  62. return InternalAdd(x, xl, y, yl);
  63. }
  64. return InternalAdd(y, yl, x, xl);
  65. }
  66. public bool AsDecimal(out decimal ret)
  67. {
  68. if (this.sign == 0)
  69. {
  70. ret = 0M;
  71. return true;
  72. }
  73. int length = this.GetLength();
  74. if (length > 3)
  75. {
  76. ret = 0M;
  77. return false;
  78. }
  79. int lo = 0;
  80. int mid = 0;
  81. int hi = 0;
  82. if (length > 2)
  83. {
  84. hi = (int)this.data[2];
  85. }
  86. if (length > 1)
  87. {
  88. mid = (int)this.data[1];
  89. }
  90. if (length > 0)
  91. {
  92. lo = (int)this.data[0];
  93. }
  94. ret = new decimal(lo, mid, hi, this.sign < 0, 0);
  95. return true;
  96. }
  97. public bool AsInt32(out int ret)
  98. {
  99. ret = 0;
  100. if (this.sign != 0)
  101. {
  102. if (this.GetLength() > 1)
  103. {
  104. return false;
  105. }
  106. if (this.data[0] > 0x80000000)
  107. {
  108. return false;
  109. }
  110. if ((this.data[0] == 0x80000000) && (this.sign == 1))
  111. {
  112. return false;
  113. }
  114. ret = (int)this.data[0];
  115. ret *= this.sign;
  116. }
  117. return true;
  118. }
  119. public bool AsInt64(out long ret)
  120. {
  121. ret = 0L;
  122. if (this.sign != 0)
  123. {
  124. if (this.GetLength() > 2)
  125. {
  126. return false;
  127. }
  128. if (this.data.Length == 1)
  129. {
  130. ret = this.sign * this.data[0];
  131. return true;
  132. }
  133. ulong num = (this.data[1] << 0x20) | this.data[0];
  134. if (num > 9223372036854775808L)
  135. {
  136. return false;
  137. }
  138. if ((num == 9223372036854775808L) && (this.sign == 1))
  139. {
  140. return false;
  141. }
  142. ret = (long)(num) * this.sign;
  143. }
  144. return true;
  145. }
  146. public bool AsUInt32(out uint ret)
  147. {
  148. ret = 0;
  149. if (this.sign != 0)
  150. {
  151. if (this.sign < 0)
  152. {
  153. return false;
  154. }
  155. if (this.GetLength() > 1)
  156. {
  157. return false;
  158. }
  159. ret = this.data[0];
  160. }
  161. return true;
  162. }
  163. public bool AsUInt64(out ulong ret)
  164. {
  165. ret = 0L;
  166. if (this.sign != 0)
  167. {
  168. if (this.sign < 0)
  169. {
  170. return false;
  171. }
  172. if (this.GetLength() > 2)
  173. {
  174. return false;
  175. }
  176. ret = this.data[0];
  177. if (this.data.Length > 1)
  178. {
  179. ret |= this.data[1] << 0x20;
  180. }
  181. }
  182. return true;
  183. }
  184. public static RubyBignum BitwiseAnd(RubyBignum x, RubyBignum y)
  185. {
  186. return (x & y);
  187. }
  188. public static RubyBignum BitwiseOr(RubyBignum x, RubyBignum y)
  189. {
  190. return (x | y);
  191. }
  192. public static int Compare(RubyBignum x, RubyBignum y)
  193. {
  194. if (object.ReferenceEquals(x, null))
  195. {
  196. throw new ArgumentNullException("x");
  197. }
  198. if (object.ReferenceEquals(y, null))
  199. {
  200. throw new ArgumentNullException("y");
  201. }
  202. if (x.sign == y.sign)
  203. {
  204. int length = x.GetLength();
  205. int num2 = y.GetLength();
  206. if (length == num2)
  207. {
  208. for (int i = length - 1; i >= 0; i--)
  209. {
  210. if (x.data[i] != y.data[i])
  211. {
  212. if (x.data[i] <= y.data[i])
  213. {
  214. return -x.sign;
  215. }
  216. return x.sign;
  217. }
  218. }
  219. return 0;
  220. }
  221. if (length <= num2)
  222. {
  223. return -x.sign;
  224. }
  225. return x.sign;
  226. }
  227. if (x.sign <= y.sign)
  228. {
  229. return -1;
  230. }
  231. return 1;
  232. }
  233. public int CompareTo(object obj)
  234. {
  235. if (obj == null)
  236. {
  237. return 1;
  238. }
  239. RubyBignum objA = obj as RubyBignum;
  240. if (object.ReferenceEquals(objA, null))
  241. {
  242. throw new ArgumentException("expected integer");
  243. }
  244. return Compare(this, objA);
  245. }
  246. private static uint[] copy(uint[] v)
  247. {
  248. uint[] destinationArray = new uint[v.Length];
  249. Array.Copy(v, destinationArray, v.Length);
  250. return destinationArray;
  251. }
  252. public static RubyBignum Create(decimal v)
  253. {
  254. int[] bits = decimal.GetBits(decimal.Truncate(v));
  255. int num = 3;
  256. while ((num > 0) && (bits[num - 1] == 0))
  257. {
  258. num--;
  259. }
  260. if (num == 0)
  261. {
  262. return Zero;
  263. }
  264. uint[] data = new uint[num];
  265. data[0] = (uint)bits[0];
  266. if (num > 1)
  267. {
  268. data[1] = (uint)bits[1];
  269. }
  270. if (num > 2)
  271. {
  272. data[2] = (uint)bits[2];
  273. }
  274. return new RubyBignum(((bits[3] & -2147483648) != 0) ? -1 : 1, data);
  275. }
  276. public static RubyBignum Create(double v)
  277. {
  278. if (double.IsNaN(v) || double.IsInfinity(v))
  279. {
  280. throw new OverflowException();
  281. }
  282. byte[] bytes = BitConverter.GetBytes(v);
  283. ulong num = Mantissa(bytes);
  284. if (num == 0L)
  285. {
  286. int num2 = Exponent(bytes);
  287. if (num2 == 0)
  288. {
  289. return Zero;
  290. }
  291. RubyBignum integer = Negative(bytes) ? Negate(One) : One;
  292. return (integer << (num2 - 0x3ff));
  293. }
  294. int num3 = Exponent(bytes);
  295. num |= (ulong)0x10000000000000L;
  296. RubyBignum integer2 = Create(num);
  297. integer2 = (num3 > 0x433) ? (integer2 << (num3 - 0x433)) : (integer2 >> (0x433 - num3));
  298. if (!Negative(bytes))
  299. {
  300. return integer2;
  301. }
  302. return (integer2 * -1);
  303. }
  304. public static RubyBignum Create(int v)
  305. {
  306. if (v == 0)
  307. {
  308. return Zero;
  309. }
  310. if (v == 1)
  311. {
  312. return One;
  313. }
  314. if (v < 0)
  315. {
  316. return new RubyBignum(-1, new uint[] { (uint) -v });
  317. }
  318. return new RubyBignum(1, new uint[] { (uint) v });
  319. }
  320. public static RubyBignum Create(long v)
  321. {
  322. ulong num;
  323. int sign = 1;
  324. if (v < 0L)
  325. {
  326. num = (ulong)-v;
  327. sign = -1;
  328. }
  329. else
  330. {
  331. num = (ulong)v;
  332. }
  333. return new RubyBignum(sign, new uint[] { (uint)num, (uint)(num >> 0x20) });
  334. }
  335. public static RubyBignum Create(uint v)
  336. {
  337. if (v == 0)
  338. {
  339. return Zero;
  340. }
  341. if (v == 1)
  342. {
  343. return One;
  344. }
  345. return new RubyBignum(1, new uint[] { v });
  346. }
  347. public static RubyBignum Create(ulong v)
  348. {
  349. return new RubyBignum(1, new uint[] { (uint)v, (uint)(v >> 0x20) });
  350. }
  351. public static RubyBignum Create(byte[] v)
  352. {
  353. ContractUtils.RequiresNotNull(v, "v");
  354. if (v.Length == 0)
  355. {
  356. return Create(0);
  357. }
  358. int length = v.Length;
  359. int num2 = length % 4;
  360. int num3 = (length / 4) + ((num2 == 0) ? 0 : 1);
  361. uint[] d = new uint[num3];
  362. bool flag = (v[length - 1] & 0x80) == 0x80;
  363. bool flag2 = true;
  364. int index = 3;
  365. int num4 = 0;
  366. while (num4 < (num3 - ((num2 == 0) ? 0 : 1)))
  367. {
  368. for (int i = 0; i < 4; i++)
  369. {
  370. if (v[index] != 0)
  371. {
  372. flag2 = false;
  373. }
  374. d[num4] = d[num4] << 8;
  375. d[num4] |= v[index];
  376. index--;
  377. }
  378. index += 8;
  379. num4++;
  380. }
  381. if (num2 != 0)
  382. {
  383. if (flag)
  384. {
  385. d[num3 - 1] = uint.MaxValue;
  386. }
  387. for (index = length - 1; index >= (length - num2); index--)
  388. {
  389. if (v[index] != 0)
  390. {
  391. flag2 = false;
  392. }
  393. d[num4] = d[num4] << 8;
  394. d[num4] |= v[index];
  395. }
  396. }
  397. if (flag2)
  398. {
  399. return Zero;
  400. }
  401. if (flag)
  402. {
  403. makeTwosComplement(d);
  404. return new RubyBignum(-1, d);
  405. }
  406. return new RubyBignum(1, d);
  407. }
  408. public static RubyBignum Divide(RubyBignum x, RubyBignum y)
  409. {
  410. return (x / y);
  411. }
  412. private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r)
  413. {
  414. int length = GetLength(u);
  415. int l = GetLength(v);
  416. if (l <= 1)
  417. {
  418. if (l == 0)
  419. {
  420. throw new DivideByZeroException();
  421. }
  422. ulong num3 = 0L;
  423. uint num4 = v[0];
  424. q = new uint[length];
  425. r = new uint[1];
  426. for (int i = length - 1; i >= 0; i--)
  427. {
  428. num3 *= (ulong)0x100000000L;
  429. num3 += u[i];
  430. ulong num6 = num3 / ((ulong)num4);
  431. num3 -= num6 * num4;
  432. q[i] = (uint)num6;
  433. }
  434. r[0] = (uint)num3;
  435. }
  436. else if (length >= l)
  437. {
  438. int normalizeShift = GetNormalizeShift(v[l - 1]);
  439. uint[] un = new uint[length + 1];
  440. uint[] numArray2 = new uint[l];
  441. Normalize(u, length, un, normalizeShift);
  442. Normalize(v, l, numArray2, normalizeShift);
  443. q = new uint[(length - l) + 1];
  444. r = null;
  445. for (int j = length - l; j >= 0; j--)
  446. {
  447. ulong num9 = (ulong)((0x100000000L * un[j + l]) + un[(j + l) - 1]);
  448. ulong num10 = num9 / ((ulong)numArray2[l - 1]);
  449. num9 -= num10 * numArray2[l - 1];
  450. do
  451. {
  452. if ((num10 < 0x100000000L) && ((num10 * numArray2[l - 2]) <= ((num9 * ((ulong)0x100000000L)) + un[(j + l) - 2])))
  453. {
  454. break;
  455. }
  456. num10 -= (ulong)1L;
  457. num9 += numArray2[l - 1];
  458. }
  459. while (num9 < 0x100000000L);
  460. long num12 = 0L;
  461. long num13 = 0L;
  462. int index = 0;
  463. while (index < l)
  464. {
  465. ulong num14 = numArray2[index] * num10;
  466. num13 = (un[index + j] - ((uint)num14)) - num12;
  467. un[index + j] = (uint)num13;
  468. num14 = num14 >> 0x20;
  469. num13 = num13 >> 0x20;
  470. num12 = ((long)num14) - num13;
  471. index++;
  472. }
  473. num13 = un[j + l] - num12;
  474. un[j + l] = (uint)num13;
  475. q[j] = (uint)num10;
  476. if (num13 < 0L)
  477. {
  478. q[j]--;
  479. ulong num15 = 0L;
  480. for (index = 0; index < l; index++)
  481. {
  482. num15 = (numArray2[index] + un[j + index]) + num15;
  483. un[j + index] = (uint)num15;
  484. num15 = num15 >> 0x20;
  485. }
  486. num15 += un[j + l];
  487. un[j + l] = (uint)num15;
  488. }
  489. }
  490. Unnormalize(un, out r, normalizeShift);
  491. }
  492. else
  493. {
  494. uint[] numArray3 = new uint[1];
  495. q = numArray3;
  496. r = u;
  497. }
  498. }
  499. public static RubyBignum DivRem(RubyBignum x, RubyBignum y, out RubyBignum remainder)
  500. {
  501. uint[] numArray;
  502. uint[] numArray2;
  503. if (object.ReferenceEquals(x, null))
  504. {
  505. throw new ArgumentNullException("x");
  506. }
  507. if (object.ReferenceEquals(y, null))
  508. {
  509. throw new ArgumentNullException("y");
  510. }
  511. DivModUnsigned(x.data, y.data, out numArray, out numArray2);
  512. remainder = new RubyBignum(x.sign, numArray2);
  513. return new RubyBignum(x.sign * y.sign, numArray);
  514. }
  515. public bool Equals(RubyBignum other)
  516. {
  517. if (object.ReferenceEquals(other, null))
  518. {
  519. return false;
  520. }
  521. return (this == other);
  522. }
  523. public override bool Equals(object obj)
  524. {
  525. return this.Equals(obj as RubyBignum);
  526. }
  527. private static ushort Exponent(byte[] v)
  528. {
  529. return (ushort)((((ushort)(v[7] & 0x7f)) << 4) | (((ushort)(v[6] & 240)) >> 4));
  530. }
  531. private static uint extend(uint v, ref bool seenNonZero)
  532. {
  533. if (seenNonZero)
  534. {
  535. return ~v;
  536. }
  537. if (v == 0)
  538. {
  539. return 0;
  540. }
  541. seenNonZero = true;
  542. return (~v + 1);
  543. }
  544. public int GetBitCount()
  545. {
  546. if (this.IsZero())
  547. {
  548. return 1;
  549. }
  550. int index = this.GetLength() - 1;
  551. uint num2 = this.data[index];
  552. int num3 = index * 0x20;
  553. do
  554. {
  555. num2 = num2 >> 1;
  556. num3++;
  557. }
  558. while (num2 > 0);
  559. return num3;
  560. }
  561. public int GetByteCount()
  562. {
  563. return ((this.GetBitCount() + 7) / 8);
  564. }
  565. public override int GetHashCode()
  566. {
  567. if (this.data.Length == 0)
  568. {
  569. return 0;
  570. }
  571. uint num = 0;
  572. foreach (uint num2 in this.data)
  573. {
  574. num += num2;
  575. }
  576. int num3 = (int)num;
  577. if (this.IsNegative())
  578. {
  579. return -num3;
  580. }
  581. return num3;
  582. }
  583. private int GetLength()
  584. {
  585. return GetLength(this.data);
  586. }
  587. private static int GetLength(uint[] data)
  588. {
  589. int index = data.Length - 1;
  590. while ((index >= 0) && (data[index] == 0))
  591. {
  592. index--;
  593. }
  594. return (index + 1);
  595. }
  596. private static int GetNormalizeShift(uint value)
  597. {
  598. int num = 0;
  599. if ((value & 0xffff0000) == 0)
  600. {
  601. value = value << 0x10;
  602. num += 0x10;
  603. }
  604. if ((value & 0xff000000) == 0)
  605. {
  606. value = value << 8;
  607. num += 8;
  608. }
  609. if ((value & 0xf0000000) == 0)
  610. {
  611. value = value << 4;
  612. num += 4;
  613. }
  614. if ((value & 0xc0000000) == 0)
  615. {
  616. value = value << 2;
  617. num += 2;
  618. }
  619. if ((value & 0x80000000) == 0)
  620. {
  621. value = value << 1;
  622. num++;
  623. }
  624. return num;
  625. }
  626. private static uint getOne(bool isNeg, uint[] data, int i, ref bool seenNonZero)
  627. {
  628. if (i < data.Length)
  629. {
  630. uint v = data[i];
  631. if (!isNeg)
  632. {
  633. return v;
  634. }
  635. return extend(v, ref seenNonZero);
  636. }
  637. if (!isNeg)
  638. {
  639. return 0;
  640. }
  641. return uint.MaxValue;
  642. }
  643. public TypeCode GetTypeCode()
  644. {
  645. return TypeCode.Object;
  646. }
  647. public uint GetWord(int index)
  648. {
  649. return this.data[index];
  650. }
  651. public int GetWordCount()
  652. {
  653. if (this.IsZero())
  654. {
  655. return 1;
  656. }
  657. return this.GetLength();
  658. }
  659. public uint[] GetWords()
  660. {
  661. if (this.sign == 0)
  662. {
  663. return new uint[1];
  664. }
  665. int length = this.GetLength();
  666. uint[] destinationArray = new uint[length];
  667. Array.Copy(this.data, destinationArray, length);
  668. return destinationArray;
  669. }
  670. private static uint[] InternalAdd(uint[] x, int xl, uint[] y, int yl)
  671. {
  672. uint[] v = new uint[xl];
  673. ulong num2 = 0L;
  674. int index = 0;
  675. while (index < yl)
  676. {
  677. num2 = (num2 + x[index]) + y[index];
  678. v[index] = (uint)num2;
  679. num2 = num2 >> 0x20;
  680. index++;
  681. }
  682. while ((index < xl) && (num2 != 0L))
  683. {
  684. num2 += x[index];
  685. v[index] = (uint)num2;
  686. num2 = num2 >> 0x20;
  687. index++;
  688. }
  689. if (num2 == 0L)
  690. {
  691. while (index < xl)
  692. {
  693. v[index] = x[index];
  694. index++;
  695. }
  696. return v;
  697. }
  698. v = resize(v, xl + 1);
  699. v[index] = (uint)num2;
  700. return v;
  701. }
  702. public bool IsNegative()
  703. {
  704. return (this.sign < 0);
  705. }
  706. private bool IsOdd()
  707. {
  708. return (((this.data != null) && (this.data.Length > 0)) && ((this.data[0] & 1) != 0));
  709. }
  710. public bool IsPositive()
  711. {
  712. return (this.sign > 0);
  713. }
  714. public bool IsZero()
  715. {
  716. return (this.sign == 0);
  717. }
  718. public static RubyBignum LeftShift(RubyBignum x, int shift)
  719. {
  720. return (x << shift);
  721. }
  722. public double Log()
  723. {
  724. return this.Log(2.7182818284590451);
  725. }
  726. public double Log(double newBase)
  727. {
  728. if ((this.IsNegative() || (newBase == 1.0)) || ((this == Zero) || ((newBase == 0.0) && (this != One))))
  729. {
  730. return double.NaN;
  731. }
  732. if (newBase == double.PositiveInfinity)
  733. {
  734. if (!(this == One))
  735. {
  736. return double.NaN;
  737. }
  738. return 0.0;
  739. }
  740. int index = this.GetLength() - 1;
  741. int num2 = -1;
  742. for (int i = 0x1f; i >= 0; i--)
  743. {
  744. if ((this.data[index] & (((int)1) << i)) != 0L)
  745. {
  746. num2 = i + (index * 0x20);
  747. break;
  748. }
  749. }
  750. long num4 = num2;
  751. double d = 0.0;
  752. double num6 = 1.0;
  753. RubyBignum one = One;
  754. long num7 = num4;
  755. while (num7 > 0x7fffffffL)
  756. {
  757. one = one << 0x7fffffff;
  758. num7 -= 0x7fffffffL;
  759. }
  760. one = one << ((int)num7);
  761. for (long j = num4; j >= 0L; j -= 1L)
  762. {
  763. if ((this & one) != Zero)
  764. {
  765. d += num6;
  766. }
  767. num6 *= 0.5;
  768. one = one >> 1;
  769. }
  770. return ((Math.Log(d) + (Math.Log(2.0) * num4)) / Math.Log(newBase));
  771. }
  772. public double Log10()
  773. {
  774. return this.Log(10.0);
  775. }
  776. private static uint[] makeTwosComplement(uint[] d)
  777. {
  778. int index = 0;
  779. uint num2 = 0;
  780. while (index < d.Length)
  781. {
  782. num2 = ~d[index] + 1;
  783. d[index] = num2;
  784. if (num2 != 0)
  785. {
  786. index++;
  787. break;
  788. }
  789. index++;
  790. }
  791. if (num2 != 0)
  792. {
  793. while (index < d.Length)
  794. {
  795. d[index] = ~d[index];
  796. index++;
  797. }
  798. return d;
  799. }
  800. d = resize(d, d.Length + 1);
  801. d[d.Length - 1] = 1;
  802. return d;
  803. }
  804. private static ulong Mantissa(byte[] v)
  805. {
  806. uint num = (uint)(((v[0] | (v[1] << 8)) | (v[2] << 0x10)) | (v[3] << 0x18));
  807. uint num2 = (uint)((v[4] | (v[5] << 8)) | ((v[6] & 15) << 0x10));
  808. return (num | (num2 << 0x20));
  809. }
  810. public static RubyBignum Mod(RubyBignum x, RubyBignum y)
  811. {
  812. return (x % y);
  813. }
  814. public RubyBignum ModPow(RubyBignum power, RubyBignum mod)
  815. {
  816. if (object.ReferenceEquals(power, null))
  817. {
  818. throw new ArgumentNullException("power");
  819. }
  820. if (object.ReferenceEquals(mod, null))
  821. {
  822. throw new ArgumentNullException("mod");
  823. }
  824. if (power < 0)
  825. {
  826. throw new ArgumentOutOfRangeException("power", "power must be >= 0");
  827. }
  828. RubyBignum integer = this;
  829. RubyBignum integer2 = One % mod;
  830. while (power != Zero)
  831. {
  832. if (power.IsOdd())
  833. {
  834. integer2 *= integer;
  835. integer2 = integer2 % mod;
  836. }
  837. if (power == One)
  838. {
  839. return integer2;
  840. }
  841. integer = integer.Square() % mod;
  842. power = power >> 1;
  843. }
  844. return integer2;
  845. }
  846. public RubyBignum ModPow(int power, RubyBignum mod)
  847. {
  848. if (object.ReferenceEquals(mod, null))
  849. {
  850. throw new ArgumentNullException("mod");
  851. }
  852. if (power < 0)
  853. {
  854. throw new ArgumentOutOfRangeException("power", "power must be >= 0");
  855. }
  856. RubyBignum integer = this;
  857. RubyBignum integer2 = One % mod;
  858. while (power != 0)
  859. {
  860. if ((power & 1) != 0)
  861. {
  862. integer2 *= integer;
  863. integer2 = integer2 % mod;
  864. }
  865. if (power == 1)
  866. {
  867. return integer2;
  868. }
  869. integer = integer.Square() % mod;
  870. power = power >> 1;
  871. }
  872. return integer2;
  873. }
  874. public static RubyBignum Multiply(RubyBignum x, RubyBignum y)
  875. {
  876. return (x * y);
  877. }
  878. public static RubyBignum Negate(RubyBignum x)
  879. {
  880. return -x;
  881. }
  882. private static bool Negative(byte[] v)
  883. {
  884. return ((v[7] & 0x80) != 0);
  885. }
  886. private static void Normalize(uint[] u, int l, uint[] un, int shift)
  887. {
  888. int num2;
  889. uint num = 0;
  890. if (shift > 0)
  891. {
  892. int num3 = 0x20 - shift;
  893. for (num2 = 0; num2 < l; num2++)
  894. {
  895. uint num4 = u[num2];
  896. un[num2] = (num4 << shift) | num;
  897. num = num4 >> num3;
  898. }
  899. }
  900. else
  901. {
  902. num2 = 0;
  903. while (num2 < l)
  904. {
  905. un[num2] = u[num2];
  906. num2++;
  907. }
  908. }
  909. while (num2 < un.Length)
  910. {
  911. un[num2++] = 0;
  912. }
  913. if (num != 0)
  914. {
  915. un[l] = num;
  916. }
  917. }
  918. public RubyBignum OnesComplement()
  919. {
  920. return ~this;
  921. }
  922. public static RubyBignum operator +(RubyBignum x, RubyBignum y)
  923. {
  924. if (object.ReferenceEquals(x, null))
  925. {
  926. throw new ArgumentNullException("x");
  927. }
  928. if (object.ReferenceEquals(y, null))
  929. {
  930. throw new ArgumentNullException("y");
  931. }
  932. if (x.sign == y.sign)
  933. {
  934. return new RubyBignum(x.sign, add0(x.data, x.GetLength(), y.data, y.GetLength()));
  935. }
  936. return (x - new RubyBignum(-y.sign, y.data));
  937. }
  938. public static RubyBignum operator &(RubyBignum x, RubyBignum y)
  939. {
  940. if (object.ReferenceEquals(x, null))
  941. {
  942. throw new ArgumentNullException("x");
  943. }
  944. if (object.ReferenceEquals(y, null))
  945. {
  946. throw new ArgumentNullException("y");
  947. }
  948. int length = x.GetLength();
  949. int num2 = y.GetLength();
  950. uint[] data = x.data;
  951. uint[] numArray2 = y.data;
  952. int num3 = Math.Max(length, num2);
  953. uint[] d = new uint[num3];
  954. bool isNeg = x.sign == -1;
  955. bool flag2 = y.sign == -1;
  956. bool seenNonZero = false;
  957. bool flag4 = false;
  958. for (int i = 0; i < num3; i++)
  959. {
  960. uint num5 = getOne(isNeg, data, i, ref seenNonZero);
  961. uint num6 = getOne(flag2, numArray2, i, ref flag4);
  962. d[i] = num5 & num6;
  963. }
  964. if (isNeg && flag2)
  965. {
  966. return new RubyBignum(-1, makeTwosComplement(d));
  967. }
  968. if (!isNeg && !flag2)
  969. {
  970. return new RubyBignum(1, d);
  971. }
  972. return new RubyBignum(1, d);
  973. }
  974. public static RubyBignum operator |(RubyBignum x, RubyBignum y)
  975. {
  976. if (object.ReferenceEquals(x, null))
  977. {
  978. throw new ArgumentNullException("x");
  979. }
  980. if (object.ReferenceEquals(y, null))
  981. {
  982. throw new ArgumentNullException("y");
  983. }
  984. int length = x.GetLength();
  985. int num2 = y.GetLength();
  986. uint[] data = x.data;
  987. uint[] numArray2 = y.data;
  988. int num3 = Math.Max(length, num2);
  989. uint[] numArray3 = new uint[num3];
  990. bool isNeg = x.sign == -1;
  991. bool flag2 = y.sign == -1;
  992. bool seenNonZero = false;
  993. bool flag4 = false;
  994. for (int i = 0; i < num3; i++)
  995. {
  996. uint num5 = getOne(isNeg, data, i, ref seenNonZero);
  997. uint num6 = getOne(flag2, numArray2, i, ref flag4);
  998. numArray3[i] = num5 | num6;
  999. }
  1000. if ((!isNeg || !flag2) && (!isNeg && !flag2))
  1001. {
  1002. return new RubyBignum(1, numArray3);
  1003. }
  1004. return new RubyBignum(-1, makeTwosComplement(numArray3));
  1005. }
  1006. public static RubyBignum operator /(RubyBignum x, RubyBignum y)
  1007. {
  1008. RubyBignum integer;
  1009. return DivRem(x, y, out integer);
  1010. }
  1011. public static bool operator ==(RubyBignum x, RubyBignum y)
  1012. {
  1013. return (Compare(x, y) == 0);
  1014. }
  1015. public static bool operator ==(RubyBignum x, double y)
  1016. {
  1017. if (object.ReferenceEquals(x, null))
  1018. {
  1019. throw new ArgumentNullException("x");
  1020. }
  1021. if ((y % 1.0) != 0.0)
  1022. {
  1023. return false;
  1024. }
  1025. return (x == Create(y));
  1026. }
  1027. public static bool operator ==(RubyBignum x, int y)
  1028. {
  1029. return (x == y);
  1030. }
  1031. public static bool operator ==(double x, RubyBignum y)
  1032. {
  1033. return (y == x);
  1034. }
  1035. public static RubyBignum operator ^(RubyBignum x, RubyBignum y)
  1036. {
  1037. if (object.ReferenceEquals(x, null))
  1038. {
  1039. throw new ArgumentNullException("x");
  1040. }
  1041. if (object.ReferenceEquals(y, null))
  1042. {
  1043. throw new ArgumentNullException("y");
  1044. }
  1045. int length = x.GetLength();
  1046. int num2 = y.GetLength();
  1047. uint[] data = x.data;
  1048. uint[] numArray2 = y.data;
  1049. int num3 = Math.Max(length, num2);
  1050. uint[] numArray3 = new uint[num3];
  1051. bool isNeg = x.sign == -1;
  1052. bool flag2 = y.sign == -1;
  1053. bool seenNonZero = false;
  1054. bool flag4 = false;
  1055. for (int i = 0; i < num3; i++)
  1056. {
  1057. uint num5 = getOne(isNeg, data, i, ref seenNonZero);
  1058. uint num6 = getOne(flag2, numArray2, i, ref flag4);
  1059. numArray3[i] = num5 ^ num6;
  1060. }
  1061. if (isNeg && flag2)
  1062. {
  1063. return new RubyBignum(1, numArray3);
  1064. }
  1065. if (!isNeg && !flag2)
  1066. {
  1067. return new RubyBignum(1, numArray3);
  1068. }
  1069. return new RubyBignum(-1, makeTwosComplement(numArray3));
  1070. }
  1071. public static explicit operator byte(RubyBignum self)
  1072. {
  1073. int num;
  1074. if (!self.AsInt32(out num))
  1075. {
  1076. throw new OverflowException();
  1077. }
  1078. return (byte)num;
  1079. }
  1080. public static explicit operator decimal(RubyBignum self)
  1081. {
  1082. decimal num;
  1083. if (!self.AsDecimal(out num))
  1084. {
  1085. throw new OverflowException();
  1086. }
  1087. return num;
  1088. }
  1089. public static explicit operator double(RubyBignum self)
  1090. {
  1091. if (object.ReferenceEquals(self, null))
  1092. {
  1093. throw new ArgumentNullException("self");
  1094. }
  1095. return self.ToFloat64();
  1096. }
  1097. public static explicit operator short(RubyBignum self)
  1098. {
  1099. int num;
  1100. if (!self.AsInt32(out num))
  1101. {
  1102. throw new OverflowException();
  1103. }
  1104. return (short)num;
  1105. }
  1106. public static explicit operator int(RubyBignum self)
  1107. {
  1108. int num;
  1109. if (!self.AsInt32(out num))
  1110. {
  1111. throw new OverflowException();
  1112. }
  1113. return num;
  1114. }
  1115. public static explicit operator long(RubyBignum self)
  1116. {
  1117. long num;
  1118. if (!self.AsInt64(out num))
  1119. {
  1120. throw new OverflowException();
  1121. }
  1122. return num;
  1123. }
  1124. public static explicit operator sbyte(RubyBignum self)
  1125. {
  1126. int num;
  1127. if (!self.AsInt32(out num))
  1128. {
  1129. throw new OverflowException();
  1130. }
  1131. return (sbyte)num;
  1132. }
  1133. public static explicit operator float(RubyBignum self)
  1134. {
  1135. if (object.ReferenceEquals(self, null))
  1136. {
  1137. throw new ArgumentNullException("self");
  1138. }
  1139. return (float)self.ToFloat64();
  1140. }
  1141. public static explicit operator ushort(RubyBignum self)
  1142. {
  1143. int num;
  1144. if (!self.AsInt32(out num))
  1145. {
  1146. throw new OverflowException();
  1147. }
  1148. return (ushort)num;
  1149. }
  1150. public static explicit operator uint(RubyBignum self)
  1151. {
  1152. uint num;
  1153. if (!self.AsUInt32(out num))
  1154. {
  1155. throw new OverflowException();
  1156. }
  1157. return num;
  1158. }
  1159. public static explicit operator ulong(RubyBignum self)
  1160. {
  1161. ulong num;
  1162. if (!self.AsUInt64(out num))
  1163. {
  1164. throw new OverflowException();
  1165. }
  1166. return num;
  1167. }
  1168. public static explicit operator RubyBignum(double self)
  1169. {
  1170. return Create(self);
  1171. }
  1172. public static explicit operator RubyBignum(float self)
  1173. {
  1174. return Create((double)self);
  1175. }
  1176. public static bool operator >(RubyBignum x, RubyBignum y)
  1177. {
  1178. return (Compare(x, y) > 0);
  1179. }
  1180. public static bool operator >=(RubyBignum x, RubyBignum y)
  1181. {
  1182. return (Compare(x, y) >= 0);
  1183. }
  1184. public static implicit operator RubyBignum(byte i)
  1185. {
  1186. return Create((uint)i);
  1187. }
  1188. public static implicit operator RubyBignum(decimal i)
  1189. {
  1190. return Create(i);
  1191. }
  1192. public static implicit operator RubyBignum(short i)
  1193. {
  1194. return Create((int)i);
  1195. }
  1196. public static implicit operator RubyBignum(int i)
  1197. {
  1198. return Create(i);
  1199. }
  1200. public static implicit operator RubyBignum(long i)
  1201. {
  1202. return Create(i);
  1203. }
  1204. public static implicit operator RubyBignum(sbyte i)
  1205. {
  1206. return Create((int)i);
  1207. }
  1208. public static implicit operator RubyBignum(ushort i)
  1209. {
  1210. return Create((uint)i);
  1211. }
  1212. public static implicit operator RubyBignum(uint i)
  1213. {
  1214. return Create(i);
  1215. }
  1216. public static implicit operator RubyBignum(ulong i)
  1217. {
  1218. return Create(i);
  1219. }
  1220. public static bool operator !=(RubyBignum x, RubyBignum y)
  1221. {
  1222. return (Compare(x, y) != 0);
  1223. }
  1224. public static bool operator !=(RubyBignum x, double y)
  1225. {
  1226. return (x != y);
  1227. }
  1228. public static bool operator !=(RubyBignum x, int y)
  1229. {
  1230. return (x != y);
  1231. }
  1232. public static bool operator !=(double x, RubyBignum y)
  1233. {
  1234. return (x != y);
  1235. }
  1236. public static RubyBignum operator <<(RubyBignum x, int shift)
  1237. {
  1238. if (object.ReferenceEquals(x, null))
  1239. {
  1240. throw new ArgumentNullException("x");
  1241. }
  1242. if (shift == 0)
  1243. {
  1244. return x;
  1245. }
  1246. if (shift < 0)
  1247. {
  1248. return (x >> -shift);
  1249. }
  1250. int num = shift / 0x20;
  1251. int num2 = shift - (num * 0x20);
  1252. int length = x.GetLength();
  1253. uint[] data = x.data;
  1254. int num4 = (length + num) + 1;
  1255. uint[] numArray2 = new uint[num4];
  1256. if (num2 == 0)
  1257. {
  1258. for (int i = 0; i < length; i++)
  1259. {
  1260. numArray2[i + num] = data[i];
  1261. }
  1262. }
  1263. else
  1264. {
  1265. int num6 = 0x20 - num2;
  1266. uint num7 = 0;
  1267. int index = 0;
  1268. while (index < length)
  1269. {
  1270. uint num9 = data[index];
  1271. numArray2[index + num] = (num9 << num2) | num7;
  1272. num7 = num9 >> num6;
  1273. index++;
  1274. }
  1275. numArray2[index + num] = num7;
  1276. }
  1277. return new RubyBignum(x.sign, numArray2);
  1278. }
  1279. public static bool operator <(RubyBignum x, RubyBignum y)
  1280. {
  1281. return (Compare(x, y) < 0);
  1282. }
  1283. public static bool operator <=(RubyBignum x, RubyBignum y)
  1284. {
  1285. return (Compare(x, y) <= 0);
  1286. }
  1287. public static RubyBignum operator %(RubyBignum x, RubyBignum y)
  1288. {
  1289. RubyBignum integer;
  1290. DivRem(x, y, out integer);
  1291. return integer;
  1292. }
  1293. public static RubyBignum operator *(RubyBignum x, RubyBignum y)
  1294. {
  1295. if (object.ReferenceEquals(x, null))
  1296. {
  1297. throw new ArgumentNullException("x");
  1298. }
  1299. if (object.ReferenceEquals(y, null))
  1300. {
  1301. throw new ArgumentNullException("y");
  1302. }
  1303. int length = x.GetLength();
  1304. int num2 = y.GetLength();
  1305. int num3 = length + num2;
  1306. uint[] data = x.data;
  1307. uint[] numArray2 = y.data;
  1308. uint[] numArray3 = new uint[num3];
  1309. for (int i = 0; i < length; i++)
  1310. {
  1311. uint num5 = data[i];
  1312. int index = i;
  1313. ulong num7 = 0L;
  1314. for (int j = 0; j < num2; j++)
  1315. {
  1316. num7 = (num7 + (num5 * numArray2[j])) + numArray3[index];
  1317. numArray3[index++] = (uint)num7;
  1318. num7 = num7 >> 0x20;
  1319. }
  1320. while (num7 != 0L)
  1321. {
  1322. num7 += numArray3[index];
  1323. numArray3[index++] = (uint)num7;
  1324. num7 = num7 >> 0x20;
  1325. }
  1326. }
  1327. return new RubyBignum(x.sign * y.sign, numArray3);
  1328. }
  1329. public static RubyBignum operator ~(RubyBignum x)
  1330. {
  1331. if (object.ReferenceEquals(x, null))
  1332. {
  1333. throw new ArgumentNullException("x");
  1334. }
  1335. return -(x + One);
  1336. }
  1337. public static RubyBignum operator >>(RubyBignum x, int shift)
  1338. {
  1339. if (object.ReferenceEquals(x, null))
  1340. {
  1341. throw new ArgumentNullException("x");
  1342. }
  1343. if (shift == 0)
  1344. {
  1345. return x;
  1346. }
  1347. if (shift < 0)
  1348. {
  1349. return (x << -shift);
  1350. }
  1351. int index = shift / 0x20;
  1352. int num2 = shift - (index * 0x20);
  1353. int length = x.GetLength();
  1354. uint[] data = x.data;
  1355. int num4 = length - index;
  1356. if (num4 < 0)
  1357. {
  1358. num4 = 0;
  1359. }
  1360. uint[] numArray2 = new uint[num4];
  1361. if (num2 == 0)
  1362. {
  1363. for (int i = length - 1; i >= index; i--)
  1364. {
  1365. numArray2[i - index] = data[i];
  1366. }
  1367. }
  1368. else
  1369. {
  1370. int num6 = 0x20 - num2;
  1371. uint num7 = 0;
  1372. for (int j = length - 1; j >= index; j--)
  1373. {
  1374. uint num9 = data[j];
  1375. numArray2[j - index] = (num9 >> num2) | num7;
  1376. num7 = num9 << num6;
  1377. }
  1378. }
  1379. RubyBignum integer = new RubyBignum(x.sign, numArray2);
  1380. if (x.IsNegative())
  1381. {
  1382. for (int k = 0; k < index; k++)
  1383. {
  1384. if (data[k] != 0)
  1385. {
  1386. return (integer - One);
  1387. }
  1388. }
  1389. if ((num2 > 0) && ((data[index] << (0x20 - num2)) != 0))
  1390. {
  1391. return (integer - One);
  1392. }
  1393. }
  1394. return integer;
  1395. }
  1396. public static RubyBignum operator -(RubyBignum x, RubyBignum y)
  1397. {
  1398. uint[] numArray;
  1399. int sign = Compare(x, y);
  1400. if (sign != 0)
  1401. {
  1402. if (x.sign != y.sign)
  1403. {
  1404. return new RubyBignum(sign, add0(x.data, x.GetLength(), y.data, y.GetLength()));
  1405. }
  1406. switch ((sign * x.sign))
  1407. {
  1408. case -1:
  1409. numArray = sub(y.data, y.GetLength(), x.data, x.GetLength());
  1410. goto Label_0084;
  1411. case 1:
  1412. numArray = sub(x.data, x.GetLength(), y.data, y.GetLength());
  1413. goto Label_0084;
  1414. }
  1415. }
  1416. return Zero;
  1417. Label_0084:
  1418. return new RubyBignum(sign, numArray);
  1419. }
  1420. public static RubyBignum operator -(RubyBignum x)
  1421. {
  1422. if (object.ReferenceEquals(x, null))
  1423. {
  1424. throw new ArgumentNullException("x");
  1425. }
  1426. return new RubyBignum(-x.sign, x.data);
  1427. }
  1428. public RubyBignum Power(int exp)
  1429. {
  1430. if (exp == 0)
  1431. {
  1432. return One;
  1433. }
  1434. if (exp < 0)
  1435. {
  1436. throw new ArgumentOutOfRangeException("exp", "exp must be >= 0");
  1437. }
  1438. RubyBignum integer = this;
  1439. RubyBignum one = One;
  1440. while (exp != 0)
  1441. {
  1442. if ((exp & 1) != 0)
  1443. {
  1444. one *= integer;
  1445. }
  1446. if (exp == 1)
  1447. {
  1448. return one;
  1449. }
  1450. integer = integer.Square();
  1451. exp = exp >> 1;
  1452. }
  1453. return one;
  1454. }
  1455. private static uint[] resize(uint[] v, int len)
  1456. {
  1457. if (v.Length == len)
  1458. {
  1459. return v;
  1460. }
  1461. uint[] numArray = new uint[len];
  1462. int num = Math.Min(v.Length, len);
  1463. for (int i = 0; i < num; i++)
  1464. {
  1465. numArray[i] = v[i];
  1466. }
  1467. return numArray;
  1468. }
  1469. public static RubyBignum RightShift(RubyBignum x, int shift)
  1470. {
  1471. return (x >> shift);
  1472. }
  1473. public RubyBignum Square()
  1474. {
  1475. return (this * this);
  1476. }
  1477. private static uint[] sub(uint[] x, int xl, uint[] y, int yl)
  1478. {
  1479. uint[] numArray = new uint[xl];
  1480. bool flag = false;
  1481. int index = 0;
  1482. while (index < yl)
  1483. {
  1484. uint maxValue = x[index];
  1485. uint num3 = y[index];
  1486. if (flag)
  1487. {
  1488. if (maxValue == 0)
  1489. {
  1490. maxValue = uint.MaxValue;
  1491. flag = true;
  1492. }
  1493. else
  1494. {
  1495. maxValue--;
  1496. flag = false;
  1497. }
  1498. }
  1499. if (num3 > maxValue)
  1500. {
  1501. flag = true;
  1502. }
  1503. numArray[index] = maxValue - num3;
  1504. index++;
  1505. }
  1506. if (flag)
  1507. {
  1508. while (index < xl)
  1509. {
  1510. uint num4 = x[index];
  1511. numArray[index] = num4 - 1;
  1512. if (num4 != 0)
  1513. {
  1514. index++;
  1515. break;
  1516. }
  1517. index++;
  1518. }
  1519. }
  1520. while (index < xl)
  1521. {
  1522. numArray[index] = x[index];
  1523. index++;
  1524. }
  1525. return numArray;
  1526. }
  1527. public static RubyBignum Subtract(RubyBignum x, RubyBignum y)
  1528. {
  1529. return (x - y);
  1530. }
  1531. string IFormattable.ToString(string format, IFormatProvider formatProvider)
  1532. {
  1533. if (format == null)
  1534. {
  1535. return this.ToString();
  1536. }
  1537. switch (format[0])
  1538. {
  1539. case 'd':
  1540. case 'D':
  1541. {
  1542. if (format.Length <= 1)
  1543. {
  1544. return this.ToString(10);
  1545. }
  1546. int num = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);
  1547. string str = this.ToString(10);
  1548. if (str.Length >= num)
  1549. {
  1550. return str;
  1551. }
  1552. string str2 = new string('0', num - str.Length);
  1553. if (str[0] != '-')
  1554. {
  1555. return (str2 + str);
  1556. }
  1557. return ("-" + str2 + str.Substring(1));
  1558. }
  1559. case 'x':
  1560. case 'X':
  1561. {
  1562. StringBuilder builder = new StringBuilder(this.ToString(0x10));
  1563. if (format[0] == 'x')
  1564. {
  1565. for (int i = 0; i < builder.Length; i++)
  1566. {
  1567. if ((builder[i] >= 'A') && (builder[i] <= 'F'))
  1568. {
  1569. builder[i] = char.ToLower(builder[i], CultureInfo.InvariantCulture);
  1570. }
  1571. }
  1572. }
  1573. if (format.Length > 1)
  1574. {
  1575. int num3 = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);
  1576. if (builder.Length < num3)
  1577. {
  1578. string str3 = new string('0', num3 - builder.Length);
  1579. if (builder[0] != '-')
  1580. {
  1581. builder.Insert(0, str3);
  1582. }
  1583. else
  1584. {
  1585. builder.Insert(1, str3);
  1586. }
  1587. }
  1588. }
  1589. return builder.ToString();
  1590. }
  1591. }
  1592. throw new NotImplementedException("format not implemented");
  1593. }
  1594. public bool ToBoolean(IFormatProvider provider)
  1595. {
  1596. return (this != Zero);
  1597. }
  1598. public byte ToByte(IFormatProvider provider)
  1599. {

Large files files are truncated, but you can click here to view the full file