int64.inc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1998 by the Free Pascal development team
  5. This file contains some helper routines for int64 and qword
  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. {$Q- no overflow checking }
  13. {$R- no range checking }
  14. type
  15. tqwordrec = packed record
  16. low : dword;
  17. high : dword;
  18. end;
  19. procedure int_overflow;
  20. begin
  21. runerror(201);
  22. end;
  23. function count_leading_zeros(q : qword) : longint;
  24. var
  25. r,i : longint;
  26. begin
  27. r:=0;
  28. for i:=0 to 31 do
  29. begin
  30. if (tqwordrec(q).high and ($80000000 shr i))<>0 then
  31. begin
  32. count_leading_zeros:=r;
  33. exit;
  34. end;
  35. inc(r);
  36. end;
  37. for i:=0 to 31 do
  38. begin
  39. if (tqwordrec(q).low and ($80000000 shr i))<>0 then
  40. begin
  41. count_leading_zeros:=r;
  42. exit;
  43. end;
  44. inc(r);
  45. end;
  46. count_leading_zeros:=r;
  47. end;
  48. function divqword(z,n : qword) : qword;[public,alias: 'FPC_DIV_QWORD'];
  49. var
  50. shift,lzz,lzn : longint;
  51. one : qword;
  52. begin
  53. { we can't write qword direct currently }
  54. divqword:=divqword xor divqword;
  55. tqwordrec(one).high:=0;
  56. tqwordrec(one).high:=1;
  57. lzz:=count_leading_zeros(z);
  58. lzn:=count_leading_zeros(n);
  59. { if the denominator contains less zeros }
  60. { then the numerator }
  61. { the d is greater than the n }
  62. if lzn<lzz then
  63. exit;
  64. shift:=lzn-lzz;
  65. n:=n shl shift;
  66. repeat
  67. if z>n then
  68. begin
  69. z:=z-n;
  70. divqword:=divqword+(one shl shift);
  71. end;
  72. dec(shift);
  73. n:=n shr one;
  74. until shift<=0;
  75. end;
  76. function modqword(z,n : qword) : qword;[public,alias: 'FPC_MOD_QWORD'];
  77. var
  78. shift,lzz,lzn : longint;
  79. begin
  80. modqword:=z;
  81. lzz:=count_leading_zeros(z);
  82. lzn:=count_leading_zeros(n);
  83. { if the denominator contains less zeros }
  84. { the d is greater than the n }
  85. if lzn<lzz then
  86. exit;
  87. shift:=lzn-lzz;
  88. n:=n shl shift;
  89. repeat
  90. if z>n then
  91. z:=z-n;
  92. dec(shift);
  93. n:=n shr 1;
  94. until shift<=0;
  95. modqword:=z;
  96. end;
  97. function divint64(z,n : int64) : int64;[public,alias: 'FPC_DIV_INT64'];
  98. var
  99. sign : boolean;
  100. q1,q2 : qword;
  101. begin
  102. sign:=false;
  103. if z<0 then
  104. begin
  105. sign:=not(sign);
  106. q1:=qword(-z);
  107. end
  108. else
  109. q1:=z;
  110. if n<0 then
  111. begin
  112. sign:=not(sign);
  113. q2:=qword(-n);
  114. end
  115. else
  116. q2:=n;
  117. { the div is coded by the compiler as call to divqword }
  118. if sign then
  119. divint64:=-q1 div q2
  120. else
  121. divint64:=q1 div q2;
  122. end;
  123. { multiplies two qwords
  124. the longbool for checkoverflow avoids a misaligned stack
  125. }
  126. function mulqword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD'];
  127. var
  128. zero,bitpos64,bitpos : qword;
  129. l : longint;
  130. begin
  131. { we can't write currently qword constants directly :( }
  132. zero:=zero xor zero;
  133. mulqword:=zero;
  134. tqwordrec(bitpos64).high:=$80000000;
  135. tqwordrec(bitpos64).low:=0;
  136. tqwordrec(bitpos).high:=0;
  137. tqwordrec(bitpos).low:=1;
  138. for l:=0 to 63 do
  139. begin
  140. { if the highest bit of f1 is set and it isn't the
  141. last run, then an overflow occcurs!
  142. }
  143. if checkoverflow and (l<>63) and
  144. ((tqwordrec(f1).high and $80000000)<>0) then
  145. int_overflow;
  146. if (f2 and bitpos)<>zero then
  147. begin
  148. if checkoverflow then
  149. {$Q+}
  150. mulqword:=mulqword+f1
  151. {$Q-}
  152. else
  153. mulqword:=mulqword+f1;
  154. end;
  155. f1:=f1 shl 1;
  156. bitpos:=bitpos shl 1;
  157. end;
  158. end;
  159. { multiplies two int64 ....
  160. fpuint64 = false:
  161. ... using the the qword multiplication
  162. fpuint64 = true:
  163. ... using the comp multiplication
  164. the longbool for checkoverflow avoids a misaligned stack
  165. }
  166. function mulint64(f1,f2 : int64;checkoverflow : longbool) : int64;[public,alias: 'FPC_MUL_INT64'];
  167. var
  168. sign : boolean;
  169. q1,q2,q3 : qword;
  170. begin
  171. sign:=false;
  172. if f1<0 then
  173. begin
  174. sign:=not(sign);
  175. q1:=qword(-f1);
  176. end
  177. else
  178. q1:=f1;
  179. if f2<0 then
  180. begin
  181. sign:=not(sign);
  182. q2:=qword(-f2);
  183. end
  184. else
  185. q2:=f2;
  186. { the q1*q2 is coded as call to mulqword }
  187. if checkoverflow then
  188. {$Q+}
  189. q3:=q1*q2
  190. else
  191. {$Q-}
  192. q3:=q1*q2;
  193. if sign then
  194. mulint64:=-q3
  195. else
  196. mulint64:=q3;
  197. end;
  198. procedure int_str(value : qword;var s : string);
  199. var
  200. hs : string;
  201. begin
  202. {!!!!!!!!!!!
  203. hs:='';
  204. repeat
  205. hs:=chr(longint(value mod 10)+48)+hs;
  206. value:=value div 10;
  207. until value=0;
  208. s:=hs;
  209. }
  210. end;
  211. procedure int_str(value : int64;var s : string);
  212. var
  213. hs : string;
  214. q : qword;
  215. begin
  216. if value<0 then
  217. begin
  218. q:=qword(-value);
  219. int_str(q,hs);
  220. s:='-'+hs;
  221. end
  222. else
  223. int_str(qword(value),s);
  224. end;
  225. {
  226. $Log$
  227. Revision 1.6 1999-06-02 10:13:16 florian
  228. * multiplication fixed
  229. Revision 1.5 1999/05/25 20:36:41 florian
  230. * some bugs removed
  231. Revision 1.4 1999/05/24 08:43:46 florian
  232. * fixed a couple of syntax errors
  233. Revision 1.3 1999/05/23 20:27:27 florian
  234. + routines for qword div and mod
  235. Revision 1.2 1999/01/06 12:25:03 florian
  236. * naming for str(...) routines inserted
  237. * don't know what in int64 changed
  238. Revision 1.1 1998/12/12 12:15:41 florian
  239. + first implementation
  240. }