genmath.inc 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541
  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. {$goto on}
  34. type
  35. TabCoef = array[0..6] of Real;
  36. { also necessary for Int() on systems with 64bit floats (JM) }
  37. {$ifndef FPC_SYSTEM_HAS_float64}
  38. {$ifdef ENDIAN_LITTLE}
  39. float64 = record
  40. {$ifndef FPC_DOUBLE_HILO_SWAPPED}
  41. low,high: longint;
  42. {$else}
  43. high,low: longint;
  44. {$endif FPC_DOUBLE_HILO_SWAPPED}
  45. end;
  46. {$else}
  47. float64 = record
  48. {$ifndef FPC_DOUBLE_HILO_SWAPPED}
  49. high,low: longint;
  50. {$else}
  51. low,high: longint;
  52. {$endif FPC_DOUBLE_HILO_SWAPPED}
  53. end;
  54. {$endif}
  55. {$endif FPC_SYSTEM_HAS_float64}
  56. const
  57. PIO2 = 1.57079632679489661923; { pi/2 }
  58. PIO4 = 7.85398163397448309616E-1; { pi/4 }
  59. SQRT2 = 1.41421356237309504880; { sqrt(2) }
  60. SQRTH = 7.07106781186547524401E-1; { sqrt(2)/2 }
  61. LOG2E = 1.4426950408889634073599; { 1/log(2) }
  62. SQ2OPI = 7.9788456080286535587989E-1; { sqrt( 2/pi )}
  63. LOGE2 = 6.93147180559945309417E-1; { log(2) }
  64. LOGSQ2 = 3.46573590279972654709E-1; { log(2)/2 }
  65. THPIO4 = 2.35619449019234492885; { 3*pi/4 }
  66. TWOOPI = 6.36619772367581343075535E-1; { 2/pi }
  67. lossth = 1.073741824e9;
  68. MAXLOG = 8.8029691931113054295988E1; { log(2**127) }
  69. MINLOG = -8.872283911167299960540E1; { log(2**-128) }
  70. DP1 = 7.85398125648498535156E-1;
  71. DP2 = 3.77489470793079817668E-8;
  72. DP3 = 2.69515142907905952645E-15;
  73. {$if not defined(FPC_SYSTEM_HAS_SIN) or not defined(FPC_SYSTEM_HAS_COS)}
  74. const sincof : TabCoef = (
  75. 1.58962301576546568060E-10,
  76. -2.50507477628578072866E-8,
  77. 2.75573136213857245213E-6,
  78. -1.98412698295895385996E-4,
  79. 8.33333333332211858878E-3,
  80. -1.66666666666666307295E-1, 0);
  81. coscof : TabCoef = (
  82. -1.13585365213876817300E-11,
  83. 2.08757008419747316778E-9,
  84. -2.75573141792967388112E-7,
  85. 2.48015872888517045348E-5,
  86. -1.38888888888730564116E-3,
  87. 4.16666666666665929218E-2, 0);
  88. {$endif}
  89. {*
  90. -------------------------------------------------------------------------------
  91. Raises the exceptions specified by `flags'. Floating-point traps can be
  92. defined here if desired. It is currently not possible for such a trap
  93. to substitute a result value. If traps are not implemented, this routine
  94. should be simply `softfloat_exception_flags |= flags;'.
  95. -------------------------------------------------------------------------------
  96. *}
  97. procedure float_raise(i: shortint);
  98. var
  99. pflags: pbyte;
  100. unmasked_flags: byte;
  101. Begin
  102. { taking address of threadvar produces somewhat more compact code }
  103. pflags := @softfloat_exception_flags;
  104. pflags^ := pflags^ or i;
  105. unmasked_flags := pflags^ and (not softfloat_exception_mask);
  106. if (unmasked_flags and float_flag_invalid) <> 0 then
  107. HandleError(207)
  108. else
  109. if (unmasked_flags and float_flag_divbyzero) <> 0 then
  110. HandleError(200)
  111. else
  112. if (unmasked_flags and float_flag_overflow) <> 0 then
  113. HandleError(205)
  114. else
  115. if (unmasked_flags and float_flag_underflow) <> 0 then
  116. HandleError(206)
  117. else
  118. if (unmasked_flags and float_flag_inexact) <> 0 then
  119. HandleError(207);
  120. end;
  121. {$ifndef FPC_SYSTEM_HAS_TRUNC}
  122. {$ifndef FPC_SYSTEM_HAS_float32}
  123. type
  124. float32 = longint;
  125. {$endif FPC_SYSTEM_HAS_float32}
  126. {$ifndef FPC_SYSTEM_HAS_flag}
  127. type
  128. flag = byte;
  129. {$endif FPC_SYSTEM_HAS_flag}
  130. {$ifndef FPC_SYSTEM_HAS_extractFloat64Frac0}
  131. Function extractFloat64Frac0(const a: float64): longint;
  132. Begin
  133. extractFloat64Frac0 := a.high and $000FFFFF;
  134. End;
  135. {$endif not FPC_SYSTEM_HAS_extractFloat64Frac0}
  136. {$ifndef FPC_SYSTEM_HAS_extractFloat64Frac1}
  137. Function extractFloat64Frac1(const a: float64): longint;
  138. Begin
  139. extractFloat64Frac1 := a.low;
  140. End;
  141. {$endif not FPC_SYSTEM_HAS_extractFloat64Frac1}
  142. {$ifndef FPC_SYSTEM_HAS_extractFloat64Exp}
  143. Function extractFloat64Exp(const a: float64): smallint;
  144. Begin
  145. extractFloat64Exp:= ( a.high shr 20 ) AND $7FF;
  146. End;
  147. {$endif not FPC_SYSTEM_HAS_extractFloat64Exp}
  148. {$ifndef FPC_SYSTEM_HAS_extractFloat64Frac}
  149. Function extractFloat64Frac(const a: float64): int64;
  150. Begin
  151. extractFloat64Frac:=int64(a) and $000FFFFFFFFFFFFF;
  152. End;
  153. {$endif not FPC_SYSTEM_HAS_extractFloat64Frac}
  154. {$ifndef FPC_SYSTEM_HAS_extractFloat64Sign}
  155. Function extractFloat64Sign(const a: float64) : flag;
  156. Begin
  157. extractFloat64Sign := a.high shr 31;
  158. End;
  159. {$endif not FPC_SYSTEM_HAS_extractFloat64Sign}
  160. Procedure shortShift64Left(a0:longint; a1:longint; count:smallint; VAR z0Ptr:longint; VAR z1Ptr:longint );
  161. Begin
  162. z1Ptr := a1 shl count;
  163. if count = 0 then
  164. z0Ptr := a0
  165. else
  166. z0Ptr := ( a0 shl count ) OR ( a1 shr ( ( - count ) AND 31 ) );
  167. End;
  168. function float64_to_int32_round_to_zero(a: float64 ): longint;
  169. Var
  170. aSign: flag;
  171. aExp, shiftCount: smallint;
  172. aSig0, aSig1, absZ, aSigExtra: longint;
  173. z: longint;
  174. label
  175. invalid;
  176. Begin
  177. aSig1 := extractFloat64Frac1( a );
  178. aSig0 := extractFloat64Frac0( a );
  179. aExp := extractFloat64Exp( a );
  180. aSign := extractFloat64Sign( a );
  181. shiftCount := aExp - $413;
  182. if 0<=shiftCount then
  183. Begin
  184. if (aExp=$7FF) and ((aSig0 or aSig1)<>0) then
  185. goto invalid;
  186. shortShift64Left(aSig0 OR $00100000, aSig1, shiftCount, absZ, aSigExtra );
  187. End
  188. else
  189. Begin
  190. if aExp<$3FF then
  191. begin
  192. float64_to_int32_round_to_zero := 0;
  193. exit;
  194. end;
  195. aSig0 := aSig0 or $00100000;
  196. aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR aSig1;
  197. absZ := aSig0 shr ( - shiftCount );
  198. End;
  199. if aSign<>0 then
  200. z:=-absZ
  201. else
  202. z:=absZ;
  203. if ((aSign<>0) xor (z<0)) AND (z<>0) then
  204. begin
  205. invalid:
  206. float_raise(float_flag_invalid);
  207. if (aSign <> 0) then
  208. float64_to_int32_round_to_zero:=longint($80000000)
  209. else
  210. float64_to_int32_round_to_zero:=$7FFFFFFF;
  211. exit;
  212. end;
  213. if ( aSigExtra <> 0) then
  214. float_raise(float_flag_inexact);
  215. float64_to_int32_round_to_zero := z;
  216. End;
  217. function genmath_float64_to_int64_round_to_zero(a : float64) : int64;
  218. var
  219. aSign : flag;
  220. aExp, shiftCount : smallint;
  221. aSig : int64;
  222. z : int64;
  223. begin
  224. aSig:=extractFloat64Frac(a);
  225. aExp:=extractFloat64Exp(a);
  226. aSign:=extractFloat64Sign(a);
  227. if aExp<>0 then
  228. aSig:=aSig or $0010000000000000;
  229. shiftCount:= aExp-$433;
  230. if 0<=shiftCount then
  231. begin
  232. if aExp>=$43e then
  233. begin
  234. if int64(a)<>$C3E0000000000000 then
  235. begin
  236. float_raise(float_flag_invalid);
  237. if (aSign=0) or ((aExp=$7FF) and
  238. (aSig<>$0010000000000000 )) then
  239. begin
  240. result:=$7FFFFFFFFFFFFFFF;
  241. exit;
  242. end;
  243. end;
  244. result:=$8000000000000000;
  245. exit;
  246. end;
  247. z:=aSig shl shiftCount;
  248. end
  249. else
  250. begin
  251. if aExp<$3fe then
  252. begin
  253. result:=0;
  254. exit;
  255. end;
  256. z:=aSig shr -shiftCount;
  257. {
  258. if (aSig shl (shiftCount and 63))<>0 then
  259. float_exception_flags |= float_flag_inexact;
  260. }
  261. end;
  262. if aSign<>0 then
  263. z:=-z;
  264. result:=z;
  265. end;
  266. Function float32_to_int32_round_to_zero( a: Float32 ): longint;
  267. Var
  268. aSign : flag;
  269. aExp, shiftCount : smallint;
  270. aSig : longint;
  271. z : longint;
  272. Begin
  273. aSig := a and $007FFFFF;
  274. aExp := (a shr 23) and $FF;
  275. aSign := a shr 31;
  276. shiftCount := aExp - $9E;
  277. if ( 0 <= shiftCount ) then
  278. Begin
  279. if ( a <> Float32($CF000000) ) then
  280. Begin
  281. float_raise( float_flag_invalid );
  282. if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  283. Begin
  284. float32_to_int32_round_to_zero:=$7fffffff;
  285. exit;
  286. end;
  287. End;
  288. float32_to_int32_round_to_zero:=longint($80000000);
  289. exit;
  290. End
  291. else
  292. if ( aExp <= $7E ) then
  293. Begin
  294. float32_to_int32_round_to_zero := 0;
  295. exit;
  296. End;
  297. aSig := ( aSig or $00800000 ) shl 8;
  298. z := aSig shr ( - shiftCount );
  299. if ( aSign<>0 ) then z := - z;
  300. float32_to_int32_round_to_zero := z;
  301. End;
  302. function fpc_trunc_real(d : ValReal) : int64;compilerproc;
  303. var
  304. f32 : float32;
  305. f64 : float64;
  306. Begin
  307. { in emulation mode the real is equal to a single }
  308. { otherwise in fpu mode, it is equal to a double }
  309. { extended is not supported yet. }
  310. if sizeof(D) > 8 then
  311. HandleError(255);
  312. if sizeof(D)=8 then
  313. begin
  314. move(d,f64,sizeof(f64));
  315. result:=genmath_float64_to_int64_round_to_zero(f64);
  316. end
  317. else
  318. begin
  319. move(d,f32,sizeof(f32));
  320. result:=float32_to_int32_round_to_zero(f32);
  321. end;
  322. end;
  323. {$endif not FPC_SYSTEM_HAS_TRUNC}
  324. {$ifndef FPC_SYSTEM_HAS_INT}
  325. {$ifdef SUPPORT_DOUBLE}
  326. { straight Pascal translation of the code for __trunc() in }
  327. { the file sysdeps/libm-ieee754/s_trunc.c of glibc (JM) }
  328. function fpc_int_real(d: ValReal): ValReal;compilerproc;
  329. var
  330. i0, j0: longint;
  331. i1: cardinal;
  332. sx: longint;
  333. f64 : float64;
  334. begin
  335. f64:=float64(d);
  336. i0 := f64.high;
  337. i1 := cardinal(f64.low);
  338. sx := i0 and $80000000;
  339. j0 := ((i0 shr 20) and $7ff) - $3ff;
  340. if (j0 < 20) then
  341. begin
  342. if (j0 < 0) then
  343. begin
  344. { the magnitude of the number is < 1 so the result is +-0. }
  345. f64.high := sx;
  346. f64.low := 0;
  347. end
  348. else
  349. begin
  350. f64.high := sx or (i0 and not($fffff shr j0));
  351. f64.low := 0;
  352. end
  353. end
  354. else if (j0 > 51) then
  355. begin
  356. if (j0 = $400) then
  357. { d is inf or NaN }
  358. exit(d + d); { don't know why they do this (JM) }
  359. end
  360. else
  361. begin
  362. f64.high := i0;
  363. f64.low := longint(i1 and not(cardinal($ffffffff) shr (j0 - 20)));
  364. end;
  365. result:=double(f64);
  366. end;
  367. {$else SUPPORT_DOUBLE}
  368. function fpc_int_real(d : ValReal) : ValReal;compilerproc;
  369. begin
  370. { this will be correct since real = single in the case of }
  371. { the motorola version of the compiler... }
  372. result:=ValReal(trunc(d));
  373. end;
  374. {$endif SUPPORT_DOUBLE}
  375. {$endif not FPC_SYSTEM_HAS_INT}
  376. {$ifndef FPC_SYSTEM_HAS_ABS}
  377. function fpc_abs_real(d : ValReal) : ValReal;compilerproc;
  378. begin
  379. if (d<0.0) then
  380. result := -d
  381. else
  382. result := d ;
  383. end;
  384. {$endif not FPC_SYSTEM_HAS_ABS}
  385. {$ifndef SYSTEM_HAS_FREXP}
  386. function frexp(x:Real; out e:Integer ):Real;
  387. {* frexp() extracts the exponent from x. It returns an integer *}
  388. {* power of two to expnt and the significand between 0.5 and 1 *}
  389. {* to y. Thus x = y * 2**expn. *}
  390. begin
  391. e :=0;
  392. if (abs(x)<0.5) then
  393. While (abs(x)<0.5) do
  394. begin
  395. x := x*2;
  396. Dec(e);
  397. end
  398. else
  399. While (abs(x)>1) do
  400. begin
  401. x := x/2;
  402. Inc(e);
  403. end;
  404. frexp := x;
  405. end;
  406. {$endif not SYSTEM_HAS_FREXP}
  407. {$ifndef SYSTEM_HAS_LDEXP}
  408. function ldexp( x: Real; N: Integer):Real;
  409. {* ldexp() multiplies x by 2**n. *}
  410. var r : Real;
  411. begin
  412. R := 1;
  413. if N>0 then
  414. while N>0 do
  415. begin
  416. R:=R*2;
  417. Dec(N);
  418. end
  419. else
  420. while N<0 do
  421. begin
  422. R:=R/2;
  423. Inc(N);
  424. end;
  425. ldexp := x * R;
  426. end;
  427. {$endif not SYSTEM_HAS_LDEXP}
  428. function polevl(var x:Real; var Coef:TabCoef; N:Integer):Real;
  429. {*****************************************************************}
  430. { Evaluate polynomial }
  431. {*****************************************************************}
  432. { }
  433. { SYNOPSIS: }
  434. { }
  435. { int N; }
  436. { double x, y, coef[N+1], polevl[]; }
  437. { }
  438. { y = polevl( x, coef, N ); }
  439. { }
  440. { DESCRIPTION: }
  441. { }
  442. { Evaluates polynomial of degree N: }
  443. { }
  444. { 2 N }
  445. { y = C + C x + C x +...+ C x }
  446. { 0 1 2 N }
  447. { }
  448. { Coefficients are stored in reverse order: }
  449. { }
  450. { coef[0] = C , ..., coef[N] = C . }
  451. { N 0 }
  452. { }
  453. { The function p1evl() assumes that coef[N] = 1.0 and is }
  454. { omitted from the array. Its calling arguments are }
  455. { otherwise the same as polevl(). }
  456. { }
  457. { SPEED: }
  458. { }
  459. { In the interest of speed, there are no checks for out }
  460. { of bounds arithmetic. This routine is used by most of }
  461. { the functions in the library. Depending on available }
  462. { equipment features, the user may wish to rewrite the }
  463. { program in microcode or assembly language. }
  464. {*****************************************************************}
  465. var ans : Real;
  466. i : Integer;
  467. begin
  468. ans := Coef[0];
  469. for i:=1 to N do
  470. ans := ans * x + Coef[i];
  471. polevl:=ans;
  472. end;
  473. function p1evl(var x:Real; var Coef:TabCoef; N:Integer):Real;
  474. { }
  475. { Evaluate polynomial when coefficient of x is 1.0. }
  476. { Otherwise same as polevl. }
  477. { }
  478. var
  479. ans : Real;
  480. i : Integer;
  481. begin
  482. ans := x + Coef[0];
  483. for i:=1 to N-1 do
  484. ans := ans * x + Coef[i];
  485. p1evl := ans;
  486. end;
  487. {$ifndef FPC_SYSTEM_HAS_SQR}
  488. function fpc_sqr_real(d : ValReal) : ValReal;compilerproc;{$ifdef MATHINLINE}inline;{$endif}
  489. begin
  490. result := d*d;
  491. end;
  492. {$endif}
  493. {$ifndef FPC_SYSTEM_HAS_PI}
  494. function fpc_pi_real : ValReal;compilerproc;{$ifdef MATHINLINE}inline;{$endif}
  495. begin
  496. result := 3.1415926535897932385;
  497. end;
  498. {$endif}
  499. {$ifndef FPC_SYSTEM_HAS_SQRT}
  500. function fpc_sqrt_real(d:ValReal):ValReal;compilerproc;
  501. {*****************************************************************}
  502. { Square root }
  503. {*****************************************************************}
  504. { }
  505. { SYNOPSIS: }
  506. { }
  507. { double x, y, sqrt(); }
  508. { }
  509. { y = sqrt( x ); }
  510. { }
  511. { DESCRIPTION: }
  512. { }
  513. { Returns the square root of x. }
  514. { }
  515. { Range reduction involves isolating the power of two of the }
  516. { argument and using a polynomial approximation to obtain }
  517. { a rough value for the square root. Then Heron's iteration }
  518. { is used three times to converge to an accurate value. }
  519. {*****************************************************************}
  520. var e : Integer;
  521. w,z : Real;
  522. begin
  523. if( d <= 0.0 ) then
  524. begin
  525. if d < 0.0 then begin
  526. float_raise(float_flag_invalid);
  527. d := 0/0;
  528. end;
  529. result := 0.0;
  530. end
  531. else
  532. begin
  533. w := d;
  534. { separate exponent and significand }
  535. z := frexp( d, e );
  536. { approximate square root of number between 0.5 and 1 }
  537. { relative error of approximation = 7.47e-3 }
  538. d := 4.173075996388649989089E-1 + 5.9016206709064458299663E-1 * z;
  539. { adjust for odd powers of 2 }
  540. if odd(e) then
  541. d := d*SQRT2;
  542. { re-insert exponent }
  543. d := ldexp( d, (e div 2) );
  544. { Newton iterations: }
  545. d := 0.5*(d + w/d);
  546. d := 0.5*(d + w/d);
  547. d := 0.5*(d + w/d);
  548. d := 0.5*(d + w/d);
  549. d := 0.5*(d + w/d);
  550. d := 0.5*(d + w/d);
  551. result := d;
  552. end;
  553. end;
  554. {$endif}
  555. {$ifndef FPC_SYSTEM_HAS_EXP}
  556. {$ifdef SUPPORT_DOUBLE}
  557. {
  558. This code was translated from uclib code, the original code
  559. had the following copyright notice:
  560. *
  561. * ====================================================
  562. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  563. *
  564. * Developed at SunPro, a Sun Microsystems, Inc. business.
  565. * Permission to use, copy, modify, and distribute this
  566. * software is freely granted, provided that this notice
  567. * is preserved.
  568. * ====================================================
  569. *}
  570. {*
  571. * Returns the exponential of x.
  572. *
  573. * Method
  574. * 1. Argument reduction:
  575. * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
  576. * Given x, find r and integer k such that
  577. *
  578. * x = k*ln2 + r, |r| <= 0.5*ln2.
  579. *
  580. * Here r will be represented as r = hi-lo for better
  581. * accuracy.
  582. *
  583. * 2. Approximation of exp(r) by a special rational function on
  584. * the interval [0,0.34658]:
  585. * Write
  586. * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
  587. * We use a special Reme algorithm on [0,0.34658] to generate
  588. * a polynomial of degree 5 to approximate R. The maximum error
  589. * of this polynomial approximation is bounded by 2**-59. In
  590. * other words,
  591. * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
  592. * (where z=r*r, and the values of P1 to P5 are listed below)
  593. * and
  594. * | 5 | -59
  595. * | 2.0+P1*z+...+P5*z - R(z) | <= 2
  596. * | |
  597. * The computation of exp(r) thus becomes
  598. * 2*r
  599. * exp(r) = 1 + -------
  600. * R - r
  601. * r*R1(r)
  602. * = 1 + r + ----------- (for better accuracy)
  603. * 2 - R1(r)
  604. * where
  605. 2 4 10
  606. * R1(r) = r - (P1*r + P2*r + ... + P5*r ).
  607. *
  608. * 3. Scale back to obtain exp(x):
  609. * From step 1, we have
  610. * exp(x) = 2^k * exp(r)
  611. *
  612. * Special cases:
  613. * exp(INF) is INF, exp(NaN) is NaN;
  614. * exp(-INF) is 0, and
  615. * for finite argument, only exp(0)=1 is exact.
  616. *
  617. * Accuracy:
  618. * according to an error analysis, the error is always less than
  619. * 1 ulp (unit in the last place).
  620. *
  621. * Misc. info.
  622. * For IEEE double
  623. * if x > 7.09782712893383973096e+02 then exp(x) overflow
  624. * if x < -7.45133219101941108420e+02 then exp(x) underflow
  625. *
  626. * Constants:
  627. * The hexadecimal values are the intended ones for the following
  628. * constants. The decimal values may be used, provided that the
  629. * compiler will convert from decimal to binary accurately enough
  630. * to produce the hexadecimal values shown.
  631. *
  632. }
  633. function fpc_exp_real(d: ValReal):ValReal;compilerproc;
  634. const
  635. one: double = 1.0;
  636. halF : array[0..1] of double = (0.5,-0.5);
  637. huge: double = 1.0e+300;
  638. twom1000: double = 9.33263618503218878990e-302; { 2**-1000=0x01700000,0}
  639. o_threshold: double = 7.09782712893383973096e+02; { 0x40862E42, 0xFEFA39EF }
  640. u_threshold: double = -7.45133219101941108420e+02; { 0xc0874910, 0xD52D3051 }
  641. ln2HI : array[0..1] of double = ( 6.93147180369123816490e-01, { 0x3fe62e42, 0xfee00000 }
  642. -6.93147180369123816490e-01); { 0xbfe62e42, 0xfee00000 }
  643. ln2LO : array[0..1] of double = (1.90821492927058770002e-10, { 0x3dea39ef, 0x35793c76 }
  644. -1.90821492927058770002e-10); { 0xbdea39ef, 0x35793c76 }
  645. invln2: double = 1.44269504088896338700e+00; { 0x3ff71547, 0x652b82fe }
  646. P1: double = 1.66666666666666019037e-01; { 0x3FC55555, 0x5555553E }
  647. P2: double = -2.77777777770155933842e-03; { 0xBF66C16C, 0x16BEBD93 }
  648. P3: double = 6.61375632143793436117e-05; { 0x3F11566A, 0xAF25DE2C }
  649. P4: double = -1.65339022054652515390e-06; { 0xBEBBBD41, 0xC5D26BF1 }
  650. P5: double = 4.13813679705723846039e-08; { 0x3E663769, 0x72BEA4D0 }
  651. var
  652. c,hi,lo,t,y : double;
  653. k,xsb : longint;
  654. hx,hy,lx : dword;
  655. begin
  656. hi:=0.0;
  657. lo:=0.0;
  658. k:=0;
  659. hx:=float64(d).high;
  660. xsb := (hx shr 31) and 1; { sign bit of d }
  661. hx := hx and $7fffffff; { high word of |d| }
  662. { filter out non-finite argument }
  663. if hx >= $40862E42 then
  664. begin { if |d|>=709.78... }
  665. if hx >= $7ff00000 then
  666. begin
  667. lx:=float64(d).low;
  668. if ((hx and $fffff) or lx)<>0 then
  669. begin
  670. result:=d+d; { NaN }
  671. exit;
  672. end
  673. else
  674. begin
  675. if xsb=0 then
  676. result:=d
  677. else
  678. result:=0.0; { exp(+-inf)=(inf,0) }
  679. exit;
  680. end;
  681. end;
  682. if d > o_threshold then begin
  683. result:=huge*huge; { overflow }
  684. exit;
  685. end;
  686. if d < u_threshold then begin
  687. result:=twom1000*twom1000; { underflow }
  688. exit;
  689. end;
  690. end;
  691. { argument reduction }
  692. if hx > $3fd62e42 then
  693. begin { if |d| > 0.5 ln2 }
  694. if hx < $3FF0A2B2 then { and |d| < 1.5 ln2 }
  695. begin
  696. hi := d-ln2HI[xsb];
  697. lo:=ln2LO[xsb];
  698. k := 1-xsb-xsb;
  699. end
  700. else
  701. begin
  702. k := trunc(invln2*d+halF[xsb]);
  703. t := k;
  704. hi := d - t*ln2HI[0]; { t*ln2HI is exact here }
  705. lo := t*ln2LO[0];
  706. end;
  707. d := hi - lo;
  708. end
  709. else if hx < $3e300000 then
  710. begin { when |d|<2**-28 }
  711. if huge+d>one then
  712. begin
  713. result:=one+d;{ trigger inexact }
  714. exit;
  715. end;
  716. end
  717. else
  718. k := 0;
  719. { d is now in primary range }
  720. t:=d*d;
  721. c:=d - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
  722. if k=0 then
  723. begin
  724. result:=one-((d*c)/(c-2.0)-d);
  725. exit;
  726. end
  727. else
  728. y := one-((lo-(d*c)/(2.0-c))-hi);
  729. if k >= -1021 then
  730. begin
  731. hy:=float64(y).high;
  732. float64(y).high:=longint(hy)+(k shl 20); { add k to y's exponent }
  733. result:=y;
  734. end
  735. else
  736. begin
  737. hy:=float64(y).high;
  738. float64(y).high:=longint(hy)+((k+1000) shl 20); { add k to y's exponent }
  739. result:=y*twom1000;
  740. end;
  741. end;
  742. {$else SUPPORT_DOUBLE}
  743. function fpc_exp_real(d: ValReal):ValReal;compilerproc;
  744. {*****************************************************************}
  745. { Exponential Function }
  746. {*****************************************************************}
  747. { }
  748. { SYNOPSIS: }
  749. { }
  750. { double x, y, exp(); }
  751. { }
  752. { y = exp( x ); }
  753. { }
  754. { DESCRIPTION: }
  755. { }
  756. { Returns e (2.71828...) raised to the x power. }
  757. { }
  758. { Range reduction is accomplished by separating the argument }
  759. { into an integer k and fraction f such that }
  760. { }
  761. { x k f }
  762. { e = 2 e. }
  763. { }
  764. { A Pade' form of degree 2/3 is used to approximate exp(f)- 1 }
  765. { in the basic range [-0.5 ln 2, 0.5 ln 2]. }
  766. {*****************************************************************}
  767. const P : TabCoef = (
  768. 1.26183092834458542160E-4,
  769. 3.02996887658430129200E-2,
  770. 1.00000000000000000000E0, 0, 0, 0, 0);
  771. Q : TabCoef = (
  772. 3.00227947279887615146E-6,
  773. 2.52453653553222894311E-3,
  774. 2.27266044198352679519E-1,
  775. 2.00000000000000000005E0, 0 ,0 ,0);
  776. C1 = 6.9335937500000000000E-1;
  777. C2 = 2.1219444005469058277E-4;
  778. var n : Integer;
  779. px, qx, xx : Real;
  780. begin
  781. if( d > MAXLOG) then
  782. float_raise(float_flag_overflow)
  783. else
  784. if( d < MINLOG ) then
  785. begin
  786. float_raise(float_flag_underflow);
  787. result:=0; { Result if underflow masked }
  788. end
  789. else
  790. begin
  791. { Express e**x = e**g 2**n }
  792. { = e**g e**( n loge(2) ) }
  793. { = e**( g + n loge(2) ) }
  794. px := d * LOG2E;
  795. qx := Trunc( px + 0.5 ); { Trunc() truncates toward -infinity. }
  796. n := Trunc(qx);
  797. d := d - qx * C1;
  798. d := d + qx * C2;
  799. { rational approximation for exponential }
  800. { of the fractional part: }
  801. { e**x - 1 = 2x P(x**2)/( Q(x**2) - P(x**2) ) }
  802. xx := d * d;
  803. px := d * polevl( xx, P, 2 );
  804. d := px/( polevl( xx, Q, 3 ) - px );
  805. d := ldexp( d, 1 );
  806. d := d + 1.0;
  807. d := ldexp( d, n );
  808. result := d;
  809. end;
  810. end;
  811. {$endif SUPPORT_DOUBLE}
  812. {$endif}
  813. {$ifndef FPC_SYSTEM_HAS_ROUND}
  814. function fpc_round_real(d : ValReal) : int64;compilerproc;
  815. var
  816. fr: ValReal;
  817. tr: Int64;
  818. Begin
  819. fr := abs(Frac(d));
  820. tr := Trunc(d);
  821. result:=0;
  822. case softfloat_rounding_mode of
  823. float_round_nearest_even:
  824. begin
  825. if fr > 0.5 then
  826. if d >= 0 then
  827. result:=tr+1
  828. else
  829. result:=tr-1
  830. else
  831. if fr < 0.5 then
  832. result:=tr
  833. else { fr = 0.5 }
  834. { check sign to decide ... }
  835. { as in Turbo Pascal... }
  836. begin
  837. if d >= 0.0 then
  838. result:=tr+1
  839. else
  840. result:=tr;
  841. { round to even }
  842. result:=result and not(1);
  843. end;
  844. end;
  845. float_round_down:
  846. if (d >= 0.0) or
  847. (fr = 0.0) then
  848. result:=tr
  849. else
  850. result:=tr-1;
  851. float_round_up:
  852. if (d >= 0.0) and
  853. (fr <> 0.0) then
  854. result:=tr+1
  855. else
  856. result:=tr;
  857. float_round_to_zero:
  858. result:=tr;
  859. else
  860. { needed for jvm: result must be initialized on all paths }
  861. result:=0;
  862. end;
  863. end;
  864. {$endif FPC_SYSTEM_HAS_ROUND}
  865. {$ifndef FPC_SYSTEM_HAS_LN}
  866. function fpc_ln_real(d:ValReal):ValReal;compilerproc;
  867. {*****************************************************************}
  868. { Natural Logarithm }
  869. {*****************************************************************}
  870. { }
  871. { SYNOPSIS: }
  872. { }
  873. { double x, y, log(); }
  874. { }
  875. { y = ln( x ); }
  876. { }
  877. { DESCRIPTION: }
  878. { }
  879. { Returns the base e (2.718...) logarithm of x. }
  880. { }
  881. { The argument is separated into its exponent and fractional }
  882. { parts. If the exponent is between -1 and +1, the logarithm }
  883. { of the fraction is approximated by }
  884. { }
  885. { log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x). }
  886. { }
  887. { Otherwise, setting z = 2(x-1)/x+1), }
  888. { }
  889. { log(x) = z + z**3 P(z)/Q(z). }
  890. { }
  891. {*****************************************************************}
  892. const P : TabCoef = (
  893. { Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
  894. 1/sqrt(2) <= x < sqrt(2) }
  895. 4.58482948458143443514E-5,
  896. 4.98531067254050724270E-1,
  897. 6.56312093769992875930E0,
  898. 2.97877425097986925891E1,
  899. 6.06127134467767258030E1,
  900. 5.67349287391754285487E1,
  901. 1.98892446572874072159E1);
  902. Q : TabCoef = (
  903. 1.50314182634250003249E1,
  904. 8.27410449222435217021E1,
  905. 2.20664384982121929218E2,
  906. 3.07254189979530058263E2,
  907. 2.14955586696422947765E2,
  908. 5.96677339718622216300E1, 0);
  909. { Coefficients for log(x) = z + z**3 P(z)/Q(z),
  910. where z = 2(x-1)/(x+1)
  911. 1/sqrt(2) <= x < sqrt(2) }
  912. R : TabCoef = (
  913. -7.89580278884799154124E-1,
  914. 1.63866645699558079767E1,
  915. -6.41409952958715622951E1, 0, 0, 0, 0);
  916. S : TabCoef = (
  917. -3.56722798256324312549E1,
  918. 3.12093766372244180303E2,
  919. -7.69691943550460008604E2, 0, 0, 0, 0);
  920. var e : Integer;
  921. z, y : Real;
  922. Label Ldone;
  923. begin
  924. if( d <= 0.0 ) then
  925. begin
  926. float_raise(float_flag_invalid);
  927. exit;
  928. end;
  929. d := frexp( d, e );
  930. { logarithm using log(x) = z + z**3 P(z)/Q(z),
  931. where z = 2(x-1)/x+1) }
  932. if( (e > 2) or (e < -2) ) then
  933. begin
  934. if( d < SQRTH ) then
  935. begin
  936. { 2( 2x-1 )/( 2x+1 ) }
  937. Dec(e, 1);
  938. z := d - 0.5;
  939. y := 0.5 * z + 0.5;
  940. end
  941. else
  942. begin
  943. { 2 (x-1)/(x+1) }
  944. z := d - 0.5;
  945. z := z - 0.5;
  946. y := 0.5 * d + 0.5;
  947. end;
  948. d := z / y;
  949. { /* rational form */ }
  950. z := d*d;
  951. z := d + d * ( z * polevl( z, R, 2 ) / p1evl( z, S, 3 ) );
  952. goto ldone;
  953. end;
  954. { logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) }
  955. if( d < SQRTH ) then
  956. begin
  957. Dec(e, 1);
  958. d := ldexp( d, 1 ) - 1.0; { 2x - 1 }
  959. end
  960. else
  961. d := d - 1.0;
  962. { rational form }
  963. z := d*d;
  964. y := d * ( z * polevl( d, P, 6 ) / p1evl( d, Q, 6 ) );
  965. y := y - ldexp( z, -1 ); { y - 0.5 * z }
  966. z := d + y;
  967. ldone:
  968. { recombine with exponent term }
  969. if( e <> 0 ) then
  970. begin
  971. y := e;
  972. z := z - y * 2.121944400546905827679e-4;
  973. z := z + y * 0.693359375;
  974. end;
  975. result:= z;
  976. end;
  977. {$endif}
  978. {$ifndef FPC_SYSTEM_HAS_SIN}
  979. function fpc_Sin_real(d:ValReal):ValReal;compilerproc;
  980. {*****************************************************************}
  981. { Circular Sine }
  982. {*****************************************************************}
  983. { }
  984. { SYNOPSIS: }
  985. { }
  986. { double x, y, sin(); }
  987. { }
  988. { y = sin( x ); }
  989. { }
  990. { DESCRIPTION: }
  991. { }
  992. { Range reduction is into intervals of pi/4. The reduction }
  993. { error is nearly eliminated by contriving an extended }
  994. { precision modular arithmetic. }
  995. { }
  996. { Two polynomial approximating functions are employed. }
  997. { Between 0 and pi/4 the sine is approximated by }
  998. { x + x**3 P(x**2). }
  999. { Between pi/4 and pi/2 the cosine is represented as }
  1000. { 1 - x**2 Q(x**2). }
  1001. {*****************************************************************}
  1002. var y, z, zz : Real;
  1003. j, sign : Integer;
  1004. begin
  1005. { make argument positive but save the sign }
  1006. sign := 1;
  1007. if( d < 0 ) then
  1008. begin
  1009. d := -d;
  1010. sign := -1;
  1011. end;
  1012. { above this value, approximate towards 0 }
  1013. if( d > lossth ) then
  1014. begin
  1015. result := 0.0;
  1016. exit;
  1017. end;
  1018. y := Trunc( d/PIO4 ); { integer part of x/PIO4 }
  1019. { strip high bits of integer part to prevent integer overflow }
  1020. z := ldexp( y, -4 );
  1021. z := Trunc(z); { integer part of y/8 }
  1022. z := y - ldexp( z, 4 ); { y - 16 * (y/16) }
  1023. j := Trunc(z); { convert to integer for tests on the phase angle }
  1024. { map zeros to origin }
  1025. { typecast is to avoid "can't determine which overloaded function }
  1026. { to call" }
  1027. if odd( longint(j) ) then
  1028. begin
  1029. inc(j);
  1030. y := y + 1.0;
  1031. end;
  1032. j := j and 7; { octant modulo 360 degrees }
  1033. { reflect in x axis }
  1034. if( j > 3) then
  1035. begin
  1036. sign := -sign;
  1037. dec(j, 4);
  1038. end;
  1039. { Extended precision modular arithmetic }
  1040. z := ((d - y * DP1) - y * DP2) - y * DP3;
  1041. zz := z * z;
  1042. if( (j=1) or (j=2) ) then
  1043. y := 1.0 - ldexp(zz,-1) + zz * zz * polevl( zz, coscof, 5 )
  1044. else
  1045. { y = z + z * (zz * polevl( zz, sincof, 5 )); }
  1046. y := z + z * z * z * polevl( zz, sincof, 5 );
  1047. if(sign < 0) then
  1048. y := -y;
  1049. result := y;
  1050. end;
  1051. {$endif}
  1052. {$ifndef FPC_SYSTEM_HAS_COS}
  1053. function fpc_Cos_real(d:ValReal):ValReal;compilerproc;
  1054. {*****************************************************************}
  1055. { Circular cosine }
  1056. {*****************************************************************}
  1057. { }
  1058. { Circular cosine }
  1059. { }
  1060. { SYNOPSIS: }
  1061. { }
  1062. { double x, y, cos(); }
  1063. { }
  1064. { y = cos( x ); }
  1065. { }
  1066. { DESCRIPTION: }
  1067. { }
  1068. { Range reduction is into intervals of pi/4. The reduction }
  1069. { error is nearly eliminated by contriving an extended }
  1070. { precision modular arithmetic. }
  1071. { }
  1072. { Two polynomial approximating functions are employed. }
  1073. { Between 0 and pi/4 the cosine is approximated by }
  1074. { 1 - x**2 Q(x**2). }
  1075. { Between pi/4 and pi/2 the sine is represented as }
  1076. { x + x**3 P(x**2). }
  1077. {*****************************************************************}
  1078. var y, z, zz : Real;
  1079. j, sign : Integer;
  1080. i : LongInt;
  1081. begin
  1082. { make argument positive }
  1083. sign := 1;
  1084. if( d < 0 ) then
  1085. d := -d;
  1086. { above this value, round towards zero }
  1087. if( d > lossth ) then
  1088. begin
  1089. result := 0.0;
  1090. exit;
  1091. end;
  1092. y := Trunc( d/PIO4 );
  1093. z := ldexp( y, -4 );
  1094. z := Trunc(z); { integer part of y/8 }
  1095. z := y - ldexp( z, 4 ); { y - 16 * (y/16) }
  1096. { integer and fractional part modulo one octant }
  1097. i := Trunc(z);
  1098. if odd( i ) then { map zeros to origin }
  1099. begin
  1100. inc(i);
  1101. y := y + 1.0;
  1102. end;
  1103. j := i and 07;
  1104. if( j > 3) then
  1105. begin
  1106. dec(j,4);
  1107. sign := -sign;
  1108. end;
  1109. if( j > 1 ) then
  1110. sign := -sign;
  1111. { Extended precision modular arithmetic }
  1112. z := ((d - y * DP1) - y * DP2) - y * DP3;
  1113. zz := z * z;
  1114. if( (j=1) or (j=2) ) then
  1115. { y = z + z * (zz * polevl( zz, sincof, 5 )); }
  1116. y := z + z * z * z * polevl( zz, sincof, 5 )
  1117. else
  1118. y := 1.0 - ldexp(zz,-1) + zz * zz * polevl( zz, coscof, 5 );
  1119. if(sign < 0) then
  1120. y := -y;
  1121. result := y ;
  1122. end;
  1123. {$endif}
  1124. {$ifndef FPC_SYSTEM_HAS_ARCTAN}
  1125. function fpc_ArcTan_real(d:ValReal):ValReal;compilerproc;
  1126. {
  1127. This code was translated from uclibc code, the original code
  1128. had the following copyright notice:
  1129. *
  1130. * ====================================================
  1131. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  1132. *
  1133. * Developed at SunPro, a Sun Microsystems, Inc. business.
  1134. * Permission to use, copy, modify, and distribute this
  1135. * software is freely granted, provided that this notice
  1136. * is preserved.
  1137. * ====================================================
  1138. *}
  1139. {********************************************************************}
  1140. { Inverse circular tangent (arctangent) }
  1141. {********************************************************************}
  1142. { }
  1143. { SYNOPSIS: }
  1144. { }
  1145. { double x, y, atan(); }
  1146. { }
  1147. { y = atan( x ); }
  1148. { }
  1149. { DESCRIPTION: }
  1150. { }
  1151. { Returns radian angle between -pi/2 and +pi/2 whose tangent }
  1152. { is x. }
  1153. { }
  1154. { Method }
  1155. { 1. Reduce x to positive by atan(x) = -atan(-x). }
  1156. { 2. According to the integer k=4t+0.25 chopped, t=x, the argument }
  1157. { is further reduced to one of the following intervals and the }
  1158. { arctangent of t is evaluated by the corresponding formula: }
  1159. { }
  1160. { [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) }
  1161. { [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) }
  1162. { [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) }
  1163. { [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) }
  1164. { [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) }
  1165. {********************************************************************}
  1166. const
  1167. atanhi: array [0..3] of double = (
  1168. 4.63647609000806093515e-01, { atan(0.5)hi 0x3FDDAC67, 0x0561BB4F }
  1169. 7.85398163397448278999e-01, { atan(1.0)hi 0x3FE921FB, 0x54442D18 }
  1170. 9.82793723247329054082e-01, { atan(1.5)hi 0x3FEF730B, 0xD281F69B }
  1171. 1.57079632679489655800e+00 { atan(inf)hi 0x3FF921FB, 0x54442D18 }
  1172. );
  1173. atanlo: array [0..3] of double = (
  1174. 2.26987774529616870924e-17, { atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 }
  1175. 3.06161699786838301793e-17, { atan(1.0)lo 0x3C81A626, 0x33145C07 }
  1176. 1.39033110312309984516e-17, { atan(1.5)lo 0x3C700788, 0x7AF0CBBD }
  1177. 6.12323399573676603587e-17 { atan(inf)lo 0x3C91A626, 0x33145C07 }
  1178. );
  1179. aT: array[0..10] of double = (
  1180. 3.33333333333329318027e-01, { 0x3FD55555, 0x5555550D }
  1181. -1.99999999998764832476e-01, { 0xBFC99999, 0x9998EBC4 }
  1182. 1.42857142725034663711e-01, { 0x3FC24924, 0x920083FF }
  1183. -1.11111104054623557880e-01, { 0xBFBC71C6, 0xFE231671 }
  1184. 9.09088713343650656196e-02, { 0x3FB745CD, 0xC54C206E }
  1185. -7.69187620504482999495e-02, { 0xBFB3B0F2, 0xAF749A6D }
  1186. 6.66107313738753120669e-02, { 0x3FB10D66, 0xA0D03D51 }
  1187. -5.83357013379057348645e-02, { 0xBFADDE2D, 0x52DEFD9A }
  1188. 4.97687799461593236017e-02, { 0x3FA97B4B, 0x24760DEB }
  1189. -3.65315727442169155270e-02, { 0xBFA2B444, 0x2C6A6C2F }
  1190. 1.62858201153657823623e-02 { 0x3F90AD3A, 0xE322DA11 }
  1191. );
  1192. one: double = 1.0;
  1193. huge: double = 1.0e300;
  1194. var
  1195. w,s1,s2,z: double;
  1196. ix,hx,id: longint;
  1197. low: longword;
  1198. begin
  1199. hx:=float64(d).high;
  1200. ix := hx and $7fffffff;
  1201. if (ix>=$44100000) then { if |x| >= 2^66 }
  1202. begin
  1203. low:=float64(d).low;
  1204. if (ix > $7ff00000) or ((ix = $7ff00000) and (low<>0)) then
  1205. exit(d+d); { NaN }
  1206. if (hx>0) then
  1207. exit(atanhi[3]+atanlo[3])
  1208. else
  1209. exit(-atanhi[3]-atanlo[3]);
  1210. end;
  1211. if (ix < $3fdc0000) then { |x| < 0.4375 }
  1212. begin
  1213. if (ix < $3e200000) then { |x| < 2^-29 }
  1214. begin
  1215. if (huge+d>one) then exit(d); { raise inexact }
  1216. end;
  1217. id := -1;
  1218. end
  1219. else
  1220. begin
  1221. d := abs(d);
  1222. if (ix < $3ff30000) then { |x| < 1.1875 }
  1223. begin
  1224. if (ix < $3fe60000) then { 7/16 <=|x|<11/16 }
  1225. begin
  1226. id := 0; d := (2.0*d-one)/(2.0+d);
  1227. end
  1228. else { 11/16<=|x|< 19/16 }
  1229. begin
  1230. id := 1; d := (d-one)/(d+one);
  1231. end
  1232. end
  1233. else
  1234. begin
  1235. if (ix < $40038000) then { |x| < 2.4375 }
  1236. begin
  1237. id := 2; d := (d-1.5)/(one+1.5*d);
  1238. end
  1239. else { 2.4375 <= |x| < 2^66 }
  1240. begin
  1241. id := 3; d := -1.0/d;
  1242. end;
  1243. end;
  1244. end;
  1245. { end of argument reduction }
  1246. z := d*d;
  1247. w := z*z;
  1248. { break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly }
  1249. s1 := z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
  1250. s2 := w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
  1251. if (id<0) then
  1252. result := d - d*(s1+s2)
  1253. else
  1254. begin
  1255. z := atanhi[id] - ((d*(s1+s2) - atanlo[id]) - d);
  1256. if hx<0 then
  1257. result := -z
  1258. else
  1259. result := z;
  1260. end;
  1261. end;
  1262. {$endif}
  1263. {$ifndef FPC_SYSTEM_HAS_FRAC}
  1264. function fpc_frac_real(d : ValReal) : ValReal;compilerproc;
  1265. begin
  1266. result := d - Int(d);
  1267. end;
  1268. {$endif}
  1269. {$ifdef FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
  1270. {$ifndef FPC_SYSTEM_HAS_QWORD_TO_DOUBLE}
  1271. function fpc_qword_to_double(q : qword): double; compilerproc;
  1272. begin
  1273. result:=dword(q and $ffffffff)+dword(q shr 32)*double(4294967296.0);
  1274. end;
  1275. {$endif FPC_SYSTEM_HAS_INT64_TO_DOUBLE}
  1276. {$ifndef FPC_SYSTEM_HAS_INT64_TO_DOUBLE}
  1277. function fpc_int64_to_double(i : int64): double; compilerproc;
  1278. begin
  1279. if i<0 then
  1280. result:=-double(qword(-i))
  1281. else
  1282. result:=qword(i);
  1283. end;
  1284. {$endif FPC_SYSTEM_HAS_INT64_TO_DOUBLE}
  1285. {$endif FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
  1286. {$ifdef SUPPORT_DOUBLE}
  1287. {****************************************************************************
  1288. Helper routines to support old TP styled reals
  1289. ****************************************************************************}
  1290. {$ifndef FPC_SYSTEM_HAS_REAL2DOUBLE}
  1291. function real2double(r : real48) : double;
  1292. var
  1293. res : array[0..7] of byte;
  1294. exponent : word;
  1295. begin
  1296. { check for zero }
  1297. if r[0]=0 then
  1298. begin
  1299. real2double:=0.0;
  1300. exit;
  1301. end;
  1302. { copy mantissa }
  1303. res[0]:=0;
  1304. res[1]:=r[1] shl 5;
  1305. res[2]:=(r[1] shr 3) or (r[2] shl 5);
  1306. res[3]:=(r[2] shr 3) or (r[3] shl 5);
  1307. res[4]:=(r[3] shr 3) or (r[4] shl 5);
  1308. res[5]:=(r[4] shr 3) or (r[5] and $7f) shl 5;
  1309. res[6]:=(r[5] and $7f) shr 3;
  1310. { copy exponent }
  1311. { correct exponent: }
  1312. exponent:=(word(r[0])+(1023-129));
  1313. res[6]:=res[6] or ((exponent and $f) shl 4);
  1314. res[7]:=exponent shr 4;
  1315. { set sign }
  1316. res[7]:=res[7] or (r[5] and $80);
  1317. real2double:=double(res);
  1318. end;
  1319. {$endif FPC_SYSTEM_HAS_REAL2DOUBLE}
  1320. {$endif SUPPORT_DOUBLE}
  1321. {$ifdef SUPPORT_EXTENDED}
  1322. { fast 10^n routine }
  1323. function FPower10(val: Extended; Power: Longint): Extended;
  1324. const
  1325. pow32 : array[0..31] of extended =
  1326. (
  1327. 1e0,1e1,1e2,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,
  1328. 1e11,1e12,1e13,1e14,1e15,1e16,1e17,1e18,1e19,1e20,
  1329. 1e21,1e22,1e23,1e24,1e25,1e26,1e27,1e28,1e29,1e30,
  1330. 1e31
  1331. );
  1332. pow512 : array[0..15] of extended =
  1333. (
  1334. 1,1e32,1e64,1e96,1e128,1e160,1e192,1e224,
  1335. 1e256,1e288,1e320,1e352,1e384,1e416,1e448,
  1336. 1e480
  1337. );
  1338. pow4096 : array[0..9] of extended =
  1339. (1,1e512,1e1024,1e1536,
  1340. 1e2048,1e2560,1e3072,1e3584,
  1341. 1e4096,1e4608
  1342. );
  1343. negpow32 : array[0..31] of extended =
  1344. (
  1345. 1e-0,1e-1,1e-2,1e-3,1e-4,1e-5,1e-6,1e-7,1e-8,1e-9,1e-10,
  1346. 1e-11,1e-12,1e-13,1e-14,1e-15,1e-16,1e-17,1e-18,1e-19,1e-20,
  1347. 1e-21,1e-22,1e-23,1e-24,1e-25,1e-26,1e-27,1e-28,1e-29,1e-30,
  1348. 1e-31
  1349. );
  1350. negpow512 : array[0..15] of extended =
  1351. (
  1352. 0,1e-32,1e-64,1e-96,1e-128,1e-160,1e-192,1e-224,
  1353. 1e-256,1e-288,1e-320,1e-352,1e-384,1e-416,1e-448,
  1354. 1e-480
  1355. );
  1356. negpow4096 : array[0..9] of extended =
  1357. (
  1358. 0,1e-512,1e-1024,1e-1536,
  1359. 1e-2048,1e-2560,1e-3072,1e-3584,
  1360. 1e-4096,1e-4608
  1361. );
  1362. begin
  1363. if Power<0 then
  1364. begin
  1365. Power:=-Power;
  1366. result:=val*negpow32[Power and $1f];
  1367. power:=power shr 5;
  1368. if power<>0 then
  1369. begin
  1370. result:=result*negpow512[Power and $f];
  1371. power:=power shr 4;
  1372. if power<>0 then
  1373. begin
  1374. if power<=9 then
  1375. result:=result*negpow4096[Power]
  1376. else
  1377. result:=1.0/0.0;
  1378. end;
  1379. end;
  1380. end
  1381. else
  1382. begin
  1383. result:=val*pow32[Power and $1f];
  1384. power:=power shr 5;
  1385. if power<>0 then
  1386. begin
  1387. result:=result*pow512[Power and $f];
  1388. power:=power shr 4;
  1389. if power<>0 then
  1390. begin
  1391. if power<=9 then
  1392. result:=result*pow4096[Power]
  1393. else
  1394. result:=1.0/0.0;
  1395. end;
  1396. end;
  1397. end;
  1398. end;
  1399. {$endif SUPPORT_EXTENDED}