math.inc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2000 by Jonas Maebe and other members of the
  5. Free Pascal development team
  6. Implementation of mathamatical Routines (only for real)
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. {****************************************************************************
  14. EXTENDED data type routines
  15. ****************************************************************************}
  16. {$define FPC_SYSTEM_HAS_PI}
  17. function pi : double;[internconst:in_pi];
  18. begin
  19. pi := 3.14159265358979320;
  20. end;
  21. {$define FPC_SYSTEM_HAS_ABS}
  22. function abs(d : extended) : extended;[internproc:in_abs_extended];
  23. {$define FPC_SYSTEM_HAS_SQR}
  24. function sqr(d : extended) : extended;[internproc:in_sqr_extended];
  25. {$define FPC_SYSTEM_HAS_SQRT}
  26. function sqrt(d : extended) : extended;[internproc:in_sqrt_extended];
  27. {
  28. function arctan(d : extended) : extended;[internconst:in_arctan_extended];
  29. begin
  30. runerror(207);
  31. end;
  32. function ln(d : extended) : extended;[internconst:in_ln_extended];
  33. begin
  34. runerror(207);
  35. end;
  36. function sin(d : extended) : extended;[internconst: in_sin_extended];
  37. begin
  38. runerror(207);
  39. end;
  40. function cos(d : extended) : extended;[internconst:in_cos_extended];
  41. begin
  42. runerror(207);
  43. end;
  44. function exp(d : extended) : extended;[internconst:in_const_exp];
  45. begin
  46. runerror(207);
  47. end;
  48. function frac(d : extended) : extended;[internconst:in_const_frac];
  49. begin
  50. runerror(207);
  51. end;
  52. }
  53. {$define FPC_SYSTEM_HAS_INT}
  54. {$warning FIX ME}
  55. function int(d : extended) : extended;[internconst:in_const_int];
  56. begin
  57. runerror(207);
  58. end;
  59. {$define FPC_SYSTEM_HAS_TRUNC}
  60. {$warning FIX ME}
  61. function trunc(d : extended) : int64;assembler;[internconst:in_const_trunc];
  62. { input: d in fr1 }
  63. { output: result in r3 }
  64. assembler;
  65. var
  66. temp:
  67. record
  68. case byte of
  69. 0: (l1,l2: longint);
  70. 1: (d: double);
  71. end;
  72. asm
  73. fctiwz fr1,fr1
  74. stfd fr1,temp.d
  75. lwz r3,temp.l1
  76. lwz r4,temp.l2
  77. end ['R3','F1'];
  78. {$define FPC_SYSTEM_HAS_ROUND}
  79. function round(d : extended) : longint;assembler;[internconst:in_const_round];
  80. { input: d in fr1 }
  81. { output: result in r3 }
  82. assembler;
  83. var
  84. temp:
  85. record
  86. case byte of
  87. 0: (l1,l2: longint);
  88. 1: (d: double);
  89. end;
  90. asm
  91. fctiw fr1,fr1
  92. stfd fr1,temp.d
  93. lwz r3,temp.l1
  94. lwz r4,temp.l2
  95. end ['R3','F1'];
  96. {$define FPC_SYSTEM_HAS_POWER}
  97. function power(bas,expo : extended) : extended;
  98. begin
  99. if bas=0 then
  100. begin
  101. if expo<>0 then
  102. power:=0.0
  103. else
  104. HandleError(207);
  105. end
  106. else if expo=0 then
  107. power:=1
  108. else
  109. { bas < 0 is not allowed }
  110. if bas<0 then
  111. handleerror(207)
  112. else
  113. power:=exp(ln(bas)*expo);
  114. end;
  115. {****************************************************************************
  116. Longint data type routines
  117. ****************************************************************************}
  118. function power(bas,expo : longint) : longint;
  119. begin
  120. if bas=0 then
  121. begin
  122. if expo<>0 then
  123. power:=0
  124. else
  125. HandleError(207);
  126. end
  127. else if expo=0 then
  128. power:=1
  129. else
  130. begin
  131. if bas<0 then
  132. begin
  133. if odd(expo) then
  134. power:=-round(exp(ln(-bas)*expo))
  135. else
  136. power:=round(exp(ln(-bas)*expo));
  137. end
  138. else
  139. power:=round(exp(ln(bas)*expo));
  140. end;
  141. end;
  142. {****************************************************************************
  143. Helper routines to support old TP styled reals
  144. ****************************************************************************}
  145. { warning: the following converts a little-endian TP-style real }
  146. { to a big-endian double. So don't byte-swap the TP real! }
  147. {$define FPC_SYSTEM_HAS_REAL2DOUBLE}
  148. function real2double(r : real48) : double;
  149. var
  150. res : array[0..7] of byte;
  151. exponent : word;
  152. begin
  153. { copy mantissa }
  154. res[6]:=0;
  155. res[5]:=r[1] shl 5;
  156. res[4]:=(r[1] shr 3) or (r[2] shl 5);
  157. res[3]:=(r[2] shr 3) or (r[3] shl 5);
  158. res[2]:=(r[3] shr 3) or (r[4] shl 5);
  159. res[1]:=(r[4] shr 3) or (r[5] and $7f) shl 5;
  160. res[0]:=(r[5] and $7f) shr 3;
  161. { copy exponent }
  162. { correct exponent: }
  163. exponent:=(word(r[0])+(1023-129));
  164. res[1]:=res[1] or ((exponent and $f) shl 4);
  165. res[0]:=exponent shr 4;
  166. { set sign }
  167. res[0]:=res[0] or (r[5] and $80);
  168. real2double:=double(res);
  169. end;
  170. {****************************************************************************
  171. Int to real helpers
  172. ****************************************************************************}
  173. const
  174. longint_to_real_helper: int64 = $4330000080000000;
  175. cardinal_to_real_helper: int64 = $430000000000000;
  176. int_to_real_factor: double = double(high(cardinal))+1.0;
  177. function fpc_int64_to_double(i: int64): double; compilerproc;
  178. assembler;
  179. { input: high(i) in r3, low(i) in r4 }
  180. { output: double(i) in f0 }
  181. var
  182. temp:
  183. record
  184. case byte of
  185. 0: (l1,l2: cardinal);
  186. 1: (d: double);
  187. end;
  188. asm
  189. lis r0,$4330
  190. stw r0,temp.l1
  191. xoris r3,r3,$8000
  192. stw r3,temp.l2
  193. lis r3,longint_to_real_helper@ha
  194. lfd fr1,longint_to_real_helper@l(r3)
  195. lfd fr0,temp.d
  196. stw r4,temp.l2
  197. fsub fr0,fr0,fr1
  198. lis r4,cardinal_to_real_helper@ha
  199. lfd fr1,cardinal_to_real_helper@l(r4)
  200. lis r3,int_to_real_factor@ha
  201. lfd fr3,temp
  202. lfd fr2,int_to_real_factor@l(r3)
  203. fsub fr3,fr3,fr1
  204. fmadd fr1,fr0,fr2,fr3
  205. end ['R0','R3','R4','F0','F1','F2','F3'];
  206. function fpc_qword_to_double(q: qword): double; compilerproc;
  207. assembler;
  208. { input: high(q) in r3, low(q) in r4 }
  209. { output: double(q) in f0 }
  210. var
  211. temp:
  212. record
  213. case byte of
  214. 0: (l1,l2: cardinal);
  215. 1: (d: double);
  216. end;
  217. asm
  218. lis r0,$4330
  219. stw r0,temp.l1
  220. stw r3,temp.l2
  221. lfd fr0,temp.d
  222. lis r3,cardinal_to_real_helper@ha
  223. lfd fr1,cardinal_to_real_helper@l(r3)
  224. stw r4,temp.l2
  225. fsub fr0,fr0,fr1
  226. lfd fr3,temp
  227. lis r3,int_to_real_factor@ha
  228. lfd fr2,int_to_real_factor@l(r3)
  229. fsub fr3,fr3,fr1
  230. fmadd fr1,fr0,fr2,fr3
  231. end ['R0','R3','F0','F1','F2','F3'];
  232. {
  233. $Log$
  234. Revision 1.8 2002-08-10 17:14:36 jonas
  235. * various fixes, mostly changing the names of the modifies registers to
  236. upper case since that seems to be required by the compiler
  237. Revision 1.7 2002/07/31 16:58:12 jonas
  238. * fixed conversion from int64/qword to double errors
  239. Revision 1.6 2002/07/29 21:28:17 florian
  240. * several fixes to get further with linux/ppc system unit compilation
  241. Revision 1.5 2002/07/28 21:39:29 florian
  242. * made abs a compiler proc if it is generic
  243. Revision 1.4 2002/07/28 20:43:49 florian
  244. * several fixes for linux/powerpc
  245. * several fixes to MT
  246. Revision 1.3 2001/12/02 16:19:45 jonas
  247. * fpu results are returned in fr1, not fr0
  248. Revision 1.2 2001/10/30 17:18:14 jonas
  249. * fixed fpc_int64_to_double and fpc_int64_to_double (fpc_int64_to_double
  250. is now mostly tested and should work fine, fpc_qword_to_double should
  251. work too since it's almost the same)
  252. Revision 1.1 2001/10/28 14:09:13 jonas
  253. + initial implementation, lots of things still missing
  254. }