genmath.inc 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2001 by Several contributors
  5. Generic mathemtical routines (on type real)
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {*************************************************************************}
  13. { Credits }
  14. {*************************************************************************}
  15. { Copyright Abandoned, 1987, Fred Fish }
  16. { }
  17. { This previously copyrighted work has been placed into the }
  18. { public domain by the author (Fred Fish) and may be freely used }
  19. { for any purpose, private or commercial. I would appreciate }
  20. { it, as a courtesy, if this notice is left in all copies and }
  21. { derivative works. Thank you, and enjoy... }
  22. { }
  23. { The author makes no warranty of any kind with respect to this }
  24. { product and explicitly disclaims any implied warranties of }
  25. { merchantability or fitness for any particular purpose. }
  26. {-------------------------------------------------------------------------}
  27. { Copyright (c) 1992 Odent Jean Philippe }
  28. { }
  29. { The source can be modified as long as my name appears and some }
  30. { notes explaining the modifications done are included in the file. }
  31. {-------------------------------------------------------------------------}
  32. { Copyright (c) 1997 Carl Eric Codere }
  33. {-------------------------------------------------------------------------}
  34. {$goto on}
  35. type
  36. TabCoef = array[0..6] of Real;
  37. const
  38. PIO2 = 1.57079632679489661923; { pi/2 }
  39. PIO4 = 7.85398163397448309616E-1; { pi/4 }
  40. SQRT2 = 1.41421356237309504880; { sqrt(2) }
  41. SQRTH = 7.07106781186547524401E-1; { sqrt(2)/2 }
  42. LOG2E = 1.4426950408889634073599; { 1/log(2) }
  43. SQ2OPI = 7.9788456080286535587989E-1; { sqrt( 2/pi )}
  44. LOGE2 = 6.93147180559945309417E-1; { log(2) }
  45. LOGSQ2 = 3.46573590279972654709E-1; { log(2)/2 }
  46. THPIO4 = 2.35619449019234492885; { 3*pi/4 }
  47. TWOOPI = 6.36619772367581343075535E-1; { 2/pi }
  48. lossth = 1.073741824e9;
  49. MAXLOG = 8.8029691931113054295988E1; { log(2**127) }
  50. MINLOG = -8.872283911167299960540E1; { log(2**-128) }
  51. DP1 = 7.85398125648498535156E-1;
  52. DP2 = 3.77489470793079817668E-8;
  53. DP3 = 2.69515142907905952645E-15;
  54. const sincof : TabCoef = (
  55. 1.58962301576546568060E-10,
  56. -2.50507477628578072866E-8,
  57. 2.75573136213857245213E-6,
  58. -1.98412698295895385996E-4,
  59. 8.33333333332211858878E-3,
  60. -1.66666666666666307295E-1, 0);
  61. coscof : TabCoef = (
  62. -1.13585365213876817300E-11,
  63. 2.08757008419747316778E-9,
  64. -2.75573141792967388112E-7,
  65. 2.48015872888517045348E-5,
  66. -1.38888888888730564116E-3,
  67. 4.16666666666665929218E-2, 0);
  68. { also necessary for Int() on systems with 64bit floats (JM) }
  69. type
  70. {$ifdef ENDIAN_LITTLE}
  71. float64 = packed record
  72. low: longint;
  73. high: longint;
  74. end;
  75. {$else}
  76. float64 = packed record
  77. high: longint;
  78. low: longint;
  79. end;
  80. {$endif}
  81. {$ifndef FPC_SYSTEM_HAS_TRUNC}
  82. type
  83. float32 = longint;
  84. flag = byte;
  85. Function extractFloat64Frac0(const a: float64): longint;
  86. Begin
  87. extractFloat64Frac0 := a.high and $000FFFFF;
  88. End;
  89. Function extractFloat64Frac1(const a: float64): longint;
  90. Begin
  91. extractFloat64Frac1 := a.low;
  92. End;
  93. Function extractFloat64Exp(const a: float64): smallint;
  94. Begin
  95. extractFloat64Exp:= ( a.high shr 20 ) AND $7FF;
  96. End;
  97. Function extractFloat64Frac(const a: float64): int64;
  98. Begin
  99. extractFloat64Frac:=int64(a) and $000FFFFFFFFFFFFF;
  100. End;
  101. Function extractFloat64Sign(const a: float64) : flag;
  102. Begin
  103. extractFloat64Sign := a.high shr 31;
  104. End;
  105. Procedure shortShift64Left(a0:longint; a1:longint; count:smallint; VAR z0Ptr:longint; VAR z1Ptr:longint );
  106. Begin
  107. z1Ptr := a1 shl count;
  108. if count = 0 then
  109. z0Ptr := a0
  110. else
  111. z0Ptr := ( a0 shl count ) OR ( a1 shr ( ( - count ) AND 31 ) );
  112. End;
  113. function float64_to_int32_round_to_zero(a: float64 ): longint;
  114. Var
  115. aSign: flag;
  116. aExp, shiftCount: smallint;
  117. aSig0, aSig1, absZ, aSigExtra: longint;
  118. z: longint;
  119. Begin
  120. aSig1 := extractFloat64Frac1( a );
  121. aSig0 := extractFloat64Frac0( a );
  122. aExp := extractFloat64Exp( a );
  123. aSign := extractFloat64Sign( a );
  124. shiftCount := aExp - $413;
  125. if 0<=shiftCount then
  126. Begin
  127. if (aExp=$7FF) and ((aSig0 or aSig1)<>0) then
  128. HandleError(207);
  129. shortShift64Left(aSig0 OR $00100000, aSig1, shiftCount, absZ, aSigExtra );
  130. End
  131. else
  132. Begin
  133. if aExp<$3FF then
  134. begin
  135. float64_to_int32_round_to_zero := 0;
  136. exit;
  137. end;
  138. aSig0 := aSig0 or $00100000;
  139. aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR aSig1;
  140. absZ := aSig0 shr ( - shiftCount );
  141. End;
  142. if aSign<>0 then
  143. z:=-absZ
  144. else
  145. z:=absZ;
  146. if ((aSign<>0) xor (z<0)) AND (z<>0) then
  147. HandleError(207);
  148. float64_to_int32_round_to_zero := z;
  149. End;
  150. {$ifndef VER1_0}
  151. function float64_to_int64_round_to_zero(a : float64) : int64;
  152. var
  153. aSign : flag;
  154. aExp, shiftCount : smallint;
  155. aSig : int64;
  156. z : int64;
  157. begin
  158. aSig:=extractFloat64Frac(a);
  159. aExp:=extractFloat64Exp(a);
  160. aSign:=extractFloat64Sign(a);
  161. if aExp<>0 then
  162. aSig:=aSig or $0010000000000000;
  163. shiftCount:= aExp-$433;
  164. if 0<=shiftCount then
  165. begin
  166. if aExp>=$43e then
  167. begin
  168. if int64(a)<>$C3E0000000000000 then
  169. HandleError(207);
  170. { pascal doesn't know Inf for int64 }
  171. HandleError(207);
  172. end;
  173. z:=aSig shl shiftCount;
  174. end
  175. else
  176. begin
  177. if aExp<$3fe then
  178. begin
  179. result:=0;
  180. exit;
  181. end;
  182. z:=aSig shr -shiftCount;
  183. {
  184. if (aSig shl (shiftCount and 63))<>0 then
  185. float_exception_flags |= float_flag_inexact;
  186. }
  187. end;
  188. if aSign<>0 then
  189. z:=-z;
  190. result:=z;
  191. end;
  192. {$endif VER1_0}
  193. Function ExtractFloat32Frac(a : Float32) : longint;
  194. Begin
  195. ExtractFloat32Frac := A AND $007FFFFF;
  196. End;
  197. Function extractFloat32Exp( a: float32 ): smallint;
  198. Begin
  199. extractFloat32Exp := (a shr 23) AND $FF;
  200. End;
  201. Function extractFloat32Sign( a: float32 ): Flag;
  202. Begin
  203. extractFloat32Sign := a shr 31;
  204. End;
  205. Function float32_to_int32_round_to_zero( a: Float32 ): longint;
  206. Var
  207. aSign : flag;
  208. aExp, shiftCount : smallint;
  209. aSig : longint;
  210. z : longint;
  211. Begin
  212. aSig := extractFloat32Frac( a );
  213. aExp := extractFloat32Exp( a );
  214. aSign := extractFloat32Sign( a );
  215. shiftCount := aExp - $9E;
  216. if ( 0 <= shiftCount ) then
  217. Begin
  218. if ( a <> Float32($CF000000) ) then
  219. Begin
  220. if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  221. Begin
  222. HandleError(207);
  223. exit;
  224. end;
  225. End;
  226. HandleError(207);
  227. exit;
  228. End
  229. else
  230. if ( aExp <= $7E ) then
  231. Begin
  232. float32_to_int32_round_to_zero := 0;
  233. exit;
  234. End;
  235. aSig := ( aSig or $00800000 ) shl 8;
  236. z := aSig shr ( - shiftCount );
  237. if ( aSign<>0 ) then z := - z;
  238. float32_to_int32_round_to_zero := z;
  239. End;
  240. {$ifdef INTERNCONSTINTF}
  241. function fpc_trunc_real(d : real) : int64;compilerproc;
  242. {$else}
  243. function trunc(d : real) : int64;[internconst:fpc_in_const_trunc];
  244. {$endif}
  245. var
  246. {$ifdef cpuarm}
  247. l: longint;
  248. {$endif cpuarm}
  249. f32 : float32;
  250. f64 : float64;
  251. Begin
  252. { in emulation mode the real is equal to a single }
  253. { otherwise in fpu mode, it is equal to a double }
  254. { extended is not supported yet. }
  255. if sizeof(D) > 8 then
  256. HandleError(255);
  257. if sizeof(D)=8 then
  258. begin
  259. move(d,f64,sizeof(f64));
  260. {$ifdef cpuarm}
  261. { the arm fpu has a strange opinion how a double has to be stored }
  262. l:=f64.low;
  263. f64.low:=f64.high;
  264. f64.high:=l;
  265. {$endif cpuarm}
  266. {$ifdef VER1_0}
  267. result:=float64_to_int32_round_to_zero(f64);
  268. {$else VER1_0}
  269. result:=float64_to_int64_round_to_zero(f64);
  270. {$endif VER1_0}
  271. end
  272. else
  273. begin
  274. move(d,f32,sizeof(f32));
  275. result:=float32_to_int32_round_to_zero(f32);
  276. end;
  277. end;
  278. {$endif}
  279. {$ifndef FPC_SYSTEM_HAS_INT}
  280. {$ifdef SUPPORT_DOUBLE}
  281. { straight Pascal translation of the code for __trunc() in }
  282. { the file sysdeps/libm-ieee754/s_trunc.c of glibc (JM) }
  283. {$ifdef INTERNCONSTINTF}
  284. function fpc_int_real(d: double): double;compilerproc;
  285. {$else}
  286. function int(d: double): double;[internconst:fpc_in_const_int];
  287. {$endif}
  288. var
  289. i0, j0: longint;
  290. i1: cardinal;
  291. sx: longint;
  292. f64 : float64;
  293. begin
  294. f64:=float64(d);
  295. {$ifdef cpuarm}
  296. { the arm fpu has a strange opinion how a double has to be stored }
  297. i0:=f64.low;
  298. f64.low:=f64.high;
  299. f64.high:=i0;
  300. {$endif cpuarm}
  301. i0 := f64.high;
  302. i1 := cardinal(f64.low);
  303. sx := i0 and $80000000;
  304. j0 := ((i0 shr 20) and $7ff) - $3ff;
  305. if (j0 < 20) then
  306. begin
  307. if (j0 < 0) then
  308. begin
  309. { the magnitude of the number is < 1 so the result is +-0. }
  310. f64.high := sx;
  311. f64.low := 0;
  312. end
  313. else
  314. begin
  315. f64.high := sx or (i0 and not($fffff shr j0));
  316. f64.low := 0;
  317. end
  318. end
  319. else if (j0 > 51) then
  320. begin
  321. if (j0 = $400) then
  322. { d is inf or NaN }
  323. exit(d + d); { don't know why they do this (JM) }
  324. end
  325. else
  326. begin
  327. f64.high := i0;
  328. f64.low := longint(i1 and not(cardinal($ffffffff) shr (j0 - 20)));
  329. end;
  330. {$ifdef cpuarm}
  331. { the arm fpu has a strange opinion how a double has to be stored }
  332. i0:=f64.low;
  333. f64.low:=f64.high;
  334. f64.high:=i0;
  335. {$endif cpuarm}
  336. result:=double(f64);
  337. end;
  338. {$else SUPPORT_DOUBLE}
  339. {$ifdef INTERNCONSTINTF}
  340. function fpc_int_real(d : real) : real;compilerproc;
  341. {$else}
  342. function int(d : real) : real;[internconst:fpc_in_const_int];
  343. {$endif}
  344. begin
  345. { this will be correct since real = single in the case of }
  346. { the motorola version of the compiler... }
  347. result:=real(trunc(d));
  348. end;
  349. {$endif SUPPORT_DOUBLE}
  350. {$endif}
  351. {$ifndef FPC_SYSTEM_HAS_ABS}
  352. {$ifdef SUPPORT_DOUBLE}
  353. {$ifdef INTERNCONSTINTF}
  354. function fpc_abs_real(d : Double) : Double;compilerproc;
  355. {$else}
  356. function abs(d : Double) : Double;[public,alias:'FPC_ABS_REAL'];
  357. {$endif}
  358. begin
  359. if (d<0.0) then
  360. result := -d
  361. else
  362. result := d ;
  363. end;
  364. {$else}
  365. {$ifdef INTERNCONSTINTF}
  366. function fpc_abs_real(d : Double) : Double;compilerproc;
  367. {$else}
  368. function abs(d : Real) : Real;[public,alias:'FPC_ABS_REAL'];
  369. {$endif}
  370. begin
  371. if (d<0.0) then
  372. result := -d
  373. else
  374. result := d ;
  375. end;
  376. {$endif}
  377. {$ifndef INTERNCONSTINTF}
  378. {$ifdef hascompilerproc}
  379. function fpc_abs_real(d:Real):Real;compilerproc; external name 'FPC_ABS_REAL';
  380. {$endif hascompilerproc}
  381. {$endif}
  382. {$endif not FPC_SYSTEM_HAS_ABS}
  383. {$ifndef SYSTEM_HAS_FREXP}
  384. function frexp(x:Real; var e:Integer ):Real;
  385. {* frexp() extracts the exponent from x. It returns an integer *}
  386. {* power of two to expnt and the significand between 0.5 and 1 *}
  387. {* to y. Thus x = y * 2**expn. *}
  388. begin
  389. e :=0;
  390. if (abs(x)<0.5) then
  391. While (abs(x)<0.5) do
  392. begin
  393. x := x*2;
  394. Dec(e);
  395. end
  396. else
  397. While (abs(x)>1) do
  398. begin
  399. x := x/2;
  400. Inc(e);
  401. end;
  402. frexp := x;
  403. end;
  404. {$endif not SYSTEM_HAS_FREXP}
  405. {$ifndef SYSTEM_HAS_LDEXP}
  406. function ldexp( x: Real; N: Integer):Real;
  407. {* ldexp() multiplies x by 2**n. *}
  408. var r : Real;
  409. begin
  410. R := 1;
  411. if N>0 then
  412. while N>0 do
  413. begin
  414. R:=R*2;
  415. Dec(N);
  416. end
  417. else
  418. while N<0 do
  419. begin
  420. R:=R/2;
  421. Inc(N);
  422. end;
  423. ldexp := x * R;
  424. end;
  425. {$endif not SYSTEM_HAS_LDEXP}
  426. function polevl(var x:Real; var Coef:TabCoef; N:Integer):Real;
  427. {*****************************************************************}
  428. { Evaluate polynomial }
  429. {*****************************************************************}
  430. { }
  431. { SYNOPSIS: }
  432. { }
  433. { int N; }
  434. { double x, y, coef[N+1], polevl[]; }
  435. { }
  436. { y = polevl( x, coef, N ); }
  437. { }
  438. { DESCRIPTION: }
  439. { }
  440. { Evaluates polynomial of degree N: }
  441. { }
  442. { 2 N }
  443. { y = C + C x + C x +...+ C x }
  444. { 0 1 2 N }
  445. { }
  446. { Coefficients are stored in reverse order: }
  447. { }
  448. { coef[0] = C , ..., coef[N] = C . }
  449. { N 0 }
  450. { }
  451. { The function p1evl() assumes that coef[N] = 1.0 and is }
  452. { omitted from the array. Its calling arguments are }
  453. { otherwise the same as polevl(). }
  454. { }
  455. { SPEED: }
  456. { }
  457. { In the interest of speed, there are no checks for out }
  458. { of bounds arithmetic. This routine is used by most of }
  459. { the functions in the library. Depending on available }
  460. { equipment features, the user may wish to rewrite the }
  461. { program in microcode or assembly language. }
  462. {*****************************************************************}
  463. var ans : Real;
  464. i : Integer;
  465. begin
  466. ans := Coef[0];
  467. for i:=1 to N do
  468. ans := ans * x + Coef[i];
  469. polevl:=ans;
  470. end;
  471. function p1evl(var x:Real; var Coef:TabCoef; N:Integer):Real;
  472. { }
  473. { Evaluate polynomial when coefficient of x is 1.0. }
  474. { Otherwise same as polevl. }
  475. { }
  476. var
  477. ans : Real;
  478. i : Integer;
  479. begin
  480. ans := x + Coef[0];
  481. for i:=1 to N-1 do
  482. ans := ans * x + Coef[i];
  483. p1evl := ans;
  484. end;
  485. {$ifndef FPC_SYSTEM_HAS_SQR}
  486. {$ifdef INTERNCONSTINTF}
  487. function fpc_sqr_real(d : Real) : Real;compilerproc;{$ifdef MATHINLINE}inline;{$endif}
  488. {$else}
  489. function sqr(d : Real) : Real;[internconst:fpc_in_const_sqr];
  490. {$endif}
  491. begin
  492. result := d*d;
  493. end;
  494. {$endif}
  495. {$ifndef FPC_SYSTEM_HAS_PI}
  496. {$ifdef INTERNCONSTINTF}
  497. function fpc_pi_real : Real;compilerproc;{$ifdef MATHINLINE}inline;{$endif}
  498. {$else}
  499. function pi : Real;[internconst:fpc_in_const_pi];
  500. {$endif}
  501. begin
  502. result := 3.1415926535897932385;
  503. end;
  504. {$endif}
  505. {$ifndef FPC_SYSTEM_HAS_SQRT}
  506. {$ifdef INTERNCONSTINTF}
  507. function fpc_sqrt_real(d:Real):Real;compilerproc;
  508. {$else}
  509. {$ifdef hascompilerproc}
  510. function fpc_sqrt_real(d:Real):Real;compilerproc; external name 'FPC_SQRT_REAL';
  511. {$endif hascompilerproc}
  512. function sqrt(d:Real):Real;[internconst:fpc_in_const_sqrt];[public, alias: 'FPC_SQRT_REAL'];
  513. {$endif}
  514. {*****************************************************************}
  515. { Square root }
  516. {*****************************************************************}
  517. { }
  518. { SYNOPSIS: }
  519. { }
  520. { double x, y, sqrt(); }
  521. { }
  522. { y = sqrt( x ); }
  523. { }
  524. { DESCRIPTION: }
  525. { }
  526. { Returns the square root of x. }
  527. { }
  528. { Range reduction involves isolating the power of two of the }
  529. { argument and using a polynomial approximation to obtain }
  530. { a rough value for the square root. Then Heron's iteration }
  531. { is used three times to converge to an accurate value. }
  532. {*****************************************************************}
  533. var e : Integer;
  534. w,z : Real;
  535. begin
  536. if( d <= 0.0 ) then
  537. begin
  538. if( d < 0.0 ) then
  539. HandleError(207);
  540. result := 0.0;
  541. end
  542. else
  543. begin
  544. w := d;
  545. { separate exponent and significand }
  546. z := frexp( d, e );
  547. { approximate square root of number between 0.5 and 1 }
  548. { relative error of approximation = 7.47e-3 }
  549. d := 4.173075996388649989089E-1 + 5.9016206709064458299663E-1 * z;
  550. { adjust for odd powers of 2 }
  551. if odd(e) then
  552. d := d*SQRT2;
  553. { re-insert exponent }
  554. d := ldexp( d, (e div 2) );
  555. { Newton iterations: }
  556. d := 0.5*(d + w/d);
  557. d := 0.5*(d + w/d);
  558. d := 0.5*(d + w/d);
  559. d := 0.5*(d + w/d);
  560. d := 0.5*(d + w/d);
  561. d := 0.5*(d + w/d);
  562. result := d;
  563. end;
  564. end;
  565. {$endif}
  566. {$ifndef FPC_SYSTEM_HAS_EXP}
  567. {$ifdef INTERNCONSTINTF}
  568. function fpc_exp_real(d:Real):Real;compilerproc;
  569. {$else}
  570. function Exp(d:Real):Real;[internconst:fpc_in_const_exp];
  571. {$endif}
  572. {*****************************************************************}
  573. { Exponential Function }
  574. {*****************************************************************}
  575. { }
  576. { SYNOPSIS: }
  577. { }
  578. { double x, y, exp(); }
  579. { }
  580. { y = exp( x ); }
  581. { }
  582. { DESCRIPTION: }
  583. { }
  584. { Returns e (2.71828...) raised to the x power. }
  585. { }
  586. { Range reduction is accomplished by separating the argument }
  587. { into an integer k and fraction f such that }
  588. { }
  589. { x k f }
  590. { e = 2 e. }
  591. { }
  592. { A Pade' form of degree 2/3 is used to approximate exp(f)- 1 }
  593. { in the basic range [-0.5 ln 2, 0.5 ln 2]. }
  594. {*****************************************************************}
  595. const P : TabCoef = (
  596. 1.26183092834458542160E-4,
  597. 3.02996887658430129200E-2,
  598. 1.00000000000000000000E0, 0, 0, 0, 0);
  599. Q : TabCoef = (
  600. 3.00227947279887615146E-6,
  601. 2.52453653553222894311E-3,
  602. 2.27266044198352679519E-1,
  603. 2.00000000000000000005E0, 0 ,0 ,0);
  604. C1 = 6.9335937500000000000E-1;
  605. C2 = 2.1219444005469058277E-4;
  606. var n : Integer;
  607. px, qx, xx : Real;
  608. begin
  609. if( d > MAXLOG) then
  610. HandleError(205)
  611. else
  612. if( d < MINLOG ) then
  613. begin
  614. HandleError(205);
  615. end
  616. else
  617. begin
  618. { Express e**x = e**g 2**n }
  619. { = e**g e**( n loge(2) ) }
  620. { = e**( g + n loge(2) ) }
  621. px := d * LOG2E;
  622. qx := Trunc( px + 0.5 ); { Trunc() truncates toward -infinity. }
  623. n := Trunc(qx);
  624. d := d - qx * C1;
  625. d := d + qx * C2;
  626. { rational approximation for exponential }
  627. { of the fractional part: }
  628. { e**x - 1 = 2x P(x**2)/( Q(x**2) - P(x**2) ) }
  629. xx := d * d;
  630. px := d * polevl( xx, P, 2 );
  631. d := px/( polevl( xx, Q, 3 ) - px );
  632. d := ldexp( d, 1 );
  633. d := d + 1.0;
  634. d := ldexp( d, n );
  635. result := d;
  636. end;
  637. end;
  638. {$endif}
  639. {$ifndef FPC_SYSTEM_HAS_ROUND}
  640. {$ifdef INTERNCONSTINTF}
  641. function fpc_round_real(d : Real) : int64;compilerproc;
  642. {$else}
  643. {$ifdef hascompilerproc}
  644. function round(d : Real) : int64;{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_round];{$endif} external name 'FPC_ROUND';
  645. function fpc_round(d : Real) : int64;[public, alias:'FPC_ROUND'];{$ifdef hascompilerproc}compilerproc;{$endif hascompilerproc}
  646. {$else}
  647. function round(d : Real) : int64;{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_round];{$endif}
  648. {$endif hascompilerproc}
  649. {$endif}
  650. var
  651. fr: Real;
  652. tr: Int64;
  653. Begin
  654. fr := abs(Frac(d));
  655. tr := Trunc(d);
  656. if fr > 0.5 then
  657. if d >= 0 then
  658. result:=tr+1
  659. else
  660. result:=tr-1
  661. else
  662. if fr < 0.5 then
  663. result:=tr
  664. else { fr = 0.5 }
  665. { check sign to decide ... }
  666. { as in Turbo Pascal... }
  667. if d >= 0.0 then
  668. result:=tr+1
  669. else
  670. result:=tr;
  671. end;
  672. {$endif}
  673. {$ifdef FPC_CURRENCY_IS_INT64}
  674. function trunc(c : currency) : int64;
  675. type
  676. tmyrec = record
  677. i: int64;
  678. end;
  679. begin
  680. result := int64(tmyrec(c)) div 10000
  681. end;
  682. function trunc(c : comp) : int64;
  683. begin
  684. result := c
  685. end;
  686. function round(c : currency) : int64;
  687. type
  688. tmyrec = record
  689. i: int64;
  690. end;
  691. var
  692. rem, absrem: longint;
  693. begin
  694. { (int64(tmyrec(c))(+/-)5000) div 10000 can overflow }
  695. result := int64(tmyrec(c)) div 10000;
  696. rem := int64(tmyrec(c)) - result * 10000;
  697. absrem := abs(rem);
  698. if (absrem > 5000) or
  699. ((absrem = 5000) and
  700. (rem > 0)) then
  701. if (rem > 0) then
  702. inc(result)
  703. else
  704. dec(result);
  705. end;
  706. function round(c : comp) : int64;
  707. begin
  708. result := c
  709. end;
  710. {$endif FPC_CURRENCY_IS_INT64}
  711. {$ifndef FPC_SYSTEM_HAS_LN}
  712. {$ifdef INTERNCONSTINTF}
  713. function fpc_ln_real(d:Real):Real;compilerproc;
  714. {$else}
  715. function Ln(d:Real):Real;[internconst:fpc_in_const_ln];
  716. {$endif}
  717. {*****************************************************************}
  718. { Natural Logarithm }
  719. {*****************************************************************}
  720. { }
  721. { SYNOPSIS: }
  722. { }
  723. { double x, y, log(); }
  724. { }
  725. { y = ln( x ); }
  726. { }
  727. { DESCRIPTION: }
  728. { }
  729. { Returns the base e (2.718...) logarithm of x. }
  730. { }
  731. { The argument is separated into its exponent and fractional }
  732. { parts. If the exponent is between -1 and +1, the logarithm }
  733. { of the fraction is approximated by }
  734. { }
  735. { log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x). }
  736. { }
  737. { Otherwise, setting z = 2(x-1)/x+1), }
  738. { }
  739. { log(x) = z + z**3 P(z)/Q(z). }
  740. { }
  741. {*****************************************************************}
  742. const P : TabCoef = (
  743. { Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
  744. 1/sqrt(2) <= x < sqrt(2) }
  745. 4.58482948458143443514E-5,
  746. 4.98531067254050724270E-1,
  747. 6.56312093769992875930E0,
  748. 2.97877425097986925891E1,
  749. 6.06127134467767258030E1,
  750. 5.67349287391754285487E1,
  751. 1.98892446572874072159E1);
  752. Q : TabCoef = (
  753. 1.50314182634250003249E1,
  754. 8.27410449222435217021E1,
  755. 2.20664384982121929218E2,
  756. 3.07254189979530058263E2,
  757. 2.14955586696422947765E2,
  758. 5.96677339718622216300E1, 0);
  759. { Coefficients for log(x) = z + z**3 P(z)/Q(z),
  760. where z = 2(x-1)/(x+1)
  761. 1/sqrt(2) <= x < sqrt(2) }
  762. R : TabCoef = (
  763. -7.89580278884799154124E-1,
  764. 1.63866645699558079767E1,
  765. -6.41409952958715622951E1, 0, 0, 0, 0);
  766. S : TabCoef = (
  767. -3.56722798256324312549E1,
  768. 3.12093766372244180303E2,
  769. -7.69691943550460008604E2, 0, 0, 0, 0);
  770. var e : Integer;
  771. z, y : Real;
  772. Label Ldone;
  773. begin
  774. if( d <= 0.0 ) then
  775. HandleError(207);
  776. d := frexp( d, e );
  777. { logarithm using log(x) = z + z**3 P(z)/Q(z),
  778. where z = 2(x-1)/x+1) }
  779. if( (e > 2) or (e < -2) ) then
  780. begin
  781. if( d < SQRTH ) then
  782. begin
  783. { 2( 2x-1 )/( 2x+1 ) }
  784. Dec(e, 1);
  785. z := d - 0.5;
  786. y := 0.5 * z + 0.5;
  787. end
  788. else
  789. begin
  790. { 2 (x-1)/(x+1) }
  791. z := d - 0.5;
  792. z := z - 0.5;
  793. y := 0.5 * d + 0.5;
  794. end;
  795. d := z / y;
  796. { /* rational form */ }
  797. z := d*d;
  798. z := d + d * ( z * polevl( z, R, 2 ) / p1evl( z, S, 3 ) );
  799. goto ldone;
  800. end;
  801. { logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) }
  802. if( d < SQRTH ) then
  803. begin
  804. Dec(e, 1);
  805. d := ldexp( d, 1 ) - 1.0; { 2x - 1 }
  806. end
  807. else
  808. d := d - 1.0;
  809. { rational form }
  810. z := d*d;
  811. y := d * ( z * polevl( d, P, 6 ) / p1evl( d, Q, 6 ) );
  812. y := y - ldexp( z, -1 ); { y - 0.5 * z }
  813. z := d + y;
  814. ldone:
  815. { recombine with exponent term }
  816. if( e <> 0 ) then
  817. begin
  818. y := e;
  819. z := z - y * 2.121944400546905827679e-4;
  820. z := z + y * 0.693359375;
  821. end;
  822. result:= z;
  823. end;
  824. {$endif}
  825. {$ifndef FPC_SYSTEM_HAS_SIN}
  826. {$ifdef INTERNCONSTINTF}
  827. function fpc_Sin_real(d:Real):Real;compilerproc;
  828. {$else}
  829. function Sin(d:Real):Real;[internconst:fpc_in_const_sin];
  830. {$endif}
  831. {*****************************************************************}
  832. { Circular Sine }
  833. {*****************************************************************}
  834. { }
  835. { SYNOPSIS: }
  836. { }
  837. { double x, y, sin(); }
  838. { }
  839. { y = sin( x ); }
  840. { }
  841. { DESCRIPTION: }
  842. { }
  843. { Range reduction is into intervals of pi/4. The reduction }
  844. { error is nearly eliminated by contriving an extended }
  845. { precision modular arithmetic. }
  846. { }
  847. { Two polynomial approximating functions are employed. }
  848. { Between 0 and pi/4 the sine is approximated by }
  849. { x + x**3 P(x**2). }
  850. { Between pi/4 and pi/2 the cosine is represented as }
  851. { 1 - x**2 Q(x**2). }
  852. {*****************************************************************}
  853. var y, z, zz : Real;
  854. j, sign : Integer;
  855. begin
  856. { make argument positive but save the sign }
  857. sign := 1;
  858. if( d < 0 ) then
  859. begin
  860. d := -d;
  861. sign := -1;
  862. end;
  863. { above this value, approximate towards 0 }
  864. if( d > lossth ) then
  865. begin
  866. result := 0.0;
  867. exit;
  868. end;
  869. y := Trunc( d/PIO4 ); { integer part of x/PIO4 }
  870. { strip high bits of integer part to prevent integer overflow }
  871. z := ldexp( y, -4 );
  872. z := Trunc(z); { integer part of y/8 }
  873. z := y - ldexp( z, 4 ); { y - 16 * (y/16) }
  874. j := Trunc(z); { convert to integer for tests on the phase angle }
  875. { map zeros to origin }
  876. { typecast is to avoid "can't determine which overloaded function }
  877. { to call" }
  878. if odd( longint(j) ) then
  879. begin
  880. inc(j);
  881. y := y + 1.0;
  882. end;
  883. j := j and 7; { octant modulo 360 degrees }
  884. { reflect in x axis }
  885. if( j > 3) then
  886. begin
  887. sign := -sign;
  888. dec(j, 4);
  889. end;
  890. { Extended precision modular arithmetic }
  891. z := ((d - y * DP1) - y * DP2) - y * DP3;
  892. zz := z * z;
  893. if( (j=1) or (j=2) ) then
  894. y := 1.0 - ldexp(zz,-1) + zz * zz * polevl( zz, coscof, 5 )
  895. else
  896. { y = z + z * (zz * polevl( zz, sincof, 5 )); }
  897. y := z + z * z * z * polevl( zz, sincof, 5 );
  898. if(sign < 0) then
  899. y := -y;
  900. result := y;
  901. end;
  902. {$endif}
  903. {$ifndef FPC_SYSTEM_HAS_COS}
  904. {$ifdef INTERNCONSTINTF}
  905. function fpc_Cos_real(d:Real):Real;compilerproc;
  906. {$else}
  907. function Cos(d:Real):Real;[internconst:fpc_in_const_cos];
  908. {$endif}
  909. {*****************************************************************}
  910. { Circular cosine }
  911. {*****************************************************************}
  912. { }
  913. { Circular cosine }
  914. { }
  915. { SYNOPSIS: }
  916. { }
  917. { double x, y, cos(); }
  918. { }
  919. { y = cos( x ); }
  920. { }
  921. { DESCRIPTION: }
  922. { }
  923. { Range reduction is into intervals of pi/4. The reduction }
  924. { error is nearly eliminated by contriving an extended }
  925. { precision modular arithmetic. }
  926. { }
  927. { Two polynomial approximating functions are employed. }
  928. { Between 0 and pi/4 the cosine is approximated by }
  929. { 1 - x**2 Q(x**2). }
  930. { Between pi/4 and pi/2 the sine is represented as }
  931. { x + x**3 P(x**2). }
  932. {*****************************************************************}
  933. var y, z, zz : Real;
  934. j, sign : Integer;
  935. i : LongInt;
  936. begin
  937. { make argument positive }
  938. sign := 1;
  939. if( d < 0 ) then
  940. d := -d;
  941. { above this value, round towards zero }
  942. if( d > lossth ) then
  943. begin
  944. result := 0.0;
  945. exit;
  946. end;
  947. y := Trunc( d/PIO4 );
  948. z := ldexp( y, -4 );
  949. z := Trunc(z); { integer part of y/8 }
  950. z := y - ldexp( z, 4 ); { y - 16 * (y/16) }
  951. { integer and fractional part modulo one octant }
  952. i := Trunc(z);
  953. if odd( i ) then { map zeros to origin }
  954. begin
  955. inc(i);
  956. y := y + 1.0;
  957. end;
  958. j := i and 07;
  959. if( j > 3) then
  960. begin
  961. dec(j,4);
  962. sign := -sign;
  963. end;
  964. if( j > 1 ) then
  965. sign := -sign;
  966. { Extended precision modular arithmetic }
  967. z := ((d - y * DP1) - y * DP2) - y * DP3;
  968. zz := z * z;
  969. if( (j=1) or (j=2) ) then
  970. { y = z + z * (zz * polevl( zz, sincof, 5 )); }
  971. y := z + z * z * z * polevl( zz, sincof, 5 )
  972. else
  973. y := 1.0 - ldexp(zz,-1) + zz * zz * polevl( zz, coscof, 5 );
  974. if(sign < 0) then
  975. y := -y;
  976. result := y ;
  977. end;
  978. {$endif}
  979. {$ifndef FPC_SYSTEM_HAS_ARCTAN}
  980. {$ifdef INTERNCONSTINTF}
  981. function fpc_ArcTan_real(d:Real):Real;compilerproc;
  982. {$else}
  983. function ArcTan(d:Real):Real;[internconst:fpc_in_const_arctan];
  984. {$endif}
  985. {*****************************************************************}
  986. { Inverse circular tangent (arctangent) }
  987. {*****************************************************************}
  988. { }
  989. { SYNOPSIS: }
  990. { }
  991. { double x, y, atan(); }
  992. { }
  993. { y = atan( x ); }
  994. { }
  995. { DESCRIPTION: }
  996. { }
  997. { Returns radian angle between -pi/2 and +pi/2 whose tangent }
  998. { is x. }
  999. { }
  1000. { Range reduction is from four intervals into the interval }
  1001. { from zero to tan( pi/8 ). The approximant uses a rational }
  1002. { function of degree 3/4 of the form x + x**3 P(x)/Q(x). }
  1003. {*****************************************************************}
  1004. const P : TabCoef = (
  1005. -8.40980878064499716001E-1,
  1006. -8.83860837023772394279E0,
  1007. -2.18476213081316705724E1,
  1008. -1.48307050340438946993E1, 0, 0, 0);
  1009. Q : TabCoef = (
  1010. 1.54974124675307267552E1,
  1011. 6.27906555762653017263E1,
  1012. 9.22381329856214406485E1,
  1013. 4.44921151021319438465E1, 0, 0, 0);
  1014. { tan( 3*pi/8 ) }
  1015. T3P8 = 2.41421356237309504880;
  1016. { tan( pi/8 ) }
  1017. TP8 = 0.41421356237309504880;
  1018. var y,z : Real;
  1019. Sign : Integer;
  1020. begin
  1021. { make argument positive and save the sign }
  1022. sign := 1;
  1023. if( d < 0.0 ) then
  1024. begin
  1025. sign := -1;
  1026. d := -d;
  1027. end;
  1028. { range reduction }
  1029. if( d > T3P8 ) then
  1030. begin
  1031. y := PIO2;
  1032. d := -( 1.0/d );
  1033. end
  1034. else if( d > TP8 ) then
  1035. begin
  1036. y := PIO4;
  1037. d := (d-1.0)/(d+1.0);
  1038. end
  1039. else
  1040. y := 0.0;
  1041. { rational form in x**2 }
  1042. z := d * d;
  1043. y := y + ( polevl( z, P, 3 ) / p1evl( z, Q, 4 ) ) * z * d + d;
  1044. if( sign < 0 ) then
  1045. y := -y;
  1046. result := y;
  1047. end;
  1048. {$endif}
  1049. {$ifndef FPC_SYSTEM_HAS_FRAC}
  1050. {$ifdef INTERNCONSTINTF}
  1051. function fpc_frac_real(d : Real) : Real;compilerproc;
  1052. {$else}
  1053. function frac(d : Real) : Real;[internconst:fpc_in_const_frac];
  1054. {$endif}
  1055. begin
  1056. result := d - Int(d);
  1057. end;
  1058. {$endif}
  1059. {$ifdef FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
  1060. {$ifndef FPC_SYSTEM_HAS_QWORD_TO_DOUBLE}
  1061. function fpc_qword_to_double(q : qword): double; compilerproc;
  1062. begin
  1063. result:=dword(q and $ffffffff)+dword(q shr 32)*4294967296.0;
  1064. end;
  1065. {$endif FPC_SYSTEM_HAS_INT64_TO_DOUBLE}
  1066. {$ifndef FPC_SYSTEM_HAS_INT64_TO_DOUBLE}
  1067. function fpc_int64_to_double(i : int64): double; compilerproc;
  1068. begin
  1069. if i<0 then
  1070. result:=-double(qword(-i))
  1071. else
  1072. result:=qword(i);
  1073. end;
  1074. {$endif FPC_SYSTEM_HAS_INT64_TO_DOUBLE}
  1075. {$endif FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
  1076. {$ifdef SUPPORT_DOUBLE}
  1077. {****************************************************************************
  1078. Helper routines to support old TP styled reals
  1079. ****************************************************************************}
  1080. {$ifndef FPC_SYSTEM_HAS_REAL2DOUBLE}
  1081. function real2double(r : real48) : double;
  1082. var
  1083. res : array[0..7] of byte;
  1084. exponent : word;
  1085. begin
  1086. { copy mantissa }
  1087. res[0]:=0;
  1088. res[1]:=r[1] shl 5;
  1089. res[2]:=(r[1] shr 3) or (r[2] shl 5);
  1090. res[3]:=(r[2] shr 3) or (r[3] shl 5);
  1091. res[4]:=(r[3] shr 3) or (r[4] shl 5);
  1092. res[5]:=(r[4] shr 3) or (r[5] and $7f) shl 5;
  1093. res[6]:=(r[5] and $7f) shr 3;
  1094. { copy exponent }
  1095. { correct exponent: }
  1096. exponent:=(word(r[0])+(1023-129));
  1097. res[6]:=res[6] or ((exponent and $f) shl 4);
  1098. res[7]:=exponent shr 4;
  1099. { set sign }
  1100. res[7]:=res[7] or (r[5] and $80);
  1101. real2double:=double(res);
  1102. end;
  1103. {$endif FPC_SYSTEM_HAS_REAL2DOUBLE}
  1104. {$endif SUPPORT_DOUBLE}
  1105. {
  1106. $Log$
  1107. Revision 1.31 2005-02-08 20:25:28 florian
  1108. - killed power from system unit
  1109. * move operator ** to math unit
  1110. Revision 1.30 2004/12/05 16:43:57 jonas
  1111. * fixed power() in genmath.inc (code duplication from math.pp for **
  1112. support!)
  1113. * fixed power() in math.pp to give an error from 0^0
  1114. Revision 1.29 2004/11/21 15:35:23 peter
  1115. * float routines all use internproc and compilerproc helpers
  1116. Revision 1.28 2004/11/20 15:49:21 jonas
  1117. * some compilation fixes for powerpc after all the internconst and
  1118. internproc changes, still crashes with internalerror(88) for ppc1
  1119. on real2str.inc(193,39)
  1120. Revision 1.27 2004/10/09 21:00:46 jonas
  1121. + cgenmath with libc math functions. Faster than the routines in genmath
  1122. and also have full double support (exp() only has support for values in
  1123. the single range in genmath, for example). Used in FPC_USE_LIBC is
  1124. defined
  1125. * several fixes to allow compilation with -dHASINLINE, but internalerrors
  1126. because of missing support for inlining assembler code
  1127. Revision 1.26 2004/10/03 14:09:39 florian
  1128. * fixed trunc for abs(value) < 1
  1129. Revision 1.25 2004/10/03 14:00:21 florian
  1130. + made generic trunc 64 bit aware
  1131. Revision 1.24 2004/05/31 20:25:04 peter
  1132. * removed warnings
  1133. Revision 1.23 2004/03/13 18:33:52 florian
  1134. * fixed some arm related real stuff
  1135. Revision 1.22 2004/03/11 22:39:53 florian
  1136. * arm startup code fixed
  1137. * made some generic math code more readable
  1138. Revision 1.21 2004/02/04 14:15:57 florian
  1139. * fixed generic system.int(...)
  1140. Revision 1.20 2004/01/24 18:15:58 florian
  1141. * fixed small bugs
  1142. * fixed some arm issues
  1143. Revision 1.18 2004/01/06 21:34:07 peter
  1144. * abs(double) added
  1145. * abs() alias
  1146. Revision 1.17 2004/01/02 17:19:04 jonas
  1147. * if currency = int64, FPC_CURRENCY_IS_INT64 is defined
  1148. + round and trunc for currency and comp if FPC_CURRENCY_IS_INT64 is
  1149. defined
  1150. * if currency = orddef, prefer currency -> int64/qword conversion over
  1151. currency -> float conversions
  1152. * optimized currency/currency if currency = orddef
  1153. * TODO: write FPC_DIV_CURRENCY and FPC_MUL_CURRENCY routines to prevent
  1154. precision loss if currency=int64 and bestreal = double
  1155. Revision 1.16 2003/12/08 19:44:11 jonas
  1156. * use HandleError instead of RunError so exception catching works
  1157. Revision 1.15 2003/09/03 14:09:37 florian
  1158. * arm fixes to the common rtl code
  1159. * some generic math code fixed
  1160. * ...
  1161. Revision 1.14 2003/05/24 13:39:32 jonas
  1162. * fsqrt is an optional instruction in the ppc architecture and isn't
  1163. implemented by any current ppc afaik, so use the generic sqrt routine
  1164. instead (adapted so it works with compilerproc)
  1165. Revision 1.13 2003/05/23 22:58:31 jonas
  1166. * added longint typecase to odd(smallint_var) call to avoid overload
  1167. problem
  1168. Revision 1.12 2003/05/02 15:12:19 jonas
  1169. - removed empty ppc-specific frac()
  1170. + added correct generic frac() implementation for doubles (translated
  1171. from glibc code)
  1172. Revision 1.11 2003/04/23 21:28:21 peter
  1173. * fpc_round added, needed for int64 currency
  1174. Revision 1.10 2003/01/15 00:45:17 peter
  1175. * use generic int64 power
  1176. Revision 1.9 2002/10/12 20:28:49 carl
  1177. * round returns int64
  1178. Revision 1.8 2002/10/07 15:15:02 florian
  1179. * fixed wrong commit
  1180. Revision 1.7 2002/10/07 15:10:45 florian
  1181. + variant wrappers for cmp operators added
  1182. Revision 1.6 2002/09/07 15:07:45 peter
  1183. * old logs removed and tabs fixed
  1184. Revision 1.5 2002/07/28 21:39:29 florian
  1185. * made abs a compiler proc if it is generic
  1186. Revision 1.4 2002/07/28 20:43:48 florian
  1187. * several fixes for linux/powerpc
  1188. * several fixes to MT
  1189. }