From b239e9cf98ca9238e61e01864ab4dbb5c7f57ce2 Mon Sep 17 00:00:00 2001 From: Yuao Ma Date: Mon, 12 May 2025 23:07:37 +0800 Subject: [PATCH] fortran: map atand(y, x) to atan2d(y, x) [PR113413] According to the Fortran standard, atand(y, x) is equivalent to atan2d(y, x). However, the current atand(y, x) function produces an error. This patch includes the necessary intrinsic mapping, related test, and intrinsic documentation. The minor comment change in intrinsic.cc is cherry-picked from Steve's previous work. PR fortran/113413 - ATAND(Y,X) is unsupported PR fortran/113413 gcc/fortran/ChangeLog: * intrinsic.cc (do_check): Minor doc polish. (add_functions): Add atand(y, x) mapping. * intrinsic.texi: Update atand example. gcc/testsuite/ChangeLog: * gfortran.dg/dec_math.f90: Add atand(y, x) testcase. Signed-off-by: Yuao Ma Co-authored-by: Steven G. Kargl --- gcc/fortran/intrinsic.cc | 19 +++++--- gcc/fortran/intrinsic.texi | 13 ++++-- gcc/testsuite/gfortran.dg/dec_math.f90 | 63 ++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 11 deletions(-) diff --git a/gcc/fortran/intrinsic.cc b/gcc/fortran/intrinsic.cc index 2eba2094606e..908e1dae128b 100644 --- a/gcc/fortran/intrinsic.cc +++ b/gcc/fortran/intrinsic.cc @@ -376,11 +376,11 @@ do_check (gfc_intrinsic_sym *specific, gfc_actual_arglist *arg) Argument list: char * name of function - int whether function is elemental - int If the function can be used as an actual argument [1] - bt return type of function - int kind of return type of function - int Fortran standard version + int whether function is elemental + int If the function can be used as an actual argument [1] + bt return type of function + int kind of return type of function + int Fortran standard version check pointer to check function simplify pointer to simplification function resolve pointer to resolution function @@ -396,7 +396,7 @@ do_check (gfc_intrinsic_sym *specific, gfc_actual_arglist *arg) [1] Whether a function can or cannot be used as an actual argument is - determined by its presence on the 13.6 list in Fortran 2003. The + determined by its presence in the 13.6 list in Fortran 2003. The following intrinsics, which are GNU extensions, are considered allowed as actual arguments: ACOSH ATANH DACOSH DASINH DATANH DCONJG DIMAG ZABS ZCOS ZEXP ZLOG ZSIN ZSQRT. */ @@ -3479,6 +3479,13 @@ add_functions (void) gfc_check_fn_r, gfc_simplify_atand, gfc_resolve_trigd, x, BT_REAL, dr, REQUIRED); + /* Two-argument version of atand, equivalent to atan2d. */ + add_sym_2 ("atand", GFC_ISYM_ATAN2D, CLASS_ELEMENTAL, ACTUAL_YES, + BT_REAL, dr, GFC_STD_F2023, + gfc_check_atan2, gfc_simplify_atan2d, gfc_resolve_trigd2, + y, BT_REAL, dr, REQUIRED, + x, BT_REAL, dr, REQUIRED); + make_generic ("atand", GFC_ISYM_ATAND, GFC_STD_F2023); add_sym_1 ("datand", GFC_ISYM_ATAND, CLASS_ELEMENTAL, ACTUAL_YES, diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index 3a105bc65f05..48c2d60826b7 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -1547,7 +1547,7 @@ Fortran 90 and later @node ATAN -@section @code{ATAN} --- Arctangent function +@section @code{ATAN} --- Arctangent function @fnindex ATAN @fnindex DATAN @cindex trigonometric function, tangent, inverse @@ -1619,6 +1619,7 @@ Degrees function: @* @item @emph{Synopsis}: @multitable @columnfractions .80 @item @code{RESULT = ATAND(X)} +@item @code{RESULT = ATAND(Y, X)} @end multitable @item @emph{Description}: @@ -1630,21 +1631,23 @@ Elemental function @item @emph{Arguments}: @multitable @columnfractions .15 .70 -@item @var{X} @tab The type shall be @code{REAL}; -if @var{Y} is present, @var{X} shall be REAL. +@item @var{X} @tab The type shall be @code{REAL}. @item @var{Y} @tab The type and kind type parameter shall be the same as @var{X}. @end multitable @item @emph{Return value}: The return value is of the same type and kind as @var{X}. -The result is in degrees and lies in the range -@math{-90 \leq \Re \atand(x) \leq 90}. +If @var{Y} is present, the result is identical to @code{ATAN2D(Y, X)}. +Otherwise, the result is in degrees and lies in the range +@math{-90 \leq \atand(x) \leq 90}. @item @emph{Example}: @smallexample program test_atand real(8) :: x = 2.866_8 + real(4) :: x1 = 1.e0_4, y1 = 0.5e0_4 x = atand(x) + x1 = atand(y1, x1) end program test_atand @end smallexample diff --git a/gcc/testsuite/gfortran.dg/dec_math.f90 b/gcc/testsuite/gfortran.dg/dec_math.f90 index 393e7def88e0..dbb4bdbefb9c 100644 --- a/gcc/testsuite/gfortran.dg/dec_math.f90 +++ b/gcc/testsuite/gfortran.dg/dec_math.f90 @@ -521,6 +521,69 @@ call cmpq(q_i1, q_oe, q_oc, q_tol, "(c) qatand") call cmpq(q_i1, q_oxe, q_ox, q_tol, "(x) qatand") #endif +! Input +f_i1 = 1.0_4 +f_i2 = 2.0_4 +d_i1 = 1.0_8 +d_i2 = 2.0_8 +#ifdef __GFC_REAL_10__ +l_i1 = 1.0_10 +l_i2 = 2.0_10 +#endif +#ifdef __GFC_REAL_16__ +q_i1 = 1.0_16 +q_i2 = 2.0_16 +#endif + +! Expected +f_oe = r2d_f * atan2 (f_i1, f_i2) +f_oxe = r2d_f * atan2 (xf * f_i1, f_i2) +d_oe = r2d_d * atan2 (d_i1, d_i2) +d_oxe = r2d_d * atan2 (xd * d_i1, d_i2) +#ifdef __GFC_REAL_10__ +l_oe = r2d_l * atan2 (l_i1, l_i2) +l_oxe = r2d_l * atan2 (xl * l_i1, l_i2) +#endif +#ifdef __GFC_REAL_16__ +q_oe = r2d_q * atan2 (q_i1, q_i2) +q_oxe = r2d_q * atan2 (xq * q_i1, q_i2) +#endif + +! Actual +f_oa = atand (f_i1, f_i2) +f_oc = atand (1.0_4, 2.0_4) +f_ox = atand (xf * f_i1, f_i2) +d_oa = atand (d_i1, d_i2) +d_oc = atand (1.0_8, 2.0_8) +d_ox = atand (xd * d_i1, d_i2) +#ifdef __GFC_REAL_10__ +l_oa = atand (l_i1, l_i2) +l_oc = atand (1.0_10, 2.0_10) +l_ox = atand (xl * l_i1, l_i2) +#endif +#ifdef __GFC_REAL_16__ +q_oa = atand (q_i1, q_i2) +q_oc = atand (1.0_16, 2.0_16) +q_ox = atand (xq * q_i1, q_i2) +#endif + +call cmpf(f_i1, f_oe, f_oa, f_tol, "( ) fatand") +call cmpf(f_i1, f_oe, f_oc, f_tol, "(c) fatand") +call cmpf(f_i1, f_oxe, f_ox, f_tol, "(x) fatand") +call cmpd(d_i1, d_oe, d_oa, d_tol, "( ) datand") +call cmpd(d_i1, d_oe, d_oc, d_tol, "(c) datand") +call cmpd(d_i1, d_oxe, d_ox, d_tol, "(x) atand") +#ifdef __GFC_REAL_10__ +call cmpl(l_i1, l_oe, l_oa, l_tol, "( ) latand") +call cmpl(l_i1, l_oe, l_oc, l_tol, "(c) latand") +call cmpl(l_i1, l_oxe, l_ox, l_tol, "(x) latand") +#endif +#ifdef __GFC_REAL_16__ +call cmpq(q_i1, q_oe, q_oa, q_tol, "( ) qatand") +call cmpq(q_i1, q_oe, q_oc, q_tol, "(c) qatand") +call cmpq(q_i1, q_oxe, q_ox, q_tol, "(x) qatand") +#endif + ! Input f_i1 = 34.3775_4 d_i1 = 34.3774677078494_8 -- 2.47.2