diff mbox series

[avr,committed] Implement atan2

Message ID e4e22a9c-1917-d868-9171-866c6625888a@gjlay.de
State New
Headers show
Series [avr,committed] Implement atan2 | expand

Commit Message

Georg-Johann Lay Oct. 12, 2023, 1:38 p.m. UTC
This implements atan2 which was missing from LibF7.

Johann

--

LibF7: Implement atan2.

libgcc/config/avr/libf7/
         * libf7.c (F7MOD_atan2_, f7_atan2): New module and function.
         * libf7.h: Adjust comments.
         * libf7-common.mk (CALL_PROLOGUES): Add atan2.
diff mbox series

Patch

diff --git a/libgcc/config/avr/libf7/libf7-common.mk 
b/libgcc/config/avr/libf7/libf7-common.mk
index 28663b52e6c..e417715a7e5 100644
--- a/libgcc/config/avr/libf7/libf7-common.mk
+++ b/libgcc/config/avr/libf7/libf7-common.mk
@@ -43,7 +43,7 @@  m_xd += lrint lround
  # -mcall-prologues
  CALL_PROLOGUES += divx sqrt cbrt get_double set_double logx exp exp10 
pow10
  CALL_PROLOGUES += put_C truncx round minmax sincos tan cotan pow powi fmod
-CALL_PROLOGUES += atan asinacos madd_msub hypot init horner sinhcosh tanh
+CALL_PROLOGUES += atan atan2 asinacos madd_msub hypot init horner 
sinhcosh tanh

  # -mstrict-X
  STRICT_X += log addsub truncx ldexp exp
diff --git a/libgcc/config/avr/libf7/libf7.c 
b/libgcc/config/avr/libf7/libf7.c
index 0d9e4c325b2..49baac73e6d 100644
--- a/libgcc/config/avr/libf7/libf7.c
+++ b/libgcc/config/avr/libf7/libf7.c
@@ -1099,7 +1099,7 @@  f7_t* f7_ldexp (f7_t *cc, const f7_t *aa, int delta)

    F7_CONST_ADDR (<ident> CST, f7_t* PTMP)

-      Return an LD address to for some f7_const_X[_P] constant.
+      Return an LD address to some f7_const_X[_P] constant.
        *PTMP might be needed to hold a copy of f7_const_X_P in RAM.

    f7_t*       F7_U16_ADDR (uint16_t     X, f7_t* PTMP)   // USE_LPM
@@ -2189,6 +2189,64 @@  void f7_atan (f7_t *cc, const f7_t *aa)
  #endif // F7MOD_atan_


+#ifdef F7MOD_atan2_
+F7_WEAK
+void f7_atan2 (f7_t *cc, const f7_t *yy, const f7_t *xx)
+{
+  uint8_t y_class = f7_classify (yy);
+  uint8_t x_class = f7_classify (xx);
+
+  // (NaN, *) -> NaN
+  // (*, NaN) -> NaN
+  if (f7_class_nan (y_class | x_class))
+    return f7_set_nan (cc);
+
+  // (0, 0) -> 0
+  if (f7_class_zero (y_class & x_class))
+    return f7_clr (cc);
+
+  f7_t pi7, *pi = &pi7;
+  f7_const (pi, pi);
+
+  // (Inf, +Inf) -> +pi/4;    (-Inf, +Inf) -> +3pi/4
+  // (Inf, -Inf) -> -pi/4;    (-Inf, -Inf) -> -3pi/4
+  if (f7_class_inf (y_class & x_class))
+    {
+      f7_copy (cc, pi);
+      if (! f7_class_sign (x_class))
+	cc->expo = F7_(const_pi_expo) - 1; // pi / 2
+      pi->expo = F7_(const_pi_expo) - 2;   // pi / 4
+      f7_Isub (cc, pi);
+      cc->flags = y_class & F7_FLAG_sign;
+      return;
+    }
+
+  // sign(pi) := sign(y)
+  pi->flags = y_class & F7_FLAG_sign;
+
+  // Only use atan(*) with |*| <= 1.
+
+  if (f7_cmp_abs (yy, xx) > 0)
+    {
+      // |y| > |x|:  atan2 = sgn(y) * pi/2 - atan (x / y);
+      pi->expo = F7_(const_pi_expo) - 1;  // +- pi / 2
+      f7_div (cc, xx, yy);
+      f7_atan (cc, cc);
+      f7_IRsub (cc, pi);
+    }
+  else
+    {
+      // x >  |y|:  atan2 = atan (y / x)
+      // x < -|y|:  atan2 = atan (y / x) +- pi
+      f7_div (cc, yy, xx);
+      f7_atan (cc, cc);
+      if (f7_class_sign (x_class))
+	f7_Iadd (cc, pi);
+    }
+}
+#endif // F7MOD_atan2_
+
+
  #ifdef F7MOD_asinacos_

  #define ARRAY_NAME coeff_func_a_zahler
diff --git a/libgcc/config/avr/libf7/libf7.h 
b/libgcc/config/avr/libf7/libf7.h
index f692854dced..b50e6e218ba 100644
--- a/libgcc/config/avr/libf7/libf7.h
+++ b/libgcc/config/avr/libf7/libf7.h
@@ -606,6 +606,7 @@  extern void f7_sin (f7_t*, const f7_t*);
  extern void f7_cos (f7_t*, const f7_t*);
  extern void f7_tan (f7_t*, const f7_t*);
  extern void f7_atan (f7_t*, const f7_t*);
+extern void f7_atan2 (f7_t*, const f7_t*, const f7_t*);
  extern void f7_asin (f7_t*, const f7_t*);
  extern void f7_acos (f7_t*, const f7_t*);
  extern void f7_tanh (f7_t*, const f7_t*);
@@ -617,7 +618,6 @@  extern void f7_exp10 (f7_t*, const f7_t*);
  extern void f7_pow10 (f7_t*, const f7_t*);

  // Just prototypes, not implemented yet.
-extern void f7_atan2 (f7_t*, const f7_t*, const f7_t*);
  extern long f7_lrint (const f7_t*);
  extern long f7_lround (const f7_t*);