This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: m68k FPU precision issue
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.3
process
Status: closed Resolution: duplicate
Dependencies: Superseder: HAVE_PY_SET_53BIT_PRECISION for m68k
View: 20904
Assigned To: Nosy List: mark.dickinson, mirabilos, schwab, skrah
Priority: normal Keywords:

Created on 2013-05-25 21:00 by mirabilos, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (15)
msg189999 - (view) Author: mirabilos (mirabilos) Date: 2013-05-25 21:00
Hi,

splitting off issue18061 by request of pitrou:

FPU precision issue: MC68881 FPU, similar to Intel 80387, uses 80-bit precision internally. We do not want to change it to 64-bit because it’s not supported in all environments. Can probably be reproduced on i386 (with disabled SSE); fixing this in general would allow keeping the FPUCW on i387 unchanged too.

See issue18061 for details.
msg190007 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2013-05-25 21:17
> We do not want to change it to 64-bit because it’s not supported in all environments.

Does this also apply to changing the precision temporarily? Because
that is what happens for other platforms, see Include/pyport.h:


HAVE_PY_SET_53BIT_PRECISION
_PY_SET_53BIT_PRECISION_START
_PY_SET_53BIT_PRECISION_END
...


To me it sounds that you'd basically have to provide these macros
for the platform.
msg190009 - (view) Author: mirabilos (mirabilos) Date: 2013-05-25 21:20
> > We do not want to change it to 64-bit because it’s not supported
> > in all environments.

> Does this also apply to changing the precision temporarily?

Yes, that’s precisely what’s not working on the most widespread emulator, at the very least. (I have working code for that, in three(!) variants, but it just ignores those requests to change precision.)

I think FPU is the one thing current m68k emulators do the worst… the responses I got from the mailing list back then said so, anyway.
msg190027 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2013-05-25 22:18
I forgot to comment on this:

> fixing this in general would allow keeping the FPUCW on i387 unchanged too.

Actually dtoa.c (which is used on i387) explicitly requires to change
the control word.


Looking at the test results, it seems to me that a couple of tests
could be skipped if PY_NO_SHORT_FLOAT_REPR is defined, i.e.the
failures are fully expected.

Not sure about the lgamma etc. failures though, perhaps that's
an emulator bug.
msg190029 - (view) Author: mirabilos (mirabilos) Date: 2013-05-25 22:19
mirabilos dixit:

>mirabilos added the comment:

>Yes, that’s precisely what’s not working on the most widespread
>emulator, at the very least. (I have working code for that, in
>three(!) variants, but it just ignores those requests to change
>precision.)

Here’s the Python testcase made into a standalone test:

-----BEGIN cutting here may damage your screen surface-----
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifndef __MirBSD__
#include <fpu_control.h>
#endif

void runtests(void);

void
runtests(void)
{
	volatile double x, y, z;

	/* 1./(1-2**-53) -> 1+2**-52 (correct), 1.0 (double rounding) */
	x = 0.99999999999999989; /* 1-2**-53 */
	y = 1./x;
	printf("test#1 %s: %.17E\n", (y == 1.) ? "fail" : "good", y);
	/* 1e16+2.99999 -> 1e16+2. (correct), 1e16+4. (double rounding) */
	x = 1e16;
	y = 2.99999;
	z = x + y;
	printf("test#2 %s: %.17E\n", z == 1e16+4. ? "fail" : "good", z);
}

int
main(void) {
#ifdef _FPU_SETCW
	fpu_control_t cwold, cwnew, cwgot;
#endif

	runtests();
#if (defined(__i386__) || defined(__m68k__)) && defined(_FPU_SETCW)
	_FPU_GETCW(cwold);
#ifdef __i386__
	cwnew = 0x127f;
#else
	cwnew = _FPU_RC_NEAREST | _FPU_DOUBLE;
#endif
	_FPU_SETCW(cwnew);
	_FPU_GETCW(cwgot);
	printf("changing FPU control word from %08X to %08X => %08X\n",
	    cwold, cwnew, cwgot);
	runtests();
#endif

	return (0);
}
-----END cutting here may damage your screen surface-----

Here’s the result of running it on the latest ARAnyM, which
did get MPFR-based FPU emulation bugfixes, but apparently
still ignores any FPUCW changes (or, at least the ones relating
to precision):

root@ara3:~ # ./a.out
test#1 fail: 1.00000000000000000E+00
test#2 fail: 1.00000000000000040E+16
changing FPU control word from 00000000 to 00000080 => 00000080
test#1 fail: 1.00000000000000000E+00
test#2 fail: 1.00000000000000040E+16

bye,
//mirabilos
-- 
  "Using Lynx is like wearing a really good pair of shades: cuts out
   the glare and harmful UV (ultra-vanity), and you feel so-o-o COOL."
                                         -- Henry Nelson, March 1999
msg190030 - (view) Author: mirabilos (mirabilos) Date: 2013-05-25 22:31
Stefan Krah dixit:

>> fixing this in general would allow keeping the FPUCW on i387 unchanged too.
>
>Actually dtoa.c (which is used on i387) explicitly requires to change
>the control word.

Right. By fixing the “older” code, i386 is not required to change
the FPUCW any more and can use it too.

The problem with changing the FPUCW on i387 is that it changes
from 64/15 bit mantissa/exponent to 53/15 bit which is still
not the 53/11 bit of IEEE double, so you *still* get double-
rounding issues (with denormal numbers only, I guess) because
the internal precision is still higher.

And on m68k we simply cannot afford to change the FPUCW because
that will cause runtime failures on some implementations.

>Looking at the test results, it seems to me that a couple of tests
>could be skipped if PY_NO_SHORT_FLOAT_REPR is defined, i.e.the
>failures are fully expected.

Ah okay.

>Not sure about the lgamma etc. failures though, perhaps that's
>an emulator bug.

If I can get self-contained test cases (preferably in C because
that makes it easier for others to test), I can ask people who
run real bare-metal Atari or Amiga to test them.

Or you can ask on debian-68k@lists.debian.org for testers.

I guess a python2.6 runnable testcase would be okay, even for
those running an a bit older “base system”. (I admit mine is
not really up to date either, just the build chroots, because
of the post-release unfreeze upload peak and related transitions.)

bye,
//mirabilos
-- 
“It is inappropriate to require that a time represented as
 seconds since the Epoch precisely represent the number of
 seconds between the referenced time and the Epoch.”
	-- IEEE Std 1003.1b-1993 (POSIX) Section B.2.2.2
msg190068 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-05-26 07:40
> The problem with changing the FPUCW on i387 is that it changes
> from 64/15 bit mantissa/exponent to 53/15 bit which is still
> not the 53/11 bit of IEEE double, so you *still* get double-
> rounding issues (with denormal numbers only, I guess) because
> the internal precision is still higher.

That's not a problem for dtoa.c, at least: dtoa.c avoids any use of subnormals in intermediate calculations.  It's not really too much of a problem for Python in general, either.  Windows typically operates in this mode.
msg190069 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-05-26 10:16
It's also an option not to use dtoa.c:  Python still has fallback code that uses the OS double <-> char* conversions for the case where the configuration step can't figure out how to change the FPU control word.  In that case compilation should still succeed, and the resulting Python would show:

>>> import sys
>>> sys.float_repr_style
'legacy'

If there are tests failing with the 'legacy' mode, that may just indicate buggy tests that haven't been properly marked as depending on the short float repr.  (E.g., by decorating with "@unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short'"), or poorly-designed tests that could be rewritten.
msg190081 - (view) Author: Andreas Schwab (schwab) * Date: 2013-05-26 12:27
Thorsten Glaser <tg@mirbsd.de> writes:

> root@ara3:~ # ./a.out
> test#1 fail: 1.00000000000000000E+00
> test#2 fail: 1.00000000000000040E+16
> changing FPU control word from 00000000 to 00000080 => 00000080
> test#1 fail: 1.00000000000000000E+00
> test#2 fail: 1.00000000000000040E+16

What is the exact sequence of fpu insns?

Andreas.
msg190086 - (view) Author: mirabilos (mirabilos) Date: 2013-05-26 12:58
Mark Dickinson dixit:

>If there are tests failing with the 'legacy' mode, that may just
>indicate buggy tests that haven't been properly marked as depending on
>the short float repr. (E.g., by decorating with

I think that’s what we’re seeing here.

Python 3.3.1 (default, May 10 2013, 02:52:57)
[GCC 4.6.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.float_repr_style
'legacy'

Andreas Schwab dixit:

>What is the exact sequence of fpu insns?

That’s all gcc-generated code and a system header…

In main (after commenting out the second getcw and printf):

        jsr runtests
#APP
| 34 "x.c" 1
        fmove.l %fpcr, %d2
| 0 "" 2
#NO_APP
        move.l %d2,-4(%fp)
        move.l #128,-8(%fp)
#APP
| 40 "x.c" 1
        fmove.l -8(%fp), %fpcr
| 0 "" 2
#NO_APP
        jsr runtests

And the subroutine:

runtests:
        link.w %fp,#-24
        move.l %d3,-(%sp)
        move.l %d2,-(%sp)
        move.l #1072693247,-8(%fp)
        move.l #-1,-4(%fp)
        move.l -8(%fp),%d0
        move.l -4(%fp),%d1
        fmovecr #0x32,%fp0
        move.l %d1,-(%sp)
        move.l %d0,-(%sp)
        fmove.d (%sp)+,%fp1
        fdiv.x %fp1,%fp0
        fmove.d %fp0,-(%sp)
        move.l (%sp)+,%d0
        move.l (%sp)+,%d1
        move.l %d0,-16(%fp)
        move.l %d1,-12(%fp)
        move.l -16(%fp),%d2
        move.l -12(%fp),%d3
        move.l -16(%fp),%a0
        move.l -12(%fp),%a1
        move.l #1072693248,%d0
        clr.l %d1
        move.l %a1,-(%sp)
        move.l %a0,-(%sp)
        fmove.d (%sp)+,%fp0
        move.l %d1,-(%sp)
        move.l %d0,-(%sp)
        fmove.d (%sp)+,%fp1
        fcmp.x %fp1,%fp0
        fjne .L2
        move.l #.LC0,%d0
        jra .L3
.L2:
        move.l #.LC1,%d0
.L3:
        move.l #.LC2,%d1
        move.l %d3,-(%sp)
        move.l %d2,-(%sp)
        move.l %d0,-(%sp)
        move.l %d1,-(%sp)
        jsr printf
        lea (16,%sp),%sp
        move.l #1128383353,-8(%fp)
        move.l #937459712,-4(%fp)
        move.l #1074266106,-16(%fp)
        move.l #-1043161657,-12(%fp)
        move.l -8(%fp),%a0
        move.l -4(%fp),%a1
        move.l -16(%fp),%d0
        move.l -12(%fp),%d1
        move.l %a1,-(%sp)
        move.l %a0,-(%sp)
        fmove.d (%sp)+,%fp0
        move.l %d1,-(%sp)
        move.l %d0,-(%sp)
        fmove.d (%sp)+,%fp1
        fadd.x %fp1,%fp0
        fmove.d %fp0,-(%sp)
        move.l (%sp)+,%d0
        move.l (%sp)+,%d1
        move.l %d0,-24(%fp)
        move.l %d1,-20(%fp)
        move.l -24(%fp),%a0
        move.l -20(%fp),%a1
        move.l -24(%fp),%d0
        move.l -20(%fp),%d1
        move.l %d1,-(%sp)
        move.l %d0,-(%sp)
        fmove.d (%sp)+,%fp0
        fcmp.d #0x4341c37937e08002,%fp0
        fjne .L4
        move.l #.LC0,%d0
        jra .L5
.L4:
        move.l #.LC1,%d0
.L5:
        move.l #.LC3,%d1
        move.l %a1,-(%sp)
        move.l %a0,-(%sp)
        move.l %d0,-(%sp)
        move.l %d1,-(%sp)
        jsr printf
        lea (16,%sp),%sp
        move.l -32(%fp),%d2
        move.l -28(%fp),%d3
        unlk %fp
        rts

bye,
//mirabilos
-- 
Yay for having to rewrite other people's Bash scripts because bash
suddenly stopped supporting the bash extensions they make use of
	-- Tonnerre Lombard in #nosec
msg190087 - (view) Author: mirabilos (mirabilos) Date: 2013-05-26 13:17
Laurent Vivier dixit:

> BTW, the result on a real CPU (68040) is :

68881 even ;-)

> test#1 fail: 1.00000000000000000E+00
> test#2 fail: 1.00000000000000040E+16
> changing FPU control word from 00000000 to 00000080 => 00000080
> test#1 good: 1.00000000000000022E+00
> test#2 good: 1.00000000000000020E+16

Thanks, that’s what I was guessing. I get similar results on i386.

Now as additional data point, UAE/WinUAE/etc. would be interesting.

Even so, I’d be very reluctant to add this code to Python to make
it change the FPU mode, because Python is heavily used in Debian,
and getting varying results between emulation and bare metal is
something we’d like to not have…

bye,
//mirabilos
-- 
  "Using Lynx is like wearing a really good pair of shades: cuts out
   the glare and harmful UV (ultra-vanity), and you feel so-o-o COOL."
                                         -- Henry Nelson, March 1999
msg190091 - (view) Author: mirabilos (mirabilos) Date: 2013-05-26 14:26
Laurent Vivier dixit:

> For the "etc" ;-) , in Qemu, I have:

Hm, I thought qemu did not emulate an MMU?

bye,
//mirabilos
-- 
[...] if maybe ext3fs wasn't a better pick, or jfs, or maybe reiserfs, oh but
what about xfs, and if only i had waited until reiser4 was ready... in the be-
ginning, there was ffs, and in the middle, there was ffs, and at the end, there
was still ffs, and the sys admins knew it was good. :)  -- Ted Unangst über *fs
msg190103 - (view) Author: mirabilos (mirabilos) Date: 2013-05-26 17:50
Eero Tamminen dixit:

>> > Now as additional data point, UAE/WinUAE/etc. would be interesting.
>
>I built the test with fpu_control.h header from eglibc, using
>Sparemint GCC 2.9.5 (with 2010 binutils) and MiNTlib.  When it's

Nice ;)

>I.e. it seems that WinUAE FPU emulation is also lacking FPUCW change
>handling (for precision).
>
>(Hatari's WinUAE CPU core code was synched with upstream last year.)

OK, thanks. I’d just say let’s say changing FPU precision is not
part of the target we support. (Funnily enough, ColdFire according
to the ’net has (unchangeable) 64-bit precision… maybe let’s just
say precision on m68k in general is not defined.)

bye,
//mirabilos
-- 
17:08⎜«Vutral» früher gabs keine packenden smartphones und so
17:08⎜«Vutral» heute gibts frauen die sind facebooksüchtig
17:10⎜«Vutral» aber auch traurig; früher warst du als nerd voll am arsch
17:10⎜«Vutral» heute bist du als nerd der einzige der wirklich damit klarkommt
msg215467 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2014-04-03 20:24
Can we somehow merge this issue with #20904?
msg218487 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2014-05-13 22:30
This should be fixed now.
History
Date User Action Args
2022-04-11 14:57:46adminsetgithub: 62262
2014-05-13 22:30:38skrahsetstatus: open -> closed
superseder: HAVE_PY_SET_53BIT_PRECISION for m68k
messages: + msg218487

type: behavior
resolution: duplicate
stage: resolved
2014-04-03 20:24:20skrahsetmessages: + msg215467
2013-05-26 17:50:38mirabilossetmessages: + msg190103
2013-05-26 14:26:35mirabilossetmessages: + msg190091
2013-05-26 13:17:51mirabilossetmessages: + msg190087
2013-05-26 12:58:05mirabilossetmessages: + msg190086
2013-05-26 12:27:23schwabsetnosy: + schwab
messages: + msg190081
2013-05-26 10:16:44mark.dickinsonsetmessages: + msg190069
2013-05-26 07:40:48mark.dickinsonsetmessages: + msg190068
2013-05-26 06:12:05serhiy.storchakalinkissue18061 dependencies
2013-05-25 22:31:39mirabilossetmessages: + msg190030
2013-05-25 22:19:28mirabilossetmessages: + msg190029
2013-05-25 22:18:07skrahsetmessages: + msg190027
2013-05-25 21:20:29mirabilossetmessages: + msg190009
2013-05-25 21:17:56skrahsetnosy: + mark.dickinson, skrah
messages: + msg190007
2013-05-25 21:00:51mirabiloscreate