int64.inc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. begin
  52. divqword:=0;
  53. lzz:=count_leading_zeros(z);
  54. lzn:=count_leading_zeros(n);
  55. { if the denominator contains less zeros }
  56. { then the numerator }
  57. { the d is greater than the n }
  58. if lzn<lzz then
  59. exit;
  60. shift:=lzn-lzz;
  61. n:=n shl shift;
  62. repeat
  63. if z>n then
  64. begin
  65. z:=z-n;
  66. divqword:=divqword+(1 shl shift);
  67. end;
  68. dec(shift);
  69. n:=n shr 1;
  70. until shift<=0;
  71. end;
  72. function modqword(z,n : qword) : qword;[public,alias: 'FPC_MOD_QWORD'];
  73. var
  74. shift,lzz,lzn : longint;
  75. begin
  76. modqword:=z;
  77. lzz:=count_leading_zeros(z);
  78. lzn:=count_leading_zeros(n);
  79. { if the denominator contains less zeros }
  80. { the d is greater than the n }
  81. if lzn<lzz then
  82. exit;
  83. shift:=lzn-lzz;
  84. n:=n shl shift;
  85. repeat
  86. if z>n then
  87. z:=z-n;
  88. dec(shift);
  89. n:=n shr 1;
  90. until shift<=0;
  91. modqword:=z;
  92. end;
  93. function divint64(z,n : int64) : int64;[public,alias: 'FPC_DIV_INT64'];
  94. var
  95. sign : boolean;
  96. q1,q2 : qword;
  97. begin
  98. sign:=false;
  99. if z<0 then
  100. begin
  101. sign:=not(sign);
  102. q1:=qword(-z);
  103. end
  104. else
  105. q1:=z;
  106. if n<0 then
  107. begin
  108. sign:=not(sign);
  109. q2:=qword(-n);
  110. end
  111. else
  112. q2:=n;
  113. { the div is coded by the compiler as call to divqword }
  114. if sign then
  115. divint64:=-q1 div q2
  116. else
  117. divint64:=q1 div q2;
  118. end;
  119. { multiplies two qwords }
  120. function mulqword(f1,f2 : qword;checkoverflow : boolean) : qword;[public,alias: 'FPC_MUL_QWORD'];
  121. var
  122. bitpos64 : qword;
  123. l : longint;
  124. begin
  125. mulqword:=0;
  126. { we can't write currently qword constants directly :( }
  127. tqwordrec(bitpos64).high:=$80000000;
  128. tqwordrec(bitpos64).low:=0;
  129. for l:=0 to 63 do
  130. begin
  131. if (f2 and bitpos64)<>0 then
  132. if checkoverflow then
  133. {$Q+}
  134. mulqword:=mulqword+f1
  135. {$Q-}
  136. else
  137. mulqword:=mulqword+f1;
  138. if ((f1 and bitpos64)<>0) and checkoverflow then
  139. int_overflow;
  140. f1:=f1 shl 1;
  141. bitpos64:=bitpos64 shl 1;
  142. end;
  143. end;
  144. { multiplies two int64 ....
  145. fpuint64 = false:
  146. ... using the the qword multiplication
  147. fpuint64 = true:
  148. ... using the comp multiplication
  149. }
  150. function mulint64(f1,f2 : int64;checkoverflow : boolean) : int64;[public,alias: 'FPC_MUL_INT64'];
  151. var
  152. sign : boolean;
  153. q1,q2,q3 : qword;
  154. begin
  155. sign:=false;
  156. if f1<0 then
  157. begin
  158. sign:=not(sign);
  159. q1:=qword(-f1);
  160. end
  161. else
  162. q1:=f1;
  163. if f2<0 then
  164. begin
  165. sign:=not(sign);
  166. q2:=qword(-f2);
  167. end
  168. else
  169. q2:=f2;
  170. { the q1*q2 is coded as call to mulqword }
  171. if checkoverflow then
  172. {$Q+}
  173. q3:=q1*q2
  174. else
  175. {$Q-}
  176. q3:=q1*q2;
  177. if sign then
  178. mulint64:=-q3
  179. else
  180. mulint64:=q3;
  181. end;
  182. procedure int_str(value : qword;var s : string);
  183. var
  184. hs : string;
  185. begin
  186. hs:='';
  187. repeat
  188. hs:=chr(longint(value mod 10)+48)+hs;
  189. value:=value div 10;
  190. until value=0;
  191. s:=hs;
  192. end;
  193. procedure int_str(value : int64;var s : string);
  194. var
  195. hs : string;
  196. q : qword;
  197. begin
  198. if value<0 then
  199. begin
  200. q:=qword(-value);
  201. int_str(q,hs);
  202. s:='-'+hs;
  203. end
  204. else
  205. int_str(qword(value),s);
  206. end;
  207. {
  208. $Log$
  209. Revision 1.4 1999-05-24 08:43:46 florian
  210. * fixed a couple of syntax errors
  211. Revision 1.3 1999/05/23 20:27:27 florian
  212. + routines for qword div and mod
  213. Revision 1.2 1999/01/06 12:25:03 florian
  214. * naming for str(...) routines inserted
  215. * don't know what in int64 changed
  216. Revision 1.1 1998/12/12 12:15:41 florian
  217. + first implementation
  218. }