math.inc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2001 by the Free Pascal development team
  5. Implementation of mathematical routines (for extended type)
  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. FPU Control word
  14. ****************************************************************************}
  15. procedure Set8087CW(cw:word);assembler;
  16. asm
  17. {$ifndef REGCALL}
  18. movw cw,%ax
  19. {$endif}
  20. movw %ax,default8087cw
  21. fnclex
  22. fldcw default8087cw
  23. end;
  24. function Get8087CW:word;assembler;
  25. asm
  26. pushl $0
  27. fnstcw (%esp)
  28. popl %eax
  29. end;
  30. {****************************************************************************
  31. EXTENDED data type routines
  32. ****************************************************************************}
  33. {$ifdef INTERNCONSTINTF}
  34. {$define FPC_SYSTEM_HAS_PI}
  35. function fpc_pi_real : ValReal;compilerproc;
  36. begin
  37. { Function is handled internal in the compiler }
  38. runerror(207);
  39. result:=0;
  40. end;
  41. {$define FPC_SYSTEM_HAS_ABS}
  42. function fpc_abs_real(d : ValReal) : ValReal;compilerproc;
  43. begin
  44. { Function is handled internal in the compiler }
  45. runerror(207);
  46. result:=0;
  47. end;
  48. {$define FPC_SYSTEM_HAS_SQR}
  49. function fpc_sqr_real(d : ValReal) : ValReal;compilerproc;
  50. begin
  51. { Function is handled internal in the compiler }
  52. runerror(207);
  53. result:=0;
  54. end;
  55. {$define FPC_SYSTEM_HAS_SQRT}
  56. function fpc_sqrt_real(d : ValReal) : ValReal;compilerproc;
  57. begin
  58. { Function is handled internal in the compiler }
  59. runerror(207);
  60. result:=0;
  61. end;
  62. {$define FPC_SYSTEM_HAS_ARCTAN}
  63. function fpc_arctan_real(d : ValReal) : ValReal;compilerproc;
  64. begin
  65. { Function is handled internal in the compiler }
  66. runerror(207);
  67. result:=0;
  68. end;
  69. {$define FPC_SYSTEM_HAS_LN}
  70. function fpc_ln_real(d : ValReal) : ValReal;compilerproc;
  71. begin
  72. { Function is handled internal in the compiler }
  73. runerror(207);
  74. result:=0;
  75. end;
  76. {$define FPC_SYSTEM_HAS_SIN}
  77. function fpc_sin_real(d : ValReal) : ValReal;compilerproc;
  78. begin
  79. { Function is handled internal in the compiler }
  80. runerror(207);
  81. result:=0;
  82. end;
  83. {$define FPC_SYSTEM_HAS_COS}
  84. function fpc_cos_real(d : ValReal) : ValReal;compilerproc;
  85. begin
  86. { Function is handled internal in the compiler }
  87. runerror(207);
  88. result:=0;
  89. end;
  90. {$else}
  91. {$define FPC_SYSTEM_HAS_PI}
  92. function pi : ValReal;[internproc:fpc_in_pi];
  93. {$define FPC_SYSTEM_HAS_ABS}
  94. function abs(d : ValReal) : ValReal;[internproc:fpc_in_abs_real];
  95. {$define FPC_SYSTEM_HAS_SQR}
  96. function sqr(d : ValReal) : ValReal;[internproc:fpc_in_sqr_real];
  97. {$define FPC_SYSTEM_HAS_SQRT}
  98. function sqrt(d : ValReal) : ValReal;[internproc:fpc_in_sqrt_real];
  99. {$define FPC_SYSTEM_HAS_ARCTAN}
  100. function arctan(d : ValReal) : ValReal;[internproc:fpc_in_arctan_real];
  101. {$define FPC_SYSTEM_HAS_LN}
  102. function ln(d : ValReal) : ValReal;[internproc:fpc_in_ln_real];
  103. {$define FPC_SYSTEM_HAS_SIN}
  104. function sin(d : ValReal) : ValReal;[internproc:fpc_in_sin_real];
  105. {$define FPC_SYSTEM_HAS_COS}
  106. function cos(d : ValReal) : ValReal;[internproc:fpc_in_cos_real];
  107. {$endif}
  108. {$define FPC_SYSTEM_HAS_EXP}
  109. {$ifdef INTERNCONSTINTF}
  110. function fpc_exp_real(d : ValReal) : ValReal;assembler;compilerproc;
  111. {$else}
  112. function exp(d : ValReal) : ValReal;assembler;[internconst:fpc_in_const_exp];
  113. {$endif}
  114. asm
  115. // comes from DJ GPP
  116. fldt d
  117. fldl2e
  118. fmulp %st,%st(1)
  119. fstcw .LCW1
  120. fstcw .LCW2
  121. andw $0xf3ff,.LCW2
  122. orw $0x0400,.LCW2
  123. fldcw .LCW2
  124. fld %st(0)
  125. frndint
  126. fldcw .LCW1
  127. fxch %st(1)
  128. fsub %st(1),%st
  129. f2xm1
  130. fld1
  131. faddp %st,%st(1)
  132. fscale
  133. fstp %st(1)
  134. jmp .LCW3
  135. // store some help data in the data segment
  136. .data
  137. .LCW1:
  138. .word 0
  139. .LCW2:
  140. .word 0
  141. .text
  142. .LCW3:
  143. end;
  144. {$define FPC_SYSTEM_HAS_FRAC}
  145. {$ifdef INTERNCONSTINTF}
  146. function fpc_frac_real(d : ValReal) : ValReal;assembler;compilerproc;
  147. {$else}
  148. function frac(d : ValReal) : ValReal;assembler;[internconst:fpc_in_const_frac];
  149. {$endif}
  150. asm
  151. subl $16,%esp
  152. fnstcw -4(%ebp)
  153. fwait
  154. movw -4(%ebp),%cx
  155. orw $0x0c3f,%cx
  156. movw %cx,-8(%ebp)
  157. fldcw -8(%ebp)
  158. fwait
  159. fldt d
  160. frndint
  161. fldt d
  162. fsub %st(1),%st
  163. fstp %st(1)
  164. fclex
  165. fldcw -4(%ebp)
  166. end;
  167. {$define FPC_SYSTEM_HAS_INT}
  168. {$ifdef INTERNCONSTINTF}
  169. function fpc_int_real(d : ValReal) : ValReal;assembler;compilerproc;
  170. {$else}
  171. function int(d : ValReal) : ValReal;assembler;[internconst:fpc_in_const_int];
  172. {$endif}
  173. asm
  174. subl $16,%esp
  175. fnstcw -4(%ebp)
  176. fwait
  177. movw -4(%ebp),%cx
  178. orw $0x0c3f,%cx
  179. movw %cx,-8(%ebp)
  180. fldcw -8(%ebp)
  181. fwait
  182. fldt d
  183. frndint
  184. fclex
  185. fldcw -4(%ebp)
  186. end;
  187. {$define FPC_SYSTEM_HAS_TRUNC}
  188. {$ifdef INTERNCONSTINTF}
  189. function fpc_trunc_real(d : ValReal) : int64;assembler;compilerproc;
  190. {$else}
  191. function trunc(d : ValReal) : int64;assembler;[internconst:fpc_in_const_trunc];
  192. {$endif}
  193. var
  194. oldcw,
  195. newcw : word;
  196. res : int64;
  197. asm
  198. fnstcw oldcw
  199. fwait
  200. movw oldcw,%cx
  201. orw $0x0c3f,%cx
  202. movw %cx,newcw
  203. fldcw newcw
  204. fwait
  205. fldt d
  206. fistpq res
  207. movl res,%eax
  208. movl res+4,%edx
  209. fclex
  210. fldcw oldcw
  211. end;
  212. {$define FPC_SYSTEM_HAS_ROUND}
  213. {$ifdef internconstintf}
  214. function fpc_round_real(d : ValReal) : int64;assembler;compilerproc;
  215. {$else}
  216. {$ifdef hascompilerproc}
  217. function round(d : ValReal) : int64;[internconst:fpc_in_const_round, external name 'FPC_ROUND'];
  218. function fpc_round(d : ValReal) : int64;assembler;[public, alias:'FPC_ROUND'];{$ifdef hascompilerproc}compilerproc;{$endif hascompilerproc}
  219. {$else}
  220. function round(d : ValReal) : int64;assembler;[internconst:fpc_in_const_round];
  221. {$endif hascompilerproc}
  222. {$endif}
  223. var
  224. oldcw,
  225. newcw : word;
  226. res : int64;
  227. asm
  228. fnstcw oldcw
  229. fwait
  230. movw $0x1372,newcw
  231. fclex
  232. fldcw newcw
  233. fwait
  234. fldt d
  235. fistpq res
  236. movl res,%eax
  237. movl res+4,%edx
  238. fclex
  239. fldcw oldcw
  240. end;
  241. {$define FPC_SYSTEM_HAS_POWER}
  242. function power(bas,expo : ValReal) : ValReal;
  243. begin
  244. if bas=0 then
  245. begin
  246. if expo<>0 then
  247. power:=0.0
  248. else
  249. HandleError(207);
  250. end
  251. else if expo=0 then
  252. power:=1
  253. else
  254. { bas < 0 is not allowed when doing roots }
  255. if (bas<0) and (frac(expo) <> 0) then
  256. handleerror(207)
  257. else
  258. begin
  259. power:=exp(ln(abs(bas))*expo);
  260. if (bas < 0) and
  261. odd(trunc(expo)) then
  262. begin
  263. power := -power;
  264. end;
  265. end;
  266. end;
  267. {
  268. $Log$
  269. Revision 1.21 2004-11-21 15:35:23 peter
  270. * float routines all use internproc and compilerproc helpers
  271. Revision 1.20 2004/11/17 22:19:04 peter
  272. internconst, internproc and some external declarations moved to interface
  273. Revision 1.19 2004/07/09 23:06:11 peter
  274. * add fclex for fpu exceptions to round/trunc
  275. Revision 1.18 2003/11/29 16:40:12 jonas
  276. * fix power() for negative base
  277. Revision 1.17 2003/11/24 21:57:43 michael
  278. + Patch from Johannes Berg for bug 2759
  279. Revision 1.16 2003/11/11 21:08:17 peter
  280. * REGCALL define added
  281. Revision 1.15 2003/09/08 18:21:37 peter
  282. * save edi,esi,ebx
  283. Revision 1.14 2003/04/23 21:28:21 peter
  284. * fpc_round added, needed for int64 currency
  285. Revision 1.13 2003/02/05 19:53:17 carl
  286. * round bugfix with -Or switch
  287. Revision 1.12 2003/01/15 00:45:17 peter
  288. * use generic int64 power
  289. Revision 1.11 2003/01/15 00:40:18 peter
  290. * power returns int64
  291. Revision 1.10 2003/01/03 20:34:02 peter
  292. * i386 fpu controlword functions added
  293. Revision 1.9 2002/10/06 21:26:17 peter
  294. * round returns int64
  295. Revision 1.8 2002/09/07 16:01:19 peter
  296. * old logs removed and tabs fixed
  297. }