LongArray.cs 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Text;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  6. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Math.EC
  7. {
  8. internal class LongArray
  9. {
  10. //private static long DEInterleave_MASK = 0x5555555555555555L;
  11. /*
  12. * This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits.
  13. * In a binary field, this operation is the same as squaring an 8 bit number.
  14. */
  15. private static readonly ushort[] INTERLEAVE2_TABLE = new ushort[]
  16. {
  17. 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
  18. 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
  19. 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
  20. 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
  21. 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
  22. 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
  23. 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
  24. 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
  25. 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
  26. 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
  27. 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
  28. 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
  29. 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
  30. 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
  31. 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
  32. 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
  33. 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
  34. 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
  35. 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
  36. 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
  37. 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
  38. 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
  39. 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
  40. 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
  41. 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
  42. 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
  43. 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
  44. 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
  45. 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
  46. 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
  47. 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
  48. 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
  49. };
  50. /*
  51. * This expands 7 bit indices into 21 bit contents (high bit 18), by inserting 0s between bits.
  52. */
  53. private static readonly int[] INTERLEAVE3_TABLE = new int[]
  54. {
  55. 0x00000, 0x00001, 0x00008, 0x00009, 0x00040, 0x00041, 0x00048, 0x00049,
  56. 0x00200, 0x00201, 0x00208, 0x00209, 0x00240, 0x00241, 0x00248, 0x00249,
  57. 0x01000, 0x01001, 0x01008, 0x01009, 0x01040, 0x01041, 0x01048, 0x01049,
  58. 0x01200, 0x01201, 0x01208, 0x01209, 0x01240, 0x01241, 0x01248, 0x01249,
  59. 0x08000, 0x08001, 0x08008, 0x08009, 0x08040, 0x08041, 0x08048, 0x08049,
  60. 0x08200, 0x08201, 0x08208, 0x08209, 0x08240, 0x08241, 0x08248, 0x08249,
  61. 0x09000, 0x09001, 0x09008, 0x09009, 0x09040, 0x09041, 0x09048, 0x09049,
  62. 0x09200, 0x09201, 0x09208, 0x09209, 0x09240, 0x09241, 0x09248, 0x09249,
  63. 0x40000, 0x40001, 0x40008, 0x40009, 0x40040, 0x40041, 0x40048, 0x40049,
  64. 0x40200, 0x40201, 0x40208, 0x40209, 0x40240, 0x40241, 0x40248, 0x40249,
  65. 0x41000, 0x41001, 0x41008, 0x41009, 0x41040, 0x41041, 0x41048, 0x41049,
  66. 0x41200, 0x41201, 0x41208, 0x41209, 0x41240, 0x41241, 0x41248, 0x41249,
  67. 0x48000, 0x48001, 0x48008, 0x48009, 0x48040, 0x48041, 0x48048, 0x48049,
  68. 0x48200, 0x48201, 0x48208, 0x48209, 0x48240, 0x48241, 0x48248, 0x48249,
  69. 0x49000, 0x49001, 0x49008, 0x49009, 0x49040, 0x49041, 0x49048, 0x49049,
  70. 0x49200, 0x49201, 0x49208, 0x49209, 0x49240, 0x49241, 0x49248, 0x49249
  71. };
  72. /*
  73. * This expands 8 bit indices into 32 bit contents (high bit 28), by inserting 0s between bits.
  74. */
  75. private static readonly int[] INTERLEAVE4_TABLE = new int[]
  76. {
  77. 0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100, 0x00000101, 0x00000110, 0x00000111,
  78. 0x00001000, 0x00001001, 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110, 0x00001111,
  79. 0x00010000, 0x00010001, 0x00010010, 0x00010011, 0x00010100, 0x00010101, 0x00010110, 0x00010111,
  80. 0x00011000, 0x00011001, 0x00011010, 0x00011011, 0x00011100, 0x00011101, 0x00011110, 0x00011111,
  81. 0x00100000, 0x00100001, 0x00100010, 0x00100011, 0x00100100, 0x00100101, 0x00100110, 0x00100111,
  82. 0x00101000, 0x00101001, 0x00101010, 0x00101011, 0x00101100, 0x00101101, 0x00101110, 0x00101111,
  83. 0x00110000, 0x00110001, 0x00110010, 0x00110011, 0x00110100, 0x00110101, 0x00110110, 0x00110111,
  84. 0x00111000, 0x00111001, 0x00111010, 0x00111011, 0x00111100, 0x00111101, 0x00111110, 0x00111111,
  85. 0x01000000, 0x01000001, 0x01000010, 0x01000011, 0x01000100, 0x01000101, 0x01000110, 0x01000111,
  86. 0x01001000, 0x01001001, 0x01001010, 0x01001011, 0x01001100, 0x01001101, 0x01001110, 0x01001111,
  87. 0x01010000, 0x01010001, 0x01010010, 0x01010011, 0x01010100, 0x01010101, 0x01010110, 0x01010111,
  88. 0x01011000, 0x01011001, 0x01011010, 0x01011011, 0x01011100, 0x01011101, 0x01011110, 0x01011111,
  89. 0x01100000, 0x01100001, 0x01100010, 0x01100011, 0x01100100, 0x01100101, 0x01100110, 0x01100111,
  90. 0x01101000, 0x01101001, 0x01101010, 0x01101011, 0x01101100, 0x01101101, 0x01101110, 0x01101111,
  91. 0x01110000, 0x01110001, 0x01110010, 0x01110011, 0x01110100, 0x01110101, 0x01110110, 0x01110111,
  92. 0x01111000, 0x01111001, 0x01111010, 0x01111011, 0x01111100, 0x01111101, 0x01111110, 0x01111111,
  93. 0x10000000, 0x10000001, 0x10000010, 0x10000011, 0x10000100, 0x10000101, 0x10000110, 0x10000111,
  94. 0x10001000, 0x10001001, 0x10001010, 0x10001011, 0x10001100, 0x10001101, 0x10001110, 0x10001111,
  95. 0x10010000, 0x10010001, 0x10010010, 0x10010011, 0x10010100, 0x10010101, 0x10010110, 0x10010111,
  96. 0x10011000, 0x10011001, 0x10011010, 0x10011011, 0x10011100, 0x10011101, 0x10011110, 0x10011111,
  97. 0x10100000, 0x10100001, 0x10100010, 0x10100011, 0x10100100, 0x10100101, 0x10100110, 0x10100111,
  98. 0x10101000, 0x10101001, 0x10101010, 0x10101011, 0x10101100, 0x10101101, 0x10101110, 0x10101111,
  99. 0x10110000, 0x10110001, 0x10110010, 0x10110011, 0x10110100, 0x10110101, 0x10110110, 0x10110111,
  100. 0x10111000, 0x10111001, 0x10111010, 0x10111011, 0x10111100, 0x10111101, 0x10111110, 0x10111111,
  101. 0x11000000, 0x11000001, 0x11000010, 0x11000011, 0x11000100, 0x11000101, 0x11000110, 0x11000111,
  102. 0x11001000, 0x11001001, 0x11001010, 0x11001011, 0x11001100, 0x11001101, 0x11001110, 0x11001111,
  103. 0x11010000, 0x11010001, 0x11010010, 0x11010011, 0x11010100, 0x11010101, 0x11010110, 0x11010111,
  104. 0x11011000, 0x11011001, 0x11011010, 0x11011011, 0x11011100, 0x11011101, 0x11011110, 0x11011111,
  105. 0x11100000, 0x11100001, 0x11100010, 0x11100011, 0x11100100, 0x11100101, 0x11100110, 0x11100111,
  106. 0x11101000, 0x11101001, 0x11101010, 0x11101011, 0x11101100, 0x11101101, 0x11101110, 0x11101111,
  107. 0x11110000, 0x11110001, 0x11110010, 0x11110011, 0x11110100, 0x11110101, 0x11110110, 0x11110111,
  108. 0x11111000, 0x11111001, 0x11111010, 0x11111011, 0x11111100, 0x11111101, 0x11111110, 0x11111111
  109. };
  110. /*
  111. * This expands 7 bit indices into 35 bit contents (high bit 30), by inserting 0s between bits.
  112. */
  113. private static readonly int[] INTERLEAVE5_TABLE = new int[] {
  114. 0x00000000, 0x00000001, 0x00000020, 0x00000021, 0x00000400, 0x00000401, 0x00000420, 0x00000421,
  115. 0x00008000, 0x00008001, 0x00008020, 0x00008021, 0x00008400, 0x00008401, 0x00008420, 0x00008421,
  116. 0x00100000, 0x00100001, 0x00100020, 0x00100021, 0x00100400, 0x00100401, 0x00100420, 0x00100421,
  117. 0x00108000, 0x00108001, 0x00108020, 0x00108021, 0x00108400, 0x00108401, 0x00108420, 0x00108421,
  118. 0x02000000, 0x02000001, 0x02000020, 0x02000021, 0x02000400, 0x02000401, 0x02000420, 0x02000421,
  119. 0x02008000, 0x02008001, 0x02008020, 0x02008021, 0x02008400, 0x02008401, 0x02008420, 0x02008421,
  120. 0x02100000, 0x02100001, 0x02100020, 0x02100021, 0x02100400, 0x02100401, 0x02100420, 0x02100421,
  121. 0x02108000, 0x02108001, 0x02108020, 0x02108021, 0x02108400, 0x02108401, 0x02108420, 0x02108421,
  122. 0x40000000, 0x40000001, 0x40000020, 0x40000021, 0x40000400, 0x40000401, 0x40000420, 0x40000421,
  123. 0x40008000, 0x40008001, 0x40008020, 0x40008021, 0x40008400, 0x40008401, 0x40008420, 0x40008421,
  124. 0x40100000, 0x40100001, 0x40100020, 0x40100021, 0x40100400, 0x40100401, 0x40100420, 0x40100421,
  125. 0x40108000, 0x40108001, 0x40108020, 0x40108021, 0x40108400, 0x40108401, 0x40108420, 0x40108421,
  126. 0x42000000, 0x42000001, 0x42000020, 0x42000021, 0x42000400, 0x42000401, 0x42000420, 0x42000421,
  127. 0x42008000, 0x42008001, 0x42008020, 0x42008021, 0x42008400, 0x42008401, 0x42008420, 0x42008421,
  128. 0x42100000, 0x42100001, 0x42100020, 0x42100021, 0x42100400, 0x42100401, 0x42100420, 0x42100421,
  129. 0x42108000, 0x42108001, 0x42108020, 0x42108021, 0x42108400, 0x42108401, 0x42108420, 0x42108421
  130. };
  131. /*
  132. * This expands 9 bit indices into 63 bit (long) contents (high bit 56), by inserting 0s between bits.
  133. */
  134. private static readonly long[] INTERLEAVE7_TABLE = new long[]
  135. {
  136. 0x0000000000000000L, 0x0000000000000001L, 0x0000000000000080L, 0x0000000000000081L,
  137. 0x0000000000004000L, 0x0000000000004001L, 0x0000000000004080L, 0x0000000000004081L,
  138. 0x0000000000200000L, 0x0000000000200001L, 0x0000000000200080L, 0x0000000000200081L,
  139. 0x0000000000204000L, 0x0000000000204001L, 0x0000000000204080L, 0x0000000000204081L,
  140. 0x0000000010000000L, 0x0000000010000001L, 0x0000000010000080L, 0x0000000010000081L,
  141. 0x0000000010004000L, 0x0000000010004001L, 0x0000000010004080L, 0x0000000010004081L,
  142. 0x0000000010200000L, 0x0000000010200001L, 0x0000000010200080L, 0x0000000010200081L,
  143. 0x0000000010204000L, 0x0000000010204001L, 0x0000000010204080L, 0x0000000010204081L,
  144. 0x0000000800000000L, 0x0000000800000001L, 0x0000000800000080L, 0x0000000800000081L,
  145. 0x0000000800004000L, 0x0000000800004001L, 0x0000000800004080L, 0x0000000800004081L,
  146. 0x0000000800200000L, 0x0000000800200001L, 0x0000000800200080L, 0x0000000800200081L,
  147. 0x0000000800204000L, 0x0000000800204001L, 0x0000000800204080L, 0x0000000800204081L,
  148. 0x0000000810000000L, 0x0000000810000001L, 0x0000000810000080L, 0x0000000810000081L,
  149. 0x0000000810004000L, 0x0000000810004001L, 0x0000000810004080L, 0x0000000810004081L,
  150. 0x0000000810200000L, 0x0000000810200001L, 0x0000000810200080L, 0x0000000810200081L,
  151. 0x0000000810204000L, 0x0000000810204001L, 0x0000000810204080L, 0x0000000810204081L,
  152. 0x0000040000000000L, 0x0000040000000001L, 0x0000040000000080L, 0x0000040000000081L,
  153. 0x0000040000004000L, 0x0000040000004001L, 0x0000040000004080L, 0x0000040000004081L,
  154. 0x0000040000200000L, 0x0000040000200001L, 0x0000040000200080L, 0x0000040000200081L,
  155. 0x0000040000204000L, 0x0000040000204001L, 0x0000040000204080L, 0x0000040000204081L,
  156. 0x0000040010000000L, 0x0000040010000001L, 0x0000040010000080L, 0x0000040010000081L,
  157. 0x0000040010004000L, 0x0000040010004001L, 0x0000040010004080L, 0x0000040010004081L,
  158. 0x0000040010200000L, 0x0000040010200001L, 0x0000040010200080L, 0x0000040010200081L,
  159. 0x0000040010204000L, 0x0000040010204001L, 0x0000040010204080L, 0x0000040010204081L,
  160. 0x0000040800000000L, 0x0000040800000001L, 0x0000040800000080L, 0x0000040800000081L,
  161. 0x0000040800004000L, 0x0000040800004001L, 0x0000040800004080L, 0x0000040800004081L,
  162. 0x0000040800200000L, 0x0000040800200001L, 0x0000040800200080L, 0x0000040800200081L,
  163. 0x0000040800204000L, 0x0000040800204001L, 0x0000040800204080L, 0x0000040800204081L,
  164. 0x0000040810000000L, 0x0000040810000001L, 0x0000040810000080L, 0x0000040810000081L,
  165. 0x0000040810004000L, 0x0000040810004001L, 0x0000040810004080L, 0x0000040810004081L,
  166. 0x0000040810200000L, 0x0000040810200001L, 0x0000040810200080L, 0x0000040810200081L,
  167. 0x0000040810204000L, 0x0000040810204001L, 0x0000040810204080L, 0x0000040810204081L,
  168. 0x0002000000000000L, 0x0002000000000001L, 0x0002000000000080L, 0x0002000000000081L,
  169. 0x0002000000004000L, 0x0002000000004001L, 0x0002000000004080L, 0x0002000000004081L,
  170. 0x0002000000200000L, 0x0002000000200001L, 0x0002000000200080L, 0x0002000000200081L,
  171. 0x0002000000204000L, 0x0002000000204001L, 0x0002000000204080L, 0x0002000000204081L,
  172. 0x0002000010000000L, 0x0002000010000001L, 0x0002000010000080L, 0x0002000010000081L,
  173. 0x0002000010004000L, 0x0002000010004001L, 0x0002000010004080L, 0x0002000010004081L,
  174. 0x0002000010200000L, 0x0002000010200001L, 0x0002000010200080L, 0x0002000010200081L,
  175. 0x0002000010204000L, 0x0002000010204001L, 0x0002000010204080L, 0x0002000010204081L,
  176. 0x0002000800000000L, 0x0002000800000001L, 0x0002000800000080L, 0x0002000800000081L,
  177. 0x0002000800004000L, 0x0002000800004001L, 0x0002000800004080L, 0x0002000800004081L,
  178. 0x0002000800200000L, 0x0002000800200001L, 0x0002000800200080L, 0x0002000800200081L,
  179. 0x0002000800204000L, 0x0002000800204001L, 0x0002000800204080L, 0x0002000800204081L,
  180. 0x0002000810000000L, 0x0002000810000001L, 0x0002000810000080L, 0x0002000810000081L,
  181. 0x0002000810004000L, 0x0002000810004001L, 0x0002000810004080L, 0x0002000810004081L,
  182. 0x0002000810200000L, 0x0002000810200001L, 0x0002000810200080L, 0x0002000810200081L,
  183. 0x0002000810204000L, 0x0002000810204001L, 0x0002000810204080L, 0x0002000810204081L,
  184. 0x0002040000000000L, 0x0002040000000001L, 0x0002040000000080L, 0x0002040000000081L,
  185. 0x0002040000004000L, 0x0002040000004001L, 0x0002040000004080L, 0x0002040000004081L,
  186. 0x0002040000200000L, 0x0002040000200001L, 0x0002040000200080L, 0x0002040000200081L,
  187. 0x0002040000204000L, 0x0002040000204001L, 0x0002040000204080L, 0x0002040000204081L,
  188. 0x0002040010000000L, 0x0002040010000001L, 0x0002040010000080L, 0x0002040010000081L,
  189. 0x0002040010004000L, 0x0002040010004001L, 0x0002040010004080L, 0x0002040010004081L,
  190. 0x0002040010200000L, 0x0002040010200001L, 0x0002040010200080L, 0x0002040010200081L,
  191. 0x0002040010204000L, 0x0002040010204001L, 0x0002040010204080L, 0x0002040010204081L,
  192. 0x0002040800000000L, 0x0002040800000001L, 0x0002040800000080L, 0x0002040800000081L,
  193. 0x0002040800004000L, 0x0002040800004001L, 0x0002040800004080L, 0x0002040800004081L,
  194. 0x0002040800200000L, 0x0002040800200001L, 0x0002040800200080L, 0x0002040800200081L,
  195. 0x0002040800204000L, 0x0002040800204001L, 0x0002040800204080L, 0x0002040800204081L,
  196. 0x0002040810000000L, 0x0002040810000001L, 0x0002040810000080L, 0x0002040810000081L,
  197. 0x0002040810004000L, 0x0002040810004001L, 0x0002040810004080L, 0x0002040810004081L,
  198. 0x0002040810200000L, 0x0002040810200001L, 0x0002040810200080L, 0x0002040810200081L,
  199. 0x0002040810204000L, 0x0002040810204001L, 0x0002040810204080L, 0x0002040810204081L,
  200. 0x0100000000000000L, 0x0100000000000001L, 0x0100000000000080L, 0x0100000000000081L,
  201. 0x0100000000004000L, 0x0100000000004001L, 0x0100000000004080L, 0x0100000000004081L,
  202. 0x0100000000200000L, 0x0100000000200001L, 0x0100000000200080L, 0x0100000000200081L,
  203. 0x0100000000204000L, 0x0100000000204001L, 0x0100000000204080L, 0x0100000000204081L,
  204. 0x0100000010000000L, 0x0100000010000001L, 0x0100000010000080L, 0x0100000010000081L,
  205. 0x0100000010004000L, 0x0100000010004001L, 0x0100000010004080L, 0x0100000010004081L,
  206. 0x0100000010200000L, 0x0100000010200001L, 0x0100000010200080L, 0x0100000010200081L,
  207. 0x0100000010204000L, 0x0100000010204001L, 0x0100000010204080L, 0x0100000010204081L,
  208. 0x0100000800000000L, 0x0100000800000001L, 0x0100000800000080L, 0x0100000800000081L,
  209. 0x0100000800004000L, 0x0100000800004001L, 0x0100000800004080L, 0x0100000800004081L,
  210. 0x0100000800200000L, 0x0100000800200001L, 0x0100000800200080L, 0x0100000800200081L,
  211. 0x0100000800204000L, 0x0100000800204001L, 0x0100000800204080L, 0x0100000800204081L,
  212. 0x0100000810000000L, 0x0100000810000001L, 0x0100000810000080L, 0x0100000810000081L,
  213. 0x0100000810004000L, 0x0100000810004001L, 0x0100000810004080L, 0x0100000810004081L,
  214. 0x0100000810200000L, 0x0100000810200001L, 0x0100000810200080L, 0x0100000810200081L,
  215. 0x0100000810204000L, 0x0100000810204001L, 0x0100000810204080L, 0x0100000810204081L,
  216. 0x0100040000000000L, 0x0100040000000001L, 0x0100040000000080L, 0x0100040000000081L,
  217. 0x0100040000004000L, 0x0100040000004001L, 0x0100040000004080L, 0x0100040000004081L,
  218. 0x0100040000200000L, 0x0100040000200001L, 0x0100040000200080L, 0x0100040000200081L,
  219. 0x0100040000204000L, 0x0100040000204001L, 0x0100040000204080L, 0x0100040000204081L,
  220. 0x0100040010000000L, 0x0100040010000001L, 0x0100040010000080L, 0x0100040010000081L,
  221. 0x0100040010004000L, 0x0100040010004001L, 0x0100040010004080L, 0x0100040010004081L,
  222. 0x0100040010200000L, 0x0100040010200001L, 0x0100040010200080L, 0x0100040010200081L,
  223. 0x0100040010204000L, 0x0100040010204001L, 0x0100040010204080L, 0x0100040010204081L,
  224. 0x0100040800000000L, 0x0100040800000001L, 0x0100040800000080L, 0x0100040800000081L,
  225. 0x0100040800004000L, 0x0100040800004001L, 0x0100040800004080L, 0x0100040800004081L,
  226. 0x0100040800200000L, 0x0100040800200001L, 0x0100040800200080L, 0x0100040800200081L,
  227. 0x0100040800204000L, 0x0100040800204001L, 0x0100040800204080L, 0x0100040800204081L,
  228. 0x0100040810000000L, 0x0100040810000001L, 0x0100040810000080L, 0x0100040810000081L,
  229. 0x0100040810004000L, 0x0100040810004001L, 0x0100040810004080L, 0x0100040810004081L,
  230. 0x0100040810200000L, 0x0100040810200001L, 0x0100040810200080L, 0x0100040810200081L,
  231. 0x0100040810204000L, 0x0100040810204001L, 0x0100040810204080L, 0x0100040810204081L,
  232. 0x0102000000000000L, 0x0102000000000001L, 0x0102000000000080L, 0x0102000000000081L,
  233. 0x0102000000004000L, 0x0102000000004001L, 0x0102000000004080L, 0x0102000000004081L,
  234. 0x0102000000200000L, 0x0102000000200001L, 0x0102000000200080L, 0x0102000000200081L,
  235. 0x0102000000204000L, 0x0102000000204001L, 0x0102000000204080L, 0x0102000000204081L,
  236. 0x0102000010000000L, 0x0102000010000001L, 0x0102000010000080L, 0x0102000010000081L,
  237. 0x0102000010004000L, 0x0102000010004001L, 0x0102000010004080L, 0x0102000010004081L,
  238. 0x0102000010200000L, 0x0102000010200001L, 0x0102000010200080L, 0x0102000010200081L,
  239. 0x0102000010204000L, 0x0102000010204001L, 0x0102000010204080L, 0x0102000010204081L,
  240. 0x0102000800000000L, 0x0102000800000001L, 0x0102000800000080L, 0x0102000800000081L,
  241. 0x0102000800004000L, 0x0102000800004001L, 0x0102000800004080L, 0x0102000800004081L,
  242. 0x0102000800200000L, 0x0102000800200001L, 0x0102000800200080L, 0x0102000800200081L,
  243. 0x0102000800204000L, 0x0102000800204001L, 0x0102000800204080L, 0x0102000800204081L,
  244. 0x0102000810000000L, 0x0102000810000001L, 0x0102000810000080L, 0x0102000810000081L,
  245. 0x0102000810004000L, 0x0102000810004001L, 0x0102000810004080L, 0x0102000810004081L,
  246. 0x0102000810200000L, 0x0102000810200001L, 0x0102000810200080L, 0x0102000810200081L,
  247. 0x0102000810204000L, 0x0102000810204001L, 0x0102000810204080L, 0x0102000810204081L,
  248. 0x0102040000000000L, 0x0102040000000001L, 0x0102040000000080L, 0x0102040000000081L,
  249. 0x0102040000004000L, 0x0102040000004001L, 0x0102040000004080L, 0x0102040000004081L,
  250. 0x0102040000200000L, 0x0102040000200001L, 0x0102040000200080L, 0x0102040000200081L,
  251. 0x0102040000204000L, 0x0102040000204001L, 0x0102040000204080L, 0x0102040000204081L,
  252. 0x0102040010000000L, 0x0102040010000001L, 0x0102040010000080L, 0x0102040010000081L,
  253. 0x0102040010004000L, 0x0102040010004001L, 0x0102040010004080L, 0x0102040010004081L,
  254. 0x0102040010200000L, 0x0102040010200001L, 0x0102040010200080L, 0x0102040010200081L,
  255. 0x0102040010204000L, 0x0102040010204001L, 0x0102040010204080L, 0x0102040010204081L,
  256. 0x0102040800000000L, 0x0102040800000001L, 0x0102040800000080L, 0x0102040800000081L,
  257. 0x0102040800004000L, 0x0102040800004001L, 0x0102040800004080L, 0x0102040800004081L,
  258. 0x0102040800200000L, 0x0102040800200001L, 0x0102040800200080L, 0x0102040800200081L,
  259. 0x0102040800204000L, 0x0102040800204001L, 0x0102040800204080L, 0x0102040800204081L,
  260. 0x0102040810000000L, 0x0102040810000001L, 0x0102040810000080L, 0x0102040810000081L,
  261. 0x0102040810004000L, 0x0102040810004001L, 0x0102040810004080L, 0x0102040810004081L,
  262. 0x0102040810200000L, 0x0102040810200001L, 0x0102040810200080L, 0x0102040810200081L,
  263. 0x0102040810204000L, 0x0102040810204001L, 0x0102040810204080L, 0x0102040810204081L
  264. };
  265. // For toString(); must have length 64
  266. private const string ZEROES = "0000000000000000000000000000000000000000000000000000000000000000";
  267. internal static readonly byte[] BitLengths =
  268. {
  269. 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
  270. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  271. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  272. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  273. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  274. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  275. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  276. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  277. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  278. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  279. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  280. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  281. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  282. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  283. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  284. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
  285. };
  286. // TODO make m fixed for the LongArray, and hence compute T once and for all
  287. private long[] m_ints;
  288. public LongArray(int intLen)
  289. {
  290. m_ints = new long[intLen];
  291. }
  292. public LongArray(long[] ints)
  293. {
  294. m_ints = ints;
  295. }
  296. public LongArray(long[] ints, int off, int len)
  297. {
  298. if (off == 0 && len == ints.Length)
  299. {
  300. m_ints = ints;
  301. }
  302. else
  303. {
  304. m_ints = new long[len];
  305. Array.Copy(ints, off, m_ints, 0, len);
  306. }
  307. }
  308. public LongArray(BigInteger bigInt)
  309. {
  310. if (bigInt == null || bigInt.SignValue < 0)
  311. {
  312. throw new ArgumentException("invalid F2m field value", "bigInt");
  313. }
  314. if (bigInt.SignValue == 0)
  315. {
  316. m_ints = new long[] { 0L };
  317. return;
  318. }
  319. byte[] barr = bigInt.ToByteArray();
  320. int barrLen = barr.Length;
  321. int barrStart = 0;
  322. if (barr[0] == 0)
  323. {
  324. // First byte is 0 to enforce highest (=sign) bit is zero.
  325. // In this case ignore barr[0].
  326. barrLen--;
  327. barrStart = 1;
  328. }
  329. int intLen = (barrLen + 7) / 8;
  330. m_ints = new long[intLen];
  331. int iarrJ = intLen - 1;
  332. int rem = barrLen % 8 + barrStart;
  333. long temp = 0;
  334. int barrI = barrStart;
  335. if (barrStart < rem)
  336. {
  337. for (; barrI < rem; barrI++)
  338. {
  339. temp <<= 8;
  340. uint barrBarrI = barr[barrI];
  341. temp |= barrBarrI;
  342. }
  343. m_ints[iarrJ--] = temp;
  344. }
  345. for (; iarrJ >= 0; iarrJ--)
  346. {
  347. temp = 0;
  348. for (int i = 0; i < 8; i++)
  349. {
  350. temp <<= 8;
  351. uint barrBarrI = barr[barrI++];
  352. temp |= barrBarrI;
  353. }
  354. m_ints[iarrJ] = temp;
  355. }
  356. }
  357. internal void CopyTo(long[] z, int zOff)
  358. {
  359. Array.Copy(m_ints, 0, z, zOff, m_ints.Length);
  360. }
  361. public bool IsOne()
  362. {
  363. long[] a = m_ints;
  364. if (a[0] != 1L)
  365. {
  366. return false;
  367. }
  368. for (int i = 1; i < a.Length; ++i)
  369. {
  370. if (a[i] != 0L)
  371. {
  372. return false;
  373. }
  374. }
  375. return true;
  376. }
  377. public bool IsZero()
  378. {
  379. long[] a = m_ints;
  380. for (int i = 0; i < a.Length; ++i)
  381. {
  382. if (a[i] != 0L)
  383. {
  384. return false;
  385. }
  386. }
  387. return true;
  388. }
  389. public int GetUsedLength()
  390. {
  391. return GetUsedLengthFrom(m_ints.Length);
  392. }
  393. public int GetUsedLengthFrom(int from)
  394. {
  395. long[] a = m_ints;
  396. from = System.Math.Min(from, a.Length);
  397. if (from < 1)
  398. {
  399. return 0;
  400. }
  401. // Check if first element will act as sentinel
  402. if (a[0] != 0)
  403. {
  404. while (a[--from] == 0)
  405. {
  406. }
  407. return from + 1;
  408. }
  409. do
  410. {
  411. if (a[--from] != 0)
  412. {
  413. return from + 1;
  414. }
  415. }
  416. while (from > 0);
  417. return 0;
  418. }
  419. public int Degree()
  420. {
  421. int i = m_ints.Length;
  422. long w;
  423. do
  424. {
  425. if (i == 0)
  426. {
  427. return 0;
  428. }
  429. w = m_ints[--i];
  430. }
  431. while (w == 0);
  432. return (i << 6) + BitLength(w);
  433. }
  434. private int DegreeFrom(int limit)
  435. {
  436. int i = (int)(((uint)limit + 62) >> 6);
  437. long w;
  438. do
  439. {
  440. if (i == 0)
  441. {
  442. return 0;
  443. }
  444. w = m_ints[--i];
  445. }
  446. while (w == 0);
  447. return (i << 6) + BitLength(w);
  448. }
  449. // private int lowestCoefficient()
  450. // {
  451. // for (int i = 0; i < m_ints.Length; ++i)
  452. // {
  453. // long mi = m_ints[i];
  454. // if (mi != 0)
  455. // {
  456. // int j = 0;
  457. // while ((mi & 0xFFL) == 0)
  458. // {
  459. // j += 8;
  460. // mi >>>= 8;
  461. // }
  462. // while ((mi & 1L) == 0)
  463. // {
  464. // ++j;
  465. // mi >>>= 1;
  466. // }
  467. // return (i << 6) + j;
  468. // }
  469. // }
  470. // return -1;
  471. // }
  472. private static int BitLength(long w)
  473. {
  474. int u = (int)((ulong)w >> 32), b;
  475. if (u == 0)
  476. {
  477. u = (int)w;
  478. b = 0;
  479. }
  480. else
  481. {
  482. b = 32;
  483. }
  484. int t = (int)((uint)u >> 16), k;
  485. if (t == 0)
  486. {
  487. t = (int)((uint)u >> 8);
  488. k = (t == 0) ? BitLengths[u] : 8 + BitLengths[t];
  489. }
  490. else
  491. {
  492. int v = (int)((uint)t >> 8);
  493. k = (v == 0) ? 16 + BitLengths[t] : 24 + BitLengths[v];
  494. }
  495. return b + k;
  496. }
  497. private long[] ResizedInts(int newLen)
  498. {
  499. long[] newInts = new long[newLen];
  500. Array.Copy(m_ints, 0, newInts, 0, System.Math.Min(m_ints.Length, newLen));
  501. return newInts;
  502. }
  503. public BigInteger ToBigInteger()
  504. {
  505. int usedLen = GetUsedLength();
  506. if (usedLen == 0)
  507. {
  508. return BigInteger.Zero;
  509. }
  510. long highestInt = m_ints[usedLen - 1];
  511. byte[] temp = new byte[8];
  512. int barrI = 0;
  513. bool trailingZeroBytesDone = false;
  514. for (int j = 7; j >= 0; j--)
  515. {
  516. byte thisByte = (byte)((ulong)highestInt >> (8 * j));
  517. if (trailingZeroBytesDone || (thisByte != 0))
  518. {
  519. trailingZeroBytesDone = true;
  520. temp[barrI++] = thisByte;
  521. }
  522. }
  523. int barrLen = 8 * (usedLen - 1) + barrI;
  524. byte[] barr = new byte[barrLen];
  525. for (int j = 0; j < barrI; j++)
  526. {
  527. barr[j] = temp[j];
  528. }
  529. // Highest value int is done now
  530. for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
  531. {
  532. long mi = m_ints[iarrJ];
  533. for (int j = 7; j >= 0; j--)
  534. {
  535. barr[barrI++] = (byte)((ulong)mi >> (8 * j));
  536. }
  537. }
  538. return new BigInteger(1, barr);
  539. }
  540. // private static long shiftUp(long[] x, int xOff, int count)
  541. // {
  542. // long prev = 0;
  543. // for (int i = 0; i < count; ++i)
  544. // {
  545. // long next = x[xOff + i];
  546. // x[xOff + i] = (next << 1) | prev;
  547. // prev = next >>> 63;
  548. // }
  549. // return prev;
  550. // }
  551. private static long ShiftUp(long[] x, int xOff, int count, int shift)
  552. {
  553. int shiftInv = 64 - shift;
  554. long prev = 0;
  555. for (int i = 0; i < count; ++i)
  556. {
  557. long next = x[xOff + i];
  558. x[xOff + i] = (next << shift) | prev;
  559. prev = (long)((ulong)next >> shiftInv);
  560. }
  561. return prev;
  562. }
  563. private static long ShiftUp(long[] x, int xOff, long[] z, int zOff, int count, int shift)
  564. {
  565. int shiftInv = 64 - shift;
  566. long prev = 0;
  567. for (int i = 0; i < count; ++i)
  568. {
  569. long next = x[xOff + i];
  570. z[zOff + i] = (next << shift) | prev;
  571. prev = (long)((ulong)next >> shiftInv);
  572. }
  573. return prev;
  574. }
  575. public LongArray AddOne()
  576. {
  577. if (m_ints.Length == 0)
  578. {
  579. return new LongArray(new long[]{ 1L });
  580. }
  581. int resultLen = System.Math.Max(1, GetUsedLength());
  582. long[] ints = ResizedInts(resultLen);
  583. ints[0] ^= 1L;
  584. return new LongArray(ints);
  585. }
  586. // private void addShiftedByBits(LongArray other, int bits)
  587. // {
  588. // int words = bits >>> 6;
  589. // int shift = bits & 0x3F;
  590. //
  591. // if (shift == 0)
  592. // {
  593. // addShiftedByWords(other, words);
  594. // return;
  595. // }
  596. //
  597. // int otherUsedLen = other.GetUsedLength();
  598. // if (otherUsedLen == 0)
  599. // {
  600. // return;
  601. // }
  602. //
  603. // int minLen = otherUsedLen + words + 1;
  604. // if (minLen > m_ints.Length)
  605. // {
  606. // m_ints = resizedInts(minLen);
  607. // }
  608. //
  609. // long carry = addShiftedByBits(m_ints, words, other.m_ints, 0, otherUsedLen, shift);
  610. // m_ints[otherUsedLen + words] ^= carry;
  611. // }
  612. private void AddShiftedByBitsSafe(LongArray other, int otherDegree, int bits)
  613. {
  614. int otherLen = (int)((uint)(otherDegree + 63) >> 6);
  615. int words = (int)((uint)bits >> 6);
  616. int shift = bits & 0x3F;
  617. if (shift == 0)
  618. {
  619. Add(m_ints, words, other.m_ints, 0, otherLen);
  620. return;
  621. }
  622. long carry = AddShiftedUp(m_ints, words, other.m_ints, 0, otherLen, shift);
  623. if (carry != 0L)
  624. {
  625. m_ints[otherLen + words] ^= carry;
  626. }
  627. }
  628. private static long AddShiftedUp(long[] x, int xOff, long[] y, int yOff, int count, int shift)
  629. {
  630. int shiftInv = 64 - shift;
  631. long prev = 0;
  632. for (int i = 0; i < count; ++i)
  633. {
  634. long next = y[yOff + i];
  635. x[xOff + i] ^= (next << shift) | prev;
  636. prev = (long)((ulong)next >> shiftInv);
  637. }
  638. return prev;
  639. }
  640. private static long AddShiftedDown(long[] x, int xOff, long[] y, int yOff, int count, int shift)
  641. {
  642. int shiftInv = 64 - shift;
  643. long prev = 0;
  644. int i = count;
  645. while (--i >= 0)
  646. {
  647. long next = y[yOff + i];
  648. x[xOff + i] ^= (long)((ulong)next >> shift) | prev;
  649. prev = next << shiftInv;
  650. }
  651. return prev;
  652. }
  653. public void AddShiftedByWords(LongArray other, int words)
  654. {
  655. int otherUsedLen = other.GetUsedLength();
  656. if (otherUsedLen == 0)
  657. {
  658. return;
  659. }
  660. int minLen = otherUsedLen + words;
  661. if (minLen > m_ints.Length)
  662. {
  663. m_ints = ResizedInts(minLen);
  664. }
  665. Add(m_ints, words, other.m_ints, 0, otherUsedLen);
  666. }
  667. private static void Add(long[] x, int xOff, long[] y, int yOff, int count)
  668. {
  669. for (int i = 0; i < count; ++i)
  670. {
  671. x[xOff + i] ^= y[yOff + i];
  672. }
  673. }
  674. private static void Add(long[] x, int xOff, long[] y, int yOff, long[] z, int zOff, int count)
  675. {
  676. for (int i = 0; i < count; ++i)
  677. {
  678. z[zOff + i] = x[xOff + i] ^ y[yOff + i];
  679. }
  680. }
  681. private static void AddBoth(long[] x, int xOff, long[] y1, int y1Off, long[] y2, int y2Off, int count)
  682. {
  683. for (int i = 0; i < count; ++i)
  684. {
  685. x[xOff + i] ^= y1[y1Off + i] ^ y2[y2Off + i];
  686. }
  687. }
  688. private static void Distribute(long[] x, int src, int dst1, int dst2, int count)
  689. {
  690. for (int i = 0; i < count; ++i)
  691. {
  692. long v = x[src + i];
  693. x[dst1 + i] ^= v;
  694. x[dst2 + i] ^= v;
  695. }
  696. }
  697. public int Length
  698. {
  699. get { return m_ints.Length; }
  700. }
  701. private static void FlipWord(long[] buf, int off, int bit, long word)
  702. {
  703. int n = off + (int)((uint)bit >> 6);
  704. int shift = bit & 0x3F;
  705. if (shift == 0)
  706. {
  707. buf[n] ^= word;
  708. }
  709. else
  710. {
  711. buf[n] ^= word << shift;
  712. word = (long)((ulong)word >> (64 - shift));
  713. if (word != 0)
  714. {
  715. buf[++n] ^= word;
  716. }
  717. }
  718. }
  719. // private static long getWord(long[] buf, int off, int len, int bit)
  720. // {
  721. // int n = off + (bit >>> 6);
  722. // int shift = bit & 0x3F;
  723. // if (shift == 0)
  724. // {
  725. // return buf[n];
  726. // }
  727. // long result = buf[n] >>> shift;
  728. // if (++n < len)
  729. // {
  730. // result |= buf[n] << (64 - shift);
  731. // }
  732. // return result;
  733. // }
  734. public bool TestBitZero()
  735. {
  736. return m_ints.Length > 0 && (m_ints[0] & 1L) != 0;
  737. }
  738. private static bool TestBit(long[] buf, int off, int n)
  739. {
  740. // theInt = n / 64
  741. int theInt = (int)((uint)n >> 6);
  742. // theBit = n % 64
  743. int theBit = n & 0x3F;
  744. long tester = 1L << theBit;
  745. return (buf[off + theInt] & tester) != 0;
  746. }
  747. private static void FlipBit(long[] buf, int off, int n)
  748. {
  749. // theInt = n / 64
  750. int theInt = (int)((uint)n >> 6);
  751. // theBit = n % 64
  752. int theBit = n & 0x3F;
  753. long flipper = 1L << theBit;
  754. buf[off + theInt] ^= flipper;
  755. }
  756. // private static void SetBit(long[] buf, int off, int n)
  757. // {
  758. // // theInt = n / 64
  759. // int theInt = n >>> 6;
  760. // // theBit = n % 64
  761. // int theBit = n & 0x3F;
  762. // long setter = 1L << theBit;
  763. // buf[off + theInt] |= setter;
  764. // }
  765. //
  766. // private static void ClearBit(long[] buf, int off, int n)
  767. // {
  768. // // theInt = n / 64
  769. // int theInt = n >>> 6;
  770. // // theBit = n % 64
  771. // int theBit = n & 0x3F;
  772. // long setter = 1L << theBit;
  773. // buf[off + theInt] &= ~setter;
  774. // }
  775. private static void MultiplyWord(long a, long[] b, int bLen, long[] c, int cOff)
  776. {
  777. if ((a & 1L) != 0L)
  778. {
  779. Add(c, cOff, b, 0, bLen);
  780. }
  781. int k = 1;
  782. while ((a = (long)((ulong)a >> 1)) != 0L)
  783. {
  784. if ((a & 1L) != 0L)
  785. {
  786. long carry = AddShiftedUp(c, cOff, b, 0, bLen, k);
  787. if (carry != 0L)
  788. {
  789. c[cOff + bLen] ^= carry;
  790. }
  791. }
  792. ++k;
  793. }
  794. }
  795. public LongArray ModMultiplyLD(LongArray other, int m, int[] ks)
  796. {
  797. /*
  798. * Find out the degree of each argument and handle the zero cases
  799. */
  800. int aDeg = Degree();
  801. if (aDeg == 0)
  802. {
  803. return this;
  804. }
  805. int bDeg = other.Degree();
  806. if (bDeg == 0)
  807. {
  808. return other;
  809. }
  810. /*
  811. * Swap if necessary so that A is the smaller argument
  812. */
  813. LongArray A = this, B = other;
  814. if (aDeg > bDeg)
  815. {
  816. A = other; B = this;
  817. int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
  818. }
  819. /*
  820. * Establish the word lengths of the arguments and result
  821. */
  822. int aLen = (int)((uint)(aDeg + 63) >> 6);
  823. int bLen = (int)((uint)(bDeg + 63) >> 6);
  824. int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6);
  825. if (aLen == 1)
  826. {
  827. long a0 = A.m_ints[0];
  828. if (a0 == 1L)
  829. {
  830. return B;
  831. }
  832. /*
  833. * Fast path for small A, with performance dependent only on the number of set bits
  834. */
  835. long[] c0 = new long[cLen];
  836. MultiplyWord(a0, B.m_ints, bLen, c0, 0);
  837. /*
  838. * Reduce the raw answer against the reduction coefficients
  839. */
  840. return ReduceResult(c0, 0, cLen, m, ks);
  841. }
  842. /*
  843. * Determine if B will get bigger during shifting
  844. */
  845. int bMax = (int)((uint)(bDeg + 7 + 63) >> 6);
  846. /*
  847. * Lookup table for the offset of each B in the tables
  848. */
  849. int[] ti = new int[16];
  850. /*
  851. * Precompute table of all 4-bit products of B
  852. */
  853. long[] T0 = new long[bMax << 4];
  854. int tOff = bMax;
  855. ti[1] = tOff;
  856. Array.Copy(B.m_ints, 0, T0, tOff, bLen);
  857. for (int i = 2; i < 16; ++i)
  858. {
  859. ti[i] = (tOff += bMax);
  860. if ((i & 1) == 0)
  861. {
  862. ShiftUp(T0, (int)((uint)tOff >> 1), T0, tOff, bMax, 1);
  863. }
  864. else
  865. {
  866. Add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
  867. }
  868. }
  869. /*
  870. * Second table with all 4-bit products of B shifted 4 bits
  871. */
  872. long[] T1 = new long[T0.Length];
  873. ShiftUp(T0, 0, T1, 0, T0.Length, 4);
  874. // shiftUp(T0, bMax, T1, bMax, tOff, 4);
  875. long[] a = A.m_ints;
  876. long[] c = new long[cLen];
  877. int MASK = 0xF;
  878. /*
  879. * Lopez-Dahab algorithm
  880. */
  881. for (int k = 56; k >= 0; k -= 8)
  882. {
  883. for (int j = 1; j < aLen; j += 2)
  884. {
  885. int aVal = (int)((ulong)a[j] >> k);
  886. int u = aVal & MASK;
  887. int v = (int)((uint)aVal >> 4) & MASK;
  888. AddBoth(c, j - 1, T0, ti[u], T1, ti[v], bMax);
  889. }
  890. ShiftUp(c, 0, cLen, 8);
  891. }
  892. for (int k = 56; k >= 0; k -= 8)
  893. {
  894. for (int j = 0; j < aLen; j += 2)
  895. {
  896. int aVal = (int)((ulong)a[j] >> k);
  897. int u = aVal & MASK;
  898. int v = (int)((uint)aVal >> 4) & MASK;
  899. AddBoth(c, j, T0, ti[u], T1, ti[v], bMax);
  900. }
  901. if (k > 0)
  902. {
  903. ShiftUp(c, 0, cLen, 8);
  904. }
  905. }
  906. /*
  907. * Finally the raw answer is collected, reduce it against the reduction coefficients
  908. */
  909. return ReduceResult(c, 0, cLen, m, ks);
  910. }
  911. public LongArray ModMultiply(LongArray other, int m, int[] ks)
  912. {
  913. /*
  914. * Find out the degree of each argument and handle the zero cases
  915. */
  916. int aDeg = Degree();
  917. if (aDeg == 0)
  918. {
  919. return this;
  920. }
  921. int bDeg = other.Degree();
  922. if (bDeg == 0)
  923. {
  924. return other;
  925. }
  926. /*
  927. * Swap if necessary so that A is the smaller argument
  928. */
  929. LongArray A = this, B = other;
  930. if (aDeg > bDeg)
  931. {
  932. A = other; B = this;
  933. int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
  934. }
  935. /*
  936. * Establish the word lengths of the arguments and result
  937. */
  938. int aLen = (int)((uint)(aDeg + 63) >> 6);
  939. int bLen = (int)((uint)(bDeg + 63) >> 6);
  940. int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6);
  941. if (aLen == 1)
  942. {
  943. long a0 = A.m_ints[0];
  944. if (a0 == 1L)
  945. {
  946. return B;
  947. }
  948. /*
  949. * Fast path for small A, with performance dependent only on the number of set bits
  950. */
  951. long[] c0 = new long[cLen];
  952. MultiplyWord(a0, B.m_ints, bLen, c0, 0);
  953. /*
  954. * Reduce the raw answer against the reduction coefficients
  955. */
  956. return ReduceResult(c0, 0, cLen, m, ks);
  957. }
  958. /*
  959. * Determine if B will get bigger during shifting
  960. */
  961. int bMax = (int)((uint)(bDeg + 7 + 63) >> 6);
  962. /*
  963. * Lookup table for the offset of each B in the tables
  964. */
  965. int[] ti = new int[16];
  966. /*
  967. * Precompute table of all 4-bit products of B
  968. */
  969. long[] T0 = new long[bMax << 4];
  970. int tOff = bMax;
  971. ti[1] = tOff;
  972. Array.Copy(B.m_ints, 0, T0, tOff, bLen);
  973. for (int i = 2; i < 16; ++i)
  974. {
  975. ti[i] = (tOff += bMax);
  976. if ((i & 1) == 0)
  977. {
  978. ShiftUp(T0, (int)((uint)tOff >> 1), T0, tOff, bMax, 1);
  979. }
  980. else
  981. {
  982. Add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
  983. }
  984. }
  985. /*
  986. * Second table with all 4-bit products of B shifted 4 bits
  987. */
  988. long[] T1 = new long[T0.Length];
  989. ShiftUp(T0, 0, T1, 0, T0.Length, 4);
  990. // ShiftUp(T0, bMax, T1, bMax, tOff, 4);
  991. long[] a = A.m_ints;
  992. long[] c = new long[cLen << 3];
  993. int MASK = 0xF;
  994. /*
  995. * Lopez-Dahab (Modified) algorithm
  996. */
  997. for (int aPos = 0; aPos < aLen; ++aPos)
  998. {
  999. long aVal = a[aPos];
  1000. int cOff = aPos;
  1001. for (;;)
  1002. {
  1003. int u = (int)aVal & MASK;
  1004. aVal = (long)((ulong)aVal >> 4);
  1005. int v = (int)aVal & MASK;
  1006. AddBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
  1007. aVal = (long)((ulong)aVal >> 4);
  1008. if (aVal == 0L)
  1009. {
  1010. break;
  1011. }
  1012. cOff += cLen;
  1013. }
  1014. }
  1015. {
  1016. int cOff = c.Length;
  1017. while ((cOff -= cLen) != 0)
  1018. {
  1019. AddShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
  1020. }
  1021. }
  1022. /*
  1023. * Finally the raw answer is collected, reduce it against the reduction coefficients
  1024. */
  1025. return ReduceResult(c, 0, cLen, m, ks);
  1026. }
  1027. public LongArray ModMultiplyAlt(LongArray other, int m, int[] ks)
  1028. {
  1029. /*
  1030. * Find out the degree of each argument and handle the zero cases
  1031. */
  1032. int aDeg = Degree();
  1033. if (aDeg == 0)
  1034. {
  1035. return this;
  1036. }
  1037. int bDeg = other.Degree();
  1038. if (bDeg == 0)
  1039. {
  1040. return other;
  1041. }
  1042. /*
  1043. * Swap if necessary so that A is the smaller argument
  1044. */
  1045. LongArray A = this, B = other;
  1046. if (aDeg > bDeg)
  1047. {
  1048. A = other; B = this;
  1049. int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
  1050. }
  1051. /*
  1052. * Establish the word lengths of the arguments and result
  1053. */
  1054. int aLen = (int)((uint)(aDeg + 63) >> 6);
  1055. int bLen = (int)((uint)(bDeg + 63) >> 6);
  1056. int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6);
  1057. if (aLen == 1)
  1058. {
  1059. long a0 = A.m_ints[0];
  1060. if (a0 == 1L)
  1061. {
  1062. return B;
  1063. }
  1064. /*
  1065. * Fast path for small A, with performance dependent only on the number of set bits
  1066. */
  1067. long[] c0 = new long[cLen];
  1068. MultiplyWord(a0, B.m_ints, bLen, c0, 0);
  1069. /*
  1070. * Reduce the raw answer against the reduction coefficients
  1071. */
  1072. return ReduceResult(c0, 0, cLen, m, ks);
  1073. }
  1074. // NOTE: This works, but is slower than width 4 processing
  1075. // if (aLen == 2)
  1076. // {
  1077. // /*
  1078. // * Use common-multiplicand optimization to save ~1/4 of the adds
  1079. // */
  1080. // long a1 = A.m_ints[0], a2 = A.m_ints[1];
  1081. // long aa = a1 & a2; a1 ^= aa; a2 ^= aa;
  1082. //
  1083. // long[] b = B.m_ints;
  1084. // long[] c = new long[cLen];
  1085. // multiplyWord(aa, b, bLen, c, 1);
  1086. // add(c, 0, c, 1, cLen - 1);
  1087. // multiplyWord(a1, b, bLen, c, 0);
  1088. // multiplyWord(a2, b, bLen, c, 1);
  1089. //
  1090. // /*
  1091. // * Reduce the raw answer against the reduction coefficients
  1092. // */
  1093. // return ReduceResult(c, 0, cLen, m, ks);
  1094. // }
  1095. /*
  1096. * Determine the parameters of the Interleaved window algorithm: the 'width' in bits to
  1097. * process together, the number of evaluation 'positions' implied by that width, and the
  1098. * 'top' position at which the regular window algorithm stops.
  1099. */
  1100. int width, positions, top, banks;
  1101. // NOTE: width 4 is the fastest over the entire range of sizes used in current crypto
  1102. // width = 1; positions = 64; top = 64; banks = 4;
  1103. // width = 2; positions = 32; top = 64; banks = 4;
  1104. // width = 3; positions = 21; top = 63; banks = 3;
  1105. width = 4; positions = 16; top = 64; banks = 8;
  1106. // width = 5; positions = 13; top = 65; banks = 7;
  1107. // width = 7; positions = 9; top = 63; banks = 9;
  1108. // width = 8; positions = 8; top = 64; banks = 8;
  1109. /*
  1110. * Determine if B will get bigger during shifting
  1111. */
  1112. int shifts = top < 64 ? positions : positions - 1;
  1113. int bMax = (int)((uint)(bDeg + shifts + 63) >> 6);
  1114. int bTotal = bMax * banks, stride = width * banks;
  1115. /*
  1116. * Create a single temporary buffer, with an offset table to find the positions of things in it
  1117. */
  1118. int[] ci = new int[1 << width];
  1119. int cTotal = aLen;
  1120. {
  1121. ci[0] = cTotal;
  1122. cTotal += bTotal;
  1123. ci[1] = cTotal;
  1124. for (int i = 2; i < ci.Length; ++i)
  1125. {
  1126. cTotal += cLen;
  1127. ci[i] = cTotal;
  1128. }
  1129. cTotal += cLen;
  1130. }
  1131. // NOTE: Provide a safe dump for "high zeroes" since we are adding 'bMax' and not 'bLen'
  1132. ++cTotal;
  1133. long[] c = new long[cTotal];
  1134. // Prepare A in Interleaved form, according to the chosen width
  1135. Interleave(A.m_ints, 0, c, 0, aLen, width);
  1136. // Make a working copy of B, since we will be shifting it
  1137. {
  1138. int bOff = aLen;
  1139. Array.Copy(B.m_ints, 0, c, bOff, bLen);
  1140. for (int bank = 1; bank < banks; ++bank)
  1141. {
  1142. ShiftUp(c, aLen, c, bOff += bMax, bMax, bank);
  1143. }
  1144. }
  1145. /*
  1146. * The main loop analyzes the Interleaved windows in A, and for each non-zero window
  1147. * a single word-array XOR is performed to a carefully selected slice of 'c'. The loop is
  1148. * breadth-first, checking the lowest window in each word, then looping again for the
  1149. * next higher window position.
  1150. */
  1151. int MASK = (1 << width) - 1;
  1152. int k = 0;
  1153. for (;;)
  1154. {
  1155. int aPos = 0;
  1156. do
  1157. {
  1158. long aVal = (long)((ulong)c[aPos] >> k);
  1159. int bank = 0, bOff = aLen;
  1160. for (;;)
  1161. {
  1162. int index = (int)(aVal) & MASK;
  1163. if (index != 0)
  1164. {
  1165. /*
  1166. * Add to a 'c' buffer based on the bit-pattern of 'index'. Since A is in
  1167. * Interleaved form, the bits represent the current B shifted by 0, 'positions',
  1168. * 'positions' * 2, ..., 'positions' * ('width' - 1)
  1169. */
  1170. Add(c, aPos + ci[index], c, bOff, bMax);
  1171. }
  1172. if (++bank == banks)
  1173. {
  1174. break;
  1175. }
  1176. bOff += bMax;
  1177. aVal = (long)((ulong)aVal >> width);
  1178. }
  1179. }
  1180. while (++aPos < aLen);
  1181. if ((k += stride) >= top)
  1182. {
  1183. if (k >= 64)
  1184. {
  1185. break;
  1186. }
  1187. /*
  1188. * Adjustment for window setups with top == 63, the final bit (if any) is processed
  1189. * as the top-bit of a window
  1190. */
  1191. k = 64 - width;
  1192. MASK &= MASK << (top - k);
  1193. }
  1194. /*
  1195. * After each position has been checked for all words of A, B is shifted up 1 place
  1196. */
  1197. ShiftUp(c, aLen, bTotal, banks);
  1198. }
  1199. int ciPos = ci.Length;
  1200. while (--ciPos > 1)
  1201. {
  1202. if ((ciPos & 1L) == 0L)
  1203. {
  1204. /*
  1205. * For even numbers, shift contents and add to the half-position
  1206. */
  1207. AddShiftedUp(c, ci[(uint)ciPos >> 1], c, ci[ciPos], cLen, positions);
  1208. }
  1209. else
  1210. {
  1211. /*
  1212. * For odd numbers, 'distribute' contents to the result and the next-lowest position
  1213. */
  1214. Distribute(c, ci[ciPos], ci[ciPos - 1], ci[1], cLen);
  1215. }
  1216. }
  1217. /*
  1218. * Finally the raw answer is collected, reduce it against the reduction coefficients
  1219. */
  1220. return ReduceResult(c, ci[1], cLen, m, ks);
  1221. }
  1222. public LongArray ModReduce(int m, int[] ks)
  1223. {
  1224. long[] buf = Arrays.Clone(m_ints);
  1225. int rLen = ReduceInPlace(buf, 0, buf.Length, m, ks);
  1226. return new LongArray(buf, 0, rLen);
  1227. }
  1228. public LongArray Multiply(LongArray other, int m, int[] ks)
  1229. {
  1230. /*
  1231. * Find out the degree of each argument and handle the zero cases
  1232. */
  1233. int aDeg = Degree();
  1234. if (aDeg == 0)
  1235. {
  1236. return this;
  1237. }
  1238. int bDeg = other.Degree();
  1239. if (bDeg == 0)
  1240. {
  1241. return other;
  1242. }
  1243. /*
  1244. * Swap if necessary so that A is the smaller argument
  1245. */
  1246. LongArray A = this, B = other;
  1247. if (aDeg > bDeg)
  1248. {
  1249. A = other; B = this;
  1250. int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
  1251. }
  1252. /*
  1253. * Establish the word lengths of the arguments and result
  1254. */
  1255. int aLen = (int)((uint)(aDeg + 63) >> 6);
  1256. int bLen = (int)((uint)(bDeg + 63) >> 6);
  1257. int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6);
  1258. if (aLen == 1)
  1259. {
  1260. long a0 = A.m_ints[0];
  1261. if (a0 == 1L)
  1262. {
  1263. return B;
  1264. }
  1265. /*
  1266. * Fast path for small A, with performance dependent only on the number of set bits
  1267. */
  1268. long[] c0 = new long[cLen];
  1269. MultiplyWord(a0, B.m_ints, bLen, c0, 0);
  1270. /*
  1271. * Reduce the raw answer against the reduction coefficients
  1272. */
  1273. //return ReduceResult(c0, 0, cLen, m, ks);
  1274. return new LongArray(c0, 0, cLen);
  1275. }
  1276. /*
  1277. * Determine if B will get bigger during shifting
  1278. */
  1279. int bMax = (int)((uint)(bDeg + 7 + 63) >> 6);
  1280. /*
  1281. * Lookup table for the offset of each B in the tables
  1282. */
  1283. int[] ti = new int[16];
  1284. /*
  1285. * Precompute table of all 4-bit products of B
  1286. */
  1287. long[] T0 = new long[bMax << 4];
  1288. int tOff = bMax;
  1289. ti[1] = tOff;
  1290. Array.Copy(B.m_ints, 0, T0, tOff, bLen);
  1291. for (int i = 2; i < 16; ++i)
  1292. {
  1293. ti[i] = (tOff += bMax);
  1294. if ((i & 1) == 0)
  1295. {
  1296. ShiftUp(T0, (int)((uint)tOff >> 1), T0, tOff, bMax, 1);
  1297. }
  1298. else
  1299. {
  1300. Add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
  1301. }
  1302. }
  1303. /*
  1304. * Second table with all 4-bit products of B shifted 4 bits
  1305. */
  1306. long[] T1 = new long[T0.Length];
  1307. ShiftUp(T0, 0, T1, 0, T0.Length, 4);
  1308. // ShiftUp(T0, bMax, T1, bMax, tOff, 4);
  1309. long[] a = A.m_ints;
  1310. long[] c = new long[cLen << 3];
  1311. int MASK = 0xF;
  1312. /*
  1313. * Lopez-Dahab (Modified) algorithm
  1314. */
  1315. for (int aPos = 0; aPos < aLen; ++aPos)
  1316. {
  1317. long aVal = a[aPos];
  1318. int cOff = aPos;
  1319. for (; ; )
  1320. {
  1321. int u = (int)aVal & MASK;
  1322. aVal = (long)((ulong)aVal >> 4);
  1323. int v = (int)aVal & MASK;
  1324. AddBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
  1325. aVal = (long)((ulong)aVal >> 4);
  1326. if (aVal == 0L)
  1327. {
  1328. break;
  1329. }
  1330. cOff += cLen;
  1331. }
  1332. }
  1333. {
  1334. int cOff = c.Length;
  1335. while ((cOff -= cLen) != 0)
  1336. {
  1337. AddShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
  1338. }
  1339. }
  1340. /*
  1341. * Finally the raw answer is collected, reduce it against the reduction coefficients
  1342. */
  1343. //return ReduceResult(c, 0, cLen, m, ks);
  1344. return new LongArray(c, 0, cLen);
  1345. }
  1346. public void Reduce(int m, int[] ks)
  1347. {
  1348. long[] buf = m_ints;
  1349. int rLen = ReduceInPlace(buf, 0, buf.Length, m, ks);
  1350. if (rLen < buf.Length)
  1351. {
  1352. m_ints = new long[rLen];
  1353. Array.Copy(buf, 0, m_ints, 0, rLen);
  1354. }
  1355. }
  1356. private static LongArray ReduceResult(long[] buf, int off, int len, int m, int[] ks)
  1357. {
  1358. int rLen = ReduceInPlace(buf, off, len, m, ks);
  1359. return new LongArray(buf, off, rLen);
  1360. }
  1361. // private static void deInterleave(long[] x, int xOff, long[] z, int zOff, int count, int rounds)
  1362. // {
  1363. // for (int i = 0; i < count; ++i)
  1364. // {
  1365. // z[zOff + i] = deInterleave(x[zOff + i], rounds);
  1366. // }
  1367. // }
  1368. //
  1369. // private static long deInterleave(long x, int rounds)
  1370. // {
  1371. // while (--rounds >= 0)
  1372. // {
  1373. // x = deInterleave32(x & DEInterleave_MASK) | (deInterleave32((x >>> 1) & DEInterleave_MASK) << 32);
  1374. // }
  1375. // return x;
  1376. // }
  1377. //
  1378. // private static long deInterleave32(long x)
  1379. // {
  1380. // x = (x | (x >>> 1)) & 0x3333333333333333L;
  1381. // x = (x | (x >>> 2)) & 0x0F0F0F0F0F0F0F0FL;
  1382. // x = (x | (x >>> 4)) & 0x00FF00FF00FF00FFL;
  1383. // x = (x | (x >>> 8)) & 0x0000FFFF0000FFFFL;
  1384. // x = (x | (x >>> 16)) & 0x00000000FFFFFFFFL;
  1385. // return x;
  1386. // }
  1387. private static int ReduceInPlace(long[] buf, int off, int len, int m, int[] ks)
  1388. {
  1389. int mLen = (m + 63) >> 6;
  1390. if (len < mLen)
  1391. {
  1392. return len;
  1393. }
  1394. int numBits = System.Math.Min(len << 6, (m << 1) - 1); // TODO use actual degree?
  1395. int excessBits = (len << 6) - numBits;
  1396. while (excessBits >= 64)
  1397. {
  1398. --len;
  1399. excessBits -= 64;
  1400. }
  1401. int kLen = ks.Length, kMax = ks[kLen - 1], kNext = kLen > 1 ? ks[kLen - 2] : 0;
  1402. int wordWiseLimit = System.Math.Max(m, kMax + 64);
  1403. int vectorableWords = (excessBits + System.Math.Min(numBits - wordWiseLimit, m - kNext)) >> 6;
  1404. if (vectorableWords > 1)
  1405. {
  1406. int vectorWiseWords = len - vectorableWords;
  1407. ReduceVectorWise(buf, off, len, vectorWiseWords, m, ks);
  1408. while (len > vectorWiseWords)
  1409. {
  1410. buf[off + --len] = 0L;
  1411. }
  1412. numBits = vectorWiseWords << 6;
  1413. }
  1414. if (numBits > wordWiseLimit)
  1415. {
  1416. ReduceWordWise(buf, off, len, wordWiseLimit, m, ks);
  1417. numBits = wordWiseLimit;
  1418. }
  1419. if (numBits > m)
  1420. {
  1421. ReduceBitWise(buf, off, numBits, m, ks);
  1422. }
  1423. return mLen;
  1424. }
  1425. private static void ReduceBitWise(long[] buf, int off, int BitLength, int m, int[] ks)
  1426. {
  1427. while (--BitLength >= m)
  1428. {
  1429. if (TestBit(buf, off, BitLength))
  1430. {
  1431. ReduceBit(buf, off, BitLength, m, ks);
  1432. }
  1433. }
  1434. }
  1435. private static void ReduceBit(long[] buf, int off, int bit, int m, int[] ks)
  1436. {
  1437. FlipBit(buf, off, bit);
  1438. int n = bit - m;
  1439. int j = ks.Length;
  1440. while (--j >= 0)
  1441. {
  1442. FlipBit(buf, off, ks[j] + n);
  1443. }
  1444. FlipBit(buf, off, n);
  1445. }
  1446. private static void ReduceWordWise(long[] buf, int off, int len, int toBit, int m, int[] ks)
  1447. {
  1448. int toPos = (int)((uint)toBit >> 6);
  1449. while (--len > toPos)
  1450. {
  1451. long word = buf[off + len];
  1452. if (word != 0)
  1453. {
  1454. buf[off + len] = 0;
  1455. ReduceWord(buf, off, (len << 6), word, m, ks);
  1456. }
  1457. }
  1458. {
  1459. int partial = toBit & 0x3F;
  1460. long word = (long)((ulong)buf[off + toPos] >> partial);
  1461. if (word != 0)
  1462. {
  1463. buf[off + toPos] ^= word << partial;
  1464. ReduceWord(buf, off, toBit, word, m, ks);
  1465. }
  1466. }
  1467. }
  1468. private static void ReduceWord(long[] buf, int off, int bit, long word, int m, int[] ks)
  1469. {
  1470. int offset = bit - m;
  1471. int j = ks.Length;
  1472. while (--j >= 0)
  1473. {
  1474. FlipWord(buf, off, offset + ks[j], word);
  1475. }
  1476. FlipWord(buf, off, offset, word);
  1477. }
  1478. private static void ReduceVectorWise(long[] buf, int off, int len, int words, int m, int[] ks)
  1479. {
  1480. /*
  1481. * NOTE: It's important we go from highest coefficient to lowest, because for the highest
  1482. * one (only) we allow the ranges to partially overlap, and therefore any changes must take
  1483. * effect for the subsequent lower coefficients.
  1484. */
  1485. int baseBit = (words << 6) - m;
  1486. int j = ks.Length;
  1487. while (--j >= 0)
  1488. {
  1489. FlipVector(buf, off, buf, off + words, len - words, baseBit + ks[j]);
  1490. }
  1491. FlipVector(buf, off, buf, off + words, len - words, baseBit);
  1492. }
  1493. private static void FlipVector(long[] x, int xOff, long[] y, int yOff, int yLen, int bits)
  1494. {
  1495. xOff += (int)((uint)bits >> 6);
  1496. bits &= 0x3F;
  1497. if (bits == 0)
  1498. {
  1499. Add(x, xOff, y, yOff, yLen);
  1500. }
  1501. else
  1502. {
  1503. long carry = AddShiftedDown(x, xOff + 1, y, yOff, yLen, 64 - bits);
  1504. x[xOff] ^= carry;
  1505. }
  1506. }
  1507. public LongArray ModSquare(int m, int[] ks)
  1508. {
  1509. int len = GetUsedLength();
  1510. if (len == 0)
  1511. {
  1512. return this;
  1513. }
  1514. int _2len = len << 1;
  1515. long[] r = new long[_2len];
  1516. int pos = 0;
  1517. while (pos < _2len)
  1518. {
  1519. long mi = m_ints[(uint)pos >> 1];
  1520. r[pos++] = Interleave2_32to64((int)mi);
  1521. r[pos++] = Interleave2_32to64((int)((ulong)mi >> 32));
  1522. }
  1523. return new LongArray(r, 0, ReduceInPlace(r, 0, r.Length, m, ks));
  1524. }
  1525. public LongArray ModSquareN(int n, int m, int[] ks)
  1526. {
  1527. int len = GetUsedLength();
  1528. if (len == 0)
  1529. {
  1530. return this;
  1531. }
  1532. int mLen = (m + 63) >> 6;
  1533. long[] r = new long[mLen << 1];
  1534. Array.Copy(m_ints, 0, r, 0, len);
  1535. while (--n >= 0)
  1536. {
  1537. SquareInPlace(r, len, m, ks);
  1538. len = ReduceInPlace(r, 0, r.Length, m, ks);
  1539. }
  1540. return new LongArray(r, 0, len);
  1541. }
  1542. public LongArray Square(int m, int[] ks)
  1543. {
  1544. int len = GetUsedLength();
  1545. if (len == 0)
  1546. {
  1547. return this;
  1548. }
  1549. int _2len = len << 1;
  1550. long[] r = new long[_2len];
  1551. int pos = 0;
  1552. while (pos < _2len)
  1553. {
  1554. long mi = m_ints[(uint)pos >> 1];
  1555. r[pos++] = Interleave2_32to64((int)mi);
  1556. r[pos++] = Interleave2_32to64((int)((ulong)mi >> 32));
  1557. }
  1558. return new LongArray(r, 0, r.Length);
  1559. }
  1560. private static void SquareInPlace(long[] x, int xLen, int m, int[] ks)
  1561. {
  1562. int pos = xLen << 1;
  1563. while (--xLen >= 0)
  1564. {
  1565. long xVal = x[xLen];
  1566. x[--pos] = Interleave2_32to64((int)((ulong)xVal >> 32));
  1567. x[--pos] = Interleave2_32to64((int)xVal);
  1568. }
  1569. }
  1570. private static void Interleave(long[] x, int xOff, long[] z, int zOff, int count, int width)
  1571. {
  1572. switch (width)
  1573. {
  1574. case 3:
  1575. Interleave3(x, xOff, z, zOff, count);
  1576. break;
  1577. case 5:
  1578. Interleave5(x, xOff, z, zOff, count);
  1579. break;
  1580. case 7:
  1581. Interleave7(x, xOff, z, zOff, count);
  1582. break;
  1583. default:
  1584. Interleave2_n(x, xOff, z, zOff, count, BitLengths[width] - 1);
  1585. break;
  1586. }
  1587. }
  1588. private static void Interleave3(long[] x, int xOff, long[] z, int zOff, int count)
  1589. {
  1590. for (int i = 0; i < count; ++i)
  1591. {
  1592. z[zOff + i] = Interleave3(x[xOff + i]);
  1593. }
  1594. }
  1595. private static long Interleave3(long x)
  1596. {
  1597. long z = x & (1L << 63);
  1598. return z
  1599. | Interleave3_21to63((int)x & 0x1FFFFF)
  1600. | Interleave3_21to63((int)((ulong)x >> 21) & 0x1FFFFF) << 1
  1601. | Interleave3_21to63((int)((ulong)x >> 42) & 0x1FFFFF) << 2;
  1602. // int zPos = 0, wPos = 0, xPos = 0;
  1603. // for (;;)
  1604. // {
  1605. // z |= ((x >>> xPos) & 1L) << zPos;
  1606. // if (++zPos == 63)
  1607. // {
  1608. // String sz2 = Long.toBinaryString(z);
  1609. // return z;
  1610. // }
  1611. // if ((xPos += 21) >= 63)
  1612. // {
  1613. // xPos = ++wPos;
  1614. // }
  1615. // }
  1616. }
  1617. private static long Interleave3_21to63(int x)
  1618. {
  1619. int r00 = INTERLEAVE3_TABLE[x & 0x7F];
  1620. int r21 = INTERLEAVE3_TABLE[((uint)x >> 7) & 0x7F];
  1621. int r42 = INTERLEAVE3_TABLE[(uint)x >> 14];
  1622. return (r42 & 0xFFFFFFFFL) << 42 | (r21 & 0xFFFFFFFFL) << 21 | (r00 & 0xFFFFFFFFL);
  1623. }
  1624. private static void Interleave5(long[] x, int xOff, long[] z, int zOff, int count)
  1625. {
  1626. for (int i = 0; i < count; ++i)
  1627. {
  1628. z[zOff + i] = Interleave5(x[xOff + i]);
  1629. }
  1630. }
  1631. private static long Interleave5(long x)
  1632. {
  1633. return Interleave3_13to65((int)x & 0x1FFF)
  1634. | Interleave3_13to65((int)((ulong)x >> 13) & 0x1FFF) << 1
  1635. | Interleave3_13to65((int)((ulong)x >> 26) & 0x1FFF) << 2
  1636. | Interleave3_13to65((int)((ulong)x >> 39) & 0x1FFF) << 3
  1637. | Interleave3_13to65((int)((ulong)x >> 52) & 0x1FFF) << 4;
  1638. // long z = 0;
  1639. // int zPos = 0, wPos = 0, xPos = 0;
  1640. // for (;;)
  1641. // {
  1642. // z |= ((x >>> xPos) & 1L) << zPos;
  1643. // if (++zPos == 64)
  1644. // {
  1645. // return z;
  1646. // }
  1647. // if ((xPos += 13) >= 64)
  1648. // {
  1649. // xPos = ++wPos;
  1650. // }
  1651. // }
  1652. }
  1653. private static long Interleave3_13to65(int x)
  1654. {
  1655. int r00 = INTERLEAVE5_TABLE[x & 0x7F];
  1656. int r35 = INTERLEAVE5_TABLE[(uint)x >> 7];
  1657. return (r35 & 0xFFFFFFFFL) << 35 | (r00 & 0xFFFFFFFFL);
  1658. }
  1659. private static void Interleave7(long[] x, int xOff, long[] z, int zOff, int count)
  1660. {
  1661. for (int i = 0; i < count; ++i)
  1662. {
  1663. z[zOff + i] = Interleave7(x[xOff + i]);
  1664. }
  1665. }
  1666. private static long Interleave7(long x)
  1667. {
  1668. long z = x & (1L << 63);
  1669. return z
  1670. | INTERLEAVE7_TABLE[(int)x & 0x1FF]
  1671. | INTERLEAVE7_TABLE[(int)((ulong)x >> 9) & 0x1FF] << 1
  1672. | INTERLEAVE7_TABLE[(int)((ulong)x >> 18) & 0x1FF] << 2
  1673. | INTERLEAVE7_TABLE[(int)((ulong)x >> 27) & 0x1FF] << 3
  1674. | INTERLEAVE7_TABLE[(int)((ulong)x >> 36) & 0x1FF] << 4
  1675. | INTERLEAVE7_TABLE[(int)((ulong)x >> 45) & 0x1FF] << 5
  1676. | INTERLEAVE7_TABLE[(int)((ulong)x >> 54) & 0x1FF] << 6;
  1677. // int zPos = 0, wPos = 0, xPos = 0;
  1678. // for (;;)
  1679. // {
  1680. // z |= ((x >>> xPos) & 1L) << zPos;
  1681. // if (++zPos == 63)
  1682. // {
  1683. // return z;
  1684. // }
  1685. // if ((xPos += 9) >= 63)
  1686. // {
  1687. // xPos = ++wPos;
  1688. // }
  1689. // }
  1690. }
  1691. private static void Interleave2_n(long[] x, int xOff, long[] z, int zOff, int count, int rounds)
  1692. {
  1693. for (int i = 0; i < count; ++i)
  1694. {
  1695. z[zOff + i] = Interleave2_n(x[xOff + i], rounds);
  1696. }
  1697. }
  1698. private static long Interleave2_n(long x, int rounds)
  1699. {
  1700. while (rounds > 1)
  1701. {
  1702. rounds -= 2;
  1703. x = Interleave4_16to64((int)x & 0xFFFF)
  1704. | Interleave4_16to64((int)((ulong)x >> 16) & 0xFFFF) << 1
  1705. | Interleave4_16to64((int)((ulong)x >> 32) & 0xFFFF) << 2
  1706. | Interleave4_16to64((int)((ulong)x >> 48) & 0xFFFF) << 3;
  1707. }
  1708. if (rounds > 0)
  1709. {
  1710. x = Interleave2_32to64((int)x) | Interleave2_32to64((int)((ulong)x >> 32)) << 1;
  1711. }
  1712. return x;
  1713. }
  1714. private static long Interleave4_16to64(int x)
  1715. {
  1716. int r00 = INTERLEAVE4_TABLE[x & 0xFF];
  1717. int r32 = INTERLEAVE4_TABLE[(uint)x >> 8];
  1718. return (r32 & 0xFFFFFFFFL) << 32 | (r00 & 0xFFFFFFFFL);
  1719. }
  1720. private static long Interleave2_32to64(int x)
  1721. {
  1722. int r00 = INTERLEAVE2_TABLE[x & 0xFF] | INTERLEAVE2_TABLE[((uint)x >> 8) & 0xFF] << 16;
  1723. int r32 = INTERLEAVE2_TABLE[((uint)x >> 16) & 0xFF] | INTERLEAVE2_TABLE[(uint)x >> 24] << 16;
  1724. return (r32 & 0xFFFFFFFFL) << 32 | (r00 & 0xFFFFFFFFL);
  1725. }
  1726. // private static LongArray ExpItohTsujii2(LongArray B, int n, int m, int[] ks)
  1727. // {
  1728. // LongArray t1 = B, t3 = new LongArray(new long[]{ 1L });
  1729. // int scale = 1;
  1730. //
  1731. // int numTerms = n;
  1732. // while (numTerms > 1)
  1733. // {
  1734. // if ((numTerms & 1) != 0)
  1735. // {
  1736. // t3 = t3.ModMultiply(t1, m, ks);
  1737. // t1 = t1.modSquareN(scale, m, ks);
  1738. // }
  1739. //
  1740. // LongArray t2 = t1.modSquareN(scale, m, ks);
  1741. // t1 = t1.ModMultiply(t2, m, ks);
  1742. // numTerms >>>= 1; scale <<= 1;
  1743. // }
  1744. //
  1745. // return t3.ModMultiply(t1, m, ks);
  1746. // }
  1747. //
  1748. // private static LongArray ExpItohTsujii23(LongArray B, int n, int m, int[] ks)
  1749. // {
  1750. // LongArray t1 = B, t3 = new LongArray(new long[]{ 1L });
  1751. // int scale = 1;
  1752. //
  1753. // int numTerms = n;
  1754. // while (numTerms > 1)
  1755. // {
  1756. // bool m03 = numTerms % 3 == 0;
  1757. // bool m14 = !m03 && (numTerms & 1) != 0;
  1758. //
  1759. // if (m14)
  1760. // {
  1761. // t3 = t3.ModMultiply(t1, m, ks);
  1762. // t1 = t1.modSquareN(scale, m, ks);
  1763. // }
  1764. //
  1765. // LongArray t2 = t1.modSquareN(scale, m, ks);
  1766. // t1 = t1.ModMultiply(t2, m, ks);
  1767. //
  1768. // if (m03)
  1769. // {
  1770. // t2 = t2.modSquareN(scale, m, ks);
  1771. // t1 = t1.ModMultiply(t2, m, ks);
  1772. // numTerms /= 3; scale *= 3;
  1773. // }
  1774. // else
  1775. // {
  1776. // numTerms >>>= 1; scale <<= 1;
  1777. // }
  1778. // }
  1779. //
  1780. // return t3.ModMultiply(t1, m, ks);
  1781. // }
  1782. //
  1783. // private static LongArray ExpItohTsujii235(LongArray B, int n, int m, int[] ks)
  1784. // {
  1785. // LongArray t1 = B, t4 = new LongArray(new long[]{ 1L });
  1786. // int scale = 1;
  1787. //
  1788. // int numTerms = n;
  1789. // while (numTerms > 1)
  1790. // {
  1791. // if (numTerms % 5 == 0)
  1792. // {
  1793. //// t1 = ExpItohTsujii23(t1, 5, m, ks);
  1794. //
  1795. // LongArray t3 = t1;
  1796. // t1 = t1.modSquareN(scale, m, ks);
  1797. //
  1798. // LongArray t2 = t1.modSquareN(scale, m, ks);
  1799. // t1 = t1.ModMultiply(t2, m, ks);
  1800. // t2 = t1.modSquareN(scale << 1, m, ks);
  1801. // t1 = t1.ModMultiply(t2, m, ks);
  1802. //
  1803. // t1 = t1.ModMultiply(t3, m, ks);
  1804. //
  1805. // numTerms /= 5; scale *= 5;
  1806. // continue;
  1807. // }
  1808. //
  1809. // bool m03 = numTerms % 3 == 0;
  1810. // bool m14 = !m03 && (numTerms & 1) != 0;
  1811. //
  1812. // if (m14)
  1813. // {
  1814. // t4 = t4.ModMultiply(t1, m, ks);
  1815. // t1 = t1.modSquareN(scale, m, ks);
  1816. // }
  1817. //
  1818. // LongArray t2 = t1.modSquareN(scale, m, ks);
  1819. // t1 = t1.ModMultiply(t2, m, ks);
  1820. //
  1821. // if (m03)
  1822. // {
  1823. // t2 = t2.modSquareN(scale, m, ks);
  1824. // t1 = t1.ModMultiply(t2, m, ks);
  1825. // numTerms /= 3; scale *= 3;
  1826. // }
  1827. // else
  1828. // {
  1829. // numTerms >>>= 1; scale <<= 1;
  1830. // }
  1831. // }
  1832. //
  1833. // return t4.ModMultiply(t1, m, ks);
  1834. // }
  1835. public LongArray ModInverse(int m, int[] ks)
  1836. {
  1837. /*
  1838. * Fermat's Little Theorem
  1839. */
  1840. // LongArray A = this;
  1841. // LongArray B = A.modSquare(m, ks);
  1842. // LongArray R0 = B, R1 = B;
  1843. // for (int i = 2; i < m; ++i)
  1844. // {
  1845. // R1 = R1.modSquare(m, ks);
  1846. // R0 = R0.ModMultiply(R1, m, ks);
  1847. // }
  1848. //
  1849. // return R0;
  1850. /*
  1851. * Itoh-Tsujii
  1852. */
  1853. // LongArray B = modSquare(m, ks);
  1854. // switch (m)
  1855. // {
  1856. // case 409:
  1857. // return ExpItohTsujii23(B, m - 1, m, ks);
  1858. // case 571:
  1859. // return ExpItohTsujii235(B, m - 1, m, ks);
  1860. // case 163:
  1861. // case 233:
  1862. // case 283:
  1863. // default:
  1864. // return ExpItohTsujii2(B, m - 1, m, ks);
  1865. // }
  1866. /*
  1867. * Inversion in F2m using the extended Euclidean algorithm
  1868. *
  1869. * Input: A nonzero polynomial a(z) of degree at most m-1
  1870. * Output: a(z)^(-1) mod f(z)
  1871. */
  1872. int uzDegree = Degree();
  1873. if (uzDegree == 0)
  1874. {
  1875. throw new InvalidOperationException();
  1876. }
  1877. if (uzDegree == 1)
  1878. {
  1879. return this;
  1880. }
  1881. // u(z) := a(z)
  1882. LongArray uz = (LongArray)Copy();
  1883. int t = (m + 63) >> 6;
  1884. // v(z) := f(z)
  1885. LongArray vz = new LongArray(t);
  1886. ReduceBit(vz.m_ints, 0, m, m, ks);
  1887. // g1(z) := 1, g2(z) := 0
  1888. LongArray g1z = new LongArray(t);
  1889. g1z.m_ints[0] = 1L;
  1890. LongArray g2z = new LongArray(t);
  1891. int[] uvDeg = new int[]{ uzDegree, m + 1 };
  1892. LongArray[] uv = new LongArray[]{ uz, vz };
  1893. int[] ggDeg = new int[]{ 1, 0 };
  1894. LongArray[] gg = new LongArray[]{ g1z, g2z };
  1895. int b = 1;
  1896. int duv1 = uvDeg[b];
  1897. int dgg1 = ggDeg[b];
  1898. int j = duv1 - uvDeg[1 - b];
  1899. for (;;)
  1900. {
  1901. if (j < 0)
  1902. {
  1903. j = -j;
  1904. uvDeg[b] = duv1;
  1905. ggDeg[b] = dgg1;
  1906. b = 1 - b;
  1907. duv1 = uvDeg[b];
  1908. dgg1 = ggDeg[b];
  1909. }
  1910. uv[b].AddShiftedByBitsSafe(uv[1 - b], uvDeg[1 - b], j);
  1911. int duv2 = uv[b].DegreeFrom(duv1);
  1912. if (duv2 == 0)
  1913. {
  1914. return gg[1 - b];
  1915. }
  1916. {
  1917. int dgg2 = ggDeg[1 - b];
  1918. gg[b].AddShiftedByBitsSafe(gg[1 - b], dgg2, j);
  1919. dgg2 += j;
  1920. if (dgg2 > dgg1)
  1921. {
  1922. dgg1 = dgg2;
  1923. }
  1924. else if (dgg2 == dgg1)
  1925. {
  1926. dgg1 = gg[b].DegreeFrom(dgg1);
  1927. }
  1928. }
  1929. j += (duv2 - duv1);
  1930. duv1 = duv2;
  1931. }
  1932. }
  1933. public override bool Equals(object obj)
  1934. {
  1935. return Equals(obj as LongArray);
  1936. }
  1937. public virtual bool Equals(LongArray other)
  1938. {
  1939. if (this == other)
  1940. return true;
  1941. if (null == other)
  1942. return false;
  1943. int usedLen = GetUsedLength();
  1944. if (other.GetUsedLength() != usedLen)
  1945. {
  1946. return false;
  1947. }
  1948. for (int i = 0; i < usedLen; i++)
  1949. {
  1950. if (m_ints[i] != other.m_ints[i])
  1951. {
  1952. return false;
  1953. }
  1954. }
  1955. return true;
  1956. }
  1957. public override int GetHashCode()
  1958. {
  1959. int usedLen = GetUsedLength();
  1960. int hash = 1;
  1961. for (int i = 0; i < usedLen; i++)
  1962. {
  1963. long mi = m_ints[i];
  1964. hash *= 31;
  1965. hash ^= (int)mi;
  1966. hash *= 31;
  1967. hash ^= (int)((ulong)mi >> 32);
  1968. }
  1969. return hash;
  1970. }
  1971. public LongArray Copy()
  1972. {
  1973. return new LongArray(Arrays.Clone(m_ints));
  1974. }
  1975. public override string ToString()
  1976. {
  1977. int i = GetUsedLength();
  1978. if (i == 0)
  1979. {
  1980. return "0";
  1981. }
  1982. StringBuilder sb = new StringBuilder(Convert.ToString(m_ints[--i], 2));
  1983. while (--i >= 0)
  1984. {
  1985. string s = Convert.ToString(m_ints[i], 2);
  1986. // Add leading zeroes, except for highest significant word
  1987. int len = s.Length;
  1988. if (len < 64)
  1989. {
  1990. sb.Append(ZEROES.Substring(len));
  1991. }
  1992. sb.Append(s);
  1993. }
  1994. return sb.ToString();
  1995. }
  1996. }
  1997. }
  1998. #pragma warning restore
  1999. #endif