Velocity Reviews > Perl > force IV to NV

# force IV to NV

Martin Mohr
Guest
Posts: n/a

 11-06-2006
Hello,

to work around a problem I'm having with SDL::OpenGL (see earlier
thread), I'd like to know a way to force an integer value (IV) to become
a double value (NV). It's not as easy as I first thought:

perl -MDevel:eek -e "\$a = 1;\$a+=0.0; Dump \$a"

This shows that \$a remains IV. How can I achive this cast?

Ciao
Martin

attn.steven.kuo@gmail.com
Guest
Posts: n/a

 11-07-2006
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

>
> I suspect that is due to 0.0 having an exact
> binary representation. You can try another
> operand for addition -- one that doesn't
> have an exact binary represenation:

Bah -- let me retract that. I should
have said that 0.0 is more simply
represented as an integer and
perl somehow uses an integer there
instead of a floating point number. Whether a floating
point number has an exact binary
representation or not has nothing to do with
it as I get the same results with:

\$ perl -MDevel:eek -le '\$z = 1; \$z + 0.5 - 0.5; Dump \$z;'
SV = PVNV(0x1803880) at 0x1800f70
REFCNT = 1
FLAGS = (IOK,NOK,pIOK,pNOK)
IV = 1
NV = 1
PV = 0

Ilya Zakharevich
Guest
Posts: n/a

 11-08-2006
[A complimentary Cc of this posting was sent to
Abigail
<(E-Mail Removed)>], who wrote in article <(E-Mail Removed)>:
> There's no need to change an IV to an NV when adding two integers.
> But there is on division:
>
>
> \$ perl -MDevel:eek -e '\$a = 1;\$a/=1; Dump \$a'
> SV = PVNV(0x818282 at 0x817fed4
> REFCNT = 1
> FLAGS = (NOK,pNOK)
> IV = 1
> NV = 1
> PV = 0

a) There is no need to mutilate \$a:

>perl -MDevel:eek -we "\$a = 1;(undef)=\$a*1.5; Dump \$a"

SV = PVNV(0x74c7c) at 0x589b8
REFCNT = 1
FLAGS = (IOK,NOK,pIOK,pNOK)
IV = 1
NV = 1
PV = 0

b) If one really NEEDS a particular field of a scalar to be present,
one uses some seriously broken Perl module.

Hope this help,
Ilya

Martin Mohr
Guest
Posts: n/a

 11-08-2006
Ilya Zakharevich wrote:
> b) If one really NEEDS a particular field of a scalar to be present,
> one uses some seriously broken Perl module.

Thanks everybody for the answers. I am afraid you are right. The XS of
SDL::OpenGL does, for example in glMultMatrix,

mat[i] = (i < items && SvNOK(ST(i)) ? SvNV(ST(i)) : 0.0 );

So it checks SvNOK before using SvNV. This causes problems when a
parameter hasn't been in touch with floating point stuff before usage.
What makes this even worse, is that scalars can also lose their floating
point property again.

So as a workaround one can bring all parameters in contact with floating
point operations (as you have shown) before passing them to
glMultMatrix. Or one uses another module. Like yours for example.

Ciao
Martin

Ilya Zakharevich
Guest
Posts: n/a

 11-08-2006
[A complimentary Cc of this posting was sent to
Martin Mohr
<(E-Mail Removed)>], who wrote in article <eitc6q\$tcs\$01\$(E-Mail Removed)-online.com>:
> Ilya Zakharevich wrote:
> > b) If one really NEEDS a particular field of a scalar to be present,
> > one uses some seriously broken Perl module.

>
> Thanks everybody for the answers. I am afraid you are right. The XS of
> SDL::OpenGL does, for example in glMultMatrix,
>
> mat[i] = (i < items && SvNOK(ST(i)) ? SvNV(ST(i)) : 0.0 );

Your analysis looks correct: this is a seriously wrong piece of code.
The only purpose I could think for writing something as horrible as
this is to avoid "undefined value used in..." warning; but then one
must have used SvOK(), not SvNOK.

> So it checks SvNOK before using SvNV.

For those less familiar with what Perl macros do: SvNV() is designed
to cover all the bases (but will emit the warning on undef if warnings
are enabled). Any homegrown modification of SvNV() (like the
conditional above) will break something...

> This causes problems when a
> parameter hasn't been in touch with floating point stuff before usage.
> What makes this even worse, is that scalars can also lose their floating
> point property again.

Do not think I know what you are talking about in the latter sentence.

> So as a workaround one can bring all parameters in contact with floating
> point operations (as you have shown) before passing them to
> glMultMatrix. Or one uses another module. Like yours for example.

Sorry, I have little time to work on it lately. Moreover, itis not
"my module". I'm just the latest of maintainers - I wrote very little
of it.

Yours,
Ilya

P.S. One solution is to run over this with a smart search-and-replace
pattern in an editor...

xhoster@gmail.com
Guest
Posts: n/a

 11-08-2006
Martin Mohr <(E-Mail Removed)> wrote:
> Ilya Zakharevich wrote:
> > b) If one really NEEDS a particular field of a scalar to be present,
> > one uses some seriously broken Perl module.

>
> Thanks everybody for the answers. I am afraid you are right. The XS of
> SDL::OpenGL does, for example in glMultMatrix,
>
> mat[i] = (i < items && SvNOK(ST(i)) ? SvNV(ST(i)) : 0.0 );
>
> So it checks SvNOK before using SvNV. This causes problems when a
> parameter hasn't been in touch with floating point stuff before usage.
> What makes this even worse, is that scalars can also lose their floating
> point property again.

Perlguts seeems to be wrong. It says:

What's Really Stored in an SV?

Recall that the usual method of determining the type of scalar you
have is to use "Sv*OK" macros. Because a scalar can be both a
number and a string, usually these macros will always return TRUE
and calling the "Sv*V" macros will do the appropriate conversion of
string to inte- ger/double or integer/double to string.

I figured that the "usually..always" means SvNOK will always return true
for non-tied, non-magical variables. But obviously it doesn't mean that.
I throught SvNOK means "Is it OK to call SvNV and trust what it gives?" but
apparently that is not what it means.

Xho

--
Usenet Newsgroup Service \$9.95/Month 30GB