Q:

perl 64 bit ints under the hood

I'm confused regarding the internal representation of 64 bit ints in perl.
Ubuntu 12.04, perl 5.16.0:
print 18440000000000001000 . "\n";
print 18450000000000001000 . "\n";
print -9220000000000001000 . "\n";
print -9230000000000001000 . "\n";

output:
18440000000000001000
1.845e+19
-9220000000000001000
-9.23e+18

Obviously positive numbers overflow and are coerced to floats, with corresponding loss of precision, at 2^64. However - that leaves no space for a sign bit, so how are the negative numbers up to -2^63 represented?

A:

Perl numbers are represented as either an IV or a UV. It's a flag on the SV structure itself.
I'm guessing when a number becomes signed, the UV becomes an IV, and vice versa.
Specifically, looking in the SV definition:
#define _SV_HEAD_UNION \
union {                             \
    char*   svu_pv;         /* pointer to malloced string */        \
    IV      svu_iv;                 \
    UV      svu_uv;                 \
    SV*     svu_rv;         /* pointer to another SV */             \
    SV**    svu_array;              \
    HE**    svu_hash;               \
    GP*     svu_gp;                 \
    PerlIO *svu_fp;                 \
}   sv_u

The SvIOK and SvUOK flags can be used to see what the actual valid field of the SV is.

