int64.inc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 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. function count_leading_zeros(q : qword) : longint;
  20. var
  21. r,i : longint;
  22. begin
  23. r:=0;
  24. for i:=0 to 31 do
  25. begin
  26. if (tqwordrec(q).high and ($80000000 shr i))<>0 then
  27. begin
  28. count_leading_zeros:=r;
  29. exit;
  30. end;
  31. inc(r);
  32. end;
  33. for i:=0 to 31 do
  34. begin
  35. if (tqwordrec(q).low and ($80000000 shr i))<>0 then
  36. begin
  37. count_leading_zeros:=r;
  38. exit;
  39. end;
  40. inc(r);
  41. end;
  42. count_leading_zeros:=r;
  43. end;
  44. function divqword(n,z : qword) : qword;[public,alias: 'FPC_DIV_QWORD'];
  45. var
  46. shift,lzz,lzn : longint;
  47. { one : qword; }
  48. begin
  49. divqword:=0;
  50. if n=0 then
  51. HandleErrorFrame(200,get_frame);
  52. lzz:=count_leading_zeros(z);
  53. lzn:=count_leading_zeros(n);
  54. { if the denominator contains less zeros }
  55. { then the numerator }
  56. { the d is greater than the n }
  57. if lzn<lzz then
  58. exit;
  59. shift:=lzn-lzz;
  60. n:=n shl shift;
  61. repeat
  62. if z>=n then
  63. begin
  64. z:=z-n;
  65. divqword:=divqword+(qword(1) shl shift);
  66. end;
  67. dec(shift);
  68. n:=n shr 1;
  69. until shift<0;
  70. end;
  71. function modqword(n,z : qword) : qword;[public,alias: 'FPC_MOD_QWORD'];
  72. var
  73. shift,lzz,lzn : longint;
  74. begin
  75. modqword:=0;
  76. if n=0 then
  77. HandleErrorFrame(200,get_frame);
  78. lzz:=count_leading_zeros(z);
  79. lzn:=count_leading_zeros(n);
  80. { if the denominator contains less zeros }
  81. { then the numerator }
  82. { the d is greater than the n }
  83. if lzn<lzz then
  84. begin
  85. modqword:=z;
  86. exit;
  87. end;
  88. shift:=lzn-lzz;
  89. n:=n shl shift;
  90. repeat
  91. if z>=n then
  92. z:=z-n;
  93. dec(shift);
  94. n:=n shr 1;
  95. until shift<0;
  96. modqword:=z;
  97. end;
  98. function divint64(n,z : int64) : int64;[public,alias: 'FPC_DIV_INT64'];
  99. var
  100. sign : boolean;
  101. q1,q2 : qword;
  102. begin
  103. if n=0 then
  104. HandleErrorFrame(200,get_frame);
  105. { can the fpu do the work? }
  106. if fpuint64 then
  107. //!!!!!!!!!!! divint64:=comp(z)/comp(n)
  108. else
  109. begin
  110. sign:=false;
  111. if z<0 then
  112. begin
  113. sign:=not(sign);
  114. q1:=qword(-z);
  115. end
  116. else
  117. q1:=z;
  118. if n<0 then
  119. begin
  120. sign:=not(sign);
  121. q2:=qword(-n);
  122. end
  123. else
  124. q2:=n;
  125. { the div is coded by the compiler as call to divqword }
  126. if sign then
  127. divint64:=-(q1 div q2)
  128. else
  129. divint64:=q1 div q2;
  130. end;
  131. end;
  132. { multiplies two qwords
  133. the longbool for checkoverflow avoids a misaligned stack
  134. }
  135. function mulqword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD'];
  136. var
  137. _f1,bitpos : qword;
  138. l : longint;
  139. begin
  140. mulqword:=0;
  141. bitpos:=1;
  142. // store f1 for overflow checking
  143. _f1:=f1;
  144. for l:=0 to 63 do
  145. begin
  146. if (f2 and bitpos)<>0 then
  147. mulqword:=mulqword+f1;
  148. f1:=f1 shl 1;
  149. bitpos:=bitpos shl 1;
  150. end;
  151. { if one of the operands is greater than the result an }
  152. { overflow occurs }
  153. if checkoverflow and ((_f1>mulqword) or (f2>mulqword)) then
  154. HandleErrorFrame(215,get_frame);
  155. end;
  156. { multiplies two int64 ....
  157. fpuint64 = false:
  158. ... using the the qword multiplication
  159. fpuint64 = true:
  160. ... using the comp multiplication
  161. the longbool for checkoverflow avoids a misaligned stack
  162. }
  163. function mulint64(f1,f2 : int64;checkoverflow : longbool) : int64;[public,alias: 'FPC_MUL_INT64'];
  164. var
  165. sign : boolean;
  166. q1,q2,q3 : qword;
  167. begin
  168. { can the fpu do the work ? }
  169. if fpuint64 and not(checkoverflow) then
  170. // !!!!!!! multint64:=comp(f1)*comp(f2)
  171. else
  172. begin
  173. sign:=false;
  174. if f1<0 then
  175. begin
  176. sign:=not(sign);
  177. q1:=qword(-f1);
  178. end
  179. else
  180. q1:=f1;
  181. if f2<0 then
  182. begin
  183. sign:=not(sign);
  184. q2:=qword(-f2);
  185. end
  186. else
  187. q2:=f2;
  188. { the q1*q2 is coded as call to mulqword }
  189. q3:=q1*q2;
  190. if checkoverflow and ((q1>q3) or (q2>q3) or
  191. { the bit 63 can be only set if we have $80000000 00000000 }
  192. { and sign is true }
  193. ((tqwordrec(q3).high and $80000000)<>0) and
  194. ((q3<>(qword(1) shl 63)) or not(sign))
  195. ) then
  196. HandleErrorFrame(215,get_frame);
  197. if sign then
  198. mulint64:=-q3
  199. else
  200. mulint64:=q3;
  201. end;
  202. end;
  203. procedure qword_str(value : qword;var s : string);
  204. var
  205. hs : string;
  206. begin
  207. hs:='';
  208. repeat
  209. hs:=chr(longint(value mod 10)+48)+hs;
  210. value:=value div 10;
  211. until value=0;
  212. s:=hs;
  213. end;
  214. procedure int64_str(value : int64;var s : string);
  215. var
  216. hs : string;
  217. q : qword;
  218. begin
  219. if value<0 then
  220. begin
  221. q:=qword(-value);
  222. int_str(q,hs);
  223. s:='-'+hs;
  224. end
  225. else
  226. qword_str(qword(value),s);
  227. end;
  228. procedure int_str_qword(v : qword;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_QWORD'];
  229. begin
  230. qword_str(v,s);
  231. if length(s)<len then
  232. s:=space(len-length(s))+s;
  233. end;
  234. procedure int_str_int64(v : int64;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_INT64'];
  235. begin
  236. int64_str(v,s);
  237. if length(s)<len then
  238. s:=space(len-length(s))+s;
  239. end;
  240. procedure int_str_qword(v : qword;len : longint;var s : ansistring);[public,alias:'FPC_ANSISTR_QWORD'];
  241. var
  242. ss : shortstring;
  243. begin
  244. int_str_qword(v,len,ss);
  245. s:=ss;
  246. end;
  247. procedure int_str_int64(v : int64;len : longint;var s : ansistring);[public,alias:'FPC_ANSISTR_INT64'];
  248. var
  249. ss : shortstring;
  250. begin
  251. int_str_int64(v,len,ss);
  252. s:=ss;
  253. end;
  254. {
  255. $Log$
  256. Revision 1.14 2000-01-07 16:41:34 daniel
  257. * copyright 2000
  258. Revision 1.13 1999/07/05 20:04:23 peter
  259. * removed temp defines
  260. Revision 1.12 1999/07/04 16:34:45 florian
  261. + str routines added
  262. Revision 1.11 1999/07/02 17:01:29 florian
  263. * multiplication overflow checking fixed
  264. Revision 1.10 1999/07/01 15:39:50 florian
  265. + qword/int64 type released
  266. Revision 1.9 1999/06/30 22:12:40 florian
  267. * qword div/mod fixed
  268. + int64 mod/div/* fully implemented
  269. * int_str(qword) fixed
  270. + dummies for read/write(qword)
  271. Revision 1.8 1999/06/28 22:25:25 florian
  272. * fixed qword division
  273. Revision 1.7 1999/06/25 12:24:44 pierre
  274. * qword one was wrong !
  275. Revision 1.6 1999/06/02 10:13:16 florian
  276. * multiplication fixed
  277. Revision 1.5 1999/05/25 20:36:41 florian
  278. * some bugs removed
  279. Revision 1.4 1999/05/24 08:43:46 florian
  280. * fixed a couple of syntax errors
  281. Revision 1.3 1999/05/23 20:27:27 florian
  282. + routines for qword div and mod
  283. Revision 1.2 1999/01/06 12:25:03 florian
  284. * naming for str(...) routines inserted
  285. * don't know what in int64 changed
  286. Revision 1.1 1998/12/12 12:15:41 florian
  287. + first implementation
  288. }