genmath.inc 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2007 by Several contributors
  4. Generic mathematical routines (on type real)
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {*************************************************************************}
  12. { Credits }
  13. {*************************************************************************}
  14. { Copyright Abandoned, 1987, Fred Fish }
  15. { }
  16. { This previously copyrighted work has been placed into the }
  17. { public domain by the author (Fred Fish) and may be freely used }
  18. { for any purpose, private or commercial. I would appreciate }
  19. { it, as a courtesy, if this notice is left in all copies and }
  20. { derivative works. Thank you, and enjoy... }
  21. { }
  22. { The author makes no warranty of any kind with respect to this }
  23. { product and explicitly disclaims any implied warranties of }
  24. { merchantability or fitness for any particular purpose. }
  25. {-------------------------------------------------------------------------}
  26. { Copyright (c) 1992 Odent Jean Philippe }
  27. { }
  28. { The source can be modified as long as my name appears and some }
  29. { notes explaining the modifications done are included in the file. }
  30. {-------------------------------------------------------------------------}
  31. { Copyright (c) 1997 Carl Eric Codere }
  32. {-------------------------------------------------------------------------}
  33. {-------------------------------------------------------------------------
  34. Using functions from AMath/DAMath libraries, which are covered by the
  35. following license:
  36. (C) Copyright 2009-2013 Wolfgang Ehrhardt
  37. This software is provided 'as-is', without any express or implied warranty.
  38. In no event will the authors be held liable for any damages arising from
  39. the use of this software.
  40. Permission is granted to anyone to use this software for any purpose,
  41. including commercial applications, and to alter it and redistribute it
  42. freely, subject to the following restrictions:
  43. 1. The origin of this software must not be misrepresented; you must not
  44. claim that you wrote the original software. If you use this software in
  45. a product, an acknowledgment in the product documentation would be
  46. appreciated but is not required.
  47. 2. Altered source versions must be plainly marked as such, and must not be
  48. misrepresented as being the original software.
  49. 3. This notice may not be removed or altered from any source distribution.
  50. ----------------------------------------------------------------------------}
  51. type
  52. PReal = ^Real;
  53. { also necessary for Int() on systems with 64bit floats (JM) }
  54. {$ifndef FPC_SYSTEM_HAS_float64}
  55. {$ifdef ENDIAN_LITTLE}
  56. float64 = record
  57. {$ifndef FPC_DOUBLE_HILO_SWAPPED}
  58. low,high: longint;
  59. {$else}
  60. high,low: longint;
  61. {$endif FPC_DOUBLE_HILO_SWAPPED}
  62. end;
  63. {$else}
  64. float64 = record
  65. {$ifndef FPC_DOUBLE_HILO_SWAPPED}
  66. high,low: longint;
  67. {$else}
  68. low,high: longint;
  69. {$endif FPC_DOUBLE_HILO_SWAPPED}
  70. end;
  71. {$endif}
  72. {$endif FPC_SYSTEM_HAS_float64}
  73. const
  74. PIO4 = 7.85398163397448309616E-1; { pi/4 }
  75. SQRT2 = 1.41421356237309504880; { sqrt(2) }
  76. LOG2E = 1.4426950408889634073599; { 1/log(2) }
  77. lossth = 1.073741824e9;
  78. MAXLOG = 8.8029691931113054295988E1; { log(2**127) }
  79. MINLOG = -8.872283911167299960540E1; { log(2**-128) }
  80. H2_54: double = 18014398509481984.0; {2^54}
  81. huge: double = 1e300;
  82. one: double = 1.0;
  83. zero: double = 0;
  84. {$if not defined(FPC_SYSTEM_HAS_SIN) or not defined(FPC_SYSTEM_HAS_COS)}
  85. const sincof : array[0..5] of Real = (
  86. 1.58962301576546568060E-10,
  87. -2.50507477628578072866E-8,
  88. 2.75573136213857245213E-6,
  89. -1.98412698295895385996E-4,
  90. 8.33333333332211858878E-3,
  91. -1.66666666666666307295E-1);
  92. coscof : array[0..5] of Real = (
  93. -1.13585365213876817300E-11,
  94. 2.08757008419747316778E-9,
  95. -2.75573141792967388112E-7,
  96. 2.48015872888517045348E-5,
  97. -1.38888888888730564116E-3,
  98. 4.16666666666665929218E-2);
  99. {$endif}
  100. {*
  101. -------------------------------------------------------------------------------
  102. Raises the exceptions specified by `flags'. Floating-point traps can be
  103. defined here if desired. It is currently not possible for such a trap
  104. to substitute a result value. If traps are not implemented, this routine
  105. should be simply `softfloat_exception_flags |= flags;'.
  106. -------------------------------------------------------------------------------
  107. *}
  108. procedure float_raise(i: TFPUException);
  109. begin
  110. float_raise([i]);
  111. end;
  112. procedure float_raise(i: TFPUExceptionMask);
  113. var
  114. pflags: ^TFPUExceptionMask;
  115. unmasked_flags: TFPUExceptionMask;
  116. Begin
  117. { taking address of threadvar produces somewhat more compact code }
  118. pflags := @softfloat_exception_flags;
  119. pflags^:=pflags^ + i;
  120. unmasked_flags := pflags^ - softfloat_exception_mask;
  121. { before we raise the exception, we mark it as handled,
  122. this behaviour is similiar to the hardware handler in SignalToRunerror }
  123. SysResetFPU;
  124. if (float_flag_invalid in unmasked_flags) then
  125. HandleError(207)
  126. else if (float_flag_divbyzero in unmasked_flags) then
  127. HandleError(200)
  128. else if (float_flag_overflow in unmasked_flags) then
  129. HandleError(205)
  130. else if (float_flag_underflow in unmasked_flags) then
  131. HandleError(206)
  132. else if (float_flag_inexact in unmasked_flags) then
  133. HandleError(207)
  134. else if (float_flag_denormal in unmasked_flags) then
  135. HandleError(216);
  136. end;
  137. { This function does nothing, but its argument is expected to be an expression
  138. which causes FPE when calculated. If exception is masked, it just returns true,
  139. allowing to use it in expressions. }
  140. function fpe_helper(x: valreal): boolean;
  141. begin
  142. result:=true;
  143. end;
  144. {$ifdef SUPPORT_DOUBLE}
  145. {$ifndef FPC_HAS_FLOAT64HIGH}
  146. {$define FPC_HAS_FLOAT64HIGH}
  147. function float64high(d: double): longint; inline;
  148. begin
  149. result:=float64(d).high;
  150. end;
  151. procedure float64sethigh(var d: double; l: longint); inline;
  152. begin
  153. float64(d).high:=l;
  154. end;
  155. {$endif FPC_HAS_FLOAT64HIGH}
  156. {$ifndef FPC_HAS_FLOAT64LOW}
  157. {$define FPC_HAS_FLOAT64LOW}
  158. function float64low(d: double): longint; inline;
  159. begin
  160. result:=float64(d).low;
  161. end;
  162. procedure float64setlow(var d: double; l: longint); inline;
  163. begin
  164. float64(d).low:=l;
  165. end;
  166. {$endif FPC_HAS_FLOAT64LOW}
  167. {$endif SUPPORT_DOUBLE}
  168. {$ifndef FPC_SYSTEM_HAS_TRUNC}
  169. {$ifndef FPC_SYSTEM_HAS_float32}
  170. type
  171. float32 = longint;
  172. {$endif FPC_SYSTEM_HAS_float32}
  173. {$ifdef SUPPORT_DOUBLE}
  174. { based on softfloat float64_to_int64_round_to_zero }
  175. function fpc_trunc_real(d : valreal) : int64; compilerproc;
  176. var
  177. aExp, shiftCount : smallint;
  178. aSig : int64;
  179. z : int64;
  180. a: float64;
  181. begin
  182. a:=float64(d);
  183. aSig:=(int64(a.high and $000fffff) shl 32) or longword(a.low);
  184. aExp:=(a.high shr 20) and $7FF;
  185. if aExp<>0 then
  186. aSig:=aSig or $0010000000000000;
  187. shiftCount:= aExp-$433;
  188. if 0<=shiftCount then
  189. begin
  190. if aExp>=$43e then
  191. begin
  192. if (a.high<>longint($C3E00000)) or (a.low<>0) then
  193. begin
  194. fpe_helper(zero/zero);
  195. if (longint(a.high)>=0) or ((aExp=$7FF) and
  196. (aSig<>$0010000000000000 )) then
  197. begin
  198. result:=$7FFFFFFFFFFFFFFF;
  199. exit;
  200. end;
  201. end;
  202. result:=$8000000000000000;
  203. exit;
  204. end;
  205. z:=aSig shl shiftCount;
  206. end
  207. else
  208. begin
  209. if aExp<$3fe then
  210. begin
  211. result:=0;
  212. exit;
  213. end;
  214. z:=aSig shr -shiftCount;
  215. {
  216. if (aSig shl (shiftCount and 63))<>0 then
  217. float_exception_flags |= float_flag_inexact;
  218. }
  219. end;
  220. if longint(a.high)<0 then
  221. z:=-z;
  222. result:=z;
  223. end;
  224. {$else SUPPORT_DOUBLE}
  225. { based on softfloat float32_to_int64_round_to_zero }
  226. Function fpc_trunc_real( d: valreal ): int64; compilerproc;
  227. Var
  228. a : float32;
  229. aExp, shiftCount : smallint;
  230. aSig : longint;
  231. aSig64, z : int64;
  232. Begin
  233. a := float32(d);
  234. aSig := a and $007FFFFF;
  235. aExp := (a shr 23) and $FF;
  236. shiftCount := aExp - $BE;
  237. if ( 0 <= shiftCount ) then
  238. Begin
  239. if ( a <> Float32($DF000000) ) then
  240. Begin
  241. fpe_helper( zero/zero );
  242. if ( (longint(a)>=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  243. Begin
  244. result:=$7fffffffffffffff;
  245. exit;
  246. end;
  247. End;
  248. result:=$8000000000000000;
  249. exit;
  250. End
  251. else
  252. if ( aExp <= $7E ) then
  253. Begin
  254. result := 0;
  255. exit;
  256. End;
  257. aSig64 := int64( aSig or $00800000 ) shl 40;
  258. z := aSig64 shr ( - shiftCount );
  259. if ( longint(a)<0 ) then z := - z;
  260. result := z;
  261. End;
  262. {$endif SUPPORT_DOUBLE}
  263. {$endif not FPC_SYSTEM_HAS_TRUNC}
  264. {$ifndef FPC_SYSTEM_HAS_INT}
  265. {$ifdef SUPPORT_DOUBLE}
  266. { straight Pascal translation of the code for __trunc() in }
  267. { the file sysdeps/libm-ieee754/s_trunc.c of glibc (JM) }
  268. function fpc_int_real(d: ValReal): ValReal;compilerproc;
  269. var
  270. i0, j0: longint;
  271. i1: cardinal;
  272. sx: longint;
  273. f64 : float64;
  274. begin
  275. f64:=float64(d);
  276. i0 := f64.high;
  277. i1 := cardinal(f64.low);
  278. sx := i0 and $80000000;
  279. j0 := ((i0 shr 20) and $7ff) - $3ff;
  280. if (j0 < 20) then
  281. begin
  282. if (j0 < 0) then
  283. begin
  284. { the magnitude of the number is < 1 so the result is +-0. }
  285. f64.high := sx;
  286. f64.low := 0;
  287. end
  288. else
  289. begin
  290. f64.high := sx or (i0 and not($fffff shr j0));
  291. f64.low := 0;
  292. end
  293. end
  294. else if (j0 > 51) then
  295. begin
  296. if (j0 = $400) then
  297. { d is inf or NaN }
  298. exit(d + d); { don't know why they do this (JM) }
  299. end
  300. else
  301. begin
  302. f64.high := i0;
  303. f64.low := longint(i1 and not(cardinal($ffffffff) shr (j0 - 20)));
  304. end;
  305. result:=double(f64);
  306. end;
  307. {$else SUPPORT_DOUBLE}
  308. function fpc_int_real(d : ValReal) : ValReal;compilerproc;
  309. begin
  310. { this will be correct since real = single in the case of }
  311. { the motorola version of the compiler... }
  312. result:=ValReal(trunc(d));
  313. end;
  314. {$endif SUPPORT_DOUBLE}
  315. {$endif not FPC_SYSTEM_HAS_INT}
  316. {$ifndef FPC_SYSTEM_HAS_ABS}
  317. function fpc_abs_real(d : ValReal) : ValReal;compilerproc;
  318. begin
  319. if (d<0.0) then
  320. result := -d
  321. else
  322. result := d ;
  323. end;
  324. {$endif not FPC_SYSTEM_HAS_ABS}
  325. {$ifndef SYSTEM_HAS_FREXP}
  326. procedure frexp(X: Real; out Mantissa: Real; out Exponent: longint);
  327. {* frexp() extracts the exponent from x. It returns an integer *}
  328. {* power of two to expnt and the significand between 0.5 and 1 *}
  329. {* to y. Thus x = y * 2**expn. *}
  330. begin
  331. exponent:=0;
  332. if (abs(x)<0.5) then
  333. While (abs(x)<0.5) do
  334. begin
  335. x := x*2;
  336. Dec(exponent);
  337. end
  338. else
  339. While (abs(x)>1) do
  340. begin
  341. x := x/2;
  342. Inc(exponent);
  343. end;
  344. Mantissa := x;
  345. end;
  346. {$endif not SYSTEM_HAS_FREXP}
  347. {$ifndef SYSTEM_HAS_LDEXP}
  348. {$ifdef SUPPORT_DOUBLE}
  349. { ldexpd function adapted from DAMath library (C) Copyright 2013 Wolfgang Ehrhardt }
  350. function ldexp( x: Real; N: Integer):Real;
  351. {* ldexp() multiplies x by 2**n. *}
  352. var
  353. i: integer;
  354. begin
  355. i := (float64high(x) and $7ff00000) shr 20;
  356. {if +-INF, NaN, 0 or if e=0 return d}
  357. if (i=$7FF) or (N=0) or (x=0.0) then
  358. ldexp := x
  359. else if i=0 then {Denormal: result = d*2^54*2^(e-54)}
  360. ldexp := ldexp(x*H2_54, N-54)
  361. else
  362. begin
  363. N := N+i;
  364. if N>$7FE then { overflow }
  365. begin
  366. if x>0.0 then
  367. ldexp := 2.0*huge
  368. else
  369. ldexp := (-2.0)*huge;
  370. end
  371. else if N<1 then
  372. begin
  373. {underflow or denormal}
  374. if N<-53 then
  375. ldexp := 0.0
  376. else
  377. begin
  378. {Denormal: result = d*2^(e+54)/2^54}
  379. inc(N,54);
  380. float64sethigh(x,(float64high(x) and $800FFFFF) or (longint(N) shl 20));
  381. ldexp := x/H2_54;
  382. end;
  383. end
  384. else
  385. begin
  386. float64sethigh(x,(float64high(x) and $800FFFFF) or (longint(N) shl 20));
  387. ldexp := x;
  388. end;
  389. end;
  390. end;
  391. {$else SUPPORT_DOUBLE}
  392. function ldexp( x: Real; N: Integer):Real;
  393. {* ldexp() multiplies x by 2**n. *}
  394. var r : Real;
  395. begin
  396. R := 1;
  397. if N>0 then
  398. while N>0 do
  399. begin
  400. R:=R*2;
  401. Dec(N);
  402. end
  403. else
  404. while N<0 do
  405. begin
  406. R:=R/2;
  407. Inc(N);
  408. end;
  409. ldexp := x * R;
  410. end;
  411. {$endif SUPPORT_DOUBLE}
  412. {$endif not SYSTEM_HAS_LDEXP}
  413. function polevl(x:Real; Coef:PReal; N:sizeint):Real;
  414. {*****************************************************************}
  415. { Evaluate polynomial }
  416. {*****************************************************************}
  417. { }
  418. { SYNOPSIS: }
  419. { }
  420. { int N; }
  421. { double x, y, coef[N+1], polevl[]; }
  422. { }
  423. { y = polevl( x, coef, N ); }
  424. { }
  425. { DESCRIPTION: }
  426. { }
  427. { Evaluates polynomial of degree N: }
  428. { }
  429. { 2 N }
  430. { y = C + C x + C x +...+ C x }
  431. { 0 1 2 N }
  432. { }
  433. { Coefficients are stored in reverse order: }
  434. { }
  435. { coef[0] = C , ..., coef[N] = C . }
  436. { N 0 }
  437. { }
  438. { The function p1evl() assumes that coef[N] = 1.0 and is }
  439. { omitted from the array. Its calling arguments are }
  440. { otherwise the same as polevl(). }
  441. { }
  442. { SPEED: }
  443. { }
  444. { In the interest of speed, there are no checks for out }
  445. { of bounds arithmetic. This routine is used by most of }
  446. { the functions in the library. Depending on available }
  447. { equipment features, the user may wish to rewrite the }
  448. { program in microcode or assembly language. }
  449. {*****************************************************************}
  450. var ans : Real;
  451. i : sizeint;
  452. begin
  453. ans := Coef[0];
  454. for i:=1 to N do
  455. ans := ans * x + Coef[i];
  456. polevl:=ans;
  457. end;
  458. function p1evl(x:Real; Coef:PReal; N:sizeint):Real;
  459. { }
  460. { Evaluate polynomial when coefficient of x is 1.0. }
  461. { Otherwise same as polevl. }
  462. { }
  463. var
  464. ans : Real;
  465. i : sizeint;
  466. begin
  467. ans := x + Coef[0];
  468. for i:=1 to N-1 do
  469. ans := ans * x + Coef[i];
  470. p1evl := ans;
  471. end;
  472. function floord(x: double): double;
  473. var
  474. t: double;
  475. begin
  476. t := int(x);
  477. if (x>=0.0) or (x=t) then
  478. floord := t
  479. else
  480. floord := t - 1.0;
  481. end;
  482. {*
  483. * ====================================================
  484. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  485. *
  486. * Developed at SunPro, a Sun Microsystems, Inc. business.
  487. * Permission to use, copy, modify, and distribute this
  488. * software is freely granted, provided that this notice
  489. * is preserved.
  490. * ====================================================
  491. *
  492. * Pascal port of this routine comes from DAMath library
  493. * (C) Copyright 2013 Wolfgang Ehrhardt
  494. *
  495. * k_rem_pio2 return the last three bits of N with y = x - N*pi/2
  496. * so that |y| < pi/2.
  497. *
  498. * The method is to compute the integer (mod 8) and fraction parts of
  499. * (2/pi)*x without doing the full multiplication. In general we
  500. * skip the part of the product that are known to be a huge integer
  501. * (more accurately, = 0 mod 8 ). Thus the number of operations are
  502. * independent of the exponent of the input.
  503. *
  504. * (2/pi) is represented by an array of 24-bit integers in ipio2[].
  505. *
  506. * Input parameters:
  507. * x[] The input value (must be positive) is broken into nx
  508. * pieces of 24-bit integers in double precision format.
  509. * x[i] will be the i-th 24 bit of x. The scaled exponent
  510. * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
  511. * match x's up to 24 bits.
  512. *
  513. * Example of breaking a double positive z into x[0]+x[1]+x[2]:
  514. * e0 = ilogb(z)-23
  515. * z = scalbn(z,-e0)
  516. * for i = 0,1,2
  517. * x[i] = floor(z)
  518. * z = (z-x[i])*2**24
  519. *
  520. *
  521. * y[] output result in an array of double precision numbers.
  522. * The dimension of y[] is:
  523. * 24-bit precision 1
  524. * 53-bit precision 2
  525. * 64-bit precision 2
  526. * 113-bit precision 3
  527. * The actual value is the sum of them. Thus for 113-bit
  528. * precison, one may have to do something like:
  529. *
  530. * long double t,w,r_head, r_tail;
  531. * t = (long double)y[2] + (long double)y[1];
  532. * w = (long double)y[0];
  533. * r_head = t+w;
  534. * r_tail = w - (r_head - t);
  535. *
  536. * e0 The exponent of x[0]. Must be <= 16360 or you need to
  537. * expand the ipio2 table.
  538. *
  539. * nx dimension of x[]
  540. *
  541. * prec an integer indicating the precision:
  542. * 0 24 bits (single)
  543. * 1 53 bits (double)
  544. * 2 64 bits (extended)
  545. * 3 113 bits (quad)
  546. *
  547. * Here is the description of some local variables:
  548. *
  549. * jk jk+1 is the initial number of terms of ipio2[] needed
  550. * in the computation. The recommended value is 2,3,4,
  551. * 6 for single, double, extended,and quad.
  552. *
  553. * jz local integer variable indicating the number of
  554. * terms of ipio2[] used.
  555. *
  556. * jx nx - 1
  557. *
  558. * jv index for pointing to the suitable ipio2[] for the
  559. * computation. In general, we want
  560. * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
  561. * is an integer. Thus
  562. * e0-3-24*jv >= 0 or (e0-3)/24 >= jv
  563. * Hence jv = max(0,(e0-3)/24).
  564. *
  565. * jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
  566. *
  567. * q[] double array with integral value, representing the
  568. * 24-bits chunk of the product of x and 2/pi.
  569. *
  570. * q0 the corresponding exponent of q[0]. Note that the
  571. * exponent for q[i] would be q0-24*i.
  572. *
  573. * PIo2[] double precision array, obtained by cutting pi/2
  574. * into 24 bits chunks.
  575. *
  576. * f[] ipio2[] in floating point
  577. *
  578. * iq[] integer array by breaking up q[] in 24-bits chunk.
  579. *
  580. * fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
  581. *
  582. * ih integer. If >0 it indicates q[] is >= 0.5, hence
  583. * it also indicates the *sign* of the result.
  584. *}
  585. {PIo2[] double array, obtained by cutting pi/2 into 24 bits chunks.}
  586. const
  587. PIo2chunked: array[0..7] of double = (
  588. 1.57079625129699707031e+00, { 0x3FF921FB, 0x40000000 }
  589. 7.54978941586159635335e-08, { 0x3E74442D, 0x00000000 }
  590. 5.39030252995776476554e-15, { 0x3CF84698, 0x80000000 }
  591. 3.28200341580791294123e-22, { 0x3B78CC51, 0x60000000 }
  592. 1.27065575308067607349e-29, { 0x39F01B83, 0x80000000 }
  593. 1.22933308981111328932e-36, { 0x387A2520, 0x40000000 }
  594. 2.73370053816464559624e-44, { 0x36E38222, 0x80000000 }
  595. 2.16741683877804819444e-51 { 0x3569F31D, 0x00000000 }
  596. );
  597. {Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi }
  598. ipio2: array[0..65] of longint = (
  599. $A2F983, $6E4E44, $1529FC, $2757D1, $F534DD, $C0DB62,
  600. $95993C, $439041, $FE5163, $ABDEBB, $C561B7, $246E3A,
  601. $424DD2, $E00649, $2EEA09, $D1921C, $FE1DEB, $1CB129,
  602. $A73EE8, $8235F5, $2EBB44, $84E99C, $7026B4, $5F7E41,
  603. $3991D6, $398353, $39F49C, $845F8B, $BDF928, $3B1FF8,
  604. $97FFDE, $05980F, $EF2F11, $8B5A0A, $6D1F6D, $367ECF,
  605. $27CB09, $B74F46, $3F669E, $5FEA2D, $7527BA, $C7EBE5,
  606. $F17B3D, $0739F7, $8A5292, $EA6BFB, $5FB11F, $8D5D08,
  607. $560330, $46FC7B, $6BABF0, $CFBC20, $9AF436, $1DA9E3,
  608. $91615E, $E61B08, $659985, $5F14A0, $68408D, $FFD880,
  609. $4D7327, $310606, $1556CA, $73A8C9, $60E27B, $C08C6B);
  610. init_jk: array[0..3] of integer = (2,3,4,6); {initial value for jk}
  611. two24: double = 16777216.0; {2^24}
  612. twon24: double = 5.9604644775390625e-08; {1/2^24}
  613. type
  614. TDA02 = array[0..2] of double; { 3 elements is enough for float128 }
  615. function k_rem_pio2(const x: TDA02; out y: TDA02; e0, nx, prec: integer): sizeint;
  616. var
  617. i,ih,j,jz,jx,jv,jp,jk,carry,k,n,q0: longint;
  618. t: longint;
  619. iq: array[0..19] of longint;
  620. f,fq,q: array[0..19] of double;
  621. z,fw: double;
  622. begin
  623. {initialize jk}
  624. jk := init_jk[prec];
  625. jp := jk;
  626. {determine jx,jv,q0, note that 3>q0}
  627. jx := nx-1;
  628. jv := (e0-3) div 24; if jv<0 then jv := 0;
  629. q0 := e0-24*(jv+1);
  630. {set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk]}
  631. j := jv-jx;
  632. for i:=0 to jx+jk do
  633. begin
  634. if j<0 then f[i] := 0.0 else f[i] := ipio2[j];
  635. inc(j);
  636. end;
  637. {compute q[0],q[1],...q[jk]}
  638. for i:=0 to jk do
  639. begin
  640. fw := 0.0;
  641. for j:=0 to jx do
  642. fw := fw + x[j]*f[jx+i-j];
  643. q[i] := fw;
  644. end;
  645. jz := jk;
  646. repeat
  647. {distill q[] into iq[] reversingly}
  648. i := 0;
  649. z := q[jz];
  650. for j:=jz downto 1 do
  651. begin
  652. fw := trunc(twon24*z);
  653. iq[i] := trunc(z-two24*fw);
  654. z := q[j-1]+fw;
  655. inc(i);
  656. end;
  657. {compute n}
  658. z := ldexp(z,q0); {actual value of z}
  659. z := z - 8.0*floord(z*0.125); {trim off integer >= 8}
  660. n := trunc(z);
  661. z := z - n;
  662. ih := 0;
  663. if q0>0 then
  664. begin
  665. {need iq[jz-1] to determine n}
  666. t := (iq[jz-1] shr (24-q0));
  667. inc(n,t);
  668. dec(iq[jz-1], t shl (24-q0));
  669. ih := iq[jz-1] shr (23-q0);
  670. end
  671. else if q0=0 then
  672. ih := iq[jz-1] shr 23
  673. else if z>=0.5 then
  674. ih := 2;
  675. if ih>0 then {q > 0.5}
  676. begin
  677. inc(n);
  678. carry := 0;
  679. for i:=0 to jz-1 do
  680. begin
  681. {compute 1-q}
  682. t := iq[i];
  683. if carry=0 then
  684. begin
  685. if t<>0 then
  686. begin
  687. carry := 1;
  688. iq[i] := $1000000 - t;
  689. end
  690. end
  691. else
  692. iq[i] := $ffffff - t;
  693. end;
  694. if q0>0 then
  695. begin
  696. {rare case: chance is 1 in 12}
  697. case q0 of
  698. 1: iq[jz-1] := iq[jz-1] and $7fffff;
  699. 2: iq[jz-1] := iq[jz-1] and $3fffff;
  700. end;
  701. end;
  702. if ih=2 then
  703. begin
  704. z := 1.0 - z;
  705. if carry<>0 then
  706. z := z - ldexp(1.0,q0);
  707. end;
  708. end;
  709. {check if recomputation is needed}
  710. if z<>0.0 then
  711. break;
  712. t := 0;
  713. for i:=jz-1 downto jk do
  714. t := t or iq[i];
  715. if t<>0 then
  716. break;
  717. {need recomputation}
  718. k := 1;
  719. while iq[jk-k]=0 do {k = no. of terms needed}
  720. inc(k);
  721. for i:=jz+1 to jz+k do
  722. begin
  723. {add q[jz+1] to q[jz+k]}
  724. f[jx+i] := ipio2[jv+i];
  725. fw := 0.0;
  726. for j:=0 to jx do
  727. fw := fw + x[j]*f[jx+i-j];
  728. q[i] := fw;
  729. end;
  730. inc(jz,k);
  731. until False;
  732. {chop off zero terms}
  733. if z=0.0 then
  734. begin
  735. repeat
  736. dec(jz);
  737. dec(q0,24);
  738. until iq[jz]<>0;
  739. end
  740. else
  741. begin
  742. {break z into 24-bit if necessary}
  743. z := ldexp(z,-q0);
  744. if z>=two24 then
  745. begin
  746. fw := trunc(twon24*z);
  747. iq[jz] := trunc(z-two24*fw);
  748. inc(jz);
  749. inc(q0,24);
  750. iq[jz] := trunc(fw);
  751. end
  752. else
  753. iq[jz] := trunc(z);
  754. end;
  755. {convert integer "bit" chunk to floating-point value}
  756. fw := ldexp(1.0,q0);
  757. for i:=jz downto 0 do
  758. begin
  759. q[i] := fw*iq[i];
  760. fw := fw*twon24;
  761. end;
  762. {compute PIo2[0,...,jp]*q[jz,...,0]}
  763. for i:=jz downto 0 do
  764. begin
  765. fw :=0.0;
  766. k := 0;
  767. while (k<=jp) and (k<=jz-i) do
  768. begin
  769. fw := fw + double(PIo2chunked[k])*(q[i+k]);
  770. inc(k);
  771. end;
  772. fq[jz-i] := fw;
  773. end;
  774. {compress fq[] into y[]}
  775. case prec of
  776. 0:
  777. begin
  778. fw := 0.0;
  779. for i:=jz downto 0 do
  780. fw := fw + fq[i];
  781. if ih=0 then
  782. y[0] := fw
  783. else
  784. y[0] := -fw;
  785. end;
  786. 1, 2:
  787. begin
  788. fw := 0.0;
  789. for i:=jz downto 0 do
  790. fw := fw + fq[i];
  791. if ih=0 then
  792. y[0] := fw
  793. else
  794. y[0] := -fw;
  795. fw := fq[0]-fw;
  796. for i:=1 to jz do
  797. fw := fw + fq[i];
  798. if ih=0 then
  799. y[1] := fw
  800. else
  801. y[1] := -fw;
  802. end;
  803. 3:
  804. begin
  805. {painful}
  806. for i:=jz downto 1 do
  807. begin
  808. fw := fq[i-1]+fq[i];
  809. fq[i] := fq[i]+(fq[i-1]-fw);
  810. fq[i-1]:= fw;
  811. end;
  812. for i:=jz downto 2 do
  813. begin
  814. fw := fq[i-1]+fq[i];
  815. fq[i] := fq[i]+(fq[i-1]-fw);
  816. fq[i-1]:= fw;
  817. end;
  818. fw := 0.0;
  819. for i:=jz downto 2 do
  820. fw := fw + fq[i];
  821. if ih=0 then
  822. begin
  823. y[0] := fq[0];
  824. y[1] := fq[1];
  825. y[2] := fw;
  826. end
  827. else
  828. begin
  829. y[0] := -fq[0];
  830. y[1] := -fq[1];
  831. y[2] := -fw;
  832. end;
  833. end;
  834. end;
  835. k_rem_pio2 := n and 7;
  836. end;
  837. { Argument reduction of x: z = x - n*Pi/2, |z| <= Pi/4, result = n mod 8.}
  838. { Uses Payne/Hanek if |x| >= lossth, Cody/Waite otherwise}
  839. function rem_pio2(x: double; out z: double): sizeint;
  840. const
  841. tol: double = 2.384185791015625E-7; {lossth*eps_d}
  842. DP1 = double(7.85398125648498535156E-1);
  843. DP2 = double(3.77489470793079817668E-8);
  844. DP3 = double(2.69515142907905952645E-15);
  845. var
  846. i,e0,nx: longint;
  847. y: double;
  848. tx,ty: TDA02;
  849. begin
  850. y := abs(x);
  851. if (y < PIO4) then
  852. begin
  853. z := x;
  854. result := 0;
  855. exit;
  856. end
  857. else if (y < lossth) then
  858. begin
  859. y := floord(x/PIO4);
  860. i := trunc(y - 16.0*floord(y*0.0625));
  861. if odd(i) then
  862. begin
  863. inc(i);
  864. y := y + 1.0;
  865. end;
  866. z := ((x - y * DP1) - y * DP2) - y * DP3;
  867. result := (i shr 1) and 7;
  868. {If x is near a multiple of Pi/2, the C/W relative error may be large.}
  869. {In this case redo the calculation with the Payne/Hanek algorithm. }
  870. if abs(z) > tol then
  871. exit;
  872. end;
  873. z := abs(x);
  874. e0 := (float64high(z) shr 20)-1046;
  875. if (e0 = ($7ff-1046)) then { z is Inf or NaN }
  876. begin
  877. z := x - x;
  878. result:=0;
  879. exit;
  880. end;
  881. float64sethigh(z,float64high(z) - (e0 shl 20));
  882. tx[0] := trunc(z);
  883. z := (z-tx[0])*two24;
  884. tx[1] := trunc(z);
  885. tx[2] := (z-tx[1])*two24;
  886. nx := 3;
  887. while (tx[nx-1]=0.0) do dec(nx); { skip zero terms }
  888. result := k_rem_pio2(tx,ty,e0,nx,2);
  889. if (x<0) then
  890. begin
  891. result := (-result) and 7;
  892. z := -ty[0] - ty[1];
  893. end
  894. else
  895. z := ty[0] + ty[1];
  896. end;
  897. {$ifndef FPC_SYSTEM_HAS_SQR}
  898. function fpc_sqr_real(d : ValReal) : ValReal;compilerproc;{$ifdef MATHINLINE}inline;{$endif}
  899. begin
  900. result := d*d;
  901. end;
  902. {$endif}
  903. {$ifndef FPC_SYSTEM_HAS_SQRT}
  904. function fpc_sqrt_real(d:ValReal):ValReal;compilerproc;
  905. {*****************************************************************}
  906. { Square root }
  907. {*****************************************************************}
  908. { }
  909. { SYNOPSIS: }
  910. { }
  911. { double x, y, sqrt(); }
  912. { }
  913. { y = sqrt( x ); }
  914. { }
  915. { DESCRIPTION: }
  916. { }
  917. { Returns the square root of x. }
  918. { }
  919. { Range reduction involves isolating the power of two of the }
  920. { argument and using a polynomial approximation to obtain }
  921. { a rough value for the square root. Then Heron's iteration }
  922. { is used three times to converge to an accurate value. }
  923. {*****************************************************************}
  924. var e : Longint;
  925. w,z : Real;
  926. begin
  927. if( d <= 0.0 ) then
  928. begin
  929. if d < 0.0 then
  930. result:=(d-d)/zero
  931. else
  932. result := 0.0;
  933. end
  934. else
  935. begin
  936. w := d;
  937. { separate exponent and significand }
  938. frexp( d, z, e );
  939. { approximate square root of number between 0.5 and 1 }
  940. { relative error of approximation = 7.47e-3 }
  941. d := 4.173075996388649989089E-1 + 5.9016206709064458299663E-1 * z;
  942. { adjust for odd powers of 2 }
  943. if odd(e) then
  944. d := d*SQRT2;
  945. { re-insert exponent }
  946. d := ldexp( d, (e div 2) );
  947. { Newton iterations: }
  948. d := 0.5*(d + w/d);
  949. d := 0.5*(d + w/d);
  950. d := 0.5*(d + w/d);
  951. d := 0.5*(d + w/d);
  952. d := 0.5*(d + w/d);
  953. d := 0.5*(d + w/d);
  954. result := d;
  955. end;
  956. end;
  957. {$endif}
  958. {$ifndef FPC_SYSTEM_HAS_EXP}
  959. {$ifdef SUPPORT_DOUBLE}
  960. {
  961. This code was translated from uclib code, the original code
  962. had the following copyright notice:
  963. *
  964. * ====================================================
  965. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  966. *
  967. * Developed at SunPro, a Sun Microsystems, Inc. business.
  968. * Permission to use, copy, modify, and distribute this
  969. * software is freely granted, provided that this notice
  970. * is preserved.
  971. * ====================================================
  972. *}
  973. {*
  974. * Returns the exponential of x.
  975. *
  976. * Method
  977. * 1. Argument reduction:
  978. * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
  979. * Given x, find r and integer k such that
  980. *
  981. * x = k*ln2 + r, |r| <= 0.5*ln2.
  982. *
  983. * Here r will be represented as r = hi-lo for better
  984. * accuracy.
  985. *
  986. * 2. Approximation of exp(r) by a special rational function on
  987. * the interval [0,0.34658]:
  988. * Write
  989. * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
  990. * We use a special Reme algorithm on [0,0.34658] to generate
  991. * a polynomial of degree 5 to approximate R. The maximum error
  992. * of this polynomial approximation is bounded by 2**-59. In
  993. * other words,
  994. * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
  995. * (where z=r*r, and the values of P1 to P5 are listed below)
  996. * and
  997. * | 5 | -59
  998. * | 2.0+P1*z+...+P5*z - R(z) | <= 2
  999. * | |
  1000. * The computation of exp(r) thus becomes
  1001. * 2*r
  1002. * exp(r) = 1 + -------
  1003. * R - r
  1004. * r*R1(r)
  1005. * = 1 + r + ----------- (for better accuracy)
  1006. * 2 - R1(r)
  1007. * where
  1008. 2 4 10
  1009. * R1(r) = r - (P1*r + P2*r + ... + P5*r ).
  1010. *
  1011. * 3. Scale back to obtain exp(x):
  1012. * From step 1, we have
  1013. * exp(x) = 2^k * exp(r)
  1014. *
  1015. * Special cases:
  1016. * exp(INF) is INF, exp(NaN) is NaN;
  1017. * exp(-INF) is 0, and
  1018. * for finite argument, only exp(0)=1 is exact.
  1019. *
  1020. * Accuracy:
  1021. * according to an error analysis, the error is always less than
  1022. * 1 ulp (unit in the last place).
  1023. *
  1024. * Misc. info.
  1025. * For IEEE double
  1026. * if x > 7.09782712893383973096e+02 then exp(x) overflow
  1027. * if x < -7.45133219101941108420e+02 then exp(x) underflow
  1028. *
  1029. * Constants:
  1030. * The hexadecimal values are the intended ones for the following
  1031. * constants. The decimal values may be used, provided that the
  1032. * compiler will convert from decimal to binary accurately enough
  1033. * to produce the hexadecimal values shown.
  1034. *
  1035. }
  1036. function fpc_exp_real(d: ValReal):ValReal;compilerproc;
  1037. const
  1038. halF : array[0..1] of double = (0.5,-0.5);
  1039. twom1000: double = 9.33263618503218878990e-302; { 2**-1000=0x01700000,0}
  1040. o_threshold: double = 7.09782712893383973096e+02; { 0x40862E42, 0xFEFA39EF }
  1041. u_threshold: double = -7.45133219101941108420e+02; { 0xc0874910, 0xD52D3051 }
  1042. ln2HI : array[0..1] of double = ( 6.93147180369123816490e-01, { 0x3fe62e42, 0xfee00000 }
  1043. -6.93147180369123816490e-01); { 0xbfe62e42, 0xfee00000 }
  1044. ln2LO : array[0..1] of double = (1.90821492927058770002e-10, { 0x3dea39ef, 0x35793c76 }
  1045. -1.90821492927058770002e-10); { 0xbdea39ef, 0x35793c76 }
  1046. invln2: double = 1.44269504088896338700e+00; { 0x3ff71547, 0x652b82fe }
  1047. P1: double = 1.66666666666666019037e-01; { 0x3FC55555, 0x5555553E }
  1048. P2: double = -2.77777777770155933842e-03; { 0xBF66C16C, 0x16BEBD93 }
  1049. P3: double = 6.61375632143793436117e-05; { 0x3F11566A, 0xAF25DE2C }
  1050. P4: double = -1.65339022054652515390e-06; { 0xBEBBBD41, 0xC5D26BF1 }
  1051. P5: double = 4.13813679705723846039e-08; { 0x3E663769, 0x72BEA4D0 }
  1052. var
  1053. c,hi,lo,t,y : double;
  1054. k,xsb : longint;
  1055. hx,hy,lx : dword;
  1056. begin
  1057. hi:=0.0;
  1058. lo:=0.0;
  1059. k:=0;
  1060. hx:=float64high(d);
  1061. xsb := (hx shr 31) and 1; { sign bit of d }
  1062. hx := hx and $7fffffff; { high word of |d| }
  1063. { filter out non-finite argument }
  1064. if hx >= $40862E42 then
  1065. begin { if |d|>=709.78... }
  1066. if hx >= $7ff00000 then
  1067. begin
  1068. lx:=float64low(d);
  1069. if ((hx and $fffff) or lx)<>0 then
  1070. begin
  1071. result:=d+d; { NaN }
  1072. exit;
  1073. end
  1074. else
  1075. begin
  1076. if xsb=0 then
  1077. result:=d
  1078. else
  1079. result:=0.0; { exp(+-inf)=(inf,0) }
  1080. exit;
  1081. end;
  1082. end;
  1083. if d > o_threshold then begin
  1084. result:=huge*huge; { overflow }
  1085. exit;
  1086. end;
  1087. if d < u_threshold then begin
  1088. result:=twom1000*twom1000; { underflow }
  1089. exit;
  1090. end;
  1091. end;
  1092. { argument reduction }
  1093. if hx > $3fd62e42 then
  1094. begin { if |d| > 0.5 ln2 }
  1095. if hx < $3FF0A2B2 then { and |d| < 1.5 ln2 }
  1096. begin
  1097. hi := d-ln2HI[xsb];
  1098. lo:=ln2LO[xsb];
  1099. k := 1-xsb-xsb;
  1100. end
  1101. else
  1102. begin
  1103. k := trunc(invln2*d+halF[xsb]);
  1104. t := k;
  1105. hi := d - t*ln2HI[0]; { t*ln2HI is exact here }
  1106. lo := t*ln2LO[0];
  1107. end;
  1108. d := hi - lo;
  1109. end
  1110. else if hx < $3e300000 then
  1111. begin { when |d|<2**-28 }
  1112. if huge+d>one then
  1113. begin
  1114. result:=one+d;{ trigger inexact }
  1115. exit;
  1116. end;
  1117. end
  1118. else
  1119. k := 0;
  1120. { d is now in primary range }
  1121. t:=d*d;
  1122. c:=d - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
  1123. if k=0 then
  1124. begin
  1125. result:=one-((d*c)/(c-2.0)-d);
  1126. exit;
  1127. end
  1128. else
  1129. y := one-((lo-(d*c)/(2.0-c))-hi);
  1130. if k >= -1021 then
  1131. begin
  1132. hy:=float64high(y);
  1133. float64sethigh(y,longint(hy)+(k shl 20)); { add k to y's exponent }
  1134. result:=y;
  1135. end
  1136. else
  1137. begin
  1138. hy:=float64high(y);
  1139. float64sethigh(y,longint(hy)+((k+1000) shl 20)); { add k to y's exponent }
  1140. result:=y*twom1000;
  1141. end;
  1142. end;
  1143. {$else SUPPORT_DOUBLE}
  1144. function fpc_exp_real(d: ValReal):ValReal;compilerproc;
  1145. {*****************************************************************}
  1146. { Exponential Function }
  1147. {*****************************************************************}
  1148. { }
  1149. { SYNOPSIS: }
  1150. { }
  1151. { double x, y, exp(); }
  1152. { }
  1153. { y = exp( x ); }
  1154. { }
  1155. { DESCRIPTION: }
  1156. { }
  1157. { Returns e (2.71828...) raised to the x power. }
  1158. { }
  1159. { Range reduction is accomplished by separating the argument }
  1160. { into an integer k and fraction f such that }
  1161. { }
  1162. { x k f }
  1163. { e = 2 e. }
  1164. { }
  1165. { A Pade' form of degree 2/3 is used to approximate exp(f)- 1 }
  1166. { in the basic range [-0.5 ln 2, 0.5 ln 2]. }
  1167. {*****************************************************************}
  1168. const P : array[0..2] of Real = (
  1169. 1.26183092834458542160E-4,
  1170. 3.02996887658430129200E-2,
  1171. 1.00000000000000000000E0);
  1172. Q : array[0..3] of Real = (
  1173. 3.00227947279887615146E-6,
  1174. 2.52453653553222894311E-3,
  1175. 2.27266044198352679519E-1,
  1176. 2.00000000000000000005E0);
  1177. C1 = 6.9335937500000000000E-1;
  1178. C2 = 2.1219444005469058277E-4;
  1179. var n : Integer;
  1180. px, qx, xx : Real;
  1181. begin
  1182. if( d > MAXLOG) then
  1183. float_raise(float_flag_overflow)
  1184. else
  1185. if( d < MINLOG ) then
  1186. begin
  1187. float_raise(float_flag_underflow);
  1188. result:=0; { Result if underflow masked }
  1189. end
  1190. else
  1191. begin
  1192. { Express e**x = e**g 2**n }
  1193. { = e**g e**( n loge(2) ) }
  1194. { = e**( g + n loge(2) ) }
  1195. px := d * LOG2E;
  1196. qx := Trunc( px + 0.5 ); { Trunc() truncates toward -infinity. }
  1197. n := Trunc(qx);
  1198. d := d - qx * C1;
  1199. d := d + qx * C2;
  1200. { rational approximation for exponential }
  1201. { of the fractional part: }
  1202. { e**x - 1 = 2x P(x**2)/( Q(x**2) - P(x**2) ) }
  1203. xx := d * d;
  1204. px := d * polevl( xx, P, 2 );
  1205. d := px/( polevl( xx, Q, 3 ) - px );
  1206. d := ldexp( d, 1 );
  1207. d := d + 1.0;
  1208. d := ldexp( d, n );
  1209. result := d;
  1210. end;
  1211. end;
  1212. {$endif SUPPORT_DOUBLE}
  1213. {$endif}
  1214. {$ifndef FPC_SYSTEM_HAS_ROUND}
  1215. function fpc_round_real(d : ValReal) : int64;compilerproc;
  1216. var
  1217. tmp: double;
  1218. j0: longint;
  1219. hx: longword;
  1220. sx: longint;
  1221. const
  1222. H2_52: array[0..1] of double = (
  1223. 4.50359962737049600000e+15,
  1224. -4.50359962737049600000e+15
  1225. );
  1226. Begin
  1227. { This basically calculates trunc((d+2**52)-2**52) }
  1228. hx:=float64high(d);
  1229. j0:=((hx shr 20) and $7ff) - $3ff;
  1230. sx:=hx shr 31;
  1231. hx:=(hx and $fffff) or $100000;
  1232. if j0>=52 then { No fraction bits, already integer }
  1233. begin
  1234. if j0>=63 then { Overflow, let trunc() raise an exception }
  1235. exit(trunc(d)) { and/or return +/-MaxInt64 if it's masked }
  1236. else
  1237. result:=((int64(hx) shl 32) or float64low(d)) shl (j0-52);
  1238. end
  1239. else
  1240. begin
  1241. { Rounding happens here. It is important that the expression is not
  1242. optimized by selecting a larger type to store 'tmp'. }
  1243. tmp:=H2_52[sx]+d;
  1244. d:=tmp-H2_52[sx];
  1245. hx:=float64high(d);
  1246. j0:=((hx shr 20) and $7ff)-$3ff;
  1247. hx:=(hx and $fffff) or $100000;
  1248. if j0<=20 then
  1249. begin
  1250. if j0<0 then
  1251. exit(0)
  1252. else { more than 32 fraction bits, low dword discarded }
  1253. result:=hx shr (20-j0);
  1254. end
  1255. else
  1256. result:=(int64(hx) shl (j0-20)) or (float64low(d) shr (52-j0));
  1257. end;
  1258. if sx<>0 then
  1259. result:=-result;
  1260. end;
  1261. {$endif FPC_SYSTEM_HAS_ROUND}
  1262. {$ifndef FPC_SYSTEM_HAS_LN}
  1263. function fpc_ln_real(d:ValReal):ValReal;compilerproc;
  1264. {
  1265. This code was translated from uclib code, the original code
  1266. had the following copyright notice:
  1267. *
  1268. * ====================================================
  1269. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  1270. *
  1271. * Developed at SunPro, a Sun Microsystems, Inc. business.
  1272. * Permission to use, copy, modify, and distribute this
  1273. * software is freely granted, provided that this notice
  1274. * is preserved.
  1275. * ====================================================
  1276. *}
  1277. {*****************************************************************}
  1278. { Natural Logarithm }
  1279. {*****************************************************************}
  1280. {*
  1281. * SYNOPSIS:
  1282. *
  1283. * double x, y, log();
  1284. *
  1285. * y = ln( x );
  1286. *
  1287. * DESCRIPTION:
  1288. *
  1289. * Returns the base e (2.718...) logarithm of x.
  1290. *
  1291. * Method :
  1292. * 1. Argument Reduction: find k and f such that
  1293. * x = 2^k * (1+f),
  1294. * where sqrt(2)/2 < 1+f < sqrt(2) .
  1295. *
  1296. * 2. Approximation of log(1+f).
  1297. * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
  1298. * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
  1299. * = 2s + s*R
  1300. * We use a special Reme algorithm on [0,0.1716] to generate
  1301. * a polynomial of degree 14 to approximate R The maximum error
  1302. * of this polynomial approximation is bounded by 2**-58.45. In
  1303. * other words,
  1304. * 2 4 6 8 10 12 14
  1305. * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
  1306. * (the values of Lg1 to Lg7 are listed in the program)
  1307. * and
  1308. * | 2 14 | -58.45
  1309. * | Lg1*s +...+Lg7*s - R(z) | <= 2
  1310. * | |
  1311. * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
  1312. * In order to guarantee error in log below 1ulp, we compute log
  1313. * by
  1314. * log(1+f) = f - s*(f - R) (if f is not too large)
  1315. * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
  1316. *
  1317. * 3. Finally, log(x) = k*ln2 + log(1+f).
  1318. * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
  1319. * Here ln2 is split into two floating point number:
  1320. * ln2_hi + ln2_lo,
  1321. * where n*ln2_hi is always exact for |n| < 2000.
  1322. *
  1323. * Special cases:
  1324. * log(x) is NaN with signal if x < 0 (including -INF) ;
  1325. * log(+INF) is +INF; log(0) is -INF with signal;
  1326. * log(NaN) is that NaN with no signal.
  1327. *
  1328. * Accuracy:
  1329. * according to an error analysis, the error is always less than
  1330. * 1 ulp (unit in the last place).
  1331. *}
  1332. const
  1333. ln2_hi: double = 6.93147180369123816490e-01; { 3fe62e42 fee00000 }
  1334. ln2_lo: double = 1.90821492927058770002e-10; { 3dea39ef 35793c76 }
  1335. two54: double = 1.80143985094819840000e+16; { 43500000 00000000 }
  1336. Lg1: double = 6.666666666666735130e-01; { 3FE55555 55555593 }
  1337. Lg2: double = 3.999999999940941908e-01; { 3FD99999 9997FA04 }
  1338. Lg3: double = 2.857142874366239149e-01; { 3FD24924 94229359 }
  1339. Lg4: double = 2.222219843214978396e-01; { 3FCC71C5 1D8E78AF }
  1340. Lg5: double = 1.818357216161805012e-01; { 3FC74664 96CB03DE }
  1341. Lg6: double = 1.531383769920937332e-01; { 3FC39A09 D078C69F }
  1342. Lg7: double = 1.479819860511658591e-01; { 3FC2F112 DF3E5244 }
  1343. zero: double = 0.0;
  1344. var
  1345. hfsq,f,s,z,R,w,t1,t2,dk: double;
  1346. k,hx,i,j: longint;
  1347. lx: longword;
  1348. begin
  1349. hx := float64high(d);
  1350. lx := float64low(d);
  1351. k := 0;
  1352. if (hx < $00100000) then { x < 2**-1022 }
  1353. begin
  1354. if (((hx and $7fffffff) or longint(lx))=0) then
  1355. exit(-two54/zero); { log(+-0)=-inf }
  1356. if (hx<0) then
  1357. exit((d-d)/zero); { log(-#) = NaN }
  1358. dec(k, 54); d := d * two54; { subnormal number, scale up x }
  1359. hx := float64high(d);
  1360. end;
  1361. if (hx >= $7ff00000) then
  1362. exit(d+d);
  1363. inc(k, (hx shr 20)-1023);
  1364. hx := hx and $000fffff;
  1365. i := (hx + $95f64) and $100000;
  1366. float64sethigh(d,hx or (i xor $3ff00000)); { normalize x or x/2 }
  1367. inc(k, (i shr 20));
  1368. f := d-1.0;
  1369. if (($000fffff and (2+hx))<3) then { |f| < 2**-20 }
  1370. begin
  1371. if (f=zero) then
  1372. begin
  1373. if (k=0) then
  1374. exit(zero)
  1375. else
  1376. begin
  1377. dk := k;
  1378. exit(dk*ln2_hi+dk*ln2_lo);
  1379. end;
  1380. end;
  1381. R := f*f*(0.5-0.33333333333333333*f);
  1382. if (k=0) then
  1383. exit(f-R)
  1384. else
  1385. begin
  1386. dk := k;
  1387. exit(dk*ln2_hi-((R-dk*ln2_lo)-f));
  1388. end;
  1389. end;
  1390. s := f/(2.0+f);
  1391. dk := k;
  1392. z := s*s;
  1393. i := hx-$6147a;
  1394. w := z*z;
  1395. j := $6b851-hx;
  1396. t1 := w*(Lg2+w*(Lg4+w*Lg6));
  1397. t2 := z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
  1398. i := i or j;
  1399. R := t2+t1;
  1400. if (i>0) then
  1401. begin
  1402. hfsq := 0.5*f*f;
  1403. if (k=0) then
  1404. result := f-(hfsq-s*(hfsq+R))
  1405. else
  1406. result := dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
  1407. end
  1408. else
  1409. begin
  1410. if (k=0) then
  1411. result := f-s*(f-R)
  1412. else
  1413. result := dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
  1414. end;
  1415. end;
  1416. {$endif}
  1417. {$ifndef FPC_SYSTEM_HAS_SIN}
  1418. function fpc_Sin_real(d:ValReal):ValReal;compilerproc;
  1419. {*****************************************************************}
  1420. { Circular Sine }
  1421. {*****************************************************************}
  1422. { }
  1423. { SYNOPSIS: }
  1424. { }
  1425. { double x, y, sin(); }
  1426. { }
  1427. { y = sin( x ); }
  1428. { }
  1429. { DESCRIPTION: }
  1430. { }
  1431. { Range reduction is into intervals of pi/4. The reduction }
  1432. { error is nearly eliminated by contriving an extended }
  1433. { precision modular arithmetic. }
  1434. { }
  1435. { Two polynomial approximating functions are employed. }
  1436. { Between 0 and pi/4 the sine is approximated by }
  1437. { x + x**3 P(x**2). }
  1438. { Between pi/4 and pi/2 the cosine is represented as }
  1439. { 1 - x**2 Q(x**2). }
  1440. {*****************************************************************}
  1441. var y, z, zz : Real;
  1442. j : sizeint;
  1443. begin
  1444. { This seemingly useless condition ensures that sin(-0.0)=-0.0 }
  1445. if (d=0.0) then
  1446. exit(d);
  1447. j := rem_pio2(d,z) and 3;
  1448. zz := z * z;
  1449. if( (j=1) or (j=3) ) then
  1450. y := 1.0 - ldexp(zz,-1) + zz * zz * polevl( zz, coscof, 5 )
  1451. else
  1452. { y = z + z * (zz * polevl( zz, sincof, 5 )); }
  1453. y := z + z * z * z * polevl( zz, sincof, 5 );
  1454. if (j > 1) then
  1455. result := -y
  1456. else
  1457. result := y;
  1458. end;
  1459. {$endif}
  1460. {$ifndef FPC_SYSTEM_HAS_COS}
  1461. function fpc_Cos_real(d:ValReal):ValReal;compilerproc;
  1462. {*****************************************************************}
  1463. { Circular cosine }
  1464. {*****************************************************************}
  1465. { }
  1466. { Circular cosine }
  1467. { }
  1468. { SYNOPSIS: }
  1469. { }
  1470. { double x, y, cos(); }
  1471. { }
  1472. { y = cos( x ); }
  1473. { }
  1474. { DESCRIPTION: }
  1475. { }
  1476. { Range reduction is into intervals of pi/4. The reduction }
  1477. { error is nearly eliminated by contriving an extended }
  1478. { precision modular arithmetic. }
  1479. { }
  1480. { Two polynomial approximating functions are employed. }
  1481. { Between 0 and pi/4 the cosine is approximated by }
  1482. { 1 - x**2 Q(x**2). }
  1483. { Between pi/4 and pi/2 the sine is represented as }
  1484. { x + x**3 P(x**2). }
  1485. {*****************************************************************}
  1486. var y, z, zz : Real;
  1487. j : sizeint;
  1488. begin
  1489. j := rem_pio2(d,z) and 3;
  1490. zz := z * z;
  1491. if( (j=1) or (j=3) ) then
  1492. { y = z + z * (zz * polevl( zz, sincof, 5 )); }
  1493. y := z + z * z * z * polevl( zz, sincof, 5 )
  1494. else
  1495. y := 1.0 - ldexp(zz,-1) + zz * zz * polevl( zz, coscof, 5 );
  1496. if (j = 1) or (j = 2) then
  1497. result := -y
  1498. else
  1499. result := y ;
  1500. end;
  1501. {$endif}
  1502. {$ifndef FPC_SYSTEM_HAS_ARCTAN}
  1503. function fpc_ArcTan_real(d:ValReal):ValReal;compilerproc;
  1504. {
  1505. This code was translated from uclibc code, the original code
  1506. had the following copyright notice:
  1507. *
  1508. * ====================================================
  1509. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  1510. *
  1511. * Developed at SunPro, a Sun Microsystems, Inc. business.
  1512. * Permission to use, copy, modify, and distribute this
  1513. * software is freely granted, provided that this notice
  1514. * is preserved.
  1515. * ====================================================
  1516. *}
  1517. {********************************************************************}
  1518. { Inverse circular tangent (arctangent) }
  1519. {********************************************************************}
  1520. { }
  1521. { SYNOPSIS: }
  1522. { }
  1523. { double x, y, atan(); }
  1524. { }
  1525. { y = atan( x ); }
  1526. { }
  1527. { DESCRIPTION: }
  1528. { }
  1529. { Returns radian angle between -pi/2 and +pi/2 whose tangent }
  1530. { is x. }
  1531. { }
  1532. { Method }
  1533. { 1. Reduce x to positive by atan(x) = -atan(-x). }
  1534. { 2. According to the integer k=4t+0.25 chopped, t=x, the argument }
  1535. { is further reduced to one of the following intervals and the }
  1536. { arctangent of t is evaluated by the corresponding formula: }
  1537. { }
  1538. { [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) }
  1539. { [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) }
  1540. { [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) }
  1541. { [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) }
  1542. { [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) }
  1543. {********************************************************************}
  1544. const
  1545. atanhi: array [0..3] of double = (
  1546. 4.63647609000806093515e-01, { atan(0.5)hi 0x3FDDAC67, 0x0561BB4F }
  1547. 7.85398163397448278999e-01, { atan(1.0)hi 0x3FE921FB, 0x54442D18 }
  1548. 9.82793723247329054082e-01, { atan(1.5)hi 0x3FEF730B, 0xD281F69B }
  1549. 1.57079632679489655800e+00 { atan(inf)hi 0x3FF921FB, 0x54442D18 }
  1550. );
  1551. atanlo: array [0..3] of double = (
  1552. 2.26987774529616870924e-17, { atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 }
  1553. 3.06161699786838301793e-17, { atan(1.0)lo 0x3C81A626, 0x33145C07 }
  1554. 1.39033110312309984516e-17, { atan(1.5)lo 0x3C700788, 0x7AF0CBBD }
  1555. 6.12323399573676603587e-17 { atan(inf)lo 0x3C91A626, 0x33145C07 }
  1556. );
  1557. aT: array[0..10] of double = (
  1558. 3.33333333333329318027e-01, { 0x3FD55555, 0x5555550D }
  1559. -1.99999999998764832476e-01, { 0xBFC99999, 0x9998EBC4 }
  1560. 1.42857142725034663711e-01, { 0x3FC24924, 0x920083FF }
  1561. -1.11111104054623557880e-01, { 0xBFBC71C6, 0xFE231671 }
  1562. 9.09088713343650656196e-02, { 0x3FB745CD, 0xC54C206E }
  1563. -7.69187620504482999495e-02, { 0xBFB3B0F2, 0xAF749A6D }
  1564. 6.66107313738753120669e-02, { 0x3FB10D66, 0xA0D03D51 }
  1565. -5.83357013379057348645e-02, { 0xBFADDE2D, 0x52DEFD9A }
  1566. 4.97687799461593236017e-02, { 0x3FA97B4B, 0x24760DEB }
  1567. -3.65315727442169155270e-02, { 0xBFA2B444, 0x2C6A6C2F }
  1568. 1.62858201153657823623e-02 { 0x3F90AD3A, 0xE322DA11 }
  1569. );
  1570. var
  1571. w,s1,s2,z: double;
  1572. ix,hx,id: longint;
  1573. low: longword;
  1574. begin
  1575. hx:=float64high(d);
  1576. ix := hx and $7fffffff;
  1577. if (ix>=$44100000) then { if |x| >= 2^66 }
  1578. begin
  1579. low:=float64low(d);
  1580. if (ix > $7ff00000) or ((ix = $7ff00000) and (low<>0)) then
  1581. exit(d+d); { NaN }
  1582. if (hx>0) then
  1583. exit(atanhi[3]+atanlo[3])
  1584. else
  1585. exit(-atanhi[3]-atanlo[3]);
  1586. end;
  1587. if (ix < $3fdc0000) then { |x| < 0.4375 }
  1588. begin
  1589. if (ix < $3e200000) then { |x| < 2^-29 }
  1590. begin
  1591. if (huge+d>one) then exit(d); { raise inexact }
  1592. end;
  1593. id := -1;
  1594. end
  1595. else
  1596. begin
  1597. d := abs(d);
  1598. if (ix < $3ff30000) then { |x| < 1.1875 }
  1599. begin
  1600. if (ix < $3fe60000) then { 7/16 <=|x|<11/16 }
  1601. begin
  1602. id := 0; d := (2.0*d-one)/(2.0+d);
  1603. end
  1604. else { 11/16<=|x|< 19/16 }
  1605. begin
  1606. id := 1; d := (d-one)/(d+one);
  1607. end
  1608. end
  1609. else
  1610. begin
  1611. if (ix < $40038000) then { |x| < 2.4375 }
  1612. begin
  1613. id := 2; d := (d-1.5)/(one+1.5*d);
  1614. end
  1615. else { 2.4375 <= |x| < 2^66 }
  1616. begin
  1617. id := 3; d := -1.0/d;
  1618. end;
  1619. end;
  1620. end;
  1621. { end of argument reduction }
  1622. z := d*d;
  1623. w := z*z;
  1624. { break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly }
  1625. s1 := z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
  1626. s2 := w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
  1627. if (id<0) then
  1628. result := d - d*(s1+s2)
  1629. else
  1630. begin
  1631. z := atanhi[id] - ((d*(s1+s2) - atanlo[id]) - d);
  1632. if hx<0 then
  1633. result := -z
  1634. else
  1635. result := z;
  1636. end;
  1637. end;
  1638. {$endif}
  1639. {$ifndef FPC_SYSTEM_HAS_FRAC}
  1640. function fpc_frac_real(d : ValReal) : ValReal;compilerproc;
  1641. begin
  1642. result := d - Int(d);
  1643. end;
  1644. {$endif}
  1645. {$ifdef FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
  1646. {$ifndef FPC_SYSTEM_HAS_QWORD_TO_DOUBLE}
  1647. function fpc_qword_to_double(q : qword): double; compilerproc;
  1648. begin
  1649. result:=dword(q and $ffffffff)+dword(q shr 32)*double(4294967296.0);
  1650. end;
  1651. {$endif FPC_SYSTEM_HAS_INT64_TO_DOUBLE}
  1652. {$ifndef FPC_SYSTEM_HAS_INT64_TO_DOUBLE}
  1653. function fpc_int64_to_double(i : int64): double; compilerproc;
  1654. begin
  1655. result:=dword(i and $ffffffff)+longint(i shr 32)*double(4294967296.0);
  1656. end;
  1657. {$endif FPC_SYSTEM_HAS_INT64_TO_DOUBLE}
  1658. {$endif FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
  1659. {$ifdef SUPPORT_DOUBLE}
  1660. {****************************************************************************
  1661. Helper routines to support old TP styled reals
  1662. ****************************************************************************}
  1663. {$ifndef FPC_SYSTEM_HAS_REAL2DOUBLE}
  1664. function real2double(r : real48) : double;
  1665. var
  1666. res : array[0..7] of byte;
  1667. exponent : word;
  1668. begin
  1669. { check for zero }
  1670. if r[0]=0 then
  1671. begin
  1672. real2double:=0.0;
  1673. exit;
  1674. end;
  1675. { copy mantissa }
  1676. res[0]:=0;
  1677. res[1]:=r[1] shl 5;
  1678. res[2]:=(r[1] shr 3) or (r[2] shl 5);
  1679. res[3]:=(r[2] shr 3) or (r[3] shl 5);
  1680. res[4]:=(r[3] shr 3) or (r[4] shl 5);
  1681. res[5]:=(r[4] shr 3) or (r[5] and $7f) shl 5;
  1682. res[6]:=(r[5] and $7f) shr 3;
  1683. { copy exponent }
  1684. { correct exponent: }
  1685. exponent:=(word(r[0])+(1023-129));
  1686. res[6]:=res[6] or ((exponent and $f) shl 4);
  1687. res[7]:=exponent shr 4;
  1688. { set sign }
  1689. res[7]:=res[7] or (r[5] and $80);
  1690. real2double:=double(res);
  1691. end;
  1692. {$endif FPC_SYSTEM_HAS_REAL2DOUBLE}
  1693. {$endif SUPPORT_DOUBLE}
  1694. {$ifdef SUPPORT_EXTENDED}
  1695. { fast 10^n routine }
  1696. function FPower10(val: Extended; Power: Longint): Extended;
  1697. const
  1698. pow32 : array[0..31] of extended =
  1699. (
  1700. 1e0,1e1,1e2,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,
  1701. 1e11,1e12,1e13,1e14,1e15,1e16,1e17,1e18,1e19,1e20,
  1702. 1e21,1e22,1e23,1e24,1e25,1e26,1e27,1e28,1e29,1e30,
  1703. 1e31
  1704. );
  1705. pow512 : array[0..15] of extended =
  1706. (
  1707. 1,1e32,1e64,1e96,1e128,1e160,1e192,1e224,
  1708. 1e256,1e288,1e320,1e352,1e384,1e416,1e448,
  1709. 1e480
  1710. );
  1711. pow4096 : array[0..9] of extended =
  1712. (1,1e512,1e1024,1e1536,
  1713. 1e2048,1e2560,1e3072,1e3584,
  1714. 1e4096,1e4608
  1715. );
  1716. negpow32 : array[0..31] of extended =
  1717. (
  1718. 1e-0,1e-1,1e-2,1e-3,1e-4,1e-5,1e-6,1e-7,1e-8,1e-9,1e-10,
  1719. 1e-11,1e-12,1e-13,1e-14,1e-15,1e-16,1e-17,1e-18,1e-19,1e-20,
  1720. 1e-21,1e-22,1e-23,1e-24,1e-25,1e-26,1e-27,1e-28,1e-29,1e-30,
  1721. 1e-31
  1722. );
  1723. negpow512 : array[0..15] of extended =
  1724. (
  1725. 0,1e-32,1e-64,1e-96,1e-128,1e-160,1e-192,1e-224,
  1726. 1e-256,1e-288,1e-320,1e-352,1e-384,1e-416,1e-448,
  1727. 1e-480
  1728. );
  1729. negpow4096 : array[0..9] of extended =
  1730. (
  1731. 0,1e-512,1e-1024,1e-1536,
  1732. 1e-2048,1e-2560,1e-3072,1e-3584,
  1733. 1e-4096,1e-4608
  1734. );
  1735. begin
  1736. if Power<0 then
  1737. begin
  1738. Power:=-Power;
  1739. result:=val*negpow32[Power and $1f];
  1740. power:=power shr 5;
  1741. if power<>0 then
  1742. begin
  1743. result:=result*negpow512[Power and $f];
  1744. power:=power shr 4;
  1745. if power<>0 then
  1746. begin
  1747. if power<=9 then
  1748. result:=result*negpow4096[Power]
  1749. else
  1750. result:=1.0/0.0;
  1751. end;
  1752. end;
  1753. end
  1754. else
  1755. begin
  1756. result:=val*pow32[Power and $1f];
  1757. power:=power shr 5;
  1758. if power<>0 then
  1759. begin
  1760. result:=result*pow512[Power and $f];
  1761. power:=power shr 4;
  1762. if power<>0 then
  1763. begin
  1764. if power<=9 then
  1765. result:=result*pow4096[Power]
  1766. else
  1767. result:=1.0/0.0;
  1768. end;
  1769. end;
  1770. end;
  1771. end;
  1772. {$endif SUPPORT_EXTENDED}
  1773. {$if defined(SUPPORT_EXTENDED) or defined(FPC_SOFT_FPUX80)}
  1774. function TExtended80Rec.Mantissa(IncludeHiddenBit: Boolean = False) : QWord;
  1775. begin
  1776. if IncludeHiddenbit then
  1777. Result:=Frac
  1778. else
  1779. Result:=Frac and $7fffffffffffffff;
  1780. end;
  1781. function TExtended80Rec.Fraction : Extended;
  1782. begin
  1783. {$ifdef SUPPORT_EXTENDED}
  1784. Result:=system.frac(Value);
  1785. {$else}
  1786. Result:=Frac / Double (1 shl 63) / 2.0;
  1787. {$endif}
  1788. end;
  1789. function TExtended80Rec.Exponent : Longint;
  1790. var
  1791. E: QWord;
  1792. begin
  1793. Result := 0;
  1794. E := GetExp;
  1795. if (0<E) and (E<2*Bias+1) then
  1796. Result:=Exp-Bias
  1797. else if (Exp=0) and (Frac<>0) then
  1798. Result:=-(Bias-1);
  1799. end;
  1800. function TExtended80Rec.GetExp : QWord;
  1801. begin
  1802. Result:=_Exp and $7fff;
  1803. end;
  1804. procedure TExtended80Rec.SetExp(e : QWord);
  1805. begin
  1806. _Exp:=(_Exp and $8000) or (e and $7fff);
  1807. end;
  1808. function TExtended80Rec.GetSign : Boolean;
  1809. begin
  1810. Result:=(_Exp and $8000)<>0;
  1811. end;
  1812. procedure TExtended80Rec.SetSign(s : Boolean);
  1813. begin
  1814. _Exp:=(_Exp and $7ffff) or (ord(s) shl 15);
  1815. end;
  1816. {
  1817. Based on information taken from http://en.wikipedia.org/wiki/Extended_precision#x86_Extended_Precision_Format
  1818. }
  1819. function TExtended80Rec.SpecialType : TFloatSpecial;
  1820. const
  1821. Denormal : array[boolean] of TFloatSpecial = (fsDenormal,fsNDenormal);
  1822. begin
  1823. case Exp of
  1824. 0:
  1825. begin
  1826. if Mantissa=0 then
  1827. begin
  1828. if Sign then
  1829. Result:=fsNZero
  1830. else
  1831. Result:=fsZero
  1832. end
  1833. else
  1834. Result:=Denormal[Sign];
  1835. end;
  1836. $7fff:
  1837. case (Frac shr 62) and 3 of
  1838. 0,1:
  1839. Result:=fsInvalidOp;
  1840. 2:
  1841. begin
  1842. if (Frac and $3fffffffffffffff)=0 then
  1843. begin
  1844. if Sign then
  1845. Result:=fsNInf
  1846. else
  1847. Result:=fsInf;
  1848. end
  1849. else
  1850. Result:=fsNaN;
  1851. end;
  1852. 3:
  1853. Result:=fsNaN;
  1854. end
  1855. else
  1856. begin
  1857. if (Frac and $8000000000000000)=0 then
  1858. Result:=fsInvalidOp
  1859. else
  1860. begin
  1861. if Sign then
  1862. Result:=fsNegative
  1863. else
  1864. Result:=fsPositive;
  1865. end;
  1866. end;
  1867. end;
  1868. end;
  1869. procedure TExtended80Rec.BuildUp(const _Sign: Boolean; const _Mantissa: QWord; const _Exponent: Longint);
  1870. begin
  1871. {$ifdef SUPPORT_EXTENDED}
  1872. Value := 0.0;
  1873. {$else SUPPORT_EXTENDED}
  1874. FillChar(Value, SizeOf(Value),0);
  1875. {$endif SUPPORT_EXTENDED}
  1876. if (_Mantissa=0) and (_Exponent=0) then
  1877. SetExp(0)
  1878. else
  1879. SetExp(_Exponent + Bias);
  1880. SetSign(_Sign);
  1881. Frac := _Mantissa;
  1882. end;
  1883. {$endif SUPPORT_EXTENDED or FPC_SOFT_FPUX80}
  1884. {$ifdef SUPPORT_DOUBLE}
  1885. function TDoubleRec.Mantissa(IncludeHiddenBit: Boolean = False) : QWord;
  1886. begin
  1887. Result:=(Data and $fffffffffffff);
  1888. if (Result=0) and (GetExp=0) then Exit;
  1889. if IncludeHiddenBit then Result := Result or $10000000000000; //add the hidden bit
  1890. end;
  1891. function TDoubleRec.Fraction : ValReal;
  1892. begin
  1893. Result:=system.frac(Value);
  1894. end;
  1895. function TDoubleRec.Exponent : Longint;
  1896. var
  1897. E: QWord;
  1898. begin
  1899. Result := 0;
  1900. E := GetExp;
  1901. if (0<E) and (E<2*Bias+1) then
  1902. Result:=Exp-Bias
  1903. else if (Exp=0) and (Frac<>0) then
  1904. Result:=-(Bias-1);
  1905. end;
  1906. function TDoubleRec.GetExp : QWord;
  1907. begin
  1908. Result:=(Data and $7ff0000000000000) shr 52;
  1909. end;
  1910. procedure TDoubleRec.SetExp(e : QWord);
  1911. begin
  1912. Data:=(Data and $800fffffffffffff) or ((e and $7ff) shl 52);
  1913. end;
  1914. function TDoubleRec.GetSign : Boolean;
  1915. begin
  1916. Result:=(Data and $8000000000000000)<>0;
  1917. end;
  1918. procedure TDoubleRec.SetSign(s : Boolean);
  1919. begin
  1920. Data:=(Data and $7fffffffffffffff) or (QWord(ord(s)) shl 63);
  1921. end;
  1922. function TDoubleRec.GetFrac : QWord;
  1923. begin
  1924. Result := Data and $fffffffffffff;
  1925. end;
  1926. procedure TDoubleRec.SetFrac(e : QWord);
  1927. begin
  1928. Data:=(Data and $7ff0000000000000) or (e and $fffffffffffff);
  1929. end;
  1930. {
  1931. Based on information taken from http://en.wikipedia.org/wiki/Double_precision#x86_Extended_Precision_Format
  1932. }
  1933. function TDoubleRec.SpecialType : TFloatSpecial;
  1934. const
  1935. Denormal : array[boolean] of TFloatSpecial = (fsDenormal,fsNDenormal);
  1936. begin
  1937. case Exp of
  1938. 0:
  1939. begin
  1940. if Mantissa=0 then
  1941. begin
  1942. if Sign then
  1943. Result:=fsNZero
  1944. else
  1945. Result:=fsZero
  1946. end
  1947. else
  1948. Result:=Denormal[Sign];
  1949. end;
  1950. $7ff:
  1951. if Mantissa=0 then
  1952. begin
  1953. if Sign then
  1954. Result:=fsNInf
  1955. else
  1956. Result:=fsInf;
  1957. end
  1958. else
  1959. Result:=fsNaN;
  1960. else
  1961. begin
  1962. if Sign then
  1963. Result:=fsNegative
  1964. else
  1965. Result:=fsPositive;
  1966. end;
  1967. end;
  1968. end;
  1969. procedure TDoubleRec.BuildUp(const _Sign: Boolean; const _Mantissa: QWord; const _Exponent: Longint);
  1970. begin
  1971. Value := 0.0;
  1972. SetSign(_Sign);
  1973. if (_Mantissa=0) and (_Exponent=0) then
  1974. Exit //SetExp(0)
  1975. else
  1976. SetExp(_Exponent + Bias);
  1977. SetFrac(_Mantissa and $fffffffffffff); //clear top bit
  1978. end;
  1979. {$endif SUPPORT_DOUBLE}
  1980. {$ifdef SUPPORT_SINGLE}
  1981. function TSingleRec.Mantissa(IncludeHiddenBit: Boolean = False) : QWord;
  1982. begin
  1983. Result:=(Data and $7fffff);
  1984. if (Result=0) and (GetExp=0) then Exit;
  1985. if IncludeHiddenBit then Result:=Result or $800000; //add the hidden bit
  1986. end;
  1987. function TSingleRec.Fraction : ValReal;
  1988. begin
  1989. Result:=system.frac(Value);
  1990. end;
  1991. function TSingleRec.Exponent : Longint;
  1992. var
  1993. E: QWord;
  1994. begin
  1995. Result := 0;
  1996. E := GetExp;
  1997. if (0<E) and (E<2*Bias+1) then
  1998. Result:=Exp-Bias
  1999. else if (Exp=0) and (Frac<>0) then
  2000. Result:=-(Bias-1);
  2001. end;
  2002. function TSingleRec.GetExp : QWord;
  2003. begin
  2004. Result:=(Data and $7f800000) shr 23;
  2005. end;
  2006. procedure TSingleRec.SetExp(e : QWord);
  2007. begin
  2008. Data:=(Data and $807fffff) or ((e and $ff) shl 23);
  2009. end;
  2010. function TSingleRec.GetSign : Boolean;
  2011. begin
  2012. Result:=(Data and $80000000)<>0;
  2013. end;
  2014. procedure TSingleRec.SetSign(s : Boolean);
  2015. begin
  2016. Data:=(Data and $7fffffff) or (DWord(ord(s)) shl 31);
  2017. end;
  2018. function TSingleRec.GetFrac : QWord;
  2019. begin
  2020. Result:=Data and $7fffff;
  2021. end;
  2022. procedure TSingleRec.SetFrac(e : QWord);
  2023. begin
  2024. Data:=(Data and $ff800000) or (e and $7fffff);
  2025. end;
  2026. {
  2027. Based on information taken from http://en.wikipedia.org/wiki/Single_precision#x86_Extended_Precision_Format
  2028. }
  2029. function TSingleRec.SpecialType : TFloatSpecial;
  2030. const
  2031. Denormal : array[boolean] of TFloatSpecial = (fsDenormal,fsNDenormal);
  2032. begin
  2033. case Exp of
  2034. 0:
  2035. begin
  2036. if Mantissa=0 then
  2037. begin
  2038. if Sign then
  2039. Result:=fsNZero
  2040. else
  2041. Result:=fsZero
  2042. end
  2043. else
  2044. Result:=Denormal[Sign];
  2045. end;
  2046. $ff:
  2047. if Mantissa=0 then
  2048. begin
  2049. if Sign then
  2050. Result:=fsNInf
  2051. else
  2052. Result:=fsInf;
  2053. end
  2054. else
  2055. Result:=fsNaN;
  2056. else
  2057. begin
  2058. if Sign then
  2059. Result:=fsNegative
  2060. else
  2061. Result:=fsPositive;
  2062. end;
  2063. end;
  2064. end;
  2065. procedure TSingleRec.BuildUp(const _Sign: Boolean; const _Mantissa: QWord; const _Exponent: Longint);
  2066. begin
  2067. Value := 0.0;
  2068. SetSign(_Sign);
  2069. if (_Mantissa=0) and (_Exponent=0) then
  2070. Exit //SetExp(0)
  2071. else
  2072. SetExp(_Exponent + Bias);
  2073. SetFrac(_Mantissa and $7fffff); //clear top bit
  2074. end;
  2075. {$endif SUPPORT_SINGLE}