Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
BigIntegerCalculator.cs
Go to the documentation of this file.
1namespace System.Numerics;
2
3internal static class BigIntegerCalculator
4{
5 internal struct BitsBuffer
6 {
7 private uint[] _bits;
8
9 private int _length;
10
11 public BitsBuffer(int size, uint value)
12 {
13 _bits = new uint[size];
14 _length = ((value != 0) ? 1 : 0);
15 _bits[0] = value;
16 }
17
18 public BitsBuffer(int size, uint[] value)
19 {
20 _bits = new uint[size];
23 }
24
25 public unsafe void MultiplySelf(ref BitsBuffer value, ref BitsBuffer temp)
26 {
27 fixed (uint* ptr2 = _bits)
28 {
29 fixed (uint* ptr = value._bits)
30 {
31 fixed (uint* bits = temp._bits)
32 {
33 if (_length < value._length)
34 {
35 Multiply(ptr, value._length, ptr2, _length, bits, _length + value._length);
36 }
37 else
38 {
39 Multiply(ptr2, _length, ptr, value._length, bits, _length + value._length);
40 }
41 }
42 }
43 }
44 Apply(ref temp, _length + value._length);
45 }
46
47 public unsafe void SquareSelf(ref BitsBuffer temp)
48 {
49 fixed (uint* value = _bits)
50 {
51 fixed (uint* bits = temp._bits)
52 {
54 }
55 }
56 Apply(ref temp, _length + _length);
57 }
58
59 public void Reduce(ref FastReducer reducer)
60 {
61 _length = reducer.Reduce(_bits, _length);
62 }
63
64 public unsafe void Reduce(uint[] modulus)
65 {
66 if (_length < modulus.Length)
67 {
68 return;
69 }
70 fixed (uint* left = _bits)
71 {
72 fixed (uint* right = modulus)
73 {
74 Divide(left, _length, right, modulus.Length, null, 0);
75 }
76 }
77 _length = ActualLength(_bits, modulus.Length);
78 }
79
80 public unsafe void Reduce(ref BitsBuffer modulus)
81 {
82 if (_length < modulus._length)
83 {
84 return;
85 }
86 fixed (uint* left = _bits)
87 {
88 fixed (uint* right = modulus._bits)
89 {
90 Divide(left, _length, right, modulus._length, null, 0);
91 }
92 }
93 _length = ActualLength(_bits, modulus._length);
94 }
95
96 public void Overwrite(ulong value)
97 {
98 if (_length > 2)
99 {
100 Array.Clear(_bits, 2, _length - 2);
101 }
102 uint num = (uint)value;
103 uint num2 = (uint)(value >> 32);
104 _bits[0] = num;
105 _bits[1] = num2;
106 _length = ((num2 != 0) ? 2 : ((num != 0) ? 1 : 0));
107 }
108
109 public void Overwrite(uint value)
110 {
111 if (_length > 1)
112 {
113 Array.Clear(_bits, 1, _length - 1);
114 }
115 _bits[0] = value;
116 _length = ((value != 0) ? 1 : 0);
117 }
118
119 public uint[] GetBits()
120 {
121 return _bits;
122 }
123
124 public int GetSize()
125 {
126 return _bits.Length;
127 }
128
129 public int GetLength()
130 {
131 return _length;
132 }
133
134 public void Refresh(int maxLength)
135 {
136 if (_length > maxLength)
137 {
138 Array.Clear(_bits, maxLength, _length - maxLength);
139 }
140 _length = ActualLength(_bits, maxLength);
141 }
142
143 private void Apply(ref BitsBuffer temp, int maxLength)
144 {
146 uint[] bits = temp._bits;
147 temp._bits = _bits;
148 _bits = bits;
149 _length = ActualLength(_bits, maxLength);
150 }
151 }
152
153 internal readonly struct FastReducer
154 {
155 private readonly uint[] _modulus;
156
157 private readonly uint[] _mu;
158
159 private readonly uint[] _q1;
160
161 private readonly uint[] _q2;
162
163 private readonly int _muLength;
164
165 public FastReducer(uint[] modulus)
166 {
167 uint[] array = new uint[modulus.Length * 2 + 1];
168 array[^1] = 1u;
169 _mu = Divide(array, modulus);
170 _modulus = modulus;
171 _q1 = new uint[modulus.Length * 2 + 2];
172 _q2 = new uint[modulus.Length * 2 + 1];
174 }
175
176 public int Reduce(uint[] value, int length)
177 {
178 if (length < _modulus.Length)
179 {
180 return length;
181 }
182 int leftLength = DivMul(value, length, _mu, _muLength, _q1, _modulus.Length - 1);
183 int rightLength = DivMul(_q1, leftLength, _modulus, _modulus.Length, _q2, _modulus.Length + 1);
184 return SubMod(value, length, _q2, rightLength, _modulus, _modulus.Length + 1);
185 }
186
187 private unsafe static int DivMul(uint[] left, int leftLength, uint[] right, int rightLength, uint[] bits, int k)
188 {
189 Array.Clear(bits);
190 if (leftLength > k)
191 {
192 leftLength -= k;
193 fixed (uint* ptr2 = left)
194 {
195 fixed (uint* ptr = right)
196 {
197 fixed (uint* bits2 = bits)
198 {
199 if (leftLength < rightLength)
200 {
201 Multiply(ptr, rightLength, ptr2 + k, leftLength, bits2, leftLength + rightLength);
202 }
203 else
204 {
205 Multiply(ptr2 + k, leftLength, ptr, rightLength, bits2, leftLength + rightLength);
206 }
207 }
208 }
209 }
210 return ActualLength(bits, leftLength + rightLength);
211 }
212 return 0;
213 }
214
215 private unsafe static int SubMod(uint[] left, int leftLength, uint[] right, int rightLength, uint[] modulus, int k)
216 {
217 if (leftLength > k)
218 {
219 leftLength = k;
220 }
221 if (rightLength > k)
222 {
223 rightLength = k;
224 }
225 fixed (uint* left2 = left)
226 {
227 fixed (uint* right2 = right)
228 {
229 fixed (uint* right3 = modulus)
230 {
231 SubtractSelf(left2, leftLength, right2, rightLength);
232 leftLength = ActualLength(left, leftLength);
233 while (Compare(left2, leftLength, right3, modulus.Length) >= 0)
234 {
235 SubtractSelf(left2, leftLength, right3, modulus.Length);
236 leftLength = ActualLength(left, leftLength);
237 }
238 }
239 }
240 }
241 Array.Clear(left, leftLength, left.Length - leftLength);
242 return leftLength;
243 }
244 }
245
246 private static int ReducerThreshold = 32;
247
248 private static int SquareThreshold = 32;
249
250 private static int AllocationThreshold = 256;
251
252 private static int MultiplyThreshold = 32;
253
254 public static uint[] Add(uint[] left, uint right)
255 {
256 uint[] array = new uint[left.Length + 1];
257 long num = (long)left[0] + (long)right;
258 array[0] = (uint)num;
259 long num2 = num >> 32;
260 for (int i = 1; i < left.Length; i++)
261 {
262 num = left[i] + num2;
263 array[i] = (uint)num;
264 num2 = num >> 32;
265 }
266 array[left.Length] = (uint)num2;
267 return array;
268 }
269
270 public unsafe static uint[] Add(uint[] left, uint[] right)
271 {
272 uint[] array = new uint[left.Length + 1];
273 fixed (uint* left2 = left)
274 {
275 fixed (uint* right2 = right)
276 {
277 fixed (uint* bits = &array[0])
278 {
279 Add(left2, left.Length, right2, right.Length, bits, array.Length);
280 }
281 }
282 }
283 return array;
284 }
285
286 private unsafe static void Add(uint* left, int leftLength, uint* right, int rightLength, uint* bits, int bitsLength)
287 {
288 int i = 0;
289 long num = 0L;
290 for (; i < rightLength; i++)
291 {
292 long num2 = left[i] + num + right[i];
293 bits[i] = (uint)num2;
294 num = num2 >> 32;
295 }
296 for (; i < leftLength; i++)
297 {
298 long num3 = left[i] + num;
299 bits[i] = (uint)num3;
300 num = num3 >> 32;
301 }
302 bits[i] = (uint)num;
303 }
304
305 private unsafe static void AddSelf(uint* left, int leftLength, uint* right, int rightLength)
306 {
307 int i = 0;
308 long num = 0L;
309 for (; i < rightLength; i++)
310 {
311 long num2 = left[i] + num + right[i];
312 left[i] = (uint)num2;
313 num = num2 >> 32;
314 }
315 while (num != 0L && i < leftLength)
316 {
317 long num3 = left[i] + num;
318 left[i] = (uint)num3;
319 num = num3 >> 32;
320 i++;
321 }
322 }
323
324 public static uint[] Subtract(uint[] left, uint right)
325 {
326 uint[] array = new uint[left.Length];
327 long num = (long)left[0] - (long)right;
328 array[0] = (uint)num;
329 long num2 = num >> 32;
330 for (int i = 1; i < left.Length; i++)
331 {
332 num = left[i] + num2;
333 array[i] = (uint)num;
334 num2 = num >> 32;
335 }
336 return array;
337 }
338
339 public unsafe static uint[] Subtract(uint[] left, uint[] right)
340 {
341 uint[] array = new uint[left.Length];
342 fixed (uint* left2 = left)
343 {
344 fixed (uint* right2 = right)
345 {
346 fixed (uint* bits = array)
347 {
348 Subtract(left2, left.Length, right2, right.Length, bits, array.Length);
349 }
350 }
351 }
352 return array;
353 }
354
355 private unsafe static void Subtract(uint* left, int leftLength, uint* right, int rightLength, uint* bits, int bitsLength)
356 {
357 int i = 0;
358 long num = 0L;
359 for (; i < rightLength; i++)
360 {
361 long num2 = left[i] + num - right[i];
362 bits[i] = (uint)num2;
363 num = num2 >> 32;
364 }
365 for (; i < leftLength; i++)
366 {
367 long num3 = left[i] + num;
368 bits[i] = (uint)num3;
369 num = num3 >> 32;
370 }
371 }
372
373 private unsafe static void SubtractSelf(uint* left, int leftLength, uint* right, int rightLength)
374 {
375 int i = 0;
376 long num = 0L;
377 for (; i < rightLength; i++)
378 {
379 long num2 = left[i] + num - right[i];
380 left[i] = (uint)num2;
381 num = num2 >> 32;
382 }
383 while (num != 0L && i < leftLength)
384 {
385 long num3 = left[i] + num;
386 left[i] = (uint)num3;
387 num = num3 >> 32;
388 i++;
389 }
390 }
391
392 public static int Compare(uint[] left, uint[] right)
393 {
394 if (left.Length < right.Length)
395 {
396 return -1;
397 }
398 if (left.Length > right.Length)
399 {
400 return 1;
401 }
402 for (int num = left.Length - 1; num >= 0; num--)
403 {
404 if (left[num] < right[num])
405 {
406 return -1;
407 }
408 if (left[num] > right[num])
409 {
410 return 1;
411 }
412 }
413 return 0;
414 }
415
416 private unsafe static int Compare(uint* left, int leftLength, uint* right, int rightLength)
417 {
418 if (leftLength < rightLength)
419 {
420 return -1;
421 }
422 if (leftLength > rightLength)
423 {
424 return 1;
425 }
426 for (int num = leftLength - 1; num >= 0; num--)
427 {
428 if (left[num] < right[num])
429 {
430 return -1;
431 }
432 if (left[num] > right[num])
433 {
434 return 1;
435 }
436 }
437 return 0;
438 }
439
440 public static uint[] Divide(uint[] left, uint right, out uint remainder)
441 {
442 uint[] array = new uint[left.Length];
443 ulong num = 0uL;
444 for (int num2 = left.Length - 1; num2 >= 0; num2--)
445 {
446 ulong num3 = (num << 32) | left[num2];
447 ulong num4 = num3 / right;
448 array[num2] = (uint)num4;
449 num = num3 - num4 * right;
450 }
451 remainder = (uint)num;
452 return array;
453 }
454
455 public static uint[] Divide(uint[] left, uint right)
456 {
457 uint[] array = new uint[left.Length];
458 ulong num = 0uL;
459 for (int num2 = left.Length - 1; num2 >= 0; num2--)
460 {
461 ulong num3 = (num << 32) | left[num2];
462 ulong num4 = num3 / right;
463 array[num2] = (uint)num4;
464 num = num3 - num4 * right;
465 }
466 return array;
467 }
468
469 public static uint Remainder(uint[] left, uint right)
470 {
471 ulong num = 0uL;
472 for (int num2 = left.Length - 1; num2 >= 0; num2--)
473 {
474 ulong num3 = (num << 32) | left[num2];
475 num = num3 % right;
476 }
477 return (uint)num;
478 }
479
480 public unsafe static uint[] Divide(uint[] left, uint[] right, out uint[] remainder)
481 {
482 uint[] array = left.AsSpan().ToArray();
483 uint[] array2 = new uint[left.Length - right.Length + 1];
484 fixed (uint* left2 = &array[0])
485 {
486 fixed (uint* right2 = &right[0])
487 {
488 fixed (uint* bits = &array2[0])
489 {
490 Divide(left2, array.Length, right2, right.Length, bits, array2.Length);
491 }
492 }
493 }
494 remainder = array;
495 return array2;
496 }
497
498 public unsafe static uint[] Divide(uint[] left, uint[] right)
499 {
501 Span<uint> span;
502 if (left.Length <= 64)
503 {
504 span = stackalloc uint[64];
505 destination = span.Slice(0, left.Length);
506 span = left.AsSpan();
507 span.CopyTo(destination);
508 }
509 else
510 {
511 span = left.AsSpan();
512 destination = span.ToArray();
513 }
514 uint[] array = new uint[left.Length - right.Length + 1];
515 fixed (uint* left2 = &destination[0])
516 {
517 fixed (uint* right2 = &right[0])
518 {
519 fixed (uint* bits = &array[0])
520 {
521 Divide(left2, destination.Length, right2, right.Length, bits, array.Length);
522 }
523 }
524 }
525 return array;
526 }
527
528 public unsafe static uint[] Remainder(uint[] left, uint[] right)
529 {
530 uint[] array = left.AsSpan().ToArray();
531 fixed (uint* left2 = &array[0])
532 {
533 fixed (uint* right2 = &right[0])
534 {
535 Divide(left2, array.Length, right2, right.Length, null, 0);
536 }
537 }
538 return array;
539 }
540
541 private unsafe static void Divide(uint* left, int leftLength, uint* right, int rightLength, uint* bits, int bitsLength)
542 {
543 uint num = right[rightLength - 1];
544 uint num2 = ((rightLength > 1) ? right[rightLength - 2] : 0u);
545 int num3 = LeadingZeros(num);
546 int num4 = 32 - num3;
547 if (num3 > 0)
548 {
549 uint num5 = ((rightLength > 2) ? right[rightLength - 3] : 0u);
550 num = (num << num3) | (num2 >> num4);
551 num2 = (num2 << num3) | (num5 >> num4);
552 }
553 for (int num6 = leftLength; num6 >= rightLength; num6--)
554 {
555 int num7 = num6 - rightLength;
556 uint num8 = ((num6 < leftLength) ? left[num6] : 0u);
557 ulong num9 = ((ulong)num8 << 32) | left[num6 - 1];
558 uint num10 = ((num6 > 1) ? left[num6 - 2] : 0u);
559 if (num3 > 0)
560 {
561 uint num11 = ((num6 > 2) ? left[num6 - 3] : 0u);
562 num9 = (num9 << num3) | (num10 >> num4);
563 num10 = (num10 << num3) | (num11 >> num4);
564 }
565 ulong num12 = num9 / num;
566 if (num12 > uint.MaxValue)
567 {
568 num12 = 4294967295uL;
569 }
570 while (DivideGuessTooBig(num12, num9, num10, num, num2))
571 {
572 num12--;
573 }
574 if (num12 != 0)
575 {
576 uint num13 = SubtractDivisor(left + num7, leftLength - num7, right, rightLength, num12);
577 if (num13 != num8)
578 {
579 num13 = AddDivisor(left + num7, leftLength - num7, right, rightLength);
580 num12--;
581 }
582 }
583 if (bitsLength != 0)
584 {
585 bits[num7] = (uint)num12;
586 }
587 if (num6 < leftLength)
588 {
589 left[num6] = 0u;
590 }
591 }
592 }
593
594 private unsafe static uint AddDivisor(uint* left, int leftLength, uint* right, int rightLength)
595 {
596 ulong num = 0uL;
597 for (int i = 0; i < rightLength; i++)
598 {
599 ulong num2 = left[i] + num + right[i];
600 left[i] = (uint)num2;
601 num = num2 >> 32;
602 }
603 return (uint)num;
604 }
605
606 private unsafe static uint SubtractDivisor(uint* left, int leftLength, uint* right, int rightLength, ulong q)
607 {
608 ulong num = 0uL;
609 for (int i = 0; i < rightLength; i++)
610 {
611 num += right[i] * q;
612 uint num2 = (uint)num;
613 num >>= 32;
614 if (left[i] < num2)
615 {
616 num++;
617 }
618 left[i] -= num2;
619 }
620 return (uint)num;
621 }
622
623 private static bool DivideGuessTooBig(ulong q, ulong valHi, uint valLo, uint divHi, uint divLo)
624 {
625 ulong num = divHi * q;
626 ulong num2 = divLo * q;
627 num += num2 >> 32;
628 num2 &= 0xFFFFFFFFu;
629 if (num < valHi)
630 {
631 return false;
632 }
633 if (num > valHi)
634 {
635 return true;
636 }
637 if (num2 < valLo)
638 {
639 return false;
640 }
641 if (num2 > valLo)
642 {
643 return true;
644 }
645 return false;
646 }
647
648 private static int LeadingZeros(uint value)
649 {
650 if (value == 0)
651 {
652 return 32;
653 }
654 int num = 0;
655 if ((value & 0xFFFF0000u) == 0)
656 {
657 num += 16;
658 value <<= 16;
659 }
660 if ((value & 0xFF000000u) == 0)
661 {
662 num += 8;
663 value <<= 8;
664 }
665 if ((value & 0xF0000000u) == 0)
666 {
667 num += 4;
668 value <<= 4;
669 }
670 if ((value & 0xC0000000u) == 0)
671 {
672 num += 2;
673 value <<= 2;
674 }
675 if ((value & 0x80000000u) == 0)
676 {
677 num++;
678 }
679 return num;
680 }
681
682 public static uint Gcd(uint left, uint right)
683 {
684 while (right != 0)
685 {
686 uint num = left % right;
687 left = right;
688 right = num;
689 }
690 return left;
691 }
692
693 public static ulong Gcd(ulong left, ulong right)
694 {
695 while (right > uint.MaxValue)
696 {
697 ulong num = left % right;
698 left = right;
699 right = num;
700 }
701 if (right != 0L)
702 {
703 return Gcd((uint)right, (uint)(left % right));
704 }
705 return left;
706 }
707
708 public static uint Gcd(uint[] left, uint right)
709 {
710 uint right2 = Remainder(left, right);
711 return Gcd(right, right2);
712 }
713
714 public static uint[] Gcd(uint[] left, uint[] right)
715 {
716 BitsBuffer left2 = new BitsBuffer(left.Length, left);
717 BitsBuffer right2 = new BitsBuffer(right.Length, right);
718 Gcd(ref left2, ref right2);
719 return left2.GetBits();
720 }
721
722 private static void Gcd(ref BitsBuffer left, ref BitsBuffer right)
723 {
724 while (right.GetLength() > 2)
725 {
726 ExtractDigits(ref left, ref right, out var x, out var y);
727 uint num = 1u;
728 uint num2 = 0u;
729 uint num3 = 0u;
730 uint num4 = 1u;
731 int num5 = 0;
732 while (y != 0L)
733 {
734 ulong num6 = x / y;
735 if (num6 > uint.MaxValue)
736 {
737 break;
738 }
739 ulong num7 = num + num6 * num3;
740 ulong num8 = num2 + num6 * num4;
741 ulong num9 = x - num6 * y;
742 if (num7 > int.MaxValue || num8 > int.MaxValue || num9 < num8 || num9 + num7 > y - num3)
743 {
744 break;
745 }
746 num = (uint)num7;
747 num2 = (uint)num8;
748 x = num9;
749 num5++;
750 if (x == num2)
751 {
752 break;
753 }
754 num6 = y / x;
755 if (num6 > uint.MaxValue)
756 {
757 break;
758 }
759 num7 = num4 + num6 * num2;
760 num8 = num3 + num6 * num;
761 num9 = y - num6 * x;
762 if (num7 > int.MaxValue || num8 > int.MaxValue || num9 < num8 || num9 + num7 > x - num2)
763 {
764 break;
765 }
766 num4 = (uint)num7;
767 num3 = (uint)num8;
768 y = num9;
769 num5++;
770 if (y == num3)
771 {
772 break;
773 }
774 }
775 if (num2 == 0)
776 {
777 left.Reduce(ref right);
778 BitsBuffer bitsBuffer = left;
779 left = right;
780 right = bitsBuffer;
781 continue;
782 }
783 LehmerCore(ref left, ref right, num, num2, num3, num4);
784 if (num5 % 2 == 1)
785 {
786 BitsBuffer bitsBuffer2 = left;
787 left = right;
788 right = bitsBuffer2;
789 }
790 }
791 if (right.GetLength() > 0)
792 {
793 left.Reduce(ref right);
794 uint[] bits = right.GetBits();
795 uint[] bits2 = left.GetBits();
796 ulong left2 = ((ulong)bits[1] << 32) | bits[0];
797 ulong right2 = ((ulong)bits2[1] << 32) | bits2[0];
798 left.Overwrite(Gcd(left2, right2));
799 right.Overwrite(0u);
800 }
801 }
802
803 private static void ExtractDigits(ref BitsBuffer xBuffer, ref BitsBuffer yBuffer, out ulong x, out ulong y)
804 {
805 uint[] bits = xBuffer.GetBits();
806 int length = xBuffer.GetLength();
807 uint[] bits2 = yBuffer.GetBits();
808 int length2 = yBuffer.GetLength();
809 ulong num = bits[length - 1];
810 ulong num2 = bits[length - 2];
811 ulong num3 = bits[length - 3];
812 ulong num4;
813 ulong num5;
814 ulong num6;
815 switch (length - length2)
816 {
817 case 0:
818 num4 = bits2[length2 - 1];
819 num5 = bits2[length2 - 2];
820 num6 = bits2[length2 - 3];
821 break;
822 case 1:
823 num4 = 0uL;
824 num5 = bits2[length2 - 1];
825 num6 = bits2[length2 - 2];
826 break;
827 case 2:
828 num4 = 0uL;
829 num5 = 0uL;
830 num6 = bits2[length2 - 1];
831 break;
832 default:
833 num4 = 0uL;
834 num5 = 0uL;
835 num6 = 0uL;
836 break;
837 }
838 int num7 = LeadingZeros((uint)num);
839 x = ((num << 32 + num7) | (num2 << num7) | (num3 >> 32 - num7)) >> 1;
840 y = ((num4 << 32 + num7) | (num5 << num7) | (num6 >> 32 - num7)) >> 1;
841 }
842
843 private static void LehmerCore(ref BitsBuffer xBuffer, ref BitsBuffer yBuffer, long a, long b, long c, long d)
844 {
845 uint[] bits = xBuffer.GetBits();
846 uint[] bits2 = yBuffer.GetBits();
847 int length = yBuffer.GetLength();
848 long num = 0L;
849 long num2 = 0L;
850 for (int i = 0; i < length; i++)
851 {
852 long num3 = a * bits[i] - b * bits2[i] + num;
853 long num4 = d * bits2[i] - c * bits[i] + num2;
854 num = num3 >> 32;
855 num2 = num4 >> 32;
856 bits[i] = (uint)num3;
857 bits2[i] = (uint)num4;
858 }
859 xBuffer.Refresh(length);
860 yBuffer.Refresh(length);
861 }
862
863 public static uint[] Pow(uint value, uint power)
864 {
865 int size = PowBound(power, 1, 1);
866 BitsBuffer value2 = new BitsBuffer(size, value);
867 return PowCore(power, ref value2);
868 }
869
870 public static uint[] Pow(uint[] value, uint power)
871 {
872 int size = PowBound(power, value.Length, 1);
873 BitsBuffer value2 = new BitsBuffer(size, value);
874 return PowCore(power, ref value2);
875 }
876
877 private static uint[] PowCore(uint power, ref BitsBuffer value)
878 {
879 int size = value.GetSize();
880 BitsBuffer temp = new BitsBuffer(size, 0u);
881 BitsBuffer result = new BitsBuffer(size, 1u);
882 PowCore(power, ref value, ref result, ref temp);
883 return result.GetBits();
884 }
885
886 private static int PowBound(uint power, int valueLength, int resultLength)
887 {
888 checked
889 {
890 while (power != 0)
891 {
892 if ((power & 1) == 1)
893 {
894 resultLength += valueLength;
895 }
896 if (power != 1)
897 {
898 valueLength += valueLength;
899 }
900 power >>= 1;
901 }
902 return resultLength;
903 }
904 }
905
906 private static void PowCore(uint power, ref BitsBuffer value, ref BitsBuffer result, ref BitsBuffer temp)
907 {
908 while (power != 0)
909 {
910 if ((power & 1) == 1)
911 {
912 result.MultiplySelf(ref value, ref temp);
913 }
914 if (power != 1)
915 {
916 value.SquareSelf(ref temp);
917 }
918 power >>= 1;
919 }
920 }
921
922 public static uint Pow(uint value, uint power, uint modulus)
923 {
924 return PowCore(power, modulus, value, 1uL);
925 }
926
927 public static uint Pow(uint[] value, uint power, uint modulus)
928 {
929 uint num = Remainder(value, modulus);
930 return PowCore(power, modulus, num, 1uL);
931 }
932
933 public static uint Pow(uint value, uint[] power, uint modulus)
934 {
935 return PowCore(power, modulus, value, 1uL);
936 }
937
938 public static uint Pow(uint[] value, uint[] power, uint modulus)
939 {
940 uint num = Remainder(value, modulus);
941 return PowCore(power, modulus, num, 1uL);
942 }
943
944 private static uint PowCore(uint[] power, uint modulus, ulong value, ulong result)
945 {
946 for (int i = 0; i < power.Length - 1; i++)
947 {
948 uint num = power[i];
949 for (int j = 0; j < 32; j++)
950 {
951 if ((num & 1) == 1)
952 {
953 result = result * value % modulus;
954 }
955 value = value * value % modulus;
956 num >>= 1;
957 }
958 }
959 return PowCore(power[^1], modulus, value, result);
960 }
961
962 private static uint PowCore(uint power, uint modulus, ulong value, ulong result)
963 {
964 while (power != 0)
965 {
966 if ((power & 1) == 1)
967 {
968 result = result * value % modulus;
969 }
970 if (power != 1)
971 {
972 value = value * value % modulus;
973 }
974 power >>= 1;
975 }
976 return (uint)(result % modulus);
977 }
978
979 public static uint[] Pow(uint value, uint power, uint[] modulus)
980 {
981 int size = modulus.Length + modulus.Length;
982 BitsBuffer value2 = new BitsBuffer(size, value);
983 return PowCore(power, modulus, ref value2);
984 }
985
986 public static uint[] Pow(uint[] value, uint power, uint[] modulus)
987 {
988 if (value.Length > modulus.Length)
989 {
990 value = Remainder(value, modulus);
991 }
992 int size = modulus.Length + modulus.Length;
993 BitsBuffer value2 = new BitsBuffer(size, value);
994 return PowCore(power, modulus, ref value2);
995 }
996
997 public static uint[] Pow(uint value, uint[] power, uint[] modulus)
998 {
999 int size = modulus.Length + modulus.Length;
1000 BitsBuffer value2 = new BitsBuffer(size, value);
1001 return PowCore(power, modulus, ref value2);
1002 }
1003
1004 public static uint[] Pow(uint[] value, uint[] power, uint[] modulus)
1005 {
1006 if (value.Length > modulus.Length)
1007 {
1008 value = Remainder(value, modulus);
1009 }
1010 int size = modulus.Length + modulus.Length;
1011 BitsBuffer value2 = new BitsBuffer(size, value);
1012 return PowCore(power, modulus, ref value2);
1013 }
1014
1015 private static uint[] PowCore(uint[] power, uint[] modulus, ref BitsBuffer value)
1016 {
1017 int size = value.GetSize();
1018 BitsBuffer temp = new BitsBuffer(size, 0u);
1019 BitsBuffer result = new BitsBuffer(size, 1u);
1020 if (modulus.Length < ReducerThreshold)
1021 {
1022 PowCore(power, modulus, ref value, ref result, ref temp);
1023 }
1024 else
1025 {
1026 FastReducer reducer = new FastReducer(modulus);
1027 PowCore(power, ref reducer, ref value, ref result, ref temp);
1028 }
1029 return result.GetBits();
1030 }
1031
1032 private static uint[] PowCore(uint power, uint[] modulus, ref BitsBuffer value)
1033 {
1034 int size = value.GetSize();
1035 BitsBuffer temp = new BitsBuffer(size, 0u);
1036 BitsBuffer result = new BitsBuffer(size, 1u);
1037 if (modulus.Length < ReducerThreshold)
1038 {
1039 PowCore(power, modulus, ref value, ref result, ref temp);
1040 }
1041 else
1042 {
1043 FastReducer reducer = new FastReducer(modulus);
1044 PowCore(power, ref reducer, ref value, ref result, ref temp);
1045 }
1046 return result.GetBits();
1047 }
1048
1049 private static void PowCore(uint[] power, uint[] modulus, ref BitsBuffer value, ref BitsBuffer result, ref BitsBuffer temp)
1050 {
1051 for (int i = 0; i < power.Length - 1; i++)
1052 {
1053 uint num = power[i];
1054 for (int j = 0; j < 32; j++)
1055 {
1056 if ((num & 1) == 1)
1057 {
1058 result.MultiplySelf(ref value, ref temp);
1059 result.Reduce(modulus);
1060 }
1061 value.SquareSelf(ref temp);
1062 value.Reduce(modulus);
1063 num >>= 1;
1064 }
1065 }
1066 PowCore(power[^1], modulus, ref value, ref result, ref temp);
1067 }
1068
1069 private static void PowCore(uint power, uint[] modulus, ref BitsBuffer value, ref BitsBuffer result, ref BitsBuffer temp)
1070 {
1071 while (power != 0)
1072 {
1073 if ((power & 1) == 1)
1074 {
1075 result.MultiplySelf(ref value, ref temp);
1076 result.Reduce(modulus);
1077 }
1078 if (power != 1)
1079 {
1080 value.SquareSelf(ref temp);
1081 value.Reduce(modulus);
1082 }
1083 power >>= 1;
1084 }
1085 }
1086
1087 private static void PowCore(uint[] power, ref FastReducer reducer, ref BitsBuffer value, ref BitsBuffer result, ref BitsBuffer temp)
1088 {
1089 for (int i = 0; i < power.Length - 1; i++)
1090 {
1091 uint num = power[i];
1092 for (int j = 0; j < 32; j++)
1093 {
1094 if ((num & 1) == 1)
1095 {
1096 result.MultiplySelf(ref value, ref temp);
1097 result.Reduce(ref reducer);
1098 }
1099 value.SquareSelf(ref temp);
1100 value.Reduce(ref reducer);
1101 num >>= 1;
1102 }
1103 }
1104 PowCore(power[^1], ref reducer, ref value, ref result, ref temp);
1105 }
1106
1107 private static void PowCore(uint power, ref FastReducer reducer, ref BitsBuffer value, ref BitsBuffer result, ref BitsBuffer temp)
1108 {
1109 while (power != 0)
1110 {
1111 if ((power & 1) == 1)
1112 {
1113 result.MultiplySelf(ref value, ref temp);
1114 result.Reduce(ref reducer);
1115 }
1116 if (power != 1)
1117 {
1118 value.SquareSelf(ref temp);
1119 value.Reduce(ref reducer);
1120 }
1121 power >>= 1;
1122 }
1123 }
1124
1125 private static int ActualLength(uint[] value)
1126 {
1127 return ActualLength(value, value.Length);
1128 }
1129
1130 private static int ActualLength(uint[] value, int length)
1131 {
1132 while (length > 0 && value[length - 1] == 0)
1133 {
1134 length--;
1135 }
1136 return length;
1137 }
1138
1139 public unsafe static uint[] Square(uint[] value)
1140 {
1141 uint[] array = new uint[value.Length + value.Length];
1142 fixed (uint* value2 = value)
1143 {
1144 fixed (uint* bits = array)
1145 {
1146 Square(value2, value.Length, bits, array.Length);
1147 }
1148 }
1149 return array;
1150 }
1151
1152 private unsafe static void Square(uint* value, int valueLength, uint* bits, int bitsLength)
1153 {
1154 if (valueLength < SquareThreshold)
1155 {
1156 for (int i = 0; i < valueLength; i++)
1157 {
1158 ulong num = 0uL;
1159 for (int j = 0; j < i; j++)
1160 {
1161 ulong num2 = bits[i + j] + num;
1162 ulong num3 = (ulong)value[j] * (ulong)value[i];
1163 bits[i + j] = (uint)(num2 + (num3 << 1));
1164 num = num3 + (num2 >> 1) >> 31;
1165 }
1166 ulong num4 = (ulong)((long)value[i] * (long)value[i]) + num;
1167 bits[i + i] = (uint)num4;
1168 bits[i + i + 1] = (uint)(num4 >> 32);
1169 }
1170 return;
1171 }
1172 int num5 = valueLength >> 1;
1173 int num6 = num5 << 1;
1174 int num7 = num5;
1175 uint* ptr = value + num5;
1176 int num8 = valueLength - num5;
1177 int num9 = num6;
1178 uint* ptr2 = bits + num6;
1179 int num10 = bitsLength - num6;
1180 Square(value, num7, bits, num9);
1181 Square(ptr, num8, ptr2, num10);
1182 int num11 = num8 + 1;
1183 int num12 = num11 + num11;
1184 if (num12 < AllocationThreshold)
1185 {
1186 uint* ptr3 = stackalloc uint[num11];
1187 new Span<uint>(ptr3, num11).Clear();
1188 uint* ptr4 = stackalloc uint[num12];
1189 new Span<uint>(ptr4, num12).Clear();
1190 Add(ptr, num8, value, num7, ptr3, num11);
1191 Square(ptr3, num11, ptr4, num12);
1192 SubtractCore(ptr2, num10, bits, num9, ptr4, num12);
1193 AddSelf(bits + num5, bitsLength - num5, ptr4, num12);
1194 return;
1195 }
1196 fixed (uint* ptr5 = new uint[num11])
1197 {
1198 fixed (uint* ptr6 = new uint[num12])
1199 {
1200 Add(ptr, num8, value, num7, ptr5, num11);
1201 Square(ptr5, num11, ptr6, num12);
1202 SubtractCore(ptr2, num10, bits, num9, ptr6, num12);
1203 AddSelf(bits + num5, bitsLength - num5, ptr6, num12);
1204 }
1205 }
1206 }
1207
1208 public static uint[] Multiply(uint[] left, uint right)
1209 {
1210 int i = 0;
1211 ulong num = 0uL;
1212 uint[] array = new uint[left.Length + 1];
1213 for (; i < left.Length; i++)
1214 {
1215 ulong num2 = (ulong)((long)left[i] * (long)right) + num;
1216 array[i] = (uint)num2;
1217 num = num2 >> 32;
1218 }
1219 array[i] = (uint)num;
1220 return array;
1221 }
1222
1223 public unsafe static uint[] Multiply(uint[] left, uint[] right)
1224 {
1225 uint[] array = new uint[left.Length + right.Length];
1226 fixed (uint* left2 = left)
1227 {
1228 fixed (uint* right2 = right)
1229 {
1230 fixed (uint* bits = array)
1231 {
1232 Multiply(left2, left.Length, right2, right.Length, bits, array.Length);
1233 }
1234 }
1235 }
1236 return array;
1237 }
1238
1239 private unsafe static void Multiply(uint* left, int leftLength, uint* right, int rightLength, uint* bits, int bitsLength)
1240 {
1241 if (rightLength < MultiplyThreshold)
1242 {
1243 for (int i = 0; i < rightLength; i++)
1244 {
1245 ulong num = 0uL;
1246 for (int j = 0; j < leftLength; j++)
1247 {
1248 ulong num2 = bits[i + j] + num + (ulong)((long)left[j] * (long)right[i]);
1249 bits[i + j] = (uint)num2;
1250 num = num2 >> 32;
1251 }
1252 bits[i + leftLength] = (uint)num;
1253 }
1254 return;
1255 }
1256 int num3 = rightLength >> 1;
1257 int num4 = num3 << 1;
1258 int num5 = num3;
1259 uint* left2 = left + num3;
1260 int num6 = leftLength - num3;
1261 int rightLength2 = num3;
1262 uint* ptr = right + num3;
1263 int num7 = rightLength - num3;
1264 int num8 = num4;
1265 uint* ptr2 = bits + num4;
1266 int num9 = bitsLength - num4;
1267 Multiply(left, num5, right, rightLength2, bits, num8);
1268 Multiply(left2, num6, ptr, num7, ptr2, num9);
1269 int num10 = num6 + 1;
1270 int num11 = num7 + 1;
1271 int num12 = num10 + num11;
1272 if (num12 < AllocationThreshold)
1273 {
1274 uint* ptr3 = stackalloc uint[num10];
1275 new Span<uint>(ptr3, num10).Clear();
1276 uint* ptr4 = stackalloc uint[num11];
1277 new Span<uint>(ptr4, num11).Clear();
1278 uint* ptr5 = stackalloc uint[num12];
1279 new Span<uint>(ptr5, num12).Clear();
1280 Add(left2, num6, left, num5, ptr3, num10);
1281 Add(ptr, num7, right, rightLength2, ptr4, num11);
1282 Multiply(ptr3, num10, ptr4, num11, ptr5, num12);
1283 SubtractCore(ptr2, num9, bits, num8, ptr5, num12);
1284 AddSelf(bits + num3, bitsLength - num3, ptr5, num12);
1285 return;
1286 }
1287 fixed (uint* ptr6 = new uint[num10])
1288 {
1289 fixed (uint* ptr7 = new uint[num11])
1290 {
1291 fixed (uint* ptr8 = new uint[num12])
1292 {
1293 Add(left2, num6, left, num5, ptr6, num10);
1294 Add(ptr, num7, right, rightLength2, ptr7, num11);
1295 Multiply(ptr6, num10, ptr7, num11, ptr8, num12);
1296 SubtractCore(ptr2, num9, bits, num8, ptr8, num12);
1297 AddSelf(bits + num3, bitsLength - num3, ptr8, num12);
1298 }
1299 }
1300 }
1301 }
1302
1303 private unsafe static void SubtractCore(uint* left, int leftLength, uint* right, int rightLength, uint* core, int coreLength)
1304 {
1305 int i = 0;
1306 long num = 0L;
1307 for (; i < rightLength; i++)
1308 {
1309 long num2 = core[i] + num - left[i] - right[i];
1310 core[i] = (uint)num2;
1311 num = num2 >> 32;
1312 }
1313 for (; i < leftLength; i++)
1314 {
1315 long num3 = core[i] + num - left[i];
1316 core[i] = (uint)num3;
1317 num = num3 >> 32;
1318 }
1319 while (num != 0L && i < coreLength)
1320 {
1321 long num4 = core[i] + num;
1322 core[i] = (uint)num4;
1323 num = num4 >> 32;
1324 i++;
1325 }
1326 }
1327}
static unsafe void Clear(Array array)
Definition Array.cs:755
static unsafe void Copy(Array sourceArray, Array destinationArray, int length)
Definition Array.cs:624
static uint[] Pow(uint[] value, uint power, uint[] modulus)
static unsafe void Subtract(uint *left, int leftLength, uint *right, int rightLength, uint *bits, int bitsLength)
static unsafe uint[] Divide(uint[] left, uint[] right, out uint[] remainder)
static uint[] Divide(uint[] left, uint right, out uint remainder)
static unsafe void Add(uint *left, int leftLength, uint *right, int rightLength, uint *bits, int bitsLength)
static unsafe void Square(uint *value, int valueLength, uint *bits, int bitsLength)
static uint[] Pow(uint[] value, uint power)
static uint Gcd(uint left, uint right)
static uint Pow(uint value, uint power, uint modulus)
static uint[] Gcd(uint[] left, uint[] right)
static uint Pow(uint[] value, uint power, uint modulus)
static void PowCore(uint power, uint[] modulus, ref BitsBuffer value, ref BitsBuffer result, ref BitsBuffer temp)
static uint[] Pow(uint value, uint power)
static uint[] Add(uint[] left, uint right)
static unsafe void SubtractCore(uint *left, int leftLength, uint *right, int rightLength, uint *core, int coreLength)
static bool DivideGuessTooBig(ulong q, ulong valHi, uint valLo, uint divHi, uint divLo)
static uint[] Pow(uint[] value, uint[] power, uint[] modulus)
static void ExtractDigits(ref BitsBuffer xBuffer, ref BitsBuffer yBuffer, out ulong x, out ulong y)
static int ActualLength(uint[] value, int length)
static uint Pow(uint[] value, uint[] power, uint modulus)
static uint Pow(uint value, uint[] power, uint modulus)
static uint[] Pow(uint value, uint[] power, uint[] modulus)
static uint[] Multiply(uint[] left, uint right)
static uint[] PowCore(uint power, uint[] modulus, ref BitsBuffer value)
static unsafe uint[] Subtract(uint[] left, uint[] right)
static uint[] Subtract(uint[] left, uint right)
static uint[] Pow(uint value, uint power, uint[] modulus)
static void LehmerCore(ref BitsBuffer xBuffer, ref BitsBuffer yBuffer, long a, long b, long c, long d)
static ulong Gcd(ulong left, ulong right)
static uint PowCore(uint power, uint modulus, ulong value, ulong result)
static int PowBound(uint power, int valueLength, int resultLength)
static uint Remainder(uint[] left, uint right)
static void PowCore(uint[] power, uint[] modulus, ref BitsBuffer value, ref BitsBuffer result, ref BitsBuffer temp)
static unsafe uint[] Square(uint[] value)
static uint[] PowCore(uint[] power, uint[] modulus, ref BitsBuffer value)
static unsafe uint AddDivisor(uint *left, int leftLength, uint *right, int rightLength)
static unsafe uint[] Divide(uint[] left, uint[] right)
static unsafe int Compare(uint *left, int leftLength, uint *right, int rightLength)
static void PowCore(uint power, ref FastReducer reducer, ref BitsBuffer value, ref BitsBuffer result, ref BitsBuffer temp)
static uint Gcd(uint[] left, uint right)
static unsafe uint[] Multiply(uint[] left, uint[] right)
static void Gcd(ref BitsBuffer left, ref BitsBuffer right)
static void PowCore(uint[] power, ref FastReducer reducer, ref BitsBuffer value, ref BitsBuffer result, ref BitsBuffer temp)
static void PowCore(uint power, ref BitsBuffer value, ref BitsBuffer result, ref BitsBuffer temp)
static unsafe void Divide(uint *left, int leftLength, uint *right, int rightLength, uint *bits, int bitsLength)
static unsafe void AddSelf(uint *left, int leftLength, uint *right, int rightLength)
static int Compare(uint[] left, uint[] right)
static unsafe uint[] Remainder(uint[] left, uint[] right)
static uint[] Divide(uint[] left, uint right)
static unsafe void Multiply(uint *left, int leftLength, uint *right, int rightLength, uint *bits, int bitsLength)
static unsafe uint[] Add(uint[] left, uint[] right)
static unsafe uint SubtractDivisor(uint *left, int leftLength, uint *right, int rightLength, ulong q)
static uint[] PowCore(uint power, ref BitsBuffer value)
static unsafe void SubtractSelf(uint *left, int leftLength, uint *right, int rightLength)
static uint PowCore(uint[] power, uint modulus, ulong value, ulong result)
void Apply(ref BitsBuffer temp, int maxLength)
unsafe void MultiplySelf(ref BitsBuffer value, ref BitsBuffer temp)
static unsafe int DivMul(uint[] left, int leftLength, uint[] right, int rightLength, uint[] bits, int k)
static unsafe int SubMod(uint[] left, int leftLength, uint[] right, int rightLength, uint[] modulus, int k)
void CopyTo(Span< T > destination)
Definition Span.cs:224
Span< T > Slice(int start)
Definition Span.cs:271
unsafe void Clear()
Definition Span.cs:198
T[] ToArray()
Definition Span.cs:291