math.inc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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;[internproc:in_pi];
  18. {$define FPC_SYSTEM_HAS_ABS}
  19. function abs(d : extended) : extended;[internproc:in_abs_extended];
  20. {$define FPC_SYSTEM_HAS_SQR}
  21. function sqr(d : extended) : extended;[internproc:in_sqr_extended];
  22. {$define FPC_SYSTEM_HAS_SQRT}
  23. function sqrt(d : extended) : extended;[internproc:in_sqrt_extended];
  24. {
  25. function arctan(d : extended) : extended;[internconst:in_arctan_extended];
  26. begin
  27. runerror(207);
  28. end;
  29. function ln(d : extended) : extended;[internconst:in_ln_extended];
  30. begin
  31. runerror(207);
  32. end;
  33. function sin(d : extended) : extended;[internconst: in_sin_extended];
  34. begin
  35. runerror(207);
  36. end;
  37. function cos(d : extended) : extended;[internconst:in_cos_extended];
  38. begin
  39. runerror(207);
  40. end;
  41. function exp(d : extended) : extended;[internconst:in_const_exp];
  42. begin
  43. runerror(207);
  44. end;
  45. function frac(d : extended) : extended;[internconst:in_const_frac];
  46. begin
  47. runerror(207);
  48. end;
  49. }
  50. {$define FPC_SYSTEM_HAS_INT}
  51. {$warning FIX ME}
  52. function int(d : extended) : extended;[internconst:in_const_int];
  53. begin
  54. runerror(207);
  55. end;
  56. {$define FPC_SYSTEM_HAS_TRUNC}
  57. {$warning FIX ME, trunc is working only for longint}
  58. function trunc(d : extended) : int64;assembler;[internconst:in_const_trunc];
  59. { input: d in fr1 }
  60. { output: result in r3 }
  61. assembler;
  62. var
  63. temp: packed record
  64. case byte of
  65. 0: (l1,l2: longint);
  66. 1: (d: double);
  67. end;
  68. asm
  69. fctiwz f1,f1
  70. stfd f1,temp
  71. xor r4,r4,r4
  72. lwz r3,4+temp
  73. end ['R3','R4','F1'];
  74. {$define FPC_SYSTEM_HAS_ROUND}
  75. {$ifdef hascompilerproc}
  76. function round(d : extended) : int64;[internconst:in_const_round, external name 'FPC_ROUND'];
  77. function fpc_round(d : extended) : int64;assembler;[public, alias:'FPC_ROUND'];{$ifdef hascompilerproc}compilerproc;{$endif hascompilerproc}
  78. {$else}
  79. function round(d : extended) : int64;assembler;[internconst:in_const_round];
  80. {$endif hascompilerproc}
  81. { input: d in fr1 }
  82. { output: result in r3 }
  83. assembler;
  84. var
  85. temp : packed record
  86. case byte of
  87. 0: (l1,l2: longint);
  88. 1: (d: double);
  89. end;
  90. asm
  91. fctiw f1,f1
  92. stfd f1,temp
  93. lwz r3,temp
  94. lwz r4,4+temp
  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. {$define FPC_SYSTEM_HAS_POWER_INT64}
  119. function power(bas,expo : int64) : int64;
  120. begin
  121. if bas=0 then
  122. begin
  123. if expo<>0 then
  124. power:=0
  125. else
  126. HandleError(207);
  127. end
  128. else if expo=0 then
  129. power:=1
  130. else
  131. begin
  132. if bas<0 then
  133. begin
  134. if odd(expo) then
  135. power:=-round(exp(ln(-bas)*expo))
  136. else
  137. power:=round(exp(ln(-bas)*expo));
  138. end
  139. else
  140. power:=round(exp(ln(bas)*expo));
  141. end;
  142. end;
  143. {****************************************************************************
  144. Helper routines to support old TP styled reals
  145. ****************************************************************************}
  146. { warning: the following converts a little-endian TP-style real }
  147. { to a big-endian double. So don't byte-swap the TP real! }
  148. {$define FPC_SYSTEM_HAS_REAL2DOUBLE}
  149. function real2double(r : real48) : double;
  150. var
  151. res : array[0..7] of byte;
  152. exponent : word;
  153. begin
  154. { copy mantissa }
  155. res[6]:=0;
  156. res[5]:=r[1] shl 5;
  157. res[4]:=(r[1] shr 3) or (r[2] shl 5);
  158. res[3]:=(r[2] shr 3) or (r[3] shl 5);
  159. res[2]:=(r[3] shr 3) or (r[4] shl 5);
  160. res[1]:=(r[4] shr 3) or (r[5] and $7f) shl 5;
  161. res[0]:=(r[5] and $7f) shr 3;
  162. { copy exponent }
  163. { correct exponent: }
  164. exponent:=(word(r[0])+(1023-129));
  165. res[1]:=res[1] or ((exponent and $f) shl 4);
  166. res[0]:=exponent shr 4;
  167. { set sign }
  168. res[0]:=res[0] or (r[5] and $80);
  169. real2double:=double(res);
  170. end;
  171. {****************************************************************************
  172. Int to real helpers
  173. ****************************************************************************}
  174. const
  175. longint_to_real_helper: int64 = $4330000080000000;
  176. cardinal_to_real_helper: int64 = $430000000000000;
  177. int_to_real_factor: double = double(high(cardinal))+1.0;
  178. function fpc_int64_to_double(i: int64): double; compilerproc;
  179. assembler;
  180. { input: high(i) in r3, low(i) in r4 }
  181. { output: double(i) in f0 }
  182. var
  183. temp: packed record
  184. case byte of
  185. 0: (l1,l2: cardinal);
  186. 1: (d: double);
  187. end;
  188. asm
  189. lis r0,0x4330
  190. stw r0,temp
  191. xoris r3,r3,0x8000
  192. stw r3,4+temp
  193. {$ifndef macos}
  194. lis r3,longint_to_real_helper@ha
  195. lfd f1,longint_to_real_helper@l(r3)
  196. {$else}
  197. lwz r3,longint_to_real_helper[TC](r2)
  198. lfd f1,0(r3)
  199. {$endif}
  200. lfd f0,temp
  201. stw r4,4+temp
  202. fsub f0,f0,f1
  203. {$ifndef macos}
  204. lis r4,cardinal_to_real_helper@ha
  205. lfd f1,cardinal_to_real_helper@l(r4)
  206. lis r3,int_to_real_factor@ha
  207. lfd f3,temp
  208. lfd f2,int_to_real_factor@l(r3)
  209. {$else}
  210. lwz r4,cardinal_to_real_helper[TC](r2)
  211. lwz r3,int_to_real_factor[TC](r2)
  212. lfd f3,temp
  213. lfd f1,0(r4)
  214. lfd f2,0(r3)
  215. {$endif}
  216. fsub f3,f3,f1
  217. fmadd f1,f0,f2,f3
  218. end ['R0','R3','R4','F0','F1','F2','F3'];
  219. function fpc_qword_to_double(q: qword): double; compilerproc;
  220. assembler;
  221. { input: high(q) in r3, low(q) in r4 }
  222. { output: double(q) in f0 }
  223. var
  224. temp: packed record
  225. case byte of
  226. 0: (l1,l2: cardinal);
  227. 1: (d: double);
  228. end;
  229. asm
  230. lis r0,0x4330
  231. stw r0,temp
  232. stw r3,4+temp
  233. lfd f0,temp
  234. {$ifndef macos}
  235. lis r3,cardinal_to_real_helper@ha
  236. lfd f1,cardinal_to_real_helper@l(r3)
  237. {$else}
  238. lwz r3,longint_to_real_helper[TC](r2)
  239. lfd f1,0(r3)
  240. {$endif}
  241. stw r4,4+temp
  242. fsub f0,f0,f1
  243. lfd f3,temp
  244. {$ifndef macos}
  245. lis r3,int_to_real_factor@ha
  246. lfd f2,int_to_real_factor@l(r3)
  247. {$else}
  248. lwz r3,int_to_real_factor[TC](r2)
  249. lfd f2,0(r3)
  250. {$endif}
  251. fsub f3,f3,f1
  252. fmadd f1,f0,f2,f3
  253. end ['R0','R3','F0','F1','F2','F3'];
  254. {
  255. $Log$
  256. Revision 1.18 2003-04-26 17:20:16 florian
  257. * fixed trunc, now it's working at least for longint range
  258. Revision 1.17 2003/04/23 21:28:21 peter
  259. * fpc_round added, needed for int64 currency
  260. Revision 1.16 2003/01/16 11:29:11 olle
  261. * changed access of globals to be indirect via TOC
  262. Revision 1.15 2003/01/15 01:09:04 florian
  263. * changed power(...) prototype to int64
  264. Revision 1.14 2002/11/28 11:04:16 olle
  265. * macos: refs to globals in asm adapted to macos
  266. Revision 1.13 2002/10/21 18:08:28 jonas
  267. * round has int64 instead of longint result
  268. Revision 1.12 2002/09/08 13:00:21 jonas
  269. * made pi an internproc instead of internconst
  270. Revision 1.11 2002/09/07 16:01:26 peter
  271. * old logs removed and tabs fixed
  272. Revision 1.10 2002/08/18 22:11:10 florian
  273. * fixed remaining assembler errors
  274. Revision 1.9 2002/08/18 21:37:48 florian
  275. * several errors in inline assembler fixed
  276. Revision 1.8 2002/08/10 17:14:36 jonas
  277. * various fixes, mostly changing the names of the modifies registers to
  278. upper case since that seems to be required by the compiler
  279. Revision 1.7 2002/07/31 16:58:12 jonas
  280. * fixed conversion from int64/qword to double errors
  281. Revision 1.6 2002/07/29 21:28:17 florian
  282. * several fixes to get further with linux/ppc system unit compilation
  283. Revision 1.5 2002/07/28 21:39:29 florian
  284. * made abs a compiler proc if it is generic
  285. Revision 1.4 2002/07/28 20:43:49 florian
  286. * several fixes for linux/powerpc
  287. * several fixes to MT
  288. }