develooper Front page | perl.perl5.porters | Postings from November 2000

Re: pp_add -> pp_i_add efficiency hack?

Thread Previous | Thread Next
From:
Nicholas Clark
Date:
November 24, 2000 13:51
Subject:
Re: pp_add -> pp_i_add efficiency hack?
Message ID:
20001124215139.A75011@plum.flirble.org
There's some bits in sv.c that I'd like to ask about:

    if (SvNOKp(sv)) {			/* See note in sv_2uv() */
	/* XXXX 64-bit?  IV may have better precision... */
	/* I tried changing this to be 64-bit-aware and
	 * the t/op/numconvert.t became very, very, angry.
	 * --jhi Sep 1999 */

Is it something like Ilya put a dragon in there which usually lies sleeping?
And did that sv_2uv used to read sv_2iv until a global search-and-replace
was done when sv_2uv was cloned and then mutated from sv_2iv?
[I'm guessing that is what happened]


	if (s - nbegin >= TYPE_DIGITS(IV))	/* Cannot cache ato[ul]() */
	    numtype |= IS_NUMBER_TO_INT_BY_ATOF | IS_NUMBER_NOT_IV;
	else
	    numtype |= IS_NUMBER_TO_INT_BY_ATOL;


I think I see what it's doing. If there are less digits than the number eof
digits in the maximum value (signed? unsigned:
31      10.332
32      10.633
35      11.5361
36      11.8371
63      19.9649
64      20.266
95      29.5979
96      29.899
127     39.2309
128     39.532
255     77.7629
256     78.0639

looks like we're safe for most things until 256 bit integers)
then the conversion defaults to going via atof, as there's this inbuilt
assumption that NV preserves UV. viz (32 bit IV, 64 bit NV):

nick@Bagpuss [bleadperl]$ ./perl -Ilib -MDevel::Peek -we '$a = "999999999"; $a |= 1; Dump ($a)' 
SV = PVIV(0x20d2f50) at 0x20dcf20
  REFCNT = 1
  FLAGS = (IOK,pIOK,IsUV)
  UV = 999999999
  PV = 0x20e1ac0 "999999999"\0
  CUR = 9
  LEN = 10
nick@Bagpuss [bleadperl]$ ./perl -Ilib -MDevel::Peek -we '$a = "1000000000"; $a |= 1; Dump ($a)' 
SV = PVNV(0x20d35d8) at 0x20dcf20
  REFCNT = 1
  FLAGS = (IOK,pIOK,IsUV)
  UV = 1000000001
  NV = 1000000000
  PV = 0x20e1ac0 "1000000000"\0
  CUR = 10
  LEN = 11

Easily fooled into thinking an NV would be needed:
nick@Bagpuss [bleadperl]$ ./perl -Ilib -MDevel::Peek -we '$a = "0999999999"; $a |= 1; Dump ($a)' 
SV = PVNV(0x20d35d8) at 0x20dcf20
  REFCNT = 1
  FLAGS = (IOK,pIOK,IsUV)
  UV = 999999999
  NV = 999999999
  PV = 0x20e1ac0 "0999999999"\0
  CUR = 10
  LEN = 11

[this might just be an issue. maybe the count should skip leading zeros.]


So does this mean that to change from "IV good, NV better" to
"all ?Vs are equal" some more effort with trying both integer and float
conversion and seeing what flies is going to be needed for numbers which
looks_like_number() counts to have the same number of digits as the largest
value?

I think numbers with less digits are safe with the current
looks_like_number() [even for systems where NV doesn't preserve IV] as long
as sv_2iv/sv_2uv/sv_2nv ensure that things that could cause trouble like
"123456789123456789.2" are converted to both NV and IV when either NV or IV
is requested
[approximated as IV 123456789123456789 and NV 1.23456789123457e+17 say]
sv_2iv will be able to tell as it will be told IS_NUMBER_NOT_IV, do the NV
conversion, check, find that the NV is less than IV_MAX, and hence also do
the direct PV->IV conversion.  Hmm. I think that will actually work for all
borderline cases, such as the "1000000000" above.


Nick

PS I don't like floating point numbers. printf can give you numbers such as
    NaN and Infinity, so why can't scanf read 'em? :-(

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About