aboutsummaryrefslogtreecommitdiff
path: root/libgcc/config/avr
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2023-10-12 15:32:41 +0200
committerGeorg-Johann Lay <avr@gjlay.de>2023-10-12 15:34:06 +0200
commitcd0185b8d155887a7d3a78d0c186289140b44e47 (patch)
treed0c0ad2f9c61fd7174c8afe0e0a3246efbaee341 /libgcc/config/avr
parent2cc4f58a7c12c9b7a82194279c201ebe389f6dba (diff)
downloadgcc-cd0185b8d155887a7d3a78d0c186289140b44e47.zip
gcc-cd0185b8d155887a7d3a78d0c186289140b44e47.tar.gz
gcc-cd0185b8d155887a7d3a78d0c186289140b44e47.tar.bz2
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.
Diffstat (limited to 'libgcc/config/avr')
-rw-r--r--libgcc/config/avr/libf7/libf7-common.mk2
-rw-r--r--libgcc/config/avr/libf7/libf7.c60
-rw-r--r--libgcc/config/avr/libf7/libf7.h2
3 files changed, 61 insertions, 3 deletions
diff --git a/libgcc/config/avr/libf7/libf7-common.mk b/libgcc/config/avr/libf7/libf7-common.mk
index 28663b5..e417715 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 0d9e4c3..49baac7 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 f692854..b50e6e2 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*);