Author: rgrjr
Date: Sat May 12 08:37:58 2007
New Revision: 18517
Modified:
trunk/src/pmc/scalar.pmc
trunk/t/pmc/bigint.t
Log:
* src/pmc/scalar.pmc:
+ (Parrot_BigInt_bitwise_shl_int): Bug fix: Force overflow for
"extreme" left shifts, and always underflow to zero for extreme
right shifts.
* t/pmc/bigint.t:
+ Add a regression test to make sure a 64-bit shl really shifts.
Tested on i686 and x86_64.
Modified: trunk/src/pmc/scalar.pmc
==============================================================================
--- trunk/src/pmc/scalar.pmc (original)
+++ trunk/src/pmc/scalar.pmc Sat May 12 08:37:58 2007
@@ -38,15 +38,23 @@
int overflow_p = 0;
/* Compute the shift. */
- if (shift_amount >= 0) {
+ if (shift_amount >= 8*INTVAL_SIZE) {
+ /* Extreme left shift; no need to do an integer shift first. */
+ overflow_p = 1;
+ }
+ else if (shift_amount >= 0) {
/* Left shift. */
result = base << shift_amount;
overflow_p = (result >> shift_amount) != base;
}
- else {
+ else if (shift_amount > -8*INTVAL_SIZE) {
/* Right shift. By definition, this can never overflow. */
result = base >> -shift_amount;
}
+ else {
+ /* Extreme right shift. */
+ result = 0;
+ }
/* Store the result. */
if (! overflow_p) {
Modified: trunk/t/pmc/bigint.t
==============================================================================
--- trunk/t/pmc/bigint.t (original)
+++ trunk/t/pmc/bigint.t Sat May 12 08:37:58 2007
@@ -25,7 +25,7 @@
=cut
if ( $PConfig{gmp} ) {
- plan tests => 43;
+ plan tests => 44;
}
else {
plan skip_all => "No BigInt Lib configured";
@@ -902,6 +902,25 @@
current instr/
OUT
+pir_output_is( <<'CODE', <<'OUT', "shl_int by 64 bits also promotes to
Bigint");
+## The C << and >> ops take the right arg modulo the word size in bits (at
least
+## on all the systems I have available), so both 32- and 64-bit systems treat
+## shifting by 64 bits as shifting by zero.
+.sub main :main
+ new $P0, .Integer
+ set $P0, 1000001
+ new $P1, .Integer
+ set $P1, 64
+ n_shl $P2, $P0, $P1
+ $S2 = typeof $P2
+ print $S2
+ print ' '
+ say $P2
+.end
+CODE
+BigInt 18446762520453625325551616
+OUT
+
pir_output_is( <<'CODE', <<'OUT', "shr_int and i_shr_int with a neg shift
promote Integer to Bigint");
.sub main :main
new $P0, .Integer