3

I want to write a program that needs 40-bit integers. The machine where I'm writing it has 64 bit integers, but I'd like to check inside the program whether there are 64-bit integers available.

How could I do that efficiently?

On a 64-bit machine, this seems to work:

~0 >= 2**63

Is that safe (read: "portable") on different architectures?

Thinking about the problem, I also wondered if the Perl compiler, or interpreter could make these results questionable for a future version of Perl:

  DB<2> sub bittest { use integer; return ((1 << $_[0]) >> $_[0]) != 0; }

  DB<3> x bittest 31
0  1
  DB<4> x bittest 63
0  1
  DB<5> x bittest 64
0  ''
U. Windl
  • 3,480
  • 26
  • 54
  • Maybe you can check the perl config hash: `perl -V:intsize`, or `perl -MConfig -E 'say $Config{intsize}'` ? – Håkon Hægland Aug 23 '21 at 10:31
  • 2
    @HåkonHægland I think `$Config{intsize}` queries the size of C's `int` (which is 4 on my machine), but it does not tell you whether Perl's integers are 64 bit long. Maybe `$Config{d_quad}` is the thing, but I'm not 100% sure. Maybe it's `d_int64_t` or `use64bitint` instead. – U. Windl Aug 23 '21 at 13:59
  • Maybe see the related question https://stackoverflow.com/q/68893773/6607497, too. – U. Windl Aug 23 '21 at 14:02

2 Answers2

2

~0 is 18446744073709551615 on 64-bit systems, so

~0 == 18446744073709551615
~0 == 0xFFFFFFFFFFFFFFFF       # (16 F's)

are efficient tests to see if you are on a 64-bit system.

I've only ever used Perl on 32-bit and 64-bit systems, but in case there are ever 39 and 41-bit systems, to use 40-bit integers you just need ~0 to be at least 2**40 - 1, or:

~0 >= 0xFFFFFFFFFF             # (10 F's)
mob
  • 117,087
  • 18
  • 149
  • 283
  • Starting with `~0 == 0xFFFFFFFFFFFFFFFF` isn't it possible that a system using 32-bit integers (for example) will truncate `0xFFFFFFFFFFFFFFFF` to `0xFFFFFFFF`? If then `~0` returns just that value also, wouldn't that test succeed? – U. Windl Aug 24 '21 at 06:04
  • No, a 32-bit perl will treat `0xFFFFFFFFFFFFFFFF` as 1.844...e+19. – mob Aug 24 '21 at 14:18
2

If you need integers in the computer sense (IV/UV), you need them to at least 40 bits in size.

~0 >= 2**40-1

or

use Config qw( %Config );

$Config{uvsize} >= 8

uvsize refes to the size in bytes of such integers.

You need this if you use any of the following:

  • the numbers as operands to bitwise operators
  • the numbers as operands to ../...
  • pack 'Q'/unpack 'Q'
  • hex literals larger than 0xFFFF_FFFF

If you need integers in the mathematical sense, floats (NV) with at least 40 bits of precision would also do.

use Config qw( %Config );

$Config{uvsize} >= 8 || eval($Config{nv_overflows_integers_at}) >= 2**40

Every integer up and including eval($Config{nv_overflows_integers_at}) can be represented exactly as an NV.

Note that every build of Perl should support at least 53 bits of precision. For example, eval($Config{nv_overflows_integers_at}) evalutes to 9007199254740992 on my builds, which corresponds to 53 bits as per log(9007199254740992)/log(2).

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • You may be more expert than I am (or the typical user), so I think the average raeder would benefit if you'd explain (or add a reference for) the concepts "IV" and "UV": It that related to "integer" and "unsigned"? What is "NV"? Is "53 bits of precision" referring to integer values? "man Config" seems to assume the reader knows what UV is, but honestly, I don't. What I'm trying to say: I'm sure xou can improve the answer. – U. Windl Aug 24 '21 at 05:58
  • IV and UV are Perl integer types (signed and unsigned). NV is it's floating point type. An NV can accurately store every integer up to and including `eval($Config{nv_overflows_integers_at})` – ikegami Aug 24 '21 at 12:41
  • Fix the spelling of "bitwise" back to the [correct spelling](https://en.wikipedia.org/wiki/Bitwise_operation). Removed incorrect information added. Left in the redundant information that was added. – ikegami Aug 25 '21 at 14:51
  • I didn't consider Wikipedia to be a spelling dictionary so far. My spell checker (in Firefox) knew bit-wise, but not bitwise, but your reputation is higher ;-) – U. Windl Aug 26 '21 at 05:43