math.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-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 %st(1)
  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 %st(1)
  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 %st(1)
  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 bas=0 then
  189. begin
  190. if expo<>0 then
  191. power:=0.0
  192. else
  193. HandleError(207);
  194. end
  195. else if expo=0 then
  196. power:=1
  197. else
  198. { bas < 0 is not allowed }
  199. if bas<0 then
  200. handleerror(207)
  201. else
  202. power:=exp(ln(bas)*expo);
  203. end;
  204. {****************************************************************************
  205. Longint data type routines
  206. ****************************************************************************}
  207. function power(bas,expo : longint) : longint;
  208. begin
  209. if bas=0 then
  210. begin
  211. if expo<>0 then
  212. power:=0
  213. else
  214. HandleError(207);
  215. end
  216. else if expo=0 then
  217. power:=1
  218. else
  219. begin
  220. if bas<0 then
  221. begin
  222. if odd(expo) then
  223. power:=-round(exp(ln(-bas)*expo))
  224. else
  225. power:=round(exp(ln(-bas)*expo));
  226. end
  227. else
  228. power:=round(exp(ln(bas)*expo));
  229. end;
  230. end;
  231. {****************************************************************************
  232. Fixed data type routines
  233. ****************************************************************************}
  234. {$ifdef HASFIXED} { Not yet allowed }
  235. function sqrt(d : fixed) : fixed;
  236. begin
  237. asm
  238. movl d,%eax
  239. movl %eax,%ebx
  240. movl %eax,%ecx
  241. jecxz .L_kl
  242. xorl %esi,%esi
  243. .L_it:
  244. xorl %edx,%edx
  245. idivl %ebx
  246. addl %ebx,%eax
  247. shrl $1,%eax
  248. subl %eax,%esi
  249. cmpl $1,%esi
  250. jbe .L_kl
  251. movl %eax,%esi
  252. movl %eax,%ebx
  253. movl %ecx,%eax
  254. jmp .L_it
  255. .L_kl:
  256. shl $8,%eax
  257. leave
  258. ret $4
  259. end;
  260. end;
  261. function int(d : fixed) : fixed;
  262. {*****************************************************************}
  263. { Returns the integral part of d }
  264. {*****************************************************************}
  265. begin
  266. int:=d and $ffff0000; { keep only upper bits }
  267. end;
  268. function trunc(d : fixed) : longint;
  269. {*****************************************************************}
  270. { Returns the Truncated integral part of d }
  271. {*****************************************************************}
  272. begin
  273. trunc:=longint(integer(d shr 16)); { keep only upper 16 bits }
  274. end;
  275. function frac(d : fixed) : fixed;
  276. {*****************************************************************}
  277. { Returns the Fractional part of d }
  278. {*****************************************************************}
  279. begin
  280. frac:=d AND $ffff; { keep only decimal parts - lower 16 bits }
  281. end;
  282. function abs(d : fixed) : fixed;
  283. {*****************************************************************}
  284. { Returns the Absolute value of d }
  285. {*****************************************************************}
  286. begin
  287. asm
  288. movl d,%eax
  289. rol $16,%eax { Swap high & low word.}
  290. {Absolute value: Invert all bits and increment when <0 .}
  291. cwd { When ax<0, dx contains $ffff}
  292. xorw %dx,%ax { Inverts all bits when dx=$ffff.}
  293. subw %dx,%ax { Increments when dx=$ffff.}
  294. rol $16,%eax { Swap high & low word.}
  295. leave
  296. ret $4
  297. end;
  298. end;
  299. function sqr(d : fixed) : fixed;
  300. {*****************************************************************}
  301. { Returns the Absolute squared value of d }
  302. {*****************************************************************}
  303. begin
  304. {16-bit precision needed, not 32 =)}
  305. sqr := d*d;
  306. { sqr := (d SHR 8 * d) SHR 8; }
  307. end;
  308. function Round(x: fixed): longint;
  309. {*****************************************************************}
  310. { Returns the Rounded value of d as a longint }
  311. {*****************************************************************}
  312. var
  313. lowf:integer;
  314. highf:integer;
  315. begin
  316. lowf:=x and $ffff; { keep decimal part ... }
  317. highf :=integer(x shr 16);
  318. if lowf > 5 then
  319. highf:=highf+1
  320. else
  321. if lowf = 5 then
  322. begin
  323. { here we must check the sign ... }
  324. { if greater or equal to zero, then }
  325. { greater value will be found by adding }
  326. { one... }
  327. if highf >= 0 then
  328. Highf:=Highf+1;
  329. end;
  330. Round:= longint(highf);
  331. end;
  332. {$endif HASFIXED}
  333. {
  334. $Log$
  335. Revision 1.1 2000-07-13 06:30:42 michael
  336. + Initial import
  337. Revision 1.23 2000/05/02 10:37:50 pierre
  338. * 0**n where n<>0 is 0; 0**0 generates RTE 207
  339. Revision 1.22 2000/04/07 21:29:00 pierre
  340. changed to get nasm to compile system
  341. Revision 1.21 2000/02/15 14:37:36 florian
  342. * disabled FIXED data type per default
  343. Revision 1.20 2000/02/09 16:59:29 peter
  344. * truncated log
  345. Revision 1.19 2000/01/07 16:41:33 daniel
  346. * copyright 2000
  347. Revision 1.18 2000/01/07 16:32:24 daniel
  348. * copyright 2000 added
  349. Revision 1.17 1999/10/06 17:44:43 peter
  350. * fixed power(int,int) with negative base
  351. * power(ext,ext) with negative base gives rte 207
  352. Revision 1.16 1999/09/15 20:24:11 florian
  353. * some math functions are now coded inline by the compiler
  354. }