math.inc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. {
  2. Implementation of mathematical routines for x86_64
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2005 by the Free Pascal development team
  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. Using functions from AMath/DAMath libraries, which are covered by the
  13. following license:
  14. (C) Copyright 2009-2013 Wolfgang Ehrhardt
  15. This software is provided 'as-is', without any express or implied warranty.
  16. In no event will the authors be held liable for any damages arising from
  17. the use of this software.
  18. Permission is granted to anyone to use this software for any purpose,
  19. including commercial applications, and to alter it and redistribute it
  20. freely, subject to the following restrictions:
  21. 1. The origin of this software must not be misrepresented; you must not
  22. claim that you wrote the original software. If you use this software in
  23. a product, an acknowledgment in the product documentation would be
  24. appreciated but is not required.
  25. 2. Altered source versions must be plainly marked as such, and must not be
  26. misrepresented as being the original software.
  27. 3. This notice may not be removed or altered from any source distribution.
  28. ----------------------------------------------------------------------------}
  29. {$push}
  30. {$codealign constmin=16}
  31. const
  32. FPC_ABSMASK_SINGLE: array[0..1] of qword=($7fffffff7fffffff,$7fffffff7fffffff); cvar; public;
  33. FPC_ABSMASK_DOUBLE: array[0..1] of qword=($7fffffffffffffff,$7fffffffffffffff); cvar; public;
  34. {$pop}
  35. {****************************************************************************
  36. FPU Control word
  37. ****************************************************************************}
  38. procedure Set8087CW(cw:word);
  39. begin
  40. default8087cw:=cw;
  41. asm
  42. fnclex
  43. fldcw cw
  44. end;
  45. end;
  46. function Get8087CW:word;assembler;
  47. var
  48. tmp: word;
  49. asm
  50. fnstcw tmp
  51. movw tmp,%ax
  52. andl $0xffff,%eax { clears bits 32-63 }
  53. end;
  54. procedure SetMXCSR(w : dword);
  55. begin
  56. defaultmxcsr:=w;
  57. asm
  58. ldmxcsr w
  59. end;
  60. end;
  61. function GetMXCSR : dword;assembler;
  62. var
  63. _w : dword;
  64. asm
  65. stmxcsr _w
  66. movl _w,%eax
  67. end;
  68. procedure SetSSECSR(w : dword);
  69. begin
  70. SetMXCSR(w);
  71. end;
  72. function GetSSECSR: dword;
  73. begin
  74. result:=GetMXCSR;
  75. end;
  76. {****************************************************************************
  77. EXTENDED data type routines
  78. ****************************************************************************}
  79. {$ifndef FPC_SYSTEM_HAS_ABS}
  80. {$define FPC_SYSTEM_HAS_ABS}
  81. function fpc_abs_real(d : ValReal) : ValReal;compilerproc;
  82. begin
  83. { Function is handled internal in the compiler }
  84. runerror(207);
  85. result:=0;
  86. end;
  87. {$endif FPC_SYSTEM_HAS_ABS}
  88. {$ifndef FPC_SYSTEM_HAS_SQR}
  89. {$define FPC_SYSTEM_HAS_SQR}
  90. function fpc_sqr_real(d : ValReal) : ValReal;compilerproc;
  91. begin
  92. { Function is handled internal in the compiler }
  93. runerror(207);
  94. result:=0;
  95. end;
  96. {$endif FPC_SYSTEM_HAS_SQR}
  97. {$ifndef FPC_SYSTEM_HAS_SQRT}
  98. {$define FPC_SYSTEM_HAS_SQRT}
  99. function fpc_sqrt_real(d : ValReal) : ValReal;compilerproc;
  100. begin
  101. { Function is handled internal in the compiler }
  102. runerror(207);
  103. result:=0;
  104. end;
  105. {$endif FPC_SYSTEM_HAS_SQRT}
  106. {$ifdef FPC_HAS_TYPE_EXTENDED}
  107. {$ifndef FPC_SYSTEM_HAS_ARCTAN}
  108. {$define FPC_SYSTEM_HAS_ARCTAN}
  109. function fpc_arctan_real(d : ValReal) : ValReal;compilerproc;
  110. begin
  111. { Function is handled internal in the compiler }
  112. runerror(207);
  113. result:=0;
  114. end;
  115. {$endif FPC_SYSTEM_HAS_ARCTAN}
  116. {$ifndef FPC_SYSTEM_HAS_LN}
  117. {$define FPC_SYSTEM_HAS_LN}
  118. function fpc_ln_real(d : ValReal) : ValReal;compilerproc;
  119. begin
  120. { Function is handled internal in the compiler }
  121. runerror(207);
  122. result:=0;
  123. end;
  124. {$endif FPC_SYSTEM_HAS_LN}
  125. {$ifndef FPC_SYSTEM_HAS_SIN}
  126. {$define FPC_SYSTEM_HAS_SIN}
  127. function fpc_sin_real(d : ValReal) : ValReal;compilerproc;
  128. begin
  129. { Function is handled internal in the compiler }
  130. runerror(207);
  131. result:=0;
  132. end;
  133. {$endif FPC_SYSTEM_HAS_SIN}
  134. {$ifndef FPC_SYSTEM_HAS_COS}
  135. {$define FPC_SYSTEM_HAS_COS}
  136. function fpc_cos_real(d : ValReal) : ValReal;compilerproc;
  137. begin
  138. { Function is handled internal in the compiler }
  139. runerror(207);
  140. result:=0;
  141. end;
  142. {$endif FPC_SYSTEM_HAS_COS}
  143. {$ifndef FPC_SYSTEM_HAS_EXP}
  144. {$define FPC_SYSTEM_HAS_EXP}
  145. { exp function adapted from AMath library (C) Copyright 2009-2013 Wolfgang Ehrhardt
  146. * translated into AT&T syntax
  147. + PIC support
  148. * return +Inf/0 for +Inf/-Inf input, instead of NaN }
  149. function fpc_exp_real(d : ValReal) : ValReal;assembler;compilerproc;
  150. const
  151. ln2hi: double=6.9314718036912382E-001;
  152. ln2lo: double=1.9082149292705877E-010;
  153. large: single=24576.0;
  154. two: single=2.0;
  155. half: single=0.5;
  156. asm
  157. fldt d
  158. fldl2e
  159. fmul %st(1),%st { z = d * log2(e) }
  160. frndint
  161. { Calculate frac(z) using modular arithmetic to avoid precision loss }
  162. fldl ln2hi(%rip)
  163. fmul %st(1),%st
  164. fsubrp %st,%st(2)
  165. fldl ln2lo(%rip)
  166. fmul %st(1),%st
  167. fsubrp %st,%st(2)
  168. fxch %st(1) { (d-int(z)*ln2_hi)-int(z)*ln2_lo }
  169. fldl2e
  170. fmulp %st,%st(1) { frac(z) }
  171. { Above calculation can yield |frac(z)|>1, particularly when rounding mode
  172. is not "round to nearest". f2xm1 is undefined in that case, so it's
  173. necessary to check }
  174. fld %st
  175. fabs
  176. fld1
  177. fcompp
  178. fstsw %ax
  179. sahf
  180. jp .L3 { NaN }
  181. jae .L1 { |frac(z)| <= 1, good }
  182. fld %st(1)
  183. fabs
  184. fcomps large(%rip)
  185. fstsw %ax
  186. sahf
  187. jb .L0 { int(z) < 24576 }
  188. .L3:
  189. fstp %st { pop frac(z) and load 0 }
  190. fldz
  191. jmp .L1
  192. .L0:
  193. { Calculate 2**frac(z)-1 as N*(N+2), where N=2**(frac(z)/2)-1 }
  194. fmuls half(%rip)
  195. f2xm1
  196. fld %st
  197. fadds two(%rip)
  198. fmulp %st,%st(1)
  199. jmp .L2
  200. .L1:
  201. f2xm1
  202. .L2:
  203. fld1
  204. faddp %st,%st(1)
  205. fscale
  206. fstp %st(1)
  207. end;
  208. {$endif FPC_SYSTEM_HAS_EXP}
  209. {$ifndef FPC_SYSTEM_HAS_FRAC}
  210. {$define FPC_SYSTEM_HAS_FRAC}
  211. function fpc_frac_real(d : ValReal) : ValReal;assembler;compilerproc;
  212. var
  213. oldcw,newcw: word;
  214. asm
  215. fnstcw oldcw
  216. fwait
  217. movw oldcw,%cx
  218. orw $0x0c3f,%cx
  219. movw %cx,newcw
  220. fldcw newcw
  221. fwait
  222. fldt d
  223. frndint
  224. fldt d
  225. fsub %st(1),%st
  226. fstp %st(1)
  227. fnclex
  228. fldcw oldcw
  229. end;
  230. {$endif FPC_SYSTEM_HAS_FRAC}
  231. {$ifndef FPC_SYSTEM_HAS_INT}
  232. {$define FPC_SYSTEM_HAS_INT}
  233. function fpc_int_real(d : ValReal) : ValReal;assembler;compilerproc;
  234. var
  235. oldcw,newcw: word;
  236. asm
  237. fnstcw oldcw
  238. fwait
  239. movw oldcw,%cx
  240. orw $0x0c3f,%cx
  241. movw %cx,newcw
  242. fldcw newcw
  243. fwait
  244. fldt d
  245. frndint
  246. fwait
  247. fldcw oldcw
  248. end;
  249. {$endif FPC_SYSTEM_HAS_INT}
  250. {$ifndef FPC_SYSTEM_HAS_TRUNC}
  251. {$define FPC_SYSTEM_HAS_TRUNC}
  252. function fpc_trunc_real(d : ValReal) : int64;assembler;compilerproc;
  253. var
  254. oldcw,
  255. newcw : word;
  256. res : int64;
  257. asm
  258. fnstcw oldcw
  259. fwait
  260. movw oldcw,%cx
  261. orw $0x0c3f,%cx
  262. movw %cx,newcw
  263. fldcw newcw
  264. fldt d
  265. fistpq res
  266. fwait
  267. movq res,%rax
  268. fldcw oldcw
  269. end;
  270. {$endif FPC_SYSTEM_HAS_TRUNC}
  271. {$ifndef FPC_SYSTEM_HAS_ROUND}
  272. {$define FPC_SYSTEM_HAS_ROUND}
  273. function fpc_round_real(d : ValReal) : int64;assembler;compilerproc;
  274. var
  275. res : int64;
  276. asm
  277. fldt d
  278. fistpq res
  279. fwait
  280. movq res,%rax
  281. end;
  282. {$endif FPC_SYSTEM_HAS_ROUND}
  283. {$else FPC_HAS_TYPE_EXTENDED}
  284. {$define FPC_SYSTEM_HAS_TRUNC}
  285. function fpc_trunc_real(d : ValReal) : int64;compilerproc; assembler; nostackframe;
  286. asm
  287. cvttsd2si %xmm0,%rax;
  288. end;
  289. {$define FPC_SYSTEM_HAS_ROUND}
  290. function fpc_round_real(d : ValReal) : int64;compilerproc; assembler; nostackframe;
  291. asm
  292. cvtsd2si %xmm0,%rax;
  293. end;
  294. {$endif FPC_HAS_TYPE_EXTENDED}