Nat.cs 88 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905
  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.Crypto.Utilities;
  6. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.Raw
  7. {
  8. internal abstract class Nat
  9. {
  10. private const ulong M = 0xFFFFFFFFUL;
  11. public static uint Add(int len, uint[] x, uint[] y, uint[] z)
  12. {
  13. ulong c = 0;
  14. for (int i = 0; i < len; ++i)
  15. {
  16. c += (ulong)x[i] + y[i];
  17. z[i] = (uint)c;
  18. c >>= 32;
  19. }
  20. return (uint)c;
  21. }
  22. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  23. public static uint Add(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> z)
  24. {
  25. ulong c = 0;
  26. for (int i = 0; i < len; ++i)
  27. {
  28. c += (ulong)x[i] + y[i];
  29. z[i] = (uint)c;
  30. c >>= 32;
  31. }
  32. return (uint)c;
  33. }
  34. #endif
  35. public static uint Add33At(int len, uint x, uint[] z, int zPos)
  36. {
  37. Debug.Assert(zPos <= (len - 2));
  38. ulong c = (ulong)z[zPos + 0] + x;
  39. z[zPos + 0] = (uint)c;
  40. c >>= 32;
  41. c += (ulong)z[zPos + 1] + 1;
  42. z[zPos + 1] = (uint)c;
  43. c >>= 32;
  44. return c == 0 ? 0 : IncAt(len, z, zPos + 2);
  45. }
  46. public static uint Add33At(int len, uint x, uint[] z, int zOff, int zPos)
  47. {
  48. Debug.Assert(zPos <= (len - 2));
  49. ulong c = (ulong)z[zOff + zPos] + x;
  50. z[zOff + zPos] = (uint)c;
  51. c >>= 32;
  52. c += (ulong)z[zOff + zPos + 1] + 1;
  53. z[zOff + zPos + 1] = (uint)c;
  54. c >>= 32;
  55. return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 2);
  56. }
  57. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  58. public static uint Add33At(int len, uint x, Span<uint> z, int zPos)
  59. {
  60. Debug.Assert(zPos <= (len - 2));
  61. ulong c = (ulong)z[zPos + 0] + x;
  62. z[zPos + 0] = (uint)c;
  63. c >>= 32;
  64. c += (ulong)z[zPos + 1] + 1;
  65. z[zPos + 1] = (uint)c;
  66. c >>= 32;
  67. return c == 0 ? 0 : IncAt(len, z, zPos + 2);
  68. }
  69. #endif
  70. public static uint Add33To(int len, uint x, uint[] z)
  71. {
  72. ulong c = (ulong)z[0] + x;
  73. z[0] = (uint)c;
  74. c >>= 32;
  75. c += (ulong)z[1] + 1;
  76. z[1] = (uint)c;
  77. c >>= 32;
  78. return c == 0 ? 0 : IncAt(len, z, 2);
  79. }
  80. public static uint Add33To(int len, uint x, uint[] z, int zOff)
  81. {
  82. ulong c = (ulong)z[zOff + 0] + x;
  83. z[zOff + 0] = (uint)c;
  84. c >>= 32;
  85. c += (ulong)z[zOff + 1] + 1;
  86. z[zOff + 1] = (uint)c;
  87. c >>= 32;
  88. return c == 0 ? 0 : IncAt(len, z, zOff, 2);
  89. }
  90. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  91. public static uint Add33To(int len, uint x, Span<uint> z)
  92. {
  93. ulong c = (ulong)z[0] + x;
  94. z[0] = (uint)c;
  95. c >>= 32;
  96. c += (ulong)z[1] + 1;
  97. z[1] = (uint)c;
  98. c >>= 32;
  99. return c == 0 ? 0 : IncAt(len, z, 2);
  100. }
  101. #endif
  102. public static uint AddBothTo(int len, uint[] x, uint[] y, uint[] z)
  103. {
  104. ulong c = 0;
  105. for (int i = 0; i < len; ++i)
  106. {
  107. c += (ulong)x[i] + y[i] + z[i];
  108. z[i] = (uint)c;
  109. c >>= 32;
  110. }
  111. return (uint)c;
  112. }
  113. public static uint AddBothTo(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  114. {
  115. ulong c = 0;
  116. for (int i = 0; i < len; ++i)
  117. {
  118. c += (ulong)x[xOff + i] + y[yOff + i] + z[zOff + i];
  119. z[zOff + i] = (uint)c;
  120. c >>= 32;
  121. }
  122. return (uint)c;
  123. }
  124. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  125. public static uint AddBothTo(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> z)
  126. {
  127. ulong c = 0;
  128. for (int i = 0; i < len; ++i)
  129. {
  130. c += (ulong)x[i] + y[i] + z[i];
  131. z[i] = (uint)c;
  132. c >>= 32;
  133. }
  134. return (uint)c;
  135. }
  136. #endif
  137. public static uint AddDWordAt(int len, ulong x, uint[] z, int zPos)
  138. {
  139. Debug.Assert(zPos <= (len - 2));
  140. ulong c = z[zPos + 0] + (x & M);
  141. z[zPos + 0] = (uint)c;
  142. c >>= 32;
  143. c += z[zPos + 1] + (x >> 32);
  144. z[zPos + 1] = (uint)c;
  145. c >>= 32;
  146. return c == 0 ? 0 : IncAt(len, z, zPos + 2);
  147. }
  148. public static uint AddDWordAt(int len, ulong x, uint[] z, int zOff, int zPos)
  149. {
  150. Debug.Assert(zPos <= (len - 2));
  151. ulong c = z[zOff + zPos] + (x & M);
  152. z[zOff + zPos] = (uint)c;
  153. c >>= 32;
  154. c += z[zOff + zPos + 1] + (x >> 32);
  155. z[zOff + zPos + 1] = (uint)c;
  156. c >>= 32;
  157. return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 2);
  158. }
  159. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  160. public static uint AddDWordAt(int len, ulong x, Span<uint> z, int zPos)
  161. {
  162. Debug.Assert(zPos <= (len - 2));
  163. ulong c = z[zPos + 0] + (x & M);
  164. z[zPos + 0] = (uint)c;
  165. c >>= 32;
  166. c += z[zPos + 1] + (x >> 32);
  167. z[zPos + 1] = (uint)c;
  168. c >>= 32;
  169. return c == 0 ? 0 : IncAt(len, z, zPos + 2);
  170. }
  171. #endif
  172. public static uint AddDWordTo(int len, ulong x, uint[] z)
  173. {
  174. ulong c = (ulong)z[0] + (x & M);
  175. z[0] = (uint)c;
  176. c >>= 32;
  177. c += (ulong)z[1] + (x >> 32);
  178. z[1] = (uint)c;
  179. c >>= 32;
  180. return c == 0 ? 0 : IncAt(len, z, 2);
  181. }
  182. public static uint AddDWordTo(int len, ulong x, uint[] z, int zOff)
  183. {
  184. ulong c = (ulong)z[zOff + 0] + (x & M);
  185. z[zOff + 0] = (uint)c;
  186. c >>= 32;
  187. c += (ulong)z[zOff + 1] + (x >> 32);
  188. z[zOff + 1] = (uint)c;
  189. c >>= 32;
  190. return c == 0 ? 0 : IncAt(len, z, zOff, 2);
  191. }
  192. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  193. public static uint AddDWordTo(int len, ulong x, Span<uint> z)
  194. {
  195. ulong c = z[0] + (x & M);
  196. z[0] = (uint)c;
  197. c >>= 32;
  198. c += z[1] + (x >> 32);
  199. z[1] = (uint)c;
  200. c >>= 32;
  201. return c == 0 ? 0 : IncAt(len, z, 2);
  202. }
  203. #endif
  204. public static uint AddTo(int len, uint[] x, uint[] z)
  205. {
  206. ulong c = 0;
  207. for (int i = 0; i < len; ++i)
  208. {
  209. c += (ulong)x[i] + z[i];
  210. z[i] = (uint)c;
  211. c >>= 32;
  212. }
  213. return (uint)c;
  214. }
  215. public static uint AddTo(int len, uint[] x, int xOff, uint[] z, int zOff)
  216. {
  217. ulong c = 0;
  218. for (int i = 0; i < len; ++i)
  219. {
  220. c += (ulong)x[xOff + i] + z[zOff + i];
  221. z[zOff + i] = (uint)c;
  222. c >>= 32;
  223. }
  224. return (uint)c;
  225. }
  226. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  227. public static uint AddTo(int len, ReadOnlySpan<uint> x, Span<uint> z)
  228. {
  229. ulong c = 0;
  230. for (int i = 0; i < len; ++i)
  231. {
  232. c += (ulong)x[i] + z[i];
  233. z[i] = (uint)c;
  234. c >>= 32;
  235. }
  236. return (uint)c;
  237. }
  238. #endif
  239. public static uint AddTo(int len, uint[] x, int xOff, uint[] z, int zOff, uint cIn)
  240. {
  241. ulong c = cIn;
  242. for (int i = 0; i < len; ++i)
  243. {
  244. c += (ulong)x[xOff + i] + z[zOff + i];
  245. z[zOff + i] = (uint)c;
  246. c >>= 32;
  247. }
  248. return (uint)c;
  249. }
  250. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  251. public static uint AddTo(int len, ReadOnlySpan<uint> x, Span<uint> z, uint cIn)
  252. {
  253. ulong c = cIn;
  254. for (int i = 0; i < len; ++i)
  255. {
  256. c += (ulong)x[i] + z[i];
  257. z[i] = (uint)c;
  258. c >>= 32;
  259. }
  260. return (uint)c;
  261. }
  262. #endif
  263. public static uint AddToEachOther(int len, uint[] u, int uOff, uint[] v, int vOff)
  264. {
  265. ulong c = 0;
  266. for (int i = 0; i < len; ++i)
  267. {
  268. c += (ulong)u[uOff + i] + v[vOff + i];
  269. u[uOff + i] = (uint)c;
  270. v[vOff + i] = (uint)c;
  271. c >>= 32;
  272. }
  273. return (uint)c;
  274. }
  275. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  276. public static uint AddToEachOther(int len, Span<uint> u, Span<uint> v)
  277. {
  278. ulong c = 0;
  279. for (int i = 0; i < len; ++i)
  280. {
  281. c += (ulong)u[i] + v[i];
  282. u[i] = (uint)c;
  283. v[i] = (uint)c;
  284. c >>= 32;
  285. }
  286. return (uint)c;
  287. }
  288. #endif
  289. public static uint AddWordAt(int len, uint x, uint[] z, int zPos)
  290. {
  291. Debug.Assert(zPos <= (len - 1));
  292. ulong c = (ulong)x + z[zPos];
  293. z[zPos] = (uint)c;
  294. c >>= 32;
  295. return c == 0 ? 0 : IncAt(len, z, zPos + 1);
  296. }
  297. public static uint AddWordAt(int len, uint x, uint[] z, int zOff, int zPos)
  298. {
  299. Debug.Assert(zPos <= (len - 1));
  300. ulong c = (ulong)x + z[zOff + zPos];
  301. z[zOff + zPos] = (uint)c;
  302. c >>= 32;
  303. return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 1);
  304. }
  305. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  306. public static uint AddWordAt(int len, uint x, Span<uint> z, int zPos)
  307. {
  308. Debug.Assert(zPos <= (len - 1));
  309. ulong c = (ulong)x + z[zPos];
  310. z[zPos] = (uint)c;
  311. c >>= 32;
  312. return c == 0 ? 0 : IncAt(len, z, zPos + 1);
  313. }
  314. #endif
  315. public static uint AddWordTo(int len, uint x, uint[] z)
  316. {
  317. ulong c = (ulong)x + z[0];
  318. z[0] = (uint)c;
  319. c >>= 32;
  320. return c == 0 ? 0 : IncAt(len, z, 1);
  321. }
  322. public static uint AddWordTo(int len, uint x, uint[] z, int zOff)
  323. {
  324. ulong c = (ulong)x + z[zOff];
  325. z[zOff] = (uint)c;
  326. c >>= 32;
  327. return c == 0 ? 0 : IncAt(len, z, zOff, 1);
  328. }
  329. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  330. public static uint AddWordTo(int len, uint x, Span<uint> z)
  331. {
  332. ulong c = (ulong)x + z[0];
  333. z[0] = (uint)c;
  334. c >>= 32;
  335. return c == 0 ? 0 : IncAt(len, z, 1);
  336. }
  337. #endif
  338. public static uint CAdd(int len, int mask, uint[] x, uint[] y, uint[] z)
  339. {
  340. uint MASK = (uint)-(mask & 1);
  341. ulong c = 0;
  342. for (int i = 0; i < len; ++i)
  343. {
  344. c += (ulong)x[i] + (y[i] & MASK);
  345. z[i] = (uint)c;
  346. c >>= 32;
  347. }
  348. return (uint)c;
  349. }
  350. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  351. public static uint CAdd(int len, int mask, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> z)
  352. {
  353. uint MASK = (uint)-(mask & 1);
  354. ulong c = 0;
  355. for (int i = 0; i < len; ++i)
  356. {
  357. c += (ulong)x[i] + (y[i] & MASK);
  358. z[i] = (uint)c;
  359. c >>= 32;
  360. }
  361. return (uint)c;
  362. }
  363. #endif
  364. public static void CMov(int len, int mask, uint[] x, int xOff, uint[] z, int zOff)
  365. {
  366. uint MASK = (uint)-(mask & 1);
  367. for (int i = 0; i < len; ++i)
  368. {
  369. uint z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
  370. z_i ^= diff & MASK;
  371. z[zOff + i] = z_i;
  372. }
  373. //uint half = 0x55555555U, rest = half << (-(int)MASK);
  374. //for (int i = 0; i < len; ++i)
  375. //{
  376. // uint z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
  377. // z_i ^= (diff & half);
  378. // z_i ^= (diff & rest);
  379. // z[zOff + i] = z_i;
  380. //}
  381. }
  382. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  383. public static void CMov(int len, int mask, ReadOnlySpan<uint> x, Span<uint> z)
  384. {
  385. uint MASK = (uint)-(mask & 1);
  386. for (int i = 0; i < len; ++i)
  387. {
  388. uint z_i = z[i], diff = z_i ^ x[i];
  389. z_i ^= diff & MASK;
  390. z[i] = z_i;
  391. }
  392. //uint half = 0x55555555U, rest = half << (-(int)MASK);
  393. //for (int i = 0; i < len; ++i)
  394. //{
  395. // uint z_i = z[i], diff = z_i ^ x[i];
  396. // z_i ^= (diff & half);
  397. // z_i ^= (diff & rest);
  398. // z[i] = z_i;
  399. //}
  400. }
  401. #endif
  402. public static int Compare(int len, uint[] x, uint[] y)
  403. {
  404. for (int i = len - 1; i >= 0; --i)
  405. {
  406. uint x_i = x[i];
  407. uint y_i = y[i];
  408. if (x_i < y_i)
  409. return -1;
  410. if (x_i > y_i)
  411. return 1;
  412. }
  413. return 0;
  414. }
  415. public static int Compare(int len, uint[] x, int xOff, uint[] y, int yOff)
  416. {
  417. for (int i = len - 1; i >= 0; --i)
  418. {
  419. uint x_i = x[xOff + i];
  420. uint y_i = y[yOff + i];
  421. if (x_i < y_i)
  422. return -1;
  423. if (x_i > y_i)
  424. return 1;
  425. }
  426. return 0;
  427. }
  428. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  429. public static int Compare(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y)
  430. {
  431. for (int i = len - 1; i >= 0; --i)
  432. {
  433. uint x_i = x[i];
  434. uint y_i = y[i];
  435. if (x_i < y_i)
  436. return -1;
  437. if (x_i > y_i)
  438. return 1;
  439. }
  440. return 0;
  441. }
  442. #endif
  443. public static uint[] Copy(int len, uint[] x)
  444. {
  445. uint[] z = new uint[len];
  446. Array.Copy(x, 0, z, 0, len);
  447. return z;
  448. }
  449. public static void Copy(int len, uint[] x, uint[] z)
  450. {
  451. Array.Copy(x, 0, z, 0, len);
  452. }
  453. public static void Copy(int len, uint[] x, int xOff, uint[] z, int zOff)
  454. {
  455. Array.Copy(x, xOff, z, zOff, len);
  456. }
  457. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  458. public static void Copy(int len, ReadOnlySpan<uint> x, Span<uint> z)
  459. {
  460. x[..len].CopyTo(z);
  461. }
  462. #endif
  463. public static ulong[] Copy64(int len, ulong[] x)
  464. {
  465. ulong[] z = new ulong[len];
  466. Array.Copy(x, 0, z, 0, len);
  467. return z;
  468. }
  469. public static void Copy64(int len, ulong[] x, ulong[] z)
  470. {
  471. Array.Copy(x, 0, z, 0, len);
  472. }
  473. public static void Copy64(int len, ulong[] x, int xOff, ulong[] z, int zOff)
  474. {
  475. Array.Copy(x, xOff, z, zOff, len);
  476. }
  477. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  478. public static void Copy64(int len, ReadOnlySpan<ulong> x, Span<ulong> z)
  479. {
  480. x[..len].CopyTo(z);
  481. }
  482. #endif
  483. public static uint[] Create(int len)
  484. {
  485. return new uint[len];
  486. }
  487. public static ulong[] Create64(int len)
  488. {
  489. return new ulong[len];
  490. }
  491. public static int CSub(int len, int mask, uint[] x, uint[] y, uint[] z)
  492. {
  493. long MASK = (uint)-(mask & 1);
  494. long c = 0;
  495. for (int i = 0; i < len; ++i)
  496. {
  497. c += x[i] - (y[i] & MASK);
  498. z[i] = (uint)c;
  499. c >>= 32;
  500. }
  501. return (int)c;
  502. }
  503. public static int CSub(int len, int mask, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  504. {
  505. long MASK = (uint)-(mask & 1);
  506. long c = 0;
  507. for (int i = 0; i < len; ++i)
  508. {
  509. c += x[xOff + i] - (y[yOff + i] & MASK);
  510. z[zOff + i] = (uint)c;
  511. c >>= 32;
  512. }
  513. return (int)c;
  514. }
  515. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  516. public static int CSub(int len, int mask, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> z)
  517. {
  518. long MASK = (uint)-(mask & 1);
  519. long c = 0;
  520. for (int i = 0; i < len; ++i)
  521. {
  522. c += x[i] - (y[i] & MASK);
  523. z[i] = (uint)c;
  524. c >>= 32;
  525. }
  526. return (int)c;
  527. }
  528. #endif
  529. public static int Dec(int len, uint[] z)
  530. {
  531. for (int i = 0; i < len; ++i)
  532. {
  533. if (--z[i] != uint.MaxValue)
  534. return 0;
  535. }
  536. return -1;
  537. }
  538. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  539. public static int Dec(int len, Span<uint> z)
  540. {
  541. for (int i = 0; i < len; ++i)
  542. {
  543. if (--z[i] != uint.MaxValue)
  544. return 0;
  545. }
  546. return -1;
  547. }
  548. #endif
  549. public static int Dec(int len, uint[] x, uint[] z)
  550. {
  551. int i = 0;
  552. while (i < len)
  553. {
  554. uint c = x[i] - 1;
  555. z[i] = c;
  556. ++i;
  557. if (c != uint.MaxValue)
  558. {
  559. while (i < len)
  560. {
  561. z[i] = x[i];
  562. ++i;
  563. }
  564. return 0;
  565. }
  566. }
  567. return -1;
  568. }
  569. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  570. public static int Dec(int len, ReadOnlySpan<uint> x, Span<uint> z)
  571. {
  572. int i = 0;
  573. while (i < len)
  574. {
  575. uint c = x[i] - 1;
  576. z[i] = c;
  577. ++i;
  578. if (c != uint.MaxValue)
  579. {
  580. while (i < len)
  581. {
  582. z[i] = x[i];
  583. ++i;
  584. }
  585. return 0;
  586. }
  587. }
  588. return -1;
  589. }
  590. #endif
  591. public static int DecAt(int len, uint[] z, int zPos)
  592. {
  593. Debug.Assert(zPos <= len);
  594. for (int i = zPos; i < len; ++i)
  595. {
  596. if (--z[i] != uint.MaxValue)
  597. return 0;
  598. }
  599. return -1;
  600. }
  601. public static int DecAt(int len, uint[] z, int zOff, int zPos)
  602. {
  603. Debug.Assert(zPos <= len);
  604. for (int i = zPos; i < len; ++i)
  605. {
  606. if (--z[zOff + i] != uint.MaxValue)
  607. return 0;
  608. }
  609. return -1;
  610. }
  611. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  612. public static int DecAt(int len, Span<uint> z, int zPos)
  613. {
  614. Debug.Assert(zPos <= len);
  615. for (int i = zPos; i < len; ++i)
  616. {
  617. if (--z[i] != uint.MaxValue)
  618. return 0;
  619. }
  620. return -1;
  621. }
  622. #endif
  623. public static bool Eq(int len, uint[] x, uint[] y)
  624. {
  625. for (int i = len - 1; i >= 0; --i)
  626. {
  627. if (x[i] != y[i])
  628. return false;
  629. }
  630. return true;
  631. }
  632. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  633. public static bool Eq(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y)
  634. {
  635. for (int i = len - 1; i >= 0; --i)
  636. {
  637. if (x[i] != y[i])
  638. return false;
  639. }
  640. return true;
  641. }
  642. #endif
  643. public static uint EqualTo(int len, uint[] x, uint y)
  644. {
  645. uint d = x[0] ^ y;
  646. for (int i = 1; i < len; ++i)
  647. {
  648. d |= x[i];
  649. }
  650. d = (d >> 1) | (d & 1);
  651. return (uint)(((int)d - 1) >> 31);
  652. }
  653. public static uint EqualTo(int len, uint[] x, int xOff, uint y)
  654. {
  655. uint d = x[xOff] ^ y;
  656. for (int i = 1; i < len; ++i)
  657. {
  658. d |= x[xOff + i];
  659. }
  660. d = (d >> 1) | (d & 1);
  661. return (uint)(((int)d - 1) >> 31);
  662. }
  663. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  664. public static uint EqualTo(int len, ReadOnlySpan<uint> x, uint y)
  665. {
  666. uint d = x[0] ^ y;
  667. for (int i = 1; i < len; ++i)
  668. {
  669. d |= x[i];
  670. }
  671. d = (d >> 1) | (d & 1);
  672. return (uint)(((int)d - 1) >> 31);
  673. }
  674. #endif
  675. public static uint EqualTo(int len, uint[] x, uint[] y)
  676. {
  677. uint d = 0;
  678. for (int i = 0; i < len; ++i)
  679. {
  680. d |= x[i] ^ y[i];
  681. }
  682. d = (d >> 1) | (d & 1);
  683. return (uint)(((int)d - 1) >> 31);
  684. }
  685. public static uint EqualTo(int len, uint[] x, int xOff, uint[] y, int yOff)
  686. {
  687. uint d = 0;
  688. for (int i = 0; i < len; ++i)
  689. {
  690. d |= x[xOff + i] ^ y[yOff + i];
  691. }
  692. d = (d >> 1) | (d & 1);
  693. return (uint)(((int)d - 1) >> 31);
  694. }
  695. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  696. public static uint EqualTo(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y)
  697. {
  698. uint d = 0;
  699. for (int i = 0; i < len; ++i)
  700. {
  701. d |= x[i] ^ y[i];
  702. }
  703. d = (d >> 1) | (d & 1);
  704. return (uint)(((int)d - 1) >> 31);
  705. }
  706. #endif
  707. public static uint EqualToZero(int len, uint[] x)
  708. {
  709. uint d = 0;
  710. for (int i = 0; i < len; ++i)
  711. {
  712. d |= x[i];
  713. }
  714. d = (d >> 1) | (d & 1);
  715. return (uint)(((int)d - 1) >> 31);
  716. }
  717. public static uint EqualToZero(int len, uint[] x, int xOff)
  718. {
  719. uint d = 0;
  720. for (int i = 0; i < len; ++i)
  721. {
  722. d |= x[xOff + i];
  723. }
  724. d = (d >> 1) | (d & 1);
  725. return (uint)(((int)d - 1) >> 31);
  726. }
  727. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  728. public static uint EqualToZero(int len, ReadOnlySpan<uint> x)
  729. {
  730. uint d = 0;
  731. for (int i = 0; i < len; ++i)
  732. {
  733. d |= x[i];
  734. }
  735. d = (d >> 1) | (d & 1);
  736. return (uint)(((int)d - 1) >> 31);
  737. }
  738. #endif
  739. public static uint[] FromBigInteger(int bits, BigInteger x)
  740. {
  741. int len = GetLengthForBits(bits);
  742. if (x.SignValue < 0 || x.BitLength > bits)
  743. throw new ArgumentException();
  744. uint[] z = Create(len);
  745. // NOTE: Use a fixed number of loop iterations
  746. z[0] = (uint)x.IntValue;
  747. for (int i = 1; i < len; ++i)
  748. {
  749. x = x.ShiftRight(32);
  750. z[i] = (uint)x.IntValue;
  751. }
  752. return z;
  753. }
  754. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  755. public static void FromBigInteger(int bits, BigInteger x, Span<uint> z)
  756. {
  757. int len = GetLengthForBits(bits);
  758. if (x.SignValue < 0 || x.BitLength > bits)
  759. throw new ArgumentException();
  760. if (z.Length < len)
  761. throw new ArgumentException();
  762. // NOTE: Use a fixed number of loop iterations
  763. z[0] = (uint)x.IntValue;
  764. for (int i = 1; i < len; ++i)
  765. {
  766. x = x.ShiftRight(32);
  767. z[i] = (uint)x.IntValue;
  768. }
  769. }
  770. #endif
  771. public static ulong[] FromBigInteger64(int bits, BigInteger x)
  772. {
  773. int len = GetLengthForBits64(bits);
  774. if (x.SignValue < 0 || x.BitLength > bits)
  775. throw new ArgumentException();
  776. ulong[] z = Create64(len);
  777. // NOTE: Use a fixed number of loop iterations
  778. z[0] = (ulong)x.LongValue;
  779. for (int i = 1; i < len; ++i)
  780. {
  781. x = x.ShiftRight(64);
  782. z[i] = (ulong)x.LongValue;
  783. }
  784. return z;
  785. }
  786. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  787. public static void FromBigInteger64(int bits, BigInteger x, Span<ulong> z)
  788. {
  789. int len = GetLengthForBits64(bits);
  790. if (x.SignValue < 0 || x.BitLength > bits)
  791. throw new ArgumentException();
  792. if (z.Length < len)
  793. throw new ArgumentException();
  794. // NOTE: Use a fixed number of loop iterations
  795. z[0] = (ulong)x.LongValue;
  796. for (int i = 1; i < len; ++i)
  797. {
  798. x = x.ShiftRight(64);
  799. z[i] = (ulong)x.LongValue;
  800. }
  801. }
  802. #endif
  803. public static uint GetBit(uint[] x, int bit)
  804. {
  805. if (bit == 0)
  806. return x[0] & 1;
  807. int w = bit >> 5;
  808. if (w < 0 || w >= x.Length)
  809. return 0;
  810. int b = bit & 31;
  811. return (x[w] >> b) & 1;
  812. }
  813. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  814. public static uint GetBit(ReadOnlySpan<uint> x, int bit)
  815. {
  816. if (bit == 0)
  817. return x[0] & 1;
  818. int w = bit >> 5;
  819. if (w < 0 || w >= x.Length)
  820. return 0;
  821. int b = bit & 31;
  822. return (x[w] >> b) & 1;
  823. }
  824. #endif
  825. public static int GetLengthForBits(int bits)
  826. {
  827. if (bits < 1)
  828. throw new ArgumentException();
  829. return (int)(((uint)bits + 31) >> 5);
  830. }
  831. public static int GetLengthForBits64(int bits)
  832. {
  833. if (bits < 1)
  834. throw new ArgumentException();
  835. return (int)(((uint)bits + 63) >> 6);
  836. }
  837. public static bool Gte(int len, uint[] x, uint[] y)
  838. {
  839. for (int i = len - 1; i >= 0; --i)
  840. {
  841. uint x_i = x[i], y_i = y[i];
  842. if (x_i < y_i)
  843. return false;
  844. if (x_i > y_i)
  845. return true;
  846. }
  847. return true;
  848. }
  849. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  850. public static bool Gte(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y)
  851. {
  852. for (int i = len - 1; i >= 0; --i)
  853. {
  854. uint x_i = x[i], y_i = y[i];
  855. if (x_i < y_i)
  856. return false;
  857. if (x_i > y_i)
  858. return true;
  859. }
  860. return true;
  861. }
  862. #endif
  863. public static uint Inc(int len, uint[] z)
  864. {
  865. for (int i = 0; i < len; ++i)
  866. {
  867. if (++z[i] != uint.MinValue)
  868. return 0;
  869. }
  870. return 1;
  871. }
  872. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  873. public static uint Inc(int len, Span<uint> z)
  874. {
  875. for (int i = 0; i < len; ++i)
  876. {
  877. if (++z[i] != uint.MinValue)
  878. return 0;
  879. }
  880. return 1;
  881. }
  882. #endif
  883. public static uint Inc(int len, uint[] x, uint[] z)
  884. {
  885. int i = 0;
  886. while (i < len)
  887. {
  888. uint c = x[i] + 1;
  889. z[i] = c;
  890. ++i;
  891. if (c != 0)
  892. {
  893. while (i < len)
  894. {
  895. z[i] = x[i];
  896. ++i;
  897. }
  898. return 0;
  899. }
  900. }
  901. return 1;
  902. }
  903. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  904. public static uint Inc(int len, ReadOnlySpan<uint> x, Span<uint> z)
  905. {
  906. int i = 0;
  907. while (i < len)
  908. {
  909. uint c = x[i] + 1;
  910. z[i] = c;
  911. ++i;
  912. if (c != 0)
  913. {
  914. while (i < len)
  915. {
  916. z[i] = x[i];
  917. ++i;
  918. }
  919. return 0;
  920. }
  921. }
  922. return 1;
  923. }
  924. #endif
  925. public static uint IncAt(int len, uint[] z, int zPos)
  926. {
  927. Debug.Assert(zPos <= len);
  928. for (int i = zPos; i < len; ++i)
  929. {
  930. if (++z[i] != uint.MinValue)
  931. return 0;
  932. }
  933. return 1;
  934. }
  935. public static uint IncAt(int len, uint[] z, int zOff, int zPos)
  936. {
  937. Debug.Assert(zPos <= len);
  938. for (int i = zPos; i < len; ++i)
  939. {
  940. if (++z[zOff + i] != uint.MinValue)
  941. return 0;
  942. }
  943. return 1;
  944. }
  945. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  946. public static uint IncAt(int len, Span<uint> z, int zPos)
  947. {
  948. Debug.Assert(zPos <= len);
  949. for (int i = zPos; i < len; ++i)
  950. {
  951. if (++z[i] != uint.MinValue)
  952. return 0;
  953. }
  954. return 1;
  955. }
  956. #endif
  957. public static bool IsOne(int len, uint[] x)
  958. {
  959. if (x[0] != 1)
  960. return false;
  961. for (int i = 1; i < len; ++i)
  962. {
  963. if (x[i] != 0)
  964. return false;
  965. }
  966. return true;
  967. }
  968. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  969. public static bool IsOne(int len, ReadOnlySpan<uint> x)
  970. {
  971. if (x[0] != 1)
  972. return false;
  973. for (int i = 1; i < len; ++i)
  974. {
  975. if (x[i] != 0)
  976. return false;
  977. }
  978. return true;
  979. }
  980. #endif
  981. public static bool IsZero(int len, uint[] x)
  982. {
  983. if (x[0] != 0)
  984. return false;
  985. for (int i = 1; i < len; ++i)
  986. {
  987. if (x[i] != 0)
  988. return false;
  989. }
  990. return true;
  991. }
  992. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  993. public static bool IsZero(int len, ReadOnlySpan<uint> x)
  994. {
  995. if (x[0] != 0)
  996. return false;
  997. for (int i = 1; i < len; ++i)
  998. {
  999. if (x[i] != 0)
  1000. return false;
  1001. }
  1002. return true;
  1003. }
  1004. #endif
  1005. public static int LessThan(int len, uint[] x, uint[] y)
  1006. {
  1007. long c = 0;
  1008. for (int i = 0; i < len; ++i)
  1009. {
  1010. c += (long)x[i] - y[i];
  1011. c >>= 32;
  1012. }
  1013. Debug.Assert(c == 0L || c == -1L);
  1014. return (int)c;
  1015. }
  1016. public static int LessThan(int len, uint[] x, int xOff, uint[] y, int yOff)
  1017. {
  1018. long c = 0;
  1019. for (int i = 0; i < len; ++i)
  1020. {
  1021. c += (long)x[xOff + i] - y[yOff + i];
  1022. c >>= 32;
  1023. }
  1024. Debug.Assert(c == 0L || c == -1L);
  1025. return (int)c;
  1026. }
  1027. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1028. public static int LessThan(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y)
  1029. {
  1030. long c = 0;
  1031. for (int i = 0; i < len; ++i)
  1032. {
  1033. c += (long)x[i] - y[i];
  1034. c >>= 32;
  1035. }
  1036. Debug.Assert(c == 0L || c == -1L);
  1037. return (int)c;
  1038. }
  1039. #endif
  1040. public static void Mul(int len, uint[] x, uint[] y, uint[] zz)
  1041. {
  1042. zz[len] = MulWord(len, x[0], y, zz);
  1043. for (int i = 1; i < len; ++i)
  1044. {
  1045. zz[i + len] = MulWordAddTo(len, x[i], y, 0, zz, i);
  1046. }
  1047. }
  1048. public static void Mul(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
  1049. {
  1050. zz[zzOff + len] = MulWord(len, x[xOff], y, yOff, zz, zzOff);
  1051. for (int i = 1; i < len; ++i)
  1052. {
  1053. zz[zzOff + i + len] = MulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff + i);
  1054. }
  1055. }
  1056. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1057. public static void Mul(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> zz)
  1058. {
  1059. zz[len] = MulWord(len, x[0], y, zz);
  1060. for (int i = 1; i < len; ++i)
  1061. {
  1062. zz[i + len] = MulWordAddTo(len, x[i], y, zz[i..]);
  1063. }
  1064. }
  1065. #endif
  1066. public static void Mul(uint[] x, int xOff, int xLen, uint[] y, int yOff, int yLen, uint[] zz, int zzOff)
  1067. {
  1068. zz[zzOff + yLen] = MulWord(yLen, x[xOff], y, yOff, zz, zzOff);
  1069. for (int i = 1; i < xLen; ++i)
  1070. {
  1071. zz[zzOff + i + yLen] = MulWordAddTo(yLen, x[xOff + i], y, yOff, zz, zzOff + i);
  1072. }
  1073. }
  1074. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1075. public static void Mul(ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> zz)
  1076. {
  1077. int xLen = x.Length, yLen = y.Length;
  1078. zz[yLen] = MulWord(yLen, x[0], y, zz);
  1079. for (int i = 1; i < xLen; ++i)
  1080. {
  1081. zz[i + yLen] = MulWordAddTo(yLen, x[i], y, zz[i..]);
  1082. }
  1083. }
  1084. #endif
  1085. public static uint MulAddTo(int len, uint[] x, uint[] y, uint[] zz)
  1086. {
  1087. ulong zc = 0;
  1088. for (int i = 0; i < len; ++i)
  1089. {
  1090. zc += MulWordAddTo(len, x[i], y, 0, zz, i) & M;
  1091. zc += zz[i + len] & M;
  1092. zz[i + len] = (uint)zc;
  1093. zc >>= 32;
  1094. }
  1095. return (uint)zc;
  1096. }
  1097. public static uint MulAddTo(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
  1098. {
  1099. ulong zc = 0;
  1100. for (int i = 0; i < len; ++i)
  1101. {
  1102. zc += MulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff) & M;
  1103. zc += zz[zzOff + len] & M;
  1104. zz[zzOff + len] = (uint)zc;
  1105. zc >>= 32;
  1106. ++zzOff;
  1107. }
  1108. return (uint)zc;
  1109. }
  1110. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1111. public static uint MulAddTo(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> zz)
  1112. {
  1113. ulong zc = 0;
  1114. for (int i = 0; i < len; ++i)
  1115. {
  1116. zc += MulWordAddTo(len, x[i], y, zz[i..]) & M;
  1117. zc += zz[i + len] & M;
  1118. zz[i + len] = (uint)zc;
  1119. zc >>= 32;
  1120. }
  1121. return (uint)zc;
  1122. }
  1123. #endif
  1124. public static uint Mul31BothAdd(int len, uint a, uint[] x, uint b, uint[] y, uint[] z, int zOff)
  1125. {
  1126. ulong c = 0, aVal = a, bVal = b;
  1127. int i = 0;
  1128. do
  1129. {
  1130. c += aVal * x[i] + bVal * y[i] + z[zOff + i];
  1131. z[zOff + i] = (uint)c;
  1132. c >>= 32;
  1133. }
  1134. while (++i < len);
  1135. return (uint)c;
  1136. }
  1137. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1138. public static uint Mul31BothAdd(int len, uint a, ReadOnlySpan<uint> x, uint b, ReadOnlySpan<uint> y,
  1139. Span<uint> z)
  1140. {
  1141. ulong c = 0, aVal = a, bVal = b;
  1142. int i = 0;
  1143. do
  1144. {
  1145. c += aVal * x[i] + bVal * y[i] + z[i];
  1146. z[i] = (uint)c;
  1147. c >>= 32;
  1148. }
  1149. while (++i < len);
  1150. return (uint)c;
  1151. }
  1152. #endif
  1153. public static uint MulWord(int len, uint x, uint[] y, uint[] z)
  1154. {
  1155. ulong c = 0, xVal = x;
  1156. int i = 0;
  1157. do
  1158. {
  1159. c += xVal * y[i];
  1160. z[i] = (uint)c;
  1161. c >>= 32;
  1162. }
  1163. while (++i < len);
  1164. return (uint)c;
  1165. }
  1166. public static uint MulWord(int len, uint x, uint[] y, int yOff, uint[] z, int zOff)
  1167. {
  1168. ulong c = 0, xVal = x;
  1169. int i = 0;
  1170. do
  1171. {
  1172. c += xVal * y[yOff + i];
  1173. z[zOff + i] = (uint)c;
  1174. c >>= 32;
  1175. }
  1176. while (++i < len);
  1177. return (uint)c;
  1178. }
  1179. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1180. public static uint MulWord(int len, uint x, ReadOnlySpan<uint> y, Span<uint> z)
  1181. {
  1182. ulong c = 0, xVal = x;
  1183. int i = 0;
  1184. do
  1185. {
  1186. c += xVal * y[i];
  1187. z[i] = (uint)c;
  1188. c >>= 32;
  1189. }
  1190. while (++i < len);
  1191. return (uint)c;
  1192. }
  1193. #endif
  1194. public static uint MulWordAddTo(int len, uint x, uint[] y, int yOff, uint[] z, int zOff)
  1195. {
  1196. ulong c = 0, xVal = x;
  1197. int i = 0;
  1198. do
  1199. {
  1200. c += xVal * y[yOff + i] + z[zOff + i];
  1201. z[zOff + i] = (uint)c;
  1202. c >>= 32;
  1203. }
  1204. while (++i < len);
  1205. return (uint)c;
  1206. }
  1207. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1208. public static uint MulWordAddTo(int len, uint x, ReadOnlySpan<uint> y, Span<uint> z)
  1209. {
  1210. ulong c = 0, xVal = x;
  1211. int i = 0;
  1212. do
  1213. {
  1214. c += xVal * y[i] + z[i];
  1215. z[i] = (uint)c;
  1216. c >>= 32;
  1217. }
  1218. while (++i < len);
  1219. return (uint)c;
  1220. }
  1221. #endif
  1222. public static uint MulWordDwordAddAt(int len, uint x, ulong y, uint[] z, int zPos)
  1223. {
  1224. Debug.Assert(zPos <= (len - 3));
  1225. ulong c = 0, xVal = x;
  1226. c += xVal * (uint)y + z[zPos + 0];
  1227. z[zPos + 0] = (uint)c;
  1228. c >>= 32;
  1229. c += xVal * (y >> 32) + z[zPos + 1];
  1230. z[zPos + 1] = (uint)c;
  1231. c >>= 32;
  1232. c += z[zPos + 2];
  1233. z[zPos + 2] = (uint)c;
  1234. c >>= 32;
  1235. return c == 0 ? 0 : IncAt(len, z, zPos + 3);
  1236. }
  1237. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1238. public static uint MulWordDwordAddAt(int len, uint x, ulong y, Span<uint> z, int zPos)
  1239. {
  1240. Debug.Assert(zPos <= (len - 3));
  1241. ulong c = 0, xVal = x;
  1242. c += xVal * (uint)y + z[zPos + 0];
  1243. z[zPos + 0] = (uint)c;
  1244. c >>= 32;
  1245. c += xVal * (y >> 32) + z[zPos + 1];
  1246. z[zPos + 1] = (uint)c;
  1247. c >>= 32;
  1248. c += z[zPos + 2];
  1249. z[zPos + 2] = (uint)c;
  1250. c >>= 32;
  1251. return c == 0 ? 0 : IncAt(len, z, zPos + 3);
  1252. }
  1253. #endif
  1254. public static uint ShiftDownBit(int len, uint[] z, uint c)
  1255. {
  1256. int i = len;
  1257. while (--i >= 0)
  1258. {
  1259. uint next = z[i];
  1260. z[i] = (next >> 1) | (c << 31);
  1261. c = next;
  1262. }
  1263. return c << 31;
  1264. }
  1265. public static uint ShiftDownBit(int len, uint[] z, int zOff, uint c)
  1266. {
  1267. int i = len;
  1268. while (--i >= 0)
  1269. {
  1270. uint next = z[zOff + i];
  1271. z[zOff + i] = (next >> 1) | (c << 31);
  1272. c = next;
  1273. }
  1274. return c << 31;
  1275. }
  1276. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1277. public static uint ShiftDownBit(int len, Span<uint> z, uint c)
  1278. {
  1279. int i = len;
  1280. while (--i >= 0)
  1281. {
  1282. uint next = z[i];
  1283. z[i] = (next >> 1) | (c << 31);
  1284. c = next;
  1285. }
  1286. return c << 31;
  1287. }
  1288. #endif
  1289. public static uint ShiftDownBit(int len, uint[] x, uint c, uint[] z)
  1290. {
  1291. int i = len;
  1292. while (--i >= 0)
  1293. {
  1294. uint next = x[i];
  1295. z[i] = (next >> 1) | (c << 31);
  1296. c = next;
  1297. }
  1298. return c << 31;
  1299. }
  1300. public static uint ShiftDownBit(int len, uint[] x, int xOff, uint c, uint[] z, int zOff)
  1301. {
  1302. int i = len;
  1303. while (--i >= 0)
  1304. {
  1305. uint next = x[xOff + i];
  1306. z[zOff + i] = (next >> 1) | (c << 31);
  1307. c = next;
  1308. }
  1309. return c << 31;
  1310. }
  1311. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1312. public static uint ShiftDownBit(int len, ReadOnlySpan<uint> x, uint c, Span<uint> z)
  1313. {
  1314. int i = len;
  1315. while (--i >= 0)
  1316. {
  1317. uint next = x[i];
  1318. z[i] = (next >> 1) | (c << 31);
  1319. c = next;
  1320. }
  1321. return c << 31;
  1322. }
  1323. #endif
  1324. public static uint ShiftDownBits(int len, uint[] z, int bits, uint c)
  1325. {
  1326. Debug.Assert(bits > 0 && bits < 32);
  1327. int i = len;
  1328. while (--i >= 0)
  1329. {
  1330. uint next = z[i];
  1331. z[i] = (next >> bits) | (c << -bits);
  1332. c = next;
  1333. }
  1334. return c << -bits;
  1335. }
  1336. public static uint ShiftDownBits(int len, uint[] z, int zOff, int bits, uint c)
  1337. {
  1338. Debug.Assert(bits > 0 && bits < 32);
  1339. int i = len;
  1340. while (--i >= 0)
  1341. {
  1342. uint next = z[zOff + i];
  1343. z[zOff + i] = (next >> bits) | (c << -bits);
  1344. c = next;
  1345. }
  1346. return c << -bits;
  1347. }
  1348. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1349. public static uint ShiftDownBits(int len, Span<uint> z, int bits, uint c)
  1350. {
  1351. Debug.Assert(bits > 0 && bits < 32);
  1352. int i = len;
  1353. while (--i >= 0)
  1354. {
  1355. uint next = z[i];
  1356. z[i] = (next >> bits) | (c << -bits);
  1357. c = next;
  1358. }
  1359. return c << -bits;
  1360. }
  1361. #endif
  1362. public static uint ShiftDownBits(int len, uint[] x, int bits, uint c, uint[] z)
  1363. {
  1364. Debug.Assert(bits > 0 && bits < 32);
  1365. int i = len;
  1366. while (--i >= 0)
  1367. {
  1368. uint next = x[i];
  1369. z[i] = (next >> bits) | (c << -bits);
  1370. c = next;
  1371. }
  1372. return c << -bits;
  1373. }
  1374. public static uint ShiftDownBits(int len, uint[] x, int xOff, int bits, uint c, uint[] z, int zOff)
  1375. {
  1376. Debug.Assert(bits > 0 && bits < 32);
  1377. int i = len;
  1378. while (--i >= 0)
  1379. {
  1380. uint next = x[xOff + i];
  1381. z[zOff + i] = (next >> bits) | (c << -bits);
  1382. c = next;
  1383. }
  1384. return c << -bits;
  1385. }
  1386. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1387. public static uint ShiftDownBits(int len, ReadOnlySpan<uint> x, int bits, uint c, Span<uint> z)
  1388. {
  1389. Debug.Assert(bits > 0 && bits < 32);
  1390. int i = len;
  1391. while (--i >= 0)
  1392. {
  1393. uint next = x[i];
  1394. z[i] = (next >> bits) | (c << -bits);
  1395. c = next;
  1396. }
  1397. return c << -bits;
  1398. }
  1399. #endif
  1400. public static uint ShiftDownWord(int len, uint[] z, uint c)
  1401. {
  1402. int i = len;
  1403. while (--i >= 0)
  1404. {
  1405. uint next = z[i];
  1406. z[i] = c;
  1407. c = next;
  1408. }
  1409. return c;
  1410. }
  1411. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1412. public static uint ShiftDownWord(int len, Span<uint> z, uint c)
  1413. {
  1414. int i = len;
  1415. while (--i >= 0)
  1416. {
  1417. uint next = z[i];
  1418. z[i] = c;
  1419. c = next;
  1420. }
  1421. return c;
  1422. }
  1423. #endif
  1424. public static uint ShiftUpBit(int len, uint[] z, uint c)
  1425. {
  1426. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1427. return ShiftUpBit(len, z.AsSpan(0, len), c);
  1428. #else
  1429. int i = 0, limit4 = len - 4;
  1430. while (i <= limit4)
  1431. {
  1432. uint next0 = z[i + 0];
  1433. uint next1 = z[i + 1];
  1434. uint next2 = z[i + 2];
  1435. uint next3 = z[i + 3];
  1436. z[i + 0] = (next0 << 1) | (c >> 31);
  1437. z[i + 1] = (next1 << 1) | (next0 >> 31);
  1438. z[i + 2] = (next2 << 1) | (next1 >> 31);
  1439. z[i + 3] = (next3 << 1) | (next2 >> 31);
  1440. c = next3;
  1441. i += 4;
  1442. }
  1443. while (i < len)
  1444. {
  1445. uint next = z[i];
  1446. z[i] = (next << 1) | (c >> 31);
  1447. c = next;
  1448. ++i;
  1449. }
  1450. return c >> 31;
  1451. #endif
  1452. }
  1453. public static uint ShiftUpBit(int len, uint[] z, int zOff, uint c)
  1454. {
  1455. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1456. return ShiftUpBit(len, z.AsSpan(zOff, len), c);
  1457. #else
  1458. int i = 0, limit4 = len - 4;
  1459. while (i <= limit4)
  1460. {
  1461. uint next0 = z[zOff + i + 0];
  1462. uint next1 = z[zOff + i + 1];
  1463. uint next2 = z[zOff + i + 2];
  1464. uint next3 = z[zOff + i + 3];
  1465. z[zOff + i + 0] = (next0 << 1) | (c >> 31);
  1466. z[zOff + i + 1] = (next1 << 1) | (next0 >> 31);
  1467. z[zOff + i + 2] = (next2 << 1) | (next1 >> 31);
  1468. z[zOff + i + 3] = (next3 << 1) | (next2 >> 31);
  1469. c = next3;
  1470. i += 4;
  1471. }
  1472. while (i < len)
  1473. {
  1474. uint next = z[zOff + i];
  1475. z[zOff + i] = (next << 1) | (c >> 31);
  1476. c = next;
  1477. ++i;
  1478. }
  1479. return c >> 31;
  1480. #endif
  1481. }
  1482. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1483. public static uint ShiftUpBit(int len, Span<uint> z, uint c)
  1484. {
  1485. int i = 0, limit4 = len - 4;
  1486. while (i <= limit4)
  1487. {
  1488. uint next0 = z[i + 0];
  1489. uint next1 = z[i + 1];
  1490. uint next2 = z[i + 2];
  1491. uint next3 = z[i + 3];
  1492. z[i + 0] = (next0 << 1) | (c >> 31);
  1493. z[i + 1] = (next1 << 1) | (next0 >> 31);
  1494. z[i + 2] = (next2 << 1) | (next1 >> 31);
  1495. z[i + 3] = (next3 << 1) | (next2 >> 31);
  1496. c = next3;
  1497. i += 4;
  1498. }
  1499. while (i < len)
  1500. {
  1501. uint next = z[i];
  1502. z[i] = (next << 1) | (c >> 31);
  1503. c = next;
  1504. ++i;
  1505. }
  1506. return c >> 31;
  1507. }
  1508. #endif
  1509. public static uint ShiftUpBit(int len, uint[] x, uint c, uint[] z)
  1510. {
  1511. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1512. return ShiftUpBit(len, x.AsSpan(0, len), c, z.AsSpan(0, len));
  1513. #else
  1514. int i = 0, limit4 = len - 4;
  1515. while (i <= limit4)
  1516. {
  1517. uint next0 = x[i + 0];
  1518. uint next1 = x[i + 1];
  1519. uint next2 = x[i + 2];
  1520. uint next3 = x[i + 3];
  1521. z[i + 0] = (next0 << 1) | (c >> 31);
  1522. z[i + 1] = (next1 << 1) | (next0 >> 31);
  1523. z[i + 2] = (next2 << 1) | (next1 >> 31);
  1524. z[i + 3] = (next3 << 1) | (next2 >> 31);
  1525. c = next3;
  1526. i += 4;
  1527. }
  1528. while (i < len)
  1529. {
  1530. uint next = x[i];
  1531. z[i] = (next << 1) | (c >> 31);
  1532. c = next;
  1533. ++i;
  1534. }
  1535. return c >> 31;
  1536. #endif
  1537. }
  1538. public static uint ShiftUpBit(int len, uint[] x, int xOff, uint c, uint[] z, int zOff)
  1539. {
  1540. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1541. return ShiftUpBit(len, x.AsSpan(xOff, len), c, z.AsSpan(zOff, len));
  1542. #else
  1543. int i = 0, limit4 = len - 4;
  1544. while (i <= limit4)
  1545. {
  1546. uint next0 = x[xOff + i + 0];
  1547. uint next1 = x[xOff + i + 1];
  1548. uint next2 = x[xOff + i + 2];
  1549. uint next3 = x[xOff + i + 3];
  1550. z[zOff + i + 0] = (next0 << 1) | (c >> 31);
  1551. z[zOff + i + 1] = (next1 << 1) | (next0 >> 31);
  1552. z[zOff + i + 2] = (next2 << 1) | (next1 >> 31);
  1553. z[zOff + i + 3] = (next3 << 1) | (next2 >> 31);
  1554. c = next3;
  1555. i += 4;
  1556. }
  1557. while (i < len)
  1558. {
  1559. uint next = x[xOff + i];
  1560. z[zOff + i] = (next << 1) | (c >> 31);
  1561. c = next;
  1562. ++i;
  1563. }
  1564. return c >> 31;
  1565. #endif
  1566. }
  1567. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1568. public static uint ShiftUpBit(int len, ReadOnlySpan<uint> x, uint c, Span<uint> z)
  1569. {
  1570. int i = 0, limit4 = len - 4;
  1571. while (i <= limit4)
  1572. {
  1573. uint next0 = x[i + 0];
  1574. uint next1 = x[i + 1];
  1575. uint next2 = x[i + 2];
  1576. uint next3 = x[i + 3];
  1577. z[i + 0] = (next0 << 1) | (c >> 31);
  1578. z[i + 1] = (next1 << 1) | (next0 >> 31);
  1579. z[i + 2] = (next2 << 1) | (next1 >> 31);
  1580. z[i + 3] = (next3 << 1) | (next2 >> 31);
  1581. c = next3;
  1582. i += 4;
  1583. }
  1584. while (i < len)
  1585. {
  1586. uint next = x[i];
  1587. z[i] = (next << 1) | (c >> 31);
  1588. c = next;
  1589. ++i;
  1590. }
  1591. return c >> 31;
  1592. }
  1593. #endif
  1594. public static ulong ShiftUpBit64(int len, ulong[] x, ulong c, ulong[] z)
  1595. {
  1596. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1597. return ShiftUpBit64(len, x.AsSpan(0, len), c, z.AsSpan(0, len));
  1598. #else
  1599. int i = 0, limit4 = len - 4;
  1600. while (i <= limit4)
  1601. {
  1602. ulong next0 = x[i + 0];
  1603. ulong next1 = x[i + 1];
  1604. ulong next2 = x[i + 2];
  1605. ulong next3 = x[i + 3];
  1606. z[i + 0] = (next0 << 1) | (c >> 63);
  1607. z[i + 1] = (next1 << 1) | (next0 >> 63);
  1608. z[i + 2] = (next2 << 1) | (next1 >> 63);
  1609. z[i + 3] = (next3 << 1) | (next2 >> 63);
  1610. c = next3;
  1611. i += 4;
  1612. }
  1613. while (i < len)
  1614. {
  1615. ulong next = x[i];
  1616. z[i] = (next << 1) | (c >> 63);
  1617. c = next;
  1618. ++i;
  1619. }
  1620. return c >> 63;
  1621. #endif
  1622. }
  1623. public static ulong ShiftUpBit64(int len, ulong[] x, int xOff, ulong c, ulong[] z, int zOff)
  1624. {
  1625. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1626. return ShiftUpBit64(len, x.AsSpan(xOff, len), c, z.AsSpan(zOff, len));
  1627. #else
  1628. int i = 0, limit4 = len - 4;
  1629. while (i <= limit4)
  1630. {
  1631. ulong next0 = x[xOff + i + 0];
  1632. ulong next1 = x[xOff + i + 1];
  1633. ulong next2 = x[xOff + i + 2];
  1634. ulong next3 = x[xOff + i + 3];
  1635. z[zOff + i + 0] = (next0 << 1) | (c >> 63);
  1636. z[zOff + i + 1] = (next1 << 1) | (next0 >> 63);
  1637. z[zOff + i + 2] = (next2 << 1) | (next1 >> 63);
  1638. z[zOff + i + 3] = (next3 << 1) | (next2 >> 63);
  1639. c = next3;
  1640. i += 4;
  1641. }
  1642. while (i < len)
  1643. {
  1644. ulong next = x[xOff + i];
  1645. z[zOff + i] = (next << 1) | (c >> 63);
  1646. c = next;
  1647. ++i;
  1648. }
  1649. return c >> 63;
  1650. #endif
  1651. }
  1652. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1653. public static ulong ShiftUpBit64(int len, ReadOnlySpan<ulong> x, ulong c, Span<ulong> z)
  1654. {
  1655. int i = 0, limit4 = len - 4;
  1656. while (i <= limit4)
  1657. {
  1658. ulong next0 = x[i + 0];
  1659. ulong next1 = x[i + 1];
  1660. ulong next2 = x[i + 2];
  1661. ulong next3 = x[i + 3];
  1662. z[i + 0] = (next0 << 1) | (c >> 63);
  1663. z[i + 1] = (next1 << 1) | (next0 >> 63);
  1664. z[i + 2] = (next2 << 1) | (next1 >> 63);
  1665. z[i + 3] = (next3 << 1) | (next2 >> 63);
  1666. c = next3;
  1667. i += 4;
  1668. }
  1669. while (i < len)
  1670. {
  1671. ulong next = x[i];
  1672. z[i] = (next << 1) | (c >> 63);
  1673. c = next;
  1674. ++i;
  1675. }
  1676. return c >> 63;
  1677. }
  1678. #endif
  1679. public static uint ShiftUpBits(int len, uint[] z, int bits, uint c)
  1680. {
  1681. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1682. return ShiftUpBits(len, z.AsSpan(0, len), bits, c);
  1683. #else
  1684. Debug.Assert(bits > 0 && bits < 32);
  1685. int i = 0, limit4 = len - 4;
  1686. while (i <= limit4)
  1687. {
  1688. uint next0 = z[i + 0];
  1689. uint next1 = z[i + 1];
  1690. uint next2 = z[i + 2];
  1691. uint next3 = z[i + 3];
  1692. z[i + 0] = (next0 << bits) | (c >> -bits);
  1693. z[i + 1] = (next1 << bits) | (next0 >> -bits);
  1694. z[i + 2] = (next2 << bits) | (next1 >> -bits);
  1695. z[i + 3] = (next3 << bits) | (next2 >> -bits);
  1696. c = next3;
  1697. i += 4;
  1698. }
  1699. while (i < len)
  1700. {
  1701. uint next = z[i];
  1702. z[i] = (next << bits) | (c >> -bits);
  1703. c = next;
  1704. ++i;
  1705. }
  1706. return c >> -bits;
  1707. #endif
  1708. }
  1709. public static uint ShiftUpBits(int len, uint[] z, int zOff, int bits, uint c)
  1710. {
  1711. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1712. return ShiftUpBits(len, z.AsSpan(zOff, len), bits, c);
  1713. #else
  1714. Debug.Assert(bits > 0 && bits < 32);
  1715. int i = 0, limit4 = len - 4;
  1716. while (i <= limit4)
  1717. {
  1718. uint next0 = z[zOff + i + 0];
  1719. uint next1 = z[zOff + i + 1];
  1720. uint next2 = z[zOff + i + 2];
  1721. uint next3 = z[zOff + i + 3];
  1722. z[zOff + i + 0] = (next0 << bits) | (c >> -bits);
  1723. z[zOff + i + 1] = (next1 << bits) | (next0 >> -bits);
  1724. z[zOff + i + 2] = (next2 << bits) | (next1 >> -bits);
  1725. z[zOff + i + 3] = (next3 << bits) | (next2 >> -bits);
  1726. c = next3;
  1727. i += 4;
  1728. }
  1729. while (i < len)
  1730. {
  1731. uint next = z[zOff + i];
  1732. z[zOff + i] = (next << bits) | (c >> -bits);
  1733. c = next;
  1734. ++i;
  1735. }
  1736. return c >> -bits;
  1737. #endif
  1738. }
  1739. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1740. public static uint ShiftUpBits(int len, Span<uint> z, int bits, uint c)
  1741. {
  1742. Debug.Assert(bits > 0 && bits < 32);
  1743. int i = 0, limit4 = len - 4;
  1744. while (i <= limit4)
  1745. {
  1746. uint next0 = z[i + 0];
  1747. uint next1 = z[i + 1];
  1748. uint next2 = z[i + 2];
  1749. uint next3 = z[i + 3];
  1750. z[i + 0] = (next0 << bits) | (c >> -bits);
  1751. z[i + 1] = (next1 << bits) | (next0 >> -bits);
  1752. z[i + 2] = (next2 << bits) | (next1 >> -bits);
  1753. z[i + 3] = (next3 << bits) | (next2 >> -bits);
  1754. c = next3;
  1755. i += 4;
  1756. }
  1757. while (i < len)
  1758. {
  1759. uint next = z[i];
  1760. z[i] = (next << bits) | (c >> -bits);
  1761. c = next;
  1762. ++i;
  1763. }
  1764. return c >> -bits;
  1765. }
  1766. #endif
  1767. public static uint ShiftUpBits(int len, uint[] x, int bits, uint c, uint[] z)
  1768. {
  1769. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1770. return ShiftUpBits(len, x.AsSpan(0, len), bits, c, z.AsSpan(0, len));
  1771. #else
  1772. Debug.Assert(bits > 0 && bits < 32);
  1773. int i = 0, limit4 = len - 4;
  1774. while (i <= limit4)
  1775. {
  1776. uint next0 = x[i + 0];
  1777. uint next1 = x[i + 1];
  1778. uint next2 = x[i + 2];
  1779. uint next3 = x[i + 3];
  1780. z[i + 0] = (next0 << bits) | (c >> -bits);
  1781. z[i + 1] = (next1 << bits) | (next0 >> -bits);
  1782. z[i + 2] = (next2 << bits) | (next1 >> -bits);
  1783. z[i + 3] = (next3 << bits) | (next2 >> -bits);
  1784. c = next3;
  1785. i += 4;
  1786. }
  1787. while (i < len)
  1788. {
  1789. uint next = x[i];
  1790. z[i] = (next << bits) | (c >> -bits);
  1791. c = next;
  1792. ++i;
  1793. }
  1794. return c >> -bits;
  1795. #endif
  1796. }
  1797. public static uint ShiftUpBits(int len, uint[] x, int xOff, int bits, uint c, uint[] z, int zOff)
  1798. {
  1799. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1800. return ShiftUpBits(len, x.AsSpan(xOff, len), bits, c, z.AsSpan(zOff, len));
  1801. #else
  1802. Debug.Assert(bits > 0 && bits < 32);
  1803. int i = 0, limit4 = len - 4;
  1804. while (i <= limit4)
  1805. {
  1806. uint next0 = x[xOff + i + 0];
  1807. uint next1 = x[xOff + i + 1];
  1808. uint next2 = x[xOff + i + 2];
  1809. uint next3 = x[xOff + i + 3];
  1810. z[zOff + i + 0] = (next0 << bits) | (c >> -bits);
  1811. z[zOff + i + 1] = (next1 << bits) | (next0 >> -bits);
  1812. z[zOff + i + 2] = (next2 << bits) | (next1 >> -bits);
  1813. z[zOff + i + 3] = (next3 << bits) | (next2 >> -bits);
  1814. c = next3;
  1815. i += 4;
  1816. }
  1817. while (i < len)
  1818. {
  1819. uint next = x[xOff + i];
  1820. z[zOff + i] = (next << bits) | (c >> -bits);
  1821. c = next;
  1822. ++i;
  1823. }
  1824. return c >> -bits;
  1825. #endif
  1826. }
  1827. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1828. public static uint ShiftUpBits(int len, ReadOnlySpan<uint> x, int bits, uint c, Span<uint> z)
  1829. {
  1830. Debug.Assert(bits > 0 && bits < 32);
  1831. int i = 0, limit4 = len - 4;
  1832. while (i <= limit4)
  1833. {
  1834. uint next0 = x[i + 0];
  1835. uint next1 = x[i + 1];
  1836. uint next2 = x[i + 2];
  1837. uint next3 = x[i + 3];
  1838. z[i + 0] = (next0 << bits) | (c >> -bits);
  1839. z[i + 1] = (next1 << bits) | (next0 >> -bits);
  1840. z[i + 2] = (next2 << bits) | (next1 >> -bits);
  1841. z[i + 3] = (next3 << bits) | (next2 >> -bits);
  1842. c = next3;
  1843. i += 4;
  1844. }
  1845. while (i < len)
  1846. {
  1847. uint next = x[i];
  1848. z[i] = (next << bits) | (c >> -bits);
  1849. c = next;
  1850. ++i;
  1851. }
  1852. return c >> -bits;
  1853. }
  1854. #endif
  1855. public static ulong ShiftUpBits64(int len, ulong[] z, int bits, ulong c)
  1856. {
  1857. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1858. return ShiftUpBits64(len, z.AsSpan(0, len), bits, c);
  1859. #else
  1860. Debug.Assert(bits > 0 && bits < 64);
  1861. int i = 0, limit4 = len - 4;
  1862. while (i <= limit4)
  1863. {
  1864. ulong next0 = z[i + 0];
  1865. ulong next1 = z[i + 1];
  1866. ulong next2 = z[i + 2];
  1867. ulong next3 = z[i + 3];
  1868. z[i + 0] = (next0 << bits) | (c >> -bits);
  1869. z[i + 1] = (next1 << bits) | (next0 >> -bits);
  1870. z[i + 2] = (next2 << bits) | (next1 >> -bits);
  1871. z[i + 3] = (next3 << bits) | (next2 >> -bits);
  1872. c = next3;
  1873. i += 4;
  1874. }
  1875. while (i < len)
  1876. {
  1877. ulong next = z[i];
  1878. z[i] = (next << bits) | (c >> -bits);
  1879. c = next;
  1880. ++i;
  1881. }
  1882. return c >> -bits;
  1883. #endif
  1884. }
  1885. public static ulong ShiftUpBits64(int len, ulong[] z, int zOff, int bits, ulong c)
  1886. {
  1887. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1888. return ShiftUpBits64(len, z.AsSpan(zOff, len), bits, c);
  1889. #else
  1890. Debug.Assert(bits > 0 && bits < 64);
  1891. int i = 0, limit4 = len - 4;
  1892. while (i <= limit4)
  1893. {
  1894. ulong next0 = z[zOff + i + 0];
  1895. ulong next1 = z[zOff + i + 1];
  1896. ulong next2 = z[zOff + i + 2];
  1897. ulong next3 = z[zOff + i + 3];
  1898. z[zOff + i + 0] = (next0 << bits) | (c >> -bits);
  1899. z[zOff + i + 1] = (next1 << bits) | (next0 >> -bits);
  1900. z[zOff + i + 2] = (next2 << bits) | (next1 >> -bits);
  1901. z[zOff + i + 3] = (next3 << bits) | (next2 >> -bits);
  1902. c = next3;
  1903. i += 4;
  1904. }
  1905. while (i < len)
  1906. {
  1907. ulong next = z[zOff + i];
  1908. z[zOff + i] = (next << bits) | (c >> -bits);
  1909. c = next;
  1910. ++i;
  1911. }
  1912. return c >> -bits;
  1913. #endif
  1914. }
  1915. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1916. public static ulong ShiftUpBits64(int len, Span<ulong> z, int bits, ulong c)
  1917. {
  1918. Debug.Assert(bits > 0 && bits < 64);
  1919. int i = 0, limit4 = len - 4;
  1920. while (i <= limit4)
  1921. {
  1922. ulong next0 = z[i + 0];
  1923. ulong next1 = z[i + 1];
  1924. ulong next2 = z[i + 2];
  1925. ulong next3 = z[i + 3];
  1926. z[i + 0] = (next0 << bits) | (c >> -bits);
  1927. z[i + 1] = (next1 << bits) | (next0 >> -bits);
  1928. z[i + 2] = (next2 << bits) | (next1 >> -bits);
  1929. z[i + 3] = (next3 << bits) | (next2 >> -bits);
  1930. c = next3;
  1931. i += 4;
  1932. }
  1933. while (i < len)
  1934. {
  1935. ulong next = z[i];
  1936. z[i] = (next << bits) | (c >> -bits);
  1937. c = next;
  1938. ++i;
  1939. }
  1940. return c >> -bits;
  1941. }
  1942. #endif
  1943. public static ulong ShiftUpBits64(int len, ulong[] x, int bits, ulong c, ulong[] z)
  1944. {
  1945. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1946. return ShiftUpBits64(len, x.AsSpan(0, len), bits, c, z.AsSpan(0, len));
  1947. #else
  1948. Debug.Assert(bits > 0 && bits < 64);
  1949. int i = 0, limit4 = len - 4;
  1950. while (i <= limit4)
  1951. {
  1952. ulong next0 = x[i + 0];
  1953. ulong next1 = x[i + 1];
  1954. ulong next2 = x[i + 2];
  1955. ulong next3 = x[i + 3];
  1956. z[i + 0] = (next0 << bits) | (c >> -bits);
  1957. z[i + 1] = (next1 << bits) | (next0 >> -bits);
  1958. z[i + 2] = (next2 << bits) | (next1 >> -bits);
  1959. z[i + 3] = (next3 << bits) | (next2 >> -bits);
  1960. c = next3;
  1961. i += 4;
  1962. }
  1963. while (i < len)
  1964. {
  1965. ulong next = x[i];
  1966. z[i] = (next << bits) | (c >> -bits);
  1967. c = next;
  1968. ++i;
  1969. }
  1970. return c >> -bits;
  1971. #endif
  1972. }
  1973. public static ulong ShiftUpBits64(int len, ulong[] x, int xOff, int bits, ulong c, ulong[] z, int zOff)
  1974. {
  1975. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  1976. return ShiftUpBits64(len, x.AsSpan(xOff, len), bits, c, z.AsSpan(zOff, len));
  1977. #else
  1978. Debug.Assert(bits > 0 && bits < 64);
  1979. int i = 0, limit4 = len - 4;
  1980. while (i <= limit4)
  1981. {
  1982. ulong next0 = x[xOff + i + 0];
  1983. ulong next1 = x[xOff + i + 1];
  1984. ulong next2 = x[xOff + i + 2];
  1985. ulong next3 = x[xOff + i + 3];
  1986. z[zOff + i + 0] = (next0 << bits) | (c >> -bits);
  1987. z[zOff + i + 1] = (next1 << bits) | (next0 >> -bits);
  1988. z[zOff + i + 2] = (next2 << bits) | (next1 >> -bits);
  1989. z[zOff + i + 3] = (next3 << bits) | (next2 >> -bits);
  1990. c = next3;
  1991. i += 4;
  1992. }
  1993. while (i < len)
  1994. {
  1995. ulong next = x[xOff + i];
  1996. z[zOff + i] = (next << bits) | (c >> -bits);
  1997. c = next;
  1998. ++i;
  1999. }
  2000. return c >> -bits;
  2001. #endif
  2002. }
  2003. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2004. public static ulong ShiftUpBits64(int len, ReadOnlySpan<ulong> x, int bits, ulong c, Span<ulong> z)
  2005. {
  2006. Debug.Assert(bits > 0 && bits < 64);
  2007. int i = 0, limit4 = len - 4;
  2008. while (i <= limit4)
  2009. {
  2010. ulong next0 = x[i + 0];
  2011. ulong next1 = x[i + 1];
  2012. ulong next2 = x[i + 2];
  2013. ulong next3 = x[i + 3];
  2014. z[i + 0] = (next0 << bits) | (c >> -bits);
  2015. z[i + 1] = (next1 << bits) | (next0 >> -bits);
  2016. z[i + 2] = (next2 << bits) | (next1 >> -bits);
  2017. z[i + 3] = (next3 << bits) | (next2 >> -bits);
  2018. c = next3;
  2019. i += 4;
  2020. }
  2021. while (i < len)
  2022. {
  2023. ulong next = x[i];
  2024. z[i] = (next << bits) | (c >> -bits);
  2025. c = next;
  2026. ++i;
  2027. }
  2028. return c >> -bits;
  2029. }
  2030. #endif
  2031. public static void Square(int len, uint[] x, uint[] zz)
  2032. {
  2033. int extLen = len << 1;
  2034. uint c = 0;
  2035. int j = len, k = extLen;
  2036. do
  2037. {
  2038. ulong xVal = (ulong)x[--j];
  2039. ulong p = xVal * xVal;
  2040. zz[--k] = (c << 31) | (uint)(p >> 33);
  2041. zz[--k] = (uint)(p >> 1);
  2042. c = (uint)p;
  2043. }
  2044. while (j > 0);
  2045. ulong d = 0UL;
  2046. int zzPos = 2;
  2047. for (int i = 1; i < len; ++i)
  2048. {
  2049. d += SquareWordAddTo(x, i, zz);
  2050. d += zz[zzPos];
  2051. zz[zzPos++] = (uint)d; d >>= 32;
  2052. d += zz[zzPos];
  2053. zz[zzPos++] = (uint)d; d >>= 32;
  2054. }
  2055. Debug.Assert(0UL == d);
  2056. ShiftUpBit(extLen, zz, x[0] << 31);
  2057. }
  2058. public static void Square(int len, uint[] x, int xOff, uint[] zz, int zzOff)
  2059. {
  2060. int extLen = len << 1;
  2061. uint c = 0;
  2062. int j = len, k = extLen;
  2063. do
  2064. {
  2065. ulong xVal = (ulong)x[xOff + --j];
  2066. ulong p = xVal * xVal;
  2067. zz[zzOff + --k] = (c << 31) | (uint)(p >> 33);
  2068. zz[zzOff + --k] = (uint)(p >> 1);
  2069. c = (uint)p;
  2070. }
  2071. while (j > 0);
  2072. ulong d = 0UL;
  2073. int zzPos = zzOff + 2;
  2074. for (int i = 1; i < len; ++i)
  2075. {
  2076. d += SquareWordAddTo(x, xOff, i, zz, zzOff);
  2077. d += zz[zzPos];
  2078. zz[zzPos++] = (uint)d; d >>= 32;
  2079. d += zz[zzPos];
  2080. zz[zzPos++] = (uint)d; d >>= 32;
  2081. }
  2082. Debug.Assert(0UL == d);
  2083. ShiftUpBit(extLen, zz, zzOff, x[xOff] << 31);
  2084. }
  2085. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2086. public static void Square(int len, ReadOnlySpan<uint> x, Span<uint> zz)
  2087. {
  2088. int extLen = len << 1;
  2089. uint c = 0;
  2090. int j = len, k = extLen;
  2091. do
  2092. {
  2093. ulong xVal = (ulong)x[--j];
  2094. ulong p = xVal * xVal;
  2095. zz[--k] = (c << 31) | (uint)(p >> 33);
  2096. zz[--k] = (uint)(p >> 1);
  2097. c = (uint)p;
  2098. }
  2099. while (j > 0);
  2100. ulong d = 0UL;
  2101. int zzPos = 2;
  2102. for (int i = 1; i < len; ++i)
  2103. {
  2104. d += SquareWordAddTo(x, i, zz);
  2105. d += zz[zzPos];
  2106. zz[zzPos++] = (uint)d; d >>= 32;
  2107. d += zz[zzPos];
  2108. zz[zzPos++] = (uint)d; d >>= 32;
  2109. }
  2110. Debug.Assert(0UL == d);
  2111. ShiftUpBit(extLen, zz, x[0] << 31);
  2112. }
  2113. #endif
  2114. public static uint SquareWordAddTo(uint[] x, int xPos, uint[] z)
  2115. {
  2116. ulong c = 0, xVal = (ulong)x[xPos];
  2117. int i = 0;
  2118. do
  2119. {
  2120. c += xVal * x[i] + z[xPos + i];
  2121. z[xPos + i] = (uint)c;
  2122. c >>= 32;
  2123. }
  2124. while (++i < xPos);
  2125. return (uint)c;
  2126. }
  2127. public static uint SquareWordAddTo(uint[] x, int xOff, int xPos, uint[] z, int zOff)
  2128. {
  2129. ulong c = 0, xVal = (ulong)x[xOff + xPos];
  2130. int i = 0;
  2131. do
  2132. {
  2133. c += xVal * (x[xOff + i] & M) + (z[xPos + zOff] & M);
  2134. z[xPos + zOff] = (uint)c;
  2135. c >>= 32;
  2136. ++zOff;
  2137. }
  2138. while (++i < xPos);
  2139. return (uint)c;
  2140. }
  2141. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2142. public static uint SquareWordAddTo(ReadOnlySpan<uint> x, int xPos, Span<uint> z)
  2143. {
  2144. ulong c = 0, xVal = x[xPos];
  2145. int i = 0;
  2146. do
  2147. {
  2148. c += xVal * x[i] + z[xPos + i];
  2149. z[xPos + i] = (uint)c;
  2150. c >>= 32;
  2151. }
  2152. while (++i < xPos);
  2153. return (uint)c;
  2154. }
  2155. #endif
  2156. public static int Sub(int len, uint[] x, uint[] y, uint[] z)
  2157. {
  2158. long c = 0;
  2159. for (int i = 0; i < len; ++i)
  2160. {
  2161. c += (long)x[i] - y[i];
  2162. z[i] = (uint)c;
  2163. c >>= 32;
  2164. }
  2165. return (int)c;
  2166. }
  2167. public static int Sub(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  2168. {
  2169. long c = 0;
  2170. for (int i = 0; i < len; ++i)
  2171. {
  2172. c += (long)x[xOff + i] - y[yOff + i];
  2173. z[zOff + i] = (uint)c;
  2174. c >>= 32;
  2175. }
  2176. return (int)c;
  2177. }
  2178. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2179. public static int Sub(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> z)
  2180. {
  2181. long c = 0;
  2182. for (int i = 0; i < len; ++i)
  2183. {
  2184. c += (long)x[i] - y[i];
  2185. z[i] = (uint)c;
  2186. c >>= 32;
  2187. }
  2188. return (int)c;
  2189. }
  2190. #endif
  2191. public static int Sub33At(int len, uint x, uint[] z, int zPos)
  2192. {
  2193. Debug.Assert(zPos <= (len - 2));
  2194. long c = (long)z[zPos + 0] - x;
  2195. z[zPos + 0] = (uint)c;
  2196. c >>= 32;
  2197. c += (long)z[zPos + 1] - 1;
  2198. z[zPos + 1] = (uint)c;
  2199. c >>= 32;
  2200. return c == 0 ? 0 : DecAt(len, z, zPos + 2);
  2201. }
  2202. public static int Sub33At(int len, uint x, uint[] z, int zOff, int zPos)
  2203. {
  2204. Debug.Assert(zPos <= (len - 2));
  2205. long c = (long)z[zOff + zPos] - x;
  2206. z[zOff + zPos] = (uint)c;
  2207. c >>= 32;
  2208. c += (long)z[zOff + zPos + 1] - 1;
  2209. z[zOff + zPos + 1] = (uint)c;
  2210. c >>= 32;
  2211. return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 2);
  2212. }
  2213. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2214. public static int Sub33At(int len, uint x, Span<uint> z, int zPos)
  2215. {
  2216. Debug.Assert(zPos <= (len - 2));
  2217. long c = (long)z[zPos + 0] - x;
  2218. z[zPos + 0] = (uint)c;
  2219. c >>= 32;
  2220. c += (long)z[zPos + 1] - 1;
  2221. z[zPos + 1] = (uint)c;
  2222. c >>= 32;
  2223. return c == 0 ? 0 : DecAt(len, z, zPos + 2);
  2224. }
  2225. #endif
  2226. public static int Sub33From(int len, uint x, uint[] z)
  2227. {
  2228. long c = (long)z[0] - x;
  2229. z[0] = (uint)c;
  2230. c >>= 32;
  2231. c += (long)z[1] - 1;
  2232. z[1] = (uint)c;
  2233. c >>= 32;
  2234. return c == 0 ? 0 : DecAt(len, z, 2);
  2235. }
  2236. public static int Sub33From(int len, uint x, uint[] z, int zOff)
  2237. {
  2238. long c = (long)z[zOff + 0] - x;
  2239. z[zOff + 0] = (uint)c;
  2240. c >>= 32;
  2241. c += (long)z[zOff + 1] - 1;
  2242. z[zOff + 1] = (uint)c;
  2243. c >>= 32;
  2244. return c == 0 ? 0 : DecAt(len, z, zOff, 2);
  2245. }
  2246. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2247. public static int Sub33From(int len, uint x, Span<uint> z)
  2248. {
  2249. long c = (long)z[0] - x;
  2250. z[0] = (uint)c;
  2251. c >>= 32;
  2252. c += (long)z[1] - 1;
  2253. z[1] = (uint)c;
  2254. c >>= 32;
  2255. return c == 0 ? 0 : DecAt(len, z, 2);
  2256. }
  2257. #endif
  2258. public static int SubBothFrom(int len, uint[] x, uint[] y, uint[] z)
  2259. {
  2260. long c = 0;
  2261. for (int i = 0; i < len; ++i)
  2262. {
  2263. c += (long)z[i] - x[i] - y[i];
  2264. z[i] = (uint)c;
  2265. c >>= 32;
  2266. }
  2267. return (int)c;
  2268. }
  2269. public static int SubBothFrom(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  2270. {
  2271. long c = 0;
  2272. for (int i = 0; i < len; ++i)
  2273. {
  2274. c += (long)z[zOff + i] - x[xOff + i] - y[yOff + i];
  2275. z[zOff + i] = (uint)c;
  2276. c >>= 32;
  2277. }
  2278. return (int)c;
  2279. }
  2280. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2281. public static int SubBothFrom(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> z)
  2282. {
  2283. long c = 0;
  2284. for (int i = 0; i < len; ++i)
  2285. {
  2286. c += (long)z[i] - x[i] - y[i];
  2287. z[i] = (uint)c;
  2288. c >>= 32;
  2289. }
  2290. return (int)c;
  2291. }
  2292. #endif
  2293. public static int SubDWordAt(int len, ulong x, uint[] z, int zPos)
  2294. {
  2295. Debug.Assert(zPos <= (len - 2));
  2296. long c = z[zPos + 0] - (long)(x & M);
  2297. z[zPos + 0] = (uint)c;
  2298. c >>= 32;
  2299. c += z[zPos + 1] - (long)(x >> 32);
  2300. z[zPos + 1] = (uint)c;
  2301. c >>= 32;
  2302. return c == 0 ? 0 : DecAt(len, z, zPos + 2);
  2303. }
  2304. public static int SubDWordAt(int len, ulong x, uint[] z, int zOff, int zPos)
  2305. {
  2306. Debug.Assert(zPos <= (len - 2));
  2307. long c = z[zOff + zPos] - (long)(x & M);
  2308. z[zOff + zPos] = (uint)c;
  2309. c >>= 32;
  2310. c += z[zOff + zPos + 1] - (long)(x >> 32);
  2311. z[zOff + zPos + 1] = (uint)c;
  2312. c >>= 32;
  2313. return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 2);
  2314. }
  2315. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2316. public static int SubDWordAt(int len, ulong x, Span<uint> z, int zPos)
  2317. {
  2318. Debug.Assert(zPos <= (len - 2));
  2319. long c = z[zPos + 0] - (long)(x & M);
  2320. z[zPos + 0] = (uint)c;
  2321. c >>= 32;
  2322. c += z[zPos + 1] - (long)(x >> 32);
  2323. z[zPos + 1] = (uint)c;
  2324. c >>= 32;
  2325. return c == 0 ? 0 : DecAt(len, z, zPos + 2);
  2326. }
  2327. #endif
  2328. public static int SubDWordFrom(int len, ulong x, uint[] z)
  2329. {
  2330. long c = z[0] - (long)(x & M);
  2331. z[0] = (uint)c;
  2332. c >>= 32;
  2333. c += z[1] - (long)(x >> 32);
  2334. z[1] = (uint)c;
  2335. c >>= 32;
  2336. return c == 0 ? 0 : DecAt(len, z, 2);
  2337. }
  2338. public static int SubDWordFrom(int len, ulong x, uint[] z, int zOff)
  2339. {
  2340. long c = z[zOff + 0] - (long)(x & M);
  2341. z[zOff + 0] = (uint)c;
  2342. c >>= 32;
  2343. c += z[zOff + 1] - (long)(x >> 32);
  2344. z[zOff + 1] = (uint)c;
  2345. c >>= 32;
  2346. return c == 0 ? 0 : DecAt(len, z, zOff, 2);
  2347. }
  2348. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2349. public static int SubDWordFrom(int len, ulong x, Span<uint> z)
  2350. {
  2351. long c = z[0] - (long)(x & M);
  2352. z[0] = (uint)c;
  2353. c >>= 32;
  2354. c += z[1] - (long)(x >> 32);
  2355. z[1] = (uint)c;
  2356. c >>= 32;
  2357. return c == 0 ? 0 : DecAt(len, z, 2);
  2358. }
  2359. #endif
  2360. public static int SubFrom(int len, uint[] x, uint[] z)
  2361. {
  2362. long c = 0;
  2363. for (int i = 0; i < len; ++i)
  2364. {
  2365. c += (long)z[i] - x[i];
  2366. z[i] = (uint)c;
  2367. c >>= 32;
  2368. }
  2369. return (int)c;
  2370. }
  2371. public static int SubFrom(int len, uint[] x, int xOff, uint[] z, int zOff)
  2372. {
  2373. long c = 0;
  2374. for (int i = 0; i < len; ++i)
  2375. {
  2376. c += (long)z[zOff + i] - x[xOff + i];
  2377. z[zOff + i] = (uint)c;
  2378. c >>= 32;
  2379. }
  2380. return (int)c;
  2381. }
  2382. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2383. public static int SubFrom(int len, ReadOnlySpan<uint> x, Span<uint> z)
  2384. {
  2385. long c = 0;
  2386. for (int i = 0; i < len; ++i)
  2387. {
  2388. c += (long)z[i] - x[i];
  2389. z[i] = (uint)c;
  2390. c >>= 32;
  2391. }
  2392. return (int)c;
  2393. }
  2394. #endif
  2395. public static int SubWordAt(int len, uint x, uint[] z, int zPos)
  2396. {
  2397. Debug.Assert(zPos <= (len - 1));
  2398. long c = (long)z[zPos] - x;
  2399. z[zPos] = (uint)c;
  2400. c >>= 32;
  2401. return c == 0 ? 0 : DecAt(len, z, zPos + 1);
  2402. }
  2403. public static int SubWordAt(int len, uint x, uint[] z, int zOff, int zPos)
  2404. {
  2405. Debug.Assert(zPos <= (len - 1));
  2406. long c = (long)z[zOff + zPos] - x;
  2407. z[zOff + zPos] = (uint)c;
  2408. c >>= 32;
  2409. return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 1);
  2410. }
  2411. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2412. public static int SubWordAt(int len, uint x, Span<uint> z, int zPos)
  2413. {
  2414. Debug.Assert(zPos <= (len - 1));
  2415. long c = (long)z[zPos] - x;
  2416. z[zPos] = (uint)c;
  2417. c >>= 32;
  2418. return c == 0 ? 0 : DecAt(len, z, zPos + 1);
  2419. }
  2420. #endif
  2421. public static int SubWordFrom(int len, uint x, uint[] z)
  2422. {
  2423. long c = (long)z[0] - x;
  2424. z[0] = (uint)c;
  2425. c >>= 32;
  2426. return c == 0 ? 0 : DecAt(len, z, 1);
  2427. }
  2428. public static int SubWordFrom(int len, uint x, uint[] z, int zOff)
  2429. {
  2430. long c = (long)z[zOff + 0] - x;
  2431. z[zOff + 0] = (uint)c;
  2432. c >>= 32;
  2433. return c == 0 ? 0 : DecAt(len, z, zOff, 1);
  2434. }
  2435. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2436. public static int SubWordFrom(int len, uint x, Span<uint> z)
  2437. {
  2438. long c = (long)z[0] - x;
  2439. z[0] = (uint)c;
  2440. c >>= 32;
  2441. return c == 0 ? 0 : DecAt(len, z, 1);
  2442. }
  2443. #endif
  2444. public static BigInteger ToBigInteger(int len, uint[] x)
  2445. {
  2446. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2447. return ToBigInteger(len, x.AsSpan());
  2448. #else
  2449. byte[] bs = new byte[len << 2];
  2450. int xPos = len, bsPos = 0;
  2451. while (--xPos >= 0)
  2452. {
  2453. Pack.UInt32_To_BE(x[xPos], bs, bsPos);
  2454. bsPos += 4;
  2455. }
  2456. return new BigInteger(1, bs);
  2457. #endif
  2458. }
  2459. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2460. public static BigInteger ToBigInteger(int len, ReadOnlySpan<uint> x)
  2461. {
  2462. int bsLen = len << 2;
  2463. Span<byte> bs = bsLen <= 512
  2464. ? stackalloc byte[bsLen]
  2465. : new byte[bsLen];
  2466. int xPos = len;
  2467. Span<byte> t = bs;
  2468. while (--xPos >= 0)
  2469. {
  2470. Pack.UInt32_To_BE(x[xPos], t);
  2471. t = t[4..];
  2472. }
  2473. return new BigInteger(1, bs);
  2474. }
  2475. #endif
  2476. public static void Xor(int len, uint[] x, uint[] y, uint[] z)
  2477. {
  2478. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2479. Xor(len, x.AsSpan(0, len), y.AsSpan(0, len), z.AsSpan(0, len));
  2480. #else
  2481. for (int i = 0; i < len; ++i)
  2482. {
  2483. z[i] = x[i] ^ y[i];
  2484. }
  2485. #endif
  2486. }
  2487. public static void Xor(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  2488. {
  2489. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2490. Xor(len, x.AsSpan(xOff, len), y.AsSpan(yOff, len), z.AsSpan(zOff, len));
  2491. #else
  2492. for (int i = 0; i < len; ++i)
  2493. {
  2494. z[zOff + i] = x[xOff + i] ^ y[yOff + i];
  2495. }
  2496. #endif
  2497. }
  2498. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2499. public static void Xor(int len, ReadOnlySpan<uint> x, ReadOnlySpan<uint> y, Span<uint> z)
  2500. {
  2501. int i = 0, limit16 = len - 16;
  2502. while (i <= limit16)
  2503. {
  2504. Nat512.Xor(x[i..], y[i..], z[i..]);
  2505. i += 16;
  2506. }
  2507. while (i < len)
  2508. {
  2509. z[i] = x[i] ^ y[i];
  2510. ++i;
  2511. }
  2512. }
  2513. #endif
  2514. public static void Xor64(int len, ulong[] x, ulong[] y, ulong[] z)
  2515. {
  2516. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2517. Xor64(len, x.AsSpan(0, len), y.AsSpan(0, len), z.AsSpan(0, len));
  2518. #else
  2519. for (int i = 0; i < len; ++i)
  2520. {
  2521. z[i] = x[i] ^ y[i];
  2522. }
  2523. #endif
  2524. }
  2525. public static void Xor64(int len, ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff)
  2526. {
  2527. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2528. Xor64(len, x.AsSpan(xOff, len), y.AsSpan(yOff, len), z.AsSpan(zOff, len));
  2529. #else
  2530. for (int i = 0; i < len; ++i)
  2531. {
  2532. z[zOff + i] = x[xOff + i] ^ y[yOff + i];
  2533. }
  2534. #endif
  2535. }
  2536. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2537. public static void Xor64(int len, ReadOnlySpan<ulong> x, ReadOnlySpan<ulong> y, Span<ulong> z)
  2538. {
  2539. int i = 0, limit8 = len - 8;
  2540. while (i <= limit8)
  2541. {
  2542. Nat512.Xor64(x[i..], y[i..], z[i..]);
  2543. i += 8;
  2544. }
  2545. while (i < len)
  2546. {
  2547. z[i] = x[i] ^ y[i];
  2548. ++i;
  2549. }
  2550. }
  2551. #endif
  2552. public static void XorTo(int len, uint[] x, uint[] z)
  2553. {
  2554. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2555. XorTo(len, x.AsSpan(0, len), z.AsSpan(0, len));
  2556. #else
  2557. for (int i = 0; i < len; ++i)
  2558. {
  2559. z[i] ^= x[i];
  2560. }
  2561. #endif
  2562. }
  2563. public static void XorTo(int len, uint[] x, int xOff, uint[] z, int zOff)
  2564. {
  2565. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2566. XorTo(len, x.AsSpan(xOff, len), z.AsSpan(zOff, len));
  2567. #else
  2568. for (int i = 0; i < len; ++i)
  2569. {
  2570. z[zOff + i] ^= x[xOff + i];
  2571. }
  2572. #endif
  2573. }
  2574. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2575. public static void XorTo(int len, ReadOnlySpan<uint> x, Span<uint> z)
  2576. {
  2577. int i = 0, limit16 = len - 16;
  2578. while (i <= limit16)
  2579. {
  2580. Nat512.XorTo(x[i..], z[i..]);
  2581. i += 16;
  2582. }
  2583. while (i < len)
  2584. {
  2585. z[i] ^= x[i];
  2586. ++i;
  2587. }
  2588. }
  2589. #endif
  2590. public static void XorTo64(int len, ulong[] x, ulong[] z)
  2591. {
  2592. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2593. XorTo64(len, x.AsSpan(0, len), z.AsSpan(0, len));
  2594. #else
  2595. for (int i = 0; i < len; ++i)
  2596. {
  2597. z[i] ^= x[i];
  2598. }
  2599. #endif
  2600. }
  2601. public static void XorTo64(int len, ulong[] x, int xOff, ulong[] z, int zOff)
  2602. {
  2603. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2604. XorTo64(len, x.AsSpan(xOff, len), z.AsSpan(zOff, len));
  2605. #else
  2606. for (int i = 0; i < len; ++i)
  2607. {
  2608. z[zOff + i] ^= x[xOff + i];
  2609. }
  2610. #endif
  2611. }
  2612. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2613. public static void XorTo64(int len, ReadOnlySpan<ulong> x, Span<ulong> z)
  2614. {
  2615. int i = 0, limit8 = len - 8;
  2616. while (i <= limit8)
  2617. {
  2618. Nat512.XorTo64(x[i..], z[i..]);
  2619. i += 8;
  2620. }
  2621. while (i < len)
  2622. {
  2623. z[i] ^= x[i];
  2624. ++i;
  2625. }
  2626. }
  2627. #endif
  2628. public static void Zero(int len, uint[] z)
  2629. {
  2630. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2631. z.AsSpan(0, len).Fill(0U);
  2632. #else
  2633. for (int i = 0; i < len; ++i)
  2634. {
  2635. z[i] = 0U;
  2636. }
  2637. #endif
  2638. }
  2639. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2640. public static void Zero(int len, Span<uint> z)
  2641. {
  2642. z[..len].Fill(0U);
  2643. }
  2644. #endif
  2645. public static void Zero64(int len, ulong[] z)
  2646. {
  2647. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2648. z.AsSpan(0, len).Fill(0UL);
  2649. #else
  2650. for (int i = 0; i < len; ++i)
  2651. {
  2652. z[i] = 0UL;
  2653. }
  2654. #endif
  2655. }
  2656. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  2657. public static void Zero64(int len, Span<ulong> z)
  2658. {
  2659. z[..len].Fill(0UL);
  2660. }
  2661. #endif
  2662. }
  2663. }
  2664. #pragma warning restore
  2665. #endif