| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141 |
- /* ------------------------------------------------------------------ */
- /* Decimal Number arithmetic module */
- /* ------------------------------------------------------------------ */
- /* Copyright (c) IBM Corporation, 2000, 2009. All rights reserved. */
- /* */
- /* This software is made available under the terms of the */
- /* ICU License -- ICU 1.8.1 and later. */
- /* */
- /* The description and User's Guide ("The decNumber C Library") for */
- /* this software is called decNumber.pdf. This document is */
- /* available, together with arithmetic and format specifications, */
- /* testcases, and Web links, on the General Decimal Arithmetic page. */
- /* */
- /* Please send comments, suggestions, and corrections to the author: */
- /* [email protected] */
- /* Mike Cowlishaw, IBM Fellow */
- /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
- /* ------------------------------------------------------------------ */
- /* This module comprises the routines for arbitrary-precision General */
- /* Decimal Arithmetic as defined in the specification which may be */
- /* found on the General Decimal Arithmetic pages. It implements both */
- /* the full ('extended') arithmetic and the simpler ('subset') */
- /* arithmetic. */
- /* */
- /* Usage notes: */
- /* */
- /* 1. This code is ANSI C89 except: */
- /* */
- /* a) C99 line comments (double forward slash) are used. (Most C */
- /* compilers accept these. If yours does not, a simple script */
- /* can be used to convert them to ANSI C comments.) */
- /* */
- /* b) Types from C99 stdint.h are used. If you do not have this */
- /* header file, see the User's Guide section of the decNumber */
- /* documentation; this lists the necessary definitions. */
- /* */
- /* c) If DECDPUN>4 or DECUSE64=1, the C99 64-bit int64_t and */
- /* uint64_t types may be used. To avoid these, set DECUSE64=0 */
- /* and DECDPUN<=4 (see documentation). */
- /* */
- /* The code also conforms to C99 restrictions; in particular, */
- /* strict aliasing rules are observed. */
- /* */
- /* 2. The decNumber format which this library uses is optimized for */
- /* efficient processing of relatively short numbers; in particular */
- /* it allows the use of fixed sized structures and minimizes copy */
- /* and move operations. It does, however, support arbitrary */
- /* precision (up to 999,999,999 digits) and arbitrary exponent */
- /* range (Emax in the range 0 through 999,999,999 and Emin in the */
- /* range -999,999,999 through 0). Mathematical functions (for */
- /* example decNumberExp) as identified below are restricted more */
- /* tightly: digits, emax, and -emin in the context must be <= */
- /* DEC_MAX_MATH (999999), and their operand(s) must be within */
- /* these bounds. */
- /* */
- /* 3. Logical functions are further restricted; their operands must */
- /* be finite, positive, have an exponent of zero, and all digits */
- /* must be either 0 or 1. The result will only contain digits */
- /* which are 0 or 1 (and will have exponent=0 and a sign of 0). */
- /* */
- /* 4. Operands to operator functions are never modified unless they */
- /* are also specified to be the result number (which is always */
- /* permitted). Other than that case, operands must not overlap. */
- /* */
- /* 5. Error handling: the type of the error is ORed into the status */
- /* flags in the current context (decContext structure). The */
- /* SIGFPE signal is then raised if the corresponding trap-enabler */
- /* flag in the decContext is set (is 1). */
- /* */
- /* It is the responsibility of the caller to clear the status */
- /* flags as required. */
- /* */
- /* The result of any routine which returns a number will always */
- /* be a valid number (which may be a special value, such as an */
- /* Infinity or NaN). */
- /* */
- /* 6. The decNumber format is not an exchangeable concrete */
- /* representation as it comprises fields which may be machine- */
- /* dependent (packed or unpacked, or special length, for example). */
- /* Canonical conversions to and from strings are provided; other */
- /* conversions are available in separate modules. */
- /* */
- /* 7. Normally, input operands are assumed to be valid. Set DECCHECK */
- /* to 1 for extended operand checking (including NULL operands). */
- /* Results are undefined if a badly-formed structure (or a NULL */
- /* pointer to a structure) is provided, though with DECCHECK */
- /* enabled the operator routines are protected against exceptions. */
- /* (Except if the result pointer is NULL, which is unrecoverable.) */
- /* */
- /* However, the routines will never cause exceptions if they are */
- /* given well-formed operands, even if the value of the operands */
- /* is inappropriate for the operation and DECCHECK is not set. */
- /* (Except for SIGFPE, as and where documented.) */
- /* */
- /* 8. Subset arithmetic is available only if DECSUBSET is set to 1. */
- /* ------------------------------------------------------------------ */
- /* Implementation notes for maintenance of this module: */
- /* */
- /* 1. Storage leak protection: Routines which use malloc are not */
- /* permitted to use return for fastpath or error exits (i.e., */
- /* they follow strict structured programming conventions). */
- /* Instead they have a do{}while(0); construct surrounding the */
- /* code which is protected -- break may be used to exit this. */
- /* Other routines can safely use the return statement inline. */
- /* */
- /* Storage leak accounting can be enabled using DECALLOC. */
- /* */
- /* 2. All loops use the for(;;) construct. Any do construct does */
- /* not loop; it is for allocation protection as just described. */
- /* */
- /* 3. Setting status in the context must always be the very last */
- /* action in a routine, as non-0 status may raise a trap and hence */
- /* the call to set status may not return (if the handler uses long */
- /* jump). Therefore all cleanup must be done first. In general, */
- /* to achieve this status is accumulated and is only applied just */
- /* before return by calling decContextSetStatus (via decStatus). */
- /* */
- /* Routines which allocate storage cannot, in general, use the */
- /* 'top level' routines which could cause a non-returning */
- /* transfer of control. The decXxxxOp routines are safe (do not */
- /* call decStatus even if traps are set in the context) and should */
- /* be used instead (they are also a little faster). */
- /* */
- /* 4. Exponent checking is minimized by allowing the exponent to */
- /* grow outside its limits during calculations, provided that */
- /* the decFinalize function is called later. Multiplication and */
- /* division, and intermediate calculations in exponentiation, */
- /* require more careful checks because of the risk of 31-bit */
- /* overflow (the most negative valid exponent is -1999999997, for */
- /* a 999999999-digit number with adjusted exponent of -999999999). */
- /* */
- /* 5. Rounding is deferred until finalization of results, with any */
- /* 'off to the right' data being represented as a single digit */
- /* residue (in the range -1 through 9). This avoids any double- */
- /* rounding when more than one shortening takes place (for */
- /* example, when a result is subnormal). */
- /* */
- /* 6. The digits count is allowed to rise to a multiple of DECDPUN */
- /* during many operations, so whole Units are handled and exact */
- /* accounting of digits is not needed. The correct digits value */
- /* is found by decGetDigits, which accounts for leading zeros. */
- /* This must be called before any rounding if the number of digits */
- /* is not known exactly. */
- /* */
- /* 7. The multiply-by-reciprocal 'trick' is used for partitioning */
- /* numbers up to four digits, using appropriate constants. This */
- /* is not useful for longer numbers because overflow of 32 bits */
- /* would lead to 4 multiplies, which is almost as expensive as */
- /* a divide (unless a floating-point or 64-bit multiply is */
- /* assumed to be available). */
- /* */
- /* 8. Unusual abbreviations that may be used in the commentary: */
- /* lhs -- left hand side (operand, of an operation) */
- /* lsd -- least significant digit (of coefficient) */
- /* lsu -- least significant Unit (of coefficient) */
- /* msd -- most significant digit (of coefficient) */
- /* msi -- most significant item (in an array) */
- /* msu -- most significant Unit (of coefficient) */
- /* rhs -- right hand side (operand, of an operation) */
- /* +ve -- positive */
- /* -ve -- negative */
- /* ** -- raise to the power */
- /* ------------------------------------------------------------------ */
- #include <stdlib.h> // for malloc, free, etc.
- #include <stdio.h> // for printf [if needed]
- #include <string.h> // for strcpy
- #include <ctype.h> // for lower
- #include "decNumber.h" // base number library
- #include "decNumberLocal.h" // decNumber local types, etc.
- /* Constants */
- // Public lookup table used by the D2U macro
- const uByte d2utable[DECMAXD2U+1]=D2UTABLE;
- #define DECVERB 1 // set to 1 for verbose DECCHECK
- #define powers DECPOWERS // old internal name
- // Local constants
- #define DIVIDE 0x80 // Divide operators
- #define REMAINDER 0x40 // ..
- #define DIVIDEINT 0x20 // ..
- #define REMNEAR 0x10 // ..
- #define COMPARE 0x01 // Compare operators
- #define COMPMAX 0x02 // ..
- #define COMPMIN 0x03 // ..
- #define COMPTOTAL 0x04 // ..
- #define COMPNAN 0x05 // .. [NaN processing]
- #define COMPSIG 0x06 // .. [signaling COMPARE]
- #define COMPMAXMAG 0x07 // ..
- #define COMPMINMAG 0x08 // ..
- #define DEC_sNaN 0x40000000 // local status: sNaN signal
- #define BADINT (Int)0x80000000 // most-negative Int; error indicator
- // Next two indicate an integer >= 10**6, and its parity (bottom bit)
- #define BIGEVEN (Int)0x80000002
- #define BIGODD (Int)0x80000003
- static Unit uarrone[1]={1}; // Unit array of 1, used for incrementing
- /* Granularity-dependent code */
- #if DECDPUN<=4
- #define eInt Int // extended integer
- #define ueInt uInt // unsigned extended integer
- // Constant multipliers for divide-by-power-of five using reciprocal
- // multiply, after removing powers of 2 by shifting, and final shift
- // of 17 [we only need up to **4]
- static const uInt multies[]={131073, 26215, 5243, 1049, 210};
- // QUOT10 -- macro to return the quotient of unit u divided by 10**n
- #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
- #else
- // For DECDPUN>4 non-ANSI-89 64-bit types are needed.
- #if !DECUSE64
- #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4
- #endif
- #define eInt Long // extended integer
- #define ueInt uLong // unsigned extended integer
- #endif
- /* Local routines */
- static decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *,
- decContext *, uByte, uInt *);
- static Flag decBiStr(const char *, const char *, const char *);
- static uInt decCheckMath(const decNumber *, decContext *, uInt *);
- static void decApplyRound(decNumber *, decContext *, Int, uInt *);
- static Int decCompare(const decNumber *lhs, const decNumber *rhs, Flag);
- static decNumber * decCompareOp(decNumber *, const decNumber *,
- const decNumber *, decContext *,
- Flag, uInt *);
- static void decCopyFit(decNumber *, const decNumber *, decContext *,
- Int *, uInt *);
- static decNumber * decDecap(decNumber *, Int);
- static decNumber * decDivideOp(decNumber *, const decNumber *,
- const decNumber *, decContext *, Flag, uInt *);
- static decNumber * decExpOp(decNumber *, const decNumber *,
- decContext *, uInt *);
- static void decFinalize(decNumber *, decContext *, Int *, uInt *);
- static Int decGetDigits(Unit *, Int);
- static Int decGetInt(const decNumber *);
- static decNumber * decLnOp(decNumber *, const decNumber *,
- decContext *, uInt *);
- static decNumber * decMultiplyOp(decNumber *, const decNumber *,
- const decNumber *, decContext *,
- uInt *);
- static decNumber * decNaNs(decNumber *, const decNumber *,
- const decNumber *, decContext *, uInt *);
- static decNumber * decQuantizeOp(decNumber *, const decNumber *,
- const decNumber *, decContext *, Flag,
- uInt *);
- static void decReverse(Unit *, Unit *);
- static void decSetCoeff(decNumber *, decContext *, const Unit *,
- Int, Int *, uInt *);
- static void decSetMaxValue(decNumber *, decContext *);
- static void decSetOverflow(decNumber *, decContext *, uInt *);
- static void decSetSubnormal(decNumber *, decContext *, Int *, uInt *);
- static Int decShiftToLeast(Unit *, Int, Int);
- static Int decShiftToMost(Unit *, Int, Int);
- static void decStatus(decNumber *, uInt, decContext *);
- static void decToString(const decNumber *, char[], Flag);
- static decNumber * decTrim(decNumber *, decContext *, Flag, Flag, Int *);
- static Int decUnitAddSub(const Unit *, Int, const Unit *, Int, Int,
- Unit *, Int);
- static Int decUnitCompare(const Unit *, Int, const Unit *, Int, Int);
- #if !DECSUBSET
- /* decFinish == decFinalize when no subset arithmetic needed */
- #define decFinish(a,b,c,d) decFinalize(a,b,c,d)
- #else
- static void decFinish(decNumber *, decContext *, Int *, uInt *);
- static decNumber * decRoundOperand(const decNumber *, decContext *, uInt *);
- #endif
- /* Local macros */
- // masked special-values bits
- #define SPECIALARG (rhs->bits & DECSPECIAL)
- #define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL)
- /* Diagnostic macros, etc. */
- #if DECALLOC
- // Handle malloc/free accounting. If enabled, our accountable routines
- // are used; otherwise the code just goes straight to the system malloc
- // and free routines.
- #define malloc(a) decMalloc(a)
- #define free(a) decFree(a)
- #define DECFENCE 0x5a // corruption detector
- // 'Our' malloc and free:
- static void *decMalloc(size_t);
- static void decFree(void *);
- uInt decAllocBytes=0; // count of bytes allocated
- // Note that DECALLOC code only checks for storage buffer overflow.
- // To check for memory leaks, the decAllocBytes variable must be
- // checked to be 0 at appropriate times (e.g., after the test
- // harness completes a set of tests). This checking may be unreliable
- // if the testing is done in a multi-thread environment.
- #endif
- #if DECCHECK
- // Optional checking routines. Enabling these means that decNumber
- // and decContext operands to operator routines are checked for
- // correctness. This roughly doubles the execution time of the
- // fastest routines (and adds 600+ bytes), so should not normally be
- // used in 'production'.
- // decCheckInexact is used to check that inexact results have a full
- // complement of digits (where appropriate -- this is not the case
- // for Quantize, for example)
- #define DECUNRESU ((decNumber *)(void *)0xffffffff)
- #define DECUNUSED ((const decNumber *)(void *)0xffffffff)
- #define DECUNCONT ((decContext *)(void *)(0xffffffff))
- static Flag decCheckOperands(decNumber *, const decNumber *,
- const decNumber *, decContext *);
- static Flag decCheckNumber(const decNumber *);
- static void decCheckInexact(const decNumber *, decContext *);
- #endif
- #if DECTRACE || DECCHECK
- // Optional trace/debugging routines (may or may not be used)
- void decNumberShow(const decNumber *); // displays the components of a number
- static void decDumpAr(char, const Unit *, Int);
- #endif
- /* ================================================================== */
- /* Conversions */
- /* ================================================================== */
- /* ------------------------------------------------------------------ */
- /* from-int32 -- conversion from Int or uInt */
- /* */
- /* dn is the decNumber to receive the integer */
- /* in or uin is the integer to be converted */
- /* returns dn */
- /* */
- /* No error is possible. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberFromInt32(decNumber *dn, Int in) {
- uInt unsig;
- if (in>=0) unsig=in;
- else { // negative (possibly BADINT)
- if (in==BADINT) unsig=(uInt)1073741824*2; // special case
- else unsig=-in; // invert
- }
- // in is now positive
- decNumberFromUInt32(dn, unsig);
- if (in<0) dn->bits=DECNEG; // sign needed
- return dn;
- } // decNumberFromInt32
- decNumber * decNumberFromUInt32(decNumber *dn, uInt uin) {
- Unit *up; // work pointer
- decNumberZero(dn); // clean
- if (uin==0) return dn; // [or decGetDigits bad call]
- for (up=dn->lsu; uin>0; up++) {
- *up=(Unit)(uin%(DECDPUNMAX+1));
- uin=uin/(DECDPUNMAX+1);
- }
- dn->digits=decGetDigits(dn->lsu, up-dn->lsu);
- return dn;
- } // decNumberFromUInt32
- /* ------------------------------------------------------------------ */
- /* to-int32 -- conversion to Int or uInt */
- /* */
- /* dn is the decNumber to convert */
- /* set is the context for reporting errors */
- /* returns the converted decNumber, or 0 if Invalid is set */
- /* */
- /* Invalid is set if the decNumber does not have exponent==0 or if */
- /* it is a NaN, Infinite, or out-of-range. */
- /* ------------------------------------------------------------------ */
- Int decNumberToInt32(const decNumber *dn, decContext *set) {
- #if DECCHECK
- if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
- #endif
- // special or too many digits, or bad exponent
- if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; // bad
- else { // is a finite integer with 10 or fewer digits
- Int d; // work
- const Unit *up; // ..
- uInt hi=0, lo; // ..
- up=dn->lsu; // -> lsu
- lo=*up; // get 1 to 9 digits
- #if DECDPUN>1 // split to higher
- hi=lo/10;
- lo=lo%10;
- #endif
- up++;
- // collect remaining Units, if any, into hi
- for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
- // now low has the lsd, hi the remainder
- if (hi>214748364 || (hi==214748364 && lo>7)) { // out of range?
- // most-negative is a reprieve
- if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000;
- // bad -- drop through
- }
- else { // in-range always
- Int i=X10(hi)+lo;
- if (dn->bits&DECNEG) return -i;
- return i;
- }
- } // integer
- decContextSetStatus(set, DEC_Invalid_operation); // [may not return]
- return 0;
- } // decNumberToInt32
- uInt decNumberToUInt32(const decNumber *dn, decContext *set) {
- #if DECCHECK
- if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
- #endif
- // special or too many digits, or bad exponent, or negative (<0)
- if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0
- || (dn->bits&DECNEG && !ISZERO(dn))); // bad
- else { // is a finite integer with 10 or fewer digits
- Int d; // work
- const Unit *up; // ..
- uInt hi=0, lo; // ..
- up=dn->lsu; // -> lsu
- lo=*up; // get 1 to 9 digits
- #if DECDPUN>1 // split to higher
- hi=lo/10;
- lo=lo%10;
- #endif
- up++;
- // collect remaining Units, if any, into hi
- for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
- // now low has the lsd, hi the remainder
- if (hi>429496729 || (hi==429496729 && lo>5)) ; // no reprieve possible
- else return X10(hi)+lo;
- } // integer
- decContextSetStatus(set, DEC_Invalid_operation); // [may not return]
- return 0;
- } // decNumberToUInt32
- /* ------------------------------------------------------------------ */
- /* to-scientific-string -- conversion to numeric string */
- /* to-engineering-string -- conversion to numeric string */
- /* */
- /* decNumberToString(dn, string); */
- /* decNumberToEngString(dn, string); */
- /* */
- /* dn is the decNumber to convert */
- /* string is the string where the result will be laid out */
- /* */
- /* string must be at least dn->digits+14 characters long */
- /* */
- /* No error is possible, and no status can be set. */
- /* ------------------------------------------------------------------ */
- char * decNumberToString(const decNumber *dn, char *string){
- decToString(dn, string, 0);
- return string;
- } // DecNumberToString
- char * decNumberToEngString(const decNumber *dn, char *string){
- decToString(dn, string, 1);
- return string;
- } // DecNumberToEngString
- /* ------------------------------------------------------------------ */
- /* to-number -- conversion from numeric string */
- /* */
- /* decNumberFromString -- convert string to decNumber */
- /* dn -- the number structure to fill */
- /* chars[] -- the string to convert ('\0' terminated) */
- /* set -- the context used for processing any error, */
- /* determining the maximum precision available */
- /* (set.digits), determining the maximum and minimum */
- /* exponent (set.emax and set.emin), determining if */
- /* extended values are allowed, and checking the */
- /* rounding mode if overflow occurs or rounding is */
- /* needed. */
- /* */
- /* The length of the coefficient and the size of the exponent are */
- /* checked by this routine, so the correct error (Underflow or */
- /* Overflow) can be reported or rounding applied, as necessary. */
- /* */
- /* If bad syntax is detected, the result will be a quiet NaN. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberFromString(decNumber *dn, const char chars[],
- decContext *set) {
- Int exponent=0; // working exponent [assume 0]
- uByte bits=0; // working flags [assume +ve]
- Unit *res; // where result will be built
- Unit resbuff[SD2U(DECBUFFER+9)];// local buffer in case need temporary
- // [+9 allows for ln() constants]
- Unit *allocres=NULL; // -> allocated result, iff allocated
- Int d=0; // count of digits found in decimal part
- const char *dotchar=NULL; // where dot was found
- const char *cfirst=chars; // -> first character of decimal part
- const char *last=NULL; // -> last digit of decimal part
- const char *c; // work
- Unit *up; // ..
- #if DECDPUN>1
- Int cut, out; // ..
- #endif
- Int residue; // rounding residue
- uInt status=0; // error code
- #if DECCHECK
- if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set))
- return decNumberZero(dn);
- #endif
- do { // status & malloc protection
- for (c=chars;; c++) { // -> input character
- if (*c>='0' && *c<='9') { // test for Arabic digit
- last=c;
- d++; // count of real digits
- continue; // still in decimal part
- }
- if (*c=='.' && dotchar==NULL) { // first '.'
- dotchar=c; // record offset into decimal part
- if (c==cfirst) cfirst++; // first digit must follow
- continue;}
- if (c==chars) { // first in string...
- if (*c=='-') { // valid - sign
- cfirst++;
- bits=DECNEG;
- continue;}
- if (*c=='+') { // valid + sign
- cfirst++;
- continue;}
- }
- // *c is not a digit, or a valid +, -, or '.'
- break;
- } // c
- if (last==NULL) { // no digits yet
- status=DEC_Conversion_syntax;// assume the worst
- if (*c=='\0') break; // and no more to come...
- #if DECSUBSET
- // if subset then infinities and NaNs are not allowed
- if (!set->extended) break; // hopeless
- #endif
- // Infinities and NaNs are possible, here
- if (dotchar!=NULL) break; // .. unless had a dot
- decNumberZero(dn); // be optimistic
- if (decBiStr(c, "infinity", "INFINITY")
- || decBiStr(c, "inf", "INF")) {
- dn->bits=bits | DECINF;
- status=0; // is OK
- break; // all done
- }
- // a NaN expected
- // 2003.09.10 NaNs are now permitted to have a sign
- dn->bits=bits | DECNAN; // assume simple NaN
- if (*c=='s' || *c=='S') { // looks like an sNaN
- c++;
- dn->bits=bits | DECSNAN;
- }
- if (*c!='n' && *c!='N') break; // check caseless "NaN"
- c++;
- if (*c!='a' && *c!='A') break; // ..
- c++;
- if (*c!='n' && *c!='N') break; // ..
- c++;
- // now either nothing, or nnnn payload, expected
- // -> start of integer and skip leading 0s [including plain 0]
- for (cfirst=c; *cfirst=='0';) cfirst++;
- if (*cfirst=='\0') { // "NaN" or "sNaN", maybe with all 0s
- status=0; // it's good
- break; // ..
- }
- // something other than 0s; setup last and d as usual [no dots]
- for (c=cfirst;; c++, d++) {
- if (*c<'0' || *c>'9') break; // test for Arabic digit
- last=c;
- }
- if (*c!='\0') break; // not all digits
- if (d>set->digits-1) {
- // [NB: payload in a decNumber can be full length unless
- // clamped, in which case can only be digits-1]
- if (set->clamp) break;
- if (d>set->digits) break;
- } // too many digits?
- // good; drop through to convert the integer to coefficient
- status=0; // syntax is OK
- bits=dn->bits; // for copy-back
- } // last==NULL
- else if (*c!='\0') { // more to process...
- // had some digits; exponent is only valid sequence now
- Flag nege; // 1=negative exponent
- const char *firstexp; // -> first significant exponent digit
- status=DEC_Conversion_syntax;// assume the worst
- if (*c!='e' && *c!='E') break;
- /* Found 'e' or 'E' -- now process explicit exponent */
- // 1998.07.11: sign no longer required
- nege=0;
- c++; // to (possible) sign
- if (*c=='-') {nege=1; c++;}
- else if (*c=='+') c++;
- if (*c=='\0') break;
- for (; *c=='0' && *(c+1)!='\0';) c++; // strip insignificant zeros
- firstexp=c; // save exponent digit place
- for (; ;c++) {
- if (*c<'0' || *c>'9') break; // not a digit
- exponent=X10(exponent)+(Int)*c-(Int)'0';
- } // c
- // if not now on a '\0', *c must not be a digit
- if (*c!='\0') break;
- // (this next test must be after the syntax checks)
- // if it was too long the exponent may have wrapped, so check
- // carefully and set it to a certain overflow if wrap possible
- if (c>=firstexp+9+1) {
- if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2;
- // [up to 1999999999 is OK, for example 1E-1000000998]
- }
- if (nege) exponent=-exponent; // was negative
- status=0; // is OK
- } // stuff after digits
- // Here when whole string has been inspected; syntax is good
- // cfirst->first digit (never dot), last->last digit (ditto)
- // strip leading zeros/dot [leave final 0 if all 0's]
- if (*cfirst=='0') { // [cfirst has stepped over .]
- for (c=cfirst; c<last; c++, cfirst++) {
- if (*c=='.') continue; // ignore dots
- if (*c!='0') break; // non-zero found
- d--; // 0 stripped
- } // c
- #if DECSUBSET
- // make a rapid exit for easy zeros if !extended
- if (*cfirst=='0' && !set->extended) {
- decNumberZero(dn); // clean result
- break; // [could be return]
- }
- #endif
- } // at least one leading 0
- // Handle decimal point...
- if (dotchar!=NULL && dotchar<last) // non-trailing '.' found?
- exponent-=(last-dotchar); // adjust exponent
- // [we can now ignore the .]
- // OK, the digits string is good. Assemble in the decNumber, or in
- // a temporary units array if rounding is needed
- if (d<=set->digits) res=dn->lsu; // fits into supplied decNumber
- else { // rounding needed
- Int needbytes=D2U(d)*sizeof(Unit);// bytes needed
- res=resbuff; // assume use local buffer
- if (needbytes>(Int)sizeof(resbuff)) { // too big for local
- allocres=(Unit *)malloc(needbytes);
- if (allocres==NULL) {status|=DEC_Insufficient_storage; break;}
- res=allocres;
- }
- }
- // res now -> number lsu, buffer, or allocated storage for Unit array
- // Place the coefficient into the selected Unit array
- // [this is often 70% of the cost of this function when DECDPUN>1]
- #if DECDPUN>1
- out=0; // accumulator
- up=res+D2U(d)-1; // -> msu
- cut=d-(up-res)*DECDPUN; // digits in top unit
- for (c=cfirst;; c++) { // along the digits
- if (*c=='.') continue; // ignore '.' [don't decrement cut]
- out=X10(out)+(Int)*c-(Int)'0';
- if (c==last) break; // done [never get to trailing '.']
- cut--;
- if (cut>0) continue; // more for this unit
- *up=(Unit)out; // write unit
- up--; // prepare for unit below..
- cut=DECDPUN; // ..
- out=0; // ..
- } // c
- *up=(Unit)out; // write lsu
- #else
- // DECDPUN==1
- up=res; // -> lsu
- for (c=last; c>=cfirst; c--) { // over each character, from least
- if (*c=='.') continue; // ignore . [don't step up]
- *up=(Unit)((Int)*c-(Int)'0');
- up++;
- } // c
- #endif
- dn->bits=bits;
- dn->exponent=exponent;
- dn->digits=d;
- // if not in number (too long) shorten into the number
- if (d>set->digits) {
- residue=0;
- decSetCoeff(dn, set, res, d, &residue, &status);
- // always check for overflow or subnormal and round as needed
- decFinalize(dn, set, &residue, &status);
- }
- else { // no rounding, but may still have overflow or subnormal
- // [these tests are just for performance; finalize repeats them]
- if ((dn->exponent-1<set->emin-dn->digits)
- || (dn->exponent-1>set->emax-set->digits)) {
- residue=0;
- decFinalize(dn, set, &residue, &status);
- }
- }
- // decNumberShow(dn);
- } while(0); // [for break]
- if (allocres!=NULL) free(allocres); // drop any storage used
- if (status!=0) decStatus(dn, status, set);
- return dn;
- } /* decNumberFromString */
- /* ================================================================== */
- /* Operators */
- /* ================================================================== */
- /* ------------------------------------------------------------------ */
- /* decNumberAbs -- absolute value operator */
- /* */
- /* This computes C = abs(A) */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context */
- /* */
- /* See also decNumberCopyAbs for a quiet bitwise version of this. */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- /* This has the same effect as decNumberPlus unless A is negative, */
- /* in which case it has the same effect as decNumberMinus. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberAbs(decNumber *res, const decNumber *rhs,
- decContext *set) {
- decNumber dzero; // for 0
- uInt status=0; // accumulator
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- decNumberZero(&dzero); // set 0
- dzero.exponent=rhs->exponent; // [no coefficient expansion]
- decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberAbs
- /* ------------------------------------------------------------------ */
- /* decNumberAdd -- add two Numbers */
- /* */
- /* This computes C = A + B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X+X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- /* This just calls the routine shared with Subtract */
- decNumber * decNumberAdd(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decAddOp(res, lhs, rhs, set, 0, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberAdd
- /* ------------------------------------------------------------------ */
- /* decNumberAnd -- AND two Numbers, digitwise */
- /* */
- /* This computes C = A & B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X&X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context (used for result length and error report) */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Logical function restrictions apply (see above); a NaN is */
- /* returned with Invalid_operation if a restriction is violated. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberAnd(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- const Unit *ua, *ub; // -> operands
- const Unit *msua, *msub; // -> operand msus
- Unit *uc, *msuc; // -> result and its msu
- Int msudigs; // digits in res msu
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
- || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
- decStatus(res, DEC_Invalid_operation, set);
- return res;
- }
- // operands are valid
- ua=lhs->lsu; // bottom-up
- ub=rhs->lsu; // ..
- uc=res->lsu; // ..
- msua=ua+D2U(lhs->digits)-1; // -> msu of lhs
- msub=ub+D2U(rhs->digits)-1; // -> msu of rhs
- msuc=uc+D2U(set->digits)-1; // -> msu of result
- msudigs=MSUDIGITS(set->digits); // [faster than remainder]
- for (; uc<=msuc; ua++, ub++, uc++) { // Unit loop
- Unit a, b; // extract units
- if (ua>msua) a=0;
- else a=*ua;
- if (ub>msub) b=0;
- else b=*ub;
- *uc=0; // can now write back
- if (a|b) { // maybe 1 bits to examine
- Int i, j;
- *uc=0; // can now write back
- // This loop could be unrolled and/or use BIN2BCD tables
- for (i=0; i<DECDPUN; i++) {
- if (a&b&1) *uc=*uc+(Unit)powers[i]; // effect AND
- j=a%10;
- a=a/10;
- j|=b%10;
- b=b/10;
- if (j>1) {
- decStatus(res, DEC_Invalid_operation, set);
- return res;
- }
- if (uc==msuc && i==msudigs-1) break; // just did final digit
- } // each digit
- } // both OK
- } // each unit
- // [here uc-1 is the msu of the result]
- res->digits=decGetDigits(res->lsu, uc-res->lsu);
- res->exponent=0; // integer
- res->bits=0; // sign=0
- return res; // [no status to set]
- } // decNumberAnd
- /* ------------------------------------------------------------------ */
- /* decNumberCompare -- compare two Numbers */
- /* */
- /* This computes C = A ? B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for one digit (or NaN). */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberCompare(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decCompareOp(res, lhs, rhs, set, COMPARE, &status);
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberCompare
- /* ------------------------------------------------------------------ */
- /* decNumberCompareSignal -- compare, signalling on all NaNs */
- /* */
- /* This computes C = A ? B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for one digit (or NaN). */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberCompareSignal(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decCompareOp(res, lhs, rhs, set, COMPSIG, &status);
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberCompareSignal
- /* ------------------------------------------------------------------ */
- /* decNumberCompareTotal -- compare two Numbers, using total ordering */
- /* */
- /* This computes C = A ? B, under total ordering */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for one digit; the result will always be one of */
- /* -1, 0, or 1. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberCompareTotal(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberCompareTotal
- /* ------------------------------------------------------------------ */
- /* decNumberCompareTotalMag -- compare, total ordering of magnitudes */
- /* */
- /* This computes C = |A| ? |B|, under total ordering */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for one digit; the result will always be one of */
- /* -1, 0, or 1. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberCompareTotalMag(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- uInt needbytes; // for space calculations
- decNumber bufa[D2N(DECBUFFER+1)];// +1 in case DECBUFFER=0
- decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated
- decNumber bufb[D2N(DECBUFFER+1)];
- decNumber *allocbufb=NULL; // -> allocated bufb, iff allocated
- decNumber *a, *b; // temporary pointers
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- do { // protect allocated storage
- // if either is negative, take a copy and absolute
- if (decNumberIsNegative(lhs)) { // lhs<0
- a=bufa;
- needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit);
- if (needbytes>sizeof(bufa)) { // need malloc space
- allocbufa=(decNumber *)malloc(needbytes);
- if (allocbufa==NULL) { // hopeless -- abandon
- status|=DEC_Insufficient_storage;
- break;}
- a=allocbufa; // use the allocated space
- }
- decNumberCopy(a, lhs); // copy content
- a->bits&=~DECNEG; // .. and clear the sign
- lhs=a; // use copy from here on
- }
- if (decNumberIsNegative(rhs)) { // rhs<0
- b=bufb;
- needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
- if (needbytes>sizeof(bufb)) { // need malloc space
- allocbufb=(decNumber *)malloc(needbytes);
- if (allocbufb==NULL) { // hopeless -- abandon
- status|=DEC_Insufficient_storage;
- break;}
- b=allocbufb; // use the allocated space
- }
- decNumberCopy(b, rhs); // copy content
- b->bits&=~DECNEG; // .. and clear the sign
- rhs=b; // use copy from here on
- }
- decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
- } while(0); // end protected
- if (allocbufa!=NULL) free(allocbufa); // drop any storage used
- if (allocbufb!=NULL) free(allocbufb); // ..
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberCompareTotalMag
- /* ------------------------------------------------------------------ */
- /* decNumberDivide -- divide one number by another */
- /* */
- /* This computes C = A / B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X/X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberDivide(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decDivideOp(res, lhs, rhs, set, DIVIDE, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberDivide
- /* ------------------------------------------------------------------ */
- /* decNumberDivideInteger -- divide and return integer quotient */
- /* */
- /* This computes C = A # B, where # is the integer divide operator */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X#X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberDivideInteger(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status);
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberDivideInteger
- /* ------------------------------------------------------------------ */
- /* decNumberExp -- exponentiation */
- /* */
- /* This computes C = exp(A) */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context; note that rounding mode has no effect */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Mathematical function restrictions apply (see above); a NaN is */
- /* returned with Invalid_operation if a restriction is violated. */
- /* */
- /* Finite results will always be full precision and Inexact, except */
- /* when A is a zero or -Infinity (giving 1 or 0 respectively). */
- /* */
- /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */
- /* almost always be correctly rounded, but may be up to 1 ulp in */
- /* error in rare cases. */
- /* ------------------------------------------------------------------ */
- /* This is a wrapper for decExpOp which can handle the slightly wider */
- /* (double) range needed by Ln (which has to be able to calculate */
- /* exp(-a) where a can be the tiniest number (Ntiny). */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberExp(decNumber *res, const decNumber *rhs,
- decContext *set) {
- uInt status=0; // accumulator
- #if DECSUBSET
- decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated
- #endif
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- // Check restrictions; these restrictions ensure that if h=8 (see
- // decExpOp) then the result will either overflow or underflow to 0.
- // Other math functions restrict the input range, too, for inverses.
- // If not violated then carry out the operation.
- if (!decCheckMath(rhs, set, &status)) do { // protect allocation
- #if DECSUBSET
- if (!set->extended) {
- // reduce operand and set lostDigits status, as needed
- if (rhs->digits>set->digits) {
- allocrhs=decRoundOperand(rhs, set, &status);
- if (allocrhs==NULL) break;
- rhs=allocrhs;
- }
- }
- #endif
- decExpOp(res, rhs, set, &status);
- } while(0); // end protected
- #if DECSUBSET
- if (allocrhs !=NULL) free(allocrhs); // drop any storage used
- #endif
- // apply significant status
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberExp
- /* ------------------------------------------------------------------ */
- /* decNumberFMA -- fused multiply add */
- /* */
- /* This computes D = (A * B) + C with only one rounding */
- /* */
- /* res is D, the result. D may be A or B or C (e.g., X=FMA(X,X,X)) */
- /* lhs is A */
- /* rhs is B */
- /* fhs is C [far hand side] */
- /* set is the context */
- /* */
- /* Mathematical function restrictions apply (see above); a NaN is */
- /* returned with Invalid_operation if a restriction is violated. */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberFMA(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, const decNumber *fhs,
- decContext *set) {
- uInt status=0; // accumulator
- decContext dcmul; // context for the multiplication
- uInt needbytes; // for space calculations
- decNumber bufa[D2N(DECBUFFER*2+1)];
- decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated
- decNumber *acc; // accumulator pointer
- decNumber dzero; // work
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- if (decCheckOperands(res, fhs, DECUNUSED, set)) return res;
- #endif
- do { // protect allocated storage
- #if DECSUBSET
- if (!set->extended) { // [undefined if subset]
- status|=DEC_Invalid_operation;
- break;}
- #endif
- // Check math restrictions [these ensure no overflow or underflow]
- if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status))
- || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status))
- || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break;
- // set up context for multiply
- dcmul=*set;
- dcmul.digits=lhs->digits+rhs->digits; // just enough
- // [The above may be an over-estimate for subset arithmetic, but that's OK]
- dcmul.emax=DEC_MAX_EMAX; // effectively unbounded ..
- dcmul.emin=DEC_MIN_EMIN; // [thanks to Math restrictions]
- // set up decNumber space to receive the result of the multiply
- acc=bufa; // may fit
- needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit);
- if (needbytes>sizeof(bufa)) { // need malloc space
- allocbufa=(decNumber *)malloc(needbytes);
- if (allocbufa==NULL) { // hopeless -- abandon
- status|=DEC_Insufficient_storage;
- break;}
- acc=allocbufa; // use the allocated space
- }
- // multiply with extended range and necessary precision
- //printf("emin=%ld\n", dcmul.emin);
- decMultiplyOp(acc, lhs, rhs, &dcmul, &status);
- // Only Invalid operation (from sNaN or Inf * 0) is possible in
- // status; if either is seen than ignore fhs (in case it is
- // another sNaN) and set acc to NaN unless we had an sNaN
- // [decMultiplyOp leaves that to caller]
- // Note sNaN has to go through addOp to shorten payload if
- // necessary
- if ((status&DEC_Invalid_operation)!=0) {
- if (!(status&DEC_sNaN)) { // but be true invalid
- decNumberZero(res); // acc not yet set
- res->bits=DECNAN;
- break;
- }
- decNumberZero(&dzero); // make 0 (any non-NaN would do)
- fhs=&dzero; // use that
- }
- #if DECCHECK
- else { // multiply was OK
- if (status!=0) printf("Status=%08lx after FMA multiply\n", (LI)status);
- }
- #endif
- // add the third operand and result -> res, and all is done
- decAddOp(res, acc, fhs, set, 0, &status);
- } while(0); // end protected
- if (allocbufa!=NULL) free(allocbufa); // drop any storage used
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberFMA
- /* ------------------------------------------------------------------ */
- /* decNumberInvert -- invert a Number, digitwise */
- /* */
- /* This computes C = ~A */
- /* */
- /* res is C, the result. C may be A (e.g., X=~X) */
- /* rhs is A */
- /* set is the context (used for result length and error report) */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Logical function restrictions apply (see above); a NaN is */
- /* returned with Invalid_operation if a restriction is violated. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberInvert(decNumber *res, const decNumber *rhs,
- decContext *set) {
- const Unit *ua, *msua; // -> operand and its msu
- Unit *uc, *msuc; // -> result and its msu
- Int msudigs; // digits in res msu
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
- decStatus(res, DEC_Invalid_operation, set);
- return res;
- }
- // operand is valid
- ua=rhs->lsu; // bottom-up
- uc=res->lsu; // ..
- msua=ua+D2U(rhs->digits)-1; // -> msu of rhs
- msuc=uc+D2U(set->digits)-1; // -> msu of result
- msudigs=MSUDIGITS(set->digits); // [faster than remainder]
- for (; uc<=msuc; ua++, uc++) { // Unit loop
- Unit a; // extract unit
- Int i, j; // work
- if (ua>msua) a=0;
- else a=*ua;
- *uc=0; // can now write back
- // always need to examine all bits in rhs
- // This loop could be unrolled and/or use BIN2BCD tables
- for (i=0; i<DECDPUN; i++) {
- if ((~a)&1) *uc=*uc+(Unit)powers[i]; // effect INVERT
- j=a%10;
- a=a/10;
- if (j>1) {
- decStatus(res, DEC_Invalid_operation, set);
- return res;
- }
- if (uc==msuc && i==msudigs-1) break; // just did final digit
- } // each digit
- } // each unit
- // [here uc-1 is the msu of the result]
- res->digits=decGetDigits(res->lsu, uc-res->lsu);
- res->exponent=0; // integer
- res->bits=0; // sign=0
- return res; // [no status to set]
- } // decNumberInvert
- /* ------------------------------------------------------------------ */
- /* decNumberLn -- natural logarithm */
- /* */
- /* This computes C = ln(A) */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context; note that rounding mode has no effect */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Notable cases: */
- /* A<0 -> Invalid */
- /* A=0 -> -Infinity (Exact) */
- /* A=+Infinity -> +Infinity (Exact) */
- /* A=1 exactly -> 0 (Exact) */
- /* */
- /* Mathematical function restrictions apply (see above); a NaN is */
- /* returned with Invalid_operation if a restriction is violated. */
- /* */
- /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */
- /* almost always be correctly rounded, but may be up to 1 ulp in */
- /* error in rare cases. */
- /* ------------------------------------------------------------------ */
- /* This is a wrapper for decLnOp which can handle the slightly wider */
- /* (+11) range needed by Ln, Log10, etc. (which may have to be able */
- /* to calculate at p+e+2). */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberLn(decNumber *res, const decNumber *rhs,
- decContext *set) {
- uInt status=0; // accumulator
- #if DECSUBSET
- decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated
- #endif
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- // Check restrictions; this is a math function; if not violated
- // then carry out the operation.
- if (!decCheckMath(rhs, set, &status)) do { // protect allocation
- #if DECSUBSET
- if (!set->extended) {
- // reduce operand and set lostDigits status, as needed
- if (rhs->digits>set->digits) {
- allocrhs=decRoundOperand(rhs, set, &status);
- if (allocrhs==NULL) break;
- rhs=allocrhs;
- }
- // special check in subset for rhs=0
- if (ISZERO(rhs)) { // +/- zeros -> error
- status|=DEC_Invalid_operation;
- break;}
- } // extended=0
- #endif
- decLnOp(res, rhs, set, &status);
- } while(0); // end protected
- #if DECSUBSET
- if (allocrhs !=NULL) free(allocrhs); // drop any storage used
- #endif
- // apply significant status
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberLn
- /* ------------------------------------------------------------------ */
- /* decNumberLogB - get adjusted exponent, by 754 rules */
- /* */
- /* This computes C = adjustedexponent(A) */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context, used only for digits and status */
- /* */
- /* For an unrounded result, digits may need to be 10 (A might have */
- /* 10**9 digits and an exponent of +999999999, or one digit and an */
- /* exponent of -1999999999). */
- /* */
- /* This returns the adjusted exponent of A after (in theory) padding */
- /* with zeros on the right to set->digits digits while keeping the */
- /* same value. The exponent is not limited by emin/emax. */
- /* */
- /* Notable cases: */
- /* A<0 -> Use |A| */
- /* A=0 -> -Infinity (Division by zero) */
- /* A=Infinite -> +Infinity (Exact) */
- /* A=1 exactly -> 0 (Exact) */
- /* NaNs are propagated as usual */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberLogB(decNumber *res, const decNumber *rhs,
- decContext *set) {
- uInt status=0; // accumulator
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- // NaNs as usual; Infinities return +Infinity; 0->oops
- if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status);
- else if (decNumberIsInfinite(rhs)) decNumberCopyAbs(res, rhs);
- else if (decNumberIsZero(rhs)) {
- decNumberZero(res); // prepare for Infinity
- res->bits=DECNEG|DECINF; // -Infinity
- status|=DEC_Division_by_zero; // as per 754
- }
- else { // finite non-zero
- Int ae=rhs->exponent+rhs->digits-1; // adjusted exponent
- if (set->digits>=10) decNumberFromInt32(res, ae); // lay it out
- else {
- decNumber buft[D2N(10)]; // temporary number
- decNumber *t=buft; // ..
- decNumberFromInt32(t, ae); // lay it out
- decNumberPlus(res, t, set); // round as necessary
- }
- }
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberLogB
- /* ------------------------------------------------------------------ */
- /* decNumberLog10 -- logarithm in base 10 */
- /* */
- /* This computes C = log10(A) */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context; note that rounding mode has no effect */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Notable cases: */
- /* A<0 -> Invalid */
- /* A=0 -> -Infinity (Exact) */
- /* A=+Infinity -> +Infinity (Exact) */
- /* A=10**n (if n is an integer) -> n (Exact) */
- /* */
- /* Mathematical function restrictions apply (see above); a NaN is */
- /* returned with Invalid_operation if a restriction is violated. */
- /* */
- /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */
- /* almost always be correctly rounded, but may be up to 1 ulp in */
- /* error in rare cases. */
- /* ------------------------------------------------------------------ */
- /* This calculates ln(A)/ln(10) using appropriate precision. For */
- /* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the */
- /* requested digits and t is the number of digits in the exponent */
- /* (maximum 6). For ln(10) it is p + 3; this is often handled by the */
- /* fastpath in decLnOp. The final division is done to the requested */
- /* precision. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberLog10(decNumber *res, const decNumber *rhs,
- decContext *set) {
- uInt status=0, ignore=0; // status accumulators
- uInt needbytes; // for space calculations
- Int p; // working precision
- Int t; // digits in exponent of A
- // buffers for a and b working decimals
- // (adjustment calculator, same size)
- decNumber bufa[D2N(DECBUFFER+2)];
- decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated
- decNumber *a=bufa; // temporary a
- decNumber bufb[D2N(DECBUFFER+2)];
- decNumber *allocbufb=NULL; // -> allocated bufb, iff allocated
- decNumber *b=bufb; // temporary b
- decNumber bufw[D2N(10)]; // working 2-10 digit number
- decNumber *w=bufw; // ..
- #if DECSUBSET
- decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated
- #endif
- decContext aset; // working context
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- // Check restrictions; this is a math function; if not violated
- // then carry out the operation.
- if (!decCheckMath(rhs, set, &status)) do { // protect malloc
- #if DECSUBSET
- if (!set->extended) {
- // reduce operand and set lostDigits status, as needed
- if (rhs->digits>set->digits) {
- allocrhs=decRoundOperand(rhs, set, &status);
- if (allocrhs==NULL) break;
- rhs=allocrhs;
- }
- // special check in subset for rhs=0
- if (ISZERO(rhs)) { // +/- zeros -> error
- status|=DEC_Invalid_operation;
- break;}
- } // extended=0
- #endif
- decContextDefault(&aset, DEC_INIT_DECIMAL64); // clean context
- // handle exact powers of 10; only check if +ve finite
- if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) {
- Int residue=0; // (no residue)
- uInt copystat=0; // clean status
- // round to a single digit...
- aset.digits=1;
- decCopyFit(w, rhs, &aset, &residue, ©stat); // copy & shorten
- // if exact and the digit is 1, rhs is a power of 10
- if (!(copystat&DEC_Inexact) && w->lsu[0]==1) {
- // the exponent, conveniently, is the power of 10; making
- // this the result needs a little care as it might not fit,
- // so first convert it into the working number, and then move
- // to res
- decNumberFromInt32(w, w->exponent);
- residue=0;
- decCopyFit(res, w, set, &residue, &status); // copy & round
- decFinish(res, set, &residue, &status); // cleanup/set flags
- break;
- } // not a power of 10
- } // not a candidate for exact
- // simplify the information-content calculation to use 'total
- // number of digits in a, including exponent' as compared to the
- // requested digits, as increasing this will only rarely cost an
- // iteration in ln(a) anyway
- t=6; // it can never be >6
- // allocate space when needed...
- p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3;
- needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
- if (needbytes>sizeof(bufa)) { // need malloc space
- allocbufa=(decNumber *)malloc(needbytes);
- if (allocbufa==NULL) { // hopeless -- abandon
- status|=DEC_Insufficient_storage;
- break;}
- a=allocbufa; // use the allocated space
- }
- aset.digits=p; // as calculated
- aset.emax=DEC_MAX_MATH; // usual bounds
- aset.emin=-DEC_MAX_MATH; // ..
- aset.clamp=0; // and no concrete format
- decLnOp(a, rhs, &aset, &status); // a=ln(rhs)
- // skip the division if the result so far is infinite, NaN, or
- // zero, or there was an error; note NaN from sNaN needs copy
- if (status&DEC_NaNs && !(status&DEC_sNaN)) break;
- if (a->bits&DECSPECIAL || ISZERO(a)) {
- decNumberCopy(res, a); // [will fit]
- break;}
- // for ln(10) an extra 3 digits of precision are needed
- p=set->digits+3;
- needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
- if (needbytes>sizeof(bufb)) { // need malloc space
- allocbufb=(decNumber *)malloc(needbytes);
- if (allocbufb==NULL) { // hopeless -- abandon
- status|=DEC_Insufficient_storage;
- break;}
- b=allocbufb; // use the allocated space
- }
- decNumberZero(w); // set up 10...
- #if DECDPUN==1
- w->lsu[1]=1; w->lsu[0]=0; // ..
- #else
- w->lsu[0]=10; // ..
- #endif
- w->digits=2; // ..
- aset.digits=p;
- decLnOp(b, w, &aset, &ignore); // b=ln(10)
- aset.digits=set->digits; // for final divide
- decDivideOp(res, a, b, &aset, DIVIDE, &status); // into result
- } while(0); // [for break]
- if (allocbufa!=NULL) free(allocbufa); // drop any storage used
- if (allocbufb!=NULL) free(allocbufb); // ..
- #if DECSUBSET
- if (allocrhs !=NULL) free(allocrhs); // ..
- #endif
- // apply significant status
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberLog10
- /* ------------------------------------------------------------------ */
- /* decNumberMax -- compare two Numbers and return the maximum */
- /* */
- /* This computes C = A ? B, returning the maximum by 754 rules */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberMax(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decCompareOp(res, lhs, rhs, set, COMPMAX, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberMax
- /* ------------------------------------------------------------------ */
- /* decNumberMaxMag -- compare and return the maximum by magnitude */
- /* */
- /* This computes C = A ? B, returning the maximum by 754 rules */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberMaxMag(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberMaxMag
- /* ------------------------------------------------------------------ */
- /* decNumberMin -- compare two Numbers and return the minimum */
- /* */
- /* This computes C = A ? B, returning the minimum by 754 rules */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberMin(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decCompareOp(res, lhs, rhs, set, COMPMIN, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberMin
- /* ------------------------------------------------------------------ */
- /* decNumberMinMag -- compare and return the minimum by magnitude */
- /* */
- /* This computes C = A ? B, returning the minimum by 754 rules */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberMinMag(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberMinMag
- /* ------------------------------------------------------------------ */
- /* decNumberMinus -- prefix minus operator */
- /* */
- /* This computes C = 0 - A */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context */
- /* */
- /* See also decNumberCopyNegate for a quiet bitwise version of this. */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- /* Simply use AddOp for the subtract, which will do the necessary. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberMinus(decNumber *res, const decNumber *rhs,
- decContext *set) {
- decNumber dzero;
- uInt status=0; // accumulator
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- decNumberZero(&dzero); // make 0
- dzero.exponent=rhs->exponent; // [no coefficient expansion]
- decAddOp(res, &dzero, rhs, set, DECNEG, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberMinus
- /* ------------------------------------------------------------------ */
- /* decNumberNextMinus -- next towards -Infinity */
- /* */
- /* This computes C = A - infinitesimal, rounded towards -Infinity */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context */
- /* */
- /* This is a generalization of 754 NextDown. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberNextMinus(decNumber *res, const decNumber *rhs,
- decContext *set) {
- decNumber dtiny; // constant
- decContext workset=*set; // work
- uInt status=0; // accumulator
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- // +Infinity is the special case
- if ((rhs->bits&(DECINF|DECNEG))==DECINF) {
- decSetMaxValue(res, set); // is +ve
- // there is no status to set
- return res;
- }
- decNumberZero(&dtiny); // start with 0
- dtiny.lsu[0]=1; // make number that is ..
- dtiny.exponent=DEC_MIN_EMIN-1; // .. smaller than tiniest
- workset.round=DEC_ROUND_FLOOR;
- decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status);
- status&=DEC_Invalid_operation|DEC_sNaN; // only sNaN Invalid please
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberNextMinus
- /* ------------------------------------------------------------------ */
- /* decNumberNextPlus -- next towards +Infinity */
- /* */
- /* This computes C = A + infinitesimal, rounded towards +Infinity */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context */
- /* */
- /* This is a generalization of 754 NextUp. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberNextPlus(decNumber *res, const decNumber *rhs,
- decContext *set) {
- decNumber dtiny; // constant
- decContext workset=*set; // work
- uInt status=0; // accumulator
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- // -Infinity is the special case
- if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
- decSetMaxValue(res, set);
- res->bits=DECNEG; // negative
- // there is no status to set
- return res;
- }
- decNumberZero(&dtiny); // start with 0
- dtiny.lsu[0]=1; // make number that is ..
- dtiny.exponent=DEC_MIN_EMIN-1; // .. smaller than tiniest
- workset.round=DEC_ROUND_CEILING;
- decAddOp(res, rhs, &dtiny, &workset, 0, &status);
- status&=DEC_Invalid_operation|DEC_sNaN; // only sNaN Invalid please
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberNextPlus
- /* ------------------------------------------------------------------ */
- /* decNumberNextToward -- next towards rhs */
- /* */
- /* This computes C = A +/- infinitesimal, rounded towards */
- /* +/-Infinity in the direction of B, as per 754-1985 nextafter */
- /* modified during revision but dropped from 754-2008. */
- /* */
- /* res is C, the result. C may be A or B. */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* This is a generalization of 754-1985 NextAfter. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberNextToward(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- decNumber dtiny; // constant
- decContext workset=*set; // work
- Int result; // ..
- uInt status=0; // accumulator
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) {
- decNaNs(res, lhs, rhs, set, &status);
- }
- else { // Is numeric, so no chance of sNaN Invalid, etc.
- result=decCompare(lhs, rhs, 0); // sign matters
- if (result==BADINT) status|=DEC_Insufficient_storage; // rare
- else { // valid compare
- if (result==0) decNumberCopySign(res, lhs, rhs); // easy
- else { // differ: need NextPlus or NextMinus
- uByte sub; // add or subtract
- if (result<0) { // lhs<rhs, do nextplus
- // -Infinity is the special case
- if ((lhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
- decSetMaxValue(res, set);
- res->bits=DECNEG; // negative
- return res; // there is no status to set
- }
- workset.round=DEC_ROUND_CEILING;
- sub=0; // add, please
- } // plus
- else { // lhs>rhs, do nextminus
- // +Infinity is the special case
- if ((lhs->bits&(DECINF|DECNEG))==DECINF) {
- decSetMaxValue(res, set);
- return res; // there is no status to set
- }
- workset.round=DEC_ROUND_FLOOR;
- sub=DECNEG; // subtract, please
- } // minus
- decNumberZero(&dtiny); // start with 0
- dtiny.lsu[0]=1; // make number that is ..
- dtiny.exponent=DEC_MIN_EMIN-1; // .. smaller than tiniest
- decAddOp(res, lhs, &dtiny, &workset, sub, &status); // + or -
- // turn off exceptions if the result is a normal number
- // (including Nmin), otherwise let all status through
- if (decNumberIsNormal(res, set)) status=0;
- } // unequal
- } // compare OK
- } // numeric
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberNextToward
- /* ------------------------------------------------------------------ */
- /* decNumberOr -- OR two Numbers, digitwise */
- /* */
- /* This computes C = A | B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X|X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context (used for result length and error report) */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Logical function restrictions apply (see above); a NaN is */
- /* returned with Invalid_operation if a restriction is violated. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberOr(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- const Unit *ua, *ub; // -> operands
- const Unit *msua, *msub; // -> operand msus
- Unit *uc, *msuc; // -> result and its msu
- Int msudigs; // digits in res msu
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
- || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
- decStatus(res, DEC_Invalid_operation, set);
- return res;
- }
- // operands are valid
- ua=lhs->lsu; // bottom-up
- ub=rhs->lsu; // ..
- uc=res->lsu; // ..
- msua=ua+D2U(lhs->digits)-1; // -> msu of lhs
- msub=ub+D2U(rhs->digits)-1; // -> msu of rhs
- msuc=uc+D2U(set->digits)-1; // -> msu of result
- msudigs=MSUDIGITS(set->digits); // [faster than remainder]
- for (; uc<=msuc; ua++, ub++, uc++) { // Unit loop
- Unit a, b; // extract units
- if (ua>msua) a=0;
- else a=*ua;
- if (ub>msub) b=0;
- else b=*ub;
- *uc=0; // can now write back
- if (a|b) { // maybe 1 bits to examine
- Int i, j;
- // This loop could be unrolled and/or use BIN2BCD tables
- for (i=0; i<DECDPUN; i++) {
- if ((a|b)&1) *uc=*uc+(Unit)powers[i]; // effect OR
- j=a%10;
- a=a/10;
- j|=b%10;
- b=b/10;
- if (j>1) {
- decStatus(res, DEC_Invalid_operation, set);
- return res;
- }
- if (uc==msuc && i==msudigs-1) break; // just did final digit
- } // each digit
- } // non-zero
- } // each unit
- // [here uc-1 is the msu of the result]
- res->digits=decGetDigits(res->lsu, uc-res->lsu);
- res->exponent=0; // integer
- res->bits=0; // sign=0
- return res; // [no status to set]
- } // decNumberOr
- /* ------------------------------------------------------------------ */
- /* decNumberPlus -- prefix plus operator */
- /* */
- /* This computes C = 0 + A */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context */
- /* */
- /* See also decNumberCopy for a quiet bitwise version of this. */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- /* This simply uses AddOp; Add will take fast path after preparing A. */
- /* Performance is a concern here, as this routine is often used to */
- /* check operands and apply rounding and overflow/underflow testing. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberPlus(decNumber *res, const decNumber *rhs,
- decContext *set) {
- decNumber dzero;
- uInt status=0; // accumulator
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- decNumberZero(&dzero); // make 0
- dzero.exponent=rhs->exponent; // [no coefficient expansion]
- decAddOp(res, &dzero, rhs, set, 0, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberPlus
- /* ------------------------------------------------------------------ */
- /* decNumberMultiply -- multiply two Numbers */
- /* */
- /* This computes C = A x B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X+X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberMultiply(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decMultiplyOp(res, lhs, rhs, set, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberMultiply
- /* ------------------------------------------------------------------ */
- /* decNumberPower -- raise a number to a power */
- /* */
- /* This computes C = A ** B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X**X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Mathematical function restrictions apply (see above); a NaN is */
- /* returned with Invalid_operation if a restriction is violated. */
- /* */
- /* However, if 1999999997<=B<=999999999 and B is an integer then the */
- /* restrictions on A and the context are relaxed to the usual bounds, */
- /* for compatibility with the earlier (integer power only) version */
- /* of this function. */
- /* */
- /* When B is an integer, the result may be exact, even if rounded. */
- /* */
- /* The final result is rounded according to the context; it will */
- /* almost always be correctly rounded, but may be up to 1 ulp in */
- /* error in rare cases. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberPower(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- #if DECSUBSET
- decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated
- decNumber *allocrhs=NULL; // .., rhs
- #endif
- decNumber *allocdac=NULL; // -> allocated acc buffer, iff used
- decNumber *allocinv=NULL; // -> allocated 1/x buffer, iff used
- Int reqdigits=set->digits; // requested DIGITS
- Int n; // rhs in binary
- Flag rhsint=0; // 1 if rhs is an integer
- Flag useint=0; // 1 if can use integer calculation
- Flag isoddint=0; // 1 if rhs is an integer and odd
- Int i; // work
- #if DECSUBSET
- Int dropped; // ..
- #endif
- uInt needbytes; // buffer size needed
- Flag seenbit; // seen a bit while powering
- Int residue=0; // rounding residue
- uInt status=0; // accumulators
- uByte bits=0; // result sign if errors
- decContext aset; // working context
- decNumber dnOne; // work value 1...
- // local accumulator buffer [a decNumber, with digits+elength+1 digits]
- decNumber dacbuff[D2N(DECBUFFER+9)];
- decNumber *dac=dacbuff; // -> result accumulator
- // same again for possible 1/lhs calculation
- decNumber invbuff[D2N(DECBUFFER+9)];
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- do { // protect allocated storage
- #if DECSUBSET
- if (!set->extended) { // reduce operands and set status, as needed
- if (lhs->digits>reqdigits) {
- alloclhs=decRoundOperand(lhs, set, &status);
- if (alloclhs==NULL) break;
- lhs=alloclhs;
- }
- if (rhs->digits>reqdigits) {
- allocrhs=decRoundOperand(rhs, set, &status);
- if (allocrhs==NULL) break;
- rhs=allocrhs;
- }
- }
- #endif
- // [following code does not require input rounding]
- // handle NaNs and rhs Infinity (lhs infinity is harder)
- if (SPECIALARGS) {
- if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { // NaNs
- decNaNs(res, lhs, rhs, set, &status);
- break;}
- if (decNumberIsInfinite(rhs)) { // rhs Infinity
- Flag rhsneg=rhs->bits&DECNEG; // save rhs sign
- if (decNumberIsNegative(lhs) // lhs<0
- && !decNumberIsZero(lhs)) // ..
- status|=DEC_Invalid_operation;
- else { // lhs >=0
- decNumberZero(&dnOne); // set up 1
- dnOne.lsu[0]=1;
- decNumberCompare(dac, lhs, &dnOne, set); // lhs ? 1
- decNumberZero(res); // prepare for 0/1/Infinity
- if (decNumberIsNegative(dac)) { // lhs<1
- if (rhsneg) res->bits|=DECINF; // +Infinity [else is +0]
- }
- else if (dac->lsu[0]==0) { // lhs=1
- // 1**Infinity is inexact, so return fully-padded 1.0000
- Int shift=set->digits-1;
- *res->lsu=1; // was 0, make int 1
- res->digits=decShiftToMost(res->lsu, 1, shift);
- res->exponent=-shift; // make 1.0000...
- status|=DEC_Inexact|DEC_Rounded; // deemed inexact
- }
- else { // lhs>1
- if (!rhsneg) res->bits|=DECINF; // +Infinity [else is +0]
- }
- } // lhs>=0
- break;}
- // [lhs infinity drops through]
- } // specials
- // Original rhs may be an integer that fits and is in range
- n=decGetInt(rhs);
- if (n!=BADINT) { // it is an integer
- rhsint=1; // record the fact for 1**n
- isoddint=(Flag)n&1; // [works even if big]
- if (n!=BIGEVEN && n!=BIGODD) // can use integer path?
- useint=1; // looks good
- }
- if (decNumberIsNegative(lhs) // -x ..
- && isoddint) bits=DECNEG; // .. to an odd power
- // handle LHS infinity
- if (decNumberIsInfinite(lhs)) { // [NaNs already handled]
- uByte rbits=rhs->bits; // save
- decNumberZero(res); // prepare
- if (n==0) *res->lsu=1; // [-]Inf**0 => 1
- else {
- // -Inf**nonint -> error
- if (!rhsint && decNumberIsNegative(lhs)) {
- status|=DEC_Invalid_operation; // -Inf**nonint is error
- break;}
- if (!(rbits & DECNEG)) bits|=DECINF; // was not a **-n
- // [otherwise will be 0 or -0]
- res->bits=bits;
- }
- break;}
- // similarly handle LHS zero
- if (decNumberIsZero(lhs)) {
- if (n==0) { // 0**0 => Error
- #if DECSUBSET
- if (!set->extended) { // [unless subset]
- decNumberZero(res);
- *res->lsu=1; // return 1
- break;}
- #endif
- status|=DEC_Invalid_operation;
- }
- else { // 0**x
- uByte rbits=rhs->bits; // save
- if (rbits & DECNEG) { // was a 0**(-n)
- #if DECSUBSET
- if (!set->extended) { // [bad if subset]
- status|=DEC_Invalid_operation;
- break;}
- #endif
- bits|=DECINF;
- }
- decNumberZero(res); // prepare
- // [otherwise will be 0 or -0]
- res->bits=bits;
- }
- break;}
- // here both lhs and rhs are finite; rhs==0 is handled in the
- // integer path. Next handle the non-integer cases
- if (!useint) { // non-integral rhs
- // any -ve lhs is bad, as is either operand or context out of
- // bounds
- if (decNumberIsNegative(lhs)) {
- status|=DEC_Invalid_operation;
- break;}
- if (decCheckMath(lhs, set, &status)
- || decCheckMath(rhs, set, &status)) break; // variable status
- decContextDefault(&aset, DEC_INIT_DECIMAL64); // clean context
- aset.emax=DEC_MAX_MATH; // usual bounds
- aset.emin=-DEC_MAX_MATH; // ..
- aset.clamp=0; // and no concrete format
- // calculate the result using exp(ln(lhs)*rhs), which can
- // all be done into the accumulator, dac. The precision needed
- // is enough to contain the full information in the lhs (which
- // is the total digits, including exponent), or the requested
- // precision, if larger, + 4; 6 is used for the exponent
- // maximum length, and this is also used when it is shorter
- // than the requested digits as it greatly reduces the >0.5 ulp
- // cases at little cost (because Ln doubles digits each
- // iteration so a few extra digits rarely causes an extra
- // iteration)
- aset.digits=MAXI(lhs->digits, set->digits)+6+4;
- } // non-integer rhs
- else { // rhs is in-range integer
- if (n==0) { // x**0 = 1
- // (0**0 was handled above)
- decNumberZero(res); // result=1
- *res->lsu=1; // ..
- break;}
- // rhs is a non-zero integer
- if (n<0) n=-n; // use abs(n)
- aset=*set; // clone the context
- aset.round=DEC_ROUND_HALF_EVEN; // internally use balanced
- // calculate the working DIGITS
- aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2;
- #if DECSUBSET
- if (!set->extended) aset.digits--; // use classic precision
- #endif
- // it's an error if this is more than can be handled
- if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;}
- } // integer path
- // aset.digits is the count of digits for the accumulator needed
- // if accumulator is too long for local storage, then allocate
- needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit);
- // [needbytes also used below if 1/lhs needed]
- if (needbytes>sizeof(dacbuff)) {
- allocdac=(decNumber *)malloc(needbytes);
- if (allocdac==NULL) { // hopeless -- abandon
- status|=DEC_Insufficient_storage;
- break;}
- dac=allocdac; // use the allocated space
- }
- // here, aset is set up and accumulator is ready for use
- if (!useint) { // non-integral rhs
- // x ** y; special-case x=1 here as it will otherwise always
- // reduce to integer 1; decLnOp has a fastpath which detects
- // the case of x=1
- decLnOp(dac, lhs, &aset, &status); // dac=ln(lhs)
- // [no error possible, as lhs 0 already handled]
- if (ISZERO(dac)) { // x==1, 1.0, etc.
- // need to return fully-padded 1.0000 etc., but rhsint->1
- *dac->lsu=1; // was 0, make int 1
- if (!rhsint) { // add padding
- Int shift=set->digits-1;
- dac->digits=decShiftToMost(dac->lsu, 1, shift);
- dac->exponent=-shift; // make 1.0000...
- status|=DEC_Inexact|DEC_Rounded; // deemed inexact
- }
- }
- else {
- decMultiplyOp(dac, dac, rhs, &aset, &status); // dac=dac*rhs
- decExpOp(dac, dac, &aset, &status); // dac=exp(dac)
- }
- // and drop through for final rounding
- } // non-integer rhs
- else { // carry on with integer
- decNumberZero(dac); // acc=1
- *dac->lsu=1; // ..
- // if a negative power the constant 1 is needed, and if not subset
- // invert the lhs now rather than inverting the result later
- if (decNumberIsNegative(rhs)) { // was a **-n [hence digits>0]
- decNumber *inv=invbuff; // asssume use fixed buffer
- decNumberCopy(&dnOne, dac); // dnOne=1; [needed now or later]
- #if DECSUBSET
- if (set->extended) { // need to calculate 1/lhs
- #endif
- // divide lhs into 1, putting result in dac [dac=1/dac]
- decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status);
- // now locate or allocate space for the inverted lhs
- if (needbytes>sizeof(invbuff)) {
- allocinv=(decNumber *)malloc(needbytes);
- if (allocinv==NULL) { // hopeless -- abandon
- status|=DEC_Insufficient_storage;
- break;}
- inv=allocinv; // use the allocated space
- }
- // [inv now points to big-enough buffer or allocated storage]
- decNumberCopy(inv, dac); // copy the 1/lhs
- decNumberCopy(dac, &dnOne); // restore acc=1
- lhs=inv; // .. and go forward with new lhs
- #if DECSUBSET
- }
- #endif
- }
- // Raise-to-the-power loop...
- seenbit=0; // set once a 1-bit is encountered
- for (i=1;;i++){ // for each bit [top bit ignored]
- // abandon if had overflow or terminal underflow
- if (status & (DEC_Overflow|DEC_Underflow)) { // interesting?
- if (status&DEC_Overflow || ISZERO(dac)) break;
- }
- // [the following two lines revealed an optimizer bug in a C++
- // compiler, with symptom: 5**3 -> 25, when n=n+n was used]
- n=n<<1; // move next bit to testable position
- if (n<0) { // top bit is set
- seenbit=1; // OK, significant bit seen
- decMultiplyOp(dac, dac, lhs, &aset, &status); // dac=dac*x
- }
- if (i==31) break; // that was the last bit
- if (!seenbit) continue; // no need to square 1
- decMultiplyOp(dac, dac, dac, &aset, &status); // dac=dac*dac [square]
- } /*i*/ // 32 bits
- // complete internal overflow or underflow processing
- if (status & (DEC_Overflow|DEC_Underflow)) {
- #if DECSUBSET
- // If subset, and power was negative, reverse the kind of -erflow
- // [1/x not yet done]
- if (!set->extended && decNumberIsNegative(rhs)) {
- if (status & DEC_Overflow)
- status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal;
- else { // trickier -- Underflow may or may not be set
- status&=~(DEC_Underflow | DEC_Subnormal); // [one or both]
- status|=DEC_Overflow;
- }
- }
- #endif
- dac->bits=(dac->bits & ~DECNEG) | bits; // force correct sign
- // round subnormals [to set.digits rather than aset.digits]
- // or set overflow result similarly as required
- decFinalize(dac, set, &residue, &status);
- decNumberCopy(res, dac); // copy to result (is now OK length)
- break;
- }
- #if DECSUBSET
- if (!set->extended && // subset math
- decNumberIsNegative(rhs)) { // was a **-n [hence digits>0]
- // so divide result into 1 [dac=1/dac]
- decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status);
- }
- #endif
- } // rhs integer path
- // reduce result to the requested length and copy to result
- decCopyFit(res, dac, set, &residue, &status);
- decFinish(res, set, &residue, &status); // final cleanup
- #if DECSUBSET
- if (!set->extended) decTrim(res, set, 0, 1, &dropped); // trailing zeros
- #endif
- } while(0); // end protected
- if (allocdac!=NULL) free(allocdac); // drop any storage used
- if (allocinv!=NULL) free(allocinv); // ..
- #if DECSUBSET
- if (alloclhs!=NULL) free(alloclhs); // ..
- if (allocrhs!=NULL) free(allocrhs); // ..
- #endif
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberPower
- /* ------------------------------------------------------------------ */
- /* decNumberQuantize -- force exponent to requested value */
- /* */
- /* This computes C = op(A, B), where op adjusts the coefficient */
- /* of C (by rounding or shifting) such that the exponent (-scale) */
- /* of C has exponent of B. The numerical value of C will equal A, */
- /* except for the effects of any rounding that occurred. */
- /* */
- /* res is C, the result. C may be A or B */
- /* lhs is A, the number to adjust */
- /* rhs is B, the number with exponent to match */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Unless there is an error or the result is infinite, the exponent */
- /* after the operation is guaranteed to be equal to that of B. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberQuantize(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decQuantizeOp(res, lhs, rhs, set, 1, &status);
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberQuantize
- /* ------------------------------------------------------------------ */
- /* decNumberReduce -- remove trailing zeros */
- /* */
- /* This computes C = 0 + A, and normalizes the result */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- // Previously known as Normalize
- decNumber * decNumberNormalize(decNumber *res, const decNumber *rhs,
- decContext *set) {
- return decNumberReduce(res, rhs, set);
- } // decNumberNormalize
- decNumber * decNumberReduce(decNumber *res, const decNumber *rhs,
- decContext *set) {
- #if DECSUBSET
- decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated
- #endif
- uInt status=0; // as usual
- Int residue=0; // as usual
- Int dropped; // work
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- do { // protect allocated storage
- #if DECSUBSET
- if (!set->extended) {
- // reduce operand and set lostDigits status, as needed
- if (rhs->digits>set->digits) {
- allocrhs=decRoundOperand(rhs, set, &status);
- if (allocrhs==NULL) break;
- rhs=allocrhs;
- }
- }
- #endif
- // [following code does not require input rounding]
- // Infinities copy through; NaNs need usual treatment
- if (decNumberIsNaN(rhs)) {
- decNaNs(res, rhs, NULL, set, &status);
- break;
- }
- // reduce result to the requested length and copy to result
- decCopyFit(res, rhs, set, &residue, &status); // copy & round
- decFinish(res, set, &residue, &status); // cleanup/set flags
- decTrim(res, set, 1, 0, &dropped); // normalize in place
- // [may clamp]
- } while(0); // end protected
- #if DECSUBSET
- if (allocrhs !=NULL) free(allocrhs); // ..
- #endif
- if (status!=0) decStatus(res, status, set);// then report status
- return res;
- } // decNumberReduce
- /* ------------------------------------------------------------------ */
- /* decNumberRescale -- force exponent to requested value */
- /* */
- /* This computes C = op(A, B), where op adjusts the coefficient */
- /* of C (by rounding or shifting) such that the exponent (-scale) */
- /* of C has the value B. The numerical value of C will equal A, */
- /* except for the effects of any rounding that occurred. */
- /* */
- /* res is C, the result. C may be A or B */
- /* lhs is A, the number to adjust */
- /* rhs is B, the requested exponent */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Unless there is an error or the result is infinite, the exponent */
- /* after the operation is guaranteed to be equal to B. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberRescale(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decQuantizeOp(res, lhs, rhs, set, 0, &status);
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberRescale
- /* ------------------------------------------------------------------ */
- /* decNumberRemainder -- divide and return remainder */
- /* */
- /* This computes C = A % B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X%X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberRemainder(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decDivideOp(res, lhs, rhs, set, REMAINDER, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberRemainder
- /* ------------------------------------------------------------------ */
- /* decNumberRemainderNear -- divide and return remainder from nearest */
- /* */
- /* This computes C = A % B, where % is the IEEE remainder operator */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X%X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberRemainderNear(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decDivideOp(res, lhs, rhs, set, REMNEAR, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberRemainderNear
- /* ------------------------------------------------------------------ */
- /* decNumberRotate -- rotate the coefficient of a Number left/right */
- /* */
- /* This computes C = A rot B (in base ten and rotating set->digits */
- /* digits). */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=XrotX) */
- /* lhs is A */
- /* rhs is B, the number of digits to rotate (-ve to right) */
- /* set is the context */
- /* */
- /* The digits of the coefficient of A are rotated to the left (if B */
- /* is positive) or to the right (if B is negative) without adjusting */
- /* the exponent or the sign of A. If lhs->digits is less than */
- /* set->digits the coefficient is padded with zeros on the left */
- /* before the rotate. Any leading zeros in the result are removed */
- /* as usual. */
- /* */
- /* B must be an integer (q=0) and in the range -set->digits through */
- /* +set->digits. */
- /* C must have space for set->digits digits. */
- /* NaNs are propagated as usual. Infinities are unaffected (but */
- /* B must be valid). No status is set unless B is invalid or an */
- /* operand is an sNaN. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberRotate(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- Int rotate; // rhs as an Int
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- // NaNs propagate as normal
- if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
- decNaNs(res, lhs, rhs, set, &status);
- // rhs must be an integer
- else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
- status=DEC_Invalid_operation;
- else { // both numeric, rhs is an integer
- rotate=decGetInt(rhs); // [cannot fail]
- if (rotate==BADINT // something bad ..
- || rotate==BIGODD || rotate==BIGEVEN // .. very big ..
- || abs(rotate)>set->digits) // .. or out of range
- status=DEC_Invalid_operation;
- else { // rhs is OK
- decNumberCopy(res, lhs);
- // convert -ve rotate to equivalent positive rotation
- if (rotate<0) rotate=set->digits+rotate;
- if (rotate!=0 && rotate!=set->digits // zero or full rotation
- && !decNumberIsInfinite(res)) { // lhs was infinite
- // left-rotate to do; 0 < rotate < set->digits
- uInt units, shift; // work
- uInt msudigits; // digits in result msu
- Unit *msu=res->lsu+D2U(res->digits)-1; // current msu
- Unit *msumax=res->lsu+D2U(set->digits)-1; // rotation msu
- for (msu++; msu<=msumax; msu++) *msu=0; // ensure high units=0
- res->digits=set->digits; // now full-length
- msudigits=MSUDIGITS(res->digits); // actual digits in msu
- // rotation here is done in-place, in three steps
- // 1. shift all to least up to one unit to unit-align final
- // lsd [any digits shifted out are rotated to the left,
- // abutted to the original msd (which may require split)]
- //
- // [if there are no whole units left to rotate, the
- // rotation is now complete]
- //
- // 2. shift to least, from below the split point only, so that
- // the final msd is in the right place in its Unit [any
- // digits shifted out will fit exactly in the current msu,
- // left aligned, no split required]
- //
- // 3. rotate all the units by reversing left part, right
- // part, and then whole
- //
- // example: rotate right 8 digits (2 units + 2), DECDPUN=3.
- //
- // start: 00a bcd efg hij klm npq
- //
- // 1a 000 0ab cde fgh|ijk lmn [pq saved]
- // 1b 00p qab cde fgh|ijk lmn
- //
- // 2a 00p qab cde fgh|00i jkl [mn saved]
- // 2b mnp qab cde fgh|00i jkl
- //
- // 3a fgh cde qab mnp|00i jkl
- // 3b fgh cde qab mnp|jkl 00i
- // 3c 00i jkl mnp qab cde fgh
- // Step 1: amount to shift is the partial right-rotate count
- rotate=set->digits-rotate; // make it right-rotate
- units=rotate/DECDPUN; // whole units to rotate
- shift=rotate%DECDPUN; // left-over digits count
- if (shift>0) { // not an exact number of units
- uInt save=res->lsu[0]%powers[shift]; // save low digit(s)
- decShiftToLeast(res->lsu, D2U(res->digits), shift);
- if (shift>msudigits) { // msumax-1 needs >0 digits
- uInt rem=save%powers[shift-msudigits];// split save
- *msumax=(Unit)(save/powers[shift-msudigits]); // and insert
- *(msumax-1)=*(msumax-1)
- +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); // ..
- }
- else { // all fits in msumax
- *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); // [maybe *1]
- }
- } // digits shift needed
- // If whole units to rotate...
- if (units>0) { // some to do
- // Step 2: the units to touch are the whole ones in rotate,
- // if any, and the shift is DECDPUN-msudigits (which may be
- // 0, again)
- shift=DECDPUN-msudigits;
- if (shift>0) { // not an exact number of units
- uInt save=res->lsu[0]%powers[shift]; // save low digit(s)
- decShiftToLeast(res->lsu, units, shift);
- *msumax=*msumax+(Unit)(save*powers[msudigits]);
- } // partial shift needed
- // Step 3: rotate the units array using triple reverse
- // (reversing is easy and fast)
- decReverse(res->lsu+units, msumax); // left part
- decReverse(res->lsu, res->lsu+units-1); // right part
- decReverse(res->lsu, msumax); // whole
- } // whole units to rotate
- // the rotation may have left an undetermined number of zeros
- // on the left, so true length needs to be calculated
- res->digits=decGetDigits(res->lsu, msumax-res->lsu+1);
- } // rotate needed
- } // rhs OK
- } // numerics
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberRotate
- /* ------------------------------------------------------------------ */
- /* decNumberSameQuantum -- test for equal exponents */
- /* */
- /* res is the result number, which will contain either 0 or 1 */
- /* lhs is a number to test */
- /* rhs is the second (usually a pattern) */
- /* */
- /* No errors are possible and no context is needed. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberSameQuantum(decNumber *res, const decNumber *lhs,
- const decNumber *rhs) {
- Unit ret=0; // return value
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res;
- #endif
- if (SPECIALARGS) {
- if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1;
- else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1;
- // [anything else with a special gives 0]
- }
- else if (lhs->exponent==rhs->exponent) ret=1;
- decNumberZero(res); // OK to overwrite an operand now
- *res->lsu=ret;
- return res;
- } // decNumberSameQuantum
- /* ------------------------------------------------------------------ */
- /* decNumberScaleB -- multiply by a power of 10 */
- /* */
- /* This computes C = A x 10**B where B is an integer (q=0) with */
- /* maximum magnitude 2*(emax+digits) */
- /* */
- /* res is C, the result. C may be A or B */
- /* lhs is A, the number to adjust */
- /* rhs is B, the requested power of ten to use */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* The result may underflow or overflow. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberScaleB(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- Int reqexp; // requested exponent change [B]
- uInt status=0; // accumulator
- Int residue; // work
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- // Handle special values except lhs infinite
- if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
- decNaNs(res, lhs, rhs, set, &status);
- // rhs must be an integer
- else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
- status=DEC_Invalid_operation;
- else {
- // lhs is a number; rhs is a finite with q==0
- reqexp=decGetInt(rhs); // [cannot fail]
- // maximum range is larger than getInt can handle, so this is
- // more restrictive than the specification
- if (reqexp==BADINT // something bad ..
- || reqexp==BIGODD || reqexp==BIGEVEN // it was huge
- || (abs(reqexp)+1)/2>(set->digits+set->emax)) // .. or out of range
- status=DEC_Invalid_operation;
- else { // rhs is OK
- decNumberCopy(res, lhs); // all done if infinite lhs
- if (!decNumberIsInfinite(res)) { // prepare to scale
- Int exp=res->exponent; // save for overflow test
- res->exponent+=reqexp; // adjust the exponent
- if (((exp^reqexp)>=0) // same sign ...
- && ((exp^res->exponent)<0)) { // .. but result had different
- // the calculation overflowed, so force right treatment
- if (exp<0) res->exponent=DEC_MIN_EMIN-DEC_MAX_DIGITS;
- else res->exponent=DEC_MAX_EMAX+1;
- }
- residue=0;
- decFinalize(res, set, &residue, &status); // final check
- } // finite LHS
- } // rhs OK
- } // rhs finite
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberScaleB
- /* ------------------------------------------------------------------ */
- /* decNumberShift -- shift the coefficient of a Number left or right */
- /* */
- /* This computes C = A << B or C = A >> -B (in base ten). */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X<<X) */
- /* lhs is A */
- /* rhs is B, the number of digits to shift (-ve to right) */
- /* set is the context */
- /* */
- /* The digits of the coefficient of A are shifted to the left (if B */
- /* is positive) or to the right (if B is negative) without adjusting */
- /* the exponent or the sign of A. */
- /* */
- /* B must be an integer (q=0) and in the range -set->digits through */
- /* +set->digits. */
- /* C must have space for set->digits digits. */
- /* NaNs are propagated as usual. Infinities are unaffected (but */
- /* B must be valid). No status is set unless B is invalid or an */
- /* operand is an sNaN. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberShift(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- Int shift; // rhs as an Int
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- // NaNs propagate as normal
- if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
- decNaNs(res, lhs, rhs, set, &status);
- // rhs must be an integer
- else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
- status=DEC_Invalid_operation;
- else { // both numeric, rhs is an integer
- shift=decGetInt(rhs); // [cannot fail]
- if (shift==BADINT // something bad ..
- || shift==BIGODD || shift==BIGEVEN // .. very big ..
- || abs(shift)>set->digits) // .. or out of range
- status=DEC_Invalid_operation;
- else { // rhs is OK
- decNumberCopy(res, lhs);
- if (shift!=0 && !decNumberIsInfinite(res)) { // something to do
- if (shift>0) { // to left
- if (shift==set->digits) { // removing all
- *res->lsu=0; // so place 0
- res->digits=1; // ..
- }
- else { //
- // first remove leading digits if necessary
- if (res->digits+shift>set->digits) {
- decDecap(res, res->digits+shift-set->digits);
- // that updated res->digits; may have gone to 1 (for a
- // single digit or for zero
- }
- if (res->digits>1 || *res->lsu) // if non-zero..
- res->digits=decShiftToMost(res->lsu, res->digits, shift);
- } // partial left
- } // left
- else { // to right
- if (-shift>=res->digits) { // discarding all
- *res->lsu=0; // so place 0
- res->digits=1; // ..
- }
- else {
- decShiftToLeast(res->lsu, D2U(res->digits), -shift);
- res->digits-=(-shift);
- }
- } // to right
- } // non-0 non-Inf shift
- } // rhs OK
- } // numerics
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberShift
- /* ------------------------------------------------------------------ */
- /* decNumberSquareRoot -- square root operator */
- /* */
- /* This computes C = squareroot(A) */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context; note that rounding mode has no effect */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- /* This uses the following varying-precision algorithm in: */
- /* */
- /* Properly Rounded Variable Precision Square Root, T. E. Hull and */
- /* A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */
- /* pp229-237, ACM, September 1985. */
- /* */
- /* The square-root is calculated using Newton's method, after which */
- /* a check is made to ensure the result is correctly rounded. */
- /* */
- /* % [Reformatted original Numerical Turing source code follows.] */
- /* function sqrt(x : real) : real */
- /* % sqrt(x) returns the properly rounded approximation to the square */
- /* % root of x, in the precision of the calling environment, or it */
- /* % fails if x < 0. */
- /* % t e hull and a abrham, august, 1984 */
- /* if x <= 0 then */
- /* if x < 0 then */
- /* assert false */
- /* else */
- /* result 0 */
- /* end if */
- /* end if */
- /* var f := setexp(x, 0) % fraction part of x [0.1 <= x < 1] */
- /* var e := getexp(x) % exponent part of x */
- /* var approx : real */
- /* if e mod 2 = 0 then */
- /* approx := .259 + .819 * f % approx to root of f */
- /* else */
- /* f := f/l0 % adjustments */
- /* e := e + 1 % for odd */
- /* approx := .0819 + 2.59 * f % exponent */
- /* end if */
- /* */
- /* var p:= 3 */
- /* const maxp := currentprecision + 2 */
- /* loop */
- /* p := min(2*p - 2, maxp) % p = 4,6,10, . . . , maxp */
- /* precision p */
- /* approx := .5 * (approx + f/approx) */
- /* exit when p = maxp */
- /* end loop */
- /* */
- /* % approx is now within 1 ulp of the properly rounded square root */
- /* % of f; to ensure proper rounding, compare squares of (approx - */
- /* % l/2 ulp) and (approx + l/2 ulp) with f. */
- /* p := currentprecision */
- /* begin */
- /* precision p + 2 */
- /* const approxsubhalf := approx - setexp(.5, -p) */
- /* if mulru(approxsubhalf, approxsubhalf) > f then */
- /* approx := approx - setexp(.l, -p + 1) */
- /* else */
- /* const approxaddhalf := approx + setexp(.5, -p) */
- /* if mulrd(approxaddhalf, approxaddhalf) < f then */
- /* approx := approx + setexp(.l, -p + 1) */
- /* end if */
- /* end if */
- /* end */
- /* result setexp(approx, e div 2) % fix exponent */
- /* end sqrt */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberSquareRoot(decNumber *res, const decNumber *rhs,
- decContext *set) {
- decContext workset, approxset; // work contexts
- decNumber dzero; // used for constant zero
- Int maxp; // largest working precision
- Int workp; // working precision
- Int residue=0; // rounding residue
- uInt status=0, ignore=0; // status accumulators
- uInt rstatus; // ..
- Int exp; // working exponent
- Int ideal; // ideal (preferred) exponent
- Int needbytes; // work
- Int dropped; // ..
- #if DECSUBSET
- decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated
- #endif
- // buffer for f [needs +1 in case DECBUFFER 0]
- decNumber buff[D2N(DECBUFFER+1)];
- // buffer for a [needs +2 to match likely maxp]
- decNumber bufa[D2N(DECBUFFER+2)];
- // buffer for temporary, b [must be same size as a]
- decNumber bufb[D2N(DECBUFFER+2)];
- decNumber *allocbuff=NULL; // -> allocated buff, iff allocated
- decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated
- decNumber *allocbufb=NULL; // -> allocated bufb, iff allocated
- decNumber *f=buff; // reduced fraction
- decNumber *a=bufa; // approximation to result
- decNumber *b=bufb; // intermediate result
- // buffer for temporary variable, up to 3 digits
- decNumber buft[D2N(3)];
- decNumber *t=buft; // up-to-3-digit constant or work
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- do { // protect allocated storage
- #if DECSUBSET
- if (!set->extended) {
- // reduce operand and set lostDigits status, as needed
- if (rhs->digits>set->digits) {
- allocrhs=decRoundOperand(rhs, set, &status);
- if (allocrhs==NULL) break;
- // [Note: 'f' allocation below could reuse this buffer if
- // used, but as this is rare they are kept separate for clarity.]
- rhs=allocrhs;
- }
- }
- #endif
- // [following code does not require input rounding]
- // handle infinities and NaNs
- if (SPECIALARG) {
- if (decNumberIsInfinite(rhs)) { // an infinity
- if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation;
- else decNumberCopy(res, rhs); // +Infinity
- }
- else decNaNs(res, rhs, NULL, set, &status); // a NaN
- break;
- }
- // calculate the ideal (preferred) exponent [floor(exp/2)]
- // [It would be nicer to write: ideal=rhs->exponent>>1, but this
- // generates a compiler warning. Generated code is the same.]
- ideal=(rhs->exponent&~1)/2; // target
- // handle zeros
- if (ISZERO(rhs)) {
- decNumberCopy(res, rhs); // could be 0 or -0
- res->exponent=ideal; // use the ideal [safe]
- // use decFinish to clamp any out-of-range exponent, etc.
- decFinish(res, set, &residue, &status);
- break;
- }
- // any other -x is an oops
- if (decNumberIsNegative(rhs)) {
- status|=DEC_Invalid_operation;
- break;
- }
- // space is needed for three working variables
- // f -- the same precision as the RHS, reduced to 0.01->0.99...
- // a -- Hull's approximation -- precision, when assigned, is
- // currentprecision+1 or the input argument precision,
- // whichever is larger (+2 for use as temporary)
- // b -- intermediate temporary result (same size as a)
- // if any is too long for local storage, then allocate
- workp=MAXI(set->digits+1, rhs->digits); // actual rounding precision
- workp=MAXI(workp, 7); // at least 7 for low cases
- maxp=workp+2; // largest working precision
- needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
- if (needbytes>(Int)sizeof(buff)) {
- allocbuff=(decNumber *)malloc(needbytes);
- if (allocbuff==NULL) { // hopeless -- abandon
- status|=DEC_Insufficient_storage;
- break;}
- f=allocbuff; // use the allocated space
- }
- // a and b both need to be able to hold a maxp-length number
- needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit);
- if (needbytes>(Int)sizeof(bufa)) { // [same applies to b]
- allocbufa=(decNumber *)malloc(needbytes);
- allocbufb=(decNumber *)malloc(needbytes);
- if (allocbufa==NULL || allocbufb==NULL) { // hopeless
- status|=DEC_Insufficient_storage;
- break;}
- a=allocbufa; // use the allocated spaces
- b=allocbufb; // ..
- }
- // copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1
- decNumberCopy(f, rhs);
- exp=f->exponent+f->digits; // adjusted to Hull rules
- f->exponent=-(f->digits); // to range
- // set up working context
- decContextDefault(&workset, DEC_INIT_DECIMAL64);
- workset.emax=DEC_MAX_EMAX;
- workset.emin=DEC_MIN_EMIN;
- // [Until further notice, no error is possible and status bits
- // (Rounded, etc.) should be ignored, not accumulated.]
- // Calculate initial approximation, and allow for odd exponent
- workset.digits=workp; // p for initial calculation
- t->bits=0; t->digits=3;
- a->bits=0; a->digits=3;
- if ((exp & 1)==0) { // even exponent
- // Set t=0.259, a=0.819
- t->exponent=-3;
- a->exponent=-3;
- #if DECDPUN>=3
- t->lsu[0]=259;
- a->lsu[0]=819;
- #elif DECDPUN==2
- t->lsu[0]=59; t->lsu[1]=2;
- a->lsu[0]=19; a->lsu[1]=8;
- #else
- t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2;
- a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8;
- #endif
- }
- else { // odd exponent
- // Set t=0.0819, a=2.59
- f->exponent--; // f=f/10
- exp++; // e=e+1
- t->exponent=-4;
- a->exponent=-2;
- #if DECDPUN>=3
- t->lsu[0]=819;
- a->lsu[0]=259;
- #elif DECDPUN==2
- t->lsu[0]=19; t->lsu[1]=8;
- a->lsu[0]=59; a->lsu[1]=2;
- #else
- t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8;
- a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2;
- #endif
- }
- decMultiplyOp(a, a, f, &workset, &ignore); // a=a*f
- decAddOp(a, a, t, &workset, 0, &ignore); // ..+t
- // [a is now the initial approximation for sqrt(f), calculated with
- // currentprecision, which is also a's precision.]
- // the main calculation loop
- decNumberZero(&dzero); // make 0
- decNumberZero(t); // set t = 0.5
- t->lsu[0]=5; // ..
- t->exponent=-1; // ..
- workset.digits=3; // initial p
- for (; workset.digits<maxp;) {
- // set p to min(2*p - 2, maxp) [hence 3; or: 4, 6, 10, ... , maxp]
- workset.digits=MINI(workset.digits*2-2, maxp);
- // a = 0.5 * (a + f/a)
- // [calculated at p then rounded to currentprecision]
- decDivideOp(b, f, a, &workset, DIVIDE, &ignore); // b=f/a
- decAddOp(b, b, a, &workset, 0, &ignore); // b=b+a
- decMultiplyOp(a, b, t, &workset, &ignore); // a=b*0.5
- } // loop
- // Here, 0.1 <= a < 1 [Hull], and a has maxp digits
- // now reduce to length, etc.; this needs to be done with a
- // having the correct exponent so as to handle subnormals
- // correctly
- approxset=*set; // get emin, emax, etc.
- approxset.round=DEC_ROUND_HALF_EVEN;
- a->exponent+=exp/2; // set correct exponent
- rstatus=0; // clear status
- residue=0; // .. and accumulator
- decCopyFit(a, a, &approxset, &residue, &rstatus); // reduce (if needed)
- decFinish(a, &approxset, &residue, &rstatus); // clean and finalize
- // Overflow was possible if the input exponent was out-of-range,
- // in which case quit
- if (rstatus&DEC_Overflow) {
- status=rstatus; // use the status as-is
- decNumberCopy(res, a); // copy to result
- break;
- }
- // Preserve status except Inexact/Rounded
- status|=(rstatus & ~(DEC_Rounded|DEC_Inexact));
- // Carry out the Hull correction
- a->exponent-=exp/2; // back to 0.1->1
- // a is now at final precision and within 1 ulp of the properly
- // rounded square root of f; to ensure proper rounding, compare
- // squares of (a - l/2 ulp) and (a + l/2 ulp) with f.
- // Here workset.digits=maxp and t=0.5, and a->digits determines
- // the ulp
- workset.digits--; // maxp-1 is OK now
- t->exponent=-a->digits-1; // make 0.5 ulp
- decAddOp(b, a, t, &workset, DECNEG, &ignore); // b = a - 0.5 ulp
- workset.round=DEC_ROUND_UP;
- decMultiplyOp(b, b, b, &workset, &ignore); // b = mulru(b, b)
- decCompareOp(b, f, b, &workset, COMPARE, &ignore); // b ? f, reversed
- if (decNumberIsNegative(b)) { // f < b [i.e., b > f]
- // this is the more common adjustment, though both are rare
- t->exponent++; // make 1.0 ulp
- t->lsu[0]=1; // ..
- decAddOp(a, a, t, &workset, DECNEG, &ignore); // a = a - 1 ulp
- // assign to approx [round to length]
- approxset.emin-=exp/2; // adjust to match a
- approxset.emax-=exp/2;
- decAddOp(a, &dzero, a, &approxset, 0, &ignore);
- }
- else {
- decAddOp(b, a, t, &workset, 0, &ignore); // b = a + 0.5 ulp
- workset.round=DEC_ROUND_DOWN;
- decMultiplyOp(b, b, b, &workset, &ignore); // b = mulrd(b, b)
- decCompareOp(b, b, f, &workset, COMPARE, &ignore); // b ? f
- if (decNumberIsNegative(b)) { // b < f
- t->exponent++; // make 1.0 ulp
- t->lsu[0]=1; // ..
- decAddOp(a, a, t, &workset, 0, &ignore); // a = a + 1 ulp
- // assign to approx [round to length]
- approxset.emin-=exp/2; // adjust to match a
- approxset.emax-=exp/2;
- decAddOp(a, &dzero, a, &approxset, 0, &ignore);
- }
- }
- // [no errors are possible in the above, and rounding/inexact during
- // estimation are irrelevant, so status was not accumulated]
- // Here, 0.1 <= a < 1 (still), so adjust back
- a->exponent+=exp/2; // set correct exponent
- // count droppable zeros [after any subnormal rounding] by
- // trimming a copy
- decNumberCopy(b, a);
- decTrim(b, set, 1, 1, &dropped); // [drops trailing zeros]
- // Set Inexact and Rounded. The answer can only be exact if
- // it is short enough so that squaring it could fit in workp
- // digits, so this is the only (relatively rare) condition that
- // a careful check is needed
- if (b->digits*2-1 > workp) { // cannot fit
- status|=DEC_Inexact|DEC_Rounded;
- }
- else { // could be exact/unrounded
- uInt mstatus=0; // local status
- decMultiplyOp(b, b, b, &workset, &mstatus); // try the multiply
- if (mstatus&DEC_Overflow) { // result just won't fit
- status|=DEC_Inexact|DEC_Rounded;
- }
- else { // plausible
- decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); // b ? rhs
- if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; // not equal
- else { // is Exact
- // here, dropped is the count of trailing zeros in 'a'
- // use closest exponent to ideal...
- Int todrop=ideal-a->exponent; // most that can be dropped
- if (todrop<0) status|=DEC_Rounded; // ideally would add 0s
- else { // unrounded
- // there are some to drop, but emax may not allow all
- Int maxexp=set->emax-set->digits+1;
- Int maxdrop=maxexp-a->exponent;
- if (todrop>maxdrop && set->clamp) { // apply clamping
- todrop=maxdrop;
- status|=DEC_Clamped;
- }
- if (dropped<todrop) { // clamp to those available
- todrop=dropped;
- status|=DEC_Clamped;
- }
- if (todrop>0) { // have some to drop
- decShiftToLeast(a->lsu, D2U(a->digits), todrop);
- a->exponent+=todrop; // maintain numerical value
- a->digits-=todrop; // new length
- }
- }
- }
- }
- }
- // double-check Underflow, as perhaps the result could not have
- // been subnormal (initial argument too big), or it is now Exact
- if (status&DEC_Underflow) {
- Int ae=rhs->exponent+rhs->digits-1; // adjusted exponent
- // check if truly subnormal
- #if DECEXTFLAG // DEC_Subnormal too
- if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow);
- #else
- if (ae>=set->emin*2) status&=~DEC_Underflow;
- #endif
- // check if truly inexact
- if (!(status&DEC_Inexact)) status&=~DEC_Underflow;
- }
- decNumberCopy(res, a); // a is now the result
- } while(0); // end protected
- if (allocbuff!=NULL) free(allocbuff); // drop any storage used
- if (allocbufa!=NULL) free(allocbufa); // ..
- if (allocbufb!=NULL) free(allocbufb); // ..
- #if DECSUBSET
- if (allocrhs !=NULL) free(allocrhs); // ..
- #endif
- if (status!=0) decStatus(res, status, set);// then report status
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberSquareRoot
- /* ------------------------------------------------------------------ */
- /* decNumberSubtract -- subtract two Numbers */
- /* */
- /* This computes C = A - B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X-X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* */
- /* C must have space for set->digits digits. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberSubtract(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- uInt status=0; // accumulator
- decAddOp(res, lhs, rhs, set, DECNEG, &status);
- if (status!=0) decStatus(res, status, set);
- #if DECCHECK
- decCheckInexact(res, set);
- #endif
- return res;
- } // decNumberSubtract
- /* ------------------------------------------------------------------ */
- /* decNumberToIntegralExact -- round-to-integral-value with InExact */
- /* decNumberToIntegralValue -- round-to-integral-value */
- /* */
- /* res is the result */
- /* rhs is input number */
- /* set is the context */
- /* */
- /* res must have space for any value of rhs. */
- /* */
- /* This implements the IEEE special operators and therefore treats */
- /* special values as valid. For finite numbers it returns */
- /* rescale(rhs, 0) if rhs->exponent is <0. */
- /* Otherwise the result is rhs (so no error is possible, except for */
- /* sNaN). */
- /* */
- /* The context is used for rounding mode and status after sNaN, but */
- /* the digits setting is ignored. The Exact version will signal */
- /* Inexact if the result differs numerically from rhs; the other */
- /* never signals Inexact. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberToIntegralExact(decNumber *res, const decNumber *rhs,
- decContext *set) {
- decNumber dn;
- decContext workset; // working context
- uInt status=0; // accumulator
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- // handle infinities and NaNs
- if (SPECIALARG) {
- if (decNumberIsInfinite(rhs)) decNumberCopy(res, rhs); // an Infinity
- else decNaNs(res, rhs, NULL, set, &status); // a NaN
- }
- else { // finite
- // have a finite number; no error possible (res must be big enough)
- if (rhs->exponent>=0) return decNumberCopy(res, rhs);
- // that was easy, but if negative exponent there is work to do...
- workset=*set; // clone rounding, etc.
- workset.digits=rhs->digits; // no length rounding
- workset.traps=0; // no traps
- decNumberZero(&dn); // make a number with exponent 0
- decNumberQuantize(res, rhs, &dn, &workset);
- status|=workset.status;
- }
- if (status!=0) decStatus(res, status, set);
- return res;
- } // decNumberToIntegralExact
- decNumber * decNumberToIntegralValue(decNumber *res, const decNumber *rhs,
- decContext *set) {
- decContext workset=*set; // working context
- workset.traps=0; // no traps
- decNumberToIntegralExact(res, rhs, &workset);
- // this never affects set, except for sNaNs; NaN will have been set
- // or propagated already, so no need to call decStatus
- set->status|=workset.status&DEC_Invalid_operation;
- return res;
- } // decNumberToIntegralValue
- /* ------------------------------------------------------------------ */
- /* decNumberXor -- XOR two Numbers, digitwise */
- /* */
- /* This computes C = A ^ B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X^X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context (used for result length and error report) */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Logical function restrictions apply (see above); a NaN is */
- /* returned with Invalid_operation if a restriction is violated. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberXor(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- const Unit *ua, *ub; // -> operands
- const Unit *msua, *msub; // -> operand msus
- Unit *uc, *msuc; // -> result and its msu
- Int msudigs; // digits in res msu
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
- || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
- decStatus(res, DEC_Invalid_operation, set);
- return res;
- }
- // operands are valid
- ua=lhs->lsu; // bottom-up
- ub=rhs->lsu; // ..
- uc=res->lsu; // ..
- msua=ua+D2U(lhs->digits)-1; // -> msu of lhs
- msub=ub+D2U(rhs->digits)-1; // -> msu of rhs
- msuc=uc+D2U(set->digits)-1; // -> msu of result
- msudigs=MSUDIGITS(set->digits); // [faster than remainder]
- for (; uc<=msuc; ua++, ub++, uc++) { // Unit loop
- Unit a, b; // extract units
- if (ua>msua) a=0;
- else a=*ua;
- if (ub>msub) b=0;
- else b=*ub;
- *uc=0; // can now write back
- if (a|b) { // maybe 1 bits to examine
- Int i, j;
- // This loop could be unrolled and/or use BIN2BCD tables
- for (i=0; i<DECDPUN; i++) {
- if ((a^b)&1) *uc=*uc+(Unit)powers[i]; // effect XOR
- j=a%10;
- a=a/10;
- j|=b%10;
- b=b/10;
- if (j>1) {
- decStatus(res, DEC_Invalid_operation, set);
- return res;
- }
- if (uc==msuc && i==msudigs-1) break; // just did final digit
- } // each digit
- } // non-zero
- } // each unit
- // [here uc-1 is the msu of the result]
- res->digits=decGetDigits(res->lsu, uc-res->lsu);
- res->exponent=0; // integer
- res->bits=0; // sign=0
- return res; // [no status to set]
- } // decNumberXor
- /* ================================================================== */
- /* Utility routines */
- /* ================================================================== */
- /* ------------------------------------------------------------------ */
- /* decNumberClass -- return the decClass of a decNumber */
- /* dn -- the decNumber to test */
- /* set -- the context to use for Emin */
- /* returns the decClass enum */
- /* ------------------------------------------------------------------ */
- enum decClass decNumberClass(const decNumber *dn, decContext *set) {
- if (decNumberIsSpecial(dn)) {
- if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN;
- if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN;
- // must be an infinity
- if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF;
- return DEC_CLASS_POS_INF;
- }
- // is finite
- if (decNumberIsNormal(dn, set)) { // most common
- if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL;
- return DEC_CLASS_POS_NORMAL;
- }
- // is subnormal or zero
- if (decNumberIsZero(dn)) { // most common
- if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO;
- return DEC_CLASS_POS_ZERO;
- }
- if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL;
- return DEC_CLASS_POS_SUBNORMAL;
- } // decNumberClass
- /* ------------------------------------------------------------------ */
- /* decNumberClassToString -- convert decClass to a string */
- /* */
- /* eclass is a valid decClass */
- /* returns a constant string describing the class (max 13+1 chars) */
- /* ------------------------------------------------------------------ */
- const char *decNumberClassToString(enum decClass eclass) {
- if (eclass==DEC_CLASS_POS_NORMAL) return DEC_ClassString_PN;
- if (eclass==DEC_CLASS_NEG_NORMAL) return DEC_ClassString_NN;
- if (eclass==DEC_CLASS_POS_ZERO) return DEC_ClassString_PZ;
- if (eclass==DEC_CLASS_NEG_ZERO) return DEC_ClassString_NZ;
- if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS;
- if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS;
- if (eclass==DEC_CLASS_POS_INF) return DEC_ClassString_PI;
- if (eclass==DEC_CLASS_NEG_INF) return DEC_ClassString_NI;
- if (eclass==DEC_CLASS_QNAN) return DEC_ClassString_QN;
- if (eclass==DEC_CLASS_SNAN) return DEC_ClassString_SN;
- return DEC_ClassString_UN; // Unknown
- } // decNumberClassToString
- /* ------------------------------------------------------------------ */
- /* decNumberCopy -- copy a number */
- /* */
- /* dest is the target decNumber */
- /* src is the source decNumber */
- /* returns dest */
- /* */
- /* (dest==src is allowed and is a no-op) */
- /* All fields are updated as required. This is a utility operation, */
- /* so special values are unchanged and no error is possible. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberCopy(decNumber *dest, const decNumber *src) {
- #if DECCHECK
- if (src==NULL) return decNumberZero(dest);
- #endif
- if (dest==src) return dest; // no copy required
- // Use explicit assignments here as structure assignment could copy
- // more than just the lsu (for small DECDPUN). This would not affect
- // the value of the results, but could disturb test harness spill
- // checking.
- dest->bits=src->bits;
- dest->exponent=src->exponent;
- dest->digits=src->digits;
- dest->lsu[0]=src->lsu[0];
- if (src->digits>DECDPUN) { // more Units to come
- const Unit *smsup, *s; // work
- Unit *d; // ..
- // memcpy for the remaining Units would be safe as they cannot
- // overlap. However, this explicit loop is faster in short cases.
- d=dest->lsu+1; // -> first destination
- smsup=src->lsu+D2U(src->digits); // -> source msu+1
- for (s=src->lsu+1; s<smsup; s++, d++) *d=*s;
- }
- return dest;
- } // decNumberCopy
- /* ------------------------------------------------------------------ */
- /* decNumberCopyAbs -- quiet absolute value operator */
- /* */
- /* This sets C = abs(A) */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* */
- /* C must have space for set->digits digits. */
- /* No exception or error can occur; this is a quiet bitwise operation.*/
- /* See also decNumberAbs for a checking version of this. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberCopyAbs(decNumber *res, const decNumber *rhs) {
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
- #endif
- decNumberCopy(res, rhs);
- res->bits&=~DECNEG; // turn off sign
- return res;
- } // decNumberCopyAbs
- /* ------------------------------------------------------------------ */
- /* decNumberCopyNegate -- quiet negate value operator */
- /* */
- /* This sets C = negate(A) */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* */
- /* C must have space for set->digits digits. */
- /* No exception or error can occur; this is a quiet bitwise operation.*/
- /* See also decNumberMinus for a checking version of this. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberCopyNegate(decNumber *res, const decNumber *rhs) {
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
- #endif
- decNumberCopy(res, rhs);
- res->bits^=DECNEG; // invert the sign
- return res;
- } // decNumberCopyNegate
- /* ------------------------------------------------------------------ */
- /* decNumberCopySign -- quiet copy and set sign operator */
- /* */
- /* This sets C = A with the sign of B */
- /* */
- /* res is C, the result. C may be A */
- /* lhs is A */
- /* rhs is B */
- /* */
- /* C must have space for set->digits digits. */
- /* No exception or error can occur; this is a quiet bitwise operation.*/
- /* ------------------------------------------------------------------ */
- decNumber * decNumberCopySign(decNumber *res, const decNumber *lhs,
- const decNumber *rhs) {
- uByte sign; // rhs sign
- #if DECCHECK
- if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
- #endif
- sign=rhs->bits & DECNEG; // save sign bit
- decNumberCopy(res, lhs);
- res->bits&=~DECNEG; // clear the sign
- res->bits|=sign; // set from rhs
- return res;
- } // decNumberCopySign
- /* ------------------------------------------------------------------ */
- /* decNumberGetBCD -- get the coefficient in BCD8 */
- /* dn is the source decNumber */
- /* bcd is the uInt array that will receive dn->digits BCD bytes, */
- /* most-significant at offset 0 */
- /* returns bcd */
- /* */
- /* bcd must have at least dn->digits bytes. No error is possible; if */
- /* dn is a NaN or Infinite, digits must be 1 and the coefficient 0. */
- /* ------------------------------------------------------------------ */
- uByte * decNumberGetBCD(const decNumber *dn, uByte *bcd) {
- uByte *ub=bcd+dn->digits-1; // -> lsd
- const Unit *up=dn->lsu; // Unit pointer, -> lsu
- #if DECDPUN==1 // trivial simple copy
- for (; ub>=bcd; ub--, up++) *ub=*up;
- #else // chopping needed
- uInt u=*up; // work
- uInt cut=DECDPUN; // downcounter through unit
- for (; ub>=bcd; ub--) {
- *ub=(uByte)(u%10); // [*6554 trick inhibits, here]
- u=u/10;
- cut--;
- if (cut>0) continue; // more in this unit
- up++;
- u=*up;
- cut=DECDPUN;
- }
- #endif
- return bcd;
- } // decNumberGetBCD
- /* ------------------------------------------------------------------ */
- /* decNumberSetBCD -- set (replace) the coefficient from BCD8 */
- /* dn is the target decNumber */
- /* bcd is the uInt array that will source n BCD bytes, most- */
- /* significant at offset 0 */
- /* n is the number of digits in the source BCD array (bcd) */
- /* returns dn */
- /* */
- /* dn must have space for at least n digits. No error is possible; */
- /* if dn is a NaN, or Infinite, or is to become a zero, n must be 1 */
- /* and bcd[0] zero. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) {
- Unit *up=dn->lsu+D2U(dn->digits)-1; // -> msu [target pointer]
- const uByte *ub=bcd; // -> source msd
- #if DECDPUN==1 // trivial simple copy
- for (; ub<bcd+n; ub++, up--) *up=*ub;
- #else // some assembly needed
- // calculate how many digits in msu, and hence first cut
- Int cut=MSUDIGITS(n); // [faster than remainder]
- for (;up>=dn->lsu; up--) { // each Unit from msu
- *up=0; // will take <=DECDPUN digits
- for (; cut>0; ub++, cut--) *up=X10(*up)+*ub;
- cut=DECDPUN; // next Unit has all digits
- }
- #endif
- dn->digits=n; // set digit count
- return dn;
- } // decNumberSetBCD
- /* ------------------------------------------------------------------ */
- /* decNumberIsNormal -- test normality of a decNumber */
- /* dn is the decNumber to test */
- /* set is the context to use for Emin */
- /* returns 1 if |dn| is finite and >=Nmin, 0 otherwise */
- /* ------------------------------------------------------------------ */
- Int decNumberIsNormal(const decNumber *dn, decContext *set) {
- Int ae; // adjusted exponent
- #if DECCHECK
- if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
- #endif
- if (decNumberIsSpecial(dn)) return 0; // not finite
- if (decNumberIsZero(dn)) return 0; // not non-zero
- ae=dn->exponent+dn->digits-1; // adjusted exponent
- if (ae<set->emin) return 0; // is subnormal
- return 1;
- } // decNumberIsNormal
- /* ------------------------------------------------------------------ */
- /* decNumberIsSubnormal -- test subnormality of a decNumber */
- /* dn is the decNumber to test */
- /* set is the context to use for Emin */
- /* returns 1 if |dn| is finite, non-zero, and <Nmin, 0 otherwise */
- /* ------------------------------------------------------------------ */
- Int decNumberIsSubnormal(const decNumber *dn, decContext *set) {
- Int ae; // adjusted exponent
- #if DECCHECK
- if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
- #endif
- if (decNumberIsSpecial(dn)) return 0; // not finite
- if (decNumberIsZero(dn)) return 0; // not non-zero
- ae=dn->exponent+dn->digits-1; // adjusted exponent
- if (ae<set->emin) return 1; // is subnormal
- return 0;
- } // decNumberIsSubnormal
- /* ------------------------------------------------------------------ */
- /* decNumberTrim -- remove insignificant zeros */
- /* */
- /* dn is the number to trim */
- /* returns dn */
- /* */
- /* All fields are updated as required. This is a utility operation, */
- /* so special values are unchanged and no error is possible. The */
- /* zeros are removed unconditionally. */
- /* ------------------------------------------------------------------ */
- decNumber * decNumberTrim(decNumber *dn) {
- Int dropped; // work
- decContext set; // ..
- #if DECCHECK
- if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn;
- #endif
- decContextDefault(&set, DEC_INIT_BASE); // clamp=0
- return decTrim(dn, &set, 0, 1, &dropped);
- } // decNumberTrim
- /* ------------------------------------------------------------------ */
- /* decNumberVersion -- return the name and version of this module */
- /* */
- /* No error is possible. */
- /* ------------------------------------------------------------------ */
- const char * decNumberVersion(void) {
- return DECVERSION;
- } // decNumberVersion
- /* ------------------------------------------------------------------ */
- /* decNumberZero -- set a number to 0 */
- /* */
- /* dn is the number to set, with space for one digit */
- /* returns dn */
- /* */
- /* No error is possible. */
- /* ------------------------------------------------------------------ */
- // Memset is not used as it is much slower in some environments.
- decNumber * decNumberZero(decNumber *dn) {
- #if DECCHECK
- if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
- #endif
- dn->bits=0;
- dn->exponent=0;
- dn->digits=1;
- dn->lsu[0]=0;
- return dn;
- } // decNumberZero
- /* ================================================================== */
- /* Local routines */
- /* ================================================================== */
- /* ------------------------------------------------------------------ */
- /* decToString -- lay out a number into a string */
- /* */
- /* dn is the number to lay out */
- /* string is where to lay out the number */
- /* eng is 1 if Engineering, 0 if Scientific */
- /* */
- /* string must be at least dn->digits+14 characters long */
- /* No error is possible. */
- /* */
- /* Note that this routine can generate a -0 or 0.000. These are */
- /* never generated in subset to-number or arithmetic, but can occur */
- /* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234). */
- /* ------------------------------------------------------------------ */
- // If DECCHECK is enabled the string "?" is returned if a number is
- // invalid.
- static void decToString(const decNumber *dn, char *string, Flag eng) {
- Int exp=dn->exponent; // local copy
- Int e; // E-part value
- Int pre; // digits before the '.'
- Int cut; // for counting digits in a Unit
- char *c=string; // work [output pointer]
- const Unit *up=dn->lsu+D2U(dn->digits)-1; // -> msu [input pointer]
- uInt u, pow; // work
- #if DECCHECK
- if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) {
- strcpy(string, "?");
- return;}
- #endif
- if (decNumberIsNegative(dn)) { // Negatives get a minus
- *c='-';
- c++;
- }
- if (dn->bits&DECSPECIAL) { // Is a special value
- if (decNumberIsInfinite(dn)) {
- strcpy(c, "Inf");
- strcpy(c+3, "inity");
- return;}
- // a NaN
- if (dn->bits&DECSNAN) { // signalling NaN
- *c='s';
- c++;
- }
- strcpy(c, "NaN");
- c+=3; // step past
- // if not a clean non-zero coefficient, that's all there is in a
- // NaN string
- if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return;
- // [drop through to add integer]
- }
- // calculate how many digits in msu, and hence first cut
- cut=MSUDIGITS(dn->digits); // [faster than remainder]
- cut--; // power of ten for digit
- if (exp==0) { // simple integer [common fastpath]
- for (;up>=dn->lsu; up--) { // each Unit from msu
- u=*up; // contains DECDPUN digits to lay out
- for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow);
- cut=DECDPUN-1; // next Unit has all digits
- }
- *c='\0'; // terminate the string
- return;}
- /* non-0 exponent -- assume plain form */
- pre=dn->digits+exp; // digits before '.'
- e=0; // no E
- if ((exp>0) || (pre<-5)) { // need exponential form
- e=exp+dn->digits-1; // calculate E value
- pre=1; // assume one digit before '.'
- if (eng && (e!=0)) { // engineering: may need to adjust
- Int adj; // adjustment
- // The C remainder operator is undefined for negative numbers, so
- // a positive remainder calculation must be used here
- if (e<0) {
- adj=(-e)%3;
- if (adj!=0) adj=3-adj;
- }
- else { // e>0
- adj=e%3;
- }
- e=e-adj;
- // if dealing with zero still produce an exponent which is a
- // multiple of three, as expected, but there will only be the
- // one zero before the E, still. Otherwise note the padding.
- if (!ISZERO(dn)) pre+=adj;
- else { // is zero
- if (adj!=0) { // 0.00Esnn needed
- e=e+3;
- pre=-(2-adj);
- }
- } // zero
- } // eng
- } // need exponent
- /* lay out the digits of the coefficient, adding 0s and . as needed */
- u=*up;
- if (pre>0) { // xxx.xxx or xx00 (engineering) form
- Int n=pre;
- for (; pre>0; pre--, c++, cut--) {
- if (cut<0) { // need new Unit
- if (up==dn->lsu) break; // out of input digits (pre>digits)
- up--;
- cut=DECDPUN-1;
- u=*up;
- }
- TODIGIT(u, cut, c, pow);
- }
- if (n<dn->digits) { // more to come, after '.'
- *c='.'; c++;
- for (;; c++, cut--) {
- if (cut<0) { // need new Unit
- if (up==dn->lsu) break; // out of input digits
- up--;
- cut=DECDPUN-1;
- u=*up;
- }
- TODIGIT(u, cut, c, pow);
- }
- }
- else for (; pre>0; pre--, c++) *c='0'; // 0 padding (for engineering) needed
- }
- else { // 0.xxx or 0.000xxx form
- *c='0'; c++;
- *c='.'; c++;
- for (; pre<0; pre++, c++) *c='0'; // add any 0's after '.'
- for (; ; c++, cut--) {
- if (cut<0) { // need new Unit
- if (up==dn->lsu) break; // out of input digits
- up--;
- cut=DECDPUN-1;
- u=*up;
- }
- TODIGIT(u, cut, c, pow);
- }
- }
- /* Finally add the E-part, if needed. It will never be 0, has a
- base maximum and minimum of +999999999 through -999999999, but
- could range down to -1999999998 for anormal numbers */
- if (e!=0) {
- Flag had=0; // 1=had non-zero
- *c='E'; c++;
- *c='+'; c++; // assume positive
- u=e; // ..
- if (e<0) {
- *(c-1)='-'; // oops, need -
- u=-e; // uInt, please
- }
- // lay out the exponent [_itoa or equivalent is not ANSI C]
- for (cut=9; cut>=0; cut--) {
- TODIGIT(u, cut, c, pow);
- if (*c=='0' && !had) continue; // skip leading zeros
- had=1; // had non-0
- c++; // step for next
- } // cut
- }
- *c='\0'; // terminate the string (all paths)
- return;
- } // decToString
- /* ------------------------------------------------------------------ */
- /* decAddOp -- add/subtract operation */
- /* */
- /* This computes C = A + B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X+X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* negate is DECNEG if rhs should be negated, or 0 otherwise */
- /* status accumulates status for the caller */
- /* */
- /* C must have space for set->digits digits. */
- /* Inexact in status must be 0 for correct Exact zero sign in result */
- /* ------------------------------------------------------------------ */
- /* If possible, the coefficient is calculated directly into C. */
- /* However, if: */
- /* -- a digits+1 calculation is needed because the numbers are */
- /* unaligned and span more than set->digits digits */
- /* -- a carry to digits+1 digits looks possible */
- /* -- C is the same as A or B, and the result would destructively */
- /* overlap the A or B coefficient */
- /* then the result must be calculated into a temporary buffer. In */
- /* this case a local (stack) buffer is used if possible, and only if */
- /* too long for that does malloc become the final resort. */
- /* */
- /* Misalignment is handled as follows: */
- /* Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp. */
- /* BPad: Apply the padding by a combination of shifting (whole */
- /* units) and multiplication (part units). */
- /* */
- /* Addition, especially x=x+1, is speed-critical. */
- /* The static buffer is larger than might be expected to allow for */
- /* calls from higher-level funtions (notable exp). */
- /* ------------------------------------------------------------------ */
- static decNumber * decAddOp(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set,
- uByte negate, uInt *status) {
- #if DECSUBSET
- decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated
- decNumber *allocrhs=NULL; // .., rhs
- #endif
- Int rhsshift; // working shift (in Units)
- Int maxdigits; // longest logical length
- Int mult; // multiplier
- Int residue; // rounding accumulator
- uByte bits; // result bits
- Flag diffsign; // non-0 if arguments have different sign
- Unit *acc; // accumulator for result
- Unit accbuff[SD2U(DECBUFFER*2+20)]; // local buffer [*2+20 reduces many
- // allocations when called from
- // other operations, notable exp]
- Unit *allocacc=NULL; // -> allocated acc buffer, iff allocated
- Int reqdigits=set->digits; // local copy; requested DIGITS
- Int padding; // work
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- do { // protect allocated storage
- #if DECSUBSET
- if (!set->extended) {
- // reduce operands and set lostDigits status, as needed
- if (lhs->digits>reqdigits) {
- alloclhs=decRoundOperand(lhs, set, status);
- if (alloclhs==NULL) break;
- lhs=alloclhs;
- }
- if (rhs->digits>reqdigits) {
- allocrhs=decRoundOperand(rhs, set, status);
- if (allocrhs==NULL) break;
- rhs=allocrhs;
- }
- }
- #endif
- // [following code does not require input rounding]
- // note whether signs differ [used all paths]
- diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG);
- // handle infinities and NaNs
- if (SPECIALARGS) { // a special bit set
- if (SPECIALARGS & (DECSNAN | DECNAN)) // a NaN
- decNaNs(res, lhs, rhs, set, status);
- else { // one or two infinities
- if (decNumberIsInfinite(lhs)) { // LHS is infinity
- // two infinities with different signs is invalid
- if (decNumberIsInfinite(rhs) && diffsign) {
- *status|=DEC_Invalid_operation;
- break;
- }
- bits=lhs->bits & DECNEG; // get sign from LHS
- }
- else bits=(rhs->bits^negate) & DECNEG;// RHS must be Infinity
- bits|=DECINF;
- decNumberZero(res);
- res->bits=bits; // set +/- infinity
- } // an infinity
- break;
- }
- // Quick exit for add 0s; return the non-0, modified as need be
- if (ISZERO(lhs)) {
- Int adjust; // work
- Int lexp=lhs->exponent; // save in case LHS==RES
- bits=lhs->bits; // ..
- residue=0; // clear accumulator
- decCopyFit(res, rhs, set, &residue, status); // copy (as needed)
- res->bits^=negate; // flip if rhs was negated
- #if DECSUBSET
- if (set->extended) { // exponents on zeros count
- #endif
- // exponent will be the lower of the two
- adjust=lexp-res->exponent; // adjustment needed [if -ve]
- if (ISZERO(res)) { // both 0: special IEEE 754 rules
- if (adjust<0) res->exponent=lexp; // set exponent
- // 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0
- if (diffsign) {
- if (set->round!=DEC_ROUND_FLOOR) res->bits=0;
- else res->bits=DECNEG; // preserve 0 sign
- }
- }
- else { // non-0 res
- if (adjust<0) { // 0-padding needed
- if ((res->digits-adjust)>set->digits) {
- adjust=res->digits-set->digits; // to fit exactly
- *status|=DEC_Rounded; // [but exact]
- }
- res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
- res->exponent+=adjust; // set the exponent.
- }
- } // non-0 res
- #if DECSUBSET
- } // extended
- #endif
- decFinish(res, set, &residue, status); // clean and finalize
- break;}
- if (ISZERO(rhs)) { // [lhs is non-zero]
- Int adjust; // work
- Int rexp=rhs->exponent; // save in case RHS==RES
- bits=rhs->bits; // be clean
- residue=0; // clear accumulator
- decCopyFit(res, lhs, set, &residue, status); // copy (as needed)
- #if DECSUBSET
- if (set->extended) { // exponents on zeros count
- #endif
- // exponent will be the lower of the two
- // [0-0 case handled above]
- adjust=rexp-res->exponent; // adjustment needed [if -ve]
- if (adjust<0) { // 0-padding needed
- if ((res->digits-adjust)>set->digits) {
- adjust=res->digits-set->digits; // to fit exactly
- *status|=DEC_Rounded; // [but exact]
- }
- res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
- res->exponent+=adjust; // set the exponent.
- }
- #if DECSUBSET
- } // extended
- #endif
- decFinish(res, set, &residue, status); // clean and finalize
- break;}
- // [NB: both fastpath and mainpath code below assume these cases
- // (notably 0-0) have already been handled]
- // calculate the padding needed to align the operands
- padding=rhs->exponent-lhs->exponent;
- // Fastpath cases where the numbers are aligned and normal, the RHS
- // is all in one unit, no operand rounding is needed, and no carry,
- // lengthening, or borrow is needed
- if (padding==0
- && rhs->digits<=DECDPUN
- && rhs->exponent>=set->emin // [some normals drop through]
- && rhs->exponent<=set->emax-set->digits+1 // [could clamp]
- && rhs->digits<=reqdigits
- && lhs->digits<=reqdigits) {
- Int partial=*lhs->lsu;
- if (!diffsign) { // adding
- partial+=*rhs->lsu;
- if ((partial<=DECDPUNMAX) // result fits in unit
- && (lhs->digits>=DECDPUN || // .. and no digits-count change
- partial<(Int)powers[lhs->digits])) { // ..
- if (res!=lhs) decNumberCopy(res, lhs); // not in place
- *res->lsu=(Unit)partial; // [copy could have overwritten RHS]
- break;
- }
- // else drop out for careful add
- }
- else { // signs differ
- partial-=*rhs->lsu;
- if (partial>0) { // no borrow needed, and non-0 result
- if (res!=lhs) decNumberCopy(res, lhs); // not in place
- *res->lsu=(Unit)partial;
- // this could have reduced digits [but result>0]
- res->digits=decGetDigits(res->lsu, D2U(res->digits));
- break;
- }
- // else drop out for careful subtract
- }
- }
- // Now align (pad) the lhs or rhs so they can be added or
- // subtracted, as necessary. If one number is much larger than
- // the other (that is, if in plain form there is a least one
- // digit between the lowest digit of one and the highest of the
- // other) padding with up to DIGITS-1 trailing zeros may be
- // needed; then apply rounding (as exotic rounding modes may be
- // affected by the residue).
- rhsshift=0; // rhs shift to left (padding) in Units
- bits=lhs->bits; // assume sign is that of LHS
- mult=1; // likely multiplier
- // [if padding==0 the operands are aligned; no padding is needed]
- if (padding!=0) {
- // some padding needed; always pad the RHS, as any required
- // padding can then be effected by a simple combination of
- // shifts and a multiply
- Flag swapped=0;
- if (padding<0) { // LHS needs the padding
- const decNumber *t;
- padding=-padding; // will be +ve
- bits=(uByte)(rhs->bits^negate); // assumed sign is now that of RHS
- t=lhs; lhs=rhs; rhs=t;
- swapped=1;
- }
- // If, after pad, rhs would be longer than lhs by digits+1 or
- // more then lhs cannot affect the answer, except as a residue,
- // so only need to pad up to a length of DIGITS+1.
- if (rhs->digits+padding > lhs->digits+reqdigits+1) {
- // The RHS is sufficient
- // for residue use the relative sign indication...
- Int shift=reqdigits-rhs->digits; // left shift needed
- residue=1; // residue for rounding
- if (diffsign) residue=-residue; // signs differ
- // copy, shortening if necessary
- decCopyFit(res, rhs, set, &residue, status);
- // if it was already shorter, then need to pad with zeros
- if (shift>0) {
- res->digits=decShiftToMost(res->lsu, res->digits, shift);
- res->exponent-=shift; // adjust the exponent.
- }
- // flip the result sign if unswapped and rhs was negated
- if (!swapped) res->bits^=negate;
- decFinish(res, set, &residue, status); // done
- break;}
- // LHS digits may affect result
- rhsshift=D2U(padding+1)-1; // this much by Unit shift ..
- mult=powers[padding-(rhsshift*DECDPUN)]; // .. this by multiplication
- } // padding needed
- if (diffsign) mult=-mult; // signs differ
- // determine the longer operand
- maxdigits=rhs->digits+padding; // virtual length of RHS
- if (lhs->digits>maxdigits) maxdigits=lhs->digits;
- // Decide on the result buffer to use; if possible place directly
- // into result.
- acc=res->lsu; // assume add direct to result
- // If destructive overlap, or the number is too long, or a carry or
- // borrow to DIGITS+1 might be possible, a buffer must be used.
- // [Might be worth more sophisticated tests when maxdigits==reqdigits]
- if ((maxdigits>=reqdigits) // is, or could be, too large
- || (res==rhs && rhsshift>0)) { // destructive overlap
- // buffer needed, choose it; units for maxdigits digits will be
- // needed, +1 Unit for carry or borrow
- Int need=D2U(maxdigits)+1;
- acc=accbuff; // assume use local buffer
- if (need*sizeof(Unit)>sizeof(accbuff)) {
- // printf("malloc add %ld %ld\n", need, sizeof(accbuff));
- allocacc=(Unit *)malloc(need*sizeof(Unit));
- if (allocacc==NULL) { // hopeless -- abandon
- *status|=DEC_Insufficient_storage;
- break;}
- acc=allocacc;
- }
- }
- res->bits=(uByte)(bits&DECNEG); // it's now safe to overwrite..
- res->exponent=lhs->exponent; // .. operands (even if aliased)
- #if DECTRACE
- decDumpAr('A', lhs->lsu, D2U(lhs->digits));
- decDumpAr('B', rhs->lsu, D2U(rhs->digits));
- printf(" :h: %ld %ld\n", rhsshift, mult);
- #endif
- // add [A+B*m] or subtract [A+B*(-m)]
- res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits),
- rhs->lsu, D2U(rhs->digits),
- rhsshift, acc, mult)
- *DECDPUN; // [units -> digits]
- if (res->digits<0) { // borrowed...
- res->digits=-res->digits;
- res->bits^=DECNEG; // flip the sign
- }
- #if DECTRACE
- decDumpAr('+', acc, D2U(res->digits));
- #endif
- // If a buffer was used the result must be copied back, possibly
- // shortening. (If no buffer was used then the result must have
- // fit, so can't need rounding and residue must be 0.)
- residue=0; // clear accumulator
- if (acc!=res->lsu) {
- #if DECSUBSET
- if (set->extended) { // round from first significant digit
- #endif
- // remove leading zeros that were added due to rounding up to
- // integral Units -- before the test for rounding.
- if (res->digits>reqdigits)
- res->digits=decGetDigits(acc, D2U(res->digits));
- decSetCoeff(res, set, acc, res->digits, &residue, status);
- #if DECSUBSET
- }
- else { // subset arithmetic rounds from original significant digit
- // May have an underestimate. This only occurs when both
- // numbers fit in DECDPUN digits and are padding with a
- // negative multiple (-10, -100...) and the top digit(s) become
- // 0. (This only matters when using X3.274 rules where the
- // leading zero could be included in the rounding.)
- if (res->digits<maxdigits) {
- *(acc+D2U(res->digits))=0; // ensure leading 0 is there
- res->digits=maxdigits;
- }
- else {
- // remove leading zeros that added due to rounding up to
- // integral Units (but only those in excess of the original
- // maxdigits length, unless extended) before test for rounding.
- if (res->digits>reqdigits) {
- res->digits=decGetDigits(acc, D2U(res->digits));
- if (res->digits<maxdigits) res->digits=maxdigits;
- }
- }
- decSetCoeff(res, set, acc, res->digits, &residue, status);
- // Now apply rounding if needed before removing leading zeros.
- // This is safe because subnormals are not a possibility
- if (residue!=0) {
- decApplyRound(res, set, residue, status);
- residue=0; // did what needed to be done
- }
- } // subset
- #endif
- } // used buffer
- // strip leading zeros [these were left on in case of subset subtract]
- res->digits=decGetDigits(res->lsu, D2U(res->digits));
- // apply checks and rounding
- decFinish(res, set, &residue, status);
- // "When the sum of two operands with opposite signs is exactly
- // zero, the sign of that sum shall be '+' in all rounding modes
- // except round toward -Infinity, in which mode that sign shall be
- // '-'." [Subset zeros also never have '-', set by decFinish.]
- if (ISZERO(res) && diffsign
- #if DECSUBSET
- && set->extended
- #endif
- && (*status&DEC_Inexact)==0) {
- if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG; // sign -
- else res->bits&=~DECNEG; // sign +
- }
- } while(0); // end protected
- if (allocacc!=NULL) free(allocacc); // drop any storage used
- #if DECSUBSET
- if (allocrhs!=NULL) free(allocrhs); // ..
- if (alloclhs!=NULL) free(alloclhs); // ..
- #endif
- return res;
- } // decAddOp
- /* ------------------------------------------------------------------ */
- /* decDivideOp -- division operation */
- /* */
- /* This routine performs the calculations for all four division */
- /* operators (divide, divideInteger, remainder, remainderNear). */
- /* */
- /* C=A op B */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X/X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* op is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively. */
- /* status is the usual accumulator */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* ------------------------------------------------------------------ */
- /* The underlying algorithm of this routine is the same as in the */
- /* 1981 S/370 implementation, that is, non-restoring long division */
- /* with bi-unit (rather than bi-digit) estimation for each unit */
- /* multiplier. In this pseudocode overview, complications for the */
- /* Remainder operators and division residues for exact rounding are */
- /* omitted for clarity. */
- /* */
- /* Prepare operands and handle special values */
- /* Test for x/0 and then 0/x */
- /* Exp =Exp1 - Exp2 */
- /* Exp =Exp +len(var1) -len(var2) */
- /* Sign=Sign1 * Sign2 */
- /* Pad accumulator (Var1) to double-length with 0's (pad1) */
- /* Pad Var2 to same length as Var1 */
- /* msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round */
- /* have=0 */
- /* Do until (have=digits+1 OR residue=0) */
- /* if exp<0 then if integer divide/residue then leave */
- /* this_unit=0 */
- /* Do forever */
- /* compare numbers */
- /* if <0 then leave inner_loop */
- /* if =0 then (* quick exit without subtract *) do */
- /* this_unit=this_unit+1; output this_unit */
- /* leave outer_loop; end */
- /* Compare lengths of numbers (mantissae): */
- /* If same then tops2=msu2pair -- {units 1&2 of var2} */
- /* else tops2=msu2plus -- {0, unit 1 of var2} */
- /* tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */
- /* mult=tops1/tops2 -- Good and safe guess at divisor */
- /* if mult=0 then mult=1 */
- /* this_unit=this_unit+mult */
- /* subtract */
- /* end inner_loop */
- /* if have\=0 | this_unit\=0 then do */
- /* output this_unit */
- /* have=have+1; end */
- /* var2=var2/10 */
- /* exp=exp-1 */
- /* end outer_loop */
- /* exp=exp+1 -- set the proper exponent */
- /* if have=0 then generate answer=0 */
- /* Return (Result is defined by Var1) */
- /* */
- /* ------------------------------------------------------------------ */
- /* Two working buffers are needed during the division; one (digits+ */
- /* 1) to accumulate the result, and the other (up to 2*digits+1) for */
- /* long subtractions. These are acc and var1 respectively. */
- /* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/
- /* The static buffers may be larger than might be expected to allow */
- /* for calls from higher-level funtions (notable exp). */
- /* ------------------------------------------------------------------ */
- static decNumber * decDivideOp(decNumber *res,
- const decNumber *lhs, const decNumber *rhs,
- decContext *set, Flag op, uInt *status) {
- #if DECSUBSET
- decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated
- decNumber *allocrhs=NULL; // .., rhs
- #endif
- Unit accbuff[SD2U(DECBUFFER+DECDPUN+10)]; // local buffer
- Unit *acc=accbuff; // -> accumulator array for result
- Unit *allocacc=NULL; // -> allocated buffer, iff allocated
- Unit *accnext; // -> where next digit will go
- Int acclength; // length of acc needed [Units]
- Int accunits; // count of units accumulated
- Int accdigits; // count of digits accumulated
- Unit varbuff[SD2U(DECBUFFER*2+DECDPUN)]; // buffer for var1
- Unit *var1=varbuff; // -> var1 array for long subtraction
- Unit *varalloc=NULL; // -> allocated buffer, iff used
- Unit *msu1; // -> msu of var1
- const Unit *var2; // -> var2 array
- const Unit *msu2; // -> msu of var2
- Int msu2plus; // msu2 plus one [does not vary]
- eInt msu2pair; // msu2 pair plus one [does not vary]
- Int var1units, var2units; // actual lengths
- Int var2ulen; // logical length (units)
- Int var1initpad=0; // var1 initial padding (digits)
- Int maxdigits; // longest LHS or required acc length
- Int mult; // multiplier for subtraction
- Unit thisunit; // current unit being accumulated
- Int residue; // for rounding
- Int reqdigits=set->digits; // requested DIGITS
- Int exponent; // working exponent
- Int maxexponent=0; // DIVIDE maximum exponent if unrounded
- uByte bits; // working sign
- Unit *target; // work
- const Unit *source; // ..
- uInt const *pow; // ..
- Int shift, cut; // ..
- #if DECSUBSET
- Int dropped; // work
- #endif
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- do { // protect allocated storage
- #if DECSUBSET
- if (!set->extended) {
- // reduce operands and set lostDigits status, as needed
- if (lhs->digits>reqdigits) {
- alloclhs=decRoundOperand(lhs, set, status);
- if (alloclhs==NULL) break;
- lhs=alloclhs;
- }
- if (rhs->digits>reqdigits) {
- allocrhs=decRoundOperand(rhs, set, status);
- if (allocrhs==NULL) break;
- rhs=allocrhs;
- }
- }
- #endif
- // [following code does not require input rounding]
- bits=(lhs->bits^rhs->bits)&DECNEG; // assumed sign for divisions
- // handle infinities and NaNs
- if (SPECIALARGS) { // a special bit set
- if (SPECIALARGS & (DECSNAN | DECNAN)) { // one or two NaNs
- decNaNs(res, lhs, rhs, set, status);
- break;
- }
- // one or two infinities
- if (decNumberIsInfinite(lhs)) { // LHS (dividend) is infinite
- if (decNumberIsInfinite(rhs) || // two infinities are invalid ..
- op & (REMAINDER | REMNEAR)) { // as is remainder of infinity
- *status|=DEC_Invalid_operation;
- break;
- }
- // [Note that infinity/0 raises no exceptions]
- decNumberZero(res);
- res->bits=bits|DECINF; // set +/- infinity
- break;
- }
- else { // RHS (divisor) is infinite
- residue=0;
- if (op&(REMAINDER|REMNEAR)) {
- // result is [finished clone of] lhs
- decCopyFit(res, lhs, set, &residue, status);
- }
- else { // a division
- decNumberZero(res);
- res->bits=bits; // set +/- zero
- // for DIVIDEINT the exponent is always 0. For DIVIDE, result
- // is a 0 with infinitely negative exponent, clamped to minimum
- if (op&DIVIDE) {
- res->exponent=set->emin-set->digits+1;
- *status|=DEC_Clamped;
- }
- }
- decFinish(res, set, &residue, status);
- break;
- }
- }
- // handle 0 rhs (x/0)
- if (ISZERO(rhs)) { // x/0 is always exceptional
- if (ISZERO(lhs)) {
- decNumberZero(res); // [after lhs test]
- *status|=DEC_Division_undefined;// 0/0 will become NaN
- }
- else {
- decNumberZero(res);
- if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation;
- else {
- *status|=DEC_Division_by_zero; // x/0
- res->bits=bits|DECINF; // .. is +/- Infinity
- }
- }
- break;}
- // handle 0 lhs (0/x)
- if (ISZERO(lhs)) { // 0/x [x!=0]
- #if DECSUBSET
- if (!set->extended) decNumberZero(res);
- else {
- #endif
- if (op&DIVIDE) {
- residue=0;
- exponent=lhs->exponent-rhs->exponent; // ideal exponent
- decNumberCopy(res, lhs); // [zeros always fit]
- res->bits=bits; // sign as computed
- res->exponent=exponent; // exponent, too
- decFinalize(res, set, &residue, status); // check exponent
- }
- else if (op&DIVIDEINT) {
- decNumberZero(res); // integer 0
- res->bits=bits; // sign as computed
- }
- else { // a remainder
- exponent=rhs->exponent; // [save in case overwrite]
- decNumberCopy(res, lhs); // [zeros always fit]
- if (exponent<res->exponent) res->exponent=exponent; // use lower
- }
- #if DECSUBSET
- }
- #endif
- break;}
- // Precalculate exponent. This starts off adjusted (and hence fits
- // in 31 bits) and becomes the usual unadjusted exponent as the
- // division proceeds. The order of evaluation is important, here,
- // to avoid wrap.
- exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits);
- // If the working exponent is -ve, then some quick exits are
- // possible because the quotient is known to be <1
- // [for REMNEAR, it needs to be < -1, as -0.5 could need work]
- if (exponent<0 && !(op==DIVIDE)) {
- if (op&DIVIDEINT) {
- decNumberZero(res); // integer part is 0
- #if DECSUBSET
- if (set->extended)
- #endif
- res->bits=bits; // set +/- zero
- break;}
- // fastpath remainders so long as the lhs has the smaller
- // (or equal) exponent
- if (lhs->exponent<=rhs->exponent) {
- if (op&REMAINDER || exponent<-1) {
- // It is REMAINDER or safe REMNEAR; result is [finished
- // clone of] lhs (r = x - 0*y)
- residue=0;
- decCopyFit(res, lhs, set, &residue, status);
- decFinish(res, set, &residue, status);
- break;
- }
- // [unsafe REMNEAR drops through]
- }
- } // fastpaths
- /* Long (slow) division is needed; roll up the sleeves... */
- // The accumulator will hold the quotient of the division.
- // If it needs to be too long for stack storage, then allocate.
- acclength=D2U(reqdigits+DECDPUN); // in Units
- if (acclength*sizeof(Unit)>sizeof(accbuff)) {
- // printf("malloc dvacc %ld units\n", acclength);
- allocacc=(Unit *)malloc(acclength*sizeof(Unit));
- if (allocacc==NULL) { // hopeless -- abandon
- *status|=DEC_Insufficient_storage;
- break;}
- acc=allocacc; // use the allocated space
- }
- // var1 is the padded LHS ready for subtractions.
- // If it needs to be too long for stack storage, then allocate.
- // The maximum units needed for var1 (long subtraction) is:
- // Enough for
- // (rhs->digits+reqdigits-1) -- to allow full slide to right
- // or (lhs->digits) -- to allow for long lhs
- // whichever is larger
- // +1 -- for rounding of slide to right
- // +1 -- for leading 0s
- // +1 -- for pre-adjust if a remainder or DIVIDEINT
- // [Note: unused units do not participate in decUnitAddSub data]
- maxdigits=rhs->digits+reqdigits-1;
- if (lhs->digits>maxdigits) maxdigits=lhs->digits;
- var1units=D2U(maxdigits)+2;
- // allocate a guard unit above msu1 for REMAINDERNEAR
- if (!(op&DIVIDE)) var1units++;
- if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) {
- // printf("malloc dvvar %ld units\n", var1units+1);
- varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit));
- if (varalloc==NULL) { // hopeless -- abandon
- *status|=DEC_Insufficient_storage;
- break;}
- var1=varalloc; // use the allocated space
- }
- // Extend the lhs and rhs to full long subtraction length. The lhs
- // is truly extended into the var1 buffer, with 0 padding, so a
- // subtract in place is always possible. The rhs (var2) has
- // virtual padding (implemented by decUnitAddSub).
- // One guard unit was allocated above msu1 for rem=rem+rem in
- // REMAINDERNEAR.
- msu1=var1+var1units-1; // msu of var1
- source=lhs->lsu+D2U(lhs->digits)-1; // msu of input array
- for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source;
- for (; target>=var1; target--) *target=0;
- // rhs (var2) is left-aligned with var1 at the start
- var2ulen=var1units; // rhs logical length (units)
- var2units=D2U(rhs->digits); // rhs actual length (units)
- var2=rhs->lsu; // -> rhs array
- msu2=var2+var2units-1; // -> msu of var2 [never changes]
- // now set up the variables which will be used for estimating the
- // multiplication factor. If these variables are not exact, add
- // 1 to make sure that the multiplier is never overestimated.
- msu2plus=*msu2; // it's value ..
- if (var2units>1) msu2plus++; // .. +1 if any more
- msu2pair=(eInt)*msu2*(DECDPUNMAX+1);// top two pair ..
- if (var2units>1) { // .. [else treat 2nd as 0]
- msu2pair+=*(msu2-1); // ..
- if (var2units>2) msu2pair++; // .. +1 if any more
- }
- // The calculation is working in units, which may have leading zeros,
- // but the exponent was calculated on the assumption that they are
- // both left-aligned. Adjust the exponent to compensate: add the
- // number of leading zeros in var1 msu and subtract those in var2 msu.
- // [This is actually done by counting the digits and negating, as
- // lead1=DECDPUN-digits1, and similarly for lead2.]
- for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--;
- for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++;
- // Now, if doing an integer divide or remainder, ensure that
- // the result will be Unit-aligned. To do this, shift the var1
- // accumulator towards least if need be. (It's much easier to
- // do this now than to reassemble the residue afterwards, if
- // doing a remainder.) Also ensure the exponent is not negative.
- if (!(op&DIVIDE)) {
- Unit *u; // work
- // save the initial 'false' padding of var1, in digits
- var1initpad=(var1units-D2U(lhs->digits))*DECDPUN;
- // Determine the shift to do.
- if (exponent<0) cut=-exponent;
- else cut=DECDPUN-exponent%DECDPUN;
- decShiftToLeast(var1, var1units, cut);
- exponent+=cut; // maintain numerical value
- var1initpad-=cut; // .. and reduce padding
- // clean any most-significant units which were just emptied
- for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0;
- } // align
- else { // is DIVIDE
- maxexponent=lhs->exponent-rhs->exponent; // save
- // optimization: if the first iteration will just produce 0,
- // preadjust to skip it [valid for DIVIDE only]
- if (*msu1<*msu2) {
- var2ulen--; // shift down
- exponent-=DECDPUN; // update the exponent
- }
- }
- // ---- start the long-division loops ------------------------------
- accunits=0; // no units accumulated yet
- accdigits=0; // .. or digits
- accnext=acc+acclength-1; // -> msu of acc [NB: allows digits+1]
- for (;;) { // outer forever loop
- thisunit=0; // current unit assumed 0
- // find the next unit
- for (;;) { // inner forever loop
- // strip leading zero units [from either pre-adjust or from
- // subtract last time around]. Leave at least one unit.
- for (; *msu1==0 && msu1>var1; msu1--) var1units--;
- if (var1units<var2ulen) break; // var1 too low for subtract
- if (var1units==var2ulen) { // unit-by-unit compare needed
- // compare the two numbers, from msu
- const Unit *pv1, *pv2;
- Unit v2; // units to compare
- pv2=msu2; // -> msu
- for (pv1=msu1; ; pv1--, pv2--) {
- // v1=*pv1 -- always OK
- v2=0; // assume in padding
- if (pv2>=var2) v2=*pv2; // in range
- if (*pv1!=v2) break; // no longer the same
- if (pv1==var1) break; // done; leave pv1 as is
- }
- // here when all inspected or a difference seen
- if (*pv1<v2) break; // var1 too low to subtract
- if (*pv1==v2) { // var1 == var2
- // reach here if var1 and var2 are identical; subtraction
- // would increase digit by one, and the residue will be 0 so
- // the calculation is done; leave the loop with residue=0.
- thisunit++; // as though subtracted
- *var1=0; // set var1 to 0
- var1units=1; // ..
- break; // from inner
- } // var1 == var2
- // *pv1>v2. Prepare for real subtraction; the lengths are equal
- // Estimate the multiplier (there's always a msu1-1)...
- // Bring in two units of var2 to provide a good estimate.
- mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair);
- } // lengths the same
- else { // var1units > var2ulen, so subtraction is safe
- // The var2 msu is one unit towards the lsu of the var1 msu,
- // so only one unit for var2 can be used.
- mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus);
- }
- if (mult==0) mult=1; // must always be at least 1
- // subtraction needed; var1 is > var2
- thisunit=(Unit)(thisunit+mult); // accumulate
- // subtract var1-var2, into var1; only the overlap needs
- // processing, as this is an in-place calculation
- shift=var2ulen-var2units;
- #if DECTRACE
- decDumpAr('1', &var1[shift], var1units-shift);
- decDumpAr('2', var2, var2units);
- printf("m=%ld\n", -mult);
- #endif
- decUnitAddSub(&var1[shift], var1units-shift,
- var2, var2units, 0,
- &var1[shift], -mult);
- #if DECTRACE
- decDumpAr('#', &var1[shift], var1units-shift);
- #endif
- // var1 now probably has leading zeros; these are removed at the
- // top of the inner loop.
- } // inner loop
- // The next unit has been calculated in full; unless it's a
- // leading zero, add to acc
- if (accunits!=0 || thisunit!=0) { // is first or non-zero
- *accnext=thisunit; // store in accumulator
- // account exactly for the new digits
- if (accunits==0) {
- accdigits++; // at least one
- for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++;
- }
- else accdigits+=DECDPUN;
- accunits++; // update count
- accnext--; // ready for next
- if (accdigits>reqdigits) break; // have enough digits
- }
- // if the residue is zero, the operation is done (unless divide
- // or divideInteger and still not enough digits yet)
- if (*var1==0 && var1units==1) { // residue is 0
- if (op&(REMAINDER|REMNEAR)) break;
- if ((op&DIVIDE) && (exponent<=maxexponent)) break;
- // [drop through if divideInteger]
- }
- // also done enough if calculating remainder or integer
- // divide and just did the last ('units') unit
- if (exponent==0 && !(op&DIVIDE)) break;
- // to get here, var1 is less than var2, so divide var2 by the per-
- // Unit power of ten and go for the next digit
- var2ulen--; // shift down
- exponent-=DECDPUN; // update the exponent
- } // outer loop
- // ---- division is complete ---------------------------------------
- // here: acc has at least reqdigits+1 of good results (or fewer
- // if early stop), starting at accnext+1 (its lsu)
- // var1 has any residue at the stopping point
- // accunits is the number of digits collected in acc
- if (accunits==0) { // acc is 0
- accunits=1; // show have a unit ..
- accdigits=1; // ..
- *accnext=0; // .. whose value is 0
- }
- else accnext++; // back to last placed
- // accnext now -> lowest unit of result
- residue=0; // assume no residue
- if (op&DIVIDE) {
- // record the presence of any residue, for rounding
- if (*var1!=0 || var1units>1) residue=1;
- else { // no residue
- // Had an exact division; clean up spurious trailing 0s.
- // There will be at most DECDPUN-1, from the final multiply,
- // and then only if the result is non-0 (and even) and the
- // exponent is 'loose'.
- #if DECDPUN>1
- Unit lsu=*accnext;
- if (!(lsu&0x01) && (lsu!=0)) {
- // count the trailing zeros
- Int drop=0;
- for (;; drop++) { // [will terminate because lsu!=0]
- if (exponent>=maxexponent) break; // don't chop real 0s
- #if DECDPUN<=4
- if ((lsu-QUOT10(lsu, drop+1)
- *powers[drop+1])!=0) break; // found non-0 digit
- #else
- if (lsu%powers[drop+1]!=0) break; // found non-0 digit
- #endif
- exponent++;
- }
- if (drop>0) {
- accunits=decShiftToLeast(accnext, accunits, drop);
- accdigits=decGetDigits(accnext, accunits);
- accunits=D2U(accdigits);
- // [exponent was adjusted in the loop]
- }
- } // neither odd nor 0
- #endif
- } // exact divide
- } // divide
- else /* op!=DIVIDE */ {
- // check for coefficient overflow
- if (accdigits+exponent>reqdigits) {
- *status|=DEC_Division_impossible;
- break;
- }
- if (op & (REMAINDER|REMNEAR)) {
- // [Here, the exponent will be 0, because var1 was adjusted
- // appropriately.]
- Int postshift; // work
- Flag wasodd=0; // integer was odd
- Unit *quotlsu; // for save
- Int quotdigits; // ..
- bits=lhs->bits; // remainder sign is always as lhs
- // Fastpath when residue is truly 0 is worthwhile [and
- // simplifies the code below]
- if (*var1==0 && var1units==1) { // residue is 0
- Int exp=lhs->exponent; // save min(exponents)
- if (rhs->exponent<exp) exp=rhs->exponent;
- decNumberZero(res); // 0 coefficient
- #if DECSUBSET
- if (set->extended)
- #endif
- res->exponent=exp; // .. with proper exponent
- res->bits=(uByte)(bits&DECNEG); // [cleaned]
- decFinish(res, set, &residue, status); // might clamp
- break;
- }
- // note if the quotient was odd
- if (*accnext & 0x01) wasodd=1; // acc is odd
- quotlsu=accnext; // save in case need to reinspect
- quotdigits=accdigits; // ..
- // treat the residue, in var1, as the value to return, via acc
- // calculate the unused zero digits. This is the smaller of:
- // var1 initial padding (saved above)
- // var2 residual padding, which happens to be given by:
- postshift=var1initpad+exponent-lhs->exponent+rhs->exponent;
- // [the 'exponent' term accounts for the shifts during divide]
- if (var1initpad<postshift) postshift=var1initpad;
- // shift var1 the requested amount, and adjust its digits
- var1units=decShiftToLeast(var1, var1units, postshift);
- accnext=var1;
- accdigits=decGetDigits(var1, var1units);
- accunits=D2U(accdigits);
- exponent=lhs->exponent; // exponent is smaller of lhs & rhs
- if (rhs->exponent<exponent) exponent=rhs->exponent;
- // Now correct the result if doing remainderNear; if it
- // (looking just at coefficients) is > rhs/2, or == rhs/2 and
- // the integer was odd then the result should be rem-rhs.
- if (op&REMNEAR) {
- Int compare, tarunits; // work
- Unit *up; // ..
- // calculate remainder*2 into the var1 buffer (which has
- // 'headroom' of an extra unit and hence enough space)
- // [a dedicated 'double' loop would be faster, here]
- tarunits=decUnitAddSub(accnext, accunits, accnext, accunits,
- 0, accnext, 1);
- // decDumpAr('r', accnext, tarunits);
- // Here, accnext (var1) holds tarunits Units with twice the
- // remainder's coefficient, which must now be compared to the
- // RHS. The remainder's exponent may be smaller than the RHS's.
- compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits),
- rhs->exponent-exponent);
- if (compare==BADINT) { // deep trouble
- *status|=DEC_Insufficient_storage;
- break;}
- // now restore the remainder by dividing by two; the lsu
- // is known to be even.
- for (up=accnext; up<accnext+tarunits; up++) {
- Int half; // half to add to lower unit
- half=*up & 0x01;
- *up/=2; // [shift]
- if (!half) continue;
- *(up-1)+=(DECDPUNMAX+1)/2;
- }
- // [accunits still describes the original remainder length]
- if (compare>0 || (compare==0 && wasodd)) { // adjustment needed
- Int exp, expunits, exprem; // work
- // This is effectively causing round-up of the quotient,
- // so if it was the rare case where it was full and all
- // nines, it would overflow and hence division-impossible
- // should be raised
- Flag allnines=0; // 1 if quotient all nines
- if (quotdigits==reqdigits) { // could be borderline
- for (up=quotlsu; ; up++) {
- if (quotdigits>DECDPUN) {
- if (*up!=DECDPUNMAX) break;// non-nines
- }
- else { // this is the last Unit
- if (*up==powers[quotdigits]-1) allnines=1;
- break;
- }
- quotdigits-=DECDPUN; // checked those digits
- } // up
- } // borderline check
- if (allnines) {
- *status|=DEC_Division_impossible;
- break;}
- // rem-rhs is needed; the sign will invert. Again, var1
- // can safely be used for the working Units array.
- exp=rhs->exponent-exponent; // RHS padding needed
- // Calculate units and remainder from exponent.
- expunits=exp/DECDPUN;
- exprem=exp%DECDPUN;
- // subtract [A+B*(-m)]; the result will always be negative
- accunits=-decUnitAddSub(accnext, accunits,
- rhs->lsu, D2U(rhs->digits),
- expunits, accnext, -(Int)powers[exprem]);
- accdigits=decGetDigits(accnext, accunits); // count digits exactly
- accunits=D2U(accdigits); // and recalculate the units for copy
- // [exponent is as for original remainder]
- bits^=DECNEG; // flip the sign
- }
- } // REMNEAR
- } // REMAINDER or REMNEAR
- } // not DIVIDE
- // Set exponent and bits
- res->exponent=exponent;
- res->bits=(uByte)(bits&DECNEG); // [cleaned]
- // Now the coefficient.
- decSetCoeff(res, set, accnext, accdigits, &residue, status);
- decFinish(res, set, &residue, status); // final cleanup
- #if DECSUBSET
- // If a divide then strip trailing zeros if subset [after round]
- if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, 1, &dropped);
- #endif
- } while(0); // end protected
- if (varalloc!=NULL) free(varalloc); // drop any storage used
- if (allocacc!=NULL) free(allocacc); // ..
- #if DECSUBSET
- if (allocrhs!=NULL) free(allocrhs); // ..
- if (alloclhs!=NULL) free(alloclhs); // ..
- #endif
- return res;
- } // decDivideOp
- /* ------------------------------------------------------------------ */
- /* decMultiplyOp -- multiplication operation */
- /* */
- /* This routine performs the multiplication C=A x B. */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X*X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* status is the usual accumulator */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* ------------------------------------------------------------------ */
- /* 'Classic' multiplication is used rather than Karatsuba, as the */
- /* latter would give only a minor improvement for the short numbers */
- /* expected to be handled most (and uses much more memory). */
- /* */
- /* There are two major paths here: the general-purpose ('old code') */
- /* path which handles all DECDPUN values, and a fastpath version */
- /* which is used if 64-bit ints are available, DECDPUN<=4, and more */
- /* than two calls to decUnitAddSub would be made. */
- /* */
- /* The fastpath version lumps units together into 8-digit or 9-digit */
- /* chunks, and also uses a lazy carry strategy to minimise expensive */
- /* 64-bit divisions. The chunks are then broken apart again into */
- /* units for continuing processing. Despite this overhead, the */
- /* fastpath can speed up some 16-digit operations by 10x (and much */
- /* more for higher-precision calculations). */
- /* */
- /* A buffer always has to be used for the accumulator; in the */
- /* fastpath, buffers are also always needed for the chunked copies of */
- /* of the operand coefficients. */
- /* Static buffers are larger than needed just for multiply, to allow */
- /* for calls from other operations (notably exp). */
- /* ------------------------------------------------------------------ */
- #define FASTMUL (DECUSE64 && DECDPUN<5)
- static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set,
- uInt *status) {
- Int accunits; // Units of accumulator in use
- Int exponent; // work
- Int residue=0; // rounding residue
- uByte bits; // result sign
- Unit *acc; // -> accumulator Unit array
- Int needbytes; // size calculator
- void *allocacc=NULL; // -> allocated accumulator, iff allocated
- Unit accbuff[SD2U(DECBUFFER*4+1)]; // buffer (+1 for DECBUFFER==0,
- // *4 for calls from other operations)
- const Unit *mer, *mermsup; // work
- Int madlength; // Units in multiplicand
- Int shift; // Units to shift multiplicand by
- #if FASTMUL
- // if DECDPUN is 1 or 3 work in base 10**9, otherwise
- // (DECDPUN is 2 or 4) then work in base 10**8
- #if DECDPUN & 1 // odd
- #define FASTBASE 1000000000 // base
- #define FASTDIGS 9 // digits in base
- #define FASTLAZY 18 // carry resolution point [1->18]
- #else
- #define FASTBASE 100000000
- #define FASTDIGS 8
- #define FASTLAZY 1844 // carry resolution point [1->1844]
- #endif
- // three buffers are used, two for chunked copies of the operands
- // (base 10**8 or base 10**9) and one base 2**64 accumulator with
- // lazy carry evaluation
- uInt zlhibuff[(DECBUFFER*2+1)/8+1]; // buffer (+1 for DECBUFFER==0)
- uInt *zlhi=zlhibuff; // -> lhs array
- uInt *alloclhi=NULL; // -> allocated buffer, iff allocated
- uInt zrhibuff[(DECBUFFER*2+1)/8+1]; // buffer (+1 for DECBUFFER==0)
- uInt *zrhi=zrhibuff; // -> rhs array
- uInt *allocrhi=NULL; // -> allocated buffer, iff allocated
- uLong zaccbuff[(DECBUFFER*2+1)/4+2]; // buffer (+1 for DECBUFFER==0)
- // [allocacc is shared for both paths, as only one will run]
- uLong *zacc=zaccbuff; // -> accumulator array for exact result
- #if DECDPUN==1
- Int zoff; // accumulator offset
- #endif
- uInt *lip, *rip; // item pointers
- uInt *lmsi, *rmsi; // most significant items
- Int ilhs, irhs, iacc; // item counts in the arrays
- Int lazy; // lazy carry counter
- uLong lcarry; // uLong carry
- uInt carry; // carry (NB not uLong)
- Int count; // work
- const Unit *cup; // ..
- Unit *up; // ..
- uLong *lp; // ..
- Int p; // ..
- #endif
- #if DECSUBSET
- decNumber *alloclhs=NULL; // -> allocated buffer, iff allocated
- decNumber *allocrhs=NULL; // -> allocated buffer, iff allocated
- #endif
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- // precalculate result sign
- bits=(uByte)((lhs->bits^rhs->bits)&DECNEG);
- // handle infinities and NaNs
- if (SPECIALARGS) { // a special bit set
- if (SPECIALARGS & (DECSNAN | DECNAN)) { // one or two NaNs
- decNaNs(res, lhs, rhs, set, status);
- return res;}
- // one or two infinities; Infinity * 0 is invalid
- if (((lhs->bits & DECINF)==0 && ISZERO(lhs))
- ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) {
- *status|=DEC_Invalid_operation;
- return res;}
- decNumberZero(res);
- res->bits=bits|DECINF; // infinity
- return res;}
- // For best speed, as in DMSRCN [the original Rexx numerics
- // module], use the shorter number as the multiplier (rhs) and
- // the longer as the multiplicand (lhs) to minimise the number of
- // adds (partial products)
- if (lhs->digits<rhs->digits) { // swap...
- const decNumber *hold=lhs;
- lhs=rhs;
- rhs=hold;
- }
- do { // protect allocated storage
- #if DECSUBSET
- if (!set->extended) {
- // reduce operands and set lostDigits status, as needed
- if (lhs->digits>set->digits) {
- alloclhs=decRoundOperand(lhs, set, status);
- if (alloclhs==NULL) break;
- lhs=alloclhs;
- }
- if (rhs->digits>set->digits) {
- allocrhs=decRoundOperand(rhs, set, status);
- if (allocrhs==NULL) break;
- rhs=allocrhs;
- }
- }
- #endif
- // [following code does not require input rounding]
- #if FASTMUL // fastpath can be used
- // use the fast path if there are enough digits in the shorter
- // operand to make the setup and takedown worthwhile
- #define NEEDTWO (DECDPUN*2) // within two decUnitAddSub calls
- if (rhs->digits>NEEDTWO) { // use fastpath...
- // calculate the number of elements in each array
- ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; // [ceiling]
- irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; // ..
- iacc=ilhs+irhs;
- // allocate buffers if required, as usual
- needbytes=ilhs*sizeof(uInt);
- if (needbytes>(Int)sizeof(zlhibuff)) {
- alloclhi=(uInt *)malloc(needbytes);
- zlhi=alloclhi;}
- needbytes=irhs*sizeof(uInt);
- if (needbytes>(Int)sizeof(zrhibuff)) {
- allocrhi=(uInt *)malloc(needbytes);
- zrhi=allocrhi;}
- // Allocating the accumulator space needs a special case when
- // DECDPUN=1 because when converting the accumulator to Units
- // after the multiplication each 8-byte item becomes 9 1-byte
- // units. Therefore iacc extra bytes are needed at the front
- // (rounded up to a multiple of 8 bytes), and the uLong
- // accumulator starts offset the appropriate number of units
- // to the right to avoid overwrite during the unchunking.
- needbytes=iacc*sizeof(uLong);
- #if DECDPUN==1
- zoff=(iacc+7)/8; // items to offset by
- needbytes+=zoff*8;
- #endif
- if (needbytes>(Int)sizeof(zaccbuff)) {
- allocacc=(uLong *)malloc(needbytes);
- zacc=(uLong *)allocacc;}
- if (zlhi==NULL||zrhi==NULL||zacc==NULL) {
- *status|=DEC_Insufficient_storage;
- break;}
- acc=(Unit *)zacc; // -> target Unit array
- #if DECDPUN==1
- zacc+=zoff; // start uLong accumulator to right
- #endif
- // assemble the chunked copies of the left and right sides
- for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++)
- for (p=0, *lip=0; p<FASTDIGS && count>0;
- p+=DECDPUN, cup++, count-=DECDPUN)
- *lip+=*cup*powers[p];
- lmsi=lip-1; // save -> msi
- for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++)
- for (p=0, *rip=0; p<FASTDIGS && count>0;
- p+=DECDPUN, cup++, count-=DECDPUN)
- *rip+=*cup*powers[p];
- rmsi=rip-1; // save -> msi
- // zero the accumulator
- for (lp=zacc; lp<zacc+iacc; lp++) *lp=0;
- /* Start the multiplication */
- // Resolving carries can dominate the cost of accumulating the
- // partial products, so this is only done when necessary.
- // Each uLong item in the accumulator can hold values up to
- // 2**64-1, and each partial product can be as large as
- // (10**FASTDIGS-1)**2. When FASTDIGS=9, this can be added to
- // itself 18.4 times in a uLong without overflowing, so during
- // the main calculation resolution is carried out every 18th
- // add -- every 162 digits. Similarly, when FASTDIGS=8, the
- // partial products can be added to themselves 1844.6 times in
- // a uLong without overflowing, so intermediate carry
- // resolution occurs only every 14752 digits. Hence for common
- // short numbers usually only the one final carry resolution
- // occurs.
- // (The count is set via FASTLAZY to simplify experiments to
- // measure the value of this approach: a 35% improvement on a
- // [34x34] multiply.)
- lazy=FASTLAZY; // carry delay count
- for (rip=zrhi; rip<=rmsi; rip++) { // over each item in rhs
- lp=zacc+(rip-zrhi); // where to add the lhs
- for (lip=zlhi; lip<=lmsi; lip++, lp++) { // over each item in lhs
- *lp+=(uLong)(*lip)*(*rip); // [this should in-line]
- } // lip loop
- lazy--;
- if (lazy>0 && rip!=rmsi) continue;
- lazy=FASTLAZY; // reset delay count
- // spin up the accumulator resolving overflows
- for (lp=zacc; lp<zacc+iacc; lp++) {
- if (*lp<FASTBASE) continue; // it fits
- lcarry=*lp/FASTBASE; // top part [slow divide]
- // lcarry can exceed 2**32-1, so check again; this check
- // and occasional extra divide (slow) is well worth it, as
- // it allows FASTLAZY to be increased to 18 rather than 4
- // in the FASTDIGS=9 case
- if (lcarry<FASTBASE) carry=(uInt)lcarry; // [usual]
- else { // two-place carry [fairly rare]
- uInt carry2=(uInt)(lcarry/FASTBASE); // top top part
- *(lp+2)+=carry2; // add to item+2
- *lp-=((uLong)FASTBASE*FASTBASE*carry2); // [slow]
- carry=(uInt)(lcarry-((uLong)FASTBASE*carry2)); // [inline]
- }
- *(lp+1)+=carry; // add to item above [inline]
- *lp-=((uLong)FASTBASE*carry); // [inline]
- } // carry resolution
- } // rip loop
- // The multiplication is complete; time to convert back into
- // units. This can be done in-place in the accumulator and in
- // 32-bit operations, because carries were resolved after the
- // final add. This needs N-1 divides and multiplies for
- // each item in the accumulator (which will become up to N
- // units, where 2<=N<=9).
- for (lp=zacc, up=acc; lp<zacc+iacc; lp++) {
- uInt item=(uInt)*lp; // decapitate to uInt
- for (p=0; p<FASTDIGS-DECDPUN; p+=DECDPUN, up++) {
- uInt part=item/(DECDPUNMAX+1);
- *up=(Unit)(item-(part*(DECDPUNMAX+1)));
- item=part;
- } // p
- *up=(Unit)item; up++; // [final needs no division]
- } // lp
- accunits=up-acc; // count of units
- }
- else { // here to use units directly, without chunking ['old code']
- #endif
- // if accumulator will be too long for local storage, then allocate
- acc=accbuff; // -> assume buffer for accumulator
- needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit);
- if (needbytes>(Int)sizeof(accbuff)) {
- allocacc=(Unit *)malloc(needbytes);
- if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;}
- acc=(Unit *)allocacc; // use the allocated space
- }
- /* Now the main long multiplication loop */
- // Unlike the equivalent in the IBM Java implementation, there
- // is no advantage in calculating from msu to lsu. So, do it
- // by the book, as it were.
- // Each iteration calculates ACC=ACC+MULTAND*MULT
- accunits=1; // accumulator starts at '0'
- *acc=0; // .. (lsu=0)
- shift=0; // no multiplicand shift at first
- madlength=D2U(lhs->digits); // this won't change
- mermsup=rhs->lsu+D2U(rhs->digits); // -> msu+1 of multiplier
- for (mer=rhs->lsu; mer<mermsup; mer++) {
- // Here, *mer is the next Unit in the multiplier to use
- // If non-zero [optimization] add it...
- if (*mer!=0) accunits=decUnitAddSub(&acc[shift], accunits-shift,
- lhs->lsu, madlength, 0,
- &acc[shift], *mer)
- + shift;
- else { // extend acc with a 0; it will be used shortly
- *(acc+accunits)=0; // [this avoids length of <=0 later]
- accunits++;
- }
- // multiply multiplicand by 10**DECDPUN for next Unit to left
- shift++; // add this for 'logical length'
- } // n
- #if FASTMUL
- } // unchunked units
- #endif
- // common end-path
- #if DECTRACE
- decDumpAr('*', acc, accunits); // Show exact result
- #endif
- // acc now contains the exact result of the multiplication,
- // possibly with a leading zero unit; build the decNumber from
- // it, noting if any residue
- res->bits=bits; // set sign
- res->digits=decGetDigits(acc, accunits); // count digits exactly
- // There can be a 31-bit wrap in calculating the exponent.
- // This can only happen if both input exponents are negative and
- // both their magnitudes are large. If there was a wrap, set a
- // safe very negative exponent, from which decFinalize() will
- // raise a hard underflow shortly.
- exponent=lhs->exponent+rhs->exponent; // calculate exponent
- if (lhs->exponent<0 && rhs->exponent<0 && exponent>0)
- exponent=-2*DECNUMMAXE; // force underflow
- res->exponent=exponent; // OK to overwrite now
- // Set the coefficient. If any rounding, residue records
- decSetCoeff(res, set, acc, res->digits, &residue, status);
- decFinish(res, set, &residue, status); // final cleanup
- } while(0); // end protected
- if (allocacc!=NULL) free(allocacc); // drop any storage used
- #if DECSUBSET
- if (allocrhs!=NULL) free(allocrhs); // ..
- if (alloclhs!=NULL) free(alloclhs); // ..
- #endif
- #if FASTMUL
- if (allocrhi!=NULL) free(allocrhi); // ..
- if (alloclhi!=NULL) free(alloclhi); // ..
- #endif
- return res;
- } // decMultiplyOp
- /* ------------------------------------------------------------------ */
- /* decExpOp -- effect exponentiation */
- /* */
- /* This computes C = exp(A) */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context; note that rounding mode has no effect */
- /* */
- /* C must have space for set->digits digits. status is updated but */
- /* not set. */
- /* */
- /* Restrictions: */
- /* */
- /* digits, emax, and -emin in the context must be less than */
- /* 2*DEC_MAX_MATH (1999998), and the rhs must be within these */
- /* bounds or a zero. This is an internal routine, so these */
- /* restrictions are contractual and not enforced. */
- /* */
- /* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */
- /* almost always be correctly rounded, but may be up to 1 ulp in */
- /* error in rare cases. */
- /* */
- /* Finite results will always be full precision and Inexact, except */
- /* when A is a zero or -Infinity (giving 1 or 0 respectively). */
- /* ------------------------------------------------------------------ */
- /* This approach used here is similar to the algorithm described in */
- /* */
- /* Variable Precision Exponential Function, T. E. Hull and */
- /* A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */
- /* pp79-91, ACM, June 1986. */
- /* */
- /* with the main difference being that the iterations in the series */
- /* evaluation are terminated dynamically (which does not require the */
- /* extra variable-precision variables which are expensive in this */
- /* context). */
- /* */
- /* The error analysis in Hull & Abrham's paper applies except for the */
- /* round-off error accumulation during the series evaluation. This */
- /* code does not precalculate the number of iterations and so cannot */
- /* use Horner's scheme. Instead, the accumulation is done at double- */
- /* precision, which ensures that the additions of the terms are exact */
- /* and do not accumulate round-off (and any round-off errors in the */
- /* terms themselves move 'to the right' faster than they can */
- /* accumulate). This code also extends the calculation by allowing, */
- /* in the spirit of other decNumber operators, the input to be more */
- /* precise than the result (the precision used is based on the more */
- /* precise of the input or requested result). */
- /* */
- /* Implementation notes: */
- /* */
- /* 1. This is separated out as decExpOp so it can be called from */
- /* other Mathematical functions (notably Ln) with a wider range */
- /* than normal. In particular, it can handle the slightly wider */
- /* (double) range needed by Ln (which has to be able to calculate */
- /* exp(-x) where x can be the tiniest number (Ntiny). */
- /* */
- /* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop */
- /* iterations by appoximately a third with additional (although */
- /* diminishing) returns as the range is reduced to even smaller */
- /* fractions. However, h (the power of 10 used to correct the */
- /* result at the end, see below) must be kept <=8 as otherwise */
- /* the final result cannot be computed. Hence the leverage is a */
- /* sliding value (8-h), where potentially the range is reduced */
- /* more for smaller values. */
- /* */
- /* The leverage that can be applied in this way is severely */
- /* limited by the cost of the raise-to-the power at the end, */
- /* which dominates when the number of iterations is small (less */
- /* than ten) or when rhs is short. As an example, the adjustment */
- /* x**10,000,000 needs 31 multiplications, all but one full-width. */
- /* */
- /* 3. The restrictions (especially precision) could be raised with */
- /* care, but the full decNumber range seems very hard within the */
- /* 32-bit limits. */
- /* */
- /* 4. The working precisions for the static buffers are twice the */
- /* obvious size to allow for calls from decNumberPower. */
- /* ------------------------------------------------------------------ */
- decNumber * decExpOp(decNumber *res, const decNumber *rhs,
- decContext *set, uInt *status) {
- uInt ignore=0; // working status
- Int h; // adjusted exponent for 0.xxxx
- Int p; // working precision
- Int residue; // rounding residue
- uInt needbytes; // for space calculations
- const decNumber *x=rhs; // (may point to safe copy later)
- decContext aset, tset, dset; // working contexts
- Int comp; // work
- // the argument is often copied to normalize it, so (unusually) it
- // is treated like other buffers, using DECBUFFER, +1 in case
- // DECBUFFER is 0
- decNumber bufr[D2N(DECBUFFER*2+1)];
- decNumber *allocrhs=NULL; // non-NULL if rhs buffer allocated
- // the working precision will be no more than set->digits+8+1
- // so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER
- // is 0 (and twice that for the accumulator)
- // buffer for t, term (working precision plus)
- decNumber buft[D2N(DECBUFFER*2+9+1)];
- decNumber *allocbuft=NULL; // -> allocated buft, iff allocated
- decNumber *t=buft; // term
- // buffer for a, accumulator (working precision * 2), at least 9
- decNumber bufa[D2N(DECBUFFER*4+18+1)];
- decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated
- decNumber *a=bufa; // accumulator
- // decNumber for the divisor term; this needs at most 9 digits
- // and so can be fixed size [16 so can use standard context]
- decNumber bufd[D2N(16)];
- decNumber *d=bufd; // divisor
- decNumber numone; // constant 1
- #if DECCHECK
- Int iterations=0; // for later sanity check
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- do { // protect allocated storage
- if (SPECIALARG) { // handle infinities and NaNs
- if (decNumberIsInfinite(rhs)) { // an infinity
- if (decNumberIsNegative(rhs)) // -Infinity -> +0
- decNumberZero(res);
- else decNumberCopy(res, rhs); // +Infinity -> self
- }
- else decNaNs(res, rhs, NULL, set, status); // a NaN
- break;}
- if (ISZERO(rhs)) { // zeros -> exact 1
- decNumberZero(res); // make clean 1
- *res->lsu=1; // ..
- break;} // [no status to set]
- // e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path
- // positive and negative tiny cases which will result in inexact
- // 1. This also allows the later add-accumulate to always be
- // exact (because its length will never be more than twice the
- // working precision).
- // The comparator (tiny) needs just one digit, so use the
- // decNumber d for it (reused as the divisor, etc., below); its
- // exponent is such that if x is positive it will have
- // set->digits-1 zeros between the decimal point and the digit,
- // which is 4, and if x is negative one more zero there as the
- // more precise result will be of the form 0.9999999 rather than
- // 1.0000001. Hence, tiny will be 0.0000004 if digits=7 and x>0
- // or 0.00000004 if digits=7 and x<0. If RHS not larger than
- // this then the result will be 1.000000
- decNumberZero(d); // clean
- *d->lsu=4; // set 4 ..
- d->exponent=-set->digits; // * 10**(-d)
- if (decNumberIsNegative(rhs)) d->exponent--; // negative case
- comp=decCompare(d, rhs, 1); // signless compare
- if (comp==BADINT) {
- *status|=DEC_Insufficient_storage;
- break;}
- if (comp>=0) { // rhs < d
- Int shift=set->digits-1;
- decNumberZero(res); // set 1
- *res->lsu=1; // ..
- res->digits=decShiftToMost(res->lsu, 1, shift);
- res->exponent=-shift; // make 1.0000...
- *status|=DEC_Inexact | DEC_Rounded; // .. inexactly
- break;} // tiny
- // set up the context to be used for calculating a, as this is
- // used on both paths below
- decContextDefault(&aset, DEC_INIT_DECIMAL64);
- // accumulator bounds are as requested (could underflow)
- aset.emax=set->emax; // usual bounds
- aset.emin=set->emin; // ..
- aset.clamp=0; // and no concrete format
- // calculate the adjusted (Hull & Abrham) exponent (where the
- // decimal point is just to the left of the coefficient msd)
- h=rhs->exponent+rhs->digits;
- // if h>8 then 10**h cannot be calculated safely; however, when
- // h=8 then exp(|rhs|) will be at least exp(1E+7) which is at
- // least 6.59E+4342944, so (due to the restriction on Emax/Emin)
- // overflow (or underflow to 0) is guaranteed -- so this case can
- // be handled by simply forcing the appropriate excess
- if (h>8) { // overflow/underflow
- // set up here so Power call below will over or underflow to
- // zero; set accumulator to either 2 or 0.02
- // [stack buffer for a is always big enough for this]
- decNumberZero(a);
- *a->lsu=2; // not 1 but < exp(1)
- if (decNumberIsNegative(rhs)) a->exponent=-2; // make 0.02
- h=8; // clamp so 10**h computable
- p=9; // set a working precision
- }
- else { // h<=8
- Int maxlever=(rhs->digits>8?1:0);
- // [could/should increase this for precisions >40 or so, too]
- // if h is 8, cannot normalize to a lower upper limit because
- // the final result will not be computable (see notes above),
- // but leverage can be applied whenever h is less than 8.
- // Apply as much as possible, up to a MAXLEVER digits, which
- // sets the tradeoff against the cost of the later a**(10**h).
- // As h is increased, the working precision below also
- // increases to compensate for the "constant digits at the
- // front" effect.
- Int lever=MINI(8-h, maxlever); // leverage attainable
- Int use=-rhs->digits-lever; // exponent to use for RHS
- h+=lever; // apply leverage selected
- if (h<0) { // clamp
- use+=h; // [may end up subnormal]
- h=0;
- }
- // Take a copy of RHS if it needs normalization (true whenever x>=1)
- if (rhs->exponent!=use) {
- decNumber *newrhs=bufr; // assume will fit on stack
- needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
- if (needbytes>sizeof(bufr)) { // need malloc space
- allocrhs=(decNumber *)malloc(needbytes);
- if (allocrhs==NULL) { // hopeless -- abandon
- *status|=DEC_Insufficient_storage;
- break;}
- newrhs=allocrhs; // use the allocated space
- }
- decNumberCopy(newrhs, rhs); // copy to safe space
- newrhs->exponent=use; // normalize; now <1
- x=newrhs; // ready for use
- // decNumberShow(x);
- }
- // Now use the usual power series to evaluate exp(x). The
- // series starts as 1 + x + x^2/2 ... so prime ready for the
- // third term by setting the term variable t=x, the accumulator
- // a=1, and the divisor d=2.
- // First determine the working precision. From Hull & Abrham
- // this is set->digits+h+2. However, if x is 'over-precise' we
- // need to allow for all its digits to potentially participate
- // (consider an x where all the excess digits are 9s) so in
- // this case use x->digits+h+2
- p=MAXI(x->digits, set->digits)+h+2; // [h<=8]
- // a and t are variable precision, and depend on p, so space
- // must be allocated for them if necessary
- // the accumulator needs to be able to hold 2p digits so that
- // the additions on the second and subsequent iterations are
- // sufficiently exact.
- needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit);
- if (needbytes>sizeof(bufa)) { // need malloc space
- allocbufa=(decNumber *)malloc(needbytes);
- if (allocbufa==NULL) { // hopeless -- abandon
- *status|=DEC_Insufficient_storage;
- break;}
- a=allocbufa; // use the allocated space
- }
- // the term needs to be able to hold p digits (which is
- // guaranteed to be larger than x->digits, so the initial copy
- // is safe); it may also be used for the raise-to-power
- // calculation below, which needs an extra two digits
- needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit);
- if (needbytes>sizeof(buft)) { // need malloc space
- allocbuft=(decNumber *)malloc(needbytes);
- if (allocbuft==NULL) { // hopeless -- abandon
- *status|=DEC_Insufficient_storage;
- break;}
- t=allocbuft; // use the allocated space
- }
- decNumberCopy(t, x); // term=x
- decNumberZero(a); *a->lsu=1; // accumulator=1
- decNumberZero(d); *d->lsu=2; // divisor=2
- decNumberZero(&numone); *numone.lsu=1; // constant 1 for increment
- // set up the contexts for calculating a, t, and d
- decContextDefault(&tset, DEC_INIT_DECIMAL64);
- dset=tset;
- // accumulator bounds are set above, set precision now
- aset.digits=p*2; // double
- // term bounds avoid any underflow or overflow
- tset.digits=p;
- tset.emin=DEC_MIN_EMIN; // [emax is plenty]
- // [dset.digits=16, etc., are sufficient]
- // finally ready to roll
- for (;;) {
- #if DECCHECK
- iterations++;
- #endif
- // only the status from the accumulation is interesting
- // [but it should remain unchanged after first add]
- decAddOp(a, a, t, &aset, 0, status); // a=a+t
- decMultiplyOp(t, t, x, &tset, &ignore); // t=t*x
- decDivideOp(t, t, d, &tset, DIVIDE, &ignore); // t=t/d
- // the iteration ends when the term cannot affect the result,
- // if rounded to p digits, which is when its value is smaller
- // than the accumulator by p+1 digits. There must also be
- // full precision in a.
- if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1))
- && (a->digits>=p)) break;
- decAddOp(d, d, &numone, &dset, 0, &ignore); // d=d+1
- } // iterate
- #if DECCHECK
- // just a sanity check; comment out test to show always
- if (iterations>p+3)
- printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
- (LI)iterations, (LI)*status, (LI)p, (LI)x->digits);
- #endif
- } // h<=8
- // apply postconditioning: a=a**(10**h) -- this is calculated
- // at a slightly higher precision than Hull & Abrham suggest
- if (h>0) {
- Int seenbit=0; // set once a 1-bit is seen
- Int i; // counter
- Int n=powers[h]; // always positive
- aset.digits=p+2; // sufficient precision
- // avoid the overhead and many extra digits of decNumberPower
- // as all that is needed is the short 'multipliers' loop; here
- // accumulate the answer into t
- decNumberZero(t); *t->lsu=1; // acc=1
- for (i=1;;i++){ // for each bit [top bit ignored]
- // abandon if have had overflow or terminal underflow
- if (*status & (DEC_Overflow|DEC_Underflow)) { // interesting?
- if (*status&DEC_Overflow || ISZERO(t)) break;}
- n=n<<1; // move next bit to testable position
- if (n<0) { // top bit is set
- seenbit=1; // OK, have a significant bit
- decMultiplyOp(t, t, a, &aset, status); // acc=acc*x
- }
- if (i==31) break; // that was the last bit
- if (!seenbit) continue; // no need to square 1
- decMultiplyOp(t, t, t, &aset, status); // acc=acc*acc [square]
- } /*i*/ // 32 bits
- // decNumberShow(t);
- a=t; // and carry on using t instead of a
- }
- // Copy and round the result to res
- residue=1; // indicate dirt to right ..
- if (ISZERO(a)) residue=0; // .. unless underflowed to 0
- aset.digits=set->digits; // [use default rounding]
- decCopyFit(res, a, &aset, &residue, status); // copy & shorten
- decFinish(res, set, &residue, status); // cleanup/set flags
- } while(0); // end protected
- if (allocrhs !=NULL) free(allocrhs); // drop any storage used
- if (allocbufa!=NULL) free(allocbufa); // ..
- if (allocbuft!=NULL) free(allocbuft); // ..
- // [status is handled by caller]
- return res;
- } // decExpOp
- /* ------------------------------------------------------------------ */
- /* Initial-estimate natural logarithm table */
- /* */
- /* LNnn -- 90-entry 16-bit table for values from .10 through .99. */
- /* The result is a 4-digit encode of the coefficient (c=the */
- /* top 14 bits encoding 0-9999) and a 2-digit encode of the */
- /* exponent (e=the bottom 2 bits encoding 0-3) */
- /* */
- /* The resulting value is given by: */
- /* */
- /* v = -c * 10**(-e-3) */
- /* */
- /* where e and c are extracted from entry k = LNnn[x-10] */
- /* where x is truncated (NB) into the range 10 through 99, */
- /* and then c = k>>2 and e = k&3. */
- /* ------------------------------------------------------------------ */
- const uShort LNnn[90]={9016, 8652, 8316, 8008, 7724, 7456, 7208,
- 6972, 6748, 6540, 6340, 6148, 5968, 5792, 5628, 5464, 5312,
- 5164, 5020, 4884, 4748, 4620, 4496, 4376, 4256, 4144, 4032,
- 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629,
- 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837,
- 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321,
- 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717,
- 10197, 9685, 9177, 8677, 8185, 7697, 7213, 6737, 6269, 5801,
- 5341, 4889, 4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254,
- 10130, 6046, 20055};
- /* ------------------------------------------------------------------ */
- /* decLnOp -- effect natural logarithm */
- /* */
- /* This computes C = ln(A) */
- /* */
- /* res is C, the result. C may be A */
- /* rhs is A */
- /* set is the context; note that rounding mode has no effect */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Notable cases: */
- /* A<0 -> Invalid */
- /* A=0 -> -Infinity (Exact) */
- /* A=+Infinity -> +Infinity (Exact) */
- /* A=1 exactly -> 0 (Exact) */
- /* */
- /* Restrictions (as for Exp): */
- /* */
- /* digits, emax, and -emin in the context must be less than */
- /* DEC_MAX_MATH+11 (1000010), and the rhs must be within these */
- /* bounds or a zero. This is an internal routine, so these */
- /* restrictions are contractual and not enforced. */
- /* */
- /* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */
- /* almost always be correctly rounded, but may be up to 1 ulp in */
- /* error in rare cases. */
- /* ------------------------------------------------------------------ */
- /* The result is calculated using Newton's method, with each */
- /* iteration calculating a' = a + x * exp(-a) - 1. See, for example, */
- /* Epperson 1989. */
- /* */
- /* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */
- /* This has to be calculated at the sum of the precision of x and the */
- /* working precision. */
- /* */
- /* Implementation notes: */
- /* */
- /* 1. This is separated out as decLnOp so it can be called from */
- /* other Mathematical functions (e.g., Log 10) with a wider range */
- /* than normal. In particular, it can handle the slightly wider */
- /* (+9+2) range needed by a power function. */
- /* */
- /* 2. The speed of this function is about 10x slower than exp, as */
- /* it typically needs 4-6 iterations for short numbers, and the */
- /* extra precision needed adds a squaring effect, twice. */
- /* */
- /* 3. Fastpaths are included for ln(10) and ln(2), up to length 40, */
- /* as these are common requests. ln(10) is used by log10(x). */
- /* */
- /* 4. An iteration might be saved by widening the LNnn table, and */
- /* would certainly save at least one if it were made ten times */
- /* bigger, too (for truncated fractions 0.100 through 0.999). */
- /* However, for most practical evaluations, at least four or five */
- /* iterations will be neede -- so this would only speed up by */
- /* 20-25% and that probably does not justify increasing the table */
- /* size. */
- /* */
- /* 5. The static buffers are larger than might be expected to allow */
- /* for calls from decNumberPower. */
- /* ------------------------------------------------------------------ */
- decNumber * decLnOp(decNumber *res, const decNumber *rhs,
- decContext *set, uInt *status) {
- uInt ignore=0; // working status accumulator
- uInt needbytes; // for space calculations
- Int residue; // rounding residue
- Int r; // rhs=f*10**r [see below]
- Int p; // working precision
- Int pp; // precision for iteration
- Int t; // work
- // buffers for a (accumulator, typically precision+2) and b
- // (adjustment calculator, same size)
- decNumber bufa[D2N(DECBUFFER+12)];
- decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated
- decNumber *a=bufa; // accumulator/work
- decNumber bufb[D2N(DECBUFFER*2+2)];
- decNumber *allocbufb=NULL; // -> allocated bufa, iff allocated
- decNumber *b=bufb; // adjustment/work
- decNumber numone; // constant 1
- decNumber cmp; // work
- decContext aset, bset; // working contexts
- #if DECCHECK
- Int iterations=0; // for later sanity check
- if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
- #endif
- do { // protect allocated storage
- if (SPECIALARG) { // handle infinities and NaNs
- if (decNumberIsInfinite(rhs)) { // an infinity
- if (decNumberIsNegative(rhs)) // -Infinity -> error
- *status|=DEC_Invalid_operation;
- else decNumberCopy(res, rhs); // +Infinity -> self
- }
- else decNaNs(res, rhs, NULL, set, status); // a NaN
- break;}
- if (ISZERO(rhs)) { // +/- zeros -> -Infinity
- decNumberZero(res); // make clean
- res->bits=DECINF|DECNEG; // set - infinity
- break;} // [no status to set]
- // Non-zero negatives are bad...
- if (decNumberIsNegative(rhs)) { // -x -> error
- *status|=DEC_Invalid_operation;
- break;}
- // Here, rhs is positive, finite, and in range
- // lookaside fastpath code for ln(2) and ln(10) at common lengths
- if (rhs->exponent==0 && set->digits<=40) {
- #if DECDPUN==1
- if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { // ln(10)
- #else
- if (rhs->lsu[0]==10 && rhs->digits==2) { // ln(10)
- #endif
- aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
- #define LN10 "2.302585092994045684017991454684364207601"
- decNumberFromString(res, LN10, &aset);
- *status|=(DEC_Inexact | DEC_Rounded); // is inexact
- break;}
- if (rhs->lsu[0]==2 && rhs->digits==1) { // ln(2)
- aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
- #define LN2 "0.6931471805599453094172321214581765680755"
- decNumberFromString(res, LN2, &aset);
- *status|=(DEC_Inexact | DEC_Rounded);
- break;}
- } // integer and short
- // Determine the working precision. This is normally the
- // requested precision + 2, with a minimum of 9. However, if
- // the rhs is 'over-precise' then allow for all its digits to
- // potentially participate (consider an rhs where all the excess
- // digits are 9s) so in this case use rhs->digits+2.
- p=MAXI(rhs->digits, MAXI(set->digits, 7))+2;
- // Allocate space for the accumulator and the high-precision
- // adjustment calculator, if necessary. The accumulator must
- // be able to hold p digits, and the adjustment up to
- // rhs->digits+p digits. They are also made big enough for 16
- // digits so that they can be used for calculating the initial
- // estimate.
- needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit);
- if (needbytes>sizeof(bufa)) { // need malloc space
- allocbufa=(decNumber *)malloc(needbytes);
- if (allocbufa==NULL) { // hopeless -- abandon
- *status|=DEC_Insufficient_storage;
- break;}
- a=allocbufa; // use the allocated space
- }
- pp=p+rhs->digits;
- needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit);
- if (needbytes>sizeof(bufb)) { // need malloc space
- allocbufb=(decNumber *)malloc(needbytes);
- if (allocbufb==NULL) { // hopeless -- abandon
- *status|=DEC_Insufficient_storage;
- break;}
- b=allocbufb; // use the allocated space
- }
- // Prepare an initial estimate in acc. Calculate this by
- // considering the coefficient of x to be a normalized fraction,
- // f, with the decimal point at far left and multiplied by
- // 10**r. Then, rhs=f*10**r and 0.1<=f<1, and
- // ln(x) = ln(f) + ln(10)*r
- // Get the initial estimate for ln(f) from a small lookup
- // table (see above) indexed by the first two digits of f,
- // truncated.
- decContextDefault(&aset, DEC_INIT_DECIMAL64); // 16-digit extended
- r=rhs->exponent+rhs->digits; // 'normalised' exponent
- decNumberFromInt32(a, r); // a=r
- decNumberFromInt32(b, 2302585); // b=ln(10) (2.302585)
- b->exponent=-6; // ..
- decMultiplyOp(a, a, b, &aset, &ignore); // a=a*b
- // now get top two digits of rhs into b by simple truncate and
- // force to integer
- residue=0; // (no residue)
- aset.digits=2; aset.round=DEC_ROUND_DOWN;
- decCopyFit(b, rhs, &aset, &residue, &ignore); // copy & shorten
- b->exponent=0; // make integer
- t=decGetInt(b); // [cannot fail]
- if (t<10) t=X10(t); // adjust single-digit b
- t=LNnn[t-10]; // look up ln(b)
- decNumberFromInt32(b, t>>2); // b=ln(b) coefficient
- b->exponent=-(t&3)-3; // set exponent
- b->bits=DECNEG; // ln(0.10)->ln(0.99) always -ve
- aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; // restore
- decAddOp(a, a, b, &aset, 0, &ignore); // acc=a+b
- // the initial estimate is now in a, with up to 4 digits correct.
- // When rhs is at or near Nmax the estimate will be low, so we
- // will approach it from below, avoiding overflow when calling exp.
- decNumberZero(&numone); *numone.lsu=1; // constant 1 for adjustment
- // accumulator bounds are as requested (could underflow, but
- // cannot overflow)
- aset.emax=set->emax;
- aset.emin=set->emin;
- aset.clamp=0; // no concrete format
- // set up a context to be used for the multiply and subtract
- bset=aset;
- bset.emax=DEC_MAX_MATH*2; // use double bounds for the
- bset.emin=-DEC_MAX_MATH*2; // adjustment calculation
- // [see decExpOp call below]
- // for each iteration double the number of digits to calculate,
- // up to a maximum of p
- pp=9; // initial precision
- // [initially 9 as then the sequence starts 7+2, 16+2, and
- // 34+2, which is ideal for standard-sized numbers]
- aset.digits=pp; // working context
- bset.digits=pp+rhs->digits; // wider context
- for (;;) { // iterate
- #if DECCHECK
- iterations++;
- if (iterations>24) break; // consider 9 * 2**24
- #endif
- // calculate the adjustment (exp(-a)*x-1) into b. This is a
- // catastrophic subtraction but it really is the difference
- // from 1 that is of interest.
- // Use the internal entry point to Exp as it allows the double
- // range for calculating exp(-a) when a is the tiniest subnormal.
- a->bits^=DECNEG; // make -a
- decExpOp(b, a, &bset, &ignore); // b=exp(-a)
- a->bits^=DECNEG; // restore sign of a
- // now multiply by rhs and subtract 1, at the wider precision
- decMultiplyOp(b, b, rhs, &bset, &ignore); // b=b*rhs
- decAddOp(b, b, &numone, &bset, DECNEG, &ignore); // b=b-1
- // the iteration ends when the adjustment cannot affect the
- // result by >=0.5 ulp (at the requested digits), which
- // is when its value is smaller than the accumulator by
- // set->digits+1 digits (or it is zero) -- this is a looser
- // requirement than for Exp because all that happens to the
- // accumulator after this is the final rounding (but note that
- // there must also be full precision in a, or a=0).
- if (decNumberIsZero(b) ||
- (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) {
- if (a->digits==p) break;
- if (decNumberIsZero(a)) {
- decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); // rhs=1 ?
- if (cmp.lsu[0]==0) a->exponent=0; // yes, exact 0
- else *status|=(DEC_Inexact | DEC_Rounded); // no, inexact
- break;
- }
- // force padding if adjustment has gone to 0 before full length
- if (decNumberIsZero(b)) b->exponent=a->exponent-p;
- }
- // not done yet ...
- decAddOp(a, a, b, &aset, 0, &ignore); // a=a+b for next estimate
- if (pp==p) continue; // precision is at maximum
- // lengthen the next calculation
- pp=pp*2; // double precision
- if (pp>p) pp=p; // clamp to maximum
- aset.digits=pp; // working context
- bset.digits=pp+rhs->digits; // wider context
- } // Newton's iteration
- #if DECCHECK
- // just a sanity check; remove the test to show always
- if (iterations>24)
- printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
- (LI)iterations, (LI)*status, (LI)p, (LI)rhs->digits);
- #endif
- // Copy and round the result to res
- residue=1; // indicate dirt to right
- if (ISZERO(a)) residue=0; // .. unless underflowed to 0
- aset.digits=set->digits; // [use default rounding]
- decCopyFit(res, a, &aset, &residue, status); // copy & shorten
- decFinish(res, set, &residue, status); // cleanup/set flags
- } while(0); // end protected
- if (allocbufa!=NULL) free(allocbufa); // drop any storage used
- if (allocbufb!=NULL) free(allocbufb); // ..
- // [status is handled by caller]
- return res;
- } // decLnOp
- /* ------------------------------------------------------------------ */
- /* decQuantizeOp -- force exponent to requested value */
- /* */
- /* This computes C = op(A, B), where op adjusts the coefficient */
- /* of C (by rounding or shifting) such that the exponent (-scale) */
- /* of C has the value B or matches the exponent of B. */
- /* The numerical value of C will equal A, except for the effects of */
- /* any rounding that occurred. */
- /* */
- /* res is C, the result. C may be A or B */
- /* lhs is A, the number to adjust */
- /* rhs is B, the requested exponent */
- /* set is the context */
- /* quant is 1 for quantize or 0 for rescale */
- /* status is the status accumulator (this can be called without */
- /* risk of control loss) */
- /* */
- /* C must have space for set->digits digits. */
- /* */
- /* Unless there is an error or the result is infinite, the exponent */
- /* after the operation is guaranteed to be that requested. */
- /* ------------------------------------------------------------------ */
- static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set,
- Flag quant, uInt *status) {
- #if DECSUBSET
- decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated
- decNumber *allocrhs=NULL; // .., rhs
- #endif
- const decNumber *inrhs=rhs; // save original rhs
- Int reqdigits=set->digits; // requested DIGITS
- Int reqexp; // requested exponent [-scale]
- Int residue=0; // rounding residue
- Int etiny=set->emin-(reqdigits-1);
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- do { // protect allocated storage
- #if DECSUBSET
- if (!set->extended) {
- // reduce operands and set lostDigits status, as needed
- if (lhs->digits>reqdigits) {
- alloclhs=decRoundOperand(lhs, set, status);
- if (alloclhs==NULL) break;
- lhs=alloclhs;
- }
- if (rhs->digits>reqdigits) { // [this only checks lostDigits]
- allocrhs=decRoundOperand(rhs, set, status);
- if (allocrhs==NULL) break;
- rhs=allocrhs;
- }
- }
- #endif
- // [following code does not require input rounding]
- // Handle special values
- if (SPECIALARGS) {
- // NaNs get usual processing
- if (SPECIALARGS & (DECSNAN | DECNAN))
- decNaNs(res, lhs, rhs, set, status);
- // one infinity but not both is bad
- else if ((lhs->bits ^ rhs->bits) & DECINF)
- *status|=DEC_Invalid_operation;
- // both infinity: return lhs
- else decNumberCopy(res, lhs); // [nop if in place]
- break;
- }
- // set requested exponent
- if (quant) reqexp=inrhs->exponent; // quantize -- match exponents
- else { // rescale -- use value of rhs
- // Original rhs must be an integer that fits and is in range,
- // which could be from -1999999997 to +999999999, thanks to
- // subnormals
- reqexp=decGetInt(inrhs); // [cannot fail]
- }
- #if DECSUBSET
- if (!set->extended) etiny=set->emin; // no subnormals
- #endif
- if (reqexp==BADINT // bad (rescale only) or ..
- || reqexp==BIGODD || reqexp==BIGEVEN // very big (ditto) or ..
- || (reqexp<etiny) // < lowest
- || (reqexp>set->emax)) { // > emax
- *status|=DEC_Invalid_operation;
- break;}
- // the RHS has been processed, so it can be overwritten now if necessary
- if (ISZERO(lhs)) { // zero coefficient unchanged
- decNumberCopy(res, lhs); // [nop if in place]
- res->exponent=reqexp; // .. just set exponent
- #if DECSUBSET
- if (!set->extended) res->bits=0; // subset specification; no -0
- #endif
- }
- else { // non-zero lhs
- Int adjust=reqexp-lhs->exponent; // digit adjustment needed
- // if adjusted coefficient will definitely not fit, give up now
- if ((lhs->digits-adjust)>reqdigits) {
- *status|=DEC_Invalid_operation;
- break;
- }
- if (adjust>0) { // increasing exponent
- // this will decrease the length of the coefficient by adjust
- // digits, and must round as it does so
- decContext workset; // work
- workset=*set; // clone rounding, etc.
- workset.digits=lhs->digits-adjust; // set requested length
- // [note that the latter can be <1, here]
- decCopyFit(res, lhs, &workset, &residue, status); // fit to result
- decApplyRound(res, &workset, residue, status); // .. and round
- residue=0; // [used]
- // If just rounded a 999s case, exponent will be off by one;
- // adjust back (after checking space), if so.
- if (res->exponent>reqexp) {
- // re-check needed, e.g., for quantize(0.9999, 0.001) under
- // set->digits==3
- if (res->digits==reqdigits) { // cannot shift by 1
- *status&=~(DEC_Inexact | DEC_Rounded); // [clean these]
- *status|=DEC_Invalid_operation;
- break;
- }
- res->digits=decShiftToMost(res->lsu, res->digits, 1); // shift
- res->exponent--; // (re)adjust the exponent.
- }
- #if DECSUBSET
- if (ISZERO(res) && !set->extended) res->bits=0; // subset; no -0
- #endif
- } // increase
- else /* adjust<=0 */ { // decreasing or = exponent
- // this will increase the length of the coefficient by -adjust
- // digits, by adding zero or more trailing zeros; this is
- // already checked for fit, above
- decNumberCopy(res, lhs); // [it will fit]
- // if padding needed (adjust<0), add it now...
- if (adjust<0) {
- res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
- res->exponent+=adjust; // adjust the exponent
- }
- } // decrease
- } // non-zero
- // Check for overflow [do not use Finalize in this case, as an
- // overflow here is a "don't fit" situation]
- if (res->exponent>set->emax-res->digits+1) { // too big
- *status|=DEC_Invalid_operation;
- break;
- }
- else {
- decFinalize(res, set, &residue, status); // set subnormal flags
- *status&=~DEC_Underflow; // suppress Underflow [as per 754]
- }
- } while(0); // end protected
- #if DECSUBSET
- if (allocrhs!=NULL) free(allocrhs); // drop any storage used
- if (alloclhs!=NULL) free(alloclhs); // ..
- #endif
- return res;
- } // decQuantizeOp
- /* ------------------------------------------------------------------ */
- /* decCompareOp -- compare, min, or max two Numbers */
- /* */
- /* This computes C = A ? B and carries out one of four operations: */
- /* COMPARE -- returns the signum (as a number) giving the */
- /* result of a comparison unless one or both */
- /* operands is a NaN (in which case a NaN results) */
- /* COMPSIG -- as COMPARE except that a quiet NaN raises */
- /* Invalid operation. */
- /* COMPMAX -- returns the larger of the operands, using the */
- /* 754 maxnum operation */
- /* COMPMAXMAG -- ditto, comparing absolute values */
- /* COMPMIN -- the 754 minnum operation */
- /* COMPMINMAG -- ditto, comparing absolute values */
- /* COMTOTAL -- returns the signum (as a number) giving the */
- /* result of a comparison using 754 total ordering */
- /* */
- /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
- /* lhs is A */
- /* rhs is B */
- /* set is the context */
- /* op is the operation flag */
- /* status is the usual accumulator */
- /* */
- /* C must have space for one digit for COMPARE or set->digits for */
- /* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG. */
- /* ------------------------------------------------------------------ */
- /* The emphasis here is on speed for common cases, and avoiding */
- /* coefficient comparison if possible. */
- /* ------------------------------------------------------------------ */
- decNumber * decCompareOp(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set,
- Flag op, uInt *status) {
- #if DECSUBSET
- decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated
- decNumber *allocrhs=NULL; // .., rhs
- #endif
- Int result=0; // default result value
- uByte merged; // work
- #if DECCHECK
- if (decCheckOperands(res, lhs, rhs, set)) return res;
- #endif
- do { // protect allocated storage
- #if DECSUBSET
- if (!set->extended) {
- // reduce operands and set lostDigits status, as needed
- if (lhs->digits>set->digits) {
- alloclhs=decRoundOperand(lhs, set, status);
- if (alloclhs==NULL) {result=BADINT; break;}
- lhs=alloclhs;
- }
- if (rhs->digits>set->digits) {
- allocrhs=decRoundOperand(rhs, set, status);
- if (allocrhs==NULL) {result=BADINT; break;}
- rhs=allocrhs;
- }
- }
- #endif
- // [following code does not require input rounding]
- // If total ordering then handle differing signs 'up front'
- if (op==COMPTOTAL) { // total ordering
- if (decNumberIsNegative(lhs) & !decNumberIsNegative(rhs)) {
- result=-1;
- break;
- }
- if (!decNumberIsNegative(lhs) & decNumberIsNegative(rhs)) {
- result=+1;
- break;
- }
- }
- // handle NaNs specially; let infinities drop through
- // This assumes sNaN (even just one) leads to NaN.
- merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN);
- if (merged) { // a NaN bit set
- if (op==COMPARE); // result will be NaN
- else if (op==COMPSIG) // treat qNaN as sNaN
- *status|=DEC_Invalid_operation | DEC_sNaN;
- else if (op==COMPTOTAL) { // total ordering, always finite
- // signs are known to be the same; compute the ordering here
- // as if the signs are both positive, then invert for negatives
- if (!decNumberIsNaN(lhs)) result=-1;
- else if (!decNumberIsNaN(rhs)) result=+1;
- // here if both NaNs
- else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1;
- else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1;
- else { // both NaN or both sNaN
- // now it just depends on the payload
- result=decUnitCompare(lhs->lsu, D2U(lhs->digits),
- rhs->lsu, D2U(rhs->digits), 0);
- // [Error not possible, as these are 'aligned']
- } // both same NaNs
- if (decNumberIsNegative(lhs)) result=-result;
- break;
- } // total order
- else if (merged & DECSNAN); // sNaN -> qNaN
- else { // here if MIN or MAX and one or two quiet NaNs
- // min or max -- 754 rules ignore single NaN
- if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) {
- // just one NaN; force choice to be the non-NaN operand
- op=COMPMAX;
- if (lhs->bits & DECNAN) result=-1; // pick rhs
- else result=+1; // pick lhs
- break;
- }
- } // max or min
- op=COMPNAN; // use special path
- decNaNs(res, lhs, rhs, set, status); // propagate NaN
- break;
- }
- // have numbers
- if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1);
- else result=decCompare(lhs, rhs, 0); // sign matters
- } while(0); // end protected
- if (result==BADINT) *status|=DEC_Insufficient_storage; // rare
- else {
- if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { // returning signum
- if (op==COMPTOTAL && result==0) {
- // operands are numerically equal or same NaN (and same sign,
- // tested first); if identical, leave result 0
- if (lhs->exponent!=rhs->exponent) {
- if (lhs->exponent<rhs->exponent) result=-1;
- else result=+1;
- if (decNumberIsNegative(lhs)) result=-result;
- } // lexp!=rexp
- } // total-order by exponent
- decNumberZero(res); // [always a valid result]
- if (result!=0) { // must be -1 or +1
- *res->lsu=1;
- if (result<0) res->bits=DECNEG;
- }
- }
- else if (op==COMPNAN); // special, drop through
- else { // MAX or MIN, non-NaN result
- Int residue=0; // rounding accumulator
- // choose the operand for the result
- const decNumber *choice;
- if (result==0) { // operands are numerically equal
- // choose according to sign then exponent (see 754)
- uByte slhs=(lhs->bits & DECNEG);
- uByte srhs=(rhs->bits & DECNEG);
- #if DECSUBSET
- if (!set->extended) { // subset: force left-hand
- op=COMPMAX;
- result=+1;
- }
- else
- #endif
- if (slhs!=srhs) { // signs differ
- if (slhs) result=-1; // rhs is max
- else result=+1; // lhs is max
- }
- else if (slhs && srhs) { // both negative
- if (lhs->exponent<rhs->exponent) result=+1;
- else result=-1;
- // [if equal, use lhs, technically identical]
- }
- else { // both positive
- if (lhs->exponent>rhs->exponent) result=+1;
- else result=-1;
- // [ditto]
- }
- } // numerically equal
- // here result will be non-0; reverse if looking for MIN
- if (op==COMPMIN || op==COMPMINMAG) result=-result;
- choice=(result>0 ? lhs : rhs); // choose
- // copy chosen to result, rounding if need be
- decCopyFit(res, choice, set, &residue, status);
- decFinish(res, set, &residue, status);
- }
- }
- #if DECSUBSET
- if (allocrhs!=NULL) free(allocrhs); // free any storage used
- if (alloclhs!=NULL) free(alloclhs); // ..
- #endif
- return res;
- } // decCompareOp
- /* ------------------------------------------------------------------ */
- /* decCompare -- compare two decNumbers by numerical value */
- /* */
- /* This routine compares A ? B without altering them. */
- /* */
- /* Arg1 is A, a decNumber which is not a NaN */
- /* Arg2 is B, a decNumber which is not a NaN */
- /* Arg3 is 1 for a sign-independent compare, 0 otherwise */
- /* */
- /* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */
- /* (the only possible failure is an allocation error) */
- /* ------------------------------------------------------------------ */
- static Int decCompare(const decNumber *lhs, const decNumber *rhs,
- Flag abs) {
- Int result; // result value
- Int sigr; // rhs signum
- Int compare; // work
- result=1; // assume signum(lhs)
- if (ISZERO(lhs)) result=0;
- if (abs) {
- if (ISZERO(rhs)) return result; // LHS wins or both 0
- // RHS is non-zero
- if (result==0) return -1; // LHS is 0; RHS wins
- // [here, both non-zero, result=1]
- }
- else { // signs matter
- if (result && decNumberIsNegative(lhs)) result=-1;
- sigr=1; // compute signum(rhs)
- if (ISZERO(rhs)) sigr=0;
- else if (decNumberIsNegative(rhs)) sigr=-1;
- if (result > sigr) return +1; // L > R, return 1
- if (result < sigr) return -1; // L < R, return -1
- if (result==0) return 0; // both 0
- }
- // signums are the same; both are non-zero
- if ((lhs->bits | rhs->bits) & DECINF) { // one or more infinities
- if (decNumberIsInfinite(rhs)) {
- if (decNumberIsInfinite(lhs)) result=0;// both infinite
- else result=-result; // only rhs infinite
- }
- return result;
- }
- // must compare the coefficients, allowing for exponents
- if (lhs->exponent>rhs->exponent) { // LHS exponent larger
- // swap sides, and sign
- const decNumber *temp=lhs;
- lhs=rhs;
- rhs=temp;
- result=-result;
- }
- compare=decUnitCompare(lhs->lsu, D2U(lhs->digits),
- rhs->lsu, D2U(rhs->digits),
- rhs->exponent-lhs->exponent);
- if (compare!=BADINT) compare*=result; // comparison succeeded
- return compare;
- } // decCompare
- /* ------------------------------------------------------------------ */
- /* decUnitCompare -- compare two >=0 integers in Unit arrays */
- /* */
- /* This routine compares A ? B*10**E where A and B are unit arrays */
- /* A is a plain integer */
- /* B has an exponent of E (which must be non-negative) */
- /* */
- /* Arg1 is A first Unit (lsu) */
- /* Arg2 is A length in Units */
- /* Arg3 is B first Unit (lsu) */
- /* Arg4 is B length in Units */
- /* Arg5 is E (0 if the units are aligned) */
- /* */
- /* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */
- /* (the only possible failure is an allocation error, which can */
- /* only occur if E!=0) */
- /* ------------------------------------------------------------------ */
- static Int decUnitCompare(const Unit *a, Int alength,
- const Unit *b, Int blength, Int exp) {
- Unit *acc; // accumulator for result
- Unit accbuff[SD2U(DECBUFFER*2+1)]; // local buffer
- Unit *allocacc=NULL; // -> allocated acc buffer, iff allocated
- Int accunits, need; // units in use or needed for acc
- const Unit *l, *r, *u; // work
- Int expunits, exprem, result; // ..
- if (exp==0) { // aligned; fastpath
- if (alength>blength) return 1;
- if (alength<blength) return -1;
- // same number of units in both -- need unit-by-unit compare
- l=a+alength-1;
- r=b+alength-1;
- for (;l>=a; l--, r--) {
- if (*l>*r) return 1;
- if (*l<*r) return -1;
- }
- return 0; // all units match
- } // aligned
- // Unaligned. If one is >1 unit longer than the other, padded
- // approximately, then can return easily
- if (alength>blength+(Int)D2U(exp)) return 1;
- if (alength+1<blength+(Int)D2U(exp)) return -1;
- // Need to do a real subtract. For this, a result buffer is needed
- // even though only the sign is of interest. Its length needs
- // to be the larger of alength and padded blength, +2
- need=blength+D2U(exp); // maximum real length of B
- if (need<alength) need=alength;
- need+=2;
- acc=accbuff; // assume use local buffer
- if (need*sizeof(Unit)>sizeof(accbuff)) {
- allocacc=(Unit *)malloc(need*sizeof(Unit));
- if (allocacc==NULL) return BADINT; // hopeless -- abandon
- acc=allocacc;
- }
- // Calculate units and remainder from exponent.
- expunits=exp/DECDPUN;
- exprem=exp%DECDPUN;
- // subtract [A+B*(-m)]
- accunits=decUnitAddSub(a, alength, b, blength, expunits, acc,
- -(Int)powers[exprem]);
- // [UnitAddSub result may have leading zeros, even on zero]
- if (accunits<0) result=-1; // negative result
- else { // non-negative result
- // check units of the result before freeing any storage
- for (u=acc; u<acc+accunits-1 && *u==0;) u++;
- result=(*u==0 ? 0 : +1);
- }
- // clean up and return the result
- if (allocacc!=NULL) free(allocacc); // drop any storage used
- return result;
- } // decUnitCompare
- /* ------------------------------------------------------------------ */
- /* decUnitAddSub -- add or subtract two >=0 integers in Unit arrays */
- /* */
- /* This routine performs the calculation: */
- /* */
- /* C=A+(B*M) */
- /* */
- /* Where M is in the range -DECDPUNMAX through +DECDPUNMAX. */
- /* */
- /* A may be shorter or longer than B. */
- /* */
- /* Leading zeros are not removed after a calculation. The result is */
- /* either the same length as the longer of A and B (adding any */
- /* shift), or one Unit longer than that (if a Unit carry occurred). */
- /* */
- /* A and B content are not altered unless C is also A or B. */
- /* C may be the same array as A or B, but only if no zero padding is */
- /* requested (that is, C may be B only if bshift==0). */
- /* C is filled from the lsu; only those units necessary to complete */
- /* the calculation are referenced. */
- /* */
- /* Arg1 is A first Unit (lsu) */
- /* Arg2 is A length in Units */
- /* Arg3 is B first Unit (lsu) */
- /* Arg4 is B length in Units */
- /* Arg5 is B shift in Units (>=0; pads with 0 units if positive) */
- /* Arg6 is C first Unit (lsu) */
- /* Arg7 is M, the multiplier */
- /* */
- /* returns the count of Units written to C, which will be non-zero */
- /* and negated if the result is negative. That is, the sign of the */
- /* returned Int is the sign of the result (positive for zero) and */
- /* the absolute value of the Int is the count of Units. */
- /* */
- /* It is the caller's responsibility to make sure that C size is */
- /* safe, allowing space if necessary for a one-Unit carry. */
- /* */
- /* This routine is severely performance-critical; *any* change here */
- /* must be measured (timed) to assure no performance degradation. */
- /* In particular, trickery here tends to be counter-productive, as */
- /* increased complexity of code hurts register optimizations on */
- /* register-poor architectures. Avoiding divisions is nearly */
- /* always a Good Idea, however. */
- /* */
- /* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark */
- /* (IBM Warwick, UK) for some of the ideas used in this routine. */
- /* ------------------------------------------------------------------ */
- static Int decUnitAddSub(const Unit *a, Int alength,
- const Unit *b, Int blength, Int bshift,
- Unit *c, Int m) {
- const Unit *alsu=a; // A lsu [need to remember it]
- Unit *clsu=c; // C ditto
- Unit *minC; // low water mark for C
- Unit *maxC; // high water mark for C
- eInt carry=0; // carry integer (could be Long)
- Int add; // work
- #if DECDPUN<=4 // myriadal, millenary, etc.
- Int est; // estimated quotient
- #endif
- #if DECTRACE
- if (alength<1 || blength<1)
- printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m);
- #endif
- maxC=c+alength; // A is usually the longer
- minC=c+blength; // .. and B the shorter
- if (bshift!=0) { // B is shifted; low As copy across
- minC+=bshift;
- // if in place [common], skip copy unless there's a gap [rare]
- if (a==c && bshift<=alength) {
- c+=bshift;
- a+=bshift;
- }
- else for (; c<clsu+bshift; a++, c++) { // copy needed
- if (a<alsu+alength) *c=*a;
- else *c=0;
- }
- }
- if (minC>maxC) { // swap
- Unit *hold=minC;
- minC=maxC;
- maxC=hold;
- }
- // For speed, do the addition as two loops; the first where both A
- // and B contribute, and the second (if necessary) where only one or
- // other of the numbers contribute.
- // Carry handling is the same (i.e., duplicated) in each case.
- for (; c<minC; c++) {
- carry+=*a;
- a++;
- carry+=((eInt)*b)*m; // [special-casing m=1/-1
- b++; // here is not a win]
- // here carry is new Unit of digits; it could be +ve or -ve
- if ((ueInt)carry<=DECDPUNMAX) { // fastpath 0-DECDPUNMAX
- *c=(Unit)carry;
- carry=0;
- continue;
- }
- #if DECDPUN==4 // use divide-by-multiply
- if (carry>=0) {
- est=(((ueInt)carry>>11)*53687)>>18;
- *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder
- carry=est; // likely quotient [89%]
- if (*c<DECDPUNMAX+1) continue; // estimate was correct
- carry++;
- *c-=DECDPUNMAX+1;
- continue;
- }
- // negative case
- carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive
- est=(((ueInt)carry>>11)*53687)>>18;
- *c=(Unit)(carry-est*(DECDPUNMAX+1));
- carry=est-(DECDPUNMAX+1); // correctly negative
- if (*c<DECDPUNMAX+1) continue; // was OK
- carry++;
- *c-=DECDPUNMAX+1;
- #elif DECDPUN==3
- if (carry>=0) {
- est=(((ueInt)carry>>3)*16777)>>21;
- *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder
- carry=est; // likely quotient [99%]
- if (*c<DECDPUNMAX+1) continue; // estimate was correct
- carry++;
- *c-=DECDPUNMAX+1;
- continue;
- }
- // negative case
- carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive
- est=(((ueInt)carry>>3)*16777)>>21;
- *c=(Unit)(carry-est*(DECDPUNMAX+1));
- carry=est-(DECDPUNMAX+1); // correctly negative
- if (*c<DECDPUNMAX+1) continue; // was OK
- carry++;
- *c-=DECDPUNMAX+1;
- #elif DECDPUN<=2
- // Can use QUOT10 as carry <= 4 digits
- if (carry>=0) {
- est=QUOT10(carry, DECDPUN);
- *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder
- carry=est; // quotient
- continue;
- }
- // negative case
- carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive
- est=QUOT10(carry, DECDPUN);
- *c=(Unit)(carry-est*(DECDPUNMAX+1));
- carry=est-(DECDPUNMAX+1); // correctly negative
- #else
- // remainder operator is undefined if negative, so must test
- if ((ueInt)carry<(DECDPUNMAX+1)*2) { // fastpath carry +1
- *c=(Unit)(carry-(DECDPUNMAX+1)); // [helps additions]
- carry=1;
- continue;
- }
- if (carry>=0) {
- *c=(Unit)(carry%(DECDPUNMAX+1));
- carry=carry/(DECDPUNMAX+1);
- continue;
- }
- // negative case
- carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive
- *c=(Unit)(carry%(DECDPUNMAX+1));
- carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
- #endif
- } // c
- // now may have one or other to complete
- // [pretest to avoid loop setup/shutdown]
- if (c<maxC) for (; c<maxC; c++) {
- if (a<alsu+alength) { // still in A
- carry+=*a;
- a++;
- }
- else { // inside B
- carry+=((eInt)*b)*m;
- b++;
- }
- // here carry is new Unit of digits; it could be +ve or -ve and
- // magnitude up to DECDPUNMAX squared
- if ((ueInt)carry<=DECDPUNMAX) { // fastpath 0-DECDPUNMAX
- *c=(Unit)carry;
- carry=0;
- continue;
- }
- // result for this unit is negative or >DECDPUNMAX
- #if DECDPUN==4 // use divide-by-multiply
- if (carry>=0) {
- est=(((ueInt)carry>>11)*53687)>>18;
- *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder
- carry=est; // likely quotient [79.7%]
- if (*c<DECDPUNMAX+1) continue; // estimate was correct
- carry++;
- *c-=DECDPUNMAX+1;
- continue;
- }
- // negative case
- carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive
- est=(((ueInt)carry>>11)*53687)>>18;
- *c=(Unit)(carry-est*(DECDPUNMAX+1));
- carry=est-(DECDPUNMAX+1); // correctly negative
- if (*c<DECDPUNMAX+1) continue; // was OK
- carry++;
- *c-=DECDPUNMAX+1;
- #elif DECDPUN==3
- if (carry>=0) {
- est=(((ueInt)carry>>3)*16777)>>21;
- *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder
- carry=est; // likely quotient [99%]
- if (*c<DECDPUNMAX+1) continue; // estimate was correct
- carry++;
- *c-=DECDPUNMAX+1;
- continue;
- }
- // negative case
- carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive
- est=(((ueInt)carry>>3)*16777)>>21;
- *c=(Unit)(carry-est*(DECDPUNMAX+1));
- carry=est-(DECDPUNMAX+1); // correctly negative
- if (*c<DECDPUNMAX+1) continue; // was OK
- carry++;
- *c-=DECDPUNMAX+1;
- #elif DECDPUN<=2
- if (carry>=0) {
- est=QUOT10(carry, DECDPUN);
- *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder
- carry=est; // quotient
- continue;
- }
- // negative case
- carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive
- est=QUOT10(carry, DECDPUN);
- *c=(Unit)(carry-est*(DECDPUNMAX+1));
- carry=est-(DECDPUNMAX+1); // correctly negative
- #else
- if ((ueInt)carry<(DECDPUNMAX+1)*2){ // fastpath carry 1
- *c=(Unit)(carry-(DECDPUNMAX+1));
- carry=1;
- continue;
- }
- // remainder operator is undefined if negative, so must test
- if (carry>=0) {
- *c=(Unit)(carry%(DECDPUNMAX+1));
- carry=carry/(DECDPUNMAX+1);
- continue;
- }
- // negative case
- carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive
- *c=(Unit)(carry%(DECDPUNMAX+1));
- carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
- #endif
- } // c
- // OK, all A and B processed; might still have carry or borrow
- // return number of Units in the result, negated if a borrow
- if (carry==0) return c-clsu; // no carry, so no more to do
- if (carry>0) { // positive carry
- *c=(Unit)carry; // place as new unit
- c++; // ..
- return c-clsu;
- }
- // -ve carry: it's a borrow; complement needed
- add=1; // temporary carry...
- for (c=clsu; c<maxC; c++) {
- add=DECDPUNMAX+add-*c;
- if (add<=DECDPUNMAX) {
- *c=(Unit)add;
- add=0;
- }
- else {
- *c=0;
- add=1;
- }
- }
- // add an extra unit iff it would be non-zero
- #if DECTRACE
- printf("UAS borrow: add %ld, carry %ld\n", add, carry);
- #endif
- if ((add-carry-1)!=0) {
- *c=(Unit)(add-carry-1);
- c++; // interesting, include it
- }
- return clsu-c; // -ve result indicates borrowed
- } // decUnitAddSub
- /* ------------------------------------------------------------------ */
- /* decTrim -- trim trailing zeros or normalize */
- /* */
- /* dn is the number to trim or normalize */
- /* set is the context to use to check for clamp */
- /* all is 1 to remove all trailing zeros, 0 for just fraction ones */
- /* noclamp is 1 to unconditional (unclamped) trim */
- /* dropped returns the number of discarded trailing zeros */
- /* returns dn */
- /* */
- /* If clamp is set in the context then the number of zeros trimmed */
- /* may be limited if the exponent is high. */
- /* All fields are updated as required. This is a utility operation, */
- /* so special values are unchanged and no error is possible. */
- /* ------------------------------------------------------------------ */
- static decNumber * decTrim(decNumber *dn, decContext *set, Flag all,
- Flag noclamp, Int *dropped) {
- Int d, exp; // work
- uInt cut; // ..
- Unit *up; // -> current Unit
- #if DECCHECK
- if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
- #endif
- *dropped=0; // assume no zeros dropped
- if ((dn->bits & DECSPECIAL) // fast exit if special ..
- || (*dn->lsu & 0x01)) return dn; // .. or odd
- if (ISZERO(dn)) { // .. or 0
- dn->exponent=0; // (sign is preserved)
- return dn;
- }
- // have a finite number which is even
- exp=dn->exponent;
- cut=1; // digit (1-DECDPUN) in Unit
- up=dn->lsu; // -> current Unit
- for (d=0; d<dn->digits-1; d++) { // [don't strip the final digit]
- // slice by powers
- #if DECDPUN<=4
- uInt quot=QUOT10(*up, cut);
- if ((*up-quot*powers[cut])!=0) break; // found non-0 digit
- #else
- if (*up%powers[cut]!=0) break; // found non-0 digit
- #endif
- // have a trailing 0
- if (!all) { // trimming
- // [if exp>0 then all trailing 0s are significant for trim]
- if (exp<=0) { // if digit might be significant
- if (exp==0) break; // then quit
- exp++; // next digit might be significant
- }
- }
- cut++; // next power
- if (cut>DECDPUN) { // need new Unit
- up++;
- cut=1;
- }
- } // d
- if (d==0) return dn; // none to drop
- // may need to limit drop if clamping
- if (set->clamp && !noclamp) {
- Int maxd=set->emax-set->digits+1-dn->exponent;
- if (maxd<=0) return dn; // nothing possible
- if (d>maxd) d=maxd;
- }
- // effect the drop
- decShiftToLeast(dn->lsu, D2U(dn->digits), d);
- dn->exponent+=d; // maintain numerical value
- dn->digits-=d; // new length
- *dropped=d; // report the count
- return dn;
- } // decTrim
- /* ------------------------------------------------------------------ */
- /* decReverse -- reverse a Unit array in place */
- /* */
- /* ulo is the start of the array */
- /* uhi is the end of the array (highest Unit to include) */
- /* */
- /* The units ulo through uhi are reversed in place (if the number */
- /* of units is odd, the middle one is untouched). Note that the */
- /* digit(s) in each unit are unaffected. */
- /* ------------------------------------------------------------------ */
- static void decReverse(Unit *ulo, Unit *uhi) {
- Unit temp;
- for (; ulo<uhi; ulo++, uhi--) {
- temp=*ulo;
- *ulo=*uhi;
- *uhi=temp;
- }
- return;
- } // decReverse
- /* ------------------------------------------------------------------ */
- /* decShiftToMost -- shift digits in array towards most significant */
- /* */
- /* uar is the array */
- /* digits is the count of digits in use in the array */
- /* shift is the number of zeros to pad with (least significant); */
- /* it must be zero or positive */
- /* */
- /* returns the new length of the integer in the array, in digits */
- /* */
- /* No overflow is permitted (that is, the uar array must be known to */
- /* be large enough to hold the result, after shifting). */
- /* ------------------------------------------------------------------ */
- static Int decShiftToMost(Unit *uar, Int digits, Int shift) {
- Unit *target, *source, *first; // work
- Int cut; // odd 0's to add
- uInt next; // work
- if (shift==0) return digits; // [fastpath] nothing to do
- if ((digits+shift)<=DECDPUN) { // [fastpath] single-unit case
- *uar=(Unit)(*uar*powers[shift]);
- return digits+shift;
- }
- next=0; // all paths
- source=uar+D2U(digits)-1; // where msu comes from
- target=source+D2U(shift); // where upper part of first cut goes
- cut=DECDPUN-MSUDIGITS(shift); // where to slice
- if (cut==0) { // unit-boundary case
- for (; source>=uar; source--, target--) *target=*source;
- }
- else {
- first=uar+D2U(digits+shift)-1; // where msu of source will end up
- for (; source>=uar; source--, target--) {
- // split the source Unit and accumulate remainder for next
- #if DECDPUN<=4
- uInt quot=QUOT10(*source, cut);
- uInt rem=*source-quot*powers[cut];
- next+=quot;
- #else
- uInt rem=*source%powers[cut];
- next+=*source/powers[cut];
- #endif
- if (target<=first) *target=(Unit)next; // write to target iff valid
- next=rem*powers[DECDPUN-cut]; // save remainder for next Unit
- }
- } // shift-move
- // propagate any partial unit to one below and clear the rest
- for (; target>=uar; target--) {
- *target=(Unit)next;
- next=0;
- }
- return digits+shift;
- } // decShiftToMost
- /* ------------------------------------------------------------------ */
- /* decShiftToLeast -- shift digits in array towards least significant */
- /* */
- /* uar is the array */
- /* units is length of the array, in units */
- /* shift is the number of digits to remove from the lsu end; it */
- /* must be zero or positive and <= than units*DECDPUN. */
- /* */
- /* returns the new length of the integer in the array, in units */
- /* */
- /* Removed digits are discarded (lost). Units not required to hold */
- /* the final result are unchanged. */
- /* ------------------------------------------------------------------ */
- static Int decShiftToLeast(Unit *uar, Int units, Int shift) {
- Unit *target, *up; // work
- Int cut, count; // work
- Int quot, rem; // for division
- if (shift==0) return units; // [fastpath] nothing to do
- if (shift==units*DECDPUN) { // [fastpath] little to do
- *uar=0; // all digits cleared gives zero
- return 1; // leaves just the one
- }
- target=uar; // both paths
- cut=MSUDIGITS(shift);
- if (cut==DECDPUN) { // unit-boundary case; easy
- up=uar+D2U(shift);
- for (; up<uar+units; target++, up++) *target=*up;
- return target-uar;
- }
- // messier
- up=uar+D2U(shift-cut); // source; correct to whole Units
- count=units*DECDPUN-shift; // the maximum new length
- #if DECDPUN<=4
- quot=QUOT10(*up, cut);
- #else
- quot=*up/powers[cut];
- #endif
- for (; ; target++) {
- *target=(Unit)quot;
- count-=(DECDPUN-cut);
- if (count<=0) break;
- up++;
- quot=*up;
- #if DECDPUN<=4
- quot=QUOT10(quot, cut);
- rem=*up-quot*powers[cut];
- #else
- rem=quot%powers[cut];
- quot=quot/powers[cut];
- #endif
- *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
- count-=cut;
- if (count<=0) break;
- }
- return target-uar+1;
- } // decShiftToLeast
- #if DECSUBSET
- /* ------------------------------------------------------------------ */
- /* decRoundOperand -- round an operand [used for subset only] */
- /* */
- /* dn is the number to round (dn->digits is > set->digits) */
- /* set is the relevant context */
- /* status is the status accumulator */
- /* */
- /* returns an allocated decNumber with the rounded result. */
- /* */
- /* lostDigits and other status may be set by this. */
- /* */
- /* Since the input is an operand, it must not be modified. */
- /* Instead, return an allocated decNumber, rounded as required. */
- /* It is the caller's responsibility to free the allocated storage. */
- /* */
- /* If no storage is available then the result cannot be used, so NULL */
- /* is returned. */
- /* ------------------------------------------------------------------ */
- static decNumber *decRoundOperand(const decNumber *dn, decContext *set,
- uInt *status) {
- decNumber *res; // result structure
- uInt newstatus=0; // status from round
- Int residue=0; // rounding accumulator
- // Allocate storage for the returned decNumber, big enough for the
- // length specified by the context
- res=(decNumber *)malloc(sizeof(decNumber)
- +(D2U(set->digits)-1)*sizeof(Unit));
- if (res==NULL) {
- *status|=DEC_Insufficient_storage;
- return NULL;
- }
- decCopyFit(res, dn, set, &residue, &newstatus);
- decApplyRound(res, set, residue, &newstatus);
- // If that set Inexact then "lost digits" is raised...
- if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits;
- *status|=newstatus;
- return res;
- } // decRoundOperand
- #endif
- /* ------------------------------------------------------------------ */
- /* decCopyFit -- copy a number, truncating the coefficient if needed */
- /* */
- /* dest is the target decNumber */
- /* src is the source decNumber */
- /* set is the context [used for length (digits) and rounding mode] */
- /* residue is the residue accumulator */
- /* status contains the current status to be updated */
- /* */
- /* (dest==src is allowed and will be a no-op if fits) */
- /* All fields are updated as required. */
- /* ------------------------------------------------------------------ */
- static void decCopyFit(decNumber *dest, const decNumber *src,
- decContext *set, Int *residue, uInt *status) {
- dest->bits=src->bits;
- dest->exponent=src->exponent;
- decSetCoeff(dest, set, src->lsu, src->digits, residue, status);
- } // decCopyFit
- /* ------------------------------------------------------------------ */
- /* decSetCoeff -- set the coefficient of a number */
- /* */
- /* dn is the number whose coefficient array is to be set. */
- /* It must have space for set->digits digits */
- /* set is the context [for size] */
- /* lsu -> lsu of the source coefficient [may be dn->lsu] */
- /* len is digits in the source coefficient [may be dn->digits] */
- /* residue is the residue accumulator. This has values as in */
- /* decApplyRound, and will be unchanged unless the */
- /* target size is less than len. In this case, the */
- /* coefficient is truncated and the residue is updated to */
- /* reflect the previous residue and the dropped digits. */
- /* status is the status accumulator, as usual */
- /* */
- /* The coefficient may already be in the number, or it can be an */
- /* external intermediate array. If it is in the number, lsu must == */
- /* dn->lsu and len must == dn->digits. */
- /* */
- /* Note that the coefficient length (len) may be < set->digits, and */
- /* in this case this merely copies the coefficient (or is a no-op */
- /* if dn->lsu==lsu). */
- /* */
- /* Note also that (only internally, from decQuantizeOp and */
- /* decSetSubnormal) the value of set->digits may be less than one, */
- /* indicating a round to left. This routine handles that case */
- /* correctly; caller ensures space. */
- /* */
- /* dn->digits, dn->lsu (and as required), and dn->exponent are */
- /* updated as necessary. dn->bits (sign) is unchanged. */
- /* */
- /* DEC_Rounded status is set if any digits are discarded. */
- /* DEC_Inexact status is set if any non-zero digits are discarded, or */
- /* incoming residue was non-0 (implies rounded) */
- /* ------------------------------------------------------------------ */
- // mapping array: maps 0-9 to canonical residues, so that a residue
- // can be adjusted in the range [-1, +1] and achieve correct rounding
- // 0 1 2 3 4 5 6 7 8 9
- static const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7};
- static void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu,
- Int len, Int *residue, uInt *status) {
- Int discard; // number of digits to discard
- uInt cut; // cut point in Unit
- const Unit *up; // work
- Unit *target; // ..
- Int count; // ..
- #if DECDPUN<=4
- uInt temp; // ..
- #endif
- discard=len-set->digits; // digits to discard
- if (discard<=0) { // no digits are being discarded
- if (dn->lsu!=lsu) { // copy needed
- // copy the coefficient array to the result number; no shift needed
- count=len; // avoids D2U
- up=lsu;
- for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
- *target=*up;
- dn->digits=len; // set the new length
- }
- // dn->exponent and residue are unchanged, record any inexactitude
- if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded);
- return;
- }
- // some digits must be discarded ...
- dn->exponent+=discard; // maintain numerical value
- *status|=DEC_Rounded; // accumulate Rounded status
- if (*residue>1) *residue=1; // previous residue now to right, so reduce
- if (discard>len) { // everything, +1, is being discarded
- // guard digit is 0
- // residue is all the number [NB could be all 0s]
- if (*residue<=0) { // not already positive
- count=len; // avoids D2U
- for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { // found non-0
- *residue=1;
- break; // no need to check any others
- }
- }
- if (*residue!=0) *status|=DEC_Inexact; // record inexactitude
- *dn->lsu=0; // coefficient will now be 0
- dn->digits=1; // ..
- return;
- } // total discard
- // partial discard [most common case]
- // here, at least the first (most significant) discarded digit exists
- // spin up the number, noting residue during the spin, until get to
- // the Unit with the first discarded digit. When reach it, extract
- // it and remember its position
- count=0;
- for (up=lsu;; up++) {
- count+=DECDPUN;
- if (count>=discard) break; // full ones all checked
- if (*up!=0) *residue=1;
- } // up
- // here up -> Unit with first discarded digit
- cut=discard-(count-DECDPUN)-1;
- if (cut==DECDPUN-1) { // unit-boundary case (fast)
- Unit half=(Unit)powers[DECDPUN]>>1;
- // set residue directly
- if (*up>=half) {
- if (*up>half) *residue=7;
- else *residue+=5; // add sticky bit
- }
- else { // <half
- if (*up!=0) *residue=3; // [else is 0, leave as sticky bit]
- }
- if (set->digits<=0) { // special for Quantize/Subnormal :-(
- *dn->lsu=0; // .. result is 0
- dn->digits=1; // ..
- }
- else { // shift to least
- count=set->digits; // now digits to end up with
- dn->digits=count; // set the new length
- up++; // move to next
- // on unit boundary, so shift-down copy loop is simple
- for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
- *target=*up;
- }
- } // unit-boundary case
- else { // discard digit is in low digit(s), and not top digit
- uInt discard1; // first discarded digit
- uInt quot, rem; // for divisions
- if (cut==0) quot=*up; // is at bottom of unit
- else /* cut>0 */ { // it's not at bottom of unit
- #if DECDPUN<=4
- quot=QUOT10(*up, cut);
- rem=*up-quot*powers[cut];
- #else
- rem=*up%powers[cut];
- quot=*up/powers[cut];
- #endif
- if (rem!=0) *residue=1;
- }
- // discard digit is now at bottom of quot
- #if DECDPUN<=4
- temp=(quot*6554)>>16; // fast /10
- // Vowels algorithm here not a win (9 instructions)
- discard1=quot-X10(temp);
- quot=temp;
- #else
- discard1=quot%10;
- quot=quot/10;
- #endif
- // here, discard1 is the guard digit, and residue is everything
- // else [use mapping array to accumulate residue safely]
- *residue+=resmap[discard1];
- cut++; // update cut
- // here: up -> Unit of the array with bottom digit
- // cut is the division point for each Unit
- // quot holds the uncut high-order digits for the current unit
- if (set->digits<=0) { // special for Quantize/Subnormal :-(
- *dn->lsu=0; // .. result is 0
- dn->digits=1; // ..
- }
- else { // shift to least needed
- count=set->digits; // now digits to end up with
- dn->digits=count; // set the new length
- // shift-copy the coefficient array to the result number
- for (target=dn->lsu; ; target++) {
- *target=(Unit)quot;
- count-=(DECDPUN-cut);
- if (count<=0) break;
- up++;
- quot=*up;
- #if DECDPUN<=4
- quot=QUOT10(quot, cut);
- rem=*up-quot*powers[cut];
- #else
- rem=quot%powers[cut];
- quot=quot/powers[cut];
- #endif
- *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
- count-=cut;
- if (count<=0) break;
- } // shift-copy loop
- } // shift to least
- } // not unit boundary
- if (*residue!=0) *status|=DEC_Inexact; // record inexactitude
- return;
- } // decSetCoeff
- /* ------------------------------------------------------------------ */
- /* decApplyRound -- apply pending rounding to a number */
- /* */
- /* dn is the number, with space for set->digits digits */
- /* set is the context [for size and rounding mode] */
- /* residue indicates pending rounding, being any accumulated */
- /* guard and sticky information. It may be: */
- /* 6-9: rounding digit is >5 */
- /* 5: rounding digit is exactly half-way */
- /* 1-4: rounding digit is <5 and >0 */
- /* 0: the coefficient is exact */
- /* -1: as 1, but the hidden digits are subtractive, that */
- /* is, of the opposite sign to dn. In this case the */
- /* coefficient must be non-0. This case occurs when */
- /* subtracting a small number (which can be reduced to */
- /* a sticky bit); see decAddOp. */
- /* status is the status accumulator, as usual */
- /* */
- /* This routine applies rounding while keeping the length of the */
- /* coefficient constant. The exponent and status are unchanged */
- /* except if: */
- /* */
- /* -- the coefficient was increased and is all nines (in which */
- /* case Overflow could occur, and is handled directly here so */
- /* the caller does not need to re-test for overflow) */
- /* */
- /* -- the coefficient was decreased and becomes all nines (in which */
- /* case Underflow could occur, and is also handled directly). */
- /* */
- /* All fields in dn are updated as required. */
- /* */
- /* ------------------------------------------------------------------ */
- static void decApplyRound(decNumber *dn, decContext *set, Int residue,
- uInt *status) {
- Int bump; // 1 if coefficient needs to be incremented
- // -1 if coefficient needs to be decremented
- if (residue==0) return; // nothing to apply
- bump=0; // assume a smooth ride
- // now decide whether, and how, to round, depending on mode
- switch (set->round) {
- case DEC_ROUND_05UP: { // round zero or five up (for reround)
- // This is the same as DEC_ROUND_DOWN unless there is a
- // positive residue and the lsd of dn is 0 or 5, in which case
- // it is bumped; when residue is <0, the number is therefore
- // bumped down unless the final digit was 1 or 6 (in which
- // case it is bumped down and then up -- a no-op)
- Int lsd5=*dn->lsu%5; // get lsd and quintate
- if (residue<0 && lsd5!=1) bump=-1;
- else if (residue>0 && lsd5==0) bump=1;
- // [bump==1 could be applied directly; use common path for clarity]
- break;} // r-05
- case DEC_ROUND_DOWN: {
- // no change, except if negative residue
- if (residue<0) bump=-1;
- break;} // r-d
- case DEC_ROUND_HALF_DOWN: {
- if (residue>5) bump=1;
- break;} // r-h-d
- case DEC_ROUND_HALF_EVEN: {
- if (residue>5) bump=1; // >0.5 goes up
- else if (residue==5) { // exactly 0.5000...
- // 0.5 goes up iff [new] lsd is odd
- if (*dn->lsu & 0x01) bump=1;
- }
- break;} // r-h-e
- case DEC_ROUND_HALF_UP: {
- if (residue>=5) bump=1;
- break;} // r-h-u
- case DEC_ROUND_UP: {
- if (residue>0) bump=1;
- break;} // r-u
- case DEC_ROUND_CEILING: {
- // same as _UP for positive numbers, and as _DOWN for negatives
- // [negative residue cannot occur on 0]
- if (decNumberIsNegative(dn)) {
- if (residue<0) bump=-1;
- }
- else {
- if (residue>0) bump=1;
- }
- break;} // r-c
- case DEC_ROUND_FLOOR: {
- // same as _UP for negative numbers, and as _DOWN for positive
- // [negative residue cannot occur on 0]
- if (!decNumberIsNegative(dn)) {
- if (residue<0) bump=-1;
- }
- else {
- if (residue>0) bump=1;
- }
- break;} // r-f
- default: { // e.g., DEC_ROUND_MAX
- *status|=DEC_Invalid_context;
- #if DECTRACE || (DECCHECK && DECVERB)
- printf("Unknown rounding mode: %d\n", set->round);
- #endif
- break;}
- } // switch
- // now bump the number, up or down, if need be
- if (bump==0) return; // no action required
- // Simply use decUnitAddSub unless bumping up and the number is
- // all nines. In this special case set to 100... explicitly
- // and adjust the exponent by one (as otherwise could overflow
- // the array)
- // Similarly handle all-nines result if bumping down.
- if (bump>0) {
- Unit *up; // work
- uInt count=dn->digits; // digits to be checked
- for (up=dn->lsu; ; up++) {
- if (count<=DECDPUN) {
- // this is the last Unit (the msu)
- if (*up!=powers[count]-1) break; // not still 9s
- // here if it, too, is all nines
- *up=(Unit)powers[count-1]; // here 999 -> 100 etc.
- for (up=up-1; up>=dn->lsu; up--) *up=0; // others all to 0
- dn->exponent++; // and bump exponent
- // [which, very rarely, could cause Overflow...]
- if ((dn->exponent+dn->digits)>set->emax+1) {
- decSetOverflow(dn, set, status);
- }
- return; // done
- }
- // a full unit to check, with more to come
- if (*up!=DECDPUNMAX) break; // not still 9s
- count-=DECDPUN;
- } // up
- } // bump>0
- else { // -1
- // here checking for a pre-bump of 1000... (leading 1, all
- // other digits zero)
- Unit *up, *sup; // work
- uInt count=dn->digits; // digits to be checked
- for (up=dn->lsu; ; up++) {
- if (count<=DECDPUN) {
- // this is the last Unit (the msu)
- if (*up!=powers[count-1]) break; // not 100..
- // here if have the 1000... case
- sup=up; // save msu pointer
- *up=(Unit)powers[count]-1; // here 100 in msu -> 999
- // others all to all-nines, too
- for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1;
- dn->exponent--; // and bump exponent
- // iff the number was at the subnormal boundary (exponent=etiny)
- // then the exponent is now out of range, so it will in fact get
- // clamped to etiny and the final 9 dropped.
- // printf(">> emin=%d exp=%d sdig=%d\n", set->emin,
- // dn->exponent, set->digits);
- if (dn->exponent+1==set->emin-set->digits+1) {
- if (count==1 && dn->digits==1) *sup=0; // here 9 -> 0[.9]
- else {
- *sup=(Unit)powers[count-1]-1; // here 999.. in msu -> 99..
- dn->digits--;
- }
- dn->exponent++;
- *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
- }
- return; // done
- }
- // a full unit to check, with more to come
- if (*up!=0) break; // not still 0s
- count-=DECDPUN;
- } // up
- } // bump<0
- // Actual bump needed. Do it.
- decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump);
- } // decApplyRound
- #if DECSUBSET
- /* ------------------------------------------------------------------ */
- /* decFinish -- finish processing a number */
- /* */
- /* dn is the number */
- /* set is the context */
- /* residue is the rounding accumulator (as in decApplyRound) */
- /* status is the accumulator */
- /* */
- /* This finishes off the current number by: */
- /* 1. If not extended: */
- /* a. Converting a zero result to clean '0' */
- /* b. Reducing positive exponents to 0, if would fit in digits */
- /* 2. Checking for overflow and subnormals (always) */
- /* Note this is just Finalize when no subset arithmetic. */
- /* All fields are updated as required. */
- /* ------------------------------------------------------------------ */
- static void decFinish(decNumber *dn, decContext *set, Int *residue,
- uInt *status) {
- if (!set->extended) {
- if ISZERO(dn) { // value is zero
- dn->exponent=0; // clean exponent ..
- dn->bits=0; // .. and sign
- return; // no error possible
- }
- if (dn->exponent>=0) { // non-negative exponent
- // >0; reduce to integer if possible
- if (set->digits >= (dn->exponent+dn->digits)) {
- dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent);
- dn->exponent=0;
- }
- }
- } // !extended
- decFinalize(dn, set, residue, status);
- } // decFinish
- #endif
- /* ------------------------------------------------------------------ */
- /* decFinalize -- final check, clamp, and round of a number */
- /* */
- /* dn is the number */
- /* set is the context */
- /* residue is the rounding accumulator (as in decApplyRound) */
- /* status is the status accumulator */
- /* */
- /* This finishes off the current number by checking for subnormal */
- /* results, applying any pending rounding, checking for overflow, */
- /* and applying any clamping. */
- /* Underflow and overflow conditions are raised as appropriate. */
- /* All fields are updated as required. */
- /* ------------------------------------------------------------------ */
- static void decFinalize(decNumber *dn, decContext *set, Int *residue,
- uInt *status) {
- Int shift; // shift needed if clamping
- Int tinyexp=set->emin-dn->digits+1; // precalculate subnormal boundary
- // Must be careful, here, when checking the exponent as the
- // adjusted exponent could overflow 31 bits [because it may already
- // be up to twice the expected].
- // First test for subnormal. This must be done before any final
- // round as the result could be rounded to Nmin or 0.
- if (dn->exponent<=tinyexp) { // prefilter
- Int comp;
- decNumber nmin;
- // A very nasty case here is dn == Nmin and residue<0
- if (dn->exponent<tinyexp) {
- // Go handle subnormals; this will apply round if needed.
- decSetSubnormal(dn, set, residue, status);
- return;
- }
- // Equals case: only subnormal if dn=Nmin and negative residue
- decNumberZero(&nmin);
- nmin.lsu[0]=1;
- nmin.exponent=set->emin;
- comp=decCompare(dn, &nmin, 1); // (signless compare)
- if (comp==BADINT) { // oops
- *status|=DEC_Insufficient_storage; // abandon...
- return;
- }
- if (*residue<0 && comp==0) { // neg residue and dn==Nmin
- decApplyRound(dn, set, *residue, status); // might force down
- decSetSubnormal(dn, set, residue, status);
- return;
- }
- }
- // now apply any pending round (this could raise overflow).
- if (*residue!=0) decApplyRound(dn, set, *residue, status);
- // Check for overflow [redundant in the 'rare' case] or clamp
- if (dn->exponent<=set->emax-set->digits+1) return; // neither needed
- // here when might have an overflow or clamp to do
- if (dn->exponent>set->emax-dn->digits+1) { // too big
- decSetOverflow(dn, set, status);
- return;
- }
- // here when the result is normal but in clamp range
- if (!set->clamp) return;
- // here when need to apply the IEEE exponent clamp (fold-down)
- shift=dn->exponent-(set->emax-set->digits+1);
- // shift coefficient (if non-zero)
- if (!ISZERO(dn)) {
- dn->digits=decShiftToMost(dn->lsu, dn->digits, shift);
- }
- dn->exponent-=shift; // adjust the exponent to match
- *status|=DEC_Clamped; // and record the dirty deed
- return;
- } // decFinalize
- /* ------------------------------------------------------------------ */
- /* decSetOverflow -- set number to proper overflow value */
- /* */
- /* dn is the number (used for sign [only] and result) */
- /* set is the context [used for the rounding mode, etc.] */
- /* status contains the current status to be updated */
- /* */
- /* This sets the sign of a number and sets its value to either */
- /* Infinity or the maximum finite value, depending on the sign of */
- /* dn and the rounding mode, following IEEE 754 rules. */
- /* ------------------------------------------------------------------ */
- static void decSetOverflow(decNumber *dn, decContext *set, uInt *status) {
- Flag needmax=0; // result is maximum finite value
- uByte sign=dn->bits&DECNEG; // clean and save sign bit
- if (ISZERO(dn)) { // zero does not overflow magnitude
- Int emax=set->emax; // limit value
- if (set->clamp) emax-=set->digits-1; // lower if clamping
- if (dn->exponent>emax) { // clamp required
- dn->exponent=emax;
- *status|=DEC_Clamped;
- }
- return;
- }
- decNumberZero(dn);
- switch (set->round) {
- case DEC_ROUND_DOWN: {
- needmax=1; // never Infinity
- break;} // r-d
- case DEC_ROUND_05UP: {
- needmax=1; // never Infinity
- break;} // r-05
- case DEC_ROUND_CEILING: {
- if (sign) needmax=1; // Infinity if non-negative
- break;} // r-c
- case DEC_ROUND_FLOOR: {
- if (!sign) needmax=1; // Infinity if negative
- break;} // r-f
- default: break; // Infinity in all other cases
- }
- if (needmax) {
- decSetMaxValue(dn, set);
- dn->bits=sign; // set sign
- }
- else dn->bits=sign|DECINF; // Value is +/-Infinity
- *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded;
- } // decSetOverflow
- /* ------------------------------------------------------------------ */
- /* decSetMaxValue -- set number to +Nmax (maximum normal value) */
- /* */
- /* dn is the number to set */
- /* set is the context [used for digits and emax] */
- /* */
- /* This sets the number to the maximum positive value. */
- /* ------------------------------------------------------------------ */
- static void decSetMaxValue(decNumber *dn, decContext *set) {
- Unit *up; // work
- Int count=set->digits; // nines to add
- dn->digits=count;
- // fill in all nines to set maximum value
- for (up=dn->lsu; ; up++) {
- if (count>DECDPUN) *up=DECDPUNMAX; // unit full o'nines
- else { // this is the msu
- *up=(Unit)(powers[count]-1);
- break;
- }
- count-=DECDPUN; // filled those digits
- } // up
- dn->bits=0; // + sign
- dn->exponent=set->emax-set->digits+1;
- } // decSetMaxValue
- /* ------------------------------------------------------------------ */
- /* decSetSubnormal -- process value whose exponent is <Emin */
- /* */
- /* dn is the number (used as input as well as output; it may have */
- /* an allowed subnormal value, which may need to be rounded) */
- /* set is the context [used for the rounding mode] */
- /* residue is any pending residue */
- /* status contains the current status to be updated */
- /* */
- /* If subset mode, set result to zero and set Underflow flags. */
- /* */
- /* Value may be zero with a low exponent; this does not set Subnormal */
- /* but the exponent will be clamped to Etiny. */
- /* */
- /* Otherwise ensure exponent is not out of range, and round as */
- /* necessary. Underflow is set if the result is Inexact. */
- /* ------------------------------------------------------------------ */
- static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue,
- uInt *status) {
- decContext workset; // work
- Int etiny, adjust; // ..
- #if DECSUBSET
- // simple set to zero and 'hard underflow' for subset
- if (!set->extended) {
- decNumberZero(dn);
- // always full overflow
- *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
- return;
- }
- #endif
- // Full arithmetic -- allow subnormals, rounded to minimum exponent
- // (Etiny) if needed
- etiny=set->emin-(set->digits-1); // smallest allowed exponent
- if ISZERO(dn) { // value is zero
- // residue can never be non-zero here
- #if DECCHECK
- if (*residue!=0) {
- printf("++ Subnormal 0 residue %ld\n", (LI)*residue);
- *status|=DEC_Invalid_operation;
- }
- #endif
- if (dn->exponent<etiny) { // clamp required
- dn->exponent=etiny;
- *status|=DEC_Clamped;
- }
- return;
- }
- *status|=DEC_Subnormal; // have a non-zero subnormal
- adjust=etiny-dn->exponent; // calculate digits to remove
- if (adjust<=0) { // not out of range; unrounded
- // residue can never be non-zero here, except in the Nmin-residue
- // case (which is a subnormal result), so can take fast-path here
- // it may already be inexact (from setting the coefficient)
- if (*status&DEC_Inexact) *status|=DEC_Underflow;
- return;
- }
- // adjust>0, so need to rescale the result so exponent becomes Etiny
- // [this code is similar to that in rescale]
- workset=*set; // clone rounding, etc.
- workset.digits=dn->digits-adjust; // set requested length
- workset.emin-=adjust; // and adjust emin to match
- // [note that the latter can be <1, here, similar to Rescale case]
- decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status);
- decApplyRound(dn, &workset, *residue, status);
- // Use 754 default rule: Underflow is set iff Inexact
- // [independent of whether trapped]
- if (*status&DEC_Inexact) *status|=DEC_Underflow;
- // if rounded up a 999s case, exponent will be off by one; adjust
- // back if so [it will fit, because it was shortened earlier]
- if (dn->exponent>etiny) {
- dn->digits=decShiftToMost(dn->lsu, dn->digits, 1);
- dn->exponent--; // (re)adjust the exponent.
- }
- // if rounded to zero, it is by definition clamped...
- if (ISZERO(dn)) *status|=DEC_Clamped;
- } // decSetSubnormal
- /* ------------------------------------------------------------------ */
- /* decCheckMath - check entry conditions for a math function */
- /* */
- /* This checks the context and the operand */
- /* */
- /* rhs is the operand to check */
- /* set is the context to check */
- /* status is unchanged if both are good */
- /* */
- /* returns non-zero if status is changed, 0 otherwise */
- /* */
- /* Restrictions enforced: */
- /* */
- /* digits, emax, and -emin in the context must be less than */
- /* DEC_MAX_MATH (999999), and A must be within these bounds if */
- /* non-zero. Invalid_operation is set in the status if a */
- /* restriction is violated. */
- /* ------------------------------------------------------------------ */
- static uInt decCheckMath(const decNumber *rhs, decContext *set,
- uInt *status) {
- uInt save=*status; // record
- if (set->digits>DEC_MAX_MATH
- || set->emax>DEC_MAX_MATH
- || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context;
- else if ((rhs->digits>DEC_MAX_MATH
- || rhs->exponent+rhs->digits>DEC_MAX_MATH+1
- || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH))
- && !ISZERO(rhs)) *status|=DEC_Invalid_operation;
- return (*status!=save);
- } // decCheckMath
- /* ------------------------------------------------------------------ */
- /* decGetInt -- get integer from a number */
- /* */
- /* dn is the number [which will not be altered] */
- /* */
- /* returns one of: */
- /* BADINT if there is a non-zero fraction */
- /* the converted integer */
- /* BIGEVEN if the integer is even and magnitude > 2*10**9 */
- /* BIGODD if the integer is odd and magnitude > 2*10**9 */
- /* */
- /* This checks and gets a whole number from the input decNumber. */
- /* The sign can be determined from dn by the caller when BIGEVEN or */
- /* BIGODD is returned. */
- /* ------------------------------------------------------------------ */
- static Int decGetInt(const decNumber *dn) {
- Int theInt; // result accumulator
- const Unit *up; // work
- Int got; // digits (real or not) processed
- Int ilength=dn->digits+dn->exponent; // integral length
- Flag neg=decNumberIsNegative(dn); // 1 if -ve
- // The number must be an integer that fits in 10 digits
- // Assert, here, that 10 is enough for any rescale Etiny
- #if DEC_MAX_EMAX > 999999999
- #error GetInt may need updating [for Emax]
- #endif
- #if DEC_MIN_EMIN < -999999999
- #error GetInt may need updating [for Emin]
- #endif
- if (ISZERO(dn)) return 0; // zeros are OK, with any exponent
- up=dn->lsu; // ready for lsu
- theInt=0; // ready to accumulate
- if (dn->exponent>=0) { // relatively easy
- // no fractional part [usual]; allow for positive exponent
- got=dn->exponent;
- }
- else { // -ve exponent; some fractional part to check and discard
- Int count=-dn->exponent; // digits to discard
- // spin up whole units until reach the Unit with the unit digit
- for (; count>=DECDPUN; up++) {
- if (*up!=0) return BADINT; // non-zero Unit to discard
- count-=DECDPUN;
- }
- if (count==0) got=0; // [a multiple of DECDPUN]
- else { // [not multiple of DECDPUN]
- Int rem; // work
- // slice off fraction digits and check for non-zero
- #if DECDPUN<=4
- theInt=QUOT10(*up, count);
- rem=*up-theInt*powers[count];
- #else
- rem=*up%powers[count]; // slice off discards
- theInt=*up/powers[count];
- #endif
- if (rem!=0) return BADINT; // non-zero fraction
- // it looks good
- got=DECDPUN-count; // number of digits so far
- up++; // ready for next
- }
- }
- // now it's known there's no fractional part
- // tricky code now, to accumulate up to 9.3 digits
- if (got==0) {theInt=*up; got+=DECDPUN; up++;} // ensure lsu is there
- if (ilength<11) {
- Int save=theInt;
- // collect any remaining unit(s)
- for (; got<ilength; up++) {
- theInt+=*up*powers[got];
- got+=DECDPUN;
- }
- if (ilength==10) { // need to check for wrap
- if (theInt/(Int)powers[got-DECDPUN]!=(Int)*(up-1)) ilength=11;
- // [that test also disallows the BADINT result case]
- else if (neg && theInt>1999999997) ilength=11;
- else if (!neg && theInt>999999999) ilength=11;
- if (ilength==11) theInt=save; // restore correct low bit
- }
- }
- if (ilength>10) { // too big
- if (theInt&1) return BIGODD; // bottom bit 1
- return BIGEVEN; // bottom bit 0
- }
- if (neg) theInt=-theInt; // apply sign
- return theInt;
- } // decGetInt
- /* ------------------------------------------------------------------ */
- /* decDecap -- decapitate the coefficient of a number */
- /* */
- /* dn is the number to be decapitated */
- /* drop is the number of digits to be removed from the left of dn; */
- /* this must be <= dn->digits (if equal, the coefficient is */
- /* set to 0) */
- /* */
- /* Returns dn; dn->digits will be <= the initial digits less drop */
- /* (after removing drop digits there may be leading zero digits */
- /* which will also be removed). Only dn->lsu and dn->digits change. */
- /* ------------------------------------------------------------------ */
- static decNumber *decDecap(decNumber *dn, Int drop) {
- Unit *msu; // -> target cut point
- Int cut; // work
- if (drop>=dn->digits) { // losing the whole thing
- #if DECCHECK
- if (drop>dn->digits)
- printf("decDecap called with drop>digits [%ld>%ld]\n",
- (LI)drop, (LI)dn->digits);
- #endif
- dn->lsu[0]=0;
- dn->digits=1;
- return dn;
- }
- msu=dn->lsu+D2U(dn->digits-drop)-1; // -> likely msu
- cut=MSUDIGITS(dn->digits-drop); // digits to be in use in msu
- if (cut!=DECDPUN) *msu%=powers[cut]; // clear left digits
- // that may have left leading zero digits, so do a proper count...
- dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1);
- return dn;
- } // decDecap
- /* ------------------------------------------------------------------ */
- /* decBiStr -- compare string with pairwise options */
- /* */
- /* targ is the string to compare */
- /* str1 is one of the strings to compare against (length may be 0) */
- /* str2 is the other; it must be the same length as str1 */
- /* */
- /* returns 1 if strings compare equal, (that is, it is the same */
- /* length as str1 and str2, and each character of targ is in either */
- /* str1 or str2 in the corresponding position), or 0 otherwise */
- /* */
- /* This is used for generic caseless compare, including the awkward */
- /* case of the Turkish dotted and dotless Is. Use as (for example): */
- /* if (decBiStr(test, "mike", "MIKE")) ... */
- /* ------------------------------------------------------------------ */
- static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
- for (;;targ++, str1++, str2++) {
- if (*targ!=*str1 && *targ!=*str2) return 0;
- // *targ has a match in one (or both, if terminator)
- if (*targ=='\0') break;
- } // forever
- return 1;
- } // decBiStr
- /* ------------------------------------------------------------------ */
- /* decNaNs -- handle NaN operand or operands */
- /* */
- /* res is the result number */
- /* lhs is the first operand */
- /* rhs is the second operand, or NULL if none */
- /* context is used to limit payload length */
- /* status contains the current status */
- /* returns res in case convenient */
- /* */
- /* Called when one or both operands is a NaN, and propagates the */
- /* appropriate result to res. When an sNaN is found, it is changed */
- /* to a qNaN and Invalid operation is set. */
- /* ------------------------------------------------------------------ */
- static decNumber * decNaNs(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set,
- uInt *status) {
- // This decision tree ends up with LHS being the source pointer,
- // and status updated if need be
- if (lhs->bits & DECSNAN)
- *status|=DEC_Invalid_operation | DEC_sNaN;
- else if (rhs==NULL);
- else if (rhs->bits & DECSNAN) {
- lhs=rhs;
- *status|=DEC_Invalid_operation | DEC_sNaN;
- }
- else if (lhs->bits & DECNAN);
- else lhs=rhs;
- // propagate the payload
- if (lhs->digits<=set->digits) decNumberCopy(res, lhs); // easy
- else { // too long
- const Unit *ul;
- Unit *ur, *uresp1;
- // copy safe number of units, then decapitate
- res->bits=lhs->bits; // need sign etc.
- uresp1=res->lsu+D2U(set->digits);
- for (ur=res->lsu, ul=lhs->lsu; ur<uresp1; ur++, ul++) *ur=*ul;
- res->digits=D2U(set->digits)*DECDPUN;
- // maybe still too long
- if (res->digits>set->digits) decDecap(res, res->digits-set->digits);
- }
- res->bits&=~DECSNAN; // convert any sNaN to NaN, while
- res->bits|=DECNAN; // .. preserving sign
- res->exponent=0; // clean exponent
- // [coefficient was copied/decapitated]
- return res;
- } // decNaNs
- /* ------------------------------------------------------------------ */
- /* decStatus -- apply non-zero status */
- /* */
- /* dn is the number to set if error */
- /* status contains the current status (not yet in context) */
- /* set is the context */
- /* */
- /* If the status is an error status, the number is set to a NaN, */
- /* unless the error was an overflow, divide-by-zero, or underflow, */
- /* in which case the number will have already been set. */
- /* */
- /* The context status is then updated with the new status. Note that */
- /* this may raise a signal, so control may never return from this */
- /* routine (hence resources must be recovered before it is called). */
- /* ------------------------------------------------------------------ */
- static void decStatus(decNumber *dn, uInt status, decContext *set) {
- if (status & DEC_NaNs) { // error status -> NaN
- // if cause was an sNaN, clear and propagate [NaN is already set up]
- if (status & DEC_sNaN) status&=~DEC_sNaN;
- else {
- decNumberZero(dn); // other error: clean throughout
- dn->bits=DECNAN; // and make a quiet NaN
- }
- }
- decContextSetStatus(set, status); // [may not return]
- return;
- } // decStatus
- /* ------------------------------------------------------------------ */
- /* decGetDigits -- count digits in a Units array */
- /* */
- /* uar is the Unit array holding the number (this is often an */
- /* accumulator of some sort) */
- /* len is the length of the array in units [>=1] */
- /* */
- /* returns the number of (significant) digits in the array */
- /* */
- /* All leading zeros are excluded, except the last if the array has */
- /* only zero Units. */
- /* ------------------------------------------------------------------ */
- // This may be called twice during some operations.
- static Int decGetDigits(Unit *uar, Int len) {
- Unit *up=uar+(len-1); // -> msu
- Int digits=(len-1)*DECDPUN+1; // possible digits excluding msu
- #if DECDPUN>4
- uInt const *pow; // work
- #endif
- // (at least 1 in final msu)
- #if DECCHECK
- if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len);
- #endif
- for (; up>=uar; up--) {
- if (*up==0) { // unit is all 0s
- if (digits==1) break; // a zero has one digit
- digits-=DECDPUN; // adjust for 0 unit
- continue;}
- // found the first (most significant) non-zero Unit
- #if DECDPUN>1 // not done yet
- if (*up<10) break; // is 1-9
- digits++;
- #if DECDPUN>2 // not done yet
- if (*up<100) break; // is 10-99
- digits++;
- #if DECDPUN>3 // not done yet
- if (*up<1000) break; // is 100-999
- digits++;
- #if DECDPUN>4 // count the rest ...
- for (pow=&powers[4]; *up>=*pow; pow++) digits++;
- #endif
- #endif
- #endif
- #endif
- break;
- } // up
- return digits;
- } // decGetDigits
- #if DECTRACE | DECCHECK
- /* ------------------------------------------------------------------ */
- /* decNumberShow -- display a number [debug aid] */
- /* dn is the number to show */
- /* */
- /* Shows: sign, exponent, coefficient (msu first), digits */
- /* or: sign, special-value */
- /* ------------------------------------------------------------------ */
- // this is public so other modules can use it
- void decNumberShow(const decNumber *dn) {
- const Unit *up; // work
- uInt u, d; // ..
- Int cut; // ..
- char isign='+'; // main sign
- if (dn==NULL) {
- printf("NULL\n");
- return;}
- if (decNumberIsNegative(dn)) isign='-';
- printf(" >> %c ", isign);
- if (dn->bits&DECSPECIAL) { // Is a special value
- if (decNumberIsInfinite(dn)) printf("Infinity");
- else { // a NaN
- if (dn->bits&DECSNAN) printf("sNaN"); // signalling NaN
- else printf("NaN");
- }
- // if coefficient and exponent are 0, no more to do
- if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) {
- printf("\n");
- return;}
- // drop through to report other information
- printf(" ");
- }
- // now carefully display the coefficient
- up=dn->lsu+D2U(dn->digits)-1; // msu
- printf("%ld", (LI)*up);
- for (up=up-1; up>=dn->lsu; up--) {
- u=*up;
- printf(":");
- for (cut=DECDPUN-1; cut>=0; cut--) {
- d=u/powers[cut];
- u-=d*powers[cut];
- printf("%ld", (LI)d);
- } // cut
- } // up
- if (dn->exponent!=0) {
- char esign='+';
- if (dn->exponent<0) esign='-';
- printf(" E%c%ld", esign, (LI)abs(dn->exponent));
- }
- printf(" [%ld]\n", (LI)dn->digits);
- } // decNumberShow
- #endif
- #if DECTRACE || DECCHECK
- /* ------------------------------------------------------------------ */
- /* decDumpAr -- display a unit array [debug/check aid] */
- /* name is a single-character tag name */
- /* ar is the array to display */
- /* len is the length of the array in Units */
- /* ------------------------------------------------------------------ */
- static void decDumpAr(char name, const Unit *ar, Int len) {
- Int i;
- const char *spec;
- #if DECDPUN==9
- spec="%09d ";
- #elif DECDPUN==8
- spec="%08d ";
- #elif DECDPUN==7
- spec="%07d ";
- #elif DECDPUN==6
- spec="%06d ";
- #elif DECDPUN==5
- spec="%05d ";
- #elif DECDPUN==4
- spec="%04d ";
- #elif DECDPUN==3
- spec="%03d ";
- #elif DECDPUN==2
- spec="%02d ";
- #else
- spec="%d ";
- #endif
- printf(" :%c: ", name);
- for (i=len-1; i>=0; i--) {
- if (i==len-1) printf("%ld ", (LI)ar[i]);
- else printf(spec, ar[i]);
- }
- printf("\n");
- return;}
- #endif
- #if DECCHECK
- /* ------------------------------------------------------------------ */
- /* decCheckOperands -- check operand(s) to a routine */
- /* res is the result structure (not checked; it will be set to */
- /* quiet NaN if error found (and it is not NULL)) */
- /* lhs is the first operand (may be DECUNRESU) */
- /* rhs is the second (may be DECUNUSED) */
- /* set is the context (may be DECUNCONT) */
- /* returns 0 if both operands, and the context are clean, or 1 */
- /* otherwise (in which case the context will show an error, */
- /* unless NULL). Note that res is not cleaned; caller should */
- /* handle this so res=NULL case is safe. */
- /* The caller is expected to abandon immediately if 1 is returned. */
- /* ------------------------------------------------------------------ */
- static Flag decCheckOperands(decNumber *res, const decNumber *lhs,
- const decNumber *rhs, decContext *set) {
- Flag bad=0;
- if (set==NULL) { // oops; hopeless
- #if DECTRACE || DECVERB
- printf("Reference to context is NULL.\n");
- #endif
- bad=1;
- return 1;}
- else if (set!=DECUNCONT
- && (set->digits<1 || set->round>=DEC_ROUND_MAX)) {
- bad=1;
- #if DECTRACE || DECVERB
- printf("Bad context [digits=%ld round=%ld].\n",
- (LI)set->digits, (LI)set->round);
- #endif
- }
- else {
- if (res==NULL) {
- bad=1;
- #if DECTRACE
- // this one not DECVERB as standard tests include NULL
- printf("Reference to result is NULL.\n");
- #endif
- }
- if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs));
- if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs));
- }
- if (bad) {
- if (set!=DECUNCONT) decContextSetStatus(set, DEC_Invalid_operation);
- if (res!=DECUNRESU && res!=NULL) {
- decNumberZero(res);
- res->bits=DECNAN; // qNaN
- }
- }
- return bad;
- } // decCheckOperands
- /* ------------------------------------------------------------------ */
- /* decCheckNumber -- check a number */
- /* dn is the number to check */
- /* returns 0 if the number is clean, or 1 otherwise */
- /* */
- /* The number is considered valid if it could be a result from some */
- /* operation in some valid context. */
- /* ------------------------------------------------------------------ */
- static Flag decCheckNumber(const decNumber *dn) {
- const Unit *up; // work
- uInt maxuint; // ..
- Int ae, d, digits; // ..
- Int emin, emax; // ..
- if (dn==NULL) { // hopeless
- #if DECTRACE
- // this one not DECVERB as standard tests include NULL
- printf("Reference to decNumber is NULL.\n");
- #endif
- return 1;}
- // check special values
- if (dn->bits & DECSPECIAL) {
- if (dn->exponent!=0) {
- #if DECTRACE || DECVERB
- printf("Exponent %ld (not 0) for a special value [%02x].\n",
- (LI)dn->exponent, dn->bits);
- #endif
- return 1;}
- // 2003.09.08: NaNs may now have coefficients, so next tests Inf only
- if (decNumberIsInfinite(dn)) {
- if (dn->digits!=1) {
- #if DECTRACE || DECVERB
- printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits);
- #endif
- return 1;}
- if (*dn->lsu!=0) {
- #if DECTRACE || DECVERB
- printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu);
- #endif
- decDumpAr('I', dn->lsu, D2U(dn->digits));
- return 1;}
- } // Inf
- // 2002.12.26: negative NaNs can now appear through proposed IEEE
- // concrete formats (decimal64, etc.).
- return 0;
- }
- // check the coefficient
- if (dn->digits<1 || dn->digits>DECNUMMAXP) {
- #if DECTRACE || DECVERB
- printf("Digits %ld in number.\n", (LI)dn->digits);
- #endif
- return 1;}
- d=dn->digits;
- for (up=dn->lsu; d>0; up++) {
- if (d>DECDPUN) maxuint=DECDPUNMAX;
- else { // reached the msu
- maxuint=powers[d]-1;
- if (dn->digits>1 && *up<powers[d-1]) {
- #if DECTRACE || DECVERB
- printf("Leading 0 in number.\n");
- decNumberShow(dn);
- #endif
- return 1;}
- }
- if (*up>maxuint) {
- #if DECTRACE || DECVERB
- printf("Bad Unit [%08lx] in %ld-digit number at offset %ld [maxuint %ld].\n",
- (LI)*up, (LI)dn->digits, (LI)(up-dn->lsu), (LI)maxuint);
- #endif
- return 1;}
- d-=DECDPUN;
- }
- // check the exponent. Note that input operands can have exponents
- // which are out of the set->emin/set->emax and set->digits range
- // (just as they can have more digits than set->digits).
- ae=dn->exponent+dn->digits-1; // adjusted exponent
- emax=DECNUMMAXE;
- emin=DECNUMMINE;
- digits=DECNUMMAXP;
- if (ae<emin-(digits-1)) {
- #if DECTRACE || DECVERB
- printf("Adjusted exponent underflow [%ld].\n", (LI)ae);
- decNumberShow(dn);
- #endif
- return 1;}
- if (ae>+emax) {
- #if DECTRACE || DECVERB
- printf("Adjusted exponent overflow [%ld].\n", (LI)ae);
- decNumberShow(dn);
- #endif
- return 1;}
- return 0; // it's OK
- } // decCheckNumber
- /* ------------------------------------------------------------------ */
- /* decCheckInexact -- check a normal finite inexact result has digits */
- /* dn is the number to check */
- /* set is the context (for status and precision) */
- /* sets Invalid operation, etc., if some digits are missing */
- /* [this check is not made for DECSUBSET compilation or when */
- /* subnormal is not set] */
- /* ------------------------------------------------------------------ */
- static void decCheckInexact(const decNumber *dn, decContext *set) {
- #if !DECSUBSET && DECEXTFLAG
- if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact
- && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) {
- #if DECTRACE || DECVERB
- printf("Insufficient digits [%ld] on normal Inexact result.\n",
- (LI)dn->digits);
- decNumberShow(dn);
- #endif
- decContextSetStatus(set, DEC_Invalid_operation);
- }
- #else
- // next is a noop for quiet compiler
- if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation;
- #endif
- return;
- } // decCheckInexact
- #endif
- #if DECALLOC
- #undef malloc
- #undef free
- /* ------------------------------------------------------------------ */
- /* decMalloc -- accountable allocation routine */
- /* n is the number of bytes to allocate */
- /* */
- /* Semantics is the same as the stdlib malloc routine, but bytes */
- /* allocated are accounted for globally, and corruption fences are */
- /* added before and after the 'actual' storage. */
- /* ------------------------------------------------------------------ */
- /* This routine allocates storage with an extra twelve bytes; 8 are */
- /* at the start and hold: */
- /* 0-3 the original length requested */
- /* 4-7 buffer corruption detection fence (DECFENCE, x4) */
- /* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */
- /* ------------------------------------------------------------------ */
- static void *decMalloc(size_t n) {
- uInt size=n+12; // true size
- void *alloc; // -> allocated storage
- uByte *b, *b0; // work
- uInt uiwork; // for macros
- alloc=malloc(size); // -> allocated storage
- if (alloc==NULL) return NULL; // out of strorage
- b0=(uByte *)alloc; // as bytes
- decAllocBytes+=n; // account for storage
- UBFROMUI(alloc, n); // save n
- // printf(" alloc ++ dAB: %ld (%ld)\n", (LI)decAllocBytes, (LI)n);
- for (b=b0+4; b<b0+8; b++) *b=DECFENCE;
- for (b=b0+n+8; b<b0+n+12; b++) *b=DECFENCE;
- return b0+8; // -> play area
- } // decMalloc
- /* ------------------------------------------------------------------ */
- /* decFree -- accountable free routine */
- /* alloc is the storage to free */
- /* */
- /* Semantics is the same as the stdlib malloc routine, except that */
- /* the global storage accounting is updated and the fences are */
- /* checked to ensure that no routine has written 'out of bounds'. */
- /* ------------------------------------------------------------------ */
- /* This routine first checks that the fences have not been corrupted. */
- /* It then frees the storage using the 'truw' storage address (that */
- /* is, offset by 8). */
- /* ------------------------------------------------------------------ */
- static void decFree(void *alloc) {
- uInt n; // original length
- uByte *b, *b0; // work
- uInt uiwork; // for macros
- if (alloc==NULL) return; // allowed; it's a nop
- b0=(uByte *)alloc; // as bytes
- b0-=8; // -> true start of storage
- n=UBTOUI(b0); // lift length
- for (b=b0+4; b<b0+8; b++) if (*b!=DECFENCE)
- printf("=== Corrupt byte [%02x] at offset %d from %ld ===\n", *b,
- b-b0-8, (LI)b0);
- for (b=b0+n+8; b<b0+n+12; b++) if (*b!=DECFENCE)
- printf("=== Corrupt byte [%02x] at offset +%d from %ld, n=%ld ===\n", *b,
- b-b0-8, (LI)b0, (LI)n);
- free(b0); // drop the storage
- decAllocBytes-=n; // account for storage
- // printf(" free -- dAB: %d (%d)\n", decAllocBytes, -n);
- } // decFree
- #define malloc(a) decMalloc(a)
- #define free(a) decFree(a)
- #endif
|