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

[PPC DoubleDouble] Can't wrap libm functions correctly

Thread Next
From:
sisyphus1
Date:
November 11, 2014 19:40
Subject:
[PPC DoubleDouble] Can't wrap libm functions correctly
Message ID:
CAED3DF30C5C43FEB40BE5838A6EA02D@OwnerPC311012
Hi,

On ppc64 (Debian Wheezy), long double (doubledouble) builds of perl 5.18 and 
later (including 5.21.5) I'm having awful trouble writing XS wrappers for 
some of the libm functions in such a way that they work correctly.

Here's an Inline::C demo of the problem I'm facing wrt wrapping the powl() 
function.
This is with perl-5.21.5, but earlier perl versions produce exactly the same 
except that $Config{longdblkind} and %a formatting are not available.

##################################
use strict;
use warnings;
use Config;

use Inline C => Config =>
  LIBS => '-lm',
  USING => 'ParseRegExp',
  BUILD_NOISY => 1;

use Inline C => <<'EOC';

SV * powl_nok(SV * op1, SV *op2) {
  long double t, t1, t2;
  t1 = (long double)SvNV(op1);
  t2 = (long double)SvNV(op2);
  if(t1 == 3.0L && t2 == 4.0L)
    printf("args successfully transferred\n");
  t = powl(t1, t2);
  return newSVnv(t);
}

SV * powl_ok(void) {
  long double t, t1 = 3.0L, t2 = 4.0L;
  t = powl(t1, t2);
  return newSVnv(t);
}

EOC

print "nvtype: ", $Config{nvtype}, "\n";
print "longdblkind: ", $Config{longdblkind}, "\n"
if $] >= 5.021004;
my $nok = powl_nok(3.0, 4.0);

print _internal($nok), "\n";
printf "%a\n", $nok if $] >= 5.021004;

my $ok = powl_ok();

print _internal($ok), "\n";
printf "%a\n", $ok if $] >= 5.021004;

sub _internal{
  return scalar reverse unpack "h*", pack "F<", $_[0];
}
##################################

This outputs:

##################################
nvtype: long double
longdblkind: 6
args successfully transferred
40544000000000003970000000000000
0x1.4400000000000000000000000004p+6
40544000000000000000000000000000
0x1.44p+6
##################################

Expected (correct) output would finish with:
40544000000000000000000000000000
0x1.44p+6
40544000000000000000000000000000
0x1.44p+6

I simply do not understand how, in this script, the powl() function that 
powl_nok() wraps returns a different value to the powl() function that 
powl_ok() wraps.
Both of those instances of the powl() function claim to take exactly the 
same arg values, yet return a different value. And powl_nok always returns 
the *same* incorrect value.

Any ideas ?

I haven't yet found a way of using powl() in a C program such that it 
emulates the incorrect behaviour we see in powl_nok().
And I haven't found a way of using powl() in an XSub such that it can 
produce the correct result - unless the arguments are hard coded into that 
XSub, such as I've done in the above powl_ok().

With some debug printing that I've done in a modified version of the above 
script, I've found evidence of heisenbugs. Sometimes the debug printing 
manages to coerce powl_ok() into returning the same incorrect value as 
powl_nok().
But powl_nok() never gets coerced into returning the correct value.

Is there some bad practice in the above demo ?
Compilation always takes place without producing any warnings.

Cheers,
Rob 


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