emulated s390 mpfr problem

Patrick Pelissier Patrick.Pelissier at loria.fr
Wed Jun 1 09:27:47 CEST 2005


Hello,

 Please use MPFR 2.1.1 instead of the one shipped with GMP 4.1.4.
 It works much better (faster, more portable and less bugs).
 Get it at www.mpfr.org .

Sincerely,
 Patrick Pelissier


On Tue, May 31, 2005 at 17:31:43 -0400, Greg Smith wrote:
> Hello,
> 
> I'm back!  I am still having trouble getting the s390 emulator to pass
> mpfr checks that pass on a real s390.  I composed a testcase,
> mpfr_add.c, that is the first addendum below.  I get one result on a
> real machine and another on the emulator.
> 
> But one thing is confusing me.  Running the testcase on intel (pentium
> 4) I am getting a weird result.  I don't see how the particular test
> passes on intel.  So I hacked mpfr/tests/tadd.c to run the same exact
> test and it passes!  I am thinking if I understand what is going on, I
> can fix the emulator.
> 
> Per your previous suggestions, I am working with gmp-4.1.4.  The
> emulator does not emulate floating point but rather uses the host's
> floating point implementation (in this case pentium 4).  For example,
> the s390 instruction that sets the rounding mode, SRNM, calls
> fesetround.  (This was my original problem, host rounding mode was not
> being set).
> 
> I fully understand that the host architecture may give different results
> in floating point arithmetic than s390 due to the number of guard bits,
> etc.  
> 
> The testcase is a special instance where the precision is px == py == pz
> == 53.  Also the bad assumption is made that sizeof(double) == sizeof
> (unsigned long long) == 8.
> 
> Below are the results of the testcase and the hacked tadd.c:
> 
> Real s390
> ------------------------------------------
> ~/gmp-4.1.4/mpfr/tests> ./mpfr_add
>  x=89e9b6bd4a167678  y=07fdb24440062c08
> z1=89e9b6bd49db11ef z2=89e9b6bd49db11ef
> 
> ~/gmp-4.1.4/mpfr/tests> ./tadd
> rounding mode set to GMP_RNDN
>  x=89e9b6bd4a167678  y=07fdb24440062c08
> z1=89e9b6bd49db11ef z2=89e9b6bd49db11ef
> 
> 
> Intel pentium 4
> ------------------------------------------
> $ ./mpfr_add
>  x=89e9b6bd4a167678  y=07fdb24440062c08
> z1=89e9b6bd49db11f0 z2=89e9b6bd49db11ef
> 
> $ ./tadd
> rounding mode set to GMP_RNDN
>  x=89e9b6bd4a167678  y=07fdb24440062c08
> z1=89e9b6bd49db11ef z2=89e9b6bd49db11ef
> 
> 
> Emulated s390
> ------------------------------------------
> ~/gmp-4.1.4/mpfr/tests> ./mpfr_add
>  x=89e9b6bd4a167678  y=07fdb24440062c08
> z1=89e9b6bd49db11f0 z2=89e9b6bd49db11ef
> 
> ~/gmp-4.1.4/mpfr/tests> ./tadd
> rounding mode set to GMP_RNDN
>  x=89e9b6bd4a167678  y=07fdb24440062c08
> z1=89e9b6bd49db11f0 z2=89e9b6bd49db11ef
> 
> z1 is the double from adding doubles x + y; z2 is the value extracted
> from the result of mpfr_add.
> 
> What I can't understand is why the pentium 4 z1 values differ between
> the two tests.  I am thinking that if I can understand this then I have
> a chance for fixing the emulator.
> 
> Finally, please let me know if I should rather attach the addenda below
> as a gzipped file.  Oh, and my mailer is probably going to wrap some of
> the lines in the tadd.c hack.
> 
> Thanks,
> Greg Smith
> 
> 
> 
> [1] mpfr_add.c
> /*
>  *  rnd_mode=GMP_RNDN  px=53 py=53 pz=53
>  *  x=89e9b6bd4a167678  y=07fdb24440062c08
>  * z1=89e9b6bd49db11f0 z2=89e9b6bd49db11ef
>  */
> #include <stdio.h>
> #include <fenv.h>
> #include "gmp.h"
> #include "mpfr.h"
> 
> typedef union {
>         double f;
>         unsigned long long i;
> } DOUBLE;
> 
> int main(int argc, char *argv[])
> {
>  DOUBLE x,y,z1,z2;
>  mpfr_t xx,yy,zz;
>  mp_rnd_t rnd_mode = GMP_RNDN;
> 
>  x.i = 0x89e9b6bd4a167678ull;
>  y.i = 0x07fdb24440062c08ull;
> 
>  mpfr_init2(xx,53);
>  mpfr_init2(yy,53);
>  mpfr_init2(zz,53);
>  mpfr_set_d(xx, x.f, rnd_mode);
>  mpfr_set_d(yy, y.f, rnd_mode);
>  mpfr_add(zz, xx, yy, rnd_mode);
> 
>  mpfr_set_machine_rnd_mode(rnd_mode);
> 
>  z1.f = x.f + y.f;
>  z2.f = mpfr_get_d1(zz);
> 
>  printf(" x=%16.16llx  y=%16.16llx\n",x.i,y.i);
>  printf("z1=%16.16llx z2=%16.16llx\n",z1.i,z2.i);
> }
> 
> 
> [2] tadd.pat
> --- tadd.c.orig 2002-11-21 16:35:37.000000000 -0500
> +++ tadd.c      2005-05-31 13:34:01.000000000 -0400
> @@ -29,6 +29,11 @@
>  #include "mpfr-impl.h"
>  #include "mpfr-test.h"
>  
> +typedef union {
> +        double f;
> +        unsigned long long i;
> +} DOUBLE;
> +
>  void checknan _PROTO((double, double, mp_rnd_t, unsigned int, unsigned
> int,
> unsigned int)); 
>  void check3 _PROTO((double, double, mp_rnd_t));
>  void check4 _PROTO((double, double, mp_rnd_t));
> @@ -55,28 +60,35 @@
>  /* checks that x+y gives the same results in double
>     and with mpfr with 53 bits of precision */
>  void
> -_check (double x, double y, double z1, mp_rnd_t rnd_mode, unsigned int
> px, 
> +_check (double _x, double _y, double _z1, mp_rnd_t rnd_mode, unsigned
> int px, 
>          unsigned int py, unsigned int pz)
>  {
> -  double z2; mpfr_t xx,yy,zz; int cert=0;
> +  DOUBLE x,y,z1,z2; mpfr_t xx,yy,zz; int cert=0;
> +
> +  x.f = _x; y.f = _y; z1.f = _z1;
>  
>    mpfr_init2(xx, px);
>    mpfr_init2(yy, py);
>    mpfr_init2(zz, pz);
> -  mpfr_set_d(xx, x, rnd_mode);
> -  mpfr_set_d(yy, y, rnd_mode);
> +  mpfr_set_d(xx, x.f, rnd_mode);
> +  mpfr_set_d(yy, y.f, rnd_mode);
>    mpfr_add(zz, xx, yy, rnd_mode);
>  #ifdef MPFR_HAVE_FESETROUND
>    mpfr_set_machine_rnd_mode(rnd_mode);
>    if (px==53 && py==53 && pz==53) cert=1;
> +printf("rounding mode set to %s\n",mpfr_print_rnd_mode(rnd_mode));
>  #endif
> -  if (z1==0.0) z1=x+y; else cert=1;
> -  z2 = mpfr_get_d1 (zz);
> -  mpfr_set_d (yy, z2, GMP_RNDN);
> -  if (!mpfr_cmp (zz, yy) && cert && z1!=z2 && !(isnan(z1) && isnan
> (z2))) {
> -    printf("expected sum is %1.20e, got %1.20e\n",z1,z2);
> +  if (z1.f==0.0) z1.f=x.f+y.f; else cert=1;
> +  z2.f = mpfr_get_d1 (zz);
> +
> +printf(" x=%16.16llx  y=%16.16llx\n",x.i,y.i);
> +printf("z1=%16.16llx z2=%16.16llx\n",z1.i,z2.i);
> +
> +  mpfr_set_d (yy, z2.f, GMP_RNDN);
> +  if (!mpfr_cmp (zz, yy) && cert && z1.f!=z2.f && !(isnan(z1.f) &&
> isnan(z2.f))) {
> +    printf("expected sum is %1.20e, got %1.20e\n",z1.f,z2.f);
>      printf("mpfr_add failed for x=%1.20e y=%1.20e with rnd_mode=%s\n",
> -          x, y, mpfr_print_rnd_mode(rnd_mode));
> +          x.f, y.f, mpfr_print_rnd_mode(rnd_mode));
>      exit(1);
>    }
>    mpfr_clear(xx); mpfr_clear(yy); mpfr_clear(zz);
> @@ -658,7 +670,15 @@
>    double x;
>    int i;
>  
> +  DOUBLE xx,yy;
> +  xx.i = 0x89e9b6bd4a167678ull;
> +  yy.i = 0x07fdb24440062c08ull;
> +
>    mpfr_test_init ();
> +
> +  check(xx.f, yy.f, GMP_RNDN, 53, 53, 53, 0.0);
> +  exit(0);
> +
>    check_inexact ();
>    check_case_1b ();
>    check_case_2 ();
> 
> 
> 
> _______________________________________________
> gmp-discuss mailing list
> gmp-discuss at swox.com
> https://gmplib.org/mailman/listinfo/gmp-discuss


More information about the gmp-discuss mailing list