Perl's newSViv() versus 64-bit ints?

Started by Tom Lanealmost 10 years ago7 messages
#1Tom Lane
tgl@sss.pgh.pa.us

Anybody know what will happen when passing a uint64 to newSViv()?

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Tom Lane (#1)
Re: Perl's newSViv() versus 64-bit ints?

I wrote:

Anybody know what will happen when passing a uint64 to newSViv()?

Oh, and how about Python's PyInt_FromLong()?
Or PyList_New()?
Or the second argument of PyList_SetItem()?

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#1)
Re: Perl's newSViv() versus 64-bit ints?

On 03/11/2016 06:49 PM, Tom Lane wrote:

Anybody know what will happen when passing a uint64 to newSViv()?

A perl IV is guaranteed large enough to hold a pointer, if that's any
help. But for an unsigned value you might be better off calling newSVuv()

cheers

andrew

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#4Salvador Fandiño
sfandino@gmail.com
In reply to: Tom Lane (#1)
Re: Perl's newSViv() versus 64-bit ints?

On 03/12/2016 12:49 AM, Tom Lane wrote:

Anybody know what will happen when passing a uint64 to newSViv()?

On 64 bit platforms, it is just interpreted as a signed integer, any
number with the upper bit set will become negative. Perl provides
newSVuv for unsigned numbers.

On 32bit platforms and Perls compiled with 32 bit IVs the number is
truncated. My module Math::Int64 can be used to add support for 64bit
numbers there. It has a C API[*] which allows calling it from C code
easily. Another possibility is to just use newSVnv(), but NVs are not
able to represent all the uint64 range precisely (IIRC, they can
represent integers up to 48bits?).

Well, and then you can always use some bigint module, but AFAIK, the
ones distributed in the Perl core do not provide a C API.

* https://metacpan.org/pod/Math::Int64#C-API

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Salvador Fandiño (#4)
Re: Perl's newSViv() versus 64-bit ints?

=?UTF-8?Q?Salvador_Fandi=c3=b1o?= <sfandino@gmail.com> writes:

Another possibility is to just use newSVnv(), but NVs are not
able to represent all the uint64 range precisely (IIRC, they can
represent integers up to 48bits?).

[ looks... ] Oh, NV is a "double", which I think would be a perfectly
reasonable choice: it'd be exact up to about 2^53, on most machines,
which should be plenty for a long time to come.

How much of a user-visible change would that be, if the "processed"
field of a spi_exec_query() result started coming back as an NV not
an IV? I'm not sure how much that would affect semantics in typical
Perl code.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#6Salvador Fandiño
sfandino@gmail.com
In reply to: Tom Lane (#5)
Re: Perl's newSViv() versus 64-bit ints?

On 03/12/2016 04:47 PM, Tom Lane wrote:

=?UTF-8?Q?Salvador_Fandi=c3=b1o?= <sfandino@gmail.com> writes:

Another possibility is to just use newSVnv(), but NVs are not
able to represent all the uint64 range precisely (IIRC, they can
represent integers up to 48bits?).

[ looks... ] Oh, NV is a "double", which I think would be a perfectly
reasonable choice: it'd be exact up to about 2^53, on most machines,
which should be plenty for a long time to come.

How much of a user-visible change would that be, if the "processed"
field of a spi_exec_query() result started coming back as an NV not
an IV? I'm not sure how much that would affect semantics in typical
Perl code.

At the Perl level, IVs and NVs are mostly indistinguishable, and Perl
does promote values internally from IVs to NVs to avoid overflows
automatically.

There are some operations that cause an implicit coercion from NV to IV
(or UV) under the hood, and in those cases, big values would get
mangled. For instance, bit operations as <<, >> or ~, or calling pack or
printf with some integer template do that.

Those don't look like common operations for "processed".

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Salvador Fandiño (#6)
Re: Perl's newSViv() versus 64-bit ints?

=?UTF-8?Q?Salvador_Fandi=c3=b1o?= <sfandino@gmail.com> writes:

On 03/12/2016 04:47 PM, Tom Lane wrote:

How much of a user-visible change would that be, if the "processed"
field of a spi_exec_query() result started coming back as an NV not
an IV? I'm not sure how much that would affect semantics in typical
Perl code.

At the Perl level, IVs and NVs are mostly indistinguishable, and Perl
does promote values internally from IVs to NVs to avoid overflows
automatically.

Sounds good. I notice that the manual discourages people from using
spi_exec_query() for "big" results, which means we could possibly get
away without doing anything here; but I'll feel better about it if we
can push the upper limit to 2^53 or so.

Given that text in the manual, I think it might be worth the code space
to do it like this:

(SPI_processed > INT_MAX) ? newSVnv(SPI_processed) : newSViv(SPI_processed)

since the NV code path is presumably a bit slower and it's very likely
that users would never actually need it.

I wonder whether this idea has analogues for python and tcl ...

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers