math.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  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. {$ifndef DEFAULT_EXTENDED}
  14. {****************************************************************************
  15. Real/Double data type routines
  16. ****************************************************************************}
  17. function pi : real;
  18. begin
  19. asm
  20. fldpi
  21. leave
  22. ret
  23. end [];
  24. end;
  25. function abs(d : real) : real;
  26. begin
  27. asm
  28. fldl 8(%ebp)
  29. fabs
  30. leave
  31. ret $8
  32. end [];
  33. end;
  34. function sqr(d : real) : real;
  35. begin
  36. asm
  37. fldl 8(%ebp)
  38. fldl 8(%ebp)
  39. fmulp
  40. leave
  41. ret $8
  42. end [];
  43. end;
  44. function sqrt(d : real) : real;
  45. begin
  46. asm
  47. fldl 8(%ebp)
  48. fsqrtl
  49. leave
  50. ret $8
  51. end [];
  52. end;
  53. function arctan(d : real) : real;
  54. begin
  55. asm
  56. fldl 8(%ebp)
  57. fld1
  58. fpatan
  59. leave
  60. ret $8
  61. end [];
  62. end;
  63. function cos(d : real) : real;
  64. begin
  65. asm
  66. fldl 8(%ebp)
  67. fcos
  68. fstsw
  69. sahf
  70. jnp .LCOS1
  71. fstp %st(0)
  72. fldl .LCOS0
  73. .LCOS1:
  74. leave
  75. ret $8
  76. .LCOS0:
  77. .quad 0xffffffffffffffff
  78. end ['EAX'];
  79. end;
  80. function exp(d : real) : real;
  81. begin
  82. asm
  83. // comes from DJ GPP
  84. fldl 8(%ebp)
  85. fldl2e
  86. fmulp
  87. fstcw .LCW1
  88. fstcw .LCW2
  89. fwait
  90. andw $0xf3ff,.LCW2
  91. orw $0x0400,.LCW2
  92. fldcw .LCW2
  93. fldl %st(0)
  94. frndint
  95. fldcw .LCW1
  96. fxch %st(1)
  97. fsub %st(1),%st
  98. f2xm1
  99. fld1
  100. faddp
  101. fscale
  102. fstp %st(1)
  103. leave
  104. ret $8
  105. // store some help data in the data segment
  106. .data
  107. .LCW1:
  108. .word 0
  109. .LCW2:
  110. .word 0
  111. .text
  112. end;
  113. end;
  114. function frac(d : real) : real;
  115. begin
  116. asm
  117. subl $16,%esp
  118. fnstcw -4(%ebp)
  119. fwait
  120. movw -4(%ebp),%cx
  121. orw $0x0c3f,%cx
  122. movw %cx,-8(%ebp)
  123. fldcw -8(%ebp)
  124. fwait
  125. fldl 8(%ebp)
  126. frndint
  127. fldl 8(%ebp)
  128. fsub %st(1)
  129. fstp %st(1)
  130. fclex
  131. fldcw -4(%ebp)
  132. leave
  133. ret $8
  134. end ['ECX'];
  135. end;
  136. function int(d : real) : real;
  137. begin
  138. asm
  139. subl $16,%esp
  140. fnstcw -4(%ebp)
  141. fwait
  142. movw -4(%ebp),%cx
  143. orw $0x0c3f,%cx
  144. movw %cx,-8(%ebp)
  145. fldcw -8(%ebp)
  146. fwait
  147. fldl 8(%ebp)
  148. frndint
  149. fclex
  150. fldcw -4(%ebp)
  151. leave
  152. ret $8
  153. end ['ECX'];
  154. end;
  155. function trunc(d : real) : longint;
  156. begin
  157. asm
  158. subl $16,%esp
  159. fnstcw -4(%ebp)
  160. fwait
  161. movw -4(%ebp),%cx
  162. orw $0x0c3f,%cx
  163. movw %cx,-8(%ebp)
  164. fldcw -8(%ebp)
  165. fwait
  166. fldl 8(%ebp)
  167. fistpl -8(%ebp)
  168. movl -8(%ebp),%eax
  169. fldcw -4(%ebp)
  170. leave
  171. ret $8
  172. end ['EAX','ECX'];
  173. end;
  174. function round(d : real) : longint;
  175. begin
  176. asm
  177. subl $8,%esp
  178. fnstcw -4(%ebp)
  179. fwait
  180. movw $0x1372,-8(%ebp)
  181. fldcw -8(%ebp)
  182. fwait
  183. fldl 8(%ebp)
  184. fistpl -8(%ebp)
  185. movl -8(%ebp),%eax
  186. fldcw -4(%ebp)
  187. leave
  188. ret $8
  189. end ['EAX','ECX'];
  190. end;
  191. function ln(d : real) : real;
  192. begin
  193. asm
  194. fldln2
  195. fldl 8(%ebp)
  196. fyl2x
  197. leave
  198. ret $8
  199. end [];
  200. end;
  201. function sin(d : real) : real;
  202. begin
  203. asm
  204. fldl 8(%ebp)
  205. fsin
  206. fstsw
  207. sahf
  208. jnp .LSIN1
  209. fstp %st(0)
  210. fldl .LSIN0
  211. .LSIN1:
  212. leave
  213. ret $8
  214. .LSIN0:
  215. .quad 0xffffffffffffffff
  216. end ['EAX'];
  217. end;
  218. function power(bas,expo : real) : real;
  219. begin
  220. power:=exp(ln(bas)*expo);
  221. end;
  222. {$else DEFAULT_EXTENDED}
  223. {****************************************************************************
  224. EXTENDED data type routines
  225. ****************************************************************************}
  226. function pi : extended;{$ifdef MORECONST}[internconst:in_const_pi];{$endif}
  227. begin
  228. asm
  229. fldpi
  230. leave
  231. ret
  232. end [];
  233. end;
  234. function abs(d : extended) : extended;[internconst:in_const_abs];
  235. begin
  236. asm
  237. fldt 8(%ebp)
  238. fabs
  239. leave
  240. ret $10
  241. end [];
  242. end;
  243. function sqr(d : extended) : extended;[internconst:in_const_sqr];
  244. begin
  245. asm
  246. fldt 8(%ebp)
  247. fldt 8(%ebp)
  248. fmulp
  249. leave
  250. ret $10
  251. end [];
  252. end;
  253. function sqrt(d : extended) : extended;{$ifdef MORECONST}[internconst:in_const_sqrt];{$endif}
  254. begin
  255. asm
  256. fldt 8(%ebp)
  257. fsqrtl
  258. leave
  259. ret $10
  260. end [];
  261. end;
  262. function arctan(d : extended) : extended;{$ifdef MORECONST}[internconst:in_const_arctan];{$endif}
  263. begin
  264. asm
  265. fldt 8(%ebp)
  266. fld1
  267. fpatan
  268. leave
  269. ret $10
  270. end [];
  271. end;
  272. function cos(d : extended) : extended;{$ifdef MORECONST}[internconst:in_const_cos];{$endif}
  273. begin
  274. asm
  275. fldt 8(%ebp)
  276. fcos
  277. fstsw
  278. sahf
  279. jnp .LCOS1
  280. fstp %st(0)
  281. fldt .LCOS0
  282. .LCOS1:
  283. leave
  284. ret $10
  285. .LCOS0:
  286. .long 0xffffffff
  287. .long 0xffffffff
  288. .word 0xffff
  289. end ['EAX'];
  290. end;
  291. function exp(d : extended) : extended;{$ifdef MORECONST}[internconst:in_const_exp];{$endif}
  292. begin
  293. asm
  294. // comes from DJ GPP
  295. fldt 8(%ebp)
  296. fldl2e
  297. fmulp
  298. fstcw .LCW1
  299. fstcw .LCW2
  300. fwait
  301. andw $0xf3ff,.LCW2
  302. orw $0x0400,.LCW2
  303. fldcw .LCW2
  304. fld %st(0)
  305. frndint
  306. fldcw .LCW1
  307. fxch %st(1)
  308. fsub %st(1),%st
  309. f2xm1
  310. fld1
  311. faddp
  312. fscale
  313. fstp %st(1)
  314. leave
  315. ret $10
  316. // store some help data in the data segment
  317. .data
  318. .LCW1:
  319. .word 0
  320. .LCW2:
  321. .word 0
  322. .text
  323. end;
  324. end;
  325. function frac(d : extended) : extended;[internconst:in_const_frac];
  326. begin
  327. asm
  328. subl $16,%esp
  329. fnstcw -4(%ebp)
  330. fwait
  331. movw -4(%ebp),%cx
  332. orw $0x0c3f,%cx
  333. movw %cx,-8(%ebp)
  334. fldcw -8(%ebp)
  335. fwait
  336. fldt 8(%ebp)
  337. frndint
  338. fldt 8(%ebp)
  339. fsub %st(1)
  340. fstp %st(1)
  341. fclex
  342. fldcw -4(%ebp)
  343. leave
  344. ret $10
  345. end ['ECX'];
  346. end;
  347. function int(d : extended) : extended;[internconst:in_const_int];
  348. begin
  349. asm
  350. subl $16,%esp
  351. fnstcw -4(%ebp)
  352. fwait
  353. movw -4(%ebp),%cx
  354. orw $0x0c3f,%cx
  355. movw %cx,-8(%ebp)
  356. fldcw -8(%ebp)
  357. fwait
  358. fldt 8(%ebp)
  359. frndint
  360. fclex
  361. fldcw -4(%ebp)
  362. leave
  363. ret $10
  364. end ['ECX'];
  365. end;
  366. function trunc(d : extended) : longint;[internconst:in_const_trunc];
  367. begin
  368. asm
  369. subl $16,%esp
  370. fnstcw -4(%ebp)
  371. fwait
  372. movw -4(%ebp),%cx
  373. orw $0x0c3f,%cx
  374. movw %cx,-8(%ebp)
  375. fldcw -8(%ebp)
  376. fwait
  377. fldt 8(%ebp)
  378. fistpl -8(%ebp)
  379. movl -8(%ebp),%eax
  380. fldcw -4(%ebp)
  381. leave
  382. ret $10
  383. end ['EAX','ECX'];
  384. end;
  385. function round(d : extended) : longint;[internconst:in_const_round];
  386. begin
  387. asm
  388. subl $8,%esp
  389. fnstcw -4(%ebp)
  390. fwait
  391. movw $0x1372,-8(%ebp)
  392. fldcw -8(%ebp)
  393. fwait
  394. fldt 8(%ebp)
  395. fistpl -8(%ebp)
  396. movl -8(%ebp),%eax
  397. fldcw -4(%ebp)
  398. leave
  399. ret $10
  400. end ['EAX','ECX'];
  401. end;
  402. function ln(d : extended) : extended;{$ifdef MORECONST}[internconst:in_const_ln];{$endif}
  403. begin
  404. asm
  405. fldln2
  406. fldt 8(%ebp)
  407. fyl2x
  408. leave
  409. ret $10
  410. end [];
  411. end;
  412. function sin(d : extended) : extended;{$ifdef MORECONST}[internconst:in_const_sin];{$endif}
  413. begin
  414. asm
  415. fldt 8(%ebp)
  416. fsin
  417. fstsw
  418. sahf
  419. jnp .LSIN1
  420. fstp %st(0)
  421. fldt .LSIN0
  422. .LSIN1:
  423. leave
  424. ret $10
  425. .LSIN0:
  426. .long 0xffffffff
  427. .long 0xffffffff
  428. .word 0xffff
  429. end ['EAX'];
  430. end;
  431. function power(bas,expo : extended) : extended;
  432. begin
  433. power:=exp(ln(bas)*expo);
  434. end;
  435. {$endif DEFAULT_EXTENDED}
  436. {****************************************************************************
  437. Longint data type routines
  438. ****************************************************************************}
  439. function power(bas,expo : longint) : longint;
  440. begin
  441. power:=round(exp(ln(bas)*expo));
  442. end;
  443. {****************************************************************************
  444. Fixed data type routines
  445. ****************************************************************************}
  446. {$ifdef _SUPPORT_FIXED} { Not yet allowed }
  447. function sqrt(d : fixed) : fixed;
  448. begin
  449. asm
  450. movl d,%eax
  451. movl %eax,%ebx
  452. movl %eax,%ecx
  453. jecxz .L_kl
  454. xorl %esi,%esi
  455. .L_it:
  456. xorl %edx,%edx
  457. idivl %ebx
  458. addl %ebx,%eax
  459. shrl $1,%eax
  460. subl %eax,%esi
  461. cmpl $1,%esi
  462. jbe .L_kl
  463. movl %eax,%esi
  464. movl %eax,%ebx
  465. movl %ecx,%eax
  466. jmp .L_it
  467. .L_kl:
  468. shl $8,%eax
  469. leave
  470. ret $4
  471. end;
  472. end;
  473. function int(d : fixed) : fixed;
  474. {*****************************************************************}
  475. { Returns the integral part of d }
  476. {*****************************************************************}
  477. begin
  478. int:=d and $ffff0000; { keep only upper bits }
  479. end;
  480. function trunc(d : fixed) : longint;
  481. {*****************************************************************}
  482. { Returns the Truncated integral part of d }
  483. {*****************************************************************}
  484. begin
  485. trunc:=longint(integer(d shr 16)); { keep only upper 16 bits }
  486. end;
  487. function frac(d : fixed) : fixed;
  488. {*****************************************************************}
  489. { Returns the Fractional part of d }
  490. {*****************************************************************}
  491. begin
  492. frac:=d AND $ffff; { keep only decimal parts - lower 16 bits }
  493. end;
  494. function abs(d : fixed) : fixed;
  495. {*****************************************************************}
  496. { Returns the Absolute value of d }
  497. {*****************************************************************}
  498. begin
  499. asm
  500. movl d,%eax
  501. rol $16,%eax { Swap high & low word.}
  502. {Absolute value: Invert all bits and increment when <0 .}
  503. cwd { When ax<0, dx contains $ffff}
  504. xorw %dx,%ax { Inverts all bits when dx=$ffff.}
  505. subw %dx,%ax { Increments when dx=$ffff.}
  506. rol $16,%eax { Swap high & low word.}
  507. leave
  508. ret $4
  509. end;
  510. end;
  511. function sqr(d : fixed) : fixed;
  512. {*****************************************************************}
  513. { Returns the Absolute squared value of d }
  514. {*****************************************************************}
  515. begin
  516. {16-bit precision needed, not 32 =)}
  517. sqr := d*d;
  518. { sqr := (d SHR 8 * d) SHR 8; }
  519. end;
  520. function Round(x: fixed): longint;
  521. {*****************************************************************}
  522. { Returns the Rounded value of d as a longint }
  523. {*****************************************************************}
  524. var
  525. lowf:integer;
  526. highf:integer;
  527. begin
  528. lowf:=x and $ffff; { keep decimal part ... }
  529. highf :=integer(x shr 16);
  530. if lowf > 5 then
  531. highf:=highf+1
  532. else
  533. if lowf = 5 then
  534. begin
  535. { here we must check the sign ... }
  536. { if greater or equal to zero, then }
  537. { greater value will be found by adding }
  538. { one... }
  539. if highf >= 0 then
  540. Highf:=Highf+1;
  541. end;
  542. Round:= longint(highf);
  543. end;
  544. {$endif SUPPORT_FIXED}
  545. {$ASMMODE ATT}
  546. {
  547. $Log$
  548. Revision 1.10 1998-10-02 09:25:29 peter
  549. * more constant expression evals
  550. Revision 1.9 1998/09/11 17:38:49 pierre
  551. merge for fixes branch
  552. Revision 1.8.2.1 1998/09/11 17:37:25 pierre
  553. * correction respective to stricter as v2.9.1 syntax
  554. Revision 1.8 1998/09/01 17:36:18 peter
  555. + internconst
  556. Revision 1.7 1998/08/25 08:49:05 florian
  557. * corrected exp() function
  558. Revision 1.6 1998/08/11 21:39:04 peter
  559. * splitted default_extended from support_extended
  560. Revision 1.5 1998/08/11 00:04:50 peter
  561. * $ifdef ver0_99_5 updates
  562. Revision 1.4 1998/08/10 15:54:50 peter
  563. * removed dup power(longint)
  564. Revision 1.3 1998/08/08 12:28:09 florian
  565. * a lot small fixes to the extended data type work
  566. Revision 1.2 1998/05/31 14:15:49 peter
  567. * force to use ATT or direct parsing
  568. }