Bug 29335

Summary: transcendental functions with constant arguments should be resolved at compile-time
Product: gcc Reporter: Kaveh Ghazi <ghazi>
Component: middle-endAssignee: Kaveh Ghazi <ghazi>
Status: RESOLVED FIXED    
Severity: enhancement CC: gcc-bugs, jackie.rosen, kargl, pinskia, rguenth, vincent-gcc
Priority: P3 Keywords: missed-optimization
Version: 4.2.0   
Target Milestone: 4.3.0   
Host: Target:
Build: Known to work: 4.3.0
Known to fail: Last reconfirmed: 2006-10-05 05:11:01
Bug Depends on:    
Bug Blocks: 30250, 30251, 31796    

Description Kaveh Ghazi 2006-10-03 16:48:18 UTC
We should use GMP/MPFR from inside builtins.c to resolve things like e.g. cos(0.12345) at compile-time.

Need to figure out:

1.  Whether a certain minimum version of GMP/MPFR is required to avoid known bugs, etc.

2.  Whether we should include GMP/MPFR in the svn archive like we do for intl and zlib.

3.  Whether GMP/MPFR works on all the platforms/configurations that GCC supports.  Are we ready to require a GMP/MPFR port for every port of GCC?

4.  If we don't do #2 and there is no system GMP/MPFR or the system lib is too old, or if we trip over #3 and can't have GMP/MPFR, then what?  Do we require the user to go get/port it, or silently eliminate this optimization during the build process?
Comment 1 Andrew Pinski 2006-10-05 05:11:01 UTC
Confirmed.
> 3.  Whether GMP/MPFR works on all the platforms/configurations that GCC
> supports.  Are we ready to require a GMP/MPFR port for every port of GCC?
As far as I know there is GMP port to all hosts that support GCC and nobody has complained they cannot use gfortran because GMP was not ported yet.
Comment 2 kargl 2006-10-05 17:54:24 UTC
(In reply to comment #0)
> 
> 1.  Whether a certain minimum version of GMP/MPFR is required to avoid known
> bugs, etc.

See my recent patch to toplevel configure.in.  THe minimum required 
versions should be gmp-4.1.x and mpfr-2.2.0.

> 2.  Whether we should include GMP/MPFR in the svn archive like we do for intl
> and zlib.

I think that gmp and mpfr would need to be imported into GCC.  If you read the
gmp webpage, it often contains warnings about using newer versions of GCC to 
gmp because of bugs.

> 3.  Whether GMP/MPFR works on all the platforms/configurations that GCC
> supports.  Are we ready to require a GMP/MPFR port for every port of GCC?
> 
> 4.  If we don't do #2 and there is no system GMP/MPFR or the system lib is too
> old, or if we trip over #3 and can't have GMP/MPFR, then what?  Do we require
> the user to go get/port it, or silently eliminate this optimization during the
> build process?

I could be mistaken, but I believe one can configure gmp for a generic library
that does not use any machine (ie., cpu) specific assembly.

If you haven't read fortran/{arith.c,simplify.c}, then I'd suggest
that you take a look to see what gmp/mpfr can do.
Comment 3 Kaveh Ghazi 2006-10-06 13:25:12 UTC
(In reply to comment #2)
> (In reply to comment #0)
> > 
> > 1.  Whether a certain minimum version of GMP/MPFR is required to avoid known
> > bugs, etc.
> See my recent patch to toplevel configure.in.  THe minimum required 
> versions should be gmp-4.1.x and mpfr-2.2.0.

I see that, but when configure detects the "broken" mpfr, it just prints out a message and proceeds happily.  It doesn't disable anything. (???)

> If you haven't read fortran/{arith.c,simplify.c}, then I'd suggest
> that you take a look to see what gmp/mpfr can do.

I looked through those and read through the mpfr docs so I think I have a good idea of what mpfr can do.  My main area of concern right now is converting between gcc's REAL_VALUE_TYPE and mpfr_t.  I found gfc_conv_mpfr_to_tree() in trans-const.c which uses a string as an intermediate type, is that the most efficient way to convert?  Also where is the function that does the reverse, i.e. tree or REAL_VALUE_TYPE to mpfr_t?
Comment 4 kargl 2006-10-06 14:40:48 UTC
(In reply to comment #3)
> (In reply to comment #2)
>> (In reply to comment #0)
>>> 
>>> 1.  Whether a certain minimum version of GMP/MPFR is required to
>>> avoid known bugs, etc.
>> See my recent patch to toplevel configure.in.  THe minimum required 
>> versions should be gmp-4.1.x and mpfr-2.2.0.
> 
> I see that, but when configure detects the "broken" mpfr, it just prints
> out a message and proceeds happily.  It doesn't disable anything. (???)

It's simply a warning to a user that there are known problems with the
version of MPFR on the system.  gfortran will work correctly with the
buggy mpfr with the exception of some corner cases and PRs that I've
fixed using newer features.  In particular, there are problems with
the old hackish way that gfortran handled subnormal numbers.  gfortran
also uses functions that are in 2.2.0 that are not available in some
of the older versions.

See simplify.c(gfc_simplify_nearest).

>> If you haven't read fortran/{arith.c,simplify.c}, then I'd suggest
>> that you take a look to see what gmp/mpfr can do.
> 
> I looked through those and read through the mpfr docs so I think I have a good
> idea of what mpfr can do.  My main area of concern right now is converting
> between gcc's REAL_VALUE_TYPE and mpfr_t.  I found gfc_conv_mpfr_to_tree() in
> trans-const.c which uses a string as an intermediate type, is that the most
> efficient way to convert?

I didn't write that function, and so I have experimented with a replacement.
There is mpfr_get_ld(), which converts to a long double.  If the data type
never exceeds the properties of long double, then one may be able to
use mpfr_get_ld() and then fold_convert() the result to the proper type.

> Also where is the function that does the reverse,
> i.e. tree or REAL_VALUE_TYPE to mpfr_t?

gfortran doesn't have a need of going in the opposite direction.
gmp/mpfr are used in the frontend for the internal representation
of data types.  By the time gfortran reaches the functions in
trans-*.c, it has done all the constant folding and manipulation
of the data types that it can.  The trans-*.c functions simply
convert gfortran's black and red trees into the tree-ssa form.

Comment 5 Kaveh Ghazi 2006-10-06 15:36:42 UTC
(In reply to comment #4)
> (In reply to comment #3)
> > (In reply to comment #2)
> >> (In reply to comment #0)
> >>> 
> > idea of what mpfr can do.  My main area of concern right now is converting
> > between gcc's REAL_VALUE_TYPE and mpfr_t.  I found gfc_conv_mpfr_to_tree() in
> > trans-const.c which uses a string as an intermediate type, is that the most
> > efficient way to convert?
> I didn't write that function, and so I have experimented with a replacement.
> There is mpfr_get_ld(), which converts to a long double.  If the data type
> never exceeds the properties of long double, then one may be able to
> use mpfr_get_ld() and then fold_convert() the result to the proper type.

I think using long double defeats the whole purpose of using mpfr.  We're supposed to avoid relying on the properties of the host's floating point for cross-compilers where the target format is different.  Otherwise I could simply call out to e.g. cosl() on the host and avoid the whole mpfr thing (okay okay, assuming cosl() and the rest of c99 math functions exist... which they don't always, but my point about target long double remains.)

I was hoping there was an easy was to extract the exponent and mantissa from one of (REAL_VALUE_TYPE/mpft_t) and put them back into the other in a way that preserves everything clean in both directions.


> > Also where is the function that does the reverse,
> > i.e. tree or REAL_VALUE_TYPE to mpfr_t?
> gfortran doesn't have a need of going in the opposite direction.
> gmp/mpfr are used in the frontend for the internal representation
> of data types.  By the time gfortran reaches the functions in
> trans-*.c, it has done all the constant folding and manipulation
> of the data types that it can.  The trans-*.c functions simply
> convert gfortran's black and red trees into the tree-ssa form.

Okay I hacked up something in the other direction using strings again.  If someone comes up with something better, then great.  But it's not strictly necessary.  I can put the two conversion functions into real.[ch].

Comment 6 kargl 2006-10-06 17:03:16 UTC
> > There is mpfr_get_ld(), which converts to a long double.  If the data type
> > never exceeds the properties of long double, then one may be able to
> > use mpfr_get_ld() and then fold_convert() the result to the proper type.
> 
> I think using long double defeats the whole purpose of using mpfr.

It appears you misread what I wrote (or meant to write).  "If the data
type never exceeds the properties of long double"  applies to a cross
compiler as well where "data type" is on the target and "long double"
is on the host.  

>  We're
> supposed to avoid relying on the properties of the host's floating point for
> cross-compilers where the target format is different.

The host's long double is simply an intermediate representation of the
value.  It is the responsibility of the fold_convert to get the right
target representation.  This is no different than using strings as the
intermediate.
 
> I was hoping there was an easy was to extract the exponent and mantissa from
> one of (REAL_VALUE_TYPE/mpft_t) and put them back into the other in a way that
> preserves everything clean in both directions.

See trans-intrinsics.c (prepare_arg_info), although I'm get ready to submit
a patch that removes that function.

> > > Also where is the function that does the reverse,
> > > i.e. tree or REAL_VALUE_TYPE to mpfr_t?
> > gfortran doesn't have a need of going in the opposite direction.
> > gmp/mpfr are used in the frontend for the internal representation
> > of data types.  By the time gfortran reaches the functions in
> > trans-*.c, it has done all the constant folding and manipulation
> > of the data types that it can.  The trans-*.c functions simply
> > convert gfortran's black and red trees into the tree-ssa form.
> 
> Okay I hacked up something in the other direction using strings again.  If
> someone comes up with something better, then great.  But it's not strictly
> necessary.  I can put the two conversion functions into real.[ch].

I would be interested in seeing the functions because gfortran currently
can't constant fold a TRANSFER() of the form

real, parameter :: x = transfer(1234,x)

This is a bitwise copy of the integer 1234 into x.  In gfortran 1235 is
a gmp mpz_t type and x is an mpfr mpfr_t type.  Emulating the bitwise 
copy will require strings manipulations. 
Comment 7 Kaveh Ghazi 2006-10-07 02:04:49 UTC
(In reply to comment #6)
> > > There is mpfr_get_ld(), which converts to a long double.  If the data type
> > > never exceeds the properties of long double, then one may be able to
> > > use mpfr_get_ld() and then fold_convert() the result to the proper type.
> > 
> > I think using long double defeats the whole purpose of using mpfr.
> It appears you misread what I wrote (or meant to write).  "If the data
> type never exceeds the properties of long double"  applies to a cross
> compiler as well where "data type" is on the target and "long double"
> is on the host.  
> >  We're
> > supposed to avoid relying on the properties of the host's floating point for
> > cross-compilers where the target format is different.
> The host's long double is simply an intermediate representation of the
> value.  It is the responsibility of the fold_convert to get the right
> target representation.  This is no different than using strings as the
> intermediate.

I want the optimization to work always, not just in certain host/target combinations.  So I'll use strings, no big deal.
Comment 8 Kaveh Ghazi 2006-10-07 14:07:58 UTC
Patch posted here:
http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00360.html

Need to decide whether we're including GMP/MPFR in GCC repo or we need configure goo to detect if we have it.

Comment 9 Kaveh Ghazi 2006-10-09 17:16:29 UTC
I decided to explore including GMP/MPFR in the GCC tree.  Dependency PR 29405 opened to track that enhancement.
Comment 10 Kaveh Ghazi 2006-10-14 16:12:08 UTC
No longer relying on PR29405.  Instead we'll force the person building GCC to acquire GMP/MPFR themselves.
Comment 11 Kaveh Ghazi 2006-10-14 16:13:52 UTC
Updated patch posted here:
http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00757.html

Comment 12 Kaveh Ghazi 2006-10-20 15:53:59 UTC
Third patch revision posted here:
http://gcc.gnu.org/ml/gcc-patches/2006-10/msg01039.html

Comment 13 Kaveh Ghazi 2006-10-23 20:25:06 UTC
Subject: Bug 29335

Author: ghazi
Date: Mon Oct 23 20:24:55 2006
New Revision: 117983

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=117983
Log:
	PR middle-end/29335
	* builtins.c (fold_builtin_sin, fold_builtin_cos,
	fold_builtin_tan): Fold all constant arguments.  Take a "type"
	argument as necessary.
	(do_mpfr_arg1): New.
	* real.c, real.h (real_from_mpfr, mpfr_from_real): New.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/real.c
    trunk/gcc/real.h

Comment 14 Kaveh Ghazi 2006-10-24 17:44:51 UTC
Subject: Bug 29335

Author: ghazi
Date: Tue Oct 24 17:44:36 2006
New Revision: 118009

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=118009
Log:
	PR middle-end/29335
	* builtins.c (fold_builtin_sin, fold_builtin_atan): Remove.
	(do_mpfr_arg1): Add `min', `max' and `inclusive' arguments.
	Update all callers.
	(BUILT_IN_SIN, BUILT_IN_ATAN): Handle in main switch.
	(BUILT_IN_ASIN, BUILT_IN_ACOS, BUILT_IN_ATAN, BUILT_IN_ASINH,
	BUILT_IN_ACOSH, BUILT_IN_ATANH, BUILT_IN_SINH, BUILT_IN_COSH,
	BUILT_IN_TANH): Calculate compile-time arguments using MPFR.

testsuite:
	* gcc.dg/torture/builtin-math-3.c: New test.



Added:
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-3.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/testsuite/ChangeLog

Comment 15 Kaveh Ghazi 2006-10-25 20:44:20 UTC
Subject: Bug 29335

Author: ghazi
Date: Wed Oct 25 20:44:09 2006
New Revision: 118042

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=118042
Log:
	PR middle-end/29335
	* builtins.c (fold_builtin_cbrt, fold_builtin_logarithm):
	Calculate compile-time constants using MPFR.
	(fold_builtin_1): Likewise handle BUILT_IN_ERF, BUILT_IN_ERFC,
	BUILT_IN_EXPM1 and BUILT_IN_LOG1P.
	
testsuite:
	* gcc.dg/torture/builtin-math-2.c (TESTIT): Use new helper macro.
	Add checks for log, log2, log10 and log1p.

	* gcc.dg/torture/builtin-math-3.c: Add checks for -0.0 everywhere
	we already test 0.0.  Add checks for expm1, log, log2, log10,
	log1p, cbrt, erf and erfc.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-2.c
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-3.c

Comment 16 Kaveh Ghazi 2006-10-28 03:20:06 UTC
I'm getting wierd NaN results when I hook up __builtin_lgamma to mpfr_lngamma.  I can expose the problem using a standlone C program calling mpfr like so.  Results are first, C testcase is second.  Now I know lgamma/mpfr_lngamma are both documented to barf on negative integers.  But as you can see, I'm passing x.5 in every case.  Seems like any time "x" is an even number I get a NaN.  I wonder if this is a bug in mpfr, or my mistake?  (I tried mpfr-2.2.0 with and without the cumulative patch.  I got the problem in both cases.)  Can anyone else reproduce this?

lgamma(-4.50) = -2.813084
mpfr_lngamma(-4.50) = @NaN@

lgamma(-3.50) = -1.309007
mpfr_lngamma(-3.50) = -1.3090066849930420

lgamma(-2.50) = -0.056244
mpfr_lngamma(-2.50) = @NaN@

lgamma(-1.50) = 0.860047
mpfr_lngamma(-1.50) = 8.6004701537648098e-1

lgamma(-0.50) = 1.265512
mpfr_lngamma(-0.50) = @NaN@



#include <stdio.h>
#include <math.h>
#include <gmp.h>
#include <mpfr.h>

#define TESTIT(X) do { \
  printf ("lgamma(%.2f) = %f\n", (X), gamma(X)); \
  mpfr_set_d(m, (X), GMP_RNDN); \
  mpfr_lngamma(m, m, GMP_RNDN); \
  printf ("mpfr_lngamma(%.2f) = ", (X)); \
  mpfr_out_str (stdout, 10, 0, m, GMP_RNDN); \
  putc ('\n', stdout); \
  putc ('\n', stdout); \
} while (0)

int main()
{
  mpfr_t m;
  mpfr_init2(m, 53);

  TESTIT(-4.5);
  TESTIT(-3.5);
  TESTIT(-2.5);
  TESTIT(-1.5);
  TESTIT(-0.5);

  mpfr_clear(m);
  return 0;
}
Comment 17 Steve Kargl 2006-10-28 03:48:47 UTC
Subject: Re:  transcendental functions with constant arguments should be resolved at compile-time

On Sat, Oct 28, 2006 at 03:20:11AM -0000, ghazi at gcc dot gnu dot org wrote:
> 
> 
> ------- Comment #16 from ghazi at gcc dot gnu dot org  2006-10-28 03:20 -------
> I'm getting wierd NaN results when I hook up __builtin_lgamma to mpfr_lngamma. 
> I can expose the problem using a standlone C program calling mpfr like so. 
> Results are first, C testcase is second.  Now I know lgamma/mpfr_lngamma are
> both documented to barf on negative integers.  But as you can see, I'm passing
> x.5 in every case.  Seems like any time "x" is an even number I get a NaN.  I
> wonder if this is a bug in mpfr, or my mistake?  (I tried mpfr-2.2.0 with and
> without the cumulative patch.  I got the problem in both cases.)  Can anyone
> else reproduce this?
> 
> lgamma(-4.50) = -2.813084
> mpfr_lngamma(-4.50) = @NaN@
> 

Yes, I can reproduce the NaN.  In fact, any negative value 
gives a NaN.
Comment 18 Vincent Lefèvre 2006-10-28 09:07:20 UTC
(In reply to comment #17)
> Yes, I can reproduce the NaN.  In fact, any negative value 
> gives a NaN.

Not any negative value, but in lngamma.c:

  /* if x < 0 and -2k-1 <= x <= -2k, then lngamma(x) = NaN */

probably because the gamma value is negative. This is because MPFR defines lngamma as log(gamma(x)) while the C standard defines it as log|gamma(x)|. I wonder if this should be regarded as a bug or if a new function (say, mpfr_lgamma) should be defined in MPFR (in which case, not before 2.3.0). Do other standards (other languages) define such a function, either as log(gamma(x)) or as log|gamma(x)|?

Also, warning! The mpfr_erfc is incomplete for x >= 4096: There is an infinite loop in the 2.2 branch. This problem is now detected in the trunk, and until this is completely fixed, a NaN is returned with the MPFR erange flag set. This should be in the 2.2 branch in a few days (and a preversion of MPFR 2.2.1 will come several days after that).
Comment 19 Kaveh Ghazi 2006-10-28 13:28:55 UTC
(In reply to comment #18)
> (In reply to comment #17)
> > Yes, I can reproduce the NaN.  In fact, any negative value 
> > gives a NaN.
> Not any negative value, but in lngamma.c:
>   /* if x < 0 and -2k-1 <= x <= -2k, then lngamma(x) = NaN */
> probably because the gamma value is negative. This is because MPFR defines
> lngamma as log(gamma(x)) while the C standard defines it as log|gamma(x)|. I
> wonder if this should be regarded as a bug or if a new function (say,
> mpfr_lgamma) should be defined in MPFR (in which case, not before 2.3.0).

The documenation in MPFR says:
 -- Function: int mpfr_lngamma (mpfr_t ROP, mpfr_t OP, mp_rnd_t RND)
     Set ROP to the value of the Gamma function on OP, and its
     logarithm respectively, rounded in the direction RND.  When OP is
     a negative integer, NaN is returned.

It only talked about negative integers, and I glossed over the fact that it left out the absolute value that C does.  So it was pilot error, but I think a clarification would help.  Many times in the docs MPFR takes pains to follow the C99 standard, e.g. the inputs to atan2 or pow.  Where you deviate from it should also be noted. 

Or you could consider it a bug and fix it. :-)

Anyway, I think I can hand wrap mpfr_log(mpfr_abs(mpfr_gamma)) myself right?


> Also, warning! The mpfr_erfc is incomplete for x >= 4096: There is an infinite
> loop in the 2.2 branch. This problem is now detected in the trunk, and until
> this is completely fixed, a NaN is returned with the MPFR erange flag set. This
> should be in the 2.2 branch in a few days (and a preversion of MPFR 2.2.1 will
> come several days after that).

If it returns NaN for now that's fine since GCC avoids any transformation that returns NaN or Inf.

Glad to hear a new version is coming out.  If you make a prerelease tarball available somewhere I'd like to try it with mainline GCC.
Comment 20 Vincent Lefèvre 2006-10-28 14:05:51 UTC
(In reply to comment #19)
> The documenation in MPFR says:
>  -- Function: int mpfr_lngamma (mpfr_t ROP, mpfr_t OP, mp_rnd_t RND)
>      Set ROP to the value of the Gamma function on OP, and its
>      logarithm respectively, rounded in the direction RND.  When OP is
>      a negative integer, NaN is returned.
> 
> It only talked about negative integers,

AFAIK, this was mainly for Gamma(negative integer). But this is also true for lngamma(negative integer). But the point is that if gamma(x) is negative, then lngamma(x) is NaN since the logarithm of a negative value is NaN. But that's why the C standard defines lgamma as log|gamma(x)| instead of log(gamma(x)).

> and I glossed over the fact that it
> left out the absolute value that C does.  So it was pilot error, but I think a
> clarification would help.  Many times in the docs MPFR takes pains to follow
> the C99 standard, e.g. the inputs to atan2 or pow.  Where you deviate from it
> should also be noted.

I agree. And I think that none of the MPFR developers were aware of this problem (I didn't notice the difference when I was looking for C functions that were missing in MPFR). I posted a mail about that on the MPFR mailing-list.

> Or you could consider it a bug and fix it. :-)

I think this is the best solution, in particular because this would change only NaN values.

> Anyway, I think I can hand wrap mpfr_log(mpfr_abs(mpfr_gamma)) myself right?

Probably not a good idea, because I think that mpfr_gamma may overflow, though the final result may be in the double-precision range.

> Glad to hear a new version is coming out.  If you make a prerelease tarball
> available somewhere I'd like to try it with mainline GCC.

OK, I hope I won't forget to announce it in the gcc dev mailing-list.
Comment 21 Kaveh Ghazi 2006-10-28 16:03:56 UTC
(In reply to comment #20)
> I agree. And I think that none of the MPFR developers were aware of this
> problem (I didn't notice the difference when I was looking for C functions
> that were missing in MPFR). 

Since you mentioned C functions missing in MPFR, what are your plans for the Bessel functions?  I'd like to hook up builtins j0/j1/jn/y0/y1/yn.  Thanks.

Comment 22 Vincent Lefèvre 2006-10-28 16:58:12 UTC
(In reply to comment #21)
> Since you mentioned C functions missing in MPFR, what are your plans for the
> Bessel functions?  I'd like to hook up builtins j0/j1/jn/y0/y1/yn.  Thanks.

They're in the TODO, but there are no plans yet to implement them.
Comment 23 Kaveh Ghazi 2006-10-29 02:02:23 UTC
Subject: Bug 29335

Author: ghazi
Date: Sun Oct 29 02:02:10 2006
New Revision: 118129

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=118129
Log:
	PR middle-end/29335
	* builtins.c (do_mpfr_arg2, fold_builtin_hypot): New.
	(fold_builtin_pow): Evaluate constant arguments at compile-time
	using MPFR.
	(fold_builtin_1): Handle BUILT_IN_ATAN2 and BUILT_IN_HYPOT.
	(do_mpfr_ckconv): New helper function.
	(do_mpfr_arg1): Use do_mpfr_ckconv.
	(do_mpfr_arg2): New.

testsuite:
	* gcc.dg/builtins-20.c: Add tests for hypot.
	* gcc.dg/torture/builtin-math-2.c (TESTIT2): New.  Add tests for
	two-argument builtins.
	* gcc.dg/torture/builtin-math-3.c (TESTIT_R): Renamed from
	TESTIT2.  Update all callers.
	(TESTIT2, TESTIT2_R): New helper macros.
	Add testcases for pow, hypot and atan2.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gcc.dg/builtins-20.c
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-2.c
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-3.c

Comment 24 Kaveh Ghazi 2006-10-30 20:22:20 UTC
Subject: Bug 29335

Author: ghazi
Date: Mon Oct 30 20:21:59 2006
New Revision: 118200

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=118200
Log:
	PR middle-end/29335
	* builtins.c (fold_builtin_1): Evaluate tgamma using MPFR.

testsuite:
	* gcc.dg/torture/builtin-math-2.c: Add tgamma tests.
	* gcc.dg/torture/builtin-math-3.c: Likewise.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-2.c
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-3.c

Comment 25 Kaveh Ghazi 2006-10-31 03:14:20 UTC
(In reply to comment #18)
> (In reply to comment #17)
> This is because MPFR defines
> lngamma as log(gamma(x)) while the C standard defines it as log|gamma(x)|. I
> wonder if this should be regarded as a bug or if a new function (say,
> mpfr_lgamma) should be defined in MPFR (in which case, not before 2.3.0). Do
> other standards (other languages) define such a function, either as
> log(gamma(x)) or as log|gamma(x)|?

As I think about it more, I'm leaning toward having a new function mpfr_lgamma.  This is because if we want this mpfr function to mimic the behavior of lgamma, we need some mechanism to retrieve the value of "signgam".  So maybe the interface you suggested at the bottom of this link would be best where we retrieve an int* from mpfr_lgamma to determine "signgam":
http://sympa.loria.fr/wwsympa/arc/mpfr/2006-10/msg00033.html

Comment 26 Vincent Lefèvre 2006-10-31 09:54:52 UTC
(In reply to comment #25)
> As I think about it more, I'm leaning toward having a new function mpfr_lgamma.
>  This is because if we want this mpfr function to mimic the behavior of lgamma,
> we need some mechanism to retrieve the value of "signgam".  So maybe the
> interface you suggested at the bottom of this link would be best where we
> retrieve an int* from mpfr_lgamma to determine "signgam":
> http://sympa.loria.fr/wwsympa/arc/mpfr/2006-10/msg00033.html

Yes, it's true that it is useful to have this value. But determining it separately is quite easy, without taking a noticeable additional time in average.
Comment 27 Kaveh Ghazi 2006-10-31 20:08:50 UTC
(In reply to comment #26)
> Yes, it's true that it is useful to have this value. But determining it
> separately is quite easy, without taking a noticeable additional time in
> average.

It's likely that I'll end up doing it, so would you please tell me how?
Thanks.
Comment 28 Vincent Lefèvre 2006-10-31 22:15:18 UTC
(In reply to comment #27)
> It's likely that I'll end up doing it, so would you please tell me how?

According to the C rationale (I haven't checked), the sign of gamma(x) is -1 if [iff] x < 0 && remainder(floor(x), 2) != 0. But if x is a non-positive integer, the sign of gamma(x) isn't defined. Handle these cases first.

The test x < 0 is easy to do. In MPFR, you can compute floor(x) (or trunc(x)) with the precision min(PREC(x),max(EXP(x),MPFR_PREC_MIN)), but then, there's no direct function to decide whether the result is even or odd (I thought we added this, but this isn't the case). The solution can be to divide x by 2 (this is exact, except in case of underflow) and call mpfr_frac directly. If the result is between -0.5 and 0, then gamma(x) is negative. If the result is between -1 and -0.5, then gamma(x) is positive. So, a 2-bit precision for mpfr_frac should be sufficient (as -0.5 is representable in this precision), but choose a directed rounding (not GMP_RNDN) for that. Then you can just do a comparison with -0.5; the case of equality with -0.5 depends on the chosen rounding (if you obtain -0.5, then it is an inexact result since x is not an integer). For instance, if you choose GMP_RNDZ, then a result > -0.5 means that gamma(x) is negative, and a result <= -0.5 means that gamma(x) is positive.
Comment 29 Kaveh Ghazi 2006-11-02 03:21:00 UTC
Subject: Bug 29335

Author: ghazi
Date: Thu Nov  2 03:20:49 2006
New Revision: 118409

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=118409
Log:
	PR middle-end/29335
	* builtins.c (do_mpfr_sincos): New.
	(fold_builtin_1): Use it to fold builtin sincos.

testsuite:
	* gcc.dg/torture/builtin-math-3.c: Fix semicolons.
	(TESTIT_2P, TESTIT_2P_R): New macros.  Test sincos.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-3.c

Comment 30 Kaveh Ghazi 2006-11-02 14:41:29 UTC
(In reply to comment #28)
> (In reply to comment #27)
> > It's likely that I'll end up doing it, so would you please tell me how?
> According to the C rationale (I haven't checked), the sign of gamma(x) is -1 if
> [iff] x < 0 && remainder(floor(x), 2) != 0. But if x is a non-positive integer,
> the sign of gamma(x) isn't defined. Handle these cases first.
> The test x < 0 is easy to do. In MPFR, you can compute floor(x) (or trunc(x))
> with the precision min(PREC(x),max(EXP(x),MPFR_PREC_MIN)), but then, there's no
> direct function to decide whether the result is even or odd (I thought we added
> this, but this isn't the case). The solution can be to divide x by 2 (this is
> exact, except in case of underflow) and call mpfr_frac directly. If the result
> is between -0.5 and 0, then gamma(x) is negative. If the result is between -1
> and -0.5, then gamma(x) is positive. So, a 2-bit precision for mpfr_frac should
> be sufficient (as -0.5 is representable in this precision), but choose a
> directed rounding (not GMP_RNDN) for that. Then you can just do a comparison
> with -0.5; the case of equality with -0.5 depends on the chosen rounding (if
> you obtain -0.5, then it is an inexact result since x is not an integer). For
> instance, if you choose GMP_RNDZ, then a result > -0.5 means that gamma(x) is
> negative, and a result <= -0.5 means that gamma(x) is positive.

Vincent, thank you for the detailed instructions.  I also read your two possible solutions posted here:
http://sympa.loria.fr/wwsympa/arc/mpfr/2006-10/msg00036.html

I could be satisfied with either solution from that message.  However in the case of choice 1, I feel the calculation of signgam should be provided from a function call in the library rather than forcing each user to write a routine to calculate it.  IMHO, I'd rather leave the math to the mathematicians. :-)  E.g. you could add a function mpfr_signgam() that figures out the value for the user and thereby leave the interface for mpfr_lngamma() unchanged.  Choice 2 also solves the issue by providing the int* parameter.

Thanks.
Comment 31 Vincent Lefèvre 2006-11-02 15:57:16 UTC
(In reply to comment #30)

So, I don't think a mpfr_signgam alone would really be useful. So, I think that choice 2 would be better.
Comment 32 Kaveh Ghazi 2006-11-02 22:44:07 UTC
(In reply to comment #31)
> (In reply to comment #30)
> So, I don't think a mpfr_signgam alone would really be useful. So, I think that
> choice 2 would be better.

Okay, sounds fine.  Would this make it into 2.2.1 or 2.3?  And do you have any very rough timeframe for each release so I can plan accordingly for gcc?
Thanks.
Comment 33 Vincent Lefèvre 2006-11-05 23:27:40 UTC
(In reply to comment #32)
> (In reply to comment #31)
> > (In reply to comment #30)
> > So, I don't think a mpfr_signgam alone would really be useful. So, I think that
> > choice 2 would be better.
> 
> Okay, sounds fine.  Would this make it into 2.2.1 or 2.3?

For compatibility reasons (i.e. the 2.2.x versions must have the same interface), this can only be in 2.3.0.

> And do you have any very rough timeframe for each release so I can plan
> accordingly for gcc?

A pre-release of 2.2.1 should be there soon; there are still bugs being fixed (they will be ported to the 2.2 branch once this is complete).

I don't know about 2.3.0; probably in a few months, because there currently aren't many differences from the 2.2 branch.
Comment 34 Kaveh Ghazi 2006-11-07 02:46:31 UTC
(In reply to comment #33)
> > Okay, sounds fine.  Would this make it into 2.2.1 or 2.3?
> For compatibility reasons (i.e. the 2.2.x versions must have the same
> interface), this can only be in 2.3.0.
> > And do you have any very rough timeframe for each release so I can plan
> > accordingly for gcc?
> A pre-release of 2.2.1 should be there soon; there are still bugs being fixed
> (they will be ported to the 2.2 branch once this is complete).
> I don't know about 2.3.0; probably in a few months, because there currently
> aren't many differences from the 2.2 branch.

Well, maybe if the Bessel functions were added to 2.3.0 it would be sufficiently different from 2.2.x to warrent a release.  See comment#22.  :-)
Comment 35 Kaveh Ghazi 2006-12-18 14:53:55 UTC
Mine, obviously.  

Almost done, targetted to gcc-4.3.

Comment 36 Kaveh Ghazi 2006-12-26 19:03:28 UTC
Subject: Bug 29335

Author: ghazi
Date: Tue Dec 26 19:03:17 2006
New Revision: 120211

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=120211
Log:
	PR middle-end/29335
	* builtins.c (do_mpfr_arg1, do_mpfr_arg2, do_mpfr_arg3,
	do_mpfr_sincos): Ensure target base equals two.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c

Comment 37 Kaveh Ghazi 2006-12-26 19:13:25 UTC
Done.

Remaining functions (Bessel & lgamma) await implementation in MPFR and marked for PR30250 & PR30251.
Comment 38 Kaveh Ghazi 2007-01-20 00:33:10 UTC
Subject: Bug 29335

Author: ghazi
Date: Sat Jan 20 00:33:00 2007
New Revision: 120993

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=120993
Log:
	PR middle-end/29335
	* builtins.c (fold_builtin_1): Handle builtin fdim.

testsuite:
	* gcc.dg/torture/builtin-math-3.c: Test fdim.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-3.c

Comment 39 Kaveh Ghazi 2007-01-31 15:06:37 UTC
Subject: Bug 29335

Author: ghazi
Date: Wed Jan 31 15:06:19 2007
New Revision: 121423

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=121423
Log:
	PR middle-end/29335
	* builtins.c (fold_builtin_sqrt): Use MPFR for constant args.

testsuite:
	* gcc.dg/torture/builtin-math-2.c: Add sqrt cases.
	* gcc.dg/torture/builtin-math-3.c: Likewise.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-2.c
    trunk/gcc/testsuite/gcc.dg/torture/builtin-math-3.c

Comment 40 Jackie Rosen 2014-02-16 10:00:22 UTC
*** Bug 260998 has been marked as a duplicate of this bug. ***
Seen from the domain http://volichat.com
Marked for reference. Resolved as fixed @bugzilla.