| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956 | #pragma warning disable SA1028 // Code should not contain trailing whitespace//// System.Numerics.BigInteger//// Authors:// Rodrigo Kumpera (rkumpera@novell.com)// Marek Safar  <marek.safar@gmail.com>//// Copyright (C) 2010 Novell, Inc (http://www.novell.com)// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com)//// Permission is hereby granted, free of charge, to any person obtaining// a copy of this software and associated documentation files (the// "Software"), to deal in the Software without restriction, including// without limitation the rights to use, copy, modify, merge, publish,// distribute, sublicense, and/or sell copies of the Software, and to// permit persons to whom the Software is furnished to do so, subject to// the following conditions:// // The above copyright notice and this permission notice shall be// included in all copies or substantial portions of the Software.// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.//// A big chuck of code comes the DLR (as hosted in http://ironpython.codeplex.com), // which has the following License:///* ****************************************************************************** Copyright (c) Microsoft Corporation.** This source code is subject to terms and conditions of the Microsoft Public License. A* copy of the license can be found in the License.html file at the root of this distribution. If* you cannot locate the Microsoft Public License, please send an email to* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound* by the terms of the Microsoft Public License.** You must not remove this notice, or any other, from this software.*** ***************************************************************************/#pragma warning restore SA1028 // Code should not contain trailing whitespaceusing System;using System.Collections.Generic;using System.Globalization;using Renci.SshNet.Abstractions;/* * Optimization: * - Have proper popcount function for IsPowerOfTwo * - Use unsafe ops to avoid bounds check * - CoreAdd could avoid some resizes by checking for equal sized array that top overflow * - For bitwise operators, hoist the conditionals out of their main loop * - Optimize BitScanBackward * - Use a carry variable to make shift opts do half the number of array ops. * -Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers */namespace Renci.SshNet.Common{    /// <summary>    /// Represents an arbitrarily large signed integer.    /// </summary>    public struct BigInteger : IComparable, IFormattable, IComparable<BigInteger>, IEquatable<BigInteger>    {        private const ulong Base = 0x100000000;        private const int Bias = 1075;        private const int DecimalSignMask = unchecked((int)0x80000000);        private static readonly BigInteger ZeroSingleton = new BigInteger(0);        private static readonly BigInteger OneSingleton = new BigInteger(1);        private static readonly BigInteger MinusOneSingleton = new BigInteger(-1);        // LSB on [0]        private readonly uint[] _data;        private readonly short _sign;        #region SSH.NET additions        /// <summary>        /// Gets number of bits used by the number.        /// </summary>        /// <value>        /// The number of the bit used.        /// </value>        public readonly int BitLength        {            get            {                if (_sign == 0)                {                    return 0;                }                var msbIndex = _data.Length - 1;                while (_data[msbIndex] == 0)                {                    msbIndex--;                }                var msbBitCount = BitScanBackward(_data[msbIndex]) + 1;                return (msbIndex * 4 * 8) + msbBitCount + ((_sign > 0) ? 0 : 1);            }        }        /// <summary>        /// Mods the inverse.        /// </summary>        /// <param name="bi">The bi.</param>        /// <param name="modulus">The modulus.</param>        /// <returns>        /// Modulus inverted number.        /// </returns>        public static BigInteger ModInverse(BigInteger bi, BigInteger modulus)        {            BigInteger a = modulus, b = bi % modulus;            BigInteger p0 = 0, p1 = 1;            while (!b.IsZero)            {                if (b.IsOne)                {                    return p1;                }                p0 += (a / b) * p1;                a %= b;                if (a.IsZero)                {                    break;                }                if (a.IsOne)                {                    return modulus - p0;                }                p1 += (b / a) * p0;                b %= a;            }            return 0;        }        /// <summary>        /// Returns positive remainder that results from division with two specified <see cref="BigInteger"/> values.        /// </summary>        /// <param name="dividend">The value to be divided.</param>        /// <param name="divisor">The value to divide by.</param>        /// <returns>        /// Positive remainder that results from the division.        /// </returns>        public static BigInteger PositiveMod(BigInteger dividend, BigInteger divisor)        {            var result = dividend % divisor;            if (result < 0)            {                result += divisor;            }            return result;        }        /// <summary>        /// Generates a new, random <see cref="BigInteger"/> of the specified length.        /// </summary>        /// <param name="bitLength">The number of bits for the new number.</param>        /// <returns>A random number of the specified length.</returns>        public static BigInteger Random(int bitLength)        {            var bytesArray = CryptoAbstraction.GenerateRandom((bitLength / 8) + (((bitLength % 8) > 0) ? 1 : 0));            bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F); // Ensure not a negative value            return new BigInteger(bytesArray);        }        #endregion SSH.NET additions        private BigInteger(short sign, uint[] data)        {            _sign = sign;            _data = data;        }        /// <summary>        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a 32-bit signed integer value.        /// </summary>        /// <param name="value">A 32-bit signed integer.</param>        public BigInteger(int value)        {            if (value == 0)            {                _sign = 0;                _data = null;            }            else if (value > 0)            {                _sign = 1;                _data = new[] { (uint)value };            }            else            {                _sign = -1;                _data = new[] { (uint)-value };            }        }        /// <summary>        /// Initializes a new instance of the <see cref="BigInteger"/> structure using an unsigned 32-bit integer value.        /// </summary>        /// <param name="value">An unsigned 32-bit integer value.</param>        [CLSCompliant(false)]        public BigInteger(uint value)        {            if (value == 0)            {                _sign = 0;                _data = null;            }            else            {                _sign = 1;                _data = new[] { value };            }        }        /// <summary>        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a 64-bit signed integer value.        /// </summary>        /// <param name="value">A 64-bit signed integer.</param>        public BigInteger(long value)        {            if (value == 0)            {                _sign = 0;                _data = null;            }            else if (value > 0)            {                _sign = 1;                var low = (uint)value;                var high = (uint)(value >> 32);                _data = new uint[high != 0 ? 2 : 1];                _data[0] = low;                if (high != 0)                {                    _data[1] = high;                }            }            else            {                _sign = -1;                value = -value;                var low = (uint)value;                var high = (uint)((ulong)value >> 32);                _data = new uint[high != 0 ? 2 : 1];                _data[0] = low;                if (high != 0)                {                    _data[1] = high;                }            }        }        /// <summary>        /// Initializes a new instance of the <see cref="BigInteger"/> structure with an unsigned 64-bit integer value.        /// </summary>        /// <param name="value">An unsigned 64-bit integer.</param>        [CLSCompliant(false)]        public BigInteger(ulong value)        {            if (value == 0)            {                _sign = 0;                _data = null;            }            else            {                _sign = 1;                var low = (uint)value;                var high = (uint)(value >> 32);                _data = new uint[high != 0 ? 2 : 1];                _data[0] = low;                if (high != 0)                {                    _data[1] = high;                }            }        }        /// <summary>        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a double-precision floating-point value.        /// </summary>        /// <param name="value">A double-precision floating-point value.</param>        public BigInteger(double value)        {            if (double.IsNaN(value) || double.IsInfinity(value))            {                throw new OverflowException();            }            var bytes = BitConverter.GetBytes(value);            var mantissa = Mantissa(bytes);            if (mantissa == 0)            {                // 1.0 * 2**exp, we have a power of 2                int exponent = Exponent(bytes);                if (exponent == 0)                {                    _sign = 0;                    _data = null;                    return;                }                var res = Negative(bytes) ? MinusOne : One;                res <<= exponent - 0x3ff;                _sign = res._sign;                _data = res._data;            }            else            {                // 1.mantissa * 2**exp                int exponent = Exponent(bytes);                mantissa |= 0x10000000000000ul;                BigInteger res = mantissa;                res = exponent > Bias ? res << (exponent - Bias) : res >> (Bias - exponent);                _sign = (short)(Negative(bytes) ? -1 : 1);                _data = res._data;            }        }        /// <summary>        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a single-precision floating-point value.        /// </summary>        /// <param name="value">A single-precision floating-point value.</param>        public BigInteger(float value)            : this((double)value)        {        }        /// <summary>        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a <see cref="decimal"/> value.        /// </summary>        /// <param name="value">A decimal number.</param>        public BigInteger(decimal value)        {            // First truncate to get scale to 0 and extract bits            var bits = decimal.GetBits(decimal.Truncate(value));            var size = 3;            while (size > 0 && bits[size - 1] == 0)            {                size--;            }            if (size == 0)            {                _sign = 0;                _data = null;                return;            }            _sign = (short)((bits[3] & DecimalSignMask) != 0 ? -1 : 1);            _data = new uint[size];            _data[0] = (uint)bits[0];            if (size > 1)            {                _data[1] = (uint)bits[1];            }            if (size > 2)            {                _data[2] = (uint)bits[2];            }        }        /// <summary>        /// Initializes a new instance of the <see cref="BigInteger"/> structure using the values in a byte array.        /// </summary>        /// <param name="value">An array of <see cref="byte"/> values in little-endian order.</param>        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception>        [CLSCompliant(false)]        public BigInteger(byte[] value)        {            if (value is null)            {                throw new ArgumentNullException(nameof(value));            }            var len = value.Length;            if (len == 0 || (len == 1 && value[0] == 0))            {                _sign = 0;                _data = null;                return;            }            if ((value[len - 1] & 0x80) != 0)            {                _sign = -1;            }            else            {                _sign = 1;            }#pragma warning disable CA1508 // Avoid dead conditional code | this is the following bug in the analyzer rule: https://github.com/dotnet/roslyn-analyzers/issues/6991            if (_sign == 1)#pragma warning restore CA1508 // Avoid dead conditional code            {                while (value[len - 1] == 0)                {                    if (--len == 0)                    {                        _sign = 0;                        _data = null;                        return;                    }                }                int size;                var fullWords = size = len / 4;                if ((len & 0x3) != 0)                {                    ++size;                }                _data = new uint[size];                var j = 0;                for (var i = 0; i < fullWords; ++i)                {                    _data[i] = (uint)value[j++] |                               (uint)(value[j++] << 8) |                               (uint)(value[j++] << 16) |                               (uint)(value[j++] << 24);                }                size = len & 0x3;                if (size > 0)                {                    var idx = _data.Length - 1;                    for (var i = 0; i < size; ++i)                    {                        _data[idx] |= (uint)(value[j++] << (i * 8));                    }                }            }            else            {                int size;                var fullWords = size = len / 4;                if ((len & 0x3) != 0)                {                    ++size;                }                _data = new uint[size];                uint word, borrow = 1;                ulong sub;                var j = 0;                for (var i = 0; i < fullWords; ++i)                {                    word = (uint)value[j++] |                           (uint)(value[j++] << 8) |                           (uint)(value[j++] << 16) |                           (uint)(value[j++] << 24);                    sub = (ulong)word - borrow;                    word = (uint)sub;                    borrow = (uint)(sub >> 32) & 0x1u;                    _data[i] = ~word;                }                size = len & 0x3;                if (size > 0)                {                    word = 0;                    uint storeMask = 0;                    for (var i = 0; i < size; ++i)                    {                        word |= (uint)(value[j++] << (i * 8));                        storeMask = (storeMask << 8) | 0xFF;                    }                    sub = word - borrow;                    word = (uint)sub;                    borrow = (uint)(sub >> 32) & 0x1u;                    if ((~word & storeMask) == 0)                    {                        Array.Resize(ref _data, _data.Length - 1);                    }                    else                    {                        _data[_data.Length - 1] = ~word & storeMask;                    }                }                if (borrow != 0)                {#pragma warning disable CA2201 // Do not raise reserved exception types                    throw new Exception("non zero final carry");#pragma warning restore CA2201 // Do not raise reserved exception types                }            }        }        private static bool Negative(byte[] v)        {            return (v[7] & 0x80) != 0;        }        private static ushort Exponent(byte[] v)        {            return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4));        }        private static ulong Mantissa(byte[] v)        {            var i1 = (uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24);            var i2 = (uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16);            return (ulong)i1 | ((ulong)i2 << 32);        }        /// <summary>        /// Gets a value indicating whether the value of the current <see cref="BigInteger"/> object is an even number.        /// </summary>        /// <value>        /// <see langword="true"/> if the value of the <see cref="BigInteger"/> object is an even number; otherwise, <see langword="false"/>.        /// </value>        public readonly bool IsEven        {            get { return _sign == 0 || (_data[0] & 0x1) == 0; }        }        /// <summary>        /// Gets a value indicating whether the value of the current <see cref="BigInteger"/> object is <see cref="One"/>.        /// </summary>        /// <value>        /// <see langword="true"/> if the value of the <see cref="BigInteger"/> object is <see cref="One"/>;        /// otherwise, <see langword="false"/>.        /// </value>        public readonly bool IsOne        {            get { return _sign == 1 && _data.Length == 1 && _data[0] == 1; }        }        // Gem from Hacker's Delight        // Returns the number of bits set in @x        private static int PopulationCount(uint x)        {            x -= (x >> 1) & 0x55555555;            x = (x & 0x33333333) + ((x >> 2) & 0x33333333);            x = (x + (x >> 4)) & 0x0F0F0F0F;            x += x >> 8;            x += x >> 16;            return (int)(x & 0x0000003F);        }        /// <summary>        /// Returns the number of bits set in <paramref name="x"/>.        /// </summary>        /// <returns>        /// The number of bits set in <paramref name="x"/>.        /// </returns>        /// <remarks>        /// Based on code by Zilong Tan on Ulib released under MIT license.        /// </remarks>        private static int PopulationCount(ulong x)        {            x -= (x >> 1) & 0x5555555555555555UL;            x = (x & 0x3333333333333333UL) + ((x >> 2) & 0x3333333333333333UL);            x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fUL;            return (int)((x * 0x0101010101010101UL) >> 56);        }        private static int LeadingZeroCount(uint value)        {            value |= value >> 1;            value |= value >> 2;            value |= value >> 4;            value |= value >> 8;            value |= value >> 16;            return 32 - PopulationCount(value); // 32 = bits in uint        }        private static int LeadingZeroCount(ulong value)        {            value |= value >> 1;            value |= value >> 2;            value |= value >> 4;            value |= value >> 8;            value |= value >> 16;            value |= value >> 32;            return 64 - PopulationCount(value); // 64 = bits in ulong        }        private static double BuildDouble(int sign, ulong mantissa, int exponent)        {            const int exponentBias = 1023;            const int mantissaLength = 52;            const int exponentLength = 11;            const int maxExponent = 2046;            const long mantissaMask = 0xfffffffffffffL;            const long exponentMask = 0x7ffL;            const ulong negativeMark = 0x8000000000000000uL;            if (sign == 0 || mantissa == 0)            {                return 0.0;            }            exponent += exponentBias + mantissaLength;            var offset = LeadingZeroCount(mantissa) - exponentLength;            if (exponent - offset > maxExponent)            {                return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity;            }            if (offset < 0)            {                mantissa >>= -offset;                exponent += -offset;            }            else if (offset >= exponent)            {                mantissa <<= exponent - 1;                exponent = 0;            }            else            {                mantissa <<= offset;                exponent -= offset;            }            mantissa &= mantissaMask;            if ((exponent & exponentMask) == exponent)            {                unchecked                {                    var bits = mantissa | ((ulong)exponent << mantissaLength);                    if (sign < 0)                    {                        bits |= negativeMark;                    }                    return BitConverter.Int64BitsToDouble((long)bits);                }            }            return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity;        }        /// <summary>        /// Gets a value Indicating whether the value of the current <see cref="BigInteger"/> object is a power of two.        /// </summary>        /// <value>        /// <see langword="true"/> if the value of the <see cref="BigInteger"/> object is a power of two;        /// otherwise, <see langword="false"/>.        /// </value>        public readonly bool IsPowerOfTwo        {            get            {                if (_sign != 1)                {                    return false;                }                var foundBit = false;                // This function is pop count == 1 for positive numbers                foreach (var bit in _data)                {                    var p = PopulationCount(bit);                    if (p > 0)                    {                        if (p > 1 || foundBit)                        {                            return false;                        }                        foundBit = true;                    }                }                return foundBit;            }        }        /// <summary>        /// Gets a value indicating whether the value of the current <see cref="BigInteger"/> object is <see cref="Zero"/>.        /// </summary>        /// <value>        /// <see langword="true"/> if the value of the <see cref="BigInteger"/> object is <see cref="Zero"/>;        /// otherwise, <see langword="false"/>.        /// </value>        public readonly bool IsZero        {            get { return _sign == 0; }        }        /// <summary>        /// Gets a number that indicates the sign (negative, positive, or zero) of the current <see cref="BigInteger"/> object.        /// </summary>        /// <value>        /// A number that indicates the sign of the <see cref="BigInteger"/> object.        /// </value>        public readonly int Sign        {            get { return _sign; }        }        /// <summary>        /// Gets a value that represents the number negative one (-1).        /// </summary>        /// <value>        /// An integer whose value is negative one (-1).        /// </value>        public static BigInteger MinusOne        {            get { return MinusOneSingleton; }        }        /// <summary>        /// Gets a value that represents the number one (1).        /// </summary>        /// <value>        /// An object whose value is one (1).        /// </value>        public static BigInteger One        {            get { return OneSingleton; }        }        /// <summary>        /// Gets a value that represents the number 0 (zero).        /// </summary>        /// <value>        /// An integer whose value is 0 (zero).        /// </value>        public static BigInteger Zero        {            get { return ZeroSingleton; }        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 32-bit signed integer value.        /// </summary>        /// <param name="value">The value to convert to a 32-bit signed integer.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator int(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (value._data is null)            {                return 0;            }            if (value._data.Length > 1)            {                throw new OverflowException();            }            var data = value._data[0];            if (value._sign == 1)            {                if (data > (uint)int.MaxValue)                {                    throw new OverflowException();                }                return (int)data;            }            if (value._sign == -1)            {                if (data > 0x80000000u)                {                    throw new OverflowException();                }                return -(int)data;            }            return 0;        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned 32-bit integer value.        /// </summary>        /// <param name="value">The value to convert to an unsigned 32-bit integer.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>        [CLSCompliant(false)]#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator uint(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (value._data is null)            {                return 0;            }            if (value._data.Length > 1 || value._sign == -1)            {                throw new OverflowException();            }            return value._data[0];        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 16-bit signed integer value.        /// </summary>        /// <param name="value">The value to convert to a 16-bit signed integer.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator short(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            var val = (int)value;            if (val is < short.MinValue or > short.MaxValue)            {                throw new OverflowException();            }            return (short)val;        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 16-bit unsigned integer value.        /// </summary>        /// <param name="value">The value to convert to a 16-bit unsigned integer.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>        [CLSCompliant(false)]#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator ushort(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            var val = (uint)value;            if (val > ushort.MaxValue)            {                throw new OverflowException();            }            return (ushort)val;        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned byte value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="byte"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator byte(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            var val = (uint)value;            if (val > byte.MaxValue)            {                throw new OverflowException();            }            return (byte)val;        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a signed 8-bit value.        /// </summary>        /// <param name="value">The value to convert to a signed 8-bit value.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>        [CLSCompliant(false)]#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator sbyte(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            var val = (int)value;            if (val is < sbyte.MinValue or > sbyte.MaxValue)            {                throw new OverflowException();            }            return (sbyte)val;        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 64-bit signed integer value.        /// </summary>        /// <param name="value">The value to convert to a 64-bit signed integer.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator long(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (value._data is null)            {                return 0;            }            if (value._data.Length > 2)            {                throw new OverflowException();            }            var low = value._data[0];            if (value._data.Length == 1)            {                if (value._sign == 1)                {                    return (long)low;                }                var res = (long)low;                return -res;            }            var high = value._data[1];            if (value._sign == 1)            {                if (high >= 0x80000000u)                {                    throw new OverflowException();                }                return (((long)high) << 32) | low;            }            /*            We cannot represent negative numbers smaller than long.MinValue.            Those values are encoded into what look negative numbers, so negating            them produces a positive value, that's why it's safe to check for that            condition.            long.MinValue works fine since it's bigint encoding looks like a negative            number, but since long.MinValue == -long.MinValue, we're good.            */            var result = -((((long)high) << 32) | (long)low);            if (result > 0)            {                throw new OverflowException();            }            return result;        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned 64-bit integer value.        /// </summary>        /// <param name="value">The value to convert to an unsigned 64-bit integer.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>        [CLSCompliant(false)]#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator ulong(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (value._data is null)            {                return 0;            }            if (value._data.Length > 2 || value._sign == -1)            {                throw new OverflowException();            }            var low = value._data[0];            if (value._data.Length == 1)            {                return low;            }            var high = value._data[1];            return (((ulong)high) << 32) | low;        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a <see cref="double"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="double"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator double(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (value._data is null)            {                return 0.0;            }            switch (value._data.Length)            {                case 1:                    return BuildDouble(value._sign, value._data[0], 0);                case 2:                    return BuildDouble(value._sign, (ulong)value._data[1] << 32 | (ulong)value._data[0], 0);                default:                    var index = value._data.Length - 1;                    var word = value._data[index];                    var mantissa = ((ulong)word << 32) | value._data[index - 1];                    var missing = LeadingZeroCount(word) - 11; // 11 = bits in exponent                    if (missing > 0)                    {                        // add the missing bits from the next word                        mantissa = (mantissa << missing) | (value._data[index - 2] >> (32 - missing));                    }                    else                    {                        mantissa >>= -missing;                    }                    return BuildDouble(value._sign, mantissa, ((value._data.Length - 2) * 32) - missing);            }        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a single-precision floating-point value.        /// </summary>        /// <param name="value">The value to convert to a single-precision floating-point value.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator float(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return (float)(double)value;        }        /// <summary>        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a <see cref="decimal"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="decimal"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator decimal(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (value._data is null)            {                return decimal.Zero;            }            var data = value._data;            if (data.Length > 3)            {                throw new OverflowException();            }            int lo = 0, mi = 0, hi = 0;            if (data.Length > 2)            {                hi = (int)data[2];            }            if (data.Length > 1)            {                mi = (int)data[1];            }            if (data.Length > 0)            {                lo = (int)data[0];            }            return new decimal(lo, mi, hi, value._sign < 0, 0);        }        /// <summary>        /// Defines an implicit conversion of a signed 32-bit integer to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static implicit operator BigInteger(int value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Defines an implicit conversion of a 32-bit unsigned integer to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>        [CLSCompliant(false)]#pragma warning disable CA2225 // Operator overloads have named alternates        public static implicit operator BigInteger(uint value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Defines an implicit conversion of a signed 16-bit integer to a BigInteger value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static implicit operator BigInteger(short value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Defines an implicit conversion of a 16-bit unsigned integer to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>        [CLSCompliant(false)]#pragma warning disable CA2225 // Operator overloads have named alternates        public static implicit operator BigInteger(ushort value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Defines an implicit conversion of an unsigned byte to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static implicit operator BigInteger(byte value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Defines an implicit conversion of a signed byte to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>        [CLSCompliant(false)]#pragma warning disable CA2225 // Operator overloads have named alternates        public static implicit operator BigInteger(sbyte value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Defines an implicit conversion of a signed 64-bit integer to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static implicit operator BigInteger(long value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Defines an implicit conversion of a 64-bit unsigned integer to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>        [CLSCompliant(false)]#pragma warning disable CA2225 // Operator overloads have named alternates        public static implicit operator BigInteger(ulong value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Defines an explicit conversion of a <see cref="double"/> value to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator BigInteger(double value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Defines an explicit conversion of a <see cref="float"/> object to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator BigInteger(float value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Defines an explicit conversion of a <see cref="decimal"/> object to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>        /// <returns>        /// An object that contains the value of the <paramref name="value"/> parameter.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static explicit operator BigInteger(decimal value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return new BigInteger(value);        }        /// <summary>        /// Adds the values of two specified <see cref="BigInteger"/> objects.        /// </summary>        /// <param name="left">The first value to add.</param>        /// <param name="right">The second value to add.</param>        /// <returns>        /// The sum of <paramref name="left"/> and <paramref name="right"/>.        /// </returns>        public static BigInteger operator +(BigInteger left, BigInteger right)        {            if (left._sign == 0)            {                return right;            }            if (right._sign == 0)            {                return left;            }            if (left._sign == right._sign)            {                return new BigInteger(left._sign, CoreAdd(left._data, right._data));            }            var r = CoreCompare(left._data, right._data);            if (r == 0)            {                return Zero;            }            if (r > 0)            {                // left > right                return new BigInteger(left._sign, CoreSub(left._data, right._data));            }            return new BigInteger(right._sign, CoreSub(right._data, left._data));        }        /// <summary>        /// Subtracts a <see cref="BigInteger"/> value from another <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The value to subtract from (the minuend).</param>        /// <param name="right">The value to subtract (the subtrahend).</param>        /// <returns>        /// The result of subtracting <paramref name="right"/> from <paramref name="left"/>.        /// </returns>        public static BigInteger operator -(BigInteger left, BigInteger right)        {            if (right._sign == 0)            {                return left;            }            if (left._sign == 0)            {                return new BigInteger((short)-right._sign, right._data);            }            if (left._sign == right._sign)            {                var r = CoreCompare(left._data, right._data);                if (r == 0)                {                    return Zero;                }                if (r > 0)                {                    // left > right                    return new BigInteger(left._sign, CoreSub(left._data, right._data));                }                return new BigInteger((short)-right._sign, CoreSub(right._data, left._data));            }            return new BigInteger(left._sign, CoreAdd(left._data, right._data));        }        /// <summary>        /// Multiplies two specified <see cref="BigInteger"/> values.        /// </summary>        /// <param name="left">The first value to multiply.</param>        /// <param name="right">The second value to multiply.</param>        /// <returns>        /// The product of left and right.        /// </returns>        public static BigInteger operator *(BigInteger left, BigInteger right)        {            if (left._sign == 0 || right._sign == 0)            {                return Zero;            }            if (left._data[0] == 1 && left._data.Length == 1)            {                if (left._sign == 1)                {                    return right;                }                return new BigInteger((short)-right._sign, right._data);            }            if (right._data[0] == 1 && right._data.Length == 1)            {                if (right._sign == 1)                {                    return left;                }                return new BigInteger((short)-left._sign, left._data);            }            var a = left._data;            var b = right._data;            var res = new uint[a.Length + b.Length];            for (var i = 0; i < a.Length; ++i)            {                var ai = a[i];                var k = i;                ulong carry = 0;                for (var j = 0; j < b.Length; ++j)                {                    carry = carry + (((ulong)ai) * b[j]) + res[k];                    res[k++] = (uint)carry;                    carry >>= 32;                }                while (carry != 0)                {                    carry += res[k];                    res[k++] = (uint)carry;                    carry >>= 32;                }            }            int m;            for (m = res.Length - 1; m >= 0 && res[m] == 0; --m)            {                // Intentionally empty block            }            if (m < res.Length - 1)            {                Array.Resize(ref res, m + 1);            }            return new BigInteger((short)(left._sign * right._sign), res);        }        /// <summary>        /// Divides a specified <see cref="BigInteger"/> value by another specified <see cref="BigInteger"/> value by using        /// integer division.        /// </summary>        /// <param name="dividend">The value to be divided.</param>        /// <param name="divisor">The value to divide by.</param>        /// <returns>        /// The integral result of the division.        /// </returns>        public static BigInteger operator /(BigInteger dividend, BigInteger divisor)        {            if (divisor._sign == 0)            {                throw new DivideByZeroException();            }            if (dividend._sign == 0)            {                return dividend;            }            DivModUnsigned(dividend._data, divisor._data, out var quotient, out _);            int i;            for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i)            {                // Intentionally empty block            }            if (i == -1)            {                return Zero;            }            if (i < quotient.Length - 1)            {                Array.Resize(ref quotient, i + 1);            }            return new BigInteger((short)(dividend._sign * divisor._sign), quotient);        }        /// <summary>        /// Returns the remainder that results from division with two specified <see cref="BigInteger"/> values.        /// </summary>        /// <param name="dividend">The value to be divided.</param>        /// <param name="divisor">The value to divide by.</param>        /// <returns>        /// The remainder that results from the division.        /// </returns>        public static BigInteger operator %(BigInteger dividend, BigInteger divisor)        {            if (divisor._sign == 0)            {                throw new DivideByZeroException();            }            if (dividend._sign == 0)            {                return dividend;            }            DivModUnsigned(dividend._data, divisor._data, out _, out var remainderValue);            int i;            for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i)            {                // Intentionally empty block            }            if (i == -1)            {                return Zero;            }            if (i < remainderValue.Length - 1)            {                Array.Resize(ref remainderValue, i + 1);            }            return new BigInteger(dividend._sign, remainderValue);        }        /// <summary>        /// Negates a specified <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to negate.</param>        /// <returns>        /// The result of the <paramref name="value"/> parameter multiplied by negative one (-1).        /// </returns>        public static BigInteger operator -(BigInteger value)        {            if (value._data is null)            {                return value;            }            return new BigInteger((short)-value._sign, value._data);        }        /// <summary>        /// Returns the value of the <see cref="BigInteger"/> operand.        /// </summary>        /// <param name="value">An integer value.</param>        /// <returns>        /// The value of the <paramref name="value"/> operand.        /// </returns>        /// <remarks>        /// The sign of the operand is unchanged.        /// </remarks>#pragma warning disable CA2225 // Operator overloads have named alternates        public static BigInteger operator +(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            return value;        }        /// <summary>        /// Increments a <see cref="BigInteger"/> value by 1.        /// </summary>        /// <param name="value">The value to increment.</param>        /// <returns>        /// The value of the <paramref name="value"/> parameter incremented by 1.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static BigInteger operator ++(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (value._data is null)            {                return One;            }            var sign = value._sign;            var data = value._data;            if (data.Length == 1)            {                if (sign == -1 && data[0] == 1)                {                    return Zero;                }                if (sign == 0)                {                    return One;                }            }            data = sign == -1 ? CoreSub(data, 1) : CoreAdd(data, 1);            return new BigInteger(sign, data);        }        /// <summary>        /// Decrements a <see cref="BigInteger"/> value by 1.        /// </summary>        /// <param name="value">The value to decrement.</param>        /// <returns>        /// The value of the <paramref name="value"/> parameter decremented by 1.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static BigInteger operator --(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (value._data is null)            {                return MinusOne;            }            var sign = value._sign;            var data = value._data;            if (data.Length == 1)            {                if (sign == 1 && data[0] == 1)                {                    return Zero;                }                if (sign == 0)                {                    return MinusOne;                }            }            data = sign == -1 ? CoreAdd(data, 1) : CoreSub(data, 1);            return new BigInteger(sign, data);        }        /// <summary>        /// Performs a bitwise <c>And</c> operation on two <see cref="BigInteger"/> values.        /// </summary>        /// <param name="left">The first value.</param>        /// <param name="right">The second value.</param>        /// <returns>        /// The result of the bitwise <c>And</c> operation.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static BigInteger operator &(BigInteger left, BigInteger right)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (left._sign == 0)            {                return left;            }            if (right._sign == 0)            {                return right;            }            var a = left._data;            var b = right._data;            int ls = left._sign;            int rs = right._sign;            var negRes = (ls == rs) && (ls == -1);            var result = new uint[Math.Max(a.Length, b.Length)];            ulong ac = 1, bc = 1, borrow = 1;            int i;            for (i = 0; i < result.Length; ++i)            {                uint va = 0;                if (i < a.Length)                {                    va = a[i];                }                if (ls == -1)                {                    ac = ~va + ac;                    va = (uint)ac;                    ac = (uint)(ac >> 32);                }                uint vb = 0;                if (i < b.Length)                {                    vb = b[i];                }                if (rs == -1)                {                    bc = ~vb + bc;                    vb = (uint)bc;                    bc = (uint)(bc >> 32);                }                var word = va & vb;                if (negRes)                {                    borrow = word - borrow;                    word = ~(uint)borrow;                    borrow = (uint)(borrow >> 32) & 0x1u;                }                result[i] = word;            }            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i)            {                // Intentionally empty block            }            if (i == -1)            {                return Zero;            }            if (i < result.Length - 1)            {                Array.Resize(ref result, i + 1);            }            return new BigInteger(negRes ? (short)-1 : (short)1, result);        }        /// <summary>        /// Performs a bitwise <c>Or</c> operation on two <see cref="BigInteger"/> values.        /// </summary>        /// <param name="left">The first value.</param>        /// <param name="right">The second value.</param>        /// <returns>        /// The result of the bitwise <c>Or</c> operation.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static BigInteger operator |(BigInteger left, BigInteger right)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (left._sign == 0)            {                return right;            }            if (right._sign == 0)            {                return left;            }            var a = left._data;            var b = right._data;            int ls = left._sign;            int rs = right._sign;            var negRes = (ls == -1) || (rs == -1);            var result = new uint[Math.Max(a.Length, b.Length)];            ulong ac = 1, bc = 1, borrow = 1;            int i;            for (i = 0; i < result.Length; ++i)            {                uint va = 0;                if (i < a.Length)                {                    va = a[i];                }                if (ls == -1)                {                    ac = ~va + ac;                    va = (uint)ac;                    ac = (uint)(ac >> 32);                }                uint vb = 0;                if (i < b.Length)                {                    vb = b[i];                }                if (rs == -1)                {                    bc = ~vb + bc;                    vb = (uint)bc;                    bc = (uint)(bc >> 32);                }                var word = va | vb;                if (negRes)                {                    borrow = word - borrow;                    word = ~(uint)borrow;                    borrow = (uint)(borrow >> 32) & 0x1u;                }                result[i] = word;            }            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i)            {                // Intentionally empty block            }            if (i == -1)            {                return Zero;            }            if (i < result.Length - 1)            {                Array.Resize(ref result, i + 1);            }            return new BigInteger(negRes ? (short)-1 : (short)1, result);        }        /// <summary>        /// Performs a bitwise exclusive <c>Or</c> (<c>XOr</c>) operation on two <see cref="BigInteger"/> values.        /// </summary>        /// <param name="left">The first value.</param>        /// <param name="right">The second value.</param>        /// <returns>        /// The result of the bitwise <c>Or</c> operation.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static BigInteger operator ^(BigInteger left, BigInteger right)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (left._sign == 0)            {                return right;            }            if (right._sign == 0)            {                return left;            }            var a = left._data;            var b = right._data;            int ls = left._sign;            int rs = right._sign;            var negRes = (ls == -1) ^ (rs == -1);            var result = new uint[Math.Max(a.Length, b.Length)];            ulong ac = 1, bc = 1, borrow = 1;            int i;            for (i = 0; i < result.Length; ++i)            {                uint va = 0;                if (i < a.Length)                {                    va = a[i];                }                if (ls == -1)                {                    ac = ~va + ac;                    va = (uint)ac;                    ac = (uint)(ac >> 32);                }                uint vb = 0;                if (i < b.Length)                {                    vb = b[i];                }                if (rs == -1)                {                    bc = ~vb + bc;                    vb = (uint)bc;                    bc = (uint)(bc >> 32);                }                var word = va ^ vb;                if (negRes)                {                    borrow = word - borrow;                    word = ~(uint)borrow;                    borrow = (uint)(borrow >> 32) & 0x1u;                }                result[i] = word;            }            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i)            {                // Intentionally empty block            }            if (i == -1)            {                return Zero;            }            if (i < result.Length - 1)            {                Array.Resize(ref result, i + 1);            }            return new BigInteger(negRes ? (short)-1 : (short)1, result);        }        /// <summary>        /// Returns the bitwise one's complement of a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">An integer value.</param>        /// <returns>        /// The bitwise one's complement of <paramref name="value"/>.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static BigInteger operator ~(BigInteger value)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (value._data is null)            {                return MinusOne;            }            var data = value._data;            int sign = value._sign;            var negRes = sign == 1;            var result = new uint[data.Length];            ulong carry = 1, borrow = 1;            int i;            for (i = 0; i < result.Length; ++i)            {                var word = data[i];                if (sign == -1)                {                    carry = ~word + carry;                    word = (uint)carry;                    carry = (uint)(carry >> 32);                }                word = ~word;                if (negRes)                {                    borrow = word - borrow;                    word = ~(uint)borrow;                    borrow = (uint)(borrow >> 32) & 0x1u;                }                result[i] = word;            }            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i)            {                // Intentionally empty block            }            if (i == -1)            {                return Zero;            }            if (i < result.Length - 1)            {                Array.Resize(ref result, i + 1);            }            return new BigInteger(negRes ? (short)-1 : (short)1, result);        }        /// <summary>        /// Returns the zero-based index of the most significant set bit.        /// </summary>        /// <param name="word">The value to scan.</param>        /// <returns>        /// The zero-based index of the most significant set bit, or zero if no bit is set.        /// </returns>        private static int BitScanBackward(uint word)        {            for (var i = 31; i >= 0; --i)            {                var mask = 1u << i;                if ((word & mask) == mask)                {                    return i;                }            }            return 0;        }        /// <summary>        /// Shifts a <see cref="BigInteger"/> value a specified number of bits to the left.        /// </summary>        /// <param name="value">The value whose bits are to be shifted.</param>        /// <param name="shift">The number of bits to shift value to the left.</param>        /// <returns>        /// A value that has been shifted to the left by the specified number of bits.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static BigInteger operator <<(BigInteger value, int shift)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (shift == 0 || value._data is null)            {                return value;            }            if (shift < 0)            {                return value >> -shift;            }            var data = value._data;            int sign = value._sign;            var topMostIdx = BitScanBackward(data[data.Length - 1]);            var bits = shift - (31 - topMostIdx);            var extraWords = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);            var res = new uint[data.Length + extraWords];            var idxShift = shift >> 5;            var bitShift = shift & 0x1F;            var carryShift = 32 - bitShift;            if (carryShift == 32)            {                for (var i = 0; i < data.Length; ++i)                {                    var word = data[i];                    res[i + idxShift] |= word << bitShift;                }            }            else            {                for (var i = 0; i < data.Length; ++i)                {                    var word = data[i];                    res[i + idxShift] |= word << bitShift;                    if (i + idxShift + 1 < res.Length)                    {                        res[i + idxShift + 1] = word >> carryShift;                    }                }            }            return new BigInteger((short)sign, res);        }        /// <summary>        /// Shifts a <see cref="BigInteger"/> value a specified number of bits to the right.        /// </summary>        /// <param name="value">The value whose bits are to be shifted.</param>        /// <param name="shift">The number of bits to shift value to the right.</param>        /// <returns>        /// A value that has been shifted to the right by the specified number of bits.        /// </returns>#pragma warning disable CA2225 // Operator overloads have named alternates        public static BigInteger operator >>(BigInteger value, int shift)#pragma warning restore CA2225 // Operator overloads have named alternates        {            if (shift == 0 || value._sign == 0)            {                return value;            }            if (shift < 0)            {                return value << -shift;            }            var data = value._data;            int sign = value._sign;            var topMostIdx = BitScanBackward(data[data.Length - 1]);            var idxShift = shift >> 5;            var bitShift = shift & 0x1F;            var extraWords = idxShift;            if (bitShift > topMostIdx)            {                ++extraWords;            }            var size = data.Length - extraWords;            if (size <= 0)            {                return sign == 1 ? Zero : MinusOne;            }            var res = new uint[size];            var carryShift = 32 - bitShift;            if (carryShift == 32)            {                for (var i = data.Length - 1; i >= idxShift; --i)                {                    var word = data[i];                    if (i - idxShift < res.Length)                    {                        res[i - idxShift] |= word >> bitShift;                    }                }            }            else            {                for (var i = data.Length - 1; i >= idxShift; --i)                {                    var word = data[i];                    if (i - idxShift < res.Length)                    {                        res[i - idxShift] |= word >> bitShift;                    }                    if (i - idxShift - 1 >= 0)                    {                        res[i - idxShift - 1] = word << carryShift;                    }                }            }            // Round down instead of toward zero            if (sign == -1)            {                for (var i = 0; i < idxShift; i++)                {                    if (data[i] != 0u)                    {                        var tmp = new BigInteger((short)sign, res);                        --tmp;                        return tmp;                    }                }                if (bitShift > 0 && (data[idxShift] << carryShift) != 0u)                {                    var tmp = new BigInteger((short)sign, res);                    --tmp;                    return tmp;                }            }            return new BigInteger((short)sign, res);        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than another        /// <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <see langword="false"/>.        /// </returns>        public static bool operator <(BigInteger left, BigInteger right)        {            return Compare(left, right) < 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than a 64-bit signed integer.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if left is <paramref name="left"/> than <paramref name="right"/>; otherwise, <see langword="false"/>.        /// </returns>        public static bool operator <(BigInteger left, long right)        {            return left.CompareTo(right) < 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is less than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator <(long left, BigInteger right)        {            return right.CompareTo(left) > 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator <(BigInteger left, ulong right)        {            return left.CompareTo(right) < 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit unsigned integer is less than a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator <(ulong left, BigInteger right)        {            return right.CompareTo(left) > 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal        /// to another <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator <=(BigInteger left, BigInteger right)        {            return Compare(left, right) <= 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal        /// to a 64-bit signed integer.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator <=(BigInteger left, long right)        {            return left.CompareTo(right) <= 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit signed integer is less than or equal to a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator <=(long left, BigInteger right)        {            return right.CompareTo(left) >= 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal to        /// a 64-bit unsigned integer.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator <=(BigInteger left, ulong right)        {            return left.CompareTo(right) <= 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit unsigned integer is less than or equal to a        /// <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator <=(ulong left, BigInteger right)        {            return right.CompareTo(left) >= 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than another        /// <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator >(BigInteger left, BigInteger right)        {            return Compare(left, right) > 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> is greater than a 64-bit signed integer value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator >(BigInteger left, long right)        {            return left.CompareTo(right) > 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit signed integer is greater than a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator >(long left, BigInteger right)        {            return right.CompareTo(left) < 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than a 64-bit unsigned integer.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator >(BigInteger left, ulong right)        {            return left.CompareTo(right) > 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit unsigned integer is greater than a <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator >(ulong left, BigInteger right)        {            return right.CompareTo(left) < 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal        /// to another <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator >=(BigInteger left, BigInteger right)        {            return Compare(left, right) >= 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal        /// to a 64-bit signed integer value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator >=(BigInteger left, long right)        {            return left.CompareTo(right) >= 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit signed integer is greater than or equal to a        /// <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator >=(long left, BigInteger right)        {            return right.CompareTo(left) <= 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal to a        /// 64-bit unsigned integer value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator >=(BigInteger left, ulong right)        {            return left.CompareTo(right) >= 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit unsigned integer is greater than or equal to a        /// <see cref="BigInteger"/> value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> is greater than <paramref name="right"/>;        /// otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator >=(ulong left, BigInteger right)        {            return right.CompareTo(left) <= 0;        }        /// <summary>        /// Returns a value that indicates whether the values of two <see cref="BigInteger"/> objects are equal.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator ==(BigInteger left, BigInteger right)        {            return Compare(left, right) == 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a signed long integer value are equal.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator ==(BigInteger left, long right)        {            return left.CompareTo(right) == 0;        }        /// <summary>        /// Returns a value that indicates whether a signed long integer value and a <see cref="BigInteger"/> value are equal.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator ==(long left, BigInteger right)        {            return right.CompareTo(left) == 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and an unsigned long integer value are equal.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;        /// otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator ==(BigInteger left, ulong right)        {            return left.CompareTo(right) == 0;        }        /// <summary>        /// Returns a value that indicates whether an unsigned long integer value and a <see cref="BigInteger"/> value are equal.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;        /// otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator ==(ulong left, BigInteger right)        {            return right.CompareTo(left) == 0;        }        /// <summary>        /// Returns a value that indicates whether two <see cref="BigInteger"/> objects have different values.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> and <paramref name="right"/> are not equal;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator !=(BigInteger left, BigInteger right)        {            return Compare(left, right) != 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a 64-bit signed integer are not equal.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> and <paramref name="right"/> are not equal;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator !=(BigInteger left, long right)        {            return left.CompareTo(right) != 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit signed integer and a <see cref="BigInteger"/> value are not equal.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> and <paramref name="right"/> are not equal;        /// otherwise, <see langword="false"/>.        /// </returns>        public static bool operator !=(long left, BigInteger right)        {            return right.CompareTo(left) != 0;        }        /// <summary>        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a 64-bit unsigned integer are not equal.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> and <paramref name="right"/> are not equal;        /// otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator !=(BigInteger left, ulong right)        {            return left.CompareTo(right) != 0;        }        /// <summary>        /// Returns a value that indicates whether a 64-bit unsigned integer and a <see cref="BigInteger"/> value are not equal.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="left"/> and <paramref name="right"/> are not equal;        /// otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public static bool operator !=(ulong left, BigInteger right)        {            return right.CompareTo(left) != 0;        }        /// <summary>        /// Returns a value that indicates whether the current instance and a specified object have the same value.        /// </summary>        /// <param name="obj">The object to compare.</param>        /// <returns>        /// <see langword="true"/> if the <paramref name="obj"/> parameter is a <see cref="BigInteger"/> object or a type capable        /// of implicit conversion to a <see cref="BigInteger"/> value, and its value is equal to the value of the        /// current <see cref="BigInteger"/> object; otherwise, <see langword="false"/>.        /// </returns>        public override readonly bool Equals(object obj)        {            if (obj is not BigInteger other)            {                return false;            }            return Equals(other);        }        /// <summary>        /// Returns a value that indicates whether the current instance and a specified <see cref="BigInteger"/> object        /// have the same value.        /// </summary>        /// <param name="other">The object to compare.</param>        /// <returns>        /// <see langword="true"/> if this <see cref="BigInteger"/> object and <paramref name="other"/> have the same value;        /// otherwise, <see langword="false"/>.        /// </returns>        public readonly bool Equals(BigInteger other)        {            if (_sign != other._sign)            {                return false;            }            var alen = _data != null ? _data.Length : 0;            var blen = other._data != null ? other._data.Length : 0;            if (alen != blen)            {                return false;            }            for (var i = 0; i < alen; ++i)            {                if (_data[i] != other._data[i])                {                    return false;                }            }            return true;        }        /// <summary>        /// Returns a value that indicates whether the current instance and a signed 64-bit integer have the same value.        /// </summary>        /// <param name="other">The signed 64-bit integer value to compare.</param>        /// <returns>        /// <see langword="true"/> if the signed 64-bit integer and the current instance have the same value; otherwise, <see langword="false"/>.        /// </returns>        public readonly bool Equals(long other)        {            return CompareTo(other) == 0;        }        /// <summary>        /// Returns a value that indicates whether the current instance and an unsigned 64-bit integer have the same value.        /// </summary>        /// <param name="other">The unsigned 64-bit integer to compare.</param>        /// <returns>        /// <see langword="true"/> if the current instance and the unsigned 64-bit integer have the same value; otherwise, <see langword="false"/>.        /// </returns>        [CLSCompliant(false)]        public readonly bool Equals(ulong other)        {            return CompareTo(other) == 0;        }        /// <summary>        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation.        /// </summary>        /// <returns>        /// The string representation of the current <see cref="BigInteger"/> value.        /// </returns>        public override readonly string ToString()        {            return ToString(10, provider: null);        }        /// <summary>        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation        /// by using the specified format.        /// </summary>        /// <param name="format">A standard or custom numeric format string.</param>        /// <returns>        /// The string representation of the current <see cref="BigInteger"/> value in the format specified by the        /// <paramref name="format"/> parameter.        /// </returns>        /// <exception cref="FormatException"><paramref name="format"/> is not a valid format string.</exception>        public readonly string ToString(string format)        {            return ToString(format, formatProvider: null);        }        /// <summary>        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation        /// by using the specified culture-specific formatting information.        /// </summary>        /// <param name="provider">An object that supplies culture-specific formatting information.</param>        /// <returns>        /// The string representation of the current <see cref="BigInteger"/> value in the format specified by the        /// <paramref name="provider"/> parameter.        /// </returns>        public readonly string ToString(IFormatProvider provider)        {            return ToString(format: null, provider);        }        /// <summary>        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation        /// by using the specified format and culture-specific format information.        /// </summary>        /// <param name="format">A standard or custom numeric format string.</param>        /// <param name="formatProvider">An object that supplies culture-specific formatting information.</param>        /// <returns>        /// The string representation of the current <see cref="BigInteger"/> value as specified by the <paramref name="format"/>        /// and <paramref name="formatProvider"/> parameters.        /// </returns>        public readonly string ToString(string format, IFormatProvider formatProvider)        {            if (string.IsNullOrEmpty(format))            {                return ToString(10, formatProvider);            }            switch (format[0])            {                case 'd':                case 'D':                case 'g':                case 'G':                case 'r':                case 'R':                    return ToStringWithPadding(format, 10, formatProvider);                case 'x':                case 'X':                    return ToStringWithPadding(format, 16, provider: null);                default:                    throw new FormatException(string.Format("format '{0}' not implemented", format));            }        }        private readonly string ToStringWithPadding(string format, uint radix, IFormatProvider provider)        {            if (format.Length > 1)            {                var precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);                var baseStr = ToString(radix, provider);                if (baseStr.Length < precision)                {                    var additional = new string('0', precision - baseStr.Length);                    if (baseStr[0] != '-')                    {                        return additional + baseStr;                    }#if NET                    return string.Concat("-", additional, baseStr.AsSpan(1));#else                    return "-" + additional + baseStr.Substring(1);#endif // NET                }                return baseStr;            }            return ToString(radix, provider);        }        private static uint[] MakeTwoComplement(uint[] v)        {            var res = new uint[v.Length];            ulong carry = 1;            for (var i = 0; i < v.Length; ++i)            {                var word = v[i];                carry = (ulong)~word + carry;                word = (uint)carry;                carry = (uint)(carry >> 32);                res[i] = word;            }            var last = res[res.Length - 1];            var idx = FirstNonFfByte(last);            uint mask = 0xFF;            for (var i = 1; i < idx; ++i)            {                mask = (mask << 8) | 0xFF;            }            res[res.Length - 1] = last & mask;            return res;        }        private readonly string ToString(uint radix, IFormatProvider provider)        {            const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";            if (characterSet.Length < radix)            {                throw new ArgumentException("charSet length less than radix", nameof(radix));            }            if (radix == 1)            {                throw new ArgumentException("There is no such thing as radix one notation", nameof(radix));            }            if (_sign == 0)            {                return "0";            }            if (_data.Length == 1 && _data[0] == 1)            {                return _sign == 1 ? "1" : "-1";            }            var digits = new List<char>(1 + ((_data.Length * 3) / 10));            BigInteger a;            if (_sign == 1)            {                a = this;            }            else            {                var dt = _data;                if (radix > 10)                {                    dt = MakeTwoComplement(dt);                }                a = new BigInteger(1, dt);            }            while (a != 0)            {                a = DivRem(a, radix, out var rem);                digits.Add(characterSet[(int)rem]);            }            if (_sign == -1 && radix == 10)            {                NumberFormatInfo info = null;                if (provider != null)                {                    info = provider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo;                }                if (info != null)                {                    var str = info.NegativeSign;                    for (var i = str.Length - 1; i >= 0; --i)                    {                        digits.Add(str[i]);                    }                }                else                {                    digits.Add('-');                }            }            var last = digits[digits.Count - 1];            if (_sign == 1 && radix > 10 && (last < '0' || last > '9'))            {                digits.Add('0');            }            digits.Reverse();            return new string(digits.ToArray());        }        /// <summary>        /// Converts the string representation of a number to its <see cref="BigInteger"/> equivalent.        /// </summary>        /// <param name="value">A string that contains the number to convert.</param>        /// <returns>        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.        /// </returns>        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception>        /// <exception cref="FormatException"><paramref name="value"/> is not in the correct format.</exception>        public static BigInteger Parse(string value)        {            if (!Parse(value, tryParse: false, out var result, out var ex))            {                throw ex;            }            return result;        }        /// <summary>        /// Converts the string representation of a number in a specified style to its <see cref="BigInteger"/> equivalent.        /// </summary>        /// <param name="value">A string that contains a number to convert.</param>        /// <param name="style">A bitwise combination of the enumeration values that specify the permitted format of <paramref name="value"/>.</param>        /// <returns>        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.        /// </returns>        /// <exception cref="ArgumentException">        /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para>        /// <para>-or-</para>        /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="NumberStyles.HexNumber"/> flag along with another value.</para>        /// </exception>        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception>        /// <exception cref="FormatException"><paramref name="value"/> does not comply with the input pattern specified by <see cref="NumberStyles"/>.</exception>        public static BigInteger Parse(string value, NumberStyles style)        {            return Parse(value, style, provider: null);        }        /// <summary>        /// Converts the string representation of a number in a specified style to its <see cref="BigInteger"/> equivalent.        /// </summary>        /// <param name="value">A string that contains a number to convert.</param>        /// <param name="provider">An object that provides culture-specific formatting information about <paramref name="value"/>.</param>        /// <returns>        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.        /// </returns>        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception>        /// <exception cref="FormatException"><paramref name="value"/> is not in the correct format.</exception>        public static BigInteger Parse(string value, IFormatProvider provider)        {            return Parse(value, NumberStyles.Integer, provider);        }        /// <summary>        /// Converts the string representation of a number in a specified style and culture-specific format to its <see cref="BigInteger"/> equivalent.        /// </summary>        /// <param name="value">A string that contains a number to convert.</param>        /// <param name="style">A bitwise combination of the enumeration values that specify the permitted format of <paramref name="value"/>.</param>        /// <param name="provider">An object that provides culture-specific formatting information about <paramref name="value"/>.</param>        /// <returns>        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.        /// </returns>        /// <exception cref="ArgumentException">        /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para>        /// <para>-or-</para>        /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="NumberStyles.HexNumber"/> flag along with another value.</para>        /// </exception>        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception>        /// <exception cref="FormatException"><paramref name="value"/> does not comply with the input pattern specified by <see cref="NumberStyles"/>.</exception>        public static BigInteger Parse(string value, NumberStyles style, IFormatProvider provider)        {            if (!Parse(value, style, provider, tryParse: false, out var res, out var exc))            {                throw exc;            }            return res;        }        /// <summary>        /// Tries to convert the string representation of a number to its <see cref="BigInteger"/> equivalent, and        /// returns a value that indicates whether the conversion succeeded.        /// </summary>        /// <param name="value">The string representation of a number.</param>        /// <param name="result">When this method returns, contains the <see cref="BigInteger"/> equivalent to the number that is contained in value, or zero (0) if the conversion fails. The conversion fails if the <paramref name="value"/> parameter is <see langword="null"/> or is not of the correct format. This parameter is passed uninitialized.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="value"/> was converted successfully; otherwise, <see langword="false"/>.        /// </returns>        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception>        public static bool TryParse(string value, out BigInteger result)        {            return Parse(value, tryParse: true, out result, out _);        }        /// <summary>        /// Tries to convert the string representation of a number in a specified style and culture-specific format to its        /// <see cref="BigInteger"/> equivalent, and returns a value that indicates whether the conversion succeeded.        /// </summary>        /// <param name="value">The string representation of a number.</param>        /// <param name="style">A bitwise combination of enumeration values that indicates the style elements that can be present in <paramref name="value"/>.</param>        /// <param name="provider">An object that supplies culture-specific formatting information about <paramref name="value"/>.</param>        /// <param name="result">When this method returns, contains the <see cref="BigInteger"/> equivalent to the number that is contained in value, or <see cref="Zero"/> if the conversion fails. The conversion fails if the <paramref name="value"/> parameter is <see langword="null"/> or is not of the correct format. This parameter is passed uninitialized.</param>        /// <returns>        /// <see langword="true"/> if <paramref name="value"/> was converted successfully; otherwise, <see langword="false"/>.        /// </returns>        /// <exception cref="ArgumentException">        /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para>        /// <para>-or-</para>        /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="NumberStyles.HexNumber"/> flag along with another value.</para>        /// </exception>        public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out BigInteger result)        {            if (!Parse(value, style, provider, tryParse: true, out result, out _))            {                result = Zero;                return false;            }            return true;        }#pragma warning disable S4136 // Method overloads should be grouped together        private static bool Parse(string value, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)#pragma warning restore S4136 // Method overloads should be grouped together        {            result = Zero;            exc = null;            if (value is null)            {                if (!tryParse)                {                    exc = new ArgumentNullException(nameof(value));                }                return false;            }            if (value.Length == 0)            {                if (!tryParse)                {                    exc = GetFormatException();                }                return false;            }            NumberFormatInfo nfi = null;            if (fp != null)            {                var typeNfi = typeof(NumberFormatInfo);                nfi = (NumberFormatInfo)fp.GetFormat(typeNfi);            }            nfi ??= NumberFormatInfo.CurrentInfo;            if (!CheckStyle(style, tryParse, ref exc))            {                return false;            }            var allowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) == NumberStyles.AllowCurrencySymbol;            var allowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier;            var allowThousands = (style & NumberStyles.AllowThousands) == NumberStyles.AllowThousands;            var allowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) == NumberStyles.AllowDecimalPoint;            var allowParentheses = (style & NumberStyles.AllowParentheses) == NumberStyles.AllowParentheses;            var allowTrailingSign = (style & NumberStyles.AllowTrailingSign) == NumberStyles.AllowTrailingSign;            var allowLeadingSign = (style & NumberStyles.AllowLeadingSign) == NumberStyles.AllowLeadingSign;            var allowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) == NumberStyles.AllowTrailingWhite;            var allowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) == NumberStyles.AllowLeadingWhite;            var allowExponent = (style & NumberStyles.AllowExponent) == NumberStyles.AllowExponent;            var pos = 0;            if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc))            {                return false;            }            var foundOpenParentheses = false;            var negative = false;            var foundSign = false;            var foundCurrency = false;            // Pre-number stuff            if (allowParentheses && value[pos] == '(')            {                foundOpenParentheses = true;                foundSign = true;                negative = true; // MS always make the number negative when there parentheses, even when NumberFormatInfo.NumberNegativePattern != 0                pos++;                if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc))                {                    return false;                }                if (value.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign)                {                    if (!tryParse)                    {                        exc = GetFormatException();                    }                    return false;                }                if (value.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign)                {                    if (!tryParse)                    {                        exc = GetFormatException();                    }                    return false;                }            }            if (allowLeadingSign && !foundSign)            {                // Sign + Currency                FindSign(ref pos, value, nfi, ref foundSign, ref negative);                if (foundSign)                {                    if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc))                    {                        return false;                    }                    if (allowCurrencySymbol)                    {                        FindCurrency(ref pos, value, nfi, ref foundCurrency);                        if (foundCurrency && allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc))                        {                            return false;                        }                    }                }            }            if (allowCurrencySymbol && !foundCurrency)            {                // Currency + sign                FindCurrency(ref pos, value, nfi, ref foundCurrency);                if (foundCurrency)                {                    if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc))                    {                        return false;                    }                    if (foundCurrency)                    {                        if (!foundSign && allowLeadingSign)                        {                            FindSign(ref pos, value, nfi, ref foundSign, ref negative);                            if (foundSign && allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc))                            {                                return false;                            }                        }                    }                }            }            var number = Zero;            var nDigits = 0;            var decimalPointPos = -1;            var firstHexDigit = true;            // Number stuff            while (pos < value.Length)            {                if (!ValidDigit(value[pos], allowHexSpecifier))                {                    if (allowThousands &&                        (FindOther(ref pos, value, nfi.NumberGroupSeparator)                        || FindOther(ref pos, value, nfi.CurrencyGroupSeparator)))                    {                        continue;                    }                    if (allowDecimalPoint && decimalPointPos < 0 &&                        (FindOther(ref pos, value, nfi.NumberDecimalSeparator)                        || FindOther(ref pos, value, nfi.CurrencyDecimalSeparator)))                    {                        decimalPointPos = nDigits;                        continue;                    }                    break;                }                nDigits++;                if (allowHexSpecifier)                {                    var hexDigit = value[pos++];                    byte digitValue;                    if (char.IsDigit(hexDigit))                    {                        digitValue = (byte)(hexDigit - '0');                    }                    else if (char.IsLower(hexDigit))                    {                        digitValue = (byte)(hexDigit - 'a' + 10);                    }                    else                    {                        digitValue = (byte)(hexDigit - 'A' + 10);                    }                    if (firstHexDigit && digitValue >= 8)                    {                        negative = true;                    }                    number = (number * 16) + digitValue;                    firstHexDigit = false;                    continue;                }                number = (number * 10) + (byte)(value[pos++] - '0');            }            // Post number stuff            if (nDigits == 0)            {                if (!tryParse)                {                    exc = GetFormatException();                }                return false;            }            // Signed hex value (Two's Complement)            if (allowHexSpecifier && negative)            {                var mask = Pow(16, nDigits) - 1;                number = (number ^ mask) + 1;            }            var exponent = 0;            if (allowExponent)            {                if (FindExponent(ref pos, value, ref exponent, tryParse, ref exc) && exc != null)                {                    return false;                }            }            if (allowTrailingSign && !foundSign)            {                // Sign + Currency                FindSign(ref pos, value, nfi, ref foundSign, ref negative);                if (foundSign && pos < value.Length)                {                    if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc))                    {                        return false;                    }                }            }            if (allowCurrencySymbol && !foundCurrency)            {                if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, tryParse, ref exc))                {                    return false;                }                // Currency + sign                FindCurrency(ref pos, value, nfi, ref foundCurrency);                if (foundCurrency && pos < value.Length)                {                    if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc))                    {                        return false;                    }                    if (!foundSign && allowTrailingSign)                    {                        FindSign(ref pos, value, nfi, ref foundSign, ref negative);                    }                }            }            if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, tryParse, ref exc))            {                return false;            }            if (foundOpenParentheses)            {                if (pos >= value.Length || value[pos++] != ')')                {                    if (!tryParse)                    {                        exc = GetFormatException();                    }                    return false;                }                if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, tryParse, ref exc))                {                    return false;                }            }            if (pos < value.Length && value[pos] != '\u0000')            {                if (!tryParse)                {                    exc = GetFormatException();                }                return false;            }            if (decimalPointPos >= 0)            {                exponent = exponent - nDigits + decimalPointPos;            }            if (exponent < 0)            {                // Any non-zero values after decimal point are not allowed                number = DivRem(number, Pow(10, -exponent), out var remainder);                if (!remainder.IsZero)                {                    if (!tryParse)                    {                        exc = new OverflowException(string.Format(CultureInfo.InvariantCulture,                                                                  "Value too large or too small. exp= {0} rem = {1} pow = {2}",                                                                  exponent,                                                                  remainder,                                                                  Pow(10, -exponent)));                    }                    return false;                }            }            else if (exponent > 0)            {                number = Pow(10, exponent) * number;            }            if (number._sign == 0)            {                result = number;            }            else if (negative)            {                result = new BigInteger(-1, number._data);            }            else            {                result = new BigInteger(1, number._data);            }            return true;        }        private static bool CheckStyle(NumberStyles style, bool tryParse, ref Exception exc)        {            if ((style & NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier)            {                var ne = style ^ NumberStyles.AllowHexSpecifier;                if ((ne & NumberStyles.AllowLeadingWhite) == NumberStyles.AllowLeadingWhite)                {                    ne ^= NumberStyles.AllowLeadingWhite;                }                if ((ne & NumberStyles.AllowTrailingWhite) == NumberStyles.AllowTrailingWhite)                {                    ne ^= NumberStyles.AllowTrailingWhite;                }                if (ne != NumberStyles.None)                {                    if (!tryParse)                    {                        exc = new ArgumentException("With AllowHexSpecifier only " +                                                    "AllowLeadingWhite and AllowTrailingWhite " +                                                    "are permitted.");                    }                    return false;                }            }            else if ((uint)style > (uint)NumberStyles.Any)            {                if (!tryParse)                {                    exc = new ArgumentException("Not a valid number style");                }                return false;            }            return true;        }        private static bool JumpOverWhitespace(ref int pos, string s, bool reportError, bool tryParse, ref Exception exc)        {            while (pos < s.Length && char.IsWhiteSpace(s[pos]))            {                pos++;            }            if (reportError && pos >= s.Length)            {                if (!tryParse)                {                    exc = GetFormatException();                }                return false;            }            return true;        }        private static void FindSign(ref int pos, string s, NumberFormatInfo nfi, ref bool foundSign, ref bool negative)        {            if ((pos + nfi.NegativeSign.Length) <= s.Length &&                string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0)            {                negative = true;                foundSign = true;                pos += nfi.NegativeSign.Length;            }            else if ((pos + nfi.PositiveSign.Length) <= s.Length &&              string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0)            {                negative = false;                pos += nfi.PositiveSign.Length;                foundSign = true;            }        }        private static void FindCurrency(ref int pos, string s, NumberFormatInfo nfi, ref bool foundCurrency)        {            if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&                 s.Substring(pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol)            {                foundCurrency = true;                pos += nfi.CurrencySymbol.Length;            }        }        private static bool FindExponent(ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc)        {            exponent = 0;            if (pos >= s.Length || (s[pos] != 'e' && s[pos] != 'E'))            {                exc = null;                return false;            }            var i = pos + 1;            if (i == s.Length)            {                exc = tryParse ? null : GetFormatException();                return true;            }            var negative = false;            if (s[i] == '-')            {                negative = true;                if (++i == s.Length)                {                    exc = tryParse ? null : GetFormatException();                    return true;                }            }            if (s[i] == '+' && ++i == s.Length)            {                exc = tryParse ? null : GetFormatException();                return true;            }            long exp = 0; // temp long value            for (; i < s.Length; i++)            {                if (!char.IsDigit(s[i]))                {                    exc = tryParse ? null : GetFormatException();                    return true;                }                // Reduce the risk of throwing an overflow exc                exp = checked((exp * 10) - (s[i] - '0'));                if (exp is < int.MinValue or > int.MaxValue)                {                    exc = tryParse ? null : new OverflowException("Value too large or too small.");                    return true;                }            }            // exp value saved as negative            if (!negative)            {                exp = -exp;            }            exc = null;            exponent = (int)exp;            pos = i;            return true;        }        private static bool FindOther(ref int pos, string s, string other)        {            if ((pos + other.Length) <= s.Length &&                 s.Substring(pos, other.Length) == other)            {                pos += other.Length;                return true;            }            return false;        }        private static bool ValidDigit(char e, bool allowHex)        {            if (allowHex)            {                return char.IsDigit(e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');            }            return char.IsDigit(e);        }        private static FormatException GetFormatException()        {            return new FormatException("Input string was not in the correct format");        }        private static bool ProcessTrailingWhitespace(bool tryParse, string s, int position, ref Exception exc)        {            var len = s.Length;            for (var i = position; i < len; i++)            {                var c = s[i];                if (c != 0 && !char.IsWhiteSpace(c))                {                    if (!tryParse)                    {                        exc = GetFormatException();                    }                    return false;                }            }            return true;        }        private static bool Parse(string value, bool tryParse, out BigInteger result, out Exception exc)        {            int i, sign = 1;            var digitsSeen = false;            result = Zero;            exc = null;            if (value is null)            {                if (!tryParse)                {                    exc = new ArgumentNullException(nameof(value));                }                return false;            }            var len = value.Length;            char c;            for (i = 0; i < len; i++)            {                c = value[i];                if (!char.IsWhiteSpace(c))                {                    break;                }            }            if (i == len)            {                if (!tryParse)                {                    exc = GetFormatException();                }                return false;            }            var info = NumberFormatInfo.CurrentInfo;            var negative = info.NegativeSign;            var positive = info.PositiveSign;            if (string.CompareOrdinal(value, i, positive, 0, positive.Length) == 0)            {                i += positive.Length;            }            else if (string.CompareOrdinal(value, i, negative, 0, negative.Length) == 0)            {                sign = -1;                i += negative.Length;            }            var val = Zero;            for (; i < len; i++)            {                c = value[i];                if (c == '\0')                {                    i = len;                    continue;                }                if (c is >= '0' and <= '9')                {                    var d = (byte)(c - '0');                    val = (val * 10) + d;                    digitsSeen = true;                }                else if (!ProcessTrailingWhitespace(tryParse, value, i, ref exc))                {                    return false;                }            }            if (!digitsSeen)            {                if (!tryParse)                {                    exc = GetFormatException();                }                return false;            }            if (val._sign == 0)            {                result = val;            }#pragma warning disable CA1508 // Avoid dead conditional code | this is the following bug in the analyzer rule: https://github.com/dotnet/roslyn-analyzers/issues/6991            else if (sign == -1)#pragma warning restore CA1508 // Avoid dead conditional code            {                result = new BigInteger(-1, val._data);            }            else            {                result = new BigInteger(1, val._data);            }            return true;        }        /// <summary>        /// Returns the smaller of two <see cref="BigInteger"/> values.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// The <paramref name="left"/> or <paramref name="right"/> parameter, whichever is smaller.        /// </returns>        public static BigInteger Min(BigInteger left, BigInteger right)        {            int ls = left._sign;            int rs = right._sign;            if (ls < rs)            {                return left;            }            if (rs < ls)            {                return right;            }            var r = CoreCompare(left._data, right._data);            if (ls == -1)            {                r = -r;            }            if (r <= 0)            {                return left;            }            return right;        }        /// <summary>        /// Returns the larger of two <see cref="BigInteger"/> values.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// The <paramref name="left"/> or <paramref name="right"/> parameter, whichever is larger.        /// </returns>        public static BigInteger Max(BigInteger left, BigInteger right)        {            int ls = left._sign;            int rs = right._sign;            if (ls > rs)            {                return left;            }            if (rs > ls)            {                return right;            }            var r = CoreCompare(left._data, right._data);            if (ls == -1)            {                r = -r;            }            if (r >= 0)            {                return left;            }            return right;        }        /// <summary>        /// Gets the absolute value of a <see cref="BigInteger"/> object.        /// </summary>        /// <param name="value">A number.</param>        /// <returns>        /// The absolute value of <paramref name="value"/>.        /// </returns>        public static BigInteger Abs(BigInteger value)        {            return new BigInteger(Math.Abs(value._sign), value._data);        }        /// <summary>        /// Divides one <see cref="BigInteger"/> value by another, returns the result, and returns the remainder in        /// an output parameter.        /// </summary>        /// <param name="dividend">The value to be divided.</param>        /// <param name="divisor">The value to divide by.</param>        /// <param name="remainder">When this method returns, contains a <see cref="BigInteger"/> value that represents the remainder from the division. This parameter is passed uninitialized.</param>        /// <returns>        /// The quotient of the division.        /// </returns>        public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder)        {            if (divisor._sign == 0)            {                throw new DivideByZeroException();            }            if (dividend._sign == 0)            {                remainder = dividend;                return dividend;            }            DivModUnsigned(dividend._data, divisor._data, out var quotient, out var remainderValue);            int i;            for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i)            {                // Intentionally empty block            }            if (i == -1)            {                remainder = Zero;            }            else            {                if (i < remainderValue.Length - 1)                {                    Array.Resize(ref remainderValue, i + 1);                }                remainder = new BigInteger(dividend._sign, remainderValue);            }            for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i)            {                // Intentionally empty block            }            if (i == -1)            {                return Zero;            }            if (i < quotient.Length - 1)            {                Array.Resize(ref quotient, i + 1);            }            return new BigInteger((short)(dividend._sign * divisor._sign), quotient);        }        /// <summary>        /// Raises a <see cref="BigInteger"/> value to the power of a specified value.        /// </summary>        /// <param name="value">The number to raise to the <paramref name="exponent"/> power.</param>        /// <param name="exponent">The exponent to raise <paramref name="value"/> by.</param>        /// <returns>        /// The result of raising <paramref name="value"/> to the <paramref name="exponent"/> power.        /// </returns>        public static BigInteger Pow(BigInteger value, int exponent)        {            if (exponent < 0)            {                throw new ArgumentOutOfRangeException(nameof(exponent), "exp must be >= 0");            }            if (exponent == 0)            {                return One;            }            if (exponent == 1)            {                return value;            }            var result = One;            while (exponent != 0)            {                if ((exponent & 1) != 0)                {                    result *= value;                }                if (exponent == 1)                {                    break;                }                value *= value;                exponent >>= 1;            }            return result;        }        /// <summary>        /// Performs modulus division on a number raised to the power of another number.        /// </summary>        /// <param name="value">The number to raise to the <paramref name="exponent"/> power.</param>        /// <param name="exponent">The exponent to raise <paramref name="value"/> by.</param>        /// <param name="modulus">The number by which to divide <paramref name="value"/> raised to the <paramref name="exponent"/> power.</param>        /// <returns>        /// The remainder after dividing <paramref name="value"/> raised by <paramref name="exponent"/> by        /// <paramref name="modulus"/>.        /// </returns>        /// <exception cref="ArgumentOutOfRangeException"><paramref name="exponent"/> is negative.</exception>        public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)        {            if (exponent._sign == -1)            {                throw new ArgumentOutOfRangeException(nameof(exponent), "power must be >= 0");            }            if (modulus._sign == 0)            {                throw new DivideByZeroException();            }            var result = One % modulus;            while (exponent._sign != 0)            {                if (!exponent.IsEven)                {                    result *= value;                    result %= modulus;                }                if (exponent.IsOne)                {                    break;                }                value *= value;                value %= modulus;                exponent >>= 1;            }            return result;        }        /// <summary>        /// Finds the greatest common divisor of two <see cref="BigInteger"/> values.        /// </summary>        /// <param name="left">The first value.</param>        /// <param name="right">The second value.</param>        /// <returns>        /// The greatest common divisor of <paramref name="left"/> and <paramref name="right"/>.        /// </returns>        public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right)        {            if (left._sign != 0 && left._data.Length == 1 && left._data[0] == 1)            {                return One;            }            if (right._sign != 0 && right._data.Length == 1 && right._data[0] == 1)            {                return One;            }            if (left.IsZero)            {                return Abs(right);            }            if (right.IsZero)            {                return Abs(left);            }            var x = new BigInteger(1, left._data);            var y = new BigInteger(1, right._data);            var g = y;            while (x._data.Length > 1)            {                g = x;                x = y % x;                y = g;            }            if (x.IsZero)            {                return g;            }            // TODO: should we have something here if we can convert to long?            /*             * Now we can just do it with single precision. I am using the binary gcd method,             * as it should be faster.             */            var yy = x._data[0];            var xx = (uint)(y % yy);            var t = 0;            while (((xx | yy) & 1) == 0)            {                xx >>= 1;                yy >>= 1;                t++;            }            while (xx != 0)            {                while ((xx & 1) == 0)                {                    xx >>= 1;                }                while ((yy & 1) == 0)                {                    yy >>= 1;                }                if (xx >= yy)                {                    xx = (xx - yy) >> 1;                }                else                {                    yy = (yy - xx) >> 1;                }            }            return yy << t;        }        /*         * LAMESPEC Log doesn't specify to how many ulp is has to be precise         * We are equilavent to MS with about 2 ULP         */        /// <summary>        /// Returns the logarithm of a specified number in a specified base.        /// </summary>        /// <param name="value">A number whose logarithm is to be found.</param>        /// <param name="baseValue">The base of the logarithm.</param>        /// <returns>        /// The base <paramref name="baseValue"/> logarithm of value.        /// </returns>        /// <exception cref="ArgumentOutOfRangeException">The log of <paramref name="value"/> is out of range of the <see cref="double"/> data type.</exception>        public static double Log(BigInteger value, double baseValue)        {            if (value._sign == -1 || baseValue == 1.0d || baseValue == -1.0d ||                    baseValue == double.NegativeInfinity || double.IsNaN(baseValue))            {                return double.NaN;            }            if (baseValue is 0.0d or double.PositiveInfinity)            {                return value.IsOne ? 0 : double.NaN;            }            if (value._data is null)            {                return double.NegativeInfinity;            }            var length = value._data.Length - 1;            var bitCount = -1;            for (var curBit = 31; curBit >= 0; curBit--)            {                if ((value._data[length] & (1 << curBit)) != 0)                {                    bitCount = curBit + (length * 32);                    break;                }            }            long bitlen = bitCount;            double c = 0, d = 1;            var testBit = One;            var tempBitlen = bitlen;            while (tempBitlen > int.MaxValue)            {                testBit <<= int.MaxValue;                tempBitlen -= int.MaxValue;            }            testBit <<= (int)tempBitlen;            for (var curbit = bitlen; curbit >= 0; --curbit)            {                if ((value & testBit)._sign != 0)                {                    c += d;                }                d *= 0.5;                testBit >>= 1;            }            return (Math.Log(c) + (Math.Log(2) * bitlen)) / Math.Log(baseValue);        }        /// <summary>        /// Returns the natural (base <c>e</c>) logarithm of a specified number.        /// </summary>        /// <param name="value">The number whose logarithm is to be found.</param>        /// <returns>        /// The natural (base <c>e</c>) logarithm of <paramref name="value"/>.        /// </returns>        /// <exception cref="ArgumentOutOfRangeException">The base 10 log of value is out of range of the <see cref="double"/> data type.</exception>        public static double Log(BigInteger value)        {            return Log(value, Math.E);        }        /// <summary>        /// Returns the base 10 logarithm of a specified number.        /// </summary>        /// <param name="value">A number whose logarithm is to be found.</param>        /// <returns>        /// The base 10 logarithm of <paramref name="value"/>.        /// </returns>        /// <exception cref="ArgumentOutOfRangeException">The base 10 log of value is out of range of the <see cref="double"/> data type.</exception>        public static double Log10(BigInteger value)        {            return Log(value, 10);        }        /// <summary>        /// Returns the hash code for the current <see cref="BigInteger"/> object.        /// </summary>        /// <returns>        /// A 32-bit signed integer hash code.        /// </returns>        public override readonly int GetHashCode()        {            var hash = (uint)(_sign * 0x01010101u);            if (_data != null)            {                foreach (var bit in _data)                {                    hash ^= bit;                }            }            return (int)hash;        }        /// <summary>        /// Adds two <see cref="BigInteger"/> values and returns the result.        /// </summary>        /// <param name="left">The first value to add.</param>        /// <param name="right">The second value to add.</param>        /// <returns>        /// The sum of <paramref name="left"/> and <paramref name="right"/>.        /// </returns>        public static BigInteger Add(BigInteger left, BigInteger right)        {            return left + right;        }        /// <summary>        /// Subtracts one <see cref="BigInteger"/> value from another and returns the result.        /// </summary>        /// <param name="left">The value to subtract from (the minuend).</param>        /// <param name="right">The value to subtract (the subtrahend).</param>        /// <returns>        /// The result of subtracting <paramref name="right"/> from <paramref name="left"/>.        /// </returns>        public static BigInteger Subtract(BigInteger left, BigInteger right)        {            return left - right;        }        /// <summary>        /// Returns the product of two <see cref="BigInteger"/> values.        /// </summary>        /// <param name="left">The first number to multiply.</param>        /// <param name="right">The second number to multiply.</param>        /// <returns>        /// The product of the <paramref name="left"/> and <paramref name="right"/> parameters.        /// </returns>        public static BigInteger Multiply(BigInteger left, BigInteger right)        {            return left * right;        }        /// <summary>        /// Divides one <see cref="BigInteger"/> value by another and returns the result.        /// </summary>        /// <param name="dividend">The value to be divided.</param>        /// <param name="divisor">The value to divide by.</param>        /// <returns>        /// The quotient of the division.        /// </returns>        public static BigInteger Divide(BigInteger dividend, BigInteger divisor)        {            return dividend / divisor;        }        /// <summary>        /// Performs integer division on two <see cref="BigInteger"/> values and returns the remainder.        /// </summary>        /// <param name="dividend">The value to be divided.</param>        /// <param name="divisor">The value to divide by.</param>        /// <returns>        /// The remainder after dividing <paramref name="dividend"/> by <paramref name="divisor"/>.        /// </returns>        public static BigInteger Remainder(BigInteger dividend, BigInteger divisor)        {            return dividend % divisor;        }        /// <summary>        /// Negates a specified <see cref="BigInteger"/> value.        /// </summary>        /// <param name="value">The value to negate.</param>        /// <returns>        /// The result of the <paramref name="value"/> parameter multiplied by negative one (-1).        /// </returns>        public static BigInteger Negate(BigInteger value)        {            return -value;        }        /// <summary>        /// Compares this instance to a specified object and returns an integer that indicates whether the value of        /// this instance is less than, equal to, or greater than the value of the specified object.        /// </summary>        /// <param name="obj">The object to compare.</param>        /// <returns>        /// A signed integer that indicates the relationship of the current instance to the <paramref name="obj"/> parameter,        /// as shown in the following table.        /// <list type="table">        ///     <listheader>        ///         <term>Value</term>        ///         <description>Condition</description>        ///     </listheader>        ///     <item>        ///         <term>Less than zero</term>        ///         <description>The current instance is less than <paramref name="obj"/>.</description>        ///     </item>        ///     <item>        ///         <term>Zero</term>        ///         <description>The current instance equals <paramref name="obj"/>.</description>        ///     </item>        ///     <item>        ///         <term>Greater than zero</term>        ///         <description>The current instance is greater than <paramref name="obj"/>.</description>        ///     </item>        /// </list>        /// </returns>        /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="BigInteger"/>.</exception>        public readonly int CompareTo(object obj)        {            if (obj is null)            {                return 1;            }            if (obj is not BigInteger other)            {                return -1;            }            return Compare(this, other);        }        /// <summary>        /// Compares this instance to a second <see cref="BigInteger"/> and returns an integer that indicates whether the        /// value of this instance is less than, equal to, or greater than the value of the specified object.        /// </summary>        /// <param name="other">The object to compare.</param>        /// <returns>        /// A signed integer value that indicates the relationship of this instance to <paramref name="other"/>, as        /// shown in the following table.        /// <list type="table">        ///     <listheader>        ///         <term>Value</term>        ///         <description>Condition</description>        ///     </listheader>        ///     <item>        ///         <term>Less than zero</term>        ///         <description>The current instance is less than <paramref name="other"/>.</description>        ///     </item>        ///     <item>        ///         <term>Zero</term>        ///         <description>The current instance equals <paramref name="other"/>.</description>        ///     </item>        ///     <item>        ///         <term>Greater than zero</term>        ///         <description>The current instance is greater than <paramref name="other"/>.</description>        ///     </item>        /// </list>        /// </returns>        public readonly int CompareTo(BigInteger other)        {            return Compare(this, other);        }        /// <summary>        /// Compares this instance to an unsigned 64-bit integer and returns an integer that indicates whether the value of this        /// instance is less than, equal to, or greater than the value of the unsigned 64-bit integer.        /// </summary>        /// <param name="other">The unsigned 64-bit integer to compare.</param>        /// <returns>        /// A signed integer that indicates the relative value of this instance and <paramref name="other"/>, as shown        /// in the following table.        /// <list type="table">        ///     <listheader>        ///         <term>Value</term>        ///         <description>Condition</description>        ///     </listheader>        ///     <item>        ///         <term>Less than zero</term>        ///         <description>The current instance is less than <paramref name="other"/>.</description>        ///     </item>        ///     <item>        ///         <term>Zero</term>        ///         <description>The current instance equals <paramref name="other"/>.</description>        ///     </item>        ///     <item>        ///         <term>Greater than zero</term>        ///         <description>The current instance is greater than <paramref name="other"/>.</description>        ///     </item>        /// </list>        /// </returns>        [CLSCompliant(false)]        public readonly int CompareTo(ulong other)        {            if (_sign < 0)            {                return -1;            }            if (_sign == 0)            {                return other == 0 ? 0 : -1;            }            if (_data.Length > 2)            {                return 1;            }            var high = (uint)(other >> 32);            var low = (uint)other;            return LongCompare(low, high);        }        /// <summary>        /// Compares this instance to a signed 64-bit integer and returns an integer that indicates whether the value of this        /// instance is less than, equal to, or greater than the value of the signed 64-bit integer.        /// </summary>        /// <param name="other">The signed 64-bit integer to compare.</param>        /// <returns>        /// A signed integer that indicates the relative value of this instance and <paramref name="other"/>, as shown        /// in the following table.        /// <list type="table">        ///     <listheader>        ///         <term>Value</term>        ///         <description>Condition</description>        ///     </listheader>        ///     <item>        ///         <term>Less than zero</term>        ///         <description>The current instance is less than <paramref name="other"/>.</description>        ///     </item>        ///     <item>        ///         <term>Zero</term>        ///         <description>The current instance equals <paramref name="other"/>.</description>        ///     </item>        ///     <item>        ///         <term>Greater than zero</term>        ///         <description>The current instance is greater than <paramref name="other"/>.</description>        ///     </item>        /// </list>        /// </returns>        public readonly int CompareTo(long other)        {            int ls = _sign;            var rs = Math.Sign(other);            if (ls != rs)            {                return ls > rs ? 1 : -1;            }            if (ls == 0)            {                return 0;            }            if (_data.Length > 2)            {                return _sign;            }            if (other < 0)            {                other = -other;            }            var low = (uint)other;            var high = (uint)((ulong)other >> 32);            var r = LongCompare(low, high);            if (ls == -1)            {                r = -r;            }            return r;        }        private readonly int LongCompare(uint low, uint high)        {            uint h = 0;            if (_data.Length > 1)            {                h = _data[1];            }            if (h > high)            {                return 1;            }            if (h < high)            {                return -1;            }            var l = _data[0];            if (l > low)            {                return 1;            }            if (l < low)            {                return -1;            }            return 0;        }        /// <summary>        /// Compares two <see cref="BigInteger"/> values and returns an integer that indicates whether the first value is less than, equal to, or greater than the second value.        /// </summary>        /// <param name="left">The first value to compare.</param>        /// <param name="right">The second value to compare.</param>        /// <returns>        /// A signed integer that indicates the relative values of left and right, as shown in the following table.        /// <list type="table">        ///     <listheader>        ///         <term>Value</term>        ///         <description>Condition</description>        ///     </listheader>        ///     <item>        ///         <term>Less than zero</term>        ///         <description><paramref name="left"/> is less than <paramref name="right"/>.</description>        ///     </item>        ///     <item>        ///         <term>Zero</term>        ///         <description><paramref name="left"/> equals <paramref name="right"/>.</description>        ///     </item>        ///     <item>        ///         <term>Greater than zero</term>        ///         <description><paramref name="left"/> is greater than <paramref name="right"/>.</description>        ///     </item>        /// </list>        /// </returns>        public static int Compare(BigInteger left, BigInteger right)        {            int ls = left._sign;            int rs = right._sign;            if (ls != rs)            {                return ls > rs ? 1 : -1;            }            var r = CoreCompare(left._data, right._data);            if (ls < 0)            {                r = -r;            }            return r;        }        private static int TopByte(uint x)        {            if ((x & 0xFFFF0000u) != 0)            {                if ((x & 0xFF000000u) != 0)                {                    return 4;                }                return 3;            }            if ((x & 0xFF00u) != 0)            {                return 2;            }            return 1;        }        private static int FirstNonFfByte(uint word)        {            if ((word & 0xFF000000u) != 0xFF000000u)            {                return 4;            }            if ((word & 0xFF0000u) != 0xFF0000u)            {                return 3;            }            if ((word & 0xFF00u) != 0xFF00u)            {                return 2;            }            return 1;        }        /// <summary>        /// Converts a <see cref="BigInteger"/> value to a byte array.        /// </summary>        /// <returns>        /// The value of the current <see cref="BigInteger"/> object converted to an array of bytes.        /// </returns>        public readonly byte[] ToByteArray()        {            if (_sign == 0)            {                return new byte[1];            }            // number of bytes not counting upper word            var bytes = (_data.Length - 1) * 4;            var needExtraZero = false;            var topWord = _data[_data.Length - 1];            int extra;            // if the topmost bit is set we need an extra            if (_sign == 1)            {                extra = TopByte(topWord);                var mask = 0x80u << ((extra - 1) * 8);                if ((topWord & mask) != 0)                {                    needExtraZero = true;                }            }            else            {                extra = TopByte(topWord);            }            var res = new byte[bytes + extra + (needExtraZero ? 1 : 0)];            if (_sign == 1)            {                var j = 0;                var end = _data.Length - 1;                for (var i = 0; i < end; ++i)                {                    var word = _data[i];                    res[j++] = (byte)word;                    res[j++] = (byte)(word >> 8);                    res[j++] = (byte)(word >> 16);                    res[j++] = (byte)(word >> 24);                }                while (extra-- > 0)                {                    res[j++] = (byte)topWord;                    topWord >>= 8;                }            }            else            {                var j = 0;                var end = _data.Length - 1;                uint carry = 1, word;                ulong add;                for (var i = 0; i < end; ++i)                {                    word = _data[i];                    add = (ulong)~word + carry;                    word = (uint)add;                    carry = (uint)(add >> 32);                    res[j++] = (byte)word;                    res[j++] = (byte)(word >> 8);                    res[j++] = (byte)(word >> 16);                    res[j++] = (byte)(word >> 24);                }                add = (ulong)~topWord + carry;                word = (uint)add;                carry = (uint)(add >> 32);                if (carry == 0)                {                    var ex = FirstNonFfByte(word);                    var needExtra = (word & (1 << ((ex * 8) - 1))) == 0;                    var to = ex + (needExtra ? 1 : 0);                    if (to != extra)                    {                        Array.Resize(ref res, bytes + to);                    }                    while (ex-- > 0)                    {                        res[j++] = (byte)word;                        word >>= 8;                    }                    if (needExtra)                    {                        res[j++] = 0xFF;                    }                }                else                {                    Array.Resize(ref res, bytes + 5);                    res[j++] = (byte)word;                    res[j++] = (byte)(word >> 8);                    res[j++] = (byte)(word >> 16);                    res[j++] = (byte)(word >> 24);                    res[j++] = 0xFF;                }            }            return res;        }        private static uint[] CoreAdd(uint[] a, uint[] b)        {            if (a.Length < b.Length)            {                var tmp = a;                a = b;                b = tmp;            }            var bl = a.Length;            var sl = b.Length;            var res = new uint[bl];            ulong sum = 0;            var i = 0;            for (; i < sl; i++)            {                sum = sum + a[i] + b[i];                res[i] = (uint)sum;                sum >>= 32;            }            for (; i < bl; i++)            {                sum += a[i];                res[i] = (uint)sum;                sum >>= 32;            }            if (sum != 0)            {                Array.Resize(ref res, bl + 1);                res[i] = (uint)sum;            }            return res;        }        private static uint[] CoreAdd(uint[] a, uint b)        {            var len = a.Length;            var res = new uint[len];            ulong sum = b;            int i;            for (i = 0; i < len; i++)            {                sum += a[i];                res[i] = (uint)sum;                sum >>= 32;            }            if (sum != 0)            {                Array.Resize(ref res, len + 1);                res[i] = (uint)sum;            }            return res;        }        /*invariant a > b*/        private static uint[] CoreSub(uint[] a, uint[] b)        {            var bl = a.Length;            var sl = b.Length;            var res = new uint[bl];            ulong borrow = 0;            int i;            for (i = 0; i < sl; ++i)            {                borrow = (ulong)a[i] - b[i] - borrow;                res[i] = (uint)borrow;                borrow = (borrow >> 32) & 0x1;            }            for (; i < bl; i++)            {                borrow = (ulong)a[i] - borrow;                res[i] = (uint)borrow;                borrow = (borrow >> 32) & 0x1;            }            // remove extra zeroes            for (i = bl - 1; i >= 0 && res[i] == 0; --i)            {                // Intentionally empty block            }            if (i < bl - 1)            {                Array.Resize(ref res, i + 1);            }            return res;        }        private static uint[] CoreSub(uint[] a, uint b)        {            var len = a.Length;            var res = new uint[len];            ulong borrow = b;            int i;            for (i = 0; i < len; i++)            {                borrow = (ulong)a[i] - borrow;                res[i] = (uint)borrow;                borrow = (borrow >> 32) & 0x1;            }            // Remove extra zeroes            for (i = len - 1; i >= 0 && res[i] == 0; --i)            {                // Intentionally empty block            }            if (i < len - 1)            {                Array.Resize(ref res, i + 1);            }            return res;        }        private static int CoreCompare(uint[] a, uint[] b)        {            var al = a != null ? a.Length : 0;            var bl = b != null ? b.Length : 0;            if (al > bl)            {                return 1;            }            if (bl > al)            {                return -1;            }            for (var i = al - 1; i >= 0; --i)            {                var ai = a[i];                var bi = b[i];                if (ai > bi)                {                    return 1;                }                if (ai < bi)                {                    return -1;                }            }            return 0;        }        private static int GetNormalizeShift(uint value)        {            var shift = 0;            if ((value & 0xFFFF0000) == 0)            {                value <<= 16;                shift += 16;            }            if ((value & 0xFF000000) == 0)            {                value <<= 8;                shift += 8;            }            if ((value & 0xF0000000) == 0)            {                value <<= 4;                shift += 4;            }            if ((value & 0xC0000000) == 0)            {                value <<= 2;                shift += 2;            }            if ((value & 0x80000000) == 0)            {#pragma warning disable IDE0059 // Unnecessary assignment of a value                value <<= 1;#pragma warning restore IDE0059 // Unnecessary assignment of a value                shift += 1;            }            return shift;        }        private static void Normalize(uint[] u, int l, uint[] un, int shift)        {            uint carry = 0;            int i;            if (shift > 0)            {                var rshift = 32 - shift;                for (i = 0; i < l; i++)                {                    var ui = u[i];                    un[i] = (ui << shift) | carry;                    carry = ui >> rshift;                }            }            else            {                for (i = 0; i < l; i++)                {                    un[i] = u[i];                }            }            while (i < un.Length)            {                un[i++] = 0;            }            if (carry != 0)            {                un[l] = carry;            }        }        private static void Unnormalize(uint[] un, out uint[] r, int shift)        {            var length = un.Length;            r = new uint[length];            if (shift > 0)            {                var lshift = 32 - shift;                uint carry = 0;                for (var i = length - 1; i >= 0; i--)                {                    var uni = un[i];                    r[i] = (uni >> shift) | carry;                    carry = uni << lshift;                }            }            else            {                for (var i = 0; i < length; i++)                {                    r[i] = un[i];                }            }        }        private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r)        {            var m = u.Length;            var n = v.Length;            if (n <= 1)            {                // Divide by single digit                ulong rem = 0;                var v0 = v[0];                q = new uint[m];                r = new uint[1];                for (var j = m - 1; j >= 0; j--)                {                    rem *= Base;                    rem += u[j];                    var div = rem / v0;                    rem -= div * v0;                    q[j] = (uint)div;                }                r[0] = (uint)rem;            }            else if (m >= n)            {                var shift = GetNormalizeShift(v[n - 1]);                var un = new uint[m + 1];                var vn = new uint[n];                Normalize(u, m, un, shift);                Normalize(v, n, vn, shift);                q = new uint[m - n + 1];                // Main division loop                for (var j = m - n; j >= 0; j--)                {                    int i;                    var rr = (Base * un[j + n]) + un[j + n - 1];                    var qq = rr / vn[n - 1];                    rr -= qq * vn[n - 1];                    for (; ; )                    {                        // Estimate too big ?                        if ((qq >= Base) || (qq * vn[n - 2] > ((rr * Base) + un[j + n - 2])))                        {                            qq--;                            rr += (ulong)vn[n - 1];                            if (rr < Base)                            {                                continue;                            }                        }                        break;                    }                    // Multiply and subtract                    long b = 0;                    long t;                    for (i = 0; i < n; i++)                    {                        var p = vn[i] * qq;                        t = (long)un[i + j] - (long)(uint)p - b;                        un[i + j] = (uint)t;                        p >>= 32;                        t >>= 32;                        b = (long)p - t;                    }                    t = (long)un[j + n] - b;                    un[j + n] = (uint)t;                    // Store the calculated value                    q[j] = (uint)qq;                    // Add back vn[0..n] to un[j..j+n]                    if (t < 0)                    {                        q[j]--;                        ulong c = 0;                        for (i = 0; i < n; i++)                        {                            c = (ulong)vn[i] + un[j + i] + c;                            un[j + i] = (uint)c;                            c >>= 32;                        }                        c += (ulong)un[j + n];                        un[j + n] = (uint)c;                    }                }                Unnormalize(un, out r, shift);            }            else            {                q = new uint[] { 0 };                r = u;            }        }    }}
 |