Nat256.cs 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. #if NETCOREAPP3_0_OR_GREATER
  6. using System.Runtime.CompilerServices;
  7. using System.Runtime.InteropServices;
  8. using System.Runtime.Intrinsics;
  9. using System.Runtime.Intrinsics.X86;
  10. #endif
  11. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
  12. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.Raw
  13. {
  14. internal abstract class Nat256
  15. {
  16. private const ulong M = 0xFFFFFFFFUL;
  17. public static uint Add(uint[] x, uint[] y, uint[] z)
  18. {
  19. ulong c = 0;
  20. c += (ulong)x[0] + y[0];
  21. z[0] = (uint)c;
  22. c >>= 32;
  23. c += (ulong)x[1] + y[1];
  24. z[1] = (uint)c;
  25. c >>= 32;
  26. c += (ulong)x[2] + y[2];
  27. z[2] = (uint)c;
  28. c >>= 32;
  29. c += (ulong)x[3] + y[3];
  30. z[3] = (uint)c;
  31. c >>= 32;
  32. c += (ulong)x[4] + y[4];
  33. z[4] = (uint)c;
  34. c >>= 32;
  35. c += (ulong)x[5] + y[5];
  36. z[5] = (uint)c;
  37. c >>= 32;
  38. c += (ulong)x[6] + y[6];
  39. z[6] = (uint)c;
  40. c >>= 32;
  41. c += (ulong)x[7] + y[7];
  42. z[7] = (uint)c;
  43. c >>= 32;
  44. return (uint)c;
  45. }
  46. public static uint Add(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  47. {
  48. ulong c = 0;
  49. c += (ulong)x[xOff + 0] + y[yOff + 0];
  50. z[zOff + 0] = (uint)c;
  51. c >>= 32;
  52. c += (ulong)x[xOff + 1] + y[yOff + 1];
  53. z[zOff + 1] = (uint)c;
  54. c >>= 32;
  55. c += (ulong)x[xOff + 2] + y[yOff + 2];
  56. z[zOff + 2] = (uint)c;
  57. c >>= 32;
  58. c += (ulong)x[xOff + 3] + y[yOff + 3];
  59. z[zOff + 3] = (uint)c;
  60. c >>= 32;
  61. c += (ulong)x[xOff + 4] + y[yOff + 4];
  62. z[zOff + 4] = (uint)c;
  63. c >>= 32;
  64. c += (ulong)x[xOff + 5] + y[yOff + 5];
  65. z[zOff + 5] = (uint)c;
  66. c >>= 32;
  67. c += (ulong)x[xOff + 6] + y[yOff + 6];
  68. z[zOff + 6] = (uint)c;
  69. c >>= 32;
  70. c += (ulong)x[xOff + 7] + y[yOff + 7];
  71. z[zOff + 7] = (uint)c;
  72. c >>= 32;
  73. return (uint)c;
  74. }
  75. public static uint AddBothTo(uint[] x, uint[] y, uint[] z)
  76. {
  77. ulong c = 0;
  78. c += (ulong)x[0] + y[0] + z[0];
  79. z[0] = (uint)c;
  80. c >>= 32;
  81. c += (ulong)x[1] + y[1] + z[1];
  82. z[1] = (uint)c;
  83. c >>= 32;
  84. c += (ulong)x[2] + y[2] + z[2];
  85. z[2] = (uint)c;
  86. c >>= 32;
  87. c += (ulong)x[3] + y[3] + z[3];
  88. z[3] = (uint)c;
  89. c >>= 32;
  90. c += (ulong)x[4] + y[4] + z[4];
  91. z[4] = (uint)c;
  92. c >>= 32;
  93. c += (ulong)x[5] + y[5] + z[5];
  94. z[5] = (uint)c;
  95. c >>= 32;
  96. c += (ulong)x[6] + y[6] + z[6];
  97. z[6] = (uint)c;
  98. c >>= 32;
  99. c += (ulong)x[7] + y[7] + z[7];
  100. z[7] = (uint)c;
  101. c >>= 32;
  102. return (uint)c;
  103. }
  104. public static uint AddBothTo(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  105. {
  106. ulong c = 0;
  107. c += (ulong)x[xOff + 0] + y[yOff + 0] + z[zOff + 0];
  108. z[zOff + 0] = (uint)c;
  109. c >>= 32;
  110. c += (ulong)x[xOff + 1] + y[yOff + 1] + z[zOff + 1];
  111. z[zOff + 1] = (uint)c;
  112. c >>= 32;
  113. c += (ulong)x[xOff + 2] + y[yOff + 2] + z[zOff + 2];
  114. z[zOff + 2] = (uint)c;
  115. c >>= 32;
  116. c += (ulong)x[xOff + 3] + y[yOff + 3] + z[zOff + 3];
  117. z[zOff + 3] = (uint)c;
  118. c >>= 32;
  119. c += (ulong)x[xOff + 4] + y[yOff + 4] + z[zOff + 4];
  120. z[zOff + 4] = (uint)c;
  121. c >>= 32;
  122. c += (ulong)x[xOff + 5] + y[yOff + 5] + z[zOff + 5];
  123. z[zOff + 5] = (uint)c;
  124. c >>= 32;
  125. c += (ulong)x[xOff + 6] + y[yOff + 6] + z[zOff + 6];
  126. z[zOff + 6] = (uint)c;
  127. c >>= 32;
  128. c += (ulong)x[xOff + 7] + y[yOff + 7] + z[zOff + 7];
  129. z[zOff + 7] = (uint)c;
  130. c >>= 32;
  131. return (uint)c;
  132. }
  133. public static uint AddTo(uint[] x, uint[] z)
  134. {
  135. ulong c = 0;
  136. c += (ulong)x[0] + z[0];
  137. z[0] = (uint)c;
  138. c >>= 32;
  139. c += (ulong)x[1] + z[1];
  140. z[1] = (uint)c;
  141. c >>= 32;
  142. c += (ulong)x[2] + z[2];
  143. z[2] = (uint)c;
  144. c >>= 32;
  145. c += (ulong)x[3] + z[3];
  146. z[3] = (uint)c;
  147. c >>= 32;
  148. c += (ulong)x[4] + z[4];
  149. z[4] = (uint)c;
  150. c >>= 32;
  151. c += (ulong)x[5] + z[5];
  152. z[5] = (uint)c;
  153. c >>= 32;
  154. c += (ulong)x[6] + z[6];
  155. z[6] = (uint)c;
  156. c >>= 32;
  157. c += (ulong)x[7] + z[7];
  158. z[7] = (uint)c;
  159. c >>= 32;
  160. return (uint)c;
  161. }
  162. public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn)
  163. {
  164. ulong c = cIn;
  165. c += (ulong)x[xOff + 0] + z[zOff + 0];
  166. z[zOff + 0] = (uint)c;
  167. c >>= 32;
  168. c += (ulong)x[xOff + 1] + z[zOff + 1];
  169. z[zOff + 1] = (uint)c;
  170. c >>= 32;
  171. c += (ulong)x[xOff + 2] + z[zOff + 2];
  172. z[zOff + 2] = (uint)c;
  173. c >>= 32;
  174. c += (ulong)x[xOff + 3] + z[zOff + 3];
  175. z[zOff + 3] = (uint)c;
  176. c >>= 32;
  177. c += (ulong)x[xOff + 4] + z[zOff + 4];
  178. z[zOff + 4] = (uint)c;
  179. c >>= 32;
  180. c += (ulong)x[xOff + 5] + z[zOff + 5];
  181. z[zOff + 5] = (uint)c;
  182. c >>= 32;
  183. c += (ulong)x[xOff + 6] + z[zOff + 6];
  184. z[zOff + 6] = (uint)c;
  185. c >>= 32;
  186. c += (ulong)x[xOff + 7] + z[zOff + 7];
  187. z[zOff + 7] = (uint)c;
  188. c >>= 32;
  189. return (uint)c;
  190. }
  191. public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff)
  192. {
  193. ulong c = 0;
  194. c += (ulong)u[uOff + 0] + v[vOff + 0];
  195. u[uOff + 0] = (uint)c;
  196. v[vOff + 0] = (uint)c;
  197. c >>= 32;
  198. c += (ulong)u[uOff + 1] + v[vOff + 1];
  199. u[uOff + 1] = (uint)c;
  200. v[vOff + 1] = (uint)c;
  201. c >>= 32;
  202. c += (ulong)u[uOff + 2] + v[vOff + 2];
  203. u[uOff + 2] = (uint)c;
  204. v[vOff + 2] = (uint)c;
  205. c >>= 32;
  206. c += (ulong)u[uOff + 3] + v[vOff + 3];
  207. u[uOff + 3] = (uint)c;
  208. v[vOff + 3] = (uint)c;
  209. c >>= 32;
  210. c += (ulong)u[uOff + 4] + v[vOff + 4];
  211. u[uOff + 4] = (uint)c;
  212. v[vOff + 4] = (uint)c;
  213. c >>= 32;
  214. c += (ulong)u[uOff + 5] + v[vOff + 5];
  215. u[uOff + 5] = (uint)c;
  216. v[vOff + 5] = (uint)c;
  217. c >>= 32;
  218. c += (ulong)u[uOff + 6] + v[vOff + 6];
  219. u[uOff + 6] = (uint)c;
  220. v[vOff + 6] = (uint)c;
  221. c >>= 32;
  222. c += (ulong)u[uOff + 7] + v[vOff + 7];
  223. u[uOff + 7] = (uint)c;
  224. v[vOff + 7] = (uint)c;
  225. c >>= 32;
  226. return (uint)c;
  227. }
  228. public static void Copy(uint[] x, uint[] z)
  229. {
  230. z[0] = x[0];
  231. z[1] = x[1];
  232. z[2] = x[2];
  233. z[3] = x[3];
  234. z[4] = x[4];
  235. z[5] = x[5];
  236. z[6] = x[6];
  237. z[7] = x[7];
  238. }
  239. public static void Copy(uint[] x, int xOff, uint[] z, int zOff)
  240. {
  241. z[zOff + 0] = x[xOff + 0];
  242. z[zOff + 1] = x[xOff + 1];
  243. z[zOff + 2] = x[xOff + 2];
  244. z[zOff + 3] = x[xOff + 3];
  245. z[zOff + 4] = x[xOff + 4];
  246. z[zOff + 5] = x[xOff + 5];
  247. z[zOff + 6] = x[xOff + 6];
  248. z[zOff + 7] = x[xOff + 7];
  249. }
  250. public static void Copy64(ulong[] x, ulong[] z)
  251. {
  252. z[0] = x[0];
  253. z[1] = x[1];
  254. z[2] = x[2];
  255. z[3] = x[3];
  256. }
  257. public static void Copy64(ulong[] x, int xOff, ulong[] z, int zOff)
  258. {
  259. z[zOff + 0] = x[xOff + 0];
  260. z[zOff + 1] = x[xOff + 1];
  261. z[zOff + 2] = x[xOff + 2];
  262. z[zOff + 3] = x[xOff + 3];
  263. }
  264. public static uint[] Create()
  265. {
  266. return new uint[8];
  267. }
  268. public static ulong[] Create64()
  269. {
  270. return new ulong[4];
  271. }
  272. public static uint[] CreateExt()
  273. {
  274. return new uint[16];
  275. }
  276. public static ulong[] CreateExt64()
  277. {
  278. return new ulong[8];
  279. }
  280. public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  281. {
  282. bool pos = Gte(x, xOff, y, yOff);
  283. if (pos)
  284. {
  285. Sub(x, xOff, y, yOff, z, zOff);
  286. }
  287. else
  288. {
  289. Sub(y, yOff, x, xOff, z, zOff);
  290. }
  291. return pos;
  292. }
  293. public static bool Eq(uint[] x, uint[] y)
  294. {
  295. for (int i = 7; i >= 0; --i)
  296. {
  297. if (x[i] != y[i])
  298. return false;
  299. }
  300. return true;
  301. }
  302. public static bool Eq64(ulong[] x, ulong[] y)
  303. {
  304. for (int i = 3; i >= 0; --i)
  305. {
  306. if (x[i] != y[i])
  307. {
  308. return false;
  309. }
  310. }
  311. return true;
  312. }
  313. public static uint GetBit(uint[] x, int bit)
  314. {
  315. if (bit == 0)
  316. {
  317. return x[0] & 1;
  318. }
  319. if ((bit & 255) != bit)
  320. {
  321. return 0;
  322. }
  323. int w = bit >> 5;
  324. int b = bit & 31;
  325. return (x[w] >> b) & 1;
  326. }
  327. public static bool Gte(uint[] x, uint[] y)
  328. {
  329. for (int i = 7; i >= 0; --i)
  330. {
  331. uint x_i = x[i], y_i = y[i];
  332. if (x_i < y_i)
  333. return false;
  334. if (x_i > y_i)
  335. return true;
  336. }
  337. return true;
  338. }
  339. public static bool Gte(uint[] x, int xOff, uint[] y, int yOff)
  340. {
  341. for (int i = 7; i >= 0; --i)
  342. {
  343. uint x_i = x[xOff + i], y_i = y[yOff + i];
  344. if (x_i < y_i)
  345. return false;
  346. if (x_i > y_i)
  347. return true;
  348. }
  349. return true;
  350. }
  351. public static bool IsOne(uint[] x)
  352. {
  353. if (x[0] != 1)
  354. {
  355. return false;
  356. }
  357. for (int i = 1; i < 8; ++i)
  358. {
  359. if (x[i] != 0)
  360. {
  361. return false;
  362. }
  363. }
  364. return true;
  365. }
  366. public static bool IsOne64(ulong[] x)
  367. {
  368. if (x[0] != 1UL)
  369. {
  370. return false;
  371. }
  372. for (int i = 1; i < 4; ++i)
  373. {
  374. if (x[i] != 0UL)
  375. {
  376. return false;
  377. }
  378. }
  379. return true;
  380. }
  381. public static bool IsZero(uint[] x)
  382. {
  383. for (int i = 0; i < 8; ++i)
  384. {
  385. if (x[i] != 0)
  386. {
  387. return false;
  388. }
  389. }
  390. return true;
  391. }
  392. public static bool IsZero64(ulong[] x)
  393. {
  394. for (int i = 0; i < 4; ++i)
  395. {
  396. if (x[i] != 0UL)
  397. {
  398. return false;
  399. }
  400. }
  401. return true;
  402. }
  403. public static void Mul(uint[] x, uint[] y, uint[] zz)
  404. {
  405. ulong y_0 = y[0];
  406. ulong y_1 = y[1];
  407. ulong y_2 = y[2];
  408. ulong y_3 = y[3];
  409. ulong y_4 = y[4];
  410. ulong y_5 = y[5];
  411. ulong y_6 = y[6];
  412. ulong y_7 = y[7];
  413. {
  414. ulong c = 0, x_0 = x[0];
  415. c += x_0 * y_0;
  416. zz[0] = (uint)c;
  417. c >>= 32;
  418. c += x_0 * y_1;
  419. zz[1] = (uint)c;
  420. c >>= 32;
  421. c += x_0 * y_2;
  422. zz[2] = (uint)c;
  423. c >>= 32;
  424. c += x_0 * y_3;
  425. zz[3] = (uint)c;
  426. c >>= 32;
  427. c += x_0 * y_4;
  428. zz[4] = (uint)c;
  429. c >>= 32;
  430. c += x_0 * y_5;
  431. zz[5] = (uint)c;
  432. c >>= 32;
  433. c += x_0 * y_6;
  434. zz[6] = (uint)c;
  435. c >>= 32;
  436. c += x_0 * y_7;
  437. zz[7] = (uint)c;
  438. c >>= 32;
  439. zz[8] = (uint)c;
  440. }
  441. for (int i = 1; i < 8; ++i)
  442. {
  443. ulong c = 0, x_i = x[i];
  444. c += x_i * y_0 + zz[i + 0];
  445. zz[i + 0] = (uint)c;
  446. c >>= 32;
  447. c += x_i * y_1 + zz[i + 1];
  448. zz[i + 1] = (uint)c;
  449. c >>= 32;
  450. c += x_i * y_2 + zz[i + 2];
  451. zz[i + 2] = (uint)c;
  452. c >>= 32;
  453. c += x_i * y_3 + zz[i + 3];
  454. zz[i + 3] = (uint)c;
  455. c >>= 32;
  456. c += x_i * y_4 + zz[i + 4];
  457. zz[i + 4] = (uint)c;
  458. c >>= 32;
  459. c += x_i * y_5 + zz[i + 5];
  460. zz[i + 5] = (uint)c;
  461. c >>= 32;
  462. c += x_i * y_6 + zz[i + 6];
  463. zz[i + 6] = (uint)c;
  464. c >>= 32;
  465. c += x_i * y_7 + zz[i + 7];
  466. zz[i + 7] = (uint)c;
  467. c >>= 32;
  468. zz[i + 8] = (uint)c;
  469. }
  470. }
  471. public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
  472. {
  473. ulong y_0 = y[yOff + 0];
  474. ulong y_1 = y[yOff + 1];
  475. ulong y_2 = y[yOff + 2];
  476. ulong y_3 = y[yOff + 3];
  477. ulong y_4 = y[yOff + 4];
  478. ulong y_5 = y[yOff + 5];
  479. ulong y_6 = y[yOff + 6];
  480. ulong y_7 = y[yOff + 7];
  481. {
  482. ulong c = 0, x_0 = x[xOff + 0];
  483. c += x_0 * y_0;
  484. zz[zzOff + 0] = (uint)c;
  485. c >>= 32;
  486. c += x_0 * y_1;
  487. zz[zzOff + 1] = (uint)c;
  488. c >>= 32;
  489. c += x_0 * y_2;
  490. zz[zzOff + 2] = (uint)c;
  491. c >>= 32;
  492. c += x_0 * y_3;
  493. zz[zzOff + 3] = (uint)c;
  494. c >>= 32;
  495. c += x_0 * y_4;
  496. zz[zzOff + 4] = (uint)c;
  497. c >>= 32;
  498. c += x_0 * y_5;
  499. zz[zzOff + 5] = (uint)c;
  500. c >>= 32;
  501. c += x_0 * y_6;
  502. zz[zzOff + 6] = (uint)c;
  503. c >>= 32;
  504. c += x_0 * y_7;
  505. zz[zzOff + 7] = (uint)c;
  506. c >>= 32;
  507. zz[zzOff + 8] = (uint)c;
  508. }
  509. for (int i = 1; i < 8; ++i)
  510. {
  511. ++zzOff;
  512. ulong c = 0, x_i = x[xOff + i];
  513. c += x_i * y_0 + zz[zzOff + 0];
  514. zz[zzOff + 0] = (uint)c;
  515. c >>= 32;
  516. c += x_i * y_1 + zz[zzOff + 1];
  517. zz[zzOff + 1] = (uint)c;
  518. c >>= 32;
  519. c += x_i * y_2 + zz[zzOff + 2];
  520. zz[zzOff + 2] = (uint)c;
  521. c >>= 32;
  522. c += x_i * y_3 + zz[zzOff + 3];
  523. zz[zzOff + 3] = (uint)c;
  524. c >>= 32;
  525. c += x_i * y_4 + zz[zzOff + 4];
  526. zz[zzOff + 4] = (uint)c;
  527. c >>= 32;
  528. c += x_i * y_5 + zz[zzOff + 5];
  529. zz[zzOff + 5] = (uint)c;
  530. c >>= 32;
  531. c += x_i * y_6 + zz[zzOff + 6];
  532. zz[zzOff + 6] = (uint)c;
  533. c >>= 32;
  534. c += x_i * y_7 + zz[zzOff + 7];
  535. zz[zzOff + 7] = (uint)c;
  536. c >>= 32;
  537. zz[zzOff + 8] = (uint)c;
  538. }
  539. }
  540. public static uint MulAddTo(uint[] x, uint[] y, uint[] zz)
  541. {
  542. ulong y_0 = y[0];
  543. ulong y_1 = y[1];
  544. ulong y_2 = y[2];
  545. ulong y_3 = y[3];
  546. ulong y_4 = y[4];
  547. ulong y_5 = y[5];
  548. ulong y_6 = y[6];
  549. ulong y_7 = y[7];
  550. ulong zc = 0;
  551. for (int i = 0; i < 8; ++i)
  552. {
  553. ulong c = 0, x_i = x[i];
  554. c += x_i * y_0 + zz[i + 0];
  555. zz[i + 0] = (uint)c;
  556. c >>= 32;
  557. c += x_i * y_1 + zz[i + 1];
  558. zz[i + 1] = (uint)c;
  559. c >>= 32;
  560. c += x_i * y_2 + zz[i + 2];
  561. zz[i + 2] = (uint)c;
  562. c >>= 32;
  563. c += x_i * y_3 + zz[i + 3];
  564. zz[i + 3] = (uint)c;
  565. c >>= 32;
  566. c += x_i * y_4 + zz[i + 4];
  567. zz[i + 4] = (uint)c;
  568. c >>= 32;
  569. c += x_i * y_5 + zz[i + 5];
  570. zz[i + 5] = (uint)c;
  571. c >>= 32;
  572. c += x_i * y_6 + zz[i + 6];
  573. zz[i + 6] = (uint)c;
  574. c >>= 32;
  575. c += x_i * y_7 + zz[i + 7];
  576. zz[i + 7] = (uint)c;
  577. c >>= 32;
  578. zc += c + zz[i + 8];
  579. zz[i + 8] = (uint)zc;
  580. zc >>= 32;
  581. }
  582. return (uint)zc;
  583. }
  584. public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
  585. {
  586. ulong y_0 = y[yOff + 0];
  587. ulong y_1 = y[yOff + 1];
  588. ulong y_2 = y[yOff + 2];
  589. ulong y_3 = y[yOff + 3];
  590. ulong y_4 = y[yOff + 4];
  591. ulong y_5 = y[yOff + 5];
  592. ulong y_6 = y[yOff + 6];
  593. ulong y_7 = y[yOff + 7];
  594. ulong zc = 0;
  595. for (int i = 0; i < 8; ++i)
  596. {
  597. ulong c = 0, x_i = x[xOff + i];
  598. c += x_i * y_0 + zz[zzOff + 0];
  599. zz[zzOff + 0] = (uint)c;
  600. c >>= 32;
  601. c += x_i * y_1 + zz[zzOff + 1];
  602. zz[zzOff + 1] = (uint)c;
  603. c >>= 32;
  604. c += x_i * y_2 + zz[zzOff + 2];
  605. zz[zzOff + 2] = (uint)c;
  606. c >>= 32;
  607. c += x_i * y_3 + zz[zzOff + 3];
  608. zz[zzOff + 3] = (uint)c;
  609. c >>= 32;
  610. c += x_i * y_4 + zz[zzOff + 4];
  611. zz[zzOff + 4] = (uint)c;
  612. c >>= 32;
  613. c += x_i * y_5 + zz[zzOff + 5];
  614. zz[zzOff + 5] = (uint)c;
  615. c >>= 32;
  616. c += x_i * y_6 + zz[zzOff + 6];
  617. zz[zzOff + 6] = (uint)c;
  618. c >>= 32;
  619. c += x_i * y_7 + zz[zzOff + 7];
  620. zz[zzOff + 7] = (uint)c;
  621. c >>= 32;
  622. zc += c + zz[zzOff + 8];
  623. zz[zzOff + 8] = (uint)zc;
  624. zc >>= 32;
  625. ++zzOff;
  626. }
  627. return (uint)zc;
  628. }
  629. public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  630. {
  631. Debug.Assert(w >> 31 == 0);
  632. ulong c = 0, wVal = w;
  633. ulong x0 = x[xOff + 0];
  634. c += wVal * x0 + y[yOff + 0];
  635. z[zOff + 0] = (uint)c;
  636. c >>= 32;
  637. ulong x1 = x[xOff + 1];
  638. c += wVal * x1 + x0 + y[yOff + 1];
  639. z[zOff + 1] = (uint)c;
  640. c >>= 32;
  641. ulong x2 = x[xOff + 2];
  642. c += wVal * x2 + x1 + y[yOff + 2];
  643. z[zOff + 2] = (uint)c;
  644. c >>= 32;
  645. ulong x3 = x[xOff + 3];
  646. c += wVal * x3 + x2 + y[yOff + 3];
  647. z[zOff + 3] = (uint)c;
  648. c >>= 32;
  649. ulong x4 = x[xOff + 4];
  650. c += wVal * x4 + x3 + y[yOff + 4];
  651. z[zOff + 4] = (uint)c;
  652. c >>= 32;
  653. ulong x5 = x[xOff + 5];
  654. c += wVal * x5 + x4 + y[yOff + 5];
  655. z[zOff + 5] = (uint)c;
  656. c >>= 32;
  657. ulong x6 = x[xOff + 6];
  658. c += wVal * x6 + x5 + y[yOff + 6];
  659. z[zOff + 6] = (uint)c;
  660. c >>= 32;
  661. ulong x7 = x[xOff + 7];
  662. c += wVal * x7 + x6 + y[yOff + 7];
  663. z[zOff + 7] = (uint)c;
  664. c >>= 32;
  665. c += x7;
  666. return c;
  667. }
  668. public static uint MulByWord(uint x, uint[] z)
  669. {
  670. ulong c = 0, xVal = x;
  671. c += xVal * (ulong)z[0];
  672. z[0] = (uint)c;
  673. c >>= 32;
  674. c += xVal * (ulong)z[1];
  675. z[1] = (uint)c;
  676. c >>= 32;
  677. c += xVal * (ulong)z[2];
  678. z[2] = (uint)c;
  679. c >>= 32;
  680. c += xVal * (ulong)z[3];
  681. z[3] = (uint)c;
  682. c >>= 32;
  683. c += xVal * (ulong)z[4];
  684. z[4] = (uint)c;
  685. c >>= 32;
  686. c += xVal * (ulong)z[5];
  687. z[5] = (uint)c;
  688. c >>= 32;
  689. c += xVal * (ulong)z[6];
  690. z[6] = (uint)c;
  691. c >>= 32;
  692. c += xVal * (ulong)z[7];
  693. z[7] = (uint)c;
  694. c >>= 32;
  695. return (uint)c;
  696. }
  697. public static uint MulByWordAddTo(uint x, uint[] y, uint[] z)
  698. {
  699. ulong c = 0, xVal = x;
  700. c += xVal * (ulong)z[0] + y[0];
  701. z[0] = (uint)c;
  702. c >>= 32;
  703. c += xVal * (ulong)z[1] + y[1];
  704. z[1] = (uint)c;
  705. c >>= 32;
  706. c += xVal * (ulong)z[2] + y[2];
  707. z[2] = (uint)c;
  708. c >>= 32;
  709. c += xVal * (ulong)z[3] + y[3];
  710. z[3] = (uint)c;
  711. c >>= 32;
  712. c += xVal * (ulong)z[4] + y[4];
  713. z[4] = (uint)c;
  714. c >>= 32;
  715. c += xVal * (ulong)z[5] + y[5];
  716. z[5] = (uint)c;
  717. c >>= 32;
  718. c += xVal * (ulong)z[6] + y[6];
  719. z[6] = (uint)c;
  720. c >>= 32;
  721. c += xVal * (ulong)z[7] + y[7];
  722. z[7] = (uint)c;
  723. c >>= 32;
  724. return (uint)c;
  725. }
  726. public static uint MulWordAddTo(uint x, uint[] y, int yOff, uint[] z, int zOff)
  727. {
  728. ulong c = 0, xVal = x;
  729. c += xVal * y[yOff + 0] + z[zOff + 0];
  730. z[zOff + 0] = (uint)c;
  731. c >>= 32;
  732. c += xVal * y[yOff + 1] + z[zOff + 1];
  733. z[zOff + 1] = (uint)c;
  734. c >>= 32;
  735. c += xVal * y[yOff + 2] + z[zOff + 2];
  736. z[zOff + 2] = (uint)c;
  737. c >>= 32;
  738. c += xVal * y[yOff + 3] + z[zOff + 3];
  739. z[zOff + 3] = (uint)c;
  740. c >>= 32;
  741. c += xVal * y[yOff + 4] + z[zOff + 4];
  742. z[zOff + 4] = (uint)c;
  743. c >>= 32;
  744. c += xVal * y[yOff + 5] + z[zOff + 5];
  745. z[zOff + 5] = (uint)c;
  746. c >>= 32;
  747. c += xVal * y[yOff + 6] + z[zOff + 6];
  748. z[zOff + 6] = (uint)c;
  749. c >>= 32;
  750. c += xVal * y[yOff + 7] + z[zOff + 7];
  751. z[zOff + 7] = (uint)c;
  752. c >>= 32;
  753. return (uint)c;
  754. }
  755. public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff)
  756. {
  757. Debug.Assert(x >> 31 == 0);
  758. Debug.Assert(zOff <= 4);
  759. ulong c = 0, xVal = x;
  760. ulong y00 = y & M;
  761. c += xVal * y00 + z[zOff + 0];
  762. z[zOff + 0] = (uint)c;
  763. c >>= 32;
  764. ulong y01 = y >> 32;
  765. c += xVal * y01 + y00 + z[zOff + 1];
  766. z[zOff + 1] = (uint)c;
  767. c >>= 32;
  768. c += y01 + z[zOff + 2];
  769. z[zOff + 2] = (uint)c;
  770. c >>= 32;
  771. c += z[zOff + 3];
  772. z[zOff + 3] = (uint)c;
  773. c >>= 32;
  774. return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 4);
  775. }
  776. public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff)
  777. {
  778. Debug.Assert(x >> 31 == 0);
  779. Debug.Assert(zOff <= 5);
  780. ulong c = 0, yVal = y;
  781. c += yVal * x + z[zOff + 0];
  782. z[zOff + 0] = (uint)c;
  783. c >>= 32;
  784. c += yVal + z[zOff + 1];
  785. z[zOff + 1] = (uint)c;
  786. c >>= 32;
  787. c += z[zOff + 2];
  788. z[zOff + 2] = (uint)c;
  789. c >>= 32;
  790. return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 3);
  791. }
  792. public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff)
  793. {
  794. Debug.Assert(zOff <= 5);
  795. ulong c = 0, xVal = x;
  796. c += xVal * y + z[zOff + 0];
  797. z[zOff + 0] = (uint)c;
  798. c >>= 32;
  799. c += xVal * (y >> 32) + z[zOff + 1];
  800. z[zOff + 1] = (uint)c;
  801. c >>= 32;
  802. c += z[zOff + 2];
  803. z[zOff + 2] = (uint)c;
  804. c >>= 32;
  805. return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 3);
  806. }
  807. public static uint MulWord(uint x, uint[] y, uint[] z, int zOff)
  808. {
  809. ulong c = 0, xVal = x;
  810. int i = 0;
  811. do
  812. {
  813. c += xVal * y[i];
  814. z[zOff + i] = (uint)c;
  815. c >>= 32;
  816. }
  817. while (++i < 8);
  818. return (uint)c;
  819. }
  820. public static void Square(uint[] x, uint[] zz)
  821. {
  822. ulong x_0 = x[0];
  823. ulong zz_1;
  824. uint c = 0, w;
  825. {
  826. int i = 7, j = 16;
  827. do
  828. {
  829. ulong xVal = x[i--];
  830. ulong p = xVal * xVal;
  831. zz[--j] = (c << 31) | (uint)(p >> 33);
  832. zz[--j] = (uint)(p >> 1);
  833. c = (uint)p;
  834. }
  835. while (i > 0);
  836. {
  837. ulong p = x_0 * x_0;
  838. zz_1 = (ulong)(c << 31) | (p >> 33);
  839. zz[0] = (uint)p;
  840. c = (uint)(p >> 32) & 1;
  841. }
  842. }
  843. ulong x_1 = x[1];
  844. ulong zz_2 = zz[2];
  845. {
  846. zz_1 += x_1 * x_0;
  847. w = (uint)zz_1;
  848. zz[1] = (w << 1) | c;
  849. c = w >> 31;
  850. zz_2 += zz_1 >> 32;
  851. }
  852. ulong x_2 = x[2];
  853. ulong zz_3 = zz[3];
  854. ulong zz_4 = zz[4];
  855. {
  856. zz_2 += x_2 * x_0;
  857. w = (uint)zz_2;
  858. zz[2] = (w << 1) | c;
  859. c = w >> 31;
  860. zz_3 += (zz_2 >> 32) + x_2 * x_1;
  861. zz_4 += zz_3 >> 32;
  862. zz_3 &= M;
  863. }
  864. ulong x_3 = x[3];
  865. ulong zz_5 = zz[5] + (zz_4 >> 32); zz_4 &= M;
  866. ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
  867. {
  868. zz_3 += x_3 * x_0;
  869. w = (uint)zz_3;
  870. zz[3] = (w << 1) | c;
  871. c = w >> 31;
  872. zz_4 += (zz_3 >> 32) + x_3 * x_1;
  873. zz_5 += (zz_4 >> 32) + x_3 * x_2;
  874. zz_4 &= M;
  875. zz_6 += zz_5 >> 32;
  876. zz_5 &= M;
  877. }
  878. ulong x_4 = x[4];
  879. ulong zz_7 = zz[7] + (zz_6 >> 32); zz_6 &= M;
  880. ulong zz_8 = zz[8] + (zz_7 >> 32); zz_7 &= M;
  881. {
  882. zz_4 += x_4 * x_0;
  883. w = (uint)zz_4;
  884. zz[4] = (w << 1) | c;
  885. c = w >> 31;
  886. zz_5 += (zz_4 >> 32) + x_4 * x_1;
  887. zz_6 += (zz_5 >> 32) + x_4 * x_2;
  888. zz_5 &= M;
  889. zz_7 += (zz_6 >> 32) + x_4 * x_3;
  890. zz_6 &= M;
  891. zz_8 += zz_7 >> 32;
  892. zz_7 &= M;
  893. }
  894. ulong x_5 = x[5];
  895. ulong zz_9 = zz[9] + (zz_8 >> 32); zz_8 &= M;
  896. ulong zz_10 = zz[10] + (zz_9 >> 32); zz_9 &= M;
  897. {
  898. zz_5 += x_5 * x_0;
  899. w = (uint)zz_5;
  900. zz[5] = (w << 1) | c;
  901. c = w >> 31;
  902. zz_6 += (zz_5 >> 32) + x_5 * x_1;
  903. zz_7 += (zz_6 >> 32) + x_5 * x_2;
  904. zz_6 &= M;
  905. zz_8 += (zz_7 >> 32) + x_5 * x_3;
  906. zz_7 &= M;
  907. zz_9 += (zz_8 >> 32) + x_5 * x_4;
  908. zz_8 &= M;
  909. zz_10 += zz_9 >> 32;
  910. zz_9 &= M;
  911. }
  912. ulong x_6 = x[6];
  913. ulong zz_11 = zz[11] + (zz_10 >> 32); zz_10 &= M;
  914. ulong zz_12 = zz[12] + (zz_11 >> 32); zz_11 &= M;
  915. {
  916. zz_6 += x_6 * x_0;
  917. w = (uint)zz_6;
  918. zz[6] = (w << 1) | c;
  919. c = w >> 31;
  920. zz_7 += (zz_6 >> 32) + x_6 * x_1;
  921. zz_8 += (zz_7 >> 32) + x_6 * x_2;
  922. zz_7 &= M;
  923. zz_9 += (zz_8 >> 32) + x_6 * x_3;
  924. zz_8 &= M;
  925. zz_10 += (zz_9 >> 32) + x_6 * x_4;
  926. zz_9 &= M;
  927. zz_11 += (zz_10 >> 32) + x_6 * x_5;
  928. zz_10 &= M;
  929. zz_12 += zz_11 >> 32;
  930. zz_11 &= M;
  931. }
  932. ulong x_7 = x[7];
  933. ulong zz_13 = zz[13] + (zz_12 >> 32); zz_12 &= M;
  934. ulong zz_14 = zz[14] + (zz_13 >> 32); zz_13 &= M;
  935. {
  936. zz_7 += x_7 * x_0;
  937. w = (uint)zz_7;
  938. zz[7] = (w << 1) | c;
  939. c = w >> 31;
  940. zz_8 += (zz_7 >> 32) + x_7 * x_1;
  941. zz_9 += (zz_8 >> 32) + x_7 * x_2;
  942. zz_10 += (zz_9 >> 32) + x_7 * x_3;
  943. zz_11 += (zz_10 >> 32) + x_7 * x_4;
  944. zz_12 += (zz_11 >> 32) + x_7 * x_5;
  945. zz_13 += (zz_12 >> 32) + x_7 * x_6;
  946. zz_14 += zz_13 >> 32;
  947. }
  948. w = (uint)zz_8;
  949. zz[8] = (w << 1) | c;
  950. c = w >> 31;
  951. w = (uint)zz_9;
  952. zz[9] = (w << 1) | c;
  953. c = w >> 31;
  954. w = (uint)zz_10;
  955. zz[10] = (w << 1) | c;
  956. c = w >> 31;
  957. w = (uint)zz_11;
  958. zz[11] = (w << 1) | c;
  959. c = w >> 31;
  960. w = (uint)zz_12;
  961. zz[12] = (w << 1) | c;
  962. c = w >> 31;
  963. w = (uint)zz_13;
  964. zz[13] = (w << 1) | c;
  965. c = w >> 31;
  966. w = (uint)zz_14;
  967. zz[14] = (w << 1) | c;
  968. c = w >> 31;
  969. w = zz[15] + (uint)(zz_14 >> 32);
  970. zz[15] = (w << 1) | c;
  971. }
  972. public static void Square(uint[] x, int xOff, uint[] zz, int zzOff)
  973. {
  974. ulong x_0 = x[xOff + 0];
  975. ulong zz_1;
  976. uint c = 0, w;
  977. {
  978. int i = 7, j = 16;
  979. do
  980. {
  981. ulong xVal = x[xOff + i--];
  982. ulong p = xVal * xVal;
  983. zz[zzOff + --j] = (c << 31) | (uint)(p >> 33);
  984. zz[zzOff + --j] = (uint)(p >> 1);
  985. c = (uint)p;
  986. }
  987. while (i > 0);
  988. {
  989. ulong p = x_0 * x_0;
  990. zz_1 = (ulong)(c << 31) | (p >> 33);
  991. zz[zzOff + 0] = (uint)p;
  992. c = (uint)(p >> 32) & 1;
  993. }
  994. }
  995. ulong x_1 = x[xOff + 1];
  996. ulong zz_2 = zz[zzOff + 2];
  997. {
  998. zz_1 += x_1 * x_0;
  999. w = (uint)zz_1;
  1000. zz[zzOff + 1] = (w << 1) | c;
  1001. c = w >> 31;
  1002. zz_2 += zz_1 >> 32;
  1003. }
  1004. ulong x_2 = x[xOff + 2];
  1005. ulong zz_3 = zz[zzOff + 3];
  1006. ulong zz_4 = zz[zzOff + 4];
  1007. {
  1008. zz_2 += x_2 * x_0;
  1009. w = (uint)zz_2;
  1010. zz[zzOff + 2] = (w << 1) | c;
  1011. c = w >> 31;
  1012. zz_3 += (zz_2 >> 32) + x_2 * x_1;
  1013. zz_4 += zz_3 >> 32;
  1014. zz_3 &= M;
  1015. }
  1016. ulong x_3 = x[xOff + 3];
  1017. ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
  1018. ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
  1019. {
  1020. zz_3 += x_3 * x_0;
  1021. w = (uint)zz_3;
  1022. zz[zzOff + 3] = (w << 1) | c;
  1023. c = w >> 31;
  1024. zz_4 += (zz_3 >> 32) + x_3 * x_1;
  1025. zz_5 += (zz_4 >> 32) + x_3 * x_2;
  1026. zz_4 &= M;
  1027. zz_6 += zz_5 >> 32;
  1028. zz_5 &= M;
  1029. }
  1030. ulong x_4 = x[xOff + 4];
  1031. ulong zz_7 = zz[zzOff + 7] + (zz_6 >> 32); zz_6 &= M;
  1032. ulong zz_8 = zz[zzOff + 8] + (zz_7 >> 32); zz_7 &= M;
  1033. {
  1034. zz_4 += x_4 * x_0;
  1035. w = (uint)zz_4;
  1036. zz[zzOff + 4] = (w << 1) | c;
  1037. c = w >> 31;
  1038. zz_5 += (zz_4 >> 32) + x_4 * x_1;
  1039. zz_6 += (zz_5 >> 32) + x_4 * x_2;
  1040. zz_5 &= M;
  1041. zz_7 += (zz_6 >> 32) + x_4 * x_3;
  1042. zz_6 &= M;
  1043. zz_8 += zz_7 >> 32;
  1044. zz_7 &= M;
  1045. }
  1046. ulong x_5 = x[xOff + 5];
  1047. ulong zz_9 = zz[zzOff + 9] + (zz_8 >> 32); zz_8 &= M;
  1048. ulong zz_10 = zz[zzOff + 10] + (zz_9 >> 32); zz_9 &= M;
  1049. {
  1050. zz_5 += x_5 * x_0;
  1051. w = (uint)zz_5;
  1052. zz[zzOff + 5] = (w << 1) | c;
  1053. c = w >> 31;
  1054. zz_6 += (zz_5 >> 32) + x_5 * x_1;
  1055. zz_7 += (zz_6 >> 32) + x_5 * x_2;
  1056. zz_6 &= M;
  1057. zz_8 += (zz_7 >> 32) + x_5 * x_3;
  1058. zz_7 &= M;
  1059. zz_9 += (zz_8 >> 32) + x_5 * x_4;
  1060. zz_8 &= M;
  1061. zz_10 += zz_9 >> 32;
  1062. zz_9 &= M;
  1063. }
  1064. ulong x_6 = x[xOff + 6];
  1065. ulong zz_11 = zz[zzOff + 11] + (zz_10 >> 32); zz_10 &= M;
  1066. ulong zz_12 = zz[zzOff + 12] + (zz_11 >> 32); zz_11 &= M;
  1067. {
  1068. zz_6 += x_6 * x_0;
  1069. w = (uint)zz_6;
  1070. zz[zzOff + 6] = (w << 1) | c;
  1071. c = w >> 31;
  1072. zz_7 += (zz_6 >> 32) + x_6 * x_1;
  1073. zz_8 += (zz_7 >> 32) + x_6 * x_2;
  1074. zz_7 &= M;
  1075. zz_9 += (zz_8 >> 32) + x_6 * x_3;
  1076. zz_8 &= M;
  1077. zz_10 += (zz_9 >> 32) + x_6 * x_4;
  1078. zz_9 &= M;
  1079. zz_11 += (zz_10 >> 32) + x_6 * x_5;
  1080. zz_10 &= M;
  1081. zz_12 += zz_11 >> 32;
  1082. zz_11 &= M;
  1083. }
  1084. ulong x_7 = x[xOff + 7];
  1085. ulong zz_13 = zz[zzOff + 13] + (zz_12 >> 32); zz_12 &= M;
  1086. ulong zz_14 = zz[zzOff + 14] + (zz_13 >> 32); zz_13 &= M;
  1087. {
  1088. zz_7 += x_7 * x_0;
  1089. w = (uint)zz_7;
  1090. zz[zzOff + 7] = (w << 1) | c;
  1091. c = w >> 31;
  1092. zz_8 += (zz_7 >> 32) + x_7 * x_1;
  1093. zz_9 += (zz_8 >> 32) + x_7 * x_2;
  1094. zz_10 += (zz_9 >> 32) + x_7 * x_3;
  1095. zz_11 += (zz_10 >> 32) + x_7 * x_4;
  1096. zz_12 += (zz_11 >> 32) + x_7 * x_5;
  1097. zz_13 += (zz_12 >> 32) + x_7 * x_6;
  1098. zz_14 += zz_13 >> 32;
  1099. }
  1100. w = (uint)zz_8;
  1101. zz[zzOff + 8] = (w << 1) | c;
  1102. c = w >> 31;
  1103. w = (uint)zz_9;
  1104. zz[zzOff + 9] = (w << 1) | c;
  1105. c = w >> 31;
  1106. w = (uint)zz_10;
  1107. zz[zzOff + 10] = (w << 1) | c;
  1108. c = w >> 31;
  1109. w = (uint)zz_11;
  1110. zz[zzOff + 11] = (w << 1) | c;
  1111. c = w >> 31;
  1112. w = (uint)zz_12;
  1113. zz[zzOff + 12] = (w << 1) | c;
  1114. c = w >> 31;
  1115. w = (uint)zz_13;
  1116. zz[zzOff + 13] = (w << 1) | c;
  1117. c = w >> 31;
  1118. w = (uint)zz_14;
  1119. zz[zzOff + 14] = (w << 1) | c;
  1120. c = w >> 31;
  1121. w = zz[zzOff + 15] + (uint)(zz_14 >> 32);
  1122. zz[zzOff + 15] = (w << 1) | c;
  1123. }
  1124. public static int Sub(uint[] x, uint[] y, uint[] z)
  1125. {
  1126. long c = 0;
  1127. c += (long)x[0] - y[0];
  1128. z[0] = (uint)c;
  1129. c >>= 32;
  1130. c += (long)x[1] - y[1];
  1131. z[1] = (uint)c;
  1132. c >>= 32;
  1133. c += (long)x[2] - y[2];
  1134. z[2] = (uint)c;
  1135. c >>= 32;
  1136. c += (long)x[3] - y[3];
  1137. z[3] = (uint)c;
  1138. c >>= 32;
  1139. c += (long)x[4] - y[4];
  1140. z[4] = (uint)c;
  1141. c >>= 32;
  1142. c += (long)x[5] - y[5];
  1143. z[5] = (uint)c;
  1144. c >>= 32;
  1145. c += (long)x[6] - y[6];
  1146. z[6] = (uint)c;
  1147. c >>= 32;
  1148. c += (long)x[7] - y[7];
  1149. z[7] = (uint)c;
  1150. c >>= 32;
  1151. return (int)c;
  1152. }
  1153. public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  1154. {
  1155. long c = 0;
  1156. c += (long)x[xOff + 0] - y[yOff + 0];
  1157. z[zOff + 0] = (uint)c;
  1158. c >>= 32;
  1159. c += (long)x[xOff + 1] - y[yOff + 1];
  1160. z[zOff + 1] = (uint)c;
  1161. c >>= 32;
  1162. c += (long)x[xOff + 2] - y[yOff + 2];
  1163. z[zOff + 2] = (uint)c;
  1164. c >>= 32;
  1165. c += (long)x[xOff + 3] - y[yOff + 3];
  1166. z[zOff + 3] = (uint)c;
  1167. c >>= 32;
  1168. c += (long)x[xOff + 4] - y[yOff + 4];
  1169. z[zOff + 4] = (uint)c;
  1170. c >>= 32;
  1171. c += (long)x[xOff + 5] - y[yOff + 5];
  1172. z[zOff + 5] = (uint)c;
  1173. c >>= 32;
  1174. c += (long)x[xOff + 6] - y[yOff + 6];
  1175. z[zOff + 6] = (uint)c;
  1176. c >>= 32;
  1177. c += (long)x[xOff + 7] - y[yOff + 7];
  1178. z[zOff + 7] = (uint)c;
  1179. c >>= 32;
  1180. return (int)c;
  1181. }
  1182. public static int SubBothFrom(uint[] x, uint[] y, uint[] z)
  1183. {
  1184. long c = 0;
  1185. c += (long)z[0] - x[0] - y[0];
  1186. z[0] = (uint)c;
  1187. c >>= 32;
  1188. c += (long)z[1] - x[1] - y[1];
  1189. z[1] = (uint)c;
  1190. c >>= 32;
  1191. c += (long)z[2] - x[2] - y[2];
  1192. z[2] = (uint)c;
  1193. c >>= 32;
  1194. c += (long)z[3] - x[3] - y[3];
  1195. z[3] = (uint)c;
  1196. c >>= 32;
  1197. c += (long)z[4] - x[4] - y[4];
  1198. z[4] = (uint)c;
  1199. c >>= 32;
  1200. c += (long)z[5] - x[5] - y[5];
  1201. z[5] = (uint)c;
  1202. c >>= 32;
  1203. c += (long)z[6] - x[6] - y[6];
  1204. z[6] = (uint)c;
  1205. c >>= 32;
  1206. c += (long)z[7] - x[7] - y[7];
  1207. z[7] = (uint)c;
  1208. c >>= 32;
  1209. return (int)c;
  1210. }
  1211. public static int SubFrom(uint[] x, uint[] z)
  1212. {
  1213. long c = 0;
  1214. c += (long)z[0] - x[0];
  1215. z[0] = (uint)c;
  1216. c >>= 32;
  1217. c += (long)z[1] - x[1];
  1218. z[1] = (uint)c;
  1219. c >>= 32;
  1220. c += (long)z[2] - x[2];
  1221. z[2] = (uint)c;
  1222. c >>= 32;
  1223. c += (long)z[3] - x[3];
  1224. z[3] = (uint)c;
  1225. c >>= 32;
  1226. c += (long)z[4] - x[4];
  1227. z[4] = (uint)c;
  1228. c >>= 32;
  1229. c += (long)z[5] - x[5];
  1230. z[5] = (uint)c;
  1231. c >>= 32;
  1232. c += (long)z[6] - x[6];
  1233. z[6] = (uint)c;
  1234. c >>= 32;
  1235. c += (long)z[7] - x[7];
  1236. z[7] = (uint)c;
  1237. c >>= 32;
  1238. return (int)c;
  1239. }
  1240. public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff)
  1241. {
  1242. long c = 0;
  1243. c += (long)z[zOff + 0] - x[xOff + 0];
  1244. z[zOff + 0] = (uint)c;
  1245. c >>= 32;
  1246. c += (long)z[zOff + 1] - x[xOff + 1];
  1247. z[zOff + 1] = (uint)c;
  1248. c >>= 32;
  1249. c += (long)z[zOff + 2] - x[xOff + 2];
  1250. z[zOff + 2] = (uint)c;
  1251. c >>= 32;
  1252. c += (long)z[zOff + 3] - x[xOff + 3];
  1253. z[zOff + 3] = (uint)c;
  1254. c >>= 32;
  1255. c += (long)z[zOff + 4] - x[xOff + 4];
  1256. z[zOff + 4] = (uint)c;
  1257. c >>= 32;
  1258. c += (long)z[zOff + 5] - x[xOff + 5];
  1259. z[zOff + 5] = (uint)c;
  1260. c >>= 32;
  1261. c += (long)z[zOff + 6] - x[xOff + 6];
  1262. z[zOff + 6] = (uint)c;
  1263. c >>= 32;
  1264. c += (long)z[zOff + 7] - x[xOff + 7];
  1265. z[zOff + 7] = (uint)c;
  1266. c >>= 32;
  1267. return (int)c;
  1268. }
  1269. public static BigInteger ToBigInteger(uint[] x)
  1270. {
  1271. byte[] bs = new byte[32];
  1272. for (int i = 0; i < 8; ++i)
  1273. {
  1274. uint x_i = x[i];
  1275. if (x_i != 0)
  1276. {
  1277. Pack.UInt32_To_BE(x_i, bs, (7 - i) << 2);
  1278. }
  1279. }
  1280. return new BigInteger(1, bs);
  1281. }
  1282. public static BigInteger ToBigInteger64(ulong[] x)
  1283. {
  1284. byte[] bs = new byte[32];
  1285. for (int i = 0; i < 4; ++i)
  1286. {
  1287. ulong x_i = x[i];
  1288. if (x_i != 0L)
  1289. {
  1290. Pack.UInt64_To_BE(x_i, bs, (3 - i) << 3);
  1291. }
  1292. }
  1293. return new BigInteger(1, bs);
  1294. }
  1295. public static void Xor(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  1296. {
  1297. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1298. Xor(x.AsSpan(xOff), y.AsSpan(yOff), z.AsSpan(zOff));
  1299. #else
  1300. for (int i = 0; i < 8; i += 4)
  1301. {
  1302. z[zOff + i + 0] = x[xOff + i + 0] ^ y[yOff + i + 0];
  1303. z[zOff + i + 1] = x[xOff + i + 1] ^ y[yOff + i + 1];
  1304. z[zOff + i + 2] = x[xOff + i + 2] ^ y[yOff + i + 2];
  1305. z[zOff + i + 3] = x[xOff + i + 3] ^ y[yOff + i + 3];
  1306. }
  1307. #endif
  1308. }
  1309. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1310. public static void Xor(ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> z)
  1311. {
  1312. #if NETCOREAPP3_0_OR_GREATER
  1313. if (Avx2.IsSupported && Unsafe.SizeOf<Vector256<byte>>() == 32)
  1314. {
  1315. var X = MemoryMarshal.AsBytes(x[..8]);
  1316. var Y = MemoryMarshal.AsBytes(y[..8]);
  1317. var Z = MemoryMarshal.AsBytes(z[..8]);
  1318. var X0 = MemoryMarshal.Read<Vector256<byte>>(X[0x00..0x20]);
  1319. var Y0 = MemoryMarshal.Read<Vector256<byte>>(Y[0x00..0x20]);
  1320. var Z0 = Avx2.Xor(X0, Y0);
  1321. MemoryMarshal.Write(Z[0x00..0x20], ref Z0);
  1322. return;
  1323. }
  1324. if (Sse2.IsSupported && Unsafe.SizeOf<Vector128<byte>>() == 16)
  1325. {
  1326. var X = MemoryMarshal.AsBytes(x[..8]);
  1327. var Y = MemoryMarshal.AsBytes(y[..8]);
  1328. var Z = MemoryMarshal.AsBytes(z[..8]);
  1329. var X0 = MemoryMarshal.Read<Vector128<byte>>(X[0x00..0x10]);
  1330. var X1 = MemoryMarshal.Read<Vector128<byte>>(X[0x10..0x20]);
  1331. var Y0 = MemoryMarshal.Read<Vector128<byte>>(Y[0x00..0x10]);
  1332. var Y1 = MemoryMarshal.Read<Vector128<byte>>(Y[0x10..0x20]);
  1333. var Z0 = Sse2.Xor(X0, Y0);
  1334. var Z1 = Sse2.Xor(X1, Y1);
  1335. MemoryMarshal.Write(Z[0x00..0x10], ref Z0);
  1336. MemoryMarshal.Write(Z[0x10..0x20], ref Z1);
  1337. return;
  1338. }
  1339. #endif
  1340. for (int i = 0; i < 8; i += 4)
  1341. {
  1342. z[i + 0] = x[i + 0] ^ y[i + 0];
  1343. z[i + 1] = x[i + 1] ^ y[i + 1];
  1344. z[i + 2] = x[i + 2] ^ y[i + 2];
  1345. z[i + 3] = x[i + 3] ^ y[i + 3];
  1346. }
  1347. }
  1348. #endif
  1349. public static void Zero(uint[] z)
  1350. {
  1351. z[0] = 0;
  1352. z[1] = 0;
  1353. z[2] = 0;
  1354. z[3] = 0;
  1355. z[4] = 0;
  1356. z[5] = 0;
  1357. z[6] = 0;
  1358. z[7] = 0;
  1359. }
  1360. }
  1361. }
  1362. #pragma warning restore
  1363. #endif