math.inc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. {$define FPC_SYSTEM_HAS_PI}
  34. function pi : extended;[internproc:in_pi];
  35. {$define FPC_SYSTEM_HAS_ABS}
  36. function abs(d : extended) : extended;[internproc:in_abs_extended];
  37. {$define FPC_SYSTEM_HAS_SQR}
  38. function sqr(d : extended) : extended;[internproc:in_sqr_extended];
  39. {$define FPC_SYSTEM_HAS_SQRT}
  40. function sqrt(d : extended) : extended;[internproc:in_sqrt_extended];
  41. {$define FPC_SYSTEM_HAS_ARCTAN}
  42. function arctan(d : extended) : extended;[internproc:in_arctan_extended];
  43. {$define FPC_SYSTEM_HAS_LN}
  44. function ln(d : extended) : extended;[internproc:in_ln_extended];
  45. {$define FPC_SYSTEM_HAS_SIN}
  46. function sin(d : extended) : extended;[internproc:in_sin_extended];
  47. {$define FPC_SYSTEM_HAS_COS}
  48. function cos(d : extended) : extended;[internproc:in_cos_extended];
  49. {$define FPC_SYSTEM_HAS_EXP}
  50. function exp(d : extended) : extended;assembler;[internconst:in_const_exp];
  51. asm
  52. // comes from DJ GPP
  53. fldt d
  54. fldl2e
  55. fmulp %st,%st(1)
  56. fstcw .LCW1
  57. fstcw .LCW2
  58. andw $0xf3ff,.LCW2
  59. orw $0x0400,.LCW2
  60. fldcw .LCW2
  61. fld %st(0)
  62. frndint
  63. fldcw .LCW1
  64. fxch %st(1)
  65. fsub %st(1),%st
  66. f2xm1
  67. fld1
  68. faddp %st,%st(1)
  69. fscale
  70. fstp %st(1)
  71. jmp .LCW3
  72. // store some help data in the data segment
  73. .data
  74. .LCW1:
  75. .word 0
  76. .LCW2:
  77. .word 0
  78. .text
  79. .LCW3:
  80. end;
  81. {$define FPC_SYSTEM_HAS_FRAC}
  82. function frac(d : extended) : extended;assembler;[internconst:in_const_frac];
  83. asm
  84. subl $16,%esp
  85. fnstcw -4(%ebp)
  86. fwait
  87. movw -4(%ebp),%cx
  88. orw $0x0c3f,%cx
  89. movw %cx,-8(%ebp)
  90. fldcw -8(%ebp)
  91. fwait
  92. fldt d
  93. frndint
  94. fldt d
  95. fsub %st(1),%st
  96. fstp %st(1)
  97. fclex
  98. fldcw -4(%ebp)
  99. end;
  100. {$define FPC_SYSTEM_HAS_INT}
  101. function int(d : extended) : extended;assembler;[internconst:in_const_int];
  102. asm
  103. subl $16,%esp
  104. fnstcw -4(%ebp)
  105. fwait
  106. movw -4(%ebp),%cx
  107. orw $0x0c3f,%cx
  108. movw %cx,-8(%ebp)
  109. fldcw -8(%ebp)
  110. fwait
  111. fldt d
  112. frndint
  113. fclex
  114. fldcw -4(%ebp)
  115. end;
  116. {$define FPC_SYSTEM_HAS_TRUNC}
  117. function trunc(d : extended) : int64;assembler;[internconst:in_const_trunc];
  118. var
  119. oldcw,
  120. newcw : word;
  121. res : int64;
  122. asm
  123. fnstcw oldcw
  124. fwait
  125. movw oldcw,%cx
  126. orw $0x0c3f,%cx
  127. movw %cx,newcw
  128. fldcw newcw
  129. fwait
  130. fldt d
  131. fistpq res
  132. movl res,%eax
  133. movl res+4,%edx
  134. fclex
  135. fldcw oldcw
  136. end;
  137. {$define FPC_SYSTEM_HAS_ROUND}
  138. {$ifdef hascompilerproc}
  139. function round(d : extended) : int64;[internconst:in_const_round, external name 'FPC_ROUND'];
  140. function fpc_round(d : extended) : int64;assembler;[public, alias:'FPC_ROUND'];{$ifdef hascompilerproc}compilerproc;{$endif hascompilerproc}
  141. {$else}
  142. function round(d : extended) : int64;assembler;[internconst:in_const_round];
  143. {$endif hascompilerproc}
  144. var
  145. oldcw,
  146. newcw : word;
  147. res : int64;
  148. asm
  149. fnstcw oldcw
  150. fwait
  151. movw $0x1372,newcw
  152. fclex
  153. fldcw newcw
  154. fwait
  155. fldt d
  156. fistpq res
  157. movl res,%eax
  158. movl res+4,%edx
  159. fclex
  160. fldcw oldcw
  161. end;
  162. {$define FPC_SYSTEM_HAS_POWER}
  163. function power(bas,expo : extended) : extended;
  164. begin
  165. if bas=0 then
  166. begin
  167. if expo<>0 then
  168. power:=0.0
  169. else
  170. HandleError(207);
  171. end
  172. else if expo=0 then
  173. power:=1
  174. else
  175. { bas < 0 is not allowed when doing roots }
  176. if (bas<0) and (frac(expo) <> 0) then
  177. handleerror(207)
  178. else
  179. begin
  180. power:=exp(ln(abs(bas))*expo);
  181. if (bas < 0) and
  182. odd(trunc(expo)) then
  183. begin
  184. power := -power;
  185. end;
  186. end;
  187. end;
  188. {
  189. $Log$
  190. Revision 1.19 2004-07-09 23:06:11 peter
  191. * add fclex for fpu exceptions to round/trunc
  192. Revision 1.18 2003/11/29 16:40:12 jonas
  193. * fix power() for negative base
  194. Revision 1.17 2003/11/24 21:57:43 michael
  195. + Patch from Johannes Berg for bug 2759
  196. Revision 1.16 2003/11/11 21:08:17 peter
  197. * REGCALL define added
  198. Revision 1.15 2003/09/08 18:21:37 peter
  199. * save edi,esi,ebx
  200. Revision 1.14 2003/04/23 21:28:21 peter
  201. * fpc_round added, needed for int64 currency
  202. Revision 1.13 2003/02/05 19:53:17 carl
  203. * round bugfix with -Or switch
  204. Revision 1.12 2003/01/15 00:45:17 peter
  205. * use generic int64 power
  206. Revision 1.11 2003/01/15 00:40:18 peter
  207. * power returns int64
  208. Revision 1.10 2003/01/03 20:34:02 peter
  209. * i386 fpu controlword functions added
  210. Revision 1.9 2002/10/06 21:26:17 peter
  211. * round returns int64
  212. Revision 1.8 2002/09/07 16:01:19 peter
  213. * old logs removed and tabs fixed
  214. }