math.inc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2001 by the Free Pascal development team
  4. Implementation of mathematical routines (for extended type)
  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. FPU Control word
  13. ****************************************************************************}
  14. procedure Set8087CW(cw:word);
  15. begin
  16. { pic-safe ; cw will not be a regvar because it's accessed from }
  17. { assembler }
  18. default8087cw:=cw;
  19. asm
  20. fnclex
  21. fldcw cw
  22. end;
  23. end;
  24. function Get8087CW:word;assembler;
  25. asm
  26. pushl $0
  27. fnstcw (%esp)
  28. popl %eax
  29. end;
  30. procedure SetSSECSR(w : dword);
  31. begin
  32. mxcsr:=w;
  33. asm
  34. ldmxcsr w
  35. end;
  36. end;
  37. function GetSSECSR : dword;
  38. var
  39. _w : dword;
  40. begin
  41. asm
  42. stmxcsr _w
  43. end;
  44. result:=_w;
  45. end;
  46. {****************************************************************************
  47. EXTENDED data type routines
  48. ****************************************************************************}
  49. {$define FPC_SYSTEM_HAS_ABS}
  50. function fpc_abs_real(d : ValReal) : ValReal;compilerproc;
  51. begin
  52. { Function is handled internal in the compiler }
  53. runerror(207);
  54. result:=0;
  55. end;
  56. {$define FPC_SYSTEM_HAS_SQR}
  57. function fpc_sqr_real(d : ValReal) : ValReal;compilerproc;
  58. begin
  59. { Function is handled internal in the compiler }
  60. runerror(207);
  61. result:=0;
  62. end;
  63. {$define FPC_SYSTEM_HAS_SQRT}
  64. function fpc_sqrt_real(d : ValReal) : ValReal;compilerproc;
  65. begin
  66. { Function is handled internal in the compiler }
  67. runerror(207);
  68. result:=0;
  69. end;
  70. {$define FPC_SYSTEM_HAS_ARCTAN}
  71. function fpc_arctan_real(d : ValReal) : ValReal;compilerproc;
  72. begin
  73. { Function is handled internal in the compiler }
  74. runerror(207);
  75. result:=0;
  76. end;
  77. {$define FPC_SYSTEM_HAS_LN}
  78. function fpc_ln_real(d : ValReal) : ValReal;compilerproc;
  79. begin
  80. { Function is handled internal in the compiler }
  81. runerror(207);
  82. result:=0;
  83. end;
  84. {$define FPC_SYSTEM_HAS_SIN}
  85. function fpc_sin_real(d : ValReal) : ValReal;compilerproc;
  86. begin
  87. { Function is handled internal in the compiler }
  88. runerror(207);
  89. result:=0;
  90. end;
  91. {$define FPC_SYSTEM_HAS_COS}
  92. function fpc_cos_real(d : ValReal) : ValReal;compilerproc;
  93. begin
  94. { Function is handled internal in the compiler }
  95. runerror(207);
  96. result:=0;
  97. end;
  98. {$define FPC_SYSTEM_HAS_EXP}
  99. { exp function adapted from AMath library (C) Copyright 2009-2013 Wolfgang Ehrhardt }
  100. function fpc_exp_real(d : ValReal) : ValReal;assembler;compilerproc;
  101. asm
  102. fldt d
  103. fldl2e
  104. fmul %st(1),%st { z = d * log2(e) }
  105. frndint
  106. { Calculate frac(z) using modular arithmetic to avoid precision loss.
  107. Avoid PIC hacks by using immediate operands (it's not the fastest,
  108. but likely the cleanest solution). }
  109. pushl $0x3fe62e42 { ln(2).hi=6.9314718036912382E-001 }
  110. pushl $0xfee00000
  111. fldl (%esp)
  112. fmul %st(1),%st
  113. fsubrp %st,%st(2)
  114. pushl $0x3dea39ef { ln(2).lo=1.9082149292705877E-010 }
  115. pushl $0x35793c76
  116. fldl (%esp)
  117. fmul %st(1),%st
  118. fsubrp %st,%st(2)
  119. fxch %st(1) { (d-int(z)*ln2_hi)-int(z)*ln2_lo }
  120. fldl2e
  121. fmulp %st,%st(1) { frac(z) }
  122. fld %st
  123. fabs
  124. fld1
  125. fcompp
  126. fstsw %ax
  127. sahf
  128. jae .L1 { frac(z) <= 1 }
  129. fld %st(1)
  130. fabs
  131. pushl $0x46c00000 { single(24576.0) }
  132. fcomps (%esp)
  133. fstsw %ax
  134. sahf
  135. jb .L0 { int(z) < 24576 }
  136. fsub %st,%st
  137. jmp .L1
  138. .L0:
  139. { Calculate 2**frac(z)-1 as N*(N+2), where N=2**(frac(z)/2)-1 }
  140. pushl $0x3f000000 { single(0.5) }
  141. fmuls (%esp)
  142. f2xm1
  143. fld %st
  144. pushl $0x40000000 { single(2.0) }
  145. fadds (%esp)
  146. fmulp %st,%st(1)
  147. jmp .L2
  148. .L1:
  149. f2xm1
  150. .L2:
  151. fld1
  152. faddp %st,%st(1)
  153. fscale
  154. fstp %st(1)
  155. end;
  156. {$define FPC_SYSTEM_HAS_FRAC}
  157. function fpc_frac_real(d : ValReal) : ValReal;assembler;compilerproc;
  158. asm
  159. subl $4,%esp
  160. fnstcw (%esp)
  161. fwait
  162. movw (%esp),%cx
  163. orw $0x0f00,(%esp)
  164. fldcw (%esp)
  165. fldt d
  166. frndint
  167. fldt d
  168. fsub %st(1),%st
  169. fstp %st(1)
  170. movw %cx,(%esp)
  171. fldcw (%esp)
  172. end;
  173. {$define FPC_SYSTEM_HAS_INT}
  174. function fpc_int_real(d : ValReal) : ValReal;assembler;compilerproc;
  175. asm
  176. subl $4,%esp
  177. fnstcw (%esp)
  178. fwait
  179. movw (%esp),%cx
  180. orw $0x0f00,(%esp)
  181. fldcw (%esp)
  182. fwait
  183. fldt d
  184. frndint
  185. fwait
  186. movw %cx,(%esp)
  187. fldcw (%esp)
  188. end;
  189. {$define FPC_SYSTEM_HAS_TRUNC}
  190. function fpc_trunc_real(d : ValReal) : int64;assembler;compilerproc;
  191. asm
  192. subl $12,%esp
  193. fldt d
  194. fnstcw (%esp)
  195. movw (%esp),%cx
  196. orw $0x0f00,(%esp)
  197. fldcw (%esp)
  198. movw %cx,(%esp)
  199. fistpq 4(%esp)
  200. fldcw (%esp)
  201. fwait
  202. movl 4(%esp),%eax
  203. movl 8(%esp),%edx
  204. end;
  205. {$define FPC_SYSTEM_HAS_ROUND}
  206. { keep for bootstrapping with 2.0.x }
  207. function fpc_round_real(d : ValReal) : int64;compilerproc;assembler;
  208. var
  209. res : int64;
  210. asm
  211. fldt d
  212. fistpq res
  213. fwait
  214. movl res,%eax
  215. movl res+4,%edx
  216. end;