No such thing as a small change PerlMonks

### How to create nan/inf

by syphilis (Chancellor)
 on Aug 09, 2008 at 03:06 UTC Need Help??
syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
How do I portably create nans and infs in perl ?
Any solution that uses a core perl module would be fine. Specifically, I'm looking to create variables that Devel::Peek::Dump() as something like:
```Positive inf:
SV = NV(0x465ffc) at 0x42fca4
REFCNT = 1
FLAGS = (NOK,pNOK)
NV = 1.#INF

Negative inf:
SV = NV(0x465ff4) at 0x42fcc4
REFCNT = 1
FLAGS = (NOK,pNOK)
NV = -1.#INF
At least that's how they should look on Windows. Other operating systems will be essentially the same, though the precise contents of the NV slot could be different (eg 'inf').
I'm not exactly sure what the nan looks like - I guess it, too, will be an NV with 1.#NAN filling the NV slot (on Windows).

Is it possible to create an IV with 1.#INF in the IV slot, or are infinities necessarily NV's ?

Cheers,
Rob

Replies are listed 'Best First'.
Re: How to create nan/inf
by ikegami (Pope) on Aug 09, 2008 at 03:56 UTC

You could also create the bit pattern yourself and unpack it. It's system dependant, but it will allow you to generate every possible special value.

For example, Windows uses little-endian IEEE

```sub double_from_hex { unpack 'd', scalar reverse pack 'H*', \$_[0] }

use constant POS_INF => double_from_hex '7FF0000000000000';
use constant NEG_INF => double_from_hex 'FFF0000000000000';

use constant qNaN    => double_from_hex '7FF8000000000000';
use constant NaN     => qNaN;

print(POS_INF, "\n");  # 1.#INF
print(NEG_INF, "\n");  # -1.#INF
print(qNaN,    "\n");  # 1.#QNAN

x86 doesn't seem to have signaled NaNs or they're not recognized when stringified. On the other hand, "FFF8000000000000" is recognized as being "-1.#IND".

That gives me (more than) enough to play with :-)
One of the PowInt.t tests on Math::GSL (version 0.07) fails on Windows but passes on Linux. It's to do with differing treatment of nans and infs. It helps if I can reliably and easily create nans and infs on both platforms - which I now can.

Thanks ikegami.

Cheers,
Rob
Re: How to create nan/inf
by ikegami (Pope) on Aug 09, 2008 at 03:21 UTC

There are tokens that will be understood as infinity, but it's dependant on the underlying C library. It's easier just to calculate it.

```use constant POS_INF => +(99**99**99);
use constant NEG_INF => -(99**99**99);

(Is that big enough for a long double system?)

Active Perl 5.6.0, 5.6.1, 5.8.0, 5.8.8, 5.10.0 on Windows:

```>perl -MDevel::Peek -e"Dump +(99**99**99)"
SV = NV(0x1832414) at 0x225334
REFCNT = 1
NV = 1.#INF

>perl -MDevel::Peek -e"Dump -(99**99**99)"
SV = NV(0x1832424) at 0x22531c
REFCNT = 1
NV = -1.#INF

Some Perl 5.8.4 on linux:

```\$ perl -MDevel::Peek -e'Dump +(99**99**99)'
SV = NV(0x8165bd0) at 0x8160954
REFCNT = 1
NV = inf

\$ perl -MDevel::Peek -e'Dump -(99**99**99)'
SV = NV(0x8165be0) at 0x814cc9c
REFCNT = 1
NV = -inf
Re: How to create nan/inf
by ikegami (Pope) on Aug 09, 2008 at 03:27 UTC

Is it possible to create an IV with 1.#INF in the IV slot

Infinity and NaN are necessarily floats. Integers use all their bits to hold the value.

Re: How to create nan/inf
by eosbuddy (Scribe) on Aug 09, 2008 at 07:20 UTC
It is beyond my expertise to answer your original (and interesting) question, nonetheless, I thought you and fellow monks might be interested in my bit of (research). I did an investigation on my system (using the ~0 >> 1 construct for integer type maximum number and working my way up using this number). Due to the dynamical typing of perl, integer numbers can go way beyond this maximum (usually that one finds in C).
```#!/usr/bin/perl

use strict;
use warnings;

my \$n;
\$n = ~0 >> 1;
print "\$n\n";
my \$x = 999999999999999;
print "\$x\n";
\$x = 1000000000000000;
print "\$x\n";
my \$z = 1.79769313486231e+308;
print "\$z\n";
\$z = 1.79769313486232e+308;
print "\$z\n";
The output:
```2147483647
999999999999999
1e+15
1.79769313486231e+308
inf
There is also another older node regarding a similar issue here: http://www.perlmonks.org/?node=657332 with an insightful summary by ysth at the end. Hope this helps.
Re: How to create nan/inf
by swampyankee (Parson) on Aug 09, 2008 at 05:28 UTC

iirc, FFFFFFFFFFFFFFFF is NaN on Windows boxes (at least with Intel Visual Fortran and C), but I can't swear that's guaranteed to be true on all x86 machines, let alone all machines using IEEE arithmetic. I know that some platforms, e.g., IBM mainframes, don't have floating point models capable of representing NaN or Inf, so a completely portable solution is impossible.

Information about American English usage here and here. Floating point issues? Please read this before posting. — emc

so a completely portable solution is impossible

That's not really an issue for me. I was just after some way of getting test 6 of PowInt.t to pass on Windows, leaving all other systems unaffected. I think I've now achieved that.

One of the things that was throwing me was that, on Linux, the strings 'nan' and 'inf' are converted to a nan/inf when used in numeric context. That is, on Linux:
```perl -MDevel::Peek -e 'Dump "inf" + 1';
outputs:
```SV = NV(0x...) at 0x....
REFCNT = 1
NV = inf
But there's no comparable behaviour (that I can find) on Windows. The strings '1.#INF' and '1.#QNAN' are not interpreted as inf/nan when used in numeric context. Instead they're just numified according to the usual rules that apply to the numification of strings - ie they take on a numeric value of 1:
```C:\>perl -MDevel::Peek -e "Dump '1.#INF' + 1"
SV = IV(0x218fe28) at 0x218fe2c
REFCNT = 1
IV = 2
I wasn't expecting such different behaviour - and that added significantly to my confusion.

Cheers,
Rob

Double FFFFFFFFFFFFFFFF is *a* IEEE 754 NaN. Anything of the form [7F]FFFxxxxxxxxxxxx where "x" is nonzero is a NaN.

There are at least two kinds of NaN: signaled and quiet. IEEE 754 doesn't define the how to encode them, but recommends using the most significant bit of "x" (0 for signaled).

Re: How to create nan/inf
by repellent (Priest) on Aug 17, 2008 at 19:42 UTC
```    my \$inf = exp(~0 >> 1);
my \$nan = \$inf / \$inf;

my \$neg_inf = -\$inf;
Note that any sufficiently large number will suffice instead of (~0 >> 1).
Re: How to create nan/inf
by Anonymous Monk on Sep 01, 2008 at 14:05 UTC
bigint/bigrat export NaN and inf
```D:\>perl -MDevel::Peek -Mbigint -e"Dump(NaN())"
SV = PV(0x225ec4) at 0x18a5984
REFCNT = 1
RV = 0x224f58
SV = PVHV(0x2299c4) at 0x224f58
REFCNT = 1
FLAGS = (OBJECT,SHAREKEYS)
IV = 2
NV = 0
STASH = 0x185c2e4   "Math::BigInt"
ARRAY = 0x1824734  (0:6, 1:2)
hash quality = 125.0%
KEYS = 2
FILL = 2
MAX = 7
RITER = -1
EITER = 0x0
Elt "value" HASH = 0x1e720953
SV = RV(0x183b380) at 0x19a5b88
REFCNT = 1
FLAGS = (ROK)
RV = 0x197f954
SV = PVAV(0x199f354) at 0x197f954
REFCNT = 1
FLAGS = ()
IV = 0
NV = 0
ARRAY = 0x1830244
FILL = 0
MAX = 0
ARYLEN = 0x0
FLAGS = (REAL)
Elt No. 0
SV = IV(0x182d3e8) at 0x19a5b64
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 0
Elt "sign" HASH = 0xe7455c8f
SV = PV(0x225ea0) at 0x19a5b58
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x182281c "NaN"\0
CUR = 3
LEN = 4
PV = 0x224f58 ""
CUR = 0
LEN = 0

D:\>perl -MDevel::Peek -Mbigrat -e"Dump(NaN())"
SV = PV(0x225ec4) at 0x188c97c
REFCNT = 1
RV = 0x224f58
SV = PVHV(0x229ae4) at 0x224f58
REFCNT = 1
FLAGS = (OBJECT,SHAREKEYS)
IV = 2
NV = 0
STASH = 0x188be6c   "Math::BigInt"
ARRAY = 0x1824734  (0:6, 1:2)
hash quality = 125.0%
KEYS = 2
FILL = 2
MAX = 7
RITER = -1
EITER = 0x0
Elt "value" HASH = 0x1e720953
SV = RV(0x183b34c) at 0x19a6fb4
REFCNT = 1
FLAGS = (ROK)
RV = 0x197d210
SV = PVAV(0x19a56b4) at 0x197d210
REFCNT = 1
FLAGS = ()
IV = 0
NV = 0
ARRAY = 0x1830244
FILL = 0
MAX = 0
ARYLEN = 0x0
FLAGS = (REAL)
Elt No. 0
SV = IV(0x19fab0c) at 0x19a6f90
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 0
Elt "sign" HASH = 0xe7455c8f
SV = PV(0x225ea0) at 0x19a6f84
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x182281c "NaN"\0
CUR = 3
LEN = 4
PV = 0x224f58 ""
CUR = 0
LEN = 0

D:\>

Create A New User
Node Status?
node history
Node Type: perlquestion [id://703222]
Approved by ikegami
Front-paged by Arunbear
help
Chatterbox?
Jar. Jar!...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2018-04-21 22:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My travels bear the most uncanny semblance to ...

Results (81 votes). Check out past polls.

Notices?