]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fortran: map atand(y, x) to atan2d(y, x) [PR113413]
authorYuao Ma <c8ef@outlook.com>
Mon, 12 May 2025 15:07:37 +0000 (23:07 +0800)
committerTobias Burnus <tburnus@baylibre.com>
Tue, 13 May 2025 22:34:07 +0000 (00:34 +0200)
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 <c8ef@outlook.com>
Co-authored-by: Steven G. Kargl <kargl@gcc.gnu.org>
gcc/fortran/intrinsic.cc
gcc/fortran/intrinsic.texi
gcc/testsuite/gfortran.dg/dec_math.f90

index 2eba2094606e5e62b1591f1cabf4ca7fea1a5a5d..908e1dae128bf7e51374073d38cd80a4729cc1a4 100644 (file)
@@ -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,
index 3a105bc65f057cda12ca507968f52a5a2907106f..48c2d60826b77ff89cf9bbfae4c10370c3becbc6 100644 (file)
@@ -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
 
index 393e7def88e046a6e34d3e957e0595a5799111e6..dbb4bdbefb9c5c3c94cdb7b2a1125c6f6f6ccab5 100644 (file)
@@ -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