softfpu.pp 154 KB

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