12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Globalization;
- using System.Text;
- using Org.BouncyCastle.Security;
- using Org.BouncyCastle.Utilities;
- namespace Org.BouncyCastle.Math
- {
- #if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT || NETFX_CORE || PORTABLE)
- [Serializable]
- #endif
- public class BigInteger
- {
- // The first few odd primes
- /*
- 3 5 7 11 13 17 19 23 29
- 31 37 41 43 47 53 59 61 67 71
- 73 79 83 89 97 101 103 107 109 113
- 127 131 137 139 149 151 157 163 167 173
- 179 181 191 193 197 199 211 223 227 229
- 233 239 241 251 257 263 269 271 277 281
- 283 293 307 311 313 317 331 337 347 349
- 353 359 367 373 379 383 389 397 401 409
- 419 421 431 433 439 443 449 457 461 463
- 467 479 487 491 499 503 509 521 523 541
- 547 557 563 569 571 577 587 593 599 601
- 607 613 617 619 631 641 643 647 653 659
- 661 673 677 683 691 701 709 719 727 733
- 739 743 751 757 761 769 773 787 797 809
- 811 821 823 827 829 839 853 857 859 863
- 877 881 883 887 907 911 919 929 937 941
- 947 953 967 971 977 983 991 997 1009
- 1013 1019 1021 1031 1033 1039 1049 1051
- 1061 1063 1069 1087 1091 1093 1097 1103
- 1109 1117 1123 1129 1151 1153 1163 1171
- 1181 1187 1193 1201 1213 1217 1223 1229
- 1231 1237 1249 1259 1277 1279 1283 1289
- */
- // Each list has a product < 2^31
- internal static readonly int[][] primeLists = new int[][]
- {
- new int[]{ 3, 5, 7, 11, 13, 17, 19, 23 },
- new int[]{ 29, 31, 37, 41, 43 },
- new int[]{ 47, 53, 59, 61, 67 },
- new int[]{ 71, 73, 79, 83 },
- new int[]{ 89, 97, 101, 103 },
- new int[]{ 107, 109, 113, 127 },
- new int[]{ 131, 137, 139, 149 },
- new int[]{ 151, 157, 163, 167 },
- new int[]{ 173, 179, 181, 191 },
- new int[]{ 193, 197, 199, 211 },
- new int[]{ 223, 227, 229 },
- new int[]{ 233, 239, 241 },
- new int[]{ 251, 257, 263 },
- new int[]{ 269, 271, 277 },
- new int[]{ 281, 283, 293 },
- new int[]{ 307, 311, 313 },
- new int[]{ 317, 331, 337 },
- new int[]{ 347, 349, 353 },
- new int[]{ 359, 367, 373 },
- new int[]{ 379, 383, 389 },
- new int[]{ 397, 401, 409 },
- new int[]{ 419, 421, 431 },
- new int[]{ 433, 439, 443 },
- new int[]{ 449, 457, 461 },
- new int[]{ 463, 467, 479 },
- new int[]{ 487, 491, 499 },
- new int[]{ 503, 509, 521 },
- new int[]{ 523, 541, 547 },
- new int[]{ 557, 563, 569 },
- new int[]{ 571, 577, 587 },
- new int[]{ 593, 599, 601 },
- new int[]{ 607, 613, 617 },
- new int[]{ 619, 631, 641 },
- new int[]{ 643, 647, 653 },
- new int[]{ 659, 661, 673 },
- new int[]{ 677, 683, 691 },
- new int[]{ 701, 709, 719 },
- new int[]{ 727, 733, 739 },
- new int[]{ 743, 751, 757 },
- new int[]{ 761, 769, 773 },
- new int[]{ 787, 797, 809 },
- new int[]{ 811, 821, 823 },
- new int[]{ 827, 829, 839 },
- new int[]{ 853, 857, 859 },
- new int[]{ 863, 877, 881 },
- new int[]{ 883, 887, 907 },
- new int[]{ 911, 919, 929 },
- new int[]{ 937, 941, 947 },
- new int[]{ 953, 967, 971 },
- new int[]{ 977, 983, 991 },
- new int[]{ 997, 1009, 1013 },
- new int[]{ 1019, 1021, 1031 },
- new int[]{ 1033, 1039, 1049 },
- new int[]{ 1051, 1061, 1063 },
- new int[]{ 1069, 1087, 1091 },
- new int[]{ 1093, 1097, 1103 },
- new int[]{ 1109, 1117, 1123 },
- new int[]{ 1129, 1151, 1153 },
- new int[]{ 1163, 1171, 1181 },
- new int[]{ 1187, 1193, 1201 },
- new int[]{ 1213, 1217, 1223 },
- new int[]{ 1229, 1231, 1237 },
- new int[]{ 1249, 1259, 1277 },
- new int[]{ 1279, 1283, 1289 },
- };
- internal static readonly int[] primeProducts;
- private const long IMASK = 0xFFFFFFFFL;
- private const ulong UIMASK = 0xFFFFFFFFUL;
- private static readonly int[] ZeroMagnitude = new int[0];
- private static readonly byte[] ZeroEncoding = new byte[0];
- private static readonly BigInteger[] SMALL_CONSTANTS = new BigInteger[17];
- public static readonly BigInteger Zero;
- public static readonly BigInteger One;
- public static readonly BigInteger Two;
- public static readonly BigInteger Three;
- public static readonly BigInteger Ten;
- //private readonly static byte[] BitCountTable =
- //{
- // 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
- // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- // 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
- //};
- private readonly static byte[] BitLengthTable =
- {
- 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
- };
- // TODO Parse radix-2 64 bits at a time and radix-8 63 bits at a time
- private const int chunk2 = 1, chunk8 = 1, chunk10 = 19, chunk16 = 16;
- private static readonly BigInteger radix2, radix2E, radix8, radix8E, radix10, radix10E, radix16, radix16E;
- private static readonly SecureRandom RandomSource = new SecureRandom();
- /*
- * These are the threshold bit-lengths (of an exponent) where we increase the window size.
- * They are calculated according to the expected savings in multiplications.
- * Some squares will also be saved on average, but we offset these against the extra storage costs.
- */
- private static readonly int[] ExpWindowThresholds = { 7, 25, 81, 241, 673, 1793, 4609, Int32.MaxValue };
- private const int BitsPerByte = 8;
- private const int BitsPerInt = 32;
- private const int BytesPerInt = 4;
- static BigInteger()
- {
- Zero = new BigInteger(0, ZeroMagnitude, false);
- Zero.nBits = 0; Zero.nBitLength = 0;
- SMALL_CONSTANTS[0] = Zero;
- for (uint i = 1; i < SMALL_CONSTANTS.Length; ++i)
- {
- SMALL_CONSTANTS[i] = CreateUValueOf(i);
- }
- One = SMALL_CONSTANTS[1];
- Two = SMALL_CONSTANTS[2];
- Three = SMALL_CONSTANTS[3];
- Ten = SMALL_CONSTANTS[10];
- radix2 = ValueOf(2);
- radix2E = radix2.Pow(chunk2);
- radix8 = ValueOf(8);
- radix8E = radix8.Pow(chunk8);
- radix10 = ValueOf(10);
- radix10E = radix10.Pow(chunk10);
- radix16 = ValueOf(16);
- radix16E = radix16.Pow(chunk16);
- primeProducts = new int[primeLists.Length];
- for (int i = 0; i < primeLists.Length; ++i)
- {
- int[] primeList = primeLists[i];
- int product = primeList[0];
- for (int j = 1; j < primeList.Length; ++j)
- {
- product *= primeList[j];
- }
- primeProducts[i] = product;
- }
- }
- private int[] magnitude; // array of ints with [0] being the most significant
- private int sign; // -1 means -ve; +1 means +ve; 0 means 0;
- private int nBits = -1; // cache BitCount() value
- private int nBitLength = -1; // cache BitLength() value
- private int mQuote = 0; // -m^(-1) mod b, b = 2^32 (see Montgomery mult.), 0 when uninitialised
- private static int GetByteLength(
- int nBits)
- {
- return (nBits + BitsPerByte - 1) / BitsPerByte;
- }
- internal static BigInteger Arbitrary(int sizeInBits)
- {
- return new BigInteger(sizeInBits, RandomSource);
- }
- private BigInteger(
- int signum,
- int[] mag,
- bool checkMag)
- {
- if (checkMag)
- {
- int i = 0;
- while (i < mag.Length && mag[i] == 0)
- {
- ++i;
- }
- if (i == mag.Length)
- {
- this.sign = 0;
- this.magnitude = ZeroMagnitude;
- }
- else
- {
- this.sign = signum;
- if (i == 0)
- {
- this.magnitude = mag;
- }
- else
- {
- // strip leading 0 words
- this.magnitude = new int[mag.Length - i];
- Array.Copy(mag, i, this.magnitude, 0, this.magnitude.Length);
- }
- }
- }
- else
- {
- this.sign = signum;
- this.magnitude = mag;
- }
- }
- public BigInteger(
- string value)
- : this(value, 10)
- {
- }
- public BigInteger(
- string str,
- int radix)
- {
- if (str.Length == 0)
- throw new FormatException("Zero length BigInteger");
- NumberStyles style;
- int chunk;
- BigInteger r;
- BigInteger rE;
- switch (radix)
- {
- case 2:
- // Is there anyway to restrict to binary digits?
- style = NumberStyles.Integer;
- chunk = chunk2;
- r = radix2;
- rE = radix2E;
- break;
- case 8:
- // Is there anyway to restrict to octal digits?
- style = NumberStyles.Integer;
- chunk = chunk8;
- r = radix8;
- rE = radix8E;
- break;
- case 10:
- // This style seems to handle spaces and minus sign already (our processing redundant?)
- style = NumberStyles.Integer;
- chunk = chunk10;
- r = radix10;
- rE = radix10E;
- break;
- case 16:
- // TODO Should this be HexNumber?
- style = NumberStyles.AllowHexSpecifier;
- chunk = chunk16;
- r = radix16;
- rE = radix16E;
- break;
- default:
- throw new FormatException("Only bases 2, 8, 10, or 16 allowed");
- }
- int index = 0;
- sign = 1;
- if (str[0] == '-')
- {
- if (str.Length == 1)
- throw new FormatException("Zero length BigInteger");
- sign = -1;
- index = 1;
- }
- // strip leading zeros from the string str
- while (index < str.Length && Int32.Parse(str[index].ToString(), style) == 0)
- {
- index++;
- }
- if (index >= str.Length)
- {
- // zero value - we're done
- sign = 0;
- magnitude = ZeroMagnitude;
- return;
- }
- //////
- // could we work out the max number of ints required to store
- // str.Length digits in the given base, then allocate that
- // storage in one hit?, then Generate the magnitude in one hit too?
- //////
- BigInteger b = Zero;
- int next = index + chunk;
- if (next <= str.Length)
- {
- do
- {
- string s = str.Substring(index, chunk);
- ulong i = ulong.Parse(s, style);
- BigInteger bi = CreateUValueOf(i);
- switch (radix)
- {
- case 2:
- // TODO Need this because we are parsing in radix 10 above
- if (i >= 2)
- throw new FormatException("Bad character in radix 2 string: " + s);
- // TODO Parse 64 bits at a time
- b = b.ShiftLeft(1);
- break;
- case 8:
- // TODO Need this because we are parsing in radix 10 above
- if (i >= 8)
- throw new FormatException("Bad character in radix 8 string: " + s);
- // TODO Parse 63 bits at a time
- b = b.ShiftLeft(3);
- break;
- case 16:
- b = b.ShiftLeft(64);
- break;
- default:
- b = b.Multiply(rE);
- break;
- }
- b = b.Add(bi);
- index = next;
- next += chunk;
- }
- while (next <= str.Length);
- }
- if (index < str.Length)
- {
- string s = str.Substring(index);
- ulong i = ulong.Parse(s, style);
- BigInteger bi = CreateUValueOf(i);
- if (b.sign > 0)
- {
- if (radix == 2)
- {
- // NB: Can't reach here since we are parsing one char at a time
- Debug.Assert(false);
- // TODO Parse all bits at once
- // b = b.ShiftLeft(s.Length);
- }
- else if (radix == 8)
- {
- // NB: Can't reach here since we are parsing one char at a time
- Debug.Assert(false);
- // TODO Parse all bits at once
- // b = b.ShiftLeft(s.Length * 3);
- }
- else if (radix == 16)
- {
- b = b.ShiftLeft(s.Length << 2);
- }
- else
- {
- b = b.Multiply(r.Pow(s.Length));
- }
- b = b.Add(bi);
- }
- else
- {
- b = bi;
- }
- }
- // Note: This is the previous (slower) algorithm
- // while (index < value.Length)
- // {
- // char c = value[index];
- // string s = c.ToString();
- // int i = Int32.Parse(s, style);
- //
- // b = b.Multiply(r).Add(ValueOf(i));
- // index++;
- // }
- magnitude = b.magnitude;
- }
- public BigInteger(
- byte[] bytes)
- : this(bytes, 0, bytes.Length)
- {
- }
- public BigInteger(
- byte[] bytes,
- int offset,
- int length)
- {
- if (length == 0)
- throw new FormatException("Zero length BigInteger");
- // TODO Move this processing into MakeMagnitude (provide sign argument)
- if ((sbyte)bytes[offset] < 0)
- {
- this.sign = -1;
- int end = offset + length;
- int iBval;
- // strip leading sign bytes
- for (iBval = offset; iBval < end && ((sbyte)bytes[iBval] == -1); iBval++)
- {
- }
- if (iBval >= end)
- {
- this.magnitude = One.magnitude;
- }
- else
- {
- int numBytes = end - iBval;
- byte[] inverse = new byte[numBytes];
- int index = 0;
- while (index < numBytes)
- {
- inverse[index++] = (byte)~bytes[iBval++];
- }
- Debug.Assert(iBval == end);
- while (inverse[--index] == byte.MaxValue)
- {
- inverse[index] = byte.MinValue;
- }
- inverse[index]++;
- this.magnitude = MakeMagnitude(inverse, 0, inverse.Length);
- }
- }
- else
- {
- // strip leading zero bytes and return magnitude bytes
- this.magnitude = MakeMagnitude(bytes, offset, length);
- this.sign = this.magnitude.Length > 0 ? 1 : 0;
- }
- }
- private static int[] MakeMagnitude(
- byte[] bytes,
- int offset,
- int length)
- {
- int end = offset + length;
- // strip leading zeros
- int firstSignificant;
- for (firstSignificant = offset; firstSignificant < end
- && bytes[firstSignificant] == 0; firstSignificant++)
- {
- }
- if (firstSignificant >= end)
- {
- return ZeroMagnitude;
- }
- int nInts = (end - firstSignificant + 3) / BytesPerInt;
- int bCount = (end - firstSignificant) % BytesPerInt;
- if (bCount == 0)
- {
- bCount = BytesPerInt;
- }
- if (nInts < 1)
- {
- return ZeroMagnitude;
- }
- int[] mag = new int[nInts];
- int v = 0;
- int magnitudeIndex = 0;
- for (int i = firstSignificant; i < end; ++i)
- {
- v <<= 8;
- v |= bytes[i] & 0xff;
- bCount--;
- if (bCount <= 0)
- {
- mag[magnitudeIndex] = v;
- magnitudeIndex++;
- bCount = BytesPerInt;
- v = 0;
- }
- }
- if (magnitudeIndex < mag.Length)
- {
- mag[magnitudeIndex] = v;
- }
- return mag;
- }
- public BigInteger(
- int sign,
- byte[] bytes)
- : this(sign, bytes, 0, bytes.Length)
- {
- }
- public BigInteger(
- int sign,
- byte[] bytes,
- int offset,
- int length)
- {
- if (sign < -1 || sign > 1)
- throw new FormatException("Invalid sign value");
- if (sign == 0)
- {
- this.sign = 0;
- this.magnitude = ZeroMagnitude;
- }
- else
- {
- // copy bytes
- this.magnitude = MakeMagnitude(bytes, offset, length);
- this.sign = this.magnitude.Length < 1 ? 0 : sign;
- }
- }
- public BigInteger(
- int sizeInBits,
- Random random)
- {
- if (sizeInBits < 0)
- throw new ArgumentException("sizeInBits must be non-negative");
- this.nBits = -1;
- this.nBitLength = -1;
- if (sizeInBits == 0)
- {
- this.sign = 0;
- this.magnitude = ZeroMagnitude;
- return;
- }
- int nBytes = GetByteLength(sizeInBits);
- byte[] b = new byte[nBytes];
- random.NextBytes(b);
- // strip off any excess bits in the MSB
- int xBits = BitsPerByte * nBytes - sizeInBits;
- b[0] &= (byte)(255U >> xBits);
- this.magnitude = MakeMagnitude(b, 0, b.Length);
- this.sign = this.magnitude.Length < 1 ? 0 : 1;
- }
- public BigInteger(
- int bitLength,
- int certainty,
- Random random)
- {
- if (bitLength < 2)
- throw new ArithmeticException("bitLength < 2");
- this.sign = 1;
- this.nBitLength = bitLength;
- if (bitLength == 2)
- {
- this.magnitude = random.Next(2) == 0
- ? Two.magnitude
- : Three.magnitude;
- return;
- }
- int nBytes = GetByteLength(bitLength);
- byte[] b = new byte[nBytes];
- int xBits = BitsPerByte * nBytes - bitLength;
- byte mask = (byte)(255U >> xBits);
- byte lead = (byte)(1 << (7 - xBits));
- for (;;)
- {
- random.NextBytes(b);
- // strip off any excess bits in the MSB
- b[0] &= mask;
- // ensure the leading bit is 1 (to meet the strength requirement)
- b[0] |= lead;
- // ensure the trailing bit is 1 (i.e. must be odd)
- b[nBytes - 1] |= 1;
- this.magnitude = MakeMagnitude(b, 0, b.Length);
- this.nBits = -1;
- this.mQuote = 0;
- if (certainty < 1)
- break;
- if (CheckProbablePrime(certainty, random, true))
- break;
- for (int j = 1; j < (magnitude.Length - 1); ++j)
- {
- this.magnitude[j] ^= random.Next();
- if (CheckProbablePrime(certainty, random, true))
- return;
- }
- }
- }
- public BigInteger Abs()
- {
- return sign >= 0 ? this : Negate();
- }
- /**
- * return a = a + b - b preserved.
- */
- private static int[] AddMagnitudes(
- int[] a,
- int[] b)
- {
- int tI = a.Length - 1;
- int vI = b.Length - 1;
- long m = 0;
- while (vI >= 0)
- {
- m += ((long)(uint)a[tI] + (long)(uint)b[vI--]);
- a[tI--] = (int)m;
- m = (long)((ulong)m >> 32);
- }
- if (m != 0)
- {
- while (tI >= 0 && ++a[tI--] == 0)
- {
- }
- }
- return a;
- }
- public BigInteger Add(
- BigInteger value)
- {
- if (this.sign == 0)
- return value;
- if (this.sign != value.sign)
- {
- if (value.sign == 0)
- return this;
- if (value.sign < 0)
- return Subtract(value.Negate());
- return value.Subtract(Negate());
- }
- return AddToMagnitude(value.magnitude);
- }
- private BigInteger AddToMagnitude(
- int[] magToAdd)
- {
- int[] big, small;
- if (this.magnitude.Length < magToAdd.Length)
- {
- big = magToAdd;
- small = this.magnitude;
- }
- else
- {
- big = this.magnitude;
- small = magToAdd;
- }
- // Conservatively avoid over-allocation when no overflow possible
- uint limit = uint.MaxValue;
- if (big.Length == small.Length)
- limit -= (uint) small[0];
- bool possibleOverflow = (uint) big[0] >= limit;
- int[] bigCopy;
- if (possibleOverflow)
- {
- bigCopy = new int[big.Length + 1];
- big.CopyTo(bigCopy, 1);
- }
- else
- {
- bigCopy = (int[]) big.Clone();
- }
- bigCopy = AddMagnitudes(bigCopy, small);
- return new BigInteger(this.sign, bigCopy, possibleOverflow);
- }
- public BigInteger And(
- BigInteger value)
- {
- if (this.sign == 0 || value.sign == 0)
- {
- return Zero;
- }
- int[] aMag = this.sign > 0
- ? this.magnitude
- : Add(One).magnitude;
- int[] bMag = value.sign > 0
- ? value.magnitude
- : value.Add(One).magnitude;
- bool resultNeg = sign < 0 && value.sign < 0;
- int resultLength = System.Math.Max(aMag.Length, bMag.Length);
- int[] resultMag = new int[resultLength];
- int aStart = resultMag.Length - aMag.Length;
- int bStart = resultMag.Length - bMag.Length;
- for (int i = 0; i < resultMag.Length; ++i)
- {
- int aWord = i >= aStart ? aMag[i - aStart] : 0;
- int bWord = i >= bStart ? bMag[i - bStart] : 0;
- if (this.sign < 0)
- {
- aWord = ~aWord;
- }
- if (value.sign < 0)
- {
- bWord = ~bWord;
- }
- resultMag[i] = aWord & bWord;
- if (resultNeg)
- {
- resultMag[i] = ~resultMag[i];
- }
- }
- BigInteger result = new BigInteger(1, resultMag, true);
- // TODO Optimise this case
- if (resultNeg)
- {
- result = result.Not();
- }
- return result;
- }
- public BigInteger AndNot(
- BigInteger val)
- {
- return And(val.Not());
- }
- public int BitCount
- {
- get
- {
- if (nBits == -1)
- {
- if (sign < 0)
- {
- // TODO Optimise this case
- nBits = Not().BitCount;
- }
- else
- {
- int sum = 0;
- for (int i = 0; i < magnitude.Length; ++i)
- {
- sum += BitCnt(magnitude[i]);
- }
- nBits = sum;
- }
- }
- return nBits;
- }
- }
- public static int BitCnt(int i)
- {
- uint u = (uint)i;
- u = u - ((u >> 1) & 0x55555555);
- u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
- u = (u + (u >> 4)) & 0x0f0f0f0f;
- u += (u >> 8);
- u += (u >> 16);
- u &= 0x3f;
- return (int)u;
- }
- private static int CalcBitLength(int sign, int indx, int[] mag)
- {
- for (;;)
- {
- if (indx >= mag.Length)
- return 0;
- if (mag[indx] != 0)
- break;
- ++indx;
- }
- // bit length for everything after the first int
- int bitLength = 32 * ((mag.Length - indx) - 1);
- // and determine bitlength of first int
- int firstMag = mag[indx];
- bitLength += BitLen(firstMag);
- // Check for negative powers of two
- if (sign < 0 && ((firstMag & -firstMag) == firstMag))
- {
- do
- {
- if (++indx >= mag.Length)
- {
- --bitLength;
- break;
- }
- }
- while (mag[indx] == 0);
- }
- return bitLength;
- }
- public int BitLength
- {
- get
- {
- if (nBitLength == -1)
- {
- nBitLength = sign == 0
- ? 0
- : CalcBitLength(sign, 0, magnitude);
- }
- return nBitLength;
- }
- }
- //
- // BitLen(value) is the number of bits in value.
- //
- internal static int BitLen(int w)
- {
- uint v = (uint)w;
- uint t = v >> 24;
- if (t != 0)
- return 24 + BitLengthTable[t];
- t = v >> 16;
- if (t != 0)
- return 16 + BitLengthTable[t];
- t = v >> 8;
- if (t != 0)
- return 8 + BitLengthTable[t];
- return BitLengthTable[v];
- }
- private bool QuickPow2Check()
- {
- return sign > 0 && nBits == 1;
- }
- public int CompareTo(
- object obj)
- {
- return CompareTo((BigInteger)obj);
- }
- /**
- * unsigned comparison on two arrays - note the arrays may
- * start with leading zeros.
- */
- private static int CompareTo(
- int xIndx,
- int[] x,
- int yIndx,
- int[] y)
- {
- while (xIndx != x.Length && x[xIndx] == 0)
- {
- xIndx++;
- }
- while (yIndx != y.Length && y[yIndx] == 0)
- {
- yIndx++;
- }
- return CompareNoLeadingZeroes(xIndx, x, yIndx, y);
- }
- private static int CompareNoLeadingZeroes(
- int xIndx,
- int[] x,
- int yIndx,
- int[] y)
- {
- int diff = (x.Length - y.Length) - (xIndx - yIndx);
- if (diff != 0)
- {
- return diff < 0 ? -1 : 1;
- }
- // lengths of magnitudes the same, test the magnitude values
- while (xIndx < x.Length)
- {
- uint v1 = (uint)x[xIndx++];
- uint v2 = (uint)y[yIndx++];
- if (v1 != v2)
- return v1 < v2 ? -1 : 1;
- }
- return 0;
- }
- public int CompareTo(
- BigInteger value)
- {
- return sign < value.sign ? -1
- : sign > value.sign ? 1
- : sign == 0 ? 0
- : sign * CompareNoLeadingZeroes(0, magnitude, 0, value.magnitude);
- }
- /**
- * return z = x / y - done in place (z value preserved, x contains the
- * remainder)
- */
- private int[] Divide(
- int[] x,
- int[] y)
- {
- int xStart = 0;
- while (xStart < x.Length && x[xStart] == 0)
- {
- ++xStart;
- }
- int yStart = 0;
- while (yStart < y.Length && y[yStart] == 0)
- {
- ++yStart;
- }
- Debug.Assert(yStart < y.Length);
- int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
- int[] count;
- if (xyCmp > 0)
- {
- int yBitLength = CalcBitLength(1, yStart, y);
- int xBitLength = CalcBitLength(1, xStart, x);
- int shift = xBitLength - yBitLength;
- int[] iCount;
- int iCountStart = 0;
- int[] c;
- int cStart = 0;
- int cBitLength = yBitLength;
- if (shift > 0)
- {
- // iCount = ShiftLeft(One.magnitude, shift);
- iCount = new int[(shift >> 5) + 1];
- iCount[0] = 1 << (shift % 32);
- c = ShiftLeft(y, shift);
- cBitLength += shift;
- }
- else
- {
- iCount = new int[] { 1 };
- int len = y.Length - yStart;
- c = new int[len];
- Array.Copy(y, yStart, c, 0, len);
- }
- count = new int[iCount.Length];
- for (;;)
- {
- if (cBitLength < xBitLength
- || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0)
- {
- Subtract(xStart, x, cStart, c);
- AddMagnitudes(count, iCount);
- while (x[xStart] == 0)
- {
- if (++xStart == x.Length)
- return count;
- }
- //xBitLength = CalcBitLength(xStart, x);
- xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]);
- if (xBitLength <= yBitLength)
- {
- if (xBitLength < yBitLength)
- return count;
- xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
- if (xyCmp <= 0)
- break;
- }
- }
- shift = cBitLength - xBitLength;
- // NB: The case where c[cStart] is 1-bit is harmless
- if (shift == 1)
- {
- uint firstC = (uint) c[cStart] >> 1;
- uint firstX = (uint) x[xStart];
- if (firstC > firstX)
- ++shift;
- }
- if (shift < 2)
- {
- ShiftRightOneInPlace(cStart, c);
- --cBitLength;
- ShiftRightOneInPlace(iCountStart, iCount);
- }
- else
- {
- ShiftRightInPlace(cStart, c, shift);
- cBitLength -= shift;
- ShiftRightInPlace(iCountStart, iCount, shift);
- }
- //cStart = c.Length - ((cBitLength + 31) / 32);
- while (c[cStart] == 0)
- {
- ++cStart;
- }
- while (iCount[iCountStart] == 0)
- {
- ++iCountStart;
- }
- }
- }
- else
- {
- count = new int[1];
- }
- if (xyCmp == 0)
- {
- AddMagnitudes(count, One.magnitude);
- Array.Clear(x, xStart, x.Length - xStart);
- }
- return count;
- }
- public BigInteger Divide(
- BigInteger val)
- {
- if (val.sign == 0)
- throw new ArithmeticException("Division by zero error");
- if (sign == 0)
- return Zero;
- if (val.QuickPow2Check()) // val is power of two
- {
- BigInteger result = this.Abs().ShiftRight(val.Abs().BitLength - 1);
- return val.sign == this.sign ? result : result.Negate();
- }
- int[] mag = (int[]) this.magnitude.Clone();
- return new BigInteger(this.sign * val.sign, Divide(mag, val.magnitude), true);
- }
- public BigInteger[] DivideAndRemainder(
- BigInteger val)
- {
- if (val.sign == 0)
- throw new ArithmeticException("Division by zero error");
- BigInteger[] biggies = new BigInteger[2];
- if (sign == 0)
- {
- biggies[0] = Zero;
- biggies[1] = Zero;
- }
- else if (val.QuickPow2Check()) // val is power of two
- {
- int e = val.Abs().BitLength - 1;
- BigInteger quotient = this.Abs().ShiftRight(e);
- int[] remainder = this.LastNBits(e);
- biggies[0] = val.sign == this.sign ? quotient : quotient.Negate();
- biggies[1] = new BigInteger(this.sign, remainder, true);
- }
- else
- {
- int[] remainder = (int[]) this.magnitude.Clone();
- int[] quotient = Divide(remainder, val.magnitude);
- biggies[0] = new BigInteger(this.sign * val.sign, quotient, true);
- biggies[1] = new BigInteger(this.sign, remainder, true);
- }
- return biggies;
- }
- public override bool Equals(
- object obj)
- {
- if (obj == this)
- return true;
- BigInteger biggie = obj as BigInteger;
- if (biggie == null)
- return false;
- return sign == biggie.sign && IsEqualMagnitude(biggie);
- }
- private bool IsEqualMagnitude(BigInteger x)
- {
- //int[] xMag = x.magnitude;
- if (magnitude.Length != x.magnitude.Length)
- return false;
- for (int i = 0; i < magnitude.Length; i++)
- {
- if (magnitude[i] != x.magnitude[i])
- return false;
- }
- return true;
- }
- public BigInteger Gcd(
- BigInteger value)
- {
- if (value.sign == 0)
- return Abs();
- if (sign == 0)
- return value.Abs();
- BigInteger r;
- BigInteger u = this;
- BigInteger v = value;
- while (v.sign != 0)
- {
- r = u.Mod(v);
- u = v;
- v = r;
- }
- return u;
- }
- public override int GetHashCode()
- {
- int hc = magnitude.Length;
- if (magnitude.Length > 0)
- {
- hc ^= magnitude[0];
- if (magnitude.Length > 1)
- {
- hc ^= magnitude[magnitude.Length - 1];
- }
- }
- return sign < 0 ? ~hc : hc;
- }
- // TODO Make public?
- private BigInteger Inc()
- {
- if (this.sign == 0)
- return One;
- if (this.sign < 0)
- return new BigInteger(-1, doSubBigLil(this.magnitude, One.magnitude), true);
- return AddToMagnitude(One.magnitude);
- }
- public int IntValue
- {
- get
- {
- if (sign == 0)
- return 0;
- int n = magnitude.Length;
- int v = magnitude[n - 1];
- return sign < 0 ? -v : v;
- }
- }
- /**
- * return whether or not a BigInteger is probably prime with a
- * probability of 1 - (1/2)**certainty.
- * <p>From Knuth Vol 2, pg 395.</p>
- */
- public bool IsProbablePrime(int certainty)
- {
- return IsProbablePrime(certainty, false);
- }
- internal bool IsProbablePrime(int certainty, bool randomlySelected)
- {
- if (certainty <= 0)
- return true;
- BigInteger n = Abs();
- if (!n.TestBit(0))
- return n.Equals(Two);
- if (n.Equals(One))
- return false;
- return n.CheckProbablePrime(certainty, RandomSource, randomlySelected);
- }
- private bool CheckProbablePrime(int certainty, Random random, bool randomlySelected)
- {
- Debug.Assert(certainty > 0);
- Debug.Assert(CompareTo(Two) > 0);
- Debug.Assert(TestBit(0));
- // Try to reduce the penalty for really small numbers
- int numLists = System.Math.Min(BitLength - 1, primeLists.Length);
- for (int i = 0; i < numLists; ++i)
- {
- int test = Remainder(primeProducts[i]);
- int[] primeList = primeLists[i];
- for (int j = 0; j < primeList.Length; ++j)
- {
- int prime = primeList[j];
- int qRem = test % prime;
- if (qRem == 0)
- {
- // We may find small numbers in the list
- return BitLength < 16 && IntValue == prime;
- }
- }
- }
- // TODO Special case for < 10^16 (RabinMiller fixed list)
- // if (BitLength < 30)
- // {
- // RabinMiller against 2, 3, 5, 7, 11, 13, 23 is sufficient
- // }
- // TODO Is it worth trying to create a hybrid of these two?
- return RabinMillerTest(certainty, random, randomlySelected);
- // return SolovayStrassenTest(certainty, random);
- // bool rbTest = RabinMillerTest(certainty, random);
- // bool ssTest = SolovayStrassenTest(certainty, random);
- //
- // Debug.Assert(rbTest == ssTest);
- //
- // return rbTest;
- }
- public bool RabinMillerTest(int certainty, Random random)
- {
- return RabinMillerTest(certainty, random, false);
- }
- internal bool RabinMillerTest(int certainty, Random random, bool randomlySelected)
- {
- int bits = BitLength;
- Debug.Assert(certainty > 0);
- Debug.Assert(bits > 2);
- Debug.Assert(TestBit(0));
- int iterations = ((certainty - 1) / 2) + 1;
- if (randomlySelected)
- {
- int itersFor100Cert = bits >= 1024 ? 4
- : bits >= 512 ? 8
- : bits >= 256 ? 16
- : 50;
- if (certainty < 100)
- {
- iterations = System.Math.Min(itersFor100Cert, iterations);
- }
- else
- {
- iterations -= 50;
- iterations += itersFor100Cert;
- }
- }
- // let n = 1 + d . 2^s
- BigInteger n = this;
- int s = n.GetLowestSetBitMaskFirst(-1 << 1);
- Debug.Assert(s >= 1);
- BigInteger r = n.ShiftRight(s);
- // NOTE: Avoid conversion to/from Montgomery form and check for R/-R as result instead
- BigInteger montRadix = One.ShiftLeft(32 * n.magnitude.Length).Remainder(n);
- BigInteger minusMontRadix = n.Subtract(montRadix);
- do
- {
- BigInteger a;
- do
- {
- a = new BigInteger(n.BitLength, random);
- }
- while (a.sign == 0 || a.CompareTo(n) >= 0
- || a.IsEqualMagnitude(montRadix) || a.IsEqualMagnitude(minusMontRadix));
- BigInteger y = ModPowMonty(a, r, n, false);
- if (!y.Equals(montRadix))
- {
- int j = 0;
- while (!y.Equals(minusMontRadix))
- {
- if (++j == s)
- return false;
- y = ModPowMonty(y, Two, n, false);
- if (y.Equals(montRadix))
- return false;
- }
- }
- }
- while (--iterations > 0);
- return true;
- }
- // private bool SolovayStrassenTest(
- // int certainty,
- // Random random)
- // {
- // Debug.Assert(certainty > 0);
- // Debug.Assert(CompareTo(Two) > 0);
- // Debug.Assert(TestBit(0));
- //
- // BigInteger n = this;
- // BigInteger nMinusOne = n.Subtract(One);
- // BigInteger e = nMinusOne.ShiftRight(1);
- //
- // do
- // {
- // BigInteger a;
- // do
- // {
- // a = new BigInteger(nBitLength, random);
- // }
- // // NB: Spec says 0 < x < n, but 1 is trivial
- // while (a.CompareTo(One) <= 0 || a.CompareTo(n) >= 0);
- //
- //
- // // TODO Check this is redundant given the way Jacobi() works?
- //// if (!a.Gcd(n).Equals(One))
- //// return false;
- //
- // int x = Jacobi(a, n);
- //
- // if (x == 0)
- // return false;
- //
- // BigInteger check = a.ModPow(e, n);
- //
- // if (x == 1 && !check.Equals(One))
- // return false;
- //
- // if (x == -1 && !check.Equals(nMinusOne))
- // return false;
- //
- // --certainty;
- // }
- // while (certainty > 0);
- //
- // return true;
- // }
- //
- // private static int Jacobi(
- // BigInteger a,
- // BigInteger b)
- // {
- // Debug.Assert(a.sign >= 0);
- // Debug.Assert(b.sign > 0);
- // Debug.Assert(b.TestBit(0));
- // Debug.Assert(a.CompareTo(b) < 0);
- //
- // int totalS = 1;
- // for (;;)
- // {
- // if (a.sign == 0)
- // return 0;
- //
- // if (a.Equals(One))
- // break;
- //
- // int e = a.GetLowestSetBit();
- //
- // int bLsw = b.magnitude[b.magnitude.Length - 1];
- // if ((e & 1) != 0 && ((bLsw & 7) == 3 || (bLsw & 7) == 5))
- // totalS = -totalS;
- //
- // // TODO Confirm this is faster than later a1.Equals(One) test
- // if (a.BitLength == e + 1)
- // break;
- // BigInteger a1 = a.ShiftRight(e);
- //// if (a1.Equals(One))
- //// break;
- //
- // int a1Lsw = a1.magnitude[a1.magnitude.Length - 1];
- // if ((bLsw & 3) == 3 && (a1Lsw & 3) == 3)
- // totalS = -totalS;
- //
- //// a = b.Mod(a1);
- // a = b.Remainder(a1);
- // b = a1;
- // }
- // return totalS;
- // }
- public long LongValue
- {
- get
- {
- if (sign == 0)
- return 0;
- int n = magnitude.Length;
- long v = magnitude[n - 1] & IMASK;
- if (n > 1)
- {
- v |= (magnitude[n - 2] & IMASK) << 32;
- }
- return sign < 0 ? -v : v;
- }
- }
- public BigInteger Max(
- BigInteger value)
- {
- return CompareTo(value) > 0 ? this : value;
- }
- public BigInteger Min(
- BigInteger value)
- {
- return CompareTo(value) < 0 ? this : value;
- }
- public BigInteger Mod(
- BigInteger m)
- {
- if (m.sign < 1)
- throw new ArithmeticException("Modulus must be positive");
- BigInteger biggie = Remainder(m);
- return (biggie.sign >= 0 ? biggie : biggie.Add(m));
- }
- public BigInteger ModInverse(
- BigInteger m)
- {
- if (m.sign < 1)
- throw new ArithmeticException("Modulus must be positive");
- // TODO Too slow at the moment
- // // "Fast Key Exchange with Elliptic Curve Systems" R.Schoeppel
- // if (m.TestBit(0))
- // {
- // //The Almost Inverse Algorithm
- // int k = 0;
- // BigInteger B = One, C = Zero, F = this, G = m, tmp;
- //
- // for (;;)
- // {
- // // While F is even, do F=F/u, C=C*u, k=k+1.
- // int zeroes = F.GetLowestSetBit();
- // if (zeroes > 0)
- // {
- // F = F.ShiftRight(zeroes);
- // C = C.ShiftLeft(zeroes);
- // k += zeroes;
- // }
- //
- // // If F = 1, then return B,k.
- // if (F.Equals(One))
- // {
- // BigInteger half = m.Add(One).ShiftRight(1);
- // BigInteger halfK = half.ModPow(BigInteger.ValueOf(k), m);
- // return B.Multiply(halfK).Mod(m);
- // }
- //
- // if (F.CompareTo(G) < 0)
- // {
- // tmp = G; G = F; F = tmp;
- // tmp = B; B = C; C = tmp;
- // }
- //
- // F = F.Add(G);
- // B = B.Add(C);
- // }
- // }
- if (m.QuickPow2Check())
- {
- return ModInversePow2(m);
- }
- BigInteger d = this.Remainder(m);
- BigInteger x;
- BigInteger gcd = ExtEuclid(d, m, out x);
- if (!gcd.Equals(One))
- throw new ArithmeticException("Numbers not relatively prime.");
- if (x.sign < 0)
- {
- x = x.Add(m);
- }
- return x;
- }
- private BigInteger ModInversePow2(BigInteger m)
- {
- Debug.Assert(m.SignValue > 0);
- Debug.Assert(m.BitCount == 1);
- if (!TestBit(0))
- {
- throw new ArithmeticException("Numbers not relatively prime.");
- }
- int pow = m.BitLength - 1;
- long inv64 = ModInverse64(LongValue);
- if (pow < 64)
- {
- inv64 &= ((1L << pow) - 1);
- }
- BigInteger x = BigInteger.ValueOf(inv64);
- if (pow > 64)
- {
- BigInteger d = this.Remainder(m);
- int bitsCorrect = 64;
- do
- {
- BigInteger t = x.Multiply(d).Remainder(m);
- x = x.Multiply(Two.Subtract(t)).Remainder(m);
- bitsCorrect <<= 1;
- }
- while (bitsCorrect < pow);
- }
- if (x.sign < 0)
- {
- x = x.Add(m);
- }
- return x;
- }
- private static int ModInverse32(int d)
- {
- // Newton's method with initial estimate "correct to 4 bits"
- Debug.Assert((d & 1) != 0);
- int x = d + (((d + 1) & 4) << 1); // d.x == 1 mod 2**4
- Debug.Assert(((d * x) & 15) == 1);
- x *= 2 - d * x; // d.x == 1 mod 2**8
- x *= 2 - d * x; // d.x == 1 mod 2**16
- x *= 2 - d * x; // d.x == 1 mod 2**32
- Debug.Assert(d * x == 1);
- return x;
- }
- private static long ModInverse64(long d)
- {
- // Newton's method with initial estimate "correct to 4 bits"
- Debug.Assert((d & 1L) != 0);
- long x = d + (((d + 1L) & 4L) << 1); // d.x == 1 mod 2**4
- Debug.Assert(((d * x) & 15L) == 1L);
- x *= 2 - d * x; // d.x == 1 mod 2**8
- x *= 2 - d * x; // d.x == 1 mod 2**16
- x *= 2 - d * x; // d.x == 1 mod 2**32
- x *= 2 - d * x; // d.x == 1 mod 2**64
- Debug.Assert(d * x == 1L);
- return x;
- }
- /**
- * Calculate the numbers u1, u2, and u3 such that:
- *
- * u1 * a + u2 * b = u3
- *
- * where u3 is the greatest common divider of a and b.
- * a and b using the extended Euclid algorithm (refer p. 323
- * of The Art of Computer Programming vol 2, 2nd ed).
- * This also seems to have the side effect of calculating
- * some form of multiplicative inverse.
- *
- * @param a First number to calculate gcd for
- * @param b Second number to calculate gcd for
- * @param u1Out the return object for the u1 value
- * @return The greatest common divisor of a and b
- */
- private static BigInteger ExtEuclid(BigInteger a, BigInteger b, out BigInteger u1Out)
- {
- BigInteger u1 = One, v1 = Zero;
- BigInteger u3 = a, v3 = b;
- if (v3.sign > 0)
- {
- for (;;)
- {
- BigInteger[] q = u3.DivideAndRemainder(v3);
- u3 = v3;
- v3 = q[1];
- BigInteger oldU1 = u1;
- u1 = v1;
- if (v3.sign <= 0)
- break;
- v1 = oldU1.Subtract(v1.Multiply(q[0]));
- }
- }
- u1Out = u1;
- return u3;
- }
- private static void ZeroOut(
- int[] x)
- {
- Array.Clear(x, 0, x.Length);
- }
- public BigInteger ModPow(BigInteger e, BigInteger m)
- {
- if (m.sign < 1)
- throw new ArithmeticException("Modulus must be positive");
- if (m.Equals(One))
- return Zero;
- if (e.sign == 0)
- return One;
- if (sign == 0)
- return Zero;
- bool negExp = e.sign < 0;
- if (negExp)
- e = e.Negate();
- BigInteger result = this.Mod(m);
- if (!e.Equals(One))
- {
- if ((m.magnitude[m.magnitude.Length - 1] & 1) == 0)
- {
- result = ModPowBarrett(result, e, m);
- }
- else
- {
- result = ModPowMonty(result, e, m, true);
- }
- }
- if (negExp)
- result = result.ModInverse(m);
- return result;
- }
- private static BigInteger ModPowBarrett(BigInteger b, BigInteger e, BigInteger m)
- {
- int k = m.magnitude.Length;
- BigInteger mr = One.ShiftLeft((k + 1) << 5);
- BigInteger yu = One.ShiftLeft(k << 6).Divide(m);
- // Sliding window from MSW to LSW
- int extraBits = 0, expLength = e.BitLength;
- while (expLength > ExpWindowThresholds[extraBits])
- {
- ++extraBits;
- }
- int numPowers = 1 << extraBits;
- BigInteger[] oddPowers = new BigInteger[numPowers];
- oddPowers[0] = b;
- BigInteger b2 = ReduceBarrett(b.Square(), m, mr, yu);
- for (int i = 1; i < numPowers; ++i)
- {
- oddPowers[i] = ReduceBarrett(oddPowers[i - 1].Multiply(b2), m, mr, yu);
- }
- int[] windowList = GetWindowList(e.magnitude, extraBits);
- Debug.Assert(windowList.Length > 0);
- int window = windowList[0];
- int mult = window & 0xFF, lastZeroes = window >> 8;
- BigInteger y;
- if (mult == 1)
- {
- y = b2;
- --lastZeroes;
- }
- else
- {
- y = oddPowers[mult >> 1];
- }
- int windowPos = 1;
- while ((window = windowList[windowPos++]) != -1)
- {
- mult = window & 0xFF;
- int bits = lastZeroes + BitLengthTable[mult];
- for (int j = 0; j < bits; ++j)
- {
- y = ReduceBarrett(y.Square(), m, mr, yu);
- }
- y = ReduceBarrett(y.Multiply(oddPowers[mult >> 1]), m, mr, yu);
- lastZeroes = window >> 8;
- }
- for (int i = 0; i < lastZeroes; ++i)
- {
- y = ReduceBarrett(y.Square(), m, mr, yu);
- }
- return y;
- }
- private static BigInteger ReduceBarrett(BigInteger x, BigInteger m, BigInteger mr, BigInteger yu)
- {
- int xLen = x.BitLength, mLen = m.BitLength;
- if (xLen < mLen)
- return x;
- if (xLen - mLen > 1)
- {
- int k = m.magnitude.Length;
- BigInteger q1 = x.DivideWords(k - 1);
- BigInteger q2 = q1.Multiply(yu); // TODO Only need partial multiplication here
- BigInteger q3 = q2.DivideWords(k + 1);
- BigInteger r1 = x.RemainderWords(k + 1);
- BigInteger r2 = q3.Multiply(m); // TODO Only need partial multiplication here
- BigInteger r3 = r2.RemainderWords(k + 1);
- x = r1.Subtract(r3);
- if (x.sign < 0)
- {
- x = x.Add(mr);
- }
- }
- while (x.CompareTo(m) >= 0)
- {
- x = x.Subtract(m);
- }
- return x;
- }
- private static BigInteger ModPowMonty(BigInteger b, BigInteger e, BigInteger m, bool convert)
- {
- int n = m.magnitude.Length;
- int powR = 32 * n;
- bool smallMontyModulus = m.BitLength + 2 <= powR;
- uint mDash = (uint)m.GetMQuote();
- // tmp = this * R mod m
- if (convert)
- {
- b = b.ShiftLeft(powR).Remainder(m);
- }
- int[] yAccum = new int[n + 1];
- int[] zVal = b.magnitude;
- Debug.Assert(zVal.Length <= n);
- if (zVal.Length < n)
- {
- int[] tmp = new int[n];
- zVal.CopyTo(tmp, n - zVal.Length);
- zVal = tmp;
- }
- // Sliding window from MSW to LSW
- int extraBits = 0;
- // Filter the common case of small RSA exponents with few bits set
- if (e.magnitude.Length > 1 || e.BitCount > 2)
- {
- int expLength = e.BitLength;
- while (expLength > ExpWindowThresholds[extraBits])
- {
- ++extraBits;
- }
- }
- int numPowers = 1 << extraBits;
- int[][] oddPowers = new int[numPowers][];
- oddPowers[0] = zVal;
- int[] zSquared = Arrays.Clone(zVal);
- SquareMonty(yAccum, zSquared, m.magnitude, mDash, smallMontyModulus);
- for (int i = 1; i < numPowers; ++i)
- {
- oddPowers[i] = Arrays.Clone(oddPowers[i - 1]);
- MultiplyMonty(yAccum, oddPowers[i], zSquared, m.magnitude, mDash, smallMontyModulus);
- }
- int[] windowList = GetWindowList(e.magnitude, extraBits);
- Debug.Assert(windowList.Length > 1);
- int window = windowList[0];
- int mult = window & 0xFF, lastZeroes = window >> 8;
- int[] yVal;
- if (mult == 1)
- {
- yVal = zSquared;
- --lastZeroes;
- }
- else
- {
- yVal = Arrays.Clone(oddPowers[mult >> 1]);
- }
- int windowPos = 1;
- while ((window = windowList[windowPos++]) != -1)
- {
- mult = window & 0xFF;
- int bits = lastZeroes + BitLengthTable[mult];
- for (int j = 0; j < bits; ++j)
- {
- SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus);
- }
- MultiplyMonty(yAccum, yVal, oddPowers[mult >> 1], m.magnitude, mDash, smallMontyModulus);
- lastZeroes = window >> 8;
- }
- for (int i = 0; i < lastZeroes; ++i)
- {
- SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus);
- }
- if (convert)
- {
- // Return y * R^(-1) mod m
- MontgomeryReduce(yVal, m.magnitude, mDash);
- }
- else if (smallMontyModulus && CompareTo(0, yVal, 0, m.magnitude) >= 0)
- {
- Subtract(0, yVal, 0, m.magnitude);
- }
- return new BigInteger(1, yVal, true);
- }
- private static int[] GetWindowList(int[] mag, int extraBits)
- {
- int v = mag[0];
- Debug.Assert(v != 0);
- int leadingBits = BitLen(v);
- int resultSize = (((mag.Length - 1) << 5) + leadingBits) / (1 + extraBits) + 2;
- int[] result = new int[resultSize];
- int resultPos = 0;
- int bitPos = 33 - leadingBits;
- v <<= bitPos;
- int mult = 1, multLimit = 1 << extraBits;
- int zeroes = 0;
- int i = 0;
- for (; ; )
- {
- for (; bitPos < 32; ++bitPos)
- {
- if (mult < multLimit)
- {
- mult = (mult << 1) | (int)((uint)v >> 31);
- }
- else if (v < 0)
- {
- result[resultPos++] = CreateWindowEntry(mult, zeroes);
- mult = 1;
- zeroes = 0;
- }
- else
- {
- ++zeroes;
- }
- v <<= 1;
- }
- if (++i == mag.Length)
- {
- result[resultPos++] = CreateWindowEntry(mult, zeroes);
- break;
- }
- v = mag[i];
- bitPos = 0;
- }
- result[resultPos] = -1;
- return result;
- }
- private static int CreateWindowEntry(int mult, int zeroes)
- {
- while ((mult & 1) == 0)
- {
- mult >>= 1;
- ++zeroes;
- }
- return mult | (zeroes << 8);
- }
- /**
- * return w with w = x * x - w is assumed to have enough space.
- */
- private static int[] Square(
- int[] w,
- int[] x)
- {
- // Note: this method allows w to be only (2 * x.Length - 1) words if result will fit
- // if (w.Length != 2 * x.Length)
- // throw new ArgumentException("no I don't think so...");
- ulong c;
- int wBase = w.Length - 1;
- for (int i = x.Length - 1; i > 0; --i)
- {
- ulong v = (uint)x[i];
- c = v * v + (uint)w[wBase];
- w[wBase] = (int)c;
- c >>= 32;
- for (int j = i - 1; j >= 0; --j)
- {
- ulong prod = v * (uint)x[j];
- c += ((uint)w[--wBase] & UIMASK) + ((uint)prod << 1);
- w[wBase] = (int)c;
- c = (c >> 32) + (prod >> 31);
- }
- c += (uint)w[--wBase];
- w[wBase] = (int)c;
- if (--wBase >= 0)
- {
- w[wBase] = (int)(c >> 32);
- }
- else
- {
- Debug.Assert((c >> 32) == 0);
- }
- wBase += i;
- }
- c = (uint)x[0];
- c = c * c + (uint)w[wBase];
- w[wBase] = (int)c;
- if (--wBase >= 0)
- {
- w[wBase] += (int)(c >> 32);
- }
- else
- {
- Debug.Assert((c >> 32) == 0);
- }
- return w;
- }
- /**
- * return x with x = y * z - x is assumed to have enough space.
- */
- private static int[] Multiply(int[] x, int[] y, int[] z)
- {
- int i = z.Length;
- if (i < 1)
- return x;
- int xBase = x.Length - y.Length;
- do
- {
- long a = z[--i] & IMASK;
- long val = 0;
- if (a != 0)
- {
- for (int j = y.Length - 1; j >= 0; j--)
- {
- val += a * (y[j] & IMASK) + (x[xBase + j] & IMASK);
- x[xBase + j] = (int)val;
- val = (long)((ulong)val >> 32);
- }
- }
- --xBase;
- if (xBase >= 0)
- {
- x[xBase] = (int)val;
- }
- else
- {
- Debug.Assert(val == 0);
- }
- }
- while (i > 0);
- return x;
- }
- /**
- * Calculate mQuote = -m^(-1) mod b with b = 2^32 (32 = word size)
- */
- private int GetMQuote()
- {
- if (mQuote != 0)
- {
- return mQuote; // already calculated
- }
- Debug.Assert(this.sign > 0);
- int d = -magnitude[magnitude.Length - 1];
- Debug.Assert((d & 1) != 0);
- return mQuote = ModInverse32(d);
- }
- private static void MontgomeryReduce(int[] x, int[] m, uint mDash) // mDash = -m^(-1) mod b
- {
- // NOTE: Not a general purpose reduction (which would allow x up to twice the bitlength of m)
- Debug.Assert(x.Length == m.Length);
- int n = m.Length;
- for (int i = n - 1; i >= 0; --i)
- {
- uint x0 = (uint)x[n - 1];
- ulong t = x0 * mDash;
- ulong carry = t * (uint)m[n - 1] + x0;
- Debug.Assert((uint)carry == 0);
- carry >>= 32;
- for (int j = n - 2; j >= 0; --j)
- {
- carry += t * (uint)m[j] + (uint)x[j];
- x[j + 1] = (int)carry;
- carry >>= 32;
- }
- x[0] = (int)carry;
- Debug.Assert(carry >> 32 == 0);
- }
- if (CompareTo(0, x, 0, m) >= 0)
- {
- Subtract(0, x, 0, m);
- }
- }
- /**
- * Montgomery multiplication: a = x * y * R^(-1) mod m
- * <br/>
- * Based algorithm 14.36 of Handbook of Applied Cryptography.
- * <br/>
- * <li> m, x, y should have length n </li>
- * <li> a should have length (n + 1) </li>
- * <li> b = 2^32, R = b^n </li>
- * <br/>
- * The result is put in x
- * <br/>
- * NOTE: the indices of x, y, m, a different in HAC and in Java
- */
- private static void MultiplyMonty(int[] a, int[] x, int[] y, int[] m, uint mDash, bool smallMontyModulus)
- // mDash = -m^(-1) mod b
- {
- int n = m.Length;
- if (n == 1)
- {
- x[0] = (int)MultiplyMontyNIsOne((uint)x[0], (uint)y[0], (uint)m[0], mDash);
- return;
- }
- uint y0 = (uint)y[n - 1];
- int aMax;
- {
- ulong xi = (uint)x[n - 1];
- ulong carry = xi * y0;
- ulong t = (uint)carry * mDash;
- ulong prod2 = t * (uint)m[n - 1];
- carry += (uint)prod2;
- Debug.Assert((uint)carry == 0);
- carry = (carry >> 32) + (prod2 >> 32);
- for (int j = n - 2; j >= 0; --j)
- {
- ulong prod1 = xi * (uint)y[j];
- prod2 = t * (uint)m[j];
- carry += (prod1 & UIMASK) + (uint)prod2;
- a[j + 2] = (int)carry;
- carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32);
- }
- a[1] = (int)carry;
- aMax = (int)(carry >> 32);
- }
- for (int i = n - 2; i >= 0; --i)
- {
- uint a0 = (uint)a[n];
- ulong xi = (uint)x[i];
- ulong prod1 = xi * y0;
- ulong carry = (prod1 & UIMASK) + a0;
- ulong t = (uint)carry * mDash;
- ulong prod2 = t * (uint)m[n - 1];
- carry += (uint)prod2;
- Debug.Assert((uint)carry == 0);
- carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32);
- for (int j = n - 2; j >= 0; --j)
- {
- prod1 = xi * (uint)y[j];
- prod2 = t * (uint)m[j];
- carry += (prod1 & UIMASK) + (uint)prod2 + (uint)a[j + 1];
- a[j + 2] = (int)carry;
- carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32);
- }
- carry += (uint)aMax;
- a[1] = (int)carry;
- aMax = (int)(carry >> 32);
- }
- a[0] = aMax;
- if (!smallMontyModulus && CompareTo(0, a, 0, m) >= 0)
- {
- Subtract(0, a, 0, m);
- }
- Array.Copy(a, 1, x, 0, n);
- }
- private static void SquareMonty(int[] a, int[] x, int[] m, uint mDash, bool smallMontyModulus)
- // mDash = -m^(-1) mod b
- {
- int n = m.Length;
- if (n == 1)
- {
- uint xVal = (uint)x[0];
- x[0] = (int)MultiplyMontyNIsOne(xVal, xVal, (uint)m[0], mDash);
- return;
- }
- ulong x0 = (uint)x[n - 1];
- int aMax;
- {
- ulong carry = x0 * x0;
- ulong t = (uint)carry * mDash;
- ulong prod2 = t * (uint)m[n - 1];
- carry += (uint)prod2;
- Debug.Assert((uint)carry == 0);
- carry = (carry >> 32) + (prod2 >> 32);
- for (int j = n - 2; j >= 0; --j)
- {
- ulong prod1 = x0 * (uint)x[j];
- prod2 = t * (uint)m[j];
- carry += (prod2 & UIMASK) + ((uint)prod1 << 1);
- a[j + 2] = (int)carry;
- carry = (carry >> 32) + (prod1 >> 31) + (prod2 >> 32);
- }
- a[1] = (int)carry;
- aMax = (int)(carry >> 32);
- }
- for (int i = n - 2; i >= 0; --i)
- {
- uint a0 = (uint)a[n];
- ulong t = a0 * mDash;
- ulong carry = t * (uint)m[n - 1] + a0;
- Debug.Assert((uint)carry == 0);
- carry >>= 32;
- for (int j = n - 2; j > i; --j)
- {
- carry += t * (uint)m[j] + (uint)a[j + 1];
- a[j + 2] = (int)carry;
- carry >>= 32;
- }
- ulong xi = (uint)x[i];
- {
- ulong prod1 = xi * xi;
- ulong prod2 = t * (uint)m[i];
- carry += (prod1 & UIMASK) + (uint)prod2 + (uint)a[i + 1];
- a[i + 2] = (int)carry;
- carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32);
- }
- for (int j = i - 1; j >= 0; --j)
- {
- ulong prod1 = xi * (uint)x[j];
- ulong prod2 = t * (uint)m[j];
- carry += (prod2 & UIMASK) + ((uint)prod1 << 1) + (uint)a[j + 1];
- a[j + 2] = (int)carry;
- carry = (carry >> 32) + (prod1 >> 31) + (prod2 >> 32);
- }
- carry += (uint)aMax;
- a[1] = (int)carry;
- aMax = (int)(carry >> 32);
- }
- a[0] = aMax;
- if (!smallMontyModulus && CompareTo(0, a, 0, m) >= 0)
- {
- Subtract(0, a, 0, m);
- }
- Array.Copy(a, 1, x, 0, n);
- }
- private static uint MultiplyMontyNIsOne(uint x, uint y, uint m, uint mDash)
- {
- ulong carry = (ulong)x * y;
- uint t = (uint)carry * mDash;
- ulong um = m;
- ulong prod2 = um * t;
- carry += (uint)prod2;
- Debug.Assert((uint)carry == 0);
- carry = (carry >> 32) + (prod2 >> 32);
- if (carry > um)
- {
- carry -= um;
- }
- Debug.Assert(carry < um);
- return (uint)carry;
- }
- public BigInteger Multiply(
- BigInteger val)
- {
- if (val == this)
- return Square();
- if ((sign & val.sign) == 0)
- return Zero;
- if (val.QuickPow2Check()) // val is power of two
- {
- BigInteger result = this.ShiftLeft(val.Abs().BitLength - 1);
- return val.sign > 0 ? result : result.Negate();
- }
- if (this.QuickPow2Check()) // this is power of two
- {
- BigInteger result = val.ShiftLeft(this.Abs().BitLength - 1);
- return this.sign > 0 ? result : result.Negate();
- }
- int resLength = magnitude.Length + val.magnitude.Length;
- int[] res = new int[resLength];
- Multiply(res, this.magnitude, val.magnitude);
- int resSign = sign ^ val.sign ^ 1;
- return new BigInteger(resSign, res, true);
- }
- public BigInteger Square()
- {
- if (sign == 0)
- return Zero;
- if (this.QuickPow2Check())
- return ShiftLeft(Abs().BitLength - 1);
- int resLength = magnitude.Length << 1;
- if ((uint)magnitude[0] >> 16 == 0)
- --resLength;
- int[] res = new int[resLength];
- Square(res, magnitude);
- return new BigInteger(1, res, false);
- }
- public BigInteger Negate()
- {
- if (sign == 0)
- return this;
- return new BigInteger(-sign, magnitude, false);
- }
- public BigInteger NextProbablePrime()
- {
- if (sign < 0)
- throw new ArithmeticException("Cannot be called on value < 0");
- if (CompareTo(Two) < 0)
- return Two;
- BigInteger n = Inc().SetBit(0);
- while (!n.CheckProbablePrime(100, RandomSource, false))
- {
- n = n.Add(Two);
- }
- return n;
- }
- public BigInteger Not()
- {
- return Inc().Negate();
- }
- public BigInteger Pow(int exp)
- {
- if (exp <= 0)
- {
- if (exp < 0)
- throw new ArithmeticException("Negative exponent");
- return One;
- }
- if (sign == 0)
- {
- return this;
- }
- if (QuickPow2Check())
- {
- long powOf2 = (long)exp * (BitLength - 1);
- if (powOf2 > Int32.MaxValue)
- {
- throw new ArithmeticException("Result too large");
- }
- return One.ShiftLeft((int)powOf2);
- }
- BigInteger y = One;
- BigInteger z = this;
- for (;;)
- {
- if ((exp & 0x1) == 1)
- {
- y = y.Multiply(z);
- }
- exp >>= 1;
- if (exp == 0) break;
- z = z.Multiply(z);
- }
- return y;
- }
- public static BigInteger ProbablePrime(
- int bitLength,
- Random random)
- {
- return new BigInteger(bitLength, 100, random);
- }
- private int Remainder(
- int m)
- {
- Debug.Assert(m > 0);
- long acc = 0;
- for (int pos = 0; pos < magnitude.Length; ++pos)
- {
- long posVal = (uint) magnitude[pos];
- acc = (acc << 32 | posVal) % m;
- }
- return (int) acc;
- }
- /**
- * return x = x % y - done in place (y value preserved)
- */
- private static int[] Remainder(
- int[] x,
- int[] y)
- {
- int xStart = 0;
- while (xStart < x.Length && x[xStart] == 0)
- {
- ++xStart;
- }
- int yStart = 0;
- while (yStart < y.Length && y[yStart] == 0)
- {
- ++yStart;
- }
- Debug.Assert(yStart < y.Length);
- int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
- if (xyCmp > 0)
- {
- int yBitLength = CalcBitLength(1, yStart, y);
- int xBitLength = CalcBitLength(1, xStart, x);
- int shift = xBitLength - yBitLength;
- int[] c;
- int cStart = 0;
- int cBitLength = yBitLength;
- if (shift > 0)
- {
- c = ShiftLeft(y, shift);
- cBitLength += shift;
- Debug.Assert(c[0] != 0);
- }
- else
- {
- int len = y.Length - yStart;
- c = new int[len];
- Array.Copy(y, yStart, c, 0, len);
- }
- for (;;)
- {
- if (cBitLength < xBitLength
- || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0)
- {
- Subtract(xStart, x, cStart, c);
- while (x[xStart] == 0)
- {
- if (++xStart == x.Length)
- return x;
- }
- //xBitLength = CalcBitLength(xStart, x);
- xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]);
- if (xBitLength <= yBitLength)
- {
- if (xBitLength < yBitLength)
- return x;
- xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
- if (xyCmp <= 0)
- break;
- }
- }
- shift = cBitLength - xBitLength;
- // NB: The case where c[cStart] is 1-bit is harmless
- if (shift == 1)
- {
- uint firstC = (uint) c[cStart] >> 1;
- uint firstX = (uint) x[xStart];
- if (firstC > firstX)
- ++shift;
- }
- if (shift < 2)
- {
- ShiftRightOneInPlace(cStart, c);
- --cBitLength;
- }
- else
- {
- ShiftRightInPlace(cStart, c, shift);
- cBitLength -= shift;
- }
- //cStart = c.Length - ((cBitLength + 31) / 32);
- while (c[cStart] == 0)
- {
- ++cStart;
- }
- }
- }
- if (xyCmp == 0)
- {
- Array.Clear(x, xStart, x.Length - xStart);
- }
- return x;
- }
- public BigInteger Remainder(
- BigInteger n)
- {
- if (n.sign == 0)
- throw new ArithmeticException("Division by zero error");
- if (this.sign == 0)
- return Zero;
- // For small values, use fast remainder method
- if (n.magnitude.Length == 1)
- {
- int val = n.magnitude[0];
- if (val > 0)
- {
- if (val == 1)
- return Zero;
- // TODO Make this func work on uint, and handle val == 1?
- int rem = Remainder(val);
- return rem == 0
- ? Zero
- : new BigInteger(sign, new int[]{ rem }, false);
- }
- }
- if (CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude) < 0)
- return this;
- int[] result;
- if (n.QuickPow2Check()) // n is power of two
- {
- // TODO Move before small values branch above?
- result = LastNBits(n.Abs().BitLength - 1);
- }
- else
- {
- result = (int[]) this.magnitude.Clone();
- result = Remainder(result, n.magnitude);
- }
- return new BigInteger(sign, result, true);
- }
- private int[] LastNBits(
- int n)
- {
- if (n < 1)
- return ZeroMagnitude;
- int numWords = (n + BitsPerInt - 1) / BitsPerInt;
- numWords = System.Math.Min(numWords, this.magnitude.Length);
- int[] result = new int[numWords];
- Array.Copy(this.magnitude, this.magnitude.Length - numWords, result, 0, numWords);
- int excessBits = (numWords << 5) - n;
- if (excessBits > 0)
- {
- result[0] &= (int)(UInt32.MaxValue >> excessBits);
- }
- return result;
- }
- private BigInteger DivideWords(int w)
- {
- Debug.Assert(w >= 0);
- int n = magnitude.Length;
- if (w >= n)
- return Zero;
- int[] mag = new int[n - w];
- Array.Copy(magnitude, 0, mag, 0, n - w);
- return new BigInteger(sign, mag, false);
- }
- private BigInteger RemainderWords(int w)
- {
- Debug.Assert(w >= 0);
- int n = magnitude.Length;
- if (w >= n)
- return this;
- int[] mag = new int[w];
- Array.Copy(magnitude, n - w, mag, 0, w);
- return new BigInteger(sign, mag, false);
- }
- /**
- * do a left shift - this returns a new array.
- */
- private static int[] ShiftLeft(
- int[] mag,
- int n)
- {
- int nInts = (int)((uint)n >> 5);
- int nBits = n & 0x1f;
- int magLen = mag.Length;
- int[] newMag;
- if (nBits == 0)
- {
- newMag = new int[magLen + nInts];
- mag.CopyTo(newMag, 0);
- }
- else
- {
- int i = 0;
- int nBits2 = 32 - nBits;
- int highBits = (int)((uint)mag[0] >> nBits2);
- if (highBits != 0)
- {
- newMag = new int[magLen + nInts + 1];
- newMag[i++] = highBits;
- }
- else
- {
- newMag = new int[magLen + nInts];
- }
- int m = mag[0];
- for (int j = 0; j < magLen - 1; j++)
- {
- int next = mag[j + 1];
- newMag[i++] = (m << nBits) | (int)((uint)next >> nBits2);
- m = next;
- }
- newMag[i] = mag[magLen - 1] << nBits;
- }
- return newMag;
- }
- private static int ShiftLeftOneInPlace(int[] x, int carry)
- {
- Debug.Assert(carry == 0 || carry == 1);
- int pos = x.Length;
- while (--pos >= 0)
- {
- uint val = (uint)x[pos];
- x[pos] = (int)(val << 1) | carry;
- carry = (int)(val >> 31);
- }
- return carry;
- }
- public BigInteger ShiftLeft(
- int n)
- {
- if (sign == 0 || magnitude.Length == 0)
- return Zero;
- if (n == 0)
- return this;
- if (n < 0)
- return ShiftRight(-n);
- BigInteger result = new BigInteger(sign, ShiftLeft(magnitude, n), true);
- if (this.nBits != -1)
- {
- result.nBits = sign > 0
- ? this.nBits
- : this.nBits + n;
- }
- if (this.nBitLength != -1)
- {
- result.nBitLength = this.nBitLength + n;
- }
- return result;
- }
- /**
- * do a right shift - this does it in place.
- */
- private static void ShiftRightInPlace(
- int start,
- int[] mag,
- int n)
- {
- int nInts = (int)((uint)n >> 5) + start;
- int nBits = n & 0x1f;
- int magEnd = mag.Length - 1;
- if (nInts != start)
- {
- int delta = (nInts - start);
- for (int i = magEnd; i >= nInts; i--)
- {
- mag[i] = mag[i - delta];
- }
- for (int i = nInts - 1; i >= start; i--)
- {
- mag[i] = 0;
- }
- }
- if (nBits != 0)
- {
- int nBits2 = 32 - nBits;
- int m = mag[magEnd];
- for (int i = magEnd; i > nInts; --i)
- {
- int next = mag[i - 1];
- mag[i] = (int)((uint)m >> nBits) | (next << nBits2);
- m = next;
- }
- mag[nInts] = (int)((uint)mag[nInts] >> nBits);
- }
- }
- /**
- * do a right shift by one - this does it in place.
- */
- private static void ShiftRightOneInPlace(
- int start,
- int[] mag)
- {
- int i = mag.Length;
- int m = mag[i - 1];
- while (--i > start)
- {
- int next = mag[i - 1];
- mag[i] = ((int)((uint)m >> 1)) | (next << 31);
- m = next;
- }
- mag[start] = (int)((uint)mag[start] >> 1);
- }
- public BigInteger ShiftRight(
- int n)
- {
- if (n == 0)
- return this;
- if (n < 0)
- return ShiftLeft(-n);
- if (n >= BitLength)
- return (this.sign < 0 ? One.Negate() : Zero);
- // int[] res = (int[]) this.magnitude.Clone();
- //
- // ShiftRightInPlace(0, res, n);
- //
- // return new BigInteger(this.sign, res, true);
- int resultLength = (BitLength - n + 31) >> 5;
- int[] res = new int[resultLength];
- int numInts = n >> 5;
- int numBits = n & 31;
- if (numBits == 0)
- {
- Array.Copy(this.magnitude, 0, res, 0, res.Length);
- }
- else
- {
- int numBits2 = 32 - numBits;
- int magPos = this.magnitude.Length - 1 - numInts;
- for (int i = resultLength - 1; i >= 0; --i)
- {
- res[i] = (int)((uint) this.magnitude[magPos--] >> numBits);
- if (magPos >= 0)
- {
- res[i] |= this.magnitude[magPos] << numBits2;
- }
- }
- }
- Debug.Assert(res[0] != 0);
- return new BigInteger(this.sign, res, false);
- }
- public int SignValue
- {
- get { return sign; }
- }
- /**
- * returns x = x - y - we assume x is >= y
- */
- private static int[] Subtract(
- int xStart,
- int[] x,
- int yStart,
- int[] y)
- {
- Debug.Assert(yStart < y.Length);
- Debug.Assert(x.Length - xStart >= y.Length - yStart);
- int iT = x.Length;
- int iV = y.Length;
- long m;
- int borrow = 0;
- do
- {
- m = (x[--iT] & IMASK) - (y[--iV] & IMASK) + borrow;
- x[iT] = (int) m;
- // borrow = (m < 0) ? -1 : 0;
- borrow = (int)(m >> 63);
- }
- while (iV > yStart);
- if (borrow != 0)
- {
- while (--x[--iT] == -1)
- {
- }
- }
- return x;
- }
- public BigInteger Subtract(
- BigInteger n)
- {
- if (n.sign == 0)
- return this;
- if (this.sign == 0)
- return n.Negate();
- if (this.sign != n.sign)
- return Add(n.Negate());
- int compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude);
- if (compare == 0)
- return Zero;
- BigInteger bigun, lilun;
- if (compare < 0)
- {
- bigun = n;
- lilun = this;
- }
- else
- {
- bigun = this;
- lilun = n;
- }
- return new BigInteger(this.sign * compare, doSubBigLil(bigun.magnitude, lilun.magnitude), true);
- }
- private static int[] doSubBigLil(
- int[] bigMag,
- int[] lilMag)
- {
- int[] res = (int[]) bigMag.Clone();
- return Subtract(0, res, 0, lilMag);
- }
- public byte[] ToByteArray()
- {
- return ToByteArray(false);
- }
- public byte[] ToByteArrayUnsigned()
- {
- return ToByteArray(true);
- }
- private byte[] ToByteArray(
- bool unsigned)
- {
- if (sign == 0)
- return unsigned ? ZeroEncoding : new byte[1];
- int nBits = (unsigned && sign > 0)
- ? BitLength
- : BitLength + 1;
- int nBytes = GetByteLength(nBits);
- byte[] bytes = new byte[nBytes];
- int magIndex = magnitude.Length;
- int bytesIndex = bytes.Length;
- if (sign > 0)
- {
- while (magIndex > 1)
- {
- uint mag = (uint) magnitude[--magIndex];
- bytes[--bytesIndex] = (byte) mag;
- bytes[--bytesIndex] = (byte)(mag >> 8);
- bytes[--bytesIndex] = (byte)(mag >> 16);
- bytes[--bytesIndex] = (byte)(mag >> 24);
- }
- uint lastMag = (uint) magnitude[0];
- while (lastMag > byte.MaxValue)
- {
- bytes[--bytesIndex] = (byte) lastMag;
- lastMag >>= 8;
- }
- bytes[--bytesIndex] = (byte) lastMag;
- }
- else // sign < 0
- {
- bool carry = true;
- while (magIndex > 1)
- {
- uint mag = ~((uint) magnitude[--magIndex]);
- if (carry)
- {
- carry = (++mag == uint.MinValue);
- }
- bytes[--bytesIndex] = (byte) mag;
- bytes[--bytesIndex] = (byte)(mag >> 8);
- bytes[--bytesIndex] = (byte)(mag >> 16);
- bytes[--bytesIndex] = (byte)(mag >> 24);
- }
- uint lastMag = (uint) magnitude[0];
- if (carry)
- {
- // Never wraps because magnitude[0] != 0
- --lastMag;
- }
- while (lastMag > byte.MaxValue)
- {
- bytes[--bytesIndex] = (byte) ~lastMag;
- lastMag >>= 8;
- }
- bytes[--bytesIndex] = (byte) ~lastMag;
- if (bytesIndex > 0)
- {
- bytes[--bytesIndex] = byte.MaxValue;
- }
- }
- return bytes;
- }
- public override string ToString()
- {
- return ToString(10);
- }
- public string ToString(int radix)
- {
- // TODO Make this method work for other radices (ideally 2 <= radix <= 36 as in Java)
- switch (radix)
- {
- case 2:
- case 8:
- case 10:
- case 16:
- break;
- default:
- throw new FormatException("Only bases 2, 8, 10, 16 are allowed");
- }
- // NB: Can only happen to internally managed instances
- if (magnitude == null)
- return "null";
- if (sign == 0)
- return "0";
- // NOTE: This *should* be unnecessary, since the magnitude *should* never have leading zero digits
- int firstNonZero = 0;
- while (firstNonZero < magnitude.Length)
- {
- if (magnitude[firstNonZero] != 0)
- {
- break;
- }
- ++firstNonZero;
- }
- if (firstNonZero == magnitude.Length)
- {
- return "0";
- }
- StringBuilder sb = new StringBuilder();
- if (sign == -1)
- {
- sb.Append('-');
- }
- switch (radix)
- {
- case 2:
- {
- int pos = firstNonZero;
- sb.Append(Convert.ToString(magnitude[pos], 2));
- while (++pos < magnitude.Length)
- {
- AppendZeroExtendedString(sb, Convert.ToString(magnitude[pos], 2), 32);
- }
- break;
- }
- case 8:
- {
- int mask = (1 << 30) - 1;
- BigInteger u = this.Abs();
- int bits = u.BitLength;
- IList S = Org.BouncyCastle.Utilities.Platform.CreateArrayList();
- while (bits > 30)
- {
- S.Add(Convert.ToString(u.IntValue & mask, 8));
- u = u.ShiftRight(30);
- bits -= 30;
- }
- sb.Append(Convert.ToString(u.IntValue, 8));
- for (int i = S.Count - 1; i >= 0; --i)
- {
- AppendZeroExtendedString(sb, (string)S[i], 10);
- }
- break;
- }
- case 16:
- {
- int pos = firstNonZero;
- sb.Append(Convert.ToString(magnitude[pos], 16));
- while (++pos < magnitude.Length)
- {
- AppendZeroExtendedString(sb, Convert.ToString(magnitude[pos], 16), 8);
- }
- break;
- }
- // TODO This could work for other radices if there is an alternative to Convert.ToString method
- //default:
- case 10:
- {
- BigInteger q = this.Abs();
- if (q.BitLength < 64)
- {
- sb.Append(Convert.ToString(q.LongValue, radix));
- break;
- }
- // Based on algorithm 1a from chapter 4.4 in Seminumerical Algorithms (Knuth)
- // Work out the largest power of 'rdx' that is a positive 64-bit integer
- // TODO possibly cache power/exponent against radix?
- long limit = Int64.MaxValue / radix;
- long power = radix;
- int exponent = 1;
- while (power <= limit)
- {
- power *= radix;
- ++exponent;
- }
- BigInteger bigPower = BigInteger.ValueOf(power);
- IList S = Org.BouncyCastle.Utilities.Platform.CreateArrayList();
- while (q.CompareTo(bigPower) >= 0)
- {
- BigInteger[] qr = q.DivideAndRemainder(bigPower);
- S.Add(Convert.ToString(qr[1].LongValue, radix));
- q = qr[0];
- }
- sb.Append(Convert.ToString(q.LongValue, radix));
- for (int i = S.Count - 1; i >= 0; --i)
- {
- AppendZeroExtendedString(sb, (string)S[i], exponent);
- }
- break;
- }
- }
- return sb.ToString();
- }
- private static void AppendZeroExtendedString(StringBuilder sb, string s, int minLength)
- {
- for (int len = s.Length; len < minLength; ++len)
- {
- sb.Append('0');
- }
- sb.Append(s);
- }
- private static BigInteger CreateUValueOf(
- ulong value)
- {
- int msw = (int)(value >> 32);
- int lsw = (int)value;
- if (msw != 0)
- return new BigInteger(1, new int[] { msw, lsw }, false);
- if (lsw != 0)
- {
- BigInteger n = new BigInteger(1, new int[] { lsw }, false);
- // Check for a power of two
- if ((lsw & -lsw) == lsw)
- {
- n.nBits = 1;
- }
- return n;
- }
- return Zero;
- }
- private static BigInteger CreateValueOf(
- long value)
- {
- if (value < 0)
- {
- if (value == long.MinValue)
- return CreateValueOf(~value).Not();
- return CreateValueOf(-value).Negate();
- }
- return CreateUValueOf((ulong)value);
- }
- public static BigInteger ValueOf(
- long value)
- {
- if (value >= 0 && value < SMALL_CONSTANTS.Length)
- {
- return SMALL_CONSTANTS[value];
- }
- return CreateValueOf(value);
- }
- public int GetLowestSetBit()
- {
- if (this.sign == 0)
- return -1;
- return GetLowestSetBitMaskFirst(-1);
- }
- private int GetLowestSetBitMaskFirst(int firstWordMask)
- {
- int w = magnitude.Length, offset = 0;
- uint word = (uint)(magnitude[--w] & firstWordMask);
- Debug.Assert(magnitude[0] != 0);
- while (word == 0)
- {
- word = (uint)magnitude[--w];
- offset += 32;
- }
- while ((word & 0xFF) == 0)
- {
- word >>= 8;
- offset += 8;
- }
- while ((word & 1) == 0)
- {
- word >>= 1;
- ++offset;
- }
- return offset;
- }
- public bool TestBit(
- int n)
- {
- if (n < 0)
- throw new ArithmeticException("Bit position must not be negative");
- if (sign < 0)
- return !Not().TestBit(n);
- int wordNum = n / 32;
- if (wordNum >= magnitude.Length)
- return false;
- int word = magnitude[magnitude.Length - 1 - wordNum];
- return ((word >> (n % 32)) & 1) > 0;
- }
- public BigInteger Or(
- BigInteger value)
- {
- if (this.sign == 0)
- return value;
- if (value.sign == 0)
- return this;
- int[] aMag = this.sign > 0
- ? this.magnitude
- : Add(One).magnitude;
- int[] bMag = value.sign > 0
- ? value.magnitude
- : value.Add(One).magnitude;
- bool resultNeg = sign < 0 || value.sign < 0;
- int resultLength = System.Math.Max(aMag.Length, bMag.Length);
- int[] resultMag = new int[resultLength];
- int aStart = resultMag.Length - aMag.Length;
- int bStart = resultMag.Length - bMag.Length;
- for (int i = 0; i < resultMag.Length; ++i)
- {
- int aWord = i >= aStart ? aMag[i - aStart] : 0;
- int bWord = i >= bStart ? bMag[i - bStart] : 0;
- if (this.sign < 0)
- {
- aWord = ~aWord;
- }
- if (value.sign < 0)
- {
- bWord = ~bWord;
- }
- resultMag[i] = aWord | bWord;
- if (resultNeg)
- {
- resultMag[i] = ~resultMag[i];
- }
- }
- BigInteger result = new BigInteger(1, resultMag, true);
- // TODO Optimise this case
- if (resultNeg)
- {
- result = result.Not();
- }
- return result;
- }
- public BigInteger Xor(
- BigInteger value)
- {
- if (this.sign == 0)
- return value;
- if (value.sign == 0)
- return this;
- int[] aMag = this.sign > 0
- ? this.magnitude
- : Add(One).magnitude;
- int[] bMag = value.sign > 0
- ? value.magnitude
- : value.Add(One).magnitude;
- // TODO Can just replace with sign != value.sign?
- bool resultNeg = (sign < 0 && value.sign >= 0) || (sign >= 0 && value.sign < 0);
- int resultLength = System.Math.Max(aMag.Length, bMag.Length);
- int[] resultMag = new int[resultLength];
- int aStart = resultMag.Length - aMag.Length;
- int bStart = resultMag.Length - bMag.Length;
- for (int i = 0; i < resultMag.Length; ++i)
- {
- int aWord = i >= aStart ? aMag[i - aStart] : 0;
- int bWord = i >= bStart ? bMag[i - bStart] : 0;
- if (this.sign < 0)
- {
- aWord = ~aWord;
- }
- if (value.sign < 0)
- {
- bWord = ~bWord;
- }
- resultMag[i] = aWord ^ bWord;
- if (resultNeg)
- {
- resultMag[i] = ~resultMag[i];
- }
- }
- BigInteger result = new BigInteger(1, resultMag, true);
- // TODO Optimise this case
- if (resultNeg)
- {
- result = result.Not();
- }
- return result;
- }
- public BigInteger SetBit(
- int n)
- {
- if (n < 0)
- throw new ArithmeticException("Bit address less than zero");
- if (TestBit(n))
- return this;
- // TODO Handle negative values and zero
- if (sign > 0 && n < (BitLength - 1))
- return FlipExistingBit(n);
- return Or(One.ShiftLeft(n));
- }
- public BigInteger ClearBit(
- int n)
- {
- if (n < 0)
- throw new ArithmeticException("Bit address less than zero");
- if (!TestBit(n))
- return this;
- // TODO Handle negative values
- if (sign > 0 && n < (BitLength - 1))
- return FlipExistingBit(n);
- return AndNot(One.ShiftLeft(n));
- }
- public BigInteger FlipBit(
- int n)
- {
- if (n < 0)
- throw new ArithmeticException("Bit address less than zero");
- // TODO Handle negative values and zero
- if (sign > 0 && n < (BitLength - 1))
- return FlipExistingBit(n);
- return Xor(One.ShiftLeft(n));
- }
- private BigInteger FlipExistingBit(
- int n)
- {
- Debug.Assert(sign > 0);
- Debug.Assert(n >= 0);
- Debug.Assert(n < BitLength - 1);
- int[] mag = (int[]) this.magnitude.Clone();
- mag[mag.Length - 1 - (n >> 5)] ^= (1 << (n & 31)); // Flip bit
- //mag[mag.Length - 1 - (n / 32)] ^= (1 << (n % 32));
- return new BigInteger(this.sign, mag, false);
- }
- }
- }
- #endif
|