| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370 | {*===============================================================================The original notice of the softfloat package is shown below. The conversionto pascal was done by Carl Eric Codere in 2002 ([email protected]).===============================================================================This C source file is part of the SoftFloat IEC/IEEE Floating-PointArithmetic Package, Release 2a.Written by John R. Hauser.  This work was made possible in part by theInternational Computer Science Institute, located at Suite 600, 1947 CenterStreet, Berkeley, California 94704.  Funding was partially provided by theNational Science Foundation under grant MIP-9311980.  The original versionof this code was written as part of a project to build a fixed-point vectorprocessor in collaboration with the University of California at Berkeley,overseen by Profs. Nelson Morgan and John Wawrzynek.  More informationis available through the Web page`http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'.THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable efforthas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL ATTIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TOPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANYAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.Derivative works are acceptable, even for commercial purposes, so long as(1) they include prominent notice that the work is derivative, and (2) theyinclude prominent notice akin to these four paragraphs for those parts ofthis code that are retained.===============================================================================The float80 and float128 part is translated from the softfloat packageby Florian Klaempfl and contained the following copyright noticeThe code might contain some duplicate stuff because the floatx80/float128 port wasdone based on the 64 bit enabled softfloat code.===============================================================================This C source file is part of the SoftFloat IEC/IEEE Floating-point ArithmeticPackage, Release 2b.Written by John R. Hauser.  This work was made possible in part by theInternational Computer Science Institute, located at Suite 600, 1947 CenterStreet, Berkeley, California 94704.  Funding was partially provided by theNational Science Foundation under grant MIP-9311980.  The original versionof this code was written as part of a project to build a fixed-point vectorprocessor in collaboration with the University of California at Berkeley,overseen by Profs. Nelson Morgan and John Wawrzynek.  More informationis available through the Web page `http://www.cs.berkeley.edu/~jhauser/arithmetic/SoftFloat.html'.THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort hasbeen made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMESRESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONSAND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMOREEFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCEINSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OROTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.Derivative works are acceptable, even for commercial purposes, so long as(1) the source code for the derivative work includes prominent notice thatthe work is derivative, and (2) the source code includes prominent notice withthese four paragraphs for those parts of this code that are retained.===============================================================================*}{ $define FPC_SOFTFLOAT_FLOATX80}{ $define FPC_SOFTFLOAT_FLOAT128}{ the softfpu unit can be also embedded directly into the system unit }{$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}{$mode objfpc}unit softfpu;{ Overflow checking must be disabled,  since some operations expect overflow!}{$Q-}{$goto on}{$macro on}{$define compilerproc:=stdcall }interface{$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}{$if not(defined(fpc_softfpu_implementation))}{-------------------------------------------------------------------------------Software IEC/IEEE floating-point types.-------------------------------------------------------------------------------}TYPE  float32 = longword;{$define FPC_SYSTEM_HAS_float32}  { we use here a record in the function header because    the record allows bitwise conversion to single }  float32rec = record    float32 : float32;  end;  flag = byte;  bits8 = byte;  sbits8 = shortint;  bits16 = word;  sbits16 = smallint;  sbits32 = longint;  bits32 = longword;{$ifndef fpc}  qword = int64;{$endif}  { now part of the system unit  uint64 = qword;  }  bits64 = qword;  sbits64 = int64;{$ifdef ENDIAN_LITTLE}  float64 = record    case byte of      1: (low,high : bits32);      // force the record to be aligned like a double      // else *_to_double will fail for cpus like sparc      // and avoid expensive unpacking/packing operations      2: (dummy : double);  end;  floatx80 = record    case byte of      1: (low : qword;high : word);      // force the record to be aligned like a double      // else *_to_double will fail for cpus like sparc      // and avoid expensive unpacking/packing operations      2: (dummy : extended);  end;  float128 = record    case byte of      1: (low,high : qword);      // force the record to be aligned like a double      // else *_to_double will fail for cpus like sparc      // and avoid expensive unpacking/packing operations      2: (dummy : qword);  end;{$else}  float64 = record      case byte of        1: (high,low : bits32);        // force the record to be aligned like a double        // else *_to_double will fail for cpus like sparc        2: (dummy : double);  end;  floatx80 = record    case byte of      1: (high : word;low : qword);      // force the record to be aligned like a double      // else *_to_double will fail for cpus like sparc      // and avoid expensive unpacking/packing operations      2: (dummy : qword);  end;  float128 = record    case byte of      1: (high : qword;low : qword);      // force the record to be aligned like a double      // else *_to_double will fail for cpus like sparc      // and avoid expensive unpacking/packing operations      2: (dummy : qword);  end;{$endif}{$define FPC_SYSTEM_HAS_float64}{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is less thanthe corresponding value `b', and 0 otherwise.  The comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_lt(a: float64;b: float64): flag; compilerproc;{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is less thanor equal to the corresponding value `b', and 0 otherwise.  The comparisonis performed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic.-------------------------------------------------------------------------------*}Function float64_le(a: float64;b: float64): flag; compilerproc;{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is equal tothe corresponding value `b', and 0 otherwise.  The comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_eq(a: float64;b: float64): flag; compilerproc;{*-------------------------------------------------------------------------------Returns the square root of the double-precision floating-point value `a'.The operation is performed according to the IEC/IEEE Standard for BinaryFloating-Point Arithmetic.-------------------------------------------------------------------------------*}function float64_sqrt( a: float64 ): float64; compilerproc;{*-------------------------------------------------------------------------------Returns the remainder of the double-precision floating-point value `a'with respect to the corresponding value `b'.  The operation is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_rem(a: float64; b : float64) : float64; compilerproc;{*-------------------------------------------------------------------------------Returns the result of dividing the double-precision floating-point value `a'by the corresponding value `b'.  The operation is performed according to theIEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_div(a: float64; b : float64) : float64; compilerproc;{*-------------------------------------------------------------------------------Returns the result of multiplying the double-precision floating-point values`a' and `b'.  The operation is performed according to the IEC/IEEE Standardfor Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_mul( a: float64; b:float64) : float64; compilerproc;{*-------------------------------------------------------------------------------Returns the result of subtracting the double-precision floating-point values`a' and `b'.  The operation is performed according to the IEC/IEEE Standardfor Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_sub(a: float64; b : float64) : float64; compilerproc;{*-------------------------------------------------------------------------------Returns the result of adding the double-precision floating-point values `a'and `b'.  The operation is performed according to the IEC/IEEE Standard forBinary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_add( a: float64; b : float64) : float64; compilerproc;{*-------------------------------------------------------------------------------Rounds the double-precision floating-point value `a' to an integer,and returns the result as a double-precision floating-point value.  Theoperation is performed according to the IEC/IEEE Standard for BinaryFloating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_round_to_int(a: float64) : float64; compilerproc;{*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the single-precision floating-point format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic.-------------------------------------------------------------------------------*}Function float64_to_float32(a: float64) : float32rec; compilerproc;{*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic, except that the conversion is always rounded toward zero.If `a' is a NaN, the largest positive integer is returned.  Otherwise, ifthe conversion overflows, the largest integer with the same sign as `a' isreturned.-------------------------------------------------------------------------------*}Function float64_to_int32_round_to_zero(a: float64 ): int32; compilerproc;{*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic---which means in particular that the conversion is roundedaccording to the current rounding mode.  If `a' is a NaN, the largestpositive integer is returned.  Otherwise, if the conversion overflows, thelargest integer with the same sign as `a' is returned.-------------------------------------------------------------------------------*}Function float64_to_int32(a: float64): int32; compilerproc;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is less thanthe corresponding value `b', and 0 otherwise.  The comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_lt( a:float32rec ; b : float32rec): flag; compilerproc;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is less thanor equal to the corresponding value `b', and 0 otherwise.  The comparisonis performed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic.-------------------------------------------------------------------------------*}Function float32_le( a: float32rec; b : float32rec ):flag; compilerproc;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is equal tothe corresponding value `b', and 0 otherwise.  The comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_eq( a:float32rec; b:float32rec): flag; compilerproc;{*-------------------------------------------------------------------------------Returns the square root of the single-precision floating-point value `a'.The operation is performed according to the IEC/IEEE Standard for BinaryFloating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_sqrt(a: float32rec ): float32rec; compilerproc;{*-------------------------------------------------------------------------------Returns the remainder of the single-precision floating-point value `a'with respect to the corresponding value `b'.  The operation is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_rem(a: float32rec; b: float32rec ):float32rec; compilerproc;{*-------------------------------------------------------------------------------Returns the result of dividing the single-precision floating-point value `a'by the corresponding value `b'.  The operation is performed according to theIEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc;{*-------------------------------------------------------------------------------Returns the result of multiplying the single-precision floating-point values`a' and `b'.  The operation is performed according to the IEC/IEEE Standardfor Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc;{*-------------------------------------------------------------------------------Returns the result of subtracting the single-precision floating-point values`a' and `b'.  The operation is performed according to the IEC/IEEE Standardfor Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_sub( a: float32rec ; b:float32rec ): float32rec; compilerproc;{*-------------------------------------------------------------------------------Returns the result of adding the single-precision floating-point values `a'and `b'.  The operation is performed according to the IEC/IEEE Standard forBinary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_add( a: float32rec; b:float32rec ): float32rec; compilerproc;{*-------------------------------------------------------------------------------Rounds the single-precision floating-point value `a' to an integer,and returns the result as a single-precision floating-point value.  Theoperation is performed according to the IEC/IEEE Standard for BinaryFloating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_round_to_int( a: float32rec): float32rec; compilerproc;{*-------------------------------------------------------------------------------Returns the result of converting the single-precision floating-point value`a' to the double-precision floating-point format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic.-------------------------------------------------------------------------------*}Function float32_to_float64( a : float32rec) : Float64; compilerproc;{*-------------------------------------------------------------------------------Returns the result of converting the single-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic, except that the conversion is always rounded toward zero.If `a' is a NaN, the largest positive integer is returned.  Otherwise, ifthe conversion overflows, the largest integer with the same sign as `a' isreturned.-------------------------------------------------------------------------------*}Function float32_to_int32_round_to_zero( a: Float32rec ): int32; compilerproc;{*-------------------------------------------------------------------------------Returns the result of converting the single-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic---which means in particular that the conversion is roundedaccording to the current rounding mode.  If `a' is a NaN, the largestpositive integer is returned.  Otherwise, if the conversion overflows, thelargest integer with the same sign as `a' is returned.-------------------------------------------------------------------------------*}Function float32_to_int32( a : float32rec) : int32; compilerproc;{*-------------------------------------------------------------------------------Returns the result of converting the 32-bit two's complement integer `a' tothe double-precision floating-point format.  The conversion is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function int32_to_float64( a: int32) : float64; compilerproc;{*-------------------------------------------------------------------------------Returns the result of converting the 32-bit two's complement integer `a' tothe single-precision floating-point format.  The conversion is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function int32_to_float32( a: int32): float32rec; compilerproc;{*----------------------------------------------------------------------------| Returns the result of converting the 64-bit two's complement integer `a'| to the double-precision floating-point format.  The conversion is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}Function int64_to_float64( a: int64 ): float64; compilerproc;Function qword_to_float64( a: qword ): float64; compilerproc;{*----------------------------------------------------------------------------| Returns the result of converting the 64-bit two's complement integer `a'| to the single-precision floating-point format.  The conversion is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}Function int64_to_float32( a: int64 ): float32rec; compilerproc;Function qword_to_float32( a: qword ): float32rec; compilerproc;// +++function float32_to_int64( a: float32 ): int64;function float32_to_int64_round_to_zero( a: float32 ): int64;function float32_eq_signaling( a: float32; b: float32) : flag;function float32_le_quiet( a: float32 ; b : float32 ): flag;function float32_lt_quiet( a: float32 ; b: float32 ): flag;function float32_is_signaling_nan( a : float32  ): flag;function float32_is_nan( a : float32 ): flag;function float64_to_int64( a: float64 ): int64;function float64_to_int64_round_to_zero( a: float64 ): int64;function float64_eq_signaling( a: float64; b: float64): flag;function float64_le_quiet(a: float64 ; b: float64 ): flag;function float64_lt_quiet(a: float64; b: float64 ): Flag;function float64_is_signaling_nan( a : float64 ): flag;function float64_is_nan( a : float64 ): flag;// ==={$ifdef FPC_SOFTFLOAT_FLOATX80}{*----------------------------------------------------------------------------| Extended double-precision rounding precision*----------------------------------------------------------------------------*}var // threadvar!?    floatx80_rounding_precision : int8 = 80;function int32_to_floatx80( a: int32 ): floatx80;function int64_to_floatx80( a: int64 ): floatx80;function qword_to_floatx80( a: qword ): floatx80;function float32_to_floatx80( a: float32 ): floatx80;function float64_to_floatx80( a: float64 ): floatx80;function floatx80_to_int32( a: floatx80 ): int32;function floatx80_to_int32_round_to_zero( a: floatx80 ): int32;function floatx80_to_int64( a: floatx80 ): int64;function floatx80_to_int64_round_to_zero( a: floatx80 ): int64;function floatx80_to_float32( a: floatx80 ): float32;function floatx80_to_float64( a: floatx80 ): float64;{$ifdef FPC_SOFTFLOAT_FLOAT128}function floatx80_to_float128( a: floatx80 ): float128;{$endif FPC_SOFTFLOAT_FLOAT128}function floatx80_round_to_int( a: floatx80 ): floatx80;function floatx80_add( a: floatx80; b: floatx80 ): floatx80;function floatx80_sub( a: floatx80; b: floatx80 ): floatx80;function floatx80_mul( a: floatx80; b: floatx80 ): floatx80;function floatx80_div( a: floatx80; b: floatx80 ): floatx80;function floatx80_rem( a: floatx80; b: floatx80 ): floatx80;function floatx80_sqrt( a: floatx80 ): floatx80;function floatx80_eq( a: floatx80; b: floatx80 ): flag;function floatx80_le( a: floatx80; b: floatx80 ): flag;function floatx80_lt( a: floatx80; b: floatx80 ): flag;function floatx80_eq_signaling( a: floatx80; b: floatx80 ): flag;function floatx80_le_quiet( a: floatx80; b: floatx80 ): flag;function floatx80_lt_quiet( a: floatx80; b: floatx80 ): flag;function floatx80_is_signaling_nan( a: floatx80 ): flag;function floatx80_is_nan(a : floatx80 ): flag;{$endif FPC_SOFTFLOAT_FLOATX80}{$ifdef FPC_SOFTFLOAT_FLOAT128}function int32_to_float128( a: int32 ): float128;function int64_to_float128( a: int64 ): float128;function qword_to_float128( a: qword ): float128;function float32_to_float128( a: float32 ): float128;function float128_is_nan( a : float128): flag;function float128_is_signaling_nan( a : float128): flag;function float128_to_int32(a: float128): int32;function float128_to_int32_round_to_zero(a: float128): int32;function float128_to_int64(a: float128): int64;function float128_to_int64_round_to_zero(a: float128): int64;function float128_to_float32(a: float128): float32;function float128_to_float64(a: float128): float64;function float64_to_float128( a : float64) : float128;{$ifdef FPC_SOFTFLOAT_FLOATX80}function float128_to_floatx80(a: float128): floatx80;{$endif FPC_SOFTFLOAT_FLOATX80}function float128_round_to_int(a: float128): float128;function float128_add(a: float128; b: float128): float128;function float128_sub(a: float128; b: float128): float128;function float128_mul(a: float128; b: float128): float128;function float128_div(a: float128; b: float128): float128;function float128_rem(a: float128; b: float128): float128;function float128_sqrt(a: float128): float128;function float128_eq(a: float128; b: float128): flag;function float128_le(a: float128; b: float128): flag;function float128_lt(a: float128; b: float128): flag;function float128_eq_signaling(a: float128; b: float128): flag;function float128_le_quiet(a: float128; b: float128): flag;function float128_lt_quiet(a: float128; b: float128): flag;{$endif FPC_SOFTFLOAT_FLOAT128}CONST{-------------------------------------------------------------------------------Software IEC/IEEE floating-point underflow tininess-detection mode.-------------------------------------------------------------------------------*}    float_tininess_after_rounding  = 0;    float_tininess_before_rounding = 1;{*-------------------------------------------------------------------------------Underflow tininess-detection mode, statically initialized to default value.(The declaration in `softfloat.h' must match the `int8' type here.)-------------------------------------------------------------------------------*}var // threadvar!?    softfloat_detect_tininess: int8 = float_tininess_after_rounding;{$endif  not(defined(fpc_softfpu_implementation))}{$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}implementation{$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}{$if not(defined(fpc_softfpu_interface))}(*****************************************************************************)(*----------------------------------------------------------------------------*)(* Primitive arithmetic functions, including multi-word arithmetic, and       *)(* division and square root approximations.  (Can be specialized to target if *)(* desired.)                                                                  *)(* ---------------------------------------------------------------------------*)(*****************************************************************************){ This procedure serves as a single access point to softfloat_exception_flags.  It also helps to reduce code size a bit because softfloat_exception_flags is  a threadvar. }procedure set_inexact_flag;begin    include(softfloat_exception_flags,float_flag_inexact);end;{*----------------------------------------------------------------------------| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6| and 7, and returns the properly rounded 32-bit integer corresponding to the| input.  If `zSign' is 1, the input is negated before being converted to an| integer.  Bit 63 of `absZ' must be zero.  Ordinarily, the fixed-point input| is simply rounded to an integer, with the inexact exception raised if the| input cannot be represented exactly as an integer.  However, if the fixed-| point input is too large, the invalid exception is raised and the largest| positive or negative integer is returned.*----------------------------------------------------------------------------*}function roundAndPackInt32( zSign: flag; absZ : bits64): int32;var    roundingMode: TFPURoundingMode;    roundNearestEven: boolean;    roundIncrement, roundBits: int8;    z: int32;begin    roundingMode := softfloat_rounding_mode;    roundNearestEven := (roundingMode = float_round_nearest_even);    roundIncrement := $40;    if not roundNearestEven then    begin        if ( roundingMode = float_round_to_zero ) then        begin            roundIncrement := 0;        end        else begin            roundIncrement := $7F;            if ( zSign<>0 ) then            begin                if ( roundingMode = float_round_up ) then                  roundIncrement := 0;            end            else begin                if ( roundingMode = float_round_down ) then                  roundIncrement := 0;            end;        end;    end;    roundBits := lo(absZ) and $7F;    absZ := ( absZ + roundIncrement ) shr 7;    absZ := absZ and not( bits64( ord( ( roundBits xor  $40 ) = 0 ) and ord(roundNearestEven) ));    z := absZ;    if ( zSign<>0 ) then      z := - z;    if ( longint(hi( absZ )) or ( z and ( ord( z < 0 ) xor  zSign ) ) )<>0 then    begin        float_raise( float_flag_invalid );        if zSign<>0 then          result:=sbits32($80000000)        else          result:=$7FFFFFFF;        exit;    end;    if ( roundBits<>0 ) then      set_inexact_flag;    result:=z;end;{*----------------------------------------------------------------------------| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and| `absZ1', with binary point between bits 63 and 64 (between the input words),| and returns the properly rounded 64-bit integer corresponding to the input.| If `zSign' is 1, the input is negated before being converted to an integer.| Ordinarily, the fixed-point input is simply rounded to an integer, with| the inexact exception raised if the input cannot be represented exactly as| an integer.  However, if the fixed-point input is too large, the invalid| exception is raised and the largest positive or negative integer is| returned.*----------------------------------------------------------------------------*}function roundAndPackInt64( zSign: flag; absZ0: bits64; absZ1 : bits64): int64;var    roundingMode: TFPURoundingMode;    roundNearestEven, increment: flag;    z: int64;label    overflow;begin    roundingMode := softfloat_rounding_mode;    roundNearestEven := ord( roundingMode = float_round_nearest_even );    increment := ord( sbits64(absZ1) < 0 );    if ( roundNearestEven=0 ) then    begin        if ( roundingMode = float_round_to_zero ) then        begin            increment := 0;        end        else begin            if ( zSign<>0 ) then            begin                increment := ord(( roundingMode = float_round_down ) and (absZ1<>0));            end            else begin                increment := ord(( roundingMode = float_round_up ) and (absZ1<>0));            end;        end;    end;    if ( increment<>0 ) then    begin        inc(absZ0);        if ( absZ0 = 0 ) then          goto overflow;        absZ0 := absZ0 and not( ord( bits64( absZ1 shl 1 ) = 0 ) and roundNearestEven );    end;    z := absZ0;    if ( zSign<>0 ) then      z := - z;    if ( (z<>0) and (( ord( z < 0 ) xor  zSign )<>0) ) then    begin overflow:        float_raise( float_flag_invalid );        if zSign<>0 then          result:=int64($8000000000000000)        else          result:=int64($7FFFFFFFFFFFFFFF);        exit;    end;    if ( absZ1<>0 ) then      set_inexact_flag;    result:=z;end;{*-------------------------------------------------------------------------------Shifts `a' right by the number of bits given in `count'.  If any nonzerobits are shifted off, they are ``jammed'' into the least significant bit ofthe result by setting the least significant bit to 1.  The value of `count'can be arbitrarily large; in particular, if `count' is greater than 32, theresult will be either 0 or 1, depending on whether `a' is zero or nonzero.The result is stored in the location pointed to by `zPtr'.-------------------------------------------------------------------------------*}Procedure shift32RightJamming( a: bits32 ; count: int16 ; VAR zPtr :bits32);var  z: Bits32;Begin    if ( count = 0 ) then        z := a   else    if ( count < 32 ) then    Begin        z := ( a shr count ) or bits32( (( a shl ( ( - count ) AND 31 )) ) <> 0);    End   else    Begin        z := bits32( a <> 0 );    End;    zPtr := z;End;{*----------------------------------------------------------------------------| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the| number of bits given in `count'.  Any bits shifted off are lost.  The value| of `count' can be arbitrarily large; in particular, if `count' is greater| than 128, the result will be 0.  The result is broken into two 64-bit pieces| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.*----------------------------------------------------------------------------*}procedure shift128Right(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);var    z0, z1: bits64;    negCount: int8;begin    negCount := ( - count ) and 63;    if ( count = 0 ) then    begin        z1 := a1;        z0 := a0;    end    else if ( count < 64 ) then    begin        z1 := ( a0 shl negCount ) or ( a1 shr count );        z0 := a0 shr count;    end    else    begin         if ( count < 128 ) then          z1 := a0 shr ( count and 63 )        else          z1 := 0;        z0 := 0;    end;    z1Ptr := z1;    z0Ptr := z0;end;{*----------------------------------------------------------------------------| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the| number of bits given in `count'.  If any nonzero bits are shifted off, they| are ``jammed'' into the least significant bit of the result by setting the| least significant bit to 1.  The value of `count' can be arbitrarily large;| in particular, if `count' is greater than 128, the result will be either| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or| nonzero.  The result is broken into two 64-bit pieces which are stored at| the locations pointed to by `z0Ptr' and `z1Ptr'.*----------------------------------------------------------------------------*}procedure shift128RightJamming(a0,a1 : bits64; count : int16; var z0Ptr, z1Ptr : bits64);var    z0,z1 : bits64;    negCount : int8;begin    negCount := ( - count ) and 63;    if ( count = 0 ) then begin        z1 := a1;        z0 := a0;    end    else if ( count < 64 ) then begin        z1 := ( a0 shl negCount ) or ( a1 shr count ) or ord( ( a1 shl negCount ) <> 0 );        z0 := a0 shr count;    end    else begin        if ( count = 64 ) then begin            z1 := a0 or ord( a1 <> 0 );        end        else if ( count < 128 ) then begin            z1 := ( a0 shr ( count and 63 ) ) or ord( ( ( a0 shl negCount ) or a1 ) <> 0 );        end        else begin            z1 := ord( ( a0 or a1 ) <> 0 );        end;        z0 := 0;    end;    z1Ptr := z1;    z0Ptr := z0;end;{*-------------------------------------------------------------------------------Shifts the 64-bit value formed by concatenating `a0' and `a1' right by thenumber of bits given in `count'.  Any bits shifted off are lost.  The valueof `count' can be arbitrarily large; in particular, if `count' is greaterthan 64, the result will be 0.  The result is broken into two 32-bit pieceswhich are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.-------------------------------------------------------------------------------*}Procedure shift64Right(     a0 :bits32; a1: bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32);Var  z0, z1: bits32;  negCount : int8;Begin    negCount := ( - count ) AND 31;    if ( count = 0 ) then    Begin        z1 := a1;        z0 := a0;    End    else if ( count < 32 ) then    Begin        z1 := ( a0 shl negCount ) OR ( a1 shr count );        z0 := a0 shr count;    End   else    Begin        if (count < 64) then          z1 := ( a0 shr ( count AND 31 ) )        else          z1 := 0;        z0 := 0;    End;    z1Ptr := z1;    z0Ptr := z0;End;{*-------------------------------------------------------------------------------Shifts the 64-bit value formed by concatenating `a0' and `a1' right by thenumber of bits given in `count'.  If any nonzero bits are shifted off, theyare ``jammed'' into the least significant bit of the result by setting theleast significant bit to 1.  The value of `count' can be arbitrarily large;in particular, if `count' is greater than 64, the result will be either 0or 1, depending on whether the concatenation of `a0' and `a1' is zero ornonzero.  The result is broken into two 32-bit pieces which are stored atthe locations pointed to by `z0Ptr' and `z1Ptr'.-------------------------------------------------------------------------------*}Procedure shift64RightJamming(     a0:bits32; a1: bits32; count:int16; VAR Z0Ptr :bits32;VAR z1Ptr: bits32 );VAR    z0, z1 : bits32;    negCount : int8;Begin    negCount := ( - count ) AND 31;    if ( count = 0 ) then    Begin        z1 := a1;        z0 := a0;    End   else    if ( count < 32 ) then    Begin        z1 := ( a0 shl negCount ) OR ( a1 shr count ) OR bits32( ( a1 shl negCount ) <> 0 );        z0 := a0 shr count;    End   else    Begin        if ( count = 32 ) then        Begin            z1 := a0 OR bits32( a1 <> 0 );        End       else        if ( count < 64 ) Then        Begin            z1 := ( a0 shr ( count AND 31 ) ) OR bits32( ( ( a0 shl negCount ) OR a1 ) <> 0 );        End       else        Begin            z1 := bits32( ( a0 OR a1 ) <> 0 );        End;        z0 := 0;    End;    z1Ptr := z1;    z0Ptr := z0;End;{*----------------------------------------------------------------------------| Shifts `a' right by the number of bits given in `count'.  If any nonzero| bits are shifted off, they are ``jammed'' into the least significant bit of| the result by setting the least significant bit to 1.  The value of `count'| can be arbitrarily large; in particular, if `count' is greater than 64, the| result will be either 0 or 1, depending on whether `a' is zero or nonzero.| The result is stored in the location pointed to by `zPtr'.*----------------------------------------------------------------------------*}procedure shift64RightJamming(a: bits64; count: int16; var zPtr : bits64);var    z: bits64;begin    if ( count = 0 ) then    begin        z := a;    end    else if ( count < 64 ) then    begin        z := ( a shr count ) or ord( ( a  shl ( ( - count ) and 63 ) ) <> 0 );    end    else    begin        z := ord( a <> 0 );    end;    zPtr := z;end;{$if not defined(shift64ExtraRightJamming)}procedure shift64ExtraRightJamming(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);overload;forward;{$endif}{*-------------------------------------------------------------------------------Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' rightby 32 _plus_ the number of bits given in `count'.  The shifted result isat most 64 nonzero bits; these are broken into two 32-bit pieces which arestored at the locations pointed to by `z0Ptr' and `z1Ptr'.  The bits shiftedoff form a third 32-bit result as follows:  The _last_ bit shifted off isthe most-significant bit of the extra result, and the other 31 bits of theextra result are all zero if and only if _all_but_the_last_ bits shifted offwere all zero.  This extra result is stored in the location pointed to by`z2Ptr'.  The value of `count' can be arbitrarily large.    (This routine makes more sense if `a0', `a1', and `a2' are consideredto form a fixed-point value with binary point between `a1' and `a2'.  Thisfixed-point value is shifted right by the number of bits given in `count',and the integer part of the result is returned at the locations pointed toby `z0Ptr' and `z1Ptr'.  The fractional part of the result may be slightlycorrupted as described above, and is returned at the location pointed to by`z2Ptr'.)-------------------------------------------------------------------------------}Procedure shift64ExtraRightJamming(     a0: bits32;     a1: bits32;     a2: bits32;     count: int16;     VAR z0Ptr: bits32;     VAR z1Ptr: bits32;     VAR z2Ptr: bits32 ); overload;Var    z0, z1, z2: bits32;    negCount : int8;Begin    negCount := ( - count ) AND 31;    if ( count = 0 ) then    Begin        z2 := a2;        z1 := a1;        z0 := a0;    End   else    Begin        if ( count < 32 ) Then        Begin            z2 := a1 shl negCount;            z1 := ( a0 shl negCount ) OR ( a1 shr count );            z0 := a0 shr count;        End       else        Begin            if ( count = 32 ) then            Begin                z2 := a1;                z1 := a0;            End           else            Begin                a2 := a2 or a1;                if ( count < 64 ) then                Begin                    z2 := a0 shl negCount;                    z1 := a0 shr ( count AND 31 );                End               else                Begin                    if count = 64 then                       z2 := a0                    else                       z2 := bits32(a0 <> 0);                    z1 := 0;                End;            End;            z0 := 0;        End;        z2 := z2 or bits32( a2 <> 0 );    End;    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;End;{*-------------------------------------------------------------------------------Shifts the 64-bit value formed by concatenating `a0' and `a1' left by thenumber of bits given in `count'.  Any bits shifted off are lost.  The valueof `count' must be less than 32.  The result is broken into two 32-bitpieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.-------------------------------------------------------------------------------*}Procedure shortShift64Left(     a0:bits32; a1:bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );Begin    z1Ptr := a1 shl count;    if count = 0 then      z0Ptr := a0    else      z0Ptr := ( a0 shl count ) OR ( a1 shr ( ( - count ) AND 31 ) );End;{*-------------------------------------------------------------------------------Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' leftby the number of bits given in `count'.  Any bits shifted off are lost.The value of `count' must be less than 32.  The result is broken into three32-bit pieces which are stored at the locations pointed to by `z0Ptr',`z1Ptr', and `z2Ptr'.-------------------------------------------------------------------------------*}Procedure shortShift96Left(     a0: bits32;     a1: bits32;     a2: bits32;     count: int16;     VAR z0Ptr: bits32;     VAR z1Ptr: bits32;     VAR z2Ptr: bits32 );Var    z0, z1, z2: bits32;    negCount: int8;Begin    z2 := a2 shl count;    z1 := a1 shl count;    z0 := a0 shl count;    if ( 0 < count ) then    Begin        negCount := ( ( - count ) AND 31 );        z1 := z1 or (a2 shr negCount);        z0 := z0 or (a1 shr negCount);    End;    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;End;{*----------------------------------------------------------------------------| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the| number of bits given in `count'.  Any bits shifted off are lost.  The value| of `count' must be less than 64.  The result is broken into two 64-bit| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.*----------------------------------------------------------------------------*}procedure shortShift128Left(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);begin    z1Ptr := a1 shl count;    if count=0 then      z0Ptr:=a0    else      z0Ptr:=( a0 shl count ) or ( a1 shr ( ( - count ) and 63 ) );end;{*-------------------------------------------------------------------------------Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bitvalue formed by concatenating `b0' and `b1'.  Addition is modulo 2^64, soany carry out is lost.  The result is broken into two 32-bit pieces whichare stored at the locations pointed to by `z0Ptr' and `z1Ptr'.-------------------------------------------------------------------------------*}Procedure add64(     a0:bits32; a1:bits32; b0:bits32; b1:bits32; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}Var    z1: bits32;Begin    z1 := a1 + b1;    z1Ptr := z1;    z0Ptr := a0 + b0 + bits32( z1 < a1 );End;{*-------------------------------------------------------------------------------Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the96-bit value formed by concatenating `b0', `b1', and `b2'.  Addition ismodulo 2^96, so any carry out is lost.  The result is broken into three32-bit pieces which are stored at the locations pointed to by `z0Ptr',`z1Ptr', and `z2Ptr'.-------------------------------------------------------------------------------*}Procedure add96(     a0: bits32;     a1: bits32;     a2: bits32;     b0: bits32;     b1: bits32;     b2: bits32;     VAR z0Ptr: bits32;     VAR z1Ptr: bits32;     VAR z2Ptr: bits32 );var    z0, z1, z2: bits32;    carry0, carry1: int8;Begin    z2 := a2 + b2;    carry1 := int8( z2 < a2 );    z1 := a1 + b1;    carry0 := int8( z1 < a1 );    z0 := a0 + b0;    z1 := z1 + carry1;    z0 := z0 + bits32( z1 < carry1 );    z0 := z0 + carry0;    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;End;{*----------------------------------------------------------------------------| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left| by the number of bits given in `count'.  Any bits shifted off are lost.| The value of `count' must be less than 64.  The result is broken into three| 64-bit pieces which are stored at the locations pointed to by `z0Ptr',| `z1Ptr', and `z2Ptr'.*----------------------------------------------------------------------------*}procedure shortShift192Left(a0,a1,a2 : bits64;count : int16;var z0Ptr,z1Ptr,z2Ptr : bits64);var    z0, z1, z2 : bits64;    negCount : int8;begin    z2 := a2 shl count;    z1 := a1 shl count;    z0 := a0 shl count;    if ( 0 < count ) then    begin        negCount := ( ( - count ) and 63 );        z1 := z1 or (a2 shr negCount);        z0 := z0 or (a1 shr negCount);    end;    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;end;{*----------------------------------------------------------------------------| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit| value formed by concatenating `b0' and `b1'.  Addition is modulo 2^128, so| any carry out is lost.  The result is broken into two 64-bit pieces which| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.*----------------------------------------------------------------------------*}procedure add128( a0, a1, b0, b1 : bits64; var z0Ptr, z1Ptr : bits64);{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}var    z1 : bits64;begin    z1 := a1 + b1;    z1Ptr := z1;    z0Ptr := a0 + b0 + ord( z1 < a1 );end;{*----------------------------------------------------------------------------| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the| 192-bit value formed by concatenating `b0', `b1', and `b2'.  Addition is| modulo 2^192, so any carry out is lost.  The result is broken into three| 64-bit pieces which are stored at the locations pointed to by `z0Ptr',| `z1Ptr', and `z2Ptr'.*----------------------------------------------------------------------------*}procedure add192(a0,a1,a2,b0,b1,b2: bits64; var z0Ptr,z1Ptr,z2Ptr : bits64);var    z0, z1, z2 : bits64;    carry0, carry1 : int8;begin    z2 := a2 + b2;    carry1 := ord( z2 < a2 );    z1 := a1 + b1;    carry0 := ord( z1 < a1 );    z0 := a0 + b0;    inc(z1, carry1);    inc(z0, ord( z1 < carry1 ));    inc(z0, carry0);    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;end;{*-------------------------------------------------------------------------------Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the64-bit value formed by concatenating `a0' and `a1'.  Subtraction is modulo2^64, so any borrow out (carry out) is lost.  The result is broken into two32-bit pieces which are stored at the locations pointed to by `z0Ptr' and`z1Ptr'.-------------------------------------------------------------------------------*}Procedure sub64(     a0: bits32; a1 : bits32; b0 :bits32; b1: bits32; VAR z0Ptr:bits32; VAR z1Ptr: bits32 );{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}Begin    z1Ptr := a1 - b1;    z0Ptr := a0 - b0 - bits32( a1 < b1 );End;{*-------------------------------------------------------------------------------Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' fromthe 96-bit value formed by concatenating `a0', `a1', and `a2'.  Subtractionis modulo 2^96, so any borrow out (carry out) is lost.  The result is brokeninto three 32-bit pieces which are stored at the locations pointed to by`z0Ptr', `z1Ptr', and `z2Ptr'.-------------------------------------------------------------------------------*}Procedure sub96(     a0:bits32;     a1:bits32;     a2:bits32;     b0:bits32;     b1:bits32;     b2:bits32;     VAR z0Ptr:bits32;     VAR z1Ptr:bits32;     VAR z2Ptr:bits32 );Var    z0, z1, z2: bits32;    borrow0, borrow1: int8;Begin    z2 := a2 - b2;    borrow1 := int8( a2 < b2 );    z1 := a1 - b1;    borrow0 := int8( a1 < b1 );    z0 := a0 - b0;    z0 := z0 - bits32( z1 < borrow1 );    z1 := z1 - borrow1;    z0 := z0 -borrow0;    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;End;{*----------------------------------------------------------------------------| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the| 128-bit value formed by concatenating `a0' and `a1'.  Subtraction is modulo| 2^128, so any borrow out (carry out) is lost.  The result is broken into two| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and| `z1Ptr'.*----------------------------------------------------------------------------*}procedure sub128( a0, a1, b0, b1 : bits64; var z0Ptr, z1Ptr : bits64);begin    z1Ptr := a1 - b1;    z0Ptr := a0 - b0 - ord( a1 < b1 );end;{*----------------------------------------------------------------------------| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'| from the 192-bit value formed by concatenating `a0', `a1', and `a2'.| Subtraction is modulo 2^192, so any borrow out (carry out) is lost.  The| result is broken into three 64-bit pieces which are stored at the locations| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.*----------------------------------------------------------------------------*}procedure sub192(a0,a1,a2,b0,b1,b2: bits64; var z0Ptr,z1Ptr,z2Ptr : bits64);var    z0, z1, z2 : bits64;    borrow0, borrow1 : int8;begin    z2 := a2 - b2;    borrow1 := ord( a2 < b2 );    z1 := a1 - b1;    borrow0 := ord( a1 < b1 );    z0 := a0 - b0;    dec(z0, ord( z1 < borrow1 ));    dec(z1, borrow1);    dec(z0, borrow0);    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;end;{*-------------------------------------------------------------------------------Multiplies `a' by `b' to obtain a 64-bit product.  The product is brokeninto two 32-bit pieces which are stored at the locations pointed to by`z0Ptr' and `z1Ptr'.-------------------------------------------------------------------------------*}{$IFDEF SOFTFPU_COMPILER_MUL32TO64}Procedure mul32To64( a:bits32; b:bits32; VAR z0Ptr: bits32; VAR z1Ptr :bits32 );{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}var  tmp: qword;begin  tmp:=qword(a) * b;  z0ptr:=hi(tmp);  z1ptr:=lo(tmp);end;{$ELSE}Procedure mul32To64( a:bits32; b:bits32; VAR z0Ptr: bits32; VAR z1Ptr:bits32 );Var    aHigh, aLow, bHigh, bLow: bits16;    z0, zMiddleA, zMiddleB, z1: bits32;Begin    aLow := bits16(a);    aHigh := a shr 16;    bLow := bits16(b);    bHigh := b shr 16;    z1 := ( bits32( aLow) ) * bLow;    zMiddleA := ( bits32 (aLow) ) * bHigh;    zMiddleB := ( bits32 (aHigh) ) * bLow;    z0 := ( bits32 (aHigh) ) * bHigh;    zMiddleA := zMiddleA + zMiddleB;    z0 := z0 + ( ( bits32 ( zMiddleA < zMiddleB ) ) shl 16 ) + ( zMiddleA shr 16 );    zMiddleA := zmiddleA shl 16;    z1 := z1 + zMiddleA;    z0 := z0 + bits32( z1 < zMiddleA );    z1Ptr := z1;    z0Ptr := z0;End;{$ENDIF}{*-------------------------------------------------------------------------------Multiplies the 64-bit value formed by concatenating `a0' and `a1' by `b'to obtain a 96-bit product.  The product is broken into three 32-bit pieceswhich are stored at the locations pointed to by `z0Ptr', `z1Ptr', and`z2Ptr'.-------------------------------------------------------------------------------*}Procedure mul64By32To96(     a0:bits32;     a1:bits32;     b:bits32;     VAR z0Ptr:bits32;     VAR z1Ptr:bits32;     VAR z2Ptr:bits32 );Var    z0, z1, z2, more1: bits32;Begin    mul32To64( a1, b, z1, z2 );    mul32To64( a0, b, z0, more1 );    add64( z0, more1, 0, z1, z0, z1 );    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;End;{*-------------------------------------------------------------------------------Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bitproduct.  The product is broken into four 32-bit pieces which are stored atthe locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.-------------------------------------------------------------------------------*}Procedure mul64To128(     a0:bits32;     a1:bits32;     b0:bits32;     b1:bits32;     VAR z0Ptr:bits32;     VAR z1Ptr:bits32;     VAR z2Ptr:bits32;     VAR z3Ptr:bits32 );Var    z0, z1, z2, z3: bits32;    more1, more2: bits32;Begin    mul32To64( a1, b1, z2, z3 );    mul32To64( a1, b0, z1, more2 );    add64( z1, more2, 0, z2, z1, z2 );    mul32To64( a0, b0, z0, more1 );    add64( z0, more1, 0, z1, z0, z1 );    mul32To64( a0, b1, more1, more2 );    add64( more1, more2, 0, z2, more1, z2 );    add64( z0, z1, 0, more1, z0, z1 );    z3Ptr := z3;    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;End;{*----------------------------------------------------------------------------| Multiplies `a' by `b' to obtain a 128-bit product.  The product is broken| into two 64-bit pieces which are stored at the locations pointed to by| `z0Ptr' and `z1Ptr'.*----------------------------------------------------------------------------*}procedure mul64To128( a, b : bits64; var z0Ptr, z1Ptr : bits64);var    aHigh, aLow, bHigh, bLow : bits32;    z0, zMiddleA, zMiddleB, z1 : bits64;begin    aLow := a;    aHigh := a shr 32;    bLow := b;    bHigh := b shr 32;    z1 := ( bits64(aLow) ) * bLow;    zMiddleA := ( bits64( aLow )) * bHigh;    zMiddleB := ( bits64( aHigh )) * bLow;    z0 := ( bits64(aHigh) ) * bHigh;    inc(zMiddleA, zMiddleB);    inc(z0 ,( ( bits64( zMiddleA < zMiddleB ) ) shl 32 ) + ( zMiddleA shr 32 ));    zMiddleA := zMiddleA shl 32;    inc(z1, zMiddleA);    inc(z0, ord( z1 < zMiddleA ));    z1Ptr := z1;    z0Ptr := z0;end;{*----------------------------------------------------------------------------| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit| product.  The product is broken into four 64-bit pieces which are stored at| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.*----------------------------------------------------------------------------*}procedure mul128To256(a0,a1,b0,b1 : bits64;var z0Ptr,z1Ptr,z2Ptr,z3Ptr : bits64);var    z0,z1,z2,z3,more1,more2 : bits64;begin    mul64To128( a1, b1, z2, z3 );    mul64To128( a1, b0, z1, more2 );    add128( z1, more2, 0, z2, z1, z2 );    mul64To128( a0, b0, z0, more1 );    add128( z0, more1, 0, z1, z0, z1 );    mul64To128( a0, b1, more1, more2 );    add128( more1, more2, 0, z2, more1, z2 );    add128( z0, z1, 0, more1, z0, z1 );    z3Ptr := z3;    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;end;{*----------------------------------------------------------------------------| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by| `b' to obtain a 192-bit product.  The product is broken into three 64-bit| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and| `z2Ptr'.*----------------------------------------------------------------------------*}procedure mul128By64To192(a0,a1,b : bits64;var z0Ptr,z1Ptr,z2Ptr : bits64);var    z0, z1, z2, more1 : bits64;begin    mul64To128( a1, b, z1, z2 );    mul64To128( a0, b, z0, more1 );    add128( z0, more1, 0, z1, z0, z1 );    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;end;{*----------------------------------------------------------------------------| Returns an approximation to the 64-bit integer quotient obtained by dividing| `b' into the 128-bit value formed by concatenating `a0' and `a1'.  The| divisor `b' must be at least 2^63.  If q is the exact quotient truncated| toward zero, the approximation returned lies between q and q + 2 inclusive.| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit| unsigned integer is returned.*----------------------------------------------------------------------------*}Function estimateDiv128To64( a0:bits64; a1: bits64; b:bits64): bits64;var    b0, b1, rem0, rem1, term0, term1, z : bits64;begin    if ( b <= a0 ) then      begin        result:=qword( $FFFFFFFFFFFFFFFF );        exit;      end;    b0 := b shr 32;    if ( b0 shl 32 <= a0 ) then      z:=qword( $FFFFFFFF00000000 )    else      z:=( a0 div b0 ) shl 32;    mul64To128( b, z, term0, term1 );    sub128( a0, a1, term0, term1, rem0, rem1 );    while ( ( sbits64(rem0) ) < 0 ) do begin        dec(z,qword( $100000000 ));        b1 := b shl 32;        add128( rem0, rem1, b0, b1, rem0, rem1 );    end;    rem0 := ( rem0 shl 32 ) or ( rem1 shr 32 );    if ( b0 shl 32 <= rem0 ) then      z:=z or $FFFFFFFF    else      z:=z or rem0 div b0;    result:=z;end;{*-------------------------------------------------------------------------------Returns an approximation to the 32-bit integer quotient obtained by dividing`b' into the 64-bit value formed by concatenating `a0' and `a1'.  Thedivisor `b' must be at least 2^31.  If q is the exact quotient truncatedtoward zero, the approximation returned lies between q and q + 2 inclusive.If the exact quotient q is larger than 32 bits, the maximum positive 32-bitunsigned integer is returned.-------------------------------------------------------------------------------*}Function estimateDiv64To32( a0:bits32; a1: bits32; b:bits32): bits32;Var    b0, b1: bits32;    rem0, rem1, term0, term1: bits32;    z: bits32;Begin    if ( b <= a0 ) then    Begin       estimateDiv64To32 := $FFFFFFFF;       exit;    End;    b0 := b shr 16;    if ( b0 shl 16 <= a0 ) then       z:= $FFFF0000     else       z:= ( a0 div b0 ) shl 16;    mul32To64( b, z, term0, term1 );    sub64( a0, a1, term0, term1, rem0, rem1 );    while ( ( sbits32 (rem0) ) < 0 ) do    Begin        z := z - $10000;        b1 := b shl 16;        add64( rem0, rem1, b0, b1, rem0, rem1 );    End;    rem0 := ( rem0 shl 16 ) OR ( rem1 shr 16 );    if ( b0 shl 16 <= rem0 ) then      z := z or $FFFF    else      z := z or (rem0 div b0);    estimateDiv64To32 := z;End;{*-------------------------------------------------------------------------------Returns an approximation to the square root of the 32-bit significand givenby `a'.  Considered as an integer, `a' must be at least 2^31.  If bit 0 of`aExp' (the least significant bit) is 1, the integer returned approximates2^31*sqrt(`a'/2^31), where `a' is considered an integer.  If bit 0 of `aExp'is 0, the integer returned approximates 2^31*sqrt(`a'/2^30).  In eithercase, the approximation returned lies strictly within +/-2 of the exactvalue.-------------------------------------------------------------------------------*}Function estimateSqrt32( aExp: int16; a: bits32 ): bits32;    const sqrtOddAdjustments: array[0..15] of bits16 = (        $0004, $0022, $005D, $00B1, $011D, $019F, $0236, $02E0,        $039C, $0468, $0545, $0631, $072B, $0832, $0946, $0A67    );    const sqrtEvenAdjustments: array[0..15] of bits16 = (        $0A2D, $08AF, $075A, $0629, $051A, $0429, $0356, $029E,        $0200, $0179, $0109, $00AF, $0068, $0034, $0012, $0002    );Var    index: int8;    z: bits32;Begin    index := ( a shr 27 ) AND 15;    if ( aExp AND 1 ) <> 0  then    Begin        z := $4000 + ( a shr 17 ) - sqrtOddAdjustments[ index ];        z := ( ( a div z ) shl 14 ) + ( z shl 15 );        a := a shr 1;    End    else    Begin        z := $8000 + ( a shr 17 ) - sqrtEvenAdjustments[ index ];        z := a div z + z;        if ( $20000 <= z ) then          z := $FFFF8000        else          z := ( z shl 15 );        if ( z <= a ) then        Begin           estimateSqrt32 := bits32 ( SarLongint( sbits32 (a)) );           exit;        End;    End;    estimateSqrt32 := ( ( estimateDiv64To32( a, 0, z ) ) shr 1 ) + ( z shr 1 );End;{*-------------------------------------------------------------------------------Returns the number of leading 0 bits before the most-significant 1 bit of`a'.  If `a' is zero, 32 is returned.-------------------------------------------------------------------------------*}Function countLeadingZeros32( a:bits32 ): int8;    const countLeadingZerosHigh:array[0..255] of int8 = (        8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0    );Var    shiftCount: int8;Begin    shiftCount := 0;    if ( a < $10000 ) then    Begin        shiftCount := shiftcount + 16;        a := a shl 16;    End;    if ( a < $1000000 ) then    Begin        shiftCount := shiftcount + 8;        a := a shl 8;    end;    shiftCount := shiftcount + countLeadingZerosHigh[ a shr 24 ];    countLeadingZeros32:= shiftCount;End;{*----------------------------------------------------------------------------| Returns the number of leading 0 bits before the most-significant 1 bit of| `a'.  If `a' is zero, 64 is returned.*----------------------------------------------------------------------------*}function countLeadingZeros64( a : bits64): int8;var shiftcount : int8;Begin    shiftCount := 0;    if ( a <  bits64(bits64(1)  shl 32 )) then        shiftCount := shiftcount + 32    else        a := a shr 32;    shiftCount := shiftCount + countLeadingZeros32( a );    countLeadingZeros64:= shiftCount;End;{*-------------------------------------------------------------------------------Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is lessthan or equal to the 64-bit value formed by concatenating `b0' and `b1'.Otherwise, returns 0.-------------------------------------------------------------------------------*}Function le64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}Begin    le64:= flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 <= b1 ) );End;{*-------------------------------------------------------------------------------Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is lessthan the 64-bit value formed by concatenating `b0' and `b1'.  Otherwise,returns 0.-------------------------------------------------------------------------------*}Function lt64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}Begin    lt64 := flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 < b1 ) );End;const  float128_default_nan_high = qword($FFFFFFFFFFFFFFFF);  float128_default_nan_low = qword($FFFFFFFFFFFFFFFF);(*****************************************************************************)(*                      End Low-Level arithmetic                             *)(*****************************************************************************){*----------------------------------------------------------------------------| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less| than the 128-bit value formed by concatenating `b0' and `b1'.  Otherwise,| returns 0.*----------------------------------------------------------------------------*}function lt128(a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;begin    result := ord(( a0 < b0 ) or ( ( a0 = b0 ) and ( a1 < b1 ) ));end;{*-------------------------------------------------------------------------------Functions and definitions to determine:  (1) whether tininess for underflowis detected before or after rounding by default, (2) what (if anything)happens when exceptions are raised, (3) how signaling NaNs are distinguishedfrom quiet NaNs, (4) the default generated quiet NaNs, and (4) how NaNsare propagated from function inputs to output.  These details are ENDIANspecific-------------------------------------------------------------------------------*}{$IFDEF ENDIAN_LITTLE}{*-------------------------------------------------------------------------------Internal canonical NaN format.-------------------------------------------------------------------------------*}TYPE commonNaNT = record   high, low : bits32;   sign: flag; end;{*-------------------------------------------------------------------------------The pattern for a default generated single-precision NaN.-------------------------------------------------------------------------------*}const float32_default_nan = $FFC00000;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is a NaN;otherwise returns 0.-------------------------------------------------------------------------------*}Function float32_is_nan( a : float32 ): flag;Begin    float32_is_nan:= flag( $FF000000 < bits32 ( a shl 1 ) );End;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is a signalingNaN; otherwise returns 0.-------------------------------------------------------------------------------*}Function float32_is_signaling_nan( a : float32  ): flag;Begin    float32_is_signaling_nan := flag      (( ( ( a shr 22 ) and $1FF ) = $1FE ) and (( a and $003FFFFF )<>0));End;{*-------------------------------------------------------------------------------Returns the result of converting the single-precision floating-point NaN`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalidexception is raised.-------------------------------------------------------------------------------*}function float32ToCommonNaN(a: float32) : commonNaNT;var    z : commonNaNT ;Begin    if ( float32_is_signaling_nan( a ) <> 0) then       float_raise( float_flag_invalid );    z.sign := a shr 31;    z.low := 0;    z.high := a shl 9;    result := z;End;{*-------------------------------------------------------------------------------Returns the result of converting the canonical NaN `a' to the single-precision floating-point format.-------------------------------------------------------------------------------*}Function commonNaNToFloat32( a : commonNaNT ): float32;Begin    commonNaNToFloat32 := ( ( bits32 (a.sign) ) shl 31 ) or $7FC00000 or ( a.high shr 9 );End;{*-------------------------------------------------------------------------------Takes two single-precision floating-point values `a' and `b', one of whichis a NaN, and returns the appropriate NaN result.  If either `a' or `b' is asignaling NaN, the invalid exception is raised.-------------------------------------------------------------------------------*}Function propagateFloat32NaN( a : float32 ; b: float32 ): float32;Var    aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;label returnLargerSignificand;Begin    aIsNaN := float32_is_nan( a );    aIsSignalingNaN := float32_is_signaling_nan( a );    bIsNaN := float32_is_nan( b );    bIsSignalingNaN := float32_is_signaling_nan( b );    a := a or $00400000;    b := b or $00400000;    if ( aIsSignalingNaN or bIsSignalingNaN ) <> 0 then        float_raise( float_flag_invalid );    if ( aIsSignalingNaN )<> 0  then    Begin        if ( bIsSignalingNaN ) <>  0 then          goto returnLargerSignificand;        if bIsNan <> 0 then          propagateFloat32NaN := b        else          propagateFloat32NaN := a;        exit;    End    else if ( aIsNaN <> 0) then    Begin        if ( bIsSignalingNaN or not bIsNaN )<> 0 then        Begin           propagateFloat32NaN := a;           exit;        End; returnLargerSignificand:        if ( bits32 ( a shl 1 ) < bits32 ( b shl 1 ) ) then        Begin           propagateFloat32NaN := b;           exit;        End;        if ( bits32 ( b shl 1 ) < bits32 ( a shl 1 ) ) then        Begin           propagateFloat32NaN :=  a;        End;        if a < b then          propagateFloat32NaN := a        else          propagateFloat32NaN := b;        exit;    End    else    Begin        propagateFloat32NaN := b;        exit;    End;End;{*-------------------------------------------------------------------------------The pattern for a default generated double-precision NaN.  The `high' and`low' values hold the most- and least-significant bits, respectively.-------------------------------------------------------------------------------*}const    float64_default_nan_high = $FFF80000;    float64_default_nan_low  = $00000000;{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is a NaN;otherwise returns 0.-------------------------------------------------------------------------------*}Function float64_is_nan( a : float64 ) : flag;Begin    float64_is_nan :=           flag(( $FFE00000 <= bits32 ( a.high shl 1 ) )        and (( a.low or ( a.high and $000FFFFF ) )<>0));End;{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is a signalingNaN; otherwise returns 0.-------------------------------------------------------------------------------*}Function float64_is_signaling_nan( a : float64 ): flag;Begin    float64_is_signaling_nan :=           flag( ( ( a.high shr 19 ) and $FFF ) = $FFE )        and ( a.low or ( a.high and $0007FFFF ) );End;{*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point NaN`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalidexception is raised.-------------------------------------------------------------------------------*}function float64ToCommonNaN( a : float64 ) : commonNaNT;Var    z : commonNaNT;Begin    if ( float64_is_signaling_nan( a )<>0 ) then        float_raise( float_flag_invalid );    z.sign := a.high shr 31;    shortShift64Left( a.high, a.low, 12, z.high, z.low );    result := z;End;{*-------------------------------------------------------------------------------Returns the result of converting the canonical NaN `a' to the double-precision floating-point format.-------------------------------------------------------------------------------*}function commonNaNToFloat64( a : commonNaNT) : float64;Var    z: float64;Begin    shift64Right( a.high, a.low, 12, z.high, z.low );    z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;    result := z;End;{*-------------------------------------------------------------------------------Takes two double-precision floating-point values `a' and `b', one of whichis a NaN, and returns the appropriate NaN result.  If either `a' or `b' is asignaling NaN, the invalid exception is raised.-------------------------------------------------------------------------------*}Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );Var    aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;    label returnLargerSignificand;Begin    aIsNaN := float64_is_nan( a );    aIsSignalingNaN := float64_is_signaling_nan( a );    bIsNaN := float64_is_nan( b );    bIsSignalingNaN := float64_is_signaling_nan( b );    a.high := a.high or $00080000;    b.high := b.high or $00080000;    if ( aIsSignalingNaN or bIsSignalingNaN )<> 0 then        float_raise( float_flag_invalid );    if ( aIsSignalingNaN )<>0 then    Begin        if ( bIsSignalingNaN )<>0 then            goto returnLargerSignificand;        if bIsNan <> 0 then           c := b        else           c := a;        exit;    End    else if ( aIsNaN )<> 0 then    Begin        if ( bIsSignalingNaN or not bIsNaN ) <> 0 then        Begin          c := a;           exit;        End; returnLargerSignificand:        if ( lt64( a.high shl 1, a.low, b.high shl 1, b.low ) ) <> 0 then        Begin           c := b;           exit;        End;        if ( lt64( b.high shl 1, b.low, a.high shl 1, a.low ) ) <> 0 then        Begin           c := a;           exit;        End;        if a.high < b.high then         c := a        else         c := b;        exit;    End    else    Begin        c := b;        exit;    End;End;{*----------------------------------------------------------------------------| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;| otherwise returns 0.*----------------------------------------------------------------------------*}function float128_is_nan( a : float128): flag;begin    result:= ord(( bits64( $FFFE000000000000 ) <= bits64( a.high shl 1 ) )        and ( (a.low<>0) or (( a.high and int64( $0000FFFFFFFFFFFF ) )<>0 ) ));end;{*----------------------------------------------------------------------------| Returns 1 if the quadruple-precision floating-point value `a' is a| signaling NaN; otherwise returns 0.*----------------------------------------------------------------------------*}function float128_is_signaling_nan( a : float128): flag;begin    result:=ord(( ( ( a.high shr 47 ) and $FFFF ) = $FFFE ) and        ( (a.low<>0) or (( a.high and int64( $00007FFFFFFFFFFF ) )<>0) ));end;{*----------------------------------------------------------------------------| Returns the result of converting the quadruple-precision floating-point NaN| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid| exception is raised.*----------------------------------------------------------------------------*}function float128ToCommonNaN( a : float128): commonNaNT;var    z: commonNaNT;    qhigh,qlow : qword;begin    if ( float128_is_signaling_nan( a )<>0)  then      float_raise( float_flag_invalid );    z.sign := a.high shr 63;    shortShift128Left( a.high, a.low, 16, qhigh, qlow );    z.high:=qhigh shr 32;    z.low:=qhigh and $ffffffff;    result:=z;end;{*----------------------------------------------------------------------------| Returns the result of converting the canonical NaN `a' to the quadruple-| precision floating-point format.*----------------------------------------------------------------------------*}function commonNaNToFloat128( a : commonNaNT): float128;var    z: float128;begin    shift128Right( a.high, a.low, 16, z.high, z.low );    z.high := z.high or ( ( bits64(a.sign) ) shl 63 ) or int64( $7FFF800000000000 );    result:=z;end;{*----------------------------------------------------------------------------| Takes two quadruple-precision floating-point values `a' and `b', one of| which is a NaN, and returns the appropriate NaN result.  If either `a' or| `b' is a signaling NaN, the invalid exception is raised.*----------------------------------------------------------------------------*}function propagateFloat128NaN( a: float128; b : float128): float128;var    aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;label    returnLargerSignificand;begin    aIsNaN := float128_is_nan( a );    aIsSignalingNaN := float128_is_signaling_nan( a );    bIsNaN := float128_is_nan( b );    bIsSignalingNaN := float128_is_signaling_nan( b );    a.high := a.high or int64( $0000800000000000 );    b.high := b.high or int64( $0000800000000000 );    if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then       float_raise( float_flag_invalid );    if ( aIsSignalingNaN )<>0 then    begin        if ( bIsSignalingNaN )<>0 then          goto returnLargerSignificand;        if bIsNaN<>0 then          result := b        else          result := a;        exit;    end    else if ( aIsNaN )<>0 then    begin        if ( bIsSignalingNaN or not( bIsNaN) )<>0 then          begin          	result := a;          	exit;          end; returnLargerSignificand:        if ( lt128( a.high shl 1, a.low, b.high shl 1, b.low ) )<>0 then          begin          	result := b;          	exit;          end;        if ( lt128( b.high shl 1, b.low, a.high shl 1, a.low ) )<>0 then          begin          	result := a;          	exit          end;        if ( a.high < b.high ) then          result := a        else          result := b;        exit;    end    else    result:=b;end;{$ELSE}{ Big endian code }(*----------------------------------------------------------------------------| Internal canonical NaN format.*----------------------------------------------------------------------------*)type commonNANT = record  high, low : bits32;  sign : flag; end;(*----------------------------------------------------------------------------| The pattern for a default generated single-precision NaN.*----------------------------------------------------------------------------*)const float32_default_nan = $7FFFFFFF;(*----------------------------------------------------------------------------| Returns 1 if the single-precision floating-point value `a' is a NaN;| otherwise returns 0.*----------------------------------------------------------------------------*)function float32_is_nan(a:  float32): flag;begin    float32_is_nan := flag( $FF000000 < bits32( a shl 1 ) );end;(*----------------------------------------------------------------------------| Returns 1 if the single-precision floating-point value `a' is a signaling| NaN; otherwise returns 0.*----------------------------------------------------------------------------*)function float32_is_signaling_nan(a: float32):flag; begin   float32_is_signaling_nan := flag( ( ( a shr 22 ) and $1FF ) = $1FE ) and flag( boolean((a and $003FFFFF)<>0) ); end;(*----------------------------------------------------------------------------| Returns the result of converting the single-precision floating-point NaN| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid| exception is raised.*----------------------------------------------------------------------------*)function float32ToCommonNaN( a: float32) : commonNaNT; var  z: commonNANT; begin   if float32_is_signaling_nan(a)<>0 then      float_raise(float_flag_invalid);   z.sign := a shr 31;   z.low := 0;   z.high := a shl 9;   result:=z; end;(*----------------------------------------------------------------------------| Returns the result of converting the canonical NaN `a' to the single-| precision floating-point format.*----------------------------------------------------------------------------*)function CommonNanToFloat32(a : CommonNaNT): float32; begin    CommonNanToFloat32:= ( ( bits32( a.sign )) shl 31 ) OR $7FC00000 OR ( a.high shr 9 ); end;(*----------------------------------------------------------------------------| Takes two single-precision floating-point values `a' and `b', one of which| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a| signaling NaN, the invalid exception is raised.*----------------------------------------------------------------------------*)function  propagateFloat32NaN( a: float32 ; b: float32): float32; var  aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag; begin    aIsNaN := float32_is_nan( a );    aIsSignalingNaN := float32_is_signaling_nan( a );    bIsNaN := float32_is_nan( b );    bIsSignalingNaN := float32_is_signaling_nan( b );    a := a or $00400000;    b := b or $00400000;    if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then       float_raise( float_flag_invalid );    if bIsSignalingNaN<>0 then        propagateFloat32Nan := b    else if aIsSignalingNan<>0 then        propagateFloat32Nan := a    else if bIsNan<>0 then        propagateFloat32Nan := b    else        propagateFloat32Nan := a; end;(*----------------------------------------------------------------------------| The pattern for a default generated double-precision NaN.  The `high' and| `low' values hold the most- and least-significant bits, respectively.*----------------------------------------------------------------------------*)const    float64_default_nan_high = $7FFFFFFF;    float64_default_nan_low  = $FFFFFFFF;(*----------------------------------------------------------------------------| Returns 1 if the double-precision floating-point value `a' is a NaN;| otherwise returns 0.*----------------------------------------------------------------------------*)function float64_is_nan(a: float64): flag; begin    float64_is_nan := flag (           ( $FFE00000 <= bits32 ( a.high shl 1 ) )        and ( (a.low<>0) or (( a.high and $000FFFFF )<>0) )); end;(*----------------------------------------------------------------------------| Returns 1 if the double-precision floating-point value `a' is a signaling| NaN; otherwise returns 0.*----------------------------------------------------------------------------*)function float64_is_signaling_nan( a:float64): flag; begin    float64_is_signaling_nan := flag(           ( ( ( a.high shr 19 ) and $FFF ) = $FFE )        and ( (a.low<>0) or ( ( a.high and $0007FFFF )<>0) )); end;(*----------------------------------------------------------------------------| Returns the result of converting the double-precision floating-point NaN| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid| exception is raised.*----------------------------------------------------------------------------*)function float64ToCommonNaN( a : float64)  : commonNaNT; var   z : commonNaNT; begin    if ( float64_is_signaling_nan( a )<>0 ) then        float_raise( float_flag_invalid );    z.sign := a.high shr 31;    shortShift64Left( a.high, a.low, 12, z.high, z.low );    result:=z; end;(*----------------------------------------------------------------------------| Returns the result of converting the canonical NaN `a' to the double-| precision floating-point format.*----------------------------------------------------------------------------*)function commonNaNToFloat64( a : commonNaNT): float64; var  z: float64; begin    shift64Right( a.high, a.low, 12, z.high, z.low );    z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;    result:=z; end;(*----------------------------------------------------------------------------| Takes two double-precision floating-point values `a' and `b', one of which| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a| signaling NaN, the invalid exception is raised.*----------------------------------------------------------------------------*)Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );var aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN : flag; begin    aIsNaN := float64_is_nan( a );    aIsSignalingNaN := float64_is_signaling_nan( a );    bIsNaN := float64_is_nan( b );    bIsSignalingNaN := float64_is_signaling_nan( b );    a.high := a.high or $00080000;    b.high := b.high or $00080000;    if ( (aIsSignalingNaN<>0) or (bIsSignalingNaN<>0) ) then       float_raise( float_flag_invalid );    if bIsSignalingNaN<>0 then        c := b    else if aIsSignalingNan<>0 then        c := a    else if bIsNan<>0 then        c := b    else        c := a; end;{*----------------------------------------------------------------------------| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;| otherwise returns 0.*----------------------------------------------------------------------------*}function float128_is_nan( a : float128): flag;begin    result:= ord(( bits64( $FFFE000000000000 ) <= bits64( a.high shl 1 ) )        and ( (a.low<>0) or (( a.high and int64( $0000FFFFFFFFFFFF ) )<>0 ) ));end;{*----------------------------------------------------------------------------| Returns 1 if the quadruple-precision floating-point value `a' is a| signaling NaN; otherwise returns 0.*----------------------------------------------------------------------------*}function float128_is_signaling_nan( a : float128): flag;begin    result:=ord(( ( ( a.high shr 47 ) and $FFFF ) = $FFFE ) and        ( (a.low<>0) or (( a.high and int64( $00007FFFFFFFFFFF ) )<>0) ));end;{*----------------------------------------------------------------------------| Returns the result of converting the quadruple-precision floating-point NaN| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid| exception is raised.*----------------------------------------------------------------------------*}function float128ToCommonNaN( a : float128): commonNaNT;var    z: commonNaNT;    qhigh,qlow : qword;begin    if ( float128_is_signaling_nan( a )<>0)  then      float_raise( float_flag_invalid );    z.sign := a.high shr 63;    shortShift128Left( a.high, a.low, 16, qhigh, qlow );    z.high:=qhigh shr 32;    z.low:=qhigh and $ffffffff;    result:=z;end;{*----------------------------------------------------------------------------| Returns the result of converting the canonical NaN `a' to the quadruple-| precision floating-point format.*----------------------------------------------------------------------------*}function commonNaNToFloat128( a : commonNaNT): float128;var    z: float128;begin    shift128Right( a.high, a.low, 16, z.high, z.low );    z.high := z.high or ( ( bits64(a.sign) ) shl 63 ) or int64( $7FFF800000000000 );    result:=z;end;{*----------------------------------------------------------------------------| Takes two quadruple-precision floating-point values `a' and `b', one of| which is a NaN, and returns the appropriate NaN result.  If either `a' or| `b' is a signaling NaN, the invalid exception is raised.*----------------------------------------------------------------------------*}function propagateFloat128NaN( a: float128; b : float128): float128;var    aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;label    returnLargerSignificand;begin    aIsNaN := float128_is_nan( a );    aIsSignalingNaN := float128_is_signaling_nan( a );    bIsNaN := float128_is_nan( b );    bIsSignalingNaN := float128_is_signaling_nan( b );    a.high := a.high or int64( $0000800000000000 );    b.high := b.high or int64( $0000800000000000 );    if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then       float_raise( float_flag_invalid );    if ( aIsSignalingNaN )<>0 then    begin        if ( bIsSignalingNaN )<>0 then          goto returnLargerSignificand;        if bIsNaN<>0 then          result := b        else          result := a;        exit;    end    else if ( aIsNaN )<>0 then    begin        if ( bIsSignalingNaN or not( bIsNaN) )<>0 then          begin          	result := a;          	exit;          end; returnLargerSignificand:        if ( lt128( a.high shl 1, a.low, b.high shl 1, b.low ) )<>0 then          begin          	result := b;          	exit;          end;        if ( lt128( b.high shl 1, b.low, a.high shl 1, a.low ) )<>0 then          begin          	result := a;          	exit          end;        if ( a.high < b.high ) then          result := a        else          result := b;        exit;    end    else    result:=b;end;{$ENDIF}(****************************************************************************)(*                        END ENDIAN SPECIFIC CODE                          *)(****************************************************************************){*-------------------------------------------------------------------------------Returns the fraction bits of the single-precision floating-point value `a'.-------------------------------------------------------------------------------*}Function ExtractFloat32Frac(a : Float32) : Bits32; inline; Begin    ExtractFloat32Frac := A AND $007FFFFF; End;{*-------------------------------------------------------------------------------Returns the exponent bits of the single-precision floating-point value `a'.-------------------------------------------------------------------------------*}Function extractFloat32Exp( a: float32 ): Int16; inline;  Begin    extractFloat32Exp := (a shr 23) AND $FF;  End;{*-------------------------------------------------------------------------------Returns the sign bit of the single-precision floating-point value `a'.-------------------------------------------------------------------------------*}Function extractFloat32Sign( a: float32 ): Flag; inline;  Begin    extractFloat32Sign := a shr 31;  End;{*-------------------------------------------------------------------------------Normalizes the subnormal single-precision floating-point value representedby the denormalized significand `aSig'.  The normalized exponent andsignificand are stored at the locations pointed to by `zExpPtr' and`zSigPtr', respectively.-------------------------------------------------------------------------------*}Procedure normalizeFloat32Subnormal( aSig : bits32; VAR zExpPtr: Int16; VAR zSigPtr :bits32); Var   ShiftCount : BYTE; Begin    shiftCount := countLeadingZeros32( aSig ) - 8;    zSigPtr := aSig shl shiftCount;    zExpPtr := 1 - shiftCount;  End;{*-------------------------------------------------------------------------------Packs the sign `zSign', exponent `zExp', and significand `zSig' into asingle-precision floating-point value, returning the result.  After beingshifted into the proper positions, the three fields are simply addedtogether to form the result.  This means that any integer portion of `zSig'will be added into the exponent.  Since a properly normalized significandwill have an integer portion equal to 1, the `zExp' input should be 1 lessthan the desired result exponent whenever `zSig' is a complete, normalizedsignificand.-------------------------------------------------------------------------------*}Function packFloat32( zSign: Flag; zExp : Int16; zSig: Bits32 ): Float32; inline; Begin    packFloat32 := ( ( bits32( zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 23 )      + zSig; End;{*-------------------------------------------------------------------------------Takes an abstract floating-point value having sign `zSign', exponent `zExp',and significand `zSig', and returns the proper single-precision floating-point value corresponding to the abstract input.  Ordinarily, the abstractvalue is simply rounded and packed into the single-precision format, withthe inexact exception raised if the abstract input cannot be representedexactly.  However, if the abstract value is too large, the overflow andinexact exceptions are raised and an infinity or maximal finite value isreturned.  If the abstract value is too small, the input value is rounded toa subnormal number, and the underflow and inexact exceptions are raised ifthe abstract input cannot be represented exactly as a subnormal single-precision floating-point number.    The input significand `zSig' has its binary point between bits 30and 29, which is 7 bits to the left of the usual location.  This shiftedsignificand must be normalized or smaller.  If `zSig' is not normalized,`zExp' must be 0; in that case, the result returned is a subnormal number,and it must not require rounding.  In the usual case that `zSig' isnormalized, `zExp' must be 1 less than the ``true'' floating-point exponent.The handling of underflow and overflow follows the IEC/IEEE Standard forBinary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function roundAndPackFloat32( zSign : Flag; zExp : Int16; zSig : Bits32 ) : float32; Var   roundingMode : TFPURoundingMode;   roundNearestEven : boolean;   roundIncrement, roundBits : BYTE;   IsTiny : boolean; Begin    roundingMode := softfloat_rounding_mode;    roundNearestEven := (roundingMode = float_round_nearest_even);    roundIncrement := $40;    if not roundNearestEven then      Begin        if ( roundingMode = float_round_to_zero ) Then          Begin            roundIncrement := 0;          End        else          Begin            roundIncrement := $7F;            if ( zSign <> 0 ) then              Begin                if roundingMode = float_round_up then roundIncrement := 0;              End            else              Begin                if roundingMode = float_round_down then roundIncrement := 0;              End;         End      End;    roundBits := zSig AND $7F;    if ($FD <= bits16 (zExp) ) then     Begin        if (( $FD < zExp ) OR  ( zExp = $FD ) AND ( sbits32 ( zSig + roundIncrement ) < 0 ) ) then          Begin             float_raise( [float_flag_overflow,float_flag_inexact] );             roundAndPackFloat32:=packFloat32( zSign, $FF, 0 ) - Flag( roundIncrement = 0 );             exit;          End;        if ( zExp < 0 ) then          Begin            isTiny :=                   ( softfloat_detect_tininess = float_tininess_before_rounding )                OR ( zExp < -1 )                OR ( (zSig + roundIncrement) < $80000000 );            shift32RightJamming( zSig, - zExp, zSig );            zExp := 0;            roundBits := zSig AND $7F;            if ( isTiny and (roundBits<>0) ) then               float_raise( float_flag_underflow );          End;    End;    if ( roundBits )<> 0 then       set_inexact_flag;    zSig := ( zSig + roundIncrement ) shr 7;    zSig := zSig AND not bits32( bits32( ( roundBits XOR $40 ) = 0 ) and ord(roundNearestEven) );    if ( zSig = 0 ) then zExp := 0;    roundAndPackFloat32 := packFloat32( zSign, zExp, zSig );  End;{*-------------------------------------------------------------------------------Takes an abstract floating-point value having sign `zSign', exponent `zExp',and significand `zSig', and returns the proper single-precision floating-point value corresponding to the abstract input.  This routine is just like`roundAndPackFloat32' except that `zSig' does not have to be normalized.Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''floating-point exponent.-------------------------------------------------------------------------------*}Function normalizeRoundAndPackFloat32( zSign: flag; zExp: int16; zSig:bits32 ): float32;  Var    ShiftCount : int8;  Begin    shiftCount := countLeadingZeros32( zSig ) - 1;    normalizeRoundAndPackFloat32 := roundAndPackFloat32( zSign, zExp - shiftCount, zSig shl shiftCount );  End;{*-------------------------------------------------------------------------------Returns the most-significant 20 fraction bits of the double-precisionfloating-point value `a'.-------------------------------------------------------------------------------*}Function extractFloat64Frac0(a: float64): bits32; inline;  Begin    extractFloat64Frac0 := a.high and $000FFFFF;  End;{*-------------------------------------------------------------------------------Returns the least-significant 32 fraction bits of the double-precisionfloating-point value `a'.-------------------------------------------------------------------------------*}Function extractFloat64Frac1(a: float64): bits32; inline;  Begin    extractFloat64Frac1 := a.low;  End;{$define FPC_SYSTEM_HAS_extractFloat64Frac}Function extractFloat64Frac(a: float64): bits64; inline;  Begin    extractFloat64Frac := bits64(a) and $000FFFFFFFFFFFFF;  End;{*-------------------------------------------------------------------------------Returns the exponent bits of the double-precision floating-point value `a'.-------------------------------------------------------------------------------*}Function extractFloat64Exp(a: float64): int16; inline; Begin    extractFloat64Exp:= ( a.high shr 20 ) AND $7FF; End;{*-------------------------------------------------------------------------------Returns the sign bit of the double-precision floating-point value `a'.-------------------------------------------------------------------------------*}Function extractFloat64Sign(a: float64) : flag; inline; Begin    extractFloat64Sign := a.high shr 31; End;{*-------------------------------------------------------------------------------Normalizes the subnormal double-precision floating-point value representedby the denormalized significand formed by the concatenation of `aSig0' and`aSig1'.  The normalized exponent is stored at the location pointed to by`zExpPtr'.  The most significant 21 bits of the normalized significand arestored at the location pointed to by `zSig0Ptr', and the least significant32 bits of the normalized significand are stored at the location pointed toby `zSig1Ptr'.-------------------------------------------------------------------------------*}Procedure normalizeFloat64Subnormal(     aSig0: bits32;     aSig1: bits32;     VAR zExpPtr : Int16;     VAR zSig0Ptr : Bits32;     VAR zSig1Ptr : Bits32 ); Var  ShiftCount : Int8; Begin    if ( aSig0 = 0 ) then      Begin        shiftCount := countLeadingZeros32( aSig1 ) - 11;        if ( shiftCount < 0 ) then          Begin            zSig0Ptr := aSig1 shr ( - shiftCount );            zSig1Ptr := aSig1 shl ( shiftCount AND 31 );          End        else           Begin            zSig0Ptr := aSig1 shl shiftCount;            zSig1Ptr := 0;           End;        zExpPtr := - shiftCount - 31;      End    else      Begin        shiftCount := countLeadingZeros32( aSig0 ) - 11;        shortShift64Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );        zExpPtr := 1 - shiftCount;      End;  End;procedure normalizeFloat64Subnormal(aSig : bits64;var zExpPtr : int16; var zSigPtr : bits64);var  shiftCount : int8;begin    shiftCount := countLeadingZeros64( aSig ) - 11;    zSigPtr := aSig shl shiftCount;    zExpPtr := 1 - shiftCount;end;{*-------------------------------------------------------------------------------Packs the sign `zSign', the exponent `zExp', and the significand formed bythe concatenation of `zSig0' and `zSig1' into a double-precision floating-point value, returning the result.  After being shifted into the properpositions, the three fields `zSign', `zExp', and `zSig0' are simply addedtogether to form the most significant 32 bits of the result.  This meansthat any integer portion of `zSig0' will be added into the exponent.  Sincea properly normalized significand will have an integer portion equal to 1,the `zExp' input should be 1 less than the desired result exponent whenever`zSig0' and `zSig1' concatenated form a complete, normalized significand.-------------------------------------------------------------------------------*}Procedure packFloat64( zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1 : Bits32; VAR c : float64); var    z: Float64; Begin    z.low := zSig1;    z.high := ( ( bits32 (zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 20 ) + zSig0;    c := z; End;{*----------------------------------------------------------------------------| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a| double-precision floating-point value, returning the result.  After being| shifted into the proper positions, the three fields are simply added| together to form the result.  This means that any integer portion of `zSig'| will be added into the exponent.  Since a properly normalized significand| will have an integer portion equal to 1, the `zExp' input should be 1 less| than the desired result exponent whenever `zSig' is a complete, normalized| significand.*----------------------------------------------------------------------------*}function packFloat64( zSign: flag; zExp: int16; zSig : bits64): float64;inline;begin    result := float64(( ( bits64(zSign) ) shl 63 ) + ( ( bits64(zExp) ) shl 52 ) + zSig);end;{*-------------------------------------------------------------------------------Takes an abstract floating-point value having sign `zSign', exponent `zExp',and extended significand formed by the concatenation of `zSig0', `zSig1',and `zSig2', and returns the proper double-precision floating-point valuecorresponding to the abstract input.  Ordinarily, the abstract value issimply rounded and packed into the double-precision format, with the inexactexception raised if the abstract input cannot be represented exactly.However, if the abstract value is too large, the overflow and inexactexceptions are raised and an infinity or maximal finite value is returned.If the abstract value is too small, the input value is rounded to asubnormal number, and the underflow and inexact exceptions are raised if theabstract input cannot be represented exactly as a subnormal double-precisionfloating-point number.    The input significand must be normalized or smaller.  If the inputsignificand is not normalized, `zExp' must be 0; in that case, the resultreturned is a subnormal number, and it must not require rounding.  In theusual case that the input significand is normalized, `zExp' must be 1 lessthan the ``true'' floating-point exponent.  The handling of underflow andoverflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Procedure roundAndPackFloat64(     zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1: Bits32; zSig2: Bits32; Var c: Float64 ); Var   roundingMode : TFPURoundingMode;   roundNearestEven, increment, isTiny : Flag; Begin    roundingMode := softfloat_rounding_mode;    roundNearestEven := flag( roundingMode = float_round_nearest_even );    increment := flag( sbits32 (zSig2) < 0 );    if ( roundNearestEven  = flag(FALSE) ) then      Begin        if ( roundingMode = float_round_to_zero ) then            increment := 0        else          Begin            if ( zSign )<> 0 then              Begin                increment := flag(( roundingMode = float_round_down ) and (zSig2<>0));              End            else              Begin                increment := flag(( roundingMode = float_round_up ) and (zSig2<>0));              End          End      End;    if ( $7FD <= bits16 (zExp) ) then      Begin        if (( $7FD < zExp )             or (( zExp = $7FD )                   and (zSig0=$001FFFFF) and (zSig1=$FFFFFFFF)                   and (increment<>0)                )           ) then           Begin            float_raise( [float_flag_overflow,float_flag_inexact] );            if (( roundingMode = float_round_to_zero )                 or ( (zSign<>0) and ( roundingMode = float_round_up ) )                 or ( (zSign = 0) and ( roundingMode = float_round_down ) )               ) then              Begin                packFloat64( zSign, $7FE, $000FFFFF, $FFFFFFFF, c );                exit;              End;            packFloat64( zSign, $7FF, 0, 0, c );            exit;           End;        if ( zExp < 0 ) then           Begin            isTiny :=                   flag( softfloat_detect_tininess = float_tininess_before_rounding )                or flag( zExp < -1 )                or  flag(increment = 0)                or flag(lt64( zSig0, zSig1, $001FFFFF, $FFFFFFFF)<>0);            shift64ExtraRightJamming(                zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );            zExp := 0;            if ( isTiny<>0) and (zSig2<>0 ) then float_raise( float_flag_underflow );            if ( roundNearestEven )<>0 then              Begin                increment := flag( sbits32 (zSig2) < 0 );              End            else              Begin                if ( zSign )<>0 then                  Begin                    increment := flag(( roundingMode = float_round_down ) and (zSig2<>0));                  End                else                  Begin                    increment := flag(( roundingMode = float_round_up ) and (zSig2<>0));                  End              End;        End;    End;    if ( zSig2 )<>0 then       set_inexact_flag;    if ( increment )<>0 then      Begin        add64( zSig0, zSig1, 0, 1, zSig0, zSig1 );        zSig1 := zSig1 and not ( bits32(flag( zSig2 + zSig2 = 0 )) and roundNearestEven );      End    else      Begin        if ( ( zSig0 or zSig1 ) = 0 ) then zExp := 0;      End;    packFloat64( zSign, zExp, zSig0, zSig1, c ); End;{*----------------------------------------------------------------------------| Takes an abstract floating-point value having sign `zSign', exponent `zExp',| and significand `zSig', and returns the proper double-precision floating-| point value corresponding to the abstract input.  Ordinarily, the abstract| value is simply rounded and packed into the double-precision format, with| the inexact exception raised if the abstract input cannot be represented| exactly.  However, if the abstract value is too large, the overflow and| inexact exceptions are raised and an infinity or maximal finite value is| returned.  If the abstract value is too small, the input value is rounded| to a subnormal number, and the underflow and inexact exceptions are raised| if the abstract input cannot be represented exactly as a subnormal double-| precision floating-point number.|     The input significand `zSig' has its binary point between bits 62| and 61, which is 10 bits to the left of the usual location.  This shifted| significand must be normalized or smaller.  If `zSig' is not normalized,| `zExp' must be 0; in that case, the result returned is a subnormal number,| and it must not require rounding.  In the usual case that `zSig' is| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.| The handling of underflow and overflow follows the IEC/IEEE Standard for| Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function roundAndPackFloat64( zSign: flag; zExp: int16; zSig : bits64): float64;var    roundingMode: TFPURoundingMode;    roundNearestEven: flag;    roundIncrement, roundBits: int16;    isTiny: flag;begin    roundingMode := softfloat_rounding_mode;    roundNearestEven := ord( roundingMode = float_round_nearest_even );    roundIncrement := $200;    if ( roundNearestEven=0 ) then    begin        if ( roundingMode = float_round_to_zero ) then        begin            roundIncrement := 0;        end        else begin            roundIncrement := $3FF;            if ( zSign<>0 ) then            begin                if ( roundingMode = float_round_up ) then                  roundIncrement := 0;            end            else begin                if ( roundingMode = float_round_down ) then                  roundIncrement := 0;            end        end    end;    roundBits := zSig and $3FF;    if ( $7FD <= bits16(zExp) ) then    begin        if (    ( $7FD < zExp )             or (    ( zExp = $7FD )                  and ( sbits64( zSig + roundIncrement ) < 0 ) )           ) then           begin            float_raise( [float_flag_overflow,float_flag_inexact] );            result := float64(qword(packFloat64( zSign, $7FF, 0 )) - ord( roundIncrement = 0 ));            exit;        end;        if ( zExp < 0 ) then        begin            isTiny := ord(                   ( softfloat_detect_tininess = float_tininess_before_rounding )                or ( zExp < -1 )                or ( (zSig + roundIncrement) < bits64( $8000000000000000 ) ) );            shift64RightJamming( zSig, - zExp, zSig );            zExp := 0;            roundBits := zSig and $3FF;            if ( isTiny and roundBits )<>0 then              float_raise( float_flag_underflow );        end    end;    if ( roundBits<>0 ) then      set_inexact_flag;    zSig := ( zSig + roundIncrement ) shr 10;    zSig := zSig and not(qword(ord( ( roundBits xor $200 ) = 0 ) and roundNearestEven ));    if ( zSig = 0 ) then      zExp := 0;    result:=packFloat64( zSign, zExp, zSig );end;{*-------------------------------------------------------------------------------Takes an abstract floating-point value having sign `zSign', exponent `zExp',and significand formed by the concatenation of `zSig0' and `zSig1', andreturns the proper double-precision floating-point value correspondingto the abstract input.  This routine is just like `roundAndPackFloat64'except that the input significand has fewer bits and does not have to benormalized.  In all cases, `zExp' must be 1 less than the ``true'' floating-point exponent.-------------------------------------------------------------------------------*}Procedure normalizeRoundAndPackFloat64(     zSign:flag; zExp:int16; zSig0:bits32; zSig1:bits32; VAR c: float64 ); Var   shiftCount : int8;   zSig2 : bits32; Begin    if ( zSig0 = 0 ) then     Begin        zSig0 := zSig1;        zSig1 := 0;        zExp := zExp -32;     End;    shiftCount := countLeadingZeros32( zSig0 ) - 11;    if ( 0 <= shiftCount ) then      Begin        zSig2 := 0;        shortShift64Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );      End    else      Begin        shift64ExtraRightJamming          (zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );      End;    zExp := zExp - shiftCount;    roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, c );  End;{*----------------------------------------------------------------------------Takes an abstract floating-point value having sign `zSign', exponent `zExp',and significand `zSig', and returns the proper double-precision floating-point value corresponding to the abstract input.  This routine is just like`roundAndPackFloat64' except that `zSig' does not have to be normalized.Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''floating-point exponent.----------------------------------------------------------------------------*}function normalizeRoundAndPackFloat64(zSign: flag; zExp: int16; zSig: bits64): float64;  var    shiftCount: int8;  begin    shiftCount := countLeadingZeros64( zSig ) - 1;    result := roundAndPackFloat64( zSign, zExp - shiftCount, zSig shl shiftCount);  end;{*-------------------------------------------------------------------------------Returns the result of converting the 32-bit two's complement integer `a' tothe single-precision floating-point format.  The conversion is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function int32_to_float32( a: int32): float32rec; compilerproc; Var  zSign : Flag; Begin    if ( a = 0 ) then      Begin       int32_to_float32.float32 := 0;       exit;      End;    if ( a = sbits32 ($80000000) ) then      Begin       int32_to_float32.float32 := packFloat32( 1, $9E, 0 );       exit;      end;    zSign := flag( a < 0 );    If zSign<>0 then      a := -a;    int32_to_float32.float32:=      normalizeRoundAndPackFloat32( zSign, $9C, a ); End;{*-------------------------------------------------------------------------------Returns the result of converting the 32-bit two's complement integer `a' tothe double-precision floating-point format.  The conversion is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function int32_to_float64( a: int32) : float64;{$ifdef fpc} [public,Alias:'INT32_TO_FLOAT64'];compilerproc;{$endif}  var    zSign : flag;    absA : bits32;    shiftCount : int8;    zSig0, zSig1 : bits32;  Begin    if ( a = 0 ) then      Begin       packFloat64( 0, 0, 0, 0, result );       exit;      end;    zSign := flag( a < 0 );    if ZSign<>0 then      AbsA := -a    else      AbsA := a;    shiftCount := countLeadingZeros32( absA ) - 11;    if ( 0 <= shiftCount ) then      Begin        zSig0 := absA shl shiftCount;        zSig1 := 0;      End    else      Begin        shift64Right( absA, 0, - shiftCount, zSig0, zSig1 );      End;    packFloat64( zSign, $412 - shiftCount, zSig0, zSig1, result );  End;{$ifdef FPC_SOFTFLOAT_FLOATX80}{$if not defined(packFloatx80)}function packFloatx80( zSign: flag; zExp: int32; zSig : bits64): floatx80;forward;{$endif}{*----------------------------------------------------------------------------| Returns the result of converting the 32-bit two's complement integer `a'| to the extended double-precision floating-point format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*}function int32_to_floatx80( a: int32 ): floatx80;var    zSign: flag;    absA: uint32;    shiftCount: int8;    zSig: bits64;begin    if ( a = 0 ) then begin        result := packFloatx80( 0, 0, 0 );        exit;    end;    zSign := ord( a < 0 );    if zSign <> 0 then absA := - a else absA := a;    shiftCount := countLeadingZeros32( absA ) + 32;    zSig := absA;    result := packFloatx80( zSign, $403E - shiftCount, zSig shl shiftCount );end;{$endif FPC_SOFTFLOAT_FLOATX80}{$ifdef FPC_SOFTFLOAT_FLOAT128}{$if not defined(packFloat128)}function packFloat128( zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64 ) : float128;forward;{$endif}{*----------------------------------------------------------------------------| Returns the result of converting the 32-bit two's complement integer `a' to| the quadruple-precision floating-point format.  The conversion is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function int32_to_float128( a: int32 ): float128;var    zSign: flag;    absA: uint32;    shiftCount: int8;    zSig0: bits64;begin    if ( a = 0 ) then begin        result := packFloat128( 0, 0, 0, 0 );        exit;    end;    zSign := ord( a < 0 );    if zSign <> 0 then absA := - a else absA := a;    shiftCount := countLeadingZeros32( absA ) + 17;    zSig0 := absA;    result := packFloat128( zSign, $402E - shiftCount, zSig0 shl shiftCount, 0 );end;{$endif FPC_SOFTFLOAT_FLOAT128}{*-------------------------------------------------------------------------------Returns the result of converting the single-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic---which means in particular that the conversion is roundedaccording to the current rounding mode.  If `a' is a NaN, the largestpositive integer is returned.  Otherwise, if the conversion overflows, thelargest integer with the same sign as `a' is returned.-------------------------------------------------------------------------------*}Function float32_to_int32( a : float32rec) : int32;compilerproc;  Var    aSign: flag;    aExp, shiftCount: int16;    aSig, aSigExtra: bits32;    z: int32;    roundingMode: TFPURoundingMode;  Begin    aSig := extractFloat32Frac( a.float32 );    aExp := extractFloat32Exp( a.float32 );    aSign := extractFloat32Sign( a.float32 );    shiftCount := aExp - $96;    if ( 0 <= shiftCount ) then      Begin        if ( $9E <= aExp ) then          Begin            if ( a.float32 <> $CF000000 ) then              Begin                float_raise( float_flag_invalid );                if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then                  Begin                    float32_to_int32 := $7FFFFFFF;                    exit;                  End;              End;            float32_to_int32 := sbits32 ($80000000);            exit;          End;        z := ( aSig or $00800000 ) shl shiftCount;        if ( aSign<>0 ) then z := - z;      End    else      Begin        if ( aExp < $7E ) then          Begin            aSigExtra := aExp OR aSig;            z := 0;          End        else         Begin            aSig := aSig OR $00800000;            aSigExtra := aSig shl ( shiftCount and 31 );            z := aSig shr ( - shiftCount );         End;        if ( aSigExtra<>0 ) then          set_inexact_flag;        roundingMode := softfloat_rounding_mode;        if ( roundingMode = float_round_nearest_even ) then          Begin            if ( sbits32 (aSigExtra) < 0 ) then              Begin                Inc(z);                if ( bits32 ( aSigExtra shl 1 ) = 0 ) then                  z := z and not 1;              End;              if ( aSign<>0 ) then                z := - z;          End        else          Begin            aSigExtra := flag( aSigExtra <> 0 );            if ( aSign<>0 ) then             Begin                z := z + (flag( roundingMode = float_round_down ) and aSigExtra);                z := - z;             End            else             Begin                z := z + (flag( roundingMode = float_round_up ) and aSigExtra);             End          End;      End;   float32_to_int32 := z;  End;{*-------------------------------------------------------------------------------Returns the result of converting the single-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic, except that the conversion is always rounded toward zero.If `a' is a NaN, the largest positive integer is returned.  Otherwise, ifthe conversion overflows, the largest integer with the same sign as `a' isreturned.-------------------------------------------------------------------------------*}Function float32_to_int32_round_to_zero( a: Float32rec ): int32;compilerproc; Var    aSign : flag;    aExp, shiftCount : int16;    aSig : bits32;    z : int32; Begin    aSig := extractFloat32Frac( a.float32 );    aExp := extractFloat32Exp( a.float32 );    aSign := extractFloat32Sign( a.float32 );    shiftCount := aExp - $9E;    if ( 0 <= shiftCount ) then      Begin        if ( a.float32 <> $CF000000 ) then          Begin            float_raise( float_flag_invalid );            if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then              Begin                float32_to_int32_round_to_zero := $7FFFFFFF;                exit;              end;          End;        float32_to_int32_round_to_zero:= sbits32 ($80000000);        exit;      End    else      if ( aExp <= $7E ) then      Begin        if ( aExp or aSig )<>0 then           set_inexact_flag;        float32_to_int32_round_to_zero := 0;        exit;      End;    aSig := ( aSig or $00800000 ) shl 8;    z := aSig shr ( - shiftCount );    if ( bits32 ( aSig shl ( shiftCount and 31 ) )<> 0 ) then      Begin        set_inexact_flag;      End;    if ( aSign<>0 ) then z := - z;    float32_to_int32_round_to_zero := z; End;{*----------------------------------------------------------------------------| Returns the result of converting the single-precision floating-point value| `a' to the 64-bit two's complement integer format.  The conversion is| performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic---which means in particular that the conversion is rounded| according to the current rounding mode.  If `a' is a NaN, the largest| positive integer is returned.  Otherwise, if the conversion overflows, the| largest integer with the same sign as `a' is returned.*----------------------------------------------------------------------------*}function float32_to_int64( a: float32 ): int64;var    aSign: flag;    aExp, shiftCount: int16;    aSig: bits32;    aSig64, aSigExtra: bits64;begin    aSig := extractFloat32Frac( a );    aExp := extractFloat32Exp( a );    aSign := extractFloat32Sign( a );    shiftCount := $BE - aExp;    if ( shiftCount < 0 ) then begin        float_raise( float_flag_invalid );        if ( aSign = 0 ) or ( ( aExp = $FF ) and ( aSig <> 0 ) ) then begin            result := $7FFFFFFFFFFFFFFF;            exit;        end;        result := $8000000000000000;        exit;    end;    if ( aExp <> 0 ) then aSig := aSig or $00800000;    aSig64 := aSig;    aSig64 := aSig64 shl 40;    shift64ExtraRightJamming( aSig64, 0, shiftCount, aSig64, aSigExtra );    result := roundAndPackInt64( aSign, aSig64, aSigExtra );end;{*----------------------------------------------------------------------------| Returns the result of converting the single-precision floating-point value| `a' to the 64-bit two's complement integer format.  The conversion is| performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic, except that the conversion is always rounded toward zero.  If| `a' is a NaN, the largest positive integer is returned.  Otherwise, if the| conversion overflows, the largest integer with the same sign as `a' is| returned.*----------------------------------------------------------------------------*}function float32_to_int64_round_to_zero( a: float32 ): int64;var    aSign: flag;    aExp, shiftCount: int16;    aSig: bits32;    aSig64: bits64;    z: int64;begin    aSig := extractFloat32Frac( a );    aExp := extractFloat32Exp( a );    aSign := extractFloat32Sign( a );    shiftCount := aExp - $BE;    if ( 0 <= shiftCount ) then begin        if ( a <> $DF000000 ) then begin            float_raise( float_flag_invalid );            if ( aSign = 0) or ( ( aExp = $FF ) and ( aSig <> 0 ) ) then begin                result := $7FFFFFFFFFFFFFFF;                exit;            end;        end;        result := $8000000000000000;        exit;    end    else if ( aExp <= $7E ) then begin        if ( aExp or aSig <> 0 ) then set_inexact_flag;        result := 0;        exit;    end;    aSig64 := aSig or $00800000;    aSig64 := aSig64 shl 40;    z := aSig64 shr ( - shiftCount );    if bits64( aSig64 shl ( shiftCount and 63 ) ) <> 0 then        set_inexact_flag;    if ( aSign <> 0 ) then z := - z;    result := z;end;{*-------------------------------------------------------------------------------Returns the result of converting the single-precision floating-point value`a' to the double-precision floating-point format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic.-------------------------------------------------------------------------------*}Function float32_to_float64( a : float32rec) : Float64;compilerproc;  Var    aSign : flag;    aExp : int16;    aSig, zSig0, zSig1: bits32;    tmp : CommonNanT;  Begin    aSig := extractFloat32Frac( a.float32 );    aExp := extractFloat32Exp( a.float32 );    aSign := extractFloat32Sign( a.float32 );    if ( aExp = $FF ) then      Begin        if ( aSig<>0 ) then          Begin            tmp:=float32ToCommonNaN(a.float32);            result:=commonNaNToFloat64(tmp);            exit;          End;          packFloat64( aSign, $7FF, 0, 0, result);          exit;      End;    if ( aExp = 0 ) then      Begin        if ( aSig = 0 ) then          Begin            packFloat64( aSign, 0, 0, 0, result );            exit;          end;        normalizeFloat32Subnormal( aSig, aExp, aSig );        Dec(aExp);      End;    shift64Right( aSig, 0, 3, zSig0, zSig1 );    packFloat64( aSign, aExp + $380, zSig0, zSig1, result );  End;{$ifdef FPC_SOFTFLOAT_FLOATX80}{*----------------------------------------------------------------------------| Returns the result of converting the canonical NaN `a' to the extended| double-precision floating-point format.*----------------------------------------------------------------------------*}function commonNaNToFloatx80( a : commonNaNT ) : floatx80;var    z : floatx80;begin    z.low := bits64( $C000000000000000 ) or ( a.high shr 1 );    z.high := ( bits16( a.sign ) shl 15 ) or $7FFF;    result := z;end;{*----------------------------------------------------------------------------| Returns the result of converting the single-precision floating-point value| `a' to the extended double-precision floating-point format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*}function float32_to_floatx80( a: float32 ): floatx80;var    aSign: flag;    aExp: int16;    aSig: bits32;    tmp: commonNaNT;begin    aSig := extractFloat32Frac( a );    aExp := extractFloat32Exp( a );    aSign := extractFloat32Sign( a );    if ( aExp = $FF ) then begin        if ( aSig <> 0 ) then begin            tmp:=float32ToCommonNaN(a);            result := commonNaNToFloatx80( tmp );            exit;        end;        result := packFloatx80( aSign, $7FFF, bits64( $8000000000000000 ) );        exit;    end;    if ( aExp = 0 ) then begin        if ( aSig = 0 ) then begin            result := packFloatx80( aSign, 0, 0 );            exit;        end;        normalizeFloat32Subnormal( aSig, aExp, aSig );    end;    aSig := aSig or $00800000;    result := packFloatx80( aSign, aExp + $3F80, bits64(aSig) shl 40 );end;{$endif FPC_SOFTFLOAT_FLOATX80}{$ifdef FPC_SOFTFLOAT_FLOAT128}{*----------------------------------------------------------------------------| Returns the result of converting the single-precision floating-point value| `a' to the double-precision floating-point format.  The conversion is| performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*}function float32_to_float128( a: float32 ): float128;var    aSign: flag;    aExp: int16;    aSig: bits32;    tmp: commonNaNT;begin    aSig := extractFloat32Frac( a );    aExp := extractFloat32Exp( a );    aSign := extractFloat32Sign( a );    if ( aExp = $FF ) then begin        if ( aSig <> 0 ) then begin            tmp:=float32ToCommonNaN(a);            result := commonNaNToFloat128( tmp );            exit;        end;        result := packFloat128( aSign, $7FFF, 0, 0 );        exit;    end;    if ( aExp = 0 ) then begin        if ( aSig = 0 ) then begin            result := packFloat128( aSign, 0, 0, 0 );            exit;        end;        normalizeFloat32Subnormal( aSig, aExp, aSig );        dec( aExp );    end;    result := packFloat128( aSign, aExp + $3F80, bits64( aSig ) shl 25, 0 );end;{$endif FPC_SOFTFLOAT_FLOAT128}{*-------------------------------------------------------------------------------Rounds the single-precision floating-point value `a' to an integer,and returns the result as a single-precision floating-point value.  Theoperation is performed according to the IEC/IEEE Standard for BinaryFloating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_round_to_int( a: float32rec): float32rec;compilerproc;  Var    aSign: flag;    aExp: int16;    lastBitMask, roundBitsMask: bits32;    roundingMode: TFPURoundingMode;    z: float32;  Begin    aExp := extractFloat32Exp( a.float32 );    if ( $96 <= aExp ) then     Begin        if ( ( aExp = $FF ) and (extractFloat32Frac( a.float32 )<>0) ) then          Begin            float32_round_to_int.float32 := propagateFloat32NaN( a.float32, a.float32 );            exit;          End;        float32_round_to_int:=a;        exit;     End;    if ( aExp <= $7E ) then      Begin        if ( bits32 ( a.float32 shl 1 ) = 0 ) then          Begin             float32_round_to_int:=a;             exit;          end;        set_inexact_flag;        aSign := extractFloat32Sign( a.float32 );        case ( softfloat_rounding_mode ) of         float_round_nearest_even:            Begin              if ( ( aExp = $7E ) and (extractFloat32Frac( a.float32 )<>0) ) then                Begin                  float32_round_to_int.float32 := packFloat32( aSign, $7F, 0 );                  exit;                End;            End;         float_round_down:            Begin              if aSign <> 0 then                 float32_round_to_int.float32 := $BF800000              else                 float32_round_to_int.float32 := 0;              exit;            End;         float_round_up:            Begin              if aSign <> 0 then                 float32_round_to_int.float32 := $80000000              else                 float32_round_to_int.float32 := $3F800000;              exit;            End;        end;        float32_round_to_int.float32 := packFloat32( aSign, 0, 0 );        exit;      End;    lastBitMask := 1;    {_____________________________!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}    lastBitMask := lastBitMask shl ($96 - aExp);    roundBitsMask := lastBitMask - 1;    z := a.float32;    roundingMode := softfloat_rounding_mode;    if ( roundingMode = float_round_nearest_even ) then      Begin        z := z + (lastBitMask shr 1);        if ( ( z and roundBitsMask ) = 0 ) then           z := z and not lastBitMask;      End    else if ( roundingMode <> float_round_to_zero ) then      Begin        if ( (extractFloat32Sign( z ) xor flag(roundingMode = float_round_up ))<>0 ) then          Begin            z := z + roundBitsMask;          End;      End;    z := z and not roundBitsMask;    if ( z <> a.float32 ) then      set_inexact_flag;    float32_round_to_int.float32 := z;  End;{*-------------------------------------------------------------------------------Returns the result of adding the absolute values of the single-precisionfloating-point values `a' and `b'.  If `zSign' is 1, the sum is negatedbefore being returned.  `zSign' is ignored if the result is a NaN.The addition is performed according to the IEC/IEEE Standard for BinaryFloating-Point Arithmetic.-------------------------------------------------------------------------------*}Function addFloat32Sigs( a:float32; b: float32; zSign:flag ): float32;  Var    aExp, bExp, zExp: int16;    aSig, bSig, zSig: bits32;    expDiff: int16;    label roundAndPack;  Begin    aSig:=extractFloat32Frac( a );    aExp:=extractFloat32Exp( a );    bSig:=extractFloat32Frac( b );    bExp := extractFloat32Exp( b );    expDiff := aExp - bExp;    aSig := aSig shl 6;    bSig := bSig shl 6;    if ( 0 < expDiff ) then    Begin        if ( aExp = $FF ) then          Begin            if ( aSig <> 0) then              Begin                addFloat32Sigs := propagateFloat32NaN( a, b );                exit;              End;            addFloat32Sigs := a;            exit;          End;        if ( bExp = 0 ) then          Begin             Dec(expDiff);          End        else          Begin            bSig := bSig or $20000000;          End;        shift32RightJamming( bSig, expDiff, bSig );        zExp := aExp;    End    else    If ( expDiff < 0 ) then      Begin        if ( bExp = $FF ) then        Begin            if ( bSig<>0 ) then              Begin                addFloat32Sigs := propagateFloat32NaN( a, b );                exit;              end;            addFloat32Sigs := packFloat32( zSign, $FF, 0 );            exit;        End;        if ( aExp = 0 ) then          Begin            Inc(expDiff);          End        else          Begin            aSig := aSig OR $20000000;          End;        shift32RightJamming( aSig, - expDiff, aSig );        zExp := bExp;    End    else    Begin        if ( aExp = $FF ) then        Begin            if ( aSig OR  bSig )<> 0 then              Begin                addFloat32Sigs := propagateFloat32NaN( a, b );                exit;              end;            addFloat32Sigs := a;            exit;        End;        if ( aExp = 0 ) then          Begin             addFloat32Sigs := packFloat32( zSign, 0, ( aSig + bSig ) shr 6 );             exit;          end;        zSig := $40000000 + aSig + bSig;        zExp := aExp;        goto roundAndPack;    End;    aSig := aSig OR $20000000;    zSig := ( aSig + bSig ) shl 1;    Dec(zExp);    if ( sbits32 (zSig) < 0 ) then      Begin        zSig := aSig + bSig;        Inc(zExp);      End; roundAndPack:    addFloat32Sigs := roundAndPackFloat32( zSign, zExp, zSig ); End;{*-------------------------------------------------------------------------------Returns the result of subtracting the absolute values of the single-precision floating-point values `a' and `b'.  If `zSign' is 1, thedifference is negated before being returned.  `zSign' is ignored if theresult is a NaN.  The subtraction is performed according to the IEC/IEEEStandard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function subFloat32Sigs( a:float32; b:float32; zSign:flag ): float32;  Var    aExp, bExp, zExp: int16;    aSig, bSig, zSig: bits32;    expDiff : int16;    label aExpBigger;    label bExpBigger;    label aBigger;    label bBigger;    label normalizeRoundAndPack;  Begin    aSig := extractFloat32Frac( a );    aExp := extractFloat32Exp( a );    bSig := extractFloat32Frac( b );    bExp := extractFloat32Exp( b );    expDiff := aExp - bExp;    aSig := aSig shl 7;    bSig := bSig shl 7;    if ( 0 < expDiff ) then goto aExpBigger;    if ( expDiff < 0 ) then goto bExpBigger;    if ( aExp = $FF ) then    Begin        if ( aSig OR  bSig )<> 0 then          Begin           subFloat32Sigs := propagateFloat32NaN( a, b );           exit;          End;        float_raise( float_flag_invalid );        subFloat32Sigs := float32_default_nan;        exit;    End;    if ( aExp = 0 ) then    Begin        aExp := 1;        bExp := 1;    End;    if ( bSig < aSig ) Then goto aBigger;    if ( aSig < bSig ) Then goto bBigger;    subFloat32Sigs := packFloat32( flag(softfloat_rounding_mode = float_round_down), 0, 0 );    exit; bExpBigger:    if ( bExp = $FF ) then    Begin        if ( bSig<>0 ) then        Begin          subFloat32Sigs := propagateFloat32NaN( a, b );          exit;        End;        subFloat32Sigs := packFloat32( zSign XOR 1, $FF, 0 );        exit;    End;    if ( aExp = 0 ) then      Begin        Inc(expDiff);      End    else      Begin        aSig := aSig OR $40000000;      End;    shift32RightJamming( aSig, - expDiff, aSig );    bSig := bSig OR $40000000; bBigger:    zSig := bSig - aSig;    zExp := bExp;    zSign := zSign xor 1;    goto normalizeRoundAndPack; aExpBigger:    if ( aExp = $FF ) then      Begin        if ( aSig <> 0) then          Begin            subFloat32Sigs := propagateFloat32NaN( a, b );            exit;          End;        subFloat32Sigs := a;        exit;      End;    if ( bExp = 0 ) then      Begin        Dec(expDiff);      End    else      Begin        bSig := bSig OR $40000000;      End;    shift32RightJamming( bSig, expDiff, bSig );    aSig := aSig OR $40000000; aBigger:    zSig := aSig - bSig;    zExp := aExp; normalizeRoundAndPack:    Dec(zExp);    subFloat32Sigs := normalizeRoundAndPackFloat32( zSign, zExp, zSig );  End;{*-------------------------------------------------------------------------------Returns the result of adding the single-precision floating-point values `a'and `b'.  The operation is performed according to the IEC/IEEE Standard forBinary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_add( a: float32rec; b:float32rec ): float32rec; compilerproc;  Var    aSign, bSign: Flag;  Begin    aSign := extractFloat32Sign( a.float32 );    bSign := extractFloat32Sign( b.float32 );    if ( aSign = bSign ) then      Begin        float32_add.float32 := addFloat32Sigs( a.float32, b.float32, aSign );      End    else      Begin        float32_add.float32 := subFloat32Sigs( a.float32, b.float32, aSign );      End;  End;{*-------------------------------------------------------------------------------Returns the result of subtracting the single-precision floating-point values`a' and `b'.  The operation is performed according to the IEC/IEEE Standardfor Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_sub( a: float32rec ; b:float32rec ): float32rec;compilerproc;  Var    aSign, bSign: flag;  Begin    aSign := extractFloat32Sign( a.float32 );    bSign := extractFloat32Sign( b.float32 );    if ( aSign = bSign ) then      Begin        float32_sub.float32 := subFloat32Sigs( a.float32, b.float32, aSign );      End    else      Begin        float32_sub.float32 := addFloat32Sigs( a.float32, b.float32, aSign );      End;  End;{*-------------------------------------------------------------------------------Returns the result of multiplying the single-precision floating-point values`a' and `b'.  The operation is performed according to the IEC/IEEE Standardfor Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc;  Var    aSign, bSign, zSign: flag;    aExp, bExp, zExp : int16;    aSig, bSig, zSig0, zSig1: bits32;  Begin    aSig := extractFloat32Frac( a.float32 );    aExp := extractFloat32Exp( a.float32 );    aSign := extractFloat32Sign( a.float32 );    bSig := extractFloat32Frac( b.float32 );    bExp := extractFloat32Exp( b.float32 );    bSign := extractFloat32Sign( b.float32 );    zSign := aSign xor bSign;    if ( aExp = $FF ) then    Begin        if ( (aSig<>0) OR ( ( bExp = $FF ) AND  (bSig<>0) ) ) then        Begin            float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 );            exit;        End;        if ( ( bits32(bExp) OR  bSig ) = 0 ) then        Begin            float_raise( float_flag_invalid );            float32_mul.float32 := float32_default_nan;            exit;        End;        float32_mul.float32 := packFloat32( zSign, $FF, 0 );        exit;    End;    if ( bExp = $FF ) then    Begin        if ( bSig <> 0 ) then        Begin           float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 );           exit;        End;        if ( ( bits32(aExp) OR  aSig ) = 0 ) then        Begin            float_raise( float_flag_invalid );            float32_mul.float32 := float32_default_nan;            exit;        End;        float32_mul.float32 := packFloat32( zSign, $FF, 0 );        exit;    End;    if ( aExp = 0 ) then    Begin        if ( aSig = 0 ) then        Begin           float32_mul.float32 := packFloat32( zSign, 0, 0 );           exit;        End;        normalizeFloat32Subnormal( aSig, aExp, aSig );    End;    if ( bExp = 0 ) then    Begin        if ( bSig = 0 ) then         Begin           float32_mul.float32 := packFloat32( zSign, 0, 0 );           exit;         End;        normalizeFloat32Subnormal( bSig, bExp, bSig );    End;    zExp := aExp + bExp - $7F;    aSig := ( aSig OR  $00800000 ) shl 7;    bSig := ( bSig OR  $00800000 ) shl 8;    mul32To64( aSig, bSig, zSig0, zSig1 );    zSig0 := zSig0 OR bits32( zSig1 <> 0 );    if ( 0 <= sbits32 ( zSig0 shl 1 ) ) then    Begin        zSig0 := zSig0 shl 1;        Dec(zExp);    End;    float32_mul.float32 := roundAndPackFloat32( zSign, zExp, zSig0 ); End;{*-------------------------------------------------------------------------------Returns the result of dividing the single-precision floating-point value `a'by the corresponding value `b'.  The operation is performed according to theIEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc;  Var    aSign, bSign, zSign: flag;    aExp, bExp, zExp: int16;    aSig, bSig, zSig, rem0, rem1, term0, term1: bits32;  Begin    aSig := extractFloat32Frac( a.float32 );    aExp := extractFloat32Exp( a.float32 );    aSign := extractFloat32Sign( a.float32 );    bSig := extractFloat32Frac( b.float32 );    bExp := extractFloat32Exp( b.float32 );    bSign := extractFloat32Sign( b.float32 );    zSign := aSign xor bSign;    if ( aExp = $FF ) then      Begin        if ( aSig <> 0 ) then        Begin           float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );           exit;        End;        if ( bExp = $FF ) then        Begin            if ( bSig <> 0) then            Begin              float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );              exit;            End;            float_raise( float_flag_invalid );            float32_div.float32 := float32_default_nan;            exit;        End;        float32_div.float32 := packFloat32( zSign, $FF, 0 );        exit;      End;    if ( bExp = $FF ) then    Begin        if ( bSig <> 0) then        Begin          float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );          exit;        End;        float32_div.float32 := packFloat32( zSign, 0, 0 );        exit;    End;    if ( bExp = 0 ) Then    Begin        if ( bSig = 0 ) Then        Begin            if ( ( bits32(aExp) OR  aSig ) = 0 ) then            Begin                float_raise( float_flag_invalid );                float32_div.float32 := float32_default_nan;                exit;            End;            float_raise( float_flag_divbyzero );            float32_div.float32 := packFloat32( zSign, $FF, 0 );            exit;        End;        normalizeFloat32Subnormal( bSig, bExp, bSig );    End;    if ( aExp = 0 ) Then    Begin        if ( aSig = 0 ) Then        Begin          float32_div.float32 := packFloat32( zSign, 0, 0 );          exit;        End;        normalizeFloat32Subnormal( aSig, aExp, aSig );    End;    zExp := aExp - bExp + $7D;    aSig := ( aSig OR  $00800000 ) shl 7;    bSig := ( bSig OR  $00800000 ) shl 8;    if ( bSig <= ( aSig + aSig ) ) then    Begin        aSig := aSig shr 1;        Inc(zExp);    End;    zSig := estimateDiv64To32( aSig, 0, bSig );    if ( ( zSig and $3F ) <= 2 ) then    Begin        mul32To64( bSig, zSig, term0, term1 );        sub64( aSig, 0, term0, term1, rem0, rem1 );        while ( sbits32 (rem0) < 0 ) do        Begin            Dec(zSig);            add64( rem0, rem1, 0, bSig, rem0, rem1 );        End;        zSig := zSig or bits32( rem1 <> 0 );    End;    float32_div.float32 := roundAndPackFloat32( zSign, zExp, zSig );  End;{*-------------------------------------------------------------------------------Returns the remainder of the single-precision floating-point value `a'with respect to the corresponding value `b'.  The operation is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_rem(a: float32rec; b: float32rec ):float32rec; compilerproc;  Var    aSign, zSign: flag;    aExp, bExp, expDiff: int16;    aSig, bSig, q, alternateASig: bits32;    sigMean: sbits32;  Begin    aSig := extractFloat32Frac( a.float32 );    aExp := extractFloat32Exp( a.float32 );    aSign := extractFloat32Sign( a.float32 );    bSig := extractFloat32Frac( b.float32 );    bExp := extractFloat32Exp( b.float32 );    if ( aExp = $FF ) then    Begin        if ( (aSig<>0) OR ( ( bExp = $FF ) AND  (bSig <>0)) ) then        Begin            float32_rem.float32 := propagateFloat32NaN( a.float32, b.float32 );            exit;        End;        float_raise( float_flag_invalid );        float32_rem.float32 := float32_default_nan;        exit;    End;    if ( bExp = $FF ) then    Begin        if ( bSig <> 0 ) then        Begin          float32_rem.float32 := propagateFloat32NaN( a.float32, b.float32 );          exit;        End;        float32_rem := a;        exit;    End;    if ( bExp = 0 ) then    Begin        if ( bSig = 0 ) then        Begin            float_raise( float_flag_invalid );            float32_rem.float32 := float32_default_nan;            exit;        End;        normalizeFloat32Subnormal( bSig, bExp, bSig );    End;    if ( aExp = 0 ) then    Begin        if ( aSig = 0 ) then        Begin           float32_rem := a;           exit;        End;        normalizeFloat32Subnormal( aSig, aExp, aSig );    End;    expDiff := aExp - bExp;    aSig := ( aSig OR  $00800000 ) shl 8;    bSig := ( bSig OR  $00800000 ) shl 8;    if ( expDiff < 0 ) then    Begin        if ( expDiff < -1 ) then        Begin           float32_rem := a;           exit;        End;        aSig := aSig shr 1;    End;    q := bits32( bSig <= aSig );    if ( q <> 0) then       aSig := aSig - bSig;    expDiff := expDiff - 32;    while ( 0 < expDiff ) do    Begin        q := estimateDiv64To32( aSig, 0, bSig );        if (2 < q) then         q := q - 2        else         q := 0;        aSig := - ( ( bSig shr 2 ) * q );        expDiff := expDiff - 30;    End;    expDiff := expDiff + 32;    if ( 0 < expDiff ) then    Begin        q := estimateDiv64To32( aSig, 0, bSig );        if (2 < q) then         q := q - 2        else         q := 0;        q := q shr (32 - expDiff);        bSig := bSig shr 2;        aSig := ( ( aSig shr 1 ) shl ( expDiff - 1 ) ) - bSig * q;    End    else    Begin        aSig := aSig shr 2;        bSig := bSig shr 2;    End;    Repeat        alternateASig := aSig;        Inc(q);        aSig := aSig - bSig;    Until not ( 0 <= sbits32 (aSig) );    sigMean := aSig + alternateASig;    if ( ( sigMean < 0 ) OR ( ( sigMean = 0 ) AND  (( q and 1 )<>0) ) ) then    Begin        aSig := alternateASig;    End;    zSign := flag( sbits32 (aSig) < 0 );    if ( zSign<>0 ) then      aSig := - aSig;    float32_rem.float32 := normalizeRoundAndPackFloat32( aSign xor zSign, bExp, aSig );  End;{*-------------------------------------------------------------------------------Returns the square root of the single-precision floating-point value `a'.The operation is performed according to the IEC/IEEE Standard for BinaryFloating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_sqrt(a: float32rec ): float32rec;compilerproc;Var    aSign : flag;    aExp, zExp : int16;    aSig, zSig, rem0, rem1, term0, term1: bits32;    label roundAndPack;Begin    aSig := extractFloat32Frac( a.float32 );    aExp := extractFloat32Exp( a.float32 );    aSign := extractFloat32Sign( a.float32 );    if ( aExp = $FF ) then    Begin        if ( aSig <> 0) then        Begin           float32_sqrt.float32 := propagateFloat32NaN( a.float32, 0 );           exit;        End;        if ( aSign = 0) then        Begin          float32_sqrt := a;          exit;        End;        float_raise( float_flag_invalid );        float32_sqrt.float32 := float32_default_nan;        exit;    End;    if ( aSign <> 0) then    Begin        if ( ( bits32(aExp) OR  aSig ) = 0 ) then        Begin           float32_sqrt := a;           exit;        End;        float_raise( float_flag_invalid );        float32_sqrt.float32 := float32_default_nan;        exit;    End;    if ( aExp = 0 ) then    Begin        if ( aSig = 0 ) then        Begin           float32_sqrt.float32 := 0;           exit;        End;        normalizeFloat32Subnormal( aSig, aExp, aSig );    End;    zExp := ( ( aExp - $7F ) shr 1 ) + $7E;    aSig := ( aSig OR  $00800000 ) shl 8;    zSig := estimateSqrt32( aExp, aSig ) + 2;    if ( ( zSig and $7F ) <= 5 ) then    Begin        if ( zSig < 2 ) then        Begin            zSig := $7FFFFFFF;            goto roundAndPack;        End        else        Begin            aSig  := aSig shr (aExp and 1);            mul32To64( zSig, zSig, term0, term1 );            sub64( aSig, 0, term0, term1, rem0, rem1 );            while ( sbits32 (rem0) < 0 ) do            Begin                Dec(zSig);                shortShift64Left( 0, zSig, 1, term0, term1 );                term1 := term1 or 1;                add64( rem0, rem1, term0, term1, rem0, rem1 );            End;            zSig := zSig OR bits32( ( rem0 OR  rem1 ) <> 0 );        End;    End;    shift32RightJamming( zSig, 1, zSig ); roundAndPack:    float32_sqrt.float32 := roundAndPackFloat32( 0, zExp, zSig );End;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is equal tothe corresponding value `b', and 0 otherwise.  The comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_eq( a:float32rec; b:float32rec): flag; compilerproc;Begin    if ((( extractFloat32Exp( a.float32 ) = $FF ) AND  (extractFloat32Frac( a.float32 )<>0))         OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND  (extractFloat32Frac( b.float32 )<>0) )       ) then    Begin        if ( (float32_is_signaling_nan( a.float32 )<>0) OR (float32_is_signaling_nan( b.float32 )<>0) ) then        Begin            float_raise( float_flag_invalid );        End;        float32_eq := 0;        exit;    End;    float32_eq := flag( a.float32 = b.float32 ) OR flag( bits32 ( ( a.float32 OR  b.float32 ) shl 1 ) = 0 );End;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is less thanor equal to the corresponding value `b', and 0 otherwise.  The comparisonis performed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic.-------------------------------------------------------------------------------*}Function float32_le( a: float32rec; b : float32rec ):flag;compilerproc;var    aSign, bSign: flag;Begin    if (    ( ( extractFloat32Exp( a.float32 ) = $FF ) AND  (extractFloat32Frac( a.float32 )<>0) )         OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND  (extractFloat32Frac( b.float32 )<>0) )       ) then    Begin        float_raise( float_flag_invalid );        float32_le := 0;        exit;    End;    aSign := extractFloat32Sign( a.float32 );    bSign := extractFloat32Sign( b.float32 );    if ( aSign <> bSign ) then    Begin       float32_le :=  aSign OR flag( bits32 ( ( a.float32 OR  b.float32 ) shl 1 ) = 0 );       exit;    End;    float32_le := flag(flag( a.float32 = b.float32 ) OR flag( aSign xor flag( a.float32 < b.float32 ) ));End;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is less thanthe corresponding value `b', and 0 otherwise.  The comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_lt( a:float32rec ; b : float32rec): flag; compilerproc;var    aSign, bSign: flag;Begin    if (    ( ( extractFloat32Exp( a.float32 ) = $FF ) AND  (extractFloat32Frac( a.float32 ) <>0))         OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND  (extractFloat32Frac( b.float32 ) <>0) )       ) then    Begin        float_raise( float_flag_invalid );        float32_lt :=0;        exit;    End;    aSign := extractFloat32Sign( a.float32 );    bSign := extractFloat32Sign( b.float32 );    if ( aSign <> bSign ) then    Begin       float32_lt := aSign AND  flag( bits32 ( ( a.float32 OR  b.float32 ) shl 1 ) <> 0 );       exit;    End;    float32_lt := flag(flag( a.float32 <> b.float32 ) AND  flag( aSign xor flag( a.float32 < b.float32 ) ));End;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is equal tothe corresponding value `b', and 0 otherwise.  The invalid exception israised if either operand is a NaN.  Otherwise, the comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_eq_signaling( a: float32; b: float32) : flag;Begin    if (    ( ( extractFloat32Exp( a ) = $FF ) AND  (extractFloat32Frac( a ) <> 0))         OR ( ( extractFloat32Exp( b ) = $FF ) AND  (extractFloat32Frac( b ) <> 0))       ) then    Begin        float_raise( float_flag_invalid );        float32_eq_signaling := 0;        exit;    End;    float32_eq_signaling := (flag( a = b ) OR flag( bits32 ( ( a OR  b ) shl 1 ) = 0 ));End;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is less than orequal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do notcause an exception.  Otherwise, the comparison is performed according to theIEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_le_quiet( a: float32 ; b : float32 ): flag;Var    aSign, bSign: flag;Begin    if (    ( ( extractFloat32Exp( a ) = $FF ) AND  (extractFloat32Frac( a )<>0) )         OR ( ( extractFloat32Exp( b ) = $FF ) AND  (extractFloat32Frac( b )<>0) )       ) then    Begin        if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then        Begin            float_raise( float_flag_invalid );        End;        float32_le_quiet := 0;        exit;    End;    aSign := extractFloat32Sign( a );    bSign := extractFloat32Sign( b );    if ( aSign <> bSign ) then    Begin       float32_le_quiet := aSign OR flag( bits32 ( ( a OR  b ) shl 1 ) = 0 );       exit;    End;    float32_le_quiet := flag(flag( a = b ) OR flag( aSign xor flag( a < b ) ));End;{*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is less thanthe corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause anexception.  Otherwise, the comparison is performed according to the IEC/IEEEStandard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float32_lt_quiet( a: float32 ; b: float32 ): flag;Var   aSign, bSign: flag;Begin    if (    ( ( extractFloat32Exp( a ) = $FF ) AND  (extractFloat32Frac( a )<>0) )         OR ( ( extractFloat32Exp( b ) = $FF ) AND  (extractFloat32Frac( b )<>0) )       ) then    Begin        if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then        Begin            float_raise( float_flag_invalid );        End;        float32_lt_quiet := 0;        exit;    End;    aSign := extractFloat32Sign( a );    bSign := extractFloat32Sign( b );    if ( aSign <> bSign ) then    Begin        float32_lt_quiet := aSign AND  flag( bits32 ( ( a OR  b ) shl 1 ) <> 0 );        exit;    End;    float32_lt_quiet := flag(flag( a <> b ) AND  ( aSign xor flag( a < b ) ));End;{*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic---which means in particular that the conversion is roundedaccording to the current rounding mode.  If `a' is a NaN, the largestpositive integer is returned.  Otherwise, if the conversion overflows, thelargest integer with the same sign as `a' is returned.-------------------------------------------------------------------------------*}Function float64_to_int32(a: float64): int32;{$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32'];compilerproc;{$endif}var    aSign: flag;    aExp, shiftCount: int16;    aSig0, aSig1, absZ, aSigExtra: bits32;    z: int32;    roundingMode: TFPURoundingMode;    label invalid;Begin    aSig1 := extractFloat64Frac1( a );    aSig0 := extractFloat64Frac0( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    shiftCount := aExp - $413;    if ( 0 <= shiftCount ) then    Begin        if ( $41E < aExp ) then        Begin            if ( ( aExp = $7FF ) AND  (( aSig0 OR  aSig1 )<>0) ) then               aSign := 0;            goto invalid;        End;        shortShift64Left(            aSig0 OR  $00100000, aSig1, shiftCount, absZ, aSigExtra );        if ( $80000000 < absZ ) then          goto invalid;    End    else    Begin        aSig1 := flag( aSig1 <> 0 );        if ( aExp < $3FE ) then        Begin            aSigExtra := aExp OR  aSig0 OR  aSig1;            absZ := 0;        End        else        Begin            aSig0 := aSig0 OR $00100000;            aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR  aSig1;            absZ := aSig0 shr ( - shiftCount );        End;    End;    roundingMode := softfloat_rounding_mode;    if ( roundingMode = float_round_nearest_even ) then    Begin        if ( sbits32(aSigExtra) < 0 ) then        Begin            Inc(absZ);            if ( bits32 ( aSigExtra shl 1 ) = 0 ) then               absZ :=  absZ and not 1;        End;        if aSign <> 0 then          z := - absZ        else          z := absZ;    End    else    Begin        aSigExtra := bits32( aSigExtra <> 0 );        if ( aSign <> 0) then        Begin            z := - (   absZ                    + ( int32( roundingMode = float_round_down ) and aSigExtra ) );        End        else        Begin            z := absZ + ( int32( roundingMode = float_round_up ) and aSigExtra );        End    End;    if ( (( aSign xor flag( z < 0 ) )<>0) AND  (z<>0) ) then    Begin invalid:        float_raise( float_flag_invalid );        if (aSign <> 0 ) then          float64_to_int32 := sbits32 ($80000000)        else          float64_to_int32 :=  $7FFFFFFF;        exit;    End;    if ( aSigExtra <> 0) then      set_inexact_flag;    float64_to_int32 := z;End;{*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic, except that the conversion is always rounded toward zero.If `a' is a NaN, the largest positive integer is returned.  Otherwise, ifthe conversion overflows, the largest integer with the same sign as `a' isreturned.-------------------------------------------------------------------------------*}Function float64_to_int32_round_to_zero(a: float64 ): int32;{$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32_ROUND_TO_ZERO'];compilerproc;{$endif}Var    aSign: flag;    aExp, shiftCount: int16;    aSig0, aSig1, absZ, aSigExtra: bits32;    z: int32;    label invalid; Begin    aSig1 := extractFloat64Frac1( a );    aSig0 := extractFloat64Frac0( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    shiftCount := aExp - $413;    if ( 0 <= shiftCount ) then    Begin        if ( $41E < aExp ) then        Begin            if ( ( aExp = $7FF ) AND  (( aSig0 OR  aSig1 )<>0) ) then               aSign := 0;            goto invalid;        End;        shortShift64Left(            aSig0 OR  $00100000, aSig1, shiftCount, absZ, aSigExtra );    End    else    Begin        if ( aExp < $3FF ) then        Begin            if ( bits32(aExp) OR  aSig0 OR  aSig1 )<>0 then            Begin              set_inexact_flag;            End;            float64_to_int32_round_to_zero := 0;            exit;        End;        aSig0 := aSig0 or $00100000;        aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR  aSig1;        absZ := aSig0 shr ( - shiftCount );    End;    if aSign <> 0 then      z := - absZ    else      z := absZ;    if ( (( aSign xor flag( z < 0 )) <> 0) AND  (z<>0) ) then    Begin invalid:        float_raise( float_flag_invalid );        if (aSign <> 0) then          float64_to_int32_round_to_zero := sbits32 ($80000000)        else          float64_to_int32_round_to_zero :=  $7FFFFFFF;        exit;    End;    if ( aSigExtra <> 0) then       set_inexact_flag;    float64_to_int32_round_to_zero := z; End;{*----------------------------------------------------------------------------| Returns the result of converting the double-precision floating-point value| `a' to the 64-bit two's complement integer format.  The conversion is| performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic---which means in particular that the conversion is rounded| according to the current rounding mode.  If `a' is a NaN, the largest| positive integer is returned.  Otherwise, if the conversion overflows, the| largest integer with the same sign as `a' is returned.*----------------------------------------------------------------------------*}function float64_to_int64( a: float64 ): int64;var    aSign: flag;    aExp, shiftCount: int16;    aSig, aSigExtra: bits64;begin    aSig := extractFloat64Frac( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    if ( aExp <> 0 ) then aSig := aSig or $0010000000000000;    shiftCount := $433 - aExp;    if ( shiftCount <= 0 ) then begin        if ( $43E < aExp ) then begin            float_raise( float_flag_invalid );            if (    ( aSign = 0 )                 or (    ( aExp = $7FF )                     and ( aSig <> $0010000000000000 ) )               ) then begin                result := $7FFFFFFFFFFFFFFF;                exit;            end;            result := $8000000000000000;            exit;        end;        aSigExtra := 0;        aSig := aSig shl ( - shiftCount );    end    else        shift64ExtraRightJamming( aSig, 0, shiftCount, aSig, aSigExtra );    result := roundAndPackInt64( aSign, aSig, aSigExtra );end;{*----------------------------------------------------------------------------| Returns the result of converting the double-precision floating-point value| `a' to the 64-bit two's complement integer format.  The conversion is| performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic, except that the conversion is always rounded toward zero.| If `a' is a NaN, the largest positive integer is returned.  Otherwise, if| the conversion overflows, the largest integer with the same sign as `a' is| returned.*----------------------------------------------------------------------------*}{$define FPC_SYSTEM_HAS_float64_to_int64_round_to_zero}function float64_to_int64_round_to_zero( a: float64 ): int64;var    aSign: flag;    aExp, shiftCount: int16;    aSig: bits64;    z: int64;begin    aSig := extractFloat64Frac( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    if ( aExp <> 0 ) then aSig := aSig or $0010000000000000;    shiftCount := aExp - $433;    if ( 0 <= shiftCount ) then begin        if ( $43E <= aExp ) then begin            if ( bits64 ( a ) <> bits64( $C3E0000000000000 ) ) then begin                float_raise( float_flag_invalid );                if (    ( aSign = 0 )                     or (    ( aExp = $7FF )                         and ( aSig <> $0010000000000000 ) )                   ) then begin                    result := $7FFFFFFFFFFFFFFF;                    exit;                end;            end;            result := $8000000000000000;            exit;        end;        z := aSig shl shiftCount;    end    else begin        if ( aExp < $3FE ) then begin            if ( aExp or aSig <> 0 ) then set_inexact_flag;            result := 0;            exit;        end;        z := aSig shr ( - shiftCount );        if ( bits64( aSig shl ( shiftCount and 63 ) ) <> 0 ) then          set_inexact_flag;    end;    if ( aSign <> 0 ) then z := - z;    result := z;end;{*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the single-precision floating-point format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic.-------------------------------------------------------------------------------*}Function float64_to_float32(a: float64 ): float32rec;compilerproc;Var    aSign: flag;    aExp: int16;    aSig0, aSig1, zSig: bits32;    allZero: bits32;    tmp : CommonNanT;Begin    aSig1 := extractFloat64Frac1( a );    aSig0 := extractFloat64Frac0( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    if ( aExp = $7FF ) then    Begin        if ( aSig0 OR  aSig1 ) <> 0 then        Begin            tmp:=float64ToCommonNaN(a);            float64_to_float32.float32 := commonNaNToFloat32( tmp );            exit;        End;        float64_to_float32.float32 := packFloat32( aSign, $FF, 0 );        exit;    End;    shift64RightJamming( aSig0, aSig1, 22, allZero, zSig );    if ( aExp <> 0) then      zSig := zSig OR $40000000;    float64_to_float32.float32 := roundAndPackFloat32( aSign, aExp - $381, zSig );End;{$ifdef FPC_SOFTFLOAT_FLOATX80}{*----------------------------------------------------------------------------| Returns the result of converting the double-precision floating-point value| `a' to the extended double-precision floating-point format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*}function float64_to_floatx80( a: float64 ): floatx80;var    aSign: flag;    aExp: int16;    aSig: bits64;begin    aSig := extractFloat64Frac( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    if ( aExp = $7FF ) then begin        if ( aSig <> 0 ) then begin            result := commonNaNToFloatx80( float64ToCommonNaN( a ) );            exit;        end;        result := packFloatx80( aSign, $7FFF, bits64( $8000000000000000 ) );        exit;    end;    if ( aExp = 0 ) then begin        if ( aSig = 0 ) then begin            result := packFloatx80( aSign, 0, 0 );            exit;        end;        normalizeFloat64Subnormal( aSig, aExp, aSig );    end;    result :=        packFloatx80(            aSign, aExp + $3C00, ( aSig or $0010000000000000 ) shl 11 );end;{$endif FPC_SOFTFLOAT_FLOATX80}{*-------------------------------------------------------------------------------Rounds the double-precision floating-point value `a' to an integer,and returns the result as a double-precision floating-point value.  Theoperation is performed according to the IEC/IEEE Standard for BinaryFloating-Point Arithmetic.-------------------------------------------------------------------------------*}function float64_round_to_int(a: float64) : Float64;{$ifdef fpc} [public,Alias:'FLOAT64_ROUND_TO_INT'];compilerproc;{$endif}Var    aSign: flag;    aExp: int16;    lastBitMask, roundBitsMask: bits32;    roundingMode: TFPURoundingMode;    z: float64;Begin    aExp := extractFloat64Exp( a );    if ( $413 <= aExp ) then    Begin        if ( $433 <= aExp ) then        Begin            if (    ( aExp = $7FF )                 AND            (            ( extractFloat64Frac0( a ) OR  extractFloat64Frac1( a )            ) <>0)            )  then            Begin                propagateFloat64NaN( a, a, result );                exit;            End;            result := a;            exit;        End;        lastBitMask := 1;        lastBitMask := ( lastBitMask shl ( $432 - aExp ) ) shl 1;        roundBitsMask := lastBitMask - 1;        z := a;        roundingMode := softfloat_rounding_mode;        if ( roundingMode = float_round_nearest_even ) then        Begin            if ( lastBitMask <> 0) then            Begin                add64( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );                if ( ( z.low and roundBitsMask ) = 0 ) then                   z.low := z.low and not lastBitMask;            End            else            Begin                if ( sbits32 (z.low) < 0 ) then                Begin                    Inc(z.high);                    if ( bits32 ( z.low shl 1 ) = 0 ) then                      z.high := z.high and not 1;                End;            End;        End        else if ( roundingMode <> float_round_to_zero ) then        Begin            if (   extractFloat64Sign( z )                 xor flag( roundingMode = float_round_up ) )<> 0 then            Begin                add64( z.high, z.low, 0, roundBitsMask, z.high, z.low );            End;        End;        z.low := z.low and not roundBitsMask;    End    else    Begin        if ( aExp <= $3FE ) then        Begin            if ( ( ( bits32 ( a.high shl 1 ) ) OR  a.low ) = 0 ) then            Begin                result := a;                exit;            End;            set_inexact_flag;            aSign := extractFloat64Sign( a );            case ( softfloat_rounding_mode ) of             float_round_nearest_even:               Begin                if (    ( aExp = $3FE )                     AND  ( (extractFloat64Frac0( a ) OR  extractFloat64Frac1( a ) )<>0)                   ) then                Begin                    packFloat64( aSign, $3FF, 0, 0, result );                    exit;                End;               End;               float_round_down:                Begin                  if aSign<>0 then                   packFloat64( 1, $3FF, 0, 0, result )                  else                   packFloat64( 0, 0, 0, 0, result );                  exit;                End;             float_round_up:                Begin                  if aSign <> 0 then                   packFloat64( 1, 0, 0, 0, result )                  else                   packFloat64( 0, $3FF, 0, 0, result );                  exit;                End;            end;            packFloat64( aSign, 0, 0, 0, result );            exit;        End;        lastBitMask := 1;        lastBitMask := lastBitMask shl ($413 - aExp);        roundBitsMask := lastBitMask - 1;        z.low := 0;        z.high := a.high;        roundingMode := softfloat_rounding_mode;        if ( roundingMode = float_round_nearest_even ) then        Begin            z.high := z.high + lastBitMask shr 1;            if ( ( ( z.high and roundBitsMask ) OR  a.low ) = 0 ) then            Begin                z.high := z.high and not lastBitMask;            End;        End        else if ( roundingMode <> float_round_to_zero ) then        Begin            if (   extractFloat64Sign( z )                 xor flag( roundingMode = float_round_up ) )<> 0 then            Begin                z.high := z.high or bits32( a.low <> 0 );                z.high := z.high + roundBitsMask;            End;        End;        z.high := z.high and not roundBitsMask;    End;    if ( ( z.low <> a.low ) OR ( z.high <> a.high ) ) then    Begin       set_inexact_flag;    End;    result := z;End;{*-------------------------------------------------------------------------------Returns the result of adding the absolute values of the double-precisionfloating-point values `a' and `b'.  If `zSign' is 1, the sum is negatedbefore being returned.  `zSign' is ignored if the result is a NaN.The addition is performed according to the IEC/IEEE Standard for BinaryFloating-Point Arithmetic.-------------------------------------------------------------------------------*}Procedure addFloat64Sigs( a:float64 ; b: float64 ; zSign:flag; Var out: float64 );Var    aExp, bExp, zExp: int16;    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;    expDiff: int16;    label shiftRight1;    label roundAndPack;Begin    aSig1 := extractFloat64Frac1( a );    aSig0 := extractFloat64Frac0( a );    aExp := extractFloat64Exp( a );    bSig1 := extractFloat64Frac1( b );    bSig0 := extractFloat64Frac0( b );    bExp := extractFloat64Exp( b );    expDiff := aExp - bExp;    if ( 0 < expDiff ) then    Begin        if ( aExp = $7FF ) then        Begin            if ( aSig0 OR  aSig1 ) <> 0 then            Begin              propagateFloat64NaN( a, b, out );              exit;            end;            out := a;            exit;        End;        if ( bExp = 0 ) then        Begin            Dec(expDiff);        End        else        Begin            bSig0 := bSig0 or $00100000;        End;        shift64ExtraRightJamming(            bSig0, bSig1, 0, expDiff, bSig0, bSig1, zSig2 );        zExp := aExp;    End    else if ( expDiff < 0 ) then    Begin        if ( bExp = $7FF ) then        Begin            if ( bSig0 OR  bSig1 ) <> 0 then            Begin               propagateFloat64NaN( a, b, out );               exit;            End;            packFloat64( zSign, $7FF, 0, 0, out );            exit;        End;        if ( aExp = 0 ) then        Begin            Inc(expDiff);        End        else        Begin            aSig0 := aSig0 or $00100000;        End;        shift64ExtraRightJamming(            aSig0, aSig1, 0, - expDiff, aSig0, aSig1, zSig2 );        zExp := bExp;    End    else    Begin        if ( aExp = $7FF ) then        Begin            if ( aSig0 OR  aSig1 OR  bSig0 OR  bSig1 ) <> 0 then            Begin                propagateFloat64NaN( a, b, out );                exit;            End;            out := a;            exit;        End;        add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );        if ( aExp = 0 ) then        Begin           packFloat64( zSign, 0, zSig0, zSig1, out );           exit;        End;        zSig2 := 0;        zSig0 := zSig0 or $00200000;        zExp := aExp;        goto shiftRight1;    End;    aSig0 := aSig0 or $00100000;    add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );    Dec(zExp);    if ( zSig0 < $00200000 ) then       goto roundAndPack;    Inc(zExp); shiftRight1:    shift64ExtraRightJamming( zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 ); roundAndPack:    roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, out );End;{*-------------------------------------------------------------------------------Returns the result of subtracting the absolute values of the double-precision floating-point values `a' and `b'.  If `zSign' is 1, thedifference is negated before being returned.  `zSign' is ignored if theresult is a NaN.  The subtraction is performed according to the IEC/IEEEStandard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Procedure subFloat64Sigs( a:float64; b: float64 ; zSign:flag; Var out: float64 );Var    aExp, bExp, zExp: int16;    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits32;    expDiff: int16;    z: float64;    label aExpBigger;    label bExpBigger;    label aBigger;    label bBigger;    label normalizeRoundAndPack;Begin    aSig1 := extractFloat64Frac1( a );    aSig0 := extractFloat64Frac0( a );    aExp := extractFloat64Exp( a );    bSig1 := extractFloat64Frac1( b );    bSig0 := extractFloat64Frac0( b );    bExp := extractFloat64Exp( b );    expDiff := aExp - bExp;    shortShift64Left( aSig0, aSig1, 10, aSig0, aSig1 );    shortShift64Left( bSig0, bSig1, 10, bSig0, bSig1 );    if ( 0 < expDiff ) then goto aExpBigger;    if ( expDiff < 0 ) then goto bExpBigger;    if ( aExp = $7FF ) then    Begin        if ( aSig0 OR  aSig1 OR  bSig0 OR  bSig1 ) <> 0 then        Begin            propagateFloat64NaN( a, b, out );            exit;        End;        float_raise( float_flag_invalid );        z.low := float64_default_nan_low;        z.high := float64_default_nan_high;        out := z;        exit;    End;    if ( aExp = 0 ) then    Begin        aExp := 1;        bExp := 1;    End;    if ( bSig0 < aSig0 ) then goto aBigger;    if ( aSig0 < bSig0 ) then goto bBigger;    if ( bSig1 < aSig1 ) then goto aBigger;    if ( aSig1 < bSig1 ) then goto bBigger;    packFloat64( flag(softfloat_rounding_mode = float_round_down), 0, 0, 0 , out);    exit; bExpBigger:    if ( bExp = $7FF ) then    Begin        if ( bSig0 OR  bSig1 ) <> 0 then        Begin           propagateFloat64NaN( a, b, out );           exit;        End;        packFloat64( zSign xor 1, $7FF, 0, 0, out );        exit;    End;    if ( aExp = 0 ) then    Begin        Inc(expDiff);    End    else    Begin        aSig0 := aSig0 or $40000000;    End;    shift64RightJamming( aSig0, aSig1, - expDiff, aSig0, aSig1 );    bSig0 := bSig0 or $40000000; bBigger:    sub64( bSig0, bSig1, aSig0, aSig1, zSig0, zSig1 );    zExp := bExp;    zSign := zSign xor 1;    goto normalizeRoundAndPack; aExpBigger:    if ( aExp = $7FF ) then    Begin        if ( aSig0 OR  aSig1 ) <> 0 then        Begin           propagateFloat64NaN( a, b, out );           exit;        End;        out :=  a;        exit;    End;    if ( bExp = 0 ) then    Begin        Dec(expDiff);    End    else    Begin        bSig0 := bSig0 or $40000000;    End;    shift64RightJamming( bSig0, bSig1, expDiff, bSig0, bSig1 );    aSig0 := aSig0 or $40000000; aBigger:    sub64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );    zExp := aExp; normalizeRoundAndPack:    Dec(zExp);    normalizeRoundAndPackFloat64( zSign, zExp - 10, zSig0, zSig1, out );End;{*-------------------------------------------------------------------------------Returns the result of adding the double-precision floating-point values `a'and `b'.  The operation is performed according to the IEC/IEEE Standard forBinary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_add( a: float64; b : float64) : Float64;{$ifdef fpc}[public,Alias:'FLOAT64_ADD'];compilerproc;{$endif}Var    aSign, bSign: flag;Begin    aSign := extractFloat64Sign( a );    bSign := extractFloat64Sign( b );    if ( aSign = bSign ) then    Begin         addFloat64Sigs( a, b, aSign, result );    End    else    Begin        subFloat64Sigs( a, b, aSign, result );    End;End;{*-------------------------------------------------------------------------------Returns the result of subtracting the double-precision floating-point values`a' and `b'.  The operation is performed according to the IEC/IEEE Standardfor Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_sub(a: float64; b : float64) : Float64;{$ifdef fpc}[public,Alias:'FLOAT64_SUB'];compilerproc;{$endif}Var    aSign, bSign: flag;Begin    aSign := extractFloat64Sign( a );    bSign := extractFloat64Sign( b );    if ( aSign = bSign ) then    Begin        subFloat64Sigs( a, b, aSign, result );    End    else    Begin        addFloat64Sigs( a, b, aSign, result );    End;End;{*-------------------------------------------------------------------------------Returns the result of multiplying the double-precision floating-point values`a' and `b'.  The operation is performed according to the IEC/IEEE Standardfor Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_mul( a: float64; b:float64) : Float64;{$ifdef fpc}[public,Alias:'FLOAT64_MUL'];compilerproc;{$endif}Var    aSign, bSign, zSign: flag;    aExp, bExp, zExp: int16;    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits32;    z: float64;    label invalid;Begin    aSig1 := extractFloat64Frac1( a );    aSig0 := extractFloat64Frac0( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    bSig1 := extractFloat64Frac1( b );    bSig0 := extractFloat64Frac0( b );    bExp := extractFloat64Exp( b );    bSign := extractFloat64Sign( b );    zSign := aSign xor bSign;    if ( aExp = $7FF ) then    Begin        if (    (( aSig0 OR  aSig1 ) <>0)             OR ( ( bExp = $7FF ) AND  (( bSig0 OR  bSig1 )<>0) ) ) then        Begin            propagateFloat64NaN( a, b, result );            exit;        End;        if ( ( bits32(bExp) OR  bSig0 OR  bSig1 ) = 0 ) then goto invalid;        packFloat64( zSign, $7FF, 0, 0, result );        exit;    End;    if ( bExp = $7FF ) then    Begin        if ( bSig0 OR  bSig1 )<> 0 then        Begin          propagateFloat64NaN( a, b, result );          exit;        End;        if ( ( aExp OR  aSig0 OR  aSig1 ) = 0 ) then        Begin invalid:            float_raise( float_flag_invalid );            z.low := float64_default_nan_low;            z.high := float64_default_nan_high;            result := z;            exit;        End;        packFloat64( zSign, $7FF, 0, 0, result );        exit;    End;    if ( aExp = 0 ) then    Begin        if ( ( aSig0 OR  aSig1 ) = 0 ) then        Begin           packFloat64( zSign, 0, 0, 0, result );           exit;        End;        normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );    End;    if ( bExp = 0 ) then    Begin        if ( ( bSig0 OR  bSig1 ) = 0 ) then        Begin          packFloat64( zSign, 0, 0, 0, result );          exit;        End;        normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );    End;    zExp := aExp + bExp - $400;    aSig0 := aSig0 or $00100000;    shortShift64Left( bSig0, bSig1, 12, bSig0, bSig1 );    mul64To128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3 );    add64( zSig0, zSig1, aSig0, aSig1, zSig0, zSig1 );    zSig2 := zSig2 or flag( zSig3 <> 0 );    if ( $00200000 <= zSig0 ) then    Begin        shift64ExtraRightJamming(            zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );        Inc(zExp);    End;    roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, result );End;{*-------------------------------------------------------------------------------Returns the result of dividing the double-precision floating-point value `a'by the corresponding value `b'.  The operation is performed according to theIEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_div(a: float64; b : float64) : Float64;{$ifdef fpc}[public,Alias:'FLOAT64_DIV'];compilerproc;{$endif}Var    aSign, bSign, zSign: flag;    aExp, bExp, zExp: int16;    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;    rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;    z: float64;    label invalid;Begin    aSig1 := extractFloat64Frac1( a );    aSig0 := extractFloat64Frac0( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    bSig1 := extractFloat64Frac1( b );    bSig0 := extractFloat64Frac0( b );    bExp := extractFloat64Exp( b );    bSign := extractFloat64Sign( b );    zSign := aSign xor bSign;    if ( aExp = $7FF ) then    Begin        if ( aSig0 OR  aSig1 )<> 0 then        Begin           propagateFloat64NaN( a, b, result );           exit;        end;        if ( bExp = $7FF ) then        Begin            if ( bSig0 OR  bSig1 )<>0 then            Begin               propagateFloat64NaN( a, b, result );               exit;            End;            goto invalid;        End;        packFloat64( zSign, $7FF, 0, 0, result );        exit;    End;    if ( bExp = $7FF ) then    Begin        if ( bSig0 OR  bSig1 )<> 0 then        Begin          propagateFloat64NaN( a, b, result );          exit;        End;        packFloat64( zSign, 0, 0, 0, result );        exit;    End;    if ( bExp = 0 ) then    Begin        if ( ( bSig0 OR  bSig1 ) = 0 ) then        Begin            if ( ( bits32(aExp) OR  aSig0 OR  aSig1 ) = 0 ) then            Begin invalid:                float_raise( float_flag_invalid );                z.low := float64_default_nan_low;                z.high := float64_default_nan_high;                result := z;                exit;            End;            float_raise( float_flag_divbyzero );            packFloat64( zSign, $7FF, 0, 0, result );            exit;        End;        normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );    End;    if ( aExp = 0 ) then    Begin        if ( ( aSig0 OR  aSig1 ) = 0 ) then        Begin           packFloat64( zSign, 0, 0, 0, result );           exit;        End;        normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );    End;    zExp := aExp - bExp + $3FD;    shortShift64Left( aSig0 OR  $00100000, aSig1, 11, aSig0, aSig1 );    shortShift64Left( bSig0 OR  $00100000, bSig1, 11, bSig0, bSig1 );    if ( le64( bSig0, bSig1, aSig0, aSig1 )<>0 ) then    Begin        shift64Right( aSig0, aSig1, 1, aSig0, aSig1 );        Inc(zExp);    End;    zSig0 := estimateDiv64To32( aSig0, aSig1, bSig0 );    mul64By32To96( bSig0, bSig1, zSig0, term0, term1, term2 );    sub96( aSig0, aSig1, 0, term0, term1, term2, rem0, rem1, rem2 );    while ( sbits32 (rem0) < 0 ) do    Begin        Dec(zSig0);        add96( rem0, rem1, rem2, 0, bSig0, bSig1, rem0, rem1, rem2 );    End;    zSig1 := estimateDiv64To32( rem1, rem2, bSig0 );    if ( ( zSig1 and $3FF ) <= 4 ) then    Begin        mul64By32To96( bSig0, bSig1, zSig1, term1, term2, term3 );        sub96( rem1, rem2, 0, term1, term2, term3, rem1, rem2, rem3 );        while ( sbits32 (rem1) < 0 ) do        Begin            Dec(zSig1);            add96( rem1, rem2, rem3, 0, bSig0, bSig1, rem1, rem2, rem3 );        End;        zSig1 := zSig1 or flag( ( rem1 OR  rem2 OR  rem3 ) <> 0 );    End;    shift64ExtraRightJamming( zSig0, zSig1, 0, 11, zSig0, zSig1, zSig2 );    roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, result );End;{*-------------------------------------------------------------------------------Returns the remainder of the double-precision floating-point value `a'with respect to the corresponding value `b'.  The operation is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_rem(a: float64; b : float64) : float64;{$ifdef fpc}[public,Alias:'FLOAT64_REM'];compilerproc;{$endif}Var    aSign, zSign: flag;    aExp, bExp, expDiff: int16;    aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits32;    allZero, alternateASig0, alternateASig1, sigMean1: bits32;    sigMean0: sbits32;    z: float64;    label invalid;Begin    aSig1 := extractFloat64Frac1( a );    aSig0 := extractFloat64Frac0( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    bSig1 := extractFloat64Frac1( b );    bSig0 := extractFloat64Frac0( b );    bExp := extractFloat64Exp( b );    if ( aExp = $7FF ) then    Begin        if ((( aSig0 OR  aSig1 )<>0)             OR ( ( bExp = $7FF ) AND  (( bSig0 OR  bSig1 )<>0) ) ) then        Begin            propagateFloat64NaN( a, b, result );            exit;        End;        goto invalid;    End;    if ( bExp = $7FF ) then    Begin        if ( bSig0 OR  bSig1 ) <> 0 then        Begin          propagateFloat64NaN( a, b, result );          exit;        End;        result := a;        exit;    End;    if ( bExp = 0 ) then    Begin        if ( ( bSig0 OR  bSig1 ) = 0 ) then        Begin invalid:            float_raise( float_flag_invalid );            z.low := float64_default_nan_low;            z.high := float64_default_nan_high;            result := z;            exit;        End;        normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );    End;    if ( aExp = 0 ) then    Begin        if ( ( aSig0 OR  aSig1 ) = 0 ) then        Begin           result := a;           exit;        End;        normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );    End;    expDiff := aExp - bExp;    if ( expDiff < -1 ) then    Begin       result := a;       exit;    End;    shortShift64Left(        aSig0 OR  $00100000, aSig1, 11 - flag( expDiff < 0 ), aSig0, aSig1 );    shortShift64Left( bSig0 OR  $00100000, bSig1, 11, bSig0, bSig1 );    q := le64( bSig0, bSig1, aSig0, aSig1 );    if ( q )<>0 then       sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );    expDiff := expDiff - 32;    while ( 0 < expDiff ) do    Begin        q := estimateDiv64To32( aSig0, aSig1, bSig0 );        if 4 < q then          q:= q - 4        else          q := 0;        mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );        shortShift96Left( term0, term1, term2, 29, term1, term2, allZero );        shortShift64Left( aSig0, aSig1, 29, aSig0, allZero );        sub64( aSig0, 0, term1, term2, aSig0, aSig1 );        expDiff := expDiff - 29;    End;    if ( -32 < expDiff ) then    Begin        q := estimateDiv64To32( aSig0, aSig1, bSig0 );        if 4 < q then          q := q - 4        else          q := 0;        q := q shr (- expDiff);        shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );        expDiff := expDiff + 24;        if ( expDiff < 0 ) then        Begin            shift64Right( aSig0, aSig1, - expDiff, aSig0, aSig1 );        End        else        Begin            shortShift64Left( aSig0, aSig1, expDiff, aSig0, aSig1 );        End;        mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );        sub64( aSig0, aSig1, term1, term2, aSig0, aSig1 );    End    else    Begin        shift64Right( aSig0, aSig1, 8, aSig0, aSig1 );        shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );    End;    Repeat        alternateASig0 := aSig0;        alternateASig1 := aSig1;        Inc(q);        sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );    Until not ( 0 <= sbits32 (aSig0) );    add64(        aSig0, aSig1, alternateASig0, alternateASig1, bits32(sigMean0), sigMean1 );    if (    ( sigMean0 < 0 )         OR ( ( ( sigMean0 OR  sigMean1 ) = 0 ) AND  (( q AND 1 )<>0) ) ) then    Begin        aSig0 := alternateASig0;        aSig1 := alternateASig1;    End;    zSign := flag( sbits32 (aSig0) < 0 );    if ( zSign <> 0 ) then       sub64( 0, 0, aSig0, aSig1, aSig0, aSig1 );    normalizeRoundAndPackFloat64( aSign xor zSign, bExp - 4, aSig0, aSig1, result );End;{*-------------------------------------------------------------------------------Returns the square root of the double-precision floating-point value `a'.The operation is performed according to the IEC/IEEE Standard for BinaryFloating-Point Arithmetic.-------------------------------------------------------------------------------*}function float64_sqrt( a: float64 ): float64;{$ifdef fpc}[public,Alias:'FLOAT64_SQRT'];compilerproc;{$endif}Var    aSign: flag;    aExp, zExp: int16;    aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits32;    rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;    label invalid;Begin    aSig1 := extractFloat64Frac1( a );    aSig0 := extractFloat64Frac0( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    if ( aExp = $7FF ) then    Begin        if ( aSig0 OR  aSig1 ) <> 0 then        Begin           propagateFloat64NaN( a, a, result );           exit;        End;        if ( aSign = 0) then        Begin          result := a;          exit;        End;        goto invalid;    End;    if ( aSign <> 0 ) then    Begin        if ( ( bits32(aExp) OR  aSig0 OR  aSig1 ) = 0 ) then        Begin           result := a;           exit;        End; invalid:        float_raise( float_flag_invalid );        result.low := float64_default_nan_low;        result.high := float64_default_nan_high;        exit;    End;    if ( aExp = 0 ) then    Begin        if ( ( aSig0 OR  aSig1 ) = 0 ) then        Begin           packFloat64( 0, 0, 0, 0, result );           exit;        End;        normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );    End;    zExp := ( ( aExp - $3FF ) shr 1 ) + $3FE;    aSig0 := aSig0 or $00100000;    shortShift64Left( aSig0, aSig1, 11, term0, term1 );    zSig0 := ( estimateSqrt32( aExp, term0 ) shr 1 ) + 1;    if ( zSig0 = 0 ) then       zSig0 := $7FFFFFFF;    doubleZSig0 := zSig0 + zSig0;    shortShift64Left( aSig0, aSig1, 9 - ( aExp and 1 ), aSig0, aSig1 );    mul32To64( zSig0, zSig0, term0, term1 );    sub64( aSig0, aSig1, term0, term1, rem0, rem1 );    while ( sbits32 (rem0) < 0 ) do    Begin        Dec(zSig0);        doubleZSig0 := doubleZSig0 - 2;        add64( rem0, rem1, 0, doubleZSig0 OR  1, rem0, rem1 );    End;    zSig1 := estimateDiv64To32( rem1, 0, doubleZSig0 );    if ( ( zSig1 and $1FF ) <= 5 ) then    Begin        if ( zSig1 = 0 ) then           zSig1 := 1;        mul32To64( doubleZSig0, zSig1, term1, term2 );        sub64( rem1, 0, term1, term2, rem1, rem2 );        mul32To64( zSig1, zSig1, term2, term3 );        sub96( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );        while ( sbits32 (rem1) < 0 ) do        Begin            Dec(zSig1);            shortShift64Left( 0, zSig1, 1, term2, term3 );            term3 := term3 or 1;            term2 := term2 or doubleZSig0;            add96( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );        End;        zSig1 := zSig1 or bits32( ( rem1 OR  rem2 OR  rem3 ) <> 0 );    End;    shift64ExtraRightJamming( zSig0, zSig1, 0, 10, zSig0, zSig1, zSig2 );    roundAndPackFloat64( 0, zExp, zSig0, zSig1, zSig2, result );End;{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is equal tothe corresponding value `b', and 0 otherwise.  The comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_eq(a: float64; b: float64): flag;{$ifdef fpc}[public,Alias:'FLOAT64_EQ'];compilerproc;{$endif}Begin    if         (                ( extractFloat64Exp( a ) = $7FF )            AND                (                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0                )         )         OR (                ( extractFloat64Exp( b ) = $7FF )           AND  (                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0                )           )       ) then    Begin        if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then            float_raise( float_flag_invalid );        float64_eq := 0;        exit;    End;    float64_eq := flag(           ( a.low = b.low )        AND  (    ( a.high = b.high )             OR (    ( a.low = 0 )                  AND  ( bits32 ( ( a.high OR  b.high ) shl 1 ) = 0 ) )           ));End;{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is less thanor equal to the corresponding value `b', and 0 otherwise.  The comparisonis performed according to the IEC/IEEE Standard for Binary Floating-PointArithmetic.-------------------------------------------------------------------------------*}Function float64_le(a: float64;b: float64): flag;{$ifdef fpc}[public,Alias:'FLOAT64_LE'];compilerproc;{$endif}Var    aSign, bSign: flag;Begin    if         (                ( extractFloat64Exp( a ) = $7FF )            AND                (                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0                )         )         OR (                ( extractFloat64Exp( b ) = $7FF )           AND  (                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0                )           )       ) then    Begin        float_raise( float_flag_invalid );        float64_le := 0;        exit;    End;    aSign := extractFloat64Sign( a );    bSign := extractFloat64Sign( b );    if ( aSign <> bSign ) then    Begin        float64_le := flag(               (aSign <> 0)            OR (    ( ( bits32 ( ( a.high OR  b.high ) shl 1 ) ) OR  a.low OR  b.low )                 = 0 ));        exit;    End;    if aSign <> 0 then      float64_le := le64( b.high, b.low, a.high, a.low )    else      float64_le := le64( a.high, a.low, b.high, b.low );End;{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is less thanthe corresponding value `b', and 0 otherwise.  The comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_lt(a: float64;b: float64): flag;{$ifdef fpc}[public,Alias:'FLOAT64_LT'];compilerproc;{$endif}Var    aSign, bSign: flag;Begin    if         (                ( extractFloat64Exp( a ) = $7FF )            AND                (                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0                )         )         OR (                ( extractFloat64Exp( b ) = $7FF )           AND  (                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0                )           )       ) then    Begin        float_raise( float_flag_invalid );        float64_lt := 0;        exit;    End;    aSign := extractFloat64Sign( a );    bSign := extractFloat64Sign( b );    if ( aSign <> bSign ) then    Begin        float64_lt := flag(               (aSign <> 0)            AND  (    ( ( bits32 ( ( a.high OR  b.high ) shl 1 ) ) OR  a.low OR  b.low )                 <> 0 ));        exit;    End;    if aSign <> 0 then       float64_lt := lt64( b.high, b.low, a.high, a.low )    else       float64_lt := lt64( a.high, a.low, b.high, b.low );End;{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is equal tothe corresponding value `b', and 0 otherwise.  The invalid exception israised if either operand is a NaN.  Otherwise, the comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_eq_signaling( a: float64; b: float64): flag;Begin    if         (                ( extractFloat64Exp( a ) = $7FF )            AND                (                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0                )         )         OR (                ( extractFloat64Exp( b ) = $7FF )           AND  (                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0                )           )       ) then    Begin        float_raise( float_flag_invalid );        float64_eq_signaling := 0;        exit;    End;    float64_eq_signaling := flag(           ( a.low = b.low )        AND  (    ( a.high = b.high )             OR (    ( a.low = 0 )                  AND  ( bits32 ( ( a.high OR  b.high ) shl 1 ) = 0 ) )           ));End;{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is less than orequal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do notcause an exception.  Otherwise, the comparison is performed according to theIEC/IEEE Standard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_le_quiet(a: float64 ; b: float64 ): flag;Var    aSign, bSign : flag;Begin    if         (                ( extractFloat64Exp( a ) = $7FF )            AND                (                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0                )         )         OR (                ( extractFloat64Exp( b ) = $7FF )           AND  (                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0                )           )       ) then    Begin        if ( (float64_is_signaling_nan( a )<>0)  OR (float64_is_signaling_nan( b )<>0) ) then            float_raise( float_flag_invalid );        float64_le_quiet := 0;        exit;    End;    aSign := extractFloat64Sign( a );    bSign := extractFloat64Sign( b );    if ( aSign <> bSign ) then    Begin     float64_le_quiet := flag      ((aSign <> 0)            OR (    ( ( bits32 ( ( a.high OR  b.high ) shl 1 ) ) OR  a.low OR  b.low )                 = 0 ));        exit;    End;    if aSign <> 0 then      float64_le_quiet := le64( b.high, b.low, a.high, a.low )    else      float64_le_quiet := le64( a.high, a.low, b.high, b.low );End;{*-------------------------------------------------------------------------------Returns 1 if the double-precision floating-point value `a' is less thanthe corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause anexception.  Otherwise, the comparison is performed according to the IEC/IEEEStandard for Binary Floating-Point Arithmetic.-------------------------------------------------------------------------------*}Function float64_lt_quiet(a: float64; b: float64 ): Flag;Var    aSign, bSign: flag;Begin    if         (                ( extractFloat64Exp( a ) = $7FF )            AND                (                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0                )         )         OR (                ( extractFloat64Exp( b ) = $7FF )           AND  (                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0                )           )       ) then    Begin        if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then            float_raise( float_flag_invalid );        float64_lt_quiet := 0;        exit;    End;    aSign := extractFloat64Sign( a );    bSign := extractFloat64Sign( b );    if ( aSign <> bSign ) then    Begin      float64_lt_quiet := flag(               (aSign<>0)            AND  (    ( ( bits32 ( ( a.high OR  b.high ) shl 1 ) ) OR  a.low OR  b.low )                 <> 0 ));        exit;    End;    If aSign <> 0 then      float64_lt_quiet :=  lt64( b.high, b.low, a.high, a.low )    else      float64_lt_quiet := lt64( a.high, a.low, b.high, b.low );End;{*----------------------------------------------------------------------------| Returns the result of converting the 64-bit two's complement integer `a'| to the single-precision floating-point format.  The conversion is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function int64_to_float32( a: int64 ): float32rec; compilerproc;var    zSign : flag;    absA : uint64;    shiftCount: int8;Begin    if ( a = 0 ) then      begin       int64_to_float32.float32 := 0;       exit;      end;    if a < 0 then      zSign := flag(TRUE)    else      zSign := flag(FALSE);    if zSign<>0 then       absA := -a    else       absA := a;    shiftCount := countLeadingZeros64( absA ) - 40;    if ( 0 <= shiftCount ) then      begin        int64_to_float32.float32:= packFloat32( zSign, $95 - shiftCount, absA shl shiftCount );      end    else       begin        shiftCount := shiftCount + 7;        if ( shiftCount < 0 ) then            shift64RightJamming( absA, - shiftCount, absA )        else            absA := absA shl shiftCount;        int64_to_float32.float32:=roundAndPackFloat32( zSign, $9C - shiftCount, absA );      end;End;{*----------------------------------------------------------------------------| Returns the result of converting the 64-bit two's complement integer `a'| to the single-precision floating-point format.  The conversion is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.| Unisgned version.*----------------------------------------------------------------------------*}function qword_to_float32( a: qword ): float32rec; compilerproc;var    absA : uint64;    shiftCount: int8;Begin    if ( a = 0 ) then      begin       qword_to_float32.float32 := 0;       exit;      end;    absA := a;    shiftCount := countLeadingZeros64( absA ) - 40;    if ( 0 <= shiftCount ) then      begin        qword_to_float32.float32:= packFloat32( 0, $95 - shiftCount, absA shl shiftCount );      end    else       begin        shiftCount := shiftCount + 7;        if ( shiftCount < 0 ) then            shift64RightJamming( absA, - shiftCount, absA )        else            absA := absA shl shiftCount;        qword_to_float32.float32:=roundAndPackFloat32( 0, $9C - shiftCount, absA );      end;End;{*----------------------------------------------------------------------------| Returns the result of converting the 64-bit two's complement integer `a'| to the double-precision floating-point format.  The conversion is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function qword_to_float64( a: qword ): float64;{$ifdef fpc}[public,Alias:'QWORD_TO_FLOAT64'];compilerproc;{$endif}var  shiftCount: int8;Begin  if ( a = 0 ) then    result := packFloat64( 0, 0, 0 )  else    begin      shiftCount := countLeadingZeros64(a) - 1;      { numbers with <= 53 significant bits are converted exactly }      if (shiftCount > 9) then        result := packFloat64(0, $43c - shiftCount, a shl (shiftCount-10))      else if (shiftCount>=0) then        result := roundAndPackFloat64( 0, $43c - shiftCount, a shl shiftCount)      else        begin          { the only possible negative value is -1, in case bit 63 of 'a' is set }          shift64RightJamming(a, 1, a);          result := roundAndPackFloat64(0, $43d, a);        end;    end;End;{*----------------------------------------------------------------------------| Returns the result of converting the 64-bit two's complement integer `a'| to the double-precision floating-point format.  The conversion is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function int64_to_float64( a: int64 ): float64;{$ifdef fpc}[public,Alias:'INT64_TO_FLOAT64'];compilerproc;{$endif}Begin  if ( a = 0 ) then    result := packFloat64( 0, 0, 0 )  else if (a = int64($8000000000000000)) then    result := packFloat64( 1, $43e, 0 )  else if (a < 0) then    result := normalizeRoundAndPackFloat64( 1, $43c, -a )  else    result := normalizeRoundAndPackFloat64( 0, $43c, a );End;{$ifdef FPC_SOFTFLOAT_FLOATX80}{*----------------------------------------------------------------------------| Returns the result of converting the 64-bit two's complement integer `a'| to the extended double-precision floating-point format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*}function int64_to_floatx80( a: int64 ): floatx80;var    zSign: flag;    absA: uint64;    shiftCount: int8;begin    if ( a = 0 ) then begin        result := packFloatx80( 0, 0, 0 );        exit;    end;    zSign := ord( a < 0 );    if zSign <> 0 then absA := - a else absA := a;    shiftCount := countLeadingZeros64( absA );    result := packFloatx80( zSign, $403E - shiftCount, absA shl shiftCount );end;{*----------------------------------------------------------------------------| Returns the result of converting the 64-bit two's complement integer `a'| to the extended double-precision floating-point format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.| Unsigned version.*----------------------------------------------------------------------------*}function qword_to_floatx80( a: qword ): floatx80;var    absA: bits64;    shiftCount: int8;begin    if ( a = 0 ) then begin        result := packFloatx80( 0, 0, 0 );        exit;    end;    absA := a;    shiftCount := countLeadingZeros64( absA );    result := packFloatx80( 0, $403E - shiftCount, absA shl shiftCount );end;{$endif FPC_SOFTFLOAT_FLOATX80}{$ifdef FPC_SOFTFLOAT_FLOAT128}{*----------------------------------------------------------------------------| Returns the result of converting the 64-bit two's complement integer `a' to| the quadruple-precision floating-point format.  The conversion is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function int64_to_float128( a: int64 ): float128;var    zSign: flag;    absA: uint64;    shiftCount: int8;    zExp: int32;    zSig0, zSig1: bits64;begin    if ( a = 0 ) then begin        result := packFloat128( 0, 0, 0, 0 );        exit;    end;    zSign := ord( a < 0 );    if zSign <> 0 then absA := - a else absA := a;    shiftCount := countLeadingZeros64( absA ) + 49;    zExp := $406E - shiftCount;    if ( 64 <= shiftCount ) then begin        zSig1 := 0;        zSig0 := absA;        dec( shiftCount, 64 );    end    else begin        zSig1 := absA;        zSig0 := 0;    end;    shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );    result := packFloat128( zSign, zExp, zSig0, zSig1 );end;{*----------------------------------------------------------------------------| Returns the result of converting the 64-bit two's complement integer `a' to| the quadruple-precision floating-point format.  The conversion is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.| Unsigned version.*----------------------------------------------------------------------------*}function qword_to_float128( a: qword ): float128;var    absA: bits64;    shiftCount: int8;    zExp: int32;    zSig0, zSig1: bits64;begin    if ( a = 0 ) then begin        result := packFloat128( 0, 0, 0, 0 );        exit;    end;    absA := a;    shiftCount := countLeadingZeros64( absA ) + 49;    zExp := $406E - shiftCount;    if ( 64 <= shiftCount ) then begin        zSig1 := 0;        zSig0 := absA;        dec( shiftCount, 64 );    end    else begin        zSig1 := absA;        zSig0 := 0;    end;    shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );    result := packFloat128( 0, zExp, zSig0, zSig1 );end;{$endif FPC_SOFTFLOAT_FLOAT128}{*----------------------------------------------------------------------------| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'| is equal to the 128-bit value formed by concatenating `b0' and `b1'.| Otherwise, returns 0.*----------------------------------------------------------------------------*}function eq128( a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;begin    result := ord(( a0 = b0 ) and ( a1 = b1 ));end;{*----------------------------------------------------------------------------| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less| than or equal to the 128-bit value formed by concatenating `b0' and `b1'.| Otherwise, returns 0.*----------------------------------------------------------------------------*}function le128( a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;begin    result:=ord(( a0 < b0 ) or ( ( a0 = b0 ) and ( a1 <= b1 ) ));end;{*----------------------------------------------------------------------------| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right| by 64 _plus_ the number of bits given in `count'.  The shifted result is| at most 128 nonzero bits; these are broken into two 64-bit pieces which are| stored at the locations pointed to by `z0Ptr' and `z1Ptr'.  The bits shifted| off form a third 64-bit result as follows:  The _last_ bit shifted off is| the most-significant bit of the extra result, and the other 63 bits of the| extra result are all zero if and only if _all_but_the_last_ bits shifted off| were all zero.  This extra result is stored in the location pointed to by| `z2Ptr'.  The value of `count' can be arbitrarily large.|     (This routine makes more sense if `a0', `a1', and `a2' are considered| to form a fixed-point value with binary point between `a1' and `a2'.  This| fixed-point value is shifted right by the number of bits given in `count',| and the integer part of the result is returned at the locations pointed to| by `z0Ptr' and `z1Ptr'.  The fractional part of the result may be slightly| corrupted as described above, and is returned at the location pointed to by| `z2Ptr'.)*----------------------------------------------------------------------------*}procedure shift128ExtraRightJamming(     a0: bits64;     a1: bits64;     a2: bits64;     count: int16;     var z0Ptr: bits64;     var z1Ptr: bits64;     var z2Ptr: bits64);var    z0, z1, z2: bits64;    negCount: int8;begin    negCount := ( - count ) and 63;    if ( count = 0 ) then    begin        z2 := a2;        z1 := a1;        z0 := a0;    end    else begin        if ( count < 64 ) then        begin            z2 := a1 shl negCount;            z1 := ( a0 shl negCount ) or  ( a1 shr count );            z0 := a0 shr count;        end        else begin            if ( count = 64 ) then            begin                z2 := a1;                z1 := a0;            end            else begin                a2 := a2 or a1;                if ( count < 128 ) then                begin                    z2 := a0 shl negCount;                    z1 := a0 shr ( count and 63 );                end                else begin                	  if ( count = 128 ) then                      z2 :=  a0                    else                      z2 := ord( a0 <> 0 );                    z1 := 0;                end;            end;            z0 := 0;        end;        z2 := z2 or ord( a2 <> 0 );    end;    z2Ptr := z2;    z1Ptr := z1;    z0Ptr := z0;end;{*----------------------------------------------------------------------------| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64| _plus_ the number of bits given in `count'.  The shifted result is at most| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'.  The| bits shifted off form a second 64-bit result as follows:  The _last_ bit| shifted off is the most-significant bit of the extra result, and the other| 63 bits of the extra result are all zero if and only if _all_but_the_last_| bits shifted off were all zero.  This extra result is stored in the location| pointed to by `z1Ptr'.  The value of `count' can be arbitrarily large.|     (This routine makes more sense if `a0' and `a1' are considered to form| a fixed-point value with binary point between `a0' and `a1'.  This fixed-| point value is shifted right by the number of bits given in `count', and| the integer part of the result is returned at the location pointed to by| `z0Ptr'.  The fractional part of the result may be slightly corrupted as| described above, and is returned at the location pointed to by `z1Ptr'.)*----------------------------------------------------------------------------*}procedure shift64ExtraRightJamming(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);var    z0, z1: bits64;    negCount: int8;begin    negCount := ( - count ) and 63;    if ( count = 0 ) then    begin        z1 := a1;        z0 := a0;    end    else if ( count < 64 ) then    begin        z1 := ( a0 shl negCount ) or ord( a1 <>  0 );        z0 := a0 shr count;    end    else begin        if ( count = 64 ) then        begin            z1 := a0 or ord( a1 <>  0 );        end        else begin            z1 := ord( ( a0 or a1 ) <>  0 );        end;        z0 := 0;    end;    z1Ptr := z1;    z0Ptr := z0;end;{$ifdef FPC_SOFTFLOAT_FLOATX80}{*----------------------------------------------------------------------------| Returns the fraction bits of the extended double-precision floating-point| value `a'.*----------------------------------------------------------------------------*}function extractFloatx80Frac(a : floatx80): bits64;inline;begin    result:=a.low;end;{*----------------------------------------------------------------------------| Returns the exponent bits of the extended double-precision floating-point| value `a'.*----------------------------------------------------------------------------*}function extractFloatx80Exp(a : floatx80): int32;inline;begin    result:=a.high and $7FFF;end;{*----------------------------------------------------------------------------| Returns the sign bit of the extended double-precision floating-point value| `a'.*----------------------------------------------------------------------------*}function extractFloatx80Sign(a : floatx80): flag;inline;begin    result:=a.high shr 15;end;{*----------------------------------------------------------------------------| Normalizes the subnormal extended double-precision floating-point value| represented by the denormalized significand `aSig'.  The normalized exponent| and significand are stored at the locations pointed to by `zExpPtr' and| `zSigPtr', respectively.*----------------------------------------------------------------------------*}procedure normalizeFloatx80Subnormal( aSig: bits64; var zExpPtr: int32; var zSigPtr : bits64);var    shiftCount: int8;begin    shiftCount := countLeadingZeros64( aSig );    zSigPtr := aSig shl shiftCount;    zExpPtr := 1 - shiftCount;end;{*----------------------------------------------------------------------------| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an| extended double-precision floating-point value, returning the result.*----------------------------------------------------------------------------*}function packFloatx80( zSign: flag; zExp: int32; zSig : bits64): floatx80;var    z: floatx80;begin    z.low := zSig;    z.high := (  bits16(zSign) shl 15 ) + zExp;    result:=z;end;{*----------------------------------------------------------------------------| Takes an abstract floating-point value having sign `zSign', exponent `zExp',| and extended significand formed by the concatenation of `zSig0' and `zSig1',| and returns the proper extended double-precision floating-point value| corresponding to the abstract input.  Ordinarily, the abstract value is| rounded and packed into the extended double-precision format, with the| inexact exception raised if the abstract input cannot be represented| exactly.  However, if the abstract value is too large, the overflow and| inexact exceptions are raised and an infinity or maximal finite value is| returned.  If the abstract value is too small, the input value is rounded to| a subnormal number, and the underflow and inexact exceptions are raised if| the abstract input cannot be represented exactly as a subnormal extended| double-precision floating-point number.|     If `roundingPrecision' is 32 or 64, the result is rounded to the same| number of bits as single or double precision, respectively.  Otherwise, the| result is rounded to the full precision of the extended double-precision| format.|     The input significand must be normalized or smaller.  If the input| significand is not normalized, `zExp' must be 0; in that case, the result| returned is a subnormal number, and it must not require rounding.  The| handling of underflow and overflow follows the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function roundAndPackFloatx80(roundingPrecision: int8; zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): floatx80;var    roundingMode: TFPURoundingMode;    roundNearestEven, increment, isTiny: flag;    roundIncrement, roundMask, roundBits: int64;label    precision80, overflow;begin    roundingMode := softfloat_rounding_mode;    roundNearestEven := flag( roundingMode = float_round_nearest_even );    if ( roundingPrecision = 80 ) then      goto precision80;    if ( roundingPrecision = 64 ) then    begin        roundIncrement := int64( $0000000000000400 );        roundMask := int64( $00000000000007FF );    end    else if ( roundingPrecision = 32 ) then    begin        roundIncrement := int64( $0000008000000000 );        roundMask := int64( $000000FFFFFFFFFF );    end    else begin        goto precision80;    end;    zSig0 := zSig0 or ord( zSig1 <> 0 );    if ( not (roundNearestEven<>0) ) then    begin        if ( roundingMode = float_round_to_zero ) then        begin            roundIncrement := 0;        end        else begin            roundIncrement := roundMask;            if ( zSign<>0 ) then            begin                if ( roundingMode = float_round_up ) then                  roundIncrement := 0;            end            else begin                if ( roundingMode = float_round_down ) then                  roundIncrement := 0;            end;        end;    end;    roundBits := zSig0 and roundMask;    if ( $7FFD <= bits32( zExp - 1 ) ) then begin        if (    ( $7FFE < zExp )             or ( ( zExp = $7FFE ) and ( zSig0 + roundIncrement < zSig0 ) )           ) then begin            goto overflow;        end;        if ( zExp <= 0 ) then begin            isTiny := ord (                   ( softfloat_detect_tininess = float_tininess_before_rounding )                or ( zExp < 0 )                or ( zSig0 <= zSig0 + roundIncrement ) );            shift64RightJamming( zSig0, 1 - zExp, zSig0 );            zExp := 0;            roundBits := zSig0 and roundMask;            if ( isTiny <> 0 ) and ( roundBits <> 0 ) then float_raise( float_flag_underflow );            if ( roundBits <> 0 ) then set_inexact_flag;            inc( zSig0, roundIncrement );            if ( sbits64( zSig0 ) < 0 ) then zExp := 1;            roundIncrement := roundMask + 1;            if ( roundNearestEven <> 0 ) and ( roundBits shl 1 = roundIncrement ) then begin                roundMask := roundMask or roundIncrement;            end;            zSig0 := zSig0 and not roundMask;            result:=packFloatx80( zSign, zExp, zSig0 );            exit;        end;    end;    if ( roundBits <> 0 ) then set_inexact_flag;    inc( zSig0, roundIncrement );    if ( zSig0 < roundIncrement ) then begin        inc(zExp);        zSig0 := bits64( $8000000000000000 );    end;    roundIncrement := roundMask + 1;    if ( roundNearestEven <> 0 ) and ( roundBits shl 1 = roundIncrement ) then begin        roundMask := roundMask or roundIncrement;    end;    zSig0 := zSig0 and not roundMask;    if ( zSig0 = 0 ) then zExp := 0;    result:=packFloatx80( zSign, zExp, zSig0 );    exit; precision80:    increment := ord ( sbits64( zSig1 ) < 0 );    if ( roundNearestEven = 0 ) then begin        if ( roundingMode = float_round_to_zero ) then begin            increment := 0;        end        else begin            if ( zSign <> 0 ) then begin                increment := ord ( roundingMode = float_round_down ) and zSig1;            end            else begin                increment := ord ( roundingMode = float_round_up ) and zSig1;            end;        end;    end;    if ( $7FFD <= bits32( zExp - 1 ) ) then begin        if (    ( $7FFE < zExp )             or (    ( zExp = $7FFE )                  and ( zSig0 = bits64( $FFFFFFFFFFFFFFFF ) )                  and ( increment <> 0 )                )           ) then begin            roundMask := 0; overflow:            float_raise( [float_flag_overflow,float_flag_inexact] );            if (    ( roundingMode = float_round_to_zero )                 or ( ( zSign <> 0) and ( roundingMode = float_round_up ) )                 or ( ( zSign = 0) and ( roundingMode = float_round_down ) )               ) then begin                result:=packFloatx80( zSign, $7FFE, not roundMask );                exit;            end;            result:=packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );            exit;        end;        if ( zExp <= 0 ) then begin            isTiny := ord(                   ( softfloat_detect_tininess = float_tininess_before_rounding )                or ( zExp < 0 )                or ( increment = 0 )                or ( zSig0 < bits64( $FFFFFFFFFFFFFFFF ) ) );            shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, zSig0, zSig1 );            zExp := 0;            if ( ( isTiny <> 0 ) and ( zSig1 <> 0 ) ) then float_raise( float_flag_underflow );            if ( zSig1 <> 0 ) then set_inexact_flag;            if ( roundNearestEven <> 0 ) then begin                increment := ord( sbits64( zSig1 ) < 0 );            end            else begin                if ( zSign <> 0 ) then begin                    increment := ord( roundingMode = float_round_down ) and zSig1;                end                else begin                    increment := ord( roundingMode = float_round_up ) and zSig1;                end;            end;            if ( increment <> 0 ) then begin                inc(zSig0);                zSig0 :=                    not ( ord( bits64( zSig1 shl 1 ) = 0 ) and roundNearestEven );                if ( sbits64( zSig0 ) < 0 ) then zExp := 1;            end;            result:=packFloatx80( zSign, zExp, zSig0 );            exit;        end;    end;    if ( zSig1 <> 0 ) then set_inexact_flag;    if ( increment <> 0 ) then begin        inc(zSig0);        if ( zSig0 = 0 ) then begin            inc(zExp);            zSig0 := bits64( $8000000000000000 );        end        else begin            zSig0 := zSig0 and not bits64( ord( bits64( zSig1 shl 1 ) = 0 ) and roundNearestEven );        end;    end    else begin        if ( zSig0 = 0 ) then zExp := 0;    end;    result:=packFloatx80( zSign, zExp, zSig0 );end;{*----------------------------------------------------------------------------| Takes an abstract floating-point value having sign `zSign', exponent| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',| and returns the proper extended double-precision floating-point value| corresponding to the abstract input.  This routine is just like| `roundAndPackFloatx80' except that the input significand does not have to be| normalized.*----------------------------------------------------------------------------*}function normalizeRoundAndPackFloatx80(roundingPrecision: int8; zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): floatx80;var    shiftCount: int8;begin    if ( zSig0 = 0 ) then begin        zSig0 := zSig1;        zSig1 := 0;        dec( zExp, 64 );    end;    shiftCount := countLeadingZeros64( zSig0 );    shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );    zExp := zExp - shiftCount;    result :=        roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );end;{*----------------------------------------------------------------------------| Returns the result of converting the extended double-precision floating-| point value `a' to the 32-bit two's complement integer format.  The| conversion is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic---which means in particular that the conversion| is rounded according to the current rounding mode.  If `a' is a NaN, the| largest positive integer is returned.  Otherwise, if the conversion| overflows, the largest integer with the same sign as `a' is returned.*----------------------------------------------------------------------------*}function floatx80_to_int32(a: floatx80): int32;var    aSign: flag;    aExp, shiftCount: int32;    aSig: bits64;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    if ( aExp = $7FFF ) and ( bits64( aSig shl 1 ) <> 0 ) then aSign := 0;    shiftCount := $4037 - aExp;    if ( shiftCount <= 0 ) then shiftCount := 1;    shift64RightJamming( aSig, shiftCount, aSig );    result := roundAndPackInt32( aSign, aSig );end;{*----------------------------------------------------------------------------| Returns the result of converting the extended double-precision floating-| point value `a' to the 32-bit two's complement integer format.  The| conversion is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic, except that the conversion is always rounded| toward zero.  If `a' is a NaN, the largest positive integer is returned.| Otherwise, if the conversion overflows, the largest integer with the same| sign as `a' is returned.*----------------------------------------------------------------------------*}function floatx80_to_int32_round_to_zero(a: floatx80): int32;var    aSign: flag;    aExp, shiftCount: int32;    aSig, savedASig: bits64;    z: int32;label    invalid;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    if ( $401E < aExp ) then begin        if ( aExp = $7FFF ) and ( bits64( aSig shl 1 )<>0 ) then aSign := 0;        goto invalid;    end    else if ( aExp < $3FFF ) then begin        if ( aExp or aSig <> 0 ) then set_inexact_flag;        result := 0;        exit;    end;    shiftCount := $403E - aExp;    savedASig := aSig;    aSig := aSig shr shiftCount;    z := aSig;    if ( aSign <> 0 ) then z := - z;    if ( ord( z < 0 ) xor aSign ) <> 0 then begin invalid:        float_raise( float_flag_invalid );        if aSign <> 0 then result := sbits32( $80000000 ) else result := $7FFFFFFF;        exit;    end;    if ( ( aSig shl shiftCount ) <> savedASig ) then begin        set_inexact_flag;    end;    result := z;end;{*----------------------------------------------------------------------------| Returns the result of converting the extended double-precision floating-| point value `a' to the 64-bit two's complement integer format.  The| conversion is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic---which means in particular that the conversion| is rounded according to the current rounding mode.  If `a' is a NaN,| the largest positive integer is returned.  Otherwise, if the conversion| overflows, the largest integer with the same sign as `a' is returned.*----------------------------------------------------------------------------*}function floatx80_to_int64(a: floatx80): int64;var    aSign: flag;    aExp, shiftCount: int32;    aSig, aSigExtra: bits64;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    shiftCount := $403E - aExp;    if ( shiftCount <= 0 ) then begin        if ( shiftCount <> 0 ) then begin            float_raise( float_flag_invalid );            if (    ( aSign = 0 )                 or (    ( aExp = $7FFF )                      and ( aSig <> bits64( $8000000000000000 ) ) )               ) then begin                result := $7FFFFFFFFFFFFFFF;                exit;            end;            result := $8000000000000000;            exit;        end;        aSigExtra := 0;    end    else begin        shift64ExtraRightJamming( aSig, 0, shiftCount, aSig, aSigExtra );    end;    result := roundAndPackInt64( aSign, aSig, aSigExtra );end;{*----------------------------------------------------------------------------| Returns the result of converting the extended double-precision floating-| point value `a' to the 64-bit two's complement integer format.  The| conversion is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic, except that the conversion is always rounded| toward zero.  If `a' is a NaN, the largest positive integer is returned.| Otherwise, if the conversion overflows, the largest integer with the same| sign as `a' is returned.*----------------------------------------------------------------------------*}function floatx80_to_int64_round_to_zero(a: floatx80): int64;var    aSign: flag;    aExp, shiftCount: int32;    aSig: bits64;    z: int64;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    shiftCount := aExp - $403E;    if ( 0 <= shiftCount ) then begin        aSig := $7FFFFFFFFFFFFFFF;        if ( ( a.high <> $C03E ) or ( aSig <> 0 ) ) then begin            float_raise( float_flag_invalid );            if ( ( aSign = 0 ) or ( ( aExp = $7FFF ) and ( aSig <> 0 ) ) ) then begin                result := $7FFFFFFFFFFFFFFF;                exit;            end;        end;        result := $8000000000000000;        exit;    end    else if ( aExp < $3FFF ) then begin        if ( aExp or aSig <> 0 ) then set_inexact_flag;        result := 0;        exit;    end;    z := aSig shr ( - shiftCount );    if bits64( aSig shl ( shiftCount and 63 ) ) <> 0 then begin        set_inexact_flag;    end;    if ( aSign <> 0 ) then z := - z;    result := z;end;{*----------------------------------------------------------------------------| The pattern for a default generated extended double-precision NaN.  The| `high' and `low' values hold the most- and least-significant bits,| respectively.*----------------------------------------------------------------------------*}const    floatx80_default_nan_high = $FFFF;    floatx80_default_nan_low  = bits64( $C000000000000000 );{*----------------------------------------------------------------------------| Returns 1 if the extended double-precision floating-point value `a' is a| signaling NaN; otherwise returns 0.*----------------------------------------------------------------------------*}function floatx80_is_signaling_nan(a : floatx80): flag;var    aLow: bits64;begin    aLow := a.low and not $4000000000000000;    result := ord(           ( a.high and $7FFF = $7FFF )       and ( bits64( aLow shl 1 ) <> 0 )       and ( a.low = aLow ) );end;{*----------------------------------------------------------------------------| Returns the result of converting the extended double-precision floating-| point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the| invalid exception is raised.*----------------------------------------------------------------------------*}function floatx80ToCommonNaN(a : floatx80): commonNaNT;var    z: commonNaNT;begin    if floatx80_is_signaling_nan( a ) <> 0 then float_raise( float_flag_invalid );    z.sign := a.high shr 15;    z.low := 0;    z.high := a.low shl 1;    result := z;end;{*----------------------------------------------------------------------------| Returns 1 if the extended double-precision floating-point value `a' is a| NaN; otherwise returns 0.*----------------------------------------------------------------------------*}function floatx80_is_nan(a : floatx80 ): flag;begin    result := ord( ( ( a.high and $7FFF ) = $7FFF ) and ( bits64( a.low shl 1 ) <> 0 ) );end;{*----------------------------------------------------------------------------| Takes two extended double-precision floating-point values `a' and `b', one| of which is a NaN, and returns the appropriate NaN result.  If either `a' or| `b' is a signaling NaN, the invalid exception is raised.*----------------------------------------------------------------------------*}function propagateFloatx80NaN(a, b: floatx80): floatx80;var    aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;label    returnLargerSignificand;begin    aIsNaN := floatx80_is_nan( a );    aIsSignalingNaN := floatx80_is_signaling_nan( a );    bIsNaN := floatx80_is_nan( b );    bIsSignalingNaN := floatx80_is_signaling_nan( b );    a.low := a.low or $C000000000000000;    b.low := b.low or $C000000000000000;    if aIsSignalingNaN or bIsSignalingNaN <> 0 then float_raise( float_flag_invalid );    if aIsSignalingNaN <> 0 then begin        if bIsSignalingNaN <> 0 then goto returnLargerSignificand;        if bIsNaN <> 0 then result := b else result := a;        exit;    end    else if aIsNaN <>0 then begin        if ( bIsSignalingNaN <> 0 ) or ( bIsNaN = 0) then begin            result := a;            exit;        end; returnLargerSignificand:        if ( a.low < b.low ) then begin            result := b;            exit;        end;        if ( b.low < a.low ) then begin            result := a;            exit;        end;        if a.high < b.high then result := a else result := b;        exit;    end    else        result := b;end;{*----------------------------------------------------------------------------| Returns the result of converting the extended double-precision floating-| point value `a' to the single-precision floating-point format.  The| conversion is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_to_float32(a: floatx80): float32;var    aSign: flag;    aExp: int32;    aSig: bits64;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    if ( aExp = $7FFF ) then begin        if bits64( aSig shl 1 ) <> 0 then begin            result := commonNaNToFloat32( floatx80ToCommonNaN( a ) );            exit;        end;        result := packFloat32( aSign, $FF, 0 );        exit;    end;    shift64RightJamming( aSig, 33, aSig );    if ( aExp or aSig <> 0 ) then dec( aExp, $3F81 );    result := roundAndPackFloat32( aSign, aExp, aSig );end;{*----------------------------------------------------------------------------| Returns the result of converting the extended double-precision floating-| point value `a' to the double-precision floating-point format.  The| conversion is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_to_float64(a: floatx80): float64;var    aSign: flag;    aExp: int32;    aSig, zSig: bits64;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    if ( aExp = $7FFF ) then begin        if bits64( aSig shl 1 ) <> 0 then begin            result:=commonNaNToFloat64(floatx80ToCommonNaN(a));            exit;        end;        result := packFloat64( aSign, $7FF, 0 );        exit;    end;    shift64RightJamming( aSig, 1, zSig );    if ( aExp or aSig <> 0 ) then dec( aExp, $3C01 );    result := roundAndPackFloat64( aSign, aExp, zSig );end;{$ifdef FPC_SOFTFLOAT_FLOAT128}{*----------------------------------------------------------------------------| Returns the result of converting the extended double-precision floating-| point value `a' to the quadruple-precision floating-point format.  The| conversion is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_to_float128(a: floatx80): float128;var    aSign: flag;    aExp: int16;    aSig, zSig0, zSig1: bits64;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    if ( aExp = $7FFF ) and ( bits64( aSig shl 1 ) <> 0 ) then begin        result := commonNaNToFloat128( floatx80ToCommonNaN( a ) );        exit;    end;    shift128Right( aSig shl 1, 0, 16, zSig0, zSig1 );    result := packFloat128( aSign, aExp, zSig0, zSig1 );end;{$endif FPC_SOFTFLOAT_FLOAT128}{*----------------------------------------------------------------------------| Rounds the extended double-precision floating-point value `a' to an integer,| and Returns the result as an extended quadruple-precision floating-point| value.  The operation is performed according to the IEC/IEEE Standard for| Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_round_to_int(a: floatx80): floatx80;var    aSign: flag;    aExp: int32;    lastBitMask, roundBitsMask: bits64;    roundingMode: TFPURoundingMode;    z: floatx80;begin    aExp := extractFloatx80Exp( a );    if ( $403E <= aExp ) then begin        if ( aExp = $7FFF ) and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) then begin            result := propagateFloatx80NaN( a, a );            exit;        end;        result := a;        exit;    end;    if ( aExp < $3FFF ) then begin        if (    ( aExp = 0 )             and ( bits64( extractFloatx80Frac( a ) shl 1 ) = 0 ) ) then begin            result := a;            exit;        end;        set_inexact_flag;        aSign := extractFloatx80Sign( a );        case softfloat_rounding_mode of         float_round_nearest_even:            if ( ( aExp = $3FFE ) and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 )               ) then begin                result :=                    packFloatx80( aSign, $3FFF, bits64( $8000000000000000 ) );                exit;            end;         float_round_down: begin            if aSign <> 0 then                result := packFloatx80( 1, $3FFF, bits64( $8000000000000000 ) )            else                result := packFloatx80( 0, 0, 0 );            exit;            end;         float_round_up: begin            if aSign <> 0 then                result := packFloatx80( 1, 0, 0 )            else                result := packFloatx80( 0, $3FFF, bits64( $8000000000000000 ) );            exit;            end;        end;        result := packFloatx80( aSign, 0, 0 );        exit;    end;    lastBitMask := 1;    lastBitMask := lastBitMask shl ( $403E - aExp );    roundBitsMask := lastBitMask - 1;    z := a;    roundingMode := softfloat_rounding_mode;    if ( roundingMode = float_round_nearest_even ) then begin        inc( z.low, lastBitMask shr 1 );        if ( ( z.low and roundBitsMask ) = 0 ) then z.low := z.low and not lastBitMask;    end    else if ( roundingMode <> float_round_to_zero ) then begin        if ( extractFloatx80Sign( z ) <> 0 ) xor ( roundingMode = float_round_up ) then begin            inc( z.low, roundBitsMask );        end;    end;    z.low := z.low and not roundBitsMask;    if ( z.low = 0 ) then begin        inc(z.high);        z.low := bits64( $8000000000000000 );    end;    if ( z.low <> a.low ) then set_inexact_flag;    result := z;end;{*----------------------------------------------------------------------------| Returns the result of adding the absolute values of the extended double-| precision floating-point values `a' and `b'.  If `zSign' is 1, the sum is| negated before being returned.  `zSign' is ignored if the result is a NaN.| The addition is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function addFloatx80Sigs(a: floatx80; b: floatx80; zSign : flag): floatx80;var    aExp, bExp, zExp: int32;    aSig, bSig, zSig0, zSig1: bits64;    expDiff: int32;label    shiftRight1, roundAndPack;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    bSig := extractFloatx80Frac( b );    bExp := extractFloatx80Exp( b );    expDiff := aExp - bExp;    if ( 0 < expDiff ) then begin        if ( aExp = $7FFF ) then begin            if ( bits64( aSig shl 1 ) <> 0 ) then begin                result := propagateFloatx80NaN( a, b );                exit;            end;            result := a;            exit;        end;        if ( bExp = 0 ) then dec(expDiff);        shift64ExtraRightJamming( bSig, 0, expDiff, bSig, zSig1 );        zExp := aExp;    end    else if ( expDiff < 0 ) then begin        if ( bExp = $7FFF ) then begin            if ( bits64( bSig shl 1 ) <> 0 ) then begin                result := propagateFloatx80NaN( a, b );                exit;            end;            result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );            exit;        end;        if ( aExp = 0 ) then inc(expDiff);        shift64ExtraRightJamming( aSig, 0, - expDiff, aSig, zSig1 );        zExp := bExp;    end    else begin        if ( aExp = $7FFF ) then begin            if ( bits64( ( aSig or bSig ) shl 1 ) <> 0 ) then begin                result := propagateFloatx80NaN( a, b );                exit;            end;            result := a;            exit;        end;        zSig1 := 0;        zSig0 := aSig + bSig;        if ( aExp = 0 ) then begin            normalizeFloatx80Subnormal( zSig0, zExp, zSig0 );            goto roundAndPack;        end;        zExp := aExp;        goto shiftRight1;    end;    zSig0 := aSig + bSig;    if ( sbits64( zSig0 ) < 0 ) then goto roundAndPack; shiftRight1:    shift64ExtraRightJamming( zSig0, zSig1, 1, zSig0, zSig1 );    zSig0 := zSig0 or $8000000000000000;    inc(zExp); roundAndPack:    result :=        roundAndPackFloatx80(            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );end;{*----------------------------------------------------------------------------| Returns the result of subtracting the absolute values of the extended| double-precision floating-point values `a' and `b'.  If `zSign' is 1, the| difference is negated before being returned.  `zSign' is ignored if the| result is a NaN.  The subtraction is performed according to the IEC/IEEE| Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function subFloatx80Sigs(a: floatx80; b: floatx80; zSign : flag): floatx80;var    aExp, bExp, zExp: int32;    aSig, bSig, zSig0, zSig1: bits64;    expDiff: int32;    z: floatx80;label    bExpBigger, bBigger, aExpBigger, aBigger, normalizeRoundAndPack;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    bSig := extractFloatx80Frac( b );    bExp := extractFloatx80Exp( b );    expDiff := aExp - bExp;    if ( 0 < expDiff ) then goto aExpBigger;    if ( expDiff < 0 ) then goto bExpBigger;    if ( aExp = $7FFF ) then begin        if ( bits64( ( aSig or bSig ) shl 1 ) <> 0 ) then begin            result := propagateFloatx80NaN( a, b );            exit;        end;        float_raise( float_flag_invalid );        z.low := floatx80_default_nan_low;        z.high := floatx80_default_nan_high;        result := z;        exit;    end;    if ( aExp = 0 ) then begin        aExp := 1;        bExp := 1;    end;    zSig1 := 0;    if ( bSig < aSig ) then goto aBigger;    if ( aSig < bSig ) then goto bBigger;    result := packFloatx80( ord( softfloat_rounding_mode = float_round_down ), 0, 0 );    exit; bExpBigger:    if ( bExp = $7FFF ) then begin        if ( bits64( bSig shl 1 ) <> 0 ) then begin            result := propagateFloatx80NaN( a, b );            exit;        end;        result := packFloatx80( zSign xor 1, $7FFF, bits64( $8000000000000000 ) );        exit;    end;    if ( aExp = 0 ) then inc(expDiff);    shift128RightJamming( aSig, 0, - expDiff, aSig, zSig1 ); bBigger:    sub128( bSig, 0, aSig, zSig1, zSig0, zSig1 );    zExp := bExp;    zSign := zSign xor  1;    goto normalizeRoundAndPack; aExpBigger:    if ( aExp = $7FFF ) then begin        if ( bits64( aSig shl 1 ) <> 0 ) then begin            result := propagateFloatx80NaN( a, b );            exit;        end;        result := a;        exit;    end;    if ( bExp = 0 ) then dec(expDiff);    shift128RightJamming( bSig, 0, expDiff, bSig, zSig1 ); aBigger:    sub128( aSig, 0, bSig, zSig1, zSig0, zSig1 );    zExp := aExp; normalizeRoundAndPack:    result :=        normalizeRoundAndPackFloatx80(            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );end;{*----------------------------------------------------------------------------| Returns the result of adding the extended double-precision floating-point| values `a' and `b'.  The operation is performed according to the IEC/IEEE| Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_add(a: floatx80; b: floatx80): floatx80;var    aSign, bSign: flag;begin    aSign := extractFloatx80Sign( a );    bSign := extractFloatx80Sign( b );    if ( aSign = bSign ) then begin        result := addFloatx80Sigs( a, b, aSign );    end    else begin        result := subFloatx80Sigs( a, b, aSign );    end;end;{*----------------------------------------------------------------------------| Returns the result of subtracting the extended double-precision floating-| point values `a' and `b'.  The operation is performed according to the| IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_sub(a: floatx80; b: floatx80 ): floatx80;var    aSign, bSign: flag;begin    aSign := extractFloatx80Sign( a );    bSign := extractFloatx80Sign( b );    if ( aSign = bSign ) then begin        result := subFloatx80Sigs( a, b, aSign );    end    else begin        result := addFloatx80Sigs( a, b, aSign );    end;end;{*----------------------------------------------------------------------------| Returns the result of multiplying the extended double-precision floating-| point values `a' and `b'.  The operation is performed according to the| IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_mul(a: floatx80; b: floatx80): floatx80;var    aSign, bSign, zSign: flag;    aExp, bExp, zExp: int32;    aSig, bSig, zSig0, zSig1: bits64;    z: floatx80;label    invalid;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    bSig := extractFloatx80Frac( b );    bExp := extractFloatx80Exp( b );    bSign := extractFloatx80Sign( b );    zSign := aSign xor bSign;    if ( aExp = $7FFF ) then begin        if ( bits64( aSig shl 1 ) <> 0 )             or ( ( bExp = $7FFF ) and ( bits64( bSig shl 1 ) <> 0 ) ) then begin            result := propagateFloatx80NaN( a, b );            exit;        end;        if ( ( bExp or bSig ) = 0 ) then goto invalid;        result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );        exit;    end;    if ( bExp = $7FFF ) then begin        if ( bits64( bSig shl 1 ) <> 0 ) then begin            result := propagateFloatx80NaN( a, b );            exit;        end;        if ( ( aExp or aSig ) = 0 ) then begin invalid:            float_raise( float_flag_invalid );            z.low := floatx80_default_nan_low;            z.high := floatx80_default_nan_high;            result := z;            exit;        end;        result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );        exit;    end;    if ( aExp = 0 ) then begin        if ( aSig = 0 ) then begin            result := packFloatx80( zSign, 0, 0 );            exit;        end;        normalizeFloatx80Subnormal( aSig, aExp, aSig );    end;    if ( bExp = 0 ) then begin        if ( bSig = 0 ) then begin            result := packFloatx80( zSign, 0, 0 );            exit;        end;        normalizeFloatx80Subnormal( bSig, bExp, bSig );    end;    zExp := aExp + bExp - $3FFE;    mul64To128( aSig, bSig, zSig0, zSig1 );    if 0 < sbits64( zSig0 ) then begin        shortShift128Left( zSig0, zSig1, 1, zSig0, zSig1 );        dec(zExp);    end;    result :=        roundAndPackFloatx80(            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );end;{*----------------------------------------------------------------------------| Returns the result of dividing the extended double-precision floating-point| value `a' by the corresponding value `b'.  The operation is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_div(a: floatx80; b: floatx80 ): floatx80;var    aSign, bSign, zSign: flag;    aExp, bExp, zExp: int32;    aSig, bSig, zSig0, zSig1: bits64;    rem0, rem1, rem2, term0, term1, term2: bits64;    z: floatx80;label    invalid;begin    aSig := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    bSig := extractFloatx80Frac( b );    bExp := extractFloatx80Exp( b );    bSign := extractFloatx80Sign( b );    zSign := aSign xor bSign;    if ( aExp = $7FFF ) then begin        if ( bits64( aSig shl 1 ) <> 0 ) then begin            result := propagateFloatx80NaN( a, b );            exit;        end;        if ( bExp = $7FFF ) then begin            if ( bits64( bSig shl 1 ) <> 0 ) then begin                result := propagateFloatx80NaN( a, b );                exit;            end;            goto invalid;        end;        result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );        exit;    end;    if ( bExp = $7FFF ) then begin        if ( bits64( bSig shl 1 ) <> 0 ) then begin            result := propagateFloatx80NaN( a, b );            exit;        end;        result := packFloatx80( zSign, 0, 0 );        exit;    end;    if ( bExp = 0 ) then begin        if ( bSig = 0 ) then begin            if ( ( aExp or aSig ) = 0 ) then begin invalid:                float_raise( float_flag_invalid );                z.low := floatx80_default_nan_low;                z.high := floatx80_default_nan_high;                result := z;                exit;            end;            float_raise( float_flag_divbyzero );            result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );            exit;        end;        normalizeFloatx80Subnormal( bSig, bExp, bSig );    end;    if ( aExp = 0 ) then begin        if ( aSig = 0 ) then begin            result := packFloatx80( zSign, 0, 0 );            exit;        end;        normalizeFloatx80Subnormal( aSig, aExp, aSig );    end;    zExp := aExp - bExp + $3FFE;    rem1 := 0;    if ( bSig <= aSig ) then begin        shift128Right( aSig, 0, 1, aSig, rem1 );        inc(zExp);    end;    zSig0 := estimateDiv128To64( aSig, rem1, bSig );    mul64To128( bSig, zSig0, term0, term1 );    sub128( aSig, rem1, term0, term1, rem0, rem1 );    while ( sbits64( rem0 ) < 0 ) do begin        dec(zSig0);        add128( rem0, rem1, 0, bSig, rem0, rem1 );    end;    zSig1 := estimateDiv128To64( rem1, 0, bSig );    if ( bits64( zSig1 shl 1 ) <= 8 ) then begin        mul64To128( bSig, zSig1, term1, term2 );        sub128( rem1, 0, term1, term2, rem1, rem2 );        while ( sbits64( rem1 ) < 0 ) do begin            dec(zSig1);            add128( rem1, rem2, 0, bSig, rem1, rem2 );        end;        zSig1 := zSig1 or ord( ( rem1 or rem2 ) <> 0 );    end;    result :=        roundAndPackFloatx80(            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );end;{*----------------------------------------------------------------------------| Returns the remainder of the extended double-precision floating-point value| `a' with respect to the corresponding value `b'.  The operation is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_rem(a: floatx80; b: floatx80 ): floatx80;var    aSign, zSign: flag;    aExp, bExp, expDiff: int32;    aSig0, aSig1, bSig: bits64;    q, term0, term1, alternateASig0, alternateASig1: bits64;    z: floatx80;label    invalid;begin    aSig0 := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    bSig := extractFloatx80Frac( b );    bExp := extractFloatx80Exp( b );    if ( aExp = $7FFF ) then begin        if ( bits64( aSig0 shl 1 ) <> 0 )             or ( ( bExp = $7FFF ) and ( bits64( bSig shl 1 ) <> 0 ) ) then begin            result := propagateFloatx80NaN( a, b );            exit;        end;        goto invalid;    end;    if ( bExp = $7FFF ) then begin        if ( bits64( bSig shl 1 ) <> 0 ) then begin            result := propagateFloatx80NaN( a, b );            exit;        end;        result := a;        exit;    end;    if ( bExp = 0 ) then begin        if ( bSig = 0 ) then begin invalid:            float_raise( float_flag_invalid );            z.low := floatx80_default_nan_low;            z.high := floatx80_default_nan_high;            result := z;            exit;        end;        normalizeFloatx80Subnormal( bSig, bExp, bSig );    end;    if ( aExp = 0 ) then begin        if ( bits64( aSig0 shl 1 ) = 0 ) then begin            result := a;            exit;        end;        normalizeFloatx80Subnormal( aSig0, aExp, aSig0 );    end;    bSig := bSig or $8000000000000000;    zSign := aSign;    expDiff := aExp - bExp;    aSig1 := 0;    if ( expDiff < 0 ) then begin        if ( expDiff < -1 ) then begin            result := a;            exit;        end;        shift128Right( aSig0, 0, 1, aSig0, aSig1 );        expDiff := 0;    end;    q := ord( bSig <= aSig0 );    if ( q <> 0 ) then dec( aSig0, bSig );    dec( expDiff, 64 );    while ( 0 < expDiff ) do begin        q := estimateDiv128To64( aSig0, aSig1, bSig );        if ( 2 < q ) then q := q - 2 else q := 0;        mul64To128( bSig, q, term0, term1 );        sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );        shortShift128Left( aSig0, aSig1, 62, aSig0, aSig1 );        dec( expDiff, 62 );    end;    inc( expDiff, 64 );    if ( 0 < expDiff ) then begin        q := estimateDiv128To64( aSig0, aSig1, bSig );        if ( 2 < q ) then q:= q - 2 else q := 0;        q := q shr ( 64 - expDiff );        mul64To128( bSig, q shl ( 64 - expDiff ), term0, term1 );        sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );        shortShift128Left( 0, bSig, 64 - expDiff, term0, term1 );        while ( le128( term0, term1, aSig0, aSig1 ) <> 0 ) do begin            inc(q);            sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );        end;    end    else begin        term1 := 0;        term0 := bSig;    end;    sub128( term0, term1, aSig0, aSig1, alternateASig0, alternateASig1 );    if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) <> 0 )         or ( ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) <> 0 )              and ( q and 1 <> 0 ) )       then begin        aSig0 := alternateASig0;        aSig1 := alternateASig1;        zSign := ord( zSign = 0 );    end;    result :=        normalizeRoundAndPackFloatx80(            80, zSign, bExp + expDiff, aSig0, aSig1 );end;{*----------------------------------------------------------------------------| Returns the square root of the extended double-precision floating-point| value `a'.  The operation is performed according to the IEC/IEEE Standard| for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_sqrt(a: floatx80): floatx80;var    aSign: flag;    aExp, zExp: int32;    aSig0, aSig1, zSig0, zSig1, doubleZSig0: bits64;    rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;    z: floatx80;label    invalid;begin    aSig0 := extractFloatx80Frac( a );    aExp := extractFloatx80Exp( a );    aSign := extractFloatx80Sign( a );    if ( aExp = $7FFF ) then begin        if ( bits64( aSig0 shl 1 ) <> 0 ) then begin            result := propagateFloatx80NaN( a, a );            exit;        end;        if ( aSign = 0 ) then begin            result := a;            exit;        end;        goto invalid;    end;    if ( aSign <> 0 ) then begin        if ( ( aExp or aSig0 ) = 0 ) then begin            result := a;            exit;        end; invalid:        float_raise( float_flag_invalid );        z.low := floatx80_default_nan_low;        z.high := floatx80_default_nan_high;        result := z;        exit;    end;    if ( aExp = 0 ) then begin        if ( aSig0 = 0 ) then begin            result := packFloatx80( 0, 0, 0 );            exit;        end;        normalizeFloatx80Subnormal( aSig0, aExp, aSig0 );    end;    zExp := ( ( aExp - $3FFF ) shr 1 ) + $3FFF;    zSig0 := estimateSqrt32( aExp, aSig0 shr 32 );    shift128Right( aSig0, 0, 2 + ( aExp and 1 ), aSig0, aSig1 );    zSig0 := estimateDiv128To64( aSig0, aSig1, zSig0 shl 32 ) + ( zSig0 shl 30 );    doubleZSig0 := zSig0 shl 1;    mul64To128( zSig0, zSig0, term0, term1 );    sub128( aSig0, aSig1, term0, term1, rem0, rem1 );    while ( sbits64( rem0 ) < 0 ) do begin        dec(zSig0);        dec( doubleZSig0, 2 );        add128( rem0, rem1, zSig0 shr 63, doubleZSig0 or 1, rem0, rem1 );    end;    zSig1 := estimateDiv128To64( rem1, 0, doubleZSig0 );    if ( ( zSig1 and $3FFFFFFFFFFFFFFF ) <= 5 ) then begin        if ( zSig1 = 0 ) then zSig1 := 1;        mul64To128( doubleZSig0, zSig1, term1, term2 );        sub128( rem1, 0, term1, term2, rem1, rem2 );        mul64To128( zSig1, zSig1, term2, term3 );        sub192( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );        while ( sbits64( rem1 ) < 0 ) do begin            dec(zSig1);            shortShift128Left( 0, zSig1, 1, term2, term3 );            term3 := term3 or 1;            term2 := term2 or doubleZSig0;            add192( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );        end;        zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );    end;    shortShift128Left( 0, zSig1, 1, zSig0, zSig1 );    zSig0 := zSig0 or doubleZSig0;    result :=        roundAndPackFloatx80(            floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );end;{*----------------------------------------------------------------------------| Returns 1 if the extended double-precision floating-point value `a' is| equal to the corresponding value `b', and 0 otherwise.  The comparison is| performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*}function floatx80_eq(a: floatx80; b: floatx80 ): flag;begin    if      (    ( extractFloatx80Exp( a ) = $7FFF )              and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 )       ) or (    ( extractFloatx80Exp( b ) = $7FFF )              and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 )       ) then begin        if (    floatx80_is_signaling_nan( a )             or floatx80_is_signaling_nan( b ) <> 0 ) then begin            float_raise( float_flag_invalid );        end;        result := 0;        exit;    end;    result := ord(           ( a.low = b.low )        and (    ( a.high = b.high )             or (    ( a.low = 0 )                  and ( bits16 ( ( a.high or b.high ) shl 1 ) = 0 ) )           ) );end;{*----------------------------------------------------------------------------| Returns 1 if the extended double-precision floating-point value `a' is| less than or equal to the corresponding value `b', and 0 otherwise.  The| comparison is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_le(a: floatx80; b: floatx80 ): flag;var    aSign, bSign: flag;begin    if      (     ( extractFloatx80Exp( a ) = $7FFF )              and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )         or (     ( extractFloatx80Exp( b ) = $7FFF )              and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )    then begin        float_raise( float_flag_invalid );        result := 0;        exit;    end;    aSign := extractFloatx80Sign( a );    bSign := extractFloatx80Sign( b );    if ( aSign <> bSign ) then begin        result := ord(               ( aSign <> 0 )            or ( bits16( ( a.high or b.high ) shl 1 ) or a.low or b.low = 0 ) );        exit;    end;    if aSign<>0 then        result := le128( b.high, b.low, a.high, a.low )    else        result := le128( a.high, a.low, b.high, b.low );end;{*----------------------------------------------------------------------------| Returns 1 if the extended double-precision floating-point value `a' is| less than the corresponding value `b', and 0 otherwise.  The comparison| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*}function floatx80_lt(a: floatx80; b: floatx80 ): flag;var    aSign, bSign: flag;begin    if      (     ( extractFloatx80Exp( a ) = $7FFF )              and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )         or (     ( extractFloatx80Exp( b ) = $7FFF )              and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )    then begin        float_raise( float_flag_invalid );        result := 0;        exit;    end;    aSign := extractFloatx80Sign( a );    bSign := extractFloatx80Sign( b );    if ( aSign <> bSign ) then begin        result := ord(                ( aSign <> 0 )            and ( bits16( ( a.high or b.high ) shl 1 ) or a.low or b.low <> 0 ) );        exit;    end;    if aSign <> 0 then        result := lt128( b.high, b.low, a.high, a.low )    else        result := lt128( a.high, a.low, b.high, b.low );end;{*----------------------------------------------------------------------------| Returns 1 if the extended double-precision floating-point value `a' is equal| to the corresponding value `b', and 0 otherwise.  The invalid exception is| raised if either operand is a NaN.  Otherwise, the comparison is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_eq_signaling(a: floatx80; b: floatx80 ): flag;begin    if      (     ( extractFloatx80Exp( a ) = $7FFF )              and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )         or (     ( extractFloatx80Exp( b ) = $7FFF )              and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )    then begin        float_raise( float_flag_invalid );        result := 0;        exit;    end;    result := ord(           ( a.low = b.low )        and (    ( a.high = b.high )             or (    ( a.low = 0 )                  and ( bits16( ( a.high or b.high ) shl 1 ) = 0 ) )           )     );end;{*----------------------------------------------------------------------------| Returns 1 if the extended double-precision floating-point value `a' is less| than or equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs| do not cause an exception.  Otherwise, the comparison is performed according| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_le_quiet(a: floatx80; b: floatx80 ): flag;var    aSign, bSign: flag;begin    if      (    ( extractFloatx80Exp( a ) = $7FFF )             and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )         or (    ( extractFloatx80Exp( b ) = $7FFF )             and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )    then begin        if (    floatx80_is_signaling_nan( a )             or floatx80_is_signaling_nan( b ) <> 0 ) then begin            float_raise( float_flag_invalid );        end;        result := 0;        exit;    end;    aSign := extractFloatx80Sign( a );    bSign := extractFloatx80Sign( b );    if ( aSign <> bSign ) then begin        result := ord(               ( aSign <> 0 )            or ( ( bits16( ( a.high or b.high ) shl 1 ) ) or a.low or b.low = 0 ) );        exit;    end;    if aSign <> 0 then        result := le128( b.high, b.low, a.high, a.low )    else        result := le128( a.high, a.low, b.high, b.low );end;{*----------------------------------------------------------------------------| Returns 1 if the extended double-precision floating-point value `a' is less| than the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause| an exception.  Otherwise, the comparison is performed according to the| IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function floatx80_lt_quiet(a: floatx80; b: floatx80 ): flag;var    aSign, bSign: flag;begin    if      (    ( extractFloatx80Exp( a ) = $7FFF )             and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )         or (    ( extractFloatx80Exp( b ) = $7FFF )             and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )    then begin        if (    floatx80_is_signaling_nan( a )             or floatx80_is_signaling_nan( b ) <> 0 ) then begin            float_raise( float_flag_invalid );        end;        result := 0;        exit;    end;    aSign := extractFloatx80Sign( a );    bSign := extractFloatx80Sign( b );    if ( aSign <> bSign ) then begin        result := ord(               ( aSign <> 0 )            and ( bits16( ( a.high or b.high ) shl 1 ) or a.low or b.low <> 0 ) );        exit;    end;    if aSign <> 0 then        result := lt128( b.high, b.low, a.high, a.low )    else        result := lt128( a.high, a.low, b.high, b.low );end;{$endif FPC_SOFTFLOAT_FLOATX80}{$ifdef FPC_SOFTFLOAT_FLOAT128}{*----------------------------------------------------------------------------| Returns the least-significant 64 fraction bits of the quadruple-precision| floating-point value `a'.*----------------------------------------------------------------------------*}function extractFloat128Frac1(a : float128): bits64;begin    result:=a.low;end;{*----------------------------------------------------------------------------| Returns the most-significant 48 fraction bits of the quadruple-precision| floating-point value `a'.*----------------------------------------------------------------------------*}function extractFloat128Frac0(a : float128): bits64;begin    result:=a.high and int64($0000FFFFFFFFFFFF);end;{*----------------------------------------------------------------------------| Returns the exponent bits of the quadruple-precision floating-point value| `a'.*----------------------------------------------------------------------------*}function extractFloat128Exp(a : float128): int32;begin    result:=( a.high shr 48 ) and $7FFF;end;{*----------------------------------------------------------------------------| Returns the sign bit of the quadruple-precision floating-point value `a'.*----------------------------------------------------------------------------*}function extractFloat128Sign(a : float128): flag;begin    result:=a.high shr 63;end;{*----------------------------------------------------------------------------| Normalizes the subnormal quadruple-precision floating-point value| represented by the denormalized significand formed by the concatenation of| `aSig0' and `aSig1'.  The normalized exponent is stored at the location| pointed to by `zExpPtr'.  The most significant 49 bits of the normalized| significand are stored at the location pointed to by `zSig0Ptr', and the| least significant 64 bits of the normalized significand are stored at the| location pointed to by `zSig1Ptr'.*----------------------------------------------------------------------------*}procedure normalizeFloat128Subnormal(     aSig0: bits64;     aSig1: bits64;     var zExpPtr: int32;     var zSig0Ptr: bits64;     var zSig1Ptr: bits64);var    shiftCount: int8;begin    if ( aSig0 = 0 ) then    begin        shiftCount := countLeadingZeros64( aSig1 ) - 15;        if ( shiftCount < 0 ) then        begin            zSig0Ptr := aSig1 shr ( - shiftCount );            zSig1Ptr := aSig1 shl ( shiftCount and 63 );        end        else begin            zSig0Ptr := aSig1 shl shiftCount;            zSig1Ptr := 0;        end;        zExpPtr := - shiftCount - 63;    end    else begin        shiftCount := countLeadingZeros64( aSig0 ) - 15;        shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );        zExpPtr := 1 - shiftCount;    end;end;{*----------------------------------------------------------------------------| Packs the sign `zSign', the exponent `zExp', and the significand formed| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision| floating-point value, returning the result.  After being shifted into the| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply| added together to form the most significant 32 bits of the result.  This| means that any integer portion of `zSig0' will be added into the exponent.| Since a properly normalized significand will have an integer portion equal| to 1, the `zExp' input should be 1 less than the desired result exponent| whenever `zSig0' and `zSig1' concatenated form a complete, normalized| significand.*----------------------------------------------------------------------------*}function packFloat128( zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64) : float128;var    z: float128;begin    z.low := zSig1;    z.high := ( ( bits64(zSign) ) shl 63 ) + ( ( bits64(zExp) ) shl 48 ) + zSig0;    result:=z;end;{*----------------------------------------------------------------------------| Takes an abstract floating-point value having sign `zSign', exponent `zExp',| and extended significand formed by the concatenation of `zSig0', `zSig1',| and `zSig2', and returns the proper quadruple-precision floating-point value| corresponding to the abstract input.  Ordinarily, the abstract value is| simply rounded and packed into the quadruple-precision format, with the| inexact exception raised if the abstract input cannot be represented| exactly.  However, if the abstract value is too large, the overflow and| inexact exceptions are raised and an infinity or maximal finite value is| returned.  If the abstract value is too small, the input value is rounded to| a subnormal number, and the underflow and inexact exceptions are raised if| the abstract input cannot be represented exactly as a subnormal quadruple-| precision floating-point number.|     The input significand must be normalized or smaller.  If the input| significand is not normalized, `zExp' must be 0; in that case, the result| returned is a subnormal number, and it must not require rounding.  In the| usual case that the input significand is normalized, `zExp' must be 1 less| than the ``true'' floating-point exponent.  The handling of underflow and| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function roundAndPackFloat128(zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64; zSig2: bits64): float128;var    roundingMode: TFPURoundingMode;    roundNearestEven, increment, isTiny: flag;begin    roundingMode := softfloat_rounding_mode;    roundNearestEven := ord( roundingMode = float_round_nearest_even );    increment := ord( sbits64(zSig2) < 0 );    if ( roundNearestEven=0 ) then    begin        if ( roundingMode = float_round_to_zero ) then        begin            increment := 0;        end        else begin            if ( zSign<>0 ) then            begin                increment := ord( roundingMode = float_round_down ) and zSig2;            end            else begin                increment := ord( roundingMode = float_round_up ) and zSig2;            end;        end;    end;    if ( $7FFD <= bits32(zExp) ) then    begin        if (    ord( $7FFD < zExp )             or (    ord( zExp = $7FFD )                  and eq128(                         int64( $0001FFFFFFFFFFFF ),                         bits64( $FFFFFFFFFFFFFFFF ),                         zSig0,                         zSig1                     )                  and increment                )           )<>0 then           begin            float_raise( [float_flag_overflow,float_flag_inexact] );            if (    ord( roundingMode = float_round_to_zero )                 or ( zSign and ord( roundingMode = float_round_up ) )                 or ( ord( zSign = 0) and ord( roundingMode = float_round_down ) )               )<>0 then               begin                result :=                    packFloat128(                        zSign,                        $7FFE,                        int64( $0000FFFFFFFFFFFF ),                        bits64( $FFFFFFFFFFFFFFFF )                    );                exit;            end;            result:=packFloat128( zSign, $7FFF, 0, 0 );            exit;        end;        if ( zExp < 0 ) then        begin            isTiny :=                   ord(( softfloat_detect_tininess = float_tininess_before_rounding )                or ( zExp < -1 )                or not( increment<>0 )                or boolean(lt128(                       zSig0,                       zSig1,                       int64( $0001FFFFFFFFFFFF ),                       bits64( $FFFFFFFFFFFFFFFF )                   )));            shift128ExtraRightJamming(                zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );            zExp := 0;            if ( isTiny and zSig2 )<>0 then              float_raise( float_flag_underflow );            if ( roundNearestEven<>0 ) then            begin                increment := ord( sbits64(zSig2) < 0 );            end            else begin                if ( zSign<>0 ) then                begin                    increment := ord( roundingMode = float_round_down ) and zSig2;                end                else begin                    increment := ord( roundingMode = float_round_up ) and zSig2;                end;            end;        end;    end;    if ( zSig2<>0 ) then      set_inexact_flag;    if ( increment<>0 ) then    begin        add128( zSig0, zSig1, 0, 1, zSig0, zSig1 );        zSig1 := zSig1 and not bits64( ord( zSig2 + zSig2 = 0 ) and roundNearestEven );    end    else begin        if ( ( zSig0 or zSig1 ) = 0 ) then          zExp := 0;    end;    result:=packFloat128( zSign, zExp, zSig0, zSig1 );end;{*----------------------------------------------------------------------------| Takes an abstract floating-point value having sign `zSign', exponent `zExp',| and significand formed by the concatenation of `zSig0' and `zSig1', and| returns the proper quadruple-precision floating-point value corresponding| to the abstract input.  This routine is just like `roundAndPackFloat128'| except that the input significand has fewer bits and does not have to be| normalized.  In all cases, `zExp' must be 1 less than the ``true'' floating-| point exponent.*----------------------------------------------------------------------------*}function normalizeRoundAndPackFloat128(zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): float128;var    shiftCount: int8;    zSig2: bits64;begin    if ( zSig0 = 0 ) then    begin        zSig0 := zSig1;        zSig1 := 0;        dec(zExp, 64);    end;    shiftCount := countLeadingZeros64( zSig0 ) - 15;    if ( 0 <= shiftCount ) then    begin        zSig2 := 0;        shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );    end    else begin        shift128ExtraRightJamming(            zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );    end;    dec(zExp, shiftCount);    result:=roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );end;{*----------------------------------------------------------------------------| Returns the result of converting the quadruple-precision floating-point| value `a' to the 32-bit two's complement integer format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic---which means in particular that the conversion is rounded| according to the current rounding mode.  If `a' is a NaN, the largest| positive integer is returned.  Otherwise, if the conversion overflows, the| largest integer with the same sign as `a' is returned.*----------------------------------------------------------------------------*}function float128_to_int32(a: float128): int32;var    aSign: flag;    aExp, shiftCount: int32;    aSig0, aSig1: bits64;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    if ( ord( aExp = $7FFF ) and ( aSig0 or aSig1 ) )<>0 then      aSign := 0;    if ( aExp<>0 ) then      aSig0 := aSig0 or int64( $0001000000000000 );    aSig0 := aSig0 or ord( aSig1 <> 0 );    shiftCount := $4028 - aExp;    if ( 0 < shiftCount ) then      shift64RightJamming( aSig0, shiftCount, aSig0 );    result := roundAndPackInt32( aSign, aSig0 );end;{*----------------------------------------------------------------------------| Returns the result of converting the quadruple-precision floating-point| value `a' to the 32-bit two's complement integer format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic, except that the conversion is always rounded toward zero.  If| `a' is a NaN, the largest positive integer is returned.  Otherwise, if the| conversion overflows, the largest integer with the same sign as `a' is| returned.*----------------------------------------------------------------------------*}function float128_to_int32_round_to_zero(a: float128): int32;var    aSign: flag;    aExp, shiftCount: int32;    aSig0, aSig1, savedASig: bits64;    z: int32;label    invalid;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    aSig0 := aSig0 or ord( aSig1 <> 0 );    if ( $401E < aExp ) then    begin        if ( ord( aExp = $7FFF ) and aSig0 )<>0 then          aSign := 0;        goto invalid;    end    else if ( aExp < $3FFF ) then    begin        if ( aExp or aSig0 )<>0 then          set_inexact_flag;        result := 0;        exit;    end;    aSig0 := aSig0 or int64( $0001000000000000 );    shiftCount := $402F - aExp;    savedASig := aSig0;    aSig0 := aSig0 shr shiftCount;    z := aSig0;    if ( aSign )<>0 then      z := - z;    if ( ord( z < 0 ) xor aSign )<>0 then    begin invalid:        float_raise( float_flag_invalid );        if aSign<>0 then          result:= int32( $80000000 )        else          result:=$7FFFFFFF;        exit;    end;    if ( ( aSig0 shl shiftCount ) <> savedASig ) then    begin        set_inexact_flag;    end;    result := z;end;{*----------------------------------------------------------------------------| Returns the result of converting the quadruple-precision floating-point| value `a' to the 64-bit two's complement integer format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic---which means in particular that the conversion is rounded| according to the current rounding mode.  If `a' is a NaN, the largest| positive integer is returned.  Otherwise, if the conversion overflows, the| largest integer with the same sign as `a' is returned.*----------------------------------------------------------------------------*}function float128_to_int64(a: float128): int64;var    aSign: flag;    aExp, shiftCount: int32;    aSig0, aSig1: bits64;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    if ( aExp<>0 ) then      aSig0 := aSig0 or int64( $0001000000000000 );    shiftCount := $402F - aExp;    if ( shiftCount <= 0 ) then    begin        if ( $403E < aExp ) then        begin            float_raise( float_flag_invalid );            if (    (aSign=0)                 or (    ( aExp = $7FFF )                      and ( (aSig1<>0) or ( aSig0 <> int64( $0001000000000000 ) ) )                    )               ) then               begin                result := int64( $7FFFFFFFFFFFFFFF );                exit;            end;            result := int64( $8000000000000000 );            exit;        end;        shortShift128Left( aSig0, aSig1, - shiftCount, aSig0, aSig1 );    end    else begin        shift64ExtraRightJamming( aSig0, aSig1, shiftCount, aSig0, aSig1 );    end;    result := roundAndPackInt64( aSign, aSig0, aSig1 );end;{*----------------------------------------------------------------------------| Returns the result of converting the quadruple-precision floating-point| value `a' to the 64-bit two's complement integer format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic, except that the conversion is always rounded toward zero.| If `a' is a NaN, the largest positive integer is returned.  Otherwise, if| the conversion overflows, the largest integer with the same sign as `a' is| returned.*----------------------------------------------------------------------------*}function float128_to_int64_round_to_zero(a: float128): int64;var    aSign: flag;    aExp, shiftCount: int32;    aSig0, aSig1: bits64;    z: int64;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    if ( aExp<>0 ) then      aSig0 := aSig0 or int64( $0001000000000000 );    shiftCount := aExp - $402F;    if ( 0 < shiftCount ) then    begin        if ( $403E <= aExp ) then        begin            aSig0 := aSig0 and int64( $0000FFFFFFFFFFFF );            if (    ( a.high = bits64( $C03E000000000000 ) )                 and ( aSig1 < int64( $0002000000000000 ) ) ) then            begin                if ( aSig1<>0 ) then                  set_inexact_flag;            end            else begin                float_raise( float_flag_invalid );                if ( (aSign=0) or ( ( aExp = $7FFF ) and (( aSig0 or aSig1 )<>0) ) ) then                begin                    result := int64( $7FFFFFFFFFFFFFFF );                    exit;                end;            end;            result := int64( $8000000000000000 );            exit;        end;        z := ( aSig0 shl shiftCount ) or ( aSig1 shr ( ( - shiftCount ) and 63 ) );        if ( int64( aSig1 shl shiftCount )<>0 ) then        begin            set_inexact_flag;        end;    end    else begin        if ( aExp < $3FFF ) then        begin            if ( aExp or aSig0 or aSig1 )<>0 then            begin                set_inexact_flag;            end;            result := 0;            exit;        end;        z := aSig0 shr ( - shiftCount );        if (    (aSig1<>0)             or ( (shiftCount<>0) and (int64( aSig0 shl ( shiftCount and 63 ) )<>0) ) ) then        begin            set_inexact_flag;        end;    end;    if ( aSign<>0 ) then      z := - z;    result := z;end;{*----------------------------------------------------------------------------| Returns the result of converting the quadruple-precision floating-point| value `a' to the single-precision floating-point format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*}function float128_to_float32(a: float128): float32;var    aSign: flag;    aExp: int32;    aSig0, aSig1: bits64;    zSig: bits32;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    if ( aExp = $7FFF ) then    begin        if ( aSig0 or aSig1 )<>0 then        begin            result := commonNaNToFloat32( float128ToCommonNaN( a ) );            exit;        end;        result := packFloat32( aSign, $FF, 0 );        exit;    end;    aSig0 := aSig0 or ord( aSig1 <> 0 );    shift64RightJamming( aSig0, 18, aSig0 );    zSig := aSig0;    if ( aExp<>0 ) or (aSig0 <> 0 ) then    begin        zSig := zSig or $40000000;        dec(aExp,$3F81);    end;    result := roundAndPackFloat32( aSign, aExp, zSig );end;{*----------------------------------------------------------------------------| Returns the result of converting the quadruple-precision floating-point| value `a' to the double-precision floating-point format.  The conversion| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*}function float128_to_float64(a: float128): float64;var    aSign: flag;    aExp: int32;    aSig0, aSig1: bits64;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    if ( aExp = $7FFF ) then    begin        if ( aSig0 or aSig1 )<>0 then        begin            result:=commonNaNToFloat64(float128ToCommonNaN(a));            exit;        end;        result:=packFloat64( aSign, $7FF, 0);        exit;    end;    shortShift128Left( aSig0, aSig1, 14, aSig0, aSig1 );    aSig0 := aSig0 or ord( aSig1 <> 0 );    if ( aExp<>0 ) or (aSig0 <> 0 ) then    begin        aSig0 := aSig0 or int64( $4000000000000000 );        dec(aExp,$3C01);    end;    result := roundAndPackFloat64( aSign, aExp, aSig0 );end;{$ifdef FPC_SOFTFLOAT_FLOATX80}{*----------------------------------------------------------------------------| Returns the result of converting the quadruple-precision floating-point| value `a' to the extended double-precision floating-point format.  The| conversion is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_to_floatx80(a: float128): floatx80;var    aSign: flag;    aExp: int32;    aSig0, aSig1: bits64;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    if ( aExp = $7FFF ) then begin        if ( aSig0 or aSig1 <> 0 ) then begin            result := commonNaNToFloatx80( float128ToCommonNaN( a ) );            exit;        end;        result := packFloatx80( aSign, $7FFF, bits64( $8000000000000000 ) );        exit;    end;    if ( aExp = 0 ) then begin        if ( ( aSig0 or aSig1 ) = 0 ) then          begin            result := packFloatx80( aSign, 0, 0 );            exit;          end;        normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );    end    else begin        aSig0 := aSig0 or int64( $0001000000000000 );    end;    shortShift128Left( aSig0, aSig1, 15, aSig0, aSig1 );    result := roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 );end;{$endif FPC_SOFTFLOAT_FLOATX80}{*----------------------------------------------------------------------------| Rounds the quadruple-precision floating-point value `a' to an integer, and| Returns the result as a quadruple-precision floating-point value.  The| operation is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_round_to_int(a: float128): float128;var    aSign: flag;    aExp: int32;    lastBitMask, roundBitsMask: bits64;    roundingMode: TFPURoundingMode;    z: float128;begin    aExp := extractFloat128Exp( a );    if ( $402F <= aExp ) then    begin        if ( $406F <= aExp ) then        begin            if (    ( aExp = $7FFF )                 and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) )<>0)               ) then               begin                result := propagateFloat128NaN( a, a );                exit;            end;            result := a;            exit;        end;        lastBitMask := 1;        lastBitMask := ( lastBitMask shl ( $406E - aExp ) ) shl 1;        roundBitsMask := lastBitMask - 1;        z := a;        roundingMode := softfloat_rounding_mode;        if ( roundingMode = float_round_nearest_even ) then        begin            if ( lastBitMask )<>0 then            begin                add128( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );                if ( ( z.low and roundBitsMask ) = 0 ) then                  z.low := z.low and not(lastBitMask);            end            else begin                if ( sbits64(z.low) < 0 ) then                begin                    inc(z.high);                    if ( bits64( z.low shl 1 ) = 0 ) then                      z.high := z.high and not bits64( 1 );                end;            end;        end        else if ( roundingMode <> float_round_to_zero ) then        begin            if (   extractFloat128Sign( z )                 xor ord( roundingMode = float_round_up ) )<>0 then            begin                add128( z.high, z.low, 0, roundBitsMask, z.high, z.low );            end;        end;        z.low := z.low and not(roundBitsMask);    end    else begin        if ( aExp < $3FFF ) then        begin            if ( ( ( bits64( a.high shl 1 ) ) or a.low ) = 0 ) then              begin                result := a;                exit;              end;            set_inexact_flag;            aSign := extractFloat128Sign( a );            case softfloat_rounding_mode of            float_round_nearest_even:                if (    ( aExp = $3FFE )                     and (   (extractFloat128Frac0( a )<>0)                          or (extractFloat128Frac1( a )<>0) )                   ) then begin                   begin                     result := packFloat128( aSign, $3FFF, 0, 0 );                     exit;                   end;                end;             float_round_down:               begin                 if aSign<>0 then                   result:=packFloat128( 1, $3FFF, 0, 0 )                 else                   result:=packFloat128( 0, 0, 0, 0 );                 exit;               end;             float_round_up:               begin                 if aSign<>0 then                   result := packFloat128( 1, 0, 0, 0 )                 else                   result:=packFloat128( 0, $3FFF, 0, 0 );                exit;               end;            end;            result := packFloat128( aSign, 0, 0, 0 );            exit;        end;        lastBitMask := 1;        lastBitMask  := lastBitMask shl ($402F - aExp);        roundBitsMask := lastBitMask - 1;        z.low := 0;        z.high := a.high;        roundingMode := softfloat_rounding_mode;        if ( roundingMode = float_round_nearest_even ) then begin            inc(z.high,lastBitMask shr 1);            if ( ( ( z.high and roundBitsMask ) or a.low ) = 0 ) then begin                z.high := z.high and not(lastBitMask);            end;        end        else if ( roundingMode <> float_round_to_zero ) then begin            if (   (extractFloat128Sign( z )<>0)                 xor ( roundingMode = float_round_up ) ) then begin                z.high := z.high or ord( a.low <> 0 );                z.high := z.high+roundBitsMask;            end;        end;        z.high := z.high and not(roundBitsMask);    end;    if ( ( z.low <> a.low ) or ( z.high <> a.high ) ) then begin        set_inexact_flag;    end;    result := z;end;{*----------------------------------------------------------------------------| Returns the result of adding the absolute values of the quadruple-precision| floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated| before being returned.  `zSign' is ignored if the result is a NaN.| The addition is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function addFloat128Sigs(a,b : float128; zSign : flag ): float128;var    aExp, bExp, zExp: int32;    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits64;    expDiff: int32;label    shiftRight1,roundAndPack;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    bSig1 := extractFloat128Frac1( b );    bSig0 := extractFloat128Frac0( b );    bExp := extractFloat128Exp( b );    expDiff := aExp - bExp;    if ( 0 < expDiff ) then begin        if ( aExp = $7FFF ) then begin            if ( aSig0 or aSig1 )<>0 then              begin                result := propagateFloat128NaN( a, b );                exit;              end;            result := a;            exit;        end;        if ( bExp = 0 ) then begin            dec(expDiff);        end        else begin            bSig0 := bSig0 or int64( $0001000000000000 );        end;        shift128ExtraRightJamming(            bSig0, bSig1, 0, expDiff, bSig0, bSig1, zSig2 );        zExp := aExp;    end    else if ( expDiff < 0 ) then begin        if ( bExp = $7FFF ) then begin            if ( bSig0 or bSig1 )<>0 then              begin                result := propagateFloat128NaN( a, b );                exit;              end;            result := packFloat128( zSign, $7FFF, 0, 0 );            exit;        end;        if ( aExp = 0 ) then begin            inc(expDiff);        end        else begin            aSig0 := aSig0 or int64( $0001000000000000 );        end;        shift128ExtraRightJamming(            aSig0, aSig1, 0, - expDiff, aSig0, aSig1, zSig2 );        zExp := bExp;    end    else begin        if ( aExp = $7FFF ) then begin            if ( aSig0 or aSig1 or bSig0 or bSig1 )<>0 then begin                result := propagateFloat128NaN( a, b );                exit;            end;            result := a;            exit;        end;        add128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );        if ( aExp = 0 ) then          begin            result := packFloat128( zSign, 0, zSig0, zSig1 );            exit;          end;        zSig2 := 0;        zSig0 := zSig0 or int64( $0002000000000000 );        zExp := aExp;        goto shiftRight1;    end;    aSig0 := aSig0 or int64( $0001000000000000 );    add128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );    dec(zExp);    if ( zSig0 < int64( $0002000000000000 ) ) then goto roundAndPack;    inc(zExp); shiftRight1:    shift128ExtraRightJamming(        zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 ); roundAndPack:    result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );end;{*----------------------------------------------------------------------------| Returns the result of subtracting the absolute values of the quadruple-| precision floating-point values `a' and `b'.  If `zSign' is 1, the| difference is negated before being returned.  `zSign' is ignored if the| result is a NaN.  The subtraction is performed according to the IEC/IEEE| Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function subFloat128Sigs( a, b : float128;  zSign : flag): float128;var    aExp, bExp, zExp: int32;    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits64;    expDiff: int32;    z: float128;label    aExpBigger,bExpBigger,aBigger,bBigger,normalizeRoundAndPack;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    bSig1 := extractFloat128Frac1( b );    bSig0 := extractFloat128Frac0( b );    bExp := extractFloat128Exp( b );    expDiff := aExp - bExp;    shortShift128Left( aSig0, aSig1, 14, aSig0, aSig1 );    shortShift128Left( bSig0, bSig1, 14, bSig0, bSig1 );    if ( 0 < expDiff ) then goto aExpBigger;    if ( expDiff < 0 ) then goto bExpBigger;    if ( aExp = $7FFF ) then begin        if ( aSig0 or aSig1 or bSig0 or bSig1 )<>0 then begin            result := propagateFloat128NaN( a, b );            exit;        end;        float_raise( float_flag_invalid );        z.low := float128_default_nan_low;        z.high := float128_default_nan_high;        result := z;        exit;    end;    if ( aExp = 0 ) then begin        aExp := 1;        bExp := 1;    end;    if ( bSig0 < aSig0 ) then goto aBigger;    if ( aSig0 < bSig0 ) then goto bBigger;    if ( bSig1 < aSig1 ) then goto aBigger;    if ( aSig1 < bSig1 ) then goto bBigger;    result := packFloat128( ord(softfloat_rounding_mode = float_round_down), 0, 0, 0 );    exit; bExpBigger:    if ( bExp = $7FFF ) then begin        if ( bSig0 or bSig1 )<>0 then          begin            result := propagateFloat128NaN( a, b );            exit;          end;        result := packFloat128( zSign xor 1, $7FFF, 0, 0 );        exit;    end;    if ( aExp = 0 ) then begin        inc(expDiff);    end    else begin        aSig0 := aSig0 or int64( $4000000000000000 );    end;    shift128RightJamming( aSig0, aSig1, - expDiff, aSig0, aSig1 );    bSig0 := bSig0 or int64( $4000000000000000 ); bBigger:    sub128( bSig0, bSig1, aSig0, aSig1, zSig0, zSig1 );    zExp := bExp;    zSign := zSign xor 1;    goto normalizeRoundAndPack; aExpBigger:    if ( aExp = $7FFF ) then begin        if ( aSig0 or aSig1 )<>0 then          begin            result := propagateFloat128NaN( a, b );            exit;          end;        result := a;        exit;    end;    if ( bExp = 0 ) then begin        dec(expDiff);    end    else begin        bSig0 := bSig0 or int64( $4000000000000000 );    end;    shift128RightJamming( bSig0, bSig1, expDiff, bSig0, bSig1 );    aSig0 := aSig0 or int64( $4000000000000000 ); aBigger:    sub128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );    zExp := aExp; normalizeRoundAndPack:    dec(zExp);    result := normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 );end;{*----------------------------------------------------------------------------| Returns the result of adding the quadruple-precision floating-point values| `a' and `b'.  The operation is performed according to the IEC/IEEE Standard| for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_add(a: float128; b: float128): float128;var    aSign, bSign: flag;begin    aSign := extractFloat128Sign( a );    bSign := extractFloat128Sign( b );    if ( aSign = bSign ) then begin        result := addFloat128Sigs( a, b, aSign );    end    else begin        result := subFloat128Sigs( a, b, aSign );    end;end;{*----------------------------------------------------------------------------| Returns the result of subtracting the quadruple-precision floating-point| values `a' and `b'.  The operation is performed according to the IEC/IEEE| Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_sub(a: float128; b: float128): float128;var    aSign, bSign: flag;begin    aSign := extractFloat128Sign( a );    bSign := extractFloat128Sign( b );    if ( aSign = bSign ) then begin        result := subFloat128Sigs( a, b, aSign );    end    else begin        result := addFloat128Sigs( a, b, aSign );    end;end;{*----------------------------------------------------------------------------| Returns the result of multiplying the quadruple-precision floating-point| values `a' and `b'.  The operation is performed according to the IEC/IEEE| Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_mul(a: float128; b: float128): float128;var    aSign, bSign, zSign: flag;    aExp, bExp, zExp: int32;    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits64;    z: float128;label    invalid;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    bSig1 := extractFloat128Frac1( b );    bSig0 := extractFloat128Frac0( b );    bExp := extractFloat128Exp( b );    bSign := extractFloat128Sign( b );    zSign := aSign xor bSign;    if ( aExp = $7FFF ) then begin        if (    (( aSig0 or aSig1 )<>0)             or ( ( bExp = $7FFF ) and (( bSig0 or bSig1 )<>0) ) ) then begin            result := propagateFloat128NaN( a, b );            exit;        end;        if ( ( bExp or bSig0 or bSig1 ) = 0 ) then goto invalid;        result := packFloat128( zSign, $7FFF, 0, 0 );        exit;    end;    if ( bExp = $7FFF ) then begin        if ( bSig0 or bSig1 )<>0 then          begin            result := propagateFloat128NaN( a, b );            exit;          end;        if ( ( aExp or aSig0 or aSig1 ) = 0 ) then begin invalid:            float_raise( float_flag_invalid );            z.low := float128_default_nan_low;            z.high := float128_default_nan_high;            result := z;            exit;        end;        result := packFloat128( zSign, $7FFF, 0, 0 );        exit;    end;    if ( aExp = 0 ) then begin        if ( ( aSig0 or aSig1 ) = 0 ) then          begin            result := packFloat128( zSign, 0, 0, 0 );            exit;          end;        normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );    end;    if ( bExp = 0 ) then begin        if ( ( bSig0 or bSig1 ) = 0 ) then          begin            result := packFloat128( zSign, 0, 0, 0 );            exit;          end;        normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );    end;    zExp := aExp + bExp - $4000;    aSig0 := aSig0 or int64( $0001000000000000 );    shortShift128Left( bSig0, bSig1, 16, bSig0, bSig1 );    mul128To256( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3 );    add128( zSig0, zSig1, aSig0, aSig1, zSig0, zSig1 );    zSig2 := zSig2 or ord( zSig3 <> 0 );    if ( int64( $0002000000000000 ) <= zSig0 ) then begin        shift128ExtraRightJamming(            zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );        inc(zExp);    end;    result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );end;{*----------------------------------------------------------------------------| Returns the result of dividing the quadruple-precision floating-point value| `a' by the corresponding value `b'.  The operation is performed according to| the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_div(a: float128; b: float128): float128;var    aSign, bSign, zSign: flag;    aExp, bExp, zExp: int32;    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits64;    rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;    z: float128;label    invalid;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    bSig1 := extractFloat128Frac1( b );    bSig0 := extractFloat128Frac0( b );    bExp := extractFloat128Exp( b );    bSign := extractFloat128Sign( b );    zSign := aSign xor bSign;    if ( aExp = $7FFF ) then begin        if ( aSig0 or aSig1 )<>0 then        begin          result := propagateFloat128NaN( a, b );          exit;        end;        if ( bExp = $7FFF ) then begin            if ( bSig0 or bSig1 )<>0 then              begin                result := propagateFloat128NaN( a, b );                exit;              end;            goto invalid;        end;        result := packFloat128( zSign, $7FFF, 0, 0 );        exit;    end;    if ( bExp = $7FFF ) then begin        if ( bSig0 or bSig1 )<>0 then          begin            result := propagateFloat128NaN( a, b );            exit;          end;        result := packFloat128( zSign, 0, 0, 0 );        exit;    end;    if ( bExp = 0 ) then begin        if ( ( bSig0 or bSig1 ) = 0 ) then begin            if ( ( aExp or aSig0 or aSig1 ) = 0 ) then begin invalid:                float_raise( float_flag_invalid );                z.low := float128_default_nan_low;                z.high := float128_default_nan_high;                result := z;                exit;            end;            float_raise( float_flag_divbyzero );            result := packFloat128( zSign, $7FFF, 0, 0 );            exit;        end;        normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );    end;    if ( aExp = 0 ) then begin        if ( ( aSig0 or aSig1 ) = 0 ) then          begin            result := packFloat128( zSign, 0, 0, 0 );            exit;          end;        normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );    end;    zExp := aExp - bExp + $3FFD;    shortShift128Left(        aSig0 or int64( $0001000000000000 ), aSig1, 15, aSig0, aSig1 );    shortShift128Left(        bSig0 or int64( $0001000000000000 ), bSig1, 15, bSig0, bSig1 );    if ( le128( bSig0, bSig1, aSig0, aSig1 )<>0 ) then begin        shift128Right( aSig0, aSig1, 1, aSig0, aSig1 );        inc(zExp);    end;    zSig0 := estimateDiv128To64( aSig0, aSig1, bSig0 );    mul128By64To192( bSig0, bSig1, zSig0, term0, term1, term2 );    sub192( aSig0, aSig1, 0, term0, term1, term2, rem0, rem1, rem2 );    while ( sbits64(rem0) < 0 ) do begin        dec(zSig0);        add192( rem0, rem1, rem2, 0, bSig0, bSig1, rem0, rem1, rem2 );    end;    zSig1 := estimateDiv128To64( rem1, rem2, bSig0 );    if ( ( zSig1 and $3FFF ) <= 4 ) then begin        mul128By64To192( bSig0, bSig1, zSig1, term1, term2, term3 );        sub192( rem1, rem2, 0, term1, term2, term3, rem1, rem2, rem3 );        while ( sbits64(rem1) < 0 ) do begin            dec(zSig1);            add192( rem1, rem2, rem3, 0, bSig0, bSig1, rem1, rem2, rem3 );        end;        zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );    end;    shift128ExtraRightJamming( zSig0, zSig1, 0, 15, zSig0, zSig1, zSig2 );    result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );end;{*----------------------------------------------------------------------------| Returns the remainder of the quadruple-precision floating-point value `a'| with respect to the corresponding value `b'.  The operation is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_rem(a: float128; b: float128): float128;var    aSign, zSign: flag;    aExp, bExp, expDiff: int32;    aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits64;    allZero, alternateASig0, alternateASig1, sigMean1: bits64;    sigMean0: sbits64;    z: float128;label    invalid;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    bSig1 := extractFloat128Frac1( b );    bSig0 := extractFloat128Frac0( b );    bExp := extractFloat128Exp( b );    if ( aExp = $7FFF ) then begin        if (    (( aSig0 or aSig1 )<>0)             or ( ( bExp = $7FFF ) and (( bSig0 or bSig1 )<>0) ) ) then begin            result := propagateFloat128NaN( a, b );            exit;        end;        goto invalid;    end;    if ( bExp = $7FFF ) then begin        if ( bSig0 or bSig1 )<>0 then          begin            result := propagateFloat128NaN( a, b );            exit;          end;        result := a;        exit;    end;    if ( bExp = 0 ) then begin        if ( ( bSig0 or bSig1 ) = 0 ) then begin invalid:            float_raise( float_flag_invalid );            z.low := float128_default_nan_low;            z.high := float128_default_nan_high;            result := z;            exit;        end;        normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );    end;    if ( aExp = 0 ) then begin        if ( ( aSig0 or aSig1 ) = 0 ) then          begin            result := a;            exit;          end;        normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );    end;    expDiff := aExp - bExp;    if ( expDiff < -1 ) then      begin        result := a;        exit;      end;    shortShift128Left(        aSig0 or int64( $0001000000000000 ),        aSig1,        15 - ord( expDiff < 0 ),        aSig0,        aSig1    );    shortShift128Left(        bSig0 or int64( $0001000000000000 ), bSig1, 15, bSig0, bSig1 );    q := le128( bSig0, bSig1, aSig0, aSig1 );    if ( q )<>0 then sub128( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );    dec(expDiff,64);    while ( 0 < expDiff ) do begin        q := estimateDiv128To64( aSig0, aSig1, bSig0 );        if ( 4 < q ) then          q := q - 4        else          q := 0;        mul128By64To192( bSig0, bSig1, q, term0, term1, term2 );        shortShift192Left( term0, term1, term2, 61, term1, term2, allZero );        shortShift128Left( aSig0, aSig1, 61, aSig0, allZero );        sub128( aSig0, 0, term1, term2, aSig0, aSig1 );        dec(expDiff,61);    end;    if ( -64 < expDiff ) then begin        q := estimateDiv128To64( aSig0, aSig1, bSig0 );        if ( 4 < q ) then          q := q - 4        else          q := 0;        q := q shr (- expDiff);        shift128Right( bSig0, bSig1, 12, bSig0, bSig1 );        inc(expDiff,52);        if ( expDiff < 0 ) then begin            shift128Right( aSig0, aSig1, - expDiff, aSig0, aSig1 );        end        else begin            shortShift128Left( aSig0, aSig1, expDiff, aSig0, aSig1 );        end;        mul128By64To192( bSig0, bSig1, q, term0, term1, term2 );        sub128( aSig0, aSig1, term1, term2, aSig0, aSig1 );    end    else begin        shift128Right( aSig0, aSig1, 12, aSig0, aSig1 );        shift128Right( bSig0, bSig1, 12, bSig0, bSig1 );    end;    repeat        alternateASig0 := aSig0;        alternateASig1 := aSig1;        inc(q);        sub128( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );    until not( 0 <= sbits64(aSig0) );    add128(        aSig0, aSig1, alternateASig0, alternateASig1, bits64(sigMean0), sigMean1 );    if (    ( sigMean0 < 0 )         or ( ( ( sigMean0 or sigMean1 ) = 0 ) and (( q and 1 )<>0) ) ) then begin        aSig0 := alternateASig0;        aSig1 := alternateASig1;    end;    zSign := ord( sbits64(aSig0) < 0 );    if ( zSign<>0 ) then sub128( 0, 0, aSig0, aSig1, aSig0, aSig1 );    result :=        normalizeRoundAndPackFloat128( aSign xor zSign, bExp - 4, aSig0, aSig1 );end;{*----------------------------------------------------------------------------| Returns the square root of the quadruple-precision floating-point value `a'.| The operation is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_sqrt(a: float128): float128;var    aSign: flag;    aExp, zExp: int32;    aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits64;    rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;    z: float128;label    invalid;begin    aSig1 := extractFloat128Frac1( a );    aSig0 := extractFloat128Frac0( a );    aExp := extractFloat128Exp( a );    aSign := extractFloat128Sign( a );    if ( aExp = $7FFF ) then begin        if ( aSig0 or aSig1 )<>0 then          begin            result := propagateFloat128NaN( a, a );            exit;          end;        if ( aSign=0 ) then          begin            result := a;            exit;          end;        goto invalid;    end;    if ( aSign<>0 ) then begin        if ( ( aExp or aSig0 or aSig1 ) = 0 ) then          begin            result := a;            exit;          end; invalid:        float_raise( float_flag_invalid );        z.low := float128_default_nan_low;        z.high := float128_default_nan_high;        result := z;        exit;    end;    if ( aExp = 0 ) then begin        if ( ( aSig0 or aSig1 ) = 0 ) then        begin          result := packFloat128( 0, 0, 0, 0 );          exit;        end;        normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );    end;    zExp := ( ( aExp - $3FFF ) shr 1 ) + $3FFE;    aSig0 := aSig0 or int64( $0001000000000000 );    zSig0 := estimateSqrt32( aExp, aSig0 shr 17 );    shortShift128Left( aSig0, aSig1, 13 - ( aExp and 1 ), aSig0, aSig1 );    zSig0 := estimateDiv128To64( aSig0, aSig1, zSig0 shl 32 ) + ( zSig0 shl 30 );    doubleZSig0 := zSig0 shl 1;    mul64To128( zSig0, zSig0, term0, term1 );    sub128( aSig0, aSig1, term0, term1, rem0, rem1 );    while ( sbits64(rem0) < 0 ) do begin        dec(zSig0);        dec(doubleZSig0,2);        add128( rem0, rem1, zSig0 shr 63, doubleZSig0 or 1, rem0, rem1 );    end;    zSig1 := estimateDiv128To64( rem1, 0, doubleZSig0 );    if ( ( zSig1 and $1FFF ) <= 5 ) then begin        if ( zSig1 = 0 ) then zSig1 := 1;        mul64To128( doubleZSig0, zSig1, term1, term2 );        sub128( rem1, 0, term1, term2, rem1, rem2 );        mul64To128( zSig1, zSig1, term2, term3 );        sub192( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );        while ( sbits64(rem1) < 0 ) do begin            dec(zSig1);            shortShift128Left( 0, zSig1, 1, term2, term3 );            term3 := term3 or 1;            term2 := term2 or doubleZSig0;            add192( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );        end;        zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );    end;    shift128ExtraRightJamming( zSig0, zSig1, 0, 14, zSig0, zSig1, zSig2 );    result := roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 );end;{*----------------------------------------------------------------------------| Returns 1 if the quadruple-precision floating-point value `a' is equal to| the corresponding value `b', and 0 otherwise.  The comparison is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_eq(a: float128; b: float128): flag;begin    if (    (    ( extractFloat128Exp( a ) = $7FFF )              and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )         or (    ( extractFloat128Exp( b ) = $7FFF )              and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )       ) then begin        if (    (float128_is_signaling_nan( a )<>0)             or (float128_is_signaling_nan( b )<>0) ) then begin            float_raise( float_flag_invalid );        end;        result := 0;        exit;    end;    result := ord(           ( a.low = b.low )        and (    ( a.high = b.high )             or (    ( a.low = 0 )                  and ( bits64( ( a.high or b.high ) shl 1 ) = 0 ) )           ));end;{*----------------------------------------------------------------------------| Returns 1 if the quadruple-precision floating-point value `a' is less than| or equal to the corresponding value `b', and 0 otherwise.  The comparison| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*}function float128_le(a: float128; b: float128): flag;var    aSign, bSign: flag;begin    if (    (    ( extractFloat128Exp( a ) = $7FFF )              and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )         or (    ( extractFloat128Exp( b ) = $7FFF )              and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )       ) then begin        float_raise( float_flag_invalid );        result := 0;        exit;    end;    aSign := extractFloat128Sign( a );    bSign := extractFloat128Sign( b );    if ( aSign <> bSign ) then begin        result := ord(               (aSign<>0)            or (    ( ( bits64 ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )                 = 0 ));        exit;    end;    if aSign<>0 then      result := le128( b.high, b.low, a.high, a.low )    else      result := le128( a.high, a.low, b.high, b.low );end;{*----------------------------------------------------------------------------| Returns 1 if the quadruple-precision floating-point value `a' is less than| the corresponding value `b', and 0 otherwise.  The comparison is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_lt(a: float128; b: float128): flag;var    aSign, bSign: flag;begin    if (    (    ( extractFloat128Exp( a ) = $7FFF )              and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )         or (    ( extractFloat128Exp( b ) = $7FFF )              and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )       ) then begin        float_raise( float_flag_invalid );        result := 0;        exit;    end;    aSign := extractFloat128Sign( a );    bSign := extractFloat128Sign( b );    if ( aSign <> bSign ) then begin        result := ord(               (aSign<>0)            and (    ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )                 <> 0 ));        exit;    end;    if aSign<>0 then      result := lt128( b.high, b.low, a.high, a.low )    else      result := lt128( a.high, a.low, b.high, b.low );end;{*----------------------------------------------------------------------------| Returns 1 if the quadruple-precision floating-point value `a' is equal to| the corresponding value `b', and 0 otherwise.  The invalid exception is| raised if either operand is a NaN.  Otherwise, the comparison is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_eq_signaling(a: float128; b: float128): flag;begin    if (    (    ( extractFloat128Exp( a ) = $7FFF )              and ( ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )         or (    ( extractFloat128Exp( b ) = $7FFF )              and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )       ) then begin        float_raise( float_flag_invalid );        result := 0;        exit;    end;    result := ord(           ( a.low = b.low )        and (    ( a.high = b.high )             or (    ( a.low = 0 )                  and ( bits64 ( ( a.high or b.high ) shl 1 ) = 0 ) )           ));end;{*----------------------------------------------------------------------------| Returns 1 if the quadruple-precision floating-point value `a' is less than| or equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not| cause an exception.  Otherwise, the comparison is performed according to the| IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_le_quiet(a: float128; b: float128): flag;var    aSign, bSign: flag;begin    if (    (    ( extractFloat128Exp( a ) = $7FFF )              and ( ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )         or (    ( extractFloat128Exp( b ) = $7FFF )              and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )       ) then begin        if (    (float128_is_signaling_nan( a )<>0)             or (float128_is_signaling_nan( b )<>0) ) then begin            float_raise( float_flag_invalid );        end;        result := 0;        exit;    end;    aSign := extractFloat128Sign( a );    bSign := extractFloat128Sign( b );    if ( aSign <> bSign ) then begin        result := ord(               (aSign<>0)            or (    ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )                 = 0 ));        exit;    end;    if aSign<>0 then      result := le128( b.high, b.low, a.high, a.low )    else      result := le128( a.high, a.low, b.high, b.low );end;{*----------------------------------------------------------------------------| Returns 1 if the quadruple-precision floating-point value `a' is less than| the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an| exception.  Otherwise, the comparison is performed according to the IEC/IEEE| Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*}function float128_lt_quiet(a: float128; b: float128): flag;var    aSign, bSign: flag;begin    if (    (    ( extractFloat128Exp( a ) = $7FFF )              and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )         or (    ( extractFloat128Exp( b ) = $7FFF )              and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )       ) then begin        if ( (float128_is_signaling_nan( a )<>0)             or (float128_is_signaling_nan( b )<>0) ) then begin            float_raise( float_flag_invalid );        end;        result := 0;        exit;    end;    aSign := extractFloat128Sign( a );    bSign := extractFloat128Sign( b );    if ( aSign <> bSign ) then begin        result := ord(               (aSign<>0)            and (    ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )                 <> 0 ));        exit;    end;    if aSign<>0 then      result:=lt128( b.high, b.low, a.high, a.low )    else      result:=lt128( a.high, a.low, b.high, b.low );end;{----------------------------------------------------------------------------| Returns the result of converting the double-precision floating-point value| `a' to the quadruple-precision floating-point format.  The conversion is| performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------}function float64_to_float128( a : float64) : float128;var    aSign : flag;    aExp : int16;    aSig, zSig0, zSig1 : bits64;begin    aSig := extractFloat64Frac( a );    aExp := extractFloat64Exp( a );    aSign := extractFloat64Sign( a );    if ( aExp = $7FF ) then begin        if ( aSig<>0 ) then begin          result:=commonNaNToFloat128( float64ToCommonNaN( a ) );          exit;        end;        result:=packFloat128( aSign, $7FFF, 0, 0 );        exit;    end;    if ( aExp = 0 ) then begin        if ( aSig = 0 ) then          begin            result:=packFloat128( aSign, 0, 0, 0 );            exit;          end;        normalizeFloat64Subnormal( aSig, aExp, aSig );        dec(aExp);    end;    shift128Right( aSig, 0, 4, zSig0, zSig1 );    result:=packFloat128( aSign, aExp + $3C00, zSig0, zSig1 );end;{$endif FPC_SOFTFLOAT_FLOAT128}{$endif not(defined(fpc_softfpu_interface))}{$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}end.{$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
 |