softfpu.pp 158 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685
  1. {*
  2. ===============================================================================
  3. The original notice of the softfloat package is shown below. The conversion
  4. to pascal was done by Carl Eric Codere in 2002 ([email protected]).
  5. ===============================================================================
  6. This C source file is part of the SoftFloat IEC/IEEE Floating-Point
  7. Arithmetic Package, Release 2a.
  8. Written by John R. Hauser. This work was made possible in part by the
  9. International Computer Science Institute, located at Suite 600, 1947 Center
  10. Street, Berkeley, California 94704. Funding was partially provided by the
  11. National Science Foundation under grant MIP-9311980. The original version
  12. of this code was written as part of a project to build a fixed-point vector
  13. processor in collaboration with the University of California at Berkeley,
  14. overseen by Profs. Nelson Morgan and John Wawrzynek. More information
  15. is available through the Web page
  16. `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'.
  17. THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
  18. has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
  19. TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
  20. PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
  21. AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
  22. Derivative works are acceptable, even for commercial purposes, so long as
  23. (1) they include prominent notice that the work is derivative, and (2) they
  24. include prominent notice akin to these four paragraphs for those parts of
  25. this code that are retained.
  26. ===============================================================================
  27. *}
  28. unit softfpu;
  29. { Overflow checking must be disabled,
  30. since some operations expect overflow!
  31. }
  32. {$Q-}
  33. {$ifndef ver1_0}
  34. {$ifdef fpc}
  35. {$define hascompilerproc}
  36. {$endif}
  37. {$endif}
  38. {$ifdef fpc}
  39. {$goto on}
  40. {$endif}
  41. interface
  42. {
  43. -------------------------------------------------------------------------------
  44. Software IEC/IEEE floating-point types.
  45. -------------------------------------------------------------------------------
  46. }
  47. TYPE
  48. float32 = longword;
  49. flag = byte;
  50. uint8 = byte;
  51. int8 = shortint;
  52. uint16 = word;
  53. int16 = integer;
  54. uint32 = longword;
  55. int32 = longint;
  56. bits8 = byte;
  57. sbits8 = shortint;
  58. bits16 = word;
  59. sbits16 = integer;
  60. sbits32 = longint;
  61. bits32 = longword;
  62. {$ifndef fpc}
  63. qword = int64;
  64. {$endif}
  65. uint64 = qword;
  66. bits64 = qword;
  67. sbits64 = int64;
  68. {$ifdef ENDIAN_LITTLE}
  69. float64 = packed record
  70. low: bits32;
  71. high: bits32;
  72. end;
  73. int64rec = packed record
  74. low: bits32;
  75. high: bits32;
  76. end;
  77. {$else}
  78. float64 = packed record
  79. high,low : bits32;
  80. end;
  81. int64rec = packed record
  82. high,low : bits32;
  83. end;
  84. {$endif}
  85. {*
  86. -------------------------------------------------------------------------------
  87. Returns 1 if the double-precision floating-point value `a' is less than
  88. the corresponding value `b', and 0 otherwise. The comparison is performed
  89. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  90. -------------------------------------------------------------------------------
  91. *}
  92. Function float64_lt(a: float64;b: float64): flag; {$ifdef hascompilerproc} compilerproc; {$endif}
  93. {*
  94. -------------------------------------------------------------------------------
  95. Returns 1 if the double-precision floating-point value `a' is less than
  96. or equal to the corresponding value `b', and 0 otherwise. The comparison
  97. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  98. Arithmetic.
  99. -------------------------------------------------------------------------------
  100. *}
  101. Function float64_le(a: float64;b: float64): flag; {$ifdef hascompilerproc} compilerproc; {$endif}
  102. {*
  103. -------------------------------------------------------------------------------
  104. Returns 1 if the double-precision floating-point value `a' is equal to
  105. the corresponding value `b', and 0 otherwise. The comparison is performed
  106. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  107. -------------------------------------------------------------------------------
  108. *}
  109. Function float64_eq(a: float64;b: float64): flag; {$ifdef hascompilerproc} compilerproc; {$endif}
  110. {*
  111. -------------------------------------------------------------------------------
  112. Returns the square root of the double-precision floating-point value `a'.
  113. The operation is performed according to the IEC/IEEE Standard for Binary
  114. Floating-Point Arithmetic.
  115. -------------------------------------------------------------------------------
  116. *}
  117. Procedure float64_sqrt( a: float64; var out: float64 ); {$ifdef hascompilerproc} compilerproc; {$endif}
  118. {*
  119. -------------------------------------------------------------------------------
  120. Returns the remainder of the double-precision floating-point value `a'
  121. with respect to the corresponding value `b'. The operation is performed
  122. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  123. -------------------------------------------------------------------------------
  124. *}
  125. Procedure float64_rem(a: float64; b : float64; var out: float64); {$ifdef hascompilerproc} compilerproc; {$endif}
  126. {*
  127. -------------------------------------------------------------------------------
  128. Returns the result of dividing the double-precision floating-point value `a'
  129. by the corresponding value `b'. The operation is performed according to the
  130. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  131. -------------------------------------------------------------------------------
  132. *}
  133. Procedure float64_div(a: float64; b : float64 ; var out: float64 ); {$ifdef hascompilerproc} compilerproc; {$endif}
  134. {*
  135. -------------------------------------------------------------------------------
  136. Returns the result of multiplying the double-precision floating-point values
  137. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  138. for Binary Floating-Point Arithmetic.
  139. -------------------------------------------------------------------------------
  140. *}
  141. Procedure float64_mul( a: float64; b:float64; Var out: float64); {$ifdef hascompilerproc} compilerproc; {$endif}
  142. {*
  143. -------------------------------------------------------------------------------
  144. Returns the result of subtracting the double-precision floating-point values
  145. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  146. for Binary Floating-Point Arithmetic.
  147. -------------------------------------------------------------------------------
  148. *}
  149. Procedure float64_sub(a: float64; b : float64; var out: float64); {$ifdef hascompilerproc} compilerproc; {$endif}
  150. {*
  151. -------------------------------------------------------------------------------
  152. Returns the result of adding the double-precision floating-point values `a'
  153. and `b'. The operation is performed according to the IEC/IEEE Standard for
  154. Binary Floating-Point Arithmetic.
  155. -------------------------------------------------------------------------------
  156. *}
  157. Procedure float64_add( a: float64; b : float64; Var out : float64); {$ifdef hascompilerproc} compilerproc; {$endif}
  158. {*
  159. -------------------------------------------------------------------------------
  160. Rounds the double-precision floating-point value `a' to an integer,
  161. and returns the result as a double-precision floating-point value. The
  162. operation is performed according to the IEC/IEEE Standard for Binary
  163. Floating-Point Arithmetic.
  164. -------------------------------------------------------------------------------
  165. *}
  166. Procedure float64_round_to_int(a: float64; var out: float64 ); {$ifdef hascompilerproc} compilerproc; {$endif}
  167. {*
  168. -------------------------------------------------------------------------------
  169. Returns the result of converting the double-precision floating-point value
  170. `a' to the single-precision floating-point format. The conversion is
  171. performed according to the IEC/IEEE Standard for Binary Floating-Point
  172. Arithmetic.
  173. -------------------------------------------------------------------------------
  174. *}
  175. Function float64_to_float32(a: float64 ): float32; {$ifdef hascompilerproc} compilerproc; {$endif}
  176. {*
  177. -------------------------------------------------------------------------------
  178. Returns the result of converting the double-precision floating-point value
  179. `a' to the 32-bit two's complement integer format. The conversion is
  180. performed according to the IEC/IEEE Standard for Binary Floating-Point
  181. Arithmetic, except that the conversion is always rounded toward zero.
  182. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  183. the conversion overflows, the largest integer with the same sign as `a' is
  184. returned.
  185. -------------------------------------------------------------------------------
  186. *}
  187. Function float64_to_int32_round_to_zero(a: float64 ): int32; {$ifdef hascompilerproc} compilerproc; {$endif}
  188. {*
  189. -------------------------------------------------------------------------------
  190. Returns the result of converting the double-precision floating-point value
  191. `a' to the 32-bit two's complement integer format. The conversion is
  192. performed according to the IEC/IEEE Standard for Binary Floating-Point
  193. Arithmetic---which means in particular that the conversion is rounded
  194. according to the current rounding mode. If `a' is a NaN, the largest
  195. positive integer is returned. Otherwise, if the conversion overflows, the
  196. largest integer with the same sign as `a' is returned.
  197. -------------------------------------------------------------------------------
  198. *}
  199. Function float64_to_int32(a: float64): int32; {$ifdef hascompilerproc} compilerproc; {$endif}
  200. {*
  201. -------------------------------------------------------------------------------
  202. Returns 1 if the single-precision floating-point value `a' is less than
  203. the corresponding value `b', and 0 otherwise. The comparison is performed
  204. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  205. -------------------------------------------------------------------------------
  206. *}
  207. Function float32_lt( a:float32 ; b : float32): flag; {$ifdef hascompilerproc} compilerproc; {$endif}
  208. {*
  209. -------------------------------------------------------------------------------
  210. Returns 1 if the single-precision floating-point value `a' is less than
  211. or equal to the corresponding value `b', and 0 otherwise. The comparison
  212. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  213. Arithmetic.
  214. -------------------------------------------------------------------------------
  215. *}
  216. Function float32_le( a: float32; b : float32 ):flag; {$ifdef hascompilerproc} compilerproc; {$endif}
  217. {*
  218. -------------------------------------------------------------------------------
  219. Returns 1 if the single-precision floating-point value `a' is equal to
  220. the corresponding value `b', and 0 otherwise. The comparison is performed
  221. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  222. -------------------------------------------------------------------------------
  223. *}
  224. Function float32_eq( a:float32; b:float32): flag; {$ifdef hascompilerproc} compilerproc; {$endif}
  225. {*
  226. -------------------------------------------------------------------------------
  227. Returns the square root of the single-precision floating-point value `a'.
  228. The operation is performed according to the IEC/IEEE Standard for Binary
  229. Floating-Point Arithmetic.
  230. -------------------------------------------------------------------------------
  231. *}
  232. Function float32_sqrt(a: float32 ): float32; {$ifdef hascompilerproc} compilerproc; {$endif}
  233. {*
  234. -------------------------------------------------------------------------------
  235. Returns the remainder of the single-precision floating-point value `a'
  236. with respect to the corresponding value `b'. The operation is performed
  237. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  238. -------------------------------------------------------------------------------
  239. *}
  240. Function float32_rem(a: float32; b: float32 ):float32; {$ifdef hascompilerproc} compilerproc; {$endif}
  241. {*
  242. -------------------------------------------------------------------------------
  243. Returns the result of dividing the single-precision floating-point value `a'
  244. by the corresponding value `b'. The operation is performed according to the
  245. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  246. -------------------------------------------------------------------------------
  247. *}
  248. Function float32_div(a: float32;b: float32 ): float32; {$ifdef hascompilerproc} compilerproc; {$endif}
  249. {*
  250. -------------------------------------------------------------------------------
  251. Returns the result of multiplying the single-precision floating-point values
  252. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  253. for Binary Floating-Point Arithmetic.
  254. -------------------------------------------------------------------------------
  255. *}
  256. Function float32_mul(a: float32; b: float32 ) : float32; {$ifdef hascompilerproc} compilerproc; {$endif}
  257. {*
  258. -------------------------------------------------------------------------------
  259. Returns the result of subtracting the single-precision floating-point values
  260. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  261. for Binary Floating-Point Arithmetic.
  262. -------------------------------------------------------------------------------
  263. *}
  264. Function float32_sub( a: float32 ; b:float32 ): float32; {$ifdef hascompilerproc} compilerproc; {$endif}
  265. {*
  266. -------------------------------------------------------------------------------
  267. Returns the result of adding the single-precision floating-point values `a'
  268. and `b'. The operation is performed according to the IEC/IEEE Standard for
  269. Binary Floating-Point Arithmetic.
  270. -------------------------------------------------------------------------------
  271. *}
  272. Function float32_add( a: float32; b:float32 ): float32; {$ifdef hascompilerproc} compilerproc; {$endif}
  273. {*
  274. -------------------------------------------------------------------------------
  275. Rounds the single-precision floating-point value `a' to an integer,
  276. and returns the result as a single-precision floating-point value. The
  277. operation is performed according to the IEC/IEEE Standard for Binary
  278. Floating-Point Arithmetic.
  279. -------------------------------------------------------------------------------
  280. *}
  281. Function float32_round_to_int( a: float32): float32; {$ifdef hascompilerproc} compilerproc; {$endif}
  282. {*
  283. -------------------------------------------------------------------------------
  284. Returns the result of converting the single-precision floating-point value
  285. `a' to the double-precision floating-point format. The conversion is
  286. performed according to the IEC/IEEE Standard for Binary Floating-Point
  287. Arithmetic.
  288. -------------------------------------------------------------------------------
  289. *}
  290. Procedure float32_to_float64( a : float32; var out: Float64); {$ifdef hascompilerproc} compilerproc; {$endif}
  291. {*
  292. -------------------------------------------------------------------------------
  293. Returns the result of converting the single-precision floating-point value
  294. `a' to the 32-bit two's complement integer format. The conversion is
  295. performed according to the IEC/IEEE Standard for Binary Floating-Point
  296. Arithmetic, except that the conversion is always rounded toward zero.
  297. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  298. the conversion overflows, the largest integer with the same sign as `a' is
  299. returned.
  300. -------------------------------------------------------------------------------
  301. *}
  302. Function float32_to_int32_round_to_zero( a: Float32 ): int32; {$ifdef hascompilerproc} compilerproc; {$endif}
  303. {*
  304. -------------------------------------------------------------------------------
  305. Returns the result of converting the single-precision floating-point value
  306. `a' to the 32-bit two's complement integer format. The conversion is
  307. performed according to the IEC/IEEE Standard for Binary Floating-Point
  308. Arithmetic---which means in particular that the conversion is rounded
  309. according to the current rounding mode. If `a' is a NaN, the largest
  310. positive integer is returned. Otherwise, if the conversion overflows, the
  311. largest integer with the same sign as `a' is returned.
  312. -------------------------------------------------------------------------------
  313. *}
  314. Function float32_to_int32( a : float32) : int32; {$ifdef hascompilerproc} compilerproc; {$endif}
  315. {*
  316. -------------------------------------------------------------------------------
  317. Returns the result of converting the 32-bit two's complement integer `a' to
  318. the double-precision floating-point format. The conversion is performed
  319. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  320. -------------------------------------------------------------------------------
  321. *}
  322. Procedure int32_to_float64( a: int32; var c: float64 ); {$ifdef hascompilerproc} compilerproc; {$endif}
  323. {*
  324. -------------------------------------------------------------------------------
  325. Returns the result of converting the 32-bit two's complement integer `a' to
  326. the single-precision floating-point format. The conversion is performed
  327. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  328. -------------------------------------------------------------------------------
  329. *}
  330. Function int32_to_float32( a: int32): float32; {$ifdef hascompilerproc} compilerproc; {$endif}
  331. {*----------------------------------------------------------------------------
  332. | Returns the result of converting the 64-bit two's complement integer `a'
  333. | to the double-precision floating-point format. The conversion is performed
  334. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  335. *----------------------------------------------------------------------------*}
  336. function int64_to_float64( a: int64 ): float64; {$ifdef hascompilerproc} compilerproc; {$endif}
  337. {*----------------------------------------------------------------------------
  338. | Returns the result of converting the 64-bit two's complement integer `a'
  339. | to the single-precision floating-point format. The conversion is performed
  340. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  341. *----------------------------------------------------------------------------*}
  342. function int64_to_float32( a: int64 ): float32; {$ifdef hascompilerproc} compilerproc; {$endif}
  343. CONST
  344. {-------------------------------------------------------------------------------
  345. Software IEC/IEEE floating-point underflow tininess-detection mode.
  346. -------------------------------------------------------------------------------
  347. *}
  348. float_tininess_after_rounding = 0;
  349. float_tininess_before_rounding = 1;
  350. {*
  351. -------------------------------------------------------------------------------
  352. Software IEC/IEEE floating-point rounding mode.
  353. -------------------------------------------------------------------------------
  354. *}
  355. {
  356. Round to nearest.
  357. This is the default mode. It should be used unless there is a specific
  358. need for one of the others. In this mode results are rounded to the
  359. nearest representable value. If the result is midway between two
  360. representable values, the even representable is chosen. Even here
  361. means the lowest-order bit is zero. This rounding mode prevents
  362. statistical bias and guarantees numeric stability: round-off errors
  363. in a lengthy calculation will remain smaller than half of FLT_EPSILON.
  364. Round toward plus Infinity.
  365. All results are rounded to the smallest representable value which is
  366. greater than the result.
  367. Round toward minus Infinity.
  368. All results are rounded to the largest representable value which is
  369. less than the result.
  370. Round toward zero.
  371. All results are rounded to the largest representable value whose
  372. magnitude is less than that of the result. In other words, if the
  373. result is negative it is rounded up; if it is positive, it is
  374. rounded down.
  375. }
  376. float_round_nearest_even = 0;
  377. float_round_down = 1;
  378. float_round_up = 2;
  379. float_round_to_zero = 3;
  380. {*
  381. -------------------------------------------------------------------------------
  382. Software IEC/IEEE floating-point exception flags.
  383. -------------------------------------------------------------------------------
  384. *}
  385. float_flag_invalid = 1;
  386. float_flag_divbyzero = 4;
  387. float_flag_overflow = 8;
  388. float_flag_underflow = 16;
  389. float_flag_inexact = 32;
  390. {*
  391. -------------------------------------------------------------------------------
  392. Floating-point rounding mode and exception flags.
  393. -------------------------------------------------------------------------------
  394. *}
  395. const
  396. float_rounding_mode : Byte = float_round_nearest_even;
  397. float_exception_flags : Byte = 0;
  398. {*
  399. -------------------------------------------------------------------------------
  400. Underflow tininess-detection mode, statically initialized to default value.
  401. (The declaration in `softfloat.h' must match the `int8' type here.)
  402. -------------------------------------------------------------------------------
  403. *}
  404. const float_detect_tininess: int8 = float_tininess_after_rounding;
  405. implementation
  406. {*
  407. -------------------------------------------------------------------------------
  408. Raises the exceptions specified by `flags'. Floating-point traps can be
  409. defined here if desired. It is currently not possible for such a trap
  410. to substitute a result value. If traps are not implemented, this routine
  411. should be simply `float_exception_flags |= flags;'.
  412. -------------------------------------------------------------------------------
  413. *}
  414. procedure float_raise( i: shortint );
  415. Begin
  416. float_exception_flags := float_exception_flags or i;
  417. if (float_exception_flags and float_flag_invalid) <> 0 then
  418. RunError(207)
  419. else
  420. if (float_exception_flags and float_flag_divbyzero) <> 0 then
  421. RunError(200)
  422. else
  423. if (float_exception_flags and float_flag_overflow) <> 0 then
  424. RunError(205)
  425. else
  426. if (float_exception_flags and float_flag_underflow) <> 0 then
  427. RunError(206);
  428. end;
  429. (*****************************************************************************)
  430. (*----------------------------------------------------------------------------*)
  431. (* Primitive arithmetic functions, including multi-word arithmetic, and *)
  432. (* division and square root approximations. (Can be specialized to target if *)
  433. (* desired.) *)
  434. (* ---------------------------------------------------------------------------*)
  435. (*****************************************************************************)
  436. {*
  437. -------------------------------------------------------------------------------
  438. Shifts `a' right by the number of bits given in `count'. If any nonzero
  439. bits are shifted off, they are ``jammed'' into the least significant bit of
  440. the result by setting the least significant bit to 1. The value of `count'
  441. can be arbitrarily large; in particular, if `count' is greater than 32, the
  442. result will be either 0 or 1, depending on whether `a' is zero or nonzero.
  443. The result is stored in the location pointed to by `zPtr'.
  444. -------------------------------------------------------------------------------
  445. *}
  446. Procedure shift32RightJamming( a: bits32 ; count: int16 ; VAR zPtr :bits32);
  447. var
  448. z: Bits32;
  449. Begin
  450. if ( count = 0 ) then
  451. z := a
  452. else
  453. if ( count < 32 ) then
  454. Begin
  455. z := ( a shr count ) or bits32( (( a shl ( ( - count ) AND 31 )) ) <> 0);
  456. End
  457. else
  458. Begin
  459. z := bits32( a <> 0 );
  460. End;
  461. zPtr := z;
  462. End;
  463. {*
  464. -------------------------------------------------------------------------------
  465. Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
  466. number of bits given in `count'. Any bits shifted off are lost. The value
  467. of `count' can be arbitrarily large; in particular, if `count' is greater
  468. than 64, the result will be 0. The result is broken into two 32-bit pieces
  469. which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  470. -------------------------------------------------------------------------------
  471. *}
  472. Procedure
  473. shift64Right(
  474. a0 :bits32; a1: bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32);
  475. Var
  476. z0, z1: bits32;
  477. negCount : int8;
  478. Begin
  479. negCount := ( - count ) AND 31;
  480. if ( count = 0 ) then
  481. Begin
  482. z1 := a1;
  483. z0 := a0;
  484. End
  485. else if ( count < 32 ) then
  486. Begin
  487. z1 := ( a0 shl negCount ) OR ( a1 shr count );
  488. z0 := a0 shr count;
  489. End
  490. else
  491. Begin
  492. if (count < 64) then
  493. z1 := ( a0 shr ( count AND 31 ) )
  494. else
  495. z1 := 0;
  496. z0 := 0;
  497. End;
  498. z1Ptr := z1;
  499. z0Ptr := z0;
  500. End;
  501. {*
  502. -------------------------------------------------------------------------------
  503. Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
  504. number of bits given in `count'. If any nonzero bits are shifted off, they
  505. are ``jammed'' into the least significant bit of the result by setting the
  506. least significant bit to 1. The value of `count' can be arbitrarily large;
  507. in particular, if `count' is greater than 64, the result will be either 0
  508. or 1, depending on whether the concatenation of `a0' and `a1' is zero or
  509. nonzero. The result is broken into two 32-bit pieces which are stored at
  510. the locations pointed to by `z0Ptr' and `z1Ptr'.
  511. -------------------------------------------------------------------------------
  512. *}
  513. Procedure
  514. shift64RightJamming(
  515. a0:bits32; a1: bits32; count:int16; VAR Z0Ptr :bits32;VAR z1Ptr: bits32 );
  516. VAR
  517. z0, z1 : bits32;
  518. negCount : int8;
  519. Begin
  520. negCount := ( - count ) AND 31;
  521. if ( count = 0 ) then
  522. Begin
  523. z1 := a1;
  524. z0 := a0;
  525. End
  526. else
  527. if ( count < 32 ) then
  528. Begin
  529. z1 := ( a0 shl negCount ) OR ( a1 shr count ) OR bits32( ( a1 shl negCount ) <> 0 );
  530. z0 := a0 shr count;
  531. End
  532. else
  533. Begin
  534. if ( count = 32 ) then
  535. Begin
  536. z1 := a0 OR bits32( a1 <> 0 );
  537. End
  538. else
  539. if ( count < 64 ) Then
  540. Begin
  541. z1 := ( a0 shr ( count AND 31 ) ) OR bits32( ( ( a0 shl negCount ) OR a1 ) <> 0 );
  542. End
  543. else
  544. Begin
  545. z1 := bits32( ( a0 OR a1 ) <> 0 );
  546. End;
  547. z0 := 0;
  548. End;
  549. z1Ptr := z1;
  550. z0Ptr := z0;
  551. End;
  552. {*
  553. -------------------------------------------------------------------------------
  554. Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right
  555. by 32 _plus_ the number of bits given in `count'. The shifted result is
  556. at most 64 nonzero bits; these are broken into two 32-bit pieces which are
  557. stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
  558. off form a third 32-bit result as follows: The _last_ bit shifted off is
  559. the most-significant bit of the extra result, and the other 31 bits of the
  560. extra result are all zero if and only if _all_but_the_last_ bits shifted off
  561. were all zero. This extra result is stored in the location pointed to by
  562. `z2Ptr'. The value of `count' can be arbitrarily large.
  563. (This routine makes more sense if `a0', `a1', and `a2' are considered
  564. to form a fixed-point value with binary point between `a1' and `a2'. This
  565. fixed-point value is shifted right by the number of bits given in `count',
  566. and the integer part of the result is returned at the locations pointed to
  567. by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
  568. corrupted as described above, and is returned at the location pointed to by
  569. `z2Ptr'.)
  570. -------------------------------------------------------------------------------
  571. }
  572. Procedure
  573. shift64ExtraRightJamming(
  574. a0: bits32;
  575. a1: bits32;
  576. a2: bits32;
  577. count: int16;
  578. VAR z0Ptr: bits32;
  579. VAR z1Ptr: bits32;
  580. VAR z2Ptr: bits32
  581. );
  582. Var
  583. z0, z1, z2: bits32;
  584. negCount : int8;
  585. Begin
  586. negCount := ( - count ) AND 31;
  587. if ( count = 0 ) then
  588. Begin
  589. z2 := a2;
  590. z1 := a1;
  591. z0 := a0;
  592. End
  593. else
  594. Begin
  595. if ( count < 32 ) Then
  596. Begin
  597. z2 := a1 shl negCount;
  598. z1 := ( a0 shl negCount ) OR ( a1 shr count );
  599. z0 := a0 shr count;
  600. End
  601. else
  602. Begin
  603. if ( count = 32 ) then
  604. Begin
  605. z2 := a1;
  606. z1 := a0;
  607. End
  608. else
  609. Begin
  610. a2 := a2 or a1;
  611. if ( count < 64 ) then
  612. Begin
  613. z2 := a0 shl negCount;
  614. z1 := a0 shr ( count AND 31 );
  615. End
  616. else
  617. Begin
  618. if count = 64 then
  619. z2 := a0
  620. else
  621. z2 := bits32(a0 <> 0);
  622. z1 := 0;
  623. End;
  624. End;
  625. z0 := 0;
  626. End;
  627. z2 := z2 or bits32( a2 <> 0 );
  628. End;
  629. z2Ptr := z2;
  630. z1Ptr := z1;
  631. z0Ptr := z0;
  632. End;
  633. {*
  634. -------------------------------------------------------------------------------
  635. Shifts the 64-bit value formed by concatenating `a0' and `a1' left by the
  636. number of bits given in `count'. Any bits shifted off are lost. The value
  637. of `count' must be less than 32. The result is broken into two 32-bit
  638. pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  639. -------------------------------------------------------------------------------
  640. *}
  641. Procedure
  642. shortShift64Left(
  643. a0:bits32; a1:bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );
  644. Begin
  645. z1Ptr := a1 shl count;
  646. if count = 0 then
  647. z0Ptr := a0
  648. else
  649. z0Ptr := ( a0 shl count ) OR ( a1 shr ( ( - count ) AND 31 ) );
  650. End;
  651. {*
  652. -------------------------------------------------------------------------------
  653. Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' left
  654. by the number of bits given in `count'. Any bits shifted off are lost.
  655. The value of `count' must be less than 32. The result is broken into three
  656. 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
  657. `z1Ptr', and `z2Ptr'.
  658. -------------------------------------------------------------------------------
  659. *}
  660. Procedure
  661. shortShift96Left(
  662. a0: bits32;
  663. a1: bits32;
  664. a2: bits32;
  665. count: int16;
  666. VAR z0Ptr: bits32;
  667. VAR z1Ptr: bits32;
  668. VAR z2Ptr: bits32
  669. );
  670. Var
  671. z0, z1, z2: bits32;
  672. negCount: int8;
  673. Begin
  674. z2 := a2 shl count;
  675. z1 := a1 shl count;
  676. z0 := a0 shl count;
  677. if ( 0 < count ) then
  678. Begin
  679. negCount := ( ( - count ) AND 31 );
  680. z1 := z1 or (a2 shr negCount);
  681. z0 := z0 or (a1 shr negCount);
  682. End;
  683. z2Ptr := z2;
  684. z1Ptr := z1;
  685. z0Ptr := z0;
  686. End;
  687. {*
  688. -------------------------------------------------------------------------------
  689. Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit
  690. value formed by concatenating `b0' and `b1'. Addition is modulo 2^64, so
  691. any carry out is lost. The result is broken into two 32-bit pieces which
  692. are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  693. -------------------------------------------------------------------------------
  694. *}
  695. Procedure
  696. add64(
  697. a0:bits32; a1:bits32; b0:bits32; b1:bits32; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );
  698. Var
  699. z1: bits32;
  700. Begin
  701. z1 := a1 + b1;
  702. z1Ptr := z1;
  703. z0Ptr := a0 + b0 + bits32( z1 < a1 );
  704. End;
  705. {*
  706. -------------------------------------------------------------------------------
  707. Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the
  708. 96-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
  709. modulo 2^96, so any carry out is lost. The result is broken into three
  710. 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
  711. `z1Ptr', and `z2Ptr'.
  712. -------------------------------------------------------------------------------
  713. *}
  714. Procedure
  715. add96(
  716. a0: bits32;
  717. a1: bits32;
  718. a2: bits32;
  719. b0: bits32;
  720. b1: bits32;
  721. b2: bits32;
  722. VAR z0Ptr: bits32;
  723. VAR z1Ptr: bits32;
  724. VAR z2Ptr: bits32
  725. );
  726. var
  727. z0, z1, z2: bits32;
  728. carry0, carry1: int8;
  729. Begin
  730. z2 := a2 + b2;
  731. carry1 := int8( z2 < a2 );
  732. z1 := a1 + b1;
  733. carry0 := int8( z1 < a1 );
  734. z0 := a0 + b0;
  735. z1 := z1 + carry1;
  736. z0 := z0 + bits32( z1 < carry1 );
  737. z0 := z0 + carry0;
  738. z2Ptr := z2;
  739. z1Ptr := z1;
  740. z0Ptr := z0;
  741. End;
  742. {*
  743. -------------------------------------------------------------------------------
  744. Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the
  745. 64-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
  746. 2^64, so any borrow out (carry out) is lost. The result is broken into two
  747. 32-bit pieces which are stored at the locations pointed to by `z0Ptr' and
  748. `z1Ptr'.
  749. -------------------------------------------------------------------------------
  750. *}
  751. Procedure
  752. sub64(
  753. a0: bits32; a1 : bits32; b0 :bits32; b1: bits32; VAR z0Ptr:bits32; VAR z1Ptr: bits32 );
  754. Begin
  755. z1Ptr := a1 - b1;
  756. z0Ptr := a0 - b0 - bits32( a1 < b1 );
  757. End;
  758. {*
  759. -------------------------------------------------------------------------------
  760. Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from
  761. the 96-bit value formed by concatenating `a0', `a1', and `a2'. Subtraction
  762. is modulo 2^96, so any borrow out (carry out) is lost. The result is broken
  763. into three 32-bit pieces which are stored at the locations pointed to by
  764. `z0Ptr', `z1Ptr', and `z2Ptr'.
  765. -------------------------------------------------------------------------------
  766. *}
  767. Procedure
  768. sub96(
  769. a0:bits32;
  770. a1:bits32;
  771. a2:bits32;
  772. b0:bits32;
  773. b1:bits32;
  774. b2:bits32;
  775. VAR z0Ptr:bits32;
  776. VAR z1Ptr:bits32;
  777. VAR z2Ptr:bits32
  778. );
  779. Var
  780. z0, z1, z2: bits32;
  781. borrow0, borrow1: int8;
  782. Begin
  783. z2 := a2 - b2;
  784. borrow1 := int8( a2 < b2 );
  785. z1 := a1 - b1;
  786. borrow0 := int8( a1 < b1 );
  787. z0 := a0 - b0;
  788. z0 := z0 - bits32( z1 < borrow1 );
  789. z1 := z1 - borrow1;
  790. z0 := z0 -borrow0;
  791. z2Ptr := z2;
  792. z1Ptr := z1;
  793. z0Ptr := z0;
  794. End;
  795. {*
  796. -------------------------------------------------------------------------------
  797. Multiplies `a' by `b' to obtain a 64-bit product. The product is broken
  798. into two 32-bit pieces which are stored at the locations pointed to by
  799. `z0Ptr' and `z1Ptr'.
  800. -------------------------------------------------------------------------------
  801. *}
  802. Procedure mul32To64( a:bits32; b:bits32; VAR z0Ptr: bits32; VAR z1Ptr
  803. :bits32 );
  804. Var
  805. aHigh, aLow, bHigh, bLow: bits16;
  806. z0, zMiddleA, zMiddleB, z1: bits32;
  807. Begin
  808. aLow := a and $ffff;
  809. aHigh := a shr 16;
  810. bLow := b and $ffff;
  811. bHigh := b shr 16;
  812. z1 := ( bits32( aLow) ) * bLow;
  813. zMiddleA := ( bits32 (aLow) ) * bHigh;
  814. zMiddleB := ( bits32 (aHigh) ) * bLow;
  815. z0 := ( bits32 (aHigh) ) * bHigh;
  816. zMiddleA := zMiddleA + zMiddleB;
  817. z0 := z0 + ( ( bits32 ( zMiddleA < zMiddleB ) ) shl 16 ) + ( zMiddleA shr 16 );
  818. zMiddleA := zmiddleA shl 16;
  819. z1 := z1 + zMiddleA;
  820. z0 := z0 + bits32( z1 < zMiddleA );
  821. z1Ptr := z1;
  822. z0Ptr := z0;
  823. End;
  824. {*
  825. -------------------------------------------------------------------------------
  826. Multiplies the 64-bit value formed by concatenating `a0' and `a1' by `b'
  827. to obtain a 96-bit product. The product is broken into three 32-bit pieces
  828. which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
  829. `z2Ptr'.
  830. -------------------------------------------------------------------------------
  831. *}
  832. Procedure
  833. mul64By32To96(
  834. a0:bits32;
  835. a1:bits32;
  836. b:bits32;
  837. VAR z0Ptr:bits32;
  838. VAR z1Ptr:bits32;
  839. VAR z2Ptr:bits32
  840. );
  841. Var
  842. z0, z1, z2, more1: bits32;
  843. Begin
  844. mul32To64( a1, b, z1, z2 );
  845. mul32To64( a0, b, z0, more1 );
  846. add64( z0, more1, 0, z1, z0, z1 );
  847. z2Ptr := z2;
  848. z1Ptr := z1;
  849. z0Ptr := z0;
  850. End;
  851. {*
  852. -------------------------------------------------------------------------------
  853. Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the
  854. 64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit
  855. product. The product is broken into four 32-bit pieces which are stored at
  856. the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
  857. -------------------------------------------------------------------------------
  858. *}
  859. Procedure
  860. mul64To128(
  861. a0:bits32;
  862. a1:bits32;
  863. b0:bits32;
  864. b1:bits32;
  865. VAR z0Ptr:bits32;
  866. VAR z1Ptr:bits32;
  867. VAR z2Ptr:bits32;
  868. VAR z3Ptr:bits32
  869. );
  870. Var
  871. z0, z1, z2, z3: bits32;
  872. more1, more2: bits32;
  873. Begin
  874. mul32To64( a1, b1, z2, z3 );
  875. mul32To64( a1, b0, z1, more2 );
  876. add64( z1, more2, 0, z2, z1, z2 );
  877. mul32To64( a0, b0, z0, more1 );
  878. add64( z0, more1, 0, z1, z0, z1 );
  879. mul32To64( a0, b1, more1, more2 );
  880. add64( more1, more2, 0, z2, more1, z2 );
  881. add64( z0, z1, 0, more1, z0, z1 );
  882. z3Ptr := z3;
  883. z2Ptr := z2;
  884. z1Ptr := z1;
  885. z0Ptr := z0;
  886. End;
  887. {*
  888. -------------------------------------------------------------------------------
  889. Returns an approximation to the 32-bit integer quotient obtained by dividing
  890. `b' into the 64-bit value formed by concatenating `a0' and `a1'. The
  891. divisor `b' must be at least 2^31. If q is the exact quotient truncated
  892. toward zero, the approximation returned lies between q and q + 2 inclusive.
  893. If the exact quotient q is larger than 32 bits, the maximum positive 32-bit
  894. unsigned integer is returned.
  895. -------------------------------------------------------------------------------
  896. *}
  897. Function estimateDiv64To32( a0:bits32; a1: bits32; b:bits32): bits32;
  898. Var
  899. b0, b1: bits32;
  900. rem0, rem1, term0, term1: bits32;
  901. z: bits32;
  902. Begin
  903. if ( b <= a0 ) then
  904. Begin
  905. estimateDiv64To32 := $FFFFFFFF;
  906. exit;
  907. End;
  908. b0 := b shr 16;
  909. if ( b0 shl 16 <= a0 ) then
  910. z:= $FFFF0000
  911. else
  912. z:= ( a0 div b0 ) shl 16;
  913. mul32To64( b, z, term0, term1 );
  914. sub64( a0, a1, term0, term1, rem0, rem1 );
  915. while ( ( sbits32 (rem0) ) < 0 ) do
  916. Begin
  917. z := z - $10000;
  918. b1 := b shl 16;
  919. add64( rem0, rem1, b0, b1, rem0, rem1 );
  920. End;
  921. rem0 := ( rem0 shl 16 ) OR ( rem1 shr 16 );
  922. if ( b0 shl 16 <= rem0 ) then
  923. z := z or $FFFF
  924. else
  925. z := z or (rem0 div b0);
  926. estimateDiv64To32 := z;
  927. End;
  928. {*
  929. -------------------------------------------------------------------------------
  930. Returns an approximation to the square root of the 32-bit significand given
  931. by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
  932. `aExp' (the least significant bit) is 1, the integer returned approximates
  933. 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
  934. is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
  935. case, the approximation returned lies strictly within +/-2 of the exact
  936. value.
  937. -------------------------------------------------------------------------------
  938. *}
  939. Function estimateSqrt32( aExp: int16; a: bits32 ): bits32;
  940. const sqrtOddAdjustments: array[0..15] of bits16 = (
  941. $0004, $0022, $005D, $00B1, $011D, $019F, $0236, $02E0,
  942. $039C, $0468, $0545, $0631, $072B, $0832, $0946, $0A67
  943. );
  944. const sqrtEvenAdjustments: array[0..15] of bits16 = (
  945. $0A2D, $08AF, $075A, $0629, $051A, $0429, $0356, $029E,
  946. $0200, $0179, $0109, $00AF, $0068, $0034, $0012, $0002
  947. );
  948. Var
  949. index: int8;
  950. z: bits32;
  951. Begin
  952. index := ( a shr 27 ) AND 15;
  953. if ( aExp AND 1 ) <> 0 then
  954. Begin
  955. z := $4000 + ( a shr 17 ) - sqrtOddAdjustments[ index ];
  956. z := ( ( a div z ) shl 14 ) + ( z shl 15 );
  957. a := a shr 1;
  958. End
  959. else
  960. Begin
  961. z := $8000 + ( a shr 17 ) - sqrtEvenAdjustments[ index ];
  962. z := a div z + z;
  963. if ( $20000 <= z ) then
  964. z := $FFFF8000
  965. else
  966. z := ( z shl 15 );
  967. if ( z <= a ) then
  968. Begin
  969. estimateSqrt32 := bits32 ( ( sbits32 (a )) shr 1 );
  970. exit;
  971. End;
  972. End;
  973. estimateSqrt32 := ( ( estimateDiv64To32( a, 0, z ) ) shr 1 ) + ( z shr 1 );
  974. End;
  975. {*
  976. -------------------------------------------------------------------------------
  977. Returns the number of leading 0 bits before the most-significant 1 bit of
  978. `a'. If `a' is zero, 32 is returned.
  979. -------------------------------------------------------------------------------
  980. *}
  981. Function countLeadingZeros32( a:bits32 ): int8;
  982. const countLeadingZerosHigh:array[0..255] of int8 = (
  983. 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
  984. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  985. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  986. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  987. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  988. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  989. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  990. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  991. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  992. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  993. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  994. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  995. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  996. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  997. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  998. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  999. );
  1000. Var
  1001. shiftCount: int8;
  1002. Begin
  1003. shiftCount := 0;
  1004. if ( a < $10000 ) then
  1005. Begin
  1006. shiftCount := shiftcount + 16;
  1007. a := a shl 16;
  1008. End;
  1009. if ( a < $1000000 ) then
  1010. Begin
  1011. shiftCount := shiftcount + 8;
  1012. a := a shl 8;
  1013. end;
  1014. shiftCount := shiftcount + countLeadingZerosHigh[ a shr 24 ];
  1015. countLeadingZeros32:= shiftCount;
  1016. End;
  1017. {*----------------------------------------------------------------------------
  1018. | Returns the number of leading 0 bits before the most-significant 1 bit of
  1019. | `a'. If `a' is zero, 64 is returned.
  1020. *----------------------------------------------------------------------------*}
  1021. function countLeadingZeros64( a : bits64): int8;
  1022. var
  1023. shiftcount : int8;
  1024. Begin
  1025. shiftCount := 0;
  1026. if ( a < (bits64(1) shl 32 )) then
  1027. shiftCount := shiftcount + 32
  1028. else
  1029. a := a shr 32;
  1030. shiftCount := shiftCount + countLeadingZeros32( a );
  1031. countLeadingZeros64:= shiftCount;
  1032. End;
  1033. {*
  1034. -------------------------------------------------------------------------------
  1035. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is
  1036. equal to the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1037. returns 0.
  1038. -------------------------------------------------------------------------------
  1039. *}
  1040. Function eq64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
  1041. Begin
  1042. eq64 := flag( a0 = b0 ) and flag( a1 = b1 );
  1043. End;
  1044. {*
  1045. -------------------------------------------------------------------------------
  1046. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
  1047. than or equal to the 64-bit value formed by concatenating `b0' and `b1'.
  1048. Otherwise, returns 0.
  1049. -------------------------------------------------------------------------------
  1050. *}
  1051. Function le64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
  1052. Begin
  1053. le64:= flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 <= b1 ) );
  1054. End;
  1055. {*
  1056. -------------------------------------------------------------------------------
  1057. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
  1058. than the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1059. returns 0.
  1060. -------------------------------------------------------------------------------
  1061. *}
  1062. Function lt64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
  1063. Begin
  1064. lt64 := flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 < b1 ) );
  1065. End;
  1066. {*
  1067. -------------------------------------------------------------------------------
  1068. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is not
  1069. equal to the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1070. returns 0.
  1071. -------------------------------------------------------------------------------
  1072. *}
  1073. Function ne64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
  1074. Begin
  1075. ne64:= flag( a0 <> b0 ) or flag( a1 <> b1 );
  1076. End;
  1077. (*****************************************************************************)
  1078. (* End Low-Level arithmetic *)
  1079. (*****************************************************************************)
  1080. {*
  1081. -------------------------------------------------------------------------------
  1082. Functions and definitions to determine: (1) whether tininess for underflow
  1083. is detected before or after rounding by default, (2) what (if anything)
  1084. happens when exceptions are raised, (3) how signaling NaNs are distinguished
  1085. from quiet NaNs, (4) the default generated quiet NaNs, and (4) how NaNs
  1086. are propagated from function inputs to output. These details are ENDIAN
  1087. specific
  1088. -------------------------------------------------------------------------------
  1089. *}
  1090. {$IFDEF ENDIAN_LITTLE}
  1091. {*
  1092. -------------------------------------------------------------------------------
  1093. Internal canonical NaN format.
  1094. -------------------------------------------------------------------------------
  1095. *}
  1096. TYPE
  1097. commonNaNT = packed record
  1098. sign: flag;
  1099. high, low : bits32;
  1100. end;
  1101. {*
  1102. -------------------------------------------------------------------------------
  1103. The pattern for a default generated single-precision NaN.
  1104. -------------------------------------------------------------------------------
  1105. *}
  1106. const float32_default_nan = $FFC00000;
  1107. {*
  1108. -------------------------------------------------------------------------------
  1109. Returns 1 if the single-precision floating-point value `a' is a NaN;
  1110. otherwise returns 0.
  1111. -------------------------------------------------------------------------------
  1112. *}
  1113. Function float32_is_nan( a : float32 ): flag;
  1114. Begin
  1115. float32_is_nan:= flag( $FF000000 < bits32 ( a shl 1 ) );
  1116. End;
  1117. {*
  1118. -------------------------------------------------------------------------------
  1119. Returns 1 if the single-precision floating-point value `a' is a signaling
  1120. NaN; otherwise returns 0.
  1121. -------------------------------------------------------------------------------
  1122. *}
  1123. Function float32_is_signaling_nan( a : float32 ): flag;
  1124. Begin
  1125. float32_is_signaling_nan := flag
  1126. ( ( ( a shr 22 ) and $1FF ) = $1FE ) and( a and $003FFFFF );
  1127. End;
  1128. {*
  1129. -------------------------------------------------------------------------------
  1130. Returns the result of converting the single-precision floating-point NaN
  1131. `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1132. exception is raised.
  1133. -------------------------------------------------------------------------------
  1134. *}
  1135. Procedure float32ToCommonNaN( a: float32; VAR c:commonNaNT );
  1136. var
  1137. z : commonNaNT ;
  1138. Begin
  1139. if ( float32_is_signaling_nan( a ) <> 0) then
  1140. float_raise( float_flag_invalid );
  1141. z.sign := a shr 31;
  1142. z.low := 0;
  1143. z.high := a shl 9;
  1144. c := z;
  1145. End;
  1146. {*
  1147. -------------------------------------------------------------------------------
  1148. Returns the result of converting the canonical NaN `a' to the single-
  1149. precision floating-point format.
  1150. -------------------------------------------------------------------------------
  1151. *}
  1152. Function commonNaNToFloat32( a : commonNaNT ): float32;
  1153. Begin
  1154. commonNaNToFloat32 := ( ( bits32 (a.sign) ) shl 31 ) or $7FC00000 or ( a.high shr 9 );
  1155. End;
  1156. {*
  1157. -------------------------------------------------------------------------------
  1158. Takes two single-precision floating-point values `a' and `b', one of which
  1159. is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1160. signaling NaN, the invalid exception is raised.
  1161. -------------------------------------------------------------------------------
  1162. *}
  1163. Function propagateFloat32NaN( a : float32 ; b: float32 ): float32;
  1164. Var
  1165. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1166. label returnLargerSignificand;
  1167. Begin
  1168. aIsNaN := float32_is_nan( a );
  1169. aIsSignalingNaN := float32_is_signaling_nan( a );
  1170. bIsNaN := float32_is_nan( b );
  1171. bIsSignalingNaN := float32_is_signaling_nan( b );
  1172. a := a or $00400000;
  1173. b := b or $00400000;
  1174. if ( aIsSignalingNaN or bIsSignalingNaN ) <> 0 then
  1175. float_raise( float_flag_invalid );
  1176. if ( aIsSignalingNaN )<> 0 then
  1177. Begin
  1178. if ( bIsSignalingNaN ) <> 0 then
  1179. goto returnLargerSignificand;
  1180. if bIsNan <> 0 then
  1181. propagateFloat32NaN := b
  1182. else
  1183. propagateFloat32NaN := a;
  1184. exit;
  1185. End
  1186. else if ( aIsNaN <> 0) then
  1187. Begin
  1188. if ( bIsSignalingNaN or not bIsNaN )<> 0 then
  1189. Begin
  1190. propagateFloat32NaN := a;
  1191. exit;
  1192. End;
  1193. returnLargerSignificand:
  1194. if ( bits32 ( a shl 1 ) < bits32 ( b shl 1 ) ) then
  1195. Begin
  1196. propagateFloat32NaN := b;
  1197. exit;
  1198. End;
  1199. if ( bits32 ( b shl 1 ) < bits32 ( a shl 1 ) ) then
  1200. Begin
  1201. propagateFloat32NaN := a;
  1202. End;
  1203. if a < b then
  1204. propagateFloat32NaN := a
  1205. else
  1206. propagateFloat32NaN := b;
  1207. exit;
  1208. End
  1209. else
  1210. Begin
  1211. propagateFloat32NaN := b;
  1212. exit;
  1213. End;
  1214. End;
  1215. {*
  1216. -------------------------------------------------------------------------------
  1217. The pattern for a default generated double-precision NaN. The `high' and
  1218. `low' values hold the most- and least-significant bits, respectively.
  1219. -------------------------------------------------------------------------------
  1220. *}
  1221. const
  1222. float64_default_nan_high = $FFF80000;
  1223. float64_default_nan_low = $00000000;
  1224. {*
  1225. -------------------------------------------------------------------------------
  1226. Returns 1 if the double-precision floating-point value `a' is a NaN;
  1227. otherwise returns 0.
  1228. -------------------------------------------------------------------------------
  1229. *}
  1230. Function float64_is_nan( a : float64 ) : flag;
  1231. Begin
  1232. float64_is_nan :=
  1233. flag( $FFE00000 <= bits32 ( a.high shl 1 ) )
  1234. and ( a.low or ( a.high and $000FFFFF ) );
  1235. End;
  1236. {*
  1237. -------------------------------------------------------------------------------
  1238. Returns 1 if the double-precision floating-point value `a' is a signaling
  1239. NaN; otherwise returns 0.
  1240. -------------------------------------------------------------------------------
  1241. *}
  1242. Function float64_is_signaling_nan( a : float64 ): flag;
  1243. Begin
  1244. float64_is_signaling_nan :=
  1245. flag( ( ( a.high shr 19 ) and $FFF ) = $FFE )
  1246. and ( a.low or ( a.high and $0007FFFF ) );
  1247. End;
  1248. {*
  1249. -------------------------------------------------------------------------------
  1250. Returns the result of converting the double-precision floating-point NaN
  1251. `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1252. exception is raised.
  1253. -------------------------------------------------------------------------------
  1254. *}
  1255. Procedure float64ToCommonNaN( a : float64; VAR c:commonNaNT );
  1256. Var
  1257. z : commonNaNT;
  1258. Begin
  1259. if ( float64_is_signaling_nan( a )<>0 ) then
  1260. float_raise( float_flag_invalid );
  1261. z.sign := a.high shr 31;
  1262. shortShift64Left( a.high, a.low, 12, z.high, z.low );
  1263. c := z;
  1264. End;
  1265. {*
  1266. -------------------------------------------------------------------------------
  1267. Returns the result of converting the canonical NaN `a' to the double-
  1268. precision floating-point format.
  1269. -------------------------------------------------------------------------------
  1270. *}
  1271. Procedure commonNaNToFloat64( a : commonNaNT; VAR c: float64 );
  1272. Var
  1273. z: float64;
  1274. Begin
  1275. shift64Right( a.high, a.low, 12, z.high, z.low );
  1276. z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;
  1277. c := z;
  1278. End;
  1279. {*
  1280. -------------------------------------------------------------------------------
  1281. Takes two double-precision floating-point values `a' and `b', one of which
  1282. is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1283. signaling NaN, the invalid exception is raised.
  1284. -------------------------------------------------------------------------------
  1285. *}
  1286. Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );
  1287. Var
  1288. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1289. label returnLargerSignificand;
  1290. Begin
  1291. aIsNaN := float64_is_nan( a );
  1292. aIsSignalingNaN := float64_is_signaling_nan( a );
  1293. bIsNaN := float64_is_nan( b );
  1294. bIsSignalingNaN := float64_is_signaling_nan( b );
  1295. a.high := a.high or $00080000;
  1296. b.high := b.high or $00080000;
  1297. if ( aIsSignalingNaN or bIsSignalingNaN )<> 0 then
  1298. float_raise( float_flag_invalid );
  1299. if ( aIsSignalingNaN )<>0 then
  1300. Begin
  1301. if ( bIsSignalingNaN )<>0 then
  1302. goto returnLargerSignificand;
  1303. if bIsNan <> 0 then
  1304. c := b
  1305. else
  1306. c := a;
  1307. exit;
  1308. End
  1309. else if ( aIsNaN )<> 0 then
  1310. Begin
  1311. if ( bIsSignalingNaN or not bIsNaN ) <> 0 then
  1312. Begin
  1313. c := a;
  1314. exit;
  1315. End;
  1316. returnLargerSignificand:
  1317. if ( lt64( a.high shl 1, a.low, b.high shl 1, b.low ) ) <> 0 then
  1318. Begin
  1319. c := b;
  1320. exit;
  1321. End;
  1322. if ( lt64( b.high shl 1, b.low, a.high shl 1, a.low ) ) <> 0 then
  1323. Begin
  1324. c := a;
  1325. exit;
  1326. End;
  1327. if a.high < b.high then
  1328. c := a
  1329. else
  1330. c := b;
  1331. exit;
  1332. End
  1333. else
  1334. Begin
  1335. c := b;
  1336. exit;
  1337. End;
  1338. End;
  1339. {$ELSE}
  1340. { Big endian code }
  1341. (*----------------------------------------------------------------------------
  1342. | Internal canonical NaN format.
  1343. *----------------------------------------------------------------------------*)
  1344. type
  1345. commonNANT = packed record
  1346. sign : flag;
  1347. high, low : bits32;
  1348. end;
  1349. (*----------------------------------------------------------------------------
  1350. | The pattern for a default generated single-precision NaN.
  1351. *----------------------------------------------------------------------------*)
  1352. const float32_default_nan = $7FFFFFFF;
  1353. (*----------------------------------------------------------------------------
  1354. | Returns 1 if the single-precision floating-point value `a' is a NaN;
  1355. | otherwise returns 0.
  1356. *----------------------------------------------------------------------------*)
  1357. function float32_is_nan(a: float32): flag;
  1358. begin
  1359. float32_is_nan := flag( $FF000000 < bits32( a shl 1 ) );
  1360. end;
  1361. (*----------------------------------------------------------------------------
  1362. | Returns 1 if the single-precision floating-point value `a' is a signaling
  1363. | NaN; otherwise returns 0.
  1364. *----------------------------------------------------------------------------*)
  1365. function float32_is_signaling_nan(a: float32):flag;
  1366. begin
  1367. float32_is_signaling_nan := flag( ( ( a shr 22 ) and $1FF ) = $1FE ) and flag( boolean((a and $003FFFFF)<>0) );
  1368. end;
  1369. (*----------------------------------------------------------------------------
  1370. | Returns the result of converting the single-precision floating-point NaN
  1371. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1372. | exception is raised.
  1373. *----------------------------------------------------------------------------*)
  1374. Procedure float32ToCommonNaN( a: float32; VAR c:commonNaNT );
  1375. var
  1376. z: commonNANT;
  1377. begin
  1378. if float32_is_signaling_nan(a)<>0 then
  1379. float_raise(float_flag_invalid);
  1380. z.sign := a shr 31;
  1381. z.low := 0;
  1382. z.high := a shl 9;
  1383. c:=z;
  1384. end;
  1385. (*----------------------------------------------------------------------------
  1386. | Returns the result of converting the canonical NaN `a' to the single-
  1387. | precision floating-point format.
  1388. *----------------------------------------------------------------------------*)
  1389. function CommonNanToFloat32(a : CommonNaNT): float32;
  1390. begin
  1391. CommonNanToFloat32:= ( ( bits32( a.sign )) shl 31 ) OR $7FC00000 OR ( a.high shr 9 );
  1392. end;
  1393. (*----------------------------------------------------------------------------
  1394. | Takes two single-precision floating-point values `a' and `b', one of which
  1395. | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1396. | signaling NaN, the invalid exception is raised.
  1397. *----------------------------------------------------------------------------*)
  1398. function propagateFloat32NaN( a: float32 ; b: float32): float32;
  1399. var
  1400. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1401. begin
  1402. aIsNaN := float32_is_nan( a );
  1403. aIsSignalingNaN := float32_is_signaling_nan( a );
  1404. bIsNaN := float32_is_nan( b );
  1405. bIsSignalingNaN := float32_is_signaling_nan( b );
  1406. a := a or $00400000;
  1407. b := b or $00400000;
  1408. if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then
  1409. float_raise( float_flag_invalid );
  1410. if bIsSignalingNaN<>0 then
  1411. propagateFloat32Nan := b
  1412. else if aIsSignalingNan<>0 then
  1413. propagateFloat32Nan := a
  1414. else if bIsNan<>0 then
  1415. propagateFloat32Nan := b
  1416. else
  1417. propagateFloat32Nan := a;
  1418. end;
  1419. (*----------------------------------------------------------------------------
  1420. | The pattern for a default generated double-precision NaN. The `high' and
  1421. | `low' values hold the most- and least-significant bits, respectively.
  1422. *----------------------------------------------------------------------------*)
  1423. const
  1424. float64_default_nan_high = $7FFFFFFF;
  1425. float64_default_nan_low = $FFFFFFFF;
  1426. (*----------------------------------------------------------------------------
  1427. | Returns 1 if the double-precision floating-point value `a' is a NaN;
  1428. | otherwise returns 0.
  1429. *----------------------------------------------------------------------------*)
  1430. function float64_is_nan(a: float64): flag;
  1431. begin
  1432. float64_is_nan := flag (
  1433. ( $FFE00000 <= bits32 ( a.high shl 1 ) )
  1434. and ( (a.low<>0) or (( a.high and $000FFFFF )<>0) ));
  1435. end;
  1436. (*----------------------------------------------------------------------------
  1437. | Returns 1 if the double-precision floating-point value `a' is a signaling
  1438. | NaN; otherwise returns 0.
  1439. *----------------------------------------------------------------------------*)
  1440. function float64_is_signaling_nan( a:float64): flag;
  1441. begin
  1442. float64_is_signaling_nan := flag
  1443. ( ( ( a.high shr 19 ) and $FFF ) = $FFE )
  1444. and ( (a.low<>0) or ( boolean(( a.high and $0007FFFF )<>0)) );
  1445. end;
  1446. (*----------------------------------------------------------------------------
  1447. | Returns the result of converting the double-precision floating-point NaN
  1448. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1449. | exception is raised.
  1450. *----------------------------------------------------------------------------*)
  1451. Procedure float64ToCommonNaN( a : float64; VAR c:commonNaNT );
  1452. var
  1453. z : commonNaNT;
  1454. begin
  1455. if ( float64_is_signaling_nan( a )<>0 ) then
  1456. float_raise( float_flag_invalid );
  1457. z.sign := a.high shr 31;
  1458. shortShift64Left( a.high, a.low, 12, z.high, z.low );
  1459. c:=z;
  1460. end;
  1461. (*----------------------------------------------------------------------------
  1462. | Returns the result of converting the canonical NaN `a' to the double-
  1463. | precision floating-point format.
  1464. *----------------------------------------------------------------------------*)
  1465. Procedure commonNaNToFloat64( a : commonNaNT; VAR c: float64 );
  1466. var
  1467. z: float64;
  1468. begin
  1469. shift64Right( a.high, a.low, 12, z.high, z.low );
  1470. z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;
  1471. c:=z;
  1472. end;
  1473. (*----------------------------------------------------------------------------
  1474. | Takes two double-precision floating-point values `a' and `b', one of which
  1475. | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1476. | signaling NaN, the invalid exception is raised.
  1477. *----------------------------------------------------------------------------*)
  1478. Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );
  1479. var
  1480. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN : flag;
  1481. begin
  1482. aIsNaN := float64_is_nan( a );
  1483. aIsSignalingNaN := float64_is_signaling_nan( a );
  1484. bIsNaN := float64_is_nan( b );
  1485. bIsSignalingNaN := float64_is_signaling_nan( b );
  1486. a.high := a.high or $00080000;
  1487. b.high := b.high or $00080000;
  1488. if ( (aIsSignalingNaN<>0) or (bIsSignalingNaN<>0) ) then
  1489. float_raise( float_flag_invalid );
  1490. if bIsSignalingNaN<>0 then
  1491. c := b
  1492. else if aIsSignalingNan<>0 then
  1493. c := a
  1494. else if bIsNan<>0 then
  1495. c := b
  1496. else
  1497. c := a;
  1498. end;
  1499. {$ENDIF}
  1500. (****************************************************************************)
  1501. (* END ENDIAN SPECIFIC CODE *)
  1502. (****************************************************************************)
  1503. {*
  1504. -------------------------------------------------------------------------------
  1505. Returns the fraction bits of the single-precision floating-point value `a'.
  1506. -------------------------------------------------------------------------------
  1507. *}
  1508. Function ExtractFloat32Frac(a : Float32) : Bits32;
  1509. Begin
  1510. ExtractFloat32Frac := A AND $007FFFFF;
  1511. End;
  1512. {*
  1513. -------------------------------------------------------------------------------
  1514. Returns the exponent bits of the single-precision floating-point value `a'.
  1515. -------------------------------------------------------------------------------
  1516. *}
  1517. Function extractFloat32Exp( a: float32 ): Int16;
  1518. Begin
  1519. extractFloat32Exp := (a shr 23) AND $FF;
  1520. End;
  1521. {*
  1522. -------------------------------------------------------------------------------
  1523. Returns the sign bit of the single-precision floating-point value `a'.
  1524. -------------------------------------------------------------------------------
  1525. *}
  1526. Function extractFloat32Sign( a: float32 ): Flag;
  1527. Begin
  1528. extractFloat32Sign := a shr 31;
  1529. End;
  1530. {*
  1531. -------------------------------------------------------------------------------
  1532. Normalizes the subnormal single-precision floating-point value represented
  1533. by the denormalized significand `aSig'. The normalized exponent and
  1534. significand are stored at the locations pointed to by `zExpPtr' and
  1535. `zSigPtr', respectively.
  1536. -------------------------------------------------------------------------------
  1537. *}
  1538. Procedure normalizeFloat32Subnormal( aSig : bits32; VAR zExpPtr: Int16; VAR zSigPtr :bits32);
  1539. Var
  1540. ShiftCount : BYTE;
  1541. Begin
  1542. shiftCount := countLeadingZeros32( aSig ) - 8;
  1543. zSigPtr := aSig shl shiftCount;
  1544. zExpPtr := 1 - shiftCount;
  1545. End;
  1546. {*
  1547. -------------------------------------------------------------------------------
  1548. Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
  1549. single-precision floating-point value, returning the result. After being
  1550. shifted into the proper positions, the three fields are simply added
  1551. together to form the result. This means that any integer portion of `zSig'
  1552. will be added into the exponent. Since a properly normalized significand
  1553. will have an integer portion equal to 1, the `zExp' input should be 1 less
  1554. than the desired result exponent whenever `zSig' is a complete, normalized
  1555. significand.
  1556. -------------------------------------------------------------------------------
  1557. *}
  1558. Function packFloat32( zSign: Flag; zExp : Int16; zSig: Bits32 ): Float32;
  1559. Begin
  1560. packFloat32 := ( ( bits32( zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 23 )
  1561. + zSig;
  1562. End;
  1563. {*
  1564. -------------------------------------------------------------------------------
  1565. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  1566. and significand `zSig', and returns the proper single-precision floating-
  1567. point value corresponding to the abstract input. Ordinarily, the abstract
  1568. value is simply rounded and packed into the single-precision format, with
  1569. the inexact exception raised if the abstract input cannot be represented
  1570. exactly. However, if the abstract value is too large, the overflow and
  1571. inexact exceptions are raised and an infinity or maximal finite value is
  1572. returned. If the abstract value is too small, the input value is rounded to
  1573. a subnormal number, and the underflow and inexact exceptions are raised if
  1574. the abstract input cannot be represented exactly as a subnormal single-
  1575. precision floating-point number.
  1576. The input significand `zSig' has its binary point between bits 30
  1577. and 29, which is 7 bits to the left of the usual location. This shifted
  1578. significand must be normalized or smaller. If `zSig' is not normalized,
  1579. `zExp' must be 0; in that case, the result returned is a subnormal number,
  1580. and it must not require rounding. In the usual case that `zSig' is
  1581. normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
  1582. The handling of underflow and overflow follows the IEC/IEEE Standard for
  1583. Binary Floating-Point Arithmetic.
  1584. -------------------------------------------------------------------------------
  1585. *}
  1586. Function roundAndPackFloat32( zSign : Flag; zExp : Int16; zSig : Bits32 ) : float32;
  1587. Var
  1588. roundingMode : BYTE;
  1589. roundNearestEven : Flag;
  1590. roundIncrement, roundBits : BYTE;
  1591. IsTiny : Flag;
  1592. Begin
  1593. roundingMode := float_rounding_mode;
  1594. if (roundingMode = float_round_nearest_even) then
  1595. Begin
  1596. roundNearestEven := Flag(TRUE);
  1597. end
  1598. else
  1599. roundNearestEven := Flag(FALSE);
  1600. roundIncrement := $40;
  1601. if ( Boolean(roundNearestEven) = FALSE) then
  1602. Begin
  1603. if ( roundingMode = float_round_to_zero ) Then
  1604. Begin
  1605. roundIncrement := 0;
  1606. End
  1607. else
  1608. Begin
  1609. roundIncrement := $7F;
  1610. if ( zSign <> 0 ) then
  1611. Begin
  1612. if roundingMode = float_round_up then roundIncrement := 0;
  1613. End
  1614. else
  1615. Begin
  1616. if roundingMode = float_round_down then roundIncrement := 0;
  1617. End;
  1618. End
  1619. End;
  1620. roundBits := zSig AND $7F;
  1621. if ($FD <= bits16 (zExp) ) then
  1622. Begin
  1623. if (( $FD < zExp ) OR ( zExp = $FD ) AND ( sbits32 ( zSig + roundIncrement ) < 0 ) ) then
  1624. Begin
  1625. float_raise( float_flag_overflow OR float_flag_inexact );
  1626. roundAndPackFloat32:=packFloat32( zSign, $FF, 0 ) - Flag( roundIncrement = 0 );
  1627. exit;
  1628. End;
  1629. if ( zExp < 0 ) then
  1630. Begin
  1631. isTiny :=
  1632. flag(( float_detect_tininess = float_tininess_before_rounding )
  1633. OR ( zExp < -1 )
  1634. OR ( (zSig + roundIncrement) < $80000000 ));
  1635. shift32RightJamming( zSig, - zExp, zSig );
  1636. zExp := 0;
  1637. roundBits := zSig AND $7F;
  1638. if ( (isTiny = flag(TRUE)) and (roundBits<>0) ) then
  1639. float_raise( float_flag_underflow );
  1640. End;
  1641. End;
  1642. if ( roundBits )<> 0 then
  1643. float_exception_flags := float_flag_inexact OR float_exception_flags;
  1644. zSig := ( zSig + roundIncrement ) shr 7;
  1645. zSig := zSig AND not bits32( bits32( ( roundBits XOR $40 ) = 0 ) and roundNearestEven );
  1646. if ( zSig = 0 ) then zExp := 0;
  1647. roundAndPackFloat32 := packFloat32( zSign, zExp, zSig );
  1648. exit;
  1649. End;
  1650. {*
  1651. -------------------------------------------------------------------------------
  1652. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  1653. and significand `zSig', and returns the proper single-precision floating-
  1654. point value corresponding to the abstract input. This routine is just like
  1655. `roundAndPackFloat32' except that `zSig' does not have to be normalized.
  1656. Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
  1657. floating-point exponent.
  1658. -------------------------------------------------------------------------------
  1659. *}
  1660. Function normalizeRoundAndPackFloat32( zSign: flag; zExp: int16; zSig:bits32 ): float32;
  1661. Var
  1662. ShiftCount : int8;
  1663. Begin
  1664. shiftCount := countLeadingZeros32( zSig ) - 1;
  1665. normalizeRoundAndPackFloat32 := roundAndPackFloat32( zSign, zExp - shiftCount, zSig shl shiftCount );
  1666. End;
  1667. {*
  1668. -------------------------------------------------------------------------------
  1669. Returns the least-significant 32 fraction bits of the double-precision
  1670. floating-point value `a'.
  1671. -------------------------------------------------------------------------------
  1672. *}
  1673. Function extractFloat64Frac( a: float64 ): bits32;
  1674. Begin
  1675. extractFloat64Frac := a.low;
  1676. End;
  1677. {*
  1678. -------------------------------------------------------------------------------
  1679. Returns the most-significant 20 fraction bits of the double-precision
  1680. floating-point value `a'.
  1681. -------------------------------------------------------------------------------
  1682. *}
  1683. Function extractFloat64Frac0(a: float64): bits32;
  1684. Begin
  1685. extractFloat64Frac0 := a.high and $000FFFFF;
  1686. End;
  1687. {*
  1688. -------------------------------------------------------------------------------
  1689. Returns the least-significant 32 fraction bits of the double-precision
  1690. floating-point value `a'.
  1691. -------------------------------------------------------------------------------
  1692. *}
  1693. Function extractFloat64Frac1(a: float64): bits32;
  1694. Begin
  1695. extractFloat64Frac1 := a.low;
  1696. End;
  1697. {*
  1698. -------------------------------------------------------------------------------
  1699. Returns the exponent bits of the double-precision floating-point value `a'.
  1700. -------------------------------------------------------------------------------
  1701. *}
  1702. Function extractFloat64Exp(a: float64): int16;
  1703. Begin
  1704. extractFloat64Exp:= ( a.high shr 20 ) AND $7FF;
  1705. End;
  1706. {*
  1707. -------------------------------------------------------------------------------
  1708. Returns the sign bit of the double-precision floating-point value `a'.
  1709. -------------------------------------------------------------------------------
  1710. *}
  1711. Function extractFloat64Sign(a: float64) : flag;
  1712. Begin
  1713. extractFloat64Sign := a.high shr 31;
  1714. End;
  1715. {*
  1716. -------------------------------------------------------------------------------
  1717. Normalizes the subnormal double-precision floating-point value represented
  1718. by the denormalized significand formed by the concatenation of `aSig0' and
  1719. `aSig1'. The normalized exponent is stored at the location pointed to by
  1720. `zExpPtr'. The most significant 21 bits of the normalized significand are
  1721. stored at the location pointed to by `zSig0Ptr', and the least significant
  1722. 32 bits of the normalized significand are stored at the location pointed to
  1723. by `zSig1Ptr'.
  1724. -------------------------------------------------------------------------------
  1725. *}
  1726. Procedure normalizeFloat64Subnormal(
  1727. aSig0: bits32;
  1728. aSig1: bits32;
  1729. VAR zExpPtr : Int16;
  1730. VAR zSig0Ptr : Bits32;
  1731. VAR zSig1Ptr : Bits32
  1732. );
  1733. Var
  1734. ShiftCount : Int8;
  1735. Begin
  1736. if ( aSig0 = 0 ) then
  1737. Begin
  1738. shiftCount := countLeadingZeros32( aSig1 ) - 11;
  1739. if ( shiftCount < 0 ) then
  1740. Begin
  1741. zSig0Ptr := aSig1 shr ( - shiftCount );
  1742. zSig1Ptr := aSig1 shl ( shiftCount AND 31 );
  1743. End
  1744. else
  1745. Begin
  1746. zSig0Ptr := aSig1 shl shiftCount;
  1747. zSig1Ptr := 0;
  1748. End;
  1749. zExpPtr := - shiftCount - 31;
  1750. End
  1751. else
  1752. Begin
  1753. shiftCount := countLeadingZeros32( aSig0 ) - 11;
  1754. shortShift64Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
  1755. zExpPtr := 1 - shiftCount;
  1756. End;
  1757. End;
  1758. {*
  1759. -------------------------------------------------------------------------------
  1760. Packs the sign `zSign', the exponent `zExp', and the significand formed by
  1761. the concatenation of `zSig0' and `zSig1' into a double-precision floating-
  1762. point value, returning the result. After being shifted into the proper
  1763. positions, the three fields `zSign', `zExp', and `zSig0' are simply added
  1764. together to form the most significant 32 bits of the result. This means
  1765. that any integer portion of `zSig0' will be added into the exponent. Since
  1766. a properly normalized significand will have an integer portion equal to 1,
  1767. the `zExp' input should be 1 less than the desired result exponent whenever
  1768. `zSig0' and `zSig1' concatenated form a complete, normalized significand.
  1769. -------------------------------------------------------------------------------
  1770. *}
  1771. Procedure
  1772. packFloat64( zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1 : Bits32; VAR c : float64);
  1773. var
  1774. z: Float64;
  1775. Begin
  1776. z.low := zSig1;
  1777. z.high := ( ( bits32 (zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 20 ) + zSig0;
  1778. c := z;
  1779. End;
  1780. {*
  1781. -------------------------------------------------------------------------------
  1782. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  1783. and extended significand formed by the concatenation of `zSig0', `zSig1',
  1784. and `zSig2', and returns the proper double-precision floating-point value
  1785. corresponding to the abstract input. Ordinarily, the abstract value is
  1786. simply rounded and packed into the double-precision format, with the inexact
  1787. exception raised if the abstract input cannot be represented exactly.
  1788. However, if the abstract value is too large, the overflow and inexact
  1789. exceptions are raised and an infinity or maximal finite value is returned.
  1790. If the abstract value is too small, the input value is rounded to a
  1791. subnormal number, and the underflow and inexact exceptions are raised if the
  1792. abstract input cannot be represented exactly as a subnormal double-precision
  1793. floating-point number.
  1794. The input significand must be normalized or smaller. If the input
  1795. significand is not normalized, `zExp' must be 0; in that case, the result
  1796. returned is a subnormal number, and it must not require rounding. In the
  1797. usual case that the input significand is normalized, `zExp' must be 1 less
  1798. than the ``true'' floating-point exponent. The handling of underflow and
  1799. overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  1800. -------------------------------------------------------------------------------
  1801. *}
  1802. Procedure
  1803. roundAndPackFloat64(
  1804. zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1: Bits32; zSig2: Bits32; Var c: Float64 );
  1805. Var
  1806. roundingMode : Int8;
  1807. roundNearestEven, increment, isTiny : Flag;
  1808. Begin
  1809. roundingMode := float_rounding_mode;
  1810. roundNearestEven := flag( roundingMode = float_round_nearest_even );
  1811. increment := flag( sbits32 (zSig2) < 0 );
  1812. if ( roundNearestEven = flag(FALSE) ) then
  1813. Begin
  1814. if ( roundingMode = float_round_to_zero ) then
  1815. increment := 0
  1816. else
  1817. Begin
  1818. if ( zSign )<> 0 then
  1819. Begin
  1820. increment := flag( roundingMode = float_round_down ) and zSig2;
  1821. End
  1822. else
  1823. Begin
  1824. increment := flag( roundingMode = float_round_up ) and zSig2;
  1825. End
  1826. End
  1827. End;
  1828. if ( $7FD <= bits16 (zExp) ) then
  1829. Begin
  1830. if (( $7FD < zExp )
  1831. or (( zExp = $7FD )
  1832. and (eq64( $001FFFFF, $FFFFFFFF, zSig0, zSig1 )<>0)
  1833. and (increment<>0)
  1834. )
  1835. ) then
  1836. Begin
  1837. float_raise( float_flag_overflow OR float_flag_inexact );
  1838. if (( roundingMode = float_round_to_zero )
  1839. or ( (zSign<>0) and ( roundingMode = float_round_up ) )
  1840. or ( (zSign = 0) and ( roundingMode = float_round_down ) )
  1841. ) then
  1842. Begin
  1843. packFloat64( zSign, $7FE, $000FFFFF, $FFFFFFFF, c );
  1844. exit;
  1845. End;
  1846. packFloat64( zSign, $7FF, 0, 0, c );
  1847. exit;
  1848. End;
  1849. if ( zExp < 0 ) then
  1850. Begin
  1851. isTiny :=
  1852. flag( float_detect_tininess = float_tininess_before_rounding )
  1853. or flag( zExp < -1 )
  1854. or flag(increment = 0)
  1855. or flag(lt64( zSig0, zSig1, $001FFFFF, $FFFFFFFF)<>0);
  1856. shift64ExtraRightJamming(
  1857. zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );
  1858. zExp := 0;
  1859. if ( isTiny<>0) and (zSig2<>0 ) then float_raise( float_flag_underflow );
  1860. if ( roundNearestEven )<>0 then
  1861. Begin
  1862. increment := flag( sbits32 (zSig2) < 0 );
  1863. End
  1864. else
  1865. Begin
  1866. if ( zSign )<>0 then
  1867. Begin
  1868. increment := flag( roundingMode = float_round_down ) and zSig2;
  1869. End
  1870. else
  1871. Begin
  1872. increment := flag( roundingMode = float_round_up ) and zSig2;
  1873. End
  1874. End;
  1875. End;
  1876. End;
  1877. if ( zSig2 )<>0 then
  1878. float_exception_flags := float_exception_flags OR float_flag_inexact;
  1879. if ( increment )<>0 then
  1880. Begin
  1881. add64( zSig0, zSig1, 0, 1, zSig0, zSig1 );
  1882. zSig1 := zSig1 and not ( bits32(flag( zSig2 + zSig2 = 0 )) and roundNearestEven );
  1883. End
  1884. else
  1885. Begin
  1886. if ( ( zSig0 or zSig1 ) = 0 ) then zExp := 0;
  1887. End;
  1888. packFloat64( zSign, zExp, zSig0, zSig1, c );
  1889. End;
  1890. {*
  1891. -------------------------------------------------------------------------------
  1892. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  1893. and significand formed by the concatenation of `zSig0' and `zSig1', and
  1894. returns the proper double-precision floating-point value corresponding
  1895. to the abstract input. This routine is just like `roundAndPackFloat64'
  1896. except that the input significand has fewer bits and does not have to be
  1897. normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
  1898. point exponent.
  1899. -------------------------------------------------------------------------------
  1900. *}
  1901. Procedure
  1902. normalizeRoundAndPackFloat64(
  1903. zSign:flag; zExp:int16; zSig0:bits32; zSig1:bits32; VAR c: float64 );
  1904. Var
  1905. shiftCount : int8;
  1906. zSig2 : bits32;
  1907. Begin
  1908. if ( zSig0 = 0 ) then
  1909. Begin
  1910. zSig0 := zSig1;
  1911. zSig1 := 0;
  1912. zExp := zExp -32;
  1913. End;
  1914. shiftCount := countLeadingZeros32( zSig0 ) - 11;
  1915. if ( 0 <= shiftCount ) then
  1916. Begin
  1917. zSig2 := 0;
  1918. shortShift64Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  1919. End
  1920. else
  1921. Begin
  1922. shift64ExtraRightJamming
  1923. (zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );
  1924. End;
  1925. zExp := zExp - shiftCount;
  1926. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, c );
  1927. End;
  1928. {*
  1929. -------------------------------------------------------------------------------
  1930. Returns the result of converting the 32-bit two's complement integer `a' to
  1931. the single-precision floating-point format. The conversion is performed
  1932. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  1933. -------------------------------------------------------------------------------
  1934. *}
  1935. Function int32_to_float32( a: int32): float32; {$ifdef fpc}[public,Alias:'INT32_TO_FLOAT32'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  1936. Var
  1937. zSign : Flag;
  1938. Begin
  1939. if ( a = 0 ) then
  1940. Begin
  1941. int32_to_float32 := 0;
  1942. exit;
  1943. End;
  1944. if ( a = sbits32 ($80000000) ) then
  1945. Begin
  1946. int32_to_float32 := packFloat32( 1, $9E, 0 );
  1947. exit;
  1948. end;
  1949. zSign := flag( a < 0 );
  1950. If zSign<>0 then
  1951. a := -a;
  1952. int32_to_float32:=
  1953. normalizeRoundAndPackFloat32( zSign, $9C, a );
  1954. End;
  1955. {*
  1956. -------------------------------------------------------------------------------
  1957. Returns the result of converting the 32-bit two's complement integer `a' to
  1958. the double-precision floating-point format. The conversion is performed
  1959. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  1960. -------------------------------------------------------------------------------
  1961. *}
  1962. Procedure int32_to_float64( a: int32; var c: float64 );{$ifdef fpc} [public,Alias:'INT32_TO_FLOAT64'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  1963. var
  1964. zSign : flag;
  1965. absA : bits32;
  1966. shiftCount : int8;
  1967. zSig0, zSig1 : bits32;
  1968. Begin
  1969. if ( a = 0 ) then
  1970. Begin
  1971. packFloat64( 0, 0, 0, 0, c );
  1972. exit;
  1973. end;
  1974. zSign := flag( a < 0 );
  1975. if ZSign<>0 then
  1976. AbsA := -a
  1977. else
  1978. AbsA := a;
  1979. shiftCount := countLeadingZeros32( absA ) - 11;
  1980. if ( 0 <= shiftCount ) then
  1981. Begin
  1982. zSig0 := absA shl shiftCount;
  1983. zSig1 := 0;
  1984. End
  1985. else
  1986. Begin
  1987. shift64Right( absA, 0, - shiftCount, zSig0, zSig1 );
  1988. End;
  1989. packFloat64( zSign, $412 - shiftCount, zSig0, zSig1,c );
  1990. End;
  1991. {*
  1992. -------------------------------------------------------------------------------
  1993. Returns the result of converting the single-precision floating-point value
  1994. `a' to the 32-bit two's complement integer format. The conversion is
  1995. performed according to the IEC/IEEE Standard for Binary Floating-Point
  1996. Arithmetic---which means in particular that the conversion is rounded
  1997. according to the current rounding mode. If `a' is a NaN, the largest
  1998. positive integer is returned. Otherwise, if the conversion overflows, the
  1999. largest integer with the same sign as `a' is returned.
  2000. -------------------------------------------------------------------------------
  2001. *}
  2002. Function float32_to_int32( a : float32) : int32;{$ifdef fpc} [public,Alias:'FLOAT32_TO_INT32'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2003. Var
  2004. aSign: flag;
  2005. aExp, shiftCount: int16;
  2006. aSig, aSigExtra: bits32;
  2007. z: int32;
  2008. roundingMode: int8;
  2009. Begin
  2010. aSig := extractFloat32Frac( a );
  2011. aExp := extractFloat32Exp( a );
  2012. aSign := extractFloat32Sign( a );
  2013. shiftCount := aExp - $96;
  2014. if ( 0 <= shiftCount ) then
  2015. Begin
  2016. if ( $9E <= aExp ) then
  2017. Begin
  2018. if ( a <> $CF000000 ) then
  2019. Begin
  2020. float_raise( float_flag_invalid );
  2021. if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  2022. Begin
  2023. float32_to_int32 := $7FFFFFFF;
  2024. exit;
  2025. End;
  2026. End;
  2027. float32_to_int32 := sbits32 ($80000000);
  2028. exit;
  2029. End;
  2030. z := ( aSig or $00800000 ) shl shiftCount;
  2031. if ( aSign<>0 ) then z := - z;
  2032. End
  2033. else
  2034. Begin
  2035. if ( aExp < $7E ) then
  2036. Begin
  2037. aSigExtra := aExp OR aSig;
  2038. z := 0;
  2039. End
  2040. else
  2041. Begin
  2042. aSig := aSig OR $00800000;
  2043. aSigExtra := aSig shl ( shiftCount and 31 );
  2044. z := aSig shr ( - shiftCount );
  2045. End;
  2046. if ( aSigExtra<>0 ) then
  2047. float_exception_flags := float_exception_flags
  2048. or float_flag_inexact;
  2049. roundingMode := float_rounding_mode;
  2050. if ( roundingMode = float_round_nearest_even ) then
  2051. Begin
  2052. if ( sbits32 (aSigExtra) < 0 ) then
  2053. Begin
  2054. Inc(z);
  2055. if ( bits32 ( aSigExtra shl 1 ) = 0 ) then
  2056. z := z and not 1;
  2057. End;
  2058. if ( aSign<>0 ) then
  2059. z := - z;
  2060. End
  2061. else
  2062. Begin
  2063. aSigExtra := flag( aSigExtra <> 0 );
  2064. if ( aSign<>0 ) then
  2065. Begin
  2066. z := z + (flag( roundingMode = float_round_down ) and aSigExtra);
  2067. z := - z;
  2068. End
  2069. else
  2070. Begin
  2071. z := z + (flag( roundingMode = float_round_up ) and aSigExtra);
  2072. End
  2073. End;
  2074. End;
  2075. float32_to_int32 := z;
  2076. End;
  2077. {*
  2078. -------------------------------------------------------------------------------
  2079. Returns the result of converting the single-precision floating-point value
  2080. `a' to the 32-bit two's complement integer format. The conversion is
  2081. performed according to the IEC/IEEE Standard for Binary Floating-Point
  2082. Arithmetic, except that the conversion is always rounded toward zero.
  2083. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  2084. the conversion overflows, the largest integer with the same sign as `a' is
  2085. returned.
  2086. -------------------------------------------------------------------------------
  2087. *}
  2088. Function float32_to_int32_round_to_zero( a: Float32 ): int32;
  2089. {$ifdef fpc}[public,Alias:'FLOAT32_TO_INT32_ROUND_TO_ZERO'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2090. Var
  2091. aSign : flag;
  2092. aExp, shiftCount : int16;
  2093. aSig : bits32;
  2094. z : int32;
  2095. Begin
  2096. aSig := extractFloat32Frac( a );
  2097. aExp := extractFloat32Exp( a );
  2098. aSign := extractFloat32Sign( a );
  2099. shiftCount := aExp - $9E;
  2100. if ( 0 <= shiftCount ) then
  2101. Begin
  2102. if ( a <> $CF000000 ) then
  2103. Begin
  2104. float_raise( float_flag_invalid );
  2105. if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  2106. Begin
  2107. float32_to_int32_round_to_zero := $7FFFFFFF;
  2108. exit;
  2109. end;
  2110. End;
  2111. float32_to_int32_round_to_zero:= sbits32 ($80000000);
  2112. exit;
  2113. End
  2114. else
  2115. if ( aExp <= $7E ) then
  2116. Begin
  2117. if ( aExp or aSig )<>0 then
  2118. float_exception_flags :=
  2119. float_exception_flags or float_flag_inexact;
  2120. float32_to_int32_round_to_zero := 0;
  2121. exit;
  2122. End;
  2123. aSig := ( aSig or $00800000 ) shl 8;
  2124. z := aSig shr ( - shiftCount );
  2125. if ( bits32 ( aSig shl ( shiftCount and 31 ) )<> 0 ) then
  2126. Begin
  2127. float_exception_flags :=
  2128. float_exception_flags or float_flag_inexact;
  2129. End;
  2130. if ( aSign<>0 ) then z := - z;
  2131. float32_to_int32_round_to_zero := z;
  2132. End;
  2133. {*
  2134. -------------------------------------------------------------------------------
  2135. Returns the result of converting the single-precision floating-point value
  2136. `a' to the double-precision floating-point format. The conversion is
  2137. performed according to the IEC/IEEE Standard for Binary Floating-Point
  2138. Arithmetic.
  2139. -------------------------------------------------------------------------------
  2140. *}
  2141. Procedure float32_to_float64( a : float32; var out: Float64);
  2142. {$ifdef fpc}[public,Alias:'FLOAT32_TO_FLOAT64'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2143. Var
  2144. aSign : flag;
  2145. aExp : int16;
  2146. aSig, zSig0, zSig1: bits32;
  2147. tmp : CommonNanT;
  2148. Begin
  2149. aSig := extractFloat32Frac( a );
  2150. aExp := extractFloat32Exp( a );
  2151. aSign := extractFloat32Sign( a );
  2152. if ( aExp = $FF ) then
  2153. Begin
  2154. if ( aSig<>0 ) then
  2155. Begin
  2156. float32ToCommonNaN(a, tmp);
  2157. commonNaNToFloat64(tmp , out);
  2158. exit;
  2159. End;
  2160. packFloat64( aSign, $7FF, 0, 0, out );
  2161. exit;
  2162. End;
  2163. if ( aExp = 0 ) then
  2164. Begin
  2165. if ( aSig = 0 ) then
  2166. Begin
  2167. packFloat64( aSign, 0, 0, 0, out );
  2168. exit;
  2169. end;
  2170. normalizeFloat32Subnormal( aSig, aExp, aSig );
  2171. Dec(aExp);
  2172. End;
  2173. shift64Right( aSig, 0, 3, zSig0, zSig1 );
  2174. packFloat64( aSign, aExp + $380, zSig0, zSig1, out );
  2175. End;
  2176. {*
  2177. -------------------------------------------------------------------------------
  2178. Rounds the single-precision floating-point value `a' to an integer,
  2179. and returns the result as a single-precision floating-point value. The
  2180. operation is performed according to the IEC/IEEE Standard for Binary
  2181. Floating-Point Arithmetic.
  2182. -------------------------------------------------------------------------------
  2183. *}
  2184. Function float32_round_to_int( a: float32): float32;
  2185. {$ifdef fpc}[public,Alias:'FLOAT32_ROUND_TO_INT'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2186. Var
  2187. aSign: flag;
  2188. aExp: int16;
  2189. lastBitMask, roundBitsMask: bits32;
  2190. roundingMode: int8;
  2191. z: float32;
  2192. Begin
  2193. aExp := extractFloat32Exp( a );
  2194. if ( $96 <= aExp ) then
  2195. Begin
  2196. if ( ( aExp = $FF ) and (extractFloat32Frac( a )<>0) ) then
  2197. Begin
  2198. float32_round_to_int:= propagateFloat32NaN( a, a );
  2199. exit;
  2200. End;
  2201. float32_round_to_int:=a;
  2202. exit;
  2203. End;
  2204. if ( aExp <= $7E ) then
  2205. Begin
  2206. if ( bits32 ( a shl 1 ) = 0 ) then
  2207. Begin
  2208. float32_round_to_int:=a;
  2209. exit;
  2210. end;
  2211. float_exception_flags
  2212. := float_exception_flags OR float_flag_inexact;
  2213. aSign := extractFloat32Sign( a );
  2214. case ( float_rounding_mode ) of
  2215. float_round_nearest_even:
  2216. Begin
  2217. if ( ( aExp = $7E ) and (extractFloat32Frac( a )<>0) ) then
  2218. Begin
  2219. float32_round_to_int := packFloat32( aSign, $7F, 0 );
  2220. exit;
  2221. End;
  2222. End;
  2223. float_round_down:
  2224. Begin
  2225. if aSign <> 0 then
  2226. float32_round_to_int := $BF800000
  2227. else
  2228. float32_round_to_int := 0;
  2229. exit;
  2230. End;
  2231. float_round_up:
  2232. Begin
  2233. if aSign <> 0 then
  2234. float32_round_to_int := $80000000
  2235. else
  2236. float32_round_to_int := $3F800000;
  2237. exit;
  2238. End;
  2239. end;
  2240. float32_round_to_int := packFloat32( aSign, 0, 0 );
  2241. End;
  2242. lastBitMask := 1;
  2243. {_____________________________!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
  2244. lastBitMask := lastBitMask shl ($96 - aExp);
  2245. roundBitsMask := lastBitMask - 1;
  2246. z := a;
  2247. roundingMode := float_rounding_mode;
  2248. if ( roundingMode = float_round_nearest_even ) then
  2249. Begin
  2250. z := z + (lastBitMask shr 1);
  2251. if ( ( z and roundBitsMask ) = 0 ) then
  2252. z := z and not lastBitMask;
  2253. End
  2254. else if ( roundingMode <> float_round_to_zero ) then
  2255. Begin
  2256. if ( (extractFloat32Sign( z ) xor flag(roundingMode = float_round_up ))<>0 ) then
  2257. Begin
  2258. z := z + roundBitsMask;
  2259. End;
  2260. End;
  2261. z := z and not roundBitsMask;
  2262. if ( z <> a ) then
  2263. float_exception_flags := float_exception_flags or float_flag_inexact;
  2264. float32_round_to_int := z;
  2265. End;
  2266. {*
  2267. -------------------------------------------------------------------------------
  2268. Returns the result of adding the absolute values of the single-precision
  2269. floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  2270. before being returned. `zSign' is ignored if the result is a NaN.
  2271. The addition is performed according to the IEC/IEEE Standard for Binary
  2272. Floating-Point Arithmetic.
  2273. -------------------------------------------------------------------------------
  2274. *}
  2275. Function addFloat32Sigs( a:float32; b: float32; zSign:flag ): float32;
  2276. Var
  2277. aExp, bExp, zExp: int16;
  2278. aSig, bSig, zSig: bits32;
  2279. expDiff: int16;
  2280. label roundAndPack;
  2281. Begin
  2282. aSig:=extractFloat32Frac( a );
  2283. aExp:=extractFloat32Exp( a );
  2284. bSig:=extractFloat32Frac( b );
  2285. bExp := extractFloat32Exp( b );
  2286. expDiff := aExp - bExp;
  2287. aSig := aSig shl 6;
  2288. bSig := bSig shl 6;
  2289. if ( 0 < expDiff ) then
  2290. Begin
  2291. if ( aExp = $FF ) then
  2292. Begin
  2293. if ( aSig <> 0) then
  2294. Begin
  2295. addFloat32Sigs := propagateFloat32NaN( a, b );
  2296. exit;
  2297. End;
  2298. addFloat32Sigs := a;
  2299. exit;
  2300. End;
  2301. if ( bExp = 0 ) then
  2302. Begin
  2303. Dec(expDiff);
  2304. End
  2305. else
  2306. Begin
  2307. bSig := bSig or $20000000;
  2308. End;
  2309. shift32RightJamming( bSig, expDiff, bSig );
  2310. zExp := aExp;
  2311. End
  2312. else
  2313. If ( expDiff < 0 ) then
  2314. Begin
  2315. if ( bExp = $FF ) then
  2316. Begin
  2317. if ( bSig<>0 ) then
  2318. Begin
  2319. addFloat32Sigs := propagateFloat32NaN( a, b );
  2320. exit;
  2321. end;
  2322. addFloat32Sigs := packFloat32( zSign, $FF, 0 );
  2323. exit;
  2324. End;
  2325. if ( aExp = 0 ) then
  2326. Begin
  2327. Inc(expDiff);
  2328. End
  2329. else
  2330. Begin
  2331. aSig := aSig OR $20000000;
  2332. End;
  2333. shift32RightJamming( aSig, - expDiff, aSig );
  2334. zExp := bExp;
  2335. End
  2336. else
  2337. Begin
  2338. if ( aExp = $FF ) then
  2339. Begin
  2340. if ( aSig OR bSig )<> 0 then
  2341. Begin
  2342. addFloat32Sigs := propagateFloat32NaN( a, b );
  2343. exit;
  2344. end;
  2345. addFloat32Sigs := a;
  2346. exit;
  2347. End;
  2348. if ( aExp = 0 ) then
  2349. Begin
  2350. addFloat32Sigs := packFloat32( zSign, 0, ( aSig + bSig ) shr 6 );
  2351. exit;
  2352. end;
  2353. zSig := $40000000 + aSig + bSig;
  2354. zExp := aExp;
  2355. goto roundAndPack;
  2356. End;
  2357. aSig := aSig OR $20000000;
  2358. zSig := ( aSig + bSig ) shl 1;
  2359. Dec(zExp);
  2360. if ( sbits32 (zSig) < 0 ) then
  2361. Begin
  2362. zSig := aSig + bSig;
  2363. Inc(zExp);
  2364. End;
  2365. roundAndPack:
  2366. addFloat32Sigs := roundAndPackFloat32( zSign, zExp, zSig );
  2367. End;
  2368. {*
  2369. -------------------------------------------------------------------------------
  2370. Returns the result of subtracting the absolute values of the single-
  2371. precision floating-point values `a' and `b'. If `zSign' is 1, the
  2372. difference is negated before being returned. `zSign' is ignored if the
  2373. result is a NaN. The subtraction is performed according to the IEC/IEEE
  2374. Standard for Binary Floating-Point Arithmetic.
  2375. -------------------------------------------------------------------------------
  2376. *}
  2377. Function subFloat32Sigs( a:float32; b:float32; zSign:flag ): float32;
  2378. Var
  2379. aExp, bExp, zExp: int16;
  2380. aSig, bSig, zSig: bits32;
  2381. expDiff : int16;
  2382. label aExpBigger;
  2383. label bExpBigger;
  2384. label aBigger;
  2385. label bBigger;
  2386. label normalizeRoundAndPack;
  2387. Begin
  2388. aSig := extractFloat32Frac( a );
  2389. aExp := extractFloat32Exp( a );
  2390. bSig := extractFloat32Frac( b );
  2391. bExp := extractFloat32Exp( b );
  2392. expDiff := aExp - bExp;
  2393. aSig := aSig shl 7;
  2394. bSig := bSig shl 7;
  2395. if ( 0 < expDiff ) then goto aExpBigger;
  2396. if ( expDiff < 0 ) then goto bExpBigger;
  2397. if ( aExp = $FF ) then
  2398. Begin
  2399. if ( aSig OR bSig )<> 0 then
  2400. Begin
  2401. subFloat32Sigs := propagateFloat32NaN( a, b );
  2402. exit;
  2403. End;
  2404. float_raise( float_flag_invalid );
  2405. subFloat32Sigs := float32_default_nan;
  2406. exit;
  2407. End;
  2408. if ( aExp = 0 ) then
  2409. Begin
  2410. aExp := 1;
  2411. bExp := 1;
  2412. End;
  2413. if ( bSig < aSig ) Then goto aBigger;
  2414. if ( aSig < bSig ) Then goto bBigger;
  2415. subFloat32Sigs := packFloat32( flag(float_rounding_mode = float_round_down), 0, 0 );
  2416. exit;
  2417. bExpBigger:
  2418. if ( bExp = $FF ) then
  2419. Begin
  2420. if ( bSig<>0 ) then
  2421. Begin
  2422. subFloat32Sigs := propagateFloat32NaN( a, b );
  2423. exit;
  2424. End;
  2425. subFloat32Sigs := packFloat32( zSign XOR 1, $FF, 0 );
  2426. exit;
  2427. End;
  2428. if ( aExp = 0 ) then
  2429. Begin
  2430. Inc(expDiff);
  2431. End
  2432. else
  2433. Begin
  2434. aSig := aSig OR $40000000;
  2435. End;
  2436. shift32RightJamming( aSig, - expDiff, aSig );
  2437. bSig := bSig OR $40000000;
  2438. bBigger:
  2439. zSig := bSig - aSig;
  2440. zExp := bExp;
  2441. zSign := zSign xor 1;
  2442. goto normalizeRoundAndPack;
  2443. aExpBigger:
  2444. if ( aExp = $FF ) then
  2445. Begin
  2446. if ( aSig <> 0) then
  2447. Begin
  2448. subFloat32Sigs := propagateFloat32NaN( a, b );
  2449. exit;
  2450. End;
  2451. subFloat32Sigs := a;
  2452. exit;
  2453. End;
  2454. if ( bExp = 0 ) then
  2455. Begin
  2456. Dec(expDiff);
  2457. End
  2458. else
  2459. Begin
  2460. bSig := bSig OR $40000000;
  2461. End;
  2462. shift32RightJamming( bSig, expDiff, bSig );
  2463. aSig := aSig OR $40000000;
  2464. aBigger:
  2465. zSig := aSig - bSig;
  2466. zExp := aExp;
  2467. normalizeRoundAndPack:
  2468. Dec(zExp);
  2469. subFloat32Sigs := normalizeRoundAndPackFloat32( zSign, zExp, zSig );
  2470. End;
  2471. {*
  2472. -------------------------------------------------------------------------------
  2473. Returns the result of adding the single-precision floating-point values `a'
  2474. and `b'. The operation is performed according to the IEC/IEEE Standard for
  2475. Binary Floating-Point Arithmetic.
  2476. -------------------------------------------------------------------------------
  2477. *}
  2478. Function float32_add( a: float32; b:float32 ): float32;{$ifdef fpc} [public,Alias:'FLOAT32_ADD'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2479. Var
  2480. aSign, bSign: Flag;
  2481. Begin
  2482. aSign := extractFloat32Sign( a );
  2483. bSign := extractFloat32Sign( b );
  2484. if ( aSign = bSign ) then
  2485. Begin
  2486. float32_add := addFloat32Sigs( a, b, aSign );
  2487. End
  2488. else
  2489. Begin
  2490. float32_add := subFloat32Sigs( a, b, aSign );
  2491. End;
  2492. End;
  2493. {*
  2494. -------------------------------------------------------------------------------
  2495. Returns the result of subtracting the single-precision floating-point values
  2496. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  2497. for Binary Floating-Point Arithmetic.
  2498. -------------------------------------------------------------------------------
  2499. *}
  2500. Function float32_sub( a: float32 ; b:float32 ): float32;{$ifdef fpc} [public,Alias:'FLOAT32_SUB'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2501. Var
  2502. aSign, bSign: flag;
  2503. Begin
  2504. aSign := extractFloat32Sign( a );
  2505. bSign := extractFloat32Sign( b );
  2506. if ( aSign = bSign ) then
  2507. Begin
  2508. float32_sub := subFloat32Sigs( a, b, aSign );
  2509. End
  2510. else
  2511. Begin
  2512. float32_sub := addFloat32Sigs( a, b, aSign );
  2513. End;
  2514. End;
  2515. {*
  2516. -------------------------------------------------------------------------------
  2517. Returns the result of multiplying the single-precision floating-point values
  2518. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  2519. for Binary Floating-Point Arithmetic.
  2520. -------------------------------------------------------------------------------
  2521. *}
  2522. Function float32_mul(a: float32; b: float32 ) : float32;{$ifdef fpc} [public,Alias:'FLOAT32_MUL'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2523. Var
  2524. aSign, bSign, zSign: flag;
  2525. aExp, bExp, zExp : int16;
  2526. aSig, bSig, zSig0, zSig1: bits32;
  2527. Begin
  2528. aSig := extractFloat32Frac( a );
  2529. aExp := extractFloat32Exp( a );
  2530. aSign := extractFloat32Sign( a );
  2531. bSig := extractFloat32Frac( b );
  2532. bExp := extractFloat32Exp( b );
  2533. bSign := extractFloat32Sign( b );
  2534. zSign := aSign xor bSign;
  2535. if ( aExp = $FF ) then
  2536. Begin
  2537. if ( (aSig<>0) OR ( ( bExp = $FF ) AND (bSig<>0) ) ) then
  2538. Begin
  2539. float32_mul := propagateFloat32NaN( a, b );
  2540. End;
  2541. if ( ( bExp OR bSig ) = 0 ) then
  2542. Begin
  2543. float_raise( float_flag_invalid );
  2544. float32_mul := float32_default_nan;
  2545. exit;
  2546. End;
  2547. float32_mul := packFloat32( zSign, $FF, 0 );
  2548. exit;
  2549. End;
  2550. if ( bExp = $FF ) then
  2551. Begin
  2552. if ( bSig <> 0 ) then
  2553. Begin
  2554. float32_mul := propagateFloat32NaN( a, b );
  2555. exit;
  2556. End;
  2557. if ( ( aExp OR aSig ) = 0 ) then
  2558. Begin
  2559. float_raise( float_flag_invalid );
  2560. float32_mul := float32_default_nan;
  2561. exit;
  2562. End;
  2563. float32_mul := packFloat32( zSign, $FF, 0 );
  2564. exit;
  2565. End;
  2566. if ( aExp = 0 ) then
  2567. Begin
  2568. if ( aSig = 0 ) then
  2569. Begin
  2570. float32_mul := packFloat32( zSign, 0, 0 );
  2571. exit;
  2572. End;
  2573. normalizeFloat32Subnormal( aSig, aExp, aSig );
  2574. End;
  2575. if ( bExp = 0 ) then
  2576. Begin
  2577. if ( bSig = 0 ) then
  2578. Begin
  2579. float32_mul := packFloat32( zSign, 0, 0 );
  2580. exit;
  2581. End;
  2582. normalizeFloat32Subnormal( bSig, bExp, bSig );
  2583. End;
  2584. zExp := aExp + bExp - $7F;
  2585. aSig := ( aSig OR $00800000 ) shl 7;
  2586. bSig := ( bSig OR $00800000 ) shl 8;
  2587. mul32To64( aSig, bSig, zSig0, zSig1 );
  2588. zSig0 := zSig0 OR bits32( zSig1 <> 0 );
  2589. if ( 0 <= sbits32 ( zSig0 shl 1 ) ) then
  2590. Begin
  2591. zSig0 := zSig0 shl 1;
  2592. Dec(zExp);
  2593. End;
  2594. float32_mul := roundAndPackFloat32( zSign, zExp, zSig0 );
  2595. End;
  2596. {*
  2597. -------------------------------------------------------------------------------
  2598. Returns the result of dividing the single-precision floating-point value `a'
  2599. by the corresponding value `b'. The operation is performed according to the
  2600. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2601. -------------------------------------------------------------------------------
  2602. *}
  2603. Function float32_div(a: float32;b: float32 ): float32;{$ifdef fpc} [public,Alias:'FLOAT32_DIV'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2604. Var
  2605. aSign, bSign, zSign: flag;
  2606. aExp, bExp, zExp: int16;
  2607. aSig, bSig, zSig, rem0, rem1, term0, term1: bits32;
  2608. Begin
  2609. aSig := extractFloat32Frac( a );
  2610. aExp := extractFloat32Exp( a );
  2611. aSign := extractFloat32Sign( a );
  2612. bSig := extractFloat32Frac( b );
  2613. bExp := extractFloat32Exp( b );
  2614. bSign := extractFloat32Sign( b );
  2615. zSign := aSign xor bSign;
  2616. if ( aExp = $FF ) then
  2617. Begin
  2618. if ( aSig <> 0 ) then
  2619. Begin
  2620. float32_div := propagateFloat32NaN( a, b );
  2621. exit;
  2622. End;
  2623. if ( bExp = $FF ) then
  2624. Begin
  2625. if ( bSig <> 0) then
  2626. Begin
  2627. float32_div := propagateFloat32NaN( a, b );
  2628. End;
  2629. float_raise( float_flag_invalid );
  2630. float32_div := float32_default_nan;
  2631. exit;
  2632. End;
  2633. float32_div := packFloat32( zSign, $FF, 0 );
  2634. exit;
  2635. End;
  2636. if ( bExp = $FF ) then
  2637. Begin
  2638. if ( bSig <> 0) then
  2639. Begin
  2640. float32_div := propagateFloat32NaN( a, b );
  2641. exit;
  2642. End;
  2643. float32_div := packFloat32( zSign, 0, 0 );
  2644. exit;
  2645. End;
  2646. if ( bExp = 0 ) Then
  2647. Begin
  2648. if ( bSig = 0 ) Then
  2649. Begin
  2650. if ( ( aExp OR aSig ) = 0 ) then
  2651. Begin
  2652. float_raise( float_flag_invalid );
  2653. float32_div := float32_default_nan;
  2654. exit;
  2655. End;
  2656. float_raise( float_flag_divbyzero );
  2657. float32_div := packFloat32( zSign, $FF, 0 );
  2658. exit;
  2659. End;
  2660. normalizeFloat32Subnormal( bSig, bExp, bSig );
  2661. End;
  2662. if ( aExp = 0 ) Then
  2663. Begin
  2664. if ( aSig = 0 ) Then
  2665. Begin
  2666. float32_div := packFloat32( zSign, 0, 0 );
  2667. exit;
  2668. End;
  2669. normalizeFloat32Subnormal( aSig, aExp, aSig );
  2670. End;
  2671. zExp := aExp - bExp + $7D;
  2672. aSig := ( aSig OR $00800000 ) shl 7;
  2673. bSig := ( bSig OR $00800000 ) shl 8;
  2674. if ( bSig <= ( aSig + aSig ) ) then
  2675. Begin
  2676. aSig := aSig shr 1;
  2677. Inc(zExp);
  2678. End;
  2679. zSig := estimateDiv64To32( aSig, 0, bSig );
  2680. if ( ( zSig and $3F ) <= 2 ) then
  2681. Begin
  2682. mul32To64( bSig, zSig, term0, term1 );
  2683. sub64( aSig, 0, term0, term1, rem0, rem1 );
  2684. while ( sbits32 (rem0) < 0 ) do
  2685. Begin
  2686. Dec(zSig);
  2687. add64( rem0, rem1, 0, bSig, rem0, rem1 );
  2688. End;
  2689. zSig := zSig or bits32( rem1 <> 0 );
  2690. End;
  2691. float32_div := roundAndPackFloat32( zSign, zExp, zSig );
  2692. End;
  2693. {*
  2694. -------------------------------------------------------------------------------
  2695. Returns the remainder of the single-precision floating-point value `a'
  2696. with respect to the corresponding value `b'. The operation is performed
  2697. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2698. -------------------------------------------------------------------------------
  2699. *}
  2700. Function float32_rem(a: float32; b: float32 ):float32;{$ifdef fpc} [public,Alias:'FLOAT32_REM'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2701. Var
  2702. aSign, bSign, zSign: flag;
  2703. aExp, bExp, expDiff: int16;
  2704. aSig, bSig, q, allZero, alternateASig: bits32;
  2705. sigMean: sbits32;
  2706. Begin
  2707. aSig := extractFloat32Frac( a );
  2708. aExp := extractFloat32Exp( a );
  2709. aSign := extractFloat32Sign( a );
  2710. bSig := extractFloat32Frac( b );
  2711. bExp := extractFloat32Exp( b );
  2712. bSign := extractFloat32Sign( b );
  2713. if ( aExp = $FF ) then
  2714. Begin
  2715. if ( (aSig<>0) OR ( ( bExp = $FF ) AND (bSig <>0)) ) then
  2716. Begin
  2717. float32_rem := propagateFloat32NaN( a, b );
  2718. exit;
  2719. End;
  2720. float_raise( float_flag_invalid );
  2721. float32_rem := float32_default_nan;
  2722. exit;
  2723. End;
  2724. if ( bExp = $FF ) then
  2725. Begin
  2726. if ( bSig <> 0 ) then
  2727. Begin
  2728. float32_rem := propagateFloat32NaN( a, b );
  2729. exit;
  2730. End;
  2731. float32_rem := a;
  2732. exit;
  2733. End;
  2734. if ( bExp = 0 ) then
  2735. Begin
  2736. if ( bSig = 0 ) then
  2737. Begin
  2738. float_raise( float_flag_invalid );
  2739. float32_rem := float32_default_nan;
  2740. exit;
  2741. End;
  2742. normalizeFloat32Subnormal( bSig, bExp, bSig );
  2743. End;
  2744. if ( aExp = 0 ) then
  2745. Begin
  2746. if ( aSig = 0 ) then
  2747. Begin
  2748. float32_rem := a;
  2749. exit;
  2750. End;
  2751. normalizeFloat32Subnormal( aSig, aExp, aSig );
  2752. End;
  2753. expDiff := aExp - bExp;
  2754. aSig := ( aSig OR $00800000 ) shl 8;
  2755. bSig := ( bSig OR $00800000 ) shl 8;
  2756. if ( expDiff < 0 ) then
  2757. Begin
  2758. if ( expDiff < -1 ) then
  2759. Begin
  2760. float32_rem := a;
  2761. exit;
  2762. End;
  2763. aSig := aSig shr 1;
  2764. End;
  2765. q := bits32( bSig <= aSig );
  2766. if ( q <> 0) then
  2767. aSig := aSig - bSig;
  2768. expDiff := expDiff - 32;
  2769. while ( 0 < expDiff ) do
  2770. Begin
  2771. q := estimateDiv64To32( aSig, 0, bSig );
  2772. if (2 < q) then
  2773. q := q - 2
  2774. else
  2775. q := 0;
  2776. aSig := - ( ( bSig shr 2 ) * q );
  2777. expDiff := expDiff - 30;
  2778. End;
  2779. expDiff := expDiff + 32;
  2780. if ( 0 < expDiff ) then
  2781. Begin
  2782. q := estimateDiv64To32( aSig, 0, bSig );
  2783. if (2 < q) then
  2784. q := q - 2
  2785. else
  2786. q := 0;
  2787. q := q shr (32 - expDiff);
  2788. bSig := bSig shr 2;
  2789. aSig := ( ( aSig shr 1 ) shl ( expDiff - 1 ) ) - bSig * q;
  2790. End
  2791. else
  2792. Begin
  2793. aSig := aSig shr 2;
  2794. bSig := bSig shr 2;
  2795. End;
  2796. Repeat
  2797. alternateASig := aSig;
  2798. Inc(q);
  2799. aSig := aSig - bSig;
  2800. Until not ( 0 <= sbits32 (aSig) );
  2801. sigMean := aSig + alternateASig;
  2802. if ( ( sigMean < 0 ) OR ( ( sigMean = 0 ) AND (( q and 1 )<>0) ) ) then
  2803. Begin
  2804. aSig := alternateASig;
  2805. End;
  2806. zSign := flag( sbits32 (aSig) < 0 );
  2807. if ( zSign<>0 ) then
  2808. aSig := - aSig;
  2809. float32_rem := normalizeRoundAndPackFloat32( aSign xor zSign, bExp, aSig );
  2810. End;
  2811. {*
  2812. -------------------------------------------------------------------------------
  2813. Returns the square root of the single-precision floating-point value `a'.
  2814. The operation is performed according to the IEC/IEEE Standard for Binary
  2815. Floating-Point Arithmetic.
  2816. -------------------------------------------------------------------------------
  2817. *}
  2818. Function float32_sqrt(a: float32 ): float32;{$ifdef fpc} [public,Alias:'FLOAT32_SQRT'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2819. Var
  2820. aSign : flag;
  2821. aExp, zExp : int16;
  2822. aSig, zSig, rem0, rem1, term0, term1: bits32;
  2823. label roundAndPack;
  2824. Begin
  2825. aSig := extractFloat32Frac( a );
  2826. aExp := extractFloat32Exp( a );
  2827. aSign := extractFloat32Sign( a );
  2828. if ( aExp = $FF ) then
  2829. Begin
  2830. if ( aSig <> 0) then
  2831. Begin
  2832. float32_sqrt := propagateFloat32NaN( a, 0 );
  2833. exit;
  2834. End;
  2835. if ( aSign = 0) then
  2836. Begin
  2837. float32_sqrt := a;
  2838. exit;
  2839. End;
  2840. float_raise( float_flag_invalid );
  2841. float32_sqrt := float32_default_nan;
  2842. exit;
  2843. End;
  2844. if ( aSign <> 0) then
  2845. Begin
  2846. if ( ( aExp OR aSig ) = 0 ) then
  2847. Begin
  2848. float32_sqrt := a;
  2849. exit;
  2850. End;
  2851. float_raise( float_flag_invalid );
  2852. float32_sqrt := float32_default_nan;
  2853. exit;
  2854. End;
  2855. if ( aExp = 0 ) then
  2856. Begin
  2857. if ( aSig = 0 ) then
  2858. Begin
  2859. float32_sqrt := 0;
  2860. exit;
  2861. End;
  2862. normalizeFloat32Subnormal( aSig, aExp, aSig );
  2863. End;
  2864. zExp := ( ( aExp - $7F ) shr 1 ) + $7E;
  2865. aSig := ( aSig OR $00800000 ) shl 8;
  2866. zSig := estimateSqrt32( aExp, aSig ) + 2;
  2867. if ( ( zSig and $7F ) <= 5 ) then
  2868. Begin
  2869. if ( zSig < 2 ) then
  2870. Begin
  2871. zSig := $7FFFFFFF;
  2872. goto roundAndPack;
  2873. End
  2874. else
  2875. Begin
  2876. aSig := aSig shr (aExp and 1);
  2877. mul32To64( zSig, zSig, term0, term1 );
  2878. sub64( aSig, 0, term0, term1, rem0, rem1 );
  2879. while ( sbits32 (rem0) < 0 ) do
  2880. Begin
  2881. Dec(zSig);
  2882. shortShift64Left( 0, zSig, 1, term0, term1 );
  2883. term1 := term1 or 1;
  2884. add64( rem0, rem1, term0, term1, rem0, rem1 );
  2885. End;
  2886. zSig := zSig OR bits32( ( rem0 OR rem1 ) <> 0 );
  2887. End;
  2888. End;
  2889. shift32RightJamming( zSig, 1, zSig );
  2890. roundAndPack:
  2891. float32_sqrt := roundAndPackFloat32( 0, zExp, zSig );
  2892. End;
  2893. {*
  2894. -------------------------------------------------------------------------------
  2895. Returns 1 if the single-precision floating-point value `a' is equal to
  2896. the corresponding value `b', and 0 otherwise. The comparison is performed
  2897. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2898. -------------------------------------------------------------------------------
  2899. *}
  2900. Function float32_eq( a:float32; b:float32): flag;{$ifdef fpc} [public,Alias:'FLOAT32_EQ'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2901. Begin
  2902. if ((( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a )<>0))
  2903. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b )<>0) )
  2904. ) then
  2905. Begin
  2906. if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
  2907. Begin
  2908. float_raise( float_flag_invalid );
  2909. End;
  2910. float32_eq := 0;
  2911. exit;
  2912. End;
  2913. float32_eq := flag( a = b ) OR flag( bits32 ( ( a OR b ) shl 1 ) = 0 );
  2914. End;
  2915. {*
  2916. -------------------------------------------------------------------------------
  2917. Returns 1 if the single-precision floating-point value `a' is less than
  2918. or equal to the corresponding value `b', and 0 otherwise. The comparison
  2919. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  2920. Arithmetic.
  2921. -------------------------------------------------------------------------------
  2922. *}
  2923. Function float32_le( a: float32; b : float32 ):flag;{$ifdef fpc} [public,Alias:'FLOAT32_LE'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2924. var
  2925. aSign, bSign: flag;
  2926. Begin
  2927. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a )<>0) )
  2928. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b )<>0) )
  2929. ) then
  2930. Begin
  2931. float_raise( float_flag_invalid );
  2932. float32_le := 0;
  2933. exit;
  2934. End;
  2935. aSign := extractFloat32Sign( a );
  2936. bSign := extractFloat32Sign( b );
  2937. if ( aSign <> bSign ) then
  2938. Begin
  2939. float32_le := aSign OR flag( bits32 ( ( a OR b ) shl 1 ) = 0 );
  2940. exit;
  2941. End;
  2942. float32_le := flag(flag( a = b ) OR flag( aSign xor flag( a < b ) ));
  2943. End;
  2944. {*
  2945. -------------------------------------------------------------------------------
  2946. Returns 1 if the single-precision floating-point value `a' is less than
  2947. the corresponding value `b', and 0 otherwise. The comparison is performed
  2948. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2949. -------------------------------------------------------------------------------
  2950. *}
  2951. Function float32_lt( a:float32 ; b : float32): flag;{$ifdef fpc} [public,Alias:'FLOAT32_LT'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  2952. var
  2953. aSign, bSign: flag;
  2954. Begin
  2955. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a ) <>0))
  2956. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b ) <>0) )
  2957. ) then
  2958. Begin
  2959. float_raise( float_flag_invalid );
  2960. float32_lt :=0;
  2961. exit;
  2962. End;
  2963. aSign := extractFloat32Sign( a );
  2964. bSign := extractFloat32Sign( b );
  2965. if ( aSign <> bSign ) then
  2966. Begin
  2967. float32_lt := aSign AND flag( bits32 ( ( a OR b ) shl 1 ) <> 0 );
  2968. exit;
  2969. End;
  2970. float32_lt := flag(flag( a <> b ) AND flag( aSign xor flag( a < b ) ));
  2971. End;
  2972. {*
  2973. -------------------------------------------------------------------------------
  2974. Returns 1 if the single-precision floating-point value `a' is equal to
  2975. the corresponding value `b', and 0 otherwise. The invalid exception is
  2976. raised if either operand is a NaN. Otherwise, the comparison is performed
  2977. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2978. -------------------------------------------------------------------------------
  2979. *}
  2980. Function float32_eq_signaling( a: float32; b: float32) : flag;
  2981. Begin
  2982. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a ) <> 0))
  2983. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b ) <> 0))
  2984. ) then
  2985. Begin
  2986. float_raise( float_flag_invalid );
  2987. float32_eq_signaling := 0;
  2988. exit;
  2989. End;
  2990. float32_eq_signaling := (flag( a = b ) OR flag( bits32 ( ( a OR b ) shl 1 ) = 0 ));
  2991. End;
  2992. {*
  2993. -------------------------------------------------------------------------------
  2994. Returns 1 if the single-precision floating-point value `a' is less than or
  2995. equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  2996. cause an exception. Otherwise, the comparison is performed according to the
  2997. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2998. -------------------------------------------------------------------------------
  2999. *}
  3000. Function float32_le_quiet( a: float32 ; b : float32 ): flag;
  3001. Var
  3002. aSign, bSign: flag;
  3003. aExp, bExp: int16;
  3004. Begin
  3005. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a )<>0) )
  3006. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b )<>0) )
  3007. ) then
  3008. Begin
  3009. if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
  3010. Begin
  3011. float_raise( float_flag_invalid );
  3012. End;
  3013. float32_le_quiet := 0;
  3014. exit;
  3015. End;
  3016. aSign := extractFloat32Sign( a );
  3017. bSign := extractFloat32Sign( b );
  3018. if ( aSign <> bSign ) then
  3019. Begin
  3020. float32_le_quiet := aSign OR flag( bits32 ( ( a OR b ) shl 1 ) = 0 );
  3021. exit;
  3022. End;
  3023. float32_le_quiet := flag(flag( a = b ) OR flag( aSign xor flag( a < b ) ));
  3024. End;
  3025. {*
  3026. -------------------------------------------------------------------------------
  3027. Returns 1 if the single-precision floating-point value `a' is less than
  3028. the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  3029. exception. Otherwise, the comparison is performed according to the IEC/IEEE
  3030. Standard for Binary Floating-Point Arithmetic.
  3031. -------------------------------------------------------------------------------
  3032. *}
  3033. Function float32_lt_quiet( a: float32 ; b: float32 ): flag;
  3034. Var
  3035. aSign, bSign: flag;
  3036. Begin
  3037. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a )<>0) )
  3038. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b )<>0) )
  3039. ) then
  3040. Begin
  3041. if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
  3042. Begin
  3043. float_raise( float_flag_invalid );
  3044. End;
  3045. float32_lt_quiet := 0;
  3046. exit;
  3047. End;
  3048. aSign := extractFloat32Sign( a );
  3049. bSign := extractFloat32Sign( b );
  3050. if ( aSign <> bSign ) then
  3051. Begin
  3052. float32_lt_quiet := aSign AND flag( bits32 ( ( a OR b ) shl 1 ) <> 0 );
  3053. exit;
  3054. End;
  3055. float32_lt_quiet := flag(flag( a <> b ) AND ( aSign xor flag( a < b ) ));
  3056. End;
  3057. {*
  3058. -------------------------------------------------------------------------------
  3059. Returns the result of converting the double-precision floating-point value
  3060. `a' to the 32-bit two's complement integer format. The conversion is
  3061. performed according to the IEC/IEEE Standard for Binary Floating-Point
  3062. Arithmetic---which means in particular that the conversion is rounded
  3063. according to the current rounding mode. If `a' is a NaN, the largest
  3064. positive integer is returned. Otherwise, if the conversion overflows, the
  3065. largest integer with the same sign as `a' is returned.
  3066. -------------------------------------------------------------------------------
  3067. *}
  3068. Function float64_to_int32(a: float64): int32;{$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  3069. var
  3070. aSign: flag;
  3071. aExp, shiftCount: int16;
  3072. aSig0, aSig1, absZ, aSigExtra: bits32;
  3073. z: int32;
  3074. roundingMode: int8;
  3075. label invalid;
  3076. Begin
  3077. aSig1 := extractFloat64Frac1( a );
  3078. aSig0 := extractFloat64Frac0( a );
  3079. aExp := extractFloat64Exp( a );
  3080. aSign := extractFloat64Sign( a );
  3081. shiftCount := aExp - $413;
  3082. if ( 0 <= shiftCount ) then
  3083. Begin
  3084. if ( $41E < aExp ) then
  3085. Begin
  3086. if ( ( aExp = $7FF ) AND (( aSig0 OR aSig1 )<>0) ) then
  3087. aSign := 0;
  3088. goto invalid;
  3089. End;
  3090. shortShift64Left(
  3091. aSig0 OR $00100000, aSig1, shiftCount, absZ, aSigExtra );
  3092. if ( $80000000 < absZ ) then
  3093. goto invalid;
  3094. End
  3095. else
  3096. Begin
  3097. aSig1 := flag( aSig1 <> 0 );
  3098. if ( aExp < $3FE ) then
  3099. Begin
  3100. aSigExtra := aExp OR aSig0 OR aSig1;
  3101. absZ := 0;
  3102. End
  3103. else
  3104. Begin
  3105. aSig0 := aSig0 OR $00100000;
  3106. aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR aSig1;
  3107. absZ := aSig0 shr ( - shiftCount );
  3108. End;
  3109. End;
  3110. roundingMode := float_rounding_mode;
  3111. if ( roundingMode = float_round_nearest_even ) then
  3112. Begin
  3113. if ( sbits32(aSigExtra) < 0 ) then
  3114. Begin
  3115. Inc(absZ);
  3116. if ( bits32 ( aSigExtra shl 1 ) = 0 ) then
  3117. absZ := absZ and not 1;
  3118. End;
  3119. if aSign <> 0 then
  3120. z := - absZ
  3121. else
  3122. z := absZ;
  3123. End
  3124. else
  3125. Begin
  3126. aSigExtra := bits32( aSigExtra <> 0 );
  3127. if ( aSign <> 0) then
  3128. Begin
  3129. z := - ( absZ
  3130. + ( int32( roundingMode = float_round_down ) and aSigExtra ) );
  3131. End
  3132. else
  3133. Begin
  3134. z := absZ + ( int32( roundingMode = float_round_up ) and aSigExtra );
  3135. End
  3136. End;
  3137. if ( (( aSign xor flag( z < 0 ) )<>0) AND (z<>0) ) then
  3138. Begin
  3139. invalid:
  3140. float_raise( float_flag_invalid );
  3141. if (aSign <> 0 ) then
  3142. float64_to_int32 := sbits32 ($80000000)
  3143. else
  3144. float64_to_int32 := $7FFFFFFF;
  3145. exit;
  3146. End;
  3147. if ( aSigExtra <> 0) then
  3148. float_exception_flags := float_exception_flags or float_flag_inexact;
  3149. float64_to_int32 := z;
  3150. End;
  3151. {*
  3152. -------------------------------------------------------------------------------
  3153. Returns the result of converting the double-precision floating-point value
  3154. `a' to the 32-bit two's complement integer format. The conversion is
  3155. performed according to the IEC/IEEE Standard for Binary Floating-Point
  3156. Arithmetic, except that the conversion is always rounded toward zero.
  3157. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  3158. the conversion overflows, the largest integer with the same sign as `a' is
  3159. returned.
  3160. -------------------------------------------------------------------------------
  3161. *}
  3162. Function float64_to_int32_round_to_zero(a: float64 ): int32;
  3163. {$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32_ROUND_TO_ZERO'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  3164. Var
  3165. aSign: flag;
  3166. aExp, shiftCount: int16;
  3167. aSig0, aSig1, absZ, aSigExtra: bits32;
  3168. z: int32;
  3169. label invalid;
  3170. Begin
  3171. aSig1 := extractFloat64Frac1( a );
  3172. aSig0 := extractFloat64Frac0( a );
  3173. aExp := extractFloat64Exp( a );
  3174. aSign := extractFloat64Sign( a );
  3175. shiftCount := aExp - $413;
  3176. if ( 0 <= shiftCount ) then
  3177. Begin
  3178. if ( $41E < aExp ) then
  3179. Begin
  3180. if ( ( aExp = $7FF ) AND (( aSig0 OR aSig1 )<>0) ) then
  3181. aSign := 0;
  3182. goto invalid;
  3183. End;
  3184. shortShift64Left(
  3185. aSig0 OR $00100000, aSig1, shiftCount, absZ, aSigExtra );
  3186. End
  3187. else
  3188. Begin
  3189. if ( aExp < $3FF ) then
  3190. Begin
  3191. if ( aExp OR aSig0 OR aSig1 )<>0 then
  3192. Begin
  3193. float_exception_flags :=
  3194. float_exception_flags or float_flag_inexact;
  3195. End;
  3196. float64_to_int32_round_to_zero := 0;
  3197. exit;
  3198. End;
  3199. aSig0 := aSig0 or $00100000;
  3200. aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR aSig1;
  3201. absZ := aSig0 shr ( - shiftCount );
  3202. End;
  3203. if aSign <> 0 then
  3204. z := - absZ
  3205. else
  3206. z := absZ;
  3207. if ( (( aSign xor flag( z < 0 )) <> 0) AND (z<>0) ) then
  3208. Begin
  3209. invalid:
  3210. float_raise( float_flag_invalid );
  3211. if (aSign <> 0) then
  3212. float64_to_int32_round_to_zero := sbits32 ($80000000)
  3213. else
  3214. float64_to_int32_round_to_zero := $7FFFFFFF;
  3215. exit;
  3216. End;
  3217. if ( aSigExtra <> 0) then
  3218. float_exception_flags := float_exception_flags or float_flag_inexact;
  3219. float64_to_int32_round_to_zero := z;
  3220. End;
  3221. {*
  3222. -------------------------------------------------------------------------------
  3223. Returns the result of converting the double-precision floating-point value
  3224. `a' to the single-precision floating-point format. The conversion is
  3225. performed according to the IEC/IEEE Standard for Binary Floating-Point
  3226. Arithmetic.
  3227. -------------------------------------------------------------------------------
  3228. *}
  3229. Function float64_to_float32(a: float64 ): float32;{$ifdef fpc} [public,Alias:'FLOAT64_TO_FLOAT32'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  3230. Var
  3231. aSign: flag;
  3232. aExp: int16;
  3233. aSig0, aSig1, zSig: bits32;
  3234. allZero: bits32;
  3235. tmp : CommonNanT;
  3236. Begin
  3237. aSig1 := extractFloat64Frac1( a );
  3238. aSig0 := extractFloat64Frac0( a );
  3239. aExp := extractFloat64Exp( a );
  3240. aSign := extractFloat64Sign( a );
  3241. if ( aExp = $7FF ) then
  3242. Begin
  3243. if ( aSig0 OR aSig1 ) <> 0 then
  3244. Begin
  3245. float64ToCommonNaN( a, tmp );
  3246. float64_to_float32 := commonNaNToFloat32( tmp );
  3247. exit;
  3248. End;
  3249. float64_to_float32 := packFloat32( aSign, $FF, 0 );
  3250. exit;
  3251. End;
  3252. shift64RightJamming( aSig0, aSig1, 22, allZero, zSig );
  3253. if ( aExp <> 0) then
  3254. zSig := zSig OR $40000000;
  3255. float64_to_float32 := roundAndPackFloat32( aSign, aExp - $381, zSig );
  3256. End;
  3257. {*
  3258. -------------------------------------------------------------------------------
  3259. Rounds the double-precision floating-point value `a' to an integer,
  3260. and returns the result as a double-precision floating-point value. The
  3261. operation is performed according to the IEC/IEEE Standard for Binary
  3262. Floating-Point Arithmetic.
  3263. -------------------------------------------------------------------------------
  3264. *}
  3265. Procedure float64_round_to_int(a: float64; var out: float64 );{$ifdef fpc} [public,Alias:'FLOAT64_ROUND_TO_INT'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  3266. Var
  3267. aSign: flag;
  3268. aExp: int16;
  3269. lastBitMask, roundBitsMask: bits32;
  3270. roundingMode: int8;
  3271. z: float64;
  3272. Begin
  3273. aExp := extractFloat64Exp( a );
  3274. if ( $413 <= aExp ) then
  3275. Begin
  3276. if ( $433 <= aExp ) then
  3277. Begin
  3278. if ( ( aExp = $7FF )
  3279. AND
  3280. (
  3281. ( extractFloat64Frac0( a ) OR extractFloat64Frac1( a )
  3282. ) <>0)
  3283. ) then
  3284. Begin
  3285. propagateFloat64NaN( a, a, out );
  3286. exit;
  3287. End;
  3288. out := a;
  3289. exit;
  3290. End;
  3291. lastBitMask := 1;
  3292. lastBitMask := ( lastBitMask shl ( $432 - aExp ) ) shl 1;
  3293. roundBitsMask := lastBitMask - 1;
  3294. z := a;
  3295. roundingMode := float_rounding_mode;
  3296. if ( roundingMode = float_round_nearest_even ) then
  3297. Begin
  3298. if ( lastBitMask <> 0) then
  3299. Begin
  3300. add64( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );
  3301. if ( ( z.low and roundBitsMask ) = 0 ) then
  3302. z.low := z.low and not lastBitMask;
  3303. End
  3304. else
  3305. Begin
  3306. if ( sbits32 (z.low) < 0 ) then
  3307. Begin
  3308. Inc(z.high);
  3309. if ( bits32 ( z.low shl 1 ) = 0 ) then
  3310. z.high := z.high and not 1;
  3311. End;
  3312. End;
  3313. End
  3314. else if ( roundingMode <> float_round_to_zero ) then
  3315. Begin
  3316. if ( extractFloat64Sign( z )
  3317. xor flag( roundingMode = float_round_up ) )<> 0 then
  3318. Begin
  3319. add64( z.high, z.low, 0, roundBitsMask, z.high, z.low );
  3320. End;
  3321. End;
  3322. z.low := z.low and not roundBitsMask;
  3323. End
  3324. else
  3325. Begin
  3326. if ( aExp <= $3FE ) then
  3327. Begin
  3328. if ( ( ( bits32 ( a.high shl 1 ) ) OR a.low ) = 0 ) then
  3329. Begin
  3330. out := a;
  3331. exit;
  3332. End;
  3333. float_exception_flags := float_exception_flags or
  3334. float_flag_inexact;
  3335. aSign := extractFloat64Sign( a );
  3336. case ( float_rounding_mode ) of
  3337. float_round_nearest_even:
  3338. Begin
  3339. if ( ( aExp = $3FE )
  3340. AND ( (extractFloat64Frac0( a ) OR extractFloat64Frac1( a ) )<>0)
  3341. ) then
  3342. Begin
  3343. packFloat64( aSign, $3FF, 0, 0, out );
  3344. exit;
  3345. End;
  3346. End;
  3347. float_round_down:
  3348. Begin
  3349. if aSign<>0 then
  3350. packFloat64( 1, $3FF, 0, 0, out )
  3351. else
  3352. packFloat64( 0, 0, 0, 0, out );
  3353. exit;
  3354. End;
  3355. float_round_up:
  3356. Begin
  3357. if aSign <> 0 then
  3358. packFloat64( 1, 0, 0, 0, out )
  3359. else
  3360. packFloat64( 0, $3FF, 0, 0, out );
  3361. exit;
  3362. End;
  3363. end;
  3364. packFloat64( aSign, 0, 0, 0, out );
  3365. exit;
  3366. End;
  3367. lastBitMask := 1;
  3368. lastBitMask := lastBitMask shl ($413 - aExp);
  3369. roundBitsMask := lastBitMask - 1;
  3370. z.low := 0;
  3371. z.high := a.high;
  3372. roundingMode := float_rounding_mode;
  3373. if ( roundingMode = float_round_nearest_even ) then
  3374. Begin
  3375. z.high := z.high + lastBitMask shr 1;
  3376. if ( ( ( z.high and roundBitsMask ) OR a.low ) = 0 ) then
  3377. Begin
  3378. z.high := z.high and not lastBitMask;
  3379. End;
  3380. End
  3381. else if ( roundingMode <> float_round_to_zero ) then
  3382. Begin
  3383. if ( extractFloat64Sign( z )
  3384. xor flag( roundingMode = float_round_up ) )<> 0 then
  3385. Begin
  3386. z.high := z.high or bits32( a.low <> 0 );
  3387. z.high := z.high + roundBitsMask;
  3388. End;
  3389. End;
  3390. z.high := z.high and not roundBitsMask;
  3391. End;
  3392. if ( ( z.low <> a.low ) OR ( z.high <> a.high ) ) then
  3393. Begin
  3394. float_exception_flags :=
  3395. float_exception_flags or float_flag_inexact;
  3396. End;
  3397. out := z;
  3398. End;
  3399. {*
  3400. -------------------------------------------------------------------------------
  3401. Returns the result of adding the absolute values of the double-precision
  3402. floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  3403. before being returned. `zSign' is ignored if the result is a NaN.
  3404. The addition is performed according to the IEC/IEEE Standard for Binary
  3405. Floating-Point Arithmetic.
  3406. -------------------------------------------------------------------------------
  3407. *}
  3408. Procedure addFloat64Sigs( a:float64 ; b: float64 ; zSign:flag; Var out: float64 );
  3409. Var
  3410. aExp, bExp, zExp: int16;
  3411. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;
  3412. expDiff: int16;
  3413. label shiftRight1;
  3414. label roundAndPack;
  3415. Begin
  3416. aSig1 := extractFloat64Frac1( a );
  3417. aSig0 := extractFloat64Frac0( a );
  3418. aExp := extractFloat64Exp( a );
  3419. bSig1 := extractFloat64Frac1( b );
  3420. bSig0 := extractFloat64Frac0( b );
  3421. bExp := extractFloat64Exp( b );
  3422. expDiff := aExp - bExp;
  3423. if ( 0 < expDiff ) then
  3424. Begin
  3425. if ( aExp = $7FF ) then
  3426. Begin
  3427. if ( aSig0 OR aSig1 ) <> 0 then
  3428. Begin
  3429. propagateFloat64NaN( a, b, out );
  3430. exit;
  3431. end;
  3432. out := a;
  3433. exit;
  3434. End;
  3435. if ( bExp = 0 ) then
  3436. Begin
  3437. Dec(expDiff);
  3438. End
  3439. else
  3440. Begin
  3441. bSig0 := bSig0 or $00100000;
  3442. End;
  3443. shift64ExtraRightJamming(
  3444. bSig0, bSig1, 0, expDiff, bSig0, bSig1, zSig2 );
  3445. zExp := aExp;
  3446. End
  3447. else if ( expDiff < 0 ) then
  3448. Begin
  3449. if ( bExp = $7FF ) then
  3450. Begin
  3451. if ( bSig0 OR bSig1 ) <> 0 then
  3452. Begin
  3453. propagateFloat64NaN( a, b, out );
  3454. exit;
  3455. End;
  3456. packFloat64( zSign, $7FF, 0, 0, out );
  3457. End;
  3458. if ( aExp = 0 ) then
  3459. Begin
  3460. Inc(expDiff);
  3461. End
  3462. else
  3463. Begin
  3464. aSig0 := aSig0 or $00100000;
  3465. End;
  3466. shift64ExtraRightJamming(
  3467. aSig0, aSig1, 0, - expDiff, aSig0, aSig1, zSig2 );
  3468. zExp := bExp;
  3469. End
  3470. else
  3471. Begin
  3472. if ( aExp = $7FF ) then
  3473. Begin
  3474. if ( aSig0 OR aSig1 OR bSig0 OR bSig1 ) <> 0 then
  3475. Begin
  3476. propagateFloat64NaN( a, b, out );
  3477. exit;
  3478. End;
  3479. out := a;
  3480. exit;
  3481. End;
  3482. add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  3483. if ( aExp = 0 ) then
  3484. Begin
  3485. packFloat64( zSign, 0, zSig0, zSig1, out );
  3486. exit;
  3487. End;
  3488. zSig2 := 0;
  3489. zSig0 := zSig0 or $00200000;
  3490. zExp := aExp;
  3491. goto shiftRight1;
  3492. End;
  3493. aSig0 := aSig0 or $00100000;
  3494. add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  3495. Dec(zExp);
  3496. if ( zSig0 < $00200000 ) then
  3497. goto roundAndPack;
  3498. Inc(zExp);
  3499. shiftRight1:
  3500. shift64ExtraRightJamming( zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  3501. roundAndPack:
  3502. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, out );
  3503. End;
  3504. {*
  3505. -------------------------------------------------------------------------------
  3506. Returns the result of subtracting the absolute values of the double-
  3507. precision floating-point values `a' and `b'. If `zSign' is 1, the
  3508. difference is negated before being returned. `zSign' is ignored if the
  3509. result is a NaN. The subtraction is performed according to the IEC/IEEE
  3510. Standard for Binary Floating-Point Arithmetic.
  3511. -------------------------------------------------------------------------------
  3512. *}
  3513. Procedure subFloat64Sigs( a:float64; b: float64 ; zSign:flag; Var out: float64 );
  3514. Var
  3515. aExp, bExp, zExp: int16;
  3516. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits32;
  3517. expDiff: int16;
  3518. z: float64;
  3519. label aExpBigger;
  3520. label bExpBigger;
  3521. label aBigger;
  3522. label bBigger;
  3523. label normalizeRoundAndPack;
  3524. Begin
  3525. aSig1 := extractFloat64Frac1( a );
  3526. aSig0 := extractFloat64Frac0( a );
  3527. aExp := extractFloat64Exp( a );
  3528. bSig1 := extractFloat64Frac1( b );
  3529. bSig0 := extractFloat64Frac0( b );
  3530. bExp := extractFloat64Exp( b );
  3531. expDiff := aExp - bExp;
  3532. shortShift64Left( aSig0, aSig1, 10, aSig0, aSig1 );
  3533. shortShift64Left( bSig0, bSig1, 10, bSig0, bSig1 );
  3534. if ( 0 < expDiff ) then goto aExpBigger;
  3535. if ( expDiff < 0 ) then goto bExpBigger;
  3536. if ( aExp = $7FF ) then
  3537. Begin
  3538. if ( aSig0 OR aSig1 OR bSig0 OR bSig1 ) <> 0 then
  3539. Begin
  3540. propagateFloat64NaN( a, b, out );
  3541. exit;
  3542. End;
  3543. float_raise( float_flag_invalid );
  3544. z.low := float64_default_nan_low;
  3545. z.high := float64_default_nan_high;
  3546. out := z;
  3547. exit;
  3548. End;
  3549. if ( aExp = 0 ) then
  3550. Begin
  3551. aExp := 1;
  3552. bExp := 1;
  3553. End;
  3554. if ( bSig0 < aSig0 ) then goto aBigger;
  3555. if ( aSig0 < bSig0 ) then goto bBigger;
  3556. if ( bSig1 < aSig1 ) then goto aBigger;
  3557. if ( aSig1 < bSig1 ) then goto bBigger;
  3558. packFloat64( flag(float_rounding_mode = float_round_down), 0, 0, 0 , out);
  3559. exit;
  3560. bExpBigger:
  3561. if ( bExp = $7FF ) then
  3562. Begin
  3563. if ( bSig0 OR bSig1 ) <> 0 then
  3564. Begin
  3565. propagateFloat64NaN( a, b, out );
  3566. exit;
  3567. End;
  3568. packFloat64( zSign xor 1, $7FF, 0, 0, out );
  3569. exit;
  3570. End;
  3571. if ( aExp = 0 ) then
  3572. Begin
  3573. Inc(expDiff);
  3574. End
  3575. else
  3576. Begin
  3577. aSig0 := aSig0 or $40000000;
  3578. End;
  3579. shift64RightJamming( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  3580. bSig0 := bSig0 or $40000000;
  3581. bBigger:
  3582. sub64( bSig0, bSig1, aSig0, aSig1, zSig0, zSig1 );
  3583. zExp := bExp;
  3584. zSign := zSign xor 1;
  3585. goto normalizeRoundAndPack;
  3586. aExpBigger:
  3587. if ( aExp = $7FF ) then
  3588. Begin
  3589. if ( aSig0 OR aSig1 ) <> 0 then
  3590. Begin
  3591. propagateFloat64NaN( a, b, out );
  3592. exit;
  3593. End;
  3594. out := a;
  3595. exit;
  3596. End;
  3597. if ( bExp = 0 ) then
  3598. Begin
  3599. Dec(expDiff);
  3600. End
  3601. else
  3602. Begin
  3603. bSig0 := bSig0 or $40000000;
  3604. End;
  3605. shift64RightJamming( bSig0, bSig1, expDiff, bSig0, bSig1 );
  3606. aSig0 := aSig0 or $40000000;
  3607. aBigger:
  3608. sub64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  3609. zExp := aExp;
  3610. normalizeRoundAndPack:
  3611. Dec(zExp);
  3612. normalizeRoundAndPackFloat64( zSign, zExp - 10, zSig0, zSig1, out );
  3613. End;
  3614. {*
  3615. -------------------------------------------------------------------------------
  3616. Returns the result of adding the double-precision floating-point values `a'
  3617. and `b'. The operation is performed according to the IEC/IEEE Standard for
  3618. Binary Floating-Point Arithmetic.
  3619. -------------------------------------------------------------------------------
  3620. *}
  3621. Procedure float64_add( a: float64; b : float64; Var out : float64);
  3622. {$ifdef fpc}[public,Alias:'FLOAT64_ADD'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  3623. Var
  3624. aSign, bSign: flag;
  3625. Begin
  3626. aSign := extractFloat64Sign( a );
  3627. bSign := extractFloat64Sign( b );
  3628. if ( aSign = bSign ) then
  3629. Begin
  3630. addFloat64Sigs( a, b, aSign, out );
  3631. End
  3632. else
  3633. Begin
  3634. subFloat64Sigs( a, b, aSign, out );
  3635. End;
  3636. End;
  3637. {*
  3638. -------------------------------------------------------------------------------
  3639. Returns the result of subtracting the double-precision floating-point values
  3640. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  3641. for Binary Floating-Point Arithmetic.
  3642. -------------------------------------------------------------------------------
  3643. *}
  3644. Procedure float64_sub(a: float64; b : float64; var out: float64);
  3645. {$ifdef fpc}[public,Alias:'FLOAT64_SUB'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  3646. Var
  3647. aSign, bSign: flag;
  3648. Begin
  3649. aSign := extractFloat64Sign( a );
  3650. bSign := extractFloat64Sign( b );
  3651. if ( aSign = bSign ) then
  3652. Begin
  3653. subFloat64Sigs( a, b, aSign, out );
  3654. End
  3655. else
  3656. Begin
  3657. addFloat64Sigs( a, b, aSign, out );
  3658. End;
  3659. End;
  3660. {*
  3661. -------------------------------------------------------------------------------
  3662. Returns the result of multiplying the double-precision floating-point values
  3663. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  3664. for Binary Floating-Point Arithmetic.
  3665. -------------------------------------------------------------------------------
  3666. *}
  3667. Procedure float64_mul( a: float64; b:float64; Var out: float64);
  3668. {$ifdef fpc}[public,Alias:'FLOAT64_MUL'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  3669. Var
  3670. aSign, bSign, zSign: flag;
  3671. aExp, bExp, zExp: int16;
  3672. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits32;
  3673. z: float64;
  3674. label invalid;
  3675. Begin
  3676. aSig1 := extractFloat64Frac1( a );
  3677. aSig0 := extractFloat64Frac0( a );
  3678. aExp := extractFloat64Exp( a );
  3679. aSign := extractFloat64Sign( a );
  3680. bSig1 := extractFloat64Frac1( b );
  3681. bSig0 := extractFloat64Frac0( b );
  3682. bExp := extractFloat64Exp( b );
  3683. bSign := extractFloat64Sign( b );
  3684. zSign := aSign xor bSign;
  3685. if ( aExp = $7FF ) then
  3686. Begin
  3687. if ( (( aSig0 OR aSig1 ) <>0)
  3688. OR ( ( bExp = $7FF ) AND (( bSig0 OR bSig1 )<>0) ) ) then
  3689. Begin
  3690. propagateFloat64NaN( a, b, out );
  3691. exit;
  3692. End;
  3693. if ( ( bExp OR bSig0 OR bSig1 ) = 0 ) then goto invalid;
  3694. packFloat64( zSign, $7FF, 0, 0, out );
  3695. exit;
  3696. End;
  3697. if ( bExp = $7FF ) then
  3698. Begin
  3699. if ( bSig0 OR bSig1 )<> 0 then
  3700. Begin
  3701. propagateFloat64NaN( a, b, out );
  3702. exit;
  3703. End;
  3704. if ( ( aExp OR aSig0 OR aSig1 ) = 0 ) then
  3705. Begin
  3706. invalid:
  3707. float_raise( float_flag_invalid );
  3708. z.low := float64_default_nan_low;
  3709. z.high := float64_default_nan_high;
  3710. out := z;
  3711. exit;
  3712. End;
  3713. packFloat64( zSign, $7FF, 0, 0, out );
  3714. exit;
  3715. End;
  3716. if ( aExp = 0 ) then
  3717. Begin
  3718. if ( ( aSig0 OR aSig1 ) = 0 ) then
  3719. Begin
  3720. packFloat64( zSign, 0, 0, 0, out );
  3721. exit;
  3722. End;
  3723. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  3724. End;
  3725. if ( bExp = 0 ) then
  3726. Begin
  3727. if ( ( bSig0 OR bSig1 ) = 0 ) then
  3728. Begin
  3729. packFloat64( zSign, 0, 0, 0, out );
  3730. exit;
  3731. End;
  3732. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  3733. End;
  3734. zExp := aExp + bExp - $400;
  3735. aSig0 := aSig0 or $00100000;
  3736. shortShift64Left( bSig0, bSig1, 12, bSig0, bSig1 );
  3737. mul64To128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3 );
  3738. add64( zSig0, zSig1, aSig0, aSig1, zSig0, zSig1 );
  3739. zSig2 := zSig2 or flag( zSig3 <> 0 );
  3740. if ( $00200000 <= zSig0 ) then
  3741. Begin
  3742. shift64ExtraRightJamming(
  3743. zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  3744. Inc(zExp);
  3745. End;
  3746. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, out );
  3747. End;
  3748. {*
  3749. -------------------------------------------------------------------------------
  3750. Returns the result of dividing the double-precision floating-point value `a'
  3751. by the corresponding value `b'. The operation is performed according to the
  3752. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3753. -------------------------------------------------------------------------------
  3754. *}
  3755. Procedure float64_div(a: float64; b : float64 ; var out: float64 );
  3756. {$ifdef fpc}[public,Alias:'FLOAT64_DIV'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  3757. Var
  3758. aSign, bSign, zSign: flag;
  3759. aExp, bExp, zExp: int16;
  3760. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;
  3761. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;
  3762. z: float64;
  3763. label invalid;
  3764. Begin
  3765. aSig1 := extractFloat64Frac1( a );
  3766. aSig0 := extractFloat64Frac0( a );
  3767. aExp := extractFloat64Exp( a );
  3768. aSign := extractFloat64Sign( a );
  3769. bSig1 := extractFloat64Frac1( b );
  3770. bSig0 := extractFloat64Frac0( b );
  3771. bExp := extractFloat64Exp( b );
  3772. bSign := extractFloat64Sign( b );
  3773. zSign := aSign xor bSign;
  3774. if ( aExp = $7FF ) then
  3775. Begin
  3776. if ( aSig0 OR aSig1 )<> 0 then
  3777. Begin
  3778. propagateFloat64NaN( a, b, out );
  3779. exit;
  3780. end;
  3781. if ( bExp = $7FF ) then
  3782. Begin
  3783. if ( bSig0 OR bSig1 )<>0 then
  3784. Begin
  3785. propagateFloat64NaN( a, b, out );
  3786. exit;
  3787. End;
  3788. goto invalid;
  3789. End;
  3790. packFloat64( zSign, $7FF, 0, 0, out );
  3791. exit;
  3792. End;
  3793. if ( bExp = $7FF ) then
  3794. Begin
  3795. if ( bSig0 OR bSig1 )<> 0 then
  3796. Begin
  3797. propagateFloat64NaN( a, b, out );
  3798. exit;
  3799. End;
  3800. packFloat64( zSign, 0, 0, 0, out );
  3801. exit;
  3802. End;
  3803. if ( bExp = 0 ) then
  3804. Begin
  3805. if ( ( bSig0 OR bSig1 ) = 0 ) then
  3806. Begin
  3807. if ( ( aExp OR aSig0 OR aSig1 ) = 0 ) then
  3808. Begin
  3809. invalid:
  3810. float_raise( float_flag_invalid );
  3811. z.low := float64_default_nan_low;
  3812. z.high := float64_default_nan_high;
  3813. out := z;
  3814. exit;
  3815. End;
  3816. float_raise( float_flag_divbyzero );
  3817. packFloat64( zSign, $7FF, 0, 0, out );
  3818. exit;
  3819. End;
  3820. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  3821. End;
  3822. if ( aExp = 0 ) then
  3823. Begin
  3824. if ( ( aSig0 OR aSig1 ) = 0 ) then
  3825. Begin
  3826. packFloat64( zSign, 0, 0, 0, out );
  3827. exit;
  3828. End;
  3829. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  3830. End;
  3831. zExp := aExp - bExp + $3FD;
  3832. shortShift64Left( aSig0 OR $00100000, aSig1, 11, aSig0, aSig1 );
  3833. shortShift64Left( bSig0 OR $00100000, bSig1, 11, bSig0, bSig1 );
  3834. if ( le64( bSig0, bSig1, aSig0, aSig1 )<>0 ) then
  3835. Begin
  3836. shift64Right( aSig0, aSig1, 1, aSig0, aSig1 );
  3837. Inc(zExp);
  3838. End;
  3839. zSig0 := estimateDiv64To32( aSig0, aSig1, bSig0 );
  3840. mul64By32To96( bSig0, bSig1, zSig0, term0, term1, term2 );
  3841. sub96( aSig0, aSig1, 0, term0, term1, term2, rem0, rem1, rem2 );
  3842. while ( sbits32 (rem0) < 0 ) do
  3843. Begin
  3844. Dec(zSig0);
  3845. add96( rem0, rem1, rem2, 0, bSig0, bSig1, rem0, rem1, rem2 );
  3846. End;
  3847. zSig1 := estimateDiv64To32( rem1, rem2, bSig0 );
  3848. if ( ( zSig1 and $3FF ) <= 4 ) then
  3849. Begin
  3850. mul64By32To96( bSig0, bSig1, zSig1, term1, term2, term3 );
  3851. sub96( rem1, rem2, 0, term1, term2, term3, rem1, rem2, rem3 );
  3852. while ( sbits32 (rem1) < 0 ) do
  3853. Begin
  3854. Dec(zSig1);
  3855. add96( rem1, rem2, rem3, 0, bSig0, bSig1, rem1, rem2, rem3 );
  3856. End;
  3857. zSig1 := zSig1 or flag( ( rem1 OR rem2 OR rem3 ) <> 0 );
  3858. End;
  3859. shift64ExtraRightJamming( zSig0, zSig1, 0, 11, zSig0, zSig1, zSig2 );
  3860. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, out );
  3861. End;
  3862. {*
  3863. -------------------------------------------------------------------------------
  3864. Returns the remainder of the double-precision floating-point value `a'
  3865. with respect to the corresponding value `b'. The operation is performed
  3866. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3867. -------------------------------------------------------------------------------
  3868. *}
  3869. Procedure float64_rem(a: float64; b : float64; var out: float64);
  3870. {$ifdef fpc}[public,Alias:'FLOAT64_REM'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  3871. Var
  3872. aSign, bSign, zSign: flag;
  3873. aExp, bExp, expDiff: int16;
  3874. aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits32;
  3875. allZero, alternateASig0, alternateASig1, sigMean1: bits32;
  3876. sigMean0: sbits32;
  3877. z: float64;
  3878. label invalid;
  3879. Begin
  3880. aSig1 := extractFloat64Frac1( a );
  3881. aSig0 := extractFloat64Frac0( a );
  3882. aExp := extractFloat64Exp( a );
  3883. aSign := extractFloat64Sign( a );
  3884. bSig1 := extractFloat64Frac1( b );
  3885. bSig0 := extractFloat64Frac0( b );
  3886. bExp := extractFloat64Exp( b );
  3887. bSign := extractFloat64Sign( b );
  3888. if ( aExp = $7FF ) then
  3889. Begin
  3890. if ((( aSig0 OR aSig1 )<>0)
  3891. OR ( ( bExp = $7FF ) AND (( bSig0 OR bSig1 )<>0) ) ) then
  3892. Begin
  3893. propagateFloat64NaN( a, b, out );
  3894. exit;
  3895. End;
  3896. goto invalid;
  3897. End;
  3898. if ( bExp = $7FF ) then
  3899. Begin
  3900. if ( bSig0 OR bSig1 ) <> 0 then
  3901. Begin
  3902. propagateFloat64NaN( a, b, out );
  3903. exit;
  3904. End;
  3905. out := a;
  3906. exit;
  3907. End;
  3908. if ( bExp = 0 ) then
  3909. Begin
  3910. if ( ( bSig0 OR bSig1 ) = 0 ) then
  3911. Begin
  3912. invalid:
  3913. float_raise( float_flag_invalid );
  3914. z.low := float64_default_nan_low;
  3915. z.high := float64_default_nan_high;
  3916. out := z;
  3917. exit;
  3918. End;
  3919. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  3920. End;
  3921. if ( aExp = 0 ) then
  3922. Begin
  3923. if ( ( aSig0 OR aSig1 ) = 0 ) then
  3924. Begin
  3925. out := a;
  3926. exit;
  3927. End;
  3928. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  3929. End;
  3930. expDiff := aExp - bExp;
  3931. if ( expDiff < -1 ) then
  3932. Begin
  3933. out := a;
  3934. exit;
  3935. End;
  3936. shortShift64Left(
  3937. aSig0 OR $00100000, aSig1, 11 - flag( expDiff < 0 ), aSig0, aSig1 );
  3938. shortShift64Left( bSig0 OR $00100000, bSig1, 11, bSig0, bSig1 );
  3939. q := le64( bSig0, bSig1, aSig0, aSig1 );
  3940. if ( q )<>0 then
  3941. sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  3942. expDiff := expDiff - 32;
  3943. while ( 0 < expDiff ) do
  3944. Begin
  3945. q := estimateDiv64To32( aSig0, aSig1, bSig0 );
  3946. if 4 < q then
  3947. q:= q - 4
  3948. else
  3949. q := 0;
  3950. mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );
  3951. shortShift96Left( term0, term1, term2, 29, term1, term2, allZero );
  3952. shortShift64Left( aSig0, aSig1, 29, aSig0, allZero );
  3953. sub64( aSig0, 0, term1, term2, aSig0, aSig1 );
  3954. expDiff := expDiff - 29;
  3955. End;
  3956. if ( -32 < expDiff ) then
  3957. Begin
  3958. q := estimateDiv64To32( aSig0, aSig1, bSig0 );
  3959. if 4 < q then
  3960. q := q - 4
  3961. else
  3962. q := 0;
  3963. q := q shr (- expDiff);
  3964. shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );
  3965. expDiff := expDiff + 24;
  3966. if ( expDiff < 0 ) then
  3967. Begin
  3968. shift64Right( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  3969. End
  3970. else
  3971. Begin
  3972. shortShift64Left( aSig0, aSig1, expDiff, aSig0, aSig1 );
  3973. End;
  3974. mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );
  3975. sub64( aSig0, aSig1, term1, term2, aSig0, aSig1 );
  3976. End
  3977. else
  3978. Begin
  3979. shift64Right( aSig0, aSig1, 8, aSig0, aSig1 );
  3980. shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );
  3981. End;
  3982. Repeat
  3983. alternateASig0 := aSig0;
  3984. alternateASig1 := aSig1;
  3985. Inc(q);
  3986. sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  3987. Until not ( 0 <= sbits32 (aSig0) );
  3988. add64(
  3989. aSig0, aSig1, alternateASig0, alternateASig1, bits32(sigMean0), sigMean1 );
  3990. if ( ( sigMean0 < 0 )
  3991. OR ( ( ( sigMean0 OR sigMean1 ) = 0 ) AND (( q AND 1 )<>0) ) ) then
  3992. Begin
  3993. aSig0 := alternateASig0;
  3994. aSig1 := alternateASig1;
  3995. End;
  3996. zSign := flag( sbits32 (aSig0) < 0 );
  3997. if ( zSign <> 0 ) then
  3998. sub64( 0, 0, aSig0, aSig1, aSig0, aSig1 );
  3999. normalizeRoundAndPackFloat64( aSign xor zSign, bExp - 4, aSig0, aSig1, out );
  4000. End;
  4001. {*
  4002. -------------------------------------------------------------------------------
  4003. Returns the square root of the double-precision floating-point value `a'.
  4004. The operation is performed according to the IEC/IEEE Standard for Binary
  4005. Floating-Point Arithmetic.
  4006. -------------------------------------------------------------------------------
  4007. *}
  4008. Procedure float64_sqrt( a: float64; var out: float64 );
  4009. {$ifdef fpc}[public,Alias:'FLOAT64_SQRT'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  4010. Var
  4011. aSign: flag;
  4012. aExp, zExp: int16;
  4013. aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits32;
  4014. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;
  4015. z: float64;
  4016. label invalid;
  4017. Begin
  4018. aSig1 := extractFloat64Frac1( a );
  4019. aSig0 := extractFloat64Frac0( a );
  4020. aExp := extractFloat64Exp( a );
  4021. aSign := extractFloat64Sign( a );
  4022. if ( aExp = $7FF ) then
  4023. Begin
  4024. if ( aSig0 OR aSig1 ) <> 0 then
  4025. Begin
  4026. propagateFloat64NaN( a, a, out );
  4027. exit;
  4028. End;
  4029. if ( aSign = 0) then
  4030. Begin
  4031. out := a;
  4032. exit;
  4033. End;
  4034. goto invalid;
  4035. End;
  4036. if ( aSign <> 0 ) then
  4037. Begin
  4038. if ( ( aExp OR aSig0 OR aSig1 ) = 0 ) then
  4039. Begin
  4040. out := a;
  4041. exit;
  4042. End;
  4043. invalid:
  4044. float_raise( float_flag_invalid );
  4045. z.low := float64_default_nan_low;
  4046. z.high := float64_default_nan_high;
  4047. out := z;
  4048. exit;
  4049. End;
  4050. if ( aExp = 0 ) then
  4051. Begin
  4052. if ( ( aSig0 OR aSig1 ) = 0 ) then
  4053. Begin
  4054. packFloat64( 0, 0, 0, 0, out );
  4055. exit;
  4056. End;
  4057. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  4058. End;
  4059. zExp := ( ( aExp - $3FF ) shr 1 ) + $3FE;
  4060. aSig0 := aSig0 or $00100000;
  4061. shortShift64Left( aSig0, aSig1, 11, term0, term1 );
  4062. zSig0 := ( estimateSqrt32( aExp, term0 ) shr 1 ) + 1;
  4063. if ( zSig0 = 0 ) then
  4064. zSig0 := $7FFFFFFF;
  4065. doubleZSig0 := zSig0 + zSig0;
  4066. shortShift64Left( aSig0, aSig1, 9 - ( aExp and 1 ), aSig0, aSig1 );
  4067. mul32To64( zSig0, zSig0, term0, term1 );
  4068. sub64( aSig0, aSig1, term0, term1, rem0, rem1 );
  4069. while ( sbits32 (rem0) < 0 ) do
  4070. Begin
  4071. Dec(zSig0);
  4072. doubleZSig0 := doubleZSig0 - 2;
  4073. add64( rem0, rem1, 0, doubleZSig0 OR 1, rem0, rem1 );
  4074. End;
  4075. zSig1 := estimateDiv64To32( rem1, 0, doubleZSig0 );
  4076. if ( ( zSig1 and $1FF ) <= 5 ) then
  4077. Begin
  4078. if ( zSig1 = 0 ) then
  4079. zSig1 := 1;
  4080. mul32To64( doubleZSig0, zSig1, term1, term2 );
  4081. sub64( rem1, 0, term1, term2, rem1, rem2 );
  4082. mul32To64( zSig1, zSig1, term2, term3 );
  4083. sub96( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
  4084. while ( sbits32 (rem1) < 0 ) do
  4085. Begin
  4086. Dec(zSig1);
  4087. shortShift64Left( 0, zSig1, 1, term2, term3 );
  4088. term3 := term3 or 1;
  4089. term2 := term2 or doubleZSig0;
  4090. add96( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
  4091. End;
  4092. zSig1 := zSig1 or bits32( ( rem1 OR rem2 OR rem3 ) <> 0 );
  4093. End;
  4094. shift64ExtraRightJamming( zSig0, zSig1, 0, 10, zSig0, zSig1, zSig2 );
  4095. roundAndPackFloat64( 0, zExp, zSig0, zSig1, zSig2, out );
  4096. End;
  4097. {*
  4098. -------------------------------------------------------------------------------
  4099. Returns 1 if the double-precision floating-point value `a' is equal to
  4100. the corresponding value `b', and 0 otherwise. The comparison is performed
  4101. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4102. -------------------------------------------------------------------------------
  4103. *}
  4104. Function float64_eq(a: float64; b: float64): flag;
  4105. {$ifdef fpc}[public,Alias:'FLOAT64_EQ'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  4106. Begin
  4107. if
  4108. (
  4109. ( extractFloat64Exp( a ) = $7FF )
  4110. AND
  4111. (
  4112. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4113. )
  4114. )
  4115. OR (
  4116. ( extractFloat64Exp( b ) = $7FF )
  4117. AND (
  4118. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4119. )
  4120. )
  4121. ) then
  4122. Begin
  4123. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  4124. float_raise( float_flag_invalid );
  4125. float64_eq := 0;
  4126. exit;
  4127. End;
  4128. float64_eq := flag(
  4129. ( a.low = b.low )
  4130. AND ( ( a.high = b.high )
  4131. OR ( ( a.low = 0 )
  4132. AND ( bits32 ( ( a.high OR b.high ) shl 1 ) = 0 ) )
  4133. ));
  4134. End;
  4135. {*
  4136. -------------------------------------------------------------------------------
  4137. Returns 1 if the double-precision floating-point value `a' is less than
  4138. or equal to the corresponding value `b', and 0 otherwise. The comparison
  4139. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  4140. Arithmetic.
  4141. -------------------------------------------------------------------------------
  4142. *}
  4143. Function float64_le(a: float64;b: float64): flag;
  4144. {$ifdef fpc}[public,Alias:'FLOAT64_LE'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  4145. Var
  4146. aSign, bSign: flag;
  4147. Begin
  4148. if
  4149. (
  4150. ( extractFloat64Exp( a ) = $7FF )
  4151. AND
  4152. (
  4153. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4154. )
  4155. )
  4156. OR (
  4157. ( extractFloat64Exp( b ) = $7FF )
  4158. AND (
  4159. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4160. )
  4161. )
  4162. ) then
  4163. Begin
  4164. float_raise( float_flag_invalid );
  4165. float64_le := 0;
  4166. exit;
  4167. End;
  4168. aSign := extractFloat64Sign( a );
  4169. bSign := extractFloat64Sign( b );
  4170. if ( aSign <> bSign ) then
  4171. Begin
  4172. float64_le := flag(
  4173. (aSign <> 0)
  4174. OR ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  4175. = 0 ));
  4176. exit;
  4177. End;
  4178. if aSign <> 0 then
  4179. float64_le := le64( b.high, b.low, a.high, a.low )
  4180. else
  4181. float64_le := le64( a.high, a.low, b.high, b.low );
  4182. End;
  4183. {*
  4184. -------------------------------------------------------------------------------
  4185. Returns 1 if the double-precision floating-point value `a' is less than
  4186. the corresponding value `b', and 0 otherwise. The comparison is performed
  4187. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4188. -------------------------------------------------------------------------------
  4189. *}
  4190. Function float64_lt(a: float64;b: float64): flag;
  4191. {$ifdef fpc}[public,Alias:'FLOAT64_LT'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  4192. Var
  4193. aSign, bSign: flag;
  4194. Begin
  4195. if
  4196. (
  4197. ( extractFloat64Exp( a ) = $7FF )
  4198. AND
  4199. (
  4200. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4201. )
  4202. )
  4203. OR (
  4204. ( extractFloat64Exp( b ) = $7FF )
  4205. AND (
  4206. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4207. )
  4208. )
  4209. ) then
  4210. Begin
  4211. float_raise( float_flag_invalid );
  4212. float64_lt := 0;
  4213. exit;
  4214. End;
  4215. aSign := extractFloat64Sign( a );
  4216. bSign := extractFloat64Sign( b );
  4217. if ( aSign <> bSign ) then
  4218. Begin
  4219. float64_lt := flag(
  4220. (aSign <> 0)
  4221. AND ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  4222. <> 0 ));
  4223. exit;
  4224. End;
  4225. if aSign <> 0 then
  4226. float64_lt := lt64( b.high, b.low, a.high, a.low )
  4227. else
  4228. float64_lt := lt64( a.high, a.low, b.high, b.low );
  4229. End;
  4230. {*
  4231. -------------------------------------------------------------------------------
  4232. Returns 1 if the double-precision floating-point value `a' is equal to
  4233. the corresponding value `b', and 0 otherwise. The invalid exception is
  4234. raised if either operand is a NaN. Otherwise, the comparison is performed
  4235. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4236. -------------------------------------------------------------------------------
  4237. *}
  4238. Function float64_eq_signaling( a: float64; b: float64): flag;
  4239. Begin
  4240. if
  4241. (
  4242. ( extractFloat64Exp( a ) = $7FF )
  4243. AND
  4244. (
  4245. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4246. )
  4247. )
  4248. OR (
  4249. ( extractFloat64Exp( b ) = $7FF )
  4250. AND (
  4251. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4252. )
  4253. )
  4254. ) then
  4255. Begin
  4256. float_raise( float_flag_invalid );
  4257. float64_eq_signaling := 0;
  4258. exit;
  4259. End;
  4260. float64_eq_signaling := flag(
  4261. ( a.low = b.low )
  4262. AND ( ( a.high = b.high )
  4263. OR ( ( a.low = 0 )
  4264. AND ( bits32 ( ( a.high OR b.high ) shl 1 ) = 0 ) )
  4265. ));
  4266. End;
  4267. {*
  4268. -------------------------------------------------------------------------------
  4269. Returns 1 if the double-precision floating-point value `a' is less than or
  4270. equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  4271. cause an exception. Otherwise, the comparison is performed according to the
  4272. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4273. -------------------------------------------------------------------------------
  4274. *}
  4275. Function float64_le_quiet(a: float64 ; b: float64 ): flag;
  4276. Var
  4277. aSign, bSign : flag;
  4278. Begin
  4279. if
  4280. (
  4281. ( extractFloat64Exp( a ) = $7FF )
  4282. AND
  4283. (
  4284. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4285. )
  4286. )
  4287. OR (
  4288. ( extractFloat64Exp( b ) = $7FF )
  4289. AND (
  4290. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4291. )
  4292. )
  4293. ) then
  4294. Begin
  4295. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  4296. float_raise( float_flag_invalid );
  4297. float64_le_quiet := 0;
  4298. exit;
  4299. End;
  4300. aSign := extractFloat64Sign( a );
  4301. bSign := extractFloat64Sign( b );
  4302. if ( aSign <> bSign ) then
  4303. Begin
  4304. float64_le_quiet := flag
  4305. ((aSign <> 0)
  4306. OR ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  4307. = 0 ));
  4308. exit;
  4309. End;
  4310. if aSign <> 0 then
  4311. float64_le_quiet := le64( b.high, b.low, a.high, a.low )
  4312. else
  4313. float64_le_quiet := le64( a.high, a.low, b.high, b.low );
  4314. End;
  4315. {*
  4316. -------------------------------------------------------------------------------
  4317. Returns 1 if the double-precision floating-point value `a' is less than
  4318. the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  4319. exception. Otherwise, the comparison is performed according to the IEC/IEEE
  4320. Standard for Binary Floating-Point Arithmetic.
  4321. -------------------------------------------------------------------------------
  4322. *}
  4323. Function float64_lt_quiet(a: float64; b: float64 ): Flag;
  4324. Var
  4325. aSign, bSign: flag;
  4326. Begin
  4327. if
  4328. (
  4329. ( extractFloat64Exp( a ) = $7FF )
  4330. AND
  4331. (
  4332. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4333. )
  4334. )
  4335. OR (
  4336. ( extractFloat64Exp( b ) = $7FF )
  4337. AND (
  4338. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4339. )
  4340. )
  4341. ) then
  4342. Begin
  4343. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  4344. float_raise( float_flag_invalid );
  4345. float64_lt_quiet := 0;
  4346. exit;
  4347. End;
  4348. aSign := extractFloat64Sign( a );
  4349. bSign := extractFloat64Sign( b );
  4350. if ( aSign <> bSign ) then
  4351. Begin
  4352. float64_lt_quiet := flag(
  4353. (aSign<>0)
  4354. AND ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  4355. <> 0 ));
  4356. exit;
  4357. End;
  4358. If aSign <> 0 then
  4359. float64_lt_quiet := lt64( b.high, b.low, a.high, a.low )
  4360. else
  4361. float64_lt_quiet := lt64( a.high, a.low, b.high, b.low );
  4362. End;
  4363. {*----------------------------------------------------------------------------
  4364. | Returns the result of converting the 64-bit two's complement integer `a'
  4365. | to the single-precision floating-point format. The conversion is performed
  4366. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4367. *----------------------------------------------------------------------------*}
  4368. function int64_to_float32( a: int64 ): float32;
  4369. {$ifdef fpc}[public,Alias:'INT64_TO_FLOAT32'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  4370. var
  4371. zSign : flag;
  4372. absA : uint64;
  4373. shiftCount: int8;
  4374. zSig : bits32;
  4375. intval : int64rec;
  4376. Begin
  4377. if ( a = 0 ) then
  4378. begin
  4379. int64_to_float32 := 0;
  4380. exit;
  4381. end;
  4382. if a < 0 then
  4383. zSign := flag(TRUE)
  4384. else
  4385. zSign := flag(FALSE);
  4386. if zSign<>0 then
  4387. absA := -a
  4388. else
  4389. absA := a;
  4390. shiftCount := countLeadingZeros64( absA ) - 40;
  4391. if ( 0 <= shiftCount ) then
  4392. begin
  4393. int64_to_float32:= packFloat32( zSign, $95 - shiftCount, absA shl shiftCount );
  4394. end
  4395. else
  4396. begin
  4397. shiftCount := shiftCount + 7;
  4398. if ( shiftCount < 0 ) then
  4399. begin
  4400. intval.low := int64rec(AbsA).low;
  4401. intval.high := int64rec(AbsA).high;
  4402. shift64RightJamming( intval.low, intval.high, - shiftCount,
  4403. intval.low, intval.high);
  4404. int64rec(absA).low := intval.low;
  4405. int64rec(absA).high := intval.high;
  4406. end
  4407. else
  4408. absA := absA shl shiftCount;
  4409. int64_to_float32:=roundAndPackFloat32( zSign, $9C - shiftCount, absA );
  4410. end;
  4411. End;
  4412. {*----------------------------------------------------------------------------
  4413. | Returns the result of converting the 64-bit two's complement integer `a'
  4414. | to the double-precision floating-point format. The conversion is performed
  4415. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4416. *----------------------------------------------------------------------------*}
  4417. function int64_to_float64( a: int64 ): float64;
  4418. {$ifdef fpc}[public,Alias:'INT64_TO_FLOAT64'];{$ifdef hascompilerproc} compilerproc; {$endif}{$endif}
  4419. var
  4420. zSign : flag;
  4421. float_result : float64;
  4422. intval : int64rec;
  4423. AbsA : bits64;
  4424. shiftcount : int8;
  4425. zSig0, zSig1 : bits32;
  4426. Begin
  4427. if ( a = 0 ) then
  4428. Begin
  4429. packFloat64( 0, 0, 0, 0, float_result );
  4430. exit;
  4431. end;
  4432. zSign := flag( a < 0 );
  4433. if ZSign<>0 then
  4434. AbsA := -a
  4435. else
  4436. AbsA := a;
  4437. shiftCount := countLeadingZeros64( absA ) - 11;
  4438. if ( 0 <= shiftCount ) then
  4439. Begin
  4440. absA := absA shl shiftcount;
  4441. zSig0:=int64rec(absA).high;
  4442. zSig1:=int64rec(absA).low;
  4443. End
  4444. else
  4445. Begin
  4446. shift64Right( absA, 0, - shiftCount, zSig0, zSig1 );
  4447. End;
  4448. packFloat64( zSign, $432 - shiftCount, zSig0, zSig1, float_result );
  4449. int64_to_float64:= float_result;
  4450. End;
  4451. end.
  4452. {
  4453. $Log$
  4454. Revision 1.6 2002-11-30 23:25:19 carl
  4455. * forgot goto on switch in last commit
  4456. Revision 1.5 2002/11/30 21:34:20 carl
  4457. + compilerproc for softfpu (first step for integration)
  4458. * several bugfixes for big-endian support
  4459. Revision 1.4 2002/10/13 15:47:39 carl
  4460. * bugfix for int64 to float conversion
  4461. Revision 1.3 2002/10/12 20:24:22 carl
  4462. + int64_tof_loat conversion routines
  4463. Revision 1.2 2002/10/08 20:07:08 carl
  4464. * fix range check errors
  4465. - overflow checking must be off always
  4466. * debugged and works as expected
  4467. Revision 1.1 2002/09/16 19:10:17 carl
  4468. * first revision of FPU emulation
  4469. }