in reply to Re: Left shift operation done more than 32 times
in thread Left shift operation done more than 32 times

You don't explain it. If you take the lower 32 bits of the result that's too big to fit into an integer, I expect the higher bits to be thrown away, and the lower bits kept. But the lower 32 bits of 4294967296 is 0, not 1.

I think Zaxo's reply is much closer to the truth.

If I do

$\ = "\n"; print 2147483648 << 1;
then I get 0. Even more:
print +(2147483648+1) << 1;
yields 2.

I think Perl does both (edit: at least, on my platform): taking $i%32 as its RHS, and drop the higher bits, just keeping the lower 32 bits, from the result.

I just wish jeshuashok's loop counter went a bit higher, to at least above 64.

Replies are listed 'Best First'.
Re^3: Left shift operation done more than 32 times
by dave_the_m (Monsignor) on May 21, 2006 at 09:20 UTC
    I think Perl does both: taking $i%32 as its RHS, and drop the higher bits, just keeping the lower 32 bits, from the result.
    No, perl is doing exactly as it says in the docs; it is just using the underlying C << operator, whose result is undefined for overflows. That means the result will vary based on C compiler and/or CPU architecture.

    from pp.c:

    const IV shift = POPi; if (PL_op->op_private & HINT_INTEGER) { const IV i = TOPi; SETi(i << shift); } else { const UV u = TOPu; SETu(u << shift); }

    Dave.

Re: Left shift operation done more than 32 times
by jonadab (Parson) on May 21, 2006 at 11:12 UTC
    <q>You don't explain it.</q>

    He explained it very exactly, _if_ you are familiar with the terminology of computer science. In computer science, when we say that the result of a particular operation is "undefined", we don't mean that you get the Perl value undef. (That would be the undefined _value_ -- this is the undefined _behavior_.) This terminology is older than Perl and means that in fact, depending on your compiler, your hardware architecture, your OS, your C libraries, and the phase of the moon, the result can and might very well be any of the following:

    • 0
    • 1
    • -1
    • 3
    • 9827345908794823.74598723459879
    • Your program crashes immediately.
    • Everything seems fine at first, but your program crashes a few minutes later for no apparent reason.
    • The entire operating system crashes. This result is unlikely under modern operating systems, unless the code with the undefined behavior is in kernel space or an important hardware driver (e.g., the video driver or a mass storage driver). Since Perl is seldom used for kernels or hardware drivers, this result is unlikely to be triggered by Perl code on modern systems.
    • Other variables elsewhere in your program have their values changed without warning. (This particular result is unlikely in Perl, but the C library and compiler retain the right to do this if you do something the result of which is undefined behavior.)
    • Small dragons fly out of your nose and attempt to re-enter your body elsewhere.
    <q>If you take the lower 32 bits of the result that's too big to fit into an integer, I expect</q>

    When it comes to undefined behavior, you don't get to have expectations.

    Frankly I would prefer that Perl intercept such things and define their behavior, even if the definition is a fatal error that stops your program and prints a suitable error message. But it doesn't.

    The long and short of it is that when the behavior is undefined that means the burden is on you, the programmer, to carefully avoid doing such things. If the result of doing left shift more than 32 times is undefined, then you must not do left shift more than 32 times -- or you must use a math library that defines it, such as the one mentioned in another reply.


    Sanity? Oh, yeah, I've got all kinds of sanity. In fact, I've developed whole new kinds of sanity. Why, I've got so much sanity it's driving me crazy.