math.inc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. function pi : double;[internconst:in_pi];
  17. begin
  18. pi := 3.14159265358979320;
  19. end;
  20. function abs(d : extended) : extended;[internproc:in_abs_extended];
  21. function sqr(d : extended) : extended;[internproc:in_sqr_extended];
  22. function sqrt(d : extended) : extended;[internproc:in_sqrt_extended];
  23. function arctan(d : extended) : extended;[internconst:in_arctan_extended];
  24. begin
  25. runerror(207);
  26. end;
  27. function ln(d : extended) : extended;[internconst:in_ln_extended];
  28. begin
  29. runerror(207);
  30. end;
  31. function sin(d : extended) : extended;[internconst: in_sin_extended];
  32. begin
  33. runerror(207);
  34. end;
  35. function cos(d : extended) : extended;[internconst:in_cos_extended];
  36. begin
  37. runerror(207);
  38. end;
  39. function exp(d : extended) : extended;assembler;[internconst:in_const_exp];
  40. begin
  41. runerror(207);
  42. end;
  43. function frac(d : extended) : extended;assembler;[internconst:in_const_frac];
  44. begin
  45. runerror(207);
  46. end;
  47. function int(d : extended) : extended;assembler;[internconst:in_const_int];
  48. begin
  49. runerror(207);
  50. end;
  51. function trunc(d : extended) : longint;assembler;[internconst:in_const_trunc];
  52. { input: d in fr1 }
  53. { output: result in r3 }
  54. assembler;
  55. var
  56. temp:
  57. record
  58. case byte of
  59. 0: (l1,l2: longint);
  60. 1: (d: double);
  61. end;
  62. asm
  63. fctiwz fr1,fr1
  64. stfd fr1,temp.d
  65. lwz r3,temp.l2
  66. end ['r3','fr1'];
  67. function round(d : extended) : longint;assembler;[internconst:in_const_round];
  68. { input: d in fr1 }
  69. { output: result in r3 }
  70. assembler;
  71. var
  72. temp:
  73. record
  74. case byte of
  75. 0: (l1,l2: longint);
  76. 1: (d: double);
  77. end;
  78. asm
  79. fctiw fr1,fr1
  80. stfd fr1,temp.d
  81. lwz r3,temp.l2
  82. end ['r3','fr1'];
  83. function power(bas,expo : extended) : extended;
  84. begin
  85. if bas=0 then
  86. begin
  87. if expo<>0 then
  88. power:=0.0
  89. else
  90. HandleError(207);
  91. end
  92. else if expo=0 then
  93. power:=1
  94. else
  95. { bas < 0 is not allowed }
  96. if bas<0 then
  97. handleerror(207)
  98. else
  99. power:=exp(ln(bas)*expo);
  100. end;
  101. {****************************************************************************
  102. Longint data type routines
  103. ****************************************************************************}
  104. function power(bas,expo : longint) : longint;
  105. begin
  106. if bas=0 then
  107. begin
  108. if expo<>0 then
  109. power:=0
  110. else
  111. HandleError(207);
  112. end
  113. else if expo=0 then
  114. power:=1
  115. else
  116. begin
  117. if bas<0 then
  118. begin
  119. if odd(expo) then
  120. power:=-round(exp(ln(-bas)*expo))
  121. else
  122. power:=round(exp(ln(-bas)*expo));
  123. end
  124. else
  125. power:=round(exp(ln(bas)*expo));
  126. end;
  127. end;
  128. {****************************************************************************
  129. Helper routines to support old TP styled reals
  130. ****************************************************************************}
  131. { warning: the following converts a little-endian TP-style real }
  132. { to a big-endian double. So don't byte-swap the TP real! }
  133. function real2double(r : real48) : double;
  134. var
  135. res : array[0..7] of byte;
  136. exponent : word;
  137. begin
  138. { copy mantissa }
  139. res[6]:=0;
  140. res[5]:=r[1] shl 5;
  141. res[4]:=(r[1] shr 3) or (r[2] shl 5);
  142. res[3]:=(r[2] shr 3) or (r[3] shl 5);
  143. res[2]:=(r[3] shr 3) or (r[4] shl 5);
  144. res[1]:=(r[4] shr 3) or (r[5] and $7f) shl 5;
  145. res[0]:=(r[5] and $7f) shr 3;
  146. { copy exponent }
  147. { correct exponent: }
  148. exponent:=(word(r[0])+(1023-129));
  149. res[1]:=res[1] or ((exponent and $f) shl 4);
  150. res[0]:=exponent shr 4;
  151. { set sign }
  152. res[0]:=res[0] or (r[5] and $80);
  153. real2double:=double(res);
  154. end;
  155. {****************************************************************************
  156. Int to real helpers
  157. ****************************************************************************}
  158. function fpc_int64_to_real(i: int64): double; compilerproc;
  159. assembler;
  160. { input: high(i) in r3, low(i) in r4 }
  161. { output: double(i) in f0 }
  162. var
  163. temp:
  164. record
  165. case byte of
  166. 0: (l1,l2: cardinal);
  167. 1: (d: double);
  168. end;
  169. asm
  170. lis r0,$4330
  171. stw r0,temp.l1
  172. xoris r3,r3,$8000
  173. stw r3,temp.l2
  174. lis r3,longint_to_real_helper@ha
  175. lfd fr1,longint_to_real_helper@l(r3)
  176. lfd fr0,temp.d
  177. stw r4,temp.l2
  178. fsub fr0,fr0,fr1
  179. lis r4,cardinal_to_real_helper@ha
  180. lfd fr1,cardinal_to_real_helper@l(r4)
  181. lis r3,int_to_real_factor@ha
  182. lfd fr3,temp
  183. lfd fr2,int_to_real_factor@l(r3)
  184. fsub fr3,fr3,fr1
  185. fmadd fr1,fr0,fr2,fr3
  186. end ['r0','r3','r4','fr0','fr1','fr2','fr3'];
  187. function fpc_qword_to_real(q: qword): double; compilerproc;
  188. assembler;
  189. { input: high(q) in r3, low(q) in r4 }
  190. { output: double(q) in f0 }
  191. var
  192. temp:
  193. record
  194. case byte of
  195. 0: (l1,l2: cardinal);
  196. 1: (d: double);
  197. end;
  198. asm
  199. lis r0,$4330
  200. stw r0,temp.l1
  201. stw r3,temp.l2
  202. lfd fr0,temp.d
  203. lis r3,cardinal_to_real_helper@ha
  204. lfd fr1,cardinal_to_real_helper@l(r3)
  205. stw r4,temp.l2
  206. fsub fr0,fr0,fr1
  207. lfd fr3,temp
  208. lis r3,int_to_real_factor@ha
  209. lfd fr2,int_to_real_factor@l(r3)
  210. fsub fr3,fr3,fr1
  211. fmadd fr1,fr0,fr2,fr3
  212. end ['r0','r3','fr0','fr1','fr2','fr3'];
  213. {
  214. $Log$
  215. Revision 1.3 2001-12-02 16:19:45 jonas
  216. * fpu results are returned in fr1, not fr0
  217. Revision 1.2 2001/10/30 17:18:14 jonas
  218. * fixed fpc_int64_to_double and fpc_int64_to_double (fpc_int64_to_double
  219. is now mostly tested and should work fine, fpc_qword_to_double should
  220. work too since it's almost the same)
  221. Revision 1.1 2001/10/28 14:09:13 jonas
  222. + initial implementation, lots of things still missing
  223. }