Nat224.cs 36 KB

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