Nat256.cs 41 KB

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