C23 added the sinpi, cospi, etc. functions. Therefore, MPFR in 4.2.0
added the mpfr_ counter parts. I assume that those internally use the
mpfr_sinu, mpfr_cosu, ... functions, which are also user accessible.

In any case, MPFR makes the ...u functions available and explicitly
documents that for u = 360, the mpfr_...u functions permits to use
angles in degree instead of rad.

Fortran 2023 added degree trigonometric functions, which gfortran already
supports. Thus:

The attach patch switches to the mpfr_...u functions for the degree
variant if MPFR 4.2.0, but keeps the fallback for older MPFR versions.

[Currently, GCC requires MPFR 3.1 or newer for build. (MPFR 4.2.0 was
releasedJanuary 2023.) We already did likewise in the past: Making
conditionally use of newer MPFR functions, if available, but have a
fallback until the minimal MPFR version is increased. (The last such
code was removed 2008 as then MPFR >= 3.1.0 was the new minimal
version and all of MPFR is currently used unconditionally.)]


Bootstrapped and regtested on x86_64-gnu-linux with MPFR 4.2.2 (the latest).
OK for mainline?

Tobias

PS: I see gfortran.dg/specifics_1.f90 fails for -O2 and higher, but not
due to this patch → https://gcc.gnu.org/PR120099 (opened on Apr 2025)
Fortran: Use mpfr_sinu etc. with mpfr 4.2.0+ for degree trigonometric functions [PR120225]

As MPFR 4.2.0 added, support for degree trigonometric functions by via the
mpfr_...u functions (for u = 360), it makes sense to use them if available.
If MPFR is older, the current implementation is used as fallback.

	PR fortran/120225

gcc/fortran/ChangeLog:

	* simplify.cc Include "trigd_fe.inc" only with MPFR < 4.2.0
	(rad2deg, rad2deg): Only define if MPFR < 4.2.0.
	(gfc_simplify_acosd, gfc_simplify_asind, gfc_simplify_atand,
	gfc_simplify_atan2d, gfc_simplify_cosd, gfc_simplify_tand,
	gfc_simplify_cotand): Use mpfr_...u functions with MPFR >= 4.2.0.

 gcc/fortran/simplify.cc | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc
index 208251b5ec5..79701be839d 100644
--- a/gcc/fortran/simplify.cc
+++ b/gcc/fortran/simplify.cc
@@ -1183,6 +1183,7 @@ gfc_simplify_asin (gfc_expr *x)
 }
 
 
+#if MPFR_VERSION < MPFR_VERSION_NUM(4,2,0)
 /* Convert radians to degrees, i.e., x * 180 / pi.  */
 
 static void
@@ -1196,6 +1197,7 @@ rad2deg (mpfr_t x)
   mpfr_div (x, x, tmp, GFC_RND_MODE);
   mpfr_clear (tmp);
 }
+#endif
 
 
 /* Simplify ACOSD(X) where the returned value has units of degree.  */
@@ -1217,8 +1219,12 @@ gfc_simplify_acosd (gfc_expr *x)
     }
 
   result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
+#if MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)
+  mpfr_acosu (result->value.real, x->value.real, 360, GFC_RND_MODE);
+#else
   mpfr_acos (result->value.real, x->value.real, GFC_RND_MODE);
   rad2deg (result->value.real);
+#endif
 
   return range_check (result, "ACOSD");
 }
@@ -1243,8 +1249,12 @@ gfc_simplify_asind (gfc_expr *x)
     }
 
   result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
+#if MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)
+  mpfr_asinu (result->value.real, x->value.real, 360, GFC_RND_MODE);
+#else
   mpfr_asin (result->value.real, x->value.real, GFC_RND_MODE);
   rad2deg (result->value.real);
+#endif
 
   return range_check (result, "ASIND");
 }
@@ -1261,8 +1271,12 @@ gfc_simplify_atand (gfc_expr *x)
     return NULL;
 
   result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
+#if MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)
+  mpfr_atanu (result->value.real, x->value.real, 360, GFC_RND_MODE);
+#else
   mpfr_atan (result->value.real, x->value.real, GFC_RND_MODE);
   rad2deg (result->value.real);
+#endif
 
   return range_check (result, "ATAND");
 }
@@ -1954,8 +1968,13 @@ gfc_simplify_atan2d (gfc_expr *y, gfc_expr *x)
     }
 
   result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
+#if MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)
+  mpfr_atan2u (result->value.real, y->value.real, x->value.real, 360,
+	       GFC_RND_MODE);
+#else
   mpfr_atan2 (result->value.real, y->value.real, x->value.real, GFC_RND_MODE);
   rad2deg (result->value.real);
+#endif
 
   return range_check (result, "ATAN2D");
 }
@@ -1990,6 +2009,8 @@ gfc_simplify_cos (gfc_expr *x)
 }
 
 
+#if MPFR_VERSION < MPFR_VERSION_NUM(4,2,0)
+/* Used by trigd_fe.inc.  */
 static void
 deg2rad (mpfr_t x)
 {
@@ -2001,11 +2022,13 @@ deg2rad (mpfr_t x)
   mpfr_mul (x, x, d2r, GFC_RND_MODE);
   mpfr_clear (d2r);
 }
+#endif
 
 
+#if MPFR_VERSION < MPFR_VERSION_NUM(4,2,0)
 /* Simplification routines for SIND, COSD, TAND.  */
 #include "trigd_fe.inc"
-
+#endif
 
 /* Simplify COSD(X) where X has the unit of degree.  */
 
@@ -2018,8 +2041,12 @@ gfc_simplify_cosd (gfc_expr *x)
     return NULL;
 
   result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
+#if MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)
+  mpfr_cosu (result->value.real, x->value.real, 360, GFC_RND_MODE);
+#else
   mpfr_set (result->value.real, x->value.real, GFC_RND_MODE);
   simplify_cosd (result->value.real);
+#endif
 
   return range_check (result, "COSD");
 }
@@ -2036,8 +2063,12 @@ gfc_simplify_sind (gfc_expr *x)
     return NULL;
 
   result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
+#if MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)
+  mpfr_sinu (result->value.real, x->value.real, 360, GFC_RND_MODE);
+#else
   mpfr_set (result->value.real, x->value.real, GFC_RND_MODE);
   simplify_sind (result->value.real);
+#endif
 
   return range_check (result, "SIND");
 }
@@ -2054,8 +2085,12 @@ gfc_simplify_tand (gfc_expr *x)
     return NULL;
 
   result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
+#if MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)
+  mpfr_tanu (result->value.real, x->value.real, 360, GFC_RND_MODE);
+#else
   mpfr_set (result->value.real, x->value.real, GFC_RND_MODE);
   simplify_tand (result->value.real);
+#endif
 
   return range_check (result, "TAND");
 }
@@ -2078,7 +2113,11 @@ gfc_simplify_cotand (gfc_expr *x)
   result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
   mpfr_set (result->value.real, x->value.real, GFC_RND_MODE);
   mpfr_add_ui (result->value.real, result->value.real, 90, GFC_RND_MODE);
+#if MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)
+  mpfr_tanu (result->value.real, x->value.real, 360, GFC_RND_MODE);
+#else
   simplify_tand (result->value.real);
+#endif
   mpfr_neg (result->value.real, result->value.real, GFC_RND_MODE);
 
   return range_check (result, "COTAND");

Reply via email to