On Sat, Apr 24, 2004 at 10:35:47AM +1000, Sisyphus wrote: > Nicholas Clark wrote: > >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.)
5.6.0 introduced the SvIsUV() test, which will tell you whether you (really) have a UV. Prior to that the whole IV/UV thing in the core was educated guesswork on the part of the ops, which mostly worked. What I think you're really looking for here are SvIOK_notUV() and SvIOK_only() > 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} Unless you need to be that polymorphic in your behaviour, I'd suggest using SvNV() or SvUV() or SvIV() which will do whatever conversion is needed, and cope with tied variables etc. The logic as you state is reasonable for 5.8.x For 5.6.x you should always take the NV value in preference to the IV or UV because all the internals are happy to set IvOK to mark that the IV slot has a valid value, rather than the IV slot has a correct value. So in 5.6.2, this is what happens and it's fine because every (non integer) op always uses NVs: perl5.6.2 -MDevel::Peek -e '$a = 2.5; $b = $a & 0; Dump $a;' SV = PVNV(0x8010a0) at 0x806e3c REFCNT = 1 FLAGS = (IOK,NOK,pIOK,pNOK,IsUV) UV = 2 NV = 2.5 PV = 0 and in 5.8.4 this what happens, because 2 isn't 2.5, and if IOK were set all the basic maths ops (such as +) would use the IV value. perl5.8.4 -MDevel::Peek -e '$a = 2.5; $b = $a & 0; Dump $a;' SV = PVNV(0x810060) at 0x8075d8 REFCNT = 1 FLAGS = (NOK,pIOK,pNOK) IV = 2 NV = 2.5 PV = 0 > 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 ... At one point during working on the maths ops I benchmarked things and found that they were a little slower if the UV flag was set (because the mixed IV/UV paths through the C code kept getting taken). This may not be the case any more. Nicholas Clark