Author: rgrjr
Date: Sun May  6 08:11:30 2007
New Revision: 18435

Modified:
   trunk/src/pmc/bigint.pmc
   trunk/t/pmc/bigint.t

Log:
* src/pmc/bigint.pmc:
   + (bigint_bitwise_shl_bigint_int, bigint_bitwise_shr_bigint_int):
     Handle negative shift values by shifting in the other direction.
     This fixes a bug where GMP would run out of memory; the arg for the
     shift amount is unsigned.
* t/pmc/bigint.t:
   + Four new tests for negative BigInt shifts.


Modified: trunk/src/pmc/bigint.pmc
==============================================================================
--- trunk/src/pmc/bigint.pmc    (original)
+++ trunk/src/pmc/bigint.pmc    Sun May  6 08:11:30 2007
@@ -267,13 +267,23 @@
 bigint_bitwise_shl_bigint_int(Interp *interp, PMC* self,
                               INTVAL value, PMC *dest)
 {
-    mpz_mul_2exp(BN(dest), BN(self), value);
+    /* The third args to mpz_mul_2exp and mpz_tdiv_q_2exp are unsigned, so we
+       need to do something sensible with negative values. */
+    if (value >= 0)
+        mpz_mul_2exp(BN(dest), BN(self), value);
+    else
+        mpz_tdiv_q_2exp(BN(dest), BN(self), -value);
 }
 static void
 bigint_bitwise_shr_bigint_int(Interp *interp, PMC* self,
                               INTVAL value, PMC *dest)
 {
-    mpz_tdiv_q_2exp(BN(dest), BN(self), value);
+    /* The third args to mpz_mul_2exp and mpz_tdiv_q_2exp are unsigned, so we
+       need to do something sensible with negative values. */
+    if (value >= 0)
+        mpz_tdiv_q_2exp(BN(dest), BN(self), value);
+    else
+        mpz_mul_2exp(BN(dest), BN(self), -value);
 }
 
 #else /* ifdef PARROT_HAS_GMP */

Modified: trunk/t/pmc/bigint.t
==============================================================================
--- trunk/t/pmc/bigint.t        (original)
+++ trunk/t/pmc/bigint.t        Sun May  6 08:11:30 2007
@@ -25,7 +25,7 @@
 =cut
 
 if ( $PConfig{gmp} ) {
-    plan tests => 36;
+    plan tests => 40;
 }
 else {
     plan skip_all => "No BigInt Lib configured";
@@ -759,6 +759,26 @@
 102400000000000
 OUT
 
+pir_output_is( <<'CODE', <<'OUT', "shl_bigint with a negative shift" );
+## cf the shr_bigint case.
+.sub main :main
+   new $P0, .BigInt
+   set $P0, 8
+   new $P1, .BigInt
+   set $P1, -2
+   new $P2, .BigInt
+   shl $P2, $P0, $P1
+   say $P2
+   set $P0, "102400000000000"
+   set $P1, -10
+   shl $P2, $P0, $P1
+   say $P2
+.end
+CODE
+2
+100000000000
+OUT
+
 pasm_output_is( <<'CODE', <<'OUT', "shl_int" );
    new P0, .BigInt
    set P0, 2
@@ -788,6 +808,31 @@
 102400000000000
 OUT
 
+pir_output_is( <<'CODE', <<'OUT', "shl_int with a negative shift" );
+## cf the shr_int case.
+.sub main :main
+   new $P0, .BigInt
+   set $P0, 4
+   new $P1, .Integer
+   set $P1, -1
+   new $P2, .BigInt
+   shl $P2, $P0, $P1
+   say $P2
+   set $P0, "200000000000"
+   set $P1, -1
+   shl $P2, $P0, $P1
+   say $P2
+   set $P0, "102400000000000"
+   set $P1, -10
+   shl $P2, $P0, $P1
+   say $P2
+.end
+CODE
+2
+100000000000
+100000000000
+OUT
+
 pasm_output_is( <<'CODE', <<'OUT', "shr_bigint" );
    new P0, .BigInt
    set P0, 8
@@ -810,6 +855,26 @@
 100000000000
 OUT
 
+pir_output_is( <<'CODE', <<'OUT', "shr_bigint with a negative shift" );
+## cf the shl_bigint case.
+.sub main :main
+   new $P0, .BigInt
+   set $P0, 2
+   new $P1, .BigInt
+   set $P1, -2
+   new $P2, .BigInt
+   shr $P2, $P0, $P1
+   say $P2
+   set $P0, "100000000000"
+   set $P1, -10
+   shr $P2, $P0, $P1
+   say $P2
+.end
+CODE
+8
+102400000000000
+OUT
+
 pasm_output_is( <<'CODE', <<'OUT', "shr_int" );
    new P0, .BigInt
    set P0, 4
@@ -839,6 +904,30 @@
 100000000000
 OUT
 
+pir_output_is( <<'CODE', <<'OUT', "shr_int with a negative shift" );
+## cf the shl_int case.
+.sub main :main
+   new $P0, .BigInt
+   set $P0, 2
+   new $P1, .Integer
+   set $P1, -1
+   new $P2, .BigInt
+   shr $P2, $P0, $P1
+   say $P2
+   set $P0, "100000000000"
+   set $P1, -1
+   shr $P2, $P0, $P1
+   say $P2
+   set $P1, -10
+   shr $P2, $P0, $P1
+   say $P2
+.end
+CODE
+4
+200000000000
+102400000000000
+OUT
+
 pir_output_is( <<'CODE', <<'OUT', "BUG #34949 gt" );
 .sub main :main
     .local pmc b

Reply via email to