math.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1998-2000 by the Free Pascal development team
  5. Implementation of mathamatical Routines (only for 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. EXTENDED data type routines
  14. ****************************************************************************}
  15. {$ifdef hasinternmath}
  16. function pi : extended;[internproc:in_pi];
  17. function abs(d : extended) : extended;[internproc:in_abs_extended];
  18. function sqr(d : extended) : extended;[internproc:in_sqr_extended];
  19. function sqrt(d : extended) : extended;[internproc:in_sqrt_extended];
  20. function arctan(d : extended) : extended;[internproc:in_arctan_extended];
  21. function ln(d : extended) : extended;[internproc:in_ln_extended];
  22. function sin(d : extended) : extended;[internproc:in_sin_extended];
  23. function cos(d : extended) : extended;[internproc:in_cos_extended];
  24. {$else hasinternmath}
  25. function pi : extended;assembler;[internconst:in_const_pi];
  26. asm
  27. fldpi
  28. end [];
  29. function abs(d : extended) : extended;assembler;[internconst:in_const_abs];
  30. asm
  31. fldt d
  32. fabs
  33. end [];
  34. function sqr(d : extended) : extended;assembler;[internconst:in_const_sqr];
  35. asm
  36. fldt d
  37. fldt d
  38. fmulp
  39. end [];
  40. function sqrt(d : extended) : extended;assembler;[internconst:in_const_sqrt];
  41. asm
  42. fldt d
  43. fsqrt
  44. end [];
  45. function arctan(d : extended) : extended;assembler;[internconst:in_const_arctan];
  46. asm
  47. fldt d
  48. fld1
  49. fpatan
  50. end [];
  51. function cos(d : extended) : extended;assembler;[internconst:in_const_cos];
  52. asm
  53. fldt d
  54. fcos
  55. fstsw
  56. sahf
  57. jnp .LCOS1
  58. fstp %st(0)
  59. fldt .LCOS0
  60. jmp .LCOS1
  61. .data
  62. .LCOS0:
  63. .long 0xffffffff
  64. .long 0xffffffff
  65. .long 0xffffffff
  66. .text
  67. .LCOS1:
  68. end ['EAX'];
  69. function ln(d : extended) : extended;assembler;[internconst:in_const_ln];
  70. asm
  71. fldln2
  72. fldt d
  73. fyl2x
  74. end [];
  75. function sin(d : extended) : extended;assembler;[internconst:in_const_sin];
  76. asm
  77. fldt d
  78. fsin
  79. fstsw
  80. sahf
  81. jnp .LSIN1
  82. fstp %st(0)
  83. fldt .LSIN0
  84. jmp .LSIN1
  85. .data
  86. .LSIN0:
  87. .long 0xffffffff
  88. .long 0xffffffff
  89. .long 0xffffffff
  90. .text
  91. .LSIN1:
  92. end ['EAX'];
  93. {$endif hasinternmath}
  94. function exp(d : extended) : extended;assembler;[internconst:in_const_exp];
  95. asm
  96. // comes from DJ GPP
  97. fldt d
  98. fldl2e
  99. fmulp
  100. fstcw .LCW1
  101. fstcw .LCW2
  102. andw $0xf3ff,.LCW2
  103. orw $0x0400,.LCW2
  104. fldcw .LCW2
  105. fld %st(0)
  106. frndint
  107. fldcw .LCW1
  108. fxch %st(1)
  109. fsub %st(1),%st
  110. f2xm1
  111. fld1
  112. faddp
  113. fscale
  114. fstp %st(1)
  115. jmp .LCW3
  116. // store some help data in the data segment
  117. .data
  118. .LCW1:
  119. .word 0
  120. .LCW2:
  121. .word 0
  122. .text
  123. .LCW3:
  124. end;
  125. function frac(d : extended) : extended;assembler;[internconst:in_const_frac];
  126. asm
  127. subl $16,%esp
  128. fnstcw -4(%ebp)
  129. fwait
  130. movw -4(%ebp),%cx
  131. orw $0x0c3f,%cx
  132. movw %cx,-8(%ebp)
  133. fldcw -8(%ebp)
  134. fwait
  135. fldt d
  136. frndint
  137. fldt d
  138. fsub %st(1)
  139. fstp %st(1)
  140. fclex
  141. fldcw -4(%ebp)
  142. end ['ECX'];
  143. function int(d : extended) : extended;assembler;[internconst:in_const_int];
  144. asm
  145. subl $16,%esp
  146. fnstcw -4(%ebp)
  147. fwait
  148. movw -4(%ebp),%cx
  149. orw $0x0c3f,%cx
  150. movw %cx,-8(%ebp)
  151. fldcw -8(%ebp)
  152. fwait
  153. fldt d
  154. frndint
  155. fclex
  156. fldcw -4(%ebp)
  157. end ['ECX'];
  158. function trunc(d : extended) : longint;assembler;[internconst:in_const_trunc];
  159. asm
  160. subl $16,%esp
  161. fnstcw -4(%ebp)
  162. fwait
  163. movw -4(%ebp),%cx
  164. orw $0x0c3f,%cx
  165. movw %cx,-8(%ebp)
  166. fldcw -8(%ebp)
  167. fwait
  168. fldt d
  169. fistpl -8(%ebp)
  170. movl -8(%ebp),%eax
  171. fldcw -4(%ebp)
  172. end ['EAX','ECX'];
  173. function round(d : extended) : longint;assembler;[internconst:in_const_round];
  174. asm
  175. subl $8,%esp
  176. fnstcw -4(%ebp)
  177. fwait
  178. movw $0x1372,-8(%ebp)
  179. fldcw -8(%ebp)
  180. fwait
  181. fldt d
  182. fistpl -8(%ebp)
  183. movl -8(%ebp),%eax
  184. fldcw -4(%ebp)
  185. end ['EAX','ECX'];
  186. function power(bas,expo : extended) : extended;
  187. begin
  188. if expo=0 then
  189. power:=1
  190. else
  191. { bas < 0 is not allowed }
  192. if bas<0 then
  193. handleerror(207)
  194. else
  195. power:=exp(ln(bas)*expo);
  196. end;
  197. {****************************************************************************
  198. Longint data type routines
  199. ****************************************************************************}
  200. function power(bas,expo : longint) : longint;
  201. begin
  202. if expo=0 then
  203. power:=1
  204. else
  205. begin
  206. if bas<0 then
  207. begin
  208. if odd(expo) then
  209. power:=-round(exp(ln(-bas)*expo))
  210. else
  211. power:=round(exp(ln(-bas)*expo));
  212. end
  213. else
  214. power:=round(exp(ln(bas)*expo));
  215. end;
  216. end;
  217. {****************************************************************************
  218. Fixed data type routines
  219. ****************************************************************************}
  220. {$ifdef _SUPPORT_FIXED} { Not yet allowed }
  221. function sqrt(d : fixed) : fixed;
  222. begin
  223. asm
  224. movl d,%eax
  225. movl %eax,%ebx
  226. movl %eax,%ecx
  227. jecxz .L_kl
  228. xorl %esi,%esi
  229. .L_it:
  230. xorl %edx,%edx
  231. idivl %ebx
  232. addl %ebx,%eax
  233. shrl $1,%eax
  234. subl %eax,%esi
  235. cmpl $1,%esi
  236. jbe .L_kl
  237. movl %eax,%esi
  238. movl %eax,%ebx
  239. movl %ecx,%eax
  240. jmp .L_it
  241. .L_kl:
  242. shl $8,%eax
  243. leave
  244. ret $4
  245. end;
  246. end;
  247. function int(d : fixed) : fixed;
  248. {*****************************************************************}
  249. { Returns the integral part of d }
  250. {*****************************************************************}
  251. begin
  252. int:=d and $ffff0000; { keep only upper bits }
  253. end;
  254. function trunc(d : fixed) : longint;
  255. {*****************************************************************}
  256. { Returns the Truncated integral part of d }
  257. {*****************************************************************}
  258. begin
  259. trunc:=longint(integer(d shr 16)); { keep only upper 16 bits }
  260. end;
  261. function frac(d : fixed) : fixed;
  262. {*****************************************************************}
  263. { Returns the Fractional part of d }
  264. {*****************************************************************}
  265. begin
  266. frac:=d AND $ffff; { keep only decimal parts - lower 16 bits }
  267. end;
  268. function abs(d : fixed) : fixed;
  269. {*****************************************************************}
  270. { Returns the Absolute value of d }
  271. {*****************************************************************}
  272. begin
  273. asm
  274. movl d,%eax
  275. rol $16,%eax { Swap high & low word.}
  276. {Absolute value: Invert all bits and increment when <0 .}
  277. cwd { When ax<0, dx contains $ffff}
  278. xorw %dx,%ax { Inverts all bits when dx=$ffff.}
  279. subw %dx,%ax { Increments when dx=$ffff.}
  280. rol $16,%eax { Swap high & low word.}
  281. leave
  282. ret $4
  283. end;
  284. end;
  285. function sqr(d : fixed) : fixed;
  286. {*****************************************************************}
  287. { Returns the Absolute squared value of d }
  288. {*****************************************************************}
  289. begin
  290. {16-bit precision needed, not 32 =)}
  291. sqr := d*d;
  292. { sqr := (d SHR 8 * d) SHR 8; }
  293. end;
  294. function Round(x: fixed): longint;
  295. {*****************************************************************}
  296. { Returns the Rounded value of d as a longint }
  297. {*****************************************************************}
  298. var
  299. lowf:integer;
  300. highf:integer;
  301. begin
  302. lowf:=x and $ffff; { keep decimal part ... }
  303. highf :=integer(x shr 16);
  304. if lowf > 5 then
  305. highf:=highf+1
  306. else
  307. if lowf = 5 then
  308. begin
  309. { here we must check the sign ... }
  310. { if greater or equal to zero, then }
  311. { greater value will be found by adding }
  312. { one... }
  313. if highf >= 0 then
  314. Highf:=Highf+1;
  315. end;
  316. Round:= longint(highf);
  317. end;
  318. {$endif SUPPORT_FIXED}
  319. {
  320. $Log$
  321. Revision 1.18 2000-01-07 16:32:24 daniel
  322. * copyright 2000 added
  323. Revision 1.17 1999/10/06 17:44:43 peter
  324. * fixed power(int,int) with negative base
  325. * power(ext,ext) with negative base gives rte 207
  326. Revision 1.16 1999/09/15 20:24:11 florian
  327. * some math functions are now coded inline by the compiler
  328. Revision 1.15 1999/07/06 15:35:59 peter
  329. * removed temp defines
  330. Revision 1.14 1999/03/01 15:40:57 peter
  331. * use external names
  332. * removed all direct assembler modes
  333. Revision 1.13 1998/12/15 22:42:56 peter
  334. * removed temp symbols
  335. Revision 1.12 1998/11/24 12:54:57 peter
  336. * removed all explicit leave;ret commands and let them generate by
  337. the compiler (needed for stack alignment)
  338. Revision 1.11 1998/11/16 14:26:03 pierre
  339. * changed fsqrtl to fsqrt (needed by as v2.9.4 for win32)
  340. Revision 1.10 1998/10/02 09:25:29 peter
  341. * more constant expression evals
  342. Revision 1.9 1998/09/11 17:38:49 pierre
  343. merge for fixes branch
  344. Revision 1.8.2.1 1998/09/11 17:37:25 pierre
  345. * correction respective to stricter as v2.9.1 syntax
  346. Revision 1.8 1998/09/01 17:36:18 peter
  347. + internconst
  348. Revision 1.7 1998/08/25 08:49:05 florian
  349. * corrected exp() function
  350. Revision 1.6 1998/08/11 21:39:04 peter
  351. * splitted default_extended from support_extended
  352. Revision 1.5 1998/08/11 00:04:50 peter
  353. * $ifdef ver0_99_5 updates
  354. Revision 1.4 1998/08/10 15:54:50 peter
  355. * removed dup power(longint)
  356. Revision 1.3 1998/08/08 12:28:09 florian
  357. * a lot small fixes to the extended data type work
  358. Revision 1.2 1998/05/31 14:15:49 peter
  359. * force to use ATT or direct parsing
  360. }