=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
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
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<Integer Arithmetic>.) 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<Integer Arithmetic>.) Shifting more than
-the width of an integer in bits (usually 32 or 64) produces undefined
-(platform dependent) results.
+be integers. (See also L<Integer Arithmetic>.) Shifting more than the
+width of the available integer in bits (usually 32 or 64) produces
+undefined (machine dependent) results.
=head2 Named Unary Operators
#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,
{
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;
}
}
{
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;
}
}
{
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);
{
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);
{
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);
{
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;
# 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;
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
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