math.inc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993-98 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. {$ASMMODE DIRECT}
  13. function abs(d : real) : real;
  14. begin
  15. asm
  16. fldl 8(%ebp)
  17. fabs
  18. leave
  19. ret $8
  20. end [];
  21. end;
  22. function sqr(d : real) : real;
  23. begin
  24. asm
  25. fldl 8(%ebp)
  26. fldl 8(%ebp)
  27. fmulp
  28. leave
  29. ret $8
  30. end [];
  31. end;
  32. function sqrt(d : real) : real;
  33. begin
  34. asm
  35. fldl 8(%ebp)
  36. fsqrtl
  37. leave
  38. ret $8
  39. end [];
  40. end;
  41. function arctan(d : real) : real;
  42. begin
  43. asm
  44. fldl 8(%ebp)
  45. fld1
  46. fpatan
  47. leave
  48. ret $8
  49. end [];
  50. end;
  51. function cos(d : real) : real;
  52. begin
  53. asm
  54. fldl 8(%ebp)
  55. fcos
  56. fstsw
  57. sahf
  58. jnp .LCOS1
  59. fstp %st(0)
  60. fldl .LCOS0
  61. .LCOS1:
  62. leave
  63. ret $8
  64. .LCOS0:
  65. .quad 0xffffffffffffffff
  66. end ['EAX'];
  67. end;
  68. function exp(d : real) : real;
  69. begin
  70. asm
  71. // comes from DJ GPP
  72. fldl 8(%ebp)
  73. fldl2e
  74. fmulp
  75. fstcww .LCW1
  76. fstcww .LCW2
  77. fwait
  78. andw $0xf3ff,.LCW2
  79. orw $0x0400,.LCW2
  80. fldcww .LCW2
  81. fldl %st(0)
  82. frndint
  83. fldcww .LCW1
  84. fxch %st(1)
  85. fsub %st(1),%st
  86. f2xm1
  87. faddl .LC0
  88. fscale
  89. fstp %st(1)
  90. leave
  91. ret $8
  92. // store some help data in the data segment
  93. .data
  94. .LCW1:
  95. .word 0
  96. .LCW2:
  97. .word 0
  98. .LC0:
  99. .double 0d1.0e+00
  100. // do not forget to switch back to text
  101. .text
  102. end;
  103. end;
  104. function frac(d : real) : real;
  105. begin
  106. asm
  107. subl $16,%esp
  108. fnstcw -4(%ebp)
  109. fwait
  110. movw -4(%ebp),%cx
  111. orw $0x0c3f,%cx
  112. movw %cx,-8(%ebp)
  113. fldcw -8(%ebp)
  114. fwait
  115. fldl 8(%ebp)
  116. frndint
  117. fldl 8(%ebp)
  118. fsub %st(1)
  119. fstp %st(1)
  120. fclex
  121. fldcw -4(%ebp)
  122. leave
  123. ret $8
  124. end ['ECX'];
  125. end;
  126. function int(d : real) : real;
  127. begin
  128. asm
  129. subl $16,%esp
  130. fnstcw -4(%ebp)
  131. fwait
  132. movw -4(%ebp),%cx
  133. orw $0x0c3f,%cx
  134. movw %cx,-8(%ebp)
  135. fldcw -8(%ebp)
  136. fwait
  137. fldl 8(%ebp)
  138. frndint
  139. fclex
  140. fldcw -4(%ebp)
  141. leave
  142. ret $8
  143. end ['ECX'];
  144. end;
  145. function trunc(d : real) : longint;
  146. begin
  147. asm
  148. subl $16,%esp
  149. fnstcw -4(%ebp)
  150. fwait
  151. movw -4(%ebp),%cx
  152. orw $0x0c3f,%cx
  153. movw %cx,-8(%ebp)
  154. fldcw -8(%ebp)
  155. fwait
  156. fldl 8(%ebp)
  157. fistpl -8(%ebp)
  158. movl -8(%ebp),%eax
  159. fldcw -4(%ebp)
  160. leave
  161. ret $8
  162. end ['EAX','ECX'];
  163. end;
  164. function round(d : real) : longint;
  165. begin
  166. asm
  167. subl $8,%esp
  168. fnstcw -4(%ebp)
  169. fwait
  170. movw $0x1372,-8(%ebp)
  171. fldcw -8(%ebp)
  172. fwait
  173. fldl 8(%ebp)
  174. fistpl -8(%ebp)
  175. movl -8(%ebp),%eax
  176. fldcw -4(%ebp)
  177. leave
  178. ret $8
  179. end ['EAX','ECX'];
  180. end;
  181. function ln(d : real) : real;
  182. begin
  183. asm
  184. fldln2
  185. fldl 8(%ebp)
  186. fyl2x
  187. leave
  188. ret $8
  189. end [];
  190. end;
  191. function pi : real;
  192. begin
  193. asm
  194. fldpi
  195. leave
  196. ret
  197. end [];
  198. end;
  199. function sin(d : real) : real;
  200. begin
  201. asm
  202. fldl 8(%ebp)
  203. fsin
  204. fstsw
  205. sahf
  206. jnp .LSIN1
  207. fstp %st(0)
  208. fldl .LSIN0
  209. .LSIN1:
  210. leave
  211. ret $8
  212. .LSIN0:
  213. .quad 0xffffffffffffffff
  214. end ['EAX'];
  215. end;
  216. function power(bas,expo : real) : real;
  217. begin
  218. power:=exp(ln(bas)*expo);
  219. end;
  220. function power(bas,expo : longint) : longint;
  221. begin
  222. power:=round(exp(ln(bas)*expo));
  223. end;
  224. {$ifdef fixed}
  225. function sqrt(d : fixed) : fixed;
  226. begin
  227. asm
  228. movl d,%eax
  229. movl %eax,%ebx
  230. movl %eax,%ecx
  231. jecxz .L_kl
  232. xorl %esi,%esi
  233. .L_it:
  234. xorl %edx,%edx
  235. idivl %ebx
  236. addl %ebx,%eax
  237. shrl $1,%eax
  238. subl %eax,%esi
  239. cmpl $1,%esi
  240. jbe .L_kl
  241. movl %eax,%esi
  242. movl %eax,%ebx
  243. movl %ecx,%eax
  244. jmp .L_it
  245. .L_kl:
  246. shl $8,%eax
  247. leave
  248. ret $4
  249. end;
  250. end;
  251. function int(d : fixed) : fixed;
  252. {*****************************************************************}
  253. { Returns the integral part of d }
  254. {*****************************************************************}
  255. begin
  256. int:=d and $ffff0000; { keep only upper bits }
  257. end;
  258. function trunc(d : fixed) : longint;
  259. {*****************************************************************}
  260. { Returns the Truncated integral part of d }
  261. {*****************************************************************}
  262. begin
  263. trunc:=longint(integer(d shr 16)); { keep only upper 16 bits }
  264. end;
  265. function frac(d : fixed) : fixed;
  266. {*****************************************************************}
  267. { Returns the Fractional part of d }
  268. {*****************************************************************}
  269. begin
  270. frac:=d AND $ffff; { keep only decimal parts - lower 16 bits }
  271. end;
  272. function abs(d : fixed) : fixed;
  273. {*****************************************************************}
  274. { Returns the Absolute value of d }
  275. {*****************************************************************}
  276. begin
  277. asm
  278. movl d,%eax
  279. rol $16,%eax { Swap high & low word.}
  280. {Absolute value: Invert all bits and increment when <0 .}
  281. cwd { When ax<0, dx contains $ffff}
  282. xorw %dx,%ax { Inverts all bits when dx=$ffff.}
  283. subw %dx,%ax { Increments when dx=$ffff.}
  284. rol $16,%eax { Swap high & low word.}
  285. leave
  286. ret $4
  287. end;
  288. end;
  289. function sqr(d : fixed) : fixed;
  290. {*****************************************************************}
  291. { Returns the Absolute squared value of d }
  292. {*****************************************************************}
  293. begin
  294. {16-bit precision needed, not 32 =)}
  295. sqr := d*d;
  296. { sqr := (d SHR 8 * d) SHR 8; }
  297. end;
  298. function Round(x: fixed): longint;
  299. {*****************************************************************}
  300. { Returns the Rounded value of d as a longint }
  301. {*****************************************************************}
  302. var
  303. lowf:integer;
  304. highf:integer;
  305. begin
  306. lowf:=x and $ffff; { keep decimal part ... }
  307. highf :=integer(x shr 16);
  308. if lowf > 5 then
  309. highf:=highf+1
  310. else
  311. if lowf = 5 then
  312. begin
  313. { here we must check the sign ... }
  314. { if greater or equal to zero, then }
  315. { greater value will be found by adding }
  316. { one... }
  317. if highf >= 0 then
  318. Highf:=Highf+1;
  319. end;
  320. Round:= longint(highf);
  321. end;
  322. {$endif}
  323. {$ASMMODE ATT}
  324. {
  325. $Log$
  326. Revision 1.2 1998-05-31 14:15:49 peter
  327. * force to use ATT or direct parsing
  328. }