2
0

softfpu.pp 320 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248
  1. {*
  2. ===============================================================================
  3. The original notice of the softfloat package is shown below. The conversion
  4. to pascal was done by Carl Eric Codere in 2002 ([email protected]).
  5. ===============================================================================
  6. This C source file is part of the SoftFloat IEC/IEEE Floating-Point
  7. Arithmetic Package, Release 2a.
  8. Written by John R. Hauser. This work was made possible in part by the
  9. International Computer Science Institute, located at Suite 600, 1947 Center
  10. Street, Berkeley, California 94704. Funding was partially provided by the
  11. National Science Foundation under grant MIP-9311980. The original version
  12. of this code was written as part of a project to build a fixed-point vector
  13. processor in collaboration with the University of California at Berkeley,
  14. overseen by Profs. Nelson Morgan and John Wawrzynek. More information
  15. is available through the Web page
  16. `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'.
  17. THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
  18. has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
  19. TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
  20. PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
  21. AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
  22. Derivative works are acceptable, even for commercial purposes, so long as
  23. (1) they include prominent notice that the work is derivative, and (2) they
  24. include prominent notice akin to these four paragraphs for those parts of
  25. this code that are retained.
  26. ===============================================================================
  27. The float80 and float128 part is translated from the softfloat package
  28. by Florian Klaempfl and contained the following copyright notice
  29. The code might contain some duplicate stuff because the floatx80/float128 port was
  30. done based on the 64 bit enabled softfloat code.
  31. ===============================================================================
  32. This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
  33. Package, Release 2b.
  34. Written by John R. Hauser. This work was made possible in part by the
  35. International Computer Science Institute, located at Suite 600, 1947 Center
  36. Street, Berkeley, California 94704. Funding was partially provided by the
  37. National Science Foundation under grant MIP-9311980. The original version
  38. of this code was written as part of a project to build a fixed-point vector
  39. processor in collaboration with the University of California at Berkeley,
  40. overseen by Profs. Nelson Morgan and John Wawrzynek. More information
  41. is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
  42. arithmetic/SoftFloat.html'.
  43. THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
  44. been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
  45. RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
  46. AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
  47. COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
  48. EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
  49. INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
  50. OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
  51. Derivative works are acceptable, even for commercial purposes, so long as
  52. (1) the source code for the derivative work includes prominent notice that
  53. the work is derivative, and (2) the source code includes prominent notice with
  54. these four paragraphs for those parts of this code that are retained.
  55. ===============================================================================
  56. *}
  57. { $define FPC_SOFTFLOAT_FLOATX80}
  58. { $define FPC_SOFTFLOAT_FLOAT128}
  59. { the softfpu unit can be also embedded directly into the system unit }
  60. {$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  61. {$mode objfpc}
  62. unit softfpu;
  63. { Overflow checking must be disabled,
  64. since some operations expect overflow!
  65. }
  66. {$Q-}
  67. {$goto on}
  68. {$macro on}
  69. {$define compilerproc:=stdcall }
  70. interface
  71. {$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  72. {$if not(defined(fpc_softfpu_implementation))}
  73. {
  74. -------------------------------------------------------------------------------
  75. Software IEC/IEEE floating-point types.
  76. -------------------------------------------------------------------------------
  77. }
  78. TYPE
  79. float32 = longword;
  80. {$define FPC_SYSTEM_HAS_float32}
  81. { we use here a record in the function header because
  82. the record allows bitwise conversion to single }
  83. float32rec = record
  84. float32 : float32;
  85. end;
  86. flag = byte;
  87. bits8 = byte;
  88. sbits8 = shortint;
  89. bits16 = word;
  90. sbits16 = smallint;
  91. sbits32 = longint;
  92. bits32 = longword;
  93. {$ifndef fpc}
  94. qword = int64;
  95. {$endif}
  96. { now part of the system unit
  97. uint64 = qword;
  98. }
  99. bits64 = qword;
  100. sbits64 = int64;
  101. {$ifdef ENDIAN_LITTLE}
  102. float64 = record
  103. case byte of
  104. 1: (low,high : bits32);
  105. // force the record to be aligned like a double
  106. // else *_to_double will fail for cpus like sparc
  107. // and avoid expensive unpacking/packing operations
  108. 2: (dummy : double);
  109. end;
  110. floatx80 = record
  111. case byte of
  112. 1: (low : qword;high : word);
  113. // force the record to be aligned like a double
  114. // else *_to_double will fail for cpus like sparc
  115. // and avoid expensive unpacking/packing operations
  116. 2: (dummy : extended);
  117. end;
  118. float128 = record
  119. case byte of
  120. 1: (low,high : qword);
  121. // force the record to be aligned like a double
  122. // else *_to_double will fail for cpus like sparc
  123. // and avoid expensive unpacking/packing operations
  124. 2: (dummy : qword);
  125. end;
  126. {$else}
  127. float64 = record
  128. case byte of
  129. 1: (high,low : bits32);
  130. // force the record to be aligned like a double
  131. // else *_to_double will fail for cpus like sparc
  132. 2: (dummy : double);
  133. end;
  134. floatx80 = record
  135. case byte of
  136. 1: (high : word;low : qword);
  137. // force the record to be aligned like a double
  138. // else *_to_double will fail for cpus like sparc
  139. // and avoid expensive unpacking/packing operations
  140. 2: (dummy : qword);
  141. end;
  142. float128 = record
  143. case byte of
  144. 1: (high : qword;low : qword);
  145. // force the record to be aligned like a double
  146. // else *_to_double will fail for cpus like sparc
  147. // and avoid expensive unpacking/packing operations
  148. 2: (dummy : qword);
  149. end;
  150. {$endif}
  151. {$define FPC_SYSTEM_HAS_float64}
  152. {*
  153. -------------------------------------------------------------------------------
  154. Returns 1 if the double-precision floating-point value `a' is less than
  155. the corresponding value `b', and 0 otherwise. The comparison is performed
  156. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  157. -------------------------------------------------------------------------------
  158. *}
  159. Function float64_lt(a: float64;b: float64): flag; compilerproc;
  160. {*
  161. -------------------------------------------------------------------------------
  162. Returns 1 if the double-precision floating-point value `a' is less than
  163. or equal to the corresponding value `b', and 0 otherwise. The comparison
  164. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  165. Arithmetic.
  166. -------------------------------------------------------------------------------
  167. *}
  168. Function float64_le(a: float64;b: float64): flag; compilerproc;
  169. {*
  170. -------------------------------------------------------------------------------
  171. Returns 1 if the double-precision floating-point value `a' is equal to
  172. the corresponding value `b', and 0 otherwise. The comparison is performed
  173. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  174. -------------------------------------------------------------------------------
  175. *}
  176. Function float64_eq(a: float64;b: float64): flag; compilerproc;
  177. {*
  178. -------------------------------------------------------------------------------
  179. Returns the square root of the double-precision floating-point value `a'.
  180. The operation is performed according to the IEC/IEEE Standard for Binary
  181. Floating-Point Arithmetic.
  182. -------------------------------------------------------------------------------
  183. *}
  184. function float64_sqrt( a: float64 ): float64; compilerproc;
  185. {*
  186. -------------------------------------------------------------------------------
  187. Returns the remainder of the double-precision floating-point value `a'
  188. with respect to the corresponding value `b'. The operation is performed
  189. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  190. -------------------------------------------------------------------------------
  191. *}
  192. Function float64_rem(a: float64; b : float64) : float64; compilerproc;
  193. {*
  194. -------------------------------------------------------------------------------
  195. Returns the result of dividing the double-precision floating-point value `a'
  196. by the corresponding value `b'. The operation is performed according to the
  197. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  198. -------------------------------------------------------------------------------
  199. *}
  200. Function float64_div(a: float64; b : float64) : float64; compilerproc;
  201. {*
  202. -------------------------------------------------------------------------------
  203. Returns the result of multiplying the double-precision floating-point values
  204. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  205. for Binary Floating-Point Arithmetic.
  206. -------------------------------------------------------------------------------
  207. *}
  208. Function float64_mul( a: float64; b:float64) : float64; compilerproc;
  209. {*
  210. -------------------------------------------------------------------------------
  211. Returns the result of subtracting the double-precision floating-point values
  212. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  213. for Binary Floating-Point Arithmetic.
  214. -------------------------------------------------------------------------------
  215. *}
  216. Function float64_sub(a: float64; b : float64) : float64; compilerproc;
  217. {*
  218. -------------------------------------------------------------------------------
  219. Returns the result of adding the double-precision floating-point values `a'
  220. and `b'. The operation is performed according to the IEC/IEEE Standard for
  221. Binary Floating-Point Arithmetic.
  222. -------------------------------------------------------------------------------
  223. *}
  224. Function float64_add( a: float64; b : float64) : float64; compilerproc;
  225. {*
  226. -------------------------------------------------------------------------------
  227. Rounds the double-precision floating-point value `a' to an integer,
  228. and returns the result as a double-precision floating-point value. The
  229. operation is performed according to the IEC/IEEE Standard for Binary
  230. Floating-Point Arithmetic.
  231. -------------------------------------------------------------------------------
  232. *}
  233. Function float64_round_to_int(a: float64) : float64; compilerproc;
  234. {*
  235. -------------------------------------------------------------------------------
  236. Returns the result of converting the double-precision floating-point value
  237. `a' to the single-precision floating-point format. The conversion is
  238. performed according to the IEC/IEEE Standard for Binary Floating-Point
  239. Arithmetic.
  240. -------------------------------------------------------------------------------
  241. *}
  242. Function float64_to_float32(a: float64) : float32rec; compilerproc;
  243. {*
  244. -------------------------------------------------------------------------------
  245. Returns the result of converting the double-precision floating-point value
  246. `a' to the 32-bit two's complement integer format. The conversion is
  247. performed according to the IEC/IEEE Standard for Binary Floating-Point
  248. Arithmetic, except that the conversion is always rounded toward zero.
  249. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  250. the conversion overflows, the largest integer with the same sign as `a' is
  251. returned.
  252. -------------------------------------------------------------------------------
  253. *}
  254. Function float64_to_int32_round_to_zero(a: float64 ): int32; compilerproc;
  255. {*
  256. -------------------------------------------------------------------------------
  257. Returns the result of converting the double-precision floating-point value
  258. `a' to the 32-bit two's complement integer format. The conversion is
  259. performed according to the IEC/IEEE Standard for Binary Floating-Point
  260. Arithmetic---which means in particular that the conversion is rounded
  261. according to the current rounding mode. If `a' is a NaN, the largest
  262. positive integer is returned. Otherwise, if the conversion overflows, the
  263. largest integer with the same sign as `a' is returned.
  264. -------------------------------------------------------------------------------
  265. *}
  266. Function float64_to_int32(a: float64): int32; compilerproc;
  267. {*
  268. -------------------------------------------------------------------------------
  269. Returns 1 if the single-precision floating-point value `a' is less than
  270. the corresponding value `b', and 0 otherwise. The comparison is performed
  271. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  272. -------------------------------------------------------------------------------
  273. *}
  274. Function float32_lt( a:float32rec ; b : float32rec): flag; compilerproc;
  275. {*
  276. -------------------------------------------------------------------------------
  277. Returns 1 if the single-precision floating-point value `a' is less than
  278. or equal to the corresponding value `b', and 0 otherwise. The comparison
  279. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  280. Arithmetic.
  281. -------------------------------------------------------------------------------
  282. *}
  283. Function float32_le( a: float32rec; b : float32rec ):flag; compilerproc;
  284. {*
  285. -------------------------------------------------------------------------------
  286. Returns 1 if the single-precision floating-point value `a' is equal to
  287. the corresponding value `b', and 0 otherwise. The comparison is performed
  288. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  289. -------------------------------------------------------------------------------
  290. *}
  291. Function float32_eq( a:float32rec; b:float32rec): flag; compilerproc;
  292. {*
  293. -------------------------------------------------------------------------------
  294. Returns the square root of the single-precision floating-point value `a'.
  295. The operation is performed according to the IEC/IEEE Standard for Binary
  296. Floating-Point Arithmetic.
  297. -------------------------------------------------------------------------------
  298. *}
  299. Function float32_sqrt(a: float32rec ): float32rec; compilerproc;
  300. {*
  301. -------------------------------------------------------------------------------
  302. Returns the remainder of the single-precision floating-point value `a'
  303. with respect to the corresponding value `b'. The operation is performed
  304. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  305. -------------------------------------------------------------------------------
  306. *}
  307. Function float32_rem(a: float32rec; b: float32rec ):float32rec; compilerproc;
  308. {*
  309. -------------------------------------------------------------------------------
  310. Returns the result of dividing the single-precision floating-point value `a'
  311. by the corresponding value `b'. The operation is performed according to the
  312. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  313. -------------------------------------------------------------------------------
  314. *}
  315. Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc;
  316. {*
  317. -------------------------------------------------------------------------------
  318. Returns the result of multiplying the single-precision floating-point values
  319. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  320. for Binary Floating-Point Arithmetic.
  321. -------------------------------------------------------------------------------
  322. *}
  323. Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc;
  324. {*
  325. -------------------------------------------------------------------------------
  326. Returns the result of subtracting the single-precision floating-point values
  327. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  328. for Binary Floating-Point Arithmetic.
  329. -------------------------------------------------------------------------------
  330. *}
  331. Function float32_sub( a: float32rec ; b:float32rec ): float32rec; compilerproc;
  332. {*
  333. -------------------------------------------------------------------------------
  334. Returns the result of adding the single-precision floating-point values `a'
  335. and `b'. The operation is performed according to the IEC/IEEE Standard for
  336. Binary Floating-Point Arithmetic.
  337. -------------------------------------------------------------------------------
  338. *}
  339. Function float32_add( a: float32rec; b:float32rec ): float32rec; compilerproc;
  340. {*
  341. -------------------------------------------------------------------------------
  342. Rounds the single-precision floating-point value `a' to an integer,
  343. and returns the result as a single-precision floating-point value. The
  344. operation is performed according to the IEC/IEEE Standard for Binary
  345. Floating-Point Arithmetic.
  346. -------------------------------------------------------------------------------
  347. *}
  348. Function float32_round_to_int( a: float32rec): float32rec; compilerproc;
  349. {*
  350. -------------------------------------------------------------------------------
  351. Returns the result of converting the single-precision floating-point value
  352. `a' to the double-precision floating-point format. The conversion is
  353. performed according to the IEC/IEEE Standard for Binary Floating-Point
  354. Arithmetic.
  355. -------------------------------------------------------------------------------
  356. *}
  357. Function float32_to_float64( a : float32rec) : Float64; compilerproc;
  358. {*
  359. -------------------------------------------------------------------------------
  360. Returns the result of converting the single-precision floating-point value
  361. `a' to the 32-bit two's complement integer format. The conversion is
  362. performed according to the IEC/IEEE Standard for Binary Floating-Point
  363. Arithmetic, except that the conversion is always rounded toward zero.
  364. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  365. the conversion overflows, the largest integer with the same sign as `a' is
  366. returned.
  367. -------------------------------------------------------------------------------
  368. *}
  369. Function float32_to_int32_round_to_zero( a: Float32rec ): int32; compilerproc;
  370. {*
  371. -------------------------------------------------------------------------------
  372. Returns the result of converting the single-precision floating-point value
  373. `a' to the 32-bit two's complement integer format. The conversion is
  374. performed according to the IEC/IEEE Standard for Binary Floating-Point
  375. Arithmetic---which means in particular that the conversion is rounded
  376. according to the current rounding mode. If `a' is a NaN, the largest
  377. positive integer is returned. Otherwise, if the conversion overflows, the
  378. largest integer with the same sign as `a' is returned.
  379. -------------------------------------------------------------------------------
  380. *}
  381. Function float32_to_int32( a : float32rec) : int32; compilerproc;
  382. {*
  383. -------------------------------------------------------------------------------
  384. Returns the result of converting the 32-bit two's complement integer `a' to
  385. the double-precision floating-point format. The conversion is performed
  386. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  387. -------------------------------------------------------------------------------
  388. *}
  389. Function int32_to_float64( a: int32) : float64; compilerproc;
  390. {*
  391. -------------------------------------------------------------------------------
  392. Returns the result of converting the 32-bit two's complement integer `a' to
  393. the single-precision floating-point format. The conversion is performed
  394. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  395. -------------------------------------------------------------------------------
  396. *}
  397. Function int32_to_float32( a: int32): float32rec; compilerproc;
  398. {*----------------------------------------------------------------------------
  399. | Returns the result of converting the 64-bit two's complement integer `a'
  400. | to the double-precision floating-point format. The conversion is performed
  401. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  402. *----------------------------------------------------------------------------*}
  403. Function int64_to_float64( a: int64 ): float64; compilerproc;
  404. Function qword_to_float64( a: qword ): float64; compilerproc;
  405. {*----------------------------------------------------------------------------
  406. | Returns the result of converting the 64-bit two's complement integer `a'
  407. | to the single-precision floating-point format. The conversion is performed
  408. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  409. *----------------------------------------------------------------------------*}
  410. Function int64_to_float32( a: int64 ): float32rec; compilerproc;
  411. Function qword_to_float32( a: qword ): float32rec; compilerproc;
  412. // +++
  413. function float32_to_int64( a: float32 ): int64;
  414. function float32_to_int64_round_to_zero( a: float32 ): int64;
  415. function float32_eq_signaling( a: float32; b: float32) : flag;
  416. function float32_le_quiet( a: float32 ; b : float32 ): flag;
  417. function float32_lt_quiet( a: float32 ; b: float32 ): flag;
  418. function float32_is_signaling_nan( a : float32 ): flag;
  419. function float32_is_nan( a : float32 ): flag;
  420. function float64_to_int64( a: float64 ): int64;
  421. function float64_to_int64_round_to_zero( a: float64 ): int64;
  422. function float64_eq_signaling( a: float64; b: float64): flag;
  423. function float64_le_quiet(a: float64 ; b: float64 ): flag;
  424. function float64_lt_quiet(a: float64; b: float64 ): Flag;
  425. function float64_is_signaling_nan( a : float64 ): flag;
  426. function float64_is_nan( a : float64 ): flag;
  427. // ===
  428. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  429. {*----------------------------------------------------------------------------
  430. | Extended double-precision rounding precision
  431. *----------------------------------------------------------------------------*}
  432. var // threadvar!?
  433. floatx80_rounding_precision : int8 = 80;
  434. function int32_to_floatx80( a: int32 ): floatx80;
  435. function int64_to_floatx80( a: int64 ): floatx80;
  436. function qword_to_floatx80( a: qword ): floatx80;
  437. function float32_to_floatx80( a: float32 ): floatx80;
  438. function float64_to_floatx80( a: float64 ): floatx80;
  439. function floatx80_to_int32( a: floatx80 ): int32;
  440. function floatx80_to_int32_round_to_zero( a: floatx80 ): int32;
  441. function floatx80_to_int64( a: floatx80 ): int64;
  442. function floatx80_to_int64_round_to_zero( a: floatx80 ): int64;
  443. function floatx80_to_float32( a: floatx80 ): float32;
  444. function floatx80_to_float64( a: floatx80 ): float64;
  445. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  446. function floatx80_to_float128( a: floatx80 ): float128;
  447. {$endif FPC_SOFTFLOAT_FLOAT128}
  448. function floatx80_round_to_int( a: floatx80 ): floatx80;
  449. function floatx80_add( a: floatx80; b: floatx80 ): floatx80;
  450. function floatx80_sub( a: floatx80; b: floatx80 ): floatx80;
  451. function floatx80_mul( a: floatx80; b: floatx80 ): floatx80;
  452. function floatx80_div( a: floatx80; b: floatx80 ): floatx80;
  453. function floatx80_rem( a: floatx80; b: floatx80 ): floatx80;
  454. function floatx80_sqrt( a: floatx80 ): floatx80;
  455. function floatx80_eq( a: floatx80; b: floatx80 ): flag;
  456. function floatx80_le( a: floatx80; b: floatx80 ): flag;
  457. function floatx80_lt( a: floatx80; b: floatx80 ): flag;
  458. function floatx80_eq_signaling( a: floatx80; b: floatx80 ): flag;
  459. function floatx80_le_quiet( a: floatx80; b: floatx80 ): flag;
  460. function floatx80_lt_quiet( a: floatx80; b: floatx80 ): flag;
  461. function floatx80_is_signaling_nan( a: floatx80 ): flag;
  462. function floatx80_is_nan(a : floatx80 ): flag;
  463. {$endif FPC_SOFTFLOAT_FLOATX80}
  464. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  465. function int32_to_float128( a: int32 ): float128;
  466. function int64_to_float128( a: int64 ): float128;
  467. function qword_to_float128( a: qword ): float128;
  468. function float32_to_float128( a: float32 ): float128;
  469. function float128_is_nan( a : float128): flag;
  470. function float128_is_signaling_nan( a : float128): flag;
  471. function float128_to_int32(a: float128): int32;
  472. function float128_to_int32_round_to_zero(a: float128): int32;
  473. function float128_to_int64(a: float128): int64;
  474. function float128_to_int64_round_to_zero(a: float128): int64;
  475. function float128_to_float32(a: float128): float32;
  476. function float128_to_float64(a: float128): float64;
  477. function float64_to_float128( a : float64) : float128;
  478. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  479. function float128_to_floatx80(a: float128): floatx80;
  480. {$endif FPC_SOFTFLOAT_FLOATX80}
  481. function float128_round_to_int(a: float128): float128;
  482. function float128_add(a: float128; b: float128): float128;
  483. function float128_sub(a: float128; b: float128): float128;
  484. function float128_mul(a: float128; b: float128): float128;
  485. function float128_div(a: float128; b: float128): float128;
  486. function float128_rem(a: float128; b: float128): float128;
  487. function float128_sqrt(a: float128): float128;
  488. function float128_eq(a: float128; b: float128): flag;
  489. function float128_le(a: float128; b: float128): flag;
  490. function float128_lt(a: float128; b: float128): flag;
  491. function float128_eq_signaling(a: float128; b: float128): flag;
  492. function float128_le_quiet(a: float128; b: float128): flag;
  493. function float128_lt_quiet(a: float128; b: float128): flag;
  494. {$endif FPC_SOFTFLOAT_FLOAT128}
  495. CONST
  496. {-------------------------------------------------------------------------------
  497. Software IEC/IEEE floating-point underflow tininess-detection mode.
  498. -------------------------------------------------------------------------------
  499. *}
  500. float_tininess_after_rounding = 0;
  501. float_tininess_before_rounding = 1;
  502. {*
  503. -------------------------------------------------------------------------------
  504. Underflow tininess-detection mode, statically initialized to default value.
  505. (The declaration in `softfloat.h' must match the `int8' type here.)
  506. -------------------------------------------------------------------------------
  507. *}
  508. var // threadvar!?
  509. softfloat_detect_tininess: int8 = float_tininess_after_rounding;
  510. {$endif not(defined(fpc_softfpu_implementation))}
  511. {$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  512. implementation
  513. {$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  514. {$if not(defined(fpc_softfpu_interface))}
  515. (*****************************************************************************)
  516. (*----------------------------------------------------------------------------*)
  517. (* Primitive arithmetic functions, including multi-word arithmetic, and *)
  518. (* division and square root approximations. (Can be specialized to target if *)
  519. (* desired.) *)
  520. (* ---------------------------------------------------------------------------*)
  521. (*****************************************************************************)
  522. { This procedure serves as a single access point to softfloat_exception_flags.
  523. It also helps to reduce code size a bit because softfloat_exception_flags is
  524. a threadvar. }
  525. procedure set_inexact_flag;
  526. begin
  527. include(softfloat_exception_flags,float_flag_inexact);
  528. end;
  529. {*----------------------------------------------------------------------------
  530. | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
  531. | and 7, and returns the properly rounded 32-bit integer corresponding to the
  532. | input. If `zSign' is 1, the input is negated before being converted to an
  533. | integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input
  534. | is simply rounded to an integer, with the inexact exception raised if the
  535. | input cannot be represented exactly as an integer. However, if the fixed-
  536. | point input is too large, the invalid exception is raised and the largest
  537. | positive or negative integer is returned.
  538. *----------------------------------------------------------------------------*}
  539. function roundAndPackInt32( zSign: flag; absZ : bits64): int32;
  540. var
  541. roundingMode: TFPURoundingMode;
  542. roundNearestEven: boolean;
  543. roundIncrement, roundBits: int8;
  544. z: int32;
  545. begin
  546. roundingMode := softfloat_rounding_mode;
  547. roundNearestEven := (roundingMode = float_round_nearest_even);
  548. roundIncrement := $40;
  549. if not roundNearestEven then
  550. begin
  551. if ( roundingMode = float_round_to_zero ) then
  552. begin
  553. roundIncrement := 0;
  554. end
  555. else begin
  556. roundIncrement := $7F;
  557. if ( zSign<>0 ) then
  558. begin
  559. if ( roundingMode = float_round_up ) then
  560. roundIncrement := 0;
  561. end
  562. else begin
  563. if ( roundingMode = float_round_down ) then
  564. roundIncrement := 0;
  565. end;
  566. end;
  567. end;
  568. roundBits := absZ and $7F;
  569. absZ := ( absZ + roundIncrement ) shr 7;
  570. absZ := absZ and not( ord( ( roundBits xor $40 ) = 0 ) and ord(roundNearestEven) );
  571. z := absZ;
  572. if ( zSign<>0 ) then
  573. z := - z;
  574. if ( ( absZ shr 32 ) or ( z and ( ord( z < 0 ) xor zSign ) ) )<>0 then
  575. begin
  576. float_raise( float_flag_invalid );
  577. if zSign<>0 then
  578. result:=sbits32($80000000)
  579. else
  580. result:=$7FFFFFFF;
  581. exit;
  582. end;
  583. if ( roundBits<>0 ) then
  584. set_inexact_flag;
  585. result:=z;
  586. end;
  587. {*----------------------------------------------------------------------------
  588. | Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
  589. | `absZ1', with binary point between bits 63 and 64 (between the input words),
  590. | and returns the properly rounded 64-bit integer corresponding to the input.
  591. | If `zSign' is 1, the input is negated before being converted to an integer.
  592. | Ordinarily, the fixed-point input is simply rounded to an integer, with
  593. | the inexact exception raised if the input cannot be represented exactly as
  594. | an integer. However, if the fixed-point input is too large, the invalid
  595. | exception is raised and the largest positive or negative integer is
  596. | returned.
  597. *----------------------------------------------------------------------------*}
  598. function roundAndPackInt64( zSign: flag; absZ0: bits64; absZ1 : bits64): int64;
  599. var
  600. roundingMode: TFPURoundingMode;
  601. roundNearestEven, increment: flag;
  602. z: int64;
  603. label
  604. overflow;
  605. begin
  606. roundingMode := softfloat_rounding_mode;
  607. roundNearestEven := ord( roundingMode = float_round_nearest_even );
  608. increment := ord( sbits64(absZ1) < 0 );
  609. if ( roundNearestEven=0 ) then
  610. begin
  611. if ( roundingMode = float_round_to_zero ) then
  612. begin
  613. increment := 0;
  614. end
  615. else begin
  616. if ( zSign<>0 ) then
  617. begin
  618. increment := ord(( roundingMode = float_round_down ) and (absZ1<>0));
  619. end
  620. else begin
  621. increment := ord(( roundingMode = float_round_up ) and (absZ1<>0));
  622. end;
  623. end;
  624. end;
  625. if ( increment<>0 ) then
  626. begin
  627. inc(absZ0);
  628. if ( absZ0 = 0 ) then
  629. goto overflow;
  630. absZ0 := absZ0 and not( ord( bits64( absZ1 shl 1 ) = 0 ) and roundNearestEven );
  631. end;
  632. z := absZ0;
  633. if ( zSign<>0 ) then
  634. z := - z;
  635. if ( (z<>0) and (( ord( z < 0 ) xor zSign )<>0) ) then
  636. begin
  637. overflow:
  638. float_raise( float_flag_invalid );
  639. if zSign<>0 then
  640. result:=int64($8000000000000000)
  641. else
  642. result:=int64($7FFFFFFFFFFFFFFF);
  643. exit;
  644. end;
  645. if ( absZ1<>0 ) then
  646. set_inexact_flag;
  647. result:=z;
  648. end;
  649. {*
  650. -------------------------------------------------------------------------------
  651. Shifts `a' right by the number of bits given in `count'. If any nonzero
  652. bits are shifted off, they are ``jammed'' into the least significant bit of
  653. the result by setting the least significant bit to 1. The value of `count'
  654. can be arbitrarily large; in particular, if `count' is greater than 32, the
  655. result will be either 0 or 1, depending on whether `a' is zero or nonzero.
  656. The result is stored in the location pointed to by `zPtr'.
  657. -------------------------------------------------------------------------------
  658. *}
  659. Procedure shift32RightJamming( a: bits32 ; count: int16 ; VAR zPtr :bits32);
  660. var
  661. z: Bits32;
  662. Begin
  663. if ( count = 0 ) then
  664. z := a
  665. else
  666. if ( count < 32 ) then
  667. Begin
  668. z := ( a shr count ) or bits32( (( a shl ( ( - count ) AND 31 )) ) <> 0);
  669. End
  670. else
  671. Begin
  672. z := bits32( a <> 0 );
  673. End;
  674. zPtr := z;
  675. End;
  676. {*----------------------------------------------------------------------------
  677. | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
  678. | number of bits given in `count'. Any bits shifted off are lost. The value
  679. | of `count' can be arbitrarily large; in particular, if `count' is greater
  680. | than 128, the result will be 0. The result is broken into two 64-bit pieces
  681. | which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  682. *----------------------------------------------------------------------------*}
  683. procedure shift128Right(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
  684. var
  685. z0, z1: bits64;
  686. negCount: int8;
  687. begin
  688. negCount := ( - count ) and 63;
  689. if ( count = 0 ) then
  690. begin
  691. z1 := a1;
  692. z0 := a0;
  693. end
  694. else if ( count < 64 ) then
  695. begin
  696. z1 := ( a0 shl negCount ) or ( a1 shr count );
  697. z0 := a0 shr count;
  698. end
  699. else
  700. begin
  701. if ( count < 128 ) then
  702. z1 := a0 shr ( count and 63 )
  703. else
  704. z1 := 0;
  705. z0 := 0;
  706. end;
  707. z1Ptr := z1;
  708. z0Ptr := z0;
  709. end;
  710. {*----------------------------------------------------------------------------
  711. | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
  712. | number of bits given in `count'. If any nonzero bits are shifted off, they
  713. | are ``jammed'' into the least significant bit of the result by setting the
  714. | least significant bit to 1. The value of `count' can be arbitrarily large;
  715. | in particular, if `count' is greater than 128, the result will be either
  716. | 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
  717. | nonzero. The result is broken into two 64-bit pieces which are stored at
  718. | the locations pointed to by `z0Ptr' and `z1Ptr'.
  719. *----------------------------------------------------------------------------*}
  720. procedure shift128RightJamming(a0,a1 : bits64; count : int16; var z0Ptr, z1Ptr : bits64);
  721. var
  722. z0,z1 : bits64;
  723. negCount : int8;
  724. begin
  725. negCount := ( - count ) and 63;
  726. if ( count = 0 ) then begin
  727. z1 := a1;
  728. z0 := a0;
  729. end
  730. else if ( count < 64 ) then begin
  731. z1 := ( a0 shl negCount ) or ( a1 shr count ) or ord( ( a1 shl negCount ) <> 0 );
  732. z0 := a0 shr count;
  733. end
  734. else begin
  735. if ( count = 64 ) then begin
  736. z1 := a0 or ord( a1 <> 0 );
  737. end
  738. else if ( count < 128 ) then begin
  739. z1 := ( a0 shr ( count and 63 ) ) or ord( ( ( a0 shl negCount ) or a1 ) <> 0 );
  740. end
  741. else begin
  742. z1 := ord( ( a0 or a1 ) <> 0 );
  743. end;
  744. z0 := 0;
  745. end;
  746. z1Ptr := z1;
  747. z0Ptr := z0;
  748. end;
  749. {*
  750. -------------------------------------------------------------------------------
  751. Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
  752. number of bits given in `count'. Any bits shifted off are lost. The value
  753. of `count' can be arbitrarily large; in particular, if `count' is greater
  754. than 64, the result will be 0. The result is broken into two 32-bit pieces
  755. which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  756. -------------------------------------------------------------------------------
  757. *}
  758. Procedure
  759. shift64Right(
  760. a0 :bits32; a1: bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32);
  761. Var
  762. z0, z1: bits32;
  763. negCount : int8;
  764. Begin
  765. negCount := ( - count ) AND 31;
  766. if ( count = 0 ) then
  767. Begin
  768. z1 := a1;
  769. z0 := a0;
  770. End
  771. else if ( count < 32 ) then
  772. Begin
  773. z1 := ( a0 shl negCount ) OR ( a1 shr count );
  774. z0 := a0 shr count;
  775. End
  776. else
  777. Begin
  778. if (count < 64) then
  779. z1 := ( a0 shr ( count AND 31 ) )
  780. else
  781. z1 := 0;
  782. z0 := 0;
  783. End;
  784. z1Ptr := z1;
  785. z0Ptr := z0;
  786. End;
  787. {*
  788. -------------------------------------------------------------------------------
  789. Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
  790. number of bits given in `count'. If any nonzero bits are shifted off, they
  791. are ``jammed'' into the least significant bit of the result by setting the
  792. least significant bit to 1. The value of `count' can be arbitrarily large;
  793. in particular, if `count' is greater than 64, the result will be either 0
  794. or 1, depending on whether the concatenation of `a0' and `a1' is zero or
  795. nonzero. The result is broken into two 32-bit pieces which are stored at
  796. the locations pointed to by `z0Ptr' and `z1Ptr'.
  797. -------------------------------------------------------------------------------
  798. *}
  799. Procedure
  800. shift64RightJamming(
  801. a0:bits32; a1: bits32; count:int16; VAR Z0Ptr :bits32;VAR z1Ptr: bits32 );
  802. VAR
  803. z0, z1 : bits32;
  804. negCount : int8;
  805. Begin
  806. negCount := ( - count ) AND 31;
  807. if ( count = 0 ) then
  808. Begin
  809. z1 := a1;
  810. z0 := a0;
  811. End
  812. else
  813. if ( count < 32 ) then
  814. Begin
  815. z1 := ( a0 shl negCount ) OR ( a1 shr count ) OR bits32( ( a1 shl negCount ) <> 0 );
  816. z0 := a0 shr count;
  817. End
  818. else
  819. Begin
  820. if ( count = 32 ) then
  821. Begin
  822. z1 := a0 OR bits32( a1 <> 0 );
  823. End
  824. else
  825. if ( count < 64 ) Then
  826. Begin
  827. z1 := ( a0 shr ( count AND 31 ) ) OR bits32( ( ( a0 shl negCount ) OR a1 ) <> 0 );
  828. End
  829. else
  830. Begin
  831. z1 := bits32( ( a0 OR a1 ) <> 0 );
  832. End;
  833. z0 := 0;
  834. End;
  835. z1Ptr := z1;
  836. z0Ptr := z0;
  837. End;
  838. {*----------------------------------------------------------------------------
  839. | Shifts `a' right by the number of bits given in `count'. If any nonzero
  840. | bits are shifted off, they are ``jammed'' into the least significant bit of
  841. | the result by setting the least significant bit to 1. The value of `count'
  842. | can be arbitrarily large; in particular, if `count' is greater than 64, the
  843. | result will be either 0 or 1, depending on whether `a' is zero or nonzero.
  844. | The result is stored in the location pointed to by `zPtr'.
  845. *----------------------------------------------------------------------------*}
  846. procedure shift64RightJamming(a: bits64; count: int16; var zPtr : bits64);
  847. var
  848. z: bits64;
  849. begin
  850. if ( count = 0 ) then
  851. begin
  852. z := a;
  853. end
  854. else if ( count < 64 ) then
  855. begin
  856. z := ( a shr count ) or ord( ( a shl ( ( - count ) and 63 ) ) <> 0 );
  857. end
  858. else
  859. begin
  860. z := ord( a <> 0 );
  861. end;
  862. zPtr := z;
  863. end;
  864. {$if not defined(shift64ExtraRightJamming)}
  865. procedure shift64ExtraRightJamming(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
  866. overload;
  867. forward;
  868. {$endif}
  869. {*
  870. -------------------------------------------------------------------------------
  871. Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right
  872. by 32 _plus_ the number of bits given in `count'. The shifted result is
  873. at most 64 nonzero bits; these are broken into two 32-bit pieces which are
  874. stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
  875. off form a third 32-bit result as follows: The _last_ bit shifted off is
  876. the most-significant bit of the extra result, and the other 31 bits of the
  877. extra result are all zero if and only if _all_but_the_last_ bits shifted off
  878. were all zero. This extra result is stored in the location pointed to by
  879. `z2Ptr'. The value of `count' can be arbitrarily large.
  880. (This routine makes more sense if `a0', `a1', and `a2' are considered
  881. to form a fixed-point value with binary point between `a1' and `a2'. This
  882. fixed-point value is shifted right by the number of bits given in `count',
  883. and the integer part of the result is returned at the locations pointed to
  884. by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
  885. corrupted as described above, and is returned at the location pointed to by
  886. `z2Ptr'.)
  887. -------------------------------------------------------------------------------
  888. }
  889. Procedure
  890. shift64ExtraRightJamming(
  891. a0: bits32;
  892. a1: bits32;
  893. a2: bits32;
  894. count: int16;
  895. VAR z0Ptr: bits32;
  896. VAR z1Ptr: bits32;
  897. VAR z2Ptr: bits32
  898. ); overload;
  899. Var
  900. z0, z1, z2: bits32;
  901. negCount : int8;
  902. Begin
  903. negCount := ( - count ) AND 31;
  904. if ( count = 0 ) then
  905. Begin
  906. z2 := a2;
  907. z1 := a1;
  908. z0 := a0;
  909. End
  910. else
  911. Begin
  912. if ( count < 32 ) Then
  913. Begin
  914. z2 := a1 shl negCount;
  915. z1 := ( a0 shl negCount ) OR ( a1 shr count );
  916. z0 := a0 shr count;
  917. End
  918. else
  919. Begin
  920. if ( count = 32 ) then
  921. Begin
  922. z2 := a1;
  923. z1 := a0;
  924. End
  925. else
  926. Begin
  927. a2 := a2 or a1;
  928. if ( count < 64 ) then
  929. Begin
  930. z2 := a0 shl negCount;
  931. z1 := a0 shr ( count AND 31 );
  932. End
  933. else
  934. Begin
  935. if count = 64 then
  936. z2 := a0
  937. else
  938. z2 := bits32(a0 <> 0);
  939. z1 := 0;
  940. End;
  941. End;
  942. z0 := 0;
  943. End;
  944. z2 := z2 or bits32( a2 <> 0 );
  945. End;
  946. z2Ptr := z2;
  947. z1Ptr := z1;
  948. z0Ptr := z0;
  949. End;
  950. {*
  951. -------------------------------------------------------------------------------
  952. Shifts the 64-bit value formed by concatenating `a0' and `a1' left by the
  953. number of bits given in `count'. Any bits shifted off are lost. The value
  954. of `count' must be less than 32. The result is broken into two 32-bit
  955. pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  956. -------------------------------------------------------------------------------
  957. *}
  958. Procedure
  959. shortShift64Left(
  960. a0:bits32; a1:bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );
  961. Begin
  962. z1Ptr := a1 shl count;
  963. if count = 0 then
  964. z0Ptr := a0
  965. else
  966. z0Ptr := ( a0 shl count ) OR ( a1 shr ( ( - count ) AND 31 ) );
  967. End;
  968. {*
  969. -------------------------------------------------------------------------------
  970. Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' left
  971. by the number of bits given in `count'. Any bits shifted off are lost.
  972. The value of `count' must be less than 32. The result is broken into three
  973. 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
  974. `z1Ptr', and `z2Ptr'.
  975. -------------------------------------------------------------------------------
  976. *}
  977. Procedure
  978. shortShift96Left(
  979. a0: bits32;
  980. a1: bits32;
  981. a2: bits32;
  982. count: int16;
  983. VAR z0Ptr: bits32;
  984. VAR z1Ptr: bits32;
  985. VAR z2Ptr: bits32
  986. );
  987. Var
  988. z0, z1, z2: bits32;
  989. negCount: int8;
  990. Begin
  991. z2 := a2 shl count;
  992. z1 := a1 shl count;
  993. z0 := a0 shl count;
  994. if ( 0 < count ) then
  995. Begin
  996. negCount := ( ( - count ) AND 31 );
  997. z1 := z1 or (a2 shr negCount);
  998. z0 := z0 or (a1 shr negCount);
  999. End;
  1000. z2Ptr := z2;
  1001. z1Ptr := z1;
  1002. z0Ptr := z0;
  1003. End;
  1004. {*----------------------------------------------------------------------------
  1005. | Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
  1006. | number of bits given in `count'. Any bits shifted off are lost. The value
  1007. | of `count' must be less than 64. The result is broken into two 64-bit
  1008. | pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  1009. *----------------------------------------------------------------------------*}
  1010. procedure shortShift128Left(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
  1011. begin
  1012. z1Ptr := a1 shl count;
  1013. if count=0 then
  1014. z0Ptr:=a0
  1015. else
  1016. z0Ptr:=( a0 shl count ) or ( a1 shr ( ( - count ) and 63 ) );
  1017. end;
  1018. {*
  1019. -------------------------------------------------------------------------------
  1020. Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit
  1021. value formed by concatenating `b0' and `b1'. Addition is modulo 2^64, so
  1022. any carry out is lost. The result is broken into two 32-bit pieces which
  1023. are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  1024. -------------------------------------------------------------------------------
  1025. *}
  1026. Procedure
  1027. add64(
  1028. a0:bits32; a1:bits32; b0:bits32; b1:bits32; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );
  1029. Var
  1030. z1: bits32;
  1031. Begin
  1032. z1 := a1 + b1;
  1033. z1Ptr := z1;
  1034. z0Ptr := a0 + b0 + bits32( z1 < a1 );
  1035. End;
  1036. {*
  1037. -------------------------------------------------------------------------------
  1038. Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the
  1039. 96-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
  1040. modulo 2^96, so any carry out is lost. The result is broken into three
  1041. 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
  1042. `z1Ptr', and `z2Ptr'.
  1043. -------------------------------------------------------------------------------
  1044. *}
  1045. Procedure
  1046. add96(
  1047. a0: bits32;
  1048. a1: bits32;
  1049. a2: bits32;
  1050. b0: bits32;
  1051. b1: bits32;
  1052. b2: bits32;
  1053. VAR z0Ptr: bits32;
  1054. VAR z1Ptr: bits32;
  1055. VAR z2Ptr: bits32
  1056. );
  1057. var
  1058. z0, z1, z2: bits32;
  1059. carry0, carry1: int8;
  1060. Begin
  1061. z2 := a2 + b2;
  1062. carry1 := int8( z2 < a2 );
  1063. z1 := a1 + b1;
  1064. carry0 := int8( z1 < a1 );
  1065. z0 := a0 + b0;
  1066. z1 := z1 + carry1;
  1067. z0 := z0 + bits32( z1 < carry1 );
  1068. z0 := z0 + carry0;
  1069. z2Ptr := z2;
  1070. z1Ptr := z1;
  1071. z0Ptr := z0;
  1072. End;
  1073. {*----------------------------------------------------------------------------
  1074. | Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left
  1075. | by the number of bits given in `count'. Any bits shifted off are lost.
  1076. | The value of `count' must be less than 64. The result is broken into three
  1077. | 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
  1078. | `z1Ptr', and `z2Ptr'.
  1079. *----------------------------------------------------------------------------*}
  1080. procedure shortShift192Left(a0,a1,a2 : bits64;count : int16;var z0Ptr,z1Ptr,z2Ptr : bits64);
  1081. var
  1082. z0, z1, z2 : bits64;
  1083. negCount : int8;
  1084. begin
  1085. z2 := a2 shl count;
  1086. z1 := a1 shl count;
  1087. z0 := a0 shl count;
  1088. if ( 0 < count ) then
  1089. begin
  1090. negCount := ( ( - count ) and 63 );
  1091. z1 := z1 or (a2 shr negCount);
  1092. z0 := z0 or (a1 shr negCount);
  1093. end;
  1094. z2Ptr := z2;
  1095. z1Ptr := z1;
  1096. z0Ptr := z0;
  1097. end;
  1098. {*----------------------------------------------------------------------------
  1099. | Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
  1100. | value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
  1101. | any carry out is lost. The result is broken into two 64-bit pieces which
  1102. | are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  1103. *----------------------------------------------------------------------------*}
  1104. procedure add128( a0, a1, b0, b1 : bits64; var z0Ptr, z1Ptr : bits64);inline;
  1105. var
  1106. z1 : bits64;
  1107. begin
  1108. z1 := a1 + b1;
  1109. z1Ptr := z1;
  1110. z0Ptr := a0 + b0 + ord( z1 < a1 );
  1111. end;
  1112. {*----------------------------------------------------------------------------
  1113. | Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
  1114. | 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
  1115. | modulo 2^192, so any carry out is lost. The result is broken into three
  1116. | 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
  1117. | `z1Ptr', and `z2Ptr'.
  1118. *----------------------------------------------------------------------------*}
  1119. procedure add192(a0,a1,a2,b0,b1,b2: bits64; var z0Ptr,z1Ptr,z2Ptr : bits64);
  1120. var
  1121. z0, z1, z2 : bits64;
  1122. carry0, carry1 : int8;
  1123. begin
  1124. z2 := a2 + b2;
  1125. carry1 := ord( z2 < a2 );
  1126. z1 := a1 + b1;
  1127. carry0 := ord( z1 < a1 );
  1128. z0 := a0 + b0;
  1129. inc(z1, carry1);
  1130. inc(z0, ord( z1 < carry1 ));
  1131. inc(z0, carry0);
  1132. z2Ptr := z2;
  1133. z1Ptr := z1;
  1134. z0Ptr := z0;
  1135. end;
  1136. {*
  1137. -------------------------------------------------------------------------------
  1138. Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the
  1139. 64-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
  1140. 2^64, so any borrow out (carry out) is lost. The result is broken into two
  1141. 32-bit pieces which are stored at the locations pointed to by `z0Ptr' and
  1142. `z1Ptr'.
  1143. -------------------------------------------------------------------------------
  1144. *}
  1145. Procedure
  1146. sub64(
  1147. a0: bits32; a1 : bits32; b0 :bits32; b1: bits32; VAR z0Ptr:bits32; VAR z1Ptr: bits32 );
  1148. Begin
  1149. z1Ptr := a1 - b1;
  1150. z0Ptr := a0 - b0 - bits32( a1 < b1 );
  1151. End;
  1152. {*
  1153. -------------------------------------------------------------------------------
  1154. Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from
  1155. the 96-bit value formed by concatenating `a0', `a1', and `a2'. Subtraction
  1156. is modulo 2^96, so any borrow out (carry out) is lost. The result is broken
  1157. into three 32-bit pieces which are stored at the locations pointed to by
  1158. `z0Ptr', `z1Ptr', and `z2Ptr'.
  1159. -------------------------------------------------------------------------------
  1160. *}
  1161. Procedure
  1162. sub96(
  1163. a0:bits32;
  1164. a1:bits32;
  1165. a2:bits32;
  1166. b0:bits32;
  1167. b1:bits32;
  1168. b2:bits32;
  1169. VAR z0Ptr:bits32;
  1170. VAR z1Ptr:bits32;
  1171. VAR z2Ptr:bits32
  1172. );
  1173. Var
  1174. z0, z1, z2: bits32;
  1175. borrow0, borrow1: int8;
  1176. Begin
  1177. z2 := a2 - b2;
  1178. borrow1 := int8( a2 < b2 );
  1179. z1 := a1 - b1;
  1180. borrow0 := int8( a1 < b1 );
  1181. z0 := a0 - b0;
  1182. z0 := z0 - bits32( z1 < borrow1 );
  1183. z1 := z1 - borrow1;
  1184. z0 := z0 -borrow0;
  1185. z2Ptr := z2;
  1186. z1Ptr := z1;
  1187. z0Ptr := z0;
  1188. End;
  1189. {*----------------------------------------------------------------------------
  1190. | Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
  1191. | 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
  1192. | 2^128, so any borrow out (carry out) is lost. The result is broken into two
  1193. | 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
  1194. | `z1Ptr'.
  1195. *----------------------------------------------------------------------------*}
  1196. procedure sub128( a0, a1, b0, b1 : bits64; var z0Ptr, z1Ptr : bits64);
  1197. begin
  1198. z1Ptr := a1 - b1;
  1199. z0Ptr := a0 - b0 - ord( a1 < b1 );
  1200. end;
  1201. {*----------------------------------------------------------------------------
  1202. | Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
  1203. | from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
  1204. | Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
  1205. | result is broken into three 64-bit pieces which are stored at the locations
  1206. | pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
  1207. *----------------------------------------------------------------------------*}
  1208. procedure sub192(a0,a1,a2,b0,b1,b2: bits64; var z0Ptr,z1Ptr,z2Ptr : bits64);
  1209. var
  1210. z0, z1, z2 : bits64;
  1211. borrow0, borrow1 : int8;
  1212. begin
  1213. z2 := a2 - b2;
  1214. borrow1 := ord( a2 < b2 );
  1215. z1 := a1 - b1;
  1216. borrow0 := ord( a1 < b1 );
  1217. z0 := a0 - b0;
  1218. dec(z0, ord( z1 < borrow1 ));
  1219. dec(z1, borrow1);
  1220. dec(z0, borrow0);
  1221. z2Ptr := z2;
  1222. z1Ptr := z1;
  1223. z0Ptr := z0;
  1224. end;
  1225. {*
  1226. -------------------------------------------------------------------------------
  1227. Multiplies `a' by `b' to obtain a 64-bit product. The product is broken
  1228. into two 32-bit pieces which are stored at the locations pointed to by
  1229. `z0Ptr' and `z1Ptr'.
  1230. -------------------------------------------------------------------------------
  1231. *}
  1232. Procedure mul32To64( a:bits32; b:bits32; VAR z0Ptr: bits32; VAR z1Ptr
  1233. :bits32 );
  1234. Var
  1235. aHigh, aLow, bHigh, bLow: bits16;
  1236. z0, zMiddleA, zMiddleB, z1: bits32;
  1237. Begin
  1238. aLow := a and $ffff;
  1239. aHigh := a shr 16;
  1240. bLow := b and $ffff;
  1241. bHigh := b shr 16;
  1242. z1 := ( bits32( aLow) ) * bLow;
  1243. zMiddleA := ( bits32 (aLow) ) * bHigh;
  1244. zMiddleB := ( bits32 (aHigh) ) * bLow;
  1245. z0 := ( bits32 (aHigh) ) * bHigh;
  1246. zMiddleA := zMiddleA + zMiddleB;
  1247. z0 := z0 + ( ( bits32 ( zMiddleA < zMiddleB ) ) shl 16 ) + ( zMiddleA shr 16 );
  1248. zMiddleA := zmiddleA shl 16;
  1249. z1 := z1 + zMiddleA;
  1250. z0 := z0 + bits32( z1 < zMiddleA );
  1251. z1Ptr := z1;
  1252. z0Ptr := z0;
  1253. End;
  1254. {*
  1255. -------------------------------------------------------------------------------
  1256. Multiplies the 64-bit value formed by concatenating `a0' and `a1' by `b'
  1257. to obtain a 96-bit product. The product is broken into three 32-bit pieces
  1258. which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
  1259. `z2Ptr'.
  1260. -------------------------------------------------------------------------------
  1261. *}
  1262. Procedure
  1263. mul64By32To96(
  1264. a0:bits32;
  1265. a1:bits32;
  1266. b:bits32;
  1267. VAR z0Ptr:bits32;
  1268. VAR z1Ptr:bits32;
  1269. VAR z2Ptr:bits32
  1270. );
  1271. Var
  1272. z0, z1, z2, more1: bits32;
  1273. Begin
  1274. mul32To64( a1, b, z1, z2 );
  1275. mul32To64( a0, b, z0, more1 );
  1276. add64( z0, more1, 0, z1, z0, z1 );
  1277. z2Ptr := z2;
  1278. z1Ptr := z1;
  1279. z0Ptr := z0;
  1280. End;
  1281. {*
  1282. -------------------------------------------------------------------------------
  1283. Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the
  1284. 64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit
  1285. product. The product is broken into four 32-bit pieces which are stored at
  1286. the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
  1287. -------------------------------------------------------------------------------
  1288. *}
  1289. Procedure
  1290. mul64To128(
  1291. a0:bits32;
  1292. a1:bits32;
  1293. b0:bits32;
  1294. b1:bits32;
  1295. VAR z0Ptr:bits32;
  1296. VAR z1Ptr:bits32;
  1297. VAR z2Ptr:bits32;
  1298. VAR z3Ptr:bits32
  1299. );
  1300. Var
  1301. z0, z1, z2, z3: bits32;
  1302. more1, more2: bits32;
  1303. Begin
  1304. mul32To64( a1, b1, z2, z3 );
  1305. mul32To64( a1, b0, z1, more2 );
  1306. add64( z1, more2, 0, z2, z1, z2 );
  1307. mul32To64( a0, b0, z0, more1 );
  1308. add64( z0, more1, 0, z1, z0, z1 );
  1309. mul32To64( a0, b1, more1, more2 );
  1310. add64( more1, more2, 0, z2, more1, z2 );
  1311. add64( z0, z1, 0, more1, z0, z1 );
  1312. z3Ptr := z3;
  1313. z2Ptr := z2;
  1314. z1Ptr := z1;
  1315. z0Ptr := z0;
  1316. End;
  1317. {*----------------------------------------------------------------------------
  1318. | Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
  1319. | into two 64-bit pieces which are stored at the locations pointed to by
  1320. | `z0Ptr' and `z1Ptr'.
  1321. *----------------------------------------------------------------------------*}
  1322. procedure mul64To128( a, b : bits64; var z0Ptr, z1Ptr : bits64);
  1323. var
  1324. aHigh, aLow, bHigh, bLow : bits32;
  1325. z0, zMiddleA, zMiddleB, z1 : bits64;
  1326. begin
  1327. aLow := a;
  1328. aHigh := a shr 32;
  1329. bLow := b;
  1330. bHigh := b shr 32;
  1331. z1 := ( bits64(aLow) ) * bLow;
  1332. zMiddleA := ( bits64( aLow )) * bHigh;
  1333. zMiddleB := ( bits64( aHigh )) * bLow;
  1334. z0 := ( bits64(aHigh) ) * bHigh;
  1335. inc(zMiddleA, zMiddleB);
  1336. inc(z0 ,( ( bits64( zMiddleA < zMiddleB ) ) shl 32 ) + ( zMiddleA shr 32 ));
  1337. zMiddleA := zMiddleA shl 32;
  1338. inc(z1, zMiddleA);
  1339. inc(z0, ord( z1 < zMiddleA ));
  1340. z1Ptr := z1;
  1341. z0Ptr := z0;
  1342. end;
  1343. {*----------------------------------------------------------------------------
  1344. | Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
  1345. | 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
  1346. | product. The product is broken into four 64-bit pieces which are stored at
  1347. | the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
  1348. *----------------------------------------------------------------------------*}
  1349. procedure mul128To256(a0,a1,b0,b1 : bits64;var z0Ptr,z1Ptr,z2Ptr,z3Ptr : bits64);
  1350. var
  1351. z0,z1,z2,z3,more1,more2 : bits64;
  1352. begin
  1353. mul64To128( a1, b1, z2, z3 );
  1354. mul64To128( a1, b0, z1, more2 );
  1355. add128( z1, more2, 0, z2, z1, z2 );
  1356. mul64To128( a0, b0, z0, more1 );
  1357. add128( z0, more1, 0, z1, z0, z1 );
  1358. mul64To128( a0, b1, more1, more2 );
  1359. add128( more1, more2, 0, z2, more1, z2 );
  1360. add128( z0, z1, 0, more1, z0, z1 );
  1361. z3Ptr := z3;
  1362. z2Ptr := z2;
  1363. z1Ptr := z1;
  1364. z0Ptr := z0;
  1365. end;
  1366. {*----------------------------------------------------------------------------
  1367. | Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
  1368. | `b' to obtain a 192-bit product. The product is broken into three 64-bit
  1369. | pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
  1370. | `z2Ptr'.
  1371. *----------------------------------------------------------------------------*}
  1372. procedure mul128By64To192(a0,a1,b : bits64;var z0Ptr,z1Ptr,z2Ptr : bits64);
  1373. var
  1374. z0, z1, z2, more1 : bits64;
  1375. begin
  1376. mul64To128( a1, b, z1, z2 );
  1377. mul64To128( a0, b, z0, more1 );
  1378. add128( z0, more1, 0, z1, z0, z1 );
  1379. z2Ptr := z2;
  1380. z1Ptr := z1;
  1381. z0Ptr := z0;
  1382. end;
  1383. {*----------------------------------------------------------------------------
  1384. | Returns an approximation to the 64-bit integer quotient obtained by dividing
  1385. | `b' into the 128-bit value formed by concatenating `a0' and `a1'. The
  1386. | divisor `b' must be at least 2^63. If q is the exact quotient truncated
  1387. | toward zero, the approximation returned lies between q and q + 2 inclusive.
  1388. | If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
  1389. | unsigned integer is returned.
  1390. *----------------------------------------------------------------------------*}
  1391. Function estimateDiv128To64( a0:bits64; a1: bits64; b:bits64): bits64;
  1392. var
  1393. b0, b1, rem0, rem1, term0, term1, z : bits64;
  1394. begin
  1395. if ( b <= a0 ) then
  1396. begin
  1397. result:=qword( $FFFFFFFFFFFFFFFF );
  1398. exit;
  1399. end;
  1400. b0 := b shr 32;
  1401. if ( b0 shl 32 <= a0 ) then
  1402. z:=qword( $FFFFFFFF00000000 )
  1403. else
  1404. z:=( a0 div b0 ) shl 32;
  1405. mul64To128( b, z, term0, term1 );
  1406. sub128( a0, a1, term0, term1, rem0, rem1 );
  1407. while ( ( sbits64(rem0) ) < 0 ) do begin
  1408. dec(z,qword( $100000000 ));
  1409. b1 := b shl 32;
  1410. add128( rem0, rem1, b0, b1, rem0, rem1 );
  1411. end;
  1412. rem0 := ( rem0 shl 32 ) or ( rem1 shr 32 );
  1413. if ( b0 shl 32 <= rem0 ) then
  1414. z:=z or $FFFFFFFF
  1415. else
  1416. z:=z or rem0 div b0;
  1417. result:=z;
  1418. end;
  1419. {*
  1420. -------------------------------------------------------------------------------
  1421. Returns an approximation to the 32-bit integer quotient obtained by dividing
  1422. `b' into the 64-bit value formed by concatenating `a0' and `a1'. The
  1423. divisor `b' must be at least 2^31. If q is the exact quotient truncated
  1424. toward zero, the approximation returned lies between q and q + 2 inclusive.
  1425. If the exact quotient q is larger than 32 bits, the maximum positive 32-bit
  1426. unsigned integer is returned.
  1427. -------------------------------------------------------------------------------
  1428. *}
  1429. Function estimateDiv64To32( a0:bits32; a1: bits32; b:bits32): bits32;
  1430. Var
  1431. b0, b1: bits32;
  1432. rem0, rem1, term0, term1: bits32;
  1433. z: bits32;
  1434. Begin
  1435. if ( b <= a0 ) then
  1436. Begin
  1437. estimateDiv64To32 := $FFFFFFFF;
  1438. exit;
  1439. End;
  1440. b0 := b shr 16;
  1441. if ( b0 shl 16 <= a0 ) then
  1442. z:= $FFFF0000
  1443. else
  1444. z:= ( a0 div b0 ) shl 16;
  1445. mul32To64( b, z, term0, term1 );
  1446. sub64( a0, a1, term0, term1, rem0, rem1 );
  1447. while ( ( sbits32 (rem0) ) < 0 ) do
  1448. Begin
  1449. z := z - $10000;
  1450. b1 := b shl 16;
  1451. add64( rem0, rem1, b0, b1, rem0, rem1 );
  1452. End;
  1453. rem0 := ( rem0 shl 16 ) OR ( rem1 shr 16 );
  1454. if ( b0 shl 16 <= rem0 ) then
  1455. z := z or $FFFF
  1456. else
  1457. z := z or (rem0 div b0);
  1458. estimateDiv64To32 := z;
  1459. End;
  1460. {*
  1461. -------------------------------------------------------------------------------
  1462. Returns an approximation to the square root of the 32-bit significand given
  1463. by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
  1464. `aExp' (the least significant bit) is 1, the integer returned approximates
  1465. 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
  1466. is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
  1467. case, the approximation returned lies strictly within +/-2 of the exact
  1468. value.
  1469. -------------------------------------------------------------------------------
  1470. *}
  1471. Function estimateSqrt32( aExp: int16; a: bits32 ): bits32;
  1472. const sqrtOddAdjustments: array[0..15] of bits16 = (
  1473. $0004, $0022, $005D, $00B1, $011D, $019F, $0236, $02E0,
  1474. $039C, $0468, $0545, $0631, $072B, $0832, $0946, $0A67
  1475. );
  1476. const sqrtEvenAdjustments: array[0..15] of bits16 = (
  1477. $0A2D, $08AF, $075A, $0629, $051A, $0429, $0356, $029E,
  1478. $0200, $0179, $0109, $00AF, $0068, $0034, $0012, $0002
  1479. );
  1480. Var
  1481. index: int8;
  1482. z: bits32;
  1483. Begin
  1484. index := ( a shr 27 ) AND 15;
  1485. if ( aExp AND 1 ) <> 0 then
  1486. Begin
  1487. z := $4000 + ( a shr 17 ) - sqrtOddAdjustments[ index ];
  1488. z := ( ( a div z ) shl 14 ) + ( z shl 15 );
  1489. a := a shr 1;
  1490. End
  1491. else
  1492. Begin
  1493. z := $8000 + ( a shr 17 ) - sqrtEvenAdjustments[ index ];
  1494. z := a div z + z;
  1495. if ( $20000 <= z ) then
  1496. z := $FFFF8000
  1497. else
  1498. z := ( z shl 15 );
  1499. if ( z <= a ) then
  1500. Begin
  1501. estimateSqrt32 := bits32 ( ( sbits32 (a )) shr 1 );
  1502. exit;
  1503. End;
  1504. End;
  1505. estimateSqrt32 := ( ( estimateDiv64To32( a, 0, z ) ) shr 1 ) + ( z shr 1 );
  1506. End;
  1507. {*
  1508. -------------------------------------------------------------------------------
  1509. Returns the number of leading 0 bits before the most-significant 1 bit of
  1510. `a'. If `a' is zero, 32 is returned.
  1511. -------------------------------------------------------------------------------
  1512. *}
  1513. Function countLeadingZeros32( a:bits32 ): int8;
  1514. const countLeadingZerosHigh:array[0..255] of int8 = (
  1515. 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
  1516. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1517. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  1518. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  1519. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1520. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1521. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1522. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1523. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1524. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1525. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1526. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1527. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1528. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1529. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1530. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  1531. );
  1532. Var
  1533. shiftCount: int8;
  1534. Begin
  1535. shiftCount := 0;
  1536. if ( a < $10000 ) then
  1537. Begin
  1538. shiftCount := shiftcount + 16;
  1539. a := a shl 16;
  1540. End;
  1541. if ( a < $1000000 ) then
  1542. Begin
  1543. shiftCount := shiftcount + 8;
  1544. a := a shl 8;
  1545. end;
  1546. shiftCount := shiftcount + countLeadingZerosHigh[ a shr 24 ];
  1547. countLeadingZeros32:= shiftCount;
  1548. End;
  1549. {*----------------------------------------------------------------------------
  1550. | Returns the number of leading 0 bits before the most-significant 1 bit of
  1551. | `a'. If `a' is zero, 64 is returned.
  1552. *----------------------------------------------------------------------------*}
  1553. function countLeadingZeros64( a : bits64): int8;
  1554. var
  1555. shiftcount : int8;
  1556. Begin
  1557. shiftCount := 0;
  1558. if ( a < bits64(bits64(1) shl 32 )) then
  1559. shiftCount := shiftcount + 32
  1560. else
  1561. a := a shr 32;
  1562. shiftCount := shiftCount + countLeadingZeros32( a );
  1563. countLeadingZeros64:= shiftCount;
  1564. End;
  1565. {*
  1566. -------------------------------------------------------------------------------
  1567. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
  1568. than or equal to the 64-bit value formed by concatenating `b0' and `b1'.
  1569. Otherwise, returns 0.
  1570. -------------------------------------------------------------------------------
  1571. *}
  1572. Function le64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
  1573. Begin
  1574. le64:= flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 <= b1 ) );
  1575. End;
  1576. {*
  1577. -------------------------------------------------------------------------------
  1578. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
  1579. than the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1580. returns 0.
  1581. -------------------------------------------------------------------------------
  1582. *}
  1583. Function lt64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
  1584. Begin
  1585. lt64 := flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 < b1 ) );
  1586. End;
  1587. const
  1588. float128_default_nan_high = qword($FFFFFFFFFFFFFFFF);
  1589. float128_default_nan_low = qword($FFFFFFFFFFFFFFFF);
  1590. (*****************************************************************************)
  1591. (* End Low-Level arithmetic *)
  1592. (*****************************************************************************)
  1593. {*
  1594. -------------------------------------------------------------------------------
  1595. Functions and definitions to determine: (1) whether tininess for underflow
  1596. is detected before or after rounding by default, (2) what (if anything)
  1597. happens when exceptions are raised, (3) how signaling NaNs are distinguished
  1598. from quiet NaNs, (4) the default generated quiet NaNs, and (4) how NaNs
  1599. are propagated from function inputs to output. These details are ENDIAN
  1600. specific
  1601. -------------------------------------------------------------------------------
  1602. *}
  1603. {$IFDEF ENDIAN_LITTLE}
  1604. {*
  1605. -------------------------------------------------------------------------------
  1606. Internal canonical NaN format.
  1607. -------------------------------------------------------------------------------
  1608. *}
  1609. TYPE
  1610. commonNaNT = record
  1611. high, low : bits32;
  1612. sign: flag;
  1613. end;
  1614. {*
  1615. -------------------------------------------------------------------------------
  1616. The pattern for a default generated single-precision NaN.
  1617. -------------------------------------------------------------------------------
  1618. *}
  1619. const float32_default_nan = $FFC00000;
  1620. {*
  1621. -------------------------------------------------------------------------------
  1622. Returns 1 if the single-precision floating-point value `a' is a NaN;
  1623. otherwise returns 0.
  1624. -------------------------------------------------------------------------------
  1625. *}
  1626. Function float32_is_nan( a : float32 ): flag;
  1627. Begin
  1628. float32_is_nan:= flag( $FF000000 < bits32 ( a shl 1 ) );
  1629. End;
  1630. {*
  1631. -------------------------------------------------------------------------------
  1632. Returns 1 if the single-precision floating-point value `a' is a signaling
  1633. NaN; otherwise returns 0.
  1634. -------------------------------------------------------------------------------
  1635. *}
  1636. Function float32_is_signaling_nan( a : float32 ): flag;
  1637. Begin
  1638. float32_is_signaling_nan := flag
  1639. (( ( ( a shr 22 ) and $1FF ) = $1FE ) and (( a and $003FFFFF )<>0));
  1640. End;
  1641. {*
  1642. -------------------------------------------------------------------------------
  1643. Returns the result of converting the single-precision floating-point NaN
  1644. `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1645. exception is raised.
  1646. -------------------------------------------------------------------------------
  1647. *}
  1648. Procedure float32ToCommonNaN( a: float32; VAR c:commonNaNT );
  1649. var
  1650. z : commonNaNT ;
  1651. Begin
  1652. if ( float32_is_signaling_nan( a ) <> 0) then
  1653. float_raise( float_flag_invalid );
  1654. z.sign := a shr 31;
  1655. z.low := 0;
  1656. z.high := a shl 9;
  1657. c := z;
  1658. End;
  1659. {*
  1660. -------------------------------------------------------------------------------
  1661. Returns the result of converting the canonical NaN `a' to the single-
  1662. precision floating-point format.
  1663. -------------------------------------------------------------------------------
  1664. *}
  1665. Function commonNaNToFloat32( a : commonNaNT ): float32;
  1666. Begin
  1667. commonNaNToFloat32 := ( ( bits32 (a.sign) ) shl 31 ) or $7FC00000 or ( a.high shr 9 );
  1668. End;
  1669. {*
  1670. -------------------------------------------------------------------------------
  1671. Takes two single-precision floating-point values `a' and `b', one of which
  1672. is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1673. signaling NaN, the invalid exception is raised.
  1674. -------------------------------------------------------------------------------
  1675. *}
  1676. Function propagateFloat32NaN( a : float32 ; b: float32 ): float32;
  1677. Var
  1678. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1679. label returnLargerSignificand;
  1680. Begin
  1681. aIsNaN := float32_is_nan( a );
  1682. aIsSignalingNaN := float32_is_signaling_nan( a );
  1683. bIsNaN := float32_is_nan( b );
  1684. bIsSignalingNaN := float32_is_signaling_nan( b );
  1685. a := a or $00400000;
  1686. b := b or $00400000;
  1687. if ( aIsSignalingNaN or bIsSignalingNaN ) <> 0 then
  1688. float_raise( float_flag_invalid );
  1689. if ( aIsSignalingNaN )<> 0 then
  1690. Begin
  1691. if ( bIsSignalingNaN ) <> 0 then
  1692. goto returnLargerSignificand;
  1693. if bIsNan <> 0 then
  1694. propagateFloat32NaN := b
  1695. else
  1696. propagateFloat32NaN := a;
  1697. exit;
  1698. End
  1699. else if ( aIsNaN <> 0) then
  1700. Begin
  1701. if ( bIsSignalingNaN or not bIsNaN )<> 0 then
  1702. Begin
  1703. propagateFloat32NaN := a;
  1704. exit;
  1705. End;
  1706. returnLargerSignificand:
  1707. if ( bits32 ( a shl 1 ) < bits32 ( b shl 1 ) ) then
  1708. Begin
  1709. propagateFloat32NaN := b;
  1710. exit;
  1711. End;
  1712. if ( bits32 ( b shl 1 ) < bits32 ( a shl 1 ) ) then
  1713. Begin
  1714. propagateFloat32NaN := a;
  1715. End;
  1716. if a < b then
  1717. propagateFloat32NaN := a
  1718. else
  1719. propagateFloat32NaN := b;
  1720. exit;
  1721. End
  1722. else
  1723. Begin
  1724. propagateFloat32NaN := b;
  1725. exit;
  1726. End;
  1727. End;
  1728. {*
  1729. -------------------------------------------------------------------------------
  1730. The pattern for a default generated double-precision NaN. The `high' and
  1731. `low' values hold the most- and least-significant bits, respectively.
  1732. -------------------------------------------------------------------------------
  1733. *}
  1734. const
  1735. float64_default_nan_high = $FFF80000;
  1736. float64_default_nan_low = $00000000;
  1737. {*
  1738. -------------------------------------------------------------------------------
  1739. Returns 1 if the double-precision floating-point value `a' is a NaN;
  1740. otherwise returns 0.
  1741. -------------------------------------------------------------------------------
  1742. *}
  1743. Function float64_is_nan( a : float64 ) : flag;
  1744. Begin
  1745. float64_is_nan :=
  1746. flag(( $FFE00000 <= bits32 ( a.high shl 1 ) )
  1747. and (( a.low or ( a.high and $000FFFFF ) )<>0));
  1748. End;
  1749. {*
  1750. -------------------------------------------------------------------------------
  1751. Returns 1 if the double-precision floating-point value `a' is a signaling
  1752. NaN; otherwise returns 0.
  1753. -------------------------------------------------------------------------------
  1754. *}
  1755. Function float64_is_signaling_nan( a : float64 ): flag;
  1756. Begin
  1757. float64_is_signaling_nan :=
  1758. flag( ( ( a.high shr 19 ) and $FFF ) = $FFE )
  1759. and ( a.low or ( a.high and $0007FFFF ) );
  1760. End;
  1761. {*
  1762. -------------------------------------------------------------------------------
  1763. Returns the result of converting the double-precision floating-point NaN
  1764. `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1765. exception is raised.
  1766. -------------------------------------------------------------------------------
  1767. *}
  1768. Procedure float64ToCommonNaN( a : float64; VAR c:commonNaNT );
  1769. Var
  1770. z : commonNaNT;
  1771. Begin
  1772. if ( float64_is_signaling_nan( a )<>0 ) then
  1773. float_raise( float_flag_invalid );
  1774. z.sign := a.high shr 31;
  1775. shortShift64Left( a.high, a.low, 12, z.high, z.low );
  1776. c := z;
  1777. End;
  1778. function float64ToCommonNaN( a : float64 ) : commonNaNT;
  1779. Var
  1780. z : commonNaNT;
  1781. Begin
  1782. if ( float64_is_signaling_nan( a )<>0 ) then
  1783. float_raise( float_flag_invalid );
  1784. z.sign := a.high shr 31;
  1785. shortShift64Left( a.high, a.low, 12, z.high, z.low );
  1786. result := z;
  1787. End;
  1788. {*
  1789. -------------------------------------------------------------------------------
  1790. Returns the result of converting the canonical NaN `a' to the double-
  1791. precision floating-point format.
  1792. -------------------------------------------------------------------------------
  1793. *}
  1794. Procedure commonNaNToFloat64( a : commonNaNT; VAR c: float64 );
  1795. Var
  1796. z: float64;
  1797. Begin
  1798. shift64Right( a.high, a.low, 12, z.high, z.low );
  1799. z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;
  1800. c := z;
  1801. End;
  1802. {*
  1803. -------------------------------------------------------------------------------
  1804. Takes two double-precision floating-point values `a' and `b', one of which
  1805. is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1806. signaling NaN, the invalid exception is raised.
  1807. -------------------------------------------------------------------------------
  1808. *}
  1809. Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );
  1810. Var
  1811. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1812. label returnLargerSignificand;
  1813. Begin
  1814. aIsNaN := float64_is_nan( a );
  1815. aIsSignalingNaN := float64_is_signaling_nan( a );
  1816. bIsNaN := float64_is_nan( b );
  1817. bIsSignalingNaN := float64_is_signaling_nan( b );
  1818. a.high := a.high or $00080000;
  1819. b.high := b.high or $00080000;
  1820. if ( aIsSignalingNaN or bIsSignalingNaN )<> 0 then
  1821. float_raise( float_flag_invalid );
  1822. if ( aIsSignalingNaN )<>0 then
  1823. Begin
  1824. if ( bIsSignalingNaN )<>0 then
  1825. goto returnLargerSignificand;
  1826. if bIsNan <> 0 then
  1827. c := b
  1828. else
  1829. c := a;
  1830. exit;
  1831. End
  1832. else if ( aIsNaN )<> 0 then
  1833. Begin
  1834. if ( bIsSignalingNaN or not bIsNaN ) <> 0 then
  1835. Begin
  1836. c := a;
  1837. exit;
  1838. End;
  1839. returnLargerSignificand:
  1840. if ( lt64( a.high shl 1, a.low, b.high shl 1, b.low ) ) <> 0 then
  1841. Begin
  1842. c := b;
  1843. exit;
  1844. End;
  1845. if ( lt64( b.high shl 1, b.low, a.high shl 1, a.low ) ) <> 0 then
  1846. Begin
  1847. c := a;
  1848. exit;
  1849. End;
  1850. if a.high < b.high then
  1851. c := a
  1852. else
  1853. c := b;
  1854. exit;
  1855. End
  1856. else
  1857. Begin
  1858. c := b;
  1859. exit;
  1860. End;
  1861. End;
  1862. {*----------------------------------------------------------------------------
  1863. | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
  1864. | than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1865. | returns 0.
  1866. *----------------------------------------------------------------------------*}
  1867. function lt128(a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
  1868. begin
  1869. result := ord(( a0 < b0 ) or ( ( a0 = b0 ) and ( a1 < b1 ) ));
  1870. end;
  1871. {*----------------------------------------------------------------------------
  1872. | Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
  1873. | otherwise returns 0.
  1874. *----------------------------------------------------------------------------*}
  1875. function float128_is_nan( a : float128): flag;
  1876. begin
  1877. result:= ord(( bits64( $FFFE000000000000 ) <= bits64( a.high shl 1 ) )
  1878. and ( (a.low<>0) or (( a.high and int64( $0000FFFFFFFFFFFF ) )<>0 ) ));
  1879. end;
  1880. {*----------------------------------------------------------------------------
  1881. | Returns 1 if the quadruple-precision floating-point value `a' is a
  1882. | signaling NaN; otherwise returns 0.
  1883. *----------------------------------------------------------------------------*}
  1884. function float128_is_signaling_nan( a : float128): flag;
  1885. begin
  1886. result:=ord(( ( ( a.high shr 47 ) and $FFFF ) = $FFFE ) and
  1887. ( (a.low<>0) or (( a.high and int64( $00007FFFFFFFFFFF ) )<>0) ));
  1888. end;
  1889. {*----------------------------------------------------------------------------
  1890. | Returns the result of converting the quadruple-precision floating-point NaN
  1891. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1892. | exception is raised.
  1893. *----------------------------------------------------------------------------*}
  1894. function float128ToCommonNaN( a : float128): commonNaNT;
  1895. var
  1896. z: commonNaNT;
  1897. qhigh,qlow : qword;
  1898. begin
  1899. if ( float128_is_signaling_nan( a )<>0) then
  1900. float_raise( float_flag_invalid );
  1901. z.sign := a.high shr 63;
  1902. shortShift128Left( a.high, a.low, 16, qhigh, qlow );
  1903. z.high:=qhigh shr 32;
  1904. z.low:=qhigh and $ffffffff;
  1905. result:=z;
  1906. end;
  1907. {*----------------------------------------------------------------------------
  1908. | Returns the result of converting the canonical NaN `a' to the quadruple-
  1909. | precision floating-point format.
  1910. *----------------------------------------------------------------------------*}
  1911. function commonNaNToFloat128( a : commonNaNT): float128;
  1912. var
  1913. z: float128;
  1914. begin
  1915. shift128Right( a.high, a.low, 16, z.high, z.low );
  1916. z.high := z.high or ( ( bits64(a.sign) ) shl 63 ) or int64( $7FFF800000000000 );
  1917. result:=z;
  1918. end;
  1919. {*----------------------------------------------------------------------------
  1920. | Takes two quadruple-precision floating-point values `a' and `b', one of
  1921. | which is a NaN, and returns the appropriate NaN result. If either `a' or
  1922. | `b' is a signaling NaN, the invalid exception is raised.
  1923. *----------------------------------------------------------------------------*}
  1924. function propagateFloat128NaN( a: float128; b : float128): float128;
  1925. var
  1926. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1927. label
  1928. returnLargerSignificand;
  1929. begin
  1930. aIsNaN := float128_is_nan( a );
  1931. aIsSignalingNaN := float128_is_signaling_nan( a );
  1932. bIsNaN := float128_is_nan( b );
  1933. bIsSignalingNaN := float128_is_signaling_nan( b );
  1934. a.high := a.high or int64( $0000800000000000 );
  1935. b.high := b.high or int64( $0000800000000000 );
  1936. if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then
  1937. float_raise( float_flag_invalid );
  1938. if ( aIsSignalingNaN )<>0 then
  1939. begin
  1940. if ( bIsSignalingNaN )<>0 then
  1941. goto returnLargerSignificand;
  1942. if bIsNaN<>0 then
  1943. result := b
  1944. else
  1945. result := a;
  1946. exit;
  1947. end
  1948. else if ( aIsNaN )<>0 then
  1949. begin
  1950. if ( bIsSignalingNaN or not( bIsNaN) )<>0 then
  1951. begin
  1952. result := a;
  1953. exit;
  1954. end;
  1955. returnLargerSignificand:
  1956. if ( lt128( a.high shl 1, a.low, b.high shl 1, b.low ) )<>0 then
  1957. begin
  1958. result := b;
  1959. exit;
  1960. end;
  1961. if ( lt128( b.high shl 1, b.low, a.high shl 1, a.low ) )<>0 then
  1962. begin
  1963. result := a;
  1964. exit
  1965. end;
  1966. if ( a.high < b.high ) then
  1967. result := a
  1968. else
  1969. result := b;
  1970. exit;
  1971. end
  1972. else
  1973. result:=b;
  1974. end;
  1975. {$ELSE}
  1976. { Big endian code }
  1977. (*----------------------------------------------------------------------------
  1978. | Internal canonical NaN format.
  1979. *----------------------------------------------------------------------------*)
  1980. type
  1981. commonNANT = record
  1982. high, low : bits32;
  1983. sign : flag;
  1984. end;
  1985. (*----------------------------------------------------------------------------
  1986. | The pattern for a default generated single-precision NaN.
  1987. *----------------------------------------------------------------------------*)
  1988. const float32_default_nan = $7FFFFFFF;
  1989. (*----------------------------------------------------------------------------
  1990. | Returns 1 if the single-precision floating-point value `a' is a NaN;
  1991. | otherwise returns 0.
  1992. *----------------------------------------------------------------------------*)
  1993. function float32_is_nan(a: float32): flag;
  1994. begin
  1995. float32_is_nan := flag( $FF000000 < bits32( a shl 1 ) );
  1996. end;
  1997. (*----------------------------------------------------------------------------
  1998. | Returns 1 if the single-precision floating-point value `a' is a signaling
  1999. | NaN; otherwise returns 0.
  2000. *----------------------------------------------------------------------------*)
  2001. function float32_is_signaling_nan(a: float32):flag;
  2002. begin
  2003. float32_is_signaling_nan := flag( ( ( a shr 22 ) and $1FF ) = $1FE ) and flag( boolean((a and $003FFFFF)<>0) );
  2004. end;
  2005. (*----------------------------------------------------------------------------
  2006. | Returns the result of converting the single-precision floating-point NaN
  2007. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  2008. | exception is raised.
  2009. *----------------------------------------------------------------------------*)
  2010. Procedure float32ToCommonNaN( a: float32; VAR c:commonNaNT );
  2011. var
  2012. z: commonNANT;
  2013. begin
  2014. if float32_is_signaling_nan(a)<>0 then
  2015. float_raise(float_flag_invalid);
  2016. z.sign := a shr 31;
  2017. z.low := 0;
  2018. z.high := a shl 9;
  2019. c:=z;
  2020. end;
  2021. (*----------------------------------------------------------------------------
  2022. | Returns the result of converting the canonical NaN `a' to the single-
  2023. | precision floating-point format.
  2024. *----------------------------------------------------------------------------*)
  2025. function CommonNanToFloat32(a : CommonNaNT): float32;
  2026. begin
  2027. CommonNanToFloat32:= ( ( bits32( a.sign )) shl 31 ) OR $7FC00000 OR ( a.high shr 9 );
  2028. end;
  2029. (*----------------------------------------------------------------------------
  2030. | Takes two single-precision floating-point values `a' and `b', one of which
  2031. | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  2032. | signaling NaN, the invalid exception is raised.
  2033. *----------------------------------------------------------------------------*)
  2034. function propagateFloat32NaN( a: float32 ; b: float32): float32;
  2035. var
  2036. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  2037. begin
  2038. aIsNaN := float32_is_nan( a );
  2039. aIsSignalingNaN := float32_is_signaling_nan( a );
  2040. bIsNaN := float32_is_nan( b );
  2041. bIsSignalingNaN := float32_is_signaling_nan( b );
  2042. a := a or $00400000;
  2043. b := b or $00400000;
  2044. if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then
  2045. float_raise( float_flag_invalid );
  2046. if bIsSignalingNaN<>0 then
  2047. propagateFloat32Nan := b
  2048. else if aIsSignalingNan<>0 then
  2049. propagateFloat32Nan := a
  2050. else if bIsNan<>0 then
  2051. propagateFloat32Nan := b
  2052. else
  2053. propagateFloat32Nan := a;
  2054. end;
  2055. (*----------------------------------------------------------------------------
  2056. | The pattern for a default generated double-precision NaN. The `high' and
  2057. | `low' values hold the most- and least-significant bits, respectively.
  2058. *----------------------------------------------------------------------------*)
  2059. const
  2060. float64_default_nan_high = $7FFFFFFF;
  2061. float64_default_nan_low = $FFFFFFFF;
  2062. (*----------------------------------------------------------------------------
  2063. | Returns 1 if the double-precision floating-point value `a' is a NaN;
  2064. | otherwise returns 0.
  2065. *----------------------------------------------------------------------------*)
  2066. function float64_is_nan(a: float64): flag;
  2067. begin
  2068. float64_is_nan := flag (
  2069. ( $FFE00000 <= bits32 ( a.high shl 1 ) )
  2070. and ( (a.low<>0) or (( a.high and $000FFFFF )<>0) ));
  2071. end;
  2072. (*----------------------------------------------------------------------------
  2073. | Returns 1 if the double-precision floating-point value `a' is a signaling
  2074. | NaN; otherwise returns 0.
  2075. *----------------------------------------------------------------------------*)
  2076. function float64_is_signaling_nan( a:float64): flag;
  2077. begin
  2078. float64_is_signaling_nan := flag(
  2079. ( ( ( a.high shr 19 ) and $FFF ) = $FFE )
  2080. and ( (a.low<>0) or ( ( a.high and $0007FFFF )<>0) ));
  2081. end;
  2082. (*----------------------------------------------------------------------------
  2083. | Returns the result of converting the double-precision floating-point NaN
  2084. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  2085. | exception is raised.
  2086. *----------------------------------------------------------------------------*)
  2087. Procedure float64ToCommonNaN( a : float64; VAR c:commonNaNT );
  2088. var
  2089. z : commonNaNT;
  2090. begin
  2091. if ( float64_is_signaling_nan( a )<>0 ) then
  2092. float_raise( float_flag_invalid );
  2093. z.sign := a.high shr 31;
  2094. shortShift64Left( a.high, a.low, 12, z.high, z.low );
  2095. c:=z;
  2096. end;
  2097. (*----------------------------------------------------------------------------
  2098. | Returns the result of converting the canonical NaN `a' to the double-
  2099. | precision floating-point format.
  2100. *----------------------------------------------------------------------------*)
  2101. Procedure commonNaNToFloat64( a : commonNaNT; VAR c: float64 );
  2102. var
  2103. z: float64;
  2104. begin
  2105. shift64Right( a.high, a.low, 12, z.high, z.low );
  2106. z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;
  2107. c:=z;
  2108. end;
  2109. (*----------------------------------------------------------------------------
  2110. | Takes two double-precision floating-point values `a' and `b', one of which
  2111. | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  2112. | signaling NaN, the invalid exception is raised.
  2113. *----------------------------------------------------------------------------*)
  2114. Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );
  2115. var
  2116. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN : flag;
  2117. begin
  2118. aIsNaN := float64_is_nan( a );
  2119. aIsSignalingNaN := float64_is_signaling_nan( a );
  2120. bIsNaN := float64_is_nan( b );
  2121. bIsSignalingNaN := float64_is_signaling_nan( b );
  2122. a.high := a.high or $00080000;
  2123. b.high := b.high or $00080000;
  2124. if ( (aIsSignalingNaN<>0) or (bIsSignalingNaN<>0) ) then
  2125. float_raise( float_flag_invalid );
  2126. if bIsSignalingNaN<>0 then
  2127. c := b
  2128. else if aIsSignalingNan<>0 then
  2129. c := a
  2130. else if bIsNan<>0 then
  2131. c := b
  2132. else
  2133. c := a;
  2134. end;
  2135. {$ENDIF}
  2136. (****************************************************************************)
  2137. (* END ENDIAN SPECIFIC CODE *)
  2138. (****************************************************************************)
  2139. {*
  2140. -------------------------------------------------------------------------------
  2141. Returns the fraction bits of the single-precision floating-point value `a'.
  2142. -------------------------------------------------------------------------------
  2143. *}
  2144. Function ExtractFloat32Frac(a : Float32) : Bits32; inline;
  2145. Begin
  2146. ExtractFloat32Frac := A AND $007FFFFF;
  2147. End;
  2148. {*
  2149. -------------------------------------------------------------------------------
  2150. Returns the exponent bits of the single-precision floating-point value `a'.
  2151. -------------------------------------------------------------------------------
  2152. *}
  2153. Function extractFloat32Exp( a: float32 ): Int16; inline;
  2154. Begin
  2155. extractFloat32Exp := (a shr 23) AND $FF;
  2156. End;
  2157. {*
  2158. -------------------------------------------------------------------------------
  2159. Returns the sign bit of the single-precision floating-point value `a'.
  2160. -------------------------------------------------------------------------------
  2161. *}
  2162. Function extractFloat32Sign( a: float32 ): Flag; inline;
  2163. Begin
  2164. extractFloat32Sign := a shr 31;
  2165. End;
  2166. {*
  2167. -------------------------------------------------------------------------------
  2168. Normalizes the subnormal single-precision floating-point value represented
  2169. by the denormalized significand `aSig'. The normalized exponent and
  2170. significand are stored at the locations pointed to by `zExpPtr' and
  2171. `zSigPtr', respectively.
  2172. -------------------------------------------------------------------------------
  2173. *}
  2174. Procedure normalizeFloat32Subnormal( aSig : bits32; VAR zExpPtr: Int16; VAR zSigPtr :bits32);
  2175. Var
  2176. ShiftCount : BYTE;
  2177. Begin
  2178. shiftCount := countLeadingZeros32( aSig ) - 8;
  2179. zSigPtr := aSig shl shiftCount;
  2180. zExpPtr := 1 - shiftCount;
  2181. End;
  2182. {*
  2183. -------------------------------------------------------------------------------
  2184. Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
  2185. single-precision floating-point value, returning the result. After being
  2186. shifted into the proper positions, the three fields are simply added
  2187. together to form the result. This means that any integer portion of `zSig'
  2188. will be added into the exponent. Since a properly normalized significand
  2189. will have an integer portion equal to 1, the `zExp' input should be 1 less
  2190. than the desired result exponent whenever `zSig' is a complete, normalized
  2191. significand.
  2192. -------------------------------------------------------------------------------
  2193. *}
  2194. Function packFloat32( zSign: Flag; zExp : Int16; zSig: Bits32 ): Float32; inline;
  2195. Begin
  2196. packFloat32 := ( ( bits32( zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 23 )
  2197. + zSig;
  2198. End;
  2199. {*
  2200. -------------------------------------------------------------------------------
  2201. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2202. and significand `zSig', and returns the proper single-precision floating-
  2203. point value corresponding to the abstract input. Ordinarily, the abstract
  2204. value is simply rounded and packed into the single-precision format, with
  2205. the inexact exception raised if the abstract input cannot be represented
  2206. exactly. However, if the abstract value is too large, the overflow and
  2207. inexact exceptions are raised and an infinity or maximal finite value is
  2208. returned. If the abstract value is too small, the input value is rounded to
  2209. a subnormal number, and the underflow and inexact exceptions are raised if
  2210. the abstract input cannot be represented exactly as a subnormal single-
  2211. precision floating-point number.
  2212. The input significand `zSig' has its binary point between bits 30
  2213. and 29, which is 7 bits to the left of the usual location. This shifted
  2214. significand must be normalized or smaller. If `zSig' is not normalized,
  2215. `zExp' must be 0; in that case, the result returned is a subnormal number,
  2216. and it must not require rounding. In the usual case that `zSig' is
  2217. normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
  2218. The handling of underflow and overflow follows the IEC/IEEE Standard for
  2219. Binary Floating-Point Arithmetic.
  2220. -------------------------------------------------------------------------------
  2221. *}
  2222. Function roundAndPackFloat32( zSign : Flag; zExp : Int16; zSig : Bits32 ) : float32;
  2223. Var
  2224. roundingMode : TFPURoundingMode;
  2225. roundNearestEven : boolean;
  2226. roundIncrement, roundBits : BYTE;
  2227. IsTiny : boolean;
  2228. Begin
  2229. roundingMode := softfloat_rounding_mode;
  2230. roundNearestEven := (roundingMode = float_round_nearest_even);
  2231. roundIncrement := $40;
  2232. if not roundNearestEven then
  2233. Begin
  2234. if ( roundingMode = float_round_to_zero ) Then
  2235. Begin
  2236. roundIncrement := 0;
  2237. End
  2238. else
  2239. Begin
  2240. roundIncrement := $7F;
  2241. if ( zSign <> 0 ) then
  2242. Begin
  2243. if roundingMode = float_round_up then roundIncrement := 0;
  2244. End
  2245. else
  2246. Begin
  2247. if roundingMode = float_round_down then roundIncrement := 0;
  2248. End;
  2249. End
  2250. End;
  2251. roundBits := zSig AND $7F;
  2252. if ($FD <= bits16 (zExp) ) then
  2253. Begin
  2254. if (( $FD < zExp ) OR ( zExp = $FD ) AND ( sbits32 ( zSig + roundIncrement ) < 0 ) ) then
  2255. Begin
  2256. float_raise( [float_flag_overflow,float_flag_inexact] );
  2257. roundAndPackFloat32:=packFloat32( zSign, $FF, 0 ) - Flag( roundIncrement = 0 );
  2258. exit;
  2259. End;
  2260. if ( zExp < 0 ) then
  2261. Begin
  2262. isTiny :=
  2263. ( softfloat_detect_tininess = float_tininess_before_rounding )
  2264. OR ( zExp < -1 )
  2265. OR ( (zSig + roundIncrement) < $80000000 );
  2266. shift32RightJamming( zSig, - zExp, zSig );
  2267. zExp := 0;
  2268. roundBits := zSig AND $7F;
  2269. if ( isTiny and (roundBits<>0) ) then
  2270. float_raise( float_flag_underflow );
  2271. End;
  2272. End;
  2273. if ( roundBits )<> 0 then
  2274. set_inexact_flag;
  2275. zSig := ( zSig + roundIncrement ) shr 7;
  2276. zSig := zSig AND not bits32( bits32( ( roundBits XOR $40 ) = 0 ) and ord(roundNearestEven) );
  2277. if ( zSig = 0 ) then zExp := 0;
  2278. roundAndPackFloat32 := packFloat32( zSign, zExp, zSig );
  2279. End;
  2280. {*
  2281. -------------------------------------------------------------------------------
  2282. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2283. and significand `zSig', and returns the proper single-precision floating-
  2284. point value corresponding to the abstract input. This routine is just like
  2285. `roundAndPackFloat32' except that `zSig' does not have to be normalized.
  2286. Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
  2287. floating-point exponent.
  2288. -------------------------------------------------------------------------------
  2289. *}
  2290. Function normalizeRoundAndPackFloat32( zSign: flag; zExp: int16; zSig:bits32 ): float32;
  2291. Var
  2292. ShiftCount : int8;
  2293. Begin
  2294. shiftCount := countLeadingZeros32( zSig ) - 1;
  2295. normalizeRoundAndPackFloat32 := roundAndPackFloat32( zSign, zExp - shiftCount, zSig shl shiftCount );
  2296. End;
  2297. {*
  2298. -------------------------------------------------------------------------------
  2299. Returns the most-significant 20 fraction bits of the double-precision
  2300. floating-point value `a'.
  2301. -------------------------------------------------------------------------------
  2302. *}
  2303. Function extractFloat64Frac0(a: float64): bits32; inline;
  2304. Begin
  2305. extractFloat64Frac0 := a.high and $000FFFFF;
  2306. End;
  2307. {*
  2308. -------------------------------------------------------------------------------
  2309. Returns the least-significant 32 fraction bits of the double-precision
  2310. floating-point value `a'.
  2311. -------------------------------------------------------------------------------
  2312. *}
  2313. Function extractFloat64Frac1(a: float64): bits32; inline;
  2314. Begin
  2315. extractFloat64Frac1 := a.low;
  2316. End;
  2317. {$define FPC_SYSTEM_HAS_extractFloat64Frac}
  2318. Function extractFloat64Frac(a: float64): bits64; inline;
  2319. Begin
  2320. extractFloat64Frac := bits64(a) and $000FFFFFFFFFFFFF;
  2321. End;
  2322. {*
  2323. -------------------------------------------------------------------------------
  2324. Returns the exponent bits of the double-precision floating-point value `a'.
  2325. -------------------------------------------------------------------------------
  2326. *}
  2327. Function extractFloat64Exp(a: float64): int16; inline;
  2328. Begin
  2329. extractFloat64Exp:= ( a.high shr 20 ) AND $7FF;
  2330. End;
  2331. {*
  2332. -------------------------------------------------------------------------------
  2333. Returns the sign bit of the double-precision floating-point value `a'.
  2334. -------------------------------------------------------------------------------
  2335. *}
  2336. Function extractFloat64Sign(a: float64) : flag; inline;
  2337. Begin
  2338. extractFloat64Sign := a.high shr 31;
  2339. End;
  2340. {*
  2341. -------------------------------------------------------------------------------
  2342. Normalizes the subnormal double-precision floating-point value represented
  2343. by the denormalized significand formed by the concatenation of `aSig0' and
  2344. `aSig1'. The normalized exponent is stored at the location pointed to by
  2345. `zExpPtr'. The most significant 21 bits of the normalized significand are
  2346. stored at the location pointed to by `zSig0Ptr', and the least significant
  2347. 32 bits of the normalized significand are stored at the location pointed to
  2348. by `zSig1Ptr'.
  2349. -------------------------------------------------------------------------------
  2350. *}
  2351. Procedure normalizeFloat64Subnormal(
  2352. aSig0: bits32;
  2353. aSig1: bits32;
  2354. VAR zExpPtr : Int16;
  2355. VAR zSig0Ptr : Bits32;
  2356. VAR zSig1Ptr : Bits32
  2357. );
  2358. Var
  2359. ShiftCount : Int8;
  2360. Begin
  2361. if ( aSig0 = 0 ) then
  2362. Begin
  2363. shiftCount := countLeadingZeros32( aSig1 ) - 11;
  2364. if ( shiftCount < 0 ) then
  2365. Begin
  2366. zSig0Ptr := aSig1 shr ( - shiftCount );
  2367. zSig1Ptr := aSig1 shl ( shiftCount AND 31 );
  2368. End
  2369. else
  2370. Begin
  2371. zSig0Ptr := aSig1 shl shiftCount;
  2372. zSig1Ptr := 0;
  2373. End;
  2374. zExpPtr := - shiftCount - 31;
  2375. End
  2376. else
  2377. Begin
  2378. shiftCount := countLeadingZeros32( aSig0 ) - 11;
  2379. shortShift64Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
  2380. zExpPtr := 1 - shiftCount;
  2381. End;
  2382. End;
  2383. procedure normalizeFloat64Subnormal(aSig : bits64;var zExpPtr : int16; var zSigPtr : bits64);
  2384. var
  2385. shiftCount : int8;
  2386. begin
  2387. shiftCount := countLeadingZeros64( aSig ) - 11;
  2388. zSigPtr := aSig shl shiftCount;
  2389. zExpPtr := 1 - shiftCount;
  2390. end;
  2391. {*
  2392. -------------------------------------------------------------------------------
  2393. Packs the sign `zSign', the exponent `zExp', and the significand formed by
  2394. the concatenation of `zSig0' and `zSig1' into a double-precision floating-
  2395. point value, returning the result. After being shifted into the proper
  2396. positions, the three fields `zSign', `zExp', and `zSig0' are simply added
  2397. together to form the most significant 32 bits of the result. This means
  2398. that any integer portion of `zSig0' will be added into the exponent. Since
  2399. a properly normalized significand will have an integer portion equal to 1,
  2400. the `zExp' input should be 1 less than the desired result exponent whenever
  2401. `zSig0' and `zSig1' concatenated form a complete, normalized significand.
  2402. -------------------------------------------------------------------------------
  2403. *}
  2404. Procedure
  2405. packFloat64( zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1 : Bits32; VAR c : float64);
  2406. var
  2407. z: Float64;
  2408. Begin
  2409. z.low := zSig1;
  2410. z.high := ( ( bits32 (zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 20 ) + zSig0;
  2411. c := z;
  2412. End;
  2413. {*----------------------------------------------------------------------------
  2414. | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
  2415. | double-precision floating-point value, returning the result. After being
  2416. | shifted into the proper positions, the three fields are simply added
  2417. | together to form the result. This means that any integer portion of `zSig'
  2418. | will be added into the exponent. Since a properly normalized significand
  2419. | will have an integer portion equal to 1, the `zExp' input should be 1 less
  2420. | than the desired result exponent whenever `zSig' is a complete, normalized
  2421. | significand.
  2422. *----------------------------------------------------------------------------*}
  2423. function packFloat64( zSign: flag; zExp: int16; zSig : bits64): float64;inline;
  2424. begin
  2425. result := float64(( ( bits64(zSign) ) shl 63 ) + ( ( bits64(zExp) ) shl 52 ) + zSig);
  2426. end;
  2427. {*
  2428. -------------------------------------------------------------------------------
  2429. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2430. and extended significand formed by the concatenation of `zSig0', `zSig1',
  2431. and `zSig2', and returns the proper double-precision floating-point value
  2432. corresponding to the abstract input. Ordinarily, the abstract value is
  2433. simply rounded and packed into the double-precision format, with the inexact
  2434. exception raised if the abstract input cannot be represented exactly.
  2435. However, if the abstract value is too large, the overflow and inexact
  2436. exceptions are raised and an infinity or maximal finite value is returned.
  2437. If the abstract value is too small, the input value is rounded to a
  2438. subnormal number, and the underflow and inexact exceptions are raised if the
  2439. abstract input cannot be represented exactly as a subnormal double-precision
  2440. floating-point number.
  2441. The input significand must be normalized or smaller. If the input
  2442. significand is not normalized, `zExp' must be 0; in that case, the result
  2443. returned is a subnormal number, and it must not require rounding. In the
  2444. usual case that the input significand is normalized, `zExp' must be 1 less
  2445. than the ``true'' floating-point exponent. The handling of underflow and
  2446. overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2447. -------------------------------------------------------------------------------
  2448. *}
  2449. Procedure
  2450. roundAndPackFloat64(
  2451. zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1: Bits32; zSig2: Bits32; Var c: Float64 );
  2452. Var
  2453. roundingMode : TFPURoundingMode;
  2454. roundNearestEven, increment, isTiny : Flag;
  2455. Begin
  2456. roundingMode := softfloat_rounding_mode;
  2457. roundNearestEven := flag( roundingMode = float_round_nearest_even );
  2458. increment := flag( sbits32 (zSig2) < 0 );
  2459. if ( roundNearestEven = flag(FALSE) ) then
  2460. Begin
  2461. if ( roundingMode = float_round_to_zero ) then
  2462. increment := 0
  2463. else
  2464. Begin
  2465. if ( zSign )<> 0 then
  2466. Begin
  2467. increment := flag(( roundingMode = float_round_down ) and (zSig2<>0));
  2468. End
  2469. else
  2470. Begin
  2471. increment := flag(( roundingMode = float_round_up ) and (zSig2<>0));
  2472. End
  2473. End
  2474. End;
  2475. if ( $7FD <= bits16 (zExp) ) then
  2476. Begin
  2477. if (( $7FD < zExp )
  2478. or (( zExp = $7FD )
  2479. and (zSig0=$001FFFFF) and (zSig1=$FFFFFFFF)
  2480. and (increment<>0)
  2481. )
  2482. ) then
  2483. Begin
  2484. float_raise( [float_flag_overflow,float_flag_inexact] );
  2485. if (( roundingMode = float_round_to_zero )
  2486. or ( (zSign<>0) and ( roundingMode = float_round_up ) )
  2487. or ( (zSign = 0) and ( roundingMode = float_round_down ) )
  2488. ) then
  2489. Begin
  2490. packFloat64( zSign, $7FE, $000FFFFF, $FFFFFFFF, c );
  2491. exit;
  2492. End;
  2493. packFloat64( zSign, $7FF, 0, 0, c );
  2494. exit;
  2495. End;
  2496. if ( zExp < 0 ) then
  2497. Begin
  2498. isTiny :=
  2499. flag( softfloat_detect_tininess = float_tininess_before_rounding )
  2500. or flag( zExp < -1 )
  2501. or flag(increment = 0)
  2502. or flag(lt64( zSig0, zSig1, $001FFFFF, $FFFFFFFF)<>0);
  2503. shift64ExtraRightJamming(
  2504. zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );
  2505. zExp := 0;
  2506. if ( isTiny<>0) and (zSig2<>0 ) then float_raise( float_flag_underflow );
  2507. if ( roundNearestEven )<>0 then
  2508. Begin
  2509. increment := flag( sbits32 (zSig2) < 0 );
  2510. End
  2511. else
  2512. Begin
  2513. if ( zSign )<>0 then
  2514. Begin
  2515. increment := flag(( roundingMode = float_round_down ) and (zSig2<>0));
  2516. End
  2517. else
  2518. Begin
  2519. increment := flag(( roundingMode = float_round_up ) and (zSig2<>0));
  2520. End
  2521. End;
  2522. End;
  2523. End;
  2524. if ( zSig2 )<>0 then
  2525. set_inexact_flag;
  2526. if ( increment )<>0 then
  2527. Begin
  2528. add64( zSig0, zSig1, 0, 1, zSig0, zSig1 );
  2529. zSig1 := zSig1 and not ( bits32(flag( zSig2 + zSig2 = 0 )) and roundNearestEven );
  2530. End
  2531. else
  2532. Begin
  2533. if ( ( zSig0 or zSig1 ) = 0 ) then zExp := 0;
  2534. End;
  2535. packFloat64( zSign, zExp, zSig0, zSig1, c );
  2536. End;
  2537. {*----------------------------------------------------------------------------
  2538. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2539. | and significand `zSig', and returns the proper double-precision floating-
  2540. | point value corresponding to the abstract input. Ordinarily, the abstract
  2541. | value is simply rounded and packed into the double-precision format, with
  2542. | the inexact exception raised if the abstract input cannot be represented
  2543. | exactly. However, if the abstract value is too large, the overflow and
  2544. | inexact exceptions are raised and an infinity or maximal finite value is
  2545. | returned. If the abstract value is too small, the input value is rounded
  2546. | to a subnormal number, and the underflow and inexact exceptions are raised
  2547. | if the abstract input cannot be represented exactly as a subnormal double-
  2548. | precision floating-point number.
  2549. | The input significand `zSig' has its binary point between bits 62
  2550. | and 61, which is 10 bits to the left of the usual location. This shifted
  2551. | significand must be normalized or smaller. If `zSig' is not normalized,
  2552. | `zExp' must be 0; in that case, the result returned is a subnormal number,
  2553. | and it must not require rounding. In the usual case that `zSig' is
  2554. | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
  2555. | The handling of underflow and overflow follows the IEC/IEEE Standard for
  2556. | Binary Floating-Point Arithmetic.
  2557. *----------------------------------------------------------------------------*}
  2558. function roundAndPackFloat64( zSign: flag; zExp: int16; zSig : bits64): float64;
  2559. var
  2560. roundingMode: TFPURoundingMode;
  2561. roundNearestEven: flag;
  2562. roundIncrement, roundBits: int16;
  2563. isTiny: flag;
  2564. begin
  2565. roundingMode := softfloat_rounding_mode;
  2566. roundNearestEven := ord( roundingMode = float_round_nearest_even );
  2567. roundIncrement := $200;
  2568. if ( roundNearestEven=0 ) then
  2569. begin
  2570. if ( roundingMode = float_round_to_zero ) then
  2571. begin
  2572. roundIncrement := 0;
  2573. end
  2574. else begin
  2575. roundIncrement := $3FF;
  2576. if ( zSign<>0 ) then
  2577. begin
  2578. if ( roundingMode = float_round_up ) then
  2579. roundIncrement := 0;
  2580. end
  2581. else begin
  2582. if ( roundingMode = float_round_down ) then
  2583. roundIncrement := 0;
  2584. end
  2585. end
  2586. end;
  2587. roundBits := zSig and $3FF;
  2588. if ( $7FD <= bits16(zExp) ) then
  2589. begin
  2590. if ( ( $7FD < zExp )
  2591. or ( ( zExp = $7FD )
  2592. and ( sbits64( zSig + roundIncrement ) < 0 ) )
  2593. ) then
  2594. begin
  2595. float_raise( [float_flag_overflow,float_flag_inexact] );
  2596. result := float64(qword(packFloat64( zSign, $7FF, 0 )) - ord( roundIncrement = 0 ));
  2597. exit;
  2598. end;
  2599. if ( zExp < 0 ) then
  2600. begin
  2601. isTiny := ord(
  2602. ( softfloat_detect_tininess = float_tininess_before_rounding )
  2603. or ( zExp < -1 )
  2604. or ( (zSig + roundIncrement) < bits64( $8000000000000000 ) ) );
  2605. shift64RightJamming( zSig, - zExp, zSig );
  2606. zExp := 0;
  2607. roundBits := zSig and $3FF;
  2608. if ( isTiny and roundBits )<>0 then
  2609. float_raise( float_flag_underflow );
  2610. end
  2611. end;
  2612. if ( roundBits<>0 ) then
  2613. set_inexact_flag;
  2614. zSig := ( zSig + roundIncrement ) shr 10;
  2615. zSig := zSig and not(qword(ord( ( roundBits xor $200 ) = 0 ) and roundNearestEven ));
  2616. if ( zSig = 0 ) then
  2617. zExp := 0;
  2618. result:=packFloat64( zSign, zExp, zSig );
  2619. end;
  2620. {*
  2621. -------------------------------------------------------------------------------
  2622. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2623. and significand formed by the concatenation of `zSig0' and `zSig1', and
  2624. returns the proper double-precision floating-point value corresponding
  2625. to the abstract input. This routine is just like `roundAndPackFloat64'
  2626. except that the input significand has fewer bits and does not have to be
  2627. normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
  2628. point exponent.
  2629. -------------------------------------------------------------------------------
  2630. *}
  2631. Procedure
  2632. normalizeRoundAndPackFloat64(
  2633. zSign:flag; zExp:int16; zSig0:bits32; zSig1:bits32; VAR c: float64 );
  2634. Var
  2635. shiftCount : int8;
  2636. zSig2 : bits32;
  2637. Begin
  2638. if ( zSig0 = 0 ) then
  2639. Begin
  2640. zSig0 := zSig1;
  2641. zSig1 := 0;
  2642. zExp := zExp -32;
  2643. End;
  2644. shiftCount := countLeadingZeros32( zSig0 ) - 11;
  2645. if ( 0 <= shiftCount ) then
  2646. Begin
  2647. zSig2 := 0;
  2648. shortShift64Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  2649. End
  2650. else
  2651. Begin
  2652. shift64ExtraRightJamming
  2653. (zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );
  2654. End;
  2655. zExp := zExp - shiftCount;
  2656. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, c );
  2657. End;
  2658. {*
  2659. ----------------------------------------------------------------------------
  2660. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2661. and significand `zSig', and returns the proper double-precision floating-
  2662. point value corresponding to the abstract input. This routine is just like
  2663. `roundAndPackFloat64' except that `zSig' does not have to be normalized.
  2664. Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
  2665. floating-point exponent.
  2666. --
  2667. additionally the Pascal version should support Bit 63 set in 'zSig'
  2668. ----------------------------------------------------------------------------
  2669. *}
  2670. function normalizeRoundAndPackFloat64(zSign: flag; zExp: int16; zSig: bits64): float64;
  2671. var
  2672. shiftCount: int8;
  2673. begin
  2674. shiftCount := countLeadingZeros64( zSig ) - 1;
  2675. if ( shiftCount <= 0) then
  2676. result := roundAndPackFloat64( zSign, zExp - shiftCount, zSig shr (-shiftCount))
  2677. else
  2678. result := roundAndPackFloat64( zSign, zExp - shiftCount, zSig shl shiftCount);
  2679. end;
  2680. {*
  2681. -------------------------------------------------------------------------------
  2682. Returns the result of converting the 32-bit two's complement integer `a' to
  2683. the single-precision floating-point format. The conversion is performed
  2684. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2685. -------------------------------------------------------------------------------
  2686. *}
  2687. Function int32_to_float32( a: int32): float32rec; compilerproc;
  2688. Var
  2689. zSign : Flag;
  2690. Begin
  2691. if ( a = 0 ) then
  2692. Begin
  2693. int32_to_float32.float32 := 0;
  2694. exit;
  2695. End;
  2696. if ( a = sbits32 ($80000000) ) then
  2697. Begin
  2698. int32_to_float32.float32 := packFloat32( 1, $9E, 0 );
  2699. exit;
  2700. end;
  2701. zSign := flag( a < 0 );
  2702. If zSign<>0 then
  2703. a := -a;
  2704. int32_to_float32.float32:=
  2705. normalizeRoundAndPackFloat32( zSign, $9C, a );
  2706. End;
  2707. {*
  2708. -------------------------------------------------------------------------------
  2709. Returns the result of converting the 32-bit two's complement integer `a' to
  2710. the double-precision floating-point format. The conversion is performed
  2711. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2712. -------------------------------------------------------------------------------
  2713. *}
  2714. Function int32_to_float64( a: int32) : float64;{$ifdef fpc} [public,Alias:'INT32_TO_FLOAT64'];compilerproc;{$endif}
  2715. var
  2716. zSign : flag;
  2717. absA : bits32;
  2718. shiftCount : int8;
  2719. zSig0, zSig1 : bits32;
  2720. Begin
  2721. if ( a = 0 ) then
  2722. Begin
  2723. packFloat64( 0, 0, 0, 0, result );
  2724. exit;
  2725. end;
  2726. zSign := flag( a < 0 );
  2727. if ZSign<>0 then
  2728. AbsA := -a
  2729. else
  2730. AbsA := a;
  2731. shiftCount := countLeadingZeros32( absA ) - 11;
  2732. if ( 0 <= shiftCount ) then
  2733. Begin
  2734. zSig0 := absA shl shiftCount;
  2735. zSig1 := 0;
  2736. End
  2737. else
  2738. Begin
  2739. shift64Right( absA, 0, - shiftCount, zSig0, zSig1 );
  2740. End;
  2741. packFloat64( zSign, $412 - shiftCount, zSig0, zSig1, result );
  2742. End;
  2743. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  2744. {$if not defined(packFloatx80)}
  2745. function packFloatx80( zSign: flag; zExp: int32; zSig : bits64): floatx80;
  2746. forward;
  2747. {$endif}
  2748. {*----------------------------------------------------------------------------
  2749. | Returns the result of converting the 32-bit two's complement integer `a'
  2750. | to the extended double-precision floating-point format. The conversion
  2751. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  2752. | Arithmetic.
  2753. *----------------------------------------------------------------------------*}
  2754. function int32_to_floatx80( a: int32 ): floatx80;
  2755. var
  2756. zSign: flag;
  2757. absA: uint32;
  2758. shiftCount: int8;
  2759. zSig: bits64;
  2760. begin
  2761. if ( a = 0 ) then begin
  2762. result := packFloatx80( 0, 0, 0 );
  2763. exit;
  2764. end;
  2765. zSign := ord( a < 0 );
  2766. if zSign <> 0 then absA := - a else absA := a;
  2767. shiftCount := countLeadingZeros32( absA ) + 32;
  2768. zSig := absA;
  2769. result := packFloatx80( zSign, $403E - shiftCount, zSig shl shiftCount );
  2770. end;
  2771. {$endif FPC_SOFTFLOAT_FLOATX80}
  2772. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  2773. {$if not defined(packFloat128)}
  2774. function packFloat128( zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64 ) : float128;
  2775. forward;
  2776. {$endif}
  2777. {*----------------------------------------------------------------------------
  2778. | Returns the result of converting the 32-bit two's complement integer `a' to
  2779. | the quadruple-precision floating-point format. The conversion is performed
  2780. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2781. *----------------------------------------------------------------------------*}
  2782. function int32_to_float128( a: int32 ): float128;
  2783. var
  2784. zSign: flag;
  2785. absA: uint32;
  2786. shiftCount: int8;
  2787. zSig0: bits64;
  2788. begin
  2789. if ( a = 0 ) then begin
  2790. result := packFloat128( 0, 0, 0, 0 );
  2791. exit;
  2792. end;
  2793. zSign := ord( a < 0 );
  2794. if zSign <> 0 then absA := - a else absA := a;
  2795. shiftCount := countLeadingZeros32( absA ) + 17;
  2796. zSig0 := absA;
  2797. result := packFloat128( zSign, $402E - shiftCount, zSig0 shl shiftCount, 0 );
  2798. end;
  2799. {$endif FPC_SOFTFLOAT_FLOAT128}
  2800. {*
  2801. -------------------------------------------------------------------------------
  2802. Returns the result of converting the single-precision floating-point value
  2803. `a' to the 32-bit two's complement integer format. The conversion is
  2804. performed according to the IEC/IEEE Standard for Binary Floating-Point
  2805. Arithmetic---which means in particular that the conversion is rounded
  2806. according to the current rounding mode. If `a' is a NaN, the largest
  2807. positive integer is returned. Otherwise, if the conversion overflows, the
  2808. largest integer with the same sign as `a' is returned.
  2809. -------------------------------------------------------------------------------
  2810. *}
  2811. Function float32_to_int32( a : float32rec) : int32;compilerproc;
  2812. Var
  2813. aSign: flag;
  2814. aExp, shiftCount: int16;
  2815. aSig, aSigExtra: bits32;
  2816. z: int32;
  2817. roundingMode: TFPURoundingMode;
  2818. Begin
  2819. aSig := extractFloat32Frac( a.float32 );
  2820. aExp := extractFloat32Exp( a.float32 );
  2821. aSign := extractFloat32Sign( a.float32 );
  2822. shiftCount := aExp - $96;
  2823. if ( 0 <= shiftCount ) then
  2824. Begin
  2825. if ( $9E <= aExp ) then
  2826. Begin
  2827. if ( a.float32 <> $CF000000 ) then
  2828. Begin
  2829. float_raise( float_flag_invalid );
  2830. if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  2831. Begin
  2832. float32_to_int32 := $7FFFFFFF;
  2833. exit;
  2834. End;
  2835. End;
  2836. float32_to_int32 := sbits32 ($80000000);
  2837. exit;
  2838. End;
  2839. z := ( aSig or $00800000 ) shl shiftCount;
  2840. if ( aSign<>0 ) then z := - z;
  2841. End
  2842. else
  2843. Begin
  2844. if ( aExp < $7E ) then
  2845. Begin
  2846. aSigExtra := aExp OR aSig;
  2847. z := 0;
  2848. End
  2849. else
  2850. Begin
  2851. aSig := aSig OR $00800000;
  2852. aSigExtra := aSig shl ( shiftCount and 31 );
  2853. z := aSig shr ( - shiftCount );
  2854. End;
  2855. if ( aSigExtra<>0 ) then
  2856. set_inexact_flag;
  2857. roundingMode := softfloat_rounding_mode;
  2858. if ( roundingMode = float_round_nearest_even ) then
  2859. Begin
  2860. if ( sbits32 (aSigExtra) < 0 ) then
  2861. Begin
  2862. Inc(z);
  2863. if ( bits32 ( aSigExtra shl 1 ) = 0 ) then
  2864. z := z and not 1;
  2865. End;
  2866. if ( aSign<>0 ) then
  2867. z := - z;
  2868. End
  2869. else
  2870. Begin
  2871. aSigExtra := flag( aSigExtra <> 0 );
  2872. if ( aSign<>0 ) then
  2873. Begin
  2874. z := z + (flag( roundingMode = float_round_down ) and aSigExtra);
  2875. z := - z;
  2876. End
  2877. else
  2878. Begin
  2879. z := z + (flag( roundingMode = float_round_up ) and aSigExtra);
  2880. End
  2881. End;
  2882. End;
  2883. float32_to_int32 := z;
  2884. End;
  2885. {*
  2886. -------------------------------------------------------------------------------
  2887. Returns the result of converting the single-precision floating-point value
  2888. `a' to the 32-bit two's complement integer format. The conversion is
  2889. performed according to the IEC/IEEE Standard for Binary Floating-Point
  2890. Arithmetic, except that the conversion is always rounded toward zero.
  2891. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  2892. the conversion overflows, the largest integer with the same sign as `a' is
  2893. returned.
  2894. -------------------------------------------------------------------------------
  2895. *}
  2896. Function float32_to_int32_round_to_zero( a: Float32rec ): int32;compilerproc;
  2897. Var
  2898. aSign : flag;
  2899. aExp, shiftCount : int16;
  2900. aSig : bits32;
  2901. z : int32;
  2902. Begin
  2903. aSig := extractFloat32Frac( a.float32 );
  2904. aExp := extractFloat32Exp( a.float32 );
  2905. aSign := extractFloat32Sign( a.float32 );
  2906. shiftCount := aExp - $9E;
  2907. if ( 0 <= shiftCount ) then
  2908. Begin
  2909. if ( a.float32 <> $CF000000 ) then
  2910. Begin
  2911. float_raise( float_flag_invalid );
  2912. if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  2913. Begin
  2914. float32_to_int32_round_to_zero := $7FFFFFFF;
  2915. exit;
  2916. end;
  2917. End;
  2918. float32_to_int32_round_to_zero:= sbits32 ($80000000);
  2919. exit;
  2920. End
  2921. else
  2922. if ( aExp <= $7E ) then
  2923. Begin
  2924. if ( aExp or aSig )<>0 then
  2925. set_inexact_flag;
  2926. float32_to_int32_round_to_zero := 0;
  2927. exit;
  2928. End;
  2929. aSig := ( aSig or $00800000 ) shl 8;
  2930. z := aSig shr ( - shiftCount );
  2931. if ( bits32 ( aSig shl ( shiftCount and 31 ) )<> 0 ) then
  2932. Begin
  2933. set_inexact_flag;
  2934. End;
  2935. if ( aSign<>0 ) then z := - z;
  2936. float32_to_int32_round_to_zero := z;
  2937. End;
  2938. {*----------------------------------------------------------------------------
  2939. | Returns the result of converting the single-precision floating-point value
  2940. | `a' to the 64-bit two's complement integer format. The conversion is
  2941. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  2942. | Arithmetic---which means in particular that the conversion is rounded
  2943. | according to the current rounding mode. If `a' is a NaN, the largest
  2944. | positive integer is returned. Otherwise, if the conversion overflows, the
  2945. | largest integer with the same sign as `a' is returned.
  2946. *----------------------------------------------------------------------------*}
  2947. function float32_to_int64( a: float32 ): int64;
  2948. var
  2949. aSign: flag;
  2950. aExp, shiftCount: int16;
  2951. aSig: bits32;
  2952. aSig64, aSigExtra: bits64;
  2953. begin
  2954. aSig := extractFloat32Frac( a );
  2955. aExp := extractFloat32Exp( a );
  2956. aSign := extractFloat32Sign( a );
  2957. shiftCount := $BE - aExp;
  2958. if ( shiftCount < 0 ) then begin
  2959. float_raise( float_flag_invalid );
  2960. if ( aSign = 0 ) or ( ( aExp = $FF ) and ( aSig <> 0 ) ) then begin
  2961. result := $7FFFFFFFFFFFFFFF;
  2962. exit;
  2963. end;
  2964. result := $8000000000000000;
  2965. exit;
  2966. end;
  2967. if ( aExp <> 0 ) then aSig := aSig or $00800000;
  2968. aSig64 := aSig;
  2969. aSig64 := aSig64 shl 40;
  2970. shift64ExtraRightJamming( aSig64, 0, shiftCount, aSig64, aSigExtra );
  2971. result := roundAndPackInt64( aSign, aSig64, aSigExtra );
  2972. end;
  2973. {*----------------------------------------------------------------------------
  2974. | Returns the result of converting the single-precision floating-point value
  2975. | `a' to the 64-bit two's complement integer format. The conversion is
  2976. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  2977. | Arithmetic, except that the conversion is always rounded toward zero. If
  2978. | `a' is a NaN, the largest positive integer is returned. Otherwise, if the
  2979. | conversion overflows, the largest integer with the same sign as `a' is
  2980. | returned.
  2981. *----------------------------------------------------------------------------*}
  2982. function float32_to_int64_round_to_zero( a: float32 ): int64;
  2983. var
  2984. aSign: flag;
  2985. aExp, shiftCount: int16;
  2986. aSig: bits32;
  2987. aSig64: bits64;
  2988. z: int64;
  2989. begin
  2990. aSig := extractFloat32Frac( a );
  2991. aExp := extractFloat32Exp( a );
  2992. aSign := extractFloat32Sign( a );
  2993. shiftCount := aExp - $BE;
  2994. if ( 0 <= shiftCount ) then begin
  2995. if ( a <> $DF000000 ) then begin
  2996. float_raise( float_flag_invalid );
  2997. if ( aSign = 0) or ( ( aExp = $FF ) and ( aSig <> 0 ) ) then begin
  2998. result := $7FFFFFFFFFFFFFFF;
  2999. exit;
  3000. end;
  3001. end;
  3002. result := $8000000000000000;
  3003. exit;
  3004. end
  3005. else if ( aExp <= $7E ) then begin
  3006. if ( aExp or aSig <> 0 ) then set_inexact_flag;
  3007. result := 0;
  3008. exit;
  3009. end;
  3010. aSig64 := aSig or $00800000;
  3011. aSig64 := aSig64 shl 40;
  3012. z := aSig64 shr ( - shiftCount );
  3013. if bits64( aSig64 shl ( shiftCount and 63 ) ) <> 0 then
  3014. set_inexact_flag;
  3015. if ( aSign <> 0 ) then z := - z;
  3016. result := z;
  3017. end;
  3018. {*
  3019. -------------------------------------------------------------------------------
  3020. Returns the result of converting the single-precision floating-point value
  3021. `a' to the double-precision floating-point format. The conversion is
  3022. performed according to the IEC/IEEE Standard for Binary Floating-Point
  3023. Arithmetic.
  3024. -------------------------------------------------------------------------------
  3025. *}
  3026. Function float32_to_float64( a : float32rec) : Float64;compilerproc;
  3027. Var
  3028. aSign : flag;
  3029. aExp : int16;
  3030. aSig, zSig0, zSig1: bits32;
  3031. tmp : CommonNanT;
  3032. Begin
  3033. aSig := extractFloat32Frac( a.float32 );
  3034. aExp := extractFloat32Exp( a.float32 );
  3035. aSign := extractFloat32Sign( a.float32 );
  3036. if ( aExp = $FF ) then
  3037. Begin
  3038. if ( aSig<>0 ) then
  3039. Begin
  3040. float32ToCommonNaN(a.float32, tmp);
  3041. commonNaNToFloat64(tmp , result);
  3042. exit;
  3043. End;
  3044. packFloat64( aSign, $7FF, 0, 0, result);
  3045. exit;
  3046. End;
  3047. if ( aExp = 0 ) then
  3048. Begin
  3049. if ( aSig = 0 ) then
  3050. Begin
  3051. packFloat64( aSign, 0, 0, 0, result );
  3052. exit;
  3053. end;
  3054. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3055. Dec(aExp);
  3056. End;
  3057. shift64Right( aSig, 0, 3, zSig0, zSig1 );
  3058. packFloat64( aSign, aExp + $380, zSig0, zSig1, result );
  3059. End;
  3060. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  3061. {*----------------------------------------------------------------------------
  3062. | Returns the result of converting the canonical NaN `a' to the extended
  3063. | double-precision floating-point format.
  3064. *----------------------------------------------------------------------------*}
  3065. function commonNaNToFloatx80( a : commonNaNT ) : floatx80;
  3066. var
  3067. z : floatx80;
  3068. begin
  3069. z.low := bits64( $C000000000000000 ) or ( a.high shr 1 );
  3070. z.high := ( bits16( a.sign ) shl 15 ) or $7FFF;
  3071. result := z;
  3072. end;
  3073. {*----------------------------------------------------------------------------
  3074. | Returns the result of converting the single-precision floating-point value
  3075. | `a' to the extended double-precision floating-point format. The conversion
  3076. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  3077. | Arithmetic.
  3078. *----------------------------------------------------------------------------*}
  3079. function float32_to_floatx80( a: float32 ): floatx80;
  3080. var
  3081. aSign: flag;
  3082. aExp: int16;
  3083. aSig: bits32;
  3084. tmp: commonNaNT;
  3085. begin
  3086. aSig := extractFloat32Frac( a );
  3087. aExp := extractFloat32Exp( a );
  3088. aSign := extractFloat32Sign( a );
  3089. if ( aExp = $FF ) then begin
  3090. if ( aSig <> 0 ) then begin
  3091. float32ToCommonNaN( a, tmp );
  3092. result := commonNaNToFloatx80( tmp );
  3093. exit;
  3094. end;
  3095. result := packFloatx80( aSign, $7FFF, bits64( $8000000000000000 ) );
  3096. exit;
  3097. end;
  3098. if ( aExp = 0 ) then begin
  3099. if ( aSig = 0 ) then begin
  3100. result := packFloatx80( aSign, 0, 0 );
  3101. exit;
  3102. end;
  3103. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3104. end;
  3105. aSig := aSig or $00800000;
  3106. result := packFloatx80( aSign, aExp + $3F80, bits64(aSig) shl 40 );
  3107. end;
  3108. {$endif FPC_SOFTFLOAT_FLOATX80}
  3109. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  3110. {*----------------------------------------------------------------------------
  3111. | Returns the result of converting the single-precision floating-point value
  3112. | `a' to the double-precision floating-point format. The conversion is
  3113. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  3114. | Arithmetic.
  3115. *----------------------------------------------------------------------------*}
  3116. function float32_to_float128( a: float32 ): float128;
  3117. var
  3118. aSign: flag;
  3119. aExp: int16;
  3120. aSig: bits32;
  3121. tmp: commonNaNT;
  3122. begin
  3123. aSig := extractFloat32Frac( a );
  3124. aExp := extractFloat32Exp( a );
  3125. aSign := extractFloat32Sign( a );
  3126. if ( aExp = $FF ) then begin
  3127. if ( aSig <> 0 ) then begin
  3128. float32ToCommonNaN( a, tmp );
  3129. result := commonNaNToFloat128( tmp );
  3130. exit;
  3131. end;
  3132. result := packFloat128( aSign, $7FFF, 0, 0 );
  3133. exit;
  3134. end;
  3135. if ( aExp = 0 ) then begin
  3136. if ( aSig = 0 ) then begin
  3137. result := packFloat128( aSign, 0, 0, 0 );
  3138. exit;
  3139. end;
  3140. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3141. dec( aExp );
  3142. end;
  3143. result := packFloat128( aSign, aExp + $3F80, bits64( aSig ) shl 25, 0 );
  3144. end;
  3145. {$endif FPC_SOFTFLOAT_FLOAT128}
  3146. {*
  3147. -------------------------------------------------------------------------------
  3148. Rounds the single-precision floating-point value `a' to an integer,
  3149. and returns the result as a single-precision floating-point value. The
  3150. operation is performed according to the IEC/IEEE Standard for Binary
  3151. Floating-Point Arithmetic.
  3152. -------------------------------------------------------------------------------
  3153. *}
  3154. Function float32_round_to_int( a: float32rec): float32rec;compilerproc;
  3155. Var
  3156. aSign: flag;
  3157. aExp: int16;
  3158. lastBitMask, roundBitsMask: bits32;
  3159. roundingMode: TFPURoundingMode;
  3160. z: float32;
  3161. Begin
  3162. aExp := extractFloat32Exp( a.float32 );
  3163. if ( $96 <= aExp ) then
  3164. Begin
  3165. if ( ( aExp = $FF ) and (extractFloat32Frac( a.float32 )<>0) ) then
  3166. Begin
  3167. float32_round_to_int.float32 := propagateFloat32NaN( a.float32, a.float32 );
  3168. exit;
  3169. End;
  3170. float32_round_to_int:=a;
  3171. exit;
  3172. End;
  3173. if ( aExp <= $7E ) then
  3174. Begin
  3175. if ( bits32 ( a.float32 shl 1 ) = 0 ) then
  3176. Begin
  3177. float32_round_to_int:=a;
  3178. exit;
  3179. end;
  3180. set_inexact_flag;
  3181. aSign := extractFloat32Sign( a.float32 );
  3182. case ( softfloat_rounding_mode ) of
  3183. float_round_nearest_even:
  3184. Begin
  3185. if ( ( aExp = $7E ) and (extractFloat32Frac( a.float32 )<>0) ) then
  3186. Begin
  3187. float32_round_to_int.float32 := packFloat32( aSign, $7F, 0 );
  3188. exit;
  3189. End;
  3190. End;
  3191. float_round_down:
  3192. Begin
  3193. if aSign <> 0 then
  3194. float32_round_to_int.float32 := $BF800000
  3195. else
  3196. float32_round_to_int.float32 := 0;
  3197. exit;
  3198. End;
  3199. float_round_up:
  3200. Begin
  3201. if aSign <> 0 then
  3202. float32_round_to_int.float32 := $80000000
  3203. else
  3204. float32_round_to_int.float32 := $3F800000;
  3205. exit;
  3206. End;
  3207. end;
  3208. float32_round_to_int.float32 := packFloat32( aSign, 0, 0 );
  3209. exit;
  3210. End;
  3211. lastBitMask := 1;
  3212. {_____________________________!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
  3213. lastBitMask := lastBitMask shl ($96 - aExp);
  3214. roundBitsMask := lastBitMask - 1;
  3215. z := a.float32;
  3216. roundingMode := softfloat_rounding_mode;
  3217. if ( roundingMode = float_round_nearest_even ) then
  3218. Begin
  3219. z := z + (lastBitMask shr 1);
  3220. if ( ( z and roundBitsMask ) = 0 ) then
  3221. z := z and not lastBitMask;
  3222. End
  3223. else if ( roundingMode <> float_round_to_zero ) then
  3224. Begin
  3225. if ( (extractFloat32Sign( z ) xor flag(roundingMode = float_round_up ))<>0 ) then
  3226. Begin
  3227. z := z + roundBitsMask;
  3228. End;
  3229. End;
  3230. z := z and not roundBitsMask;
  3231. if ( z <> a.float32 ) then
  3232. set_inexact_flag;
  3233. float32_round_to_int.float32 := z;
  3234. End;
  3235. {*
  3236. -------------------------------------------------------------------------------
  3237. Returns the result of adding the absolute values of the single-precision
  3238. floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  3239. before being returned. `zSign' is ignored if the result is a NaN.
  3240. The addition is performed according to the IEC/IEEE Standard for Binary
  3241. Floating-Point Arithmetic.
  3242. -------------------------------------------------------------------------------
  3243. *}
  3244. Function addFloat32Sigs( a:float32; b: float32; zSign:flag ): float32;
  3245. Var
  3246. aExp, bExp, zExp: int16;
  3247. aSig, bSig, zSig: bits32;
  3248. expDiff: int16;
  3249. label roundAndPack;
  3250. Begin
  3251. aSig:=extractFloat32Frac( a );
  3252. aExp:=extractFloat32Exp( a );
  3253. bSig:=extractFloat32Frac( b );
  3254. bExp := extractFloat32Exp( b );
  3255. expDiff := aExp - bExp;
  3256. aSig := aSig shl 6;
  3257. bSig := bSig shl 6;
  3258. if ( 0 < expDiff ) then
  3259. Begin
  3260. if ( aExp = $FF ) then
  3261. Begin
  3262. if ( aSig <> 0) then
  3263. Begin
  3264. addFloat32Sigs := propagateFloat32NaN( a, b );
  3265. exit;
  3266. End;
  3267. addFloat32Sigs := a;
  3268. exit;
  3269. End;
  3270. if ( bExp = 0 ) then
  3271. Begin
  3272. Dec(expDiff);
  3273. End
  3274. else
  3275. Begin
  3276. bSig := bSig or $20000000;
  3277. End;
  3278. shift32RightJamming( bSig, expDiff, bSig );
  3279. zExp := aExp;
  3280. End
  3281. else
  3282. If ( expDiff < 0 ) then
  3283. Begin
  3284. if ( bExp = $FF ) then
  3285. Begin
  3286. if ( bSig<>0 ) then
  3287. Begin
  3288. addFloat32Sigs := propagateFloat32NaN( a, b );
  3289. exit;
  3290. end;
  3291. addFloat32Sigs := packFloat32( zSign, $FF, 0 );
  3292. exit;
  3293. End;
  3294. if ( aExp = 0 ) then
  3295. Begin
  3296. Inc(expDiff);
  3297. End
  3298. else
  3299. Begin
  3300. aSig := aSig OR $20000000;
  3301. End;
  3302. shift32RightJamming( aSig, - expDiff, aSig );
  3303. zExp := bExp;
  3304. End
  3305. else
  3306. Begin
  3307. if ( aExp = $FF ) then
  3308. Begin
  3309. if ( aSig OR bSig )<> 0 then
  3310. Begin
  3311. addFloat32Sigs := propagateFloat32NaN( a, b );
  3312. exit;
  3313. end;
  3314. addFloat32Sigs := a;
  3315. exit;
  3316. End;
  3317. if ( aExp = 0 ) then
  3318. Begin
  3319. addFloat32Sigs := packFloat32( zSign, 0, ( aSig + bSig ) shr 6 );
  3320. exit;
  3321. end;
  3322. zSig := $40000000 + aSig + bSig;
  3323. zExp := aExp;
  3324. goto roundAndPack;
  3325. End;
  3326. aSig := aSig OR $20000000;
  3327. zSig := ( aSig + bSig ) shl 1;
  3328. Dec(zExp);
  3329. if ( sbits32 (zSig) < 0 ) then
  3330. Begin
  3331. zSig := aSig + bSig;
  3332. Inc(zExp);
  3333. End;
  3334. roundAndPack:
  3335. addFloat32Sigs := roundAndPackFloat32( zSign, zExp, zSig );
  3336. End;
  3337. {*
  3338. -------------------------------------------------------------------------------
  3339. Returns the result of subtracting the absolute values of the single-
  3340. precision floating-point values `a' and `b'. If `zSign' is 1, the
  3341. difference is negated before being returned. `zSign' is ignored if the
  3342. result is a NaN. The subtraction is performed according to the IEC/IEEE
  3343. Standard for Binary Floating-Point Arithmetic.
  3344. -------------------------------------------------------------------------------
  3345. *}
  3346. Function subFloat32Sigs( a:float32; b:float32; zSign:flag ): float32;
  3347. Var
  3348. aExp, bExp, zExp: int16;
  3349. aSig, bSig, zSig: bits32;
  3350. expDiff : int16;
  3351. label aExpBigger;
  3352. label bExpBigger;
  3353. label aBigger;
  3354. label bBigger;
  3355. label normalizeRoundAndPack;
  3356. Begin
  3357. aSig := extractFloat32Frac( a );
  3358. aExp := extractFloat32Exp( a );
  3359. bSig := extractFloat32Frac( b );
  3360. bExp := extractFloat32Exp( b );
  3361. expDiff := aExp - bExp;
  3362. aSig := aSig shl 7;
  3363. bSig := bSig shl 7;
  3364. if ( 0 < expDiff ) then goto aExpBigger;
  3365. if ( expDiff < 0 ) then goto bExpBigger;
  3366. if ( aExp = $FF ) then
  3367. Begin
  3368. if ( aSig OR bSig )<> 0 then
  3369. Begin
  3370. subFloat32Sigs := propagateFloat32NaN( a, b );
  3371. exit;
  3372. End;
  3373. float_raise( float_flag_invalid );
  3374. subFloat32Sigs := float32_default_nan;
  3375. exit;
  3376. End;
  3377. if ( aExp = 0 ) then
  3378. Begin
  3379. aExp := 1;
  3380. bExp := 1;
  3381. End;
  3382. if ( bSig < aSig ) Then goto aBigger;
  3383. if ( aSig < bSig ) Then goto bBigger;
  3384. subFloat32Sigs := packFloat32( flag(softfloat_rounding_mode = float_round_down), 0, 0 );
  3385. exit;
  3386. bExpBigger:
  3387. if ( bExp = $FF ) then
  3388. Begin
  3389. if ( bSig<>0 ) then
  3390. Begin
  3391. subFloat32Sigs := propagateFloat32NaN( a, b );
  3392. exit;
  3393. End;
  3394. subFloat32Sigs := packFloat32( zSign XOR 1, $FF, 0 );
  3395. exit;
  3396. End;
  3397. if ( aExp = 0 ) then
  3398. Begin
  3399. Inc(expDiff);
  3400. End
  3401. else
  3402. Begin
  3403. aSig := aSig OR $40000000;
  3404. End;
  3405. shift32RightJamming( aSig, - expDiff, aSig );
  3406. bSig := bSig OR $40000000;
  3407. bBigger:
  3408. zSig := bSig - aSig;
  3409. zExp := bExp;
  3410. zSign := zSign xor 1;
  3411. goto normalizeRoundAndPack;
  3412. aExpBigger:
  3413. if ( aExp = $FF ) then
  3414. Begin
  3415. if ( aSig <> 0) then
  3416. Begin
  3417. subFloat32Sigs := propagateFloat32NaN( a, b );
  3418. exit;
  3419. End;
  3420. subFloat32Sigs := a;
  3421. exit;
  3422. End;
  3423. if ( bExp = 0 ) then
  3424. Begin
  3425. Dec(expDiff);
  3426. End
  3427. else
  3428. Begin
  3429. bSig := bSig OR $40000000;
  3430. End;
  3431. shift32RightJamming( bSig, expDiff, bSig );
  3432. aSig := aSig OR $40000000;
  3433. aBigger:
  3434. zSig := aSig - bSig;
  3435. zExp := aExp;
  3436. normalizeRoundAndPack:
  3437. Dec(zExp);
  3438. subFloat32Sigs := normalizeRoundAndPackFloat32( zSign, zExp, zSig );
  3439. End;
  3440. {*
  3441. -------------------------------------------------------------------------------
  3442. Returns the result of adding the single-precision floating-point values `a'
  3443. and `b'. The operation is performed according to the IEC/IEEE Standard for
  3444. Binary Floating-Point Arithmetic.
  3445. -------------------------------------------------------------------------------
  3446. *}
  3447. Function float32_add( a: float32rec; b:float32rec ): float32rec; compilerproc;
  3448. Var
  3449. aSign, bSign: Flag;
  3450. Begin
  3451. aSign := extractFloat32Sign( a.float32 );
  3452. bSign := extractFloat32Sign( b.float32 );
  3453. if ( aSign = bSign ) then
  3454. Begin
  3455. float32_add.float32 := addFloat32Sigs( a.float32, b.float32, aSign );
  3456. End
  3457. else
  3458. Begin
  3459. float32_add.float32 := subFloat32Sigs( a.float32, b.float32, aSign );
  3460. End;
  3461. End;
  3462. {*
  3463. -------------------------------------------------------------------------------
  3464. Returns the result of subtracting the single-precision floating-point values
  3465. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  3466. for Binary Floating-Point Arithmetic.
  3467. -------------------------------------------------------------------------------
  3468. *}
  3469. Function float32_sub( a: float32rec ; b:float32rec ): float32rec;compilerproc;
  3470. Var
  3471. aSign, bSign: flag;
  3472. Begin
  3473. aSign := extractFloat32Sign( a.float32 );
  3474. bSign := extractFloat32Sign( b.float32 );
  3475. if ( aSign = bSign ) then
  3476. Begin
  3477. float32_sub.float32 := subFloat32Sigs( a.float32, b.float32, aSign );
  3478. End
  3479. else
  3480. Begin
  3481. float32_sub.float32 := addFloat32Sigs( a.float32, b.float32, aSign );
  3482. End;
  3483. End;
  3484. {*
  3485. -------------------------------------------------------------------------------
  3486. Returns the result of multiplying the single-precision floating-point values
  3487. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  3488. for Binary Floating-Point Arithmetic.
  3489. -------------------------------------------------------------------------------
  3490. *}
  3491. Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc;
  3492. Var
  3493. aSign, bSign, zSign: flag;
  3494. aExp, bExp, zExp : int16;
  3495. aSig, bSig, zSig0, zSig1: bits32;
  3496. Begin
  3497. aSig := extractFloat32Frac( a.float32 );
  3498. aExp := extractFloat32Exp( a.float32 );
  3499. aSign := extractFloat32Sign( a.float32 );
  3500. bSig := extractFloat32Frac( b.float32 );
  3501. bExp := extractFloat32Exp( b.float32 );
  3502. bSign := extractFloat32Sign( b.float32 );
  3503. zSign := aSign xor bSign;
  3504. if ( aExp = $FF ) then
  3505. Begin
  3506. if ( (aSig<>0) OR ( ( bExp = $FF ) AND (bSig<>0) ) ) then
  3507. Begin
  3508. float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3509. exit;
  3510. End;
  3511. if ( ( bits32(bExp) OR bSig ) = 0 ) then
  3512. Begin
  3513. float_raise( float_flag_invalid );
  3514. float32_mul.float32 := float32_default_nan;
  3515. exit;
  3516. End;
  3517. float32_mul.float32 := packFloat32( zSign, $FF, 0 );
  3518. exit;
  3519. End;
  3520. if ( bExp = $FF ) then
  3521. Begin
  3522. if ( bSig <> 0 ) then
  3523. Begin
  3524. float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3525. exit;
  3526. End;
  3527. if ( ( bits32(aExp) OR aSig ) = 0 ) then
  3528. Begin
  3529. float_raise( float_flag_invalid );
  3530. float32_mul.float32 := float32_default_nan;
  3531. exit;
  3532. End;
  3533. float32_mul.float32 := packFloat32( zSign, $FF, 0 );
  3534. exit;
  3535. End;
  3536. if ( aExp = 0 ) then
  3537. Begin
  3538. if ( aSig = 0 ) then
  3539. Begin
  3540. float32_mul.float32 := packFloat32( zSign, 0, 0 );
  3541. exit;
  3542. End;
  3543. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3544. End;
  3545. if ( bExp = 0 ) then
  3546. Begin
  3547. if ( bSig = 0 ) then
  3548. Begin
  3549. float32_mul.float32 := packFloat32( zSign, 0, 0 );
  3550. exit;
  3551. End;
  3552. normalizeFloat32Subnormal( bSig, bExp, bSig );
  3553. End;
  3554. zExp := aExp + bExp - $7F;
  3555. aSig := ( aSig OR $00800000 ) shl 7;
  3556. bSig := ( bSig OR $00800000 ) shl 8;
  3557. mul32To64( aSig, bSig, zSig0, zSig1 );
  3558. zSig0 := zSig0 OR bits32( zSig1 <> 0 );
  3559. if ( 0 <= sbits32 ( zSig0 shl 1 ) ) then
  3560. Begin
  3561. zSig0 := zSig0 shl 1;
  3562. Dec(zExp);
  3563. End;
  3564. float32_mul.float32 := roundAndPackFloat32( zSign, zExp, zSig0 );
  3565. End;
  3566. {*
  3567. -------------------------------------------------------------------------------
  3568. Returns the result of dividing the single-precision floating-point value `a'
  3569. by the corresponding value `b'. The operation is performed according to the
  3570. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3571. -------------------------------------------------------------------------------
  3572. *}
  3573. Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc;
  3574. Var
  3575. aSign, bSign, zSign: flag;
  3576. aExp, bExp, zExp: int16;
  3577. aSig, bSig, zSig, rem0, rem1, term0, term1: bits32;
  3578. Begin
  3579. aSig := extractFloat32Frac( a.float32 );
  3580. aExp := extractFloat32Exp( a.float32 );
  3581. aSign := extractFloat32Sign( a.float32 );
  3582. bSig := extractFloat32Frac( b.float32 );
  3583. bExp := extractFloat32Exp( b.float32 );
  3584. bSign := extractFloat32Sign( b.float32 );
  3585. zSign := aSign xor bSign;
  3586. if ( aExp = $FF ) then
  3587. Begin
  3588. if ( aSig <> 0 ) then
  3589. Begin
  3590. float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3591. exit;
  3592. End;
  3593. if ( bExp = $FF ) then
  3594. Begin
  3595. if ( bSig <> 0) then
  3596. Begin
  3597. float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3598. exit;
  3599. End;
  3600. float_raise( float_flag_invalid );
  3601. float32_div.float32 := float32_default_nan;
  3602. exit;
  3603. End;
  3604. float32_div.float32 := packFloat32( zSign, $FF, 0 );
  3605. exit;
  3606. End;
  3607. if ( bExp = $FF ) then
  3608. Begin
  3609. if ( bSig <> 0) then
  3610. Begin
  3611. float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3612. exit;
  3613. End;
  3614. float32_div.float32 := packFloat32( zSign, 0, 0 );
  3615. exit;
  3616. End;
  3617. if ( bExp = 0 ) Then
  3618. Begin
  3619. if ( bSig = 0 ) Then
  3620. Begin
  3621. if ( ( bits32(aExp) OR aSig ) = 0 ) then
  3622. Begin
  3623. float_raise( float_flag_invalid );
  3624. float32_div.float32 := float32_default_nan;
  3625. exit;
  3626. End;
  3627. float_raise( float_flag_divbyzero );
  3628. float32_div.float32 := packFloat32( zSign, $FF, 0 );
  3629. exit;
  3630. End;
  3631. normalizeFloat32Subnormal( bSig, bExp, bSig );
  3632. End;
  3633. if ( aExp = 0 ) Then
  3634. Begin
  3635. if ( aSig = 0 ) Then
  3636. Begin
  3637. float32_div.float32 := packFloat32( zSign, 0, 0 );
  3638. exit;
  3639. End;
  3640. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3641. End;
  3642. zExp := aExp - bExp + $7D;
  3643. aSig := ( aSig OR $00800000 ) shl 7;
  3644. bSig := ( bSig OR $00800000 ) shl 8;
  3645. if ( bSig <= ( aSig + aSig ) ) then
  3646. Begin
  3647. aSig := aSig shr 1;
  3648. Inc(zExp);
  3649. End;
  3650. zSig := estimateDiv64To32( aSig, 0, bSig );
  3651. if ( ( zSig and $3F ) <= 2 ) then
  3652. Begin
  3653. mul32To64( bSig, zSig, term0, term1 );
  3654. sub64( aSig, 0, term0, term1, rem0, rem1 );
  3655. while ( sbits32 (rem0) < 0 ) do
  3656. Begin
  3657. Dec(zSig);
  3658. add64( rem0, rem1, 0, bSig, rem0, rem1 );
  3659. End;
  3660. zSig := zSig or bits32( rem1 <> 0 );
  3661. End;
  3662. float32_div.float32 := roundAndPackFloat32( zSign, zExp, zSig );
  3663. End;
  3664. {*
  3665. -------------------------------------------------------------------------------
  3666. Returns the remainder of the single-precision floating-point value `a'
  3667. with respect to the corresponding value `b'. The operation is performed
  3668. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3669. -------------------------------------------------------------------------------
  3670. *}
  3671. Function float32_rem(a: float32rec; b: float32rec ):float32rec; compilerproc;
  3672. Var
  3673. aSign, zSign: flag;
  3674. aExp, bExp, expDiff: int16;
  3675. aSig, bSig, q, alternateASig: bits32;
  3676. sigMean: sbits32;
  3677. Begin
  3678. aSig := extractFloat32Frac( a.float32 );
  3679. aExp := extractFloat32Exp( a.float32 );
  3680. aSign := extractFloat32Sign( a.float32 );
  3681. bSig := extractFloat32Frac( b.float32 );
  3682. bExp := extractFloat32Exp( b.float32 );
  3683. if ( aExp = $FF ) then
  3684. Begin
  3685. if ( (aSig<>0) OR ( ( bExp = $FF ) AND (bSig <>0)) ) then
  3686. Begin
  3687. float32_rem.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3688. exit;
  3689. End;
  3690. float_raise( float_flag_invalid );
  3691. float32_rem.float32 := float32_default_nan;
  3692. exit;
  3693. End;
  3694. if ( bExp = $FF ) then
  3695. Begin
  3696. if ( bSig <> 0 ) then
  3697. Begin
  3698. float32_rem.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3699. exit;
  3700. End;
  3701. float32_rem := a;
  3702. exit;
  3703. End;
  3704. if ( bExp = 0 ) then
  3705. Begin
  3706. if ( bSig = 0 ) then
  3707. Begin
  3708. float_raise( float_flag_invalid );
  3709. float32_rem.float32 := float32_default_nan;
  3710. exit;
  3711. End;
  3712. normalizeFloat32Subnormal( bSig, bExp, bSig );
  3713. End;
  3714. if ( aExp = 0 ) then
  3715. Begin
  3716. if ( aSig = 0 ) then
  3717. Begin
  3718. float32_rem := a;
  3719. exit;
  3720. End;
  3721. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3722. End;
  3723. expDiff := aExp - bExp;
  3724. aSig := ( aSig OR $00800000 ) shl 8;
  3725. bSig := ( bSig OR $00800000 ) shl 8;
  3726. if ( expDiff < 0 ) then
  3727. Begin
  3728. if ( expDiff < -1 ) then
  3729. Begin
  3730. float32_rem := a;
  3731. exit;
  3732. End;
  3733. aSig := aSig shr 1;
  3734. End;
  3735. q := bits32( bSig <= aSig );
  3736. if ( q <> 0) then
  3737. aSig := aSig - bSig;
  3738. expDiff := expDiff - 32;
  3739. while ( 0 < expDiff ) do
  3740. Begin
  3741. q := estimateDiv64To32( aSig, 0, bSig );
  3742. if (2 < q) then
  3743. q := q - 2
  3744. else
  3745. q := 0;
  3746. aSig := - ( ( bSig shr 2 ) * q );
  3747. expDiff := expDiff - 30;
  3748. End;
  3749. expDiff := expDiff + 32;
  3750. if ( 0 < expDiff ) then
  3751. Begin
  3752. q := estimateDiv64To32( aSig, 0, bSig );
  3753. if (2 < q) then
  3754. q := q - 2
  3755. else
  3756. q := 0;
  3757. q := q shr (32 - expDiff);
  3758. bSig := bSig shr 2;
  3759. aSig := ( ( aSig shr 1 ) shl ( expDiff - 1 ) ) - bSig * q;
  3760. End
  3761. else
  3762. Begin
  3763. aSig := aSig shr 2;
  3764. bSig := bSig shr 2;
  3765. End;
  3766. Repeat
  3767. alternateASig := aSig;
  3768. Inc(q);
  3769. aSig := aSig - bSig;
  3770. Until not ( 0 <= sbits32 (aSig) );
  3771. sigMean := aSig + alternateASig;
  3772. if ( ( sigMean < 0 ) OR ( ( sigMean = 0 ) AND (( q and 1 )<>0) ) ) then
  3773. Begin
  3774. aSig := alternateASig;
  3775. End;
  3776. zSign := flag( sbits32 (aSig) < 0 );
  3777. if ( zSign<>0 ) then
  3778. aSig := - aSig;
  3779. float32_rem.float32 := normalizeRoundAndPackFloat32( aSign xor zSign, bExp, aSig );
  3780. End;
  3781. {*
  3782. -------------------------------------------------------------------------------
  3783. Returns the square root of the single-precision floating-point value `a'.
  3784. The operation is performed according to the IEC/IEEE Standard for Binary
  3785. Floating-Point Arithmetic.
  3786. -------------------------------------------------------------------------------
  3787. *}
  3788. Function float32_sqrt(a: float32rec ): float32rec;compilerproc;
  3789. Var
  3790. aSign : flag;
  3791. aExp, zExp : int16;
  3792. aSig, zSig, rem0, rem1, term0, term1: bits32;
  3793. label roundAndPack;
  3794. Begin
  3795. aSig := extractFloat32Frac( a.float32 );
  3796. aExp := extractFloat32Exp( a.float32 );
  3797. aSign := extractFloat32Sign( a.float32 );
  3798. if ( aExp = $FF ) then
  3799. Begin
  3800. if ( aSig <> 0) then
  3801. Begin
  3802. float32_sqrt.float32 := propagateFloat32NaN( a.float32, 0 );
  3803. exit;
  3804. End;
  3805. if ( aSign = 0) then
  3806. Begin
  3807. float32_sqrt := a;
  3808. exit;
  3809. End;
  3810. float_raise( float_flag_invalid );
  3811. float32_sqrt.float32 := float32_default_nan;
  3812. exit;
  3813. End;
  3814. if ( aSign <> 0) then
  3815. Begin
  3816. if ( ( bits32(aExp) OR aSig ) = 0 ) then
  3817. Begin
  3818. float32_sqrt := a;
  3819. exit;
  3820. End;
  3821. float_raise( float_flag_invalid );
  3822. float32_sqrt.float32 := float32_default_nan;
  3823. exit;
  3824. End;
  3825. if ( aExp = 0 ) then
  3826. Begin
  3827. if ( aSig = 0 ) then
  3828. Begin
  3829. float32_sqrt.float32 := 0;
  3830. exit;
  3831. End;
  3832. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3833. End;
  3834. zExp := ( ( aExp - $7F ) shr 1 ) + $7E;
  3835. aSig := ( aSig OR $00800000 ) shl 8;
  3836. zSig := estimateSqrt32( aExp, aSig ) + 2;
  3837. if ( ( zSig and $7F ) <= 5 ) then
  3838. Begin
  3839. if ( zSig < 2 ) then
  3840. Begin
  3841. zSig := $7FFFFFFF;
  3842. goto roundAndPack;
  3843. End
  3844. else
  3845. Begin
  3846. aSig := aSig shr (aExp and 1);
  3847. mul32To64( zSig, zSig, term0, term1 );
  3848. sub64( aSig, 0, term0, term1, rem0, rem1 );
  3849. while ( sbits32 (rem0) < 0 ) do
  3850. Begin
  3851. Dec(zSig);
  3852. shortShift64Left( 0, zSig, 1, term0, term1 );
  3853. term1 := term1 or 1;
  3854. add64( rem0, rem1, term0, term1, rem0, rem1 );
  3855. End;
  3856. zSig := zSig OR bits32( ( rem0 OR rem1 ) <> 0 );
  3857. End;
  3858. End;
  3859. shift32RightJamming( zSig, 1, zSig );
  3860. roundAndPack:
  3861. float32_sqrt.float32 := roundAndPackFloat32( 0, zExp, zSig );
  3862. End;
  3863. {*
  3864. -------------------------------------------------------------------------------
  3865. Returns 1 if the single-precision floating-point value `a' is equal to
  3866. the corresponding value `b', and 0 otherwise. The comparison is performed
  3867. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3868. -------------------------------------------------------------------------------
  3869. *}
  3870. Function float32_eq( a:float32rec; b:float32rec): flag; compilerproc;
  3871. Begin
  3872. if ((( extractFloat32Exp( a.float32 ) = $FF ) AND (extractFloat32Frac( a.float32 )<>0))
  3873. OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND (extractFloat32Frac( b.float32 )<>0) )
  3874. ) then
  3875. Begin
  3876. if ( (float32_is_signaling_nan( a.float32 )<>0) OR (float32_is_signaling_nan( b.float32 )<>0) ) then
  3877. Begin
  3878. float_raise( float_flag_invalid );
  3879. End;
  3880. float32_eq := 0;
  3881. exit;
  3882. End;
  3883. float32_eq := flag( a.float32 = b.float32 ) OR flag( bits32 ( ( a.float32 OR b.float32 ) shl 1 ) = 0 );
  3884. End;
  3885. {*
  3886. -------------------------------------------------------------------------------
  3887. Returns 1 if the single-precision floating-point value `a' is less than
  3888. or equal to the corresponding value `b', and 0 otherwise. The comparison
  3889. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  3890. Arithmetic.
  3891. -------------------------------------------------------------------------------
  3892. *}
  3893. Function float32_le( a: float32rec; b : float32rec ):flag;compilerproc;
  3894. var
  3895. aSign, bSign: flag;
  3896. Begin
  3897. if ( ( ( extractFloat32Exp( a.float32 ) = $FF ) AND (extractFloat32Frac( a.float32 )<>0) )
  3898. OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND (extractFloat32Frac( b.float32 )<>0) )
  3899. ) then
  3900. Begin
  3901. float_raise( float_flag_invalid );
  3902. float32_le := 0;
  3903. exit;
  3904. End;
  3905. aSign := extractFloat32Sign( a.float32 );
  3906. bSign := extractFloat32Sign( b.float32 );
  3907. if ( aSign <> bSign ) then
  3908. Begin
  3909. float32_le := aSign OR flag( bits32 ( ( a.float32 OR b.float32 ) shl 1 ) = 0 );
  3910. exit;
  3911. End;
  3912. float32_le := flag(flag( a.float32 = b.float32 ) OR flag( aSign xor flag( a.float32 < b.float32 ) ));
  3913. End;
  3914. {*
  3915. -------------------------------------------------------------------------------
  3916. Returns 1 if the single-precision floating-point value `a' is less than
  3917. the corresponding value `b', and 0 otherwise. The comparison is performed
  3918. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3919. -------------------------------------------------------------------------------
  3920. *}
  3921. Function float32_lt( a:float32rec ; b : float32rec): flag; compilerproc;
  3922. var
  3923. aSign, bSign: flag;
  3924. Begin
  3925. if ( ( ( extractFloat32Exp( a.float32 ) = $FF ) AND (extractFloat32Frac( a.float32 ) <>0))
  3926. OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND (extractFloat32Frac( b.float32 ) <>0) )
  3927. ) then
  3928. Begin
  3929. float_raise( float_flag_invalid );
  3930. float32_lt :=0;
  3931. exit;
  3932. End;
  3933. aSign := extractFloat32Sign( a.float32 );
  3934. bSign := extractFloat32Sign( b.float32 );
  3935. if ( aSign <> bSign ) then
  3936. Begin
  3937. float32_lt := aSign AND flag( bits32 ( ( a.float32 OR b.float32 ) shl 1 ) <> 0 );
  3938. exit;
  3939. End;
  3940. float32_lt := flag(flag( a.float32 <> b.float32 ) AND flag( aSign xor flag( a.float32 < b.float32 ) ));
  3941. End;
  3942. {*
  3943. -------------------------------------------------------------------------------
  3944. Returns 1 if the single-precision floating-point value `a' is equal to
  3945. the corresponding value `b', and 0 otherwise. The invalid exception is
  3946. raised if either operand is a NaN. Otherwise, the comparison is performed
  3947. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3948. -------------------------------------------------------------------------------
  3949. *}
  3950. Function float32_eq_signaling( a: float32; b: float32) : flag;
  3951. Begin
  3952. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a ) <> 0))
  3953. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b ) <> 0))
  3954. ) then
  3955. Begin
  3956. float_raise( float_flag_invalid );
  3957. float32_eq_signaling := 0;
  3958. exit;
  3959. End;
  3960. float32_eq_signaling := (flag( a = b ) OR flag( bits32 ( ( a OR b ) shl 1 ) = 0 ));
  3961. End;
  3962. {*
  3963. -------------------------------------------------------------------------------
  3964. Returns 1 if the single-precision floating-point value `a' is less than or
  3965. equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  3966. cause an exception. Otherwise, the comparison is performed according to the
  3967. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3968. -------------------------------------------------------------------------------
  3969. *}
  3970. Function float32_le_quiet( a: float32 ; b : float32 ): flag;
  3971. Var
  3972. aSign, bSign: flag;
  3973. Begin
  3974. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a )<>0) )
  3975. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b )<>0) )
  3976. ) then
  3977. Begin
  3978. if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
  3979. Begin
  3980. float_raise( float_flag_invalid );
  3981. End;
  3982. float32_le_quiet := 0;
  3983. exit;
  3984. End;
  3985. aSign := extractFloat32Sign( a );
  3986. bSign := extractFloat32Sign( b );
  3987. if ( aSign <> bSign ) then
  3988. Begin
  3989. float32_le_quiet := aSign OR flag( bits32 ( ( a OR b ) shl 1 ) = 0 );
  3990. exit;
  3991. End;
  3992. float32_le_quiet := flag(flag( a = b ) OR flag( aSign xor flag( a < b ) ));
  3993. End;
  3994. {*
  3995. -------------------------------------------------------------------------------
  3996. Returns 1 if the single-precision floating-point value `a' is less than
  3997. the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  3998. exception. Otherwise, the comparison is performed according to the IEC/IEEE
  3999. Standard for Binary Floating-Point Arithmetic.
  4000. -------------------------------------------------------------------------------
  4001. *}
  4002. Function float32_lt_quiet( a: float32 ; b: float32 ): flag;
  4003. Var
  4004. aSign, bSign: flag;
  4005. Begin
  4006. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a )<>0) )
  4007. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b )<>0) )
  4008. ) then
  4009. Begin
  4010. if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
  4011. Begin
  4012. float_raise( float_flag_invalid );
  4013. End;
  4014. float32_lt_quiet := 0;
  4015. exit;
  4016. End;
  4017. aSign := extractFloat32Sign( a );
  4018. bSign := extractFloat32Sign( b );
  4019. if ( aSign <> bSign ) then
  4020. Begin
  4021. float32_lt_quiet := aSign AND flag( bits32 ( ( a OR b ) shl 1 ) <> 0 );
  4022. exit;
  4023. End;
  4024. float32_lt_quiet := flag(flag( a <> b ) AND ( aSign xor flag( a < b ) ));
  4025. End;
  4026. {*
  4027. -------------------------------------------------------------------------------
  4028. Returns the result of converting the double-precision floating-point value
  4029. `a' to the 32-bit two's complement integer format. The conversion is
  4030. performed according to the IEC/IEEE Standard for Binary Floating-Point
  4031. Arithmetic---which means in particular that the conversion is rounded
  4032. according to the current rounding mode. If `a' is a NaN, the largest
  4033. positive integer is returned. Otherwise, if the conversion overflows, the
  4034. largest integer with the same sign as `a' is returned.
  4035. -------------------------------------------------------------------------------
  4036. *}
  4037. Function float64_to_int32(a: float64): int32;{$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32'];compilerproc;{$endif}
  4038. var
  4039. aSign: flag;
  4040. aExp, shiftCount: int16;
  4041. aSig0, aSig1, absZ, aSigExtra: bits32;
  4042. z: int32;
  4043. roundingMode: TFPURoundingMode;
  4044. label invalid;
  4045. Begin
  4046. aSig1 := extractFloat64Frac1( a );
  4047. aSig0 := extractFloat64Frac0( a );
  4048. aExp := extractFloat64Exp( a );
  4049. aSign := extractFloat64Sign( a );
  4050. shiftCount := aExp - $413;
  4051. if ( 0 <= shiftCount ) then
  4052. Begin
  4053. if ( $41E < aExp ) then
  4054. Begin
  4055. if ( ( aExp = $7FF ) AND (( aSig0 OR aSig1 )<>0) ) then
  4056. aSign := 0;
  4057. goto invalid;
  4058. End;
  4059. shortShift64Left(
  4060. aSig0 OR $00100000, aSig1, shiftCount, absZ, aSigExtra );
  4061. if ( $80000000 < absZ ) then
  4062. goto invalid;
  4063. End
  4064. else
  4065. Begin
  4066. aSig1 := flag( aSig1 <> 0 );
  4067. if ( aExp < $3FE ) then
  4068. Begin
  4069. aSigExtra := aExp OR aSig0 OR aSig1;
  4070. absZ := 0;
  4071. End
  4072. else
  4073. Begin
  4074. aSig0 := aSig0 OR $00100000;
  4075. aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR aSig1;
  4076. absZ := aSig0 shr ( - shiftCount );
  4077. End;
  4078. End;
  4079. roundingMode := softfloat_rounding_mode;
  4080. if ( roundingMode = float_round_nearest_even ) then
  4081. Begin
  4082. if ( sbits32(aSigExtra) < 0 ) then
  4083. Begin
  4084. Inc(absZ);
  4085. if ( bits32 ( aSigExtra shl 1 ) = 0 ) then
  4086. absZ := absZ and not 1;
  4087. End;
  4088. if aSign <> 0 then
  4089. z := - absZ
  4090. else
  4091. z := absZ;
  4092. End
  4093. else
  4094. Begin
  4095. aSigExtra := bits32( aSigExtra <> 0 );
  4096. if ( aSign <> 0) then
  4097. Begin
  4098. z := - ( absZ
  4099. + ( int32( roundingMode = float_round_down ) and aSigExtra ) );
  4100. End
  4101. else
  4102. Begin
  4103. z := absZ + ( int32( roundingMode = float_round_up ) and aSigExtra );
  4104. End
  4105. End;
  4106. if ( (( aSign xor flag( z < 0 ) )<>0) AND (z<>0) ) then
  4107. Begin
  4108. invalid:
  4109. float_raise( float_flag_invalid );
  4110. if (aSign <> 0 ) then
  4111. float64_to_int32 := sbits32 ($80000000)
  4112. else
  4113. float64_to_int32 := $7FFFFFFF;
  4114. exit;
  4115. End;
  4116. if ( aSigExtra <> 0) then
  4117. set_inexact_flag;
  4118. float64_to_int32 := z;
  4119. End;
  4120. {*
  4121. -------------------------------------------------------------------------------
  4122. Returns the result of converting the double-precision floating-point value
  4123. `a' to the 32-bit two's complement integer format. The conversion is
  4124. performed according to the IEC/IEEE Standard for Binary Floating-Point
  4125. Arithmetic, except that the conversion is always rounded toward zero.
  4126. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  4127. the conversion overflows, the largest integer with the same sign as `a' is
  4128. returned.
  4129. -------------------------------------------------------------------------------
  4130. *}
  4131. Function float64_to_int32_round_to_zero(a: float64 ): int32;
  4132. {$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32_ROUND_TO_ZERO'];compilerproc;{$endif}
  4133. Var
  4134. aSign: flag;
  4135. aExp, shiftCount: int16;
  4136. aSig0, aSig1, absZ, aSigExtra: bits32;
  4137. z: int32;
  4138. label invalid;
  4139. Begin
  4140. aSig1 := extractFloat64Frac1( a );
  4141. aSig0 := extractFloat64Frac0( a );
  4142. aExp := extractFloat64Exp( a );
  4143. aSign := extractFloat64Sign( a );
  4144. shiftCount := aExp - $413;
  4145. if ( 0 <= shiftCount ) then
  4146. Begin
  4147. if ( $41E < aExp ) then
  4148. Begin
  4149. if ( ( aExp = $7FF ) AND (( aSig0 OR aSig1 )<>0) ) then
  4150. aSign := 0;
  4151. goto invalid;
  4152. End;
  4153. shortShift64Left(
  4154. aSig0 OR $00100000, aSig1, shiftCount, absZ, aSigExtra );
  4155. End
  4156. else
  4157. Begin
  4158. if ( aExp < $3FF ) then
  4159. Begin
  4160. if ( bits32(aExp) OR aSig0 OR aSig1 )<>0 then
  4161. Begin
  4162. set_inexact_flag;
  4163. End;
  4164. float64_to_int32_round_to_zero := 0;
  4165. exit;
  4166. End;
  4167. aSig0 := aSig0 or $00100000;
  4168. aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR aSig1;
  4169. absZ := aSig0 shr ( - shiftCount );
  4170. End;
  4171. if aSign <> 0 then
  4172. z := - absZ
  4173. else
  4174. z := absZ;
  4175. if ( (( aSign xor flag( z < 0 )) <> 0) AND (z<>0) ) then
  4176. Begin
  4177. invalid:
  4178. float_raise( float_flag_invalid );
  4179. if (aSign <> 0) then
  4180. float64_to_int32_round_to_zero := sbits32 ($80000000)
  4181. else
  4182. float64_to_int32_round_to_zero := $7FFFFFFF;
  4183. exit;
  4184. End;
  4185. if ( aSigExtra <> 0) then
  4186. set_inexact_flag;
  4187. float64_to_int32_round_to_zero := z;
  4188. End;
  4189. {*----------------------------------------------------------------------------
  4190. | Returns the result of converting the double-precision floating-point value
  4191. | `a' to the 64-bit two's complement integer format. The conversion is
  4192. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  4193. | Arithmetic---which means in particular that the conversion is rounded
  4194. | according to the current rounding mode. If `a' is a NaN, the largest
  4195. | positive integer is returned. Otherwise, if the conversion overflows, the
  4196. | largest integer with the same sign as `a' is returned.
  4197. *----------------------------------------------------------------------------*}
  4198. function float64_to_int64( a: float64 ): int64;
  4199. var
  4200. aSign: flag;
  4201. aExp, shiftCount: int16;
  4202. aSig, aSigExtra: bits64;
  4203. begin
  4204. aSig := extractFloat64Frac( a );
  4205. aExp := extractFloat64Exp( a );
  4206. aSign := extractFloat64Sign( a );
  4207. if ( aExp <> 0 ) then aSig := aSig or $0010000000000000;
  4208. shiftCount := $433 - aExp;
  4209. if ( shiftCount <= 0 ) then begin
  4210. if ( $43E < aExp ) then begin
  4211. float_raise( float_flag_invalid );
  4212. if ( ( aSign = 0 )
  4213. or ( ( aExp = $7FF )
  4214. and ( aSig <> $0010000000000000 ) )
  4215. ) then begin
  4216. result := $7FFFFFFFFFFFFFFF;
  4217. exit;
  4218. end;
  4219. result := $8000000000000000;
  4220. exit;
  4221. end;
  4222. aSigExtra := 0;
  4223. aSig := aSig shl ( - shiftCount );
  4224. end
  4225. else
  4226. shift64ExtraRightJamming( aSig, 0, shiftCount, aSig, aSigExtra );
  4227. result := roundAndPackInt64( aSign, aSig, aSigExtra );
  4228. end;
  4229. {*----------------------------------------------------------------------------
  4230. | Returns the result of converting the double-precision floating-point value
  4231. | `a' to the 64-bit two's complement integer format. The conversion is
  4232. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  4233. | Arithmetic, except that the conversion is always rounded toward zero.
  4234. | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  4235. | the conversion overflows, the largest integer with the same sign as `a' is
  4236. | returned.
  4237. *----------------------------------------------------------------------------*}
  4238. {$define FPC_SYSTEM_HAS_float64_to_int64_round_to_zero}
  4239. function float64_to_int64_round_to_zero( a: float64 ): int64;
  4240. var
  4241. aSign: flag;
  4242. aExp, shiftCount: int16;
  4243. aSig: bits64;
  4244. z: int64;
  4245. begin
  4246. aSig := extractFloat64Frac( a );
  4247. aExp := extractFloat64Exp( a );
  4248. aSign := extractFloat64Sign( a );
  4249. if ( aExp <> 0 ) then aSig := aSig or $0010000000000000;
  4250. shiftCount := aExp - $433;
  4251. if ( 0 <= shiftCount ) then begin
  4252. if ( $43E <= aExp ) then begin
  4253. if ( bits64 ( a ) <> bits64( $C3E0000000000000 ) ) then begin
  4254. float_raise( float_flag_invalid );
  4255. if ( ( aSign = 0 )
  4256. or ( ( aExp = $7FF )
  4257. and ( aSig <> $0010000000000000 ) )
  4258. ) then begin
  4259. result := $7FFFFFFFFFFFFFFF;
  4260. exit;
  4261. end;
  4262. end;
  4263. result := $8000000000000000;
  4264. exit;
  4265. end;
  4266. z := aSig shl shiftCount;
  4267. end
  4268. else begin
  4269. if ( aExp < $3FE ) then begin
  4270. if ( aExp or aSig <> 0 ) then set_inexact_flag;
  4271. result := 0;
  4272. exit;
  4273. end;
  4274. z := aSig shr ( - shiftCount );
  4275. if ( bits64( aSig shl ( shiftCount and 63 ) ) <> 0 ) then
  4276. set_inexact_flag;
  4277. end;
  4278. if ( aSign <> 0 ) then z := - z;
  4279. result := z;
  4280. end;
  4281. {*
  4282. -------------------------------------------------------------------------------
  4283. Returns the result of converting the double-precision floating-point value
  4284. `a' to the single-precision floating-point format. The conversion is
  4285. performed according to the IEC/IEEE Standard for Binary Floating-Point
  4286. Arithmetic.
  4287. -------------------------------------------------------------------------------
  4288. *}
  4289. Function float64_to_float32(a: float64 ): float32rec;compilerproc;
  4290. Var
  4291. aSign: flag;
  4292. aExp: int16;
  4293. aSig0, aSig1, zSig: bits32;
  4294. allZero: bits32;
  4295. tmp : CommonNanT;
  4296. Begin
  4297. aSig1 := extractFloat64Frac1( a );
  4298. aSig0 := extractFloat64Frac0( a );
  4299. aExp := extractFloat64Exp( a );
  4300. aSign := extractFloat64Sign( a );
  4301. if ( aExp = $7FF ) then
  4302. Begin
  4303. if ( aSig0 OR aSig1 ) <> 0 then
  4304. Begin
  4305. float64ToCommonNaN( a, tmp );
  4306. float64_to_float32.float32 := commonNaNToFloat32( tmp );
  4307. exit;
  4308. End;
  4309. float64_to_float32.float32 := packFloat32( aSign, $FF, 0 );
  4310. exit;
  4311. End;
  4312. shift64RightJamming( aSig0, aSig1, 22, allZero, zSig );
  4313. if ( aExp <> 0) then
  4314. zSig := zSig OR $40000000;
  4315. float64_to_float32.float32 := roundAndPackFloat32( aSign, aExp - $381, zSig );
  4316. End;
  4317. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  4318. {*----------------------------------------------------------------------------
  4319. | Returns the result of converting the double-precision floating-point value
  4320. | `a' to the extended double-precision floating-point format. The conversion
  4321. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  4322. | Arithmetic.
  4323. *----------------------------------------------------------------------------*}
  4324. function float64_to_floatx80( a: float64 ): floatx80;
  4325. var
  4326. aSign: flag;
  4327. aExp: int16;
  4328. aSig: bits64;
  4329. begin
  4330. aSig := extractFloat64Frac( a );
  4331. aExp := extractFloat64Exp( a );
  4332. aSign := extractFloat64Sign( a );
  4333. if ( aExp = $7FF ) then begin
  4334. if ( aSig <> 0 ) then begin
  4335. result := commonNaNToFloatx80( float64ToCommonNaN( a ) );
  4336. exit;
  4337. end;
  4338. result := packFloatx80( aSign, $7FFF, bits64( $8000000000000000 ) );
  4339. exit;
  4340. end;
  4341. if ( aExp = 0 ) then begin
  4342. if ( aSig = 0 ) then begin
  4343. result := packFloatx80( aSign, 0, 0 );
  4344. exit;
  4345. end;
  4346. normalizeFloat64Subnormal( aSig, aExp, aSig );
  4347. end;
  4348. result :=
  4349. packFloatx80(
  4350. aSign, aExp + $3C00, ( aSig or $0010000000000000 ) shl 11 );
  4351. end;
  4352. {$endif FPC_SOFTFLOAT_FLOATX80}
  4353. {*
  4354. -------------------------------------------------------------------------------
  4355. Rounds the double-precision floating-point value `a' to an integer,
  4356. and returns the result as a double-precision floating-point value. The
  4357. operation is performed according to the IEC/IEEE Standard for Binary
  4358. Floating-Point Arithmetic.
  4359. -------------------------------------------------------------------------------
  4360. *}
  4361. function float64_round_to_int(a: float64) : Float64;{$ifdef fpc} [public,Alias:'FLOAT64_ROUND_TO_INT'];compilerproc;{$endif}
  4362. Var
  4363. aSign: flag;
  4364. aExp: int16;
  4365. lastBitMask, roundBitsMask: bits32;
  4366. roundingMode: TFPURoundingMode;
  4367. z: float64;
  4368. Begin
  4369. aExp := extractFloat64Exp( a );
  4370. if ( $413 <= aExp ) then
  4371. Begin
  4372. if ( $433 <= aExp ) then
  4373. Begin
  4374. if ( ( aExp = $7FF )
  4375. AND
  4376. (
  4377. ( extractFloat64Frac0( a ) OR extractFloat64Frac1( a )
  4378. ) <>0)
  4379. ) then
  4380. Begin
  4381. propagateFloat64NaN( a, a, result );
  4382. exit;
  4383. End;
  4384. result := a;
  4385. exit;
  4386. End;
  4387. lastBitMask := 1;
  4388. lastBitMask := ( lastBitMask shl ( $432 - aExp ) ) shl 1;
  4389. roundBitsMask := lastBitMask - 1;
  4390. z := a;
  4391. roundingMode := softfloat_rounding_mode;
  4392. if ( roundingMode = float_round_nearest_even ) then
  4393. Begin
  4394. if ( lastBitMask <> 0) then
  4395. Begin
  4396. add64( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );
  4397. if ( ( z.low and roundBitsMask ) = 0 ) then
  4398. z.low := z.low and not lastBitMask;
  4399. End
  4400. else
  4401. Begin
  4402. if ( sbits32 (z.low) < 0 ) then
  4403. Begin
  4404. Inc(z.high);
  4405. if ( bits32 ( z.low shl 1 ) = 0 ) then
  4406. z.high := z.high and not 1;
  4407. End;
  4408. End;
  4409. End
  4410. else if ( roundingMode <> float_round_to_zero ) then
  4411. Begin
  4412. if ( extractFloat64Sign( z )
  4413. xor flag( roundingMode = float_round_up ) )<> 0 then
  4414. Begin
  4415. add64( z.high, z.low, 0, roundBitsMask, z.high, z.low );
  4416. End;
  4417. End;
  4418. z.low := z.low and not roundBitsMask;
  4419. End
  4420. else
  4421. Begin
  4422. if ( aExp <= $3FE ) then
  4423. Begin
  4424. if ( ( ( bits32 ( a.high shl 1 ) ) OR a.low ) = 0 ) then
  4425. Begin
  4426. result := a;
  4427. exit;
  4428. End;
  4429. set_inexact_flag;
  4430. aSign := extractFloat64Sign( a );
  4431. case ( softfloat_rounding_mode ) of
  4432. float_round_nearest_even:
  4433. Begin
  4434. if ( ( aExp = $3FE )
  4435. AND ( (extractFloat64Frac0( a ) OR extractFloat64Frac1( a ) )<>0)
  4436. ) then
  4437. Begin
  4438. packFloat64( aSign, $3FF, 0, 0, result );
  4439. exit;
  4440. End;
  4441. End;
  4442. float_round_down:
  4443. Begin
  4444. if aSign<>0 then
  4445. packFloat64( 1, $3FF, 0, 0, result )
  4446. else
  4447. packFloat64( 0, 0, 0, 0, result );
  4448. exit;
  4449. End;
  4450. float_round_up:
  4451. Begin
  4452. if aSign <> 0 then
  4453. packFloat64( 1, 0, 0, 0, result )
  4454. else
  4455. packFloat64( 0, $3FF, 0, 0, result );
  4456. exit;
  4457. End;
  4458. end;
  4459. packFloat64( aSign, 0, 0, 0, result );
  4460. exit;
  4461. End;
  4462. lastBitMask := 1;
  4463. lastBitMask := lastBitMask shl ($413 - aExp);
  4464. roundBitsMask := lastBitMask - 1;
  4465. z.low := 0;
  4466. z.high := a.high;
  4467. roundingMode := softfloat_rounding_mode;
  4468. if ( roundingMode = float_round_nearest_even ) then
  4469. Begin
  4470. z.high := z.high + lastBitMask shr 1;
  4471. if ( ( ( z.high and roundBitsMask ) OR a.low ) = 0 ) then
  4472. Begin
  4473. z.high := z.high and not lastBitMask;
  4474. End;
  4475. End
  4476. else if ( roundingMode <> float_round_to_zero ) then
  4477. Begin
  4478. if ( extractFloat64Sign( z )
  4479. xor flag( roundingMode = float_round_up ) )<> 0 then
  4480. Begin
  4481. z.high := z.high or bits32( a.low <> 0 );
  4482. z.high := z.high + roundBitsMask;
  4483. End;
  4484. End;
  4485. z.high := z.high and not roundBitsMask;
  4486. End;
  4487. if ( ( z.low <> a.low ) OR ( z.high <> a.high ) ) then
  4488. Begin
  4489. set_inexact_flag;
  4490. End;
  4491. result := z;
  4492. End;
  4493. {*
  4494. -------------------------------------------------------------------------------
  4495. Returns the result of adding the absolute values of the double-precision
  4496. floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  4497. before being returned. `zSign' is ignored if the result is a NaN.
  4498. The addition is performed according to the IEC/IEEE Standard for Binary
  4499. Floating-Point Arithmetic.
  4500. -------------------------------------------------------------------------------
  4501. *}
  4502. Procedure addFloat64Sigs( a:float64 ; b: float64 ; zSign:flag; Var out: float64 );
  4503. Var
  4504. aExp, bExp, zExp: int16;
  4505. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;
  4506. expDiff: int16;
  4507. label shiftRight1;
  4508. label roundAndPack;
  4509. Begin
  4510. aSig1 := extractFloat64Frac1( a );
  4511. aSig0 := extractFloat64Frac0( a );
  4512. aExp := extractFloat64Exp( a );
  4513. bSig1 := extractFloat64Frac1( b );
  4514. bSig0 := extractFloat64Frac0( b );
  4515. bExp := extractFloat64Exp( b );
  4516. expDiff := aExp - bExp;
  4517. if ( 0 < expDiff ) then
  4518. Begin
  4519. if ( aExp = $7FF ) then
  4520. Begin
  4521. if ( aSig0 OR aSig1 ) <> 0 then
  4522. Begin
  4523. propagateFloat64NaN( a, b, out );
  4524. exit;
  4525. end;
  4526. out := a;
  4527. exit;
  4528. End;
  4529. if ( bExp = 0 ) then
  4530. Begin
  4531. Dec(expDiff);
  4532. End
  4533. else
  4534. Begin
  4535. bSig0 := bSig0 or $00100000;
  4536. End;
  4537. shift64ExtraRightJamming(
  4538. bSig0, bSig1, 0, expDiff, bSig0, bSig1, zSig2 );
  4539. zExp := aExp;
  4540. End
  4541. else if ( expDiff < 0 ) then
  4542. Begin
  4543. if ( bExp = $7FF ) then
  4544. Begin
  4545. if ( bSig0 OR bSig1 ) <> 0 then
  4546. Begin
  4547. propagateFloat64NaN( a, b, out );
  4548. exit;
  4549. End;
  4550. packFloat64( zSign, $7FF, 0, 0, out );
  4551. exit;
  4552. End;
  4553. if ( aExp = 0 ) then
  4554. Begin
  4555. Inc(expDiff);
  4556. End
  4557. else
  4558. Begin
  4559. aSig0 := aSig0 or $00100000;
  4560. End;
  4561. shift64ExtraRightJamming(
  4562. aSig0, aSig1, 0, - expDiff, aSig0, aSig1, zSig2 );
  4563. zExp := bExp;
  4564. End
  4565. else
  4566. Begin
  4567. if ( aExp = $7FF ) then
  4568. Begin
  4569. if ( aSig0 OR aSig1 OR bSig0 OR bSig1 ) <> 0 then
  4570. Begin
  4571. propagateFloat64NaN( a, b, out );
  4572. exit;
  4573. End;
  4574. out := a;
  4575. exit;
  4576. End;
  4577. add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  4578. if ( aExp = 0 ) then
  4579. Begin
  4580. packFloat64( zSign, 0, zSig0, zSig1, out );
  4581. exit;
  4582. End;
  4583. zSig2 := 0;
  4584. zSig0 := zSig0 or $00200000;
  4585. zExp := aExp;
  4586. goto shiftRight1;
  4587. End;
  4588. aSig0 := aSig0 or $00100000;
  4589. add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  4590. Dec(zExp);
  4591. if ( zSig0 < $00200000 ) then
  4592. goto roundAndPack;
  4593. Inc(zExp);
  4594. shiftRight1:
  4595. shift64ExtraRightJamming( zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  4596. roundAndPack:
  4597. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, out );
  4598. End;
  4599. {*
  4600. -------------------------------------------------------------------------------
  4601. Returns the result of subtracting the absolute values of the double-
  4602. precision floating-point values `a' and `b'. If `zSign' is 1, the
  4603. difference is negated before being returned. `zSign' is ignored if the
  4604. result is a NaN. The subtraction is performed according to the IEC/IEEE
  4605. Standard for Binary Floating-Point Arithmetic.
  4606. -------------------------------------------------------------------------------
  4607. *}
  4608. Procedure subFloat64Sigs( a:float64; b: float64 ; zSign:flag; Var out: float64 );
  4609. Var
  4610. aExp, bExp, zExp: int16;
  4611. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits32;
  4612. expDiff: int16;
  4613. z: float64;
  4614. label aExpBigger;
  4615. label bExpBigger;
  4616. label aBigger;
  4617. label bBigger;
  4618. label normalizeRoundAndPack;
  4619. Begin
  4620. aSig1 := extractFloat64Frac1( a );
  4621. aSig0 := extractFloat64Frac0( a );
  4622. aExp := extractFloat64Exp( a );
  4623. bSig1 := extractFloat64Frac1( b );
  4624. bSig0 := extractFloat64Frac0( b );
  4625. bExp := extractFloat64Exp( b );
  4626. expDiff := aExp - bExp;
  4627. shortShift64Left( aSig0, aSig1, 10, aSig0, aSig1 );
  4628. shortShift64Left( bSig0, bSig1, 10, bSig0, bSig1 );
  4629. if ( 0 < expDiff ) then goto aExpBigger;
  4630. if ( expDiff < 0 ) then goto bExpBigger;
  4631. if ( aExp = $7FF ) then
  4632. Begin
  4633. if ( aSig0 OR aSig1 OR bSig0 OR bSig1 ) <> 0 then
  4634. Begin
  4635. propagateFloat64NaN( a, b, out );
  4636. exit;
  4637. End;
  4638. float_raise( float_flag_invalid );
  4639. z.low := float64_default_nan_low;
  4640. z.high := float64_default_nan_high;
  4641. out := z;
  4642. exit;
  4643. End;
  4644. if ( aExp = 0 ) then
  4645. Begin
  4646. aExp := 1;
  4647. bExp := 1;
  4648. End;
  4649. if ( bSig0 < aSig0 ) then goto aBigger;
  4650. if ( aSig0 < bSig0 ) then goto bBigger;
  4651. if ( bSig1 < aSig1 ) then goto aBigger;
  4652. if ( aSig1 < bSig1 ) then goto bBigger;
  4653. packFloat64( flag(softfloat_rounding_mode = float_round_down), 0, 0, 0 , out);
  4654. exit;
  4655. bExpBigger:
  4656. if ( bExp = $7FF ) then
  4657. Begin
  4658. if ( bSig0 OR bSig1 ) <> 0 then
  4659. Begin
  4660. propagateFloat64NaN( a, b, out );
  4661. exit;
  4662. End;
  4663. packFloat64( zSign xor 1, $7FF, 0, 0, out );
  4664. exit;
  4665. End;
  4666. if ( aExp = 0 ) then
  4667. Begin
  4668. Inc(expDiff);
  4669. End
  4670. else
  4671. Begin
  4672. aSig0 := aSig0 or $40000000;
  4673. End;
  4674. shift64RightJamming( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  4675. bSig0 := bSig0 or $40000000;
  4676. bBigger:
  4677. sub64( bSig0, bSig1, aSig0, aSig1, zSig0, zSig1 );
  4678. zExp := bExp;
  4679. zSign := zSign xor 1;
  4680. goto normalizeRoundAndPack;
  4681. aExpBigger:
  4682. if ( aExp = $7FF ) then
  4683. Begin
  4684. if ( aSig0 OR aSig1 ) <> 0 then
  4685. Begin
  4686. propagateFloat64NaN( a, b, out );
  4687. exit;
  4688. End;
  4689. out := a;
  4690. exit;
  4691. End;
  4692. if ( bExp = 0 ) then
  4693. Begin
  4694. Dec(expDiff);
  4695. End
  4696. else
  4697. Begin
  4698. bSig0 := bSig0 or $40000000;
  4699. End;
  4700. shift64RightJamming( bSig0, bSig1, expDiff, bSig0, bSig1 );
  4701. aSig0 := aSig0 or $40000000;
  4702. aBigger:
  4703. sub64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  4704. zExp := aExp;
  4705. normalizeRoundAndPack:
  4706. Dec(zExp);
  4707. normalizeRoundAndPackFloat64( zSign, zExp - 10, zSig0, zSig1, out );
  4708. End;
  4709. {*
  4710. -------------------------------------------------------------------------------
  4711. Returns the result of adding the double-precision floating-point values `a'
  4712. and `b'. The operation is performed according to the IEC/IEEE Standard for
  4713. Binary Floating-Point Arithmetic.
  4714. -------------------------------------------------------------------------------
  4715. *}
  4716. Function float64_add( a: float64; b : float64) : Float64;
  4717. {$ifdef fpc}[public,Alias:'FLOAT64_ADD'];compilerproc;{$endif}
  4718. Var
  4719. aSign, bSign: flag;
  4720. Begin
  4721. aSign := extractFloat64Sign( a );
  4722. bSign := extractFloat64Sign( b );
  4723. if ( aSign = bSign ) then
  4724. Begin
  4725. addFloat64Sigs( a, b, aSign, result );
  4726. End
  4727. else
  4728. Begin
  4729. subFloat64Sigs( a, b, aSign, result );
  4730. End;
  4731. End;
  4732. {*
  4733. -------------------------------------------------------------------------------
  4734. Returns the result of subtracting the double-precision floating-point values
  4735. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  4736. for Binary Floating-Point Arithmetic.
  4737. -------------------------------------------------------------------------------
  4738. *}
  4739. Function float64_sub(a: float64; b : float64) : Float64;
  4740. {$ifdef fpc}[public,Alias:'FLOAT64_SUB'];compilerproc;{$endif}
  4741. Var
  4742. aSign, bSign: flag;
  4743. Begin
  4744. aSign := extractFloat64Sign( a );
  4745. bSign := extractFloat64Sign( b );
  4746. if ( aSign = bSign ) then
  4747. Begin
  4748. subFloat64Sigs( a, b, aSign, result );
  4749. End
  4750. else
  4751. Begin
  4752. addFloat64Sigs( a, b, aSign, result );
  4753. End;
  4754. End;
  4755. {*
  4756. -------------------------------------------------------------------------------
  4757. Returns the result of multiplying the double-precision floating-point values
  4758. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  4759. for Binary Floating-Point Arithmetic.
  4760. -------------------------------------------------------------------------------
  4761. *}
  4762. Function float64_mul( a: float64; b:float64) : Float64;
  4763. {$ifdef fpc}[public,Alias:'FLOAT64_MUL'];compilerproc;{$endif}
  4764. Var
  4765. aSign, bSign, zSign: flag;
  4766. aExp, bExp, zExp: int16;
  4767. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits32;
  4768. z: float64;
  4769. label invalid;
  4770. Begin
  4771. aSig1 := extractFloat64Frac1( a );
  4772. aSig0 := extractFloat64Frac0( a );
  4773. aExp := extractFloat64Exp( a );
  4774. aSign := extractFloat64Sign( a );
  4775. bSig1 := extractFloat64Frac1( b );
  4776. bSig0 := extractFloat64Frac0( b );
  4777. bExp := extractFloat64Exp( b );
  4778. bSign := extractFloat64Sign( b );
  4779. zSign := aSign xor bSign;
  4780. if ( aExp = $7FF ) then
  4781. Begin
  4782. if ( (( aSig0 OR aSig1 ) <>0)
  4783. OR ( ( bExp = $7FF ) AND (( bSig0 OR bSig1 )<>0) ) ) then
  4784. Begin
  4785. propagateFloat64NaN( a, b, result );
  4786. exit;
  4787. End;
  4788. if ( ( bits32(bExp) OR bSig0 OR bSig1 ) = 0 ) then goto invalid;
  4789. packFloat64( zSign, $7FF, 0, 0, result );
  4790. exit;
  4791. End;
  4792. if ( bExp = $7FF ) then
  4793. Begin
  4794. if ( bSig0 OR bSig1 )<> 0 then
  4795. Begin
  4796. propagateFloat64NaN( a, b, result );
  4797. exit;
  4798. End;
  4799. if ( ( aExp OR aSig0 OR aSig1 ) = 0 ) then
  4800. Begin
  4801. invalid:
  4802. float_raise( float_flag_invalid );
  4803. z.low := float64_default_nan_low;
  4804. z.high := float64_default_nan_high;
  4805. result := z;
  4806. exit;
  4807. End;
  4808. packFloat64( zSign, $7FF, 0, 0, result );
  4809. exit;
  4810. End;
  4811. if ( aExp = 0 ) then
  4812. Begin
  4813. if ( ( aSig0 OR aSig1 ) = 0 ) then
  4814. Begin
  4815. packFloat64( zSign, 0, 0, 0, result );
  4816. exit;
  4817. End;
  4818. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  4819. End;
  4820. if ( bExp = 0 ) then
  4821. Begin
  4822. if ( ( bSig0 OR bSig1 ) = 0 ) then
  4823. Begin
  4824. packFloat64( zSign, 0, 0, 0, result );
  4825. exit;
  4826. End;
  4827. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  4828. End;
  4829. zExp := aExp + bExp - $400;
  4830. aSig0 := aSig0 or $00100000;
  4831. shortShift64Left( bSig0, bSig1, 12, bSig0, bSig1 );
  4832. mul64To128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3 );
  4833. add64( zSig0, zSig1, aSig0, aSig1, zSig0, zSig1 );
  4834. zSig2 := zSig2 or flag( zSig3 <> 0 );
  4835. if ( $00200000 <= zSig0 ) then
  4836. Begin
  4837. shift64ExtraRightJamming(
  4838. zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  4839. Inc(zExp);
  4840. End;
  4841. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, result );
  4842. End;
  4843. {*
  4844. -------------------------------------------------------------------------------
  4845. Returns the result of dividing the double-precision floating-point value `a'
  4846. by the corresponding value `b'. The operation is performed according to the
  4847. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4848. -------------------------------------------------------------------------------
  4849. *}
  4850. Function float64_div(a: float64; b : float64) : Float64;
  4851. {$ifdef fpc}[public,Alias:'FLOAT64_DIV'];compilerproc;{$endif}
  4852. Var
  4853. aSign, bSign, zSign: flag;
  4854. aExp, bExp, zExp: int16;
  4855. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;
  4856. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;
  4857. z: float64;
  4858. label invalid;
  4859. Begin
  4860. aSig1 := extractFloat64Frac1( a );
  4861. aSig0 := extractFloat64Frac0( a );
  4862. aExp := extractFloat64Exp( a );
  4863. aSign := extractFloat64Sign( a );
  4864. bSig1 := extractFloat64Frac1( b );
  4865. bSig0 := extractFloat64Frac0( b );
  4866. bExp := extractFloat64Exp( b );
  4867. bSign := extractFloat64Sign( b );
  4868. zSign := aSign xor bSign;
  4869. if ( aExp = $7FF ) then
  4870. Begin
  4871. if ( aSig0 OR aSig1 )<> 0 then
  4872. Begin
  4873. propagateFloat64NaN( a, b, result );
  4874. exit;
  4875. end;
  4876. if ( bExp = $7FF ) then
  4877. Begin
  4878. if ( bSig0 OR bSig1 )<>0 then
  4879. Begin
  4880. propagateFloat64NaN( a, b, result );
  4881. exit;
  4882. End;
  4883. goto invalid;
  4884. End;
  4885. packFloat64( zSign, $7FF, 0, 0, result );
  4886. exit;
  4887. End;
  4888. if ( bExp = $7FF ) then
  4889. Begin
  4890. if ( bSig0 OR bSig1 )<> 0 then
  4891. Begin
  4892. propagateFloat64NaN( a, b, result );
  4893. exit;
  4894. End;
  4895. packFloat64( zSign, 0, 0, 0, result );
  4896. exit;
  4897. End;
  4898. if ( bExp = 0 ) then
  4899. Begin
  4900. if ( ( bSig0 OR bSig1 ) = 0 ) then
  4901. Begin
  4902. if ( ( bits32(aExp) OR aSig0 OR aSig1 ) = 0 ) then
  4903. Begin
  4904. invalid:
  4905. float_raise( float_flag_invalid );
  4906. z.low := float64_default_nan_low;
  4907. z.high := float64_default_nan_high;
  4908. result := z;
  4909. exit;
  4910. End;
  4911. float_raise( float_flag_divbyzero );
  4912. packFloat64( zSign, $7FF, 0, 0, result );
  4913. exit;
  4914. End;
  4915. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  4916. End;
  4917. if ( aExp = 0 ) then
  4918. Begin
  4919. if ( ( aSig0 OR aSig1 ) = 0 ) then
  4920. Begin
  4921. packFloat64( zSign, 0, 0, 0, result );
  4922. exit;
  4923. End;
  4924. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  4925. End;
  4926. zExp := aExp - bExp + $3FD;
  4927. shortShift64Left( aSig0 OR $00100000, aSig1, 11, aSig0, aSig1 );
  4928. shortShift64Left( bSig0 OR $00100000, bSig1, 11, bSig0, bSig1 );
  4929. if ( le64( bSig0, bSig1, aSig0, aSig1 )<>0 ) then
  4930. Begin
  4931. shift64Right( aSig0, aSig1, 1, aSig0, aSig1 );
  4932. Inc(zExp);
  4933. End;
  4934. zSig0 := estimateDiv64To32( aSig0, aSig1, bSig0 );
  4935. mul64By32To96( bSig0, bSig1, zSig0, term0, term1, term2 );
  4936. sub96( aSig0, aSig1, 0, term0, term1, term2, rem0, rem1, rem2 );
  4937. while ( sbits32 (rem0) < 0 ) do
  4938. Begin
  4939. Dec(zSig0);
  4940. add96( rem0, rem1, rem2, 0, bSig0, bSig1, rem0, rem1, rem2 );
  4941. End;
  4942. zSig1 := estimateDiv64To32( rem1, rem2, bSig0 );
  4943. if ( ( zSig1 and $3FF ) <= 4 ) then
  4944. Begin
  4945. mul64By32To96( bSig0, bSig1, zSig1, term1, term2, term3 );
  4946. sub96( rem1, rem2, 0, term1, term2, term3, rem1, rem2, rem3 );
  4947. while ( sbits32 (rem1) < 0 ) do
  4948. Begin
  4949. Dec(zSig1);
  4950. add96( rem1, rem2, rem3, 0, bSig0, bSig1, rem1, rem2, rem3 );
  4951. End;
  4952. zSig1 := zSig1 or flag( ( rem1 OR rem2 OR rem3 ) <> 0 );
  4953. End;
  4954. shift64ExtraRightJamming( zSig0, zSig1, 0, 11, zSig0, zSig1, zSig2 );
  4955. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, result );
  4956. End;
  4957. {*
  4958. -------------------------------------------------------------------------------
  4959. Returns the remainder of the double-precision floating-point value `a'
  4960. with respect to the corresponding value `b'. The operation is performed
  4961. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4962. -------------------------------------------------------------------------------
  4963. *}
  4964. Function float64_rem(a: float64; b : float64) : float64;
  4965. {$ifdef fpc}[public,Alias:'FLOAT64_REM'];compilerproc;{$endif}
  4966. Var
  4967. aSign, zSign: flag;
  4968. aExp, bExp, expDiff: int16;
  4969. aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits32;
  4970. allZero, alternateASig0, alternateASig1, sigMean1: bits32;
  4971. sigMean0: sbits32;
  4972. z: float64;
  4973. label invalid;
  4974. Begin
  4975. aSig1 := extractFloat64Frac1( a );
  4976. aSig0 := extractFloat64Frac0( a );
  4977. aExp := extractFloat64Exp( a );
  4978. aSign := extractFloat64Sign( a );
  4979. bSig1 := extractFloat64Frac1( b );
  4980. bSig0 := extractFloat64Frac0( b );
  4981. bExp := extractFloat64Exp( b );
  4982. if ( aExp = $7FF ) then
  4983. Begin
  4984. if ((( aSig0 OR aSig1 )<>0)
  4985. OR ( ( bExp = $7FF ) AND (( bSig0 OR bSig1 )<>0) ) ) then
  4986. Begin
  4987. propagateFloat64NaN( a, b, result );
  4988. exit;
  4989. End;
  4990. goto invalid;
  4991. End;
  4992. if ( bExp = $7FF ) then
  4993. Begin
  4994. if ( bSig0 OR bSig1 ) <> 0 then
  4995. Begin
  4996. propagateFloat64NaN( a, b, result );
  4997. exit;
  4998. End;
  4999. result := a;
  5000. exit;
  5001. End;
  5002. if ( bExp = 0 ) then
  5003. Begin
  5004. if ( ( bSig0 OR bSig1 ) = 0 ) then
  5005. Begin
  5006. invalid:
  5007. float_raise( float_flag_invalid );
  5008. z.low := float64_default_nan_low;
  5009. z.high := float64_default_nan_high;
  5010. result := z;
  5011. exit;
  5012. End;
  5013. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  5014. End;
  5015. if ( aExp = 0 ) then
  5016. Begin
  5017. if ( ( aSig0 OR aSig1 ) = 0 ) then
  5018. Begin
  5019. result := a;
  5020. exit;
  5021. End;
  5022. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  5023. End;
  5024. expDiff := aExp - bExp;
  5025. if ( expDiff < -1 ) then
  5026. Begin
  5027. result := a;
  5028. exit;
  5029. End;
  5030. shortShift64Left(
  5031. aSig0 OR $00100000, aSig1, 11 - flag( expDiff < 0 ), aSig0, aSig1 );
  5032. shortShift64Left( bSig0 OR $00100000, bSig1, 11, bSig0, bSig1 );
  5033. q := le64( bSig0, bSig1, aSig0, aSig1 );
  5034. if ( q )<>0 then
  5035. sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  5036. expDiff := expDiff - 32;
  5037. while ( 0 < expDiff ) do
  5038. Begin
  5039. q := estimateDiv64To32( aSig0, aSig1, bSig0 );
  5040. if 4 < q then
  5041. q:= q - 4
  5042. else
  5043. q := 0;
  5044. mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );
  5045. shortShift96Left( term0, term1, term2, 29, term1, term2, allZero );
  5046. shortShift64Left( aSig0, aSig1, 29, aSig0, allZero );
  5047. sub64( aSig0, 0, term1, term2, aSig0, aSig1 );
  5048. expDiff := expDiff - 29;
  5049. End;
  5050. if ( -32 < expDiff ) then
  5051. Begin
  5052. q := estimateDiv64To32( aSig0, aSig1, bSig0 );
  5053. if 4 < q then
  5054. q := q - 4
  5055. else
  5056. q := 0;
  5057. q := q shr (- expDiff);
  5058. shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );
  5059. expDiff := expDiff + 24;
  5060. if ( expDiff < 0 ) then
  5061. Begin
  5062. shift64Right( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  5063. End
  5064. else
  5065. Begin
  5066. shortShift64Left( aSig0, aSig1, expDiff, aSig0, aSig1 );
  5067. End;
  5068. mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );
  5069. sub64( aSig0, aSig1, term1, term2, aSig0, aSig1 );
  5070. End
  5071. else
  5072. Begin
  5073. shift64Right( aSig0, aSig1, 8, aSig0, aSig1 );
  5074. shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );
  5075. End;
  5076. Repeat
  5077. alternateASig0 := aSig0;
  5078. alternateASig1 := aSig1;
  5079. Inc(q);
  5080. sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  5081. Until not ( 0 <= sbits32 (aSig0) );
  5082. add64(
  5083. aSig0, aSig1, alternateASig0, alternateASig1, bits32(sigMean0), sigMean1 );
  5084. if ( ( sigMean0 < 0 )
  5085. OR ( ( ( sigMean0 OR sigMean1 ) = 0 ) AND (( q AND 1 )<>0) ) ) then
  5086. Begin
  5087. aSig0 := alternateASig0;
  5088. aSig1 := alternateASig1;
  5089. End;
  5090. zSign := flag( sbits32 (aSig0) < 0 );
  5091. if ( zSign <> 0 ) then
  5092. sub64( 0, 0, aSig0, aSig1, aSig0, aSig1 );
  5093. normalizeRoundAndPackFloat64( aSign xor zSign, bExp - 4, aSig0, aSig1, result );
  5094. End;
  5095. {*
  5096. -------------------------------------------------------------------------------
  5097. Returns the square root of the double-precision floating-point value `a'.
  5098. The operation is performed according to the IEC/IEEE Standard for Binary
  5099. Floating-Point Arithmetic.
  5100. -------------------------------------------------------------------------------
  5101. *}
  5102. function float64_sqrt( a: float64 ): float64;
  5103. {$ifdef fpc}[public,Alias:'FLOAT64_SQRT'];compilerproc;{$endif}
  5104. Var
  5105. aSign: flag;
  5106. aExp, zExp: int16;
  5107. aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits32;
  5108. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;
  5109. label invalid;
  5110. Begin
  5111. aSig1 := extractFloat64Frac1( a );
  5112. aSig0 := extractFloat64Frac0( a );
  5113. aExp := extractFloat64Exp( a );
  5114. aSign := extractFloat64Sign( a );
  5115. if ( aExp = $7FF ) then
  5116. Begin
  5117. if ( aSig0 OR aSig1 ) <> 0 then
  5118. Begin
  5119. propagateFloat64NaN( a, a, result );
  5120. exit;
  5121. End;
  5122. if ( aSign = 0) then
  5123. Begin
  5124. result := a;
  5125. exit;
  5126. End;
  5127. goto invalid;
  5128. End;
  5129. if ( aSign <> 0 ) then
  5130. Begin
  5131. if ( ( bits32(aExp) OR aSig0 OR aSig1 ) = 0 ) then
  5132. Begin
  5133. result := a;
  5134. exit;
  5135. End;
  5136. invalid:
  5137. float_raise( float_flag_invalid );
  5138. result.low := float64_default_nan_low;
  5139. result.high := float64_default_nan_high;
  5140. exit;
  5141. End;
  5142. if ( aExp = 0 ) then
  5143. Begin
  5144. if ( ( aSig0 OR aSig1 ) = 0 ) then
  5145. Begin
  5146. packFloat64( 0, 0, 0, 0, result );
  5147. exit;
  5148. End;
  5149. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  5150. End;
  5151. zExp := ( ( aExp - $3FF ) shr 1 ) + $3FE;
  5152. aSig0 := aSig0 or $00100000;
  5153. shortShift64Left( aSig0, aSig1, 11, term0, term1 );
  5154. zSig0 := ( estimateSqrt32( aExp, term0 ) shr 1 ) + 1;
  5155. if ( zSig0 = 0 ) then
  5156. zSig0 := $7FFFFFFF;
  5157. doubleZSig0 := zSig0 + zSig0;
  5158. shortShift64Left( aSig0, aSig1, 9 - ( aExp and 1 ), aSig0, aSig1 );
  5159. mul32To64( zSig0, zSig0, term0, term1 );
  5160. sub64( aSig0, aSig1, term0, term1, rem0, rem1 );
  5161. while ( sbits32 (rem0) < 0 ) do
  5162. Begin
  5163. Dec(zSig0);
  5164. doubleZSig0 := doubleZSig0 - 2;
  5165. add64( rem0, rem1, 0, doubleZSig0 OR 1, rem0, rem1 );
  5166. End;
  5167. zSig1 := estimateDiv64To32( rem1, 0, doubleZSig0 );
  5168. if ( ( zSig1 and $1FF ) <= 5 ) then
  5169. Begin
  5170. if ( zSig1 = 0 ) then
  5171. zSig1 := 1;
  5172. mul32To64( doubleZSig0, zSig1, term1, term2 );
  5173. sub64( rem1, 0, term1, term2, rem1, rem2 );
  5174. mul32To64( zSig1, zSig1, term2, term3 );
  5175. sub96( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
  5176. while ( sbits32 (rem1) < 0 ) do
  5177. Begin
  5178. Dec(zSig1);
  5179. shortShift64Left( 0, zSig1, 1, term2, term3 );
  5180. term3 := term3 or 1;
  5181. term2 := term2 or doubleZSig0;
  5182. add96( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
  5183. End;
  5184. zSig1 := zSig1 or bits32( ( rem1 OR rem2 OR rem3 ) <> 0 );
  5185. End;
  5186. shift64ExtraRightJamming( zSig0, zSig1, 0, 10, zSig0, zSig1, zSig2 );
  5187. roundAndPackFloat64( 0, zExp, zSig0, zSig1, zSig2, result );
  5188. End;
  5189. {*
  5190. -------------------------------------------------------------------------------
  5191. Returns 1 if the double-precision floating-point value `a' is equal to
  5192. the corresponding value `b', and 0 otherwise. The comparison is performed
  5193. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5194. -------------------------------------------------------------------------------
  5195. *}
  5196. Function float64_eq(a: float64; b: float64): flag;
  5197. {$ifdef fpc}[public,Alias:'FLOAT64_EQ'];compilerproc;{$endif}
  5198. Begin
  5199. if
  5200. (
  5201. ( extractFloat64Exp( a ) = $7FF )
  5202. AND
  5203. (
  5204. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5205. )
  5206. )
  5207. OR (
  5208. ( extractFloat64Exp( b ) = $7FF )
  5209. AND (
  5210. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5211. )
  5212. )
  5213. ) then
  5214. Begin
  5215. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  5216. float_raise( float_flag_invalid );
  5217. float64_eq := 0;
  5218. exit;
  5219. End;
  5220. float64_eq := flag(
  5221. ( a.low = b.low )
  5222. AND ( ( a.high = b.high )
  5223. OR ( ( a.low = 0 )
  5224. AND ( bits32 ( ( a.high OR b.high ) shl 1 ) = 0 ) )
  5225. ));
  5226. End;
  5227. {*
  5228. -------------------------------------------------------------------------------
  5229. Returns 1 if the double-precision floating-point value `a' is less than
  5230. or equal to the corresponding value `b', and 0 otherwise. The comparison
  5231. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  5232. Arithmetic.
  5233. -------------------------------------------------------------------------------
  5234. *}
  5235. Function float64_le(a: float64;b: float64): flag;
  5236. {$ifdef fpc}[public,Alias:'FLOAT64_LE'];compilerproc;{$endif}
  5237. Var
  5238. aSign, bSign: flag;
  5239. Begin
  5240. if
  5241. (
  5242. ( extractFloat64Exp( a ) = $7FF )
  5243. AND
  5244. (
  5245. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5246. )
  5247. )
  5248. OR (
  5249. ( extractFloat64Exp( b ) = $7FF )
  5250. AND (
  5251. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5252. )
  5253. )
  5254. ) then
  5255. Begin
  5256. float_raise( float_flag_invalid );
  5257. float64_le := 0;
  5258. exit;
  5259. End;
  5260. aSign := extractFloat64Sign( a );
  5261. bSign := extractFloat64Sign( b );
  5262. if ( aSign <> bSign ) then
  5263. Begin
  5264. float64_le := flag(
  5265. (aSign <> 0)
  5266. OR ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  5267. = 0 ));
  5268. exit;
  5269. End;
  5270. if aSign <> 0 then
  5271. float64_le := le64( b.high, b.low, a.high, a.low )
  5272. else
  5273. float64_le := le64( a.high, a.low, b.high, b.low );
  5274. End;
  5275. {*
  5276. -------------------------------------------------------------------------------
  5277. Returns 1 if the double-precision floating-point value `a' is less than
  5278. the corresponding value `b', and 0 otherwise. The comparison is performed
  5279. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5280. -------------------------------------------------------------------------------
  5281. *}
  5282. Function float64_lt(a: float64;b: float64): flag;
  5283. {$ifdef fpc}[public,Alias:'FLOAT64_LT'];compilerproc;{$endif}
  5284. Var
  5285. aSign, bSign: flag;
  5286. Begin
  5287. if
  5288. (
  5289. ( extractFloat64Exp( a ) = $7FF )
  5290. AND
  5291. (
  5292. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5293. )
  5294. )
  5295. OR (
  5296. ( extractFloat64Exp( b ) = $7FF )
  5297. AND (
  5298. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5299. )
  5300. )
  5301. ) then
  5302. Begin
  5303. float_raise( float_flag_invalid );
  5304. float64_lt := 0;
  5305. exit;
  5306. End;
  5307. aSign := extractFloat64Sign( a );
  5308. bSign := extractFloat64Sign( b );
  5309. if ( aSign <> bSign ) then
  5310. Begin
  5311. float64_lt := flag(
  5312. (aSign <> 0)
  5313. AND ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  5314. <> 0 ));
  5315. exit;
  5316. End;
  5317. if aSign <> 0 then
  5318. float64_lt := lt64( b.high, b.low, a.high, a.low )
  5319. else
  5320. float64_lt := lt64( a.high, a.low, b.high, b.low );
  5321. End;
  5322. {*
  5323. -------------------------------------------------------------------------------
  5324. Returns 1 if the double-precision floating-point value `a' is equal to
  5325. the corresponding value `b', and 0 otherwise. The invalid exception is
  5326. raised if either operand is a NaN. Otherwise, the comparison is performed
  5327. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5328. -------------------------------------------------------------------------------
  5329. *}
  5330. Function float64_eq_signaling( a: float64; b: float64): flag;
  5331. Begin
  5332. if
  5333. (
  5334. ( extractFloat64Exp( a ) = $7FF )
  5335. AND
  5336. (
  5337. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5338. )
  5339. )
  5340. OR (
  5341. ( extractFloat64Exp( b ) = $7FF )
  5342. AND (
  5343. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5344. )
  5345. )
  5346. ) then
  5347. Begin
  5348. float_raise( float_flag_invalid );
  5349. float64_eq_signaling := 0;
  5350. exit;
  5351. End;
  5352. float64_eq_signaling := flag(
  5353. ( a.low = b.low )
  5354. AND ( ( a.high = b.high )
  5355. OR ( ( a.low = 0 )
  5356. AND ( bits32 ( ( a.high OR b.high ) shl 1 ) = 0 ) )
  5357. ));
  5358. End;
  5359. {*
  5360. -------------------------------------------------------------------------------
  5361. Returns 1 if the double-precision floating-point value `a' is less than or
  5362. equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  5363. cause an exception. Otherwise, the comparison is performed according to the
  5364. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5365. -------------------------------------------------------------------------------
  5366. *}
  5367. Function float64_le_quiet(a: float64 ; b: float64 ): flag;
  5368. Var
  5369. aSign, bSign : flag;
  5370. Begin
  5371. if
  5372. (
  5373. ( extractFloat64Exp( a ) = $7FF )
  5374. AND
  5375. (
  5376. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5377. )
  5378. )
  5379. OR (
  5380. ( extractFloat64Exp( b ) = $7FF )
  5381. AND (
  5382. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5383. )
  5384. )
  5385. ) then
  5386. Begin
  5387. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  5388. float_raise( float_flag_invalid );
  5389. float64_le_quiet := 0;
  5390. exit;
  5391. End;
  5392. aSign := extractFloat64Sign( a );
  5393. bSign := extractFloat64Sign( b );
  5394. if ( aSign <> bSign ) then
  5395. Begin
  5396. float64_le_quiet := flag
  5397. ((aSign <> 0)
  5398. OR ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  5399. = 0 ));
  5400. exit;
  5401. End;
  5402. if aSign <> 0 then
  5403. float64_le_quiet := le64( b.high, b.low, a.high, a.low )
  5404. else
  5405. float64_le_quiet := le64( a.high, a.low, b.high, b.low );
  5406. End;
  5407. {*
  5408. -------------------------------------------------------------------------------
  5409. Returns 1 if the double-precision floating-point value `a' is less than
  5410. the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  5411. exception. Otherwise, the comparison is performed according to the IEC/IEEE
  5412. Standard for Binary Floating-Point Arithmetic.
  5413. -------------------------------------------------------------------------------
  5414. *}
  5415. Function float64_lt_quiet(a: float64; b: float64 ): Flag;
  5416. Var
  5417. aSign, bSign: flag;
  5418. Begin
  5419. if
  5420. (
  5421. ( extractFloat64Exp( a ) = $7FF )
  5422. AND
  5423. (
  5424. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5425. )
  5426. )
  5427. OR (
  5428. ( extractFloat64Exp( b ) = $7FF )
  5429. AND (
  5430. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5431. )
  5432. )
  5433. ) then
  5434. Begin
  5435. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  5436. float_raise( float_flag_invalid );
  5437. float64_lt_quiet := 0;
  5438. exit;
  5439. End;
  5440. aSign := extractFloat64Sign( a );
  5441. bSign := extractFloat64Sign( b );
  5442. if ( aSign <> bSign ) then
  5443. Begin
  5444. float64_lt_quiet := flag(
  5445. (aSign<>0)
  5446. AND ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  5447. <> 0 ));
  5448. exit;
  5449. End;
  5450. If aSign <> 0 then
  5451. float64_lt_quiet := lt64( b.high, b.low, a.high, a.low )
  5452. else
  5453. float64_lt_quiet := lt64( a.high, a.low, b.high, b.low );
  5454. End;
  5455. {*----------------------------------------------------------------------------
  5456. | Returns the result of converting the 64-bit two's complement integer `a'
  5457. | to the single-precision floating-point format. The conversion is performed
  5458. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5459. *----------------------------------------------------------------------------*}
  5460. function int64_to_float32( a: int64 ): float32rec; compilerproc;
  5461. var
  5462. zSign : flag;
  5463. absA : uint64;
  5464. shiftCount: int8;
  5465. Begin
  5466. if ( a = 0 ) then
  5467. begin
  5468. int64_to_float32.float32 := 0;
  5469. exit;
  5470. end;
  5471. if a < 0 then
  5472. zSign := flag(TRUE)
  5473. else
  5474. zSign := flag(FALSE);
  5475. if zSign<>0 then
  5476. absA := -a
  5477. else
  5478. absA := a;
  5479. shiftCount := countLeadingZeros64( absA ) - 40;
  5480. if ( 0 <= shiftCount ) then
  5481. begin
  5482. int64_to_float32.float32:= packFloat32( zSign, $95 - shiftCount, absA shl shiftCount );
  5483. end
  5484. else
  5485. begin
  5486. shiftCount := shiftCount + 7;
  5487. if ( shiftCount < 0 ) then
  5488. shift64RightJamming( absA, - shiftCount, absA )
  5489. else
  5490. absA := absA shl shiftCount;
  5491. int64_to_float32.float32:=roundAndPackFloat32( zSign, $9C - shiftCount, absA );
  5492. end;
  5493. End;
  5494. {*----------------------------------------------------------------------------
  5495. | Returns the result of converting the 64-bit two's complement integer `a'
  5496. | to the single-precision floating-point format. The conversion is performed
  5497. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5498. | Unisgned version.
  5499. *----------------------------------------------------------------------------*}
  5500. function qword_to_float32( a: qword ): float32rec; compilerproc;
  5501. var
  5502. absA : uint64;
  5503. shiftCount: int8;
  5504. Begin
  5505. if ( a = 0 ) then
  5506. begin
  5507. qword_to_float32.float32 := 0;
  5508. exit;
  5509. end;
  5510. absA := a;
  5511. shiftCount := countLeadingZeros64( absA ) - 40;
  5512. if ( 0 <= shiftCount ) then
  5513. begin
  5514. qword_to_float32.float32:= packFloat32( 0, $95 - shiftCount, absA shl shiftCount );
  5515. end
  5516. else
  5517. begin
  5518. shiftCount := shiftCount + 7;
  5519. if ( shiftCount < 0 ) then
  5520. shift64RightJamming( absA, - shiftCount, absA )
  5521. else
  5522. absA := absA shl shiftCount;
  5523. qword_to_float32.float32:=roundAndPackFloat32( 0, $9C - shiftCount, absA );
  5524. end;
  5525. End;
  5526. {*----------------------------------------------------------------------------
  5527. | Returns the result of converting the 64-bit two's complement integer `a'
  5528. | to the double-precision floating-point format. The conversion is performed
  5529. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5530. *----------------------------------------------------------------------------*}
  5531. function qword_to_float64( a: qword ): float64;
  5532. {$ifdef fpc}[public,Alias:'QWORD_TO_FLOAT64'];compilerproc;{$endif}
  5533. Begin
  5534. if ( a = 0 ) then
  5535. result := packFloat64( 0, 0, 0 )
  5536. else
  5537. result := normalizeRoundAndPackFloat64( 0, $43c, a );
  5538. End;
  5539. {*----------------------------------------------------------------------------
  5540. | Returns the result of converting the 64-bit two's complement integer `a'
  5541. | to the double-precision floating-point format. The conversion is performed
  5542. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5543. *----------------------------------------------------------------------------*}
  5544. function int64_to_float64( a: int64 ): float64;
  5545. {$ifdef fpc}[public,Alias:'INT64_TO_FLOAT64'];compilerproc;{$endif}
  5546. Begin
  5547. if ( a = 0 ) then
  5548. result := packFloat64( 0, 0, 0 )
  5549. else if (a = int64($8000000000000000)) then
  5550. result := packFloat64( 1, $43e, 0 )
  5551. else if (a < 0) then
  5552. result := normalizeRoundAndPackFloat64( 1, $43c, -a )
  5553. else
  5554. result := normalizeRoundAndPackFloat64( 0, $43c, a );
  5555. End;
  5556. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  5557. {*----------------------------------------------------------------------------
  5558. | Returns the result of converting the 64-bit two's complement integer `a'
  5559. | to the extended double-precision floating-point format. The conversion
  5560. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  5561. | Arithmetic.
  5562. *----------------------------------------------------------------------------*}
  5563. function int64_to_floatx80( a: int64 ): floatx80;
  5564. var
  5565. zSign: flag;
  5566. absA: uint64;
  5567. shiftCount: int8;
  5568. begin
  5569. if ( a = 0 ) then begin
  5570. result := packFloatx80( 0, 0, 0 );
  5571. exit;
  5572. end;
  5573. zSign := ord( a < 0 );
  5574. if zSign <> 0 then absA := - a else absA := a;
  5575. shiftCount := countLeadingZeros64( absA );
  5576. result := packFloatx80( zSign, $403E - shiftCount, absA shl shiftCount );
  5577. end;
  5578. {*----------------------------------------------------------------------------
  5579. | Returns the result of converting the 64-bit two's complement integer `a'
  5580. | to the extended double-precision floating-point format. The conversion
  5581. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  5582. | Arithmetic.
  5583. | Unsigned version.
  5584. *----------------------------------------------------------------------------*}
  5585. function qword_to_floatx80( a: qword ): floatx80;
  5586. var
  5587. absA: bits64;
  5588. shiftCount: int8;
  5589. begin
  5590. if ( a = 0 ) then begin
  5591. result := packFloatx80( 0, 0, 0 );
  5592. exit;
  5593. end;
  5594. absA := a;
  5595. shiftCount := countLeadingZeros64( absA );
  5596. result := packFloatx80( 0, $403E - shiftCount, absA shl shiftCount );
  5597. end;
  5598. {$endif FPC_SOFTFLOAT_FLOATX80}
  5599. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  5600. {*----------------------------------------------------------------------------
  5601. | Returns the result of converting the 64-bit two's complement integer `a' to
  5602. | the quadruple-precision floating-point format. The conversion is performed
  5603. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5604. *----------------------------------------------------------------------------*}
  5605. function int64_to_float128( a: int64 ): float128;
  5606. var
  5607. zSign: flag;
  5608. absA: uint64;
  5609. shiftCount: int8;
  5610. zExp: int32;
  5611. zSig0, zSig1: bits64;
  5612. begin
  5613. if ( a = 0 ) then begin
  5614. result := packFloat128( 0, 0, 0, 0 );
  5615. exit;
  5616. end;
  5617. zSign := ord( a < 0 );
  5618. if zSign <> 0 then absA := - a else absA := a;
  5619. shiftCount := countLeadingZeros64( absA ) + 49;
  5620. zExp := $406E - shiftCount;
  5621. if ( 64 <= shiftCount ) then begin
  5622. zSig1 := 0;
  5623. zSig0 := absA;
  5624. dec( shiftCount, 64 );
  5625. end
  5626. else begin
  5627. zSig1 := absA;
  5628. zSig0 := 0;
  5629. end;
  5630. shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  5631. result := packFloat128( zSign, zExp, zSig0, zSig1 );
  5632. end;
  5633. {*----------------------------------------------------------------------------
  5634. | Returns the result of converting the 64-bit two's complement integer `a' to
  5635. | the quadruple-precision floating-point format. The conversion is performed
  5636. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5637. | Unsigned version.
  5638. *----------------------------------------------------------------------------*}
  5639. function qword_to_float128( a: qword ): float128;
  5640. var
  5641. absA: bits64;
  5642. shiftCount: int8;
  5643. zExp: int32;
  5644. zSig0, zSig1: bits64;
  5645. begin
  5646. if ( a = 0 ) then begin
  5647. result := packFloat128( 0, 0, 0, 0 );
  5648. exit;
  5649. end;
  5650. absA := a;
  5651. shiftCount := countLeadingZeros64( absA ) + 49;
  5652. zExp := $406E - shiftCount;
  5653. if ( 64 <= shiftCount ) then begin
  5654. zSig1 := 0;
  5655. zSig0 := absA;
  5656. dec( shiftCount, 64 );
  5657. end
  5658. else begin
  5659. zSig1 := absA;
  5660. zSig0 := 0;
  5661. end;
  5662. shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  5663. result := packFloat128( 0, zExp, zSig0, zSig1 );
  5664. end;
  5665. {$endif FPC_SOFTFLOAT_FLOAT128}
  5666. {*----------------------------------------------------------------------------
  5667. | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
  5668. | is equal to the 128-bit value formed by concatenating `b0' and `b1'.
  5669. | Otherwise, returns 0.
  5670. *----------------------------------------------------------------------------*}
  5671. function eq128( a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
  5672. begin
  5673. result := ord(( a0 = b0 ) and ( a1 = b1 ));
  5674. end;
  5675. {*----------------------------------------------------------------------------
  5676. | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
  5677. | than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
  5678. | Otherwise, returns 0.
  5679. *----------------------------------------------------------------------------*}
  5680. function le128( a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
  5681. begin
  5682. result:=ord(( a0 < b0 ) or ( ( a0 = b0 ) and ( a1 <= b1 ) ));
  5683. end;
  5684. {*----------------------------------------------------------------------------
  5685. | Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
  5686. | by 64 _plus_ the number of bits given in `count'. The shifted result is
  5687. | at most 128 nonzero bits; these are broken into two 64-bit pieces which are
  5688. | stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
  5689. | off form a third 64-bit result as follows: The _last_ bit shifted off is
  5690. | the most-significant bit of the extra result, and the other 63 bits of the
  5691. | extra result are all zero if and only if _all_but_the_last_ bits shifted off
  5692. | were all zero. This extra result is stored in the location pointed to by
  5693. | `z2Ptr'. The value of `count' can be arbitrarily large.
  5694. | (This routine makes more sense if `a0', `a1', and `a2' are considered
  5695. | to form a fixed-point value with binary point between `a1' and `a2'. This
  5696. | fixed-point value is shifted right by the number of bits given in `count',
  5697. | and the integer part of the result is returned at the locations pointed to
  5698. | by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
  5699. | corrupted as described above, and is returned at the location pointed to by
  5700. | `z2Ptr'.)
  5701. *----------------------------------------------------------------------------*}
  5702. procedure shift128ExtraRightJamming(
  5703. a0: bits64;
  5704. a1: bits64;
  5705. a2: bits64;
  5706. count: int16;
  5707. var z0Ptr: bits64;
  5708. var z1Ptr: bits64;
  5709. var z2Ptr: bits64);
  5710. var
  5711. z0, z1, z2: bits64;
  5712. negCount: int8;
  5713. begin
  5714. negCount := ( - count ) and 63;
  5715. if ( count = 0 ) then
  5716. begin
  5717. z2 := a2;
  5718. z1 := a1;
  5719. z0 := a0;
  5720. end
  5721. else begin
  5722. if ( count < 64 ) then
  5723. begin
  5724. z2 := a1 shl negCount;
  5725. z1 := ( a0 shl negCount ) or ( a1 shr count );
  5726. z0 := a0 shr count;
  5727. end
  5728. else begin
  5729. if ( count = 64 ) then
  5730. begin
  5731. z2 := a1;
  5732. z1 := a0;
  5733. end
  5734. else begin
  5735. a2 := a2 or a1;
  5736. if ( count < 128 ) then
  5737. begin
  5738. z2 := a0 shl negCount;
  5739. z1 := a0 shr ( count and 63 );
  5740. end
  5741. else begin
  5742. if ( count = 128 ) then
  5743. z2 := a0
  5744. else
  5745. z2 := ord( a0 <> 0 );
  5746. z1 := 0;
  5747. end;
  5748. end;
  5749. z0 := 0;
  5750. end;
  5751. z2 := z2 or ord( a2 <> 0 );
  5752. end;
  5753. z2Ptr := z2;
  5754. z1Ptr := z1;
  5755. z0Ptr := z0;
  5756. end;
  5757. {*----------------------------------------------------------------------------
  5758. | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
  5759. | _plus_ the number of bits given in `count'. The shifted result is at most
  5760. | 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
  5761. | bits shifted off form a second 64-bit result as follows: The _last_ bit
  5762. | shifted off is the most-significant bit of the extra result, and the other
  5763. | 63 bits of the extra result are all zero if and only if _all_but_the_last_
  5764. | bits shifted off were all zero. This extra result is stored in the location
  5765. | pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
  5766. | (This routine makes more sense if `a0' and `a1' are considered to form
  5767. | a fixed-point value with binary point between `a0' and `a1'. This fixed-
  5768. | point value is shifted right by the number of bits given in `count', and
  5769. | the integer part of the result is returned at the location pointed to by
  5770. | `z0Ptr'. The fractional part of the result may be slightly corrupted as
  5771. | described above, and is returned at the location pointed to by `z1Ptr'.)
  5772. *----------------------------------------------------------------------------*}
  5773. procedure shift64ExtraRightJamming(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
  5774. var
  5775. z0, z1: bits64;
  5776. negCount: int8;
  5777. begin
  5778. negCount := ( - count ) and 63;
  5779. if ( count = 0 ) then
  5780. begin
  5781. z1 := a1;
  5782. z0 := a0;
  5783. end
  5784. else if ( count < 64 ) then
  5785. begin
  5786. z1 := ( a0 shl negCount ) or ord( a1 <> 0 );
  5787. z0 := a0 shr count;
  5788. end
  5789. else begin
  5790. if ( count = 64 ) then
  5791. begin
  5792. z1 := a0 or ord( a1 <> 0 );
  5793. end
  5794. else begin
  5795. z1 := ord( ( a0 or a1 ) <> 0 );
  5796. end;
  5797. z0 := 0;
  5798. end;
  5799. z1Ptr := z1;
  5800. z0Ptr := z0;
  5801. end;
  5802. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  5803. {*----------------------------------------------------------------------------
  5804. | Returns the fraction bits of the extended double-precision floating-point
  5805. | value `a'.
  5806. *----------------------------------------------------------------------------*}
  5807. function extractFloatx80Frac(a : floatx80): bits64;inline;
  5808. begin
  5809. result:=a.low;
  5810. end;
  5811. {*----------------------------------------------------------------------------
  5812. | Returns the exponent bits of the extended double-precision floating-point
  5813. | value `a'.
  5814. *----------------------------------------------------------------------------*}
  5815. function extractFloatx80Exp(a : floatx80): int32;inline;
  5816. begin
  5817. result:=a.high and $7FFF;
  5818. end;
  5819. {*----------------------------------------------------------------------------
  5820. | Returns the sign bit of the extended double-precision floating-point value
  5821. | `a'.
  5822. *----------------------------------------------------------------------------*}
  5823. function extractFloatx80Sign(a : floatx80): flag;inline;
  5824. begin
  5825. result:=a.high shr 15;
  5826. end;
  5827. {*----------------------------------------------------------------------------
  5828. | Normalizes the subnormal extended double-precision floating-point value
  5829. | represented by the denormalized significand `aSig'. The normalized exponent
  5830. | and significand are stored at the locations pointed to by `zExpPtr' and
  5831. | `zSigPtr', respectively.
  5832. *----------------------------------------------------------------------------*}
  5833. procedure normalizeFloatx80Subnormal( aSig: bits64; var zExpPtr: int32; var zSigPtr : bits64);
  5834. var
  5835. shiftCount: int8;
  5836. begin
  5837. shiftCount := countLeadingZeros64( aSig );
  5838. zSigPtr := aSig shl shiftCount;
  5839. zExpPtr := 1 - shiftCount;
  5840. end;
  5841. {*----------------------------------------------------------------------------
  5842. | Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
  5843. | extended double-precision floating-point value, returning the result.
  5844. *----------------------------------------------------------------------------*}
  5845. function packFloatx80( zSign: flag; zExp: int32; zSig : bits64): floatx80;
  5846. var
  5847. z: floatx80;
  5848. begin
  5849. z.low := zSig;
  5850. z.high := ( bits16(zSign) shl 15 ) + zExp;
  5851. result:=z;
  5852. end;
  5853. {*----------------------------------------------------------------------------
  5854. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  5855. | and extended significand formed by the concatenation of `zSig0' and `zSig1',
  5856. | and returns the proper extended double-precision floating-point value
  5857. | corresponding to the abstract input. Ordinarily, the abstract value is
  5858. | rounded and packed into the extended double-precision format, with the
  5859. | inexact exception raised if the abstract input cannot be represented
  5860. | exactly. However, if the abstract value is too large, the overflow and
  5861. | inexact exceptions are raised and an infinity or maximal finite value is
  5862. | returned. If the abstract value is too small, the input value is rounded to
  5863. | a subnormal number, and the underflow and inexact exceptions are raised if
  5864. | the abstract input cannot be represented exactly as a subnormal extended
  5865. | double-precision floating-point number.
  5866. | If `roundingPrecision' is 32 or 64, the result is rounded to the same
  5867. | number of bits as single or double precision, respectively. Otherwise, the
  5868. | result is rounded to the full precision of the extended double-precision
  5869. | format.
  5870. | The input significand must be normalized or smaller. If the input
  5871. | significand is not normalized, `zExp' must be 0; in that case, the result
  5872. | returned is a subnormal number, and it must not require rounding. The
  5873. | handling of underflow and overflow follows the IEC/IEEE Standard for Binary
  5874. | Floating-Point Arithmetic.
  5875. *----------------------------------------------------------------------------*}
  5876. function roundAndPackFloatx80(roundingPrecision: int8; zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): floatx80;
  5877. var
  5878. roundingMode: int8;
  5879. roundNearestEven, increment, isTiny: flag;
  5880. roundIncrement, roundMask, roundBits: int64;
  5881. label
  5882. precision80, overflow;
  5883. begin
  5884. roundingMode := softfloat_rounding_mode;
  5885. roundNearestEven := flag( roundingMode = float_round_nearest_even );
  5886. if ( roundingPrecision = 80 ) then
  5887. goto precision80;
  5888. if ( roundingPrecision = 64 ) then
  5889. begin
  5890. roundIncrement := int64( $0000000000000400 );
  5891. roundMask := int64( $00000000000007FF );
  5892. end
  5893. else if ( roundingPrecision = 32 ) then
  5894. begin
  5895. roundIncrement := int64( $0000008000000000 );
  5896. roundMask := int64( $000000FFFFFFFFFF );
  5897. end
  5898. else begin
  5899. goto precision80;
  5900. end;
  5901. zSig0 := zSig0 or ord( zSig1 <> 0 );
  5902. if ( not (roundNearestEven<>0) ) then
  5903. begin
  5904. if ( roundingMode = float_round_to_zero ) then
  5905. begin
  5906. roundIncrement := 0;
  5907. end
  5908. else begin
  5909. roundIncrement := roundMask;
  5910. if ( zSign<>0 ) then
  5911. begin
  5912. if ( roundingMode = float_round_up ) then
  5913. roundIncrement := 0;
  5914. end
  5915. else begin
  5916. if ( roundingMode = float_round_down ) then
  5917. roundIncrement := 0;
  5918. end;
  5919. end;
  5920. end;
  5921. roundBits := zSig0 and roundMask;
  5922. if ( $7FFD <= bits32( zExp - 1 ) ) then begin
  5923. if ( ( $7FFE < zExp )
  5924. or ( ( zExp = $7FFE ) and ( zSig0 + roundIncrement < zSig0 ) )
  5925. ) then begin
  5926. goto overflow;
  5927. end;
  5928. if ( zExp <= 0 ) then begin
  5929. isTiny := ord (
  5930. ( softfloat_detect_tininess = float_tininess_before_rounding )
  5931. or ( zExp < 0 )
  5932. or ( zSig0 <= zSig0 + roundIncrement ) );
  5933. shift64RightJamming( zSig0, 1 - zExp, zSig0 );
  5934. zExp := 0;
  5935. roundBits := zSig0 and roundMask;
  5936. if ( isTiny <> 0 ) and ( roundBits <> 0 ) then float_raise( float_flag_underflow );
  5937. if ( roundBits <> 0 ) then set_inexact_flag;
  5938. inc( zSig0, roundIncrement );
  5939. if ( sbits64( zSig0 ) < 0 ) then zExp := 1;
  5940. roundIncrement := roundMask + 1;
  5941. if ( roundNearestEven <> 0 ) and ( roundBits shl 1 = roundIncrement ) then begin
  5942. roundMask := roundMask or roundIncrement;
  5943. end;
  5944. zSig0 := zSig0 and not roundMask;
  5945. result:=packFloatx80( zSign, zExp, zSig0 );
  5946. exit;
  5947. end;
  5948. end;
  5949. if ( roundBits <> 0 ) then set_inexact_flag;
  5950. inc( zSig0, roundIncrement );
  5951. if ( zSig0 < roundIncrement ) then begin
  5952. inc(zExp);
  5953. zSig0 := bits64( $8000000000000000 );
  5954. end;
  5955. roundIncrement := roundMask + 1;
  5956. if ( roundNearestEven <> 0 ) and ( roundBits shl 1 = roundIncrement ) then begin
  5957. roundMask := roundMask or roundIncrement;
  5958. end;
  5959. zSig0 := zSig0 and not roundMask;
  5960. if ( zSig0 = 0 ) then zExp := 0;
  5961. result:=packFloatx80( zSign, zExp, zSig0 );
  5962. exit;
  5963. precision80:
  5964. increment := ord ( sbits64( zSig1 ) < 0 );
  5965. if ( roundNearestEven = 0 ) then begin
  5966. if ( roundingMode = float_round_to_zero ) then begin
  5967. increment := 0;
  5968. end
  5969. else begin
  5970. if ( zSign <> 0 ) then begin
  5971. increment := ord ( roundingMode = float_round_down ) and zSig1;
  5972. end
  5973. else begin
  5974. increment := ord ( roundingMode = float_round_up ) and zSig1;
  5975. end;
  5976. end;
  5977. end;
  5978. if ( $7FFD <= bits32( zExp - 1 ) ) then begin
  5979. if ( ( $7FFE < zExp )
  5980. or ( ( zExp = $7FFE )
  5981. and ( zSig0 = bits64( $FFFFFFFFFFFFFFFF ) )
  5982. and ( increment <> 0 )
  5983. )
  5984. ) then begin
  5985. roundMask := 0;
  5986. overflow:
  5987. float_raise( [float_flag_overflow,float_flag_inexact] );
  5988. if ( ( roundingMode = float_round_to_zero )
  5989. or ( ( zSign <> 0) and ( roundingMode = float_round_up ) )
  5990. or ( ( zSign = 0) and ( roundingMode = float_round_down ) )
  5991. ) then begin
  5992. result:=packFloatx80( zSign, $7FFE, not roundMask );
  5993. exit;
  5994. end;
  5995. result:=packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  5996. exit;
  5997. end;
  5998. if ( zExp <= 0 ) then begin
  5999. isTiny := ord(
  6000. ( softfloat_detect_tininess = float_tininess_before_rounding )
  6001. or ( zExp < 0 )
  6002. or ( increment = 0 )
  6003. or ( zSig0 < bits64( $FFFFFFFFFFFFFFFF ) ) );
  6004. shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, zSig0, zSig1 );
  6005. zExp := 0;
  6006. if ( ( isTiny <> 0 ) and ( zSig1 <> 0 ) ) then float_raise( float_flag_underflow );
  6007. if ( zSig1 <> 0 ) then set_inexact_flag;
  6008. if ( roundNearestEven <> 0 ) then begin
  6009. increment := ord( sbits64( zSig1 ) < 0 );
  6010. end
  6011. else begin
  6012. if ( zSign <> 0 ) then begin
  6013. increment := ord( roundingMode = float_round_down ) and zSig1;
  6014. end
  6015. else begin
  6016. increment := ord( roundingMode = float_round_up ) and zSig1;
  6017. end;
  6018. end;
  6019. if ( increment <> 0 ) then begin
  6020. inc(zSig0);
  6021. zSig0 :=
  6022. not ( ord( bits64( zSig1 shl 1 ) = 0 ) and roundNearestEven );
  6023. if ( sbits64( zSig0 ) < 0 ) then zExp := 1;
  6024. end;
  6025. result:=packFloatx80( zSign, zExp, zSig0 );
  6026. exit;
  6027. end;
  6028. end;
  6029. if ( zSig1 <> 0 ) then set_inexact_flag;
  6030. if ( increment <> 0 ) then begin
  6031. inc(zSig0);
  6032. if ( zSig0 = 0 ) then begin
  6033. inc(zExp);
  6034. zSig0 := bits64( $8000000000000000 );
  6035. end
  6036. else begin
  6037. zSig0 := zSig0 and not bits64( ord( bits64( zSig1 shl 1 ) = 0 ) and roundNearestEven );
  6038. end;
  6039. end
  6040. else begin
  6041. if ( zSig0 = 0 ) then zExp := 0;
  6042. end;
  6043. result:=packFloatx80( zSign, zExp, zSig0 );
  6044. end;
  6045. {*----------------------------------------------------------------------------
  6046. | Takes an abstract floating-point value having sign `zSign', exponent
  6047. | `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
  6048. | and returns the proper extended double-precision floating-point value
  6049. | corresponding to the abstract input. This routine is just like
  6050. | `roundAndPackFloatx80' except that the input significand does not have to be
  6051. | normalized.
  6052. *----------------------------------------------------------------------------*}
  6053. function normalizeRoundAndPackFloatx80(roundingPrecision: int8; zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): floatx80;
  6054. var
  6055. shiftCount: int8;
  6056. begin
  6057. if ( zSig0 = 0 ) then begin
  6058. zSig0 := zSig1;
  6059. zSig1 := 0;
  6060. dec( zExp, 64 );
  6061. end;
  6062. shiftCount := countLeadingZeros64( zSig0 );
  6063. shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  6064. zExp := zExp - shiftCount;
  6065. result :=
  6066. roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );
  6067. end;
  6068. {*----------------------------------------------------------------------------
  6069. | Returns the result of converting the extended double-precision floating-
  6070. | point value `a' to the 32-bit two's complement integer format. The
  6071. | conversion is performed according to the IEC/IEEE Standard for Binary
  6072. | Floating-Point Arithmetic---which means in particular that the conversion
  6073. | is rounded according to the current rounding mode. If `a' is a NaN, the
  6074. | largest positive integer is returned. Otherwise, if the conversion
  6075. | overflows, the largest integer with the same sign as `a' is returned.
  6076. *----------------------------------------------------------------------------*}
  6077. function floatx80_to_int32(a: floatx80): int32;
  6078. var
  6079. aSign: flag;
  6080. aExp, shiftCount: int32;
  6081. aSig: bits64;
  6082. begin
  6083. aSig := extractFloatx80Frac( a );
  6084. aExp := extractFloatx80Exp( a );
  6085. aSign := extractFloatx80Sign( a );
  6086. if ( aExp = $7FFF ) and ( bits64( aSig shl 1 ) <> 0 ) then aSign := 0;
  6087. shiftCount := $4037 - aExp;
  6088. if ( shiftCount <= 0 ) then shiftCount := 1;
  6089. shift64RightJamming( aSig, shiftCount, aSig );
  6090. result := roundAndPackInt32( aSign, aSig );
  6091. end;
  6092. {*----------------------------------------------------------------------------
  6093. | Returns the result of converting the extended double-precision floating-
  6094. | point value `a' to the 32-bit two's complement integer format. The
  6095. | conversion is performed according to the IEC/IEEE Standard for Binary
  6096. | Floating-Point Arithmetic, except that the conversion is always rounded
  6097. | toward zero. If `a' is a NaN, the largest positive integer is returned.
  6098. | Otherwise, if the conversion overflows, the largest integer with the same
  6099. | sign as `a' is returned.
  6100. *----------------------------------------------------------------------------*}
  6101. function floatx80_to_int32_round_to_zero(a: floatx80): int32;
  6102. var
  6103. aSign: flag;
  6104. aExp, shiftCount: int32;
  6105. aSig, savedASig: bits64;
  6106. z: int32;
  6107. label
  6108. invalid;
  6109. begin
  6110. aSig := extractFloatx80Frac( a );
  6111. aExp := extractFloatx80Exp( a );
  6112. aSign := extractFloatx80Sign( a );
  6113. if ( $401E < aExp ) then begin
  6114. if ( aExp = $7FFF ) and ( bits64( aSig shl 1 )<>0 ) then aSign := 0;
  6115. goto invalid;
  6116. end
  6117. else if ( aExp < $3FFF ) then begin
  6118. if ( aExp or aSig <> 0 ) then set_inexact_flag;
  6119. result := 0;
  6120. exit;
  6121. end;
  6122. shiftCount := $403E - aExp;
  6123. savedASig := aSig;
  6124. aSig := aSig shr shiftCount;
  6125. z := aSig;
  6126. if ( aSign <> 0 ) then z := - z;
  6127. if ( ord( z < 0 ) xor aSign ) <> 0 then begin
  6128. invalid:
  6129. float_raise( float_flag_invalid );
  6130. if aSign <> 0 then result := sbits32( $80000000 ) else result := $7FFFFFFF;
  6131. exit;
  6132. end;
  6133. if ( ( aSig shl shiftCount ) <> savedASig ) then begin
  6134. set_inexact_flag;
  6135. end;
  6136. result := z;
  6137. end;
  6138. {*----------------------------------------------------------------------------
  6139. | Returns the result of converting the extended double-precision floating-
  6140. | point value `a' to the 64-bit two's complement integer format. The
  6141. | conversion is performed according to the IEC/IEEE Standard for Binary
  6142. | Floating-Point Arithmetic---which means in particular that the conversion
  6143. | is rounded according to the current rounding mode. If `a' is a NaN,
  6144. | the largest positive integer is returned. Otherwise, if the conversion
  6145. | overflows, the largest integer with the same sign as `a' is returned.
  6146. *----------------------------------------------------------------------------*}
  6147. function floatx80_to_int64(a: floatx80): int64;
  6148. var
  6149. aSign: flag;
  6150. aExp, shiftCount: int32;
  6151. aSig, aSigExtra: bits64;
  6152. begin
  6153. aSig := extractFloatx80Frac( a );
  6154. aExp := extractFloatx80Exp( a );
  6155. aSign := extractFloatx80Sign( a );
  6156. shiftCount := $403E - aExp;
  6157. if ( shiftCount <= 0 ) then begin
  6158. if ( shiftCount <> 0 ) then begin
  6159. float_raise( float_flag_invalid );
  6160. if ( ( aSign = 0 )
  6161. or ( ( aExp = $7FFF )
  6162. and ( aSig <> bits64( $8000000000000000 ) ) )
  6163. ) then begin
  6164. result := $7FFFFFFFFFFFFFFF;
  6165. exit;
  6166. end;
  6167. result := $8000000000000000;
  6168. exit;
  6169. end;
  6170. aSigExtra := 0;
  6171. end
  6172. else begin
  6173. shift64ExtraRightJamming( aSig, 0, shiftCount, aSig, aSigExtra );
  6174. end;
  6175. result := roundAndPackInt64( aSign, aSig, aSigExtra );
  6176. end;
  6177. {*----------------------------------------------------------------------------
  6178. | Returns the result of converting the extended double-precision floating-
  6179. | point value `a' to the 64-bit two's complement integer format. The
  6180. | conversion is performed according to the IEC/IEEE Standard for Binary
  6181. | Floating-Point Arithmetic, except that the conversion is always rounded
  6182. | toward zero. If `a' is a NaN, the largest positive integer is returned.
  6183. | Otherwise, if the conversion overflows, the largest integer with the same
  6184. | sign as `a' is returned.
  6185. *----------------------------------------------------------------------------*}
  6186. function floatx80_to_int64_round_to_zero(a: floatx80): int64;
  6187. var
  6188. aSign: flag;
  6189. aExp, shiftCount: int32;
  6190. aSig: bits64;
  6191. z: int64;
  6192. begin
  6193. aSig := extractFloatx80Frac( a );
  6194. aExp := extractFloatx80Exp( a );
  6195. aSign := extractFloatx80Sign( a );
  6196. shiftCount := aExp - $403E;
  6197. if ( 0 <= shiftCount ) then begin
  6198. aSig := $7FFFFFFFFFFFFFFF;
  6199. if ( ( a.high <> $C03E ) or ( aSig <> 0 ) ) then begin
  6200. float_raise( float_flag_invalid );
  6201. if ( ( aSign = 0 ) or ( ( aExp = $7FFF ) and ( aSig <> 0 ) ) ) then begin
  6202. result := $7FFFFFFFFFFFFFFF;
  6203. exit;
  6204. end;
  6205. end;
  6206. result := $8000000000000000;
  6207. exit;
  6208. end
  6209. else if ( aExp < $3FFF ) then begin
  6210. if ( aExp or aSig <> 0 ) then set_inexact_flag;
  6211. result := 0;
  6212. exit;
  6213. end;
  6214. z := aSig shr ( - shiftCount );
  6215. if bits64( aSig shl ( shiftCount and 63 ) ) <> 0 then begin
  6216. set_inexact_flag;
  6217. end;
  6218. if ( aSign <> 0 ) then z := - z;
  6219. result := z;
  6220. end;
  6221. {*----------------------------------------------------------------------------
  6222. | The pattern for a default generated extended double-precision NaN. The
  6223. | `high' and `low' values hold the most- and least-significant bits,
  6224. | respectively.
  6225. *----------------------------------------------------------------------------*}
  6226. const
  6227. floatx80_default_nan_high = $FFFF;
  6228. floatx80_default_nan_low = bits64( $C000000000000000 );
  6229. {*----------------------------------------------------------------------------
  6230. | Returns 1 if the extended double-precision floating-point value `a' is a
  6231. | signaling NaN; otherwise returns 0.
  6232. *----------------------------------------------------------------------------*}
  6233. function floatx80_is_signaling_nan(a : floatx80): flag;
  6234. var
  6235. aLow: bits64;
  6236. begin
  6237. aLow := a.low and not $4000000000000000;
  6238. result := ord(
  6239. ( a.high and $7FFF = $7FFF )
  6240. and ( bits64( aLow shl 1 ) <> 0 )
  6241. and ( a.low = aLow ) );
  6242. end;
  6243. {*----------------------------------------------------------------------------
  6244. | Returns the result of converting the extended double-precision floating-
  6245. | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
  6246. | invalid exception is raised.
  6247. *----------------------------------------------------------------------------*}
  6248. function floatx80ToCommonNaN(a : floatx80): commonNaNT;
  6249. var
  6250. z: commonNaNT;
  6251. begin
  6252. if floatx80_is_signaling_nan( a ) <> 0 then float_raise( float_flag_invalid );
  6253. z.sign := a.high shr 15;
  6254. z.low := 0;
  6255. z.high := a.low shl 1;
  6256. result := z;
  6257. end;
  6258. {*----------------------------------------------------------------------------
  6259. | Returns 1 if the extended double-precision floating-point value `a' is a
  6260. | NaN; otherwise returns 0.
  6261. *----------------------------------------------------------------------------*}
  6262. function floatx80_is_nan(a : floatx80 ): flag;
  6263. begin
  6264. result := ord( ( ( a.high and $7FFF ) = $7FFF ) and ( bits64( a.low shl 1 ) <> 0 ) );
  6265. end;
  6266. {*----------------------------------------------------------------------------
  6267. | Takes two extended double-precision floating-point values `a' and `b', one
  6268. | of which is a NaN, and returns the appropriate NaN result. If either `a' or
  6269. | `b' is a signaling NaN, the invalid exception is raised.
  6270. *----------------------------------------------------------------------------*}
  6271. function propagateFloatx80NaN(a, b: floatx80): floatx80;
  6272. var
  6273. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  6274. label
  6275. returnLargerSignificand;
  6276. begin
  6277. aIsNaN := floatx80_is_nan( a );
  6278. aIsSignalingNaN := floatx80_is_signaling_nan( a );
  6279. bIsNaN := floatx80_is_nan( b );
  6280. bIsSignalingNaN := floatx80_is_signaling_nan( b );
  6281. a.low := a.low or $C000000000000000;
  6282. b.low := b.low or $C000000000000000;
  6283. if aIsSignalingNaN or bIsSignalingNaN <> 0 then float_raise( float_flag_invalid );
  6284. if aIsSignalingNaN <> 0 then begin
  6285. if bIsSignalingNaN <> 0 then goto returnLargerSignificand;
  6286. if bIsNaN <> 0 then result := b else result := a;
  6287. exit;
  6288. end
  6289. else if aIsNaN <>0 then begin
  6290. if ( bIsSignalingNaN <> 0 ) or ( bIsNaN = 0) then begin
  6291. result := a;
  6292. exit;
  6293. end;
  6294. returnLargerSignificand:
  6295. if ( a.low < b.low ) then begin
  6296. result := b;
  6297. exit;
  6298. end;
  6299. if ( b.low < a.low ) then begin
  6300. result := a;
  6301. exit;
  6302. end;
  6303. if a.high < b.high then result := a else result := b;
  6304. exit;
  6305. end
  6306. else
  6307. result := b;
  6308. end;
  6309. {*----------------------------------------------------------------------------
  6310. | Returns the result of converting the extended double-precision floating-
  6311. | point value `a' to the single-precision floating-point format. The
  6312. | conversion is performed according to the IEC/IEEE Standard for Binary
  6313. | Floating-Point Arithmetic.
  6314. *----------------------------------------------------------------------------*}
  6315. function floatx80_to_float32(a: floatx80): float32;
  6316. var
  6317. aSign: flag;
  6318. aExp: int32;
  6319. aSig: bits64;
  6320. begin
  6321. aSig := extractFloatx80Frac( a );
  6322. aExp := extractFloatx80Exp( a );
  6323. aSign := extractFloatx80Sign( a );
  6324. if ( aExp = $7FFF ) then begin
  6325. if bits64( aSig shl 1 ) <> 0 then begin
  6326. result := commonNaNToFloat32( floatx80ToCommonNaN( a ) );
  6327. exit;
  6328. end;
  6329. result := packFloat32( aSign, $FF, 0 );
  6330. exit;
  6331. end;
  6332. shift64RightJamming( aSig, 33, aSig );
  6333. if ( aExp or aSig <> 0 ) then dec( aExp, $3F81 );
  6334. result := roundAndPackFloat32( aSign, aExp, aSig );
  6335. end;
  6336. {*----------------------------------------------------------------------------
  6337. | Returns the result of converting the extended double-precision floating-
  6338. | point value `a' to the double-precision floating-point format. The
  6339. | conversion is performed according to the IEC/IEEE Standard for Binary
  6340. | Floating-Point Arithmetic.
  6341. *----------------------------------------------------------------------------*}
  6342. function floatx80_to_float64(a: floatx80): float64;
  6343. var
  6344. aSign: flag;
  6345. aExp: int32;
  6346. aSig, zSig: bits64;
  6347. begin
  6348. aSig := extractFloatx80Frac( a );
  6349. aExp := extractFloatx80Exp( a );
  6350. aSign := extractFloatx80Sign( a );
  6351. if ( aExp = $7FFF ) then begin
  6352. if bits64( aSig shl 1 ) <> 0 then begin
  6353. commonNaNToFloat64( floatx80ToCommonNaN( a ), result );
  6354. exit;
  6355. end;
  6356. result := packFloat64( aSign, $7FF, 0 );
  6357. exit;
  6358. end;
  6359. shift64RightJamming( aSig, 1, zSig );
  6360. if ( aExp or aSig <> 0 ) then dec( aExp, $3C01 );
  6361. result := roundAndPackFloat64( aSign, aExp, zSig );
  6362. end;
  6363. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  6364. {*----------------------------------------------------------------------------
  6365. | Returns the result of converting the extended double-precision floating-
  6366. | point value `a' to the quadruple-precision floating-point format. The
  6367. | conversion is performed according to the IEC/IEEE Standard for Binary
  6368. | Floating-Point Arithmetic.
  6369. *----------------------------------------------------------------------------*}
  6370. function floatx80_to_float128(a: floatx80): float128;
  6371. var
  6372. aSign: flag;
  6373. aExp: int16;
  6374. aSig, zSig0, zSig1: bits64;
  6375. begin
  6376. aSig := extractFloatx80Frac( a );
  6377. aExp := extractFloatx80Exp( a );
  6378. aSign := extractFloatx80Sign( a );
  6379. if ( aExp = $7FFF ) and ( bits64( aSig shl 1 ) <> 0 ) then begin
  6380. result := commonNaNToFloat128( floatx80ToCommonNaN( a ) );
  6381. exit;
  6382. end;
  6383. shift128Right( aSig shl 1, 0, 16, zSig0, zSig1 );
  6384. result := packFloat128( aSign, aExp, zSig0, zSig1 );
  6385. end;
  6386. {$endif FPC_SOFTFLOAT_FLOAT128}
  6387. {*----------------------------------------------------------------------------
  6388. | Rounds the extended double-precision floating-point value `a' to an integer,
  6389. | and Returns the result as an extended quadruple-precision floating-point
  6390. | value. The operation is performed according to the IEC/IEEE Standard for
  6391. | Binary Floating-Point Arithmetic.
  6392. *----------------------------------------------------------------------------*}
  6393. function floatx80_round_to_int(a: floatx80): floatx80;
  6394. var
  6395. aSign: flag;
  6396. aExp: int32;
  6397. lastBitMask, roundBitsMask: bits64;
  6398. roundingMode: int8;
  6399. z: floatx80;
  6400. begin
  6401. aExp := extractFloatx80Exp( a );
  6402. if ( $403E <= aExp ) then begin
  6403. if ( aExp = $7FFF ) and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) then begin
  6404. result := propagateFloatx80NaN( a, a );
  6405. exit;
  6406. end;
  6407. result := a;
  6408. exit;
  6409. end;
  6410. if ( aExp < $3FFF ) then begin
  6411. if ( ( aExp = 0 )
  6412. and ( bits64( extractFloatx80Frac( a ) shl 1 ) = 0 ) ) then begin
  6413. result := a;
  6414. exit;
  6415. end;
  6416. set_inexact_flag;
  6417. aSign := extractFloatx80Sign( a );
  6418. case softfloat_rounding_mode of
  6419. float_round_nearest_even:
  6420. if ( ( aExp = $3FFE ) and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 )
  6421. ) then begin
  6422. result :=
  6423. packFloatx80( aSign, $3FFF, bits64( $8000000000000000 ) );
  6424. exit;
  6425. end;
  6426. float_round_down: begin
  6427. if aSign <> 0 then
  6428. result := packFloatx80( 1, $3FFF, bits64( $8000000000000000 ) )
  6429. else
  6430. result := packFloatx80( 0, 0, 0 );
  6431. exit;
  6432. end;
  6433. float_round_up: begin
  6434. if aSign <> 0 then
  6435. result := packFloatx80( 1, 0, 0 )
  6436. else
  6437. result := packFloatx80( 0, $3FFF, bits64( $8000000000000000 ) );
  6438. exit;
  6439. end;
  6440. end;
  6441. result := packFloatx80( aSign, 0, 0 );
  6442. exit;
  6443. end;
  6444. lastBitMask := 1;
  6445. lastBitMask := lastBitMask shl ( $403E - aExp );
  6446. roundBitsMask := lastBitMask - 1;
  6447. z := a;
  6448. roundingMode := softfloat_rounding_mode;
  6449. if ( roundingMode = float_round_nearest_even ) then begin
  6450. inc( z.low, lastBitMask shr 1 );
  6451. if ( ( z.low and roundBitsMask ) = 0 ) then z.low := z.low and not lastBitMask;
  6452. end
  6453. else if ( roundingMode <> float_round_to_zero ) then begin
  6454. if ( extractFloatx80Sign( z ) <> 0 ) xor ( roundingMode = float_round_up ) then begin
  6455. inc( z.low, roundBitsMask );
  6456. end;
  6457. end;
  6458. z.low := z.low and not roundBitsMask;
  6459. if ( z.low = 0 ) then begin
  6460. inc(z.high);
  6461. z.low := bits64( $8000000000000000 );
  6462. end;
  6463. if ( z.low <> a.low ) then set_inexact_flag;
  6464. result := z;
  6465. end;
  6466. {*----------------------------------------------------------------------------
  6467. | Returns the result of adding the absolute values of the extended double-
  6468. | precision floating-point values `a' and `b'. If `zSign' is 1, the sum is
  6469. | negated before being returned. `zSign' is ignored if the result is a NaN.
  6470. | The addition is performed according to the IEC/IEEE Standard for Binary
  6471. | Floating-Point Arithmetic.
  6472. *----------------------------------------------------------------------------*}
  6473. function addFloatx80Sigs(a: floatx80; b: floatx80; zSign : flag): floatx80;
  6474. var
  6475. aExp, bExp, zExp: int32;
  6476. aSig, bSig, zSig0, zSig1: bits64;
  6477. expDiff: int32;
  6478. label
  6479. shiftRight1, roundAndPack;
  6480. begin
  6481. aSig := extractFloatx80Frac( a );
  6482. aExp := extractFloatx80Exp( a );
  6483. bSig := extractFloatx80Frac( b );
  6484. bExp := extractFloatx80Exp( b );
  6485. expDiff := aExp - bExp;
  6486. if ( 0 < expDiff ) then begin
  6487. if ( aExp = $7FFF ) then begin
  6488. if ( bits64( aSig shl 1 ) <> 0 ) then begin
  6489. result := propagateFloatx80NaN( a, b );
  6490. exit;
  6491. end;
  6492. result := a;
  6493. exit;
  6494. end;
  6495. if ( bExp = 0 ) then dec(expDiff);
  6496. shift64ExtraRightJamming( bSig, 0, expDiff, bSig, zSig1 );
  6497. zExp := aExp;
  6498. end
  6499. else if ( expDiff < 0 ) then begin
  6500. if ( bExp = $7FFF ) then begin
  6501. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6502. result := propagateFloatx80NaN( a, b );
  6503. exit;
  6504. end;
  6505. result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6506. exit;
  6507. end;
  6508. if ( aExp = 0 ) then inc(expDiff);
  6509. shift64ExtraRightJamming( aSig, 0, - expDiff, aSig, zSig1 );
  6510. zExp := bExp;
  6511. end
  6512. else begin
  6513. if ( aExp = $7FFF ) then begin
  6514. if ( bits64( ( aSig or bSig ) shl 1 ) <> 0 ) then begin
  6515. result := propagateFloatx80NaN( a, b );
  6516. exit;
  6517. end;
  6518. result := a;
  6519. exit;
  6520. end;
  6521. zSig1 := 0;
  6522. zSig0 := aSig + bSig;
  6523. if ( aExp = 0 ) then begin
  6524. normalizeFloatx80Subnormal( zSig0, zExp, zSig0 );
  6525. goto roundAndPack;
  6526. end;
  6527. zExp := aExp;
  6528. goto shiftRight1;
  6529. end;
  6530. zSig0 := aSig + bSig;
  6531. if ( sbits64( zSig0 ) < 0 ) then goto roundAndPack;
  6532. shiftRight1:
  6533. shift64ExtraRightJamming( zSig0, zSig1, 1, zSig0, zSig1 );
  6534. zSig0 := zSig0 or $8000000000000000;
  6535. inc(zExp);
  6536. roundAndPack:
  6537. result :=
  6538. roundAndPackFloatx80(
  6539. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6540. end;
  6541. {*----------------------------------------------------------------------------
  6542. | Returns the result of subtracting the absolute values of the extended
  6543. | double-precision floating-point values `a' and `b'. If `zSign' is 1, the
  6544. | difference is negated before being returned. `zSign' is ignored if the
  6545. | result is a NaN. The subtraction is performed according to the IEC/IEEE
  6546. | Standard for Binary Floating-Point Arithmetic.
  6547. *----------------------------------------------------------------------------*}
  6548. function subFloatx80Sigs(a: floatx80; b: floatx80; zSign : flag): floatx80;
  6549. var
  6550. aExp, bExp, zExp: int32;
  6551. aSig, bSig, zSig0, zSig1: bits64;
  6552. expDiff: int32;
  6553. z: floatx80;
  6554. label
  6555. bExpBigger, bBigger, aExpBigger, aBigger, normalizeRoundAndPack;
  6556. begin
  6557. aSig := extractFloatx80Frac( a );
  6558. aExp := extractFloatx80Exp( a );
  6559. bSig := extractFloatx80Frac( b );
  6560. bExp := extractFloatx80Exp( b );
  6561. expDiff := aExp - bExp;
  6562. if ( 0 < expDiff ) then goto aExpBigger;
  6563. if ( expDiff < 0 ) then goto bExpBigger;
  6564. if ( aExp = $7FFF ) then begin
  6565. if ( bits64( ( aSig or bSig ) shl 1 ) <> 0 ) then begin
  6566. result := propagateFloatx80NaN( a, b );
  6567. exit;
  6568. end;
  6569. float_raise( float_flag_invalid );
  6570. z.low := floatx80_default_nan_low;
  6571. z.high := floatx80_default_nan_high;
  6572. result := z;
  6573. exit;
  6574. end;
  6575. if ( aExp = 0 ) then begin
  6576. aExp := 1;
  6577. bExp := 1;
  6578. end;
  6579. zSig1 := 0;
  6580. if ( bSig < aSig ) then goto aBigger;
  6581. if ( aSig < bSig ) then goto bBigger;
  6582. result := packFloatx80( ord( softfloat_rounding_mode = float_round_down ), 0, 0 );
  6583. exit;
  6584. bExpBigger:
  6585. if ( bExp = $7FFF ) then begin
  6586. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6587. result := propagateFloatx80NaN( a, b );
  6588. exit;
  6589. end;
  6590. result := packFloatx80( zSign xor 1, $7FFF, bits64( $8000000000000000 ) );
  6591. exit;
  6592. end;
  6593. if ( aExp = 0 ) then inc(expDiff);
  6594. shift128RightJamming( aSig, 0, - expDiff, aSig, zSig1 );
  6595. bBigger:
  6596. sub128( bSig, 0, aSig, zSig1, zSig0, zSig1 );
  6597. zExp := bExp;
  6598. zSign := zSign xor 1;
  6599. goto normalizeRoundAndPack;
  6600. aExpBigger:
  6601. if ( aExp = $7FFF ) then begin
  6602. if ( bits64( aSig shl 1 ) <> 0 ) then begin
  6603. result := propagateFloatx80NaN( a, b );
  6604. exit;
  6605. end;
  6606. result := a;
  6607. exit;
  6608. end;
  6609. if ( bExp = 0 ) then dec(expDiff);
  6610. shift128RightJamming( bSig, 0, expDiff, bSig, zSig1 );
  6611. aBigger:
  6612. sub128( aSig, 0, bSig, zSig1, zSig0, zSig1 );
  6613. zExp := aExp;
  6614. normalizeRoundAndPack:
  6615. result :=
  6616. normalizeRoundAndPackFloatx80(
  6617. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6618. end;
  6619. {*----------------------------------------------------------------------------
  6620. | Returns the result of adding the extended double-precision floating-point
  6621. | values `a' and `b'. The operation is performed according to the IEC/IEEE
  6622. | Standard for Binary Floating-Point Arithmetic.
  6623. *----------------------------------------------------------------------------*}
  6624. function floatx80_add(a: floatx80; b: floatx80): floatx80;
  6625. var
  6626. aSign, bSign: flag;
  6627. begin
  6628. aSign := extractFloatx80Sign( a );
  6629. bSign := extractFloatx80Sign( b );
  6630. if ( aSign = bSign ) then begin
  6631. result := addFloatx80Sigs( a, b, aSign );
  6632. end
  6633. else begin
  6634. result := subFloatx80Sigs( a, b, aSign );
  6635. end;
  6636. end;
  6637. {*----------------------------------------------------------------------------
  6638. | Returns the result of subtracting the extended double-precision floating-
  6639. | point values `a' and `b'. The operation is performed according to the
  6640. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6641. *----------------------------------------------------------------------------*}
  6642. function floatx80_sub(a: floatx80; b: floatx80 ): floatx80;
  6643. var
  6644. aSign, bSign: flag;
  6645. begin
  6646. aSign := extractFloatx80Sign( a );
  6647. bSign := extractFloatx80Sign( b );
  6648. if ( aSign = bSign ) then begin
  6649. result := subFloatx80Sigs( a, b, aSign );
  6650. end
  6651. else begin
  6652. result := addFloatx80Sigs( a, b, aSign );
  6653. end;
  6654. end;
  6655. {*----------------------------------------------------------------------------
  6656. | Returns the result of multiplying the extended double-precision floating-
  6657. | point values `a' and `b'. The operation is performed according to the
  6658. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6659. *----------------------------------------------------------------------------*}
  6660. function floatx80_mul(a: floatx80; b: floatx80): floatx80;
  6661. var
  6662. aSign, bSign, zSign: flag;
  6663. aExp, bExp, zExp: int32;
  6664. aSig, bSig, zSig0, zSig1: bits64;
  6665. z: floatx80;
  6666. label
  6667. invalid;
  6668. begin
  6669. aSig := extractFloatx80Frac( a );
  6670. aExp := extractFloatx80Exp( a );
  6671. aSign := extractFloatx80Sign( a );
  6672. bSig := extractFloatx80Frac( b );
  6673. bExp := extractFloatx80Exp( b );
  6674. bSign := extractFloatx80Sign( b );
  6675. zSign := aSign xor bSign;
  6676. if ( aExp = $7FFF ) then begin
  6677. if ( bits64( aSig shl 1 ) <> 0 )
  6678. or ( ( bExp = $7FFF ) and ( bits64( bSig shl 1 ) <> 0 ) ) then begin
  6679. result := propagateFloatx80NaN( a, b );
  6680. exit;
  6681. end;
  6682. if ( ( bExp or bSig ) = 0 ) then goto invalid;
  6683. result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6684. exit;
  6685. end;
  6686. if ( bExp = $7FFF ) then begin
  6687. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6688. result := propagateFloatx80NaN( a, b );
  6689. exit;
  6690. end;
  6691. if ( ( aExp or aSig ) = 0 ) then begin
  6692. invalid:
  6693. float_raise( float_flag_invalid );
  6694. z.low := floatx80_default_nan_low;
  6695. z.high := floatx80_default_nan_high;
  6696. result := z;
  6697. exit;
  6698. end;
  6699. result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6700. exit;
  6701. end;
  6702. if ( aExp = 0 ) then begin
  6703. if ( aSig = 0 ) then begin
  6704. result := packFloatx80( zSign, 0, 0 );
  6705. exit;
  6706. end;
  6707. normalizeFloatx80Subnormal( aSig, aExp, aSig );
  6708. end;
  6709. if ( bExp = 0 ) then begin
  6710. if ( bSig = 0 ) then begin
  6711. result := packFloatx80( zSign, 0, 0 );
  6712. exit;
  6713. end;
  6714. normalizeFloatx80Subnormal( bSig, bExp, bSig );
  6715. end;
  6716. zExp := aExp + bExp - $3FFE;
  6717. mul64To128( aSig, bSig, zSig0, zSig1 );
  6718. if 0 < sbits64( zSig0 ) then begin
  6719. shortShift128Left( zSig0, zSig1, 1, zSig0, zSig1 );
  6720. dec(zExp);
  6721. end;
  6722. result :=
  6723. roundAndPackFloatx80(
  6724. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6725. end;
  6726. {*----------------------------------------------------------------------------
  6727. | Returns the result of dividing the extended double-precision floating-point
  6728. | value `a' by the corresponding value `b'. The operation is performed
  6729. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6730. *----------------------------------------------------------------------------*}
  6731. function floatx80_div(a: floatx80; b: floatx80 ): floatx80;
  6732. var
  6733. aSign, bSign, zSign: flag;
  6734. aExp, bExp, zExp: int32;
  6735. aSig, bSig, zSig0, zSig1: bits64;
  6736. rem0, rem1, rem2, term0, term1, term2: bits64;
  6737. z: floatx80;
  6738. label
  6739. invalid;
  6740. begin
  6741. aSig := extractFloatx80Frac( a );
  6742. aExp := extractFloatx80Exp( a );
  6743. aSign := extractFloatx80Sign( a );
  6744. bSig := extractFloatx80Frac( b );
  6745. bExp := extractFloatx80Exp( b );
  6746. bSign := extractFloatx80Sign( b );
  6747. zSign := aSign xor bSign;
  6748. if ( aExp = $7FFF ) then begin
  6749. if ( bits64( aSig shl 1 ) <> 0 ) then begin
  6750. result := propagateFloatx80NaN( a, b );
  6751. exit;
  6752. end;
  6753. if ( bExp = $7FFF ) then begin
  6754. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6755. result := propagateFloatx80NaN( a, b );
  6756. exit;
  6757. end;
  6758. goto invalid;
  6759. end;
  6760. result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6761. exit;
  6762. end;
  6763. if ( bExp = $7FFF ) then begin
  6764. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6765. result := propagateFloatx80NaN( a, b );
  6766. exit;
  6767. end;
  6768. result := packFloatx80( zSign, 0, 0 );
  6769. exit;
  6770. end;
  6771. if ( bExp = 0 ) then begin
  6772. if ( bSig = 0 ) then begin
  6773. if ( ( aExp or aSig ) = 0 ) then begin
  6774. invalid:
  6775. float_raise( float_flag_invalid );
  6776. z.low := floatx80_default_nan_low;
  6777. z.high := floatx80_default_nan_high;
  6778. result := z;
  6779. exit;
  6780. end;
  6781. float_raise( float_flag_divbyzero );
  6782. result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6783. exit;
  6784. end;
  6785. normalizeFloatx80Subnormal( bSig, bExp, bSig );
  6786. end;
  6787. if ( aExp = 0 ) then begin
  6788. if ( aSig = 0 ) then begin
  6789. result := packFloatx80( zSign, 0, 0 );
  6790. exit;
  6791. end;
  6792. normalizeFloatx80Subnormal( aSig, aExp, aSig );
  6793. end;
  6794. zExp := aExp - bExp + $3FFE;
  6795. rem1 := 0;
  6796. if ( bSig <= aSig ) then begin
  6797. shift128Right( aSig, 0, 1, aSig, rem1 );
  6798. inc(zExp);
  6799. end;
  6800. zSig0 := estimateDiv128To64( aSig, rem1, bSig );
  6801. mul64To128( bSig, zSig0, term0, term1 );
  6802. sub128( aSig, rem1, term0, term1, rem0, rem1 );
  6803. while ( sbits64( rem0 ) < 0 ) do begin
  6804. dec(zSig0);
  6805. add128( rem0, rem1, 0, bSig, rem0, rem1 );
  6806. end;
  6807. zSig1 := estimateDiv128To64( rem1, 0, bSig );
  6808. if ( bits64( zSig1 shl 1 ) <= 8 ) then begin
  6809. mul64To128( bSig, zSig1, term1, term2 );
  6810. sub128( rem1, 0, term1, term2, rem1, rem2 );
  6811. while ( sbits64( rem1 ) < 0 ) do begin
  6812. dec(zSig1);
  6813. add128( rem1, rem2, 0, bSig, rem1, rem2 );
  6814. end;
  6815. zSig1 := zSig1 or ord( ( rem1 or rem2 ) <> 0 );
  6816. end;
  6817. result :=
  6818. roundAndPackFloatx80(
  6819. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6820. end;
  6821. {*----------------------------------------------------------------------------
  6822. | Returns the remainder of the extended double-precision floating-point value
  6823. | `a' with respect to the corresponding value `b'. The operation is performed
  6824. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6825. *----------------------------------------------------------------------------*}
  6826. function floatx80_rem(a: floatx80; b: floatx80 ): floatx80;
  6827. var
  6828. aSign, zSign: flag;
  6829. aExp, bExp, expDiff: int32;
  6830. aSig0, aSig1, bSig: bits64;
  6831. q, term0, term1, alternateASig0, alternateASig1: bits64;
  6832. z: floatx80;
  6833. label
  6834. invalid;
  6835. begin
  6836. aSig0 := extractFloatx80Frac( a );
  6837. aExp := extractFloatx80Exp( a );
  6838. aSign := extractFloatx80Sign( a );
  6839. bSig := extractFloatx80Frac( b );
  6840. bExp := extractFloatx80Exp( b );
  6841. if ( aExp = $7FFF ) then begin
  6842. if ( bits64( aSig0 shl 1 ) <> 0 )
  6843. or ( ( bExp = $7FFF ) and ( bits64( bSig shl 1 ) <> 0 ) ) then begin
  6844. result := propagateFloatx80NaN( a, b );
  6845. exit;
  6846. end;
  6847. goto invalid;
  6848. end;
  6849. if ( bExp = $7FFF ) then begin
  6850. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6851. result := propagateFloatx80NaN( a, b );
  6852. exit;
  6853. end;
  6854. result := a;
  6855. exit;
  6856. end;
  6857. if ( bExp = 0 ) then begin
  6858. if ( bSig = 0 ) then begin
  6859. invalid:
  6860. float_raise( float_flag_invalid );
  6861. z.low := floatx80_default_nan_low;
  6862. z.high := floatx80_default_nan_high;
  6863. result := z;
  6864. exit;
  6865. end;
  6866. normalizeFloatx80Subnormal( bSig, bExp, bSig );
  6867. end;
  6868. if ( aExp = 0 ) then begin
  6869. if ( bits64( aSig0 shl 1 ) = 0 ) then begin
  6870. result := a;
  6871. exit;
  6872. end;
  6873. normalizeFloatx80Subnormal( aSig0, aExp, aSig0 );
  6874. end;
  6875. bSig := bSig or $8000000000000000;
  6876. zSign := aSign;
  6877. expDiff := aExp - bExp;
  6878. aSig1 := 0;
  6879. if ( expDiff < 0 ) then begin
  6880. if ( expDiff < -1 ) then begin
  6881. result := a;
  6882. exit;
  6883. end;
  6884. shift128Right( aSig0, 0, 1, aSig0, aSig1 );
  6885. expDiff := 0;
  6886. end;
  6887. q := ord( bSig <= aSig0 );
  6888. if ( q <> 0 ) then dec( aSig0, bSig );
  6889. dec( expDiff, 64 );
  6890. while ( 0 < expDiff ) do begin
  6891. q := estimateDiv128To64( aSig0, aSig1, bSig );
  6892. if ( 2 < q ) then q := q - 2 else q := 0;
  6893. mul64To128( bSig, q, term0, term1 );
  6894. sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );
  6895. shortShift128Left( aSig0, aSig1, 62, aSig0, aSig1 );
  6896. dec( expDiff, 62 );
  6897. end;
  6898. inc( expDiff, 64 );
  6899. if ( 0 < expDiff ) then begin
  6900. q := estimateDiv128To64( aSig0, aSig1, bSig );
  6901. if ( 2 < q ) then q:= q - 2 else q := 0;
  6902. q := q shr ( 64 - expDiff );
  6903. mul64To128( bSig, q shl ( 64 - expDiff ), term0, term1 );
  6904. sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );
  6905. shortShift128Left( 0, bSig, 64 - expDiff, term0, term1 );
  6906. while ( le128( term0, term1, aSig0, aSig1 ) <> 0 ) do begin
  6907. inc(q);
  6908. sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );
  6909. end;
  6910. end
  6911. else begin
  6912. term1 := 0;
  6913. term0 := bSig;
  6914. end;
  6915. sub128( term0, term1, aSig0, aSig1, alternateASig0, alternateASig1 );
  6916. if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) <> 0 )
  6917. or ( ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) <> 0 )
  6918. and ( q and 1 <> 0 ) )
  6919. then begin
  6920. aSig0 := alternateASig0;
  6921. aSig1 := alternateASig1;
  6922. zSign := ord( zSign = 0 );
  6923. end;
  6924. result :=
  6925. normalizeRoundAndPackFloatx80(
  6926. 80, zSign, bExp + expDiff, aSig0, aSig1 );
  6927. end;
  6928. {*----------------------------------------------------------------------------
  6929. | Returns the square root of the extended double-precision floating-point
  6930. | value `a'. The operation is performed according to the IEC/IEEE Standard
  6931. | for Binary Floating-Point Arithmetic.
  6932. *----------------------------------------------------------------------------*}
  6933. function floatx80_sqrt(a: floatx80): floatx80;
  6934. var
  6935. aSign: flag;
  6936. aExp, zExp: int32;
  6937. aSig0, aSig1, zSig0, zSig1, doubleZSig0: bits64;
  6938. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
  6939. z: floatx80;
  6940. label
  6941. invalid;
  6942. begin
  6943. aSig0 := extractFloatx80Frac( a );
  6944. aExp := extractFloatx80Exp( a );
  6945. aSign := extractFloatx80Sign( a );
  6946. if ( aExp = $7FFF ) then begin
  6947. if ( bits64( aSig0 shl 1 ) <> 0 ) then begin
  6948. result := propagateFloatx80NaN( a, a );
  6949. exit;
  6950. end;
  6951. if ( aSign = 0 ) then begin
  6952. result := a;
  6953. exit;
  6954. end;
  6955. goto invalid;
  6956. end;
  6957. if ( aSign <> 0 ) then begin
  6958. if ( ( aExp or aSig0 ) = 0 ) then begin
  6959. result := a;
  6960. exit;
  6961. end;
  6962. invalid:
  6963. float_raise( float_flag_invalid );
  6964. z.low := floatx80_default_nan_low;
  6965. z.high := floatx80_default_nan_high;
  6966. result := z;
  6967. exit;
  6968. end;
  6969. if ( aExp = 0 ) then begin
  6970. if ( aSig0 = 0 ) then begin
  6971. result := packFloatx80( 0, 0, 0 );
  6972. exit;
  6973. end;
  6974. normalizeFloatx80Subnormal( aSig0, aExp, aSig0 );
  6975. end;
  6976. zExp := ( ( aExp - $3FFF ) shr 1 ) + $3FFF;
  6977. zSig0 := estimateSqrt32( aExp, aSig0 shr 32 );
  6978. shift128Right( aSig0, 0, 2 + ( aExp and 1 ), aSig0, aSig1 );
  6979. zSig0 := estimateDiv128To64( aSig0, aSig1, zSig0 shl 32 ) + ( zSig0 shl 30 );
  6980. doubleZSig0 := zSig0 shl 1;
  6981. mul64To128( zSig0, zSig0, term0, term1 );
  6982. sub128( aSig0, aSig1, term0, term1, rem0, rem1 );
  6983. while ( sbits64( rem0 ) < 0 ) do begin
  6984. dec(zSig0);
  6985. dec( doubleZSig0, 2 );
  6986. add128( rem0, rem1, zSig0 shr 63, doubleZSig0 or 1, rem0, rem1 );
  6987. end;
  6988. zSig1 := estimateDiv128To64( rem1, 0, doubleZSig0 );
  6989. if ( ( zSig1 and $3FFFFFFFFFFFFFFF ) <= 5 ) then begin
  6990. if ( zSig1 = 0 ) then zSig1 := 1;
  6991. mul64To128( doubleZSig0, zSig1, term1, term2 );
  6992. sub128( rem1, 0, term1, term2, rem1, rem2 );
  6993. mul64To128( zSig1, zSig1, term2, term3 );
  6994. sub192( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
  6995. while ( sbits64( rem1 ) < 0 ) do begin
  6996. dec(zSig1);
  6997. shortShift128Left( 0, zSig1, 1, term2, term3 );
  6998. term3 := term3 or 1;
  6999. term2 := term2 or doubleZSig0;
  7000. add192( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
  7001. end;
  7002. zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );
  7003. end;
  7004. shortShift128Left( 0, zSig1, 1, zSig0, zSig1 );
  7005. zSig0 := zSig0 or doubleZSig0;
  7006. result :=
  7007. roundAndPackFloatx80(
  7008. floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );
  7009. end;
  7010. {*----------------------------------------------------------------------------
  7011. | Returns 1 if the extended double-precision floating-point value `a' is
  7012. | equal to the corresponding value `b', and 0 otherwise. The comparison is
  7013. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  7014. | Arithmetic.
  7015. *----------------------------------------------------------------------------*}
  7016. function floatx80_eq(a: floatx80; b: floatx80 ): flag;
  7017. begin
  7018. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7019. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 )
  7020. ) or ( ( extractFloatx80Exp( b ) = $7FFF )
  7021. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 )
  7022. ) then begin
  7023. if ( floatx80_is_signaling_nan( a )
  7024. or floatx80_is_signaling_nan( b ) <> 0 ) then begin
  7025. float_raise( float_flag_invalid );
  7026. end;
  7027. result := 0;
  7028. exit;
  7029. end;
  7030. result := ord(
  7031. ( a.low = b.low )
  7032. and ( ( a.high = b.high )
  7033. or ( ( a.low = 0 )
  7034. and ( bits16 ( ( a.high or b.high ) shl 1 ) = 0 ) )
  7035. ) );
  7036. end;
  7037. {*----------------------------------------------------------------------------
  7038. | Returns 1 if the extended double-precision floating-point value `a' is
  7039. | less than or equal to the corresponding value `b', and 0 otherwise. The
  7040. | comparison is performed according to the IEC/IEEE Standard for Binary
  7041. | Floating-Point Arithmetic.
  7042. *----------------------------------------------------------------------------*}
  7043. function floatx80_le(a: floatx80; b: floatx80 ): flag;
  7044. var
  7045. aSign, bSign: flag;
  7046. begin
  7047. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7048. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )
  7049. or ( ( extractFloatx80Exp( b ) = $7FFF )
  7050. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )
  7051. then begin
  7052. float_raise( float_flag_invalid );
  7053. result := 0;
  7054. exit;
  7055. end;
  7056. aSign := extractFloatx80Sign( a );
  7057. bSign := extractFloatx80Sign( b );
  7058. if ( aSign <> bSign ) then begin
  7059. result := ord(
  7060. ( aSign <> 0 )
  7061. or ( bits16( ( a.high or b.high ) shl 1 ) or a.low or b.low = 0 ) );
  7062. exit;
  7063. end;
  7064. if aSign<>0 then
  7065. result := le128( b.high, b.low, a.high, a.low )
  7066. else
  7067. result := le128( a.high, a.low, b.high, b.low );
  7068. end;
  7069. {*----------------------------------------------------------------------------
  7070. | Returns 1 if the extended double-precision floating-point value `a' is
  7071. | less than the corresponding value `b', and 0 otherwise. The comparison
  7072. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7073. | Arithmetic.
  7074. *----------------------------------------------------------------------------*}
  7075. function floatx80_lt(a: floatx80; b: floatx80 ): flag;
  7076. var
  7077. aSign, bSign: flag;
  7078. begin
  7079. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7080. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )
  7081. or ( ( extractFloatx80Exp( b ) = $7FFF )
  7082. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )
  7083. then begin
  7084. float_raise( float_flag_invalid );
  7085. result := 0;
  7086. exit;
  7087. end;
  7088. aSign := extractFloatx80Sign( a );
  7089. bSign := extractFloatx80Sign( b );
  7090. if ( aSign <> bSign ) then begin
  7091. result := ord(
  7092. ( aSign <> 0 )
  7093. and ( bits16( ( a.high or b.high ) shl 1 ) or a.low or b.low <> 0 ) );
  7094. exit;
  7095. end;
  7096. if aSign <> 0 then
  7097. result := lt128( b.high, b.low, a.high, a.low )
  7098. else
  7099. result := lt128( a.high, a.low, b.high, b.low );
  7100. end;
  7101. {*----------------------------------------------------------------------------
  7102. | Returns 1 if the extended double-precision floating-point value `a' is equal
  7103. | to the corresponding value `b', and 0 otherwise. The invalid exception is
  7104. | raised if either operand is a NaN. Otherwise, the comparison is performed
  7105. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7106. *----------------------------------------------------------------------------*}
  7107. function floatx80_eq_signaling(a: floatx80; b: floatx80 ): flag;
  7108. begin
  7109. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7110. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )
  7111. or ( ( extractFloatx80Exp( b ) = $7FFF )
  7112. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )
  7113. then begin
  7114. float_raise( float_flag_invalid );
  7115. result := 0;
  7116. exit;
  7117. end;
  7118. result := ord(
  7119. ( a.low = b.low )
  7120. and ( ( a.high = b.high )
  7121. or ( ( a.low = 0 )
  7122. and ( bits16( ( a.high or b.high ) shl 1 ) = 0 ) )
  7123. ) );
  7124. end;
  7125. {*----------------------------------------------------------------------------
  7126. | Returns 1 if the extended double-precision floating-point value `a' is less
  7127. | than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs
  7128. | do not cause an exception. Otherwise, the comparison is performed according
  7129. | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7130. *----------------------------------------------------------------------------*}
  7131. function floatx80_le_quiet(a: floatx80; b: floatx80 ): flag;
  7132. var
  7133. aSign, bSign: flag;
  7134. begin
  7135. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7136. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )
  7137. or ( ( extractFloatx80Exp( b ) = $7FFF )
  7138. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )
  7139. then begin
  7140. if ( floatx80_is_signaling_nan( a )
  7141. or floatx80_is_signaling_nan( b ) <> 0 ) then begin
  7142. float_raise( float_flag_invalid );
  7143. end;
  7144. result := 0;
  7145. exit;
  7146. end;
  7147. aSign := extractFloatx80Sign( a );
  7148. bSign := extractFloatx80Sign( b );
  7149. if ( aSign <> bSign ) then begin
  7150. result := ord(
  7151. ( aSign <> 0 )
  7152. or ( ( bits16( ( a.high or b.high ) shl 1 ) ) or a.low or b.low = 0 ) );
  7153. exit;
  7154. end;
  7155. if aSign <> 0 then
  7156. result := le128( b.high, b.low, a.high, a.low )
  7157. else
  7158. result := le128( a.high, a.low, b.high, b.low );
  7159. end;
  7160. {*----------------------------------------------------------------------------
  7161. | Returns 1 if the extended double-precision floating-point value `a' is less
  7162. | than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause
  7163. | an exception. Otherwise, the comparison is performed according to the
  7164. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7165. *----------------------------------------------------------------------------*}
  7166. function floatx80_lt_quiet(a: floatx80; b: floatx80 ): flag;
  7167. var
  7168. aSign, bSign: flag;
  7169. begin
  7170. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7171. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )
  7172. or ( ( extractFloatx80Exp( b ) = $7FFF )
  7173. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )
  7174. then begin
  7175. if ( floatx80_is_signaling_nan( a )
  7176. or floatx80_is_signaling_nan( b ) <> 0 ) then begin
  7177. float_raise( float_flag_invalid );
  7178. end;
  7179. result := 0;
  7180. exit;
  7181. end;
  7182. aSign := extractFloatx80Sign( a );
  7183. bSign := extractFloatx80Sign( b );
  7184. if ( aSign <> bSign ) then begin
  7185. result := ord(
  7186. ( aSign <> 0 )
  7187. and ( bits16( ( a.high or b.high ) shl 1 ) or a.low or b.low <> 0 ) );
  7188. exit;
  7189. end;
  7190. if aSign <> 0 then
  7191. result := lt128( b.high, b.low, a.high, a.low )
  7192. else
  7193. result := lt128( a.high, a.low, b.high, b.low );
  7194. end;
  7195. {$endif FPC_SOFTFLOAT_FLOATX80}
  7196. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  7197. {*----------------------------------------------------------------------------
  7198. | Returns the least-significant 64 fraction bits of the quadruple-precision
  7199. | floating-point value `a'.
  7200. *----------------------------------------------------------------------------*}
  7201. function extractFloat128Frac1(a : float128): bits64;
  7202. begin
  7203. result:=a.low;
  7204. end;
  7205. {*----------------------------------------------------------------------------
  7206. | Returns the most-significant 48 fraction bits of the quadruple-precision
  7207. | floating-point value `a'.
  7208. *----------------------------------------------------------------------------*}
  7209. function extractFloat128Frac0(a : float128): bits64;
  7210. begin
  7211. result:=a.high and int64($0000FFFFFFFFFFFF);
  7212. end;
  7213. {*----------------------------------------------------------------------------
  7214. | Returns the exponent bits of the quadruple-precision floating-point value
  7215. | `a'.
  7216. *----------------------------------------------------------------------------*}
  7217. function extractFloat128Exp(a : float128): int32;
  7218. begin
  7219. result:=( a.high shr 48 ) and $7FFF;
  7220. end;
  7221. {*----------------------------------------------------------------------------
  7222. | Returns the sign bit of the quadruple-precision floating-point value `a'.
  7223. *----------------------------------------------------------------------------*}
  7224. function extractFloat128Sign(a : float128): flag;
  7225. begin
  7226. result:=a.high shr 63;
  7227. end;
  7228. {*----------------------------------------------------------------------------
  7229. | Normalizes the subnormal quadruple-precision floating-point value
  7230. | represented by the denormalized significand formed by the concatenation of
  7231. | `aSig0' and `aSig1'. The normalized exponent is stored at the location
  7232. | pointed to by `zExpPtr'. The most significant 49 bits of the normalized
  7233. | significand are stored at the location pointed to by `zSig0Ptr', and the
  7234. | least significant 64 bits of the normalized significand are stored at the
  7235. | location pointed to by `zSig1Ptr'.
  7236. *----------------------------------------------------------------------------*}
  7237. procedure normalizeFloat128Subnormal(
  7238. aSig0: bits64;
  7239. aSig1: bits64;
  7240. var zExpPtr: int32;
  7241. var zSig0Ptr: bits64;
  7242. var zSig1Ptr: bits64);
  7243. var
  7244. shiftCount: int8;
  7245. begin
  7246. if ( aSig0 = 0 ) then
  7247. begin
  7248. shiftCount := countLeadingZeros64( aSig1 ) - 15;
  7249. if ( shiftCount < 0 ) then
  7250. begin
  7251. zSig0Ptr := aSig1 shr ( - shiftCount );
  7252. zSig1Ptr := aSig1 shl ( shiftCount and 63 );
  7253. end
  7254. else begin
  7255. zSig0Ptr := aSig1 shl shiftCount;
  7256. zSig1Ptr := 0;
  7257. end;
  7258. zExpPtr := - shiftCount - 63;
  7259. end
  7260. else begin
  7261. shiftCount := countLeadingZeros64( aSig0 ) - 15;
  7262. shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
  7263. zExpPtr := 1 - shiftCount;
  7264. end;
  7265. end;
  7266. {*----------------------------------------------------------------------------
  7267. | Packs the sign `zSign', the exponent `zExp', and the significand formed
  7268. | by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
  7269. | floating-point value, returning the result. After being shifted into the
  7270. | proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
  7271. | added together to form the most significant 32 bits of the result. This
  7272. | means that any integer portion of `zSig0' will be added into the exponent.
  7273. | Since a properly normalized significand will have an integer portion equal
  7274. | to 1, the `zExp' input should be 1 less than the desired result exponent
  7275. | whenever `zSig0' and `zSig1' concatenated form a complete, normalized
  7276. | significand.
  7277. *----------------------------------------------------------------------------*}
  7278. function packFloat128( zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64) : float128;
  7279. var
  7280. z: float128;
  7281. begin
  7282. z.low := zSig1;
  7283. z.high := ( ( bits64(zSign) ) shl 63 ) + ( ( bits64(zExp) ) shl 48 ) + zSig0;
  7284. result:=z;
  7285. end;
  7286. {*----------------------------------------------------------------------------
  7287. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  7288. | and extended significand formed by the concatenation of `zSig0', `zSig1',
  7289. | and `zSig2', and returns the proper quadruple-precision floating-point value
  7290. | corresponding to the abstract input. Ordinarily, the abstract value is
  7291. | simply rounded and packed into the quadruple-precision format, with the
  7292. | inexact exception raised if the abstract input cannot be represented
  7293. | exactly. However, if the abstract value is too large, the overflow and
  7294. | inexact exceptions are raised and an infinity or maximal finite value is
  7295. | returned. If the abstract value is too small, the input value is rounded to
  7296. | a subnormal number, and the underflow and inexact exceptions are raised if
  7297. | the abstract input cannot be represented exactly as a subnormal quadruple-
  7298. | precision floating-point number.
  7299. | The input significand must be normalized or smaller. If the input
  7300. | significand is not normalized, `zExp' must be 0; in that case, the result
  7301. | returned is a subnormal number, and it must not require rounding. In the
  7302. | usual case that the input significand is normalized, `zExp' must be 1 less
  7303. | than the ``true'' floating-point exponent. The handling of underflow and
  7304. | overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7305. *----------------------------------------------------------------------------*}
  7306. function roundAndPackFloat128(zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64; zSig2: bits64): float128;
  7307. var
  7308. roundingMode: int8;
  7309. roundNearestEven, increment, isTiny: flag;
  7310. begin
  7311. roundingMode := softfloat_rounding_mode;
  7312. roundNearestEven := ord( roundingMode = float_round_nearest_even );
  7313. increment := ord( sbits64(zSig2) < 0 );
  7314. if ( roundNearestEven=0 ) then
  7315. begin
  7316. if ( roundingMode = float_round_to_zero ) then
  7317. begin
  7318. increment := 0;
  7319. end
  7320. else begin
  7321. if ( zSign<>0 ) then
  7322. begin
  7323. increment := ord( roundingMode = float_round_down ) and zSig2;
  7324. end
  7325. else begin
  7326. increment := ord( roundingMode = float_round_up ) and zSig2;
  7327. end;
  7328. end;
  7329. end;
  7330. if ( $7FFD <= bits32(zExp) ) then
  7331. begin
  7332. if ( ord( $7FFD < zExp )
  7333. or ( ord( zExp = $7FFD )
  7334. and eq128(
  7335. int64( $0001FFFFFFFFFFFF ),
  7336. bits64( $FFFFFFFFFFFFFFFF ),
  7337. zSig0,
  7338. zSig1
  7339. )
  7340. and increment
  7341. )
  7342. )<>0 then
  7343. begin
  7344. float_raise( [float_flag_overflow,float_flag_inexact] );
  7345. if ( ord( roundingMode = float_round_to_zero )
  7346. or ( zSign and ord( roundingMode = float_round_up ) )
  7347. or ( ord( zSign = 0) and ord( roundingMode = float_round_down ) )
  7348. )<>0 then
  7349. begin
  7350. result :=
  7351. packFloat128(
  7352. zSign,
  7353. $7FFE,
  7354. int64( $0000FFFFFFFFFFFF ),
  7355. bits64( $FFFFFFFFFFFFFFFF )
  7356. );
  7357. exit;
  7358. end;
  7359. result:=packFloat128( zSign, $7FFF, 0, 0 );
  7360. exit;
  7361. end;
  7362. if ( zExp < 0 ) then
  7363. begin
  7364. isTiny :=
  7365. ord(( softfloat_detect_tininess = float_tininess_before_rounding )
  7366. or ( zExp < -1 )
  7367. or not( increment<>0 )
  7368. or boolean(lt128(
  7369. zSig0,
  7370. zSig1,
  7371. int64( $0001FFFFFFFFFFFF ),
  7372. bits64( $FFFFFFFFFFFFFFFF )
  7373. )));
  7374. shift128ExtraRightJamming(
  7375. zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );
  7376. zExp := 0;
  7377. if ( isTiny and zSig2 )<>0 then
  7378. float_raise( float_flag_underflow );
  7379. if ( roundNearestEven<>0 ) then
  7380. begin
  7381. increment := ord( sbits64(zSig2) < 0 );
  7382. end
  7383. else begin
  7384. if ( zSign<>0 ) then
  7385. begin
  7386. increment := ord( roundingMode = float_round_down ) and zSig2;
  7387. end
  7388. else begin
  7389. increment := ord( roundingMode = float_round_up ) and zSig2;
  7390. end;
  7391. end;
  7392. end;
  7393. end;
  7394. if ( zSig2<>0 ) then
  7395. set_inexact_flag;
  7396. if ( increment<>0 ) then
  7397. begin
  7398. add128( zSig0, zSig1, 0, 1, zSig0, zSig1 );
  7399. zSig1 := zSig1 and not bits64( ord( zSig2 + zSig2 = 0 ) and roundNearestEven );
  7400. end
  7401. else begin
  7402. if ( ( zSig0 or zSig1 ) = 0 ) then
  7403. zExp := 0;
  7404. end;
  7405. result:=packFloat128( zSign, zExp, zSig0, zSig1 );
  7406. end;
  7407. {*----------------------------------------------------------------------------
  7408. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  7409. | and significand formed by the concatenation of `zSig0' and `zSig1', and
  7410. | returns the proper quadruple-precision floating-point value corresponding
  7411. | to the abstract input. This routine is just like `roundAndPackFloat128'
  7412. | except that the input significand has fewer bits and does not have to be
  7413. | normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
  7414. | point exponent.
  7415. *----------------------------------------------------------------------------*}
  7416. function normalizeRoundAndPackFloat128(zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): float128;
  7417. var
  7418. shiftCount: int8;
  7419. zSig2: bits64;
  7420. begin
  7421. if ( zSig0 = 0 ) then
  7422. begin
  7423. zSig0 := zSig1;
  7424. zSig1 := 0;
  7425. dec(zExp, 64);
  7426. end;
  7427. shiftCount := countLeadingZeros64( zSig0 ) - 15;
  7428. if ( 0 <= shiftCount ) then
  7429. begin
  7430. zSig2 := 0;
  7431. shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  7432. end
  7433. else begin
  7434. shift128ExtraRightJamming(
  7435. zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );
  7436. end;
  7437. dec(zExp, shiftCount);
  7438. result:=roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  7439. end;
  7440. {*----------------------------------------------------------------------------
  7441. | Returns the result of converting the quadruple-precision floating-point
  7442. | value `a' to the 32-bit two's complement integer format. The conversion
  7443. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7444. | Arithmetic---which means in particular that the conversion is rounded
  7445. | according to the current rounding mode. If `a' is a NaN, the largest
  7446. | positive integer is returned. Otherwise, if the conversion overflows, the
  7447. | largest integer with the same sign as `a' is returned.
  7448. *----------------------------------------------------------------------------*}
  7449. function float128_to_int32(a: float128): int32;
  7450. var
  7451. aSign: flag;
  7452. aExp, shiftCount: int32;
  7453. aSig0, aSig1: bits64;
  7454. begin
  7455. aSig1 := extractFloat128Frac1( a );
  7456. aSig0 := extractFloat128Frac0( a );
  7457. aExp := extractFloat128Exp( a );
  7458. aSign := extractFloat128Sign( a );
  7459. if ( ord( aExp = $7FFF ) and ( aSig0 or aSig1 ) )<>0 then
  7460. aSign := 0;
  7461. if ( aExp<>0 ) then
  7462. aSig0 := aSig0 or int64( $0001000000000000 );
  7463. aSig0 := aSig0 or ord( aSig1 <> 0 );
  7464. shiftCount := $4028 - aExp;
  7465. if ( 0 < shiftCount ) then
  7466. shift64RightJamming( aSig0, shiftCount, aSig0 );
  7467. result := roundAndPackInt32( aSign, aSig0 );
  7468. end;
  7469. {*----------------------------------------------------------------------------
  7470. | Returns the result of converting the quadruple-precision floating-point
  7471. | value `a' to the 32-bit two's complement integer format. The conversion
  7472. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7473. | Arithmetic, except that the conversion is always rounded toward zero. If
  7474. | `a' is a NaN, the largest positive integer is returned. Otherwise, if the
  7475. | conversion overflows, the largest integer with the same sign as `a' is
  7476. | returned.
  7477. *----------------------------------------------------------------------------*}
  7478. function float128_to_int32_round_to_zero(a: float128): int32;
  7479. var
  7480. aSign: flag;
  7481. aExp, shiftCount: int32;
  7482. aSig0, aSig1, savedASig: bits64;
  7483. z: int32;
  7484. label
  7485. invalid;
  7486. begin
  7487. aSig1 := extractFloat128Frac1( a );
  7488. aSig0 := extractFloat128Frac0( a );
  7489. aExp := extractFloat128Exp( a );
  7490. aSign := extractFloat128Sign( a );
  7491. aSig0 := aSig0 or ord( aSig1 <> 0 );
  7492. if ( $401E < aExp ) then
  7493. begin
  7494. if ( ord( aExp = $7FFF ) and aSig0 )<>0 then
  7495. aSign := 0;
  7496. goto invalid;
  7497. end
  7498. else if ( aExp < $3FFF ) then
  7499. begin
  7500. if ( aExp or aSig0 )<>0 then
  7501. set_inexact_flag;
  7502. result := 0;
  7503. exit;
  7504. end;
  7505. aSig0 := aSig0 or int64( $0001000000000000 );
  7506. shiftCount := $402F - aExp;
  7507. savedASig := aSig0;
  7508. aSig0 := aSig0 shr shiftCount;
  7509. z := aSig0;
  7510. if ( aSign )<>0 then
  7511. z := - z;
  7512. if ( ord( z < 0 ) xor aSign )<>0 then
  7513. begin
  7514. invalid:
  7515. float_raise( float_flag_invalid );
  7516. if aSign<>0 then
  7517. result:= int32( $80000000 )
  7518. else
  7519. result:=$7FFFFFFF;
  7520. exit;
  7521. end;
  7522. if ( ( aSig0 shl shiftCount ) <> savedASig ) then
  7523. begin
  7524. set_inexact_flag;
  7525. end;
  7526. result := z;
  7527. end;
  7528. {*----------------------------------------------------------------------------
  7529. | Returns the result of converting the quadruple-precision floating-point
  7530. | value `a' to the 64-bit two's complement integer format. The conversion
  7531. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7532. | Arithmetic---which means in particular that the conversion is rounded
  7533. | according to the current rounding mode. If `a' is a NaN, the largest
  7534. | positive integer is returned. Otherwise, if the conversion overflows, the
  7535. | largest integer with the same sign as `a' is returned.
  7536. *----------------------------------------------------------------------------*}
  7537. function float128_to_int64(a: float128): int64;
  7538. var
  7539. aSign: flag;
  7540. aExp, shiftCount: int32;
  7541. aSig0, aSig1: bits64;
  7542. begin
  7543. aSig1 := extractFloat128Frac1( a );
  7544. aSig0 := extractFloat128Frac0( a );
  7545. aExp := extractFloat128Exp( a );
  7546. aSign := extractFloat128Sign( a );
  7547. if ( aExp<>0 ) then
  7548. aSig0 := aSig0 or int64( $0001000000000000 );
  7549. shiftCount := $402F - aExp;
  7550. if ( shiftCount <= 0 ) then
  7551. begin
  7552. if ( $403E < aExp ) then
  7553. begin
  7554. float_raise( float_flag_invalid );
  7555. if ( (aSign=0)
  7556. or ( ( aExp = $7FFF )
  7557. and ( (aSig1<>0) or ( aSig0 <> int64( $0001000000000000 ) ) )
  7558. )
  7559. ) then
  7560. begin
  7561. result := int64( $7FFFFFFFFFFFFFFF );
  7562. exit;
  7563. end;
  7564. result := int64( $8000000000000000 );
  7565. exit;
  7566. end;
  7567. shortShift128Left( aSig0, aSig1, - shiftCount, aSig0, aSig1 );
  7568. end
  7569. else begin
  7570. shift64ExtraRightJamming( aSig0, aSig1, shiftCount, aSig0, aSig1 );
  7571. end;
  7572. result := roundAndPackInt64( aSign, aSig0, aSig1 );
  7573. end;
  7574. {*----------------------------------------------------------------------------
  7575. | Returns the result of converting the quadruple-precision floating-point
  7576. | value `a' to the 64-bit two's complement integer format. The conversion
  7577. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7578. | Arithmetic, except that the conversion is always rounded toward zero.
  7579. | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  7580. | the conversion overflows, the largest integer with the same sign as `a' is
  7581. | returned.
  7582. *----------------------------------------------------------------------------*}
  7583. function float128_to_int64_round_to_zero(a: float128): int64;
  7584. var
  7585. aSign: flag;
  7586. aExp, shiftCount: int32;
  7587. aSig0, aSig1: bits64;
  7588. z: int64;
  7589. begin
  7590. aSig1 := extractFloat128Frac1( a );
  7591. aSig0 := extractFloat128Frac0( a );
  7592. aExp := extractFloat128Exp( a );
  7593. aSign := extractFloat128Sign( a );
  7594. if ( aExp<>0 ) then
  7595. aSig0 := aSig0 or int64( $0001000000000000 );
  7596. shiftCount := aExp - $402F;
  7597. if ( 0 < shiftCount ) then
  7598. begin
  7599. if ( $403E <= aExp ) then
  7600. begin
  7601. aSig0 := aSig0 and int64( $0000FFFFFFFFFFFF );
  7602. if ( ( a.high = bits64( $C03E000000000000 ) )
  7603. and ( aSig1 < int64( $0002000000000000 ) ) ) then
  7604. begin
  7605. if ( aSig1<>0 ) then
  7606. set_inexact_flag;
  7607. end
  7608. else begin
  7609. float_raise( float_flag_invalid );
  7610. if ( (aSign=0) or ( ( aExp = $7FFF ) and (( aSig0 or aSig1 )<>0) ) ) then
  7611. begin
  7612. result := int64( $7FFFFFFFFFFFFFFF );
  7613. exit;
  7614. end;
  7615. end;
  7616. result := int64( $8000000000000000 );
  7617. exit;
  7618. end;
  7619. z := ( aSig0 shl shiftCount ) or ( aSig1 shr ( ( - shiftCount ) and 63 ) );
  7620. if ( int64( aSig1 shl shiftCount )<>0 ) then
  7621. begin
  7622. set_inexact_flag;
  7623. end;
  7624. end
  7625. else begin
  7626. if ( aExp < $3FFF ) then
  7627. begin
  7628. if ( aExp or aSig0 or aSig1 )<>0 then
  7629. begin
  7630. set_inexact_flag;
  7631. end;
  7632. result := 0;
  7633. exit;
  7634. end;
  7635. z := aSig0 shr ( - shiftCount );
  7636. if ( (aSig1<>0)
  7637. or ( (shiftCount<>0) and (int64( aSig0 shl ( shiftCount and 63 ) )<>0) ) ) then
  7638. begin
  7639. set_inexact_flag;
  7640. end;
  7641. end;
  7642. if ( aSign<>0 ) then
  7643. z := - z;
  7644. result := z;
  7645. end;
  7646. {*----------------------------------------------------------------------------
  7647. | Returns the result of converting the quadruple-precision floating-point
  7648. | value `a' to the single-precision floating-point format. The conversion
  7649. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7650. | Arithmetic.
  7651. *----------------------------------------------------------------------------*}
  7652. function float128_to_float32(a: float128): float32;
  7653. var
  7654. aSign: flag;
  7655. aExp: int32;
  7656. aSig0, aSig1: bits64;
  7657. zSig: bits32;
  7658. begin
  7659. aSig1 := extractFloat128Frac1( a );
  7660. aSig0 := extractFloat128Frac0( a );
  7661. aExp := extractFloat128Exp( a );
  7662. aSign := extractFloat128Sign( a );
  7663. if ( aExp = $7FFF ) then
  7664. begin
  7665. if ( aSig0 or aSig1 )<>0 then
  7666. begin
  7667. result := commonNaNToFloat32( float128ToCommonNaN( a ) );
  7668. exit;
  7669. end;
  7670. result := packFloat32( aSign, $FF, 0 );
  7671. exit;
  7672. end;
  7673. aSig0 := aSig0 or ord( aSig1 <> 0 );
  7674. shift64RightJamming( aSig0, 18, aSig0 );
  7675. zSig := aSig0;
  7676. if ( aExp<>0 ) or (aSig0 <> 0 ) then
  7677. begin
  7678. zSig := zSig or $40000000;
  7679. dec(aExp,$3F81);
  7680. end;
  7681. result := roundAndPackFloat32( aSign, aExp, zSig );
  7682. end;
  7683. {*----------------------------------------------------------------------------
  7684. | Returns the result of converting the quadruple-precision floating-point
  7685. | value `a' to the double-precision floating-point format. The conversion
  7686. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7687. | Arithmetic.
  7688. *----------------------------------------------------------------------------*}
  7689. function float128_to_float64(a: float128): float64;
  7690. var
  7691. aSign: flag;
  7692. aExp: int32;
  7693. aSig0, aSig1: bits64;
  7694. begin
  7695. aSig1 := extractFloat128Frac1( a );
  7696. aSig0 := extractFloat128Frac0( a );
  7697. aExp := extractFloat128Exp( a );
  7698. aSign := extractFloat128Sign( a );
  7699. if ( aExp = $7FFF ) then
  7700. begin
  7701. if ( aSig0 or aSig1 )<>0 then
  7702. begin
  7703. commonNaNToFloat64( float128ToCommonNaN( a ),result);
  7704. exit;
  7705. end;
  7706. result:=packFloat64( aSign, $7FF, 0);
  7707. exit;
  7708. end;
  7709. shortShift128Left( aSig0, aSig1, 14, aSig0, aSig1 );
  7710. aSig0 := aSig0 or ord( aSig1 <> 0 );
  7711. if ( aExp<>0 ) or (aSig0 <> 0 ) then
  7712. begin
  7713. aSig0 := aSig0 or int64( $4000000000000000 );
  7714. dec(aExp,$3C01);
  7715. end;
  7716. result := roundAndPackFloat64( aSign, aExp, aSig0 );
  7717. end;
  7718. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  7719. {*----------------------------------------------------------------------------
  7720. | Returns the result of converting the quadruple-precision floating-point
  7721. | value `a' to the extended double-precision floating-point format. The
  7722. | conversion is performed according to the IEC/IEEE Standard for Binary
  7723. | Floating-Point Arithmetic.
  7724. *----------------------------------------------------------------------------*}
  7725. function float128_to_floatx80(a: float128): floatx80;
  7726. var
  7727. aSign: flag;
  7728. aExp: int32;
  7729. aSig0, aSig1: bits64;
  7730. begin
  7731. aSig1 := extractFloat128Frac1( a );
  7732. aSig0 := extractFloat128Frac0( a );
  7733. aExp := extractFloat128Exp( a );
  7734. aSign := extractFloat128Sign( a );
  7735. if ( aExp = $7FFF ) then begin
  7736. if ( aSig0 or aSig1 <> 0 ) then begin
  7737. result := commonNaNToFloatx80( float128ToCommonNaN( a ) );
  7738. exit;
  7739. end;
  7740. result := packFloatx80( aSign, $7FFF, bits64( $8000000000000000 ) );
  7741. exit;
  7742. end;
  7743. if ( aExp = 0 ) then begin
  7744. if ( ( aSig0 or aSig1 ) = 0 ) then
  7745. begin
  7746. result := packFloatx80( aSign, 0, 0 );
  7747. exit;
  7748. end;
  7749. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  7750. end
  7751. else begin
  7752. aSig0 := aSig0 or int64( $0001000000000000 );
  7753. end;
  7754. shortShift128Left( aSig0, aSig1, 15, aSig0, aSig1 );
  7755. result := roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 );
  7756. end;
  7757. {$endif FPC_SOFTFLOAT_FLOATX80}
  7758. {*----------------------------------------------------------------------------
  7759. | Rounds the quadruple-precision floating-point value `a' to an integer, and
  7760. | Returns the result as a quadruple-precision floating-point value. The
  7761. | operation is performed according to the IEC/IEEE Standard for Binary
  7762. | Floating-Point Arithmetic.
  7763. *----------------------------------------------------------------------------*}
  7764. function float128_round_to_int(a: float128): float128;
  7765. var
  7766. aSign: flag;
  7767. aExp: int32;
  7768. lastBitMask, roundBitsMask: bits64;
  7769. roundingMode: int8;
  7770. z: float128;
  7771. begin
  7772. aExp := extractFloat128Exp( a );
  7773. if ( $402F <= aExp ) then
  7774. begin
  7775. if ( $406F <= aExp ) then
  7776. begin
  7777. if ( ( aExp = $7FFF )
  7778. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) )<>0)
  7779. ) then
  7780. begin
  7781. result := propagateFloat128NaN( a, a );
  7782. exit;
  7783. end;
  7784. result := a;
  7785. exit;
  7786. end;
  7787. lastBitMask := 1;
  7788. lastBitMask := ( lastBitMask shl ( $406E - aExp ) ) shl 1;
  7789. roundBitsMask := lastBitMask - 1;
  7790. z := a;
  7791. roundingMode := softfloat_rounding_mode;
  7792. if ( roundingMode = float_round_nearest_even ) then
  7793. begin
  7794. if ( lastBitMask )<>0 then
  7795. begin
  7796. add128( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );
  7797. if ( ( z.low and roundBitsMask ) = 0 ) then
  7798. z.low := z.low and not(lastBitMask);
  7799. end
  7800. else begin
  7801. if ( sbits64(z.low) < 0 ) then
  7802. begin
  7803. inc(z.high);
  7804. if ( bits64( z.low shl 1 ) = 0 ) then
  7805. z.high := z.high and not bits64( 1 );
  7806. end;
  7807. end;
  7808. end
  7809. else if ( roundingMode <> float_round_to_zero ) then
  7810. begin
  7811. if ( extractFloat128Sign( z )
  7812. xor ord( roundingMode = float_round_up ) )<>0 then
  7813. begin
  7814. add128( z.high, z.low, 0, roundBitsMask, z.high, z.low );
  7815. end;
  7816. end;
  7817. z.low := z.low and not(roundBitsMask);
  7818. end
  7819. else begin
  7820. if ( aExp < $3FFF ) then
  7821. begin
  7822. if ( ( ( bits64( a.high shl 1 ) ) or a.low ) = 0 ) then
  7823. begin
  7824. result := a;
  7825. exit;
  7826. end;
  7827. set_inexact_flag;
  7828. aSign := extractFloat128Sign( a );
  7829. case softfloat_rounding_mode of
  7830. float_round_nearest_even:
  7831. if ( ( aExp = $3FFE )
  7832. and ( (extractFloat128Frac0( a )<>0)
  7833. or (extractFloat128Frac1( a )<>0) )
  7834. ) then begin
  7835. begin
  7836. result := packFloat128( aSign, $3FFF, 0, 0 );
  7837. exit;
  7838. end;
  7839. end;
  7840. float_round_down:
  7841. begin
  7842. if aSign<>0 then
  7843. result:=packFloat128( 1, $3FFF, 0, 0 )
  7844. else
  7845. result:=packFloat128( 0, 0, 0, 0 );
  7846. exit;
  7847. end;
  7848. float_round_up:
  7849. begin
  7850. if aSign<>0 then
  7851. result := packFloat128( 1, 0, 0, 0 )
  7852. else
  7853. result:=packFloat128( 0, $3FFF, 0, 0 );
  7854. exit;
  7855. end;
  7856. end;
  7857. result := packFloat128( aSign, 0, 0, 0 );
  7858. exit;
  7859. end;
  7860. lastBitMask := 1;
  7861. lastBitMask := lastBitMask shl ($402F - aExp);
  7862. roundBitsMask := lastBitMask - 1;
  7863. z.low := 0;
  7864. z.high := a.high;
  7865. roundingMode := softfloat_rounding_mode;
  7866. if ( roundingMode = float_round_nearest_even ) then begin
  7867. inc(z.high,lastBitMask shr 1);
  7868. if ( ( ( z.high and roundBitsMask ) or a.low ) = 0 ) then begin
  7869. z.high := z.high and not(lastBitMask);
  7870. end;
  7871. end
  7872. else if ( roundingMode <> float_round_to_zero ) then begin
  7873. if ( (extractFloat128Sign( z )<>0)
  7874. xor ( roundingMode = float_round_up ) ) then begin
  7875. z.high := z.high or ord( a.low <> 0 );
  7876. z.high := z.high+roundBitsMask;
  7877. end;
  7878. end;
  7879. z.high := z.high and not(roundBitsMask);
  7880. end;
  7881. if ( ( z.low <> a.low ) or ( z.high <> a.high ) ) then begin
  7882. set_inexact_flag;
  7883. end;
  7884. result := z;
  7885. end;
  7886. {*----------------------------------------------------------------------------
  7887. | Returns the result of adding the absolute values of the quadruple-precision
  7888. | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  7889. | before being returned. `zSign' is ignored if the result is a NaN.
  7890. | The addition is performed according to the IEC/IEEE Standard for Binary
  7891. | Floating-Point Arithmetic.
  7892. *----------------------------------------------------------------------------*}
  7893. function addFloat128Sigs(a,b : float128; zSign : flag ): float128;
  7894. var
  7895. aExp, bExp, zExp: int32;
  7896. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits64;
  7897. expDiff: int32;
  7898. label
  7899. shiftRight1,roundAndPack;
  7900. begin
  7901. aSig1 := extractFloat128Frac1( a );
  7902. aSig0 := extractFloat128Frac0( a );
  7903. aExp := extractFloat128Exp( a );
  7904. bSig1 := extractFloat128Frac1( b );
  7905. bSig0 := extractFloat128Frac0( b );
  7906. bExp := extractFloat128Exp( b );
  7907. expDiff := aExp - bExp;
  7908. if ( 0 < expDiff ) then begin
  7909. if ( aExp = $7FFF ) then begin
  7910. if ( aSig0 or aSig1 )<>0 then
  7911. begin
  7912. result := propagateFloat128NaN( a, b );
  7913. exit;
  7914. end;
  7915. result := a;
  7916. exit;
  7917. end;
  7918. if ( bExp = 0 ) then begin
  7919. dec(expDiff);
  7920. end
  7921. else begin
  7922. bSig0 := bSig0 or int64( $0001000000000000 );
  7923. end;
  7924. shift128ExtraRightJamming(
  7925. bSig0, bSig1, 0, expDiff, bSig0, bSig1, zSig2 );
  7926. zExp := aExp;
  7927. end
  7928. else if ( expDiff < 0 ) then begin
  7929. if ( bExp = $7FFF ) then begin
  7930. if ( bSig0 or bSig1 )<>0 then
  7931. begin
  7932. result := propagateFloat128NaN( a, b );
  7933. exit;
  7934. end;
  7935. result := packFloat128( zSign, $7FFF, 0, 0 );
  7936. exit;
  7937. end;
  7938. if ( aExp = 0 ) then begin
  7939. inc(expDiff);
  7940. end
  7941. else begin
  7942. aSig0 := aSig0 or int64( $0001000000000000 );
  7943. end;
  7944. shift128ExtraRightJamming(
  7945. aSig0, aSig1, 0, - expDiff, aSig0, aSig1, zSig2 );
  7946. zExp := bExp;
  7947. end
  7948. else begin
  7949. if ( aExp = $7FFF ) then begin
  7950. if ( aSig0 or aSig1 or bSig0 or bSig1 )<>0 then begin
  7951. result := propagateFloat128NaN( a, b );
  7952. exit;
  7953. end;
  7954. result := a;
  7955. exit;
  7956. end;
  7957. add128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  7958. if ( aExp = 0 ) then
  7959. begin
  7960. result := packFloat128( zSign, 0, zSig0, zSig1 );
  7961. exit;
  7962. end;
  7963. zSig2 := 0;
  7964. zSig0 := zSig0 or int64( $0002000000000000 );
  7965. zExp := aExp;
  7966. goto shiftRight1;
  7967. end;
  7968. aSig0 := aSig0 or int64( $0001000000000000 );
  7969. add128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  7970. dec(zExp);
  7971. if ( zSig0 < int64( $0002000000000000 ) ) then goto roundAndPack;
  7972. inc(zExp);
  7973. shiftRight1:
  7974. shift128ExtraRightJamming(
  7975. zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  7976. roundAndPack:
  7977. result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  7978. end;
  7979. {*----------------------------------------------------------------------------
  7980. | Returns the result of subtracting the absolute values of the quadruple-
  7981. | precision floating-point values `a' and `b'. If `zSign' is 1, the
  7982. | difference is negated before being returned. `zSign' is ignored if the
  7983. | result is a NaN. The subtraction is performed according to the IEC/IEEE
  7984. | Standard for Binary Floating-Point Arithmetic.
  7985. *----------------------------------------------------------------------------*}
  7986. function subFloat128Sigs( a, b : float128; zSign : flag): float128;
  7987. var
  7988. aExp, bExp, zExp: int32;
  7989. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits64;
  7990. expDiff: int32;
  7991. z: float128;
  7992. label
  7993. aExpBigger,bExpBigger,aBigger,bBigger,normalizeRoundAndPack;
  7994. begin
  7995. aSig1 := extractFloat128Frac1( a );
  7996. aSig0 := extractFloat128Frac0( a );
  7997. aExp := extractFloat128Exp( a );
  7998. bSig1 := extractFloat128Frac1( b );
  7999. bSig0 := extractFloat128Frac0( b );
  8000. bExp := extractFloat128Exp( b );
  8001. expDiff := aExp - bExp;
  8002. shortShift128Left( aSig0, aSig1, 14, aSig0, aSig1 );
  8003. shortShift128Left( bSig0, bSig1, 14, bSig0, bSig1 );
  8004. if ( 0 < expDiff ) then goto aExpBigger;
  8005. if ( expDiff < 0 ) then goto bExpBigger;
  8006. if ( aExp = $7FFF ) then begin
  8007. if ( aSig0 or aSig1 or bSig0 or bSig1 )<>0 then begin
  8008. result := propagateFloat128NaN( a, b );
  8009. exit;
  8010. end;
  8011. float_raise( float_flag_invalid );
  8012. z.low := float128_default_nan_low;
  8013. z.high := float128_default_nan_high;
  8014. result := z;
  8015. exit;
  8016. end;
  8017. if ( aExp = 0 ) then begin
  8018. aExp := 1;
  8019. bExp := 1;
  8020. end;
  8021. if ( bSig0 < aSig0 ) then goto aBigger;
  8022. if ( aSig0 < bSig0 ) then goto bBigger;
  8023. if ( bSig1 < aSig1 ) then goto aBigger;
  8024. if ( aSig1 < bSig1 ) then goto bBigger;
  8025. result := packFloat128( ord(softfloat_rounding_mode = float_round_down), 0, 0, 0 );
  8026. exit;
  8027. bExpBigger:
  8028. if ( bExp = $7FFF ) then begin
  8029. if ( bSig0 or bSig1 )<>0 then
  8030. begin
  8031. result := propagateFloat128NaN( a, b );
  8032. exit;
  8033. end;
  8034. result := packFloat128( zSign xor 1, $7FFF, 0, 0 );
  8035. exit;
  8036. end;
  8037. if ( aExp = 0 ) then begin
  8038. inc(expDiff);
  8039. end
  8040. else begin
  8041. aSig0 := aSig0 or int64( $4000000000000000 );
  8042. end;
  8043. shift128RightJamming( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  8044. bSig0 := bSig0 or int64( $4000000000000000 );
  8045. bBigger:
  8046. sub128( bSig0, bSig1, aSig0, aSig1, zSig0, zSig1 );
  8047. zExp := bExp;
  8048. zSign := zSign xor 1;
  8049. goto normalizeRoundAndPack;
  8050. aExpBigger:
  8051. if ( aExp = $7FFF ) then begin
  8052. if ( aSig0 or aSig1 )<>0 then
  8053. begin
  8054. result := propagateFloat128NaN( a, b );
  8055. exit;
  8056. end;
  8057. result := a;
  8058. exit;
  8059. end;
  8060. if ( bExp = 0 ) then begin
  8061. dec(expDiff);
  8062. end
  8063. else begin
  8064. bSig0 := bSig0 or int64( $4000000000000000 );
  8065. end;
  8066. shift128RightJamming( bSig0, bSig1, expDiff, bSig0, bSig1 );
  8067. aSig0 := aSig0 or int64( $4000000000000000 );
  8068. aBigger:
  8069. sub128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  8070. zExp := aExp;
  8071. normalizeRoundAndPack:
  8072. dec(zExp);
  8073. result := normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 );
  8074. end;
  8075. {*----------------------------------------------------------------------------
  8076. | Returns the result of adding the quadruple-precision floating-point values
  8077. | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  8078. | for Binary Floating-Point Arithmetic.
  8079. *----------------------------------------------------------------------------*}
  8080. function float128_add(a: float128; b: float128): float128;
  8081. var
  8082. aSign, bSign: flag;
  8083. begin
  8084. aSign := extractFloat128Sign( a );
  8085. bSign := extractFloat128Sign( b );
  8086. if ( aSign = bSign ) then begin
  8087. result := addFloat128Sigs( a, b, aSign );
  8088. end
  8089. else begin
  8090. result := subFloat128Sigs( a, b, aSign );
  8091. end;
  8092. end;
  8093. {*----------------------------------------------------------------------------
  8094. | Returns the result of subtracting the quadruple-precision floating-point
  8095. | values `a' and `b'. The operation is performed according to the IEC/IEEE
  8096. | Standard for Binary Floating-Point Arithmetic.
  8097. *----------------------------------------------------------------------------*}
  8098. function float128_sub(a: float128; b: float128): float128;
  8099. var
  8100. aSign, bSign: flag;
  8101. begin
  8102. aSign := extractFloat128Sign( a );
  8103. bSign := extractFloat128Sign( b );
  8104. if ( aSign = bSign ) then begin
  8105. result := subFloat128Sigs( a, b, aSign );
  8106. end
  8107. else begin
  8108. result := addFloat128Sigs( a, b, aSign );
  8109. end;
  8110. end;
  8111. {*----------------------------------------------------------------------------
  8112. | Returns the result of multiplying the quadruple-precision floating-point
  8113. | values `a' and `b'. The operation is performed according to the IEC/IEEE
  8114. | Standard for Binary Floating-Point Arithmetic.
  8115. *----------------------------------------------------------------------------*}
  8116. function float128_mul(a: float128; b: float128): float128;
  8117. var
  8118. aSign, bSign, zSign: flag;
  8119. aExp, bExp, zExp: int32;
  8120. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits64;
  8121. z: float128;
  8122. label
  8123. invalid;
  8124. begin
  8125. aSig1 := extractFloat128Frac1( a );
  8126. aSig0 := extractFloat128Frac0( a );
  8127. aExp := extractFloat128Exp( a );
  8128. aSign := extractFloat128Sign( a );
  8129. bSig1 := extractFloat128Frac1( b );
  8130. bSig0 := extractFloat128Frac0( b );
  8131. bExp := extractFloat128Exp( b );
  8132. bSign := extractFloat128Sign( b );
  8133. zSign := aSign xor bSign;
  8134. if ( aExp = $7FFF ) then begin
  8135. if ( (( aSig0 or aSig1 )<>0)
  8136. or ( ( bExp = $7FFF ) and (( bSig0 or bSig1 )<>0) ) ) then begin
  8137. result := propagateFloat128NaN( a, b );
  8138. exit;
  8139. end;
  8140. if ( ( bExp or bSig0 or bSig1 ) = 0 ) then goto invalid;
  8141. result := packFloat128( zSign, $7FFF, 0, 0 );
  8142. exit;
  8143. end;
  8144. if ( bExp = $7FFF ) then begin
  8145. if ( bSig0 or bSig1 )<>0 then
  8146. begin
  8147. result := propagateFloat128NaN( a, b );
  8148. exit;
  8149. end;
  8150. if ( ( aExp or aSig0 or aSig1 ) = 0 ) then begin
  8151. invalid:
  8152. float_raise( float_flag_invalid );
  8153. z.low := float128_default_nan_low;
  8154. z.high := float128_default_nan_high;
  8155. result := z;
  8156. exit;
  8157. end;
  8158. result := packFloat128( zSign, $7FFF, 0, 0 );
  8159. exit;
  8160. end;
  8161. if ( aExp = 0 ) then begin
  8162. if ( ( aSig0 or aSig1 ) = 0 ) then
  8163. begin
  8164. result := packFloat128( zSign, 0, 0, 0 );
  8165. exit;
  8166. end;
  8167. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  8168. end;
  8169. if ( bExp = 0 ) then begin
  8170. if ( ( bSig0 or bSig1 ) = 0 ) then
  8171. begin
  8172. result := packFloat128( zSign, 0, 0, 0 );
  8173. exit;
  8174. end;
  8175. normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  8176. end;
  8177. zExp := aExp + bExp - $4000;
  8178. aSig0 := aSig0 or int64( $0001000000000000 );
  8179. shortShift128Left( bSig0, bSig1, 16, bSig0, bSig1 );
  8180. mul128To256( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3 );
  8181. add128( zSig0, zSig1, aSig0, aSig1, zSig0, zSig1 );
  8182. zSig2 := zSig2 or ord( zSig3 <> 0 );
  8183. if ( int64( $0002000000000000 ) <= zSig0 ) then begin
  8184. shift128ExtraRightJamming(
  8185. zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  8186. inc(zExp);
  8187. end;
  8188. result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  8189. end;
  8190. {*----------------------------------------------------------------------------
  8191. | Returns the result of dividing the quadruple-precision floating-point value
  8192. | `a' by the corresponding value `b'. The operation is performed according to
  8193. | the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8194. *----------------------------------------------------------------------------*}
  8195. function float128_div(a: float128; b: float128): float128;
  8196. var
  8197. aSign, bSign, zSign: flag;
  8198. aExp, bExp, zExp: int32;
  8199. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits64;
  8200. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
  8201. z: float128;
  8202. label
  8203. invalid;
  8204. begin
  8205. aSig1 := extractFloat128Frac1( a );
  8206. aSig0 := extractFloat128Frac0( a );
  8207. aExp := extractFloat128Exp( a );
  8208. aSign := extractFloat128Sign( a );
  8209. bSig1 := extractFloat128Frac1( b );
  8210. bSig0 := extractFloat128Frac0( b );
  8211. bExp := extractFloat128Exp( b );
  8212. bSign := extractFloat128Sign( b );
  8213. zSign := aSign xor bSign;
  8214. if ( aExp = $7FFF ) then begin
  8215. if ( aSig0 or aSig1 )<>0 then
  8216. begin
  8217. result := propagateFloat128NaN( a, b );
  8218. exit;
  8219. end;
  8220. if ( bExp = $7FFF ) then begin
  8221. if ( bSig0 or bSig1 )<>0 then
  8222. begin
  8223. result := propagateFloat128NaN( a, b );
  8224. exit;
  8225. end;
  8226. goto invalid;
  8227. end;
  8228. result := packFloat128( zSign, $7FFF, 0, 0 );
  8229. exit;
  8230. end;
  8231. if ( bExp = $7FFF ) then begin
  8232. if ( bSig0 or bSig1 )<>0 then
  8233. begin
  8234. result := propagateFloat128NaN( a, b );
  8235. exit;
  8236. end;
  8237. result := packFloat128( zSign, 0, 0, 0 );
  8238. exit;
  8239. end;
  8240. if ( bExp = 0 ) then begin
  8241. if ( ( bSig0 or bSig1 ) = 0 ) then begin
  8242. if ( ( aExp or aSig0 or aSig1 ) = 0 ) then begin
  8243. invalid:
  8244. float_raise( float_flag_invalid );
  8245. z.low := float128_default_nan_low;
  8246. z.high := float128_default_nan_high;
  8247. result := z;
  8248. exit;
  8249. end;
  8250. float_raise( float_flag_divbyzero );
  8251. result := packFloat128( zSign, $7FFF, 0, 0 );
  8252. exit;
  8253. end;
  8254. normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  8255. end;
  8256. if ( aExp = 0 ) then begin
  8257. if ( ( aSig0 or aSig1 ) = 0 ) then
  8258. begin
  8259. result := packFloat128( zSign, 0, 0, 0 );
  8260. exit;
  8261. end;
  8262. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  8263. end;
  8264. zExp := aExp - bExp + $3FFD;
  8265. shortShift128Left(
  8266. aSig0 or int64( $0001000000000000 ), aSig1, 15, aSig0, aSig1 );
  8267. shortShift128Left(
  8268. bSig0 or int64( $0001000000000000 ), bSig1, 15, bSig0, bSig1 );
  8269. if ( le128( bSig0, bSig1, aSig0, aSig1 )<>0 ) then begin
  8270. shift128Right( aSig0, aSig1, 1, aSig0, aSig1 );
  8271. inc(zExp);
  8272. end;
  8273. zSig0 := estimateDiv128To64( aSig0, aSig1, bSig0 );
  8274. mul128By64To192( bSig0, bSig1, zSig0, term0, term1, term2 );
  8275. sub192( aSig0, aSig1, 0, term0, term1, term2, rem0, rem1, rem2 );
  8276. while ( sbits64(rem0) < 0 ) do begin
  8277. dec(zSig0);
  8278. add192( rem0, rem1, rem2, 0, bSig0, bSig1, rem0, rem1, rem2 );
  8279. end;
  8280. zSig1 := estimateDiv128To64( rem1, rem2, bSig0 );
  8281. if ( ( zSig1 and $3FFF ) <= 4 ) then begin
  8282. mul128By64To192( bSig0, bSig1, zSig1, term1, term2, term3 );
  8283. sub192( rem1, rem2, 0, term1, term2, term3, rem1, rem2, rem3 );
  8284. while ( sbits64(rem1) < 0 ) do begin
  8285. dec(zSig1);
  8286. add192( rem1, rem2, rem3, 0, bSig0, bSig1, rem1, rem2, rem3 );
  8287. end;
  8288. zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );
  8289. end;
  8290. shift128ExtraRightJamming( zSig0, zSig1, 0, 15, zSig0, zSig1, zSig2 );
  8291. result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  8292. end;
  8293. {*----------------------------------------------------------------------------
  8294. | Returns the remainder of the quadruple-precision floating-point value `a'
  8295. | with respect to the corresponding value `b'. The operation is performed
  8296. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8297. *----------------------------------------------------------------------------*}
  8298. function float128_rem(a: float128; b: float128): float128;
  8299. var
  8300. aSign, zSign: flag;
  8301. aExp, bExp, expDiff: int32;
  8302. aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits64;
  8303. allZero, alternateASig0, alternateASig1, sigMean1: bits64;
  8304. sigMean0: sbits64;
  8305. z: float128;
  8306. label
  8307. invalid;
  8308. begin
  8309. aSig1 := extractFloat128Frac1( a );
  8310. aSig0 := extractFloat128Frac0( a );
  8311. aExp := extractFloat128Exp( a );
  8312. aSign := extractFloat128Sign( a );
  8313. bSig1 := extractFloat128Frac1( b );
  8314. bSig0 := extractFloat128Frac0( b );
  8315. bExp := extractFloat128Exp( b );
  8316. if ( aExp = $7FFF ) then begin
  8317. if ( (( aSig0 or aSig1 )<>0)
  8318. or ( ( bExp = $7FFF ) and (( bSig0 or bSig1 )<>0) ) ) then begin
  8319. result := propagateFloat128NaN( a, b );
  8320. exit;
  8321. end;
  8322. goto invalid;
  8323. end;
  8324. if ( bExp = $7FFF ) then begin
  8325. if ( bSig0 or bSig1 )<>0 then
  8326. begin
  8327. result := propagateFloat128NaN( a, b );
  8328. exit;
  8329. end;
  8330. result := a;
  8331. exit;
  8332. end;
  8333. if ( bExp = 0 ) then begin
  8334. if ( ( bSig0 or bSig1 ) = 0 ) then begin
  8335. invalid:
  8336. float_raise( float_flag_invalid );
  8337. z.low := float128_default_nan_low;
  8338. z.high := float128_default_nan_high;
  8339. result := z;
  8340. exit;
  8341. end;
  8342. normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  8343. end;
  8344. if ( aExp = 0 ) then begin
  8345. if ( ( aSig0 or aSig1 ) = 0 ) then
  8346. begin
  8347. result := a;
  8348. exit;
  8349. end;
  8350. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  8351. end;
  8352. expDiff := aExp - bExp;
  8353. if ( expDiff < -1 ) then
  8354. begin
  8355. result := a;
  8356. exit;
  8357. end;
  8358. shortShift128Left(
  8359. aSig0 or int64( $0001000000000000 ),
  8360. aSig1,
  8361. 15 - ord( expDiff < 0 ),
  8362. aSig0,
  8363. aSig1
  8364. );
  8365. shortShift128Left(
  8366. bSig0 or int64( $0001000000000000 ), bSig1, 15, bSig0, bSig1 );
  8367. q := le128( bSig0, bSig1, aSig0, aSig1 );
  8368. if ( q )<>0 then sub128( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  8369. dec(expDiff,64);
  8370. while ( 0 < expDiff ) do begin
  8371. q := estimateDiv128To64( aSig0, aSig1, bSig0 );
  8372. if ( 4 < q ) then
  8373. q := q - 4
  8374. else
  8375. q := 0;
  8376. mul128By64To192( bSig0, bSig1, q, term0, term1, term2 );
  8377. shortShift192Left( term0, term1, term2, 61, term1, term2, allZero );
  8378. shortShift128Left( aSig0, aSig1, 61, aSig0, allZero );
  8379. sub128( aSig0, 0, term1, term2, aSig0, aSig1 );
  8380. dec(expDiff,61);
  8381. end;
  8382. if ( -64 < expDiff ) then begin
  8383. q := estimateDiv128To64( aSig0, aSig1, bSig0 );
  8384. if ( 4 < q ) then
  8385. q := q - 4
  8386. else
  8387. q := 0;
  8388. q := q shr (- expDiff);
  8389. shift128Right( bSig0, bSig1, 12, bSig0, bSig1 );
  8390. inc(expDiff,52);
  8391. if ( expDiff < 0 ) then begin
  8392. shift128Right( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  8393. end
  8394. else begin
  8395. shortShift128Left( aSig0, aSig1, expDiff, aSig0, aSig1 );
  8396. end;
  8397. mul128By64To192( bSig0, bSig1, q, term0, term1, term2 );
  8398. sub128( aSig0, aSig1, term1, term2, aSig0, aSig1 );
  8399. end
  8400. else begin
  8401. shift128Right( aSig0, aSig1, 12, aSig0, aSig1 );
  8402. shift128Right( bSig0, bSig1, 12, bSig0, bSig1 );
  8403. end;
  8404. repeat
  8405. alternateASig0 := aSig0;
  8406. alternateASig1 := aSig1;
  8407. inc(q);
  8408. sub128( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  8409. until not( 0 <= sbits64(aSig0) );
  8410. add128(
  8411. aSig0, aSig1, alternateASig0, alternateASig1, bits64(sigMean0), sigMean1 );
  8412. if ( ( sigMean0 < 0 )
  8413. or ( ( ( sigMean0 or sigMean1 ) = 0 ) and (( q and 1 )<>0) ) ) then begin
  8414. aSig0 := alternateASig0;
  8415. aSig1 := alternateASig1;
  8416. end;
  8417. zSign := ord( sbits64(aSig0) < 0 );
  8418. if ( zSign<>0 ) then sub128( 0, 0, aSig0, aSig1, aSig0, aSig1 );
  8419. result :=
  8420. normalizeRoundAndPackFloat128( aSign xor zSign, bExp - 4, aSig0, aSig1 );
  8421. end;
  8422. {*----------------------------------------------------------------------------
  8423. | Returns the square root of the quadruple-precision floating-point value `a'.
  8424. | The operation is performed according to the IEC/IEEE Standard for Binary
  8425. | Floating-Point Arithmetic.
  8426. *----------------------------------------------------------------------------*}
  8427. function float128_sqrt(a: float128): float128;
  8428. var
  8429. aSign: flag;
  8430. aExp, zExp: int32;
  8431. aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits64;
  8432. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
  8433. z: float128;
  8434. label
  8435. invalid;
  8436. begin
  8437. aSig1 := extractFloat128Frac1( a );
  8438. aSig0 := extractFloat128Frac0( a );
  8439. aExp := extractFloat128Exp( a );
  8440. aSign := extractFloat128Sign( a );
  8441. if ( aExp = $7FFF ) then begin
  8442. if ( aSig0 or aSig1 )<>0 then
  8443. begin
  8444. result := propagateFloat128NaN( a, a );
  8445. exit;
  8446. end;
  8447. if ( aSign=0 ) then
  8448. begin
  8449. result := a;
  8450. exit;
  8451. end;
  8452. goto invalid;
  8453. end;
  8454. if ( aSign<>0 ) then begin
  8455. if ( ( aExp or aSig0 or aSig1 ) = 0 ) then
  8456. begin
  8457. result := a;
  8458. exit;
  8459. end;
  8460. invalid:
  8461. float_raise( float_flag_invalid );
  8462. z.low := float128_default_nan_low;
  8463. z.high := float128_default_nan_high;
  8464. result := z;
  8465. exit;
  8466. end;
  8467. if ( aExp = 0 ) then begin
  8468. if ( ( aSig0 or aSig1 ) = 0 ) then
  8469. begin
  8470. result := packFloat128( 0, 0, 0, 0 );
  8471. exit;
  8472. end;
  8473. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  8474. end;
  8475. zExp := ( ( aExp - $3FFF ) shr 1 ) + $3FFE;
  8476. aSig0 := aSig0 or int64( $0001000000000000 );
  8477. zSig0 := estimateSqrt32( aExp, aSig0 shr 17 );
  8478. shortShift128Left( aSig0, aSig1, 13 - ( aExp and 1 ), aSig0, aSig1 );
  8479. zSig0 := estimateDiv128To64( aSig0, aSig1, zSig0 shl 32 ) + ( zSig0 shl 30 );
  8480. doubleZSig0 := zSig0 shl 1;
  8481. mul64To128( zSig0, zSig0, term0, term1 );
  8482. sub128( aSig0, aSig1, term0, term1, rem0, rem1 );
  8483. while ( sbits64(rem0) < 0 ) do begin
  8484. dec(zSig0);
  8485. dec(doubleZSig0,2);
  8486. add128( rem0, rem1, zSig0 shr 63, doubleZSig0 or 1, rem0, rem1 );
  8487. end;
  8488. zSig1 := estimateDiv128To64( rem1, 0, doubleZSig0 );
  8489. if ( ( zSig1 and $1FFF ) <= 5 ) then begin
  8490. if ( zSig1 = 0 ) then zSig1 := 1;
  8491. mul64To128( doubleZSig0, zSig1, term1, term2 );
  8492. sub128( rem1, 0, term1, term2, rem1, rem2 );
  8493. mul64To128( zSig1, zSig1, term2, term3 );
  8494. sub192( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
  8495. while ( sbits64(rem1) < 0 ) do begin
  8496. dec(zSig1);
  8497. shortShift128Left( 0, zSig1, 1, term2, term3 );
  8498. term3 := term3 or 1;
  8499. term2 := term2 or doubleZSig0;
  8500. add192( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
  8501. end;
  8502. zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );
  8503. end;
  8504. shift128ExtraRightJamming( zSig0, zSig1, 0, 14, zSig0, zSig1, zSig2 );
  8505. result := roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 );
  8506. end;
  8507. {*----------------------------------------------------------------------------
  8508. | Returns 1 if the quadruple-precision floating-point value `a' is equal to
  8509. | the corresponding value `b', and 0 otherwise. The comparison is performed
  8510. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8511. *----------------------------------------------------------------------------*}
  8512. function float128_eq(a: float128; b: float128): flag;
  8513. begin
  8514. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8515. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8516. or ( ( extractFloat128Exp( b ) = $7FFF )
  8517. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8518. ) then begin
  8519. if ( (float128_is_signaling_nan( a )<>0)
  8520. or (float128_is_signaling_nan( b )<>0) ) then begin
  8521. float_raise( float_flag_invalid );
  8522. end;
  8523. result := 0;
  8524. exit;
  8525. end;
  8526. result := ord(
  8527. ( a.low = b.low )
  8528. and ( ( a.high = b.high )
  8529. or ( ( a.low = 0 )
  8530. and ( bits64( ( a.high or b.high ) shl 1 ) = 0 ) )
  8531. ));
  8532. end;
  8533. {*----------------------------------------------------------------------------
  8534. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  8535. | or equal to the corresponding value `b', and 0 otherwise. The comparison
  8536. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  8537. | Arithmetic.
  8538. *----------------------------------------------------------------------------*}
  8539. function float128_le(a: float128; b: float128): flag;
  8540. var
  8541. aSign, bSign: flag;
  8542. begin
  8543. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8544. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8545. or ( ( extractFloat128Exp( b ) = $7FFF )
  8546. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8547. ) then begin
  8548. float_raise( float_flag_invalid );
  8549. result := 0;
  8550. exit;
  8551. end;
  8552. aSign := extractFloat128Sign( a );
  8553. bSign := extractFloat128Sign( b );
  8554. if ( aSign <> bSign ) then begin
  8555. result := ord(
  8556. (aSign<>0)
  8557. or ( ( ( bits64 ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  8558. = 0 ));
  8559. exit;
  8560. end;
  8561. if aSign<>0 then
  8562. result := le128( b.high, b.low, a.high, a.low )
  8563. else
  8564. result := le128( a.high, a.low, b.high, b.low );
  8565. end;
  8566. {*----------------------------------------------------------------------------
  8567. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  8568. | the corresponding value `b', and 0 otherwise. The comparison is performed
  8569. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8570. *----------------------------------------------------------------------------*}
  8571. function float128_lt(a: float128; b: float128): flag;
  8572. var
  8573. aSign, bSign: flag;
  8574. begin
  8575. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8576. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8577. or ( ( extractFloat128Exp( b ) = $7FFF )
  8578. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8579. ) then begin
  8580. float_raise( float_flag_invalid );
  8581. result := 0;
  8582. exit;
  8583. end;
  8584. aSign := extractFloat128Sign( a );
  8585. bSign := extractFloat128Sign( b );
  8586. if ( aSign <> bSign ) then begin
  8587. result := ord(
  8588. (aSign<>0)
  8589. and ( ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  8590. <> 0 ));
  8591. exit;
  8592. end;
  8593. if aSign<>0 then
  8594. result := lt128( b.high, b.low, a.high, a.low )
  8595. else
  8596. result := lt128( a.high, a.low, b.high, b.low );
  8597. end;
  8598. {*----------------------------------------------------------------------------
  8599. | Returns 1 if the quadruple-precision floating-point value `a' is equal to
  8600. | the corresponding value `b', and 0 otherwise. The invalid exception is
  8601. | raised if either operand is a NaN. Otherwise, the comparison is performed
  8602. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8603. *----------------------------------------------------------------------------*}
  8604. function float128_eq_signaling(a: float128; b: float128): flag;
  8605. begin
  8606. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8607. and ( ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8608. or ( ( extractFloat128Exp( b ) = $7FFF )
  8609. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8610. ) then begin
  8611. float_raise( float_flag_invalid );
  8612. result := 0;
  8613. exit;
  8614. end;
  8615. result := ord(
  8616. ( a.low = b.low )
  8617. and ( ( a.high = b.high )
  8618. or ( ( a.low = 0 )
  8619. and ( bits64 ( ( a.high or b.high ) shl 1 ) = 0 ) )
  8620. ));
  8621. end;
  8622. {*----------------------------------------------------------------------------
  8623. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  8624. | or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  8625. | cause an exception. Otherwise, the comparison is performed according to the
  8626. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8627. *----------------------------------------------------------------------------*}
  8628. function float128_le_quiet(a: float128; b: float128): flag;
  8629. var
  8630. aSign, bSign: flag;
  8631. begin
  8632. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8633. and ( ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8634. or ( ( extractFloat128Exp( b ) = $7FFF )
  8635. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8636. ) then begin
  8637. if ( (float128_is_signaling_nan( a )<>0)
  8638. or (float128_is_signaling_nan( b )<>0) ) then begin
  8639. float_raise( float_flag_invalid );
  8640. end;
  8641. result := 0;
  8642. exit;
  8643. end;
  8644. aSign := extractFloat128Sign( a );
  8645. bSign := extractFloat128Sign( b );
  8646. if ( aSign <> bSign ) then begin
  8647. result := ord(
  8648. (aSign<>0)
  8649. or ( ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  8650. = 0 ));
  8651. exit;
  8652. end;
  8653. if aSign<>0 then
  8654. result := le128( b.high, b.low, a.high, a.low )
  8655. else
  8656. result := le128( a.high, a.low, b.high, b.low );
  8657. end;
  8658. {*----------------------------------------------------------------------------
  8659. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  8660. | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  8661. | exception. Otherwise, the comparison is performed according to the IEC/IEEE
  8662. | Standard for Binary Floating-Point Arithmetic.
  8663. *----------------------------------------------------------------------------*}
  8664. function float128_lt_quiet(a: float128; b: float128): flag;
  8665. var
  8666. aSign, bSign: flag;
  8667. begin
  8668. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8669. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8670. or ( ( extractFloat128Exp( b ) = $7FFF )
  8671. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8672. ) then begin
  8673. if ( (float128_is_signaling_nan( a )<>0)
  8674. or (float128_is_signaling_nan( b )<>0) ) then begin
  8675. float_raise( float_flag_invalid );
  8676. end;
  8677. result := 0;
  8678. exit;
  8679. end;
  8680. aSign := extractFloat128Sign( a );
  8681. bSign := extractFloat128Sign( b );
  8682. if ( aSign <> bSign ) then begin
  8683. result := ord(
  8684. (aSign<>0)
  8685. and ( ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  8686. <> 0 ));
  8687. exit;
  8688. end;
  8689. if aSign<>0 then
  8690. result:=lt128( b.high, b.low, a.high, a.low )
  8691. else
  8692. result:=lt128( a.high, a.low, b.high, b.low );
  8693. end;
  8694. {----------------------------------------------------------------------------
  8695. | Returns the result of converting the double-precision floating-point value
  8696. | `a' to the quadruple-precision floating-point format. The conversion is
  8697. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  8698. | Arithmetic.
  8699. *----------------------------------------------------------------------------}
  8700. function float64_to_float128( a : float64) : float128;
  8701. var
  8702. aSign : flag;
  8703. aExp : int16;
  8704. aSig, zSig0, zSig1 : bits64;
  8705. begin
  8706. aSig := extractFloat64Frac( a );
  8707. aExp := extractFloat64Exp( a );
  8708. aSign := extractFloat64Sign( a );
  8709. if ( aExp = $7FF ) then begin
  8710. if ( aSig<>0 ) then begin
  8711. result:=commonNaNToFloat128( float64ToCommonNaN( a ) );
  8712. exit;
  8713. end;
  8714. result:=packFloat128( aSign, $7FFF, 0, 0 );
  8715. exit;
  8716. end;
  8717. if ( aExp = 0 ) then begin
  8718. if ( aSig = 0 ) then
  8719. begin
  8720. result:=packFloat128( aSign, 0, 0, 0 );
  8721. exit;
  8722. end;
  8723. normalizeFloat64Subnormal( aSig, aExp, aSig );
  8724. dec(aExp);
  8725. end;
  8726. shift128Right( aSig, 0, 4, zSig0, zSig1 );
  8727. result:=packFloat128( aSign, aExp + $3C00, zSig0, zSig1 );
  8728. end;
  8729. {$endif FPC_SOFTFLOAT_FLOAT128}
  8730. {$endif not(defined(fpc_softfpu_interface))}
  8731. {$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  8732. end.
  8733. {$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}