format with clang-format-18
[liba.git] / src / complex.c
bloba54defaa93a032088b8ecf91488198b0ea8eb722
1 #include "a/a.h"
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 */
8 #define LIBA_COMPLEX_C
9 #include "a/complex.h"
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__)
21 #include <complex.h>
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 */
28 #include "a/math.h"
29 #include <stdlib.h>
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 */
46 union
48 char const *s;
49 char *p;
50 } u;
51 u.s = str;
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);
58 break;
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);
66 break;
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)
84 a_float r, u;
85 a_float const xabs = a_float_abs(z.real);
86 a_float const yabs = a_float_abs(z.imag);
87 if (xabs >= yabs)
89 r = xabs;
90 u = yabs / xabs;
92 else
94 r = yabs;
95 u = xabs / yabs;
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);
116 return 0;
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)
164 #undef A_HAVE_CSQRT
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)
172 union
174 a_complex *_z;
175 A_COMPLEX *z;
176 } u;
177 u._z = _z;
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);
186 a_float w;
187 if (x >= y)
189 a_float u = y / x;
190 w = A_FLOAT_SQRT1_2 * a_float_sqrt(x) * a_float_sqrt(a_float_sqrt(u * u + 1) + 1);
192 else
194 a_float u = x / y;
195 w = A_FLOAT_SQRT1_2 * a_float_sqrt(y) * a_float_sqrt(a_float_sqrt(u * u + 1) + u);
197 if (_z->real >= 0)
199 _z->real = w;
200 _z->imag = _z->imag / (2 * w);
202 else
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)
213 if (x >= 0)
215 _z->real = a_float_sqrt(x);
216 _z->imag = 0;
218 else
220 _z->real = 0;
221 _z->imag = a_float_sqrt(-x);
225 #if defined(A_HAVE_CPOW) && (A_HAVE_CPOW + 0 < 1)
226 #undef A_HAVE_CPOW
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)
234 union
236 a_complex *_z;
237 A_COMPLEX *z;
238 } u, v;
239 u._z = _z;
240 v._z = &a;
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);
253 else
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);
270 else
272 _z->real = (a == 0) ? 1 : 0;
276 #if defined(A_HAVE_CEXP) && (A_HAVE_CEXP + 0 < 1)
277 #undef A_HAVE_CEXP
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)
285 union
287 a_complex *_z;
288 A_COMPLEX *z;
289 } u;
290 u._z = _z;
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)
300 #undef A_HAVE_CLOG
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)
308 union
310 a_complex *_z;
311 A_COMPLEX *z;
312 } u;
313 u._z = _z;
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)
325 a_complex_log_(_z);
326 a_complex_mul_real_(_z, A_FLOAT_LN1_2);
329 void a_complex_log10_(a_complex *_z)
331 a_complex_log_(_z);
332 a_complex_mul_real_(_z, A_FLOAT_LN1_10);
335 void a_complex_logb_(a_complex *_z, a_complex b)
337 a_complex_log_(_z);
338 a_complex_log_(&b);
339 a_complex_div_(_z, b);
342 #if defined(A_HAVE_CSIN) && (A_HAVE_CSIN + 0 < 1)
343 #undef A_HAVE_CSIN
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)
351 union
353 a_complex *_z;
354 A_COMPLEX *z;
355 } u;
356 u._z = _z;
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 */
361 if (_z->imag != 0)
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);
367 else
369 _z->real = a_float_sin(_z->real);
371 #endif /* A_HAVE_CSIN */
374 #if defined(A_HAVE_CCOS) && (A_HAVE_CCOS + 0 < 1)
375 #undef A_HAVE_CCOS
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)
383 union
385 a_complex *_z;
386 A_COMPLEX *z;
387 } u;
388 u._z = _z;
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 */
393 if (_z->imag != 0)
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);
399 else
401 _z->real = a_float_cos(_z->real);
403 #endif /* A_HAVE_CCOS */
406 #if defined(A_HAVE_CTAN) && (A_HAVE_CTAN + 0 < 1)
407 #undef A_HAVE_CTAN
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)
415 union
417 a_complex *_z;
418 A_COMPLEX *z;
419 } u;
420 u._z = _z;
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;
433 else
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)
443 a_complex_cos_(_z);
444 a_complex_inv_(_z);
447 void a_complex_csc_(a_complex *_z)
449 a_complex_sin_(_z);
450 a_complex_inv_(_z);
453 void a_complex_cot_(a_complex *_z)
455 a_complex_tan_(_z);
456 a_complex_inv_(_z);
459 #if defined(A_HAVE_CASIN) && (A_HAVE_CASIN + 0 < 1)
460 #undef A_HAVE_CASIN
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)
468 union
470 a_complex *_z;
471 A_COMPLEX *z;
472 } u;
473 u._z = _z;
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 */
478 if (_z->imag != 0)
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);
495 else if (x <= 1)
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));
500 else
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)
508 a_float am1;
509 if (x < 1)
511 am1 = A_FLOAT_C(0.5) * (y2 / (r + x + 1) + y2 / (s + 1 - x));
513 else
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));
519 else
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; }
526 else
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);
538 _z->imag = 0;
540 else
542 if (x > 0)
544 _z->real = +A_FLOAT_PI_2;
545 _z->imag = -a_float_acosh(+x);
547 else
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)
556 #undef A_HAVE_CACOS
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)
564 union
566 a_complex *_z;
567 A_COMPLEX *z;
568 } u;
569 u._z = _z;
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 */
574 if (_z->imag != 0)
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);
591 else if (x <= 1)
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);
596 else
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)
604 a_float am1;
605 if (x < 1)
607 am1 = A_FLOAT_C(0.5) * (y2 / (r + x + 1) + y2 / (s + 1 - x));
609 else
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));
615 else
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; }
622 else
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);
634 _z->imag = 0;
636 else
638 if (x > 0)
640 _z->real = 0;
641 _z->imag = +a_float_acosh(+x);
643 else
645 _z->real = A_FLOAT_PI;
646 _z->imag = -a_float_acosh(-x);
651 #if defined(A_HAVE_CATAN) && (A_HAVE_CATAN + 0 < 1)
652 #undef A_HAVE_CATAN
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)
660 union
662 a_complex *_z;
663 A_COMPLEX *z;
664 } u;
665 u._z = _z;
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 */
670 if (_z->imag != 0)
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));
679 else
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);
685 if (_z->real != 0)
687 _z->real = A_FLOAT_C(0.5) * a_float_atan2(2 * _z->real, (1 + r) * (1 - r));
689 else
691 if (imag > 1)
693 _z->real = +A_FLOAT_PI;
695 else if (imag < -1)
697 _z->real = -A_FLOAT_PI;
699 else
701 _z->real = 0;
705 else
707 _z->real = a_float_atan(_z->real);
709 #endif /* A_HAVE_CATAN */
712 void a_complex_asec_(a_complex *_z)
714 a_complex_inv_(_z);
715 a_complex_acos_(_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);
723 _z->imag = 0;
725 else
727 if (x >= 0)
729 _z->real = 0;
730 _z->imag = +a_float_acosh(+1 / x);
732 else
734 _z->real = A_FLOAT_PI;
735 _z->imag = -a_float_acosh(-1 / x);
740 void a_complex_acsc_(a_complex *_z)
742 a_complex_inv_(_z);
743 a_complex_asin_(_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);
751 _z->imag = 0;
753 else
755 if (x >= 0)
757 _z->real = +A_FLOAT_PI_2;
758 _z->imag = -a_float_acosh(+1 / x);
760 else
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)
772 a_complex_inv_(_z);
773 a_complex_atan_(_z);
775 else
777 _z->real = A_FLOAT_PI_2;
781 #if defined(A_HAVE_CSINH) && (A_HAVE_CSINH + 0 < 1)
782 #undef A_HAVE_CSINH
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)
790 union
792 a_complex *_z;
793 A_COMPLEX *z;
794 } u;
795 u._z = _z;
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)
807 #undef A_HAVE_CCOSH
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)
815 union
817 a_complex *_z;
818 A_COMPLEX *z;
819 } u;
820 u._z = _z;
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)
832 #undef A_HAVE_CTANH
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)
840 union
842 a_complex *_z;
843 A_COMPLEX *z;
844 } u;
845 u._z = _z;
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;
858 else
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)
868 a_complex_cosh_(_z);
869 a_complex_inv_(_z);
872 void a_complex_csch_(a_complex *_z)
874 a_complex_sinh_(_z);
875 a_complex_inv_(_z);
878 void a_complex_coth_(a_complex *_z)
880 a_complex_tanh_(_z);
881 a_complex_inv_(_z);
884 #if defined(A_HAVE_CASINH) && (A_HAVE_CASINH + 0 < 1)
885 #undef A_HAVE_CASINH
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)
893 union
895 a_complex *_z;
896 A_COMPLEX *z;
897 } u;
898 u._z = _z;
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);
904 a_complex_asin_(_z);
905 a_complex_mul_imag_(_z, -1);
906 #endif /* A_HAVE_CASINH */
909 #if defined(A_HAVE_CACOSH) && (A_HAVE_CACOSH + 0 < 1)
910 #undef A_HAVE_CACOSH
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)
918 union
920 a_complex *_z;
921 A_COMPLEX *z;
922 } u;
923 u._z = _z;
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 */
928 a_complex_acsc_(_z);
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)
935 if (x >= 1)
937 _z->real = a_float_acosh(+x);
938 _z->imag = 0;
940 else if (x >= -1)
942 _z->real = 0;
943 _z->imag = a_float_acos(x);
945 else
947 _z->real = a_float_acosh(-x);
948 _z->imag = A_FLOAT_PI;
952 #undef A_HAVE_CATANH
953 #if defined(A_HAVE_CATANH) && (A_HAVE_CATANH + 0 < 1)
954 #undef A_HAVE_CATANH
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)
962 union
964 a_complex *_z;
965 A_COMPLEX *z;
966 } u;
967 u._z = _z;
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 */
972 if (_z->imag != 0)
974 a_complex_mul_imag_(_z, +1);
975 a_complex_atan_(_z);
976 a_complex_mul_imag_(_z, -1);
978 else
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)
987 if (x > -1 && x < 1)
989 _z->real = a_float_atanh(x);
990 _z->imag = 0;
992 else
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)
1001 a_complex_inv_(_z);
1002 a_complex_acosh_(_z);
1005 void a_complex_acsch_(a_complex *_z)
1007 a_complex_inv_(_z);
1008 a_complex_asinh_(_z);
1011 void a_complex_acoth_(a_complex *_z)
1013 a_complex_inv_(_z);
1014 a_complex_atanh_(_z);