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

casting (Re: pp_add -> pp_i_add efficiency hack?)

Thread Previous | Thread Next
From:
Nicholas Clark
Date:
December 8, 2000 14:54
Subject:
casting (Re: pp_add -> pp_i_add efficiency hack?)
Message ID:
20001208225452.A96430@plum.flirble.org
mmm. casting. just because it works for 32 bit, doesn't mean it does for 64:

#include <stdio.h>
int main (void) {
  double d = -9.22337203685478e+18;
  long long l;
  long long min = 0x8000000000000000;
  long long max = 0x7FFFFFFFFFFFFFFF;

  l = (long long) d;

  printf ("d\t%.24g\n", d);
  printf ("l\t %lld\n", l);
  printf ("min\t%lld\n", min);
  printf ("max\t %lld\n", max);
  printf ("\nd < (double) min\t%d\n", d < (double)min);
  printf ("l < max\t\t\t%d\n", l < max);

  return 0;
}

arm, glibc2.1:
d       -9223372036854779904
l        -9223372036854775808
min     -9223372036854775808
max      9223372036854775807

d < (double) min        1
l < max                 1

x86, FreeBSD's C library
d       -9223372036854779904
l        -9223372036854775808
min     -9223372036854775808
max      9223372036854775807

d < (double) min        1
l < max                 1

x86, glibc again:
d       -9223372036854779904
l        -9223372036854775808
min     -9223372036854775808
max      9223372036854775807

d < (double) min        1
l < max                 1


I don't think that the exiting castflags work (but I'm not sure) - what forces
the use of Perl_cast_iv?

Castflags says:

/* CASTFLAGS:
 *	This symbol contains flags that say what difficulties the compiler
 *	has casting odd floating values to unsigned long:
 *		0 = ok
 *		1 = couldn't cast < 0
 *		2 = couldn't cast >= 0x80000000
 *		4 = couldn't cast in argument expression list
 */

Do we s/unsigned long/UV/ there? and probe with UV type in Configure?

Which still leaves me wondering how to probe for my problems casting negative
doubles to signed long longs. [which appears to be the floating point
emulation, not the C library. I've got the source to the floating point
emulation, but I don't think it would help trying to grok it]


The only regression test that notices this oddity is op/numconvert.t
That, op/64bitint.t and lib/peek.t are the only tests failing with my
current 64bitness. (sv conversions and pp's in pp_hot.c)

op/64bitint.t is failing because multiply is in NVs, but == is now
IV/UV/NV

I have a plan for how to make all operators integer aware except for
multiply, divide and modulo. (I'm assuming that you have 2s complement
if you want your 64 bit IVs preserved. Are there any 64 bit systems that
are not 2s complement? For what it's worth we had a couple of implicit
2s complement assumptions in the code already I think - (UV)-iv with
a note that IV_MIN == -IV_MIN "so it works" in a couple of places)

How can * / % be done efficiently so that integers are preserved as best
possible, overflow is detected, floating point divide used if the answer
isn't integer, all without g o i n g   v  e  r  y     s  l  o  w  l  y  ?

[and don't assume that you can cast reliably]

Nicholas Clark

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