int64.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  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. c : comp;
  103. begin
  104. if n=0 then
  105. HandleErrorFrame(200,get_frame);
  106. { can the fpu do the work? }
  107. if fpuint64 then
  108. begin
  109. // the c:=comp(...) is necessary to shut up the compiler
  110. c:=comp(comp(z)/comp(n));
  111. divint64:=qword(c);
  112. end
  113. else
  114. begin
  115. sign:=false;
  116. if z<0 then
  117. begin
  118. sign:=not(sign);
  119. q1:=qword(-z);
  120. end
  121. else
  122. q1:=z;
  123. if n<0 then
  124. begin
  125. sign:=not(sign);
  126. q2:=qword(-n);
  127. end
  128. else
  129. q2:=n;
  130. { the div is coded by the compiler as call to divqword }
  131. if sign then
  132. divint64:=-(q1 div q2)
  133. else
  134. divint64:=q1 div q2;
  135. end;
  136. end;
  137. { multiplies two qwords
  138. the longbool for checkoverflow avoids a misaligned stack
  139. }
  140. function mulqword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD'];
  141. var
  142. _f1,bitpos : qword;
  143. l : longint;
  144. {$ifdef i386}
  145. r : qword;
  146. {$endif i386}
  147. begin
  148. {$ifdef i386}
  149. if not(checkoverflow) then
  150. begin
  151. asm
  152. movl f1+4,%edx
  153. movl f2+4,%ecx
  154. orl %ecx,%edx
  155. movl f2,%edx
  156. movl f1,%eax
  157. jnz .Lqwordmultwomul
  158. mull %edx
  159. jmp .Lqwordmulready
  160. .Lqwordmultwomul:
  161. imul f1+4,%edx
  162. imul %eax,%ecx
  163. addl %edx,%ecx
  164. mull f2
  165. add %ecx,%edx
  166. .Lqwordmulready:
  167. movl %eax,r
  168. movl %edx,r+4
  169. end;
  170. mulqword:=r;
  171. end
  172. else
  173. {$endif i386}
  174. begin
  175. mulqword:=0;
  176. bitpos:=1;
  177. // store f1 for overflow checking
  178. _f1:=f1;
  179. for l:=0 to 63 do
  180. begin
  181. if (f2 and bitpos)<>0 then
  182. mulqword:=mulqword+f1;
  183. f1:=f1 shl 1;
  184. bitpos:=bitpos shl 1;
  185. end;
  186. { if one of the operands is greater than the result an }
  187. { overflow occurs }
  188. if checkoverflow and ((_f1>mulqword) or (f2>mulqword)) then
  189. HandleErrorFrame(215,get_frame);
  190. end;
  191. end;
  192. { multiplies two int64 ....
  193. fpuint64 = false:
  194. ... using the the qword multiplication
  195. fpuint64 = true:
  196. ... using the comp multiplication
  197. the longbool for checkoverflow avoids a misaligned stack
  198. }
  199. function mulint64(f1,f2 : int64;checkoverflow : longbool) : int64;[public,alias: 'FPC_MUL_INT64'];
  200. var
  201. sign : boolean;
  202. q1,q2,q3 : qword;
  203. c : comp;
  204. begin
  205. { can the fpu do the work ? }
  206. if fpuint64 and not(checkoverflow) then
  207. begin
  208. // the c:=comp(...) is necessary to shut up the compiler
  209. c:=comp(comp(f1)*comp(f2));
  210. mulint64:=int64(c);
  211. end
  212. else
  213. begin
  214. sign:=false;
  215. if f1<0 then
  216. begin
  217. sign:=not(sign);
  218. q1:=qword(-f1);
  219. end
  220. else
  221. q1:=f1;
  222. if f2<0 then
  223. begin
  224. sign:=not(sign);
  225. q2:=qword(-f2);
  226. end
  227. else
  228. q2:=f2;
  229. { the q1*q2 is coded as call to mulqword }
  230. q3:=q1*q2;
  231. if checkoverflow and ((q1>q3) or (q2>q3) or
  232. { the bit 63 can be only set if we have $80000000 00000000 }
  233. { and sign is true }
  234. ((tqwordrec(q3).high and $80000000)<>0) and
  235. ((q3<>(qword(1) shl 63)) or not(sign))
  236. ) then
  237. HandleErrorFrame(215,get_frame);
  238. if sign then
  239. mulint64:=-q3
  240. else
  241. mulint64:=q3;
  242. end;
  243. end;
  244. procedure qword_str(value : qword;var s : string);
  245. var
  246. hs : string;
  247. begin
  248. hs:='';
  249. repeat
  250. hs:=chr(longint(value mod 10)+48)+hs;
  251. value:=value div 10;
  252. until value=0;
  253. s:=hs;
  254. end;
  255. procedure int64_str(value : int64;var s : string);
  256. var
  257. hs : string;
  258. q : qword;
  259. begin
  260. if value<0 then
  261. begin
  262. q:=qword(-value);
  263. qword_str(q,hs);
  264. s:='-'+hs;
  265. end
  266. else
  267. qword_str(qword(value),s);
  268. end;
  269. procedure int_str_qword(v : qword;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_QWORD'];
  270. begin
  271. qword_str(v,s);
  272. if length(s)<len then
  273. s:=space(len-length(s))+s;
  274. end;
  275. procedure int_str_int64(v : int64;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_INT64'];
  276. begin
  277. int64_str(v,s);
  278. if length(s)<len then
  279. s:=space(len-length(s))+s;
  280. end;
  281. procedure int_str_qword(v : qword;len : longint;var s : ansistring);[public,alias:'FPC_ANSISTR_QWORD'];
  282. var
  283. ss : shortstring;
  284. begin
  285. int_str_qword(v,len,ss);
  286. s:=ss;
  287. end;
  288. procedure int_str_int64(v : int64;len : longint;var s : ansistring);[public,alias:'FPC_ANSISTR_INT64'];
  289. var
  290. ss : shortstring;
  291. begin
  292. int_str_int64(v,len,ss);
  293. s:=ss;
  294. end;
  295. Function ValInt64(DestSize: longint; Const S: ShortString; var Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR'];
  296. var
  297. u, temp, prev : Int64;
  298. base : byte;
  299. negative : boolean;
  300. begin
  301. ValInt64 := 0;
  302. Temp:=0;
  303. Code:=InitVal(s,negative,base);
  304. if Code>length(s) then
  305. exit;
  306. if negative and (s='-9223372036854775808') then
  307. begin
  308. Code:=0;
  309. ValInt64:=Int64($80000000) shl 32;
  310. exit;
  311. end;
  312. while Code<=Length(s) do
  313. begin
  314. case s[Code] of
  315. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  316. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  317. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  318. else
  319. u:=16;
  320. end;
  321. Prev:=Temp;
  322. Temp:=Temp*Int64(base);
  323. if (Temp<prev) Then
  324. Begin
  325. ValInt64:=0;
  326. Exit
  327. End;
  328. prev:=temp;
  329. Temp:=Temp+u;
  330. if prev>temp then
  331. begin
  332. ValInt64:=0;
  333. exit;
  334. end;
  335. inc(code);
  336. end;
  337. code:=0;
  338. ValInt64:=Temp;
  339. If Negative Then
  340. ValInt64:=-ValInt64;
  341. end;
  342. Function ValQWord(Const S: ShortString; var Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR'];
  343. var
  344. u, prev: QWord;
  345. base : byte;
  346. negative : boolean;
  347. begin
  348. ValQWord:=0;
  349. Code:=InitVal(s,negative,base);
  350. If Negative or (Code>length(s)) Then
  351. Exit;
  352. while Code<=Length(s) do
  353. begin
  354. case s[Code] of
  355. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  356. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  357. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  358. else
  359. u:=16;
  360. end;
  361. prev := ValQWord;
  362. ValQWord:=ValQWord*QWord(base);
  363. If (prev>ValQWord) or (u>base) Then
  364. Begin
  365. ValQWord := 0;
  366. Exit
  367. End;
  368. prev:=ValQWord;
  369. ValQWord:=ValQWord+u;
  370. if prev>ValQWord then
  371. begin
  372. ValQWord:=0;
  373. exit;
  374. end;
  375. inc(code);
  376. end;
  377. code := 0;
  378. end;
  379. {
  380. $Log$
  381. Revision 1.17 2000-01-27 15:43:02 florian
  382. * improved qword*qword code, if no overflow checking is done
  383. Revision 1.16 2000/01/23 12:27:39 florian
  384. * int64/int64 and int64*int64 is now done by the fpu if possible
  385. Revision 1.15 2000/01/23 12:22:37 florian
  386. * reading of 64 bit type implemented
  387. Revision 1.14 2000/01/07 16:41:34 daniel
  388. * copyright 2000
  389. Revision 1.13 1999/07/05 20:04:23 peter
  390. * removed temp defines
  391. Revision 1.12 1999/07/04 16:34:45 florian
  392. + str routines added
  393. Revision 1.11 1999/07/02 17:01:29 florian
  394. * multiplication overflow checking fixed
  395. Revision 1.10 1999/07/01 15:39:50 florian
  396. + qword/int64 type released
  397. Revision 1.9 1999/06/30 22:12:40 florian
  398. * qword div/mod fixed
  399. + int64 mod/div/* fully implemented
  400. * int_str(qword) fixed
  401. + dummies for read/write(qword)
  402. Revision 1.8 1999/06/28 22:25:25 florian
  403. * fixed qword division
  404. Revision 1.7 1999/06/25 12:24:44 pierre
  405. * qword one was wrong !
  406. Revision 1.6 1999/06/02 10:13:16 florian
  407. * multiplication fixed
  408. Revision 1.5 1999/05/25 20:36:41 florian
  409. * some bugs removed
  410. Revision 1.4 1999/05/24 08:43:46 florian
  411. * fixed a couple of syntax errors
  412. Revision 1.3 1999/05/23 20:27:27 florian
  413. + routines for qword div and mod
  414. Revision 1.2 1999/01/06 12:25:03 florian
  415. * naming for str(...) routines inserted
  416. * don't know what in int64 changed
  417. Revision 1.1 1998/12/12 12:15:41 florian
  418. + first implementation
  419. }