On Fri, Apr 23, 2004 at 02:05:08PM +1000, Sisyphus wrote:
Hi,
I'm wanting to know the precise sets of conditions under which the IV, UV, and NV flags will be set. Is this documented somewhwere ? I've tried
Its not really documented. It differs in 5.005_XX, 5.6.x and 5.8.x
For what purpose do you need to know this?
eg. if I code:
$x = ~0;
then subsequently pass $x to an XS function, how does that function tell whether the argument it has just received holds the UV value ~0, or whether it's the IV value -1 ? (Given that it's quite valid to pass both signed and unsigned values to that function.)
Looks to me that for such a function (which can also take NV's, btw) one needs to follow this procedure:
if(the UV flag is set) {then take the UV value} elsif(the IV flag is set) {then take the IV value} elsif(the NV flag is set) {then take the NV value} else {take appropriate action}
That's basically all I need. The rest was just curiosity. I was surprised to find that the UV flag is set only when the scalar contains a 32-bit positive integer value (on my 32-bit platform). I had expected the UV flag to be set for *all* positive integers <= 32 bits in size. I don't think there's anything wrong with this logic regarding the setting of these flags - it simply wasn't what I expected - which started me wondering and looking for documentation ...
Also what's the best way (within XS) to determine whether a scalar that has the NV flag set contains an integer value (as opposed to a value that includes a fractional component).
Try Perl_floor() on the value and see if it's identical to the original. (I think that this will always work.) This answers your question as phrased. Not all integer values fit into IVs.
Thanks for that pointer.
I've been doing some operator overloading (with XS functions), and thinking ahead to the overloading of the '**' operator it occurred to me that you might want to know whether an NV is an integer or not.
If someone expects to be able to get a square root by doing
$obj_sqrt = $obj ** 0.5;
then you should either be able to accommodate that expectation or deliver an error message that it's not supported.
On the other hand, if $x has the NV flag set, but holds a small integer value, then you probably want to allow
$obj_raised = $obj ** $x;
Or it might be simpler to handle all this at the perl level with int() as Tels suggested .... I'm getting a little ahead of myself here - I was just after something I could use *in case* I needed it :-)
Thanks Tels, Nicholas.
Cheers, Rob