diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2023-10-12 15:32:41 +0200 |
---|---|---|
committer | Georg-Johann Lay <avr@gjlay.de> | 2023-10-12 15:34:06 +0200 |
commit | cd0185b8d155887a7d3a78d0c186289140b44e47 (patch) | |
tree | d0c0ad2f9c61fd7174c8afe0e0a3246efbaee341 /libgcc/config | |
parent | 2cc4f58a7c12c9b7a82194279c201ebe389f6dba (diff) | |
download | gcc-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')
-rw-r--r-- | libgcc/config/avr/libf7/libf7-common.mk | 2 | ||||
-rw-r--r-- | libgcc/config/avr/libf7/libf7.c | 60 | ||||
-rw-r--r-- | libgcc/config/avr/libf7/libf7.h | 2 |
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*); |