X448Field.cs 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.Raw;
  6. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.EC.Rfc7748
  7. {
  8. [CLSCompliant(false)]
  9. public static class X448Field
  10. {
  11. public const int Size = 16;
  12. private const uint M28 = 0x0FFFFFFFU;
  13. private static readonly uint[] P32 = new uint[]{ 0xFFFFFFFFU, 0xFFFFFFFFU, 0xFFFFFFFFU, 0xFFFFFFFFU,
  14. 0xFFFFFFFFU, 0xFFFFFFFFU, 0xFFFFFFFFU, 0xFFFFFFFEU, 0xFFFFFFFFU, 0xFFFFFFFFU, 0xFFFFFFFFU, 0xFFFFFFFFU,
  15. 0xFFFFFFFFU, 0xFFFFFFFFU };
  16. public static void Add(uint[] x, uint[] y, uint[] z)
  17. {
  18. for (int i = 0; i < Size; ++i)
  19. {
  20. z[i] = x[i] + y[i];
  21. }
  22. }
  23. public static void AddOne(uint[] z)
  24. {
  25. z[0] += 1;
  26. }
  27. public static void AddOne(uint[] z, int zOff)
  28. {
  29. z[zOff] += 1;
  30. }
  31. //public static void Apm(int[] x, int[] y, int[] zp, int[] zm)
  32. //{
  33. // for (int i = 0; i < Size; ++i)
  34. // {
  35. // int xi = x[i], yi = y[i];
  36. // zp[i] = xi + yi;
  37. // zm[i] = xi - yi;
  38. // }
  39. //}
  40. public static int AreEqual(uint[] x, uint[] y)
  41. {
  42. uint d = 0;
  43. for (int i = 0; i < Size; ++i)
  44. {
  45. d |= x[i] ^ y[i];
  46. }
  47. d |= d >> 16;
  48. d &= 0xFFFF;
  49. return ((int)d - 1) >> 31;
  50. }
  51. public static bool AreEqualVar(uint[] x, uint[] y)
  52. {
  53. return 0 != AreEqual(x, y);
  54. }
  55. public static void Carry(uint[] z)
  56. {
  57. uint z0 = z[0], z1 = z[1], z2 = z[2], z3 = z[3], z4 = z[4], z5 = z[5], z6 = z[6], z7 = z[7];
  58. uint z8 = z[8], z9 = z[9], z10 = z[10], z11 = z[11], z12 = z[12], z13 = z[13], z14 = z[14], z15 = z[15];
  59. z1 += (z0 >> 28); z0 &= M28;
  60. z5 += (z4 >> 28); z4 &= M28;
  61. z9 += (z8 >> 28); z8 &= M28;
  62. z13 += (z12 >> 28); z12 &= M28;
  63. z2 += (z1 >> 28); z1 &= M28;
  64. z6 += (z5 >> 28); z5 &= M28;
  65. z10 += (z9 >> 28); z9 &= M28;
  66. z14 += (z13 >> 28); z13 &= M28;
  67. z3 += (z2 >> 28); z2 &= M28;
  68. z7 += (z6 >> 28); z6 &= M28;
  69. z11 += (z10 >> 28); z10 &= M28;
  70. z15 += (z14 >> 28); z14 &= M28;
  71. uint t = z15 >> 28; z15 &= M28;
  72. z0 += t;
  73. z8 += t;
  74. z4 += (z3 >> 28); z3 &= M28;
  75. z8 += (z7 >> 28); z7 &= M28;
  76. z12 += (z11 >> 28); z11 &= M28;
  77. z1 += (z0 >> 28); z0 &= M28;
  78. z5 += (z4 >> 28); z4 &= M28;
  79. z9 += (z8 >> 28); z8 &= M28;
  80. z13 += (z12 >> 28); z12 &= M28;
  81. z[0] = z0; z[1] = z1; z[2] = z2; z[3] = z3; z[4] = z4; z[5] = z5; z[6] = z6; z[7] = z7;
  82. z[8] = z8; z[9] = z9; z[10] = z10; z[11] = z11; z[12] = z12; z[13] = z13; z[14] = z14; z[15] = z15;
  83. }
  84. public static void CMov(int cond, uint[] x, int xOff, uint[] z, int zOff)
  85. {
  86. Debug.Assert(0 == cond || -1 == cond);
  87. uint MASK = (uint)cond;
  88. for (int i = 0; i < Size; ++i)
  89. {
  90. uint z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
  91. z_i ^= (diff & MASK);
  92. z[zOff + i] = z_i;
  93. }
  94. }
  95. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  96. public static void CMov(int cond, ReadOnlySpan<uint> x, Span<uint> z)
  97. {
  98. Debug.Assert(0 == cond || -1 == cond);
  99. uint MASK = (uint)cond;
  100. for (int i = 0; i < Size; ++i)
  101. {
  102. uint z_i = z[i], diff = z_i ^ x[i];
  103. z_i ^= (diff & MASK);
  104. z[i] = z_i;
  105. }
  106. }
  107. #endif
  108. public static void CNegate(int negate, uint[] z)
  109. {
  110. Debug.Assert(negate >> 1 == 0);
  111. uint[] t = Create();
  112. Sub(t, z, t);
  113. CMov(-negate, t, 0, z, 0);
  114. }
  115. public static void Copy(uint[] x, int xOff, uint[] z, int zOff)
  116. {
  117. for (int i = 0; i < Size; ++i)
  118. {
  119. z[zOff + i] = x[xOff + i];
  120. }
  121. }
  122. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  123. public static void Copy(ReadOnlySpan<uint> x, Span<uint> z)
  124. {
  125. x[..Size].CopyTo(z);
  126. }
  127. #endif
  128. public static uint[] Create()
  129. {
  130. return new uint[Size];
  131. }
  132. public static uint[] CreateTable(int n)
  133. {
  134. return new uint[Size * n];
  135. }
  136. public static void CSwap(int swap, uint[] a, uint[] b)
  137. {
  138. Debug.Assert(swap >> 1 == 0);
  139. Debug.Assert(a != b);
  140. uint mask = (uint)(0 - swap);
  141. for (int i = 0; i < Size; ++i)
  142. {
  143. uint ai = a[i], bi = b[i];
  144. uint dummy = mask & (ai ^ bi);
  145. a[i] = ai ^ dummy;
  146. b[i] = bi ^ dummy;
  147. }
  148. }
  149. public static void Decode(uint[] x, int xOff, uint[] z)
  150. {
  151. Decode224(x, xOff, z, 0);
  152. Decode224(x, xOff + 7, z, 8);
  153. }
  154. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  155. public static void Decode(ReadOnlySpan<uint> x, Span<uint> z)
  156. {
  157. Decode224(x, z);
  158. Decode224(x[7..], z[8..]);
  159. }
  160. #endif
  161. public static void Decode(byte[] x, int xOff, uint[] z)
  162. {
  163. Decode56(x, xOff, z, 0);
  164. Decode56(x, xOff + 7, z, 2);
  165. Decode56(x, xOff + 14, z, 4);
  166. Decode56(x, xOff + 21, z, 6);
  167. Decode56(x, xOff + 28, z, 8);
  168. Decode56(x, xOff + 35, z, 10);
  169. Decode56(x, xOff + 42, z, 12);
  170. Decode56(x, xOff + 49, z, 14);
  171. }
  172. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  173. public static void Decode(ReadOnlySpan<byte> x, Span<uint> z)
  174. {
  175. Decode56(x, z);
  176. Decode56(x[7..], z[2..]);
  177. Decode56(x[14..], z[4..]);
  178. Decode56(x[21..], z[6..]);
  179. Decode56(x[28..], z[8..]);
  180. Decode56(x[35..], z[10..]);
  181. Decode56(x[42..], z[12..]);
  182. Decode56(x[49..], z[14..]);
  183. }
  184. #endif
  185. private static void Decode224(uint[] x, int xOff, uint[] z, int zOff)
  186. {
  187. uint x0 = x[xOff + 0], x1 = x[xOff + 1], x2 = x[xOff + 2], x3 = x[xOff + 3];
  188. uint x4 = x[xOff + 4], x5 = x[xOff + 5], x6 = x[xOff + 6];
  189. z[zOff + 0] = x0 & M28;
  190. z[zOff + 1] = (x0 >> 28 | x1 << 4) & M28;
  191. z[zOff + 2] = (x1 >> 24 | x2 << 8) & M28;
  192. z[zOff + 3] = (x2 >> 20 | x3 << 12) & M28;
  193. z[zOff + 4] = (x3 >> 16 | x4 << 16) & M28;
  194. z[zOff + 5] = (x4 >> 12 | x5 << 20) & M28;
  195. z[zOff + 6] = (x5 >> 8 | x6 << 24) & M28;
  196. z[zOff + 7] = x6 >> 4;
  197. }
  198. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  199. private static void Decode224(ReadOnlySpan<uint> x, Span<uint> z)
  200. {
  201. uint x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
  202. uint x4 = x[4], x5 = x[5], x6 = x[6];
  203. z[0] = x0 & M28;
  204. z[1] = (x0 >> 28 | x1 << 4) & M28;
  205. z[2] = (x1 >> 24 | x2 << 8) & M28;
  206. z[3] = (x2 >> 20 | x3 << 12) & M28;
  207. z[4] = (x3 >> 16 | x4 << 16) & M28;
  208. z[5] = (x4 >> 12 | x5 << 20) & M28;
  209. z[6] = (x5 >> 8 | x6 << 24) & M28;
  210. z[7] = x6 >> 4;
  211. }
  212. #endif
  213. private static uint Decode24(byte[] bs, int off)
  214. {
  215. uint n = bs[off];
  216. n |= (uint)bs[++off] << 8;
  217. n |= (uint)bs[++off] << 16;
  218. return n;
  219. }
  220. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  221. private static uint Decode24(ReadOnlySpan<byte> bs)
  222. {
  223. uint n = bs[0];
  224. n |= (uint)bs[1] << 8;
  225. n |= (uint)bs[2] << 16;
  226. return n;
  227. }
  228. #endif
  229. private static uint Decode32(byte[] bs, int off)
  230. {
  231. uint n = bs[off];
  232. n |= (uint)bs[++off] << 8;
  233. n |= (uint)bs[++off] << 16;
  234. n |= (uint)bs[++off] << 24;
  235. return n;
  236. }
  237. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  238. private static uint Decode32(ReadOnlySpan<byte> bs)
  239. {
  240. uint n = bs[0];
  241. n |= (uint)bs[1] << 8;
  242. n |= (uint)bs[2] << 16;
  243. n |= (uint)bs[3] << 24;
  244. return n;
  245. }
  246. #endif
  247. private static void Decode56(byte[] bs, int off, uint[] z, int zOff)
  248. {
  249. uint lo = Decode32(bs, off);
  250. uint hi = Decode24(bs, off + 4);
  251. z[zOff] = lo & M28;
  252. z[zOff + 1] = (lo >> 28) | (hi << 4);
  253. }
  254. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  255. private static void Decode56(ReadOnlySpan<byte> bs, Span<uint> z)
  256. {
  257. uint lo = Decode32(bs);
  258. uint hi = Decode24(bs[4..]);
  259. z[0] = lo & M28;
  260. z[1] = (lo >> 28) | (hi << 4);
  261. }
  262. #endif
  263. public static void Encode(uint[] x, uint[] z, int zOff)
  264. {
  265. Encode224(x, 0, z, zOff);
  266. Encode224(x, 8, z, zOff + 7);
  267. }
  268. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  269. public static void Encode(ReadOnlySpan<uint> x, Span<uint> z)
  270. {
  271. Encode224(x, z);
  272. Encode224(x[8..], z[7..]);
  273. }
  274. #endif
  275. public static void Encode(uint[] x, byte[] z, int zOff)
  276. {
  277. Encode56(x, 0, z, zOff);
  278. Encode56(x, 2, z, zOff + 7);
  279. Encode56(x, 4, z, zOff + 14);
  280. Encode56(x, 6, z, zOff + 21);
  281. Encode56(x, 8, z, zOff + 28);
  282. Encode56(x, 10, z, zOff + 35);
  283. Encode56(x, 12, z, zOff + 42);
  284. Encode56(x, 14, z, zOff + 49);
  285. }
  286. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  287. public static void Encode(ReadOnlySpan<uint> x, Span<byte> z)
  288. {
  289. Encode56(x, z);
  290. Encode56(x[2..], z[7..]);
  291. Encode56(x[4..], z[14..]);
  292. Encode56(x[6..], z[21..]);
  293. Encode56(x[8..], z[28..]);
  294. Encode56(x[10..], z[35..]);
  295. Encode56(x[12..], z[42..]);
  296. Encode56(x[14..], z[49..]);
  297. }
  298. #endif
  299. private static void Encode224(uint[] x, int xOff, uint[] z, int zOff)
  300. {
  301. uint x0 = x[xOff + 0], x1 = x[xOff + 1], x2 = x[xOff + 2], x3 = x[xOff + 3];
  302. uint x4 = x[xOff + 4], x5 = x[xOff + 5], x6 = x[xOff + 6], x7 = x[xOff + 7];
  303. z[zOff + 0] = x0 | (x1 << 28);
  304. z[zOff + 1] = (x1 >> 4) | (x2 << 24);
  305. z[zOff + 2] = (x2 >> 8) | (x3 << 20);
  306. z[zOff + 3] = (x3 >> 12) | (x4 << 16);
  307. z[zOff + 4] = (x4 >> 16) | (x5 << 12);
  308. z[zOff + 5] = (x5 >> 20) | (x6 << 8);
  309. z[zOff + 6] = (x6 >> 24) | (x7 << 4);
  310. }
  311. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  312. private static void Encode224(ReadOnlySpan<uint> x, Span<uint> z)
  313. {
  314. uint x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
  315. uint x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7];
  316. z[0] = x0 | (x1 << 28);
  317. z[1] = (x1 >> 4) | (x2 << 24);
  318. z[2] = (x2 >> 8) | (x3 << 20);
  319. z[3] = (x3 >> 12) | (x4 << 16);
  320. z[4] = (x4 >> 16) | (x5 << 12);
  321. z[5] = (x5 >> 20) | (x6 << 8);
  322. z[6] = (x6 >> 24) | (x7 << 4);
  323. }
  324. #endif
  325. private static void Encode24(uint n, byte[] bs, int off)
  326. {
  327. bs[ off] = (byte)(n );
  328. bs[++off] = (byte)(n >> 8);
  329. bs[++off] = (byte)(n >> 16);
  330. }
  331. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  332. private static void Encode24(uint n, Span<byte> bs)
  333. {
  334. bs[0] = (byte)(n );
  335. bs[1] = (byte)(n >> 8);
  336. bs[2] = (byte)(n >> 16);
  337. }
  338. #endif
  339. private static void Encode32(uint n, byte[] bs, int off)
  340. {
  341. bs[ off] = (byte)(n );
  342. bs[++off] = (byte)(n >> 8);
  343. bs[++off] = (byte)(n >> 16);
  344. bs[++off] = (byte)(n >> 24);
  345. }
  346. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  347. private static void Encode32(uint n, Span<byte> bs)
  348. {
  349. bs[0] = (byte)(n );
  350. bs[1] = (byte)(n >> 8);
  351. bs[2] = (byte)(n >> 16);
  352. bs[3] = (byte)(n >> 24);
  353. }
  354. #endif
  355. private static void Encode56(uint[] x, int xOff, byte[] bs, int off)
  356. {
  357. uint lo = x[xOff], hi = x[xOff + 1];
  358. Encode32(lo | (hi << 28), bs, off);
  359. Encode24(hi >> 4, bs, off + 4);
  360. }
  361. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  362. private static void Encode56(ReadOnlySpan<uint> x, Span<byte> bs)
  363. {
  364. uint lo = x[0], hi = x[1];
  365. Encode32(lo | (hi << 28), bs);
  366. Encode24(hi >> 4, bs[4..]);
  367. }
  368. #endif
  369. public static void Inv(uint[] x, uint[] z)
  370. {
  371. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  372. Inv(x.AsSpan(), z.AsSpan());
  373. #else
  374. //uint[] t = Create();
  375. //PowPm3d4(x, t);
  376. //Sqr(t, 2, t);
  377. //Mul(t, x, z);
  378. uint[] t = Create();
  379. uint[] u = new uint[14];
  380. Copy(x, 0, t, 0);
  381. Normalize(t);
  382. Encode(t, u, 0);
  383. Mod.ModOddInverse(P32, u, u);
  384. Decode(u, 0, z);
  385. #endif
  386. }
  387. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  388. public static void Inv(ReadOnlySpan<uint> x, Span<uint> z)
  389. {
  390. Span<uint> t = stackalloc uint[Size];
  391. Span<uint> u = stackalloc uint[14];
  392. Copy(x, t);
  393. Normalize(t);
  394. Encode(t, u);
  395. Mod.ModOddInverse(P32, u, u);
  396. Decode(u, z);
  397. }
  398. #endif
  399. public static void InvVar(uint[] x, uint[] z)
  400. {
  401. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  402. InvVar(x.AsSpan(), z.AsSpan());
  403. #else
  404. uint[] t = Create();
  405. uint[] u = new uint[14];
  406. Copy(x, 0, t, 0);
  407. Normalize(t);
  408. Encode(t, u, 0);
  409. Mod.ModOddInverseVar(P32, u, u);
  410. Decode(u, 0, z);
  411. #endif
  412. }
  413. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  414. public static void InvVar(ReadOnlySpan<uint> x, Span<uint> z)
  415. {
  416. Span<uint> t = stackalloc uint[Size];
  417. Span<uint> u = stackalloc uint[14];
  418. Copy(x, t);
  419. Normalize(t);
  420. Encode(t, u);
  421. Mod.ModOddInverseVar(P32, u, u);
  422. Decode(u, z);
  423. }
  424. #endif
  425. public static int IsOne(uint[] x)
  426. {
  427. uint d = x[0] ^ 1;
  428. for (int i = 1; i < Size; ++i)
  429. {
  430. d |= x[i];
  431. }
  432. d |= d >> 16;
  433. d &= 0xFFFF;
  434. return ((int)d - 1) >> 31;
  435. }
  436. public static bool IsOneVar(uint[] x)
  437. {
  438. return 0 != IsOne(x);
  439. }
  440. public static int IsZero(uint[] x)
  441. {
  442. uint d = 0;
  443. for (int i = 0; i < Size; ++i)
  444. {
  445. d |= x[i];
  446. }
  447. d |= d >> 16;
  448. d &= 0xFFFF;
  449. return ((int)d - 1) >> 31;
  450. }
  451. public static bool IsZeroVar(uint[] x)
  452. {
  453. return 0U != IsZero(x);
  454. }
  455. public static void Mul(uint[] x, uint y, uint[] z)
  456. {
  457. uint x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7];
  458. uint x8 = x[8], x9 = x[9], x10 = x[10], x11 = x[11], x12 = x[12], x13 = x[13], x14 = x[14], x15 = x[15];
  459. uint z1, z5, z9, z13;
  460. ulong c, d, e, f;
  461. c = (ulong)x1 * y;
  462. z1 = (uint)c & M28; c >>= 28;
  463. d = (ulong)x5 * y;
  464. z5 = (uint)d & M28; d >>= 28;
  465. e = (ulong)x9 * y;
  466. z9 = (uint)e & M28; e >>= 28;
  467. f = (ulong)x13 * y;
  468. z13 = (uint)f & M28; f >>= 28;
  469. c += (ulong)x2 * y;
  470. z[2] = (uint)c & M28; c >>= 28;
  471. d += (ulong)x6 * y;
  472. z[6] = (uint)d & M28; d >>= 28;
  473. e += (ulong)x10 * y;
  474. z[10] = (uint)e & M28; e >>= 28;
  475. f += (ulong)x14 * y;
  476. z[14] = (uint)f & M28; f >>= 28;
  477. c += (ulong)x3 * y;
  478. z[3] = (uint)c & M28; c >>= 28;
  479. d += (ulong)x7 * y;
  480. z[7] = (uint)d & M28; d >>= 28;
  481. e += (ulong)x11 * y;
  482. z[11] = (uint)e & M28; e >>= 28;
  483. f += (ulong)x15 * y;
  484. z[15] = (uint)f & M28; f >>= 28;
  485. d += f;
  486. c += (ulong)x4 * y;
  487. z[4] = (uint)c & M28; c >>= 28;
  488. d += (ulong)x8 * y;
  489. z[8] = (uint)d & M28; d >>= 28;
  490. e += (ulong)x12 * y;
  491. z[12] = (uint)e & M28; e >>= 28;
  492. f += (ulong)x0 * y;
  493. z[0] = (uint)f & M28; f >>= 28;
  494. z[1] = z1 + (uint)f;
  495. z[5] = z5 + (uint)c;
  496. z[9] = z9 + (uint)d;
  497. z[13] = z13 + (uint)e;
  498. }
  499. public static void Mul(uint[] x, uint[] y, uint[] z)
  500. {
  501. uint x0 = x[0];
  502. uint x1 = x[1];
  503. uint x2 = x[2];
  504. uint x3 = x[3];
  505. uint x4 = x[4];
  506. uint x5 = x[5];
  507. uint x6 = x[6];
  508. uint x7 = x[7];
  509. uint u0 = x[8];
  510. uint u1 = x[9];
  511. uint u2 = x[10];
  512. uint u3 = x[11];
  513. uint u4 = x[12];
  514. uint u5 = x[13];
  515. uint u6 = x[14];
  516. uint u7 = x[15];
  517. uint y0 = y[0];
  518. uint y1 = y[1];
  519. uint y2 = y[2];
  520. uint y3 = y[3];
  521. uint y4 = y[4];
  522. uint y5 = y[5];
  523. uint y6 = y[6];
  524. uint y7 = y[7];
  525. uint v0 = y[8];
  526. uint v1 = y[9];
  527. uint v2 = y[10];
  528. uint v3 = y[11];
  529. uint v4 = y[12];
  530. uint v5 = y[13];
  531. uint v6 = y[14];
  532. uint v7 = y[15];
  533. uint s0 = x0 + u0;
  534. uint s1 = x1 + u1;
  535. uint s2 = x2 + u2;
  536. uint s3 = x3 + u3;
  537. uint s4 = x4 + u4;
  538. uint s5 = x5 + u5;
  539. uint s6 = x6 + u6;
  540. uint s7 = x7 + u7;
  541. uint t0 = y0 + v0;
  542. uint t1 = y1 + v1;
  543. uint t2 = y2 + v2;
  544. uint t3 = y3 + v3;
  545. uint t4 = y4 + v4;
  546. uint t5 = y5 + v5;
  547. uint t6 = y6 + v6;
  548. uint t7 = y7 + v7;
  549. uint z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15;
  550. ulong c, d;
  551. ulong f0 = (ulong)x0 * y0;
  552. ulong f8 = (ulong)x7 * y1
  553. + (ulong)x6 * y2
  554. + (ulong)x5 * y3
  555. + (ulong)x4 * y4
  556. + (ulong)x3 * y5
  557. + (ulong)x2 * y6
  558. + (ulong)x1 * y7;
  559. ulong g0 = (ulong)u0 * v0;
  560. ulong g8 = (ulong)u7 * v1
  561. + (ulong)u6 * v2
  562. + (ulong)u5 * v3
  563. + (ulong)u4 * v4
  564. + (ulong)u3 * v5
  565. + (ulong)u2 * v6
  566. + (ulong)u1 * v7;
  567. ulong h0 = (ulong)s0 * t0;
  568. ulong h8 = (ulong)s7 * t1
  569. + (ulong)s6 * t2
  570. + (ulong)s5 * t3
  571. + (ulong)s4 * t4
  572. + (ulong)s3 * t5
  573. + (ulong)s2 * t6
  574. + (ulong)s1 * t7;
  575. c = f0 + g0 + h8 - f8;
  576. z0 = (uint)c & M28; c >>= 28;
  577. d = g8 + h0 - f0 + h8;
  578. z8 = (uint)d & M28; d >>= 28;
  579. ulong f1 = (ulong)x1 * y0
  580. + (ulong)x0 * y1;
  581. ulong f9 = (ulong)x7 * y2
  582. + (ulong)x6 * y3
  583. + (ulong)x5 * y4
  584. + (ulong)x4 * y5
  585. + (ulong)x3 * y6
  586. + (ulong)x2 * y7;
  587. ulong g1 = (ulong)u1 * v0
  588. + (ulong)u0 * v1;
  589. ulong g9 = (ulong)u7 * v2
  590. + (ulong)u6 * v3
  591. + (ulong)u5 * v4
  592. + (ulong)u4 * v5
  593. + (ulong)u3 * v6
  594. + (ulong)u2 * v7;
  595. ulong h1 = (ulong)s1 * t0
  596. + (ulong)s0 * t1;
  597. ulong h9 = (ulong)s7 * t2
  598. + (ulong)s6 * t3
  599. + (ulong)s5 * t4
  600. + (ulong)s4 * t5
  601. + (ulong)s3 * t6
  602. + (ulong)s2 * t7;
  603. c += f1 + g1 + h9 - f9;
  604. z1 = (uint)c & M28; c >>= 28;
  605. d += g9 + h1 - f1 + h9;
  606. z9 = (uint)d & M28; d >>= 28;
  607. ulong f2 = (ulong)x2 * y0
  608. + (ulong)x1 * y1
  609. + (ulong)x0 * y2;
  610. ulong f10 = (ulong)x7 * y3
  611. + (ulong)x6 * y4
  612. + (ulong)x5 * y5
  613. + (ulong)x4 * y6
  614. + (ulong)x3 * y7;
  615. ulong g2 = (ulong)u2 * v0
  616. + (ulong)u1 * v1
  617. + (ulong)u0 * v2;
  618. ulong g10 = (ulong)u7 * v3
  619. + (ulong)u6 * v4
  620. + (ulong)u5 * v5
  621. + (ulong)u4 * v6
  622. + (ulong)u3 * v7;
  623. ulong h2 = (ulong)s2 * t0
  624. + (ulong)s1 * t1
  625. + (ulong)s0 * t2;
  626. ulong h10 = (ulong)s7 * t3
  627. + (ulong)s6 * t4
  628. + (ulong)s5 * t5
  629. + (ulong)s4 * t6
  630. + (ulong)s3 * t7;
  631. c += f2 + g2 + h10 - f10;
  632. z2 = (uint)c & M28; c >>= 28;
  633. d += g10 + h2 - f2 + h10;
  634. z10 = (uint)d & M28; d >>= 28;
  635. ulong f3 = (ulong)x3 * y0
  636. + (ulong)x2 * y1
  637. + (ulong)x1 * y2
  638. + (ulong)x0 * y3;
  639. ulong f11 = (ulong)x7 * y4
  640. + (ulong)x6 * y5
  641. + (ulong)x5 * y6
  642. + (ulong)x4 * y7;
  643. ulong g3 = (ulong)u3 * v0
  644. + (ulong)u2 * v1
  645. + (ulong)u1 * v2
  646. + (ulong)u0 * v3;
  647. ulong g11 = (ulong)u7 * v4
  648. + (ulong)u6 * v5
  649. + (ulong)u5 * v6
  650. + (ulong)u4 * v7;
  651. ulong h3 = (ulong)s3 * t0
  652. + (ulong)s2 * t1
  653. + (ulong)s1 * t2
  654. + (ulong)s0 * t3;
  655. ulong h11 = (ulong)s7 * t4
  656. + (ulong)s6 * t5
  657. + (ulong)s5 * t6
  658. + (ulong)s4 * t7;
  659. c += f3 + g3 + h11 - f11;
  660. z3 = (uint)c & M28; c >>= 28;
  661. d += g11 + h3 - f3 + h11;
  662. z11 = (uint)d & M28; d >>= 28;
  663. ulong f4 = (ulong)x4 * y0
  664. + (ulong)x3 * y1
  665. + (ulong)x2 * y2
  666. + (ulong)x1 * y3
  667. + (ulong)x0 * y4;
  668. ulong f12 = (ulong)x7 * y5
  669. + (ulong)x6 * y6
  670. + (ulong)x5 * y7;
  671. ulong g4 = (ulong)u4 * v0
  672. + (ulong)u3 * v1
  673. + (ulong)u2 * v2
  674. + (ulong)u1 * v3
  675. + (ulong)u0 * v4;
  676. ulong g12 = (ulong)u7 * v5
  677. + (ulong)u6 * v6
  678. + (ulong)u5 * v7;
  679. ulong h4 = (ulong)s4 * t0
  680. + (ulong)s3 * t1
  681. + (ulong)s2 * t2
  682. + (ulong)s1 * t3
  683. + (ulong)s0 * t4;
  684. ulong h12 = (ulong)s7 * t5
  685. + (ulong)s6 * t6
  686. + (ulong)s5 * t7;
  687. c += f4 + g4 + h12 - f12;
  688. z4 = (uint)c & M28; c >>= 28;
  689. d += g12 + h4 - f4 + h12;
  690. z12 = (uint)d & M28; d >>= 28;
  691. ulong f5 = (ulong)x5 * y0
  692. + (ulong)x4 * y1
  693. + (ulong)x3 * y2
  694. + (ulong)x2 * y3
  695. + (ulong)x1 * y4
  696. + (ulong)x0 * y5;
  697. ulong f13 = (ulong)x7 * y6
  698. + (ulong)x6 * y7;
  699. ulong g5 = (ulong)u5 * v0
  700. + (ulong)u4 * v1
  701. + (ulong)u3 * v2
  702. + (ulong)u2 * v3
  703. + (ulong)u1 * v4
  704. + (ulong)u0 * v5;
  705. ulong g13 = (ulong)u7 * v6
  706. + (ulong)u6 * v7;
  707. ulong h5 = (ulong)s5 * t0
  708. + (ulong)s4 * t1
  709. + (ulong)s3 * t2
  710. + (ulong)s2 * t3
  711. + (ulong)s1 * t4
  712. + (ulong)s0 * t5;
  713. ulong h13 = (ulong)s7 * t6
  714. + (ulong)s6 * t7;
  715. c += f5 + g5 + h13 - f13;
  716. z5 = (uint)c & M28; c >>= 28;
  717. d += g13 + h5 - f5 + h13;
  718. z13 = (uint)d & M28; d >>= 28;
  719. ulong f6 = (ulong)x6 * y0
  720. + (ulong)x5 * y1
  721. + (ulong)x4 * y2
  722. + (ulong)x3 * y3
  723. + (ulong)x2 * y4
  724. + (ulong)x1 * y5
  725. + (ulong)x0 * y6;
  726. ulong f14 = (ulong)x7 * y7;
  727. ulong g6 = (ulong)u6 * v0
  728. + (ulong)u5 * v1
  729. + (ulong)u4 * v2
  730. + (ulong)u3 * v3
  731. + (ulong)u2 * v4
  732. + (ulong)u1 * v5
  733. + (ulong)u0 * v6;
  734. ulong g14 = (ulong)u7 * v7;
  735. ulong h6 = (ulong)s6 * t0
  736. + (ulong)s5 * t1
  737. + (ulong)s4 * t2
  738. + (ulong)s3 * t3
  739. + (ulong)s2 * t4
  740. + (ulong)s1 * t5
  741. + (ulong)s0 * t6;
  742. ulong h14 = (ulong)s7 * t7;
  743. c += f6 + g6 + h14 - f14;
  744. z6 = (uint)c & M28; c >>= 28;
  745. d += g14 + h6 - f6 + h14;
  746. z14 = (uint)d & M28; d >>= 28;
  747. ulong f7 = (ulong)x7 * y0
  748. + (ulong)x6 * y1
  749. + (ulong)x5 * y2
  750. + (ulong)x4 * y3
  751. + (ulong)x3 * y4
  752. + (ulong)x2 * y5
  753. + (ulong)x1 * y6
  754. + (ulong)x0 * y7;
  755. ulong g7 = (ulong)u7 * v0
  756. + (ulong)u6 * v1
  757. + (ulong)u5 * v2
  758. + (ulong)u4 * v3
  759. + (ulong)u3 * v4
  760. + (ulong)u2 * v5
  761. + (ulong)u1 * v6
  762. + (ulong)u0 * v7;
  763. ulong h7 = (ulong)s7 * t0
  764. + (ulong)s6 * t1
  765. + (ulong)s5 * t2
  766. + (ulong)s4 * t3
  767. + (ulong)s3 * t4
  768. + (ulong)s2 * t5
  769. + (ulong)s1 * t6
  770. + (ulong)s0 * t7;
  771. c += f7 + g7;
  772. z7 = (uint)c & M28; c >>= 28;
  773. d += h7 - f7;
  774. z15 = (uint)d & M28; d >>= 28;
  775. c += d;
  776. c += z8;
  777. z8 = (uint)c & M28; c >>= 28;
  778. d += z0;
  779. z0 = (uint)d & M28; d >>= 28;
  780. z9 += (uint)c;
  781. z1 += (uint)d;
  782. z[0] = z0;
  783. z[1] = z1;
  784. z[2] = z2;
  785. z[3] = z3;
  786. z[4] = z4;
  787. z[5] = z5;
  788. z[6] = z6;
  789. z[7] = z7;
  790. z[8] = z8;
  791. z[9] = z9;
  792. z[10] = z10;
  793. z[11] = z11;
  794. z[12] = z12;
  795. z[13] = z13;
  796. z[14] = z14;
  797. z[15] = z15;
  798. }
  799. public static void Negate(uint[] x, uint[] z)
  800. {
  801. uint[] zero = Create();
  802. Sub(zero, x, z);
  803. }
  804. public static void Normalize(uint[] z)
  805. {
  806. //int x = (z[15] >> (28 - 1)) & 1;
  807. Reduce(z, 1);
  808. Reduce(z, -1);
  809. Debug.Assert(z[15] >> 28 == 0U);
  810. }
  811. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  812. public static void Normalize(Span<uint> z)
  813. {
  814. //int x = (z[15] >> (28 - 1)) & 1;
  815. Reduce(z, 1);
  816. Reduce(z, -1);
  817. Debug.Assert(z[15] >> 28 == 0U);
  818. }
  819. #endif
  820. public static void One(uint[] z)
  821. {
  822. z[0] = 1U;
  823. for (int i = 1; i < Size; ++i)
  824. {
  825. z[i] = 0;
  826. }
  827. }
  828. private static void PowPm3d4(uint[] x, uint[] z)
  829. {
  830. // z = x^((p-3)/4) = x^(2^446 - 2^222 - 1)
  831. // (223 1s) (1 0s) (222 1s)
  832. // Addition chain: 1 2 3 6 9 18 19 37 74 111 [222] [223]
  833. uint[] x2 = Create(); Sqr(x, x2); Mul(x, x2, x2);
  834. uint[] x3 = Create(); Sqr(x2, x3); Mul(x, x3, x3);
  835. uint[] x6 = Create(); Sqr(x3, 3, x6); Mul(x3, x6, x6);
  836. uint[] x9 = Create(); Sqr(x6, 3, x9); Mul(x3, x9, x9);
  837. uint[] x18 = Create(); Sqr(x9, 9, x18); Mul(x9, x18, x18);
  838. uint[] x19 = Create(); Sqr(x18, x19); Mul(x, x19, x19);
  839. uint[] x37 = Create(); Sqr(x19, 18, x37); Mul(x18, x37, x37);
  840. uint[] x74 = Create(); Sqr(x37, 37, x74); Mul(x37, x74, x74);
  841. uint[] x111 = Create(); Sqr(x74, 37, x111); Mul(x37, x111, x111);
  842. uint[] x222 = Create(); Sqr(x111, 111, x222); Mul(x111, x222, x222);
  843. uint[] x223 = Create(); Sqr(x222, x223); Mul(x, x223, x223);
  844. uint[] t = Create();
  845. Sqr(x223, 223, t);
  846. Mul(t, x222, z);
  847. }
  848. private static void Reduce(uint[] z, int x)
  849. {
  850. uint u = z[15], z15 = u & M28;
  851. int t = (int)(u >> 28) + x;
  852. long cc = t;
  853. for (int i = 0; i < 8; ++i)
  854. {
  855. cc += z[i]; z[i] = (uint)cc & M28; cc >>= 28;
  856. }
  857. cc += t;
  858. for (int i = 8; i < 15; ++i)
  859. {
  860. cc += z[i]; z[i] = (uint)cc & M28; cc >>= 28;
  861. }
  862. z[15] = z15 + (uint)cc;
  863. }
  864. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  865. private static void Reduce(Span<uint> z, int x)
  866. {
  867. uint u = z[15], z15 = u & M28;
  868. int t = (int)(u >> 28) + x;
  869. long cc = t;
  870. for (int i = 0; i < 8; ++i)
  871. {
  872. cc += z[i]; z[i] = (uint)cc & M28; cc >>= 28;
  873. }
  874. cc += t;
  875. for (int i = 8; i < 15; ++i)
  876. {
  877. cc += z[i]; z[i] = (uint)cc & M28; cc >>= 28;
  878. }
  879. z[15] = z15 + (uint)cc;
  880. }
  881. #endif
  882. public static void Sqr(uint[] x, uint[] z)
  883. {
  884. uint x0 = x[0];
  885. uint x1 = x[1];
  886. uint x2 = x[2];
  887. uint x3 = x[3];
  888. uint x4 = x[4];
  889. uint x5 = x[5];
  890. uint x6 = x[6];
  891. uint x7 = x[7];
  892. uint u0 = x[8];
  893. uint u1 = x[9];
  894. uint u2 = x[10];
  895. uint u3 = x[11];
  896. uint u4 = x[12];
  897. uint u5 = x[13];
  898. uint u6 = x[14];
  899. uint u7 = x[15];
  900. uint x0_2 = x0 * 2;
  901. uint x1_2 = x1 * 2;
  902. uint x2_2 = x2 * 2;
  903. uint x3_2 = x3 * 2;
  904. uint x4_2 = x4 * 2;
  905. uint x5_2 = x5 * 2;
  906. uint x6_2 = x6 * 2;
  907. uint u0_2 = u0 * 2;
  908. uint u1_2 = u1 * 2;
  909. uint u2_2 = u2 * 2;
  910. uint u3_2 = u3 * 2;
  911. uint u4_2 = u4 * 2;
  912. uint u5_2 = u5 * 2;
  913. uint u6_2 = u6 * 2;
  914. uint s0 = x0 + u0;
  915. uint s1 = x1 + u1;
  916. uint s2 = x2 + u2;
  917. uint s3 = x3 + u3;
  918. uint s4 = x4 + u4;
  919. uint s5 = x5 + u5;
  920. uint s6 = x6 + u6;
  921. uint s7 = x7 + u7;
  922. uint s0_2 = s0 * 2;
  923. uint s1_2 = s1 * 2;
  924. uint s2_2 = s2 * 2;
  925. uint s3_2 = s3 * 2;
  926. uint s4_2 = s4 * 2;
  927. uint s5_2 = s5 * 2;
  928. uint s6_2 = s6 * 2;
  929. uint z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15;
  930. ulong c, d;
  931. ulong f0 = (ulong)x0 * x0;
  932. ulong f8 = (ulong)x7 * x1_2
  933. + (ulong)x6 * x2_2
  934. + (ulong)x5 * x3_2
  935. + (ulong)x4 * x4;
  936. ulong g0 = (ulong)u0 * u0;
  937. ulong g8 = (ulong)u7 * u1_2
  938. + (ulong)u6 * u2_2
  939. + (ulong)u5 * u3_2
  940. + (ulong)u4 * u4;
  941. ulong h0 = (ulong)s0 * s0;
  942. ulong h8 = (ulong)s7 * s1_2
  943. + (ulong)s6 * s2_2
  944. + (ulong)s5 * s3_2
  945. + (ulong)s4 * s4;
  946. c = f0 + g0 + h8 - f8;
  947. z0 = (uint)c & M28; c >>= 28;
  948. d = g8 + h0 - f0 + h8;
  949. z8 = (uint)d & M28; d >>= 28;
  950. ulong f1 = (ulong)x1 * x0_2;
  951. ulong f9 = (ulong)x7 * x2_2
  952. + (ulong)x6 * x3_2
  953. + (ulong)x5 * x4_2;
  954. ulong g1 = (ulong)u1 * u0_2;
  955. ulong g9 = (ulong)u7 * u2_2
  956. + (ulong)u6 * u3_2
  957. + (ulong)u5 * u4_2;
  958. ulong h1 = (ulong)s1 * s0_2;
  959. ulong h9 = (ulong)s7 * s2_2
  960. + (ulong)s6 * s3_2
  961. + (ulong)s5 * s4_2;
  962. c += f1 + g1 + h9 - f9;
  963. z1 = (uint)c & M28; c >>= 28;
  964. d += g9 + h1 - f1 + h9;
  965. z9 = (uint)d & M28; d >>= 28;
  966. ulong f2 = (ulong)x2 * x0_2
  967. + (ulong)x1 * x1;
  968. ulong f10 = (ulong)x7 * x3_2
  969. + (ulong)x6 * x4_2
  970. + (ulong)x5 * x5;
  971. ulong g2 = (ulong)u2 * u0_2
  972. + (ulong)u1 * u1;
  973. ulong g10 = (ulong)u7 * u3_2
  974. + (ulong)u6 * u4_2
  975. + (ulong)u5 * u5;
  976. ulong h2 = (ulong)s2 * s0_2
  977. + (ulong)s1 * s1;
  978. ulong h10 = (ulong)s7 * s3_2
  979. + (ulong)s6 * s4_2
  980. + (ulong)s5 * s5;
  981. c += f2 + g2 + h10 - f10;
  982. z2 = (uint)c & M28; c >>= 28;
  983. d += g10 + h2 - f2 + h10;
  984. z10 = (uint)d & M28; d >>= 28;
  985. ulong f3 = (ulong)x3 * x0_2
  986. + (ulong)x2 * x1_2;
  987. ulong f11 = (ulong)x7 * x4_2
  988. + (ulong)x6 * x5_2;
  989. ulong g3 = (ulong)u3 * u0_2
  990. + (ulong)u2 * u1_2;
  991. ulong g11 = (ulong)u7 * u4_2
  992. + (ulong)u6 * u5_2;
  993. ulong h3 = (ulong)s3 * s0_2
  994. + (ulong)s2 * s1_2;
  995. ulong h11 = (ulong)s7 * s4_2
  996. + (ulong)s6 * s5_2;
  997. c += f3 + g3 + h11 - f11;
  998. z3 = (uint)c & M28; c >>= 28;
  999. d += g11 + h3 - f3 + h11;
  1000. z11 = (uint)d & M28; d >>= 28;
  1001. ulong f4 = (ulong)x4 * x0_2
  1002. + (ulong)x3 * x1_2
  1003. + (ulong)x2 * x2;
  1004. ulong f12 = (ulong)x7 * x5_2
  1005. + (ulong)x6 * x6;
  1006. ulong g4 = (ulong)u4 * u0_2
  1007. + (ulong)u3 * u1_2
  1008. + (ulong)u2 * u2;
  1009. ulong g12 = (ulong)u7 * u5_2
  1010. + (ulong)u6 * u6;
  1011. ulong h4 = (ulong)s4 * s0_2
  1012. + (ulong)s3 * s1_2
  1013. + (ulong)s2 * s2;
  1014. ulong h12 = (ulong)s7 * s5_2
  1015. + (ulong)s6 * s6;
  1016. c += f4 + g4 + h12 - f12;
  1017. z4 = (uint)c & M28; c >>= 28;
  1018. d += g12 + h4 - f4 + h12;
  1019. z12 = (uint)d & M28; d >>= 28;
  1020. ulong f5 = (ulong)x5 * x0_2
  1021. + (ulong)x4 * x1_2
  1022. + (ulong)x3 * x2_2;
  1023. ulong f13 = (ulong)x7 * x6_2;
  1024. ulong g5 = (ulong)u5 * u0_2
  1025. + (ulong)u4 * u1_2
  1026. + (ulong)u3 * u2_2;
  1027. ulong g13 = (ulong)u7 * u6_2;
  1028. ulong h5 = (ulong)s5 * s0_2
  1029. + (ulong)s4 * s1_2
  1030. + (ulong)s3 * s2_2;
  1031. ulong h13 = (ulong)s7 * s6_2;
  1032. c += f5 + g5 + h13 - f13;
  1033. z5 = (uint)c & M28; c >>= 28;
  1034. d += g13 + h5 - f5 + h13;
  1035. z13 = (uint)d & M28; d >>= 28;
  1036. ulong f6 = (ulong)x6 * x0_2
  1037. + (ulong)x5 * x1_2
  1038. + (ulong)x4 * x2_2
  1039. + (ulong)x3 * x3;
  1040. ulong f14 = (ulong)x7 * x7;
  1041. ulong g6 = (ulong)u6 * u0_2
  1042. + (ulong)u5 * u1_2
  1043. + (ulong)u4 * u2_2
  1044. + (ulong)u3 * u3;
  1045. ulong g14 = (ulong)u7 * u7;
  1046. ulong h6 = (ulong)s6 * s0_2
  1047. + (ulong)s5 * s1_2
  1048. + (ulong)s4 * s2_2
  1049. + (ulong)s3 * s3;
  1050. ulong h14 = (ulong)s7 * s7;
  1051. c += f6 + g6 + h14 - f14;
  1052. z6 = (uint)c & M28; c >>= 28;
  1053. d += g14 + h6 - f6 + h14;
  1054. z14 = (uint)d & M28; d >>= 28;
  1055. ulong f7 = (ulong)x7 * x0_2
  1056. + (ulong)x6 * x1_2
  1057. + (ulong)x5 * x2_2
  1058. + (ulong)x4 * x3_2;
  1059. ulong g7 = (ulong)u7 * u0_2
  1060. + (ulong)u6 * u1_2
  1061. + (ulong)u5 * u2_2
  1062. + (ulong)u4 * u3_2;
  1063. ulong h7 = (ulong)s7 * s0_2
  1064. + (ulong)s6 * s1_2
  1065. + (ulong)s5 * s2_2
  1066. + (ulong)s4 * s3_2;
  1067. c += f7 + g7;
  1068. z7 = (uint)c & M28; c >>= 28;
  1069. d += h7 - f7;
  1070. z15 = (uint)d & M28; d >>= 28;
  1071. c += d;
  1072. c += z8;
  1073. z8 = (uint)c & M28; c >>= 28;
  1074. d += z0;
  1075. z0 = (uint)d & M28; d >>= 28;
  1076. z9 += (uint)c;
  1077. z1 += (uint)d;
  1078. z[0] = z0;
  1079. z[1] = z1;
  1080. z[2] = z2;
  1081. z[3] = z3;
  1082. z[4] = z4;
  1083. z[5] = z5;
  1084. z[6] = z6;
  1085. z[7] = z7;
  1086. z[8] = z8;
  1087. z[9] = z9;
  1088. z[10] = z10;
  1089. z[11] = z11;
  1090. z[12] = z12;
  1091. z[13] = z13;
  1092. z[14] = z14;
  1093. z[15] = z15;
  1094. }
  1095. public static void Sqr(uint[] x, int n, uint[] z)
  1096. {
  1097. Debug.Assert(n > 0);
  1098. Sqr(x, z);
  1099. while (--n > 0)
  1100. {
  1101. Sqr(z, z);
  1102. }
  1103. }
  1104. public static bool SqrtRatioVar(uint[] u, uint[] v, uint[] z)
  1105. {
  1106. uint[] u3v = Create();
  1107. uint[] u5v3 = Create();
  1108. Sqr(u, u3v);
  1109. Mul(u3v, v, u3v);
  1110. Sqr(u3v, u5v3);
  1111. Mul(u3v, u, u3v);
  1112. Mul(u5v3, u, u5v3);
  1113. Mul(u5v3, v, u5v3);
  1114. uint[] x = Create();
  1115. PowPm3d4(u5v3, x);
  1116. Mul(x, u3v, x);
  1117. uint[] t = Create();
  1118. Sqr(x, t);
  1119. Mul(t, v, t);
  1120. Sub(u, t, t);
  1121. Normalize(t);
  1122. if (IsZeroVar(t))
  1123. {
  1124. Copy(x, 0, z, 0);
  1125. return true;
  1126. }
  1127. return false;
  1128. }
  1129. public static void Sub(uint[] x, uint[] y, uint[] z)
  1130. {
  1131. uint x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7];
  1132. uint x8 = x[8], x9 = x[9], x10 = x[10], x11 = x[11], x12 = x[12], x13 = x[13], x14 = x[14], x15 = x[15];
  1133. uint y0 = y[0], y1 = y[1], y2 = y[2], y3 = y[3], y4 = y[4], y5 = y[5], y6 = y[6], y7 = y[7];
  1134. uint y8 = y[8], y9 = y[9], y10 = y[10], y11 = y[11], y12 = y[12], y13 = y[13], y14 = y[14], y15 = y[15];
  1135. uint z0 = x0 + 0x1FFFFFFEU - y0;
  1136. uint z1 = x1 + 0x1FFFFFFEU - y1;
  1137. uint z2 = x2 + 0x1FFFFFFEU - y2;
  1138. uint z3 = x3 + 0x1FFFFFFEU - y3;
  1139. uint z4 = x4 + 0x1FFFFFFEU - y4;
  1140. uint z5 = x5 + 0x1FFFFFFEU - y5;
  1141. uint z6 = x6 + 0x1FFFFFFEU - y6;
  1142. uint z7 = x7 + 0x1FFFFFFEU - y7;
  1143. uint z8 = x8 + 0x1FFFFFFCU - y8;
  1144. uint z9 = x9 + 0x1FFFFFFEU - y9;
  1145. uint z10 = x10 + 0x1FFFFFFEU - y10;
  1146. uint z11 = x11 + 0x1FFFFFFEU - y11;
  1147. uint z12 = x12 + 0x1FFFFFFEU - y12;
  1148. uint z13 = x13 + 0x1FFFFFFEU - y13;
  1149. uint z14 = x14 + 0x1FFFFFFEU - y14;
  1150. uint z15 = x15 + 0x1FFFFFFEU - y15;
  1151. z2 += z1 >> 28; z1 &= M28;
  1152. z6 += z5 >> 28; z5 &= M28;
  1153. z10 += z9 >> 28; z9 &= M28;
  1154. z14 += z13 >> 28; z13 &= M28;
  1155. z3 += z2 >> 28; z2 &= M28;
  1156. z7 += z6 >> 28; z6 &= M28;
  1157. z11 += z10 >> 28; z10 &= M28;
  1158. z15 += z14 >> 28; z14 &= M28;
  1159. uint t = z15 >> 28; z15 &= M28;
  1160. z0 += t;
  1161. z8 += t;
  1162. z4 += z3 >> 28; z3 &= M28;
  1163. z8 += z7 >> 28; z7 &= M28;
  1164. z12 += z11 >> 28; z11 &= M28;
  1165. z1 += z0 >> 28; z0 &= M28;
  1166. z5 += z4 >> 28; z4 &= M28;
  1167. z9 += z8 >> 28; z8 &= M28;
  1168. z13 += z12 >> 28; z12 &= M28;
  1169. z[0] = z0;
  1170. z[1] = z1;
  1171. z[2] = z2;
  1172. z[3] = z3;
  1173. z[4] = z4;
  1174. z[5] = z5;
  1175. z[6] = z6;
  1176. z[7] = z7;
  1177. z[8] = z8;
  1178. z[9] = z9;
  1179. z[10] = z10;
  1180. z[11] = z11;
  1181. z[12] = z12;
  1182. z[13] = z13;
  1183. z[14] = z14;
  1184. z[15] = z15;
  1185. }
  1186. public static void SubOne(uint[] z)
  1187. {
  1188. uint[] one = Create();
  1189. one[0] = 1U;
  1190. Sub(z, one, z);
  1191. }
  1192. public static void Zero(uint[] z)
  1193. {
  1194. for (int i = 0; i < Size; ++i)
  1195. {
  1196. z[i] = 0;
  1197. }
  1198. }
  1199. }
  1200. }
  1201. #pragma warning restore
  1202. #endif