From: Jarkko Hietaniemi Date: Sun, 5 Sep 1999 21:30:54 +0000 (+0000) Subject: Time is not yet ripe. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d0ba1bd2be06981094763112f29fa147de3d9441;p=p5sagit%2Fp5-mst-13.2.git Time is not yet ripe. p4raw-id: //depot/cfgperl@4079 --- diff --git a/pod/perldelta.pod b/pod/perldelta.pod index a228530..353c62d 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -150,37 +150,31 @@ use "quads" (64-integers) as follows: =over 4 -=item literal numeric constants in the code +=item constants in the code =item arguments to oct() and hex() =item arguments to print(), printf() and sprintf() -=item pack() and unpack() "q" and "Q" formats +=item pack() and unpack() "q" format -=item in basic arithmetics: +, -, *, /, % +=item in basic arithmetics -=item in bit arithmetics: &, |, ^, ~, <<, >>, vec() +=item vec() (but see the below note about bit arithmetics) =back Note that unless you have the case (a) you will have to configure and compile Perl using the -Duse64bits Configure flag. +Unfortunately bit arithmetics (&, |, ^, ~, <<, >>) are not 64-bit clean. + Last but not least: note that due to Perl's habit of always using -floating point numbers (inherently inexact) the quads are still not -true integers (exact). When the quads overflow their limits -(0...18_446_744_073_709_551_615 unsigned, -9_223_372_036_854_775_808... -9_223_372_036_854_775_807 signed), they are silently promoted to -floating point numbers, after which they will start losing precision -(their lower digits). What this means, among other things, is that -adding/subtracting small numbers doesn't change the large number, -and that == may return equalness for numbers that are not equal. -One particular cause of grief is using the ~ operator which when -used on small numbers produces large numbers. These large numbers -stay (internally) integers for only as long as bit arithmetics are -used, but for example + will turn the results into floating point -numbers. +floating point numbers the quads are still not true integers. +When quads overflow their limits (0...18_446_744_073_709_551_615 unsigned, +-9_223_372_036_854_775_808...9_223_372_036_854_775_807 signed), they +are silently promoted to floating point numbers, after which they will +start losing precision (their lower digits). =head2 Large file support @@ -188,10 +182,9 @@ If you have filesystems that support "large files" (files larger than 2 gigabytes), you may now also be able to create and access them from Perl. Note that in addition to requiring a proper file system to do this you -may also need to adjust your per-process (or even your per-system, or -per-user group) maximum filesize limits before running Perl scripts -that try to handle large files, especially if you intend to write such -files (reading may work even without adjustments). +may also need to adjust your per-process (or even your per-system) +maximum filesize limits before running Perl scripts that try to handle +large files, especially if you intend to write such files. Adjusting your file system/system limits is outside the scope of Perl. For process limits, you may try to increase the limits using your diff --git a/pod/perlop.pod b/pod/perlop.pod index 6c2cb33..2b5b789 100644 --- a/pod/perlop.pod +++ b/pod/perlop.pod @@ -221,14 +221,14 @@ Binary "." concatenates two strings. Binary "<<" returns the value of its left argument shifted left by the number of bits specified by the right argument. Arguments should be integers. (See also L.) Shifting more than the -width of an integer in bits (usually 32 or 64) produces undefined -(platform dependent) results. +width of the available integer in bits (usually 32 or 64) produces +undefined (machine dependent) results. Binary ">>" returns the value of its left argument shifted right by the number of bits specified by the right argument. Arguments should -be integers. (See also L.) Shifting more than -the width of an integer in bits (usually 32 or 64) produces undefined -(platform dependent) results. +be integers. (See also L.) Shifting more than the +width of the available integer in bits (usually 32 or 64) produces +undefined (machine dependent) results. =head2 Named Unary Operators diff --git a/pp.c b/pp.c index cde539c..081d4b4 100644 --- a/pp.c +++ b/pp.c @@ -28,6 +28,37 @@ static double UV_MAX_cxux = ((double)UV_MAX); #endif /* + * Types used in bitwise operations. + * + * Normally we'd just use IV and UV. However, some hardware and + * software combinations (e.g. Alpha and current OSF/1) don't have a + * floating-point type to use for NV that has adequate bits to fully + * hold an IV/UV. (In other words, sizeof(long) == sizeof(double).) + * + * It just so happens that "int" is the right size almost everywhere. + */ +typedef int IBW; +typedef unsigned UBW; + +/* + * Mask used after bitwise operations. + * + * There is at least one realm (Cray word machines) that doesn't + * have an integral type (except char) small enough to be represented + * in a double without loss; that is, it has no 32-bit type. + */ +#if LONGSIZE > 4 && defined(_CRAY) && !defined(_CRAYMPP) +# define BW_BITS 32 +# define BW_MASK ((1 << BW_BITS) - 1) +# define BW_SIGN (1 << (BW_BITS - 1)) +# define BWi(i) (((i) & BW_SIGN) ? ((i) | ~BW_MASK) : ((i) & BW_MASK)) +# define BWu(u) ((u) & BW_MASK) +#else +# define BWi(i) (i) +# define BWu(u) (u) +#endif + +/* * Offset for integer pack/unpack. * * On architectures where I16 and I32 aren't really 16 and 32 bits, @@ -1100,11 +1131,17 @@ PP(pp_left_shift) { djSP; dATARGET; tryAMAGICbin(lshift,opASSIGN); { - IV shift = POPi; - if (PL_op->op_private & HINT_INTEGER) - SETi(TOPi << shift); - else - SETu(TOPu << shift); + IBW shift = POPi; + if (PL_op->op_private & HINT_INTEGER) { + IBW i = TOPi; + i = BWi(i) << shift; + SETi(BWi(i)); + } + else { + UBW u = TOPu; + u <<= shift; + SETu(BWu(u)); + } RETURN; } } @@ -1113,11 +1150,17 @@ PP(pp_right_shift) { djSP; dATARGET; tryAMAGICbin(rshift,opASSIGN); { - IV shift = POPi; - if (PL_op->op_private & HINT_INTEGER) - SETi(TOPi >> shift); - else - SETu(TOPu >> shift); + IBW shift = POPi; + if (PL_op->op_private & HINT_INTEGER) { + IBW i = TOPi; + i = BWi(i) >> shift; + SETi(BWi(i)); + } + else { + UBW u = TOPu; + u >>= shift; + SETu(BWu(u)); + } RETURN; } } @@ -1285,10 +1328,14 @@ PP(pp_bit_and) { dPOPTOPssrl; if (SvNIOKp(left) || SvNIOKp(right)) { - if (PL_op->op_private & HINT_INTEGER) - SETi( SvIV(left) & SvIV(right) ); - else - SETu( SvUV(left) & SvUV(right) ); + if (PL_op->op_private & HINT_INTEGER) { + IBW value = SvIV(left) & SvIV(right); + SETi(BWi(value)); + } + else { + UBW value = SvUV(left) & SvUV(right); + SETu(BWu(value)); + } } else { do_vop(PL_op->op_type, TARG, left, right); @@ -1304,10 +1351,14 @@ PP(pp_bit_xor) { dPOPTOPssrl; if (SvNIOKp(left) || SvNIOKp(right)) { - if (PL_op->op_private & HINT_INTEGER) - SETi( (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right) ); - else - SETu( (USE_LEFT(left) ? SvUV(left) : 0) ^ SvUV(right) ); + if (PL_op->op_private & HINT_INTEGER) { + IBW value = (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right); + SETi(BWi(value)); + } + else { + UBW value = (USE_LEFT(left) ? SvUV(left) : 0) ^ SvUV(right); + SETu(BWu(value)); + } } else { do_vop(PL_op->op_type, TARG, left, right); @@ -1323,10 +1374,14 @@ PP(pp_bit_or) { dPOPTOPssrl; if (SvNIOKp(left) || SvNIOKp(right)) { - if (PL_op->op_private & HINT_INTEGER) - SETi( (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right) ); - else - SETu( (USE_LEFT(left) ? SvUV(left) : 0) | SvUV(right) ); + if (PL_op->op_private & HINT_INTEGER) { + IBW value = (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right); + SETi(BWi(value)); + } + else { + UBW value = (USE_LEFT(left) ? SvUV(left) : 0) | SvUV(right); + SETu(BWu(value)); + } } else { do_vop(PL_op->op_type, TARG, left, right); @@ -1385,10 +1440,14 @@ PP(pp_complement) { dTOPss; if (SvNIOKp(sv)) { - if (PL_op->op_private & HINT_INTEGER) - SETi( ~SvIV(sv) ); - else - SETu( ~SvUV(sv) ); + if (PL_op->op_private & HINT_INTEGER) { + IBW value = ~SvIV(sv); + SETi(BWi(value)); + } + else { + UBW value = ~SvUV(sv); + SETu(BWu(value)); + } } else { register char *tmps; diff --git a/t/op/64bit.t b/t/op/64bit.t index fce8e7a..5625b4f 100644 --- a/t/op/64bit.t +++ b/t/op/64bit.t @@ -13,19 +13,17 @@ BEGIN { # Nota bene: bit operations (&, |, ^, ~, <<, >>) are not 64-bit clean. # See the beginning of pp.c and the explanation next to IBW/UBW. -# So that using > 0xfffffff constants and -# 32+ bit vector sizes and shift doesn't cause noise. +# so that using > 0xfffffff constants and +# 32+ bit vector sizes doesn't cause noise no warnings qw(overflow portable); -print "1..48\n"; +print "1..39\n"; my $q = 12345678901; my $r = 23456789012; my $f = 0xffffffff; my $x; my $y; -my $z; - $x = unpack "q", pack "q", $q; print "not " unless $x == $q && $x > $f; @@ -202,32 +200,4 @@ print "ok 38\n"; print "not " unless vec($x, 0, 64) == 0 && vec($x, 2, 64) == 0; print "ok 39\n"; - -print "not " unless ($q & $r) == 1442844692; -print "ok 40\n"; - -print "not " unless ($q | $r) == 34359623221; -print "ok 41\n"; - -print "not " unless ($q ^ $r) == 32916778529; -print "ok 42\n"; - -print "not " unless ~$q == 18446744061363872714; -print "ok 43\n"; - -print "not " unless ($q << 1) == 24691357802; -print "ok 44\n"; - -print "not " unless (($q << 1) >> 1) == $q; -print "ok 45\n"; - -print "not " unless (1 << 32) == 2**32; # Risky because of the **? -print "ok 46\n"; - -print "not " unless ((1 << 40) >> 32) == 256; -print "ok 47\n"; - -print "not " unless (1 << 63) == ~0 ^ (~0 >> 1); -print "ok 48\n"; - # eof diff --git a/t/op/misc.t b/t/op/misc.t index 3c385cd..926c7f3 100755 --- a/t/op/misc.t +++ b/t/op/misc.t @@ -59,12 +59,11 @@ $a = ":="; split /($a)/o, "a:=b:=c"; print "@_" EXPECT a := b := c ######## -use integer; $cusp = ~0 ^ (~0 >> 1); $, = " "; print +($cusp - 1) % 8, $cusp % 8, -$cusp % 8, ($cusp + 1) % 8, "!\n"; EXPECT --1 0 0 1 ! +7 0 0 1 ! ######## $foo=undef; $foo->go; EXPECT