develooper Front page | perl.perl5.porters | Postings from October 2005

RFC: make leftwise bit-shift always work up to 2**64-1

Thread Next
From:
Tassilo von Parseval
Date:
October 28, 2005 00:22
Subject:
RFC: make leftwise bit-shift always work up to 2**64-1
Message ID:
20051028071941.GA1940@ethan
Hi,

As seen on clpm:

> So I wrote:
>   $Roll32 = (1 << 32);    # the way I would for a C macro but the
>                           # value was (after I did some looking) one! 
> Then I wrote: 
>   $Roll32 = 1 << 32;      # in case the parens were a issue bit it 
>                           # was still one, 
> so I wrote: 
>   $Roll32 = ( 4 * (1 << 30) ); # which works (4G)

The reason for that being of course that perl has a chance to upgrade to
using the NV slot before doing the multiplication.

Now I wondered why perl couldn't always try to use the biggest available
native integer type for a left bit-shift. If the result is too large to
fit into 32bit, then use an NV.

So I came up with this patch-draft:

--- perl-p-5.8.0@25859~/pp.c	2005-10-27 08:58:48.000000000 +0200
+++ perl-p-5.8.0@25859/pp.c	2005-10-28 08:42:45.000000000 +0200
@@ -1627,12 +1627,32 @@ PP(pp_left_shift)
     {
       const IV shift = POPi;
       if (PL_op->op_private & HINT_INTEGER) {
+#if !defined(USE_64_BIT_INT) && defined(I64TYPE)
+	I64TYPE i = TOPi;
+	i <<= shift;
+	if (i > I32_MAX) {
+	    SETn((NV)i);
+	    SvNOK_only(TARG);
+	} else
+	    SETi(i);
+#else
 	IV i = TOPi;
 	SETi(i << shift);
+#endif
       }
       else {
+#if !defined(USE_64_BIT_INT) && defined(U64TYPE)
+	U64TYPE u = TOPu;
+	u <<= shift;
+	if (u > U32_MAX) {
+	    SETn((NV)u);
+	    SvNOK_only(TARG);
+	} else
+	    SETu(u);
+#else
 	UV u = TOPu;
 	SETu(u << shift);
+#endif
       }
       RETURN;
     }
END-OF-DRAFT

Is the above a bad idea or is it something that could go into perl? For
bit-shifts below 2**32-1 there is at least a minimal (but negligible)
performance penalty because of the additional if-condition. But I am
wondering about potential glitches beyond that.

Note that this patch is probably not quite what it should be: I had
difficulties detecting the existence of a native 64bit wide integer. I
thought HAS_QUAD is #defined in that case but it wasn't here so I had to
check for (I|U)64TYPE directly.

Tassilo
-- 
use bigint;
$n=71423350343770280161397026330337371139054411854220053437565440;
$m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About