X25519Field.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Math.EC.Rfc7748
  6. {
  7. public abstract class X25519Field
  8. {
  9. public const int Size = 10;
  10. private const int M24 = 0x00FFFFFF;
  11. private const int M25 = 0x01FFFFFF;
  12. private const int M26 = 0x03FFFFFF;
  13. private static readonly int[] RootNegOne = { 0x020EA0B0, 0x0386C9D2, 0x00478C4E, 0x0035697F, 0x005E8630,
  14. 0x01FBD7A7, 0x0340264F, 0x01F0B2B4, 0x00027E0E, 0x00570649 };
  15. private X25519Field() {}
  16. public static void Add(int[] x, int[] y, int[] 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(int[] z)
  24. {
  25. z[0] += 1;
  26. }
  27. public static void AddOne(int[] 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 void Carry(int[] z)
  41. {
  42. int z0 = z[0], z1 = z[1], z2 = z[2], z3 = z[3], z4 = z[4];
  43. int z5 = z[5], z6 = z[6], z7 = z[7], z8 = z[8], z9 = z[9];
  44. z3 += (z2 >> 25); z2 &= M25;
  45. z5 += (z4 >> 25); z4 &= M25;
  46. z8 += (z7 >> 25); z7 &= M25;
  47. //z0 += (z9 >> 24) * 19; z9 &= M24;
  48. z0 += (z9 >> 25) * 38; z9 &= M25;
  49. z1 += (z0 >> 26); z0 &= M26;
  50. z6 += (z5 >> 26); z5 &= M26;
  51. z2 += (z1 >> 26); z1 &= M26;
  52. z4 += (z3 >> 26); z3 &= M26;
  53. z7 += (z6 >> 26); z6 &= M26;
  54. z9 += (z8 >> 26); z8 &= M26;
  55. z[0] = z0; z[1] = z1; z[2] = z2; z[3] = z3; z[4] = z4;
  56. z[5] = z5; z[6] = z6; z[7] = z7; z[8] = z8; z[9] = z9;
  57. }
  58. public static void CNegate(int negate, int[] z)
  59. {
  60. Debug.Assert(negate >> 1 == 0);
  61. int mask = 0 - negate;
  62. for (int i = 0; i < Size; ++i)
  63. {
  64. z[i] = (z[i] ^ mask) - mask;
  65. }
  66. }
  67. public static void Copy(int[] x, int xOff, int[] z, int zOff)
  68. {
  69. for (int i = 0; i < Size; ++i)
  70. {
  71. z[zOff + i] = x[xOff + i];
  72. }
  73. }
  74. public static int[] Create()
  75. {
  76. return new int[Size];
  77. }
  78. public static int[] CreateTable(int n)
  79. {
  80. return new int[Size * n];
  81. }
  82. public static void CSwap(int swap, int[] a, int[] b)
  83. {
  84. Debug.Assert(swap >> 1 == 0);
  85. Debug.Assert(a != b);
  86. int mask = 0 - swap;
  87. for (int i = 0; i < Size; ++i)
  88. {
  89. int ai = a[i], bi = b[i];
  90. int dummy = mask & (ai ^ bi);
  91. a[i] = ai ^ dummy;
  92. b[i] = bi ^ dummy;
  93. }
  94. }
  95. public static void Decode(byte[] x, int xOff, int[] z)
  96. {
  97. Decode128(x, xOff, z, 0);
  98. Decode128(x, xOff + 16, z, 5);
  99. z[9] &= M24;
  100. }
  101. private static void Decode128(byte[] bs, int off, int[] z, int zOff)
  102. {
  103. uint t0 = Decode32(bs, off + 0);
  104. uint t1 = Decode32(bs, off + 4);
  105. uint t2 = Decode32(bs, off + 8);
  106. uint t3 = Decode32(bs, off + 12);
  107. z[zOff + 0] = (int)t0 & M26;
  108. z[zOff + 1] = (int)((t1 << 6) | (t0 >> 26)) & M26;
  109. z[zOff + 2] = (int)((t2 << 12) | (t1 >> 20)) & M25;
  110. z[zOff + 3] = (int)((t3 << 19) | (t2 >> 13)) & M26;
  111. z[zOff + 4] = (int)(t3 >> 7);
  112. }
  113. private static uint Decode32(byte[] bs, int off)
  114. {
  115. uint n = bs[off];
  116. n |= (uint)bs[++off] << 8;
  117. n |= (uint)bs[++off] << 16;
  118. n |= (uint)bs[++off] << 24;
  119. return n;
  120. }
  121. public static void Encode(int[] x, byte[] z, int zOff)
  122. {
  123. Encode128(x, 0, z, zOff);
  124. Encode128(x, 5, z, zOff + 16);
  125. }
  126. private static void Encode128(int[] x, int xOff, byte[] bs, int off)
  127. {
  128. uint x0 = (uint)x[xOff + 0], x1 = (uint)x[xOff + 1], x2 = (uint)x[xOff + 2];
  129. uint x3 = (uint)x[xOff + 3], x4 = (uint)x[xOff + 4];
  130. uint t0 = x0 | (x1 << 26); Encode32(t0, bs, off + 0);
  131. uint t1 = (x1 >> 6) | (x2 << 20); Encode32(t1, bs, off + 4);
  132. uint t2 = (x2 >> 12) | (x3 << 13); Encode32(t2, bs, off + 8);
  133. uint t3 = (x3 >> 19) | (x4 << 7); Encode32(t3, bs, off + 12);
  134. }
  135. private static void Encode32(uint n, byte[] bs, int off)
  136. {
  137. bs[ off] = (byte)(n );
  138. bs[++off] = (byte)(n >> 8);
  139. bs[++off] = (byte)(n >> 16);
  140. bs[++off] = (byte)(n >> 24);
  141. }
  142. public static void Inv(int[] x, int[] z)
  143. {
  144. // z = x^(p-2) = x^7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB
  145. // (250 1s) (1 0s) (1 1s) (1 0s) (2 1s)
  146. // Addition chain: [1] [2] 3 5 10 15 25 50 75 125 [250]
  147. int[] x2 = Create();
  148. int[] t = Create();
  149. PowPm5d8(x, x2, t);
  150. Sqr(t, 3, t);
  151. Mul(t, x2, z);
  152. }
  153. public static bool IsZeroVar(int[] x)
  154. {
  155. int d = 0;
  156. for (int i = 0; i < Size; ++i)
  157. {
  158. d |= x[i];
  159. }
  160. return d == 0;
  161. }
  162. public static void Mul(int[] x, int y, int[] z)
  163. {
  164. int x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4];
  165. int x5 = x[5], x6 = x[6], x7 = x[7], x8 = x[8], x9 = x[9];
  166. long c0, c1, c2, c3;
  167. c0 = (long)x2 * y; x2 = (int)c0 & M25; c0 >>= 25;
  168. c1 = (long)x4 * y; x4 = (int)c1 & M25; c1 >>= 25;
  169. c2 = (long)x7 * y; x7 = (int)c2 & M25; c2 >>= 25;
  170. //c3 = (long)x9 * y; x9 = (int)c3 & M24; c3 >>= 24;
  171. //c3 *= 19;
  172. c3 = (long)x9 * y; x9 = (int)c3 & M25; c3 >>= 25;
  173. c3 *= 38;
  174. c3 += (long)x0 * y; z[0] = (int)c3 & M26; c3 >>= 26;
  175. c1 += (long)x5 * y; z[5] = (int)c1 & M26; c1 >>= 26;
  176. c3 += (long)x1 * y; z[1] = (int)c3 & M26; c3 >>= 26;
  177. c0 += (long)x3 * y; z[3] = (int)c0 & M26; c0 >>= 26;
  178. c1 += (long)x6 * y; z[6] = (int)c1 & M26; c1 >>= 26;
  179. c2 += (long)x8 * y; z[8] = (int)c2 & M26; c2 >>= 26;
  180. z[2] = x2 + (int)c3;
  181. z[4] = x4 + (int)c0;
  182. z[7] = x7 + (int)c1;
  183. z[9] = x9 + (int)c2;
  184. }
  185. public static void Mul(int[] x, int[] y, int[] z)
  186. {
  187. int x0 = x[0], y0 = y[0];
  188. int x1 = x[1], y1 = y[1];
  189. int x2 = x[2], y2 = y[2];
  190. int x3 = x[3], y3 = y[3];
  191. int x4 = x[4], y4 = y[4];
  192. int u0 = x[5], v0 = y[5];
  193. int u1 = x[6], v1 = y[6];
  194. int u2 = x[7], v2 = y[7];
  195. int u3 = x[8], v3 = y[8];
  196. int u4 = x[9], v4 = y[9];
  197. long a0 = (long)x0 * y0;
  198. long a1 = (long)x0 * y1
  199. + (long)x1 * y0;
  200. long a2 = (long)x0 * y2
  201. + (long)x1 * y1
  202. + (long)x2 * y0;
  203. long a3 = (long)x1 * y2
  204. + (long)x2 * y1;
  205. a3 <<= 1;
  206. a3 += (long)x0 * y3
  207. + (long)x3 * y0;
  208. long a4 = (long)x2 * y2;
  209. a4 <<= 1;
  210. a4 += (long)x0 * y4
  211. + (long)x1 * y3
  212. + (long)x3 * y1
  213. + (long)x4 * y0;
  214. long a5 = (long)x1 * y4
  215. + (long)x2 * y3
  216. + (long)x3 * y2
  217. + (long)x4 * y1;
  218. a5 <<= 1;
  219. long a6 = (long)x2 * y4
  220. + (long)x4 * y2;
  221. a6 <<= 1;
  222. a6 += (long)x3 * y3;
  223. long a7 = (long)x3 * y4
  224. + (long)x4 * y3;
  225. long a8 = (long)x4 * y4;
  226. a8 <<= 1;
  227. long b0 = (long)u0 * v0;
  228. long b1 = (long)u0 * v1
  229. + (long)u1 * v0;
  230. long b2 = (long)u0 * v2
  231. + (long)u1 * v1
  232. + (long)u2 * v0;
  233. long b3 = (long)u1 * v2
  234. + (long)u2 * v1;
  235. b3 <<= 1;
  236. b3 += (long)u0 * v3
  237. + (long)u3 * v0;
  238. long b4 = (long)u2 * v2;
  239. b4 <<= 1;
  240. b4 += (long)u0 * v4
  241. + (long)u1 * v3
  242. + (long)u3 * v1
  243. + (long)u4 * v0;
  244. long b5 = (long)u1 * v4
  245. + (long)u2 * v3
  246. + (long)u3 * v2
  247. + (long)u4 * v1;
  248. //b5 <<= 1;
  249. long b6 = (long)u2 * v4
  250. + (long)u4 * v2;
  251. b6 <<= 1;
  252. b6 += (long)u3 * v3;
  253. long b7 = (long)u3 * v4
  254. + (long)u4 * v3;
  255. long b8 = (long)u4 * v4;
  256. //b8 <<= 1;
  257. a0 -= b5 * 76;
  258. a1 -= b6 * 38;
  259. a2 -= b7 * 38;
  260. a3 -= b8 * 76;
  261. a5 -= b0;
  262. a6 -= b1;
  263. a7 -= b2;
  264. a8 -= b3;
  265. //long a9 = -b4;
  266. x0 += u0; y0 += v0;
  267. x1 += u1; y1 += v1;
  268. x2 += u2; y2 += v2;
  269. x3 += u3; y3 += v3;
  270. x4 += u4; y4 += v4;
  271. long c0 = (long)x0 * y0;
  272. long c1 = (long)x0 * y1
  273. + (long)x1 * y0;
  274. long c2 = (long)x0 * y2
  275. + (long)x1 * y1
  276. + (long)x2 * y0;
  277. long c3 = (long)x1 * y2
  278. + (long)x2 * y1;
  279. c3 <<= 1;
  280. c3 += (long)x0 * y3
  281. + (long)x3 * y0;
  282. long c4 = (long)x2 * y2;
  283. c4 <<= 1;
  284. c4 += (long)x0 * y4
  285. + (long)x1 * y3
  286. + (long)x3 * y1
  287. + (long)x4 * y0;
  288. long c5 = (long)x1 * y4
  289. + (long)x2 * y3
  290. + (long)x3 * y2
  291. + (long)x4 * y1;
  292. c5 <<= 1;
  293. long c6 = (long)x2 * y4
  294. + (long)x4 * y2;
  295. c6 <<= 1;
  296. c6 += (long)x3 * y3;
  297. long c7 = (long)x3 * y4
  298. + (long)x4 * y3;
  299. long c8 = (long)x4 * y4;
  300. c8 <<= 1;
  301. int z8, z9;
  302. long t;
  303. t = a8 + (c3 - a3);
  304. z8 = (int)t & M26; t >>= 26;
  305. //t += a9 + (c4 - a4);
  306. t += (c4 - a4) - b4;
  307. //z9 = (int)t & M24; t >>= 24;
  308. //t = a0 + (t + ((c5 - a5) << 1)) * 19;
  309. z9 = (int)t & M25; t >>= 25;
  310. t = a0 + (t + c5 - a5) * 38;
  311. z[0] = (int)t & M26; t >>= 26;
  312. t += a1 + (c6 - a6) * 38;
  313. z[1] = (int)t & M26; t >>= 26;
  314. t += a2 + (c7 - a7) * 38;
  315. z[2] = (int)t & M25; t >>= 25;
  316. t += a3 + (c8 - a8) * 38;
  317. z[3] = (int)t & M26; t >>= 26;
  318. //t += a4 - a9 * 38;
  319. t += a4 + b4 * 38;
  320. z[4] = (int)t & M25; t >>= 25;
  321. t += a5 + (c0 - a0);
  322. z[5] = (int)t & M26; t >>= 26;
  323. t += a6 + (c1 - a1);
  324. z[6] = (int)t & M26; t >>= 26;
  325. t += a7 + (c2 - a2);
  326. z[7] = (int)t & M25; t >>= 25;
  327. t += z8;
  328. z[8] = (int)t & M26; t >>= 26;
  329. z[9] = z9 + (int)t;
  330. }
  331. public static void Negate(int[] x, int[] z)
  332. {
  333. for (int i = 0; i < Size; ++i)
  334. {
  335. z[i] = -x[i];
  336. }
  337. }
  338. public static void Normalize(int[] z)
  339. {
  340. int x = (z[9] >> 23) & 1;
  341. Reduce(z, x);
  342. Reduce(z, -x);
  343. Debug.Assert(z[9] >> 24 == 0);
  344. }
  345. public static void One(int[] z)
  346. {
  347. z[0] = 1;
  348. for (int i = 1; i < Size; ++i)
  349. {
  350. z[i] = 0;
  351. }
  352. }
  353. private static void PowPm5d8(int[] x, int[] rx2, int[] rz)
  354. {
  355. // z = x^((p-5)/8) = x^FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD
  356. // (250 1s) (1 0s) (1 1s)
  357. // Addition chain: [1] 2 3 5 10 15 25 50 75 125 [250]
  358. int[] x2 = rx2; Sqr(x, x2); Mul(x, x2, x2);
  359. int[] x3 = Create(); Sqr(x2, x3); Mul(x, x3, x3);
  360. int[] x5 = x3; Sqr(x3, 2, x5); Mul(x2, x5, x5);
  361. int[] x10 = Create(); Sqr(x5, 5, x10); Mul(x5, x10, x10);
  362. int[] x15 = Create(); Sqr(x10, 5, x15); Mul(x5, x15, x15);
  363. int[] x25 = x5; Sqr(x15, 10, x25); Mul(x10, x25, x25);
  364. int[] x50 = x10; Sqr(x25, 25, x50); Mul(x25, x50, x50);
  365. int[] x75 = x15; Sqr(x50, 25, x75); Mul(x25, x75, x75);
  366. int[] x125 = x25; Sqr(x75, 50, x125); Mul(x50, x125, x125);
  367. int[] x250 = x50; Sqr(x125, 125, x250); Mul(x125, x250, x250);
  368. int[] t = x125;
  369. Sqr(x250, 2, t);
  370. Mul(t, x, rz);
  371. }
  372. private static void Reduce(int[] z, int c)
  373. {
  374. int z9 = z[9], t = z9;
  375. z9 = t & M24; t >>= 24;
  376. t += c;
  377. t *= 19;
  378. t += z[0]; z[0] = t & M26; t >>= 26;
  379. t += z[1]; z[1] = t & M26; t >>= 26;
  380. t += z[2]; z[2] = t & M25; t >>= 25;
  381. t += z[3]; z[3] = t & M26; t >>= 26;
  382. t += z[4]; z[4] = t & M25; t >>= 25;
  383. t += z[5]; z[5] = t & M26; t >>= 26;
  384. t += z[6]; z[6] = t & M26; t >>= 26;
  385. t += z[7]; z[7] = t & M25; t >>= 25;
  386. t += z[8]; z[8] = t & M26; t >>= 26;
  387. t += z9; z[9] = t;
  388. }
  389. public static void Sqr(int[] x, int[] z)
  390. {
  391. int x0 = x[0];
  392. int x1 = x[1];
  393. int x2 = x[2];
  394. int x3 = x[3];
  395. int x4 = x[4];
  396. int u0 = x[5];
  397. int u1 = x[6];
  398. int u2 = x[7];
  399. int u3 = x[8];
  400. int u4 = x[9];
  401. int x1_2 = x1 * 2;
  402. int x2_2 = x2 * 2;
  403. int x3_2 = x3 * 2;
  404. int x4_2 = x4 * 2;
  405. long a0 = (long)x0 * x0;
  406. long a1 = (long)x0 * x1_2;
  407. long a2 = (long)x0 * x2_2
  408. + (long)x1 * x1;
  409. long a3 = (long)x1_2 * x2_2
  410. + (long)x0 * x3_2;
  411. long a4 = (long)x2 * x2_2
  412. + (long)x0 * x4_2
  413. + (long)x1 * x3_2;
  414. long a5 = (long)x1_2 * x4_2
  415. + (long)x2_2 * x3_2;
  416. long a6 = (long)x2_2 * x4_2
  417. + (long)x3 * x3;
  418. long a7 = (long)x3 * x4_2;
  419. long a8 = (long)x4 * x4_2;
  420. int u1_2 = u1 * 2;
  421. int u2_2 = u2 * 2;
  422. int u3_2 = u3 * 2;
  423. int u4_2 = u4 * 2;
  424. long b0 = (long)u0 * u0;
  425. long b1 = (long)u0 * u1_2;
  426. long b2 = (long)u0 * u2_2
  427. + (long)u1 * u1;
  428. long b3 = (long)u1_2 * u2_2
  429. + (long)u0 * u3_2;
  430. long b4 = (long)u2 * u2_2
  431. + (long)u0 * u4_2
  432. + (long)u1 * u3_2;
  433. long b5 = (long)u1_2 * u4_2
  434. + (long)u2_2 * u3_2;
  435. long b6 = (long)u2_2 * u4_2
  436. + (long)u3 * u3;
  437. long b7 = (long)u3 * u4_2;
  438. long b8 = (long)u4 * u4_2;
  439. a0 -= b5 * 38;
  440. a1 -= b6 * 38;
  441. a2 -= b7 * 38;
  442. a3 -= b8 * 38;
  443. a5 -= b0;
  444. a6 -= b1;
  445. a7 -= b2;
  446. a8 -= b3;
  447. //long a9 = -b4;
  448. x0 += u0;
  449. x1 += u1;
  450. x2 += u2;
  451. x3 += u3;
  452. x4 += u4;
  453. x1_2 = x1 * 2;
  454. x2_2 = x2 * 2;
  455. x3_2 = x3 * 2;
  456. x4_2 = x4 * 2;
  457. long c0 = (long)x0 * x0;
  458. long c1 = (long)x0 * x1_2;
  459. long c2 = (long)x0 * x2_2
  460. + (long)x1 * x1;
  461. long c3 = (long)x1_2 * x2_2
  462. + (long)x0 * x3_2;
  463. long c4 = (long)x2 * x2_2
  464. + (long)x0 * x4_2
  465. + (long)x1 * x3_2;
  466. long c5 = (long)x1_2 * x4_2
  467. + (long)x2_2 * x3_2;
  468. long c6 = (long)x2_2 * x4_2
  469. + (long)x3 * x3;
  470. long c7 = (long)x3 * x4_2;
  471. long c8 = (long)x4 * x4_2;
  472. int z8, z9;
  473. long t;
  474. t = a8 + (c3 - a3);
  475. z8 = (int)t & M26; t >>= 26;
  476. //t += a9 + (c4 - a4);
  477. t += (c4 - a4) - b4;
  478. //z9 = (int)t & M24; t >>= 24;
  479. //t = a0 + (t + ((c5 - a5) << 1)) * 19;
  480. z9 = (int)t & M25; t >>= 25;
  481. t = a0 + (t + c5 - a5) * 38;
  482. z[0] = (int)t & M26; t >>= 26;
  483. t += a1 + (c6 - a6) * 38;
  484. z[1] = (int)t & M26; t >>= 26;
  485. t += a2 + (c7 - a7) * 38;
  486. z[2] = (int)t & M25; t >>= 25;
  487. t += a3 + (c8 - a8) * 38;
  488. z[3] = (int)t & M26; t >>= 26;
  489. //t += a4 - a9 * 38;
  490. t += a4 + b4 * 38;
  491. z[4] = (int)t & M25; t >>= 25;
  492. t += a5 + (c0 - a0);
  493. z[5] = (int)t & M26; t >>= 26;
  494. t += a6 + (c1 - a1);
  495. z[6] = (int)t & M26; t >>= 26;
  496. t += a7 + (c2 - a2);
  497. z[7] = (int)t & M25; t >>= 25;
  498. t += z8;
  499. z[8] = (int)t & M26; t >>= 26;
  500. z[9] = z9 + (int)t;
  501. }
  502. public static void Sqr(int[] x, int n, int[] z)
  503. {
  504. Debug.Assert(n > 0);
  505. Sqr(x, z);
  506. while (--n > 0)
  507. {
  508. Sqr(z, z);
  509. }
  510. }
  511. public static bool SqrtRatioVar(int[] u, int[] v, int[] z)
  512. {
  513. int[] uv3 = Create();
  514. int[] uv7 = Create();
  515. Mul(u, v, uv3);
  516. Sqr(v, uv7);
  517. Mul(uv3, uv7, uv3);
  518. Sqr(uv7, uv7);
  519. Mul(uv7, uv3, uv7);
  520. int[] t = Create();
  521. int[] x = Create();
  522. PowPm5d8(uv7, t, x);
  523. Mul(x, uv3, x);
  524. int[] vx2 = Create();
  525. Sqr(x, vx2);
  526. Mul(vx2, v, vx2);
  527. Sub(vx2, u, t);
  528. Normalize(t);
  529. if (IsZeroVar(t))
  530. {
  531. Copy(x, 0, z, 0);
  532. return true;
  533. }
  534. Add(vx2, u, t);
  535. Normalize(t);
  536. if (IsZeroVar(t))
  537. {
  538. Mul(x, RootNegOne, z);
  539. return true;
  540. }
  541. return false;
  542. }
  543. public static void Sub(int[] x, int[] y, int[] z)
  544. {
  545. for (int i = 0; i < Size; ++i)
  546. {
  547. z[i] = x[i] - y[i];
  548. }
  549. }
  550. public static void SubOne(int[] z)
  551. {
  552. z[0] -= 1;
  553. }
  554. public static void Zero(int[] z)
  555. {
  556. for (int i = 0; i < Size; ++i)
  557. {
  558. z[i] = 0;
  559. }
  560. }
  561. }
  562. }
  563. #pragma warning restore
  564. #endif