Bug 10644 - float calculation exceeds representation max, only when optimizer is turned on
Summary: float calculation exceeds representation max, only when optimizer is turned on
Status: RESOLVED DUPLICATE of bug 323
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 3.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2003-05-06 16:46 UTC by bird
Modified: 2003-07-06 19:11 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
factorial.cpp (358 bytes, text/x-c++ )
2003-05-21 15:17 UTC, bird
Details

Note You need to log in before you can comment on or make changes to this bug.
Description bird 2003-05-06 16:46:00 UTC
#include <iostream>			// ostream
#include <limits>		      	// numeric_limits<T>::max
using namespace std; 

// -------------------------------------------------------------------
template<class T>			    // T = double or float
static T factorial(T value)
{
    T fact = 1.0;
    while (value > 1.0) 
        fact *= value--;	
    return fact;
}

// -------------------------------------------------------------------
template<class T>			// T = double or float
static void test(T)
{
    cout << "representation max = " << numeric_limits<T>::max() << "\n\n";

    cout << "factorial(34) = "<< factorial(T(34)) << endl;	
    cout << "factorial(35) = " << factorial(T(35)) << endl;	
    cout << "factorial(170) = " << factorial(T(170)) << endl;	
    cout << "factorial(171) = " << factorial(T(171)) << "\n\n";	
}

// -------------------------------------------------------------------
int main()
{
    cout << "factorial limits for floats:\n";
    test((float)0);
    cout << "factorial limits for doubles:\n";
    test((double)0);
    return 0;
}

Release:
gcc version 3.2.3 (also 3.2.1 and 3.2)

Environment:
Red Hat Linux 7.2, kernel 2.4.18, on Pentium IV

How-To-Repeat:
The code explores the range of the factorial function for floats vs doubles.  When run without optimization:
    g++-3.2  factorial.cpp -o test
the code correctly outputs "inf" for arguments > 34 for float instantiation, and "inf" for arguments > 170 for double.

When any optimization level is used, say:
    g++-3.2  -O3 factorial.cpp -o test
the double output remains the same, but factorial(float 35) and factorial(float 170) now give incorrect results.  Specifically, the float instantiation returns values 1.03331e+40 for 35! and 7.25742e+306 for 170! which are more than the max float = 2.95233e+38.
Comment 1 bird 2003-05-06 16:46:00 UTC
Fix:
If I add code to factorial such as:
    T fact = 1.0;
    ostringstream ist;		
    ist <<  fact;	
the program produces correct answers even with optimization turned on.  However, this slows down the processing time for the factorial routine (and shouldn't be necessary).
Comment 2 tprince 2003-05-06 18:09:19 UTC
From: "Timothy C Prince" <tprince@myrealbox.com>
To: bird@bainet.com
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: optimization/10644: float calculation exceeds representation max, only when optimizer is turned on 
Date: Tue, 06 May 2003 18:09:19 +0000

 -----Original Message-----
 From: bird@bainet.com
 To: gcc-gnats@gcc.gnu.org
 Date: 6 May 2003 16:38:32 -0000
 Subject: optimization/10644: float calculation exceeds representation max, =
 only when optimizer is turned on=20
 
 
 >Number:         10644
 >Category:       optimization
 >Synopsis:       float calculation exceeds representation max, only when op=
 timizer is turned on
 >Confidential:   no
 >Severity:       non-critical
 >Priority:       medium
 >Responsible:    unassigned
 >State:          open
 >Class:          wrong-code
 >Submitter-Id:   net
 >Arrival-Date:   Tue May 06 16:46:00 UTC 2003
 >Closed-Date:
 >Last-Modified:
 >Originator:     Rebecca Bird
 >Release:        gcc version 3.2.3 (also 3.2.1 and 3.2)
 >Organization:
 >Environment:
 Red Hat Linux 7.2, kernel 2.4.18, on Pentium IV
 >Description:
 #include <iostream>=09=09=09// ostream
 #include <limits>=09=09      =09// numeric_limits<T>::max
 using namespace std;=20
 
 // -------------------------------------------------------------------
 template<class T>=09=09=09    // T =3D double or float
 static T factorial(T value)
 {
     T fact =3D 1.0;
     while (value > 1.0)=20
         fact *=3D value--;=09
     return fact;
 }
 
 // -------------------------------------------------------------------
 template<class T>=09=09=09// T =3D double or float
 static void test(T)
 {
     cout << "representation max =3D " << numeric_limits<T>::max() << "\n\n"=
 ;
 
     cout << "factorial(34) =3D "<< factorial(T(34)) << endl;=09
     cout << "factorial(35) =3D " << factorial(T(35)) << endl;=09
     cout << "factorial(170) =3D " << factorial(T(170)) << endl;=09
     cout << "factorial(171) =3D " << factorial(T(171)) << "\n\n";=09
 }
 
 // -------------------------------------------------------------------
 int main()
 {
     cout << "factorial limits for floats:\n";
     test((float)0);
     cout << "factorial limits for doubles:\n";
     test((double)0);
     return 0;
 }
 >How-To-Repeat:
 The code explores the range of the factorial function for floats vs doubles=
 .  When run without optimization:
     g++-3.2  factorial.cpp -o test
 the code correctly outputs "inf" for arguments > 34 for float instantiation=
 , and "inf" for arguments > 170 for double.
 
 When any optimization level is used, say:
     g++-3.2  -O3 factorial.cpp -o test
 the double output remains the same, but factorial(float 35) and factorial(f=
 loat 170) now give incorrect results.  Specifically, the float instantiat=
 ion returns values 1.03331e+40 for 35! and 7.25742e+306 for 170! which ar=
 e more than the max float =3D 2.95233e+38.
 
 >Fix:
 If I add code to factorial such as:
     T fact =3D 1.0;
     ostringstream ist;=09=09
     ist <<  fact;=09
 the program produces correct answers even with optimization turned on.  How=
 ever, this slows down the processing time for the factorial routine (and =
 shouldn't be necessary).
 >Release-Note:
 >Audit-Trail:
 >Unformatted:
 ----gnatsweb-attachment----
 Content-Type: text/plain; name=3D"factorial.cpp"
 Content-Disposition: inline; filename=3D"factorial.cpp"
 
 // Show limits of factorial routine for floats vs doubles
 
 #include <iostream>=09=09=09// ostream
 #include <limits>=09=09=09// numeric_limits<T>::max
 using namespace std;=20
 
 // -------------------------------------------------------------------
 template<class T>=09=09=09// T =3D double or float
 static T factorial(T value)
 {
 =09T fact =3D 1.0;
 =09while (value > 1.0)=20
 =09=09fact *=3D value--;=09
 =09return fact;
 }
 
 // -------------------------------------------------------------------
 template<class T>=09=09=09// T =3D double or float
 static void test(T)
 {
 =09cout << "representation max =3D " << numeric_limits<T>::max() << "\n\n";
 
 =09cout << "factorial(34) =3D "<< factorial(T(34)) << endl;=09
 =09cout << "factorial(35) =3D " << factorial(T(35)) << endl;=09
 =09cout << "factorial(170) =3D " << factorial(T(170)) << endl;=09
 =09cout << "factorial(171) =3D " << factorial(T(171)) << "\n\n";=09
 }
 
 // -------------------------------------------------------------------
 int main()
 {
 =09cout << "factorial limits for floats:\n";
 =09test((float)0);
 =09cout << "factorial limits for doubles:\n";
 =09test((double)0);
 =09return 0;
 }
 
 
 The results with -march=3Dpentium4 -mfpmath=3Dsse might be more to your lik=
 ing.
 
 Tim Prince
Comment 3 Christian Ehrhardt 2003-05-06 21:09:15 UTC
State-Changed-From-To: open->closed
State-Changed-Why: Not a Bug. If you want exact floating point behaviour use -ffloat-store
    which fixes your problem. If you don't do this gcc will happily do your
    calculations at higher precision if that helps optimization.
Comment 4 Andrew Pinski 2003-07-06 19:11:00 UTC
Reopening bug so I can mark it as a dup of ....
Comment 5 Andrew Pinski 2003-07-06 19:11:52 UTC
bug 323, which is the master bug for excessive precision.

*** This bug has been marked as a duplicate of 323 ***