| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226 |
- //
- // 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.
- *
- *
- * ***************************************************************************/
- //
- // slashdocs based on MSDN
- using System;
- using System.Collections.Generic;
- using System.Diagnostics.CodeAnalysis;
- using System.Globalization;
- using System.Threading;
- using Renci.SshNet.Security.Cryptography;
- /*
- 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>
- [SuppressMessage("ReSharper", "EmptyEmbeddedStatement")]
- [SuppressMessage("ReSharper", "RedundantCast")]
- [SuppressMessage("ReSharper", "RedundantAssignment")]
- [SuppressMessage("ReSharper", "SuggestBaseTypeForParameter")]
- [SuppressMessage("ReSharper", "MergeConditionalExpression")]
- public struct BigInteger : IComparable, IFormattable, IComparable<BigInteger>, IEquatable<BigInteger>
- {
- private static readonly BigInteger ZeroSingleton = new BigInteger(0);
- private static readonly BigInteger OneSingleton = new BigInteger(1);
- private static readonly BigInteger MinusOneSingleton = new BigInteger(-1);
- private const ulong Base = 0x100000000;
- private const int Bias = 1075;
- private const int DecimalSignMask = unchecked((int) 0x80000000);
- //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 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 random <see cref="BigInteger"/> number.
- /// </summary>
- /// <param name="bitLength">Length of random number in bits.</param>
- /// <returns>
- /// A random number.
- /// </returns>
- public static BigInteger Random(int bitLength)
- {
- var bytesArray = new byte[bitLength / 8 + (((bitLength % 8) > 0) ? 1 : 0)];
- HashAlgorithmFactory.GenerateRandom(bytesArray);
- 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;
- }
- }
- 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)((ulong)i1 | ((ulong)i2 << 32));
- }
- /// <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 = 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 <c>null</c>.</exception>
- [CLSCompliant(false)]
- public BigInteger(byte[] value)
- {
- if (value == null)
- throw new ArgumentNullException("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;
- if (_sign == 1)
- {
- 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) //FIXME I believe this can't happen, can someone write a test for it?
- throw new Exception("non zero final carry");
- }
- }
- /// <summary>
- /// Indicates whether the value of the current <see cref="BigInteger"/> object is an even number.
- /// </summary>
- /// <value>
- /// <c>true</c> if the value of the BigInteger object is an even number; otherwise, <c>false</c>.
- /// </value>
- public bool IsEven
- {
- get { return _sign == 0 || (_data[0] & 0x1) == 0; }
- }
- /// <summary>
- /// Indicates whether the value of the current <see cref="BigInteger"/> object is <see cref="One"/>.
- /// </summary>
- /// <value>
- /// <c>true</c> if the value of the <see cref="BigInteger"/> object is <see cref="One"/>;
- /// otherwise, <c>false</c>.
- /// </value>
- public 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
- static int PopulationCount(uint x)
- {
- x = x - ((x >> 1) & 0x55555555);
- x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
- x = (x + (x >> 4)) & 0x0F0F0F0F;
- x = x + (x >> 8);
- x = x + (x >> 16);
- return (int)(x & 0x0000003F);
- }
- //Based on code by Zilong Tan on Ulib released under MIT license
- //Returns the number of bits set in @x
- 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);
- }
- 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
- }
- 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
- }
- 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 = 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>
- /// Indicates whether the value of the current <see cref="BigInteger"/> object is a power of two.
- /// </summary>
- /// <value>
- /// <c>true</c> if the value of the <see cref="BigInteger"/> object is a power of two;
- /// otherwise, <c>false</c>.
- /// </value>
- public bool IsPowerOfTwo
- {
- get
- {
- var foundBit = false;
- if (_sign != 1)
- return 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>
- /// Indicates whether the value of the current <see cref="BigInteger"/> object is <see cref="Zero"/>.
- /// </summary>
- /// <value>
- /// <c>true</c> if the value of the <see cref="BigInteger"/> object is <see cref="Zero"/>;
- /// otherwise, <c>false</c>.
- /// </value>
- public 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 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>
- public static explicit operator int(BigInteger value)
- {
- if (value._data == 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)]
- public static explicit operator uint(BigInteger value)
- {
- if (value._data == 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>
- public static explicit operator short(BigInteger value)
- {
- var val = (int)value;
- if (val < short.MinValue || val > short.MaxValue)
- throw new OverflowException();
- return (short)val;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="value"></param>
- /// <returns>
- /// An object that contains the value of the <paramref name="value"/> parameter.
- /// </returns>
- [CLSCompliantAttribute(false)]
- public static explicit operator ushort(BigInteger value)
- {
- 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>
- public static explicit operator byte(BigInteger value)
- {
- 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)]
- public static explicit operator sbyte(BigInteger value)
- {
- var val = (int)value;
- if (val < sbyte.MinValue || val > 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>
- public static explicit operator long(BigInteger value)
- {
- if (value._data == 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)]
- public static explicit operator ulong(BigInteger value)
- {
- if (value._data == 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>
- public static explicit operator double(BigInteger value)
- {
- if (value._data == 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>
- public static explicit operator float(BigInteger value)
- {
- 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>
- public static explicit operator decimal(BigInteger value)
- {
- if (value._data == 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>
- public static implicit operator BigInteger(int value)
- {
- 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)]
- public static implicit operator BigInteger(uint value)
- {
- 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>
- public static implicit operator BigInteger(short value)
- {
- 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>
- [CLSCompliantAttribute(false)]
- public static implicit operator BigInteger(ushort value)
- {
- 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>
- public static implicit operator BigInteger(byte value)
- {
- return new BigInteger(value);
- }
- /// <summary>
- ///
- /// </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)]
- public static implicit operator BigInteger(sbyte value)
- {
- 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>
- public static implicit operator BigInteger(long value)
- {
- 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)]
- public static implicit operator BigInteger(ulong value)
- {
- 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>
- public static explicit operator BigInteger(double value)
- {
- 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>
- public static explicit operator BigInteger(float value)
- {
- 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>
- public static explicit operator BigInteger(decimal value)
- {
- 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) ;
- 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;
- uint[] quotient;
- uint[] remainderValue;
- DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue);
- int i;
- for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) ;
- 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;
- uint[] quotient;
- uint[] remainderValue;
- DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue);
- int i;
- for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) ;
- 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 == 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>
- public static BigInteger operator +(BigInteger value)
- {
- 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>
- public static BigInteger operator ++(BigInteger value)
- {
- if (value._data == 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>
- public static BigInteger operator --(BigInteger value)
- {
- if (value._data == 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>
- public static BigInteger operator &(BigInteger left, BigInteger right)
- {
- 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) ;
- 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>
- public static BigInteger operator |(BigInteger left, BigInteger right)
- {
- 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) ;
- 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>
- public static BigInteger operator ^(BigInteger left, BigInteger right)
- {
- 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) ;
- 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>
- public static BigInteger operator ~(BigInteger value)
- {
- if (value._data == 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) ;
- 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);
- }
- //returns the 0-based index of the most significant set bit
- //returns 0 if no bit is set, so extra care when using it
- 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>
- public static BigInteger operator <<(BigInteger value, int shift)
- {
- if (shift == 0 || value._data == 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>
- public static BigInteger operator >>(BigInteger value, int shift)
- {
- 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)
- {
- if (sign == 1)
- return Zero;
- return 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>
- /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if left is <paramref name="left"/> than <paramref name="right"/>; otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
- /// otherwise, <c>false</c>.
- /// </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>
- /// <c>true</c> 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, <c>false</c>.
- /// </returns>
- public override bool Equals(object obj)
- {
- if (!(obj is BigInteger))
- return false;
- return Equals((BigInteger)obj);
- }
- /// <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>
- /// <c>true</c> if this <see cref="BigInteger"/> object and <paramref name="other"/> have the same value;
- /// otherwise, <c>false</c>.
- /// </returns>
- public 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>
- /// <c>true</c> if the signed 64-bit integer and the current instance have the same value; otherwise, <c>false</c>.
- /// </returns>
- public bool Equals(long 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 string ToString()
- {
- return ToString(10, null);
- }
- private 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;
- }
- return "-" + additional + baseStr.Substring(1);
- }
- return baseStr;
- }
- return ToString(radix, provider);
- }
- /// <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 string ToString(string format)
- {
- return ToString(format, 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 string ToString(IFormatProvider provider)
- {
- return ToString(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="provider">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="provider"/> parameters.
- /// </returns>
- public string ToString(string format, IFormatProvider provider)
- {
- if (string.IsNullOrEmpty(format))
- return ToString(10, provider);
- switch (format[0])
- {
- case 'd':
- case 'D':
- case 'g':
- case 'G':
- case 'r':
- case 'R':
- return ToStringWithPadding(format, 10, provider);
- case 'x':
- case 'X':
- return ToStringWithPadding(format, 16, null);
- default:
- throw new FormatException(string.Format("format '{0}' not implemented", format));
- }
- }
- 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 string ToString(uint radix, IFormatProvider provider)
- {
- const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- if (characterSet.Length < radix)
- throw new ArgumentException("charSet length less than radix", "characterSet");
- if (radix == 1)
- throw new ArgumentException("There is no such thing as radix one notation", "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)
- {
- BigInteger rem;
- a = DivRem(a, radix, out 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 <c>null</c>.</exception>
- /// <exception cref="FormatException"><paramref name="value"/> is not in the correct format.</exception>
- public static BigInteger Parse(string value)
- {
- Exception ex;
- BigInteger result;
- if (!Parse(value, false, out result, out 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 <c>null</c>.</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, 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 <c>null</c>.</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 <c>null</c>.</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)
- {
- Exception exc;
- BigInteger res;
- if (!Parse(value, style, provider, false, out res, out 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 <c>null</c> or is not of the correct format. This parameter is passed uninitialized.</param>
- /// <returns>
- /// <c>true</c> if <paramref name="value"/> was converted successfully; otherwise, <c>false</c>.
- /// </returns>
- /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
- public static bool TryParse(string value, out BigInteger result)
- {
- Exception ex;
- return Parse(value, true, out result, out ex);
- }
- /// <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 <c>null</c> or is not of the correct format. This parameter is passed uninitialized.</param>
- /// <returns>
- /// <c>true</c> if <paramref name="value"/> was converted successfully; otherwise, <c>false</c>.
- /// </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)
- {
- Exception exc;
- if (!Parse(value, style, provider, true, out result, out exc))
- {
- result = Zero;
- return false;
- }
- return true;
- }
- private static bool Parse(string value, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)
- {
- result = Zero;
- exc = null;
- if (value == null)
- {
- if (!tryParse)
- exc = new ArgumentNullException("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);
- }
- if (nfi == null)
- nfi = NumberFormatInfo.CurrentInfo;
- if (!CheckStyle(style, tryParse, ref exc))
- return false;
- var allowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
- var allowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
- var allowThousands = (style & NumberStyles.AllowThousands) != 0;
- var allowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
- var allowParentheses = (style & NumberStyles.AllowParentheses) != 0;
- var allowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
- var allowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
- var allowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
- var allowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
- var allowExponent = (style & NumberStyles.AllowExponent) != 0;
- var pos = 0;
- if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, 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, 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, true, tryParse, ref exc))
- return false;
- if (allowCurrencySymbol)
- {
- FindCurrency(ref pos, value, nfi,
- ref foundCurrency);
- if (foundCurrency && allowLeadingWhite &&
- !JumpOverWhitespace(ref pos, value, 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, 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, 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, true, tryParse, ref exc))
- return false;
- }
- }
- if (allowCurrencySymbol && !foundCurrency)
- {
- if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, 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, 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, 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, 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
- //
- BigInteger remainder;
- number = DivRem(number, Pow(10, -exponent), out remainder);
- if (!remainder.IsZero)
- {
- if (!tryParse)
- exc = new OverflowException("Value too large or too small. exp=" + exponent + " rem = " + remainder + " pow = " + 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) != 0)
- {
- var ne = style ^ NumberStyles.AllowHexSpecifier;
- if ((ne & NumberStyles.AllowLeadingWhite) != 0)
- ne ^= NumberStyles.AllowLeadingWhite;
- if ((ne & NumberStyles.AllowTrailingWhite) != 0)
- ne ^= NumberStyles.AllowTrailingWhite;
- if (ne != 0)
- {
- 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 - (int)(s[i] - '0'));
- if (exp < int.MinValue || exp > 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 Exception 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 == null)
- {
- if (!tryParse)
- exc = new ArgumentNullException("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 >= '0' && c <= '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;
- else if (sign == -1)
- 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((short)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;
- }
- uint[] quotient;
- uint[] remainderValue;
- DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue);
- int i;
- for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) ;
- 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) ;
- 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("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 = result * value;
- if (exponent == 1)
- break;
- value = 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("exponent", "power must be >= 0");
- if (modulus._sign == 0)
- throw new DivideByZeroException();
- var result = One % modulus;
- while (exponent._sign != 0)
- {
- if (!exponent.IsEven)
- {
- result = result * value;
- result = result % modulus;
- }
- if (exponent.IsOne)
- break;
- value = value * 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 == 0.0d || baseValue == double.PositiveInfinity)
- return value.IsOne ? 0 : double.NaN;
- if (value._data == 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 = testBit << int.MaxValue;
- tempBitlen -= int.MaxValue;
- }
- testBit = testBit << (int)tempBitlen;
- for (var curbit = bitlen; curbit >= 0; --curbit)
- {
- if ((value & testBit)._sign != 0)
- c += d;
- d *= 0.5;
- testBit = 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 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>
- /// <c>true</c> if the current instance and the unsigned 64-bit integer have the same value; otherwise, <c>false</c>.
- /// </returns>
- [CLSCompliant(false)]
- public bool Equals(ulong other)
- {
- return CompareTo(other) == 0;
- }
- /// <summary>
- /// Returns the hash code for the current <see cref="BigInteger"/> object.
- /// </summary>
- /// <returns>
- /// A 32-bit signed integer hash code.
- /// </returns>
- public override 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 int CompareTo(object obj)
- {
- if (obj == null)
- return 1;
- if (!(obj is BigInteger))
- return -1;
- return Compare(this, (BigInteger)obj);
- }
- /// <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 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 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);
- }
- private 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 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 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;
- }
- /// <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 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 = sum + a[i];
- res[i] = (uint)sum;
- sum >>= 32;
- }
- if (sum != 0)
- {
- Array.Resize(ref res, bl + 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) ;
- if (i < bl - 1)
- Array.Resize(ref res, i + 1);
- 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 = sum + a[i];
- res[i] = (uint)sum;
- sum >>= 32;
- }
- if (sum != 0)
- {
- Array.Resize(ref res, len + 1);
- res[i] = (uint)sum;
- }
- 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) ;
- 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) { value <<= 1; 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];
- r = null;
- // 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 = 0;
- 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;
- }
- }
- }
- }
|