2 #if defined(__MINGW32__) && A_PREREQ_GNUC(3, 0)
3 #pragma GCC diagnostic ignored "-Wfloat-conversion"
4 #endif /* __MINGW32__ */
5 #if A_PREREQ_GNUC(3, 0) || __has_warning("-Wfloat-equal")
6 #pragma GCC diagnostic ignored "-Wfloat-equal"
7 #endif /* -Wfloat-equal */
10 /* compiler built-in complex number type */
11 #if A_PREREQ_MSVC(18, 0)
12 #include <complex.h> // 12.0
13 #if A_FLOAT_TYPE + 0 == A_FLOAT_SINGLE
14 #define A_COMPLEX _Fcomplex
15 #elif A_FLOAT_TYPE + 0 == A_FLOAT_DOUBLE
16 #define A_COMPLEX _Dcomplex
17 #elif A_FLOAT_TYPE + 0 == A_FLOAT_EXTEND
18 #define A_COMPLEX _Lcomplex
19 #endif /* A_COMPLEX */
20 #elif defined(__GNUC__) || defined(__clang__)
22 #define A_COMPLEX _Complex A_FLOAT
23 #else /* !A_FLOAT_TYPE */
24 #if A_PREREQ_GNUC(2, 95) || __has_warning("-Waggregate-return")
25 #pragma GCC diagnostic ignored "-Waggregate-return"
26 #endif /* -Waggregate-return */
27 #endif /* A_FLOAT_TYPE */
31 void a_complex_polar(a_complex
*_z
, a_float rho
, a_float theta
)
33 _z
->real
= rho
* a_float_cos(theta
);
34 _z
->imag
= rho
* a_float_sin(theta
);
37 unsigned int a_complex_parse(a_complex
*_z
, char const *str
)
39 #if A_FLOAT_TYPE + 0 == A_FLOAT_SINGLE
40 #define strtonum(string, endptr) strtof(string, endptr)
41 #elif A_FLOAT_TYPE + 0 == A_FLOAT_DOUBLE
42 #define strtonum(string, endptr) strtod(string, endptr)
43 #elif A_FLOAT_TYPE + 0 == A_FLOAT_EXTEND
44 #define strtonum(string, endptr) strtold(string, endptr)
45 #endif /* A_FLOAT_TYPE */
52 if (!str
) { return 0; }
53 for (_z
->real
= 0; *u
.s
; ++u
.s
)
55 if (*u
.s
== '+' || *u
.s
== '-' || ('0' <= *u
.s
&& *u
.s
<= '9') || *u
.s
== '.')
57 _z
->real
= strtonum(u
.s
, &u
.p
);
61 for (_z
->imag
= 0; *u
.s
; ++u
.s
)
63 if (*u
.s
== '+' || *u
.s
== '-' || ('0' <= *u
.s
&& *u
.s
<= '9') || *u
.s
== '.')
65 _z
->imag
= strtonum(u
.s
, &u
.p
);
69 return (unsigned int)(u
.s
- str
);
72 a_bool
a_complex_eq(a_complex x
, a_complex y
)
74 return x
.real
== y
.real
&& x
.imag
== y
.imag
;
77 a_bool
a_complex_ne(a_complex x
, a_complex y
)
79 return x
.real
!= y
.real
|| x
.imag
!= y
.imag
;
82 a_float
a_complex_logabs(a_complex z
)
85 a_float
const xabs
= a_float_abs(z
.real
);
86 a_float
const yabs
= a_float_abs(z
.imag
);
97 return a_float_log(r
) + A_FLOAT_C(0.5) * a_float_log1p(u
* u
);
100 a_float
a_complex_abs2(a_complex z
)
102 return z
.real
* z
.real
+ z
.imag
* z
.imag
;
105 a_float
a_complex_abs(a_complex z
)
107 return a_float_hypot(z
.real
, z
.imag
);
110 a_float
a_complex_arg(a_complex z
)
112 if (z
.real
!= 0 || z
.imag
!= 0)
114 return a_float_atan2(z
.imag
, z
.real
);
119 void a_complex_proj_(a_complex
*_z
)
121 if (isinf(_z
->real
) || isinf(_z
->imag
))
123 _z
->real
= A_FLOAT_INF
;
124 _z
->imag
= a_float_copysign(0, _z
->imag
);
128 void a_complex_mul_(a_complex
*_z
, a_complex z
)
130 a_float
const real
= _z
->real
;
131 _z
->real
= real
* z
.real
- _z
->imag
* z
.imag
;
132 _z
->imag
= real
* z
.imag
+ _z
->imag
* z
.real
;
135 void a_complex_div_(a_complex
*_z
, a_complex z
)
137 a_float
const inv
= 1 / a_complex_abs(z
);
138 a_float
const xr
= _z
->real
* inv
;
139 a_float
const xi
= _z
->imag
* inv
;
140 a_float
const yr
= z
.real
* inv
;
141 a_float
const yi
= z
.imag
* inv
;
142 _z
->real
= xr
* yr
+ xi
* yi
;
143 _z
->imag
= xi
* yr
- xr
* yi
;
146 void a_complex_inv_(a_complex
*_z
)
148 a_float
const inv
= 1 / a_complex_abs(*_z
);
149 _z
->real
= +inv
* _z
->real
* inv
;
150 _z
->imag
= -inv
* _z
->imag
* inv
;
153 #if A_PREREQ_GNUC(2, 95) || __has_warning("-Wimplicit-function-declaration")
154 #pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
155 #endif /* gcc 2.95+ */
156 #if __has_warning("-Wincompatible-library-redeclaration")
157 #pragma clang diagnostic ignored "-Wincompatible-library-redeclaration"
158 #endif /* clang 4.0+ */
159 #if A_PREREQ_GNUC(10, 1)
160 #pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
161 #endif /* gcc 10.1+ */
163 #if defined(A_HAVE_CSQRT) && (A_HAVE_CSQRT + 0 < 1)
165 #endif /* A_HAVE_CSQRT */
166 #if defined(A_HAVE_CSQRT) && !defined A_COMPLEX
167 a_complex
A_FLOAT_F1(csqrt
, a_complex
);
168 #endif /* A_HAVE_CSQRT */
169 void a_complex_sqrt_(a_complex
*_z
)
171 #if defined(A_HAVE_CSQRT) && defined(A_COMPLEX)
178 *u
.z
= A_FLOAT_F1(csqrt
, *u
.z
);
179 #elif defined(A_HAVE_CSQRT)
180 *_z
= A_FLOAT_F1(csqrt
, *_z
);
181 #else /* !A_HAVE_CSQRT */
182 if (_z
->real
!= 0 || _z
->imag
!= 0)
184 a_float
const x
= a_float_abs(_z
->real
);
185 a_float
const y
= a_float_abs(_z
->imag
);
190 w
= A_FLOAT_SQRT1_2
* a_float_sqrt(x
) * a_float_sqrt(a_float_sqrt(u
* u
+ 1) + 1);
195 w
= A_FLOAT_SQRT1_2
* a_float_sqrt(y
) * a_float_sqrt(a_float_sqrt(u
* u
+ 1) + u
);
200 _z
->imag
= _z
->imag
/ (2 * w
);
204 _z
->real
= _z
->imag
/ (2 * w
);
205 _z
->imag
= _z
->imag
< 0 ? -w
: w
;
208 #endif /* A_HAVE_CSQRT */
211 void a_complex_sqrt_real(a_complex
*_z
, a_float x
)
215 _z
->real
= a_float_sqrt(x
);
221 _z
->imag
= a_float_sqrt(-x
);
225 #if defined(A_HAVE_CPOW) && (A_HAVE_CPOW + 0 < 1)
227 #endif /* A_HAVE_CPOW */
228 #if defined(A_HAVE_CPOW) && !defined A_COMPLEX
229 a_complex
A_FLOAT_F2(cpow
, a_complex
, a_complex
);
230 #endif /* A_HAVE_CPOW */
231 void a_complex_pow_(a_complex
*_z
, a_complex a
)
233 #if defined(A_HAVE_CPOW) && defined(A_COMPLEX)
241 *u
.z
= A_FLOAT_F2(cpow
, *u
.z
, *v
.z
);
242 #elif defined(A_HAVE_CPOW)
243 *_z
= A_FLOAT_F2(cpow
, *_z
, a
);
244 #else /* !A_HAVE_CPOW */
245 if (_z
->real
!= 0 || _z
->imag
!= 0)
247 a_float
const logr
= a_complex_logabs(*_z
);
248 a_float
const theta
= a_complex_arg(*_z
);
249 a_float
const rho
= a_float_exp(logr
* a
.real
- theta
* a
.imag
);
250 a_float
const beta
= theta
* a
.real
+ logr
* a
.imag
;
251 a_complex_polar(_z
, rho
, beta
);
255 _z
->real
= (a
.real
== 0 && a
.imag
== 0) ? 1 : 0;
257 #endif /* A_HAVE_CPOW */
260 void a_complex_pow_real_(a_complex
*_z
, a_float a
)
262 if (_z
->real
!= 0 || _z
->imag
!= 0)
264 a_float
const logr
= a_complex_logabs(*_z
);
265 a_float
const theta
= a_complex_arg(*_z
);
266 a_float
const rho
= a_float_exp(logr
* a
);
267 a_float
const beta
= theta
* a
;
268 a_complex_polar(_z
, rho
, beta
);
272 _z
->real
= (a
== 0) ? 1 : 0;
276 #if defined(A_HAVE_CEXP) && (A_HAVE_CEXP + 0 < 1)
278 #endif /* A_HAVE_CEXP */
279 #if defined(A_HAVE_CEXP) && !defined A_COMPLEX
280 a_complex
A_FLOAT_F1(cexp
, a_complex
);
281 #endif /* A_HAVE_CEXP */
282 void a_complex_exp_(a_complex
*_z
)
284 #if defined(A_HAVE_CEXP) && defined(A_COMPLEX)
291 *u
.z
= A_FLOAT_F1(cexp
, *u
.z
);
292 #elif defined(A_HAVE_CEXP)
293 *_z
= A_FLOAT_F1(cexp
, *_z
);
294 #else /* !A_HAVE_CEXP */
295 a_complex_polar(_z
, a_float_exp(_z
->real
), _z
->imag
);
296 #endif /* A_HAVE_CEXP */
299 #if defined(A_HAVE_CLOG) && (A_HAVE_CLOG + 0 < 1)
301 #endif /* A_HAVE_CLOG */
302 #if defined(A_HAVE_CLOG) && !defined A_COMPLEX
303 a_complex
A_FLOAT_F1(clog
, a_complex
);
304 #endif /* A_HAVE_CLOG */
305 void a_complex_log_(a_complex
*_z
)
307 #if defined(A_HAVE_CLOG) && defined(A_COMPLEX)
314 *u
.z
= A_FLOAT_F1(clog
, *u
.z
);
315 #elif defined(A_HAVE_CLOG)
316 *_z
= A_FLOAT_F1(clog
, *_z
);
317 #else /* !A_HAVE_CLOG */
318 _z
->real
= a_complex_logabs(*_z
);
319 _z
->imag
= a_complex_arg(*_z
);
320 #endif /* A_HAVE_CLOG */
323 void a_complex_log2_(a_complex
*_z
)
326 a_complex_mul_real_(_z
, A_FLOAT_LN1_2
);
329 void a_complex_log10_(a_complex
*_z
)
332 a_complex_mul_real_(_z
, A_FLOAT_LN1_10
);
335 void a_complex_logb_(a_complex
*_z
, a_complex b
)
339 a_complex_div_(_z
, b
);
342 #if defined(A_HAVE_CSIN) && (A_HAVE_CSIN + 0 < 1)
344 #endif /* A_HAVE_CSIN */
345 #if defined(A_HAVE_CSIN) && !defined A_COMPLEX
346 a_complex
A_FLOAT_F1(csin
, a_complex
);
347 #endif /* A_HAVE_CSIN */
348 void a_complex_sin_(a_complex
*_z
)
350 #if defined(A_HAVE_CSIN) && defined(A_COMPLEX)
357 *u
.z
= A_FLOAT_F1(csin
, *u
.z
);
358 #elif defined(A_HAVE_CSIN)
359 *_z
= A_FLOAT_F1(csin
, *_z
);
360 #else /* !A_HAVE_CSIN */
363 a_float
const real
= _z
->real
;
364 _z
->real
= a_float_sin(real
) * a_float_cosh(_z
->imag
);
365 _z
->imag
= a_float_cos(real
) * a_float_sinh(_z
->imag
);
369 _z
->real
= a_float_sin(_z
->real
);
371 #endif /* A_HAVE_CSIN */
374 #if defined(A_HAVE_CCOS) && (A_HAVE_CCOS + 0 < 1)
376 #endif /* A_HAVE_CCOS */
377 #if defined(A_HAVE_CCOS) && !defined A_COMPLEX
378 a_complex
A_FLOAT_F1(ccos
, a_complex
);
379 #endif /* A_HAVE_CCOS */
380 void a_complex_cos_(a_complex
*_z
)
382 #if defined(A_HAVE_CCOS) && defined(A_COMPLEX)
389 *u
.z
= A_FLOAT_F1(ccos
, *u
.z
);
390 #elif defined(A_HAVE_CCOS)
391 *_z
= A_FLOAT_F1(ccos
, *_z
);
392 #else /* !A_HAVE_CCOS */
395 a_float
const real
= _z
->real
;
396 _z
->real
= a_float_cos(real
) * a_float_cosh(+_z
->imag
);
397 _z
->imag
= a_float_sin(real
) * a_float_sinh(-_z
->imag
);
401 _z
->real
= a_float_cos(_z
->real
);
403 #endif /* A_HAVE_CCOS */
406 #if defined(A_HAVE_CTAN) && (A_HAVE_CTAN + 0 < 1)
408 #endif /* A_HAVE_CTAN */
409 #if defined(A_HAVE_CTAN) && !defined A_COMPLEX
410 a_complex
A_FLOAT_F1(ctan
, a_complex
);
411 #endif /* A_HAVE_CTAN */
412 void a_complex_tan_(a_complex
*_z
)
414 #if defined(A_HAVE_CTAN) && defined(A_COMPLEX)
421 *u
.z
= A_FLOAT_F1(ctan
, *u
.z
);
422 #elif defined(A_HAVE_CTAN)
423 *_z
= A_FLOAT_F1(ctan
, *_z
);
424 #else /* !A_HAVE_CTAN */
425 a_float
const cr
= a_float_cos(_z
->real
);
426 a_float
const si
= a_float_sinh(_z
->imag
);
427 a_float
const den
= cr
* cr
+ si
* si
;
428 _z
->real
= A_FLOAT_C(0.5) * a_float_sin(2 * _z
->real
) / den
;
429 if (a_float_abs(_z
->imag
) < 1)
431 _z
->imag
= A_FLOAT_C(0.5) * a_float_sinh(2 * _z
->imag
) / den
;
435 a_float
const d
= a_float_pow(cr
/ si
, 2) + 1;
436 _z
->imag
= 1 / (a_float_tanh(_z
->imag
) * d
);
438 #endif /* A_HAVE_CTAN */
441 void a_complex_sec_(a_complex
*_z
)
447 void a_complex_csc_(a_complex
*_z
)
453 void a_complex_cot_(a_complex
*_z
)
459 #if defined(A_HAVE_CASIN) && (A_HAVE_CASIN + 0 < 1)
461 #endif /* A_HAVE_CASIN */
462 #if defined(A_HAVE_CASIN) && !defined A_COMPLEX
463 a_complex
A_FLOAT_F1(casin
, a_complex
);
464 #endif /* A_HAVE_CASIN */
465 void a_complex_asin_(a_complex
*_z
)
467 #if defined(A_HAVE_CASIN) && defined(A_COMPLEX)
474 *u
.z
= A_FLOAT_F1(casin
, *u
.z
);
475 #elif defined(A_HAVE_CASIN)
476 *_z
= A_FLOAT_F1(casin
, *_z
);
477 #else /* !A_HAVE_CASIN */
480 a_float
const a_crossover
= A_FLOAT_C(1.5);
481 a_float
const b_crossover
= A_FLOAT_C(0.6417);
482 a_float
const x
= a_float_abs(_z
->real
);
483 a_float
const y
= a_float_abs(_z
->imag
);
484 a_float
const r
= a_float_hypot(x
+ 1, y
);
485 a_float
const s
= a_float_hypot(x
- 1, y
);
486 a_float
const a
= A_FLOAT_C(0.5) * (r
+ s
);
487 a_float
const b
= x
/ a
;
488 a_float
const y2
= y
* y
;
489 a_float
const real
= _z
->real
;
490 a_float
const imag
= _z
->imag
;
491 if (b
<= b_crossover
)
493 _z
->real
= a_float_asin(b
);
497 a_float
const den
= A_FLOAT_C(0.5) * (a
+ x
) * (y2
/ (r
+ x
+ 1) + (s
+ 1 - x
));
498 _z
->real
= a_float_atan(x
/ a_float_sqrt(den
));
502 a_float
const apx
= a
+ x
;
503 a_float
const den
= A_FLOAT_C(0.5) * (apx
/ (r
+ x
+ 1) + apx
/ (s
+ x
- 1));
504 _z
->real
= a_float_atan(x
/ (a_float_sqrt(den
) * y
));
506 if (a
<= a_crossover
)
511 am1
= A_FLOAT_C(0.5) * (y2
/ (r
+ x
+ 1) + y2
/ (s
+ 1 - x
));
515 am1
= A_FLOAT_C(0.5) * (y2
/ (r
+ x
+ 1) + (s
+ x
- 1));
517 _z
->imag
= a_float_log1p(am1
+ a_float_sqrt((a
+ 1) * am1
));
521 _z
->imag
= a_float_log(a
+ a_float_sqrt(a
* a
- 1));
523 if (real
< 0) { _z
->real
= -_z
->real
; }
524 if (imag
< 0) { _z
->imag
= -_z
->imag
; }
528 a_complex_asin_real(_z
, _z
->real
);
530 #endif /* A_HAVE_CASIN */
533 void a_complex_asin_real(a_complex
*_z
, a_float x
)
535 if (a_float_abs(x
) <= 1)
537 _z
->real
= a_float_asin(x
);
544 _z
->real
= +A_FLOAT_PI_2
;
545 _z
->imag
= -a_float_acosh(+x
);
549 _z
->real
= -A_FLOAT_PI_2
;
550 _z
->imag
= +a_float_acosh(-x
);
555 #if defined(A_HAVE_CACOS) && (A_HAVE_CACOS + 0 < 1)
557 #endif /* A_HAVE_CACOS */
558 #if defined(A_HAVE_CACOS) && !defined A_COMPLEX
559 a_complex
A_FLOAT_F1(cacos
, a_complex
);
560 #endif /* A_HAVE_CACOS */
561 void a_complex_acos_(a_complex
*_z
)
563 #if defined(A_HAVE_CACOS) && defined(A_COMPLEX)
570 *u
.z
= A_FLOAT_F1(cacos
, *u
.z
);
571 #elif defined(A_HAVE_CACOS)
572 *_z
= A_FLOAT_F1(cacos
, *_z
);
573 #else /* !A_HAVE_CACOS */
576 a_float
const a_crossover
= A_FLOAT_C(1.5);
577 a_float
const b_crossover
= A_FLOAT_C(0.6417);
578 a_float
const x
= a_float_abs(_z
->real
);
579 a_float
const y
= a_float_abs(_z
->imag
);
580 a_float
const r
= a_float_hypot(x
+ 1, y
);
581 a_float
const s
= a_float_hypot(x
- 1, y
);
582 a_float
const a
= A_FLOAT_C(0.5) * (r
+ s
);
583 a_float
const b
= x
/ a
;
584 a_float
const y2
= y
* y
;
585 a_float
const real
= _z
->real
;
586 a_float
const imag
= _z
->imag
;
587 if (b
<= b_crossover
)
589 _z
->real
= a_float_acos(b
);
593 a_float
const den
= A_FLOAT_C(0.5) * (a
+ x
) * (y2
/ (r
+ x
+ 1) + (s
+ 1 - x
));
594 _z
->real
= a_float_atan(a_float_sqrt(den
) / x
);
598 a_float
const apx
= a
+ x
;
599 a_float
const den
= A_FLOAT_C(0.5) * (apx
/ (r
+ x
+ 1) + apx
/ (s
+ x
- 1));
600 _z
->real
= a_float_atan(a_float_sqrt(den
) * y
/ x
);
602 if (a
<= a_crossover
)
607 am1
= A_FLOAT_C(0.5) * (y2
/ (r
+ x
+ 1) + y2
/ (s
+ 1 - x
));
611 am1
= A_FLOAT_C(0.5) * (y2
/ (r
+ x
+ 1) + (s
+ x
- 1));
613 _z
->imag
= a_float_log1p(am1
+ a_float_sqrt((a
+ 1) * am1
));
617 _z
->imag
= a_float_log(a
+ a_float_sqrt(a
* a
- 1));
619 if (real
< 0) { _z
->real
= A_FLOAT_PI
- _z
->real
; }
620 if (imag
>= 0) { _z
->imag
= -_z
->imag
; }
624 a_complex_acos_real(_z
, _z
->real
);
626 #endif /* A_HAVE_CACOS */
629 void a_complex_acos_real(a_complex
*_z
, a_float x
)
631 if (a_float_abs(x
) <= 1)
633 _z
->real
= a_float_acos(x
);
641 _z
->imag
= +a_float_acosh(+x
);
645 _z
->real
= A_FLOAT_PI
;
646 _z
->imag
= -a_float_acosh(-x
);
651 #if defined(A_HAVE_CATAN) && (A_HAVE_CATAN + 0 < 1)
653 #endif /* A_HAVE_CATAN */
654 #if defined(A_HAVE_CATAN) && !defined A_COMPLEX
655 a_complex
A_FLOAT_F1(catan
, a_complex
);
656 #endif /* A_HAVE_CATAN */
657 void a_complex_atan_(a_complex
*_z
)
659 #if defined(A_HAVE_CATAN) && defined(A_COMPLEX)
666 *u
.z
= A_FLOAT_F1(cacos
, *u
.z
);
667 #elif defined(A_HAVE_CATAN)
668 *_z
= A_FLOAT_F1(catan
, *_z
);
669 #else /* !A_HAVE_CATAN */
672 a_float
const r
= a_float_hypot(_z
->real
, _z
->imag
);
673 a_float
const u
= 2 * _z
->imag
/ (r
* r
+ 1);
674 a_float
const imag
= _z
->imag
;
675 if (a_float_abs(u
) < A_FLOAT_C(0.1))
677 _z
->imag
= A_FLOAT_C(0.25) * (a_float_log1p(u
) - a_float_log1p(-u
));
681 a_float
const a
= a_float_hypot(_z
->real
, _z
->imag
+ 1);
682 a_float
const b
= a_float_hypot(_z
->real
, _z
->imag
- 1);
683 _z
->imag
= A_FLOAT_C(0.5) * a_float_log(a
/ b
);
687 _z
->real
= A_FLOAT_C(0.5) * a_float_atan2(2 * _z
->real
, (1 + r
) * (1 - r
));
693 _z
->real
= +A_FLOAT_PI
;
697 _z
->real
= -A_FLOAT_PI
;
707 _z
->real
= a_float_atan(_z
->real
);
709 #endif /* A_HAVE_CATAN */
712 void a_complex_asec_(a_complex
*_z
)
718 void a_complex_asec_real(a_complex
*_z
, a_float x
)
720 if (x
<= -1 || x
>= 1)
722 _z
->real
= a_float_acos(1 / x
);
730 _z
->imag
= +a_float_acosh(+1 / x
);
734 _z
->real
= A_FLOAT_PI
;
735 _z
->imag
= -a_float_acosh(-1 / x
);
740 void a_complex_acsc_(a_complex
*_z
)
746 void a_complex_acsc_real(a_complex
*_z
, a_float x
)
748 if (x
<= -1 || x
>= 1)
750 _z
->real
= a_float_asin(1 / x
);
757 _z
->real
= +A_FLOAT_PI_2
;
758 _z
->imag
= -a_float_acosh(+1 / x
);
762 _z
->real
= -A_FLOAT_PI_2
;
763 _z
->imag
= +a_float_acosh(-1 / x
);
768 void a_complex_acot_(a_complex
*_z
)
770 if (_z
->real
!= 0 || _z
->imag
!= 0)
777 _z
->real
= A_FLOAT_PI_2
;
781 #if defined(A_HAVE_CSINH) && (A_HAVE_CSINH + 0 < 1)
783 #endif /* A_HAVE_CSINH */
784 #if defined(A_HAVE_CSINH) && !defined A_COMPLEX
785 a_complex
A_FLOAT_F1(csinh
, a_complex
);
786 #endif /* A_HAVE_CSINH */
787 void a_complex_sinh_(a_complex
*_z
)
789 #if defined(A_HAVE_CSINH) && defined(A_COMPLEX)
796 *u
.z
= A_FLOAT_F1(csinh
, *u
.z
);
797 #elif defined(A_HAVE_CSINH)
798 *_z
= A_FLOAT_F1(csinh
, *_z
);
799 #else /* !A_HAVE_CSINH */
800 a_float
const real
= _z
->real
;
801 _z
->real
= a_float_sinh(real
) * a_float_cos(_z
->imag
);
802 _z
->imag
= a_float_cosh(real
) * a_float_sin(_z
->imag
);
803 #endif /* A_HAVE_CSINH */
806 #if defined(A_HAVE_CCOSH) && (A_HAVE_CCOSH + 0 < 1)
808 #endif /* A_HAVE_CCOSH */
809 #if defined(A_HAVE_CCOSH) && !defined A_COMPLEX
810 a_complex
A_FLOAT_F1(ccosh
, a_complex
);
811 #endif /* A_HAVE_CCOSH */
812 void a_complex_cosh_(a_complex
*_z
)
814 #if defined(A_HAVE_CCOSH) && defined(A_COMPLEX)
821 *u
.z
= A_FLOAT_F1(ccosh
, *u
.z
);
822 #elif defined(A_HAVE_CCOSH)
823 *_z
= A_FLOAT_F1(ccosh
, *_z
);
824 #else /* !A_HAVE_CCOSH */
825 a_float
const real
= _z
->real
;
826 _z
->real
= a_float_cosh(real
) * a_float_cos(_z
->imag
);
827 _z
->imag
= a_float_sinh(real
) * a_float_sin(_z
->imag
);
828 #endif /* A_HAVE_CCOSH */
831 #if defined(A_HAVE_CTANH) && (A_HAVE_CTANH + 0 < 1)
833 #endif /* A_HAVE_CTANH */
834 #if defined(A_HAVE_CTANH) && !defined A_COMPLEX
835 a_complex
A_FLOAT_F1(ctanh
, a_complex
);
836 #endif /* A_HAVE_CTANH */
837 void a_complex_tanh_(a_complex
*_z
)
839 #if defined(A_HAVE_CTANH) && defined(A_COMPLEX)
846 *u
.z
= A_FLOAT_F1(ctanh
, *u
.z
);
847 #elif defined(A_HAVE_CTANH)
848 *_z
= A_FLOAT_F1(ctanh
, *_z
);
849 #else /* !A_HAVE_CTANH */
850 a_float
const ci
= a_float_cos(_z
->imag
);
851 a_float
const sr
= a_float_sinh(_z
->real
);
852 a_float
const den
= ci
* ci
+ sr
* sr
;
853 _z
->imag
= A_FLOAT_C(0.5) * a_float_sin(2 * _z
->imag
) / den
;
854 if (a_float_abs(_z
->real
) < 1)
856 _z
->real
= a_float_sinh(_z
->real
) * a_float_cosh(_z
->real
) / den
;
860 a_float
const d
= a_float_pow(ci
/ sr
, 2) + 1;
861 _z
->real
= 1 / (a_float_tanh(_z
->real
) * d
);
863 #endif /* A_HAVE_CTANH */
866 void a_complex_sech_(a_complex
*_z
)
872 void a_complex_csch_(a_complex
*_z
)
878 void a_complex_coth_(a_complex
*_z
)
884 #if defined(A_HAVE_CASINH) && (A_HAVE_CASINH + 0 < 1)
886 #endif /* A_HAVE_CASINH */
887 #if defined(A_HAVE_CASINH) && !defined A_COMPLEX
888 a_complex
A_FLOAT_F1(casinh
, a_complex
);
889 #endif /* A_HAVE_CASINH */
890 void a_complex_asinh_(a_complex
*_z
)
892 #if defined(A_HAVE_CASINH) && defined(A_COMPLEX)
899 *u
.z
= A_FLOAT_F1(casinh
, *u
.z
);
900 #elif defined(A_HAVE_CASINH)
901 *_z
= A_FLOAT_F1(casinh
, *_z
);
902 #else /* !A_HAVE_CASINH */
903 a_complex_mul_imag_(_z
, +1);
905 a_complex_mul_imag_(_z
, -1);
906 #endif /* A_HAVE_CASINH */
909 #if defined(A_HAVE_CACOSH) && (A_HAVE_CACOSH + 0 < 1)
911 #endif /* A_HAVE_CACOSH */
912 #if defined(A_HAVE_CACOSH) && !defined A_COMPLEX
913 a_complex
A_FLOAT_F1(cacosh
, a_complex
);
914 #endif /* A_HAVE_CACOSH */
915 void a_complex_acosh_(a_complex
*_z
)
917 #if defined(A_HAVE_CACOSH) && defined(A_COMPLEX)
924 *u
.z
= A_FLOAT_F1(cacosh
, *u
.z
);
925 #elif defined(A_HAVE_CACOSH)
926 *_z
= A_FLOAT_F1(cacosh
, *_z
);
927 #else /* !A_HAVE_CACOSH */
929 a_complex_mul_imag_(_z
, _z
->imag
> 0 ? -1 : +1);
930 #endif /* A_HAVE_CACOSH */
933 void a_complex_acosh_real(a_complex
*_z
, a_float x
)
937 _z
->real
= a_float_acosh(+x
);
943 _z
->imag
= a_float_acos(x
);
947 _z
->real
= a_float_acosh(-x
);
948 _z
->imag
= A_FLOAT_PI
;
953 #if defined(A_HAVE_CATANH) && (A_HAVE_CATANH + 0 < 1)
955 #endif /* A_HAVE_CATANH */
956 #if defined(A_HAVE_CATANH) && !defined A_COMPLEX
957 a_complex
A_FLOAT_F1(catanh
, a_complex
);
958 #endif /* A_HAVE_CATANH */
959 void a_complex_atanh_(a_complex
*_z
)
961 #if defined(A_HAVE_CATANH) && defined(A_COMPLEX)
968 *u
.z
= A_FLOAT_F1(catanh
, *u
.z
);
969 #elif defined(A_HAVE_CATANH)
970 *_z
= A_FLOAT_F1(catanh
, *_z
);
971 #else /* !A_HAVE_CATANH */
974 a_complex_mul_imag_(_z
, +1);
976 a_complex_mul_imag_(_z
, -1);
980 a_complex_atanh_real(_z
, _z
->real
);
982 #endif /* A_HAVE_CATANH */
985 void a_complex_atanh_real(a_complex
*_z
, a_float x
)
989 _z
->real
= a_float_atanh(x
);
994 _z
->real
= a_float_atanh(1 / x
);
995 _z
->imag
= (x
< 0) ? +A_FLOAT_PI_2
: -A_FLOAT_PI_2
;
999 void a_complex_asech_(a_complex
*_z
)
1002 a_complex_acosh_(_z
);
1005 void a_complex_acsch_(a_complex
*_z
)
1008 a_complex_asinh_(_z
);
1011 void a_complex_acoth_(a_complex
*_z
)
1014 a_complex_atanh_(_z
);