www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 8476] New: float comparison operand not truncated from real

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476

           Summary: float comparison operand not truncated from real
           Product: D
           Version: D2
          Platform: x86
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: ellery-newcomer utulsa.edu



14:28:26 PDT ---
The following code produces different results on a comparison.
The problem is in fitnessCompare; it looks like one of the two operands has
float precision, while the other has real precision.

assembly dump:

08065710
<_D19travelling_salesman4mainFZv14fitnessCompareMFS19travelling_salesman10chromosomeS19travelling_salesman10chromosomeZb>:
 8065710:       55                      push   ebp
 8065711:       8b ec                   mov    ebp,esp
 8065713:       83 ec 10                sub    esp,0x10
 8065716:       ff 75 14                push   DWORD PTR [ebp+0x14]
 8065719:       ff 75 10                push   DWORD PTR [ebp+0x10]
 806571c:       e8 27 00 00 00          call   8065748
<_D19travelling_salesman7fitnessFNaxS19travelling_salesman10chromosomeZf>
 8065721:       ff 75 0c                push   DWORD PTR [ebp+0xc]
 8065724:       ff 75 08                push   DWORD PTR [ebp+0x8]
 8065727:       d9 5d f0                fstp   DWORD PTR [ebp-0x10]
 806572a:       e8 19 00 00 00          call   8065748
<_D19travelling_salesman7fitnessFNaxS19travelling_salesman10chromosomeZf>
 806572f:       d9 45 f0                fld    DWORD PTR [ebp-0x10]
 8065732:       d9 c9                   fxch   st(1)
 8065734:       de d9                   fcompp
 8065736:       df e0                   fnstsw ax
 8065738:       9e                      sahf
 8065739:       b8 01 00 00 00          mov    eax,0x1
 806573e:       7a 02                   jp     8065742
<_D19travelling_salesman4mainFZv14fitnessCompareMFS19travelling_salesman10chromosomeS19travelling_salesman10chromosomeZb+0x32>
 8065740:       72 02                   jb     8065744
<_D19travelling_salesman4mainFZv14fitnessCompareMFS19travelling_salesman10chromosomeS19travelling_salesman10chromosomeZb+0x34>
 8065742:       31 c0                   xor    eax,eax
 8065744:       c9                      leave
 8065745:       c2 10 00                ret    0x10



actual code:



import std.stdio;  
import std.random;
import std.array;
import std.math;

struct city{
    int x;
    int y;
}

struct chromosome{
    city[] dna;
}    

void main(){
    bool fitnessCompare(chromosome first,chromosome second){ 
        return fitness(first)>fitness(second);
    }
    auto less = &fitnessCompare;
    auto z = chromosome([city(0, 10), city(25, 25), city(10, 65), city(50, 50),
city(75, 30), city(20, 0)]);
    auto f = fitness(z); 
    writeln("fitness(z) > fitness(z) ?",f > f);
    writeln("fitness(z) > fitness(z) ?",less(z,z));
}

float fitness(const chromosome victim) pure{
    const city[] cities=city(0,0) ~ victim.dna ~ city(0,0);

    //we need to start from home and return to home

    float travelled=0f;
    for(int x=0;x<cities.length-1;x++)
        travelled+=distance(cities[x],cities[x+1]);
    //writeln(100/travelled);
    return 100/travelled;
}

float distance(city from,city to) pure{
    return sqrt(cast(float)(pow(to.x-from.x,2) + pow(to.y-from.y,2)));
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 30 2012
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla digitalmars.com



14:44:36 PDT ---
I'm not sure what the issue is here. Can you point to what you think it should
be doing?

Also, the compiler is allowed to not truncate reals to floats when doing
comparisons, even if it is typed as a float. This is a feature, not a bug. The
compiler is always allowed to use a higher precision for intermediate
calculations than the source is typed.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 30 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476


bearophile_hugs eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs eml.cc





 The compiler is always allowed to use a higher precision
 for intermediate calculations than the source is typed.
A disadvantage of this is loss of floating point reproducibility across compilers, maybe similar to using the "-ffast-math" of GCC. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 30 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476




16:09:48 PDT ---

 I'm not sure what the issue is here. Can you point to what you think it should
 be doing?
 
 Also, the compiler is allowed to not truncate reals to floats when doing
 comparisons, even if it is typed as a float. This is a feature, not a bug. The
 compiler is always allowed to use a higher precision for intermediate
 calculations than the source is typed.
my diagnosis is probably wrong, but writeln("fitness(z) > fitness(z) ?",f > f); writeln("fitness(z) > fitness(z) ?",less(z,z)); are printing out different results when they should be printing the same thing. dmd 2.059, 32 bit only. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 30 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476




20:58:21 PDT ---
f is of type float.

z is of type chromosome.

Where are they the same types?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 30 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476




21:00:54 PDT ---


 
 The compiler is always allowed to use a higher precision
 for intermediate calculations than the source is typed.
A disadvantage of this is loss of floating point reproducibility across compilers, maybe similar to using the "-ffast-math" of GCC.
D made the decision early on that: more precision == better and that any program that relied on results being less accurate was a faulty program. Use of float should be for: 1. speed 2. less memory consumption and *never* for reduced precision. float guarantees a *minimum* precision, not a maximum. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 30 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476






 D made the decision early on that:
 
     more precision == better
 
 and that any program that relied on results being less accurate was a faulty
 program.
You are right, of course, and such problems are common: http://www.parashift.com/c++-faq-lite/floating-point-arith2.html On the other hand I remember one of my D programs not being as efficient as a very similar C++ program just because the C++ code used float-based operations instead of double-based ones, despite me typing float every FP variable and tagging with "f" every floating point literal. In some cases std.math return a double even if all it's required is a float, and the useless computation of the extra precision slows down the code compared to the C++ code that uses functions that return only a float precision. I presume the float versions of some functions perform less iterations to compute the smaller number of precision digits, and this makes them faster. And in some way std.math was unable to let me use the faster float version. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 31 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476




17:16:10 PDT ---
Alright, let's try this again, except with me being comprehensible this time.

There is one thing happening here, and that is 

float f;
...
bool result = f < f;

It is happening in two places: main, and main.fitnessCompare. In both places, f
has the same value (4.2 or something). In both places, f is the result of the
pure function fitness.

result should always be false for a non-{nan, inf, other floating point
screwball}

In main.fitnessCompare, result is true. This is wrong.

Running the debugger, it appeared to me that one of the two operands to the
floating point compare in main.fitnessCompare had 80 bits of precision, while
the other only had 64 (or maybe 64 and 32, I don't remember).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 15 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476


Maxim Fomin <maxim maxim-fomin.ru> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra gmail.com



---
*** Issue 8745 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 16 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476


Maxim Fomin <maxim maxim-fomin.ru> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |maxim maxim-fomin.ru



---
Regardless of whether (when comparing floats with reals) compiler should
compare with full or truncated to smaller type precision, current behavior
seems to be inconsistent with spec. According to the spec in section "Equality
Expressions" floating point types are compared bitwise. This means that if two
floats are compared, compiler need not care about extra precision but currently
it compares 32 bit with 80 bit (issue is better revealed in 8745). 

But if this is feature and not a bug, spec should be changed and better explain
the issue.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 16 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8476


Vladimir Panteleev <thecybershadow gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |thecybershadow gmail.com



10:05:10 EEST ---
*** Issue 10187 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 28 2013