Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Differing output between C++ and NativeCall in Raku

I am trying to write a function for cumulative distribution function taken from here.

This is my cpp code:

#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;

double normalCDF( double x )
{
   return  0.5 * ( 1.0 + erf( M_SQRT1_2 * x ) );

}

int main() {

    cout << normalCDF(4.8) << endl;    
    cout << normalCDF(5.4) << endl;
    cout << normalCDF(5.6) << endl;
    cout << normalCDF(5.8) << endl;
    cout << normalCDF(5.1) << endl;
    cout << normalCDF(-37.5) << endl;
    cout << normalCDF(-36.0) << endl;
    cout << normalCDF(-37.6) << endl;
    cout << normalCDF(-37.5) << endl;

    return 0;
    }

This is the output when compiled in linux with gcc 6.3.0

0.999999                                                                                                                
1                                                                                                                       
1                                                                                                                       
1                                                                                                                       
1                                                                                                                       
0                                                                                                                       
0                                                                                                                       
0                                                                                                                       
0 

I wanted to call same code from raku using NativeCall, so I modified code

test.cpp

extern "C" double normalCDF( double x )
{
   return  0.5 * ( 1.0 + erf( M_SQRT1_2 * x ) );

}

created dynamic shared .so library and wrote nativecall code as:

use NativeCall;

sub normalCDF(num64) returns num64 is native('libtest.so') { * };


say normalCDF((4.8).Num);
say normalCDF((5.4).Num);
say normalCDF((5.6).Num);
say normalCDF((5.8).Num);
say normalCDF((5.1).Num);
say normalCDF((-37.5).Num);
say normalCDF((-36.0).Num);
say normalCDF((-37.6).Num);
say normalCDF((-37.5).Num);

The output is:

0.999999206671848
0.9999999666795515
0.9999999892824097
0.9999999966842541
0.9999998301732593
0
0
0
0

Why is the output of same algorithm differing, though the data containers are used as recommended.

System information:

  • Ubuntu 18.04 64bit with gcc 6.3.0
  • Rakudo is 2019.07.1 version.
like image 665
Suman Khanal Avatar asked Oct 27 '19 15:10

Suman Khanal


1 Answers

You need to print the floating point numbers with increased precision. The following will give you the maximum precision:

#include <limits>
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;

double normalCDF( double x )
{
   return  0.5 * ( 1.0 + erf( M_SQRT1_2 * x ) );

}

int main() {

    typedef std::numeric_limits< double > dmax;
    cout.precision(dmax::max_digits10);

    cout << normalCDF(4.8) << endl;    
    cout << normalCDF(5.4) << endl;
    cout << normalCDF(5.6) << endl;
    cout << normalCDF(5.8) << endl;
    cout << normalCDF(5.1) << endl;
    cout << normalCDF(-37.5) << endl;
    cout << normalCDF(-36.0) << endl;
    cout << normalCDF(-37.6) << endl;
    cout << normalCDF(-37.5) << endl;

    return 0;
    }

Notice the #include <limits> and the first two lines in main, although line 2 is what matters.

like image 122
Javier Silva Ortíz Avatar answered Sep 22 '22 01:09

Javier Silva Ortíz