3 This file is part of the Free Pascal run time library.
4 Copyright (c) 1999-2000 by the Free Pascal development team
6 This file contains some helper routines for int64 and qword
8 See the file COPYING.FPC, included in this distribution,
9 for details about the copyright.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 **********************************************************************}
16 {$Q- no overflow checking }
17 {$R- no range checking }
20 tqwordrec = packed record
25 function count_leading_zeros(q : qword) : longint;
34 if (tqwordrec(q).high and ($80000000 shr i))<>0 then
36 count_leading_zeros:=r;
43 if (tqwordrec(q).low and ($80000000 shr i))<>0 then
45 count_leading_zeros:=r;
50 count_leading_zeros:=r;
53 function divqword(n,z : qword) : qword;[public,alias: 'FPC_DIV_QWORD'];
56 shift,lzz,lzn : longint;
62 HandleErrorFrame(200,get_frame);
63 lzz:=count_leading_zeros(z);
64 lzn:=count_leading_zeros(n);
65 { if the denominator contains less zeros }
66 { then the numerator }
67 { the d is greater than the n }
76 divqword:=divqword+(qword(1) shl shift);
83 function modqword(n,z : qword) : qword;[public,alias: 'FPC_MOD_QWORD'];
86 shift,lzz,lzn : longint;
91 HandleErrorFrame(200,get_frame);
92 lzz:=count_leading_zeros(z);
93 lzn:=count_leading_zeros(n);
94 { if the denominator contains less zeros }
95 { then the numerator }
96 { the d is greater than the n }
113 function divint64(n,z : int64) : int64;[public,alias: 'FPC_DIV_INT64'];
122 HandleErrorFrame(200,get_frame);
123 { can the fpu do the work? }
126 // the c:=comp(...) is necessary to shut up the compiler
127 c:=comp(comp(z)/comp(n));
148 { the div is coded by the compiler as call to divqword }
150 divint64:=-(q1 div q2)
156 function modint64(n,z : int64) : int64;[public,alias: 'FPC_MOD_INT64'];
164 HandleErrorFrame(200,get_frame);
189 { multiplies two qwords
190 the longbool for checkoverflow avoids a misaligned stack
192 function mulqword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD'];
204 if not(checkoverflow) then
233 // store f1 for overflow checking
238 if (f2 and bitpos)<>0 then
239 mulqword:=mulqword+f1;
242 bitpos:=bitpos shl 1;
245 { if one of the operands is greater than the result an }
247 if checkoverflow and (_f1 <> 0) and (f2 <>0) and
248 ((_f1>mulqword) or (f2>mulqword)) then
249 HandleErrorFrame(215,get_frame);
253 { multiplies two int64 ....
255 ... using the the qword multiplication
257 ... using the comp multiplication
258 the longbool for checkoverflow avoids a misaligned stack
260 function mulint64(f1,f2 : int64;checkoverflow : longbool) : int64;[public,alias: 'FPC_MUL_INT64'];
268 { can the fpu do the work ? }
269 if fpuint64 and not(checkoverflow) then
271 // the c:=comp(...) is necessary to shut up the compiler
272 c:=comp(comp(f1)*comp(f2));
292 { the q1*q2 is coded as call to mulqword }
295 if checkoverflow and (q1 <> 0) and (q2 <>0) and
296 ((q1>q3) or (q2>q3) or
297 { the bit 63 can be only set if we have $80000000 00000000 }
299 ((tqwordrec(q3).high and $80000000)<>0) and
300 ((q3<>(qword(1) shl 63)) or not(sign))
302 HandleErrorFrame(215,get_frame);
311 procedure qword_str(value : qword;var s : string);
319 hs:=chr(longint(value mod 10)+48)+hs;
325 procedure int64_str(value : int64;var s : string);
339 qword_str(qword(value),s);
342 procedure int_str_qword(v : qword;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_QWORD'];
346 if length(s)<len then
347 s:=space(len-length(s))+s;
350 procedure int_str_int64(v : int64;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_INT64'];
354 if length(s)<len then
355 s:=space(len-length(s))+s;
358 procedure int_str_qword(v : qword;len : longint;var s : ansistring);[public,alias:'FPC_ANSISTR_QWORD'];
364 int_str_qword(v,len,ss);
368 procedure int_str_int64(v : int64;len : longint;var s : ansistring);[public,alias:'FPC_ANSISTR_INT64'];
374 int_str_int64(v,len,ss);
378 Function ValInt64(Const S: ShortString; var Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR'];
380 QWordRec = packed record
385 u, temp, prev, maxint64, maxqword : qword;
392 Code:=InitVal(s,negative,base);
393 if Code>length(s) then
395 { high(int64) produces 0 in version 1.0 (JM) }
396 with qwordrec(maxint64) do
401 with qwordrec(maxqword) do
407 while Code<=Length(s) do
410 '0'..'9' : u:=Ord(S[Code])-Ord('0');
411 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
412 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
417 Temp:=Temp*Int64(base);
420 (maxint64-temp+ord(negative) < u)) or
422 (qword(maxqword-temp) < u)) or
423 (prev > maxqword div qword(base)) Then
432 ValInt64:=int64(Temp);
438 Function ValQWord(Const S: ShortString; var Code: ValSInt):QWord;[public,alias:'FPC_VAL_QWORD_SHORTSTR'];
439 type qwordrec = packed record
443 u, prev, maxqword: QWord;
448 Code:=InitVal(s,negative,base);
449 If Negative or (Code>length(s)) Then
451 with qwordrec(maxqword) do
456 while Code<=Length(s) do
459 '0'..'9' : u:=Ord(S[Code])-Ord('0');
460 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
461 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
467 ((QWord(maxqword-u) div QWord(base))<prev) then
472 ValQWord:=ValQWord*QWord(base)+u;
480 Revision 1.1 2002/02/19 08:25:23 sasu
483 Revision 1.1.2.6 2000/12/09 22:54:06 florian
484 * helper name for qword-val fixed
486 Revision 1.1.2.5 2000/12/09 22:37:31 florian
487 * fixed last commit, under go32v2 it worked
489 Revision 1.1.2.4 2000/12/09 20:49:33 florian
490 * val for dword and qword didn't handle the max values
492 * val for qword works again
493 + val with int64/qword and ansistring implemented
495 Revision 1.1.2.3 2000/11/17 16:56:42 jonas
496 * fixed bug for val when processing -2147483648 and low(int64)
498 Revision 1.1.2.2 2000/07/28 12:19:21 jonas
500 * fixed similar (and other) problems in val() for int64 and qword
502 Revision 1.1.2.1 2000/07/16 08:55:26 jonas
503 * fixed false overflow error if one of the operands of an int64/qword
506 Revision 1.1 2000/07/13 06:30:47 michael
509 Revision 1.20 2000/03/17 21:27:56 jonas
510 * fixed declaration of val_int64 (removed destsize parameter)
511 * fixed val_int64 and val_qword so they reject invalid input
513 * when reading a number, invalid input is removed from the input
514 buffer (+ it should be faster as well)
516 Revision 1.19 2000/02/09 22:19:24 florian
517 + helper routine for <int64> mod <in64> added
519 Revision 1.18 2000/02/09 16:59:30 peter
522 Revision 1.17 2000/01/27 15:43:02 florian
523 * improved qword*qword code, if no overflow checking is done
525 Revision 1.16 2000/01/23 12:27:39 florian
526 * int64/int64 and int64*int64 is now done by the fpu if possible
528 Revision 1.15 2000/01/23 12:22:37 florian
529 * reading of 64 bit type implemented
531 Revision 1.14 2000/01/07 16:41:34 daniel