123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198 |
- [/
- Copyright 2011, 2013 John Maddock.
- Copyright 2013 - 2019 Paul A. Bristow.
- Copyright 2013 Christopher Kormanyos.
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt).
- ]
- [library Boost.Multiprecision
- [quickbook 1.7]
- [copyright 2002-2019 John Maddock and Christopher Kormanyos]
- [purpose Multiprecision Number library]
- [license
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or copy at
- [@http://www.boost.org/LICENSE_1_0.txt])
- ]
- [authors [Maddock, John], [Kormanyos, Christopher]]
- [/last-revision $Date: 2011-07-08 18:51:46 +0100 (Fri, 08 Jul 2011) $]
- ]
- [import html4_symbols.qbk] [/Ideally this should be the same as Boost.Math I:\boost\libs\math\doc]
- [import ../example/gmp_snips.cpp]
- [import ../example/mpfr_snips.cpp]
- [import ../example/mpfi_snips.cpp]
- [import ../example/float128_snips.cpp]
- [import ../example/cpp_dec_float_snips.cpp]
- [import ../example/cpp_bin_float_snips.cpp]
- [import ../example/cpp_int_import_export.cpp]
- [import ../example/cpp_bin_float_import_export.cpp]
- [import ../example/tommath_snips.cpp]
- [import ../example/cpp_int_snips.cpp]
- [import ../example/random_snips.cpp]
- [import ../example/safe_prime.cpp]
- [import ../example/mixed_integer_arithmetic.cpp]
- [import ../example/logged_adaptor.cpp]
- [import ../example/numeric_limits_snips.cpp]
- [import ../example/hashing_examples.cpp]
- [import ../example/cpp_complex_examples.cpp]
- [import ../example/mpc_examples.cpp]
- [import ../example/complex128_examples.cpp]
- [import ../example/eigen_example.cpp]
- [import ../example/mpfr_precision.cpp]
- [import ../example/constexpr_float_arithmetic_examples.cpp]
- [import ../test/constexpr_test_cpp_int_5.cpp]
- [/External links as templates (see also some defs below)]
- [template mpfr[] [@http://www.mpfr.org MPFR]]
- [template mpc[] [@http://www.multiprecision.org MPC]]
- [template mpfi[] [@http://perso.ens-lyon.fr/nathalie.revol/software.html MPFI]]
- [template gmp[] [@http://gmplib.org GMP]]
- [template mpf_class[] [@http://gmplib.org/manual/C_002b_002b-Interface-Floats.html#C_002b_002b-Interface-Floats mpf_class]]
- [template mpfr_class[] [@http://math.berkeley.edu/~wilken/code/gmpfrxx/ mpfr_class]]
- [template mpreal[] [@http://www.holoborodko.com/pavel/mpfr/ mpreal]]
- [template mpir[] [@http://mpir.org/ MPIR]]
- [template tommath[] [@http://libtom.net libtommath]]
- [template quadmath[] [@http://gcc.gnu.org/onlinedocs/libquadmath/ libquadmath]]
- [template super[x]'''<superscript>'''[x]'''</superscript>''']
- [template sub[x]'''<subscript>'''[x]'''</subscript>''']
- [/insert Equation as a PNG or SVG image, previous generated with an external tool like Latex.]
- [/Used thus [equation ellint6] - without the file type suffix which will chosen automatically.]
- [template equation[name] '''<inlinemediaobject>
- <imageobject role="html">
- <imagedata fileref="../'''[name]'''.png"></imagedata>
- </imageobject>
- <imageobject role="print">
- <imagedata fileref="../'''[name]'''.svg"></imagedata>
- </imageobject>
- </inlinemediaobject>''']
- [/insert Indented one-line expression italic and serif font probably using Unicode symbols for Greek and symbols.]
- [/Example: [expression [sub 1]F[sub 0](a, z) = (1-z)[super -a]]]
- [template expression[equation]
- [:
- [role serif_italic [equation]]
- ]
- [/ Hint you may need to enclose equation in brackets if it contains comma(s) to avoid "error invalid number of arguments"]
- ]
- [def __tick [role aligncenter [role green \u2714]]] [/ u2714 is a HEAVY CHECK MARK tick (2713 check mark), green]
- [def __cross [role aligncenter [role red \u2718]]] [/ u2718 is a heavy cross, red]
- [def __star [role aligncenter [role red \u2736]]] [/ 6-point star red ]
- [/Boost.Multiprecision internals links]
- [def __cpp_int [link boost_multiprecision.tut.ints.cpp_int cpp_int]]
- [def __gmp_int [link boost_multiprecision.tut.ints.gmp_int gmp_int]]
- [def __tom_int [link boost_multiprecision.tut.ints.tom_int tom_int]]
- [def __gmp_float [link boost_multiprecision.tut.floats.gmp_float gmp_float]]
- [def __mpf_float [link boost_multiprecision.tut.floats.gmp_float gmp_float]]
- [def __mpfr_float_backend [link boost_multiprecision.tut.floats.mpfr_float mpfr_float]]
- [def __cpp_bin_float [link boost_multiprecision.tut.floats.cpp_bin_float cpp_bin_float]]
- [def __cpp_dec_float [link boost_multiprecision.tut.floats.cpp_dec_float cpp_dec_float]]
- [def __gmp_rational [link boost_multiprecision.tut.rational.gmp_rational gmp_rational]]
- [def __cpp_rational [link boost_multiprecision.tut.rational.cpp_rational cpp_rational]]
- [def __tommath_rational [link boost_multiprecision.tut.rational.tommath_rational tommath_rational]]
- [def __number [link boost_multiprecision.ref.number number]]
- [def __float128 [link boost_multiprecision.tut.floats.float128 float128]]
- [def __cpp_complex [link boost_multiprecision.tut.complex.cpp_complex cpp_complex]]
- [def __mpc_complex [link boost_multiprecision.tut.complex.mpc_complex mpc_complex]]
- [def __debug_adaptor [link boost_multiprecision.tut.misc.debug_adaptor debug_adaptor]]
- [def __logged_adaptor [link boost_multiprecision.tut.misc.logged_adaptor logged_adaptor]]
- [def __rational_adaptor [link boost_multiprecision.tut.rational.rational_adaptor rational_adaptor]]
- [def __cpp_complex [link boost_multiprecision.tut.complex.cpp_complex cpp_complex]]
- [def __mpc_complex [link boost_multiprecision.tut.complex.mpc_complex mpc_complex]]
- [def __complex128 [link boost_multiprecision.tut.complex.complex128 complex128]]
- [def __complex_adaptor [link boost_multiprecision.tut.complex.complex_adaptor complex_adaptor]]
- [/External links as macro definitions.]
- [def __expression_template [@https://en.wikipedia.org/wiki/Expression_templates expression template]]
- [def __expression_templates [@https://en.wikipedia.org/wiki/Expression_templates expression templates]] [/plural version]
- [def __UDT [@http://eel.is/c++draft/definitions#defns.prog.def.type program-defined type]]
- [def __fundamental_type [@https://en.cppreference.com/w/cpp/language/types fundamental (built-in) type]]
- [section:intro Introduction]
- The Multiprecision Library provides [link boost_multiprecision.tut.ints integer],
- [link boost_multiprecision.tut.rational rational],
- [link boost_multiprecision.tut.floats floating-point],
- and [link boost_multiprecision.tut.complex complex] types in C++ that have more
- range and precision than C++'s ordinary built-in types.
- The big number types in Multiprecision can be used with a wide
- selection of basic mathematical operations, elementary transcendental
- functions as well as the functions in Boost.Math.
- The Multiprecision types can also interoperate with any
- __fundamental_type in C++ using clearly defined conversion rules.
- This allows Boost.Multiprecision to be used for all
- kinds of mathematical calculations involving integer,
- rational and floating-point types requiring extended
- range and precision.
- Multiprecision consists of a generic interface to the
- mathematics of large numbers as well as a selection of
- big number back-ends, with support for integer, rational,
- floating-point, and complex types. Boost.Multiprecision provides a selection
- of back-ends provided off-the-rack in including
- interfaces to GMP, MPFR, MPIR, MPC, TomMath as well as
- its own collection of Boost-licensed, header-only back-ends for
- integers, rationals and floats. In addition, user-defined back-ends
- can be created and used with the interface of Multiprecision,
- provided the class implementation adheres to the necessary
- [link boost_multiprecision.ref.backendconc concepts].
- Depending upon the number type, precision may be arbitrarily large
- (limited only by available memory), fixed at compile time
- (for example, 50 or 100 decimal digits), or a variable controlled at run-time
- by member functions. The types are __expression_templates - enabled for
- better performance than naive user-defined types.
- The Multiprecision library comes in two distinct parts:
- * An expression-template-enabled front-end `number`
- that handles all the operator overloading, expression evaluation optimization, and code reduction.
- * A selection of back-ends that implement the actual arithmetic operations, and need conform only to the
- reduced interface requirements of the front-end.
- Separation of front-end and back-end allows use of highly refined, but restricted license libraries
- where possible, but provides Boost license alternatives for users who must have a portable
- unconstrained license.
- Which is to say some back-ends rely on 3rd party libraries,
- but a header-only Boost license version is always available (if somewhat slower).
- [h5:getting_started Getting started with Boost.Multiprecision]
- Should you just wish to 'cut to the chase' just to get bigger integers and/or bigger and more precise reals as simply and portably as possible,
- close to 'drop-in' replacements for the __fundamental_type analogs,
- then use a fully Boost-licensed number type, and skip to one of more of :
- * __cpp_int for multiprecision integers,
- * __cpp_rational for rational types,
- * __cpp_bin_float and __cpp_dec_float for multiprecision floating-point types,
- * __cpp_complex for complex types.
- The library is very often used via one of the predefined convenience `typedef`s
- like `boost::multiprecision::int128_t` or `boost::multiprecision::cpp_bin_float_quad`.
- For example, if you want a signed, 128-bit fixed size integer:
- #include <boost/multiprecision/cpp_int.hpp> // Integer types.
-
- boost::multiprecision::int128_t my_128_bit_int;
- Alternatively, and more adventurously, if you wanted an
- [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision]
- integer type using [gmp] as the underlying implementation then you could use:
- #include <boost/multiprecision/gmp.hpp> // Defines the wrappers around the GMP library's types
- boost::multiprecision::mpz_int myint; // Arbitrary precision integer type.
-
- Or for a simple, portable 128-bit floating-point close to a drop-in for a __fundamental_type like `double`, usually 64-bit
- #include <boost/multiprecision/cpp_bin_float.hpp>
-
- boost::multiprecision::cpp_bin_float_quad my_quad_real;
- Alternatively, you can compose your own 'custom' multiprecision type, by combining `number` with one of the
- predefined back-end types. For example, suppose you wanted a 300 decimal digit floating-point type
- based on the [mpfr] library. In this case, there's no predefined `typedef` with that level of precision,
- so instead we compose our own:
- #include <boost/multiprecision/mpfr.hpp> // Defines the Backend type that wraps MPFR.
- namespace mp = boost::multiprecision; // Reduce the typing a bit later...
- typedef mp::number<mp::mpfr_float_backend<300> > my_float;
- my_float a, b, c; // These variables have 300 decimal digits precision.
- We can repeat the above example, but with the expression templates disabled (for faster compile times, but slower runtimes)
- by passing a second template argument to `number`:
- #include <boost/multiprecision/mpfr.hpp> // Defines the Backend type that wraps MPFR.
- namespace mp = boost::multiprecision; // Reduce the typing a bit later...
- typedef mp::number<mp::mpfr_float_backend<300>, et_off> my_float;
- my_float a, b, c; // These variables have 300 decimal digits precision
- We can also mix arithmetic operations between different types, provided there is an unambiguous implicit conversion from one
- type to the other:
- #include <boost/multiprecision/cpp_int.hpp>
- namespace mp = boost::multiprecision; // Reduce the typing a bit later...
- mp::int128_t a(3), b(4);
- mp::int512_t c(50), d;
- d = c * a; // OK, result of mixed arithmetic is an int512_t
- Conversions are also allowed:
- d = a; // OK, widening conversion.
- d = a * b; // OK, can convert from an expression template too.
- However conversions that are inherently lossy are either declared explicit or else forbidden altogether:
- d = 3.14; // Error implicit conversion from double not allowed.
- d = static_cast<mp::int512_t>(3.14); // OK explicit construction is allowed
- Mixed arithmetic will fail if the conversion is either ambiguous or explicit:
- number<cpp_int_backend<>, et_off> a(2);
- number<cpp_int_backend<>, et_on> b(3);
- b = a * b; // Error, implicit conversion could go either way.
- b = a * 3.14; // Error, no operator overload if the conversion would be explicit.
- [h4 Move Semantics]
- On compilers that support rvalue-references, class `number` is move-enabled if the underlying backend is.
- In addition the non-expression template operator overloads (see below) are move aware and have overloads
- that look something like:
- template <class B>
- number<B, et_off> operator + (number<B, et_off>&& a, const number<B, et_off>& b)
- {
- return std::move(a += b);
- }
- These operator overloads ensure that many expressions can be evaluated without actually generating any temporaries.
- However, there are still many simple expressions such as
- a = b * c;
- which don't noticeably benefit from move support. Therefore, optimal performance comes from having both
- move-support, and expression templates enabled.
- Note that while "moved-from" objects are left in a sane state, they have an unspecified value, and the only permitted
- operations on them are destruction or the assignment of a new value. Any other operation should be considered
- a programming error and all of our backends will trigger an assertion if any other operation is attempted. This behavior
- allows for optimal performance on move-construction (i.e. no allocation required, we just take ownership of the existing
- object's internal state), while maintaining usability in the standard library containers.
- [h4:expression_templates Expression Templates]
- Class `number` is expression-template-enabled: that means that rather than having a multiplication
- operator that looks like this:
- template <class Backend>
- number<Backend> operator * (const number<Backend>& a, const number<Backend>& b)
- {
- number<Backend> result(a);
- result *= b;
- return result;
- }
- Instead the operator looks more like this:
- template <class Backend>
- ``['unmentionable-type]`` operator * (const number<Backend>& a, const number<Backend>& b);
- Where the '['unmentionable]' return type is an implementation detail that, rather than containing the result
- of the multiplication, contains instructions on how to compute the result. In effect it's just a pair
- of references to the arguments of the function, plus some compile-time information that stores what the operation
- is.
- The great advantage of this method is the ['elimination of temporaries]: for example, the "naive" implementation
- of `operator*` above, requires one temporary for computing the result, and at least another one to return it. It's true
- that sometimes this overhead can be reduced by using move-semantics, but it can't be eliminated completely. For example,
- lets suppose we're evaluating a polynomial via Horner's method, something like this:
- T a[7] = { /* some values */ };
- //....
- y = (((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0];
- If type `T` is a `number`, then this expression is evaluated ['without creating a single temporary value]. In contrast,
- if we were using the [mpfr_class] C++ wrapper for [mpfr] - then this expression would result in no less than 11
- temporaries (this is true even though [mpfr_class] does use expression templates to reduce the number of temporaries somewhat). Had
- we used an even simpler wrapper around [mpfr] like [mpreal] things would have been even worse and no less that 24 temporaries
- are created for this simple expression (note - we actually measure the number of memory allocations performed rather than
- the number of temporaries directly, note also that the [mpf_class] wrapper that will be supplied with GMP-5.1 reduces the number of
- temporaries to pretty much zero). Note that if we compile with expression templates disabled and rvalue-reference support
- on, then actually still have no wasted memory allocations as even though temporaries are created, their contents are moved
- rather than copied.
- [footnote The actual number generated will depend on the compiler, how well it optimizes the code, and whether it supports
- rvalue references. The number of 11 temporaries was generated with Visual C++ 2010.]
- [important
- Expression templates can radically reorder the operations in an expression, for example:
- a = (b * c) * a;
- Will get transformed into:
- a *= c;
- a *= b;
- If this is likely to be an issue for a particular application, then they should be disabled.
- ]
- This library also extends expression template support to standard library functions like `abs` or `sin` with `number`
- arguments. This means that an expression such as:
- y = abs(x);
- can be evaluated without a single temporary being calculated. Even expressions like:
- y = sin(x);
- get this treatment, so that variable 'y' is used as "working storage" within the implementation of `sin`,
- thus reducing the number of temporaries used by one. Of course, should you write:
- x = sin(x);
- Then we clearly can't use `x` as working storage during the calculation, so then a temporary variable
- is created in this case.
- Given the comments above, you might be forgiven for thinking that expression-templates are some kind of universal-panacea:
- sadly though, all tricks like this have their downsides. For one thing, expression template libraries
- like this one, tend to be slower to compile than their simpler cousins, they're also harder to debug
- (should you actually want to step through our code!), and rely on compiler optimizations being turned
- on to give really good performance. Also, since the return type from expressions involving `number`s
- is an "unmentionable implementation detail", you have to be careful to cast the result of an expression
- to the actual number type when passing an expression to a template function. For example, given:
- template <class T>
- void my_proc(const T&);
- Then calling:
- my_proc(a+b);
- Will very likely result in obscure error messages inside the body of `my_proc` - since we've passed it
- an expression template type, and not a number type. Instead we probably need:
- my_proc(my_number_type(a+b));
- Having said that, these situations don't occur that often - or indeed not at all for non-template functions.
- In addition, all the functions in the Boost.Math library will automatically convert expression-template arguments
- to the underlying number type without you having to do anything, so:
- mpfr_float_100 a(20), delta(0.125);
- boost::math::gamma_p(a, a + delta);
- Will work just fine, with the `a + delta` expression template argument getting converted to an `mpfr_float_100`
- internally by the Boost.Math library.
- [caution In C++11 you should never store an expression template using:
- `auto my_expression = a + b - c;`
- unless you're absolutely sure that the lifetimes of `a`, `b` and `c` will outlive that of `my_expression`.
- In fact, it is particularly easy to create dangling references by mixing expression templates with the `auto`
- keyword, for example:
- `auto val = cpp_dec_float_50("23.1") * 100;`
- In this situation, the integer literal is stored directly in the expression template - so its use is OK here -
- but the `cpp_dec_float_50` temporary is stored by reference and then destructed when the statement completes,
- leaving a dangling reference.
- [*['If in doubt, do not ever mix expression templates with the `auto` keyword.]]
- ]
- And finally... the performance improvements from an expression template library like this are often not as
- dramatic as the reduction in number of temporaries would suggest. For example, if we compare this library with
- [mpfr_class] and [mpreal], with all three using the underlying [mpfr] library at 50 decimal digits precision then
- we see the following typical results for polynomial execution:
- [table Evaluation of Order 6 Polynomial.
- [[Library] [Relative Time] [Relative number of memory allocations]]
- [[number] [1.0 (0.00957s)] [1.0 (2996 total)]]
- [[[mpfr_class]] [1.1 (0.0102s)] [4.3 (12976 total)]]
- [[[mpreal]] [1.6 (0.0151s)] [9.3 (27947 total)]]
- ]
- As you can see, the execution time increases a lot more slowly than the number of memory allocations. There are
- a number of reasons for this:
- * The cost of extended-precision multiplication and division is so great, that the times taken for these tend to
- swamp everything else.
- * The cost of an in-place multiplication (using `operator*=`) tends to be more than an out-of-place
- `operator*` (typically `operator *=` has to create a temporary workspace to carry out the multiplication, where
- as `operator*` can use the target variable as workspace). Since the expression templates carry out their
- magic by converting out-of-place operators to in-place ones, we necessarily take this hit. Even so the
- transformation is more efficient than creating the extra temporary variable, just not by as much as
- one would hope.
- Finally, note that `number` takes a second template argument, which, when set to `et_off` disables all
- the expression template machinery. The result is much faster to compile, but slower at runtime.
- We'll conclude this section by providing some more performance comparisons between these three libraries,
- again, all are using [mpfr] to carry out the underlying arithmetic, and all are operating at the same precision
- (50 decimal digits):
- [table Evaluation of Boost.Math's Bessel function test data
- [[Library] [Relative Time] [Relative Number of Memory Allocations]]
- [[mpfr_float_50] [1.0 (5.78s)] [1.0 (1611963)]]
- [[number<mpfr_float_backend<50>, et_off>[br](but with rvalue reference support)]
- [1.1 (6.29s)] [2.64 (4260868)]]
- [[[mpfr_class]] [1.1 (6.28s)] [2.45 (3948316)]]
- [[[mpreal]] [1.65 (9.54s)] [8.21 (13226029)]]
- ]
- [table Evaluation of Boost.Math's Non-Central T distribution test data
- [[Library][Relative Time][Relative Number of Memory Allocations]]
- [[number] [1.0 (263s)][1.0 (127710873)]]
- [[number<mpfr_float_backend<50>, et_off>[br](but with rvalue reference support)]
- [1.0 (260s)][1.2 (156797871)]]
- [[[mpfr_class]] [1.1 (287s)][2.1 (268336640)]]
- [[[mpreal]] [1.5 (389s)][3.6 (466960653)]]
- ]
- The above results were generated on Win32 compiling with Visual C++ 2010, all optimizations on (/Ox),
- with MPFR 3.0 and MPIR 2.3.0.
- [endsect] [/section:intro Introduction]
- [section:tut Tutorial]
- In order to use this library you need to make two choices:
- * What kind of number do I want ([link boost_multiprecision.tut.ints integer],
- [link boost_multiprecision.tut.floats floating-point], [link boost_multiprecision.tut.rational rational], or [link boost_multiprecision.tut.complex complex]).
- * Which back-end do I want to perform the actual arithmetic (Boost-supplied, GMP, MPFR, MPC, Tommath etc)?
- [section:ints Integer Types]
- The following back-ends provide integer arithmetic:
- [table
- [[Backend Type][Header][Radix][Dependencies][Pros][Cons]]
- [[`cpp_int`][boost/multiprecision/cpp_int.hpp][2][None]
- [Very versatile, Boost licensed, all C++ integer type which support both [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] and fixed precision integer types.][Slower than [gmp], though typically not as slow as [tommath]]]
- [[`gmp_int`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]]
- [[`tom_int`][boost/multiprecision/tommath.hpp][2][[tommath]][Public domain back-end with no licence restrictions.][Slower than [gmp].]]
- ]
- [section:cpp_int cpp_int]
- `#include <boost/multiprecision/cpp_int.hpp>`
- namespace boost{ namespace multiprecision{
- typedef unspecified-type limb_type;
- enum cpp_integer_type { signed_magnitude, unsigned_magnitude };
- enum cpp_int_check_type { checked, unchecked };
- template <unsigned MinBits = 0,
- unsigned MaxBits = 0,
- cpp_integer_type SignType = signed_magnitude,
- cpp_int_check_type Checked = unchecked,
- class Allocator = std::allocator<limb_type> >
- class cpp_int_backend;
- //
- // Expression templates default to et_off if there is no allocator:
- //
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked>
- struct expression_template_default<cpp_int_backend<MinBits, MaxBits, SignType, Checked, void> >
- { static const expression_template_option value = et_off; };
- typedef number<cpp_int_backend<> > cpp_int; // arbitrary precision integer
- typedef rational_adaptor<cpp_int_backend<> > cpp_rational_backend;
- typedef number<cpp_rational_backend> cpp_rational; // arbitrary precision rational number
- // Fixed precision unsigned types:
- typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> > uint128_t;
- typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> > uint256_t;
- typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> > uint512_t;
- typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t;
- // Fixed precision signed types:
- typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> > int128_t;
- typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> > int256_t;
- typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> > int512_t;
- typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> > int1024_t;
- // Over again, but with checking enabled this time:
- typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_int;
- typedef rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_rational_backend;
- typedef number<cpp_rational_backend> checked_cpp_rational;
- // Checked fixed precision unsigned types:
- typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> > checked_uint128_t;
- typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> > checked_uint256_t;
- typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> > checked_uint512_t;
- typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> > checked_uint1024_t;
- // Fixed precision signed types:
- typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> > checked_int128_t;
- typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> > checked_int256_t;
- typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> > checked_int512_t;
- typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> > checked_int1024_t;
- }} // namespaces
- The `cpp_int_backend` type is normally used via one of the convenience typedefs given above.
- This back-end is the "Swiss Army Knife" of integer types as it can represent both fixed and
- [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision]
- integer types, and both signed and unsigned types. There are five template arguments:
- [variablelist
- [[MinBits][Determines the number of Bits to store directly within the object before resorting to dynamic memory
- allocation. When zero, this field is determined automatically based on how many bits can be stored
- in union with the dynamic storage header: setting a larger value may improve performance as larger integer
- values will be stored internally before memory allocation is required.]]
- [[MaxBits][Determines the maximum number of bits to be stored in the type: resulting in a fixed precision type.
- When this value is the same as MinBits, then the Allocator parameter is ignored, as no dynamic
- memory allocation will ever be performed: in this situation the Allocator parameter should be set to
- type `void`. Note that this parameter should not be used simply to prevent large memory
- allocations, not only is that role better performed by the allocator, but fixed precision
- integers have a tendency to allocate all of MaxBits of storage more often than one would expect.]]
- [[SignType][Determines whether the resulting type is signed or not. Note that for
- [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] types
- this parameter must be `signed_magnitude`. For fixed precision
- types then this type may be either `signed_magnitude` or `unsigned_magnitude`.]]
- [[Checked][This parameter has two values: `checked` or `unchecked`. See below.]]
- [[Allocator][The allocator to use for dynamic memory allocation, or type `void` if MaxBits == MinBits.]]
- ]
- When the template parameter Checked is set to `checked` then the result is a ['checked-integer], checked
- and unchecked integers have the following properties:
- [table
- [[Condition][Checked-Integer][Unchecked-Integer]]
- [[Numeric overflow in fixed precision arithmetic][Throws a `std::overflow_error`.][Performs arithmetic modulo 2[super MaxBits]]]
- [[Constructing an integer from a value that can not be represented in the target type][Throws a `std::range_error`.]
- [Converts the value modulo 2[super MaxBits], signed to unsigned conversions extract the last MaxBits bits of the
- 2's complement representation of the input value.]]
- [[Unsigned subtraction yielding a negative value.][Throws a `std::range_error`.][Yields the value that would
- result from treating the unsigned type as a 2's complement signed type.]]
- [[Attempting a bitwise operation on a negative value.][Throws a `std::range_error`][Yields the value, but not the bit pattern,
- that would result from performing the operation on a 2's complement integer type.]]
- ]
- Things you should know when using this type:
- * Default constructed `cpp_int_backend`s have the value zero.
- * Division by zero results in a `std::overflow_error` being thrown.
- * Construction from a string that contains invalid non-numeric characters results in a `std::runtime_error` being thrown.
- * Since the precision of `cpp_int_backend` is necessarily limited when the allocator parameter is void,
- care should be taken to avoid numeric overflow when using this type
- unless you actually want modulo-arithmetic behavior.
- * The type uses a sign-magnitude representation internally, so type `int128_t` has 128-bits of precision plus an extra sign bit.
- In this respect the behaviour of these types differs from built-in 2's complement types. In might be tempting to use a
- 127-bit type instead, and indeed this does work, but behaviour is still slightly different from a 2's complement built-in type
- as the min and max values are identical (apart from the sign), where as they differ by one for a true 2's complement type.
- That said it should be noted that there's no requirement for built-in types to be 2's complement either - it's simply that this
- is the most common format by far.
- * Attempting to print negative values as either an Octal or Hexadecimal string results in a `std::runtime_error` being thrown,
- this is a direct consequence of the sign-magnitude representation.
- * The fixed precision types `[checked_][u]intXXX_t` have expression template support turned off - it seems to make little
- difference to the performance of these types either way - so we may as well have the faster compile times by turning
- the feature off.
- * Unsigned types support subtraction - the result is "as if" a 2's complement operation had been performed as long as they are not
- ['checked-integers] (see above).
- In other words they behave pretty much as a built in integer type would in this situation. So for example if we were using
- `uint128_t` then `uint128_t(1)-4` would result in the value `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD`
- of type `uint128_t`. However, had this operation been performed on `checked_uint128_t` then a `std::range_error` would have
- been thrown.
- * Unary negation of unsigned types results in a compiler error (static assertion).
- * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
- * When used at fixed precision, the size of this type is always one machine word (plus any compiler-applied alignment padding)
- larger than you would expect for an N-bit integer:
- the extra word stores both the sign, and how many machine words in the integer are actually in use.
- The latter is an optimisation for larger fixed precision integers, so that a 1024-bit integer has almost the same performance
- characteristics as a 128-bit integer, rather than being 4 times slower for addition and 16 times slower for multiplication
- (assuming the values involved would always fit in 128 bits).
- Typically this means you can use
- an integer type wide enough for the "worst case scenario" with only minor performance degradation even if most of the time
- the arithmetic could in fact be done with a narrower type.
- Also note that unsigned fixed precision types small enough to fit inside the largest native integer become a simple wrapper around that type,
- this includes the "checked" variants. Small signed types will always have an extra sign word and so be larger than their native equivalent.
- * When used at fixed precision and MaxBits is smaller than the number of bits in the largest native integer type, then
- internally `cpp_int_backend` switches to a "trivial" implementation where it is just a thin wrapper around a single
- integer. Note that it will still be slightly slower than a bare native integer, as it emulates a
- signed-magnitude representation rather than simply using the platforms native sign representation: this ensures
- there is no step change in behavior as a cpp_int grows in size.
- * Fixed precision `cpp_int`'s have some support for `constexpr` values and user-defined literals, see
- [link boost_multiprecision.tut.lits here] for the full description. For example `0xfffff_cppi1024`
- specifies a 1024-bit integer with the value 0xffff. This can be used to generate compile time constants that are
- too large to fit into any built in number type.
- * The __cpp_int types support constexpr arithmetic, provided it is a fixed precision type with no allocator. It may also
- be a checked integer: in which case a compiler error will be generated on overflow or undefined behaviour. In addition
- the free functions `abs`, `swap`, `multiply`, `add`, `subtract`, `divide_qr`, `integer_modulus`, `powm`, `lsb`, `msb`,
- `bit_test`, `bit_set`, `bit_unset`, `bit_flip`, `sqrt`, `gcd`, `lcm` are all supported. Use of __cpp_int in this way
- requires either a C++2a compiler (one which supports `std::is_constant_evaluated()`), or GCC-6 or later in C++14 mode.
- Compilers other than GCC and without `std::is_constant_evaluated()` will support a very limited set of operations:
- expect to hit roadblocks rather easily.
- * You can import/export the raw bits of a __cpp_int to and from external storage via the `import_bits` and `export_bits`
- functions. More information is in the [link boost_multiprecision.tut.import_export section on import/export].
- [h5:cpp_int_eg Example:]
- [cpp_int_eg]
- [endsect] [/section:cpp_int cpp_int]
- [section:gmp_int gmp_int]
- `#include <boost/multiprecision/gmp.hpp>`
- namespace boost{ namespace multiprecision{
- class gmp_int;
- typedef number<gmp_int > mpz_int;
- }} // namespaces
- The `gmp_int` back-end is used via the typedef `boost::multiprecision::mpz_int`. It acts as a thin wrapper around the [gmp] `mpz_t`
- to provide an integer type that is a drop-in replacement for the native C++ integer types, but with unlimited precision.
- As well as the usual conversions from arithmetic and string types, type `mpz_int` is copy constructible and assignable from:
- * The [gmp] native types: `mpf_t`, `mpz_t`, `mpq_t`.
- * Instances of `number<T>` that are wrappers around those types: `number<gmp_float<N> >`, `number<gmp_rational>`.
- It's also possible to access the underlying `mpz_t` via the `data()` member function of `gmp_int`.
- Things you should know when using this type:
- * No changes are made to the GMP library's global settings - so you can safely mix this type with
- existing code that uses [gmp].
- * Default constructed `gmp_int`s have the value zero (this is GMP's default behavior).
- * Formatted IO for this type does not support octal or hexadecimal notation for negative values,
- as a result performing formatted output on this type when the argument is negative and either of the flags
- `std::ios_base::oct` or `std::ios_base::hex` are set, will result in a `std::runtime_error` will be thrown.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid integer.
- * Division by zero results in a `std::overflow_error` being thrown.
- * Although this type is a wrapper around [gmp] it will work equally well with [mpir]. Indeed use of [mpir]
- is recommended on Win32.
- * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
- [h5 Example:]
- [mpz_eg]
- [endsect] [/section:gmp_int gmp_int]
- [section:tom_int tom_int]
- `#include <boost/multiprecision/tommath.hpp>`
- namespace boost{ namespace multiprecision{
- class tommath_int;
- typedef number<tommath_int > tom_int;
- }} // namespaces
- The `tommath_int` back-end is used via the typedef `boost::multiprecision::tom_int`. It acts as a thin wrapper around the [tommath] `tom_int`
- to provide an integer type that is a drop-in replacement for the native C++ integer types, but with unlimited precision.
- Things you should know when using this type:
- * Default constructed objects have the value zero (this is [tommath]'s default behavior).
- * Although `tom_int` is mostly a drop in replacement for the builtin integer types, it should be noted that it is a
- rather strange beast as it's a signed type that is not a 2's complement type. As a result the bitwise operations
- `| & ^` will throw a `std::runtime_error` exception if either of the arguments is negative. Similarly the complement
- operator`~` is deliberately not implemented for this type.
- * Formatted IO for this type does not support octal or hexadecimal notation for negative values,
- as a result performing formatted output on this type when the argument is negative and either of the flags
- `std::ios_base::oct` or `std::ios_base::hex` are set, will result in a `std::runtime_error` will be thrown.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid integer.
- * Division by zero results in a `std::overflow_error` being thrown.
- [h5 Example:]
- [tommath_eg]
- [endsect] [/section:tom_int tom_int]
- [section:egs Examples]
- [import ../example/integer_examples.cpp]
- [section:factorials Factorials]
- [FAC1]
- [endsect] [/section:factorials Factorials]
- [section:bitops Bit Operations]
- [BITOPS]
- [endsect] [/section:bitops Bit Operations]
- [endsect]
- [endsect]
- [section:floats floating-point Numbers]
- The following back-ends provide floating-point arithmetic:
- [table
- [[Backend Type][Header][Radix][Dependencies][Pros][Cons]]
- [[`cpp_bin_float<N>`][boost/multiprecision/cpp_bin_float.hpp][2][None][Header only, all C++ implementation. Boost licence.][Approximately 2x slower than the [mpfr] or [gmp] libraries.]]
- [[`cpp_dec_float<N>`][boost/multiprecision/cpp_dec_float.hpp][10][None][Header only, all C++ implementation. Boost licence.][Approximately 2x slower than the [mpfr] or [gmp] libraries.]]
- [[`mpf_float<N>`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]]
- [[`mpfr_float<N>`][boost/multiprecision/mpfr.hpp][2][[gmp] and [mpfr]][Very fast and efficient back-end, with its own standard library implementation.][Dependency on GNU licensed [gmp] and [mpfr] libraries.]]
- [[`float128`][boost/multiprecision/float128.hpp][2][Either [quadmath] or the Intel C++ Math library.][Very fast and efficient back-end for 128-bit floating-point values (113-bit mantissa, equivalent to FORTRAN's QUAD real)][Depends on the compiler being either recent GCC or Intel C++ versions.]]
- ]
- [section:cpp_bin_float cpp_bin_float]
- `#include <boost/multiprecision/cpp_bin_float.hpp>`
- namespace boost{ namespace multiprecision{
- enum digit_base_type
- {
- digit_base_2 = 2,
- digit_base_10 = 10
- };
- template <unsigned Digits, digit_base_type base = digit_base_10, class Allocator = void, class Exponent = int, ExponentMin = 0, ExponentMax = 0>
- class cpp_bin_float;
- typedef number<cpp_bin_float<50> > cpp_bin_float_50;
- typedef number<cpp_bin_float<100> > cpp_bin_float_100;
- typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> cpp_bin_float_single;
- typedef number<backends::cpp_bin_float<53, backends::digit_base_2, void, boost::int16_t, -1022, 1023>, et_off> cpp_bin_float_double;
- typedef number<backends::cpp_bin_float<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_double_extended;
- typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad;
- typedef number<backends::cpp_bin_float<237, backends::digit_base_2, void, boost::int32_t, -262142, 262143>, et_off> cpp_bin_float_oct;
- }} // namespaces
- The `cpp_bin_float` back-end is used in conjunction with `number`: It acts as an entirely C++ (header only and dependency free)
- floating-point number type that is a drop-in replacement for the native C++ floating-point types, but with
- much greater precision.
- Type `cpp_bin_float` can be used at fixed precision by specifying a non-zero `Digits` template parameter.
- The typedefs `cpp_bin_float_50` and `cpp_bin_float_100` provide arithmetic types at 50 and 100 decimal digits precision
- respectively.
- Optionally, you can specify whether the precision is specified in decimal digits or binary bits - for example
- to declare a `cpp_bin_float` with exactly the same precision as `double` one would use
- `number<cpp_bin_float<53, digit_base_2> >`. The typedefs `cpp_bin_float_single`, `cpp_bin_float_double`,
- `cpp_bin_float_quad`, `cpp_bin_float_oct` and `cpp_bin_float_double_extended` provide
- software analogues of the IEEE single, double, quad and octuple float data types, plus the Intel-extended-double type respectively.
- Note that while these types are functionally equivalent to the native IEEE types, but they do not have the same size
- or bit-layout as true IEEE compatible types.
- Normally `cpp_bin_float` allocates no memory: all of the space required for its digits are allocated
- directly within the class. As a result care should be taken not to use the class with too high a digit count
- as stack space requirements can grow out of control. If that represents a problem then providing an allocator
- as a template parameter causes `cpp_bin_float` to dynamically allocate the memory it needs: this
- significantly reduces the size of `cpp_bin_float` and increases the viable upper limit on the number of digits
- at the expense of performance. However, please bear in mind that arithmetic operations rapidly become ['very] expensive
- as the digit count grows: the current implementation really isn't optimized or designed for large digit counts.
- Note that since the actual type of the objects allocated
- is completely opaque, the suggestion would be to use an allocator with `void` `value_type`, for example:
- `number<cpp_bin_float<1000, digit_base_10, std::allocator<void> > >`.
- The final template parameters determine the type and range of the exponent: parameter `Exponent` can be
- any signed integer type, but note that `MinExponent` and `MaxExponent` can not go right up to the limits
- of the `Exponent` type as there has to be a little extra headroom for internal calculations. You will
- get a compile time error if this is the case. In addition if MinExponent or MaxExponent are zero, then
- the library will choose suitable values that are as large as possible given the constraints of the type
- and need for extra headroom for internal calculations.
- There is full standard library and `numeric_limits` support available for this type.
- Things you should know when using this type:
- * Default constructed `cpp_bin_float`s have a value of zero.
- * The radix of this type is 2, even when the precision is specified as decimal digits.
- * The type supports both infinities and NaN's. An infinity is generated whenever the result would overflow,
- and a NaN is generated for any mathematically undefined operation.
- * There is a `std::numeric_limits` specialisation for this type.
- * Any `number` instantiated on this type, is convertible to any other `number` instantiated on this type -
- for example you can convert from `number<cpp_bin_float<50> >` to `number<cpp_bin_float<SomeOtherValue> >`.
- Narrowing conversions round to nearest and are `explicit`.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid floating-point number.
- * All arithmetic operations are correctly rounded to nearest. String conversions and the `sqrt` function
- are also correctly rounded, but transcendental functions (sin, cos, pow, exp etc) are not.
- [h5 cpp_bin_float example:]
- [cpp_bin_float_eg]
- [endsect]
- [section:cpp_dec_float cpp_dec_float]
- `#include <boost/multiprecision/cpp_dec_float.hpp>`
- namespace boost{ namespace multiprecision{
- template <unsigned Digits10, class ExponentType = boost::int32_t, class Allocator = void>
- class cpp_dec_float;
- typedef number<cpp_dec_float<50> > cpp_dec_float_50;
- typedef number<cpp_dec_float<100> > cpp_dec_float_100;
- }} // namespaces
- The `cpp_dec_float` back-end is used in conjunction with `number`: It acts as an entirely C++ (header only and dependency free)
- floating-point number type that is a drop-in replacement for the native C++ floating-point types, but with
- much greater precision.
- Type `cpp_dec_float` can be used at fixed precision by specifying a non-zero `Digits10` template parameter.
- The typedefs `cpp_dec_float_50` and `cpp_dec_float_100` provide arithmetic types at 50 and 100 decimal digits precision
- respectively. Optionally, you can specify an integer type to use for the exponent, this defaults to a 32-bit integer type
- which is more than large enough for the vast majority of use cases, but larger types such as `long long` can also be specified
- if you need a truly huge exponent range. In any case the ExponentType must be a built in signed integer type at least 2 bytes
- and 16-bits wide.
- Normally `cpp_dec_float` allocates no memory: all of the space required for its digits are allocated
- directly within the class. As a result care should be taken not to use the class with too high a digit count
- as stack space requirements can grow out of control. If that represents a problem then providing an allocator
- as the final template parameter causes `cpp_dec_float` to dynamically allocate the memory it needs: this
- significantly reduces the size of `cpp_dec_float` and increases the viable upper limit on the number of digits
- at the expense of performance. However, please bear in mind that arithmetic operations rapidly become ['very] expensive
- as the digit count grows: the current implementation really isn't optimized or designed for large digit counts.
- There is full standard library and `numeric_limits` support available for this type.
- Things you should know when using this type:
- * Default constructed `cpp_dec_float`s have a value of zero.
- * The radix of this type is 10. As a result it can behave subtly differently from base-2 types.
- * The type has a number of internal guard digits over and above those specified in the template argument.
- Normally these should not be visible to the user.
- * The type supports both infinities and NaN's. An infinity is generated whenever the result would overflow,
- and a NaN is generated for any mathematically undefined operation.
- * There is a `std::numeric_limits` specialisation for this type.
- * Any `number` instantiated on this type, is convertible to any other `number` instantiated on this type -
- for example you can convert from `number<cpp_dec_float<50> >` to `number<cpp_dec_float<SomeOtherValue> >`.
- Narrowing conversions are truncating and `explicit`.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid floating-point number.
- * The actual precision of a `cpp_dec_float` is always slightly higher than the number of digits specified in
- the template parameter, actually how much higher is an implementation detail but is always at least 8 decimal
- digits.
- * Operations involving `cpp_dec_float` are always truncating. However, note that since their are guard digits
- in effect, in practice this has no real impact on accuracy for most use cases.
- [h5 cpp_dec_float example:]
- [cpp_dec_float_eg]
- [endsect]
- [section:gmp_float gmp_float]
- `#include <boost/multiprecision/gmp.hpp>`
- namespace boost{ namespace multiprecision{
- template <unsigned Digits10>
- class gmp_float;
- typedef number<gmp_float<50> > mpf_float_50;
- typedef number<gmp_float<100> > mpf_float_100;
- typedef number<gmp_float<500> > mpf_float_500;
- typedef number<gmp_float<1000> > mpf_float_1000;
- typedef number<gmp_float<0> > mpf_float;
- }} // namespaces
- The `gmp_float` back-end is used in conjunction with `number` : it acts as a thin wrapper around the [gmp] `mpf_t`
- to provide an real-number type that is a drop-in replacement for the native C++ floating-point types, but with
- much greater precision.
- Type `gmp_float` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or
- at variable precision by setting the template argument to zero. The typedefs mpf_float_50, mpf_float_100,
- mpf_float_500, mpf_float_1000 provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision
- respectively. The typedef mpf_float provides a variable precision type whose precision can be controlled via the
- `number`s member functions.
- [note This type only provides standard library and `numeric_limits` support when the precision is fixed at compile time.]
- As well as the usual conversions from arithmetic and string types, instances of `number<mpf_float<N> >` are
- copy constructible and assignable from:
- * The [gmp] native types `mpf_t`, `mpz_t`, `mpq_t`.
- * The `number` wrappers around those types: `number<mpf_float<M> >`, `number<gmp_int>`, `number<gmp_rational>`.
- It's also possible to access the underlying `mpf_t` via the `data()` member function of `gmp_float`.
- Things you should know when using this type:
- * Default constructed `gmp_float`s have the value zero (this is the [gmp] library's default behavior).
- * No changes are made to the [gmp] library's global settings, so this type can be safely mixed with
- existing [gmp] code.
- * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
- * It is not possible to round-trip objects of this type to and from a string and get back
- exactly the same value. This appears to be a limitation of [gmp].
- * Since the underlying [gmp] types have no notion of infinities or NaN's, care should be taken
- to avoid numeric overflow or division by zero. That latter will result in a std::overflow_error being thrown,
- while generating excessively large exponents may result in instability of the underlying [gmp]
- library (in testing, converting a number with an excessively large or small exponent
- to a string caused [gmp] to segfault).
- * This type can equally be used with [mpir] as the underlying implementation - indeed that is
- the recommended option on Win32.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid floating-point number.
- * Division by zero results in a `std::overflow_error` being thrown.
- [h5 [gmp] example:]
- [mpf_eg]
- [endsect]
- [section:mpfr_float mpfr_float]
- `#include <boost/multiprecision/mpfr.hpp>`
- namespace boost{ namespace multiprecision{
- enum mpfr_allocation_type
- {
- allocate_stack,
- allocate_dynamic
- };
- template <unsigned Digits10, mpfr_allocation_type AllocateType = allocate_dynamic>
- class mpfr_float_backend;
- typedef number<mpfr_float_backend<50> > mpfr_float_50;
- typedef number<mpfr_float_backend<100> > mpfr_float_100;
- typedef number<mpfr_float_backend<500> > mpfr_float_500;
- typedef number<mpfr_float_backend<1000> > mpfr_float_1000;
- typedef number<mpfr_float_backend<0> > mpfr_float;
- typedef number<mpfr_float_backend<50, allocate_stack> > static_mpfr_float_50;
- typedef number<mpfr_float_backend<100, allocate_stack> > static_mpfr_float_100;
- }} // namespaces
- The `mpfr_float_backend` type is used in conjunction with `number`: It acts as a thin wrapper around the [mpfr] `mpfr_t`
- to provide an real-number type that is a drop-in replacement for the native C++ floating-point types, but with
- much greater precision.
- Type `mpfr_float_backend` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or
- at variable precision by setting the template argument to zero. The typedefs mpfr_float_50, mpfr_float_100,
- mpfr_float_500, mpfr_float_1000 provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision
- respectively. The typedef mpfr_float provides a variable precision type whose precision can be controlled via the
- `number`s member functions.
- In addition the second template parameter lets you choose between dynamic allocation (the default,
- and uses MPFR's normal allocation routines),
- or stack allocation (where all the memory required for the underlying data types is stored
- within `mpfr_float_backend`). The latter option can result in significantly faster code, at the
- expense of growing the size of `mpfr_float_backend`. It can only be used at fixed precision, and
- should only be used for lower digit counts. Note that we can not guarantee that using `allocate_stack`
- won't cause any calls to mpfr's allocation routines, as mpfr may call these inside it's own code.
- The following table gives an idea of the performance tradeoff's at 50 decimal digits
- precision[footnote Compiled with VC++10 and /Ox, with MPFR-3.0.0 and MPIR-2.3.0]:
- [table
- [[Type][Bessel function evaluation, relative times]]
- [[`number<mpfr_float_backend<50, allocate_static>, et_on>`][1.0 (5.5s)]]
- [[`number<mpfr_float_backend<50, allocate_static>, et_off>`][1.05 (5.8s)]]
- [[`number<mpfr_float_backend<50, allocate_dynamic>, et_on>`][1.05 (5.8s)]]
- [[`number<mpfr_float_backend<50, allocate_dynamic>, et_off>`][1.16 (6.4s)]]
- ]
- [note This type only provides `numeric_limits` support when the precision is fixed at compile time.]
- As well as the usual conversions from arithmetic and string types, instances of `number<mpfr_float_backend<N> >` are
- copy constructible and assignable from:
- * The [gmp] native types `mpf_t`, `mpz_t`, `mpq_t`.
- * The [mpfr] native type `mpfr_t`.
- * The `number` wrappers around those types: `number<mpfr_float_backend<M> >`, `number<mpf_float<M> >`, `number<gmp_int>`, `number<gmp_rational>`.
- It's also possible to access the underlying `mpfr_t` via the data() member function of `mpfr_float_backend`.
- Things you should know when using this type:
- * A default constructed `mpfr_float_backend` is set to zero (['Note that this is [*not] the default [mpfr] behavior]).
- * All operations use round to nearest.
- * No changes are made to [gmp] or [mpfr] global settings, so this type can coexist with existing
- [mpfr] or [gmp] code.
- * The code can equally use [mpir] in place of [gmp] - indeed that is the preferred option on Win32.
- * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid floating-point number.
- * Division by zero results in an infinity.
- * When using the variable precision type `mpfr_float`, then copy construction and assignment ['copies the precision
- of the source variable]. Likewise move construction and assignment.
- * When constructing the variable precision type `mpfr_float` you can specify two arguments to the constructor - the first
- is the value to assign to the variable, the second is an unsigned integer specifying the precision in decimal places. The
- `assign` member function similarly has a 2-argument overload taking the value to assign and the precision. You can use this
- to preserve the precision of the target variable using the somewhat arcane: `a.assign(b, a.precision())`, which assigns `b` to `a`
- but preserves the precision of `a`.
- [h5 [mpfr] example:]
- [mpfr_eg]
- [endsect]
- [section:float128 float128]
- `#include <boost/multiprecision/float128.hpp>`
- namespace boost{ namespace multiprecision{
- class float128_backend;
- typedef number<float128_backend, et_off> float128;
- }} // namespaces
- The `float128` number type is a very thin wrapper around GCC's `__float128` or Intel's `_Quad` data types
- and provides an real-number type that is a drop-in replacement for the native C++ floating-point types, but with
- a 113 bit mantissa, and compatible with FORTRAN's 128-bit QUAD real.
- All the usual standard library and `numeric_limits` support are available, performance should be equivalent
- to the underlying native types: for example the LINPACK benchmarks for GCC's `__float128` and
- `boost::multiprecision::float128` both achieved 5.6 MFLOPS[footnote On 64-bit Ubuntu 11.10, GCC-4.8.0, Intel Core 2 Duo T5800.].
- As well as the usual conversions from arithmetic and string types, instances of `float128` are
- copy constructible and assignable from GCC's `__float128` and Intel's `_Quad` data types.
- It's also possible to access the underlying `__float128` or `_Quad` type via the `data()` member
- function of `float128_backend`.
- Things you should know when using this type:
- * Default constructed `float128`s have the value zero.
- * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
- * This type is fully `constexpr` aware - basic constexpr arithmetic is supported from C++14 and onwards, comparisons,
- plus the functions `fabs`, `abs`, `fpclassify`, `isnormal`, `isfinite`, `isinf` and `isnan` are also supported if either
- the compiler implements C++20's `std::is_constant_evaluated()`, or if the compiler is GCC.
- * It is not possible to round-trip objects of this type to and from a string and get back
- exactly the same value when compiled with Intel's C++ compiler and using `_Quad` as the underlying type: this is a current limitation of
- our code. Round tripping when using `__float128` as the underlying type is possible (both for GCC and Intel).
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid floating-point number.
- * Division by zero results in an infinity being produced.
- * Type `float128` can be used as a literal type (constexpr support).
- * Type `float128` can be used for full `constexpr` arithmetic from C++14 and later with GCC. The functions `abs`, `fabs`,
- `fpclassify`, `isnan`, `isinf`, `isfinite` and `isnormal` are also `constexpr`, but the transcendental functions are not.
- * When using the Intel compiler, the underlying type defaults to `__float128` if it's available and `_Quad` if not. You can override
- the default by defining either `BOOST_MP_USE_FLOAT128` or `BOOST_MP_USE_QUAD`.
- * When the underlying type is Intel's `_Quad` type, the code must be compiled with the compiler option `-Qoption,cpp,--extended_float_type`.
- * When compiling with `gcc`, you need to use the flag `--std=gnu++11/14/17`, as the suffix 'Q' is a GNU extension. Compilation fails with the flag `--std=c++11/14/17`
- unless you also use `-fext-numeric-literals`.
- [h5 float128 example:]
- [float128_eg]
- [endsect]
- [section:fp_eg Examples]
- [import ../example/floating_point_examples.cpp]
- [section:aos Area of Circle]
- [AOS1]
- [AOS2]
- [AOS3]
- [endsect]
- [section:jel Defining a Special Function.]
- [JEL]
- [endsect]
- [section:nd Calculating a Derivative]
- [ND1]
- [ND2]
- [ND3]
- [endsect]
- [section:gi Calculating an Integral]
- [GI1]
- [GI2]
- [endsect]
- [section:poly_eg Polynomial Evaluation]
- [POLY]
- [endsect] [/section:poly_eg Polynomial Evaluation]
- [section:variable_precision Variable Precision Newton Evaluation]
- [mpfr_variable]
- [endsect]
- [endsect] [/section:fp_eg Examples]
- [endsect] [/section:floats floating-point Numbers]
- [section:interval Interval Number Types]
- There is one currently only one interval number type supported - [mpfi].
- [section:mpfi mpfi_float]
- `#include <boost/multiprecision/mpfi.hpp>`
- namespace boost{ namespace multiprecision{
- template <unsigned Digits10>
- class mpfi_float_backend;
- typedef number<mpfi_float_backend<50> > mpfi_float_50;
- typedef number<mpfi_float_backend<100> > mpfifloat_100;
- typedef number<mpfi_float_backend<500> > mpfifloat_500;
- typedef number<mpfi_float_backend<1000> > mpfi_float_1000;
- typedef number<mpfi_float_backend<0> > mpfi_float;
- }} // namespaces
- The `mpfi_float_backend` type is used in conjunction with `number`: It acts as a thin wrapper around the [mpfi] `mpfi_t`
- to provide an real-number type that is a drop-in replacement for the native C++ floating-point types, but with
- much greater precision and implementing interval arithmetic.
- Type `mpfi_float_backend` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or
- at variable precision by setting the template argument to zero. The `typedef`s `mpfi_float_50`, `mpfi_float_100`,
- `mpfi_float_500`, `mpfi_float_1000` provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision
- respectively. The `typedef mpfi_float` provides a variable precision type whose precision can be controlled via the
- `number`s member functions.
- [note This type only provides `numeric_limits` support when the precision is fixed at compile time.]
- As well as the usual conversions from arithmetic and string types, instances of `number<mpfi_float_backend<N> >` are
- copy constructible and assignable from:
- * The [mpfi] native type `mpfi_t`.
- * The `number` wrappers around [mpfi] or [mpfr]: `number<mpfi_float_backend<M> >` and `number<mpfr_float<M> >`.
- * There is a two argument constructor taking two `number<mpfr_float<M> >` arguments specifying the interval.
- It's also possible to access the underlying `mpfi_t` via the data() member function of `mpfi_float_backend`.
- Things you should know when using this type:
- * A default constructed `mpfi_float_backend` is set to zero (['Note that this is [*not] the default [mpfi] behavior]).
- * No changes are made to [gmp] or [mpfr] global settings, so this type can coexist with existing
- [mpfr] or [gmp] code.
- * The code can equally use [mpir] in place of [gmp] - indeed that is the preferred option on Win32.
- * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid floating-point number.
- * Division by zero results in an infinity.
- There are some additional non member functions for working on intervals:
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- number<mpfr_float_backend<Digits10>, ExpressionTemplates> lower(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val);
- Returns the lower end of the interval.
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- number<mpfr_float_backend<Digits10>, ExpressionTemplates> upper(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val);
- Returns the upper end of the interval.
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- number<mpfr_float_backend<Digits10>, ExpressionTemplates> median(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val);
- Returns the mid point of the interval.
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- number<mpfr_float_backend<Digits10>, ExpressionTemplates> width(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val);
- Returns the absolute width of the interval.
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- number<mpfi_float_backend<Digits10>, ExpressionTemplates> intersect(
- const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a,
- const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b);
- Returns the interval which is the intersection of the ['a] and ['b]. Returns an
- unspecified empty interval if there is no such intersection.
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- number<mpfi_float_backend<Digits10>, ExpressionTemplates> hull(
- const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a,
- const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b);
- Returns the interval which is the union of ['a] and ['b].
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- bool overlap(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a,
- const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b);
- Returns `true` only if the intervals ['a] and ['b] overlap.
- template <unsigned Digits10, expression_template_option ExpressionTemplates1, expression_template_option ExpressionTemplates2>
- bool in(const number<mpfr_float_backend<Digits10>, ExpressionTemplates1>& a,
- const number<mpfi_float_backend<Digits10>, ExpressionTemplates2>& b);
- Returns `true` only if point ['a] is contained within the interval ['b].
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- bool zero_in(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a);
- Returns `true` only if the interval ['a] contains the value zero.
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- bool subset(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a,
- const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b);
- Returns `true` only if ['a] is a subset of ['b].
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- bool proper_subset(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a,
- const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b);
- Returns `true` only if ['a] is a proper subset of ['b].
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- bool empty(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a);
- Returns `true` only if ['a] is an empty interval, equivalent to `upper(a) < lower(a)`.
- template <unsigned Digits10, expression_template_option ExpressionTemplates>
- bool singleton(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a);
- Returns `true` if `lower(a) == upper(a)`.
- [h5 [mpfi] example:]
- [mpfi_eg]
- [endsect]
- [endsect]
- [section:complex Complex Number Types]
- The following backends provide complex number arithmetic:
- [table
- [[Backend Type][Header][Radix][Dependencies][Pros][Cons]]
- [[`cpp_complex`][boost/multiprecision/cpp_complex.hpp][2][None][An all C++ Boost-licensed implementation.][Slower than [mpc].]]
- [[`mpc`][boost/multiprecision/mpc.hpp][2][[mpc]][Very fast and efficient back-end.][Dependency on LGLP-licensed [MPC] library.]]
- [[`compplex128`][boost/multiprecision/complex128.hpp][2][`__float128` and libquadmath][Very fast and efficient number type.][128-bit precision only, and resticted to GCC.]]
- [[`complex_adaptor`][boost/multiprecision/complex_adaptor.hpp][-][none][Can convert any backend type into a complex number backend.][Not a numbe rin it's own right, and hard to use as a result.]]
- ]
- [section:cpp_complex cpp_complex]
- `#include <boost/multiprecision/cpp_complex.hpp>`
- namespace boost{ namespace multiprecision{
- template <unsigned Digits, backends::digit_base_type DigitBase = backends::digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0>
- using cpp_complex_backend = complex_adaptor<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> >;
- template <unsigned Digits, backends::digit_base_type DigitBase = digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0, expression_template_option ExpressionTemplates = et_off>
- using cpp_complex = number<complex_adaptor<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> >, ExpressionTemplates>;
- typedef cpp_complex<50> cpp_complex_50;
- typedef cpp_complex<100> cpp_complex_100;
- typedef cpp_complex<24, backends::digit_base_2, void, boost::int16_t, -126, 127> cpp_complex_single;
- typedef cpp_complex<53, backends::digit_base_2, void, boost::int16_t, -1022, 1023> cpp_complex_double;
- typedef cpp_complex<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383> cpp_complex_extended;
- typedef cpp_complex<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383> cpp_complex_quad;
- typedef cpp_complex<237, backends::digit_base_2, void, boost::int32_t, -262142, 262143> cpp_complex_oct;
- }} // namespaces
- The `cpp_complex_backend` back-end is used in conjunction with `number`: It acts as an entirely C++ (header only and dependency free)
- complex number type that is a drop-in replacement for `std::complex`, but with much greater precision.
- The template alias `cpp_complex` avoids the need to use class `number` directly.
- Type `cpp_complex` can be used at fixed precision by specifying a non-zero `Digits` template parameter.
- The typedefs `cpp_complex_50` and `cpp_complex_100` provide complex number types at 50 and 100 decimal digits precision
- respectively.
- Optionally, you can specify whether the precision is specified in decimal digits or binary bits - for example
- to declare a `cpp_complex` with exactly the same precision as `std::complex<double>` one would use
- `cpp_complex<53, digit_base_2>`. The typedefs `cpp_complex_single`, `cpp_complex_double`,
- `cpp_complex_quad`, `cpp_complex_oct` and `cpp_complex_double_extended` provide
- software analogues of the IEEE single, double, quad and octuple float data types, plus the Intel-extended-double type respectively.
- Note that while these types are functionally equivalent to the native IEEE types, but they do not have the same size
- or bit-layout as true IEEE compatible types.
- Normally `cpp_complex` allocates no memory: all of the space required for its digits are allocated
- directly within the class. As a result care should be taken not to use the class with too high a digit count
- as stack space requirements can grow out of control. If that represents a problem then providing an allocator
- as a template parameter causes `cpp_complex` to dynamically allocate the memory it needs: this
- significantly reduces the size of `cpp_complex` and increases the viable upper limit on the number of digits
- at the expense of performance. However, please bear in mind that arithmetic operations rapidly become ['very] expensive
- as the digit count grows: the current implementation really isn't optimized or designed for large digit counts.
- Note that since the actual type of the objects allocated
- is completely opaque, the suggestion would be to use an allocator with `char` `value_type`, for example:
- `cpp_complex<1000, digit_base_10, std::allocator<char> >`.
- The next template parameters determine the type and range of the exponent: parameter `Exponent` can be
- any signed integer type, but note that `MinExponent` and `MaxExponent` can not go right up to the limits
- of the `Exponent` type as there has to be a little extra headroom for internal calculations. You will
- get a compile time error if this is the case. In addition if MinExponent or MaxExponent are zero, then
- the library will choose suitable values that are as large as possible given the constraints of the type
- and need for extra headroom for internal calculations.
- Finally, as with class `number`, the final template parameter determines whether expression templates are turn
- on or not. Since by default this type allocates no memory, expression template support is off by default.
- However, you should probably turn it on if you specify an allocator.
- There is full standard library support available for this type, comparable with what `std::complex` provides.
- Things you should know when using this type:
- * Default constructed `cpp_complex`s have a value of zero.
- * The radix of this type is 2, even when the precision is specified as decimal digits.
- * The type supports both infinities and NaN's. An infinity is generated whenever the result would overflow,
- and a NaN is generated for any mathematically undefined operation.
- * There is no `std::numeric_limits` specialisation for this type: this is the same behaviour as `std::complex`. If you need
- `std::numeric_limits` support you need to look at `std::numeric_limits<my_complex_number_type::value_type>`.
- * Any `number` instantiated on this type, is convertible to any other `number` instantiated on this type -
- for example you can convert from `number<cpp_complex<50> >` to `number<cpp_bin_float<SomeOtherValue> >`.
- Narrowing conversions round to nearest and are `explicit`.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid complex number.
- [h5 example:]
- [cpp_complex_eg]
- Which produces the output (for the multiprecision type):
- [cpp_complex_out]
- [endsect]
- [section:mpc_complex mpc_complex]
- `#include <boost/multiprecision/mpc.hpp>`
- namespace boost{ namespace multiprecision{
- template <unsigned Digits10>
- class mpc_complex_backend;
- typedef number<mpc_complex_backend<50> > mpc_complex_50;
- typedef number<mpc_complex_backend<100> > mpc_complex_100;
- typedef number<mpc_complex_backend<500> > mpc_complex_500;
- typedef number<mpc_complex_backend<1000> > mpc_complex_1000;
- typedef number<mpc_complex_backend<0> > mpc_complex;
- }} // namespaces
- The `mpc_complex_backend` type is used in conjunction with `number`: It acts as a thin wrapper around the [mpc] `mpc_t`
- to provide an real-number type that is a drop-in replacement for `std::complex`, but with
- much greater precision.
- Type `mpc_complex_backend` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or
- at variable precision by setting the template argument to zero. The typedefs mpc_complex_50, mpc_complex_100,
- mpc_complex_500, mpc_complex_1000 provide complex types at 50, 100, 500 and 1000 decimal digits precision
- respectively. The typedef mpc_complex provides a variable precision type whose precision can be controlled via the
- `number`s member functions.
- The `mpc` backend should allow use of the same syntax as the C++ standard library complex type.
- When using this backend, remember to link with the flags `-lmpc -lmpfr -lgmp`.
- As well as the usual conversions from arithmetic and string types, instances of `number<mpc_complex_backend<N> >` are
- copy constructible and assignable from:
- * The [gmp] native types `mpf_t`, `mpz_t`, `mpq_t`.
- * The [mpfr] native type `mpfr_t`.
- * The [mpc] native type `mpc_t`.
- * The `number` wrappers around those types: `number<mpfr_float_backend<M> >`, `number<mpf_float<M> >`, `number<gmp_int>`, `number<gmp_rational>`.
- It's also possible to access the underlying `mpc_t` via the data() member function of `mpfr_float_backend`.
- Things you should know when using this type:
- * A default constructed `mpc_complex_backend` is set to zero (['Note that this is [*not] the default [mpc] behavior]).
- * All operations use round to nearest.
- * No changes are made to [mpc], [gmp] or [mpfr] global settings, so this type can coexist with existing
- [mpc], [mpfr] or [gmp] code.
- * The code can equally use [mpir] in place of [gmp] - indeed that is the preferred option on Win32.
- * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid complex number.
- * Division by zero results in a complex-infinity.
- * Unlike `std::complex`, you can not use `reinterpret_cast` to treat this type as an array of the underlying floating point type.
- * Unlike `std::complex`, there are no literals for imaginary values.
- * When using the variable precision type `mpc_complex`, then copy construction and assignment ['copies the precision
- of the source variable]. Likewise move construction and assignment.
- * When constructing the variable precision type `mpc_complex` you can specify two arguments to the constructor - the first
- is the value to assign to the variable, the second is an unsigned integer specifying the precision in decimal places. The
- `assign` member function similarly has a 2-argument overload taking the value to assign and the precision. You can use this
- to preserve the precision of the target variable using the somewhat arcane: `a.assign(b, a.precision())`, which assigns `b` to `a`
- but preserves the precision of `a`.
- [h5 [mpc] example:]
- [mpc_eg]
- Which produces the output (for the multiprecision type):
- [mpc_out]
- [endsect]
- [section:complex128 complex128]
- `#include <boost/multiprecision/complex128.hpp>`
- namespace boost{ namespace multiprecision{
- class complex128_backend;
- typedef number<complex128_backend, et_off> complex128;
- }} // namespaces
- The `complex128` number type is a very thin wrapper around GCC's `__float128` or Intel's `_Quad` data types
- and provides a complex-number type that is a drop-in replacement for the native C++ floating-point types, but with
- a 113 bit mantissa, and compatible with FORTRAN's 128-bit QUAD real.
- All the usual standard library functions are available, performance should be equivalent
- to the underlying native types.
- As well as the usual conversions from arithmetic and string types, instances of `float128` are
- copy constructible and assignable from GCC's `__float128` and Intel's `_Quad` data types.
- Things you should know when using this type:
- * Default constructed `complex128`s have the value zero.
- * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
- * It is not possible to round-trip objects of this type to and from a string and get back
- exactly the same value when compiled with Intel's C++ compiler and using `_Quad` as the underlying type: this is a current limitation of
- our code. Round tripping when using `__float128` as the underlying type is possible (both for GCC and Intel).
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
- as a valid floating-point number.
- * Division by zero results in an infinity being produced.
- * When using the Intel compiler, the underlying type defaults to `__float128` if it's available and `_Quad` if not. You can override
- the default by defining either `BOOST_MP_USE_FLOAT128` or `BOOST_MP_USE_QUAD`.
- * When the underlying type is Intel's `_Quad` type, the code must be compiled with the compiler option `-Qoption,cpp,--extended_float_type`.
- [h5 complex128 example:]
- [complex128_eg]
- Which results in the output:
- [complex128_out]
- [endsect]
- [section:complex_adaptor complex_adaptor]
- namespace boost{ namespace multiprecision{
- template <class Backend>
- struct complex_adaptor;
- }}
- Class template `complex_adaptor` is designed to sit inbetween class `number` and an actual floating point backend,
- in order to create a new complex number type.
- It is the means by which we implement __cpp_complex and __complex128.
- [endsect]
- [endsect]
- [section:rational Rational Number Types]
- The following back-ends provide rational number arithmetic:
- [table
- [[Backend Type][Header][Radix][Dependencies][Pros][Cons]]
- [[`cpp_rational`][boost/multiprecision/cpp_int.hpp][2][None][An all C++ Boost-licensed implementation.][Slower than [gmp].]]
- [[`gmp_rational`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]]
- [[`tommath_rational`][boost/multiprecision/tommath.hpp][2][[tommath]][All C/C++ implementation that's Boost Software Licence compatible.][Slower than [gmp].]]
- [[`rational_adaptor`][boost/multiprecision/rational_adaptor.hpp][N/A][none][All C++ adaptor that allows any integer back-end type to be used as a rational type.][Requires an underlying integer back-end type.]]
- [[`boost::rational`][boost/rational.hpp][N/A][None][A C++ rational number type that can used with any `number` integer type.][The expression templates used by `number` end up being "hidden" inside `boost::rational`: performance may well suffer as a result.]]
- ]
- [section:cpp_rational cpp_rational]
- `#include <boost/multiprecision/cpp_int.hpp>`
- namespace boost{ namespace multiprecision{
- typedef rational_adaptor<cpp_int_backend<> > cpp_rational_backend;
- typedef number<cpp_rational_backend> cpp_rational;
- }} // namespaces
- The `cpp_rational_backend` type is used via the typedef `boost::multiprecision::cpp_rational`. It provides
- a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision.
- As well as the usual conversions from arithmetic and string types, instances of `cpp_rational` are copy constructible
- and assignable from type `cpp_int`.
- There is also a two argument constructor that accepts a numerator and denominator: both of type `cpp_int`.
- There are also non-member functions:
- cpp_int numerator(const cpp_rational&);
- cpp_int denominator(const cpp_rational&);
- which return the numerator and denominator of the number.
- Things you should know when using this type:
- * Default constructed `cpp_rational`s have the value zero.
- * Division by zero results in a `std::overflow_error` being thrown.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be
- interpreted as a valid rational number.
- [h5 Example:]
- [cpp_rational_eg]
- [endsect]
- [section:gmp_rational gmp_rational]
- `#include <boost/multiprecision/gmp.hpp>`
- namespace boost{ namespace multiprecision{
- class gmp_rational;
- typedef number<gmp_rational > mpq_rational;
- }} // namespaces
- The `gmp_rational` back-end is used via the typedef `boost::multiprecision::mpq_rational`. It acts as a thin wrapper around the [gmp] `mpq_t`
- to provide a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision.
- As well as the usual conversions from arithmetic and string types, instances of `number<gmp_rational>` are copy constructible
- and assignable from:
- * The [gmp] native types: `mpz_t`, `mpq_t`.
- * `number<gmp_int>`.
- There is also a two-argument constructor that accepts a numerator and denominator (both of type `number<gmp_int>`).
- There are also non-member functions:
- mpz_int numerator(const mpq_rational&);
- mpz_int denominator(const mpq_rational&);
- which return the numerator and denominator of the number.
- It's also possible to access the underlying `mpq_t` via the `data()` member function of `mpq_rational`.
- Things you should know when using this type:
- * Default constructed `mpq_rational`s have the value zero (this is the [gmp] default behavior).
- * Division by zero results in a `std::overflow_error` being thrown.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be
- interpreted as a valid rational number.
- * No changes are made to the [gmp] library's global settings, so this type can coexist with existing
- [gmp] code.
- * The code can equally be used with [mpir] as the underlying library - indeed that is the preferred option on Win32.
- [h5 Example:]
- [mpq_eg]
- [endsect]
- [section:tommath_rational tommath_rational]
- `#include <boost/multiprecision/tommath.hpp>`
- namespace boost{ namespace multiprecision{
- typedef rational_adpater<tommath_int> tommath_rational;
- typedef number<tommath_rational > tom_rational;
- }} // namespaces
- The `tommath_rational` back-end is used via the typedef `boost::multiprecision::tom_rational`. It acts as a thin wrapper around
- `boost::rational<tom_int>`
- to provide a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision.
- The advantage of using this type rather than `boost::rational<tom_int>` directly, is that it is expression-template enabled,
- greatly reducing the number of temporaries created in complex expressions.
- There are also non-member functions:
- tom_int numerator(const tom_rational&);
- tom_int denominator(const tom_rational&);
- which return the numerator and denominator of the number.
- Things you should know when using this type:
- * Default constructed `tom_rational`s have the value zero (this the inherited Boost.Rational behavior).
- * Division by zero results in a `std::overflow_error` being thrown.
- * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be
- interpreted as a valid rational number.
- * No changes are made to [tommath]'s global state, so this type can safely coexist with other [tommath] code.
- * Performance of this type has been found to be pretty poor - this need further investigation - but it appears that Boost.Rational
- needs some improvement in this area.
- [h5 Example:]
- [mp_rat_eg]
- [endsect]
- [section:br Use With Boost.Rational]
- All of the integer types in this library can be used as template arguments to `boost::rational<IntType>`.
- Note that using the library in this way largely negates the effect of the expression templates in `number`.
- [endsect]
- [section:rational_adaptor rational_adaptor]
- namespace boost{ namespace multiprecision{
- template <class IntBackend>
- class rational_adpater;
- }}
- The class template `rational_adaptor` is a back-end for `number` which converts any existing integer back-end
- into a rational-number back-end.
- So for example, given an integer back-end type `MyIntegerBackend`, the use would be something like:
- typedef number<MyIntegerBackend> MyInt;
- typedef number<rational_adaptor<MyIntegerBackend> > MyRational;
- MyRational r = 2;
- r /= 3;
- MyInt i = numerator(r);
- assert(i == 2);
- [endsect]
- [endsect]
- [section:misc Miscellaneous Number Types.]
- Backend types listed in this section are predominantly designed to aid debugging.
- [section:logged_adaptor logged_adaptor]
- `#include <boost/multiprecision/logged_adaptor.hpp>`
- namespace boost{ namespace multiprecision{
- template <class Backend>
- void log_postfix_event(const Backend& result, const char* event_description);
- template <class Backend, class T>
- void log_postfix_event(const Backend& result1, const T& result2, const char* event_description);
- template <class Backend>
- void log_prefix_event(const Backend& arg1, const char* event_description);
- template <class Backend, class T>
- void log_prefix_event(const Backend& arg1, const T& arg2, const char* event_description);
- template <class Backend, class T, class U>
- void log_prefix_event(const Backend& arg1, const T& arg2, const U& arg3, const char* event_description);
- template <class Backend, class T, class U, class V>
- void log_prefix_event(const Backend& arg1, const T& arg2, const U& arg3, const V& arg4, const char* event_description);
- template <Backend>
- class logged_adaptor;
- }} // namespaces
- The `logged_adaptor` type is used in conjunction with `number` and some other backend type: it acts as a thin wrapper around
- some other backend to class `number` and logs all the events that take place on that object. Before any number operation takes
- place, it calls `log_prefix_event` with the arguments to the operation (up to 4), plus a string describing the operation.
- Then after the operation it calls `log_postfix_event` with the result of the operation, plus a string describing the operation.
- Optionally, `log_postfix_event` takes a second result argument: this occurs when the result of the operation is not a `number`,
- for example when `fpclassify` is called, `log_postfix_event` will be called with `result1` being the argument to the function, and
- `result2` being the integer result of `fpclassify`.
- The default versions of `log_prefix_event` and `log_postfix_event` do nothing, it is therefore up to the user to overload these
- for the particular backend being observed.
- This type provides `numeric_limits` support whenever the template argument Backend does so.
- This type is particularly useful when combined with an interval number type - in this case we can use `log_postfix_event`
- to monitor the error accumulated after each operation. We could either set some kind of trap whenever the accumulated error
- exceeds some threshold, or simply print out diagnostic information. Using this technique we can quickly locate the cause of
- numerical instability in a particular routine. The following example demonstrates this technique in a trivial algorithm
- that deliberately introduces cancellation error:
- [logged_adaptor]
- When we examine program output we can clearly see that the diameter of the interval increases after each subtraction:
- [logged_adaptor_output]
- [endsect]
- [section:debug_adaptor debug_adaptor]
- `#include <boost/multiprecision/debug_adaptor.hpp>`
- namespace boost{ namespace multiprecision{
- template <Backend>
- class debug_adaptor;
- }} // namespaces
- The `debug_adaptor` type is used in conjunction with `number` and some other backend type: it acts as a thin wrapper around
- some other backend to class `number` and intercepts all operations on that object storing the result as a string within itself.
- This type provides `numeric_limits` support whenever the template argument Backend does so.
- This type is particularly useful when your debugger provides a good view of `std::string`: when this is the case
- multiprecision values can easily be inspected in the debugger by looking at the `debug_value` member of `debug_adaptor`.
- The down side of this approach is that runtimes are much slower when using this type. Set against that it can make
- debugging very much easier, certainly much easier than sprinkling code with `printf` statements.
- When used in conjunction with the Visual C++ debugger visualisers, the value of a multiprecision type that uses this
- backend is displayed in the debugger just a builtin value would be, here we're inspecting a value of type
- `number<debug_adaptor<cpp_dec_float<50> > >`:
- [$../debugger1.png]
- Otherwise you will need to expand out the view and look at the "debug_value" member:
- [$../debugger2.png]
- It works for all the backend types equally too, here it is inspecting a `number<debug_adaptor<gmp_rational> >`:
- [$../debugger3.png]
- [endsect]
- [section:visualizers Visual C++ Debugger Visualizers]
- Let's face it debugger multiprecision numbers is hard - simply because we can't easily inspect the value of the numbers.
- Visual C++ provides a partial solution in the shape of "visualizers" which provide improved views of complex data structures,
- these visualizers need to be added to the `[Visualizer]` section of `autoexp.dat` located in the `Common7/Packages/Debugger`
- directory of your Visual Studio installation. The actual visualizer code is in the sandbox
- [@https://svn.boost.org/svn/boost/sandbox/boost_docs/subprojects/DebuggerVisualizers/multiprecision.vis.txt here] - just cut and paste the code
- into your `autoexp.dat` file.
- [note These visualizers have only been tested with VC10, also given the ability of buggy visualizers to crash your Visual C++
- debugger, make sure you back up `autoexp.dat` file before using these!!]
- The first visualizer provides improved views of `debug_adaptor`:
- [$../debugger1.png]
- The next visualizer provides improved views of cpp_int: small numbers are displayed as actual values, while larger numbers are
- displayed as an array of hexadecimal parts, with the most significant part first.
- Here's what it looks like for small values:
- [$../debugger4.png]
- And for larger values:
- [$../debugger5.png]
- There is also a `~raw` child member that
- lets you see the actual members of the class:
- [$../debugger6.png]
- The visualizer for `cpp_dec_float` shows the first few digits of the value in the preview field, and the full array of digits
- when you expand the view. As before the `~raw` child gives you access to the actual data members:
- [$../debugger7.png]
- [endsect]
- [endsect]
- [section:conversions Constructing and Interconverting Between Number Types]
- All of the number types that are based on `number` have certain conversion rules in common.
- In particular:
- * Any number type can be constructed (or assigned) from any builtin arithmetic type, as long
- as the conversion isn't lossy (for example float to int conversion):
- cpp_dec_float_50 df(0.5); // OK construction from double
- cpp_int i(450); // OK constructs from signed int
- cpp_int j = 3.14; // Error, lossy conversion.
- * A number can be explicitly constructed from an arithmetic type, even when the conversion is lossy:
- cpp_int i(3.14); // OK explicit conversion
- i = static_cast<cpp_int>(3.14) // OK explicit conversion
- i.assign(3.14); // OK, explicit assign and avoid a temporary from the cast above
- i = 3.14; // Error, no implicit assignment operator for lossy conversion.
- cpp_int j = 3.14; // Error, no implicit constructor for lossy conversion.
- * A `number` can be converted to any built in type, via the `convert_to` member function:
- mpz_int z(2);
- int i = z.convert_to<int>(); // sets i to 2
- * Conversions to rational numbers from floating-point ones are always allowed, and are exact and implicit
- as long as the rational number uses an unbounded integer type. Please be aware that constructing a rational
- number from an extended precision floating-point type with a large exponent range can effectively run the system
- out of memory, as in the extreme case ['2[super max_exponent] / CHAR_BITS] bytes of storage may be required. This
- does not represent a problem for built in floating-point types however, as the exponent range for these is rather
- limited.
- * Conversions to floating-point numbers from rational ones are rounded to nearest (less than 0.5ulp error)
- as long as the floating-point number is binary, and the integer type used by the rational number is unbounded.
- Additional conversions may be supported by particular backends.
- * A `number` can be converted to any built in type, via an explicit conversion operator:
- this functionality is only available on compilers supporting C++11's explicit conversion syntax.
- mpz_int z(2);
- int i = z; // Error, implicit conversion not allowed.
- int j = static_cast<int>(z); // OK explicit conversion.
- * Any number type can be ['explicitly] constructed (or assigned) from a `const char*` or a `std::string`:
- // pi to 50 places from a string:
- cpp_dec_float_50 df("3.14159265358979323846264338327950288419716939937510");
- // Integer type will automatically detect "0x" and "0" prefixes and parse the string accordingly:
- cpp_int i("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000");
- // Invalid input always results in a std::runtime_error being thrown:
- i = static_cast<cpp_int>("3.14");
- // implicit conversions from strings are not allowed:
- i = "23"; // Error, no assignment operator for implicit conversion from string
- // assign member function, avoids having to create a temporary via a static_cast:
- i.assign("23"); // OK
- * Any number type will interoperate with the builtin types in arithmetic expressions as long as the conversions
- are not lossy:
- // pi to 50 places from a string:
- cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510";
- // Multiply by 2 - using an integer literal here is usually more efficient
- // than constructing a temporary:
- df *= 2;
- // You can't mix integer types with floats though:
- cpp_int i = 2;
- i *= 3.14; // Error, no *= operator will be found.
- * Any number type can be streamed to and from the C++ iostreams:
- cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510";
- // Now print at full precision:
- std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10)
- << df << std::endl
- cpp_int i = 1;
- i <<= 256;
- // Now print in hex format with prefix:
- std::cout << std::hex << std::showbase << i << std::endl;
- * Interconversions between number types of the same family are allowed and are implicit conversions if no
- loss of precision is involved, and explicit if it is:
- int128_t i128 = 0;
- int266_t i256 = i128; // OK implicit widening conversion
- i128_t = i256; // Error, no assignment operator found, narrowing conversion is explicit.
- i128_t = static_cast<int128_t>(i256); // OK, explicit narrowing conversion.
- mpz_int z = 0;
- mpf_float f = z; // OK, GMP handles this conversion natively, and it's not lossy and therefore implicit.
- mpf_float_50 f50 = 2;
- f = f50; // OK, conversion from fixed to variable precision, f will have 50 digits precision.
- f50 = f; // Error, conversion from variable to fixed precision is potentially lossy, explicit cast required.
- * Some interconversions between number types are completely generic, and are always available, albeit the conversions are always ['explicit]:
- cpp_int cppi(2);
- // We can always convert between numbers of the same category -
- // int to int, rational to rational, or float to float, so this is OK
- // as long as we use an explicit conversion:
- mpz_int z(cppi);
- // We can always promote from int to rational, int to float, or rational to float:
- cpp_rational cppr(cppi); // OK, int to rational
- cpp_dec_float_50 df(cppi); // OK, int to float
- df = static_cast<cpp_dec_float_50>(cppr); // OK, explicit rational to float conversion
- // However narrowing and/or implicit conversions always fail:
- cppi = df; // Compiler error, conversion not allowed
- * Other interconversions may be allowed as special cases, whenever the backend allows it:
- mpf_t m; // Native GMP type.
- mpf_init_set_ui(m, 0); // set to a value;
- mpf_float i(m); // copies the value of the native type.
- More information on what additional types a backend supports conversions from are given in the tutorial for each backend.
- The converting constructor will be implicit if the backend's converting constructor is also implicit, and explicit if the
- backends converting constructor is also explicit.
- [endsect]
- [section:random Generating Random Numbers]
- Random numbers are generated in conjunction with Boost.Random.
- There is a single generator that supports generating random integers with large bit counts:
- [@http://www.boost.org/doc/html/boost/random/independent_bits_engine.html `independent_bits_engine`].
- This type can be used with either ['unbounded] integer types, or with ['bounded] (ie fixed precision) unsigned integers:
- [random_eg1]
- Program output is:
- [random_eg1_out]
- In addition, the generator adaptors [@http://www.boost.org/doc/html/boost/random/discard_block_engine.html `discard_block`],
- [@http://www.boost.org/doc/html/boost/random/xor_combine_engine.html `xor_combine_engine`] and
- [@http://www.boost.org/doc/html/boost/random/discrete_distribution.html `discrete_distribution`] can be used
- with multiprecision types. Note that if you seed an `independent_bits_engine`, then you are actually seeding
- the underlying generator, and should therefore provide a sequence of unsigned 32-bit values as the seed.
- Alternatively we can generate integers in a given range using
- [@http://www.boost.org/doc/html/boost/random/uniform_int_distribution.html `uniform_int_distribution`], this will
- invoke the underlying engine multiple times to build up the required number of bits in the result:
- [random_eg2]
- [random_eg2_out]
- It is also possible to use [@http://www.boost.org/doc/html/boost/random/uniform_int_distribution.html `uniform_int_distribution`]
- with a multiprecision generator such as [@http://www.boost.org/doc/html/boost/random/independent_bits_engine.html `independent_bits_engine`].
- Or to use [@http://www.boost.org/doc/html/boost/random/uniform_smallint.html `uniform_smallint`] or
- [@http://www.boost.org/doc/html/boost/random/random_number_generator.html `random_number_generator`] with multiprecision types.
- floating-point values in \[0,1) are most easily generated using [@http://www.boost.org/doc/html/boost/random/generate_canonical.html `generate_canonical`],
- note that `generate_canonical` will call the generator multiple times to produce the requested number of bits, for example we can use
- it with a regular generator like so:
- [random_eg3]
- [random_eg3_out]
- Note however, the distributions do not invoke the generator multiple times to fill up the mantissa of a multiprecision floating-point type
- with random bits. For these therefore, we should probably use a multiprecision generator (ie `independent_bits_engine`) in combination
- with the distribution:
- [random_eg4]
- [random_eg4_out]
- And finally, it is possible to use the floating-point generators [@http://www.boost.org/doc/html/boost/random/lagged_fibonacci_01_engine.html `lagged_fibonacci_01_engine`]
- and [@http://www.boost.org/doc/html/boost/random/subtract_with_idp144360752.html `subtract_with_carry_01_engine`] directly with multiprecision floating-point types.
- It's worth noting however, that there is a distinct lack of literature on generating high bit-count random numbers, and therefore a lack of "known good" parameters to
- use with these generators in this situation. For this reason, these should probably be used for research purposes only:
- [random_eg5]
- [endsect]
- [section:primetest Primality Testing]
- The library implements a Miller-Rabin test for primality:
- #include <boost/multiprecision/miller_rabin.hpp>
- template <class Backend, expression_template_option ExpressionTemplates, class Engine>
- bool miller_rabin_test(const number<Backend, ExpressionTemplates>& n, unsigned trials, Engine& gen);
- template <class Backend, expression_template_option ExpressionTemplates, class Engine>
- bool miller_rabin_test(const number<Backend, ExpressionTemplates>& n, unsigned trials);
- These functions perform a Miller-Rabin test for primality, if the result is `false` then /n/ is definitely composite,
- while if the result is true then n is probably prime. The probability to declare a composite n as probable prime is
- at most 0.25[super trials]. Note that this does not allow a statement about the probability of n being actually
- prime (for that, the prior probability would have to be known). The algorithm used performs some
- trial divisions to exclude small prime factors, does one Fermat test to exclude many more composites, and then
- uses the Miller-Rabin algorithm straight out of
- Knuth Vol 2, which recommends 25 trials for a pretty strong likelihood that /n/ is prime.
- The third optional argument is for a Uniform Random Number Generator from Boost.Random. When not provided the `mt19937`
- generator is used. Note that when producing random primes then you should probably use a different random number generator
- to produce candidate prime numbers for testing, than is used internally by `miller_rabin_test` for determining
- whether the value is prime. It also helps of course to seed the generators with some source of randomness.
- The following example searches for a prime `p` for which `(p-1)/2` is also probably prime:
- [safe_prime]
- [endsect]
- [section:lits Literal Types and `constexpr` Support]
- There are two kinds of `constexpr` support in this library:
- * The more basic version requires only C++11 and allow the construction of some number types as literals.
- * The more advanced support permits constexpr arithmetic and requires at least C++14
- constexpr support, and for many operations C++2a support
- [h4 Declaring numeric literals]
- There are two backend types which are literals:
- * __float128 (which requires GCC), and
- * Instantiations of `cpp_int_backend` where the Allocator parameter is type `void`.
- In addition, prior to C++14 the Checked parameter must be `boost::multiprecision::unchecked`.
- For example:
- using namespace boost::multiprecision;
- constexpr float128 f = 0.1Q // OK, float128's are always literals in C++11
- constexpr int128_t i = 0; // OK, fixed precision int128_t has no allocator.
- constexpr uint1024_t j = 0xFFFFFFFF00000000uLL; // OK, fixed precision uint1024_t has no allocator.
- constexpr checked_uint128_t k = 1; // OK from C++14 and later, not supported for C++11.
- constexpr checked_uint128_t k = -1; // Error, as this would normally lead to a runtime failure (exception).
- constexpr cpp_int l = 2; // Error, type is not a literal as it performs memory management.
- There is also support for user defined-literals with __cpp_int - these are limited to unchecked, fixed precision `cpp_int`'s
- which are specified in hexadecimal notation. The suffixes supported are:
- [table
- [[Suffix][Meaning]]
- [[_cppi][Specifies a value of type: `number<cpp_int_backend<N,N,signed_magnitude,unchecked,void> >`, where N is chosen
- to contain just enough digits to hold the number specified.]]
- [[_cppui][Specifies a value of type: `number<cpp_int_backend<N,N,unsigned_magnitude,unchecked,void> >`, where N is chosen
- to contain just enough digits to hold the number specified.]]
- [[_cppi['N]][Specifies a value of type `number<cpp_int_backend<N,N,signed_magnitude,unchecked,void> >`.]]
- [[_cppui['N]][Specifies a value of type `number<cpp_int_backend<N,N,signed_magnitude,unchecked,void> >`.]]
- ]
- In each case, use of these suffixes with hexadecimal values produces a `constexpr` result.
- Examples:
- //
- // Any use of user defined literals requires that we import the literal-operators
- // into current scope first:
- using namespace boost::multiprecision::literals;
- //
- // To keep things simple in the example, we'll make our types used visible to this scope as well:
- using namespace boost::multiprecision;
- //
- // The value zero as a number<cpp_int_backend<4,4,signed_magnitude,unchecked,void> >:
- constexpr auto a = 0x0_cppi;
- // The type of each constant has 4 bits per hexadecimal digit,
- // so this is of type uint256_t (ie number<cpp_int_backend<256,256,unsigned_magnitude,unchecked,void> >):
- constexpr auto b = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_cppui;
- //
- // Smaller values can be assigned to larger values:
- int256_t c = 0x1234_cppi; // OK
- //
- // However, this only works in constexpr contexts from C++14 onwards:
- constexpr int256_t d = 0x1_cppi; // Compiler error in C++11, requires C++14
- //
- // Constants can be padded out with leading zeros to generate wider types:
- constexpr uint256_t e = 0x0000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFF_cppui; // OK
- //
- // However, specific width types are best produced with specific-width suffixes,
- // ones supported by default are `_cpp[u]i128`, `_cpp[u]i256`, `_cpp[u]i512`, `_cpp[u]i1024`.
- //
- constexpr int128_t f = 0x1234_cppi128; // OK, always produces an int128_t as the result.
- constexpr uint1024_t g = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccc_cppui1024;
- //
- // If other specific width types are required, then there is a macro for generating the operators
- // for these. The macro can be used at namespace scope only:
- //
- BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(2048);
- //
- // Now we can create 2048-bit literals as well:
- constexpr auto h = 0xff_cppi2048; // h is of type number<cpp_int_backend<2048,2048,signed_magnitude,unchecked,void> >
- //
- // Finally negative values are handled via the unary minus operator:
- //
- constexpr int1024_t i = -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_cppui1024;
- //
- // Which means this also works:
- constexpr int1024_t j = -g; // OK: unary minus operator is constexpr.
- [h4 constexpr arithmetic]
- The front end of the library is all `constexpr` from C++14 and later. Currently there are only two
- back end types that are `constexpr` aware: __float128 and __cpp_int. More backends will follow at a later date.
- Provided the compiler is GCC, type __float128 support `constexpr` operations on all arithmetic operations from C++14, comparisons,
- `abs`, `fabs`, `fpclassify`, `isnan`, `isinf`, `isfinite` and `isnormal` are also fully supported, but the transcendental functions are not.
- The __cpp_int types support constexpr arithmetic, provided it is a fixed precision type with no allocator. It may also
- be a checked integer: in which case a compiler error will be generated on overflow or undefined behaviour. In addition
- the free functions `abs`, `swap`, `multiply`, `add`, `subtract`, `divide_qr`, `integer_modulus`, `powm`, `lsb`, `msb`,
- `bit_test`, `bit_set`, `bit_unset`, `bit_flip`, `sqrt`, `gcd`, `lcm` are all supported. Use of __cpp_int in this way
- requires either a C++2a compiler (one which supports `std::is_constant_evaluated()` - currently only gcc-9 or clang-9 or later),
- or GCC-6 or later in C++14 mode.
- Compilers other than GCC and without `std::is_constant_evaluated()` will support a very limited set of operations:
- expect to hit roadblocks rather easily.
- For example given:
- [constexpr_circle]
- We can now calculate areas and circumferences using all constexpr arithmetic:
- [constexpr_circle_usage]
- Note that these make use of the numeric constants from the Math library, which also happen to be `constexpr`.
- For a more interesting example, in [@../../example/constexpr_float_arithmetic_examples.cpp constexpr_float_arithmetic_examples.cpp]
- we define a simple class for `constexpr` polynomial arithmetic:
- template <class T, unsigned Order>
- struct const_polynomial;
- Given this, we can use recurrence relations to calculate the coefficients for various orthogonal
- polynomials - in the example we use the Hermite polynomials, only the constructor does any work -
- it uses the recurrence relations to calculate the coefficient array:
- [hermite_example]
- Now we just need to define H[sub 0] and H[sub 1] as termination conditions for the recurrence:
- [hermite_example2]
- We can now declare H[sub 9] as a constexpr object, access the coefficients, and evaluate
- at an abscissa value, all using `constexpr` arithmetic:
- [hermite_example3]
- Also since the coefficients to the Hermite polynomials are integers, we can also generate the Hermite
- coefficients using (fixed precision) cpp_int's: see [@../../test/constexpr_test_cpp_int_6.cpp constexpr_test_cpp_int_6.cpp].
- We can also generate factorials (and validate the result) like so:
- [factorial_decl]
- constexpr uint1024_t f1 = factorial(uint1024_t(31));
- static_assert(f1 == 0x1956ad0aae33a4560c5cd2c000000_cppi);
- Another example in [@../../test/constexpr_test_cpp_int_7.cpp constexpr_test_cpp_int_7.cpp] generates
- a fresh multiprecision random number each time the file is compiled.
- [endsect]
- [section:import_export Importing and Exporting Data to and from `cpp_int` and `cpp_bin_float`]
- Any integer number type that uses `cpp_int_backend` as it's implementation layer can import or export its bits via two non-member functions:
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator,
- expression_template_option ExpressionTemplates, class OutputIterator>
- OutputIterator export_bits(
- const number<const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val,
- OutputIterator out,
- unsigned chunk_size,
- bool msv_first = true);
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator,
- expression_template_option ExpressionTemplates, class Iterator>
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
- import_bits(
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val,
- Iterator i,
- Iterator j,
- unsigned chunk_size = 0,
- bool msv_first = true);
- These functions are designed for data-interchange with other storage formats, and since __cpp_bin_float uses __cpp_int internally,
- by extension they can be used for floating-point numbers based on that backend as well (see example below).
- Parameters and use are as follows:
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator,
- expression_template_option ExpressionTemplates, class OutputIterator>
- OutputIterator export_bits(
- const number<const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val,
- OutputIterator out,
- unsigned chunk_size,
- bool msv_first = true);
- Exports the absolute value of `val` to OutputIterator `out`. The function will write `chunk_size` bits at a time
- to the OutputIterator, and if `msv_first` is true, will write the most-significant block first. Byte and bit order
- within each `chunk_size` block is always in the machines native format. Further, each block is stored in a
- `boost::uintmax_t` when it's assigned to `*out`.
- [note Unfortunately, the standard's OutputIterator concept provides no means of deducing the type to output since
- `std::iterator_traits<OutputIteratorType>::value_type` is type `void`. This is why the bit count for each block
- has to be specified manually. It may also result in compiler warnings about the value being narrowed.]
- [tip If you're exporting to non-native byte layout, then use
- [@http://www.boost.org/doc/libs/release/libs/endian/doc/index.html Boost.Endian]
- to create a custom OutputIterator that reverses the byte order of each chunk prior to actually storing the result.]
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator,
- expression_template_option ExpressionTemplates, class ForwardIterator>
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
- import_bits(
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val,
- ForwardIterator i,
- ForwardIterator j,
- unsigned chunk_size = 0,
- bool msv_first = true);
- Imports bits from the iterator range ['\[i,j)] and stores them in `val` to produce an unsigned result (if the result
- is to be signed you will need to handle that separately). When `msv_first` is true, takes `*i` as the most significant
- chunk. Assumes there are `chunk_size` bits in each value read from the iterator range, and that these are in machine native
- bit/byte order. When `chunk_size` is zero, then assumes that each chunk contains
- `std::numeric_limits<std::iterator_traits<ForwardIterator>::value_type>::digits`, note that this will give the wrong result
- if dereferencing the iterators leads to a signed-integer type, [*and] the sign bit is significant (be particularly careful
- if you expect type `char` to contain 8-bit values, as by default it will extract only 7-bits at a time if `char` is signed).
- As with exporting, if the external data is to be in a non-native byte order (within each chunk), then you will need to create an iterator adaptor
- that presents it in native order (see [@http://www.boost.org/doc/libs/release/libs/endian/doc/index.html Boost.Endian]).
- [note
- Note that this function is optimized for the case where the data can be `memcpy`ed from the source to the integer - in this case both
- iterators much be pointers, and everything must be little-endian.]
- [h4 Examples]
- [IE1]
- [IE2]
- [endsect] [/section:import_export Importing and Exporting Data to and from `cpp_int` and `cpp_bin_float`]
- [section:rounding Rounding Rules for Conversions]
- As a general rule, all conversions between unrelated types are performed using basic arithmetic operations, therefore
- conversions are either exact, or follow the same rounding rules as arithmetic for the type in question.
- The following table summarises the situation for conversions from native types:
- [table
- [[Backend][Rounding Rules]]
- [[__cpp_int][Conversions from integer types are exact if the target has sufficient precision, otherwise they
- truncate to the first 2^MaxBits bits (modulo arithmetic). Conversions from floating-point types
- are truncating to the nearest integer.]]
- [[__gmp_int][Conversions are performed by the GMP library except for conversion from `long double` which is truncating.]]
- [[__tom_int][Conversions from floating-point types are truncating, all others are performed by libtommath and are exact.]]
- [[__gmp_float][Conversions are performed by the GMP library except for conversion from `long double` which should be exact
- provided the target type has as much precision as a `long double`.]]
- [[__mpfr_float_backend][All conversions are performed by the underlying MPFR library.]]
- [[__cpp_dec_float][All conversions are performed using basic arithmetic operations and are truncating.]]
- [[__gmp_rational][See __gmp_int]]
- [[__cpp_rational][See __cpp_int]]
- [[__tommath_rational][See __tom_int]]
- ]
- [endsect] [/section:rounding Rounding Rules for Conversions]
- [section:mixed Mixed Precision Arithmetic]
- Mixed precision arithmetic is fully supported by the library.
- There are two different forms:
- * Where the operands are of different precision.
- * Where the operands are of the same precision, but yield a higher precision result.
- [h4 Mixing Operands of Differing Precision]
- If the arguments to a binary operator are of different precision, then the operation is allowed
- as long as there is an unambiguous implicit conversion from one argument type to the other.
- In all cases the arithmetic is performed "as if" the lower precision type is promoted to the
- higher precision type before applying the operator. However, particular backends may optimise
- this and avoid actually creating a temporary if they are able to do so.
- For example:
- mpfr_float_50 a(2), b;
- mpfr_float_100 c(3), d;
- static_mpfr_float_50 e(5), f;
- mpz_int i(20);
- d = a * c; // OK, result of operand is an mpfr_float_100.
- b = a * c; // Error, can't convert the result to an mpfr_float_50 as it will lose digits.
- f = a * e; // Error, operator is ambiguous, result could be of either type.
- f = e * i; // OK, unambiguous conversion from mpz_int to static_mpfr_float_50
- [h4 Operands of the Same Precision]
- Sometimes you want to apply an operator to two arguments of the same precision in
- such a way as to obtain a result of higher precision. The most common situation
- occurs with fixed precision integers, where you want to multiply two N-bit numbers
- to obtain a 2N-bit result. This is supported in this library by the following
- free functions:
- template <class ResultType, class Source1 class Source2>
- ResultType& add(ResultType& result, const Source1& a, const Source2& b);
- template <class ResultType, class Source1 class Source2>
- ResultType& subtract(ResultType& result, const Source1& a, const Source2& b);
- template <class ResultType, class Source1 class Source2>
- ResultType& multiply(ResultType& result, const Source1& a, const Source2& b);
- These functions apply the named operator to the arguments ['a] and ['b] and store the
- result in ['result], returning ['result]. In all cases they behave "as if"
- arguments ['a] and ['b] were first promoted to type `ResultType` before applying the
- operator, though particular backends may well avoid that step by way of an optimization.
- The type `ResultType` must be an instance of class `number`, and the types `Source1` and `Source2`
- may be either instances of class `number` or native integer types. The latter is an optimization
- that allows arithmetic to be performed on native integer types producing an extended precision result.
- For example:
- [mixed_eg]
- Produces the output:
- [mixed_output]
- [h4 Backends With Optimized Mixed Precision Arithmetic]
- The following backends have at least some direct support for mixed precision arithmetic,
- and therefore avoid creating unnecessary temporaries when using the interfaces above.
- Therefore when using these types it's more efficient to use mixed precision arithmetic,
- than it is to explicitly cast the operands to the result type:
- __mpfr_float_backend, __mpf_float, __cpp_int.
- [endsect] [/section:mixed Mixed Precision Arithmetic]
- [section:gen_int Generic Integer Operations]
- All of the [link boost_multiprecision.ref.number.integer_functions non-member integer operations] are overloaded for the
- built in integer types in
- `<boost/multiprecision/integer.hpp>`.
- Where these operations require a temporary increase in precision (such as for `powm`), then
- if no built in type is available, a __cpp_int of appropriate precision will be used.
- Some of these functions are trivial, others use compiler intrinsics (where available) to ensure optimal evaluation.
- The overloaded functions are:
- template <class Integer, class I2>
- Integer& multiply(Integer& result, const I2& a, const I2& b);
- Multiplies two `I2` values, to produce a wider `Integer` result.
- Returns `result = a * b` without overflow or loss of precision in the multiplication.
- template <class Integer, class I2>
- Integer& add(Integer& result, const I2& a, const I2& b);
- Adds two `I2` values, to produce a wider `Integer` result.
- Returns `result = a + b` without overflow or loss of precision in the addition.
- template <class Integer, class I2>
- Integer& subtract(Integer& result, const I2& a, const I2& b);
- Subtracts two `I2` values, to produce a wider `Integer` result.
- Returns `result = a - b` without overflow or loss of precision in the subtraction.
- template <class Integer>
- Integer powm(const Integer& b, const Integer& p, const Integer& m);
- Returns b[super p] % m.
- template <class Integer>
- void divide_qr(const Integer& x, const Integer& y, Integer& q, Integer& r);
- Sets `q = x / y` and `r = x % y`.
- template <class Integer1, class Integer2>
- Integer2 integer_modulus(const Integer1& x, Integer2 val);
- Returns x % val;
- template <class Integer>
- unsigned lsb(const Integer& x);
- Returns the (zero-based) index of the least significant bit of `x`.
- Throws a `std::domain_error` if `x <= 0`.
- template <class Integer>
- unsigned msb(const Integer& x);
- Returns the (zero-based) index of the most significant bit of `x`.
- Throws a `std::domain_error` if `x <= 0`.
- template <class Integer>
- bool bit_test(const Integer& val, unsigned index);
- Returns `true` if bit `index` is set in `val`.
- template <class Integer>
- Integer& bit_set(Integer& val, unsigned index);
- Sets the `index` bit in `val`.
- template <class Integer>
- Integer& bit_unset(Integer& val, unsigned index);
- Unsets the `index` bit in `val`.
- template <class Integer>
- Integer& bit_flip(Integer& val, unsigned index);
- Flips the `index` bit in `val`.
- template <class Integer>
- Integer sqrt(const Integer& x);
- template <class Integer>
- Integer sqrt(const Integer& x, Integer& r);
- Returns the integer square root `s` of x and sets `r` to the remainder ['x - s[super 2]].
- template <class Engine>
- bool miller_rabin_test(const number-or-expression-template-type& n, unsigned trials, Engine& gen);
- bool miller_rabin_test(const number-or-expression-template-type& n, unsigned trials);
- The regular Miller-Rabin functions in `<boost/multiprecision/miller_rabin.hpp>` are defined in terms of the above
- generic operations, and so function equally well for built-in or __fundamental_types and multiprecision types.
- [endsect] [/section:gen_int Generic Integer Operations]
- [section:serial Boost.Serialization Support]
- Support for serialization comes in two forms:
- * Classes __number, __debug_adaptor, __logged_adaptor and __rational_adaptor have "pass through" serialization
- support which requires the underlying backend to be serializable.
- * Backends __cpp_int, __cpp_bin_float, __cpp_dec_float and __float128 have full support for Boost.Serialization.
- [endsect] [/section:serialization Boost Serialization]
- [section:limits Numeric Limits]
- Boost.Multiprecision tries hard to implement `std::numeric_limits` for all types
- as far as possible and meaningful because experience with Boost.Math has shown that this aids portability.
- The [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf C++ standard library]
- defines `std::numeric_limits` in section 18.3.2.
- This in turn refers to the C standard
- [@http://www.open-std.org/jtc1/sc22/wg11/docs/n507.pdf SC22/WG11 N507 DRAFT INTERNATIONAL ISO/IEC STANDARD
- WD 10967-1]
- Information technology Language independent arithmetic Part 1: Integer and floating-point arithmetic.
- That C Standard in turn refers to
- [@https://doi.org/10.1109/IEEESTD.1985.82928 IEEE754 IEEE Standard for Binary
- Floating-Point Arithmetic]
- There is a useful summary at
- [@http://www.cplusplus.com/reference/limits/numeric_limits/ C++ reference].
- The chosen backend often determines how completely `std::numeric_limits` is available.
- Compiler options, processor type, and definition of macros or assembler instructions to control denormal numbers will alter
- the values in the tables given below.
- [warning GMP's `mpf_t` does not have a concept of overflow:
- operations that lead to overflow eventually run of out of resources
- and terminate with stack overflow (often after several seconds).]
- [section:constants std::numeric_limits<> constants]
- [h4 is_specialized]
- `true` for all arithmetic types (integer, floating and fixed-point)
- for which `std::numeric_limits<T>::numeric_limits` is specialized.
- A typical test is
- if (std::numeric_limits<T>::is_specialized == false)
- {
- std::cout << "type " << typeid(T).name() << " is not specialized for std::numeric_limits!" << std::endl;
- // ...
- }
- Typically `numeric_limits<T>::is_specialized` is `true` for all `T` where the compile-time constant
- members of `numeric_limits` are indeed known at compile time, and don't vary at runtime. For example
- floating-point types with runtime-variable precision such as `mpfr_float` have no `numeric_limits`
- specialization as it would be impossible to define all the members at compile time. In contrast
- the precision of a type such as `mpfr_float_50` is known at compile time, and so it ['does] have a
- `numeric_limits` specialization.
- Note that not all the `std::numeric_limits` member constants and functions are meaningful for all user-defined types (UDT),
- such as the decimal and binary multiprecision types provided here. More information on this is given in the sections below.
- [h4 infinity]
- For floating-point types, [infin] is defined wherever possible,
- but clearly infinity is meaningless for __arbitrary_precision arithmetic backends,
- and there is one floating-point type (GMP's `mpf_t`, see __mpf_float) which has no notion
- of infinity or NaN at all.
- A typical test whether infinity is implemented is
- if(std::numeric_limits<T>::has_infinity)
- {
- std::cout << std::numeric_limits<T>::infinity() << std::endl;
- }
- and using tests like this is strongly recommended to improve portability.
- If the backend is switched to a type that does not support infinity then,
- without checks like this, there will be trouble.
- [h4 is_signed]
- `std::numeric_limits<T>::is_signed == true` if the type `T` is signed.
- For built-in binary types, the sign is held in a single bit,
- but for other types (cpp_dec_float and cpp_bin_float)
- it may be a separate storage element, usually `bool`.
- [h4 is_exact]
- `std::numeric_limits<T>::is_exact == true` if type T uses exact representations.
- This is defined as `true` for all integer types and `false` for floating-point types.
- [@http://stackoverflow.com/questions/14203654/stdnumeric-limitsis-exact-what-is-a-usable-definition A usable definition]
- has been discussed.
- ISO/IEC 10967-1, Language independent arithmetic, noted by the C++ Standard defines
- A floating-point type F shall be a finite subset of [real].
- The important practical distinction is that all integers (up to `max()`) can be stored exactly.
- [@http://en.wikipedia.org/wiki/Rational_number Rational]
- types using two integer types are also exact.
- Floating-point types [*cannot store all real values]
- (those in the set of [real]) [*exactly].
- For example, 0.5 can be stored exactly in a binary floating-point, but 0.1 cannot.
- What is stored is the nearest representable real value, that is, rounded to nearest.
- Fixed-point types (usually decimal) are also defined as exact, in that they only
- store a [*fixed precision], so half cents or pennies (or less) cannot be stored.
- The results of computations are rounded up or down,
- just like the result of integer division stored as an integer result.
- There are number of proposals to
- [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3407.html
- add Decimal floating-point Support to C++].
- [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2849.pdf Decimal TR].
- And also
- [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3352.html
- C++ Binary Fixed-Point Arithmetic].
- [h4 is_bounded]
- `std::numeric_limits<T>::is_bounded == true` if the set of values represented by the type `T` is finite.
- This is `true` for all built-in integer, fixed and floating-point types,
- and most multi-precision types.
- It is only `false` for a few __arbitrary_precision types like `cpp_int`.
- Rational and fixed-exponent representations are exact but not integer.
- [h4 is_modulo]
- `std::numeric_limits<T>::is_modulo` is defined as `true` if adding two positive values of type T
- can yield a result less than either value.
- `is_modulo == true` means that the type does not overflow, but, for example,
- 'wraps around' to zero, when adding one to the `max()` value.
- For most built-in integer types, `std::numeric_limits<>::is_modulo` is `true`.
- `bool` is the only exception.
- The modulo behaviour is sometimes useful,
- but also can be unexpected, and sometimes undesired, behaviour.
- Overflow of signed integers can be especially unexpected,
- possibly causing change of sign.
- Boost.Multiprecision integer type `cpp_int` is not modulo
- because as an __arbitrary_precision types,
- it expands to hold any value that the machine resources permit.
- However fixed precision __cpp_int's may be modulo if they are unchecked
- (i.e. they behave just like built in integers), but not if they are checked
- (overflow causes an exception to be raised).
- Built-in and multi-precision floating-point types are normally not modulo.
- Where possible, overflow is to `std::numeric_limits<>::infinity()`,
- provided `std::numeric_limits<>::has_infinity == true`.
- [h4 radix]
- Constant `std::numeric_limits<T>::radix` returns either 2 (for built-in and binary types)
- or 10 (for decimal types).
- [h4 digits]
- The number of `radix` digits that be represented without change:
- * for integer types, the number of [*non-sign bits] in the significand.
- * for floating types, the number of [*radix digits] in the significand.
- The values include any implicit bit, so for example, for the ubiquious
- `double` using 64 bits
- ([@http://en.wikipedia.org/wiki/Double_precision_floating-point_format IEEE binary64 ]),
- `digits` == 53, even though there are only 52 actual bits of the significand stored in the representation.
- The value of `digits` reflects the fact that there is one implicit bit which is always set to 1.
- The Boost.Multiprecision binary types do not use an implicit bit, so the
- `digits` member reflects exactly how many bits of precision were requested:
- typedef number<cpp_bin_float<53, digit_base_2> > float64;
- typedef number<cpp_bin_float<113, digit_base_2> > float128;
- std::numeric_limits<float64>::digits == 53.
- std::numeric_limits<float128>::digits == 113.
- For the most common case of `radix == 2`,
- `std::numeric_limits<T>::digits` is the number of bits in the representation,
- not counting any sign bit.
- For a decimal integer type, when `radix == 10`, it is the number of decimal digits.
- [h4 digits10]
- Constant `std::numeric_limits<T>::digits10` returns the number of
- decimal digits that can be represented without change or loss.
- For example, `numeric_limits<unsigned char>::digits10` is 2.
- This somewhat inscrutable definition means that an `unsigned char`
- can hold decimal values `0..99`
- without loss of precision or accuracy, usually from truncation.
- Had the definition been 3 then that would imply it could hold 0..999,
- but as we all know, an 8-bit `unsigned char` can only hold 0..255,
- and an attempt to store 256 or more will involve loss or change.
- For bounded integers, it is thus [*one less] than number of decimal digits
- you need to display the biggest integer `std::numeric_limits<T>::max()`.
- This value can be used to predict the layout width required for
- [digits10_1]
- For example, `unsigned short` is often stored in 16 bits,
- so the maximum value is 0xFFFF or 65535.
- [digits10_2]
- For bounded floating-point types,
- if we create a `double` with a value with `digits10` (usually 15) decimal digits,
- `1e15` or `1000000000000000` :
- [digits10_3]
- and we can increment this value to `1000000000000001`
- as expected and show the difference too.
- But if we try to repeat this with more than `digits10` digits,
- [digits10_4]
- then we find that when we add one it has no effect,
- and display show that there is loss of precision. See
- [@http://en.wikipedia.org/wiki/Loss_of_significance Loss of significance or cancellation error].
- So `digits10` is the number of decimal digits [*guaranteed] to be correct.
- For example, 'round-tripping' for `double`:
- * If a decimal string with at most `digits10`( == 15) significant decimal digits
- is converted to `double` and then converted back to the
- same number of significant decimal digits,
- then the final string will match the original 15 decimal digit string.
- * If a `double` floating-point number is converted to a decimal string
- with at least 17 decimal digits
- and then converted back to `double`,
- then the result will be binary identical to the original `double` value.
- For most purposes, you will much more likely want
- `std::numeric_limits<>::max_digits10`,
- the number of decimal digits that ensure that a change of one least significant bit (ULP)
- produces a different decimal digits string.
- For the most common `double` floating-point type,`max_digits10` is `digits10+2`,
- but you should use C++11 `max_digits10`
- where possible (see [link boost_multiprecision.tut.limits.constants.max_digits10 below]).
- [h4:max_digits10 max_digits10]
- `std::numeric_limits<T>::max_digits10` was added for floating-point
- because `digits10` decimal digits are insufficient to show
- a least significant bit (ULP) change giving puzzling displays like
- 0.666666666666667 != 0.666666666666667
- from failure to 'round-trip', for example:
- [max_digits10_2]
- If you wish to ensure that a change of one least significant bit (ULP)
- produces a different decimal digits string,
- then `max_digits10` is the precision to use.
- For example:
- [max_digits10_3]
- will display [pi] to the maximum possible precision using a `double`.
- [max_digits10_4]
- For integer types, `max_digits10` is implementation-dependent,
- but is usually `digits10 + 2`.
- This is the output field-width required for the maximum value of the type T
- `std::numeric_limits<T>::max()` ['including a sign and a space].
- So this will produce neat columns.
- std::cout << std::setw(std::numeric_limits<int>::max_digits10) ...
- The extra two or three least-significant digits are 'noisy' and may be junk,
- but if you want to 'round-trip' - printing a value out as a decimal digit string and reading it back in -
- (most commonly during serialization and de-serialization)
- you must use `os.precision(std::numeric_limits<T>::max_digits10)`.
- [note For Microsoft Visual Studio 2010,
- `std::numeric_limits<float>::max_digits10` is wrongly defined as 8. It should be 9.
- ]
- [note For Microsoft Visual Studio before 2013 and the default floating-point
- format, a small range of double-precision floating-point values with a
- significand of approximately 0.0001 to 0.004 and exponent values of 1010 to
- 1014 do not round-trip exactly being off by one least significant bit,
- for probably every third value of the significand.
- A workaround is using the scientific or exponential format `std::scientific`.
- Other compilers also fail to implement round-tripping entirely fault-free, for example, see
- [@https://www.exploringbinary.com/incorrectly-rounded-conversions-in-gcc-and-glibc/ Incorrectly Rounded Conversions in GCC and GLIBC].
- For more details see
- [@https://www.exploringbinary.com/incorrect-round-trip-conversions-in-visual-c-plus-plus/ Incorrect Round-Trip Conversions in Visual C++],
- and references therein
- and
- [@https://arxiv.org/pdf/1310.8121.pdf Easy Accurate Reading and Writing of Floating-Point Numbers, Aubrey Jaffer (August 2018)].
- Microsoft VS2017 and other recent compilers, now use the
- [@https://doi.org/10.1145/3192366.3192369 Ryu fast float-to-string conversion by Ulf Adams]
- algorithm, claimed to be both exact and fast for 32 and 64-bit floating-point numbers.
- ] [/note]
- [note BOOST_NO_CXX11_NUMERIC_LIMITS is a suitable feature-test macro to determine if
- `std::numeric_limits<float>::max_digits10` is implemented on any platform.
- ] [/note]
- [note ['requires cxx11_numeric_limits] is a suitable test for use of `std::numeric_limits<float>::max_digits10`
- to control if a target in a jamfile used by a Boost B2/bjam program is built, or not.
- ] [/note]
- If `max_digits10` is not available, you should use the
- [@http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF Kahan formula for floating-point type T].
- In C++, the equations for what Kahan (on page 4) describes as 'at least' and 'at most' are:
- static long double const log10Two = 0.30102999566398119521373889472449L; // log10(2.)
- static_cast<int>(floor((significand_digits - 1) * log10Two)); // == digits10 - 'at least' .
- static_cast<int>(ceil(1 + significand_digits * log10Two)); // == max_digits10 - 'at most'.
- Unfortunately, these cannot be evaluated (at least by C++03) at [*compile-time].
- So the following expression is often used instead.
- max_digits10 = 2 + std::numeric_limits<T>::digits * 3010U/10000U;
- // == 2 + std::numeric_limits<T>::digits for double and 64-bit long double.
- // == 3 + std::numeric_limits<T>::digits for float, 80-bit long-double and __float128.
- often the actual values are computed for the C limits macros:
- #define FLT_MAXDIG10 (2+FLT_MANT_DIG * 3010U/10000U) // 9
- #define DBL_MAXDIG10 (2+ (DBL_MANT_DIG * 3010U)/10000U) // 17
- #define LDBL_MAXDIG10 (2+ (LDBL_MANT_DIG * 3010U)/10000U) // 17 for MSVC, 18 for others.
- The factor 3010U/10000U is ['log[sub 10](2) = 0.3010]
- that can be evaluated at compile-time using only `short unsigned int`s to be a desirable `const` or `constexpr` (and usually also `static`).
- Boost macros allow this to be done portably, see
- [@http://www.boost.org/doc/libs/1_58_0/libs/config/doc/html/boost_config/boost_macro_reference.html BOOST_CONSTEXPR_OR_CONST or BOOST_STATIC_CONSTEXPR].
- (See also
- [@http://www.loria.fr/~zimmerma/mca/mca-cup-0.5.9.pdf Richard P. Brent and Paul Zimmerman, Modern Computer Arithmetic]
- Equation 3.8 on page 116).
- [max_digits10_1] [/ example for using max_digits10]
- [h4 round_style]
- The rounding style determines how the result of floating-point operations
- is treated when the result cannot be [*exactly represented] in the significand.
- Various rounding modes may be provided:
- * round to nearest up or down (default for floating-point types).
- * round up (toward positive infinity).
- * round down (toward negative infinity).
- * round toward zero (integer types).
- * no rounding (if decimal radix).
- * rounding mode is not determinable.
- For integer types, `std::numeric_limits<T>::round_style` is always towards zero, so
- std::numeric_limits<T>::round_style == std::round_to_zero;
- A decimal type, `cpp_dec_float` rounds in no particular direction,
- which is to say it doesn't round at all.
- And since there are several guard digits,
- it's not really the same as truncation (round toward zero) either.
- For floating-point types, it is normal to round to nearest.
- std::numeric_limits<T>::round_style == std::round_to_nearest;
- See function `std::numeric_limits<T>::round_error` for the maximum error (in ULP)
- that rounding can cause.
- [h4 has_denorm_loss]
- `true` if a loss of precision is detected as a
- [@http://en.wikipedia.org/wiki/Denormalization denormalization] loss,
- rather than an inexact result.
- Always `false` for integer types.
- `false` for all types which do not have `has_denorm` == `std::denorm_present`.
- [h4 denorm_style]
- [@http://en.wikipedia.org/wiki/Denormal_number Denormalized values] are
- representations with a variable number of exponent bits that can permit
- gradual underflow, so that, if type T is `double`.
- std::numeric_limits<T>::denorm_min() < std::numeric_limits<T>::min()
- A type may have any of the following `enum float_denorm_style` values:
- * `std::denorm_absent`, if it does not allow denormalized values.
- (Always used for all integer and exact types).
- * `std::denorm_present`, if the floating-point type allows denormalized values.
- *`std::denorm_indeterminate`, if indeterminate at compile time.
- [h4 Tinyness before rounding]
- `bool std::numeric_limits<T>::tinyness_before`
- `true` if a type can determine that a value is too small
- to be represent as a normalized value before rounding it.
- Generally true for `is_iec559` floating-point built-in types,
- but false for integer types.
- Standard-compliant IEEE 754 floating-point implementations may detect the floating-point underflow at three predefined moments:
- # After computation of a result with absolute value smaller than
- `std::numeric_limits<T>::min()`,
- such implementation detects ['tinyness before rounding] (e.g. UltraSparc).
- # After rounding of the result to `std::numeric_limits<T>::digits` bits,
- if the result is tiny, such implementation detects ['tinyness after rounding]
- (e.g. SuperSparc).
- # If the conversion of the rounded tiny result to subnormal form
- resulted in the loss of precision, such implementation detects ['denorm loss].
- [endsect] [/section:constants std::numeric_limits<> Constants]
- [section:functions `std::numeric_limits<>` functions]
- [h4:max_function `max` function]
- Function `(std::numeric_limits<T>::max)()` returns the largest finite value
- that can be represented by the type T. If there is no such value (and
- `numeric_limits<T>::bounded` is `false`) then returns `T()`.
- For built-in types there is usually a corresponding MACRO value TYPE_MAX,
- where TYPE is CHAR, INT, FLOAT etc.
- Other types, including those provided by a typedef,
- for example `INT64_T_MAX` for `int64_t`, may provide a macro definition.
- To cater for situations where no `numeric_limits` specialization is available
- (for example because the precision of the type varies at runtime),
- packaged versions of this (and other functions) are provided using
- #include <boost/math/tools/precision.hpp>
- T = boost::math::tools::max_value<T>();
- Of course, these simply use `(std::numeric_limits<T>::max)()` if available,
- but otherwise 'do something sensible'.
- [h4 lowest function]
- Since C++11: `std::numeric_limits<T>::lowest()` is
- * For integral types, the same as function `min()`.
- * For floating-point types, generally the negative of `max()`
- (but implementation-dependent).
- [digits10_5]
- [h4:min_function `min` function]
- Function `(std::numeric_limits<T>::min)()` returns the minimum finite value
- that can be represented by the type T.
- For built-in types, there is usually a corresponding MACRO value TYPE_MIN,
- where TYPE is CHAR, INT, FLOAT etc.
- Other types, including those provided by a `typedef`,
- for example, `INT64_T_MIN` for `int64_t`, may provide a macro definition.
- For floating-point types,
- it is more fully defined as the ['minimum positive normalized value].
- See `std::numeric_limits<T>::denorm_min()` for the smallest denormalized value, provided
- std::numeric_limits<T>::has_denorm == std::denorm_present
- To cater for situations where no `numeric_limits` specialization is available
- (for example because the precision of the type varies at runtime),
- packaged versions of this (and other functions) are provided using
- #include <boost/math/tools/precision.hpp>
- T = boost::math::tools::min_value<T>();
- Of course, these simply use `std::numeric_limits<T>::min()` if available.
- [h4 denorm_min function]
- Function `std::numeric_limits<T>::denorm_min()`
- returns the smallest
- [@http://en.wikipedia.org/wiki/Denormal_number denormalized value],
- provided
- std::numeric_limits<T>::has_denorm == std::denorm_present
- [denorm_min_1]
- The exponent is effectively reduced from -308 to -324
- (though it remains encoded as zero and leading zeros appear in the significand,
- thereby losing precision until the significand reaches zero).
- [h4 round_error]
- Function `std::numeric_limits<T>::round_error()` returns the maximum error
- (in units of [@http://en.wikipedia.org/wiki/Unit_in_the_last_place ULP])
- that can be caused by any basic arithmetic operation.
- round_style == std::round_indeterminate;
- The rounding style is indeterminable at compile time.
- For floating-point types, when rounding is to nearest,
- only half a bit is lost by rounding, and `round_error == 0.5`.
- In contrast when rounding is towards zero, or plus/minus infinity,
- we can loose up to one bit from rounding, and `round_error == 1`.
- For integer types, rounding always to zero, so at worst almost one bit can be rounded,
- so `round_error == 1`.
- `round_error()` can be used with `std::numeric_limits<T>::epsilon()` to estimate
- the maximum potential error caused by rounding. For typical floating-point types,
- `round_error() = 1/2`, so half epsilon is the maximum potential error.
- [round_error_1]
- There are, of course, many occasions when much bigger loss of precision occurs,
- for example, caused by
- [@http://en.wikipedia.org/wiki/Loss_of_significance Loss of significance or cancellation error]
- or very many iterations.
- [h4:epsilon epsilon]
- Function `std::numeric_limits<T>::epsilon()` is meaningful only for non-integral types.
- It returns the difference between `1.0` and the next value representable
- by the floating-point type T.
- So it is a one least-significant-bit change in this floating-point value.
- For `double` (`float_64t`) it is `2.2204460492503131e-016`
- showing all possibly significant 17 decimal digits.
- [epsilon_1]
- We can explicitly increment by one bit using the function `boost::math::float_next()`
- and the result is the same as adding `epsilon`.
- [epsilon_2]
- Adding any smaller value, like half `epsilon`, will have no effect on this value.
- [epsilon_3]
- So this cancellation error leaves the values equal, despite adding half `epsilon`.
- To achieve greater portability over platform and floating-point type,
- Boost.Math and Boost.Multiprecision provide a package of functions that
- 'do something sensible' if the standard `numeric_limits` is not available.
- To use these `#include <boost/math/tools/precision.hpp>`.
- [epsilon_4]
- [h5:FP_tolerance Tolerance for Floating-point Comparisons]
- [@https://en.wikipedia.org/wiki/Machine_epsilon Machine epsilon [epsilon]]
- is very useful to compute a tolerance when comparing floating-point values,
- a much more difficult task than is commonly imagined.
- The C++ standard specifies [@https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon `std::numeric_limits<>::epsilon()`]
- and Boost.Multiprecision implements this (where possible) for its program-defined types analogous to the
- __fundamental floating-point types like `double` `float`.
- For more information than you probably want (but still need) see
- [@http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html What Every Computer Scientist Should Know About Floating-Point Arithmetic]
- The naive test comparing the absolute difference between two values and a tolerance
- does not give useful results if the values are too large or too small.
- So Boost.Test uses an algorithm first devised by Knuth
- for reliably checking if floating-point values are close enough.
- See Donald. E. Knuth. The art of computer programming (vol II).
- Copyright 1998 Addison-Wesley Longman, Inc., 0-201-89684-2.
- Addison-Wesley Professional; 3rd edition. (The relevant equations are in paragraph 4.2.2, Eq. 36 and 37.)
- See [@https://www.boost.org/doc/libs/release/libs/test/doc/html/boost_test/testing_tools/extended_comparison/floating_point/floating_points_comparison_theory.html Boost.Math floating_point comparison]
- for more details.
- See also:
- [@http://adtmag.com/articles/2000/03/15/comparing-floats-how-to-determine-if-floating-quantities-are-close-enough-once-a-tolerance-has-been.aspx Alberto Squassia, Comparing floats]
- [@http://adtmag.com/articles/2000/03/16/comparing-floats-how-to-determine-if-floating-quantities-are-close-enough-once-a-tolerance-has-been.aspx Alberto Squassia, Comparing floats code]
- [@https://www.boost.org/doc/libs/release/libs/test/doc/html/boost_test/testing_tools/extended_comparison/floating_point.html Boost.Test Floating-Point_Comparison]
- [tolerance_1]
- used thus:
- cd ./test
- BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);
- (There is also a version BOOST_CHECK_CLOSE using tolerance as a [*percentage] rather than a fraction;
- usually the fraction version is simpler to use).
- [tolerance_2]
- [h4:infinity Infinity - positive and negative]
- For floating-point types only, for which
- `std::numeric_limits<T>::has_infinity == true`,
- function `std::numeric_limits<T>::infinity()`
- provides an implementation-defined representation for [infin].
- The 'representation' is a particular bit pattern reserved for infinity.
- For IEEE754 system (for which `std::numeric_limits<T>::is_iec559 == true`)
- [@http://en.wikipedia.org/wiki/IEEE_754-1985#Positive_and_negative_infinity positive and negative infinity]
- are assigned bit patterns for all defined floating-point types.
- Confusingly, the string resulting from outputting this representation, is also
- implementation-defined. And the string that can be input to generate the representation is also implementation-defined.
- For example, the output is `1.#INF` on Microsoft systems, but `inf` on most *nix platforms.
- This implementation-defined-ness has hampered use of infinity (and NaNs)
- but Boost.Math and Boost.Multiprecision work hard to provide a sensible representation
- for [*all] floating-point types, not just the built-in types,
- which with the use of suitable facets to define the input and output strings, makes it possible
- to use these useful features portably and including Boost.Serialization.
- [h4 Not-A-Number NaN]
- [h5 Quiet_NaN]
- For floating-point types only, for which
- `std::numeric_limits<T>::has_quiet_NaN == true`,
- function `std::numeric_limits<T>::quiet_NaN()`
- provides an implementation-defined representation for NaN.
- [@http://en.wikipedia.org/wiki/NaN NaNs] are values to indicate that the
- result of an assignment or computation is meaningless.
- A typical example is `0/0` but there are many others.
- NaNs may also be used, to represent missing values: for example,
- these could, by convention, be ignored in calculations of statistics like means.
- Many of the problems with a representation for
- [@http://en.wikipedia.org/wiki/NaN Not-A-Number] has hampered portable use,
- similar to those with infinity.
- [nan_1]
- But using Boost.Math and suitable facets can permit portable use
- of both NaNs and positive and negative infinity.
- [facet_1]
- [h5 Signaling NaN]
- For floating-point types only, for which
- `std::numeric_limits<T>::has_signaling_NaN == true`,
- function `std::numeric_limits<T>::signaling_NaN()`
- provides an implementation-defined representation for NaN that causes a hardware trap.
- It should be noted however, that at least one implementation of this function causes a hardware
- trap to be triggered simply by calling `std::numeric_limits<T>::signaling_NaN()`, and not only
- by using the value returned.
- [endsect] [/section:functions std::numeric_limits<> functions]
- [/ Tables of values for numeric_limits for various built-in and cpp_bin_float types]
- [include numeric_limits_32_tables.qbk]
- [/include numeric_limits_64_tables.qbk]
- [section:how_to_tell How to Determine the Kind of a Number From `std::numeric_limits`]
- Based on the information above, one can see that different kinds of numbers can be
- differentiated based on the information stored in `std::numeric_limits`. This is
- in addition to the traits class [link boost_multiprecision.ref.number.traits_class_support
- number_category] provided by this library.
- [h4 Integer Types]
- For an integer type T, all of the following conditions hold:
- std::numeric_limits<T>::is_specialized == true
- std::numeric_limits<T>::is_integer == true
- std::numeric_limits<T>::is_exact == true
- std::numeric_limits<T>::min_exponent == 0
- std::numeric_limits<T>::max_exponent == 0
- std::numeric_limits<T>::min_exponent10 == 0
- std::numeric_limits<T>::max_exponent10 == 0
- In addition the type is /signed/ if:
- std::numeric_limits<T>::is_signed == true
- If the type is arbitrary precision then:
- std::numeric_limits<T>::is_bounded == false
- Otherwise the type is bounded, and returns a non zero value
- from:
- std::numeric_limits<T>::max()
- and has:
- std::numeric_limits<T>::is_modulo == true
- if the type implements modulo arithmetic on overflow.
- [h4 Rational Types]
- Rational types are just like integers except that:
- std::numeric_limits<T>::is_integer == false
- [h4 Fixed Precision Types]
- There appears to be no way to tell these apart from rational types, unless they set:
- std::numeric_limits<T>::is_exact == false
- This is because these types are in essence a rational type with a fixed denominator.
- [h4 floating-point Types]
- For a floating-point type T, all of the following conditions hold:
- std::numeric_limits<T>::is_specialized == true
- std::numeric_limits<T>::is_integer == false
- std::numeric_limits<T>::is_exact == false
- std::numeric_limits<T>::min_exponent != 0
- std::numeric_limits<T>::max_exponent != 0
- std::numeric_limits<T>::min_exponent10 != 0
- std::numeric_limits<T>::max_exponent10 != 0
- In addition the type is /signed/ if:
- std::numeric_limits<T>::is_signed == true
- And the type may be decimal or binary depending on the value of:
- std::numeric_limits<T>::radix
- In general, there are no arbitrary precision floating-point types, and so:
- std::numeric_limits<T>::is_bounded == false
- [h4 Exact floating-point Types]
- Exact floating-point types are a [@http://en.wikipedia.org/wiki/Field_%28mathematics%29 field]
- composed of an arbitrary precision integer scaled by an exponent. Such types
- have no division operator and are the same as floating-point types except:
- std::numeric_limits<T>::is_exact == true
- [h4 Complex Numbers]
- For historical reasons, complex numbers do not specialize `std::numeric_limits`, instead you must
- inspect `std::numeric_limits<typename T::value_type>`.
- [endsect] [/section:how_to_tell How to Determine the Kind of a Number From `std::numeric_limits`]
- [endsect] [/section:limits Numeric Limits]
- [section:input_output Input Output]
- [h4 Loopback testing]
- ['Loopback] or ['round-tripping] refers to writing out a value as a decimal digit string using `std::iostream`,
- usually to a `std::stringstream`, and then reading the string back in to another value,
- and confirming that the two values are identical. A trivial example using `float` is:
- float write; // Value to round-trip.
- std::stringstream ss; // Read and write std::stringstream.
- ss.precision(std::numeric_limits<T>::max_digits10); // Ensure all potentially significant bits are output.
- ss.flags(std::ios_base::fmtflags(std::ios_base::scientific)); // Use scientific format.
- ss << write; // Output to string.
- float read; // Expected.
- ss >> read; // Read decimal digits string from stringstream.
- BOOST_CHECK_EQUAL(write, read); // Should be the same.
- and this can be run in a loop for all possible values of a 32-bit float.
- For other floating-point types `T`, including built-in `double`,
- it takes far too long to test all values,
- so a reasonable test strategy is to use a large number of random values.
- T write;
- std::stringstream ss;
- ss.precision(std::numeric_limits<T>::max_digits10); // Ensure all potentially significant bits are output.
- ss.flags(f); // Changed from default iostream format flags if desired.
- ss << write; // Output to stringstream.
- T read;
- ss >> read; // Get read using operator>> from stringstream.
- BOOST_CHECK_EQUAL(read, write);
- read = static_cast<T>(ss.str()); // Get read by converting from decimal digits string representation of write.
- BOOST_CHECK_EQUAL(read, write);
- read = static_cast<T>(write.str(0, f)); // Get read using format specified when written.
- BOOST_CHECK_EQUAL(read, write);
- The test at
- [@../../test/test_cpp_bin_float_io.cpp test_cpp_bin_float_io.cpp]
- allows any floating-point type to be ['round_tripped] using a wide range of fairly random values.
- It also includes tests compared a collection of
- [@../../test/string_data.ipp stringdata] test cases in a file.
- [h4 Comparing with output using Built-in types]
- One can make some comparisons with the output of
- <number<cpp_bin_float<53, digit_count_2> >
- which has the same number of significant bits (53) as 64-bit double precision floating-point.
- However, although most outputs are identical, there are differences on some platforms
- caused by the implementation-dependent behaviours allowed by the C99 specification
- [@http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf C99 ISO/IEC 9899:TC2],
- incorporated by C++.
- [:['"For e, E, f, F, g, and G conversions, if the number of significant decimal digits
- is at most DECIMAL_DIG, then the result should be correctly rounded.
- If the number of significant decimal digits is more than DECIMAL_DIG
- but the source value is exactly representable with DECIMAL_DIG digits,
- then the result should be an exact representation with trailing zeros.
- Otherwise, the source value is bounded by two adjacent decimal strings L < U,
- both having DECIMAL_DIG significant digits;
- the value of the resultant decimal string D should satisfy L<= D <= U,
- with the extra stipulation that the error should have a correct sign
- for the current rounding direction."]]
- So not only is correct rounding for the full number of digits not required,
- but even if the *optional* recommended practice is followed,
- then the value of these last few digits is unspecified
- as long as the value is within certain bounds.
- [note Do not expect the output from different platforms
- to be [*identical], but `cpp_dec_float`, `cpp_bin_float` (and other backends) outputs should be
- correctly rounded to the number of digits requested by the set precision and format.]
- [h4 Macro BOOST_MP_MIN_EXPONENT_DIGITS]
- [@http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf C99 Standard]
- for [/e and E] format specifiers, 7.19.6 Formatted input/output functions requires:
- \"The exponent always contains at least two digits,
- and only as many more digits as necessary to represent the exponent.\"
- So to conform to the C99 standard (incorporated by C++)
- #define BOOST_MP_MIN_EXPONENT_DIGITS 2
- Confusingly, Microsoft (and MinGW) do not conform to this standard and provide
- [*at least three digits], for example `1e+001`.
- So if you want the output to match that from
- built-in floating-point types on compilers that use Microsofts runtime then use:
- #define BOOST_MP_MIN_EXPONENT_DIGITS 3
- Also useful to get the minimum exponent field width is
- #define BOOST_MP_MIN_EXPONENT_DIGITS 1
- producing a compact output like `2e+4`,
- useful when conserving space is important.
- Larger values are also supported, for example, value 4 for `2e+0004`
- which may be useful to ensure that columns line up.
- [endsect] [/section:input_output Input Output]
- [section:hash Hash Function Support]
- [hash1]
- [hash2]
- [hash3]
- [hash4]
- [endsect][/hash]
- [section:eigen Eigen Interoperability]
- This library provides the header:
- #include <boost/multiprecision/eigen.hpp>
- which defines the traits classes and functions that the Eigen library needs all user-defined number types to provide.
- For example the following code performs quad-precision matrix solving on complex numbers:
- [eigen_eg]
- Which produces the following output:
- [eigen_out]
- [endsect]
- [endsect]
- [section:ref Reference]
- [section:number number]
- [h4 Synopsis]
- namespace boost{ namespace multiprecision{
- enum expression_template_option { et_on = 1, et_off = 0 };
- template <class Backend> struct expression_template_default
- { static const expression_template_option value = et_on; };
- template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
- class number
- {
- public:
- typedef Backend backend_type;
- typedef typename component_type<self_type>::type value_type;
- number();
- number(see-below);
- number& operator=(see-below);
- number& assign(see-below);
- // Member operators
- number& operator+=(const ``['see-below]``&);
- number& operator-=(const ``['see-below]``&);
- number& operator*=(const ``['see-below]``&);
- number& operator/=(const ``['see-below]``&);
- number& operator++();
- number& operator--();
- number operator++(int);
- number operator--(int);
- number& operator%=(const ``['see-below]``&);
- number& operator&=(const ``['see-below]``&);
- number& operator|=(const ``['see-below]``&);
- number& operator^=(const ``['see-below]``&);
- number& operator<<=(const ``['integer-type]``&);
- number& operator>>=(const ``['integer-type]``&);
- // Use in Boolean context:
- operator ``['convertible-to-bool-type]``()const;
- // swap:
- void swap(number& other);
- // Sign:
- bool is_zero()const;
- int sign()const;
- // string conversion:
- std::string str()const;
- // Generic conversion mechanism
- template <class T>
- T convert_to()const;
- template <class T>
- explicit operator T ()const;
- // precision control:
- static unsigned default_precision();
- static void default_precision(unsigned digits10);
- unsigned precision()const;
- void precision(unsigned digits10);
- // Comparison:
- int compare(const number<Backend>& o)const;
- template <class V>
- typename enable_if<is_convertible<V, number<Backend, ExpressionTemplates> >, int>::type
- compare(const V& o)const;
- // real and imaginary parts:
- value_type real()const;
- value_type imag()const;
- template <class T>
- void real(const T& val);
- template <class T>
- void imag(const T& val);
- // Access to the underlying implementation:
- Backend& backend();
- const Backend& backend()const;
- };
- // Non member operators:
- ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator*(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator/(const ``['see-below]``&, const ``['see-below]``&);
- // Integer only operations:
- ``['unmentionable-expression-template-type]`` operator%(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator&(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator|(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator^(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator<<(const ``['see-below]``&, const ``['integer-type]``&);
- ``['unmentionable-expression-template-type]`` operator>>(const ``['see-below]``&, const ``['integer-type]``&);
- // Comparison operators:
- bool operator==(const ``['see-below]``&, const ``['see-below]``&);
- bool operator!=(const ``['see-below]``&, const ``['see-below]``&);
- bool operator< (const ``['see-below]``&, const ``['see-below]``&);
- bool operator> (const ``['see-below]``&, const ``['see-below]``&);
- bool operator<=(const ``['see-below]``&, const ``['see-below]``&);
- bool operator>=(const ``['see-below]``&, const ``['see-below]``&);
- // Swap:
- template <class Backend, expression_template_option ExpressionTemplates>
- void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b);
- // iostream support:
- template <class Backend, expression_template_option ExpressionTemplates>
- std::ostream& operator << (std::ostream& os, const number<Backend, ExpressionTemplates>& r);
- std::ostream& operator << (std::ostream& os, const ``['unmentionable-expression-template-type]``& r);
- template <class Backend, expression_template_option ExpressionTemplates>
- std::istream& operator >> (std::istream& is, number<Backend, ExpressionTemplates>& r);
- // Arithmetic with a higher precision result:
- template <class ResultType, class Source1 class Source2>
- ResultType& add(ResultType& result, const Source1& a, const Source2& b);
- template <class ResultType, class Source1 class Source2>
- ResultType& subtract(ResultType& result, const Source1& a, const Source2& b);
- template <class ResultType, class Source1 class Source2>
- ResultType& multiply(ResultType& result, const Source1& a, const Source2& b);
- // min and max overloads:
- ``['number]`` min (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['number]`` max (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- // C99 Non-member function standard library support:
- ``['unmentionable-expression-template-type]`` abs (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` acos (const ``['number-or-expression-template-type]``&);
- ``['number]`` acosh (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` asin (const ``['number-or-expression-template-type]``&);
- ``['number]`` asinh (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` atan (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` atan2 (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['number]`` atanh (const ``['number-or-expression-template-type]``&);
- ``['number]`` cbrt (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` ceil (const ``['number-or-expression-template-type]``&);
- ``['number]`` copysign (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` cos (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` cosh (const ``['number-or-expression-template-type]``&);
- ``['number]`` erf (const ``['number-or-expression-template-type]``&);
- ``['number]`` erfc (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` exp (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` exp2 (const ``['number-or-expression-template-type]``&);
- ``['number]`` expm1 (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fabs (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fdim (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` floor (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fma (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fmin (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fmax (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fmod (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` frexp (const ``['number-or-expression-template-type]``&, ``['integer-type]``*);
- ``['unmentionable-expression-template-type]`` hypot (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['integer-type]`` ilogb (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` ldexp (const ``['number-or-expression-template-type]``&, ``['integer-type]``);
- ``['number]`` lgamma (const ``['number-or-expression-template-type]``&);
- long long llrint (const ``['number-or-expression-template-type]``&);
- long long llround (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` log (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` log2 (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` log10 (const ``['number-or-expression-template-type]``&);
- ``['number]`` log1p (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` logb (const ``['number-or-expression-template-type]``&);
- long lrint (const ``['number-or-expression-template-type]``&);
- long lround (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` modf (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` nearbyint (const ``['number-or-expression-template-type]``&);
- ``['number]`` nextafter (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['number]`` nexttoward (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` pow (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` remainder (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` remquo (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&, int*);
- ``['unmentionable-expression-template-type]`` rint (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` round (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` scalbn (const ``['number-or-expression-template-type]``&, ``['integer-type]``);
- ``['unmentionable-expression-template-type]`` scalbln (const ``['number-or-expression-template-type]``&, ``['integer-type]``);
- ``['unmentionable-expression-template-type]`` sin (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` sinh (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` sqrt (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` tan (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` tanh (const ``['number-or-expression-template-type]``&);
- ``['number]`` tgamma (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` trunc (const ``['number-or-expression-template-type]``&);
- int fpclassify (const ``['number-or-expression-template-type]``&);
- bool isfinite (const ``['number-or-expression-template-type]``&);
- bool isinf (const ``['number-or-expression-template-type]``&);
- bool isnan (const ``['number-or-expression-template-type]``&);
- bool isnormal (const ``['number-or-expression-template-type]``&);
- int signbit (const ``['number-or-expression-template-type]``&);
- bool isgreater (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- bool isgreaterequal(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- bool isless (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- bool islessequal(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- bool islessgreater(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- bool isunordered(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- // Complex number functions:
- ``['number<...>::value_type]`` real (const ``['number-or-expression-template-type]``&);
- ``['number<...>::value_type]`` imag (const ``['number-or-expression-template-type]``&);
- ``['number<...>::value_type]`` abs (const ``['number-or-expression-template-type]``&);
- ``['number<...>::value_type]`` arg (const ``['number-or-expression-template-type]``&);
- ``['number<...>::value_type]`` norm (const ``['number-or-expression-template-type]``&);
- ``['number]`` conj (const ``['number-or-expression-template-type]``&);
- ``['number]`` proj (const ``['number-or-expression-template-type]``&);
- ``['number]`` polar (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- // Misc other common C library functions:
- ``['unmentionable-expression-template-type]`` itrunc (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` ltrunc (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` lltrunc(const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` iround (const ``['number-or-expression-template-type]``&);
- ``['number]`` changesign(const ``['number-or-expression-template-type]``&);
- ``['number]`` copysign(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- // Traits support:
- template <class T>
- struct component_type;
- template <class T>
- struct number_category;
- template <class T>
- struct is_number;
- template <class T>
- struct is_number_expression;
- // Integer specific functions:
- ``['unmentionable-expression-template-type]`` gcd(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` lcm(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` pow(const ``['number-or-expression-template-type]``&, unsigned);
- ``['unmentionable-expression-template-type]`` powm(const ``['number-or-expression-template-type]``& b, const ``['number-or-expression-template-type]``& p, const ``['number-or-expression-template-type]``& m);
- ``['unmentionable-expression-template-type]`` sqrt(const ``['number-or-expression-template-type]``&);
- template <class Backend, expression_template_option ExpressionTemplates>
- number<Backend, EXpressionTemplates> sqrt(const ``['number-or-expression-template-type]``&, number<Backend, EXpressionTemplates>&);
- template <class Backend, expression_template_option ExpressionTemplates>
- void divide_qr(const ``['number-or-expression-template-type]``& x, const ``['number-or-expression-template-type]``& y,
- number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r);
- template <class Integer>
- Integer integer_modulus(const ``['number-or-expression-template-type]``& x, Integer val);
- unsigned lsb(const ``['number-or-expression-template-type]``& x);
- unsigned msb(const ``['number-or-expression-template-type]``& x);
- template <class Backend, class ExpressionTemplates>
- bool bit_test(const number<Backend, ExpressionTemplates>& val, unsigned index);
- template <class Backend, class ExpressionTemplates>
- number<Backend, ExpressionTemplates>& bit_set(number<Backend, ExpressionTemplates>& val, unsigned index);
- template <class Backend, class ExpressionTemplates>
- number<Backend, ExpressionTemplates>& bit_unset(number<Backend, ExpressionTemplates>& val, unsigned index);
- template <class Backend, class ExpressionTemplates>
- number<Backend, ExpressionTemplates>& bit_flip(number<Backend, ExpressionTemplates>& val, unsigned index);
- template <class Engine>
- bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials, Engine& gen);
- bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials);
- // Rational number support:
- typename component_type<``['number-or-expression-template-type]``>::type numerator (const ``['number-or-expression-template-type]``&);
- typename component_type<``['number-or-expression-template-type]``>::type denominator(const ``['number-or-expression-template-type]``&);
- }} // namespaces
- namespace boost{ namespace math{
- // Boost.Math interoperability functions:
- int fpclassify (const ``['number-or-expression-template-type]``&, int);
- bool isfinite (const ``['number-or-expression-template-type]``&, int);
- bool isnan (const ``['number-or-expression-template-type]``&, int);
- bool isinf (const ``['number-or-expression-template-type]``&, int);
- bool isnormal (const ``['number-or-expression-template-type]``&, int);
- }} // namespaces
- // numeric_limits support:
- namespace std{
- template <class Backend, expression_template_option ExpressionTemplates>
- struct numeric_limits<boost::multiprecision<Backend, ExpressionTemplates> >
- {
- /* Usual members here */
- };
- }
- [h4 Description]
- enum expression_template_option { et_on = 1, et_off = 0 };
- This enumerated type is used to specify whether expression templates are turned on (et_on) or turned off (et_off).
- template <class Backend> struct expression_template_default
- { static const expression_template_option value = et_on; };
- This traits class specifies the default expression template option to be used with a particular Backend type.
- It defaults to `et_on`.
- template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
- class number;
- Class `number` has two template arguments:
- [variablelist
- [[Backend][The actual arithmetic back-end that does all the work.]]
- [[ExpressionTemplates][A Boolean value: when `et_on`, then expression templates are enabled, otherwise when set to `et_off` they are disabled.
- The default for this parameter is computed via the traits class `expression_template_default` whose member `value` defaults to `et_on` unless
- the traits class is specialized for a particular backend.]]
- ]
- number();
- number(see-below);
- number& operator=(see-below);
- number& assign(see-below);
- Type `number` is default constructible, and both copy constructible and assignable from:
- * Itself.
- * An expression template which is the result of one of the arithmetic operators.
- * Any builtin arithmetic type, as long as the result would not be lossy (for example float to integer conversion).
- * Any type that the Backend is implicitly constructible or assignable from.
- * An rvalue reference to another `number`. Move-semantics are used for construction if the backend also
- supports rvalue reference construction. In the case of assignment, move semantics are always supported
- when the argument is an rvalue reference irrespective of the backend.
- * Any type in the same family, as long as no loss of precision is involved. For example from `int128_t` to `int256_t`,
- or `cpp_dec_float_50` to `cpp_dec_float_100`.
- Type `number` is explicitly constructible from:
- * Any type mentioned above.
- * A `std::string` or any type which is convertible to `const char*`.
- * Any arithmetic type (including those that would result in lossy conversions).
- * Any type in the same family, including those that result in loss of precision.
- * Any type that the Backend is explicitly constructible from.
- * Any pair of types for which a generic interconversion exists: that is from integer to integer, integer
- to rational, integer to float, rational to rational, rational to float, or float to float.
- The assign member function is available for any type for which an explicit converting constructor exists.
- It is intended to be used where a temporary generated from an explicit assignment would be expensive, for example:
- mpfr_float_50 f50;
- mpfr_float_100 f100;
- f50 = static_cast<mpfr_float_50>(f100); // explicit cast create a temporary
- f50.assign(f100); // explicit call to assign create no temporary
- In addition, if the type has multiple components (for example rational or complex number types), then there is a
- two argument constructor:
- number(arg1, arg2);
- Where the two args must either be arithmetic types, or types that are convertible to the two components of `this`.
- Finally, when the type has a variable precision, then there are constructors:
- number(arg1, precision);
- number(arg1, arg2, precision);
- Where `precision` is an unsigned value, the 2 arg version is active for scalar types and/or copy-construction with specific precision, and the 3-arg version for complex types.
- Likewise `assign` has a 2-arg overloaded, with the second argument being the precision.
- number& operator+=(const ``['see-below]``&);
- number& operator-=(const ``['see-below]``&);
- number& operator*=(const ``['see-below]``&);
- number& operator/=(const ``['see-below]``&);
- number& operator++();
- number& operator--();
- number operator++(int);
- number operator--(int);
- // Integer only operations:
- number& operator%=(const ``['see-below]``&);
- number& operator&=(const ``['see-below]``&);
- number& operator|=(const ``['see-below]``&);
- number& operator^=(const ``['see-below]``&);
- number& operator<<=(const ``['integer-type]``&);
- number& operator>>=(const ``['integer-type]``&);
- These operators all take their usual arithmetic meanings.
- The arguments to these operators is either:
- * Another `number<Backend, ExpressionTemplates>`.
- * An expression template derived from `number<Backend>`.
- * Any type implicitly convertible to `number<Backend, ExpressionTemplates>`, including some other instance of class `number`.
- For the left and right shift operations, the argument must be a builtin
- integer type with a positive value (negative values result in a `std::runtime_error` being thrown).
- operator ``['convertible-to-bool-type]``()const;
- Returns an ['unmentionable-type] that is usable in Boolean contexts (this allows `number` to be used in any
- Boolean context - if statements, conditional statements, or as an argument to a logical operator - without
- type `number` being convertible to type `bool`.
- This operator also enables the use of `number` with any of the following operators:
- `!`, `||`, `&&` and `?:`.
- void swap(number& other);
- Swaps `*this` with `other`.
- bool is_zero()const;
- Returns `true` is `*this` is zero, otherwise `false`.
- int sign()const;
- Returns a value less than zero if `*this` is negative, a value greater than zero if `*this` is positive, and zero
- if `*this` is zero.
- std::string str(unsigned precision, bool scientific = true)const;
- Returns the number formatted as a string, with at least /precision/ digits, and in scientific format
- if /scientific/ is true.
- template <class T>
- T convert_to()const;
- template <class T>
- explicit operator T ()const;
- Provides a generic conversion mechanism to convert `*this` to type `T`. Type `T` may be any arithmetic type.
- Optionally other types may also be supported by specific `Backend` types.
- static unsigned default_precision();
- static void default_precision(unsigned digits10);
- unsigned precision()const;
- void precision(unsigned digits10);
- These functions are only available if the Backend template parameter supports runtime changes to precision. They get and set
- the default precision and the precision of `*this` respectively.
- int compare(const number<Backend, ExpressionTemplates>& o)const;
- template <class V>
- typename enable_if<is_convertible<V, number<Backend, ExpressionTemplates> >, int>::type
- compare(const V& other)const;
- Returns:
- * A value less that 0 for `*this < other`
- * A value greater that 0 for `*this > other`
- * Zero for `*this == other`
- value_type real()const;
- value_type imag()const;
- These return the real and imaginary parts respectively. If the number is not a complex type, then the imaginary part is always zero.
- template <class T>
- void real(const T& val);
- template <class T>
- void imag(const T& val);
- These set the real and imaginary parts respectively of the number. If the number is not a complex type, then setting the real part
- is equivalent to assignment, and attempting to set the imaginary part will result in a compile time error.
- Backend& backend();
- const Backend& backend()const;
- Returns the underlying back-end instance used by `*this`.
- [h4 Non-member operators]
- // Non member operators:
- ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator*(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator/(const ``['see-below]``&, const ``['see-below]``&);
- // Integer only operations:
- ``['unmentionable-expression-template-type]`` operator%(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator&(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator|(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator^(const ``['see-below]``&, const ``['see-below]``&);
- ``['unmentionable-expression-template-type]`` operator<<(const ``['see-below]``&, const ``['integer-type]``&);
- ``['unmentionable-expression-template-type]`` operator>>(const ``['see-below]``&, const ``['integer-type]``&);
- // Comparison operators:
- bool operator==(const ``['see-below]``&, const ``['see-below]``&);
- bool operator!=(const ``['see-below]``&, const ``['see-below]``&);
- bool operator< (const ``['see-below]``&, const ``['see-below]``&);
- bool operator> (const ``['see-below]``&, const ``['see-below]``&);
- bool operator<=(const ``['see-below]``&, const ``['see-below]``&);
- bool operator>=(const ``['see-below]``&, const ``['see-below]``&);
- These operators all take their usual arithmetic meanings.
- The arguments to these functions must contain at least one of the following:
- * A `number`.
- * An expression template type derived from `number`.
- * Any type for which `number` has an implicit constructor - for example a builtin arithmetic type.
- The return type of these operators is either:
- * An ['unmentionable-type] expression template type when `ExpressionTemplates` is `true`.
- * Type `number<Backend, et_off>` when `ExpressionTemplates` is `false`.
- * Type `bool` if the operator is a comparison operator.
- Finally note that the second argument to the left and right shift operations must be a builtin integer type,
- and that the argument must be positive (negative arguments result in a `std::runtime_error` being thrown).
- [h4 swap]
- template <class Backend, ExpressionTemplates>
- void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b);
- Swaps `a` and `b`.
- [h4 Iostream Support]
- template <class Backend, expression_template_option ExpressionTemplates>
- std::ostream& operator << (std::ostream& os, const number<Backend, ExpressionTemplates>& r);
- template <class Unspecified...>
- std::ostream& operator << (std::ostream& os, const unmentionable-expression-template& r);
- template <class Backend, expression_template_option ExpressionTemplates>
- inline std::istream& operator >> (std::istream& is, number<Backend, ExpressionTemplates>& r)
- These operators provided formatted input-output operations on `number` types, and expression templates derived from them.
- It's down to the back-end type to actually implement string conversion. However, the back-ends provided with
- this library support all of the iostream formatting flags, field width and precision settings.
- [h4 Arithmetic with a higher precision result]
- template <class ResultType, class Source1 class Source2>
- ResultType& add(ResultType& result, const Source1& a, const Source2& b);
- template <class ResultType, class Source1 class Source2>
- ResultType& subtract(ResultType& result, const Source1& a, const Source2& b);
- template <class ResultType, class Source1 class Source2>
- ResultType& multiply(ResultType& result, const Source1& a, const Source2& b);
- These functions apply the named operator to the arguments ['a] and ['b] and store the
- result in ['result], returning ['result]. In all cases they behave "as if"
- arguments ['a] and ['b] were first promoted to type `ResultType` before applying the
- operator, though particular backends may well avoid that step by way of an optimization.
- The type `ResultType` must be an instance of class `number`, and the types `Source1` and `Source2`
- may be either instances of class `number` or native integer types. The latter is an optimization
- that allows arithmetic to be performed on native integer types producing an extended precision result.
- [h4 Non-member standard library function support]
- ``['unmentionable-expression-template-type]`` abs (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` acos (const ``['number-or-expression-template-type]``&);
- ``['number]`` acosh (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` asin (const ``['number-or-expression-template-type]``&);
- ``['number]`` asinh (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` atan (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` atan2 (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['number]`` atanh (const ``['number-or-expression-template-type]``&);
- ``['number]`` cbrt (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` ceil (const ``['number-or-expression-template-type]``&);
- ``['number]`` copysign (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` cos (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` cosh (const ``['number-or-expression-template-type]``&);
- ``['number]`` erf (const ``['number-or-expression-template-type]``&);
- ``['number]`` erfc (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` exp (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` exp2 (const ``['number-or-expression-template-type]``&);
- ``['number]`` expm1 (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fabs (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fdim (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` floor (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fma (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fmin (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fmax (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fmod (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` frexp (const ``['number-or-expression-template-type]``&, ``['integer-type]``*);
- ``['unmentionable-expression-template-type]`` hypot (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['integer-type]`` ilogb (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` ldexp (const ``['number-or-expression-template-type]``&, ``['integer-type]``);
- ``['number]`` lgamma (const ``['number-or-expression-template-type]``&);
- long long llrint (const ``['number-or-expression-template-type]``&);
- long long llround (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` log (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` log2 (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` log10 (const ``['number-or-expression-template-type]``&);
- ``['number]`` log1p (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` logb (const ``['number-or-expression-template-type]``&);
- long lrint (const ``['number-or-expression-template-type]``&);
- long lround (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` modf (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` nearbyint (const ``['number-or-expression-template-type]``&);
- ``['number]`` nextafter (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['number]`` nexttoward (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` pow (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` remainder (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` remquo (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&, int*);
- ``['unmentionable-expression-template-type]`` rint (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` round (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` scalbn (const ``['number-or-expression-template-type]``&, ``['integer-type]``);
- ``['unmentionable-expression-template-type]`` scalbln (const ``['number-or-expression-template-type]``&, ``['integer-type]``);
- ``['unmentionable-expression-template-type]`` sin (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` sinh (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` sqrt (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` tan (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` tanh (const ``['number-or-expression-template-type]``&);
- ``['number]`` tgamma (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` trunc (const ``['number-or-expression-template-type]``&);
- int fpclassify (const ``['number-or-expression-template-type]``&);
- bool isfinite (const ``['number-or-expression-template-type]``&);
- bool isinf (const ``['number-or-expression-template-type]``&);
- bool isnan (const ``['number-or-expression-template-type]``&);
- bool isnormal (const ``['number-or-expression-template-type]``&);
- int signbit (const ``['number-or-expression-template-type]``&);
- bool isgreater (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- bool isgreaterequal(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- bool isless (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- bool islessequal(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- bool islessgreater(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- bool isunordered(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- These functions all behave exactly as their standard library C++11 counterparts do: their argument is either an instance of `number` or
- an expression template derived from it; If the argument is of type `number<Backend, et_off>` then that is also the return type,
- otherwise the return type is an expression template unless otherwise stated.
- The integer type arguments to `ldexp`, `frexp`, `scalbn` and `ilogb` may be either type `int`, or the actual
- type of the exponent of the number type.
- Complex number types support the following functions:
- // Complex number functions:
- ``['number<...>::value_type]`` real (const ``['number-or-expression-template-type]``&);
- ``['number<...>::value_type]`` imag (const ``['number-or-expression-template-type]``&);
- ``['number<...>::value_type]`` abs (const ``['number-or-expression-template-type]``&);
- ``['number<...>::value_type]`` arg (const ``['number-or-expression-template-type]``&);
- ``['number<...>::value_type]`` norm (const ``['number-or-expression-template-type]``&);
- ``['number]`` conj (const ``['number-or-expression-template-type]``&);
- ``['number]`` proj (const ``['number-or-expression-template-type]``&);
- ``['number]`` polar (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- In addition the functions `real`, `imag`, `arg`, `norm`, `conj` and `proj` are overloaded for scalar (ie non-complex) types in the same
- manner as `<complex>` and treat the argument as a value whose imaginary part is zero.
- There are also some functions implemented for compatibility with the Boost.Math functions of the same name:
- ``['unmentionable-expression-template-type]`` itrunc (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` ltrunc (const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` lltrunc(const ``['number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` iround (const ``['number-or-expression-template-type]``&);
- ``['number]`` changesign(const ``['number-or-expression-template-type]``&);
- ``['number]`` copysign(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- All these functions are normally implemented by the Backend type. However, default versions are provided for Backend types that
- don't have native support for these functions. Please note however, that this default support requires the precision of the type
- to be a compile time constant - this means for example that the [gmp] MPF Backend will not work with these functions when that type is
- used at variable precision.
- Also note that with the exception of `abs` that these functions can only be used with floating-point Backend types (if any other types
- such as fixed precision or complex types are added to the library later, then these functions may be extended to support those number types).
- The precision of these functions is generally determined by the backend implementation. For example the precision
- of these functions when used with __mpfr_float_backend is determined entirely by [mpfr]. When these functions use our own
- implementations, the accuracy of the transcendental functions is generally a few epsilon. Note however, that the trigonometrical
- functions incur the usual accuracy loss when reducing arguments by large multiples of [pi]. Also note that both __mpf_float
- and __cpp_dec_float have a number of guard digits beyond their stated precision, so the error rates listed for these
- are in some sense artificially low.
- The following table shows the error rates we observe for these functions with various backend types, functions not listed
- here are exact (tested on Win32 with VC++10, MPFR-3.0.0, MPIR-2.1.1):
- [table
- [[Function][mpfr_float_50][mpf_float_50][cpp_dec_float_50]]
- [[sqrt][1eps][0eps][0eps]]
- [[exp][1eps][0eps][0eps]]
- [[log][1eps][0eps][0eps]]
- [[log10][1eps][0eps][0eps]]
- [[cos][700eps][0eps][0eps]]
- [[sin][1eps][0eps][0eps]]
- [[tan][0eps][0eps][0eps]]
- [[acos][0eps][0eps][0eps]]
- [[asin][0eps][0eps][0eps]]
- [[atan][1eps][0eps][0eps]]
- [[cosh][1045eps[footnote It's likely that the inherent error in the input values to our test cases are to blame here.]][0eps][0eps]]
- [[sinh][2eps][0eps][0eps]]
- [[tanh][1eps][0eps][0eps]]
- [[pow][0eps][4eps][3eps]]
- [[atan2][1eps][0eps][0eps]]
- ]
- [h4 Traits Class Support]
- template <class T>
- struct component_type;
- If this is a type with multiple components (for example rational or complex types), then this trait has a single member
- `type` that is the type of those components.
- template <class T>
- struct number_category;
- A traits class that inherits from `mpl::int_<N>` where `N` is one of the enumerated values `number_kind_integer`, `number_kind_floating_point`,
- `number_kind_rational`, `number_kind_fixed_point`, or `number_kind_unknown`. This traits class is specialized for any type that has
- `std::numeric_limits` support as well as for classes in this library: which means it can be used for generic code that must work
- with built in arithmetic types as well as multiprecision ones.
- template <class T>
- struct is_number;
- A traits class that inherits from `mpl::true_` if T is an instance of `number<>`, otherwise from `mpl::false_`.
- template <class T>
- struct is_number_expression;
- A traits class that inherits from `mpl::true_` if T is an expression template type derived from `number<>`, otherwise from `mpl::false_`.
- [h4 Integer functions]
- In addition to functioning with types from this library, these functions are also overloaded for built in integer
- types if you include `<boost/multiprecision/integer.hpp>`. Further, when used with fixed precision types (whether
- built in integers or multiprecision ones), the functions will promote to a wider type internally when the algorithm
- requires it. Versions overloaded for built in integer types return that integer type rather than an expression
- template.
- ``['unmentionable-expression-template-type]`` gcd(const ``['number-or-expression-template-type]``& a, const ``['number-or-expression-template-type]``& b);
- Returns the largest integer `x` that divides both `a` and `b`.
- ``['unmentionable-expression-template-type]`` lcm(const ``['number-or-expression-template-type]``& a, const ``['number-or-expression-template-type]``& b);
- Returns the smallest integer `x` that is divisible by both `a` and `b`.
- ``['unmentionable-expression-template-type]`` pow(const ``['number-or-expression-template-type]``& b, unsigned p);
- Returns ['b[super p]] as an expression template. Note that this function should be used with extreme care as the result can grow so
- large as to take "effectively forever" to compute, or else simply run the host machine out of memory. This is the one function in
- this category that is not overloaded for built in integer types, further, it's probably not a good idea to use it with
- fixed precision `cpp_int`'s either.
- ``['unmentionable-expression-template-type]`` powm(const ``['number-or-expression-template-type]``& b, const ``['number-or-expression-template-type]``& p, const ``['number-or-expression-template-type]``& m);
- Returns ['b[super p] mod m] as an expression template. Fixed precision types are promoted internally to ensure accuracy.
- ``['unmentionable-expression-template-type]`` sqrt(const ``['number-or-expression-template-type]``& a);
- Returns the largest integer `x` such that `x * x < a`.
- template <class Backend, expression_template_option ExpressionTemplates>
- number<Backend, EXpressionTemplates> sqrt(const ``['number-or-expression-template-type]``& a, number<Backend, EXpressionTemplates>& r);
- Returns the largest integer `x` such that `x * x < a`, and sets the remainder `r` such that `r = a - x * x`.
- template <class Backend, expression_template_option ExpressionTemplates>
- void divide_qr(const ``['number-or-expression-template-type]``& x, const ``['number-or-expression-template-type]``& y,
- number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r);
- Divides x by y and returns both the quotient and remainder. After the call `q = x / y` and `r = x % y`.
- template <class Integer>
- Integer integer_modulus(const ``['number-or-expression-template-type]``& x, Integer val);
- Returns the absolute value of `x % val`.
- unsigned lsb(const ``['number-or-expression-template-type]``& x);
- Returns the (zero-based) index of the least significant bit that is set to 1.
- Throws a `std::range_error` if the argument is <= 0.
- unsigned msb(const ``['number-or-expression-template-type]``& x);
- Returns the (zero-based) index of the most significant bit.
- Throws a `std::range_error` if the argument is <= 0.
- template <class Backend, class ExpressionTemplates>
- bool bit_test(const number<Backend, ExpressionTemplates>& val, unsigned index);
- Returns `true` if the bit at /index/ in /val/ is set.
- template <class Backend, class ExpressionTemplates>
- number<Backend, ExpressionTemplates>& bit_set(number<Backend, ExpressionTemplates>& val, unsigned index);
- Sets the bit at /index/ in /val/, and returns /val/.
- template <class Backend, class ExpressionTemplates>
- number<Backend, ExpressionTemplates>& bit_unset(number<Backend, ExpressionTemplates>& val, unsigned index);
- Unsets the bit at /index/ in /val/, and returns /val/.
- template <class Backend, class ExpressionTemplates>
- number<Backend, ExpressionTemplates>& bit_flip(number<Backend, ExpressionTemplates>& val, unsigned index);
- Flips the bit at /index/ in /val/, and returns /val/.
- template <class Engine>
- bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials, Engine& gen);
- bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials);
- Tests to see if the number /n/ is probably prime - the test excludes the vast majority of composite numbers
- by excluding small prime factors and performing a single Fermat test. Then performs /trials/ Miller-Rabin
- tests. Returns `false` if /n/ is definitely composite, or `true` if /n/ is probably prime with the
- probability of it being composite less than 0.25^trials. Fixed precision types are promoted internally
- to ensure accuracy.
- [h4 Rational Number Functions]
- typename component_type<``['number-or-expression-template-type]``>::type numerator (const ``['number-or-expression-template-type]``&);
- typename component_type<``['number-or-expression-template-type]``>::type denominator(const ``['number-or-expression-template-type]``&);
- These functions return the numerator and denominator of a rational number respectively.
- [h4 Boost.Math Interoperability Support]
- namespace boost{ namespace math{
- int fpclassify (const ``['number-or-expression-template-type]``&, int);
- bool isfinite (const ``['number-or-expression-template-type]``&, int);
- bool isnan (const ``['number-or-expression-template-type]``&, int);
- bool isinf (const ``['number-or-expression-template-type]``&, int);
- bool isnormal (const ``['number-or-expression-template-type]``&, int);
- }} // namespaces
- These floating-point classification functions behave exactly as their Boost.Math equivalents.
- Other Boost.Math functions and templates may also be
- specialized or overloaded to ensure interoperability.
- [h4 std::numeric_limits support]
- namespace std{
- template <class Backend, ExpressionTemplates>
- struct numeric_limits<boost::multiprecision<Backend, ExpressionTemplates> >
- {
- /* Usual members here */
- };
- }
- Class template `std::numeric_limits` is specialized for all instantiations of `number` whose precision is known at compile time, plus those
- types whose precision is unlimited (though it is much less useful in those cases). It is not specialized for types
- whose precision can vary at compile time (such as `mpf_float`).
- [endsect]
- [section:cpp_int_ref cpp_int]
- namespace boost{ namespace multiprecision{
- typedef unspecified-type limb_type;
- enum cpp_integer_type { signed_magnitude, unsigned_magnitude };
- enum cpp_int_check_type { checked, unchecked };
- template <unsigned MinDigits = 0,
- unsigned MaxDits = 0,
- cpp_integer_type SignType = signed_magnitude,
- cpp_int_check_type Checked = unchecked,
- class Allocator = std::allocator<limb_type> >
- class cpp_int_backend;
- //
- // Expression templates default to et_off if there is no allocator:
- //
- template <unsigned MinDigits, unsigned MaxDigits, cpp_integer_type SignType, cpp_int_check_type Checked>
- struct expression_template_default<cpp_int_backend<MinDigits, MaxDigits, SignType, Checked, void> >
- { static const expression_template_option value = et_off; };
- typedef number<cpp_int_backend<> > cpp_int; // arbitrary precision integer
- typedef rational_adaptor<cpp_int_backend<> > cpp_rational_backend;
- typedef number<cpp_rational_backend> cpp_rational; // arbitrary precision rational number
- // Fixed precision unsigned types:
- typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> > uint128_t;
- typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> > uint256_t;
- typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> > uint512_t;
- typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t;
- // Fixed precision signed types:
- typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> > int128_t;
- typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> > int256_t;
- typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> > int512_t;
- typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> > int1024_t;
- // Over again, but with checking enabled this time:
- typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_int;
- typedef rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_rational_backend;
- typedef number<checked_cpp_rational_backend> checked_cpp_rational;
- // Checked fixed precision unsigned types:
- typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> > checked_uint128_t;
- typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> > checked_uint256_t;
- typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> > checked_uint512_t;
- typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> > checked_uint1024_t;
- // Fixed precision signed types:
- typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> > checked_int128_t;
- typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> > checked_int256_t;
- typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> > checked_int512_t;
- typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> > checked_int1024_t;
- }} // namespaces
- Class template `cpp_int_backend` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
- Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
- to change.
- The template arguments are:
- [variablelist
- [[MinBits][Determines the number of Bits to store directly within the object before resorting to dynamic memory
- allocation. When zero, this field is determined automatically based on how many bits can be stored
- in union with the dynamic storage header: setting a larger value may improve performance as larger integer
- values will be stored internally before memory allocation is required.]]
- [[MaxBits][Determines the maximum number of bits to be stored in the type: resulting in a fixed precision type.
- When this value is the same as MinBits, then the Allocator parameter is ignored, as no dynamic
- memory allocation will ever be performed: in this situation the Allocator parameter should be set to
- type `void`. Note that this parameter should not be used simply to prevent large memory
- allocations, not only is that role better performed by the allocator, but fixed precision
- integers have a tendency to allocate all of MaxBits of storage more often than one would expect.]]
- [[SignType][Determines whether the resulting type is signed or not. Note that for
- [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] types
- this parameter must be `signed_magnitude`. For fixed precision
- types then this type may be either `signed_magnitude` or `unsigned_magnitude`.]]
- [[Checked][This parameter has two values: `checked` or `unchecked`. See the [link boost_multiprecision.tut.ints.cpp_int tutorial] for more information.]]
- [[Allocator][The allocator to use for dynamic memory allocation, or type `void` if MaxBits == MinBits.]]
- ]
- The type of `number_category<cpp_int<Args...> >::type` is `mpl::int_<number_kind_integer>`.
- More information on this type can be found in the [link boost_multiprecision.tut.ints.cpp_int tutorial].
- [endsect]
- [section:gmp_int_ref gmp_int]
- namespace boost{ namespace multiprecision{
- class gmp_int;
- typedef number<gmp_int > mpz_int;
- }} // namespaces
- Class template `gmp_int` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
- Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
- to change.
- The type of `number_category<cpp_int<Args...> >::type` is `mpl::int_<number_kind_integer>`.
- More information on this type can be found in the [link boost_multiprecision.tut.ints.gmp_int tutorial].
- [endsect]
- [section:tom_int_ref tom_int]
- namespace boost{ namespace multiprecision{
- class tommath_int;
- typedef number<tommath_int > tom_int;
- }} // namespaces
- Class template `tommath_int` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
- Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
- to change.
- The type of `number_category<cpp_int<Args...> >::type` is `mpl::int_<number_kind_integer>`.
- More information on this type can be found in the [link boost_multiprecision.tut.ints.tom_int tutorial].
- [endsect]
- [section:mpf_ref gmp_float]
- namespace boost{ namespace multiprecision{
- template <unsigned Digits10>
- class gmp_float;
- typedef number<gmp_float<50> > mpf_float_50;
- typedef number<gmp_float<100> > mpf_float_100;
- typedef number<gmp_float<500> > mpf_float_500;
- typedef number<gmp_float<1000> > mpf_float_1000;
- typedef number<gmp_float<0> > mpf_float;
- }} // namespaces
- Class template `gmp_float` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
- Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
- to change.
- The class takes a single template parameter - `Digits10` - which is the number of decimal digits precision the type
- should support. When this parameter is zero, then the precision can be set at runtime via `number::default_precision`
- and `number::precision`. Note that this type does not in any way change the GMP library's global state (for example
- it does not change the default precision of the mpf_t data type), therefore you can safely mix this type with existing
- code that uses GMP, and also mix `gmp_float`s of differing precision.
- The type of `number_category<cpp_int<Args...> >::type` is `mpl::int_<number_kind_floating_point>`.
- More information on this type can be found in the [link boost_multiprecision.tut.floats.gmp_float tutorial].
- [endsect]
- [section:mpfr_ref mpfr_float_backend]
- namespace boost{ namespace multiprecision{
- template <unsigned Digits10>
- class mpfr_float_backend;
- typedef number<mpfr_float_backend<50> > mpfr_float_50;
- typedef number<mpfr_float_backend<100> > mpfr_float_100;
- typedef number<mpfr_float_backend<500> > mpfr_float_500;
- typedef number<mpfr_float_backend<1000> > mpfr_float_1000;
- typedef number<mpfr_float_backend<0> > mpfr_float;
- }} // namespaces
- Class template `mpfr_float_backend` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
- Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
- to change.
- The class takes a single template parameter - `Digits10` - which is the number of decimal digits precision the type
- should support. When this parameter is zero, then the precision can be set at runtime via `number::default_precision`
- and `number::precision`. Note that this type does not in any way change the GMP or MPFR library's global state (for example
- it does not change the default precision of the mpfr_t data type), therefore you can safely mix this type with existing
- code that uses GMP or MPFR, and also mix `mpfr_float_backend`s of differing precision.
- The type of `number_category<cpp_int<Args...> >::type` is `mpl::int_<number_kind_floating_point>`.
- More information on this type can be found in the [link boost_multiprecision.tut.floats.mpfr_float tutorial].
- [endsect]
- [section:cpp_bin_float_ref cpp_bin_float]
- namespace boost{ namespace multiprecision{
- enum digit_base_type
- {
- digit_base_2 = 2,
- digit_base_10 = 10
- };
- template <unsigned Digits, digit_base_type base = digit_base_10, class Allocator = void, class Exponent = int, ExponentMin = 0, ExponentMax = 0>
- class cpp_bin_float;
- typedef number<cpp_bin_float<50> > cpp_bin_float_50;
- typedef number<cpp_bin_float<100> > cpp_bin_float_100;
- typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> cpp_bin_float_single;
- typedef number<backends::cpp_bin_float<53, backends::digit_base_2, void, boost::int16_t, -1022, 1023>, et_off> cpp_bin_float_double;
- typedef number<backends::cpp_bin_float<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_double_extended;
- typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad;
- typedef number<backends::cpp_bin_float<237, backends::digit_base_2, void, boost::int32_t, -262142, 262143>, et_off> cpp_bin_float_oct;
- }} // namespaces
- Class template `cpp_bin_float` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
- Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
- to change.
- The class takes six template parameters:
- [variablelist
- [[Digits][The number of digits precision the type
- should support. This is normally expressed as base-10 digits, but that can be changed via the second template parameter.]]
- [[base][An enumerated value (either `digit_base_10` or `digit_base_2`) that indicates whether `Digits` is base-10 or base-2]]
- [[Allocator][The allocator used: defaults to type `void`, meaning all storage is within the class, and no dynamic
- allocation is performed, but can be set to a standard library allocator if dynamic allocation makes more sense.]]
- [[Exponent][A signed integer type to use as the type of the exponent - defaults to `int`.]]
- [[ExponentMin][The smallest (most negative) permitted exponent, defaults to zero, meaning "define as small as possible
- given the limitations of the type and our internal requirements".]]
- [[ExponentMax][The largest (most positive) permitted exponent, defaults to zero, meaning "define as large as possible
- given the limitations of the type and our internal requirements".]]
- ]
- The type of `number_category<cpp_bin_float<Args...> >::type` is `mpl::int_<number_kind_floating_point>`.
- More information on this type can be found in the [link boost_multiprecision.tut.floats.cpp_bin_float tutorial].
- [h4 Implementation Notes]
- Internally, an N-bit `cpp_bin_float` is represented as an N-bit unsigned integer along with an exponent and a sign.
- The integer part is normalized so that it's most significant bit is always 1. The decimal point is assumed to be
- directly after the most significant bit of the integer part. The special values zero, infinity and NaN all have
- the integer part set to zero, and the exponent to one of 3 special values above the maximum permitted exponent.
- Multiplication is trivial: multiply the two N-bit integer mantissa's to obtain a 2N-bit number, then round and
- adjust the sign and exponent.
- Addition and subtraction proceed similarly - if the exponents are such that there is overlap between the two
- values, then left shift the larger value to produce a number with between N and 2N bits, then perform integer
- addition or subtraction, round, and adjust the exponent.
- Division proceeds as follows: first scale the numerator by some power of 2 so that integer division will
- produce either an N-bit or N+1 bit result plus a remainder. If we get an N bit result then the size of
- twice the remainder compared to the denominator gives us the rounding direction. Otherwise we have one extra bit
- in the result which we can use to determine rounding (in this case ties occur only if the remainder is zero and
- the extra bit is a 1).
- Square root uses integer square root in a manner analogous to division.
- Decimal string to binary conversion proceeds as follows: first parse the digits to
- produce an integer multiplied by a decimal exponent. Note that we stop parsing digits
- once we have parsed as many as can possibly effect the result - this stops the integer
- part growing too large when there are a very large number of input digits provided.
- At this stage if the decimal exponent is positive then the result is an integer and we
- can in principle simply multiply by 10^N to get an exact integer result. In practice
- however, that could produce some very large integers. We also need to be able to divide
- by 10^N in the event that the exponent is negative. Therefore calculation of the 10^N
- values plus the multiplication or division are performed using limited precision
- integer arithmetic, plus an exponent, and a track of the accumulated error. At the end of
- the calculation we will either be able to round unambiguously, or the error will be such
- that we can't tell which way to round. In the latter case we simply up the precision and try
- again until we have an unambiguously rounded result.
- Binary to decimal conversion proceeds very similarly to the above, our aim is to calculate
- `mantissa * 2^shift * 10^E` where `E` is the decimal exponent and `shift` is calculated
- so that the result is an N bit integer assuming we want N digits printed in the result.
- As before we use limited precision arithmetic to calculate the result and up the
- precision as necessary until the result is unambiguously correctly rounded. In addition
- our initial calculation of the decimal exponent may be out by 1, so we have to correct
- that and loop as well in the that case.
- [endsect]
- [section:cpp_dec_ref cpp_dec_float]
- namespace boost{ namespace multiprecision{
- template <unsigned Digits10, class ExponentType = boost::int32_t, class Allocator = void>
- class cpp_dec_float;
- typedef number<cpp_dec_float<50> > cpp_dec_float_50;
- typedef number<cpp_dec_float<100> > cpp_dec_float_100;
- }} // namespaces
- Class template `cpp_dec_float` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
- Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
- to change.
- The class takes three template parameters:
- [variablelist
- [[Digits10][The number of decimal digits precision the type
- should support. Note that this type does not normally perform any dynamic memory allocation, and as a result the `Digits10`
- template argument should not be set too high or the class's size will grow unreasonably large.]]
- [[ExponentType][A signed integer type that represents the exponent of the number]]
- [[Allocator][The allocator used: defaults to type `void`, meaning all storage is within the class, and no dynamic
- allocation is performed, but can be set to a standard library allocator if dynamic allocation makes more sense.]]
- ]
- The type of `number_category<cpp_dec_float<Args...> >::type` is `mpl::int_<number_kind_floating_point>`.
- More information on this type can be found in the [link boost_multiprecision.tut.floats.cpp_dec_float tutorial].
- [endsect]
- [section:internals Internal Support Code]
- There are some traits classes which authors of new backends should be aware of:
- namespace boost{ namespace multiprecision{ namespace detail{
- template<typename From, typename To>
- struct is_explicitly_convertible;
- }}}
- Inherits from `boost::integral_constant<bool,true>` if type `From` has an explicit conversion from `To`.
- For compilers that support C++11 SFINAE-expressions this trait should "just work". Otherwise it inherits
- from `boost::is_convertible<From, To>::type`, and will need to be specialised for Backends that have
- constructors marked as `explicit`.
- template <class From, class To>
- struct is_lossy_conversion
- {
- static const bool value = see below;
- };
- Member `value` is true if the conversion from `From` to `To` would result in a loss of precision, and `false` otherwise.
- The default version of this trait simply checks whether the ['kind] of conversion (for example from a floating-point to an integer type)
- is inherently lossy. Note that if either of the types `From` or `To` are of an unknown number category (because `number_category` is not
- specialised for that type) then this trait will be `true`.
- template<typename From, typename To>
- struct is_restricted_conversion
- {
- static const bool value = see below;
- };
- Member `value` is `true` if `From` is only explicitly convertible to `To` and not implicitly convertible, or
- if `is_lossy_conversion<From, To>::value` is `true`. Otherwise `false`.
- Note that while this trait is the ultimate arbiter of which constructors are marked as `explicit` in class `number`,
- authors of backend types should generally specialise one of the traits above, rather than this one directly.
- template <class T>
- is_signed_number;
- template <class T>
- is_unsigned_number;
- These two traits inherit from either `mpl::true_` or `mpl::false_`, by default types are assumed to be signed unless
- `is_unsigned_number` is specialized for that type.
- [endsect]
- [section:backendconc Backend Requirements]
- The requirements on the `Backend` template argument to `number` are split up into
- sections: compulsory and optional.
- Compulsory requirements have no default implementation in the library, therefore if the feature
- they implement is to be supported at all, then they must be implemented by the backend.
- Optional requirements have default implementations that are called if the backend doesn't provide
- it's own. Typically the backend will implement these to improve performance.
- In the following tables, type B is the `Backend` template argument to `number`, `b` and `b2` are
- a variables of type B, `pb` is a variable of type B*, `cb`, `cb2` and `cb3` are constant variables of type `const B`,
- `rb` is a variable of type `B&&`, `a` and `a2` are variables of Arithmetic type,
- `s` is a variable of type `const char*`, `ui` is a variable of type `unsigned`, `bb` is a variable of type `bool`,
- `pa` is a variable of type pointer-to-arithmetic-type, `exp` is a variable of type `B::exp_type`,
- `pexp` is a variable of type `B::exp_type*`, `i` is a variable of type `int`, `pi` pointer to a variable of type `int`,
- B2 is another type that meets these requirements, b2 is a variable of type B2, `ss` is variable of type `std::streamsize`
- and `ff` is a variable of type `std::ios_base::fmtflags`.
- [table Compulsory Requirements on the Backend type.
- [[Expression][Return Type][Comments][Throws]]
- [[`B::signed_types`][`mpl::list<type-list>`][A list of signed integral types that can be assigned to type B. The types shall be
- listed in order of size, smallest first, and shall terminate in the type that is `std::intmax_t`.][[space]]]
- [[`B::unsigned_types`][`mpl::list<type-list>`][A list of unsigned integral types that can be assigned to type B. The types shall be
- listed in order of size, smallest first, and shall terminate in the type that is `std::uintmax_t`.][[space]]]
- [[`B::float_types`][`mpl::list<type-list>`][A list of floating-point types that can be assigned to type B.The types shall be
- listed in order of size, smallest first, and shall terminate in type `long double`.][[space]]]
- [[`B::exponent_type`][A signed integral type.][The type of the exponent of type B. This type is required only for floating-point types.][[space]]]
- [[`B()`][ ][Default constructor.][[space]]]
- [[`B(cb)`][ ][Copy Constructor.][[space]]]
- [[`b = b`][`B&`][Assignment operator.][[space]]]
- [[`b = a`][`B&`][Assignment from an Arithmetic type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]]
- [[`b = s`][`B&`][Assignment from a string.][Throws a `std::runtime_error` if the string could not be interpreted as a valid number.]]
- [[`b.swap(b)`][`void`][Swaps the contents of its arguments.][`noexcept`]]
- [[`cb.str(ss, ff)`][`std::string`][Returns the string representation of `b` with `ss` digits and formatted according to the flags set in `ff`.
- If `ss` is zero, then returns as many digits as are required to reconstruct the original value.][[space]]]
- [[`b.negate()`][`void`][Negates `b`.][[space]]]
- [[`cb.compare(cb2)`][`int`][Compares `cb` and `cb2`, returns a value less than zero if `cb < cb2`, a value greater than zero if `cb > cb2` and zero
- if `cb == cb2`.][`noexcept`]]
- [[`cb.compare(a)`][`int`][Compares `cb` and `a`, returns a value less than zero if `cb < a`, a value greater than zero if `cb > a` and zero
- if `cb == a`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]]
- [[`eval_add(b, cb)`][`void`][Adds `cb` to `b`.][[space]]]
- [[`eval_subtract(b, cb)`][`void`][Subtracts `cb` from `b`.][[space]]]
- [[`eval_multiply(b, cb)`][`void`][Multiplies `b` by `cb`.][[space]]]
- [[`eval_divide(b, cb)`][`void`][Divides `b` by `cb`.]
- [`std::overflow_error` if cb has the value zero, and `std::numeric_limits<number<B> >::has_infinity == false`]]
- [[`eval_modulus(b, cb)`][`void`][Computes `b %= cb`, only required when `B` is an integer type.]
- [`std::overflow_error` if cb has the value zero.]]
- [[`eval_bitwise_and(b, cb)`][`void`][Computes `b &= cb`, only required when `B` is an integer type.][[space]]]
- [[`eval_bitwise_or(b, cb)`][`void`][Computes `b |= cb`, only required when `B` is an integer type.][[space]]]
- [[`eval_bitwise_xor(b, cb)`][`void`][Computes `b ^= cb`, only required when `B` is an integer type.][[space]]]
- [[`eval_complement(b, cb)`][`void`][Computes the ones-complement of `cb` and stores the result in `b`, only required when `B` is an integer type.][[space]]]
- [[`eval_left_shift(b, ui)`][`void`][Computes `b <<= ui`, only required when `B` is an integer type.][[space]]]
- [[`eval_right_shift(b, ui)`][`void`][Computes `b >>= ui`, only required when `B` is an integer type.][[space]]]
- [[`eval_convert_to(pa, cb)`][`void`][Converts `cb` to the type of `*pa` and store the result in `*pa`. Type `B` shall support
- conversion to at least types `std::intmax_t`, `std::uintmax_t` and `long long`.
- Conversion to other arithmetic types can then be synthesised using other operations.
- Conversions to other types are entirely optional.][[space]]]
- [[`eval_frexp(b, cb, pexp)`][`void`][Stores values in `b` and `*pexp` such that the value of `cb` is b * 2[super *pexp], only required when `B` is a floating-point type.][[space]]]
- [[`eval_ldexp(b, cb, exp)`][`void`][Stores a value in `b` that is cb * 2[super exp], only required when `B` is a floating-point type.][[space]]]
- [[`eval_frexp(b, cb, pi)`][`void`][Stores values in `b` and `*pi` such that the value of `cb` is b * 2[super *pi], only required when `B` is a floating-point type.]
- [`std::runtime_error` if the exponent of cb is too large to be stored in an `int`.]]
- [[`eval_ldexp(b, cb, i)`][`void`][Stores a value in `b` that is cb * 2[super i], only required when `B` is a floating-point type.][[space]]]
- [[`eval_floor(b, cb)`][`void`][Stores the floor of `cb` in `b`, only required when `B` is a floating-point type.][[space]]]
- [[`eval_ceil(b, cb)`][`void`][Stores the ceiling of `cb` in `b`, only required when `B` is a floating-point type.][[space]]]
- [[`eval_sqrt(b, cb)`][`void`][Stores the square root of `cb` in `b`, only required when `B` is a floating-point type.][[space]]]
- [[`boost::multiprecision::number_category<B>::type`][`mpl::int_<N>`][`N` is one of the values `number_kind_integer`, `number_kind_floating_point`, `number_kind_complex`, `number_kind_rational` or `number_kind_fixed_point`.
- Defaults to `number_kind_floating_point`.][[space]]]
- [[`eval_conj(b, cb)`][`void`][Sets `b` to the complex conjugate of `cb`. Required for complex types only - other types have a sensible default.][[space]]]
- [[`eval_proj(b, cb)`][`void`][Sets `b` to the Riemann projection of `cb`. Required for complex types only - other types have a sensible default.][[space]]]
- [[`eval_real(b, cb)`][`void`][Sets `b` to the real part of `cb`. Required for complex types only - other types have a sensible default.][[space]]]
- [[`eval_imag(b, cb)`][`void`][Sets `b` to the imaginary of `cb`. Required for complex types only - other types have a sensible default.][[space]]]
- [[`eval_set_real(b, a)`][`void`][Sets the real part of `b` to `cb`. Required for complex types only - other types have a sensible default.][[space]]]
- [[`eval_set_imag(b, a)`][`void`][Sets the imaginary part of `b` to `cb`. Required for complex types only - other types have a sensible default.][[space]]]
- ]
- [table Optional Requirements on the Backend Type
- [[Expression][Returns][Comments][Throws]]
- [[['Construct and assign:]]]
- [[`B(rb)`][`B`][Move constructor. Afterwards variable `rb` shall be in sane state, albeit with unspecified value.
- Only destruction and assignment to the moved-from variable `rb` need be supported after the operation.][`noexcept`]]
- [[`b = rb`][`B&`][Move-assign. Afterwards variable `rb` shall be in sane state, albeit with unspecified value.
- Only destruction and assignment to the moved-from variable `rb` need be supported after the operation.][`noexcept`]]
- [[`B(a)`][`B`][Direct construction from an arithmetic type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, this operation is simulated using default-construction followed by assignment.][[space]]]
- [[`B(b2)`][`B`][Copy constructor from a different back-end type. When not provided, a generic interconversion routine is used.
- This constructor may be `explicit` if the corresponding frontend constructor should also be `explicit`.][[space]]]
- [[`b = b2`][`b&`][Assignment operator from a different back-end type. When not provided, a generic interconversion routine is used.][[space]]]
- [[`assign_components(b, a, a)`][`void`][Assigns to `b` the two components in the following arguments.
- Only applies to rational and complex number types.
- When not provided, arithmetic operations are used to synthesise the result from the two values.][[space]]]
- [[`assign_components(b, b2, b2)`][`void`][Assigns to `b` the two components in the following arguments.
- Only applies to rational and complex number types.
- When not provided, arithmetic operations are used to synthesise the result from the two values.][[space]]]
- [[['Comparisons:]]]
- [[`eval_eq(cb, cb2)`][`bool`][Returns `true` if `cb` and `cb2` are equal in value.
- When not provided, the default implementation returns `cb.compare(cb2) == 0`.][`noexcept`]]
- [[`eval_eq(cb, a)`][`bool`][Returns `true` if `cb` and `a` are equal in value.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, return the equivalent of `eval_eq(cb, B(a))`.][[space]]]
- [[`eval_eq(a, cb)`][`bool`][Returns `true` if `cb` and `a` are equal in value.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default version returns `eval_eq(cb, a)`.][[space]]]
- [[`eval_lt(cb, cb2)`][`bool`][Returns `true` if `cb` is less than `cb2` in value.
- When not provided, the default implementation returns `cb.compare(cb2) < 0`.][`noexcept`]]
- [[`eval_lt(cb, a)`][`bool`][Returns `true` if `cb` is less than `a` in value.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default implementation returns `eval_lt(cb, B(a))`.][[space]]]
- [[`eval_lt(a, cb)`][`bool`][Returns `true` if `a` is less than `cb` in value.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default implementation returns `eval_gt(cb, a)`.][[space]]]
- [[`eval_gt(cb, cb2)`][`bool`][Returns `true` if `cb` is greater than `cb2` in value.
- When not provided, the default implementation returns `cb.compare(cb2) > 0`.][`noexcept`]]
- [[`eval_gt(cb, a)`][`bool`][Returns `true` if `cb` is greater than `a` in value.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default implementation returns `eval_gt(cb, B(a))`.][[space]]]
- [[`eval_gt(a, cb)`][`bool`][Returns `true` if `a` is greater than `cb` in value.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default implementation returns `eval_lt(cb, a)`.][[space]]]
- [[`eval_is_zero(cb)`][`bool`][Returns `true` if `cb` is zero, otherwise `false`. The default version of this function
- returns `cb.compare(ui_type(0)) == 0`, where `ui_type` is `ui_type` is
- `typename mpl::front<typename B::unsigned_types>::type`.][[space]]]
- [[`eval_get_sign(cb)`][`int`][Returns a value < zero if `cb` is negative, a value > zero if `cb` is positive, and zero if `cb` is zero.
- The default version of this function
- returns `cb.compare(ui_type(0))`, where `ui_type` is `ui_type` is
- `typename mpl::front<typename B::unsigned_types>::type`.][[space]]]
- [[['Basic arithmetic:]]]
- [[`eval_add(b, a)`][`void`][Adds `a` to `b`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default version calls `eval_add(b, B(a))`][[space]]]
- [[`eval_add(b, cb, cb2)`][`void`][Add `cb` to `cb2` and stores the result in `b`.
- When not provided, does the equivalent of `b = cb; eval_add(b, cb2)`.][[space]]]
- [[`eval_add(b, cb, a)`][`void`][Add `cb` to `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_add(b, cb, B(a))`.][[space]]]
- [[`eval_add(b, a, cb)`][`void`][Add `a` to `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_add(b, cb, a)`.][[space]]]
- [[`eval_subtract(b, a)`][`void`][Subtracts `a` from `b`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default version calls `eval_subtract(b, B(a))`][[space]]]
- [[`eval_subtract(b, cb, cb2)`][`void`][Subtracts `cb2` from `cb` and stores the result in `b`.
- When not provided, does the equivalent of `b = cb; eval_subtract(b, cb2)`.][[space]]]
- [[`eval_subtract(b, cb, a)`][`void`][Subtracts `a` from `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_subtract(b, cb, B(a))`.][[space]]]
- [[`eval_subtract(b, a, cb)`][`void`][Subtracts `cb` from `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_subtract(b, cb, a); b.negate();`.][[space]]]
- [[`eval_multiply(b, a)`][`void`][Multiplies `b` by `a`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default version calls `eval_multiply(b, B(a))`][[space]]]
- [[`eval_multiply(b, cb, cb2)`][`void`][Multiplies `cb` by `cb2` and stores the result in `b`.
- When not provided, does the equivalent of `b = cb; eval_multiply(b, cb2)`.][[space]]]
- [[`eval_multiply(b, cb, a)`][`void`][Multiplies `cb` by `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_multiply(b, cb, B(a))`.][[space]]]
- [[`eval_multiply(b, a, cb)`][`void`][Multiplies `a` by `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_multiply(b, cb, a)`.][[space]]]
- [[`eval_multiply_add(b, cb, cb2)`][`void`][Multiplies `cb` by `cb2` and adds the result to `b`.
- When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, cb2)` followed by
- `eval_add(b, t)`.][[space]]]
- [[`eval_multiply_add(b, cb, a)`][`void`][Multiplies `a` by `cb` and adds the result to `b`.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, a)` followed by
- `eval_add(b, t)`.][[space]]]
- [[`eval_multiply_add(b, a, cb)`][`void`][Multiplies `a` by `cb` and adds the result to `b`.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided does the equivalent of `eval_multiply_add(b, cb, a)`.][[space]]]
- [[`eval_multiply_subtract(b, cb, cb2)`][`void`][Multiplies `cb` by `cb2` and subtracts the result from `b`.
- When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, cb2)` followed by
- `eval_subtract(b, t)`.][[space]]]
- [[`eval_multiply_subtract(b, cb, a)`][`void`][Multiplies `a` by `cb` and subtracts the result from `b`.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, a)` followed by
- `eval_subtract(b, t)`.][[space]]]
- [[`eval_multiply_subtract(b, a, cb)`][`void`][Multiplies `a` by `cb` and subtracts the result from `b`.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided does the equivalent of `eval_multiply_subtract(b, cb, a)`.][[space]]]
- [[`eval_multiply_add(b, cb, cb2, cb3)`][`void`][Multiplies `cb` by `cb2` and adds the result to `cb3` storing the result in `b`.
- When not provided does the equivalent of `eval_multiply(b, cb, cb2)` followed by
- `eval_add(b, cb3)`.
- For brevity, only a version showing all arguments of type `B` is shown here, but you can replace up to any 2 of
- `cb`, `cb2` and `cb3` with any type listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]]
- [[`eval_multiply_subtract(b, cb, cb2, cb3)`][`void`][Multiplies `cb` by `cb2` and subtracts from the result `cb3` storing the result in `b`.
- When not provided does the equivalent of `eval_multiply(b, cb, cb2)` followed by
- `eval_subtract(b, cb3)`.
- For brevity, only a version showing all arguments of type `B` is shown here, but you can replace up to any 2 of
- `cb`, `cb2` and `cb3` with any type listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]]
- [[`eval_divide(b, a)`][`void`][Divides `b` by `a`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default version calls `eval_divide(b, B(a))`]
- [`std::overflow_error` if `a` has the value zero, and `std::numeric_limits<number<B> >::has_infinity == false`]]
- [[`eval_divide(b, cb, cb2)`][`void`][Divides `cb` by `cb2` and stores the result in `b`.
- When not provided, does the equivalent of `b = cb; eval_divide(b, cb2)`.]
- [`std::overflow_error` if `cb2` has the value zero, and `std::numeric_limits<number<B> >::has_infinity == false`]]
- [[`eval_divide(b, cb, a)`][`void`][Divides `cb` by `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_divide(b, cb, B(a))`.]
- [`std::overflow_error` if `a` has the value zero, and `std::numeric_limits<number<B> >::has_infinity == false`]]
- [[`eval_divide(b, a, cb)`][`void`][Divides `a` by `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_divide(b, B(a), cb)`.]
- [`std::overflow_error` if cb has the value zero, and `std::numeric_limits<number<B> >::has_infinity == false`]]
- [[`eval_increment(b)`][void][Increments the value of `b` by one.
- When not provided, does the equivalent of `eval_add(b, static_cast<ui_type>(1u))`.
- Where `ui_type` is `typename mpl::front<typename B::unsigned_types>::type`.][[space]]]
- [[`eval_decrement(b)`][void][Decrements the value of `b` by one.
- When not provided, does the equivalent of `eval_subtract(b, static_cast<ui_type>(1u))`.
- Where `ui_type` is `typename mpl::front<typename B::unsigned_types>::type`.][[space]]]
- [[['Integer specific operations:]]]
- [[`eval_modulus(b, a)`][`void`][Computes `b %= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default version calls `eval_modulus(b, B(a))`]
- [`std::overflow_error` if `a` has the value zero.]]
- [[`eval_modulus(b, cb, cb2)`][`void`][Computes `cb % cb2` and stores the result in `b`, only required when `B` is an integer type.
- When not provided, does the equivalent of `b = cb; eval_modulus(b, cb2)`.]
- [`std::overflow_error` if `a` has the value zero.]]
- [[`eval_modulus(b, cb, a)`][`void`][Computes `cb % a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_modulus(b, cb, B(a))`.]
- [`std::overflow_error` if `a` has the value zero.]]
- [[`eval_modulus(b, a, cb)`][`void`][Computes `cb % a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_modulus(b, B(a), cb)`.]
- [`std::overflow_error` if `a` has the value zero.]]
- [[`eval_bitwise_and(b, a)`][`void`][Computes `b &= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default version calls `eval_bitwise_and(b, B(a))`][[space]]]
- [[`eval_bitwise_and(b, cb, cb2)`][`void`][Computes `cb & cb2` and stores the result in `b`, only required when `B` is an integer type.
- When not provided, does the equivalent of `b = cb; eval_bitwise_and(b, cb2)`.][[space]]]
- [[`eval_bitwise_and(b, cb, a)`][`void`][Computes `cb & a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_bitwise_and(b, cb, B(a))`.][[space]]]
- [[`eval_bitwise_and(b, a, cb)`][`void`][Computes `cb & a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_bitwise_and(b, cb, a)`.][[space]]]
- [[`eval_bitwise_or(b, a)`][`void`][Computes `b |= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default version calls `eval_bitwise_or(b, B(a))`][[space]]]
- [[`eval_bitwise_or(b, cb, cb2)`][`void`][Computes `cb | cb2` and stores the result in `b`, only required when `B` is an integer type.
- When not provided, does the equivalent of `b = cb; eval_bitwise_or(b, cb2)`.][[space]]]
- [[`eval_bitwise_or(b, cb, a)`][`void`][Computes `cb | a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_bitwise_or(b, cb, B(a))`.][[space]]]
- [[`eval_bitwise_or(b, a, cb)`][`void`][Computes `cb | a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_bitwise_or(b, cb, a)`.][[space]]]
- [[`eval_bitwise_xor(b, a)`][`void`][Computes `b ^= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, the default version calls `eval_bitwise_xor(b, B(a))`][[space]]]
- [[`eval_bitwise_xor(b, cb, cb2)`][`void`][Computes `cb ^ cb2` and stores the result in `b`, only required when `B` is an integer type.
- When not provided, does the equivalent of `b = cb; eval_bitwise_xor(b, cb2)`.][[space]]]
- [[`eval_bitwise_xor(b, cb, a)`][`void`][Computes `cb ^ a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_bitwise_xor(b, cb, B(a))`.][[space]]]
- [[`eval_bitwise_xor(b, a, cb)`][`void`][Computes `a ^ cb` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- When not provided, does the equivalent of `eval_bitwise_xor(b, cb, a)`.][[space]]]
- [[`eval_left_shift(b, cb, ui)`][`void`][Computes `cb << ui` and stores the result in `b`, only required when `B` is an integer type.
- When not provided, does the equivalent of `b = cb; eval_left_shift(b, a);`.][[space]]]
- [[`eval_right_shift(b, cb, ui)`][`void`][Computes `cb >> ui` and stores the result in `b`, only required when `B` is an integer type.
- When not provided, does the equivalent of `b = cb; eval_right_shift(b, a);`.][[space]]]
- [[`eval_qr(cb, cb2, b, b2)`][`void`][Sets `b` to the result of `cb / cb2` and `b2` to the result of `cb % cb2`. Only required when `B` is an integer type.
- The default version of this function is synthesised from other operations above.]
- [`std::overflow_error` if `a` has the value zero.]]
- [[`eval_integer_modulus(cb, ui)`][`unsigned`][Returns the result of `cb % ui`. Only required when `B` is an integer type.
- The default version of this function is synthesised from other operations above.]
- [`std::overflow_error` if `a` has the value zero.]]
- [[`eval_lsb(cb)`][`unsigned`][Returns the index of the least significant bit that is set. Only required when `B` is an integer type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_msb(cb)`][`unsigned`][Returns the index of the most significant bit that is set. Only required when `B` is an integer type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_bit_test(cb, ui)`][`bool`][Returns true if `cb` has bit `ui` set. Only required when `B` is an integer type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_bit_set(b, ui)`][`void`][Sets the bit at index `ui` in `b`. Only required when `B` is an integer type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_bit_unset(b, ui)`][`void`][Unsets the bit at index `ui` in `b`. Only required when `B` is an integer type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_bit_flip(b, ui)`][`void`][Flips the bit at index `ui` in `b`. Only required when `B` is an integer type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_gcd(b, cb, cb2)`][`void`][Sets `b` to the greatest common divisor of `cb` and `cb2`. Only required when `B` is an integer type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_lcm(b, cb, cb2)`][`void`][Sets `b` to the least common multiple of `cb` and `cb2`. Only required when `B` is an integer type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_gcd(b, cb, a)`][`void`][Sets `b` to the greatest common divisor of `cb` and `cb2`. Only required when `B` is an integer type.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- The default version of this function calls `eval_gcd(b, cb, B(a))`.][[space]]]
- [[`eval_lcm(b, cb, a)`][`void`][Sets `b` to the least common multiple of `cb` and `cb2`. Only required when `B` is an integer type.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- The default version of this function calls `eval_lcm(b, cb, B(a))`.][[space]]]
- [[`eval_gcd(b, a, cb)`][`void`][Sets `b` to the greatest common divisor of `cb` and `a`. Only required when `B` is an integer type.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- The default version of this function calls `eval_gcd(b, cb, a)`.][[space]]]
- [[`eval_lcm(b, a, cb)`][`void`][Sets `b` to the least common multiple of `cb` and `a`. Only required when `B` is an integer type.
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types` or `B::float_types`.
- The default version of this function calls `eval_lcm(b, cb, a)`.][[space]]]
- [[`eval_powm(b, cb, cb2, cb3)`][`void`][Sets `b` to the result of ['(cb^cb2)%cb3].
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_powm(b, cb, cb2, a)`][`void`][Sets `b` to the result of ['(cb^cb2)%a].
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types`.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_powm(b, cb, a, cb2)`][`void`][Sets `b` to the result of ['(cb^a)%cb2].
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types`.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_powm(b, cb, a, a2)`][`void`][Sets `b` to the result of ['(cb^a)%a2].
- The type of `a` shall be listed in one of the type lists
- `B::signed_types`, `B::unsigned_types`.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_integer_sqrt(b, cb, b2)`][`void`][Sets `b` to the largest integer which when squared is less than `cb`, also
- sets `b2` to the remainder, ie to ['cb - b[super 2]].
- The default version of this function is synthesised from other operations above.][[space]]]
- [[['Sign manipulation:]]]
- [[`eval_abs(b, cb)`][`void`][Set `b` to the absolute value of `cb`.
- The default version of this functions assigns `cb` to `b`, and then calls `b.negate()` if
- `eval_get_sign(cb) < 0`.][[space]]]
- [[`eval_fabs(b, cb)`][`void`][Set `b` to the absolute value of `cb`.
- The default version of this functions assigns `cb` to `b`, and then calls `b.negate()` if
- `eval_get_sign(cb) < 0`.][[space]]]
- [[['floating-point functions:]]]
- [[`eval_fpclassify(cb)`][`int`][Returns one of the same values returned by `std::fpclassify`. Only required when `B` is an floating-point type.
- The default version of this function will only test for zero `cb`.][[space]]]
- [[`eval_trunc(b, cb)`][`void`][Performs the equivalent operation to `std::trunc` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_round(b, cb)`][`void`][Performs the equivalent operation to `std::round` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_exp(b, cb)`][`void`][Performs the equivalent operation to `std::exp` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_exp2(b, cb)`][`void`][Performs the equivalent operation to `std::exp2` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is implemented in terms of `eval_pow`.][[space]]]
- [[`eval_log(b, cb)`][`void`][Performs the equivalent operation to `std::log` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_log10(b, cb)`][`void`][Performs the equivalent operation to `std::log10` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_sin(b, cb)`][`void`][Performs the equivalent operation to `std::sin` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_cos(b, cb)`][`void`][Performs the equivalent operation to `std::cos` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_tan(b, cb)`][`void`][Performs the equivalent operation to `std::exp` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_asin(b, cb)`][`void`][Performs the equivalent operation to `std::asin` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_acos(b, cb)`][`void`][Performs the equivalent operation to `std::acos` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_atan(b, cb)`][`void`][Performs the equivalent operation to `std::atan` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_sinh(b, cb)`][`void`][Performs the equivalent operation to `std::sinh` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_cosh(b, cb)`][`void`][Performs the equivalent operation to `std::cosh` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_tanh(b, cb)`][`void`][Performs the equivalent operation to `std::tanh` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_fmod(b, cb, cb2)`][`void`][Performs the equivalent operation to `std::fmod` on arguments `cb` and `cb2`, and store the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_modf(b, cb, pb)`][`void`][Performs the equivalent operation to `std::modf` on argument `cb`, and store the integer result in `*pb` and the fractional part in `b`.
- Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_pow(b, cb, cb2)`][`void`][Performs the equivalent operation to `std::pow` on arguments `cb` and `cb2`, and store the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_atan2(b, cb, cb2)`][`void`][Performs the equivalent operation to `std::atan` on arguments `cb` and `cb2`, and store the result in `b`. Only required when `B` is an floating-point type.
- The default version of this function is synthesised from other operations above.][[space]]]
- [[`eval_scalbn(b, cb, e)`][`void`][Scales value `cb` by ['r[super e]], where ['r] is the radix of the type. The default version of this function
- is implemented in terms of eval_ldexp, consequently this function must be provided for types with a radix other than 2.]]
- [[`eval_scalbln(b, cb, e)`][`void`][Calls `eval_scalbn(b, cb, e)`.]]
- [[`eval_ilogb(cb)`][`B::exponent_type`][Returns the exponent ['e] of value `cb` such that ['1 <= cb*r[super -e] < r], where ['r] is the radix of type B.
- The default version of this function is implemented in terms of eval_frexp, consequently this function must be provided for types with a radix other than 2.]]
- [[`eval_remquo(b, cb, cb2, pi)`][`void`][Sets `b = cb - n * cb2` and stores `n` in `*pi`.]]
- [[`eval_remquo(b, cb, a, pi)`][`void`][Default version converts a to type B and calls the overload above.]]
- [[`eval_remquo(b, a, cb, pi)`][`void`][Default version converts a to type B and calls the overload above.]]
- [[`eval_remainder(b, cb, cb2)`][`void`][Default version calls eval_remquo with a dummy final argument.]]
- [[`eval_remainder(b, cb, a)`][`void`][Default version calls eval_remquo with a dummy final argument.]]
- [[`eval_remainder(b, a, cb)`][`void`][Default version calls eval_remquo with a dummy final argument.]]
- [[`eval_fdim(b, cb, cb2)`][`void`][Default version sets `b = cb - cb2` if `cb > cb2` and zero otherwise. Special cases are handled as in the C99 annex.]]
- [[`eval_fdim(b, cb, a)`][`void`][Default version sets `b = cb - cb2` if `cb > cb2` and zero otherwise. Special cases are handled as in the C99 annex.]]
- [[`eval_fdim(b, a, cb)`][`void`][Default version sets `b = cb - cb2` if `cb > cb2` and zero otherwise. Special cases are handled as in the C99 annex.]]
- [[`eval_fmax(b, cb, cb2)`][`void`][Sets `b` to the larger of `cb` and `cb2`.]]
- [[`eval_fmax(b, cb, a)`][`void`][Sets `b` to the larger of `cb` and `a`.]]
- [[`eval_fmax(b, a, cb)`][`void`][Sets `b` to the larger of `cb` and `a`.]]
- [[`eval_fmin(b, cb, cb2)`][`void`][Sets `b` to the smaller of `cb` and `cb2`.]]
- [[`eval_fmin(b, cb, a)`][`void`][Sets `b` to the smaller of `cb` and `a`.]]
- [[`eval_fmin(b, a, cb)`][`void`][Sets `b` to the smaller of `cb` and `a`.]]
- [[`eval_hypot(b, cb, cb2)`][`void`][Sets `b` to the square root of the sum of the squares of `cb` and `cb2` without undue over or under flow.]]
- [[`eval_hypot(b, cb, a)`][`void`][As above.]]
- [[`eval_hypot(b, a, cb)`][`void`][As above.]]
- [[`eval_logb(b, cb)`][`B::exponent_type`][Sets `b` to the exponent ['e] of value `cb` such that ['1 <= cb*r[super -b] < r], where ['r] is the radix of type B.
- The default version of this function is implemented in terms of `eval_ilogb`.]]
- [[`eval_nearbyint(b, cb)`][`void`][Calls `eval_round(b, cb)`.]]
- [[`eval_rint(b, cb)`][`void`][Calls `eval_nearbyint(b, cb)`.]]
- [[`eval_log2(b, cb)`][`void`][Sets `b` to the logarithm base 2 of `cb`.]]
- [[['hashing:]]]
- [[`hash_value(cb)`][`std::size_t`]
- [Returns a hash value for the argument that is suitable for use with `std::hash` etc. If not provided then no automatic hashing support will be available for the number type.]]
- ]
- When the tables above place no ['throws] requirements on an operation, then it is up to each type modelling this concept to
- decide when or whether throwing an exception is desirable. However, thrown exceptions should always either be the type, or
- inherit from the type `std::runtime_error`. For example, a floating-point type might choose to throw `std::overflow_error`
- whenever the result of an operation would be infinite, and `std::underflow_error` whenever it would round to zero.
- [note
- The non-member functions are all named with an "eval_" prefix to avoid conflicts with template classes of the same name -
- in point of fact this naming convention shouldn't be necessary, but rather works around some compiler bugs.]
- [h4 Overloadable Functions]
- Some of the C99 math functions do not have `eval_` functions but must be overloaded directly: these functions
- are either trivial or are forwarded to the Boost.Math implementations by default.
- The full list of these functions is:
- int sign (const ``['number-or-expression-template-type]``&);
- int signbit (const ``['number-or-expression-template-type]``&);
- ``['number]`` changesign (const ``['number-or-expression-template-type]``&);
- ``['number]`` copysign (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['number]`` asinh (const ``['number-or-expression-template-type]``&);
- ``['number]`` acosh (const ``['number-or-expression-template-type]``&);
- ``['number]`` atanh (const ``['number-or-expression-template-type]``&);
- ``['number]`` cbrt (const ``['number-or-expression-template-type]``&);
- ``['number]`` erf (const ``['number-or-expression-template-type]``&);
- ``['number]`` erfc (const ``['number-or-expression-template-type]``&);
- ``['number]`` expm1 (const ``['number-or-expression-template-type]``&);
- ``['number]`` log1p (const ``['number-or-expression-template-type]``&);
- ``['number]`` tgamma (const ``['number-or-expression-template-type]``&);
- ``['number]`` lgamma (const ``['number-or-expression-template-type]``&);
- long lrint (const ``['number-or-expression-template-type]``&);
- long long llrint (const ``['number-or-expression-template-type]``&);
- ``['number]`` nextafter (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- ``['number]`` nexttoward (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
- [endsect]
- [section:headers Header File Structure]
- [table Top level headers
- [[Header][Contains]]
- [[cpp_int.hpp][The `cpp_int` backend type.]]
- [[gmp.hpp][Defines all [gmp] related backends.]]
- [[miller_rabin.hpp][Miller Rabin primality testing code.]]
- [[number.hpp][Defines the `number` backend, is included by all the backend headers.]]
- [[mpfr.hpp][Defines the mpfr_float_backend backend.]]
- [[random.hpp][Defines code to interoperate with Boost.Random.]]
- [[rational_adaptor.hpp][Defines the `rational_adaptor` backend.]]
- [[cpp_dec_float.hpp][Defines the `cpp_dec_float` backend.]]
- [[tommath.hpp][Defines the `tommath_int` backend.]]
- [[concepts/number_archetypes.hpp][Defines a backend concept archetypes for testing use.]]
- ]
- [table Implementation Headers
- [[Header][Contains]]
- [[cpp_int/add.hpp][Add and subtract operators for `cpp_int_backend`.]]
- [[cpp_int/bitwise.hpp][Bitwise operators for `cpp_int_backend`.]]
- [[cpp_int/checked.hpp][Helper functions for checked arithmetic for `cpp_int_backend`.]]
- [[cpp_int/comparison.hpp][Comparison operators for `cpp_int_backend`.]]
- [[cpp_int/cpp_int_config.hpp][Basic setup and configuration for `cpp_int_backend`.]]
- [[cpp_int/divide.hpp][Division and modulus operators for `cpp_int_backend`.]]
- [[cpp_int/limits.hpp][`numeric_limits` support for `cpp_int_backend`.]]
- [[cpp_int/misc.hpp][Miscellaneous operators for `cpp_int_backend`.]]
- [[cpp_int/multiply.hpp][Multiply operators for `cpp_int_backend`.]]
- [[detail/big_lanczos.hpp][Lanczos support for Boost.Math integration.]]
- [[detail/default_ops.hpp][Default versions of the optional backend non-member functions.]]
- [[detail/generic_interconvert.hpp][Generic interconversion routines.]]
- [[detail/number_base.hpp][All the expression template code, metaprogramming, and operator overloads for `number`.]]
- [[detail/no_et_ops.hpp][The non-expression template operators.]]
- [[detail/functions/constants.hpp][Defines constants used by the floating-point functions.]]
- [[detail/functions/pow.hpp][Defines default versions of the power and exponential related floating-point functions.]]
- [[detail/functions/trig.hpp][Defines default versions of the trigonometric related floating-point functions.]]
- ]
- [endsect]
- [endsect]
- [section:perf Performance Comparison]
- [section:overhead The Overhead in the Number Class Wrapper]
- Using a simple [@../../performance/arithmetic_backend.hpp backend class] that wraps any built in arithmetic type
- we can measure the overhead involved in wrapping a type inside the `number` frontend, and the effect that turning
- on expression templates has. The following table compares the performance between `double` and a `double` wrapped
- inside class `number`:
- [table
- [[Type][Bessel Function Evaluation][Non-Central T Evaluation]]
- [[`double`] [[*1.0 (0.016s)]] [[*1.0] (0.46s)]]
- [[`number<arithmetic_backend<double>, et_off>`] [1.2 (0.019s)] [[*1.0](0.46s)]]
- [[`number<arithmetic_backend<double>, et_on>`] [1.2 (0.019s)] [1.7 (0.79s)]]
- ]
- As you can see whether or not there is an overhead, and how large it is depends on the actual situation,
- but the overhead is in any cases small. Expression templates generally add a greater overhead the
- more complex the expression becomes due to the logic of figuring out how to best unpack and evaluate
- the expression, but of course this is also the situation where you save more temporaries. For a
- "trivial" backend like this, saving temporaries has no benefit, but for larger types it becomes
- a bigger win.
- The following table compares arithmetic using either `long long` or `number<arithmetic_backend<long long> >`
- for the [@../../performance/voronoi_performance.cpp voronoi-diagram builder test]:
- [table
- [[Type][Relative time]]
- [[`long long`][[*1.0](0.0823s)]]
- [[`number<arithmetic_backend<long long>, et_off>`][1.05 (0.0875s)]]
- ]
- This test involves mainly creating a lot of temporaries and performing a small amount of arithmetic on them,
- with very little difference in performance between the native and "wrapped" types.
- The test code was compiled with Microsoft Visual Studio 2010 with all optimisations
- turned on (/Ox), and used MPIR-2.3.0 and [tommath]-0.42.0. The tests were run on 32-bit
- Windows Vista machine.
- [endsect]
- [section:realworld Floating-Point Real World Tests]
- These tests test the total time taken to execute all of Boost.Math's test cases for these functions.
- In each case the best performing library gets a relative score of 1, with the total execution time
- given in brackets. The first three libraries listed are the various floating-point types provided
- by this library, while for comparison, two popular C++ front-ends to [mpfr] ([mpfr_class] and [mpreal])
- are also shown.
- [table Bessel Function Performance
- [[Library][50 Decimal Digits][100 Decimal Digits]]
- [[mpfr_float] [1.2 (5.78s)] [1.2 (9.56s)]]
- [[static_mpfr_float] [1.1 (5.47s)] [1.1 (9.09s)]]
- [[mpf_float] [[*1.0] (4.82s)] [[*1.0](8.07s)]]
- [[cpp_dec_float] [1.8 (8.54s)] [2.6 (20.66s)]]
- [[[mpfr_class]] [1.3 (6.28s)] [1.2(10.06s)]]
- [[[mpreal]] [2.0 (9.54s)] [1.7 (14.08s)]]
- ]
- [table Non-Central T Distribution Performance
- [[Library][50 Decimal Digits]]
- [[mpfr_float] [1.3 (263.27s)]]
- [[static_mpfr_float] [1.2 (232.88s)]]
- [[mpf_float] [[*1.0] (195.73s)]]
- [[cpp_dec_float] [1.9 (366.38s)]]
- [[[mpfr_class]] [1.5 (286.94s)]]
- [[[mpreal]] [2.0 (388.70s)]]
- ]
- Test code was compiled with Microsoft Visual Studio 2010 with all optimisations
- turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit
- Windows Vista machine.
- [endsect]
- [section:int_real_world Integer Real World Tests]
- The first set of [@../../performance/voronoi_performance.cpp tests] measure the times taken to
- execute the multiprecision part of the Voronoi-diagram builder from Boost.Polygon. The tests
- mainly create a large number of temporaries "just in case" multiprecision arithmetic is required,
- for comparison, also included in the tests is Boost.Polygon's own partial-multiprecision integer
- type which was custom written for this specific task:
- [table
- [[Integer Type][Relative Performance (Actual time in parenthesis)]]
- [[polygon::detail::extended_int][1(0.138831s)]]
- [[int256_t][1.19247(0.165551s)]]
- [[int512_t][1.23301(0.17118s)]]
- [[int1024_t][1.21463(0.168628s)]]
- [[checked_int256_t][1.31711(0.182855s)]]
- [[checked_int512_t][1.57413(0.218538s)]]
- [[checked_int1024_t][1.36992(0.190187s)]]
- [[cpp_int][1.63244(0.226632s)]]
- [[mpz_int][5.42511(0.753172s)]]
- [[tom_int][29.0793(4.03709s)]]
- ]
- Note how for this use case, any dynamic allocation is a performance killer.
- The next [@../../performance/miller_rabin_performance.cpp tests] measure the time taken to generate 1000 128-bit
- random numbers and test for primality using the Miller Rabin test. This is primarily a test of modular-exponentiation
- since that is the rate limiting step:
- [table
- [[Integer Type][Relative Performance (Actual time in parenthesis)]]
- [[cpp_int][5.25827(0.379597s)]]
- [[cpp_int (no Expression templates)][5.15675(0.372268s)]]
- [[cpp_int (128-bit cache)][5.10882(0.368808s)]]
- [[cpp_int (256-bit cache)][5.50623(0.397497s)]]
- [[cpp_int (512-bit cache)][4.82257(0.348144s)]]
- [[cpp_int (1024-bit cache)][5.00053(0.360991s)]]
- [[int1024_t][4.37589(0.315897s)]]
- [[checked_int1024_t][4.52396(0.326587s)]]
- [[mpz_int][1(0.0721905s)]]
- [[mpz_int (no Expression templates)][1.0248(0.0739806s)]]
- [[tom_int][2.60673(0.188181s)]]
- [[tom_int (no Expression templates)][2.64997(0.191303s)]]
- ]
- It's interesting to note that expression templates have little effect here - perhaps because the actual expressions involved
- are relatively trivial in this case - so the time taken for multiplication and division tends to dominate. Also note
- how increasing the internal cache size used by `cpp_int` is quite effective in this case in cutting out memory allocations
- altogether - cutting about a third off the total runtime. Finally the much quicker times from GMP and tommath are down to their
- much better modular-exponentiation algorithms (GMP's is about 5x faster). That's an issue which needs to be addressed
- in a future release for __cpp_int.
- Test code was compiled with Microsoft Visual Studio 2010 with all optimisations
- turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit
- Windows Vista machine.
- [endsect]
- [section:float_performance Float Algorithm Performance]
- Note that these tests are carefully designed to test performance of the underlying algorithms
- and not memory allocation or variable copying. As usual, performance results should be taken
- with a healthy dose of scepticism, and real-world performance may vary widely depending upon the
- specifics of the program. In each table relative times are given first, with the best performer
- given a score of 1. Total actual times are given in brackets, measured in seconds for 500000
- operations.
- [table Operator +
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.0575156s)][[*1] (0.0740086s)][[*1] (0.219073s)]]
- [[gmp_float][2.45065 (0.14095s)][2.01398 (0.149052s)][1.09608 (0.240122s)]]
- [[mpfr_float][2.6001 (0.149546s)][2.12079 (0.156957s)][1.09078 (0.23896s)]]
- ]
- [table Operator +(int)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][1.46115 (0.0855392s)][2.60353 (0.114398s)][3.62562 (0.264905s)]]
- [[gmp_float][[*1] (0.0585424s)][[*1] (0.0439398s)][[*1] (0.0730648s)]]
- [[mpfr_float][2.40441 (0.14076s)][3.2877 (0.144461s)][2.40379 (0.175632s)]]
- ]
- [table Operator +(unsigned long long)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.118146s)][[*1] (0.144714s)][[*1] (0.315639s)]]
- [[gmp_float][4.5555 (0.538213s)][3.83096 (0.554395s)][1.95079 (0.615745s)]]
- [[mpfr_float][5.74477 (0.678719s)][4.85295 (0.702291s)][2.70354 (0.853342s)]]
- ]
- [table Operator +=(unsigned long long)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.101188s)][[*1] (0.122394s)][[*1] (0.251975s)]]
- [[gmp_float][5.199 (0.526079s)][4.39327 (0.537712s)][2.42151 (0.610159s)]]
- [[mpfr_float][6.08318 (0.615547s)][5.18525 (0.634645s)][3.1022 (0.781677s)]]
- ]
- [table Operator -
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.0895163s)][[*1] (0.129248s)][1.5088 (0.374512s)]]
- [[gmp_float][1.72566 (0.154474s)][1.22567 (0.158415s)][[*1] (0.248219s)]]
- [[mpfr_float][1.83764 (0.164499s)][1.34284 (0.173559s)][1.00226 (0.248781s)]]
- ]
- [table Operator -(int)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.105285s)][[*1] (0.142741s)][[*1] (0.278718s)]]
- [[gmp_float][2.34437 (0.246828s)][1.28814 (0.183871s)][1.00731 (0.280754s)]]
- [[mpfr_float][2.8032 (0.295136s)][2.09178 (0.298582s)][1.25213 (0.34899s)]]
- ]
- [table Operator -(unsigned long long)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.13719s)][[*1] (0.184428s)][[*1] (0.344212s)]]
- [[gmp_float][4.0804 (0.559791s)][3.06776 (0.565781s)][2.07736 (0.715053s)]]
- [[mpfr_float][5.10114 (0.699828s)][3.88684 (0.716843s)][2.50074 (0.860784s)]]
- ]
- [table Operator -=(unsigned long long)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.100984s)][[*1] (0.123148s)][[*1] (0.246181s)]]
- [[gmp_float][5.68353 (0.573944s)][4.68636 (0.577116s)][2.6958 (0.663655s)]]
- [[mpfr_float][6.19738 (0.625834s)][5.18544 (0.638577s)][3.18738 (0.784673s)]]
- ]
- [table Operator *
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][1.03667 (0.284251s)][1.30576 (0.536527s)][1.44686 (4.81057s)]]
- [[gmp_float][[*1] (0.274196s)][[*1] (0.410891s)][[*1] (3.32484s)]]
- [[mpfr_float][1.24537 (0.341477s)][1.15785 (0.475749s)][1.1796 (3.92199s)]]
- ]
- [table Operator *(int)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][3.97453 (0.240262s)][9.91222 (0.463473s)][50.7926 (4.36527s)]]
- [[gmp_float][[*1] (0.0604505s)][[*1] (0.0467577s)][[*1] (0.0859431s)]]
- [[mpfr_float][2.56974 (0.155342s)][3.56312 (0.166603s)][3.22964 (0.277565s)]]
- ]
- [table Operator *(unsigned long long)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.331877s)][1.01058 (0.586122s)][6.688 (4.7931s)]]
- [[gmp_float][1.72433 (0.572266s)][[*1] (0.579987s)][[*1] (0.716672s)]]
- [[mpfr_float][2.5553 (0.848047s)][1.74987 (1.0149s)][1.80403 (1.2929s)]]
- ]
- [table Operator *=(unsigned long long)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.321397s)][1.00772 (0.574887s)][6.65946 (4.7468s)]]
- [[gmp_float][1.77419 (0.570218s)][[*1] (0.570482s)][[*1] (0.712791s)]]
- [[mpfr_float][2.62172 (0.842611s)][1.77691 (1.01369s)][1.77511 (1.26528s)]]
- ]
- [table Operator /
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][2.96096 (4.00777s)][4.53244 (7.86435s)][6.11936 (51.5509s)]]
- [[gmp_float][[*1] (1.35354s)][[*1] (1.73512s)][[*1] (8.42422s)]]
- [[mpfr_float][1.30002 (1.75963s)][1.39045 (2.41261s)][1.66762 (14.0484s)]]
- ]
- [table Operator /(int)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][8.60726 (1.8181s)][15.4122 (3.67479s)][34.5119 (24.729s)]]
- [[gmp_float][1.24394 (0.262756s)][[*1] (0.238433s)][[*1] (0.716536s)]]
- [[mpfr_float][[*1] (0.211229s)][1.12178 (0.26747s)][1.02237 (0.732562s)]]
- ]
- [table Operator /(unsigned long long)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][2.10976 (1.97569s)][3.73601 (3.9133s)][11.3085 (25.4533s)]]
- [[gmp_float][[*1] (0.936452s)][[*1] (1.04746s)][[*1] (2.25081s)]]
- [[mpfr_float][1.3423 (1.257s)][1.51575 (1.58768s)][3.31513 (7.46175s)]]
- ]
- [table Operator /=(unsigned long long)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][2.17401 (1.96883s)][3.79591 (3.8965s)][11.2328 (25.2606s)]]
- [[gmp_float][[*1] (0.905621s)][[*1] (1.0265s)][[*1] (2.24882s)]]
- [[mpfr_float][1.37953 (1.24933s)][1.53073 (1.57129s)][3.30546 (7.43339s)]]
- ]
- [table Operator construct
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.00929804s)][[*1] (0.0268321s)][[*1] (0.0310685s)]]
- [[gmp_float][30.8781 (0.287106s)][7.59969 (0.203916s)][6.51873 (0.202527s)]]
- [[mpfr_float][23.5296 (0.218779s)][8.11058 (0.217624s)][7.16325 (0.222552s)]]
- ]
- [table Operator construct(unsigned)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.0603971s)][[*1] (0.0735485s)][[*1] (0.116464s)]]
- [[gmp_float][3.91573 (0.236498s)][2.88171 (0.211945s)][1.81075 (0.210887s)]]
- [[mpfr_float][4.90052 (0.295977s)][4.01118 (0.295017s)][2.62005 (0.305141s)]]
- ]
- [table Operator construct(unsigned long long)
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][[*1] (0.0610288s)][[*1] (0.0759005s)][[*1] (0.118511s)]]
- [[gmp_float][8.26247 (0.504249s)][6.69042 (0.507806s)][4.32819 (0.51294s)]]
- [[mpfr_float][10.1593 (0.620013s)][8.45884 (0.64203s)][5.51472 (0.653557s)]]
- ]
- [table Operator str
- [[Backend][50 Bits][100 Bits][500 Bits]]
- [[cpp_dec_float][2.95848 (0.0223061s)][3.33461 (0.033471s)][3.0159 (0.132732s)]]
- [[gmp_float][[*1] (0.00753971s)][[*1] (0.0100374s)][[*1] (0.0440106s)]]
- [[mpfr_float][1.25424 (0.00945658s)][1.24943 (0.012541s)][1.09428 (0.0481601s)]]
- ]
- Test code was compiled with Microsoft Visual Studio 2010 with all optimisations
- turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit
- Windows Vista machine.
- [endsect]
- [section:integer_performance Integer Algorithm Performance]
- Note that these tests are carefully designed to test performance of the underlying algorithms
- and not memory allocation or variable copying. As usual, performance results should be taken
- with a healthy dose of scepticism, and real-world performance may vary widely depending upon the
- specifics of the program. In each table relative times are given first, with the best performer
- given a score of 1. Total actual times are given in brackets, measured in seconds for 500000
- operations.
- [table Operator +
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.23704 (0.0274266s)][1.09358 (0.0383278s)][1.26645 (0.0558828s)][1.32188 (0.0916899s)]]
- [[cpp_int(fixed)][1.62044 (0.0359271s)][1.5277 (0.053543s)][1.73059 (0.076363s)][1.71537 (0.118983s)]]
- [[gmp_int][1.87515 (0.0415741s)][1.21699 (0.042653s)][1.15599 (0.0510088s)][[*1] (0.0693631s)]]
- [[tommath_int][[*1] (0.0221711s)][[*1] (0.035048s)][[*1] (0.0441255s)][1.04441 (0.0724435s)]]
- ]
- [table Operator +(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][[*1] (0.0155377s)][[*1] (0.0209523s)][[*1] (0.0306377s)][[*1] (0.043125s)]]
- [[cpp_int(fixed)][1.31904 (0.0204948s)][1.76211 (0.0369203s)][1.52941 (0.0468577s)][1.60412 (0.0691778s)]]
- [[gmp_int][1.96204 (0.0304855s)][2.02569 (0.0424428s)][2.11505 (0.0648002s)][2.65993 (0.114709s)]]
- [[tommath_int][14.0654 (0.218543s)][10.8239 (0.226786s)][7.76691 (0.23796s)][6.10039 (0.263079s)]]
- ]
- [table Operator +(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][[*1] (0.026624s)][[*1] (0.0291407s)][[*1] (0.0373209s)][[*1] (0.0464919s)]]
- [[cpp_int(fixed)][1.31378 (0.034978s)][1.54897 (0.045138s)][1.53649 (0.0573431s)][1.27833 (0.0594319s)]]
- [[gmp_int][25.5775 (0.680974s)][24.0117 (0.699717s)][19.5633 (0.730121s)][16.8939 (0.785432s)]]
- [[tommath_int][19.4694 (0.518354s)][18.4246 (0.536907s)][14.7715 (0.551288s)][12.3637 (0.574812s)]]
- ]
- [table Operator +=(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.18405 (0.0196905s)][1.22304 (0.0206476s)][1.25861 (0.0217397s)][1.29525 (0.0220829s)]]
- [[cpp_int(fixed)][[*1] (0.0166298s)][[*1] (0.0168822s)][[*1] (0.0172728s)][[*1] (0.0170492s)]]
- [[gmp_int][39.9082 (0.663668s)][39.4584 (0.666147s)][38.5504 (0.665873s)][39.2231 (0.668722s)]]
- [[tommath_int][30.6219 (0.509238s)][30.4135 (0.513447s)][30.9077 (0.533863s)][32.3086 (0.550835s)]]
- ]
- [table Operator -
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.06986 (0.0296064s)][[*1] (0.0381508s)][1.05932 (0.053186s)][1.1766 (0.0844721s)]]
- [[cpp_int(fixed)][1.3304 (0.0368163s)][1.44506 (0.0551303s)][1.4431 (0.0724545s)][1.57255 (0.112898s)]]
- [[gmp_int][1.48072 (0.0409761s)][1.19003 (0.0454007s)][1.0794 (0.0541942s)][[*1] (0.0717934s)]]
- [[tommath_int][[*1] (0.0276731s)][1.10891 (0.0423057s)][[*1] (0.0502076s)][1.08479 (0.0778811s)]]
- ]
- [table Operator -(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][[*1] (0.0147372s)][[*1] (0.0170001s)][[*1] (0.0232882s)][[*1] (0.0310734s)]]
- [[cpp_int(fixed)][1.4267 (0.0210256s)][1.98887 (0.0338109s)][1.83788 (0.0428009s)][1.81269 (0.0563264s)]]
- [[gmp_int][2.07504 (0.0305803s)][2.40928 (0.0409579s)][2.58711 (0.0602493s)][3.26438 (0.101435s)]]
- [[tommath_int][13.5424 (0.199577s)][12.1793 (0.207048s)][9.28855 (0.216314s)][7.49327 (0.232842s)]]
- ]
- [table Operator -(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][[*1] (0.0277377s)][[*1] (0.0296807s)][[*1] (0.0372392s)][[*1] (0.0455855s)]]
- [[cpp_int(fixed)][1.19867 (0.0332484s)][1.48639 (0.0441169s)][1.43253 (0.0533464s)][1.27697 (0.0582111s)]]
- [[gmp_int][24.1794 (0.670683s)][22.9073 (0.679904s)][18.8758 (0.702922s)][16.5837 (0.755975s)]]
- [[tommath_int][18.149 (0.503413s)][17.4116 (0.516787s)][14.0411 (0.52288s)][11.8237 (0.538987s)]]
- ]
- [table Operator -=(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.26896 (0.0203467s)][1.25722 (0.0206147s)][1.36108 (0.0225485s)][1.18351 (0.0226161s)]]
- [[cpp_int(fixed)][[*1] (0.0160342s)][[*1] (0.0163971s)][[*1] (0.0165667s)][[*1] (0.0191094s)]]
- [[gmp_int][41.1339 (0.659547s)][40.3982 (0.662411s)][39.925 (0.661425s)][34.636 (0.661874s)]]
- [[tommath_int][31.1543 (0.499533s)][31.0303 (0.508806s)][30.7699 (0.509756s)][27.7054 (0.529434s)]]
- ]
- [table Operator *
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.11839 (0.0757577s)][1.61061 (0.207951s)][1.4501 (0.696912s)][1.72796 (2.64108s)]]
- [[cpp_int(fixed)][1.01115 (0.0684934s)][1.28687 (0.166152s)][[*1] (0.480595s)][[*1] (1.52844s)]]
- [[gmp_int][[*1] (0.0677384s)][[*1] (0.129113s)][1.09011 (0.523902s)][1.03374 (1.58s)]]
- [[tommath_int][1.6322 (0.110562s)][2.71751 (0.350866s)][2.05222 (0.986288s)][2.0644 (3.15531s)]]
- ]
- [table Operator *(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.01611 (0.0229536s)][1.12175 (0.0298152s)][1.16413 (0.0416439s)][1.31747 (0.0666043s)]]
- [[cpp_int(fixed)][1.30215 (0.0294152s)][1.669 (0.0443606s)][1.72395 (0.0616701s)][1.88315 (0.095202s)]]
- [[gmp_int][[*1] (0.0225897s)][[*1] (0.0265791s)][[*1] (0.0357725s)][[*1] (0.0505547s)]]
- [[tommath_int][10.8281 (0.244603s)][10.1516 (0.26982s)][8.76424 (0.313519s)][8.04364 (0.406644s)]]
- ]
- [table Operator *(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][[*1] (0.0570721s)][[*1] (0.0856141s)][[*1] (0.143279s)][[*1] (0.252785s)]]
- [[cpp_int(fixed)][1.10857 (0.0632686s)][1.2951 (0.110878s)][1.20827 (0.173121s)][1.18463 (0.299456s)]]
- [[gmp_int][12.0605 (0.68832s)][8.13434 (0.696415s)][5.21762 (0.747577s)][3.11601 (0.787681s)]]
- [[tommath_int][10.0524 (0.57371s)][7.33116 (0.627651s)][4.85202 (0.695193s)][3.35808 (0.848871s)]]
- ]
- [table Operator *=(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][111.27 (7.43118s)][67.7078 (7.34138s)][43.3851 (7.4075s)][25.3089 (7.55455s)]]
- [[cpp_int(fixed)][[*1] (0.0667848s)][[*1] (0.108427s)][[*1] (0.170738s)][[*1] (0.298493s)]]
- [[gmp_int][46.3718 (3.09693s)][28.4639 (3.08626s)][18.1719 (3.10264s)][10.5223 (3.14083s)]]
- [[tommath_int][276.674 (18.4776s)][169.146 (18.34s)][108.491 (18.5236s)][63.3261 (18.9024s)]]
- ]
- [table Operator /
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][2.68035 (0.595251s)][2.04702 (0.707471s)][1.62314 (0.921536s)][1.43112 (1.38811s)]]
- [[cpp_int(fixed)][[*1] (0.222079s)][[*1] (0.34561s)][[*1] (0.567748s)][[*1] (0.969945s)]]
- [[gmp_int][3.79283 (0.842308s)][2.73668 (0.945824s)][1.86649 (1.05969s)][1.32141 (1.2817s)]]
- [[tommath_int][13.2531 (2.94324s)][11.2054 (3.87271s)][9.83293 (5.58262s)][13.0164 (12.6252s)]]
- ]
- [table Operator /(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][4.06026 (0.225473s)][3.45732 (0.340049s)][3.00195 (0.547957s)][2.80587 (0.978029s)]]
- [[cpp_int(fixed)][2.43766 (0.135367s)][2.56264 (0.252052s)][2.44011 (0.445402s)][2.38009 (0.829617s)]]
- [[gmp_int][[*1] (0.0555316s)][[*1] (0.0983563s)][[*1] (0.182534s)][[*1] (0.348566s)]]
- [[tommath_int][35.9988 (1.99907s)][27.1024 (2.66569s)][21.8333 (3.98531s)][25.8066 (8.99528s)]]
- ]
- [table Operator /(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.50505 (0.705756s)][1.39347 (1.58556s)][2.63348 (3.57438s)][4.75451 (8.52733s)]]
- [[cpp_int(fixed)][[*1] (0.468925s)][1.12378 (1.27869s)][2.29966 (3.12128s)][4.4844 (8.04288s)]]
- [[gmp_int][2.17234 (1.01866s)][[*1] (1.13785s)][[*1] (1.35728s)][[*1] (1.79352s)]]
- [[tommath_int][4.74612 (2.22557s)][2.70088 (3.07319s)][3.65634 (4.96268s)][6.79408 (12.1853s)]]
- ]
- [table Operator /=(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.76281 (0.0574966s)][1.76471 (0.0604224s)][1.56085 (0.0716403s)][1.31422 (0.124043s)]]
- [[cpp_int(fixed)][[*1] (0.0326164s)][[*1] (0.0342393s)][[*1] (0.0458981s)][[*1] (0.0943852s)]]
- [[gmp_int][20.2862 (0.661664s)][19.4043 (0.664389s)][14.4881 (0.664976s)][7.14238 (0.674135s)]]
- [[tommath_int][32.9555 (1.07489s)][30.1525 (1.0324s)][22.8324 (1.04796s)][11.7456 (1.10861s)]]
- ]
- [table Operator %
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.8501 (0.364131s)][1.46527 (0.476653s)][1.27509 (0.689738s)][1.20064 (1.11769s)]]
- [[cpp_int(fixed)][[*1] (0.196817s)][[*1] (0.325301s)][[*1] (0.540932s)][[*1] (0.930916s)]]
- [[gmp_int][3.2533 (0.640305s)][2.15441 (0.700832s)][1.47898 (0.800029s)][1.07439 (1.00016s)]]
- [[tommath_int][15.3501 (3.02116s)][12.1106 (3.9396s)][11.0689 (5.98752s)][13.5535 (12.6172s)]]
- ]
- [table Operator %(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.82761 (0.104331s)][2.01496 (0.202512s)][2.10004 (0.389523s)][2.17252 (0.768097s)]]
- [[cpp_int(fixed)][1.78851 (0.102099s)][1.96844 (0.197838s)][2.02956 (0.376451s)][2.07257 (0.73276s)]]
- [[gmp_int][[*1] (0.057086s)][[*1] (0.100505s)][[*1] (0.185483s)][[*1] (0.353552s)]]
- [[tommath_int][36.3018 (2.07233s)][26.3075 (2.64402s)][21.9525 (4.07183s)][25.6759 (9.07775s)]]
- ]
- [table Operator construct
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.40211 (0.0026854s)][[*1] (0.00278639s)][[*1] (0.00322813s)][[*1] (0.0027185s)]]
- [[cpp_int(fixed)][[*1] (0.00191526s)][1.40721 (0.00392103s)][1.90346 (0.00614463s)][2.14621 (0.00583447s)]]
- [[gmp_int][98.705 (0.189046s)][68.9726 (0.192184s)][58.8994 (0.190135s)][70.0525 (0.190438s)]]
- [[tommath_int][105.602 (0.202255s)][74.1994 (0.206748s)][63.6455 (0.205456s)][76.8935 (0.209035s)]]
- ]
- [table Operator construct(unsigned)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.73436 (0.00348927s)][[*1] (0.00263476s)][[*1] (0.0027009s)][[*1] (0.00318651s)]]
- [[cpp_int(fixed)][[*1] (0.00201185s)][1.36851 (0.0036057s)][2.07362 (0.00560064s)][1.66856 (0.00531688s)]]
- [[gmp_int][97.2414 (0.195635s)][76.3759 (0.201232s)][72.7396 (0.196462s)][63.8129 (0.20334s)]]
- [[tommath_int][210.112 (0.422713s)][162.652 (0.42855s)][158.33 (0.427634s)][134.626 (0.428987s)]]
- ]
- [table Operator construct(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][2.34403 (0.00739542s)][1.66376 (0.00713834s)][1.22989 (0.0074969s)][1.23708 (0.00711417s)]]
- [[cpp_int(fixed)][[*1] (0.00315501s)][[*1] (0.00429049s)][[*1] (0.00609561s)][[*1] (0.0057508s)]]
- [[gmp_int][222.866 (0.703144s)][164.331 (0.705059s)][115.363 (0.70321s)][122.347 (0.703596s)]]
- [[tommath_int][218.681 (0.689941s)][163.796 (0.702765s)][114.57 (0.698376s)][122.422 (0.704027s)]]
- ]
- [table Operator gcd
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.16358 (2.74442s)][1.39847 (8.11559s)][1.64677 (22.2518s)][1.95096 (64.4961s)]]
- [[cpp_int(fixed)][[*1] (2.35859s)][1.30986 (7.60133s)][1.67681 (22.6577s)][2.0895 (69.0758s)]]
- [[gmp_int][1.03392 (2.4386s)][[*1] (5.80319s)][[*1] (13.5124s)][[*1] (33.0586s)]]
- [[tommath_int][5.25978 (12.4057s)][4.4619 (25.8932s)][4.15577 (56.1542s)][3.91192 (129.323s)]]
- ]
- [table Operator powm
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][2.50722 (2.91621s)][3.5561 (13.406s)][4.37066 (73.483s)][4.88831 (473.91s)]]
- [[cpp_int(fixed)][1.93385 (2.24931s)][3.18107 (11.9922s)][4.20753 (70.7403s)][4.8158 (466.88s)]]
- [[gmp_int][[*1] (1.16313s)][[*1] (3.76986s)][[*1] (16.8128s)][[*1] (96.9476s)]]
- [[tommath_int][1.44081 (1.67584s)][1.8794 (7.08507s)][2.19115 (36.8394s)][2.17186 (210.557s)]]
- ]
- [table Operator str
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.17175 (0.00160006s)][1.41999 (0.00329476s)][1.40856 (0.00813784s)][1.52964 (0.0229767s)]]
- [[cpp_int(fixed)][[*1] (0.00136554s)][[*1] (0.00232027s)][[*1] (0.00577741s)][1.14754 (0.0172372s)]]
- [[gmp_int][1.50501 (0.00205515s)][1.52968 (0.00354926s)][1.01989 (0.0058923s)][[*1] (0.015021s)]]
- [[tommath_int][12.2161 (0.0166816s)][16.9577 (0.0393463s)][18.7474 (0.108311s)][22.7368 (0.341528s)]]
- ]
- [table Operator |
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][[*1] (0.0301617s)][[*1] (0.0423404s)][[*1] (0.0522358s)][[*1] (0.0813156s)]]
- [[cpp_int(fixed)][1.0638 (0.0320861s)][1.22566 (0.0518951s)][1.28515 (0.0671305s)][1.16118 (0.094422s)]]
- [[gmp_int][1.76553 (0.0532514s)][1.51489 (0.0641408s)][1.70708 (0.0891706s)][1.77346 (0.14421s)]]
- [[tommath_int][4.37637 (0.131999s)][3.46212 (0.146587s)][2.91875 (0.152463s)][4.19621 (0.341217s)]]
- ]
- [table Operator |(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][[*1] (0.0289129s)][[*1] (0.0351119s)][[*1] (0.0406779s)][[*1] (0.0525891s)]]
- [[cpp_int(fixed)][1.06091 (0.030674s)][1.25979 (0.0442336s)][1.36194 (0.0554009s)][1.37438 (0.0722772s)]]
- [[gmp_int][4.92854 (0.142498s)][4.34687 (0.152627s)][3.71442 (0.151095s)][2.981 (0.156768s)]]
- [[tommath_int][10.9847 (0.317598s)][9.37065 (0.329021s)][8.53651 (0.347248s)][11.2155 (0.589813s)]]
- ]
- [table Operator ^
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][[*1] (0.0305149s)][[*1] (0.04217s)][[*1] (0.0525977s)][[*1] (0.0816632s)]]
- [[cpp_int(fixed)][1.01544 (0.0309861s)][1.24872 (0.0526585s)][1.26661 (0.066621s)][1.15965 (0.0947007s)]]
- [[gmp_int][1.64675 (0.0502505s)][1.47181 (0.0620663s)][1.66038 (0.0873322s)][1.67895 (0.137108s)]]
- [[tommath_int][4.30668 (0.131418s)][3.45859 (0.145849s)][2.91462 (0.153303s)][4.15538 (0.339342s)]]
- ]
- [table Operator ^(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.01566 (0.0296088s)][[*1] (0.0356634s)][[*1] (0.0401898s)][[*1] (0.0514097s)]]
- [[cpp_int(fixed)][[*1] (0.0291524s)][1.2393 (0.0441976s)][1.38556 (0.0556856s)][1.38899 (0.0714075s)]]
- [[gmp_int][4.68027 (0.136441s)][4.15243 (0.14809s)][3.74237 (0.150405s)][3.0483 (0.156712s)]]
- [[tommath_int][10.919 (0.318314s)][9.16311 (0.326788s)][8.62554 (0.346659s)][11.6212 (0.597442s)]]
- ]
- [table Operator &
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.0346 (0.0303431s)][[*1] (0.0427309s)][[*1] (0.0535587s)][1.06945 (0.0828084s)]]
- [[cpp_int(fixed)][[*1] (0.0293284s)][1.10435 (0.04719s)][1.05262 (0.0563769s)][[*1] (0.0774309s)]]
- [[gmp_int][1.86057 (0.0545675s)][1.58432 (0.0676995s)][1.69164 (0.0906018s)][1.86625 (0.144505s)]]
- [[tommath_int][4.4157 (0.129506s)][3.60396 (0.154s)][2.95985 (0.158525s)][4.4032 (0.340944s)]]
- ]
- [table Operator &(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][1.05874 (0.038946s)][[*1] (0.0483903s)][[*1] (0.063842s)][[*1] (0.100361s)]]
- [[cpp_int(fixed)][[*1] (0.0367853s)][1.05827 (0.0512099s)][1.09114 (0.0696605s)][1.09432 (0.109826s)]]
- [[gmp_int][3.92298 (0.144308s)][2.99447 (0.144903s)][2.228 (0.14224s)][1.42296 (0.142809s)]]
- [[tommath_int][8.79208 (0.323419s)][7.02288 (0.339839s)][5.65271 (0.36088s)][6.27104 (0.629365s)]]
- ]
- [table Operator <<
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][[*1] (0.0248801s)][1.23196 (0.04s)][[*1] (0.0424149s)][[*1] (0.060157s)]]
- [[cpp_int(fixed)][1.08931 (0.027102s)][1.40572 (0.0456418s)][1.3475 (0.0571542s)][1.24573 (0.0749397s)]]
- [[gmp_int][1.05561 (0.0262636s)][[*1] (0.0324686s)][1.09914 (0.0466199s)][1.16315 (0.0699719s)]]
- [[tommath_int][1.60497 (0.0399319s)][2.13048 (0.0691737s)][2.31219 (0.0980712s)][2.74695 (0.165248s)]]
- ]
- [table Operator >>
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_int][[*1] (0.0213349s)][1.02127 (0.0295019s)][[*1] (0.0327116s)][1.13168 (0.0433804s)]]
- [[cpp_int(fixed)][1.13514 (0.0242181s)][1.16938 (0.0337803s)][1.46999 (0.0480859s)][1.60077 (0.061362s)]]
- [[gmp_int][1.26614 (0.0270129s)][[*1] (0.0288873s)][1.42219 (0.0465221s)][[*1] (0.0383329s)]]
- [[tommath_int][12.0066 (0.25616s)][10.2837 (0.297067s)][9.99696 (0.327017s)][16.0943 (0.616942s)]]
- ]
- Test code was compiled with Microsoft Visual Studio 2010 with all optimisations
- turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit
- Windows Vista machine.
- Linux x86_64 results are broadly similar, except that libtommath performs much better there.
- [endsect]
- [section:rational_performance Rational Type Performance]
- Note that these tests are carefully designed to test performance of the underlying algorithms
- and not memory allocation or variable copying. As usual, performance results should be taken
- with a healthy dose of scepticism, and real-world performance may vary widely depending upon the
- specifics of the program. In each table relative times are given first, with the best performer
- given a score of 1. Total actual times are given in brackets, measured in seconds for 500000
- operations.
- [table Operator +
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][5.89417 (18.4116s)][6.87256 (47.4698s)][6.65008 (107.715s)][6.53801 (256.244s)]]
- [[mpq_rational][[*1] (3.1237s)][[*1] (6.90715s)][[*1] (16.1975s)][[*1] (39.1929s)]]
- ]
- [table Operator +(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][3.62367 (2.46488s)][4.18291 (2.94603s)][4.726 (3.74866s)][6.1388 (5.56817s)]]
- [[mpq_rational][[*1] (0.680215s)][[*1] (0.704303s)][[*1] (0.7932s)][[*1] (0.907046s)]]
- ]
- [table Operator +(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][1.1527 (2.6378s)][1.31751 (3.09863s)][1.58996 (4.00714s)][2.15642 (5.75702s)]]
- [[mpq_rational][[*1] (2.28837s)][[*1] (2.35189s)][[*1] (2.52028s)][[*1] (2.66971s)]]
- ]
- [table Operator +=(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][1.18436 (2.7059s)][1.32279 (3.11099s)][1.61398 (4.05389s)][2.20048 (5.84623s)]]
- [[mpq_rational][[*1] (2.2847s)][[*1] (2.35183s)][[*1] (2.51174s)][[*1] (2.6568s)]]
- ]
- [table Operator -
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][5.81893 (18.3457s)][6.82209 (47.1928s)][6.64143 (107.498s)][6.51362 (255.137s)]]
- [[mpq_rational][[*1] (3.15277s)][[*1] (6.91765s)][[*1] (16.1859s)][[*1] (39.1698s)]]
- ]
- [table Operator -(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][3.72441 (2.48756s)][4.27663 (2.98713s)][4.62109 (3.72114s)][6.17605 (5.56503s)]]
- [[mpq_rational][[*1] (0.667908s)][[*1] (0.698479s)][[*1] (0.805252s)][[*1] (0.901066s)]]
- ]
- [table Operator -(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][1.15627 (2.63239s)][1.32096 (3.12092s)][1.61044 (4.00106s)][2.19378 (5.7644s)]]
- [[mpq_rational][[*1] (2.27663s)][[*1] (2.36262s)][[*1] (2.48445s)][[*1] (2.62761s)]]
- ]
- [table Operator -=(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][1.1984 (2.73444s)][1.34141 (3.15698s)][1.64159 (4.06997s)][2.23017 (5.88108s)]]
- [[mpq_rational][[*1] (2.28174s)][[*1] (2.35348s)][[*1] (2.47929s)][[*1] (2.63706s)]]
- ]
- [table Operator *
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][5.4306 (32.5882s)][6.91805 (89.9436s)][6.94556 (207.307s)][6.88704 (492.151s)]]
- [[mpq_rational][[*1] (6.00084s)][[*1] (13.0013s)][[*1] (29.8475s)][[*1] (71.4604s)]]
- ]
- [table Operator *(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][2.12892 (2.51376s)][2.47245 (3.07841s)][2.86832 (3.93619s)][3.94086 (6.02565s)]]
- [[mpq_rational][[*1] (1.18077s)][[*1] (1.24508s)][[*1] (1.3723s)][[*1] (1.52902s)]]
- ]
- [table Operator *(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][1.32254 (5.43565s)][1.56078 (6.73163s)][1.97701 (9.32522s)][2.85404 (15.1573s)]]
- [[mpq_rational][[*1] (4.11002s)][[*1] (4.313s)][[*1] (4.71682s)][[*1] (5.31082s)]]
- ]
- [table Operator *=(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][6.29806 (58.1188s)][6.30556 (59.5076s)][6.3385 (62.1007s)][6.55345 (67.6905s)]]
- [[mpq_rational][[*1] (9.22804s)][[*1] (9.43733s)][[*1] (9.79739s)][[*1] (10.329s)]]
- ]
- [table Operator /
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][4.4269 (66.8031s)][6.40103 (173.527s)][6.32347 (348.193s)][6.61148 (824.063s)]]
- [[mpq_rational][[*1] (15.0903s)][[*1] (27.1093s)][[*1] (55.0637s)][[*1] (124.641s)]]
- ]
- [table Operator /(int)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][1.78772 (2.50984s)][2.10623 (3.10606s)][2.46986 (3.99358s)][3.37428 (5.96678s)]]
- [[mpq_rational][[*1] (1.40393s)][[*1] (1.4747s)][[*1] (1.61693s)][[*1] (1.76831s)]]
- ]
- [table Operator /(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][1.29695 (5.45454s)][1.55248 (6.85353s)][1.93237 (9.28765s)][2.75211 (14.8541s)]]
- [[mpq_rational][[*1] (4.20568s)][[*1] (4.41458s)][[*1] (4.80635s)][[*1] (5.39734s)]]
- ]
- [table Operator /=(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][6.19401 (58.4278s)][6.20135 (59.643s)][6.21327 (62.0338s)][6.40576 (67.6778s)]]
- [[mpq_rational][[*1] (9.43295s)][[*1] (9.61774s)][[*1] (9.98407s)][[*1] (10.5652s)]]
- ]
- [table Operator construct
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][[*1] (0.00978288s)][[*1] (0.0100574s)][[*1] (0.0101393s)][[*1] (0.0101847s)]]
- [[mpq_rational][39.1516 (0.383015s)][38.3523 (0.385725s)][37.5812 (0.381048s)][37.6007 (0.382953s)]]
- ]
- [table Operator construct(unsigned)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][[*1] (0.0548151s)][[*1] (0.0557542s)][[*1] (0.055825s)][[*1] (0.0552808s)]]
- [[mpq_rational][7.21073 (0.395257s)][7.1016 (0.395944s)][7.02046 (0.391917s)][7.16881 (0.396297s)]]
- ]
- [table Operator construct(unsigned long long)
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][[*1] (0.0605156s)][[*1] (0.0616657s)][[*1] (0.0592056s)][[*1] (0.0603081s)]]
- [[mpq_rational][35.1604 (2.12775s)][34.7575 (2.14335s)][35.7232 (2.11502s)][35.0437 (2.11342s)]]
- ]
- [table Operator str
- [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]]
- [[cpp_rational][5.48898 (0.0208949s)][8.49668 (0.0546688s)][10.107 (0.121897s)][10.5339 (0.310584s)]]
- [[mpq_rational][[*1] (0.0038067s)][[*1] (0.00643413s)][[*1] (0.0120606s)][[*1] (0.0294843s)]]
- ]
- Test code was compiled with Microsoft Visual Studio 2010 with all optimisations
- turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit
- Windows Vista machine.
- [endsect]
- [endsect]
- [section:map Roadmap]
- * Support for atomic loads and stores is not currently supported, but will become more important as a larger number of floating point algorithms become parallelized.
- [section:hist History]
- [h4 Multiprecision-3.2.3 (Boost-1.72)]
- * Big `constexpr` update allows __cpp_int and __float128 arithmetic to be fully `constexpr` with gcc and clang 9 or later,
- or any compiler supporting `std::is_constant_evaluated()`.
- [h4 Multiprecision-3.1.3 (Boost-1.71)]
- * Support hexfloat io-formatting for float128.
- * Fix various bugs in variable precision interconversions.
- * Respect uppercase for '0x' prefix outputs.
- * Incorporate some unit tests from the Etherium project.
- * Fix some gcc warnings.
- [h4 Multiprecision-3.1.2 (Boost-1.70)]
- * Fix various conversion issues in the traits classes, check for compatibility with Boost.Optional.
- * Prevent instantiation of `std::numeric_limits` on any old type when checking for convertibility. See [@https://github.com/boostorg/multiprecision/issues/98 #98].
- * Update variable precision code to accound for arbitrary precision integers. See [@https://github.com/boostorg/multiprecision/issues/103 #103].
- * Add support for XML serialization archives.
- * Fix bug in fixed precision iostream formatting in `mpf_float` and `mpfr_float`. See [@https://github.com/boostorg/multiprecision/issues/113 #113].
- * Add more overloads for special functions which are better handled natively by MPFR.
- * Fixed bug in generic `exp` implementation which could cause invariant failure.
- * Fixed generic conversion from float to integer to avoid undefined behaviour. See [@https://github.com/boostorg/multiprecision/issues/110 #110].
- [h4 Multiprecision-3.1.1 (Boost-1.69)]
- * Big update to better support variable precision types so that the precision of the result
- is always the largest of all the arguments.
- * Add support for allocators that are `final` in __cpp_int.
- * Removed use of deprecated Boost.Endian in favour of Predef.
- * Add support for `std::string_view`.
- * Fixed minor bug in constant initialization. See [@https://github.com/boostorg/multiprecision/issues/67 #67].
- * Make assignment of non-finite value to `cpp_int` a runtime errors. See [@https://github.com/boostorg/multiprecision/issues/58 #58].
- * Added typedefs for `cpp_bin_float_oct` and `cpp_complex_oct`.
- [h4 Multiprecision-3.1.0 (Boost-1.68)]
- * Support added for complex multiprecision numbers.
- * Changed conversion to unsigned integer types to be truncating to match standard defined behaviour.
- * Correct bug in MPFR string formatting.
- * Fix undefined behaviour in cpp_dec_float conversion from long long.
- * Add support for Eigen interoperability.
- * float128.hpp: Fix Intel on Windows build.
- * Fix type used in temporaries when expanding expression templates containing mixed expressions.
- * Fix infinite loop in gmp_float to fixed-point string conversion.
- * Update the expression templates to issue static_asserts with better error messages when you try and do something unsupported.
- * Fix bug in cpp_int where incrementing to zero doesn't set the sign correctly.
- * Remove erroneous use of std::move, and rely on NVRO instead.
- * Fix up support for changes to MPIR-3.0.
- * Fix various conversion errors in cpp_bin_float when the exponent type is a `long long`, or else we're converting to
- an integer that is wider than we are.
- * Fix compatibility issue with GCC-8 caused by the introduction of `std::byte`.
- [h4 Multiprecision-3.0.0 (Boost-1.67)]
- * [*Breaking Change:] When converting a multiprecision integer to a narrower type, if the value is too large (or negative) to
- fit in the smaller type, then the result is either the maximum (or minimum) value of the target type. This was always the intended
- behaviour, but was somewhat haphazardly enforced before. If you really do want just the low order N bits of a value, then you will
- need to mask these out prior to the case, for example: `static_cast<unsigned>(~static_cast<unsigned>(0) & my_value)`. Note that
- technically (to avoid undefined behaviour) you should do the same thing with built in integer types too.
- See [@https://svn.boost.org/trac/boost/ticket/13109 #13109].
- * Fix bug in conversion of decimal to rational types (zero needs special handling), see [@https://svn.boost.org/trac/boost/ticket/13148 #13148].
- * Fix conversion from cpp_bin_float to a wider built in integer type, see [@https://svn.boost.org/trac/boost/ticket/13301 #13301].
- * Improve performance heurists used in cpp_bin_float exp function.
- * Fix bug in floor/ceil and cpp_bin_float when the exponent type is wider than an int, see [@https://svn.boost.org/trac/boost/ticket/13264 #13264].
- * Disable explicit conversion operator when the target type is already constructible from this type, see [@https://github.com/boostorg/multiprecision/issues/30 #30].
- * Fix support for changes new to MPIR-3.0, see [@https://svn.boost.org/trac/boost/ticket/13124 #13124].
- [h4 Multiprecision-2.3.2 (Boost-1.65)]
- * Updated expression templates to store arithmetic literals directly in the expression template to prevent dangling references, see [@https://github.com/boostorg/multiprecision/issues/19 #19].
- * Fix various issues with huge values and overflow in the trig, pow and exp functions, see [@https://github.com/boostorg/multiprecision/issues/24 #24].
- * Fix error handling of checked cpp_int multiply that could cause some overflows to be missed.
- [h4 Multiprecision-2.3.1 (Boost-1.64)]
- * In `cpp_bin_float` prevent double rounding when converting to a denormalized float. See [@https://svn.boost.org/trac/boost/ticket/12527 #12527].
- * Fix bug in integer sqrt for very small integers. See [@https://svn.boost.org/trac/boost/ticket/12559 #12559].
- * Fix conversion to signed-zero in `cpp_bin_float`.
- * Change `cpp_bin_float` rounding code to round at arbitrary location so we can use it for conversions, see [@https://svn.boost.org/trac/boost/ticket/12527 #12527].
- * Improve performance of 128-bit bit-scan operations.
- * Fix subtraction of very small quantities in `cpp_bin_float`. See: [@https://svn.boost.org/trac/boost/ticket/12580 #12580].
- * Bring error handling into line with C99 Annex F. See [@https://svn.boost.org/trac/boost/ticket/12581 #12581].
- * Fix bitwise export of trivial `cpp_int`'s, see [@https://svn.boost.org/trac/boost/ticket/12627 #12627].
- * Fix `ilogb` (and code that uses it) to consistently return the smallest value of the exponent type when the argument is zero, see [@https://svn.boost.org/trac/boost/ticket/12625 #12625].
- * Allow conversion from `__float128` to `cpp_bin_float`.
- * Fix bug in left shift of `cpp_int` which would result in bit-loss, see [@https://svn.boost.org/trac/boost/ticket/12790 #12790].
- * Fixed bugs in bounded but variable precision `cpp_int`'s caused by over-aggressive constexpr optimization, see [@https://svn.boost.org/trac/boost/ticket/12798 #12798].
- [h4 Multiprecision-2.3.0 (Boost-1.63)]
- * Added support for all the C99 math functions.
- * Extended generic-interconversions to handle narrowing cases as well, changed convert_to member function and hence explicit
- conversion operators to use the same conversion code as the explicit constructors.
- * Fix IO stream parsing error, see [@https://svn.boost.org/trac/boost/ticket/12488 #12488].
- * Make default constructed floating point types all zero for consistency, see [@https://svn.boost.org/trac/boost/ticket/12500 #12500].
- * Fix conversion of cpp_bin_float to float/double/long double when the exponent value would overflow an int, see [@https://svn.boost.org/trac/boost/ticket/12512 #12512].
- * Fix cpp_bin_float subtractions that yield signed-zeros, see [@https://svn.boost.org/trac/boost/ticket/12524 #12524].
- * Fix ceil/trunc/round applied to cpp_bin_float and yielding a signed zero, see [@https://svn.boost.org/trac/boost/ticket/12525 #12525].
- [h4 Multiprecision-2.2.8 (Boost-1.62)]
- * Added support for hashing via `Boost.Hash` or `std::hash`.
- * Fixed some arithmetic operations in cpp_bin_float and cpp_dec_float that should generate a NaN, see [@https://svn.boost.org/trac/boost/ticket/12157 #12157].
- * Prevent inadvertant instantiation of variable-precision `mpfr_float_backend` with fixed allocation.
- * Fixed division over/underflow in cpp_bin_float, see [@https://svn.boost.org/trac/boost/ticket/12167 #12167].
- * Added support for signed-zeros throughout the library, including support for `signbit` and `copysign`, mpfr, float128, and cpp_bin_float types
- should now respect signed-zeros correctly.
- * Fixed bug in conversion of cpp_bin_float infinities to double etc, see [@https://svn.boost.org/trac/boost/ticket/12196 #12196].
- * Fix add and subtract of cpp_bin_float when the exponents would overflow., see [@https://svn.boost.org/trac/boost/ticket/12198 #12198].
- * Improve variable-precision support in mpfr and mpf backends, allow these types to be used with Boost.Math.
- * Fixed bug in subtraction of signed infinities in cpp_bin_float, see [@https://svn.boost.org/trac/boost/ticket/12209 #12209].
- * Fix result of sqrt(infinity) in cpp_bin_float (result should be infinity), see [@https://svn.boost.org/trac/boost/ticket/12227 #12227].
- * Added workaround in gmp.hpp for recent MPIR releases which are not quite source-compatible with GMP on Windows x64.
- * Allow `cpp_int` code to be used with /RTCc with MSVC.
- * Fix conversion of `cpp_int` to signed integer when the result is INT_MIN, see [@https://svn.boost.org/trac/boost/ticket/12343 #12343].
- * Update uBlas support to match latest uBlas code.
- * Fix some errors present when building on big-endian machines (not all `cpp_int` constructors are available on non-little-endian machines).
- * Fix fencepost error in rational to float conversion routines, see [@https://svn.boost.org/trac/boost/ticket/12327 #12327].
- * Fix some Oracle C++ compiler compatibility issues.
- * Add modf support to complete C90 compatibility.
- * Fix self assignment bug in expression template code for expressions such as `a = a * a * a`, see [@https://svn.boost.org/trac/boost/ticket/12408 #12408].
- * Fixed some compiler errors that occur when converting from `cpp_int` to `cpp_bin_float`.
- [h4 Multiprecision-2.2.7 (Boost-1.61)]
- * Fixed bug in stream input for integer types, see [@https://svn.boost.org/trac/boost/ticket/11857 #11857].
- * Fixed some ambiguous conversions involving expression templates see [@https://svn.boost.org/trac/boost/ticket/11922 #11922].
- * Add expression template aware min/max overloads see [@https://svn.boost.org/trac/boost/ticket/11149 #11149].
- * Fix bug in right shifting negative small integers in cpp_int see [@https://svn.boost.org/trac/boost/ticket/11999 #11999].
- * Use memmove for bitshifts in cpp_int when possible see [@https://svn.boost.org/trac/boost/ticket/9233 #9233].
- * Use memcpy for data import into cpp_int where possible, see [@https://svn.boost.org/trac/boost/ticket/9235 #9235].
- * Changed `cpp_bin_float.convert_to<double>()` to a function template rather than proceding via `long double` to avoid
- double-rounding bug, see [@https://svn.boost.org/trac/boost/ticket/12039 #12039].
- * Fixed conversions from NaN's and Infinities, see [@https://svn.boost.org/trac/boost/ticket/12112 #12112].
- * Enabled better support for Clang on Windows.
- * Fixed handling of NaN's and Infinities in basic arithmetic for cpp_dec_float and cpp_bin_float, see [@https://svn.boost.org/trac/boost/ticket/12090 #12090].
- * Fixed fencepost error in cpp_bin_float subtraction.
- * Fixed double-rounding in conversion to float routines for cpp_bin_float, see [@https://svn.boost.org/trac/boost/ticket/12039 #12039].
- * Make float128 denorm aware, see [@https://svn.boost.org/trac/boost/ticket/12075 #12075].
- * Allow the library and tests to be used without exception handling support, see [@https://svn.boost.org/trac/boost/ticket/12070 #12070].
- * Fixed buggy comparison operator overloads for boost::rational.
- * Added some workarounds for Oracle C++.
- * Fixed some missing typecasts for cases where cpp_int's limb_type is wider than unsigned.
- [h4 Multiprecision-2.2.6 (Boost-1.60)]
- * Fixed result of Miller Rabin primality test for value 2, see [@https://svn.boost.org/trac/boost/ticket/11495 #11495].
- * Improved initialization of cpp_int from very large strings of hex or octal digits, see [@https://svn.boost.org/trac/boost/ticket/11590 #11590].
- * Fixed fmod behaviour for negative divisors, see [@https://svn.boost.org/trac/boost/ticket/11641 #11641].
- * Fixed infinite division loop in cpp_int special case, see [@https://svn.boost.org/trac/boost/ticket/11648 #11648].
- * Patched missing return statement in [@https://svn.boost.org/trac/boost/ticket/11762 #11762].
- * Fixed mixed mode arithmetic compiler error in [@https://svn.boost.org/trac/boost/ticket/11764 #11764].
- * Fixed over-aggressive use of noexcept in [@https://svn.boost.org/trac/boost/ticket/11826 #11826].
- [h4 Multiprecision-2.2.5 (Boost-1.59)]
- * Depricated boost/multiprecision/random.hpp as it's no longer needed, updated random examples to match.
- * Fixed a bug in cpp_int's right shift operator when shifting negative values - semantics now gives the
- same values as shifting 2's compliment integers, though not the same bit pattern.
- * Fixed support for GCC-4.6.4 in C++0x mode by disabling conditional noexcept suppoprt for that compiler
- see [@https://svn.boost.org/trac/boost/ticket/11402 #11402].
- * Suppressed numerous compiler warnings.
- [h4 Multiprecision-2.2.4 (Boost-1.58)]
- * Changed `frexp` to always be non-expression template generating, see: [@https://svn.boost.org/trac/boost/ticket/10993 10993].
- * Improved support of cpp_dec_float on Cygwin and other platforms with missing long double support, see [@https://svn.boost.org/trac/boost/ticket/10924 10924].
- * Improved noexcept support and added some more tests, see [@https://svn.boost.org/trac/boost/ticket/10990 10990].
- * Various workarounds applied for Intel-15.0 and Solaris-12.4 compilers.
- [h4 Multiprecision-2.2.3 (Boost-1.57)]
- * Changed rational to float conversions to exactly round to nearest, see [@https://svn.boost.org/trac/boost/ticket/10085 10085].
- * Added improved generic float to rational conversions.
- * Fixed rare bug in exponent function for __cpp_bin_float.
- * Fixed various minor documentation issues.
- [h4 Multiprecision-2.2.2 (Boost-1.56)]
- * Change floating-point to rational conversions to be implicit, see [@https://svn.boost.org/trac/boost/ticket/10082 10082].
- * Fix definition of checked_cpp_rational typedef.
- [h4 Multiprecision-2.2.1]
- * Fix bug in assignment from string in cpp_int, see [@https://svn.boost.org/trac/boost/ticket/9936 9936].
- [h4 Multiprecision-2.2.0]
- * Moved to Boost.Multiprecision specific version number - we have one breaking change in Boost-1.54
- which makes this major version 2, plus two releases with new features since then.
- * Added new __cpp_bin_float backend for binary floating-point.
- * Added MSVC-specific #include for compiler intrinsics, see [@https://svn.boost.org/trac/boost/ticket/9336 9336].
- * Fixed various typos in docs, see [@https://svn.boost.org/trac/boost/ticket/9432 9432].
- * Fixed __gmp_rational to allow move-copy from an already copied-from object, see [@https://svn.boost.org/trac/boost/ticket/9497 9497].
- * Added list of values for numeric_limits.
- [h4 Boost-1.55]
- * Added support for Boost.Serialization.
- * Suppressed some GCC warnings. See [@https://svn.boost.org/trac/boost/ticket/8872 8872].
- * Fixed bug in pow for large integer arguments. See [@https://svn.boost.org/trac/boost/ticket/8809 8809].
- * Fixed bug in pow for calculation of 0[super N]. See [@https://svn.boost.org/trac/boost/ticket/8798 8798].
- * Fixed bug in fixed precision cpp_int IO code that causes conversion to string to fail when the
- bit count is very small (less than CHAR_BIT). See [@https://svn.boost.org/trac/boost/ticket/8745 8745].
- * Fixed bug in cpp_int that causes left shift to fail when a fixed precision type would overflow.
- See [@https://svn.boost.org/trac/boost/ticket/8741 8741].
- * Fixed some cosmetic warnings from cpp_int. See [@https://svn.boost.org/trac/boost/ticket/8748 8748].
- * Fixed calls to functions which are required to be macros in C99. See [@https://svn.boost.org/trac/boost/ticket/8732 8732].
- * Fixed bug that causes construction from INT_MIN, LONG_MIN etc to fail in cpp_int. See [@https://svn.boost.org/trac/boost/ticket/8711 8711].
- [h4 1.54]
- * [*Breaking change] renamed `rational_adapter` to `rational_adaptor`.
- * Add support for [mpfi].
- * Add logged_adaptor.
- * Add support for 128-bit floats via GCC's `__float128` or Intel's `_Quad` data types.
- * Add support for user-defined literals in cpp_int, improve `constexpr` support.
- * Fixed bug in integer division of `cpp_int` that results in incorrect sign of `cpp_int` when both arguments are small enough
- to fit in a `double_limb_type`. See [@https://svn.boost.org/trac/boost/ticket/8126 8126].
- * Fixed bug in subtraction of a single limb in `cpp_int` that results in incorrect value when the result should have a 0
- in the last limb: [@https://svn.boost.org/trac/boost/ticket/8133 8133].
- * Fixed bug in `cpp_int` where division of 0 by something doesn't get zero in the result: [@https://svn.boost.org/trac/boost/ticket/8160 8160].
- * Fixed bug in some transcendental functions that caused incorrect return values when variables are reused, for example with
- `a = pow(a, b)`. See [@https://svn.boost.org/trac/boost/ticket/8326 8326].
- * Fixed some assignment operations in the mpfr and gmp backends to be safe if the target has been moved from: [@https://svn.boost.org/trac/boost/ticket/8326 8667].
- * Fixed bug in `cpp_int` that gives incorrect answer for 0%N for large N: [@https://svn.boost.org/trac/boost/ticket/8670 8670].
- * Fixed set_precision in mpfr backend so it doesn't trample over an existing value: [@https://svn.boost.org/trac/boost/ticket/8692 8692].
- [h4 1.53]
- * First Release.
- * Fix bug in [@https://svn.boost.org/trac/boost/ticket/7878 cpp_int division].
- * Fix issue [@https://svn.boost.org/trac/boost/ticket/7806 #7806].
- [h4 Post review changes]
- * Non-expression template operators further optimised with rvalue reference support.
- * Many functions made `constexp`.
- * Differentiate between explicit and implicit conversions in the number constructor.
- * Removed "mp_" prefix from types.
- * Allowed mixed precision arithmetic.
- * Changed ExpressionTemplates parameter to class `number` to use enumerated values rather than true/false.
- * Changed ExpressionTemplate parameter default value to use a traits class so that the default value depends on the backend used.
- * Added support for fused-multiply-add/subtract with GMP support.
- * Tweaked expression template unpacking to use fewer temporaries when the LHS also appears in the RHS.
- * Refactored `cpp_int_backend` based on review comments with new template parameter structure.
- * Added additional template parameter to `mpfr_float_backend` to allow stack-based allocation.
- * Added section on mixed precision arithmetic, and added support for operations yielding a higher precision result
- than either of the arguments.
- * Added overloads of integer-specific functions for built in integer types.
- [h4 Pre-review history]
- *2011-2012, John Maddock adds an expression template enabled front end to Christopher's code,
- and adds support for other backends.
- * 2011, Christopher Kormanyos publishes the decimal floating-point code under the Boost
- Software Licence. The code is published as: [@http://doi.acm.org/10.1145/1916461.1916469
- "Algorithm 910: A Portable C++ Multiple-Precision
- System for Special-Function Calculations"], in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM,
- 2011.
- * 2002-2011, Christopher Kormanyos develops the all C++ decimal arithmetic floating-point
- code.
- [endsect]
- [section:todo TODO]
- More a list of what ['could] be done, rather than what ['should] be done (which may be a much smaller list!).
- * Add back-end support for libdecNumber.
- * Add an adaptor back-end for complex number types.
- * Add better multiplication routines (Karatsuba, FFT etc) to cpp_int_backend.
- * Add assembly level routines to cpp_int_backend.
- * Can ring types (exact floating-point types) be supported? The answer should be yes, but someone needs to write it,
- the hard part is IO and binary-decimal conversion.
- * Should there be a choice of rounding mode (probably MPFR specific)?
- * We can reuse temporaries in multiple subtrees (temporary caching).
- * cpp_dec_float should round to nearest.
- * A 2's complement fixed precision int that uses exactly N bits and no more.
- Things requested in review:
- * The performances of mp_number<a_trivial_adaptor<float>, false>respect to
- float and mp_number<a_trivial_adaptor<int>, false> and int should be
- given to show the cost of using the generic interface (Mostly done, just need to update docs to the latest results).
- * Should we provide min/max overloads for expression templates? (Not done - we can't overload functions declared in the std namespace :-( ).
- * The rounding applied when converting must be documented (Done).
- * Document why we don't abstract out addition/multiplication algorithms etc. (done - FAQ)
- * Document why we don't use proto (compile times) (Done).
- * We can reuse temporaries in multiple subtrees (temporary caching) Moved to TODO list.
- * Emphasise in the docs that ET's may reorder operations (done 2012/10/31).
- * Document what happens to small fixed precision cpp_int's (done 2012/10/31).
- * The use of bool in template parameters could be improved by the use of
- an enum class which will be more explicit. E.g `enum class expression_template {disabled, enabled};
- enum class sign {unsigned, signed};` (Partly done 2012/09/15, done 2012/10/31).
- * Each back-end should document the requirements it satisfies (not currently scheduled for inclusion: it's
- deliberately an implementation detail, and "optional" requirements are optimisations which can't be detected
- by the user). Not done: this is an implementation detail, the exact list of requirements satisfied is purely
- an optimization, not something the user can detect.
- * A backend for an overflow aware integers (done 2012/10/31).
- * IIUC convert_to is used to emulate in c++98 compilers C++11 explicit
- conversions. Could the explicit conversion operator be added on
- compilers supporting it? (Done 2012/09/15).
- * The front-end should make the differences between implicit and explicit
- construction (Done 2012/09/15).
- * The tutorial should add more examples concerning implicit or explicit
- conversions. (Done 2012/09/15).
- * The documentation must explain how move semantics helps in this domain
- and what the backend needs to do to profit from this optimization. (Done 2012/09/15).
- * The documentation should contain Throws specification on the mp_number
- and backend requirements operations. (Done 2012/09/15).
- * The library interface should use the noexcept (BOOST_NOEXCEPT, ...)
- facilities (Done 2012/09/15).
- * It is unfortunate that the generic mp_number front end can not make use
- constexpr as not all the backends can ensure this (done - we can go quite a way).
- * literals: The library doesn't provide some kind of literals. I think that the
- mp_number class should provide a way to create literals if the backend
- is able to. (Done 2012/09/15).
- * The ExpresionTemplate parameter could be defaulted to a traits class for more sensible defaults (done 2012/09/20).
- * In a = exp1 op exp2 where a occurs inside one of exp1 or exp2 then we can optimise and eliminate one more temporary (done 2012/09/20).
- [h4 Pre-Review Comments]
- * Make fixed precision orthogonal to Allocator type in cpp_int. Possible solution - add an additional MaxBits
- template argument that defaults to 0 (meaning keep going till no more space/memory). Done.
- * Can ring types (exact floating-point types) be supported? The answer should be yes, but someone needs to write it (Moved to TODO list).
- * Should there be a choice of rounding mode (probably MPFR specific)? Moved to TODO list.
- * Make the exponent type for cpp_dec_float a template parameter, maybe include support for big-integer exponents.
- Open question - what should be the default - int32_t or int64_t? (done 2012/09/06)
- * Document the size requirements of fixed precision ints (done 2012/09/15).
- * Document std lib function accuracy (done 2012/09/15).
- * Be a bit clearer on the effects of sign-magnitude representation of cpp_int - min == -max etc - done.
- * Document cpp_dec_float precision, rounding, and exponent size (done 2012/09/06).
- * Can we be clearer in the docs that mixed arithmetic doesn't work (no longer applicable as of 2012/09/06)?
- * Document round functions behaviour better (they behave as in C++11) (added note 2012/09/06).
- * Document limits on size of cpp_dec_float (done 2012/09/06).
- * Add support for fused multiply add (and subtract). GMP mpz_t could use this (done 2012/09/20).
- [endsect]
- [section:faq FAQ]
- [variablelist
- [[Why do I get compiler errors when passing a `number` to a template function?]
- [Most likely you are actually passing an expression template type to the function and
- template-argument-deduction deduces the "wrong" type. Try casting the arguments
- involving expressions to the actual number type, or as a last resort turning off
- expression template support in the number type you are using.]]
- [[When is expression template support a performance gain?]
- [As a general rule, expression template support adds a small runtime overhead
- creating and unpacking the expression templates, but greatly reduces the number of
- temporaries created. So it's most effective in improving performance when the cost
- of creating a temporary is high: for example when creating a temporary involves a memory
- allocation. It is least effective (and may even be a dis-optimisation) when temporaries
- are cheap: for example if the number type is basically a thin wrapper around a native
- arithmetic type. In addition, since the library makes extensive use of thin inline wrapper
- functions, turning on compiler optimization is essential to achieving high performance.]]
- [[Do expression templates reorder operations?]
- [Yes they do, sometimes quite radically so, if this is a concern then they should be turned
- off for the number type you are using.]]
- [[I can't construct my number type from ['some other type], but the docs indicate that the conversion should be allowed, what's up?]
- [Some conversions are ['explicit], that includes construction from a string, or constructing from any type
- that may result in loss of precision (for example constructing an integer type from a float).]]
- [[Why do I get an exception thrown (or the program crash due to an uncaught exception) when using the bitwise operators on a checked `cpp_int`?]
- [Bitwise operations on negative values (or indeed any signed integer type) are unspecified by the standard. As a result
- any attempt to carry out a bitwise operation on a negative checked-integer will result in a `std::range_error` being thrown.]]
- [[Why do I get compiler errors when trying to use the complement operator?]
- [Use of the complement operator on signed types is problematic as the result is unspecified by the standard, and is further
- complicated by the fact that most extended precision integer types use a sign-magnitude representation rather than the 2's
- complement one favored by most native integer types. As a result the complement operator is deliberately disabled for
- checked `cpp_int`'s. Unchecked `cpp_int`'s give the same valued result as a 2's complement type would, but not the same bit-pattern.]]
- [[Why can't I negate an unsigned type?]
- [The unary negation operator is deliberately disabled for unsigned integer types as its use would almost always be a programming error.]]
- [[Why doesn't the library use proto?]
- [A very early version of the library did use proto, but compile times became too slow
- for the library to be usable. Since the library only required a tiny fraction of what
- proto has to offer anyway, a lightweight expression template mechanism was used instead.
- Compile times are still too slow...]]
- [[Why not abstract out addition/multiplication algorithms?]
- [This was deemed not to be practical: these algorithms are intimately
- tied to the actual data representation used.]]
- [[How do I choose between Boost.Multiprecision `cpp_bin_50` and `cpp_dec_50`?]
- [Unless you have a specific reason to choose `cpp_dec_`, then the default choice should be `cpp_bin_`,
- for example using the convenience `typedefs` like `boost::multiprecision::cpp_bin_50` or `boost::multiprecision::cpp_bin_100`.
- In general, both work well and give the same results and at roughly the same speed with `cpp_dec_50` sometimes faster.
- `cpp_dec_` was developed first paving the way for `cpp_bin_`.
- `cpp_dec_` has several guard digits and is not rounded at all, using 'brute force' to get the promised number of decimal digits correct,
- but making it difficult to reason about precision and computational uncertainty, for example see [*https://svn.boost.org/trac10/ticket/12133].
- It also has a fast but imprecise division operator giving surprising results sometimes, see [*https://svn.boost.org/trac10/ticket/11178].
- `cpp_bin_` is correctly/exactly rounded making it possible to reason about both the precision and rounding of the results.]]
- ] [/variablelist]
- [endsect]
- [section:ack Acknowledgements]
- This library would not have happened without:
- * Christopher Kormanyos' C++ decimal number code.
- * Paul Bristow for patiently testing, and commenting on the library.
- * All the folks at GMP, MPFR and libtommath, for providing the "guts" that makes this library work.
- * [@http://www-cs-faculty.stanford.edu/~uno/taocp.html "The Art Of Computer Programming"],
- Donald E. Knuth, Volume 2: Seminumerical Algorithms, Third Edition
- (Reading, Massachusetts: Addison-Wesley, 1997), xiv+762pp. ISBN 0-201-89684-2
- [endsect]
- [endsect]
- [section:indexes Indexes]
- '''
- <index type="function_name">
- <title>Function Index</title>
- </index>
- <index type="class_name">
- <title>Class Index</title>
- </index>
- <index type="typedef_name">
- <title>Typedef Index</title>
- </index>
- <index/>
- '''
- [endsect]
|