# Atoms and Integers

Atoms can have any integer or floating point value.

On first reading you might want to skip this entire section as it is just a deep dive into number limits and accuracy, which is reasonably common to all programming languages, except for 31/63-bit integers and the fact that some other languages have arbitrary precision numbers "baked in", whereas in Phix it is an explicit add-on much like say plain C.

On 32-bit atoms can hold about ±1e+308, with ˜15 decimal digits of accuracy and ±1e-324 the nearest non-0 thing to 0.

On 64-bit atoms can hold about ±1e+4932, with ˜19 decimal digits of accuracy and ±1e-4951 the closest non-0 thing to 0.

In other words, for atoms 32-bit Phix uses the native FPU hardware 64-bit IEEE-754 floats, while 64-bit Phix uses 80-bit ones.

Integers in Phix are limited to the subset that begin with 0b00 or 0b11: on a 32-bit architecture they can contain a single value in the range -1,073,741,824 to +1,073,741,823 (-#40000000 to #3FFFFFFF), with no fractional part, hence technically speaking Phix integers are 31-bit, straddling the "middle half" of the actual hardware range (-2GB..+2GB-1).

On 64-bit the range is -4,611,686,018,427,387,904 to +4,611,686,018,427,387,903 (-#4000000000000000 to #3FFFFFFFFFFFFFFF), which technically speaking makes them 63-bit.

Should you need to hold full 32 (or 64) bit "integers", simply use an atom (trust me, it works).

In other words, for integers Phix uses the standard machine-word-sized CPU registers, always signed, less one bit.

The following values may also prove useful:

Technically speaking maxatm should be treated as an inexact value, because it is ambiguous whether it is really maxatm or maxatm+1, or in other words it is the first/lowest value that if you add 1 to it, you’ll get the same value right back - the same thing occurs in C/asm/etc.

While technically integers stored in IEEE-754 floats are limited to 53/64 bits of precision, that doesn’t mean you cannot (sometimes) hold higher numbers, in particular exact powers of two. Consider (in this case on 32 bit) 9223372036854775808 === #8000000000000000 === power(2,63). Such numbers can only be held to the nearest multiple of 2048, but since the last 11 bits are zero that does not matter. However the decimal one can cause friction: should you type that into a source code file, at some point the tokeniser fetches each next digit, multiplies what it already has by ten and adds it on, and alas that means it succesively stores (or would like to):

9223372036854775

92233720368547758

922337203685477580

9223372036854775808

but those are individually rounded to the nearest multiple of 4, 32, 256, and 2048 respectively, making them and everything that follows slightly wrong. In contrast, when parsing #8..00 it only ever drops bits which are all zero anyway, so that ends up spot on. Just something you should bear in mind. (As it happens, I know exactly how to parse decimal as accurately as hex, but someone would actually have to pay me lots to do it.)

Phix does

While you can store any integer value in a variable declared as an atom, the reverse is not true.

Here are some Phix integers and atoms:

Of course if you need to replicate the truncating/wrapping behaviour of C integer maths, for instance in hashing and cryptographic functions, you can easily do that with a bit of inline assembly, and should you need to work with ridiculously large numbers, an arbitrary precision maths library, mpfr, is included with the distribution.

pwa/p2js: JavaScript is inherently a 32-bit system, and the limits above for 32-bit (atoms) apply, even in 64-bit browsers (not that I have thoroughly tested or researched that).

See also: Number Bases

On first reading you might want to skip this entire section as it is just a deep dive into number limits and accuracy, which is reasonably common to all programming languages, except for 31/63-bit integers and the fact that some other languages have arbitrary precision numbers "baked in", whereas in Phix it is an explicit add-on much like say plain C.

On 32-bit atoms can hold about ±1e+308, with ˜15 decimal digits of accuracy and ±1e-324 the nearest non-0 thing to 0.

On 64-bit atoms can hold about ±1e+4932, with ˜19 decimal digits of accuracy and ±1e-4951 the closest non-0 thing to 0.

In other words, for atoms 32-bit Phix uses the native FPU hardware 64-bit IEEE-754 floats, while 64-bit Phix uses 80-bit ones.

Integers in Phix are limited to the subset that begin with 0b00 or 0b11: on a 32-bit architecture they can contain a single value in the range -1,073,741,824 to +1,073,741,823 (-#40000000 to #3FFFFFFF), with no fractional part, hence technically speaking Phix integers are 31-bit, straddling the "middle half" of the actual hardware range (-2GB..+2GB-1).

On 64-bit the range is -4,611,686,018,427,387,904 to +4,611,686,018,427,387,903 (-#4000000000000000 to #3FFFFFFFFFFFFFFF), which technically speaking makes them 63-bit.

Should you need to hold full 32 (or 64) bit "integers", simply use an atom (trust me, it works).

In other words, for integers Phix uses the standard machine-word-sized CPU registers, always signed, less one bit.

The following values may also prove useful:

printf(1,"maxint %,d (#%x)\n",power(2,machine_bits()-2)-1) printf(1,"minint %,d (#%x)\n",-power(2,machine_bits()-2)) printf(1,"maxatm %,d\n",{power(2,iff(machine_bits()=32?53:64))})where maxatm is the largest integer (with no prior gaps) than can be held exactly in a native atom, above that you need to use mpfr/gmp.--32-bit:maxint 1,073,741,823 (#3FFFFFFF) minint -1,073,741,824 (#C0000000) maxatm 9,007,199,254,740,992-- 64-bit:maxint 4,611,686,018,427,387,903 (#3FFFFFFFFFFFFFFF) minint -4,611,686,018,427,387,904 (#C000000000000000) maxatm 18,446,744,073,709,551,616

Technically speaking maxatm should be treated as an inexact value, because it is ambiguous whether it is really maxatm or maxatm+1, or in other words it is the first/lowest value that if you add 1 to it, you’ll get the same value right back - the same thing occurs in C/asm/etc.

While technically integers stored in IEEE-754 floats are limited to 53/64 bits of precision, that doesn’t mean you cannot (sometimes) hold higher numbers, in particular exact powers of two. Consider (in this case on 32 bit) 9223372036854775808 === #8000000000000000 === power(2,63). Such numbers can only be held to the nearest multiple of 2048, but since the last 11 bits are zero that does not matter. However the decimal one can cause friction: should you type that into a source code file, at some point the tokeniser fetches each next digit, multiplies what it already has by ten and adds it on, and alas that means it succesively stores (or would like to):

9223372036854775

92233720368547758

922337203685477580

9223372036854775808

but those are individually rounded to the nearest multiple of 4, 32, 256, and 2048 respectively, making them and everything that follows slightly wrong. In contrast, when parsing #8..00 it only ever drops bits which are all zero anyway, so that ends up spot on. Just something you should bear in mind. (As it happens, I know exactly how to parse decimal as accurately as hex, but someone would actually have to pay me lots to do it.)

Phix does

*entertain the idea of unsigned integers: zero less one is -1, not four billion/GB or eight quintillion/PB. You can easily mimic all that kinda stuff explicitly for cryptography, hashing, compression and the like when needed, but there is no need to be wary of any such strange side-effects, all day and every day. Exceeding the capacity of an integer leads to a clear no-nonsense type check error, telling you the file name and line number where it went wrong (with Edita jumping there automatically), rather than quietly hiding the error/overflow and stumbling on in some kind of forlorn and frankly foolish hope it somehow won’t matter. At least when you exceed a float/FPU register it ends up inf, which is simply never mistaken for anything else, but there’s just nothing remotely equivalent for an integer/CPU register.***not**While you can store any integer value in a variable declared as an atom, the reverse is not true.

Here are some Phix integers and atoms:

0Phix stores integer-valued atoms as machine integers (4 or 8 bytes) to save space and improve execution speed. When fractional results occur or numbers get too big, conversion to floating-point happens automatically. As we shall soon see, should that conversion be the wrong thing to do, you are immediately notified in a clear and no-nonsense, human-readable manner.-- (integer)1000-- (integer)98.6-- (atom)-1e60-- (atom)

Of course if you need to replicate the truncating/wrapping behaviour of C integer maths, for instance in hashing and cryptographic functions, you can easily do that with a bit of inline assembly, and should you need to work with ridiculously large numbers, an arbitrary precision maths library, mpfr, is included with the distribution.

pwa/p2js: JavaScript is inherently a 32-bit system, and the limits above for 32-bit (atoms) apply, even in 64-bit browsers (not that I have thoroughly tested or researched that).

See also: Number Bases