softfpu.pp 156 KB

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