├── .gitignore ├── COPYRIGHT ├── README ├── __cexp.c ├── __cexpf.c ├── __invtrigl.h ├── cabs.c ├── cabsf.c ├── cabsl.c ├── cacos.c ├── cacosf.c ├── cacosh.c ├── cacoshf.c ├── cacoshl.c ├── cacosl.c ├── carg.c ├── cargf.c ├── cargl.c ├── casin.c ├── casinf.c ├── casinh.c ├── casinhf.c ├── casinhl.c ├── casinl.c ├── catan.c ├── catanf.c ├── catanh.c ├── catanhf.c ├── catanhl.c ├── catanl.c ├── ccos.c ├── ccosf.c ├── ccosh.c ├── ccoshf.c ├── ccoshl.c ├── ccosl.c ├── cexp.c ├── cexpf.c ├── cexpl.c ├── cimag.c ├── cimagf.c ├── cimagl.c ├── clog.c ├── clogf.c ├── clogl.c ├── conj.c ├── conjf.c ├── conjl.c ├── cpow.c ├── cpowf.c ├── cpowl.c ├── cproj.c ├── cprojf.c ├── cprojl.c ├── creal.c ├── crealf.c ├── creall.c ├── csin.c ├── csinf.c ├── csinh.c ├── csinhf.c ├── csinhl.c ├── csinl.c ├── csqrt.c ├── csqrtf.c ├── csqrtl.c ├── ctan.c ├── ctanf.c ├── ctanh.c ├── ctanhf.c ├── ctanhl.c ├── ctanl.c ├── include ├── complex.h └── libm.h └── makefile /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.a 4 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | musl as a whole is licensed under the following standard MIT license: 2 | 3 | ---------------------------------------------------------------------- 4 | Copyright © 2005-2014 Rich Felker, et al. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | ---------------------------------------------------------------------- 25 | 26 | Authors/contributors include: 27 | 28 | Alex Dowad 29 | Alexander Monakov 30 | Anthony G. Basile 31 | Arvid Picciani 32 | Bobby Bingham 33 | Boris Brezillon 34 | Brent Cook 35 | Chris Spiegel 36 | Clément Vasseur 37 | Daniel Micay 38 | Denys Vlasenko 39 | Emil Renner Berthing 40 | Felix Fietkau 41 | Felix Janda 42 | Gianluca Anzolin 43 | Hauke Mehrtens 44 | Hiltjo Posthuma 45 | Isaac Dunham 46 | Jaydeep Patil 47 | Jens Gustedt 48 | Jeremy Huntwork 49 | Jo-Philipp Wich 50 | Joakim Sindholt 51 | John Spencer 52 | Josiah Worcester 53 | Justin Cormack 54 | Khem Raj 55 | Kylie McClain 56 | Luca Barbato 57 | Luka Perkov 58 | M Farkas-Dyck (Strake) 59 | Mahesh Bodapati 60 | Michael Forney 61 | Natanael Copa 62 | Nicholas J. Kain 63 | orc 64 | Pascal Cuoq 65 | Petr Hosek 66 | Pierre Carrier 67 | Rich Felker 68 | Richard Pennington 69 | Shiz 70 | sin 71 | Solar Designer 72 | Stefan Kristiansson 73 | Szabolcs Nagy 74 | Timo Teräs 75 | Trutz Behn 76 | Valentin Ochs 77 | William Haddon 78 | 79 | Portions of this software are derived from third-party works licensed 80 | under terms compatible with the above MIT license: 81 | 82 | The TRE regular expression implementation (src/regex/reg* and 83 | src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed 84 | under a 2-clause BSD license (license text in the source files). The 85 | included version has been heavily modified by Rich Felker in 2012, in 86 | the interests of size, simplicity, and namespace cleanliness. 87 | 88 | Much of the math library code (src/math/* and src/complex/*) is 89 | Copyright © 1993,2004 Sun Microsystems or 90 | Copyright © 2003-2011 David Schultz or 91 | Copyright © 2003-2009 Steven G. Kargl or 92 | Copyright © 2003-2009 Bruce D. Evans or 93 | Copyright © 2008 Stephen L. Moshier 94 | and labelled as such in comments in the individual source files. All 95 | have been licensed under extremely permissive terms. 96 | 97 | The ARM memcpy code (src/string/arm/memcpy_el.S) is Copyright © 2008 98 | The Android Open Source Project and is licensed under a two-clause BSD 99 | license. It was taken from Bionic libc, used on Android. 100 | 101 | The implementation of DES for crypt (src/crypt/crypt_des.c) is 102 | Copyright © 1994 David Burren. It is licensed under a BSD license. 103 | 104 | The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was 105 | originally written by Solar Designer and placed into the public 106 | domain. The code also comes with a fallback permissive license for use 107 | in jurisdictions that may not recognize the public domain. 108 | 109 | The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 110 | Valentin Ochs and is licensed under an MIT-style license. 111 | 112 | The BSD PRNG implementation (src/prng/random.c) and XSI search API 113 | (src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and 114 | licensed under following terms: "Permission to use, copy, modify, 115 | and/or distribute this code for any purpose with or without fee is 116 | hereby granted. There is no warranty." 117 | 118 | The x86_64 port was written by Nicholas J. Kain and is licensed under 119 | the standard MIT terms. 120 | 121 | The mips and microblaze ports were originally written by Richard 122 | Pennington for use in the ellcc project. The original code was adapted 123 | by Rich Felker for build system and code conventions during upstream 124 | integration. It is licensed under the standard MIT terms. 125 | 126 | The mips64 port was contributed by Imagination Technologies and is 127 | licensed under the standard MIT terms. 128 | 129 | The powerpc port was also originally written by Richard Pennington, 130 | and later supplemented and integrated by John Spencer. It is licensed 131 | under the standard MIT terms. 132 | 133 | All other files which have no copyright comments are original works 134 | produced specifically for use as part of this library, written either 135 | by Rich Felker, the main author of the library, or by one or more 136 | contibutors listed above. Details on authorship of individual files 137 | can be found in the git version control history of the project. The 138 | omission of copyright and license comments in each file is in the 139 | interest of source tree size. 140 | 141 | In addition, permission is hereby granted for all public header files 142 | (include/* and arch/*/bits/*) and crt files intended to be linked into 143 | applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit 144 | the copyright notice and permission notice otherwise required by the 145 | license, and to use these files without any requirement of 146 | attribution. These files include substantial contributions from: 147 | 148 | Bobby Bingham 149 | John Spencer 150 | Nicholas J. Kain 151 | Rich Felker 152 | Richard Pennington 153 | Stefan Kristiansson 154 | Szabolcs Nagy 155 | 156 | all of whom have explicitly granted such permission. 157 | 158 | This file previously contained text expressing a belief that most of 159 | the files covered by the above exception were sufficiently trivial not 160 | to be subject to copyright, resulting in confusion over whether it 161 | negated the permissions granted in the license. In the spirit of 162 | permissive licensing, and of not having licensing issues being an 163 | obstacle to adoption, that text has been removed. 164 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | libcomplex is the complex math portion from musl's libm. musl is a complete libc whose license is included with this project. 2 | 3 | libcomplex is provided as an easy way to build complex math for systems which do not provide it. For example, developers targeting Android native are not provided with complex math functionality for early API versions. This library can be easily built and linked to for that purpose. 4 | -------------------------------------------------------------------------------- /__cexp.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/k_exp.c */ 2 | /*- 3 | * Copyright (c) 2011 David Schultz 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | 28 | #include "libm.h" 29 | 30 | static const uint32_t k = 1799; /* constant for reduction */ 31 | static const double kln2 = 1246.97177782734161156; /* k * ln2 */ 32 | 33 | /* 34 | * Compute exp(x), scaled to avoid spurious overflow. An exponent is 35 | * returned separately in 'expt'. 36 | * 37 | * Input: ln(DBL_MAX) <= x < ln(2 * DBL_MAX / DBL_MIN_DENORM) ~= 1454.91 38 | * Output: 2**1023 <= y < 2**1024 39 | */ 40 | static double __frexp_exp(double x, int *expt) 41 | { 42 | double exp_x; 43 | uint32_t hx; 44 | 45 | /* 46 | * We use exp(x) = exp(x - kln2) * 2**k, carefully chosen to 47 | * minimize |exp(kln2) - 2**k|. We also scale the exponent of 48 | * exp_x to MAX_EXP so that the result can be multiplied by 49 | * a tiny number without losing accuracy due to denormalization. 50 | */ 51 | exp_x = exp(x - kln2); 52 | GET_HIGH_WORD(hx, exp_x); 53 | *expt = (hx >> 20) - (0x3ff + 1023) + k; 54 | SET_HIGH_WORD(exp_x, (hx & 0xfffff) | ((0x3ff + 1023) << 20)); 55 | return exp_x; 56 | } 57 | 58 | /* 59 | * __ldexp_cexp(x, expt) compute exp(x) * 2**expt. 60 | * It is intended for large arguments (real part >= ln(DBL_MAX)) 61 | * where care is needed to avoid overflow. 62 | * 63 | * The present implementation is narrowly tailored for our hyperbolic and 64 | * exponential functions. We assume expt is small (0 or -1), and the caller 65 | * has filtered out very large x, for which overflow would be inevitable. 66 | */ 67 | double complex __ldexp_cexp(double complex z, int expt) 68 | { 69 | double x, y, exp_x, scale1, scale2; 70 | int ex_expt, half_expt; 71 | 72 | x = creal(z); 73 | y = cimag(z); 74 | exp_x = __frexp_exp(x, &ex_expt); 75 | expt += ex_expt; 76 | 77 | /* 78 | * Arrange so that scale1 * scale2 == 2**expt. We use this to 79 | * compensate for scalbn being horrendously slow. 80 | */ 81 | half_expt = expt / 2; 82 | INSERT_WORDS(scale1, (0x3ff + half_expt) << 20, 0); 83 | half_expt = expt - half_expt; 84 | INSERT_WORDS(scale2, (0x3ff + half_expt) << 20, 0); 85 | 86 | return CMPLX(cos(y) * exp_x * scale1 * scale2, sin(y) * exp_x * scale1 * scale2); 87 | } 88 | -------------------------------------------------------------------------------- /__cexpf.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/k_expf.c */ 2 | /*- 3 | * Copyright (c) 2011 David Schultz 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | 28 | #include "libm.h" 29 | 30 | static const uint32_t k = 235; /* constant for reduction */ 31 | static const float kln2 = 162.88958740F; /* k * ln2 */ 32 | 33 | /* 34 | * See __cexp.c for details. 35 | * 36 | * Input: ln(FLT_MAX) <= x < ln(2 * FLT_MAX / FLT_MIN_DENORM) ~= 192.7 37 | * Output: 2**127 <= y < 2**128 38 | */ 39 | static float __frexp_expf(float x, int *expt) 40 | { 41 | float exp_x; 42 | uint32_t hx; 43 | 44 | exp_x = expf(x - kln2); 45 | GET_FLOAT_WORD(hx, exp_x); 46 | *expt = (hx >> 23) - (0x7f + 127) + k; 47 | SET_FLOAT_WORD(exp_x, (hx & 0x7fffff) | ((0x7f + 127) << 23)); 48 | return exp_x; 49 | } 50 | 51 | float complex __ldexp_cexpf(float complex z, int expt) 52 | { 53 | float x, y, exp_x, scale1, scale2; 54 | int ex_expt, half_expt; 55 | 56 | x = crealf(z); 57 | y = cimagf(z); 58 | exp_x = __frexp_expf(x, &ex_expt); 59 | expt += ex_expt; 60 | 61 | half_expt = expt / 2; 62 | SET_FLOAT_WORD(scale1, (0x7f + half_expt) << 23); 63 | half_expt = expt - half_expt; 64 | SET_FLOAT_WORD(scale2, (0x7f + half_expt) << 23); 65 | 66 | return CMPLXF(cosf(y) * exp_x * scale1 * scale2, 67 | sinf(y) * exp_x * scale1 * scale2); 68 | } 69 | -------------------------------------------------------------------------------- /__invtrigl.h: -------------------------------------------------------------------------------- 1 | /* shared by acosl, asinl and atan2l */ 2 | #define pio2_hi __pio2_hi 3 | #define pio2_lo __pio2_lo 4 | extern const long double pio2_hi, pio2_lo; 5 | 6 | long double __invtrigl_R(long double z); 7 | -------------------------------------------------------------------------------- /cabs.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double cabs(double complex z) 4 | { 5 | return hypot(creal(z), cimag(z)); 6 | } 7 | -------------------------------------------------------------------------------- /cabsf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float cabsf(float complex z) 4 | { 5 | return hypotf(crealf(z), cimagf(z)); 6 | } 7 | -------------------------------------------------------------------------------- /cabsl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double cabsl(long double complex z) 5 | { 6 | return cabs(z); 7 | } 8 | #else 9 | long double cabsl(long double complex z) 10 | { 11 | return hypotl(creall(z), cimagl(z)); 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /cacos.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | // FIXME: Hull et al. "Implementing the complex arcsine and arccosine functions using exception handling" 1997 4 | 5 | /* acos(z) = pi/2 - asin(z) */ 6 | 7 | double complex cacos(double complex z) 8 | { 9 | z = casin(z); 10 | return CMPLX(M_PI_2 - creal(z), -cimag(z)); 11 | } 12 | -------------------------------------------------------------------------------- /cacosf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | // FIXME 4 | 5 | float complex cacosf(float complex z) 6 | { 7 | z = casinf(z); 8 | return CMPLXF((float)M_PI_2 - crealf(z), -cimagf(z)); 9 | } 10 | -------------------------------------------------------------------------------- /cacosh.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | /* acosh(z) = i acos(z) */ 4 | 5 | double complex cacosh(double complex z) 6 | { 7 | z = cacos(z); 8 | return CMPLX(-cimag(z), creal(z)); 9 | } 10 | -------------------------------------------------------------------------------- /cacoshf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float complex cacoshf(float complex z) 4 | { 5 | z = cacosf(z); 6 | return CMPLXF(-cimagf(z), crealf(z)); 7 | } 8 | -------------------------------------------------------------------------------- /cacoshl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex cacoshl(long double complex z) 5 | { 6 | return cacosh(z); 7 | } 8 | #else 9 | long double complex cacoshl(long double complex z) 10 | { 11 | z = cacosl(z); 12 | return CMPLXL(-cimagl(z), creall(z)); 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /cacosl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex cacosl(long double complex z) 5 | { 6 | return cacos(z); 7 | } 8 | #else 9 | // FIXME 10 | #define PI_2 1.57079632679489661923132169163975144L 11 | long double complex cacosl(long double complex z) 12 | { 13 | z = casinl(z); 14 | return CMPLXL(PI_2 - creall(z), -cimagl(z)); 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /carg.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double carg(double complex z) 4 | { 5 | return atan2(cimag(z), creal(z)); 6 | } 7 | -------------------------------------------------------------------------------- /cargf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float cargf(float complex z) 4 | { 5 | return atan2f(cimagf(z), crealf(z)); 6 | } 7 | -------------------------------------------------------------------------------- /cargl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double cargl(long double complex z) 5 | { 6 | return carg(z); 7 | } 8 | #else 9 | long double cargl(long double complex z) 10 | { 11 | return atan2l(cimagl(z), creall(z)); 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /casin.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | // FIXME 4 | 5 | /* asin(z) = -i log(i z + sqrt(1 - z*z)) */ 6 | 7 | double complex casin(double complex z) 8 | { 9 | double complex w; 10 | double x, y; 11 | 12 | x = creal(z); 13 | y = cimag(z); 14 | w = CMPLX(1.0 - (x - y)*(x + y), -2.0*x*y); 15 | return clog(CMPLX(-y, x) + csqrt(w)); 16 | } 17 | -------------------------------------------------------------------------------- /casinf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | // FIXME 4 | 5 | float complex casinf(float complex z) 6 | { 7 | float complex w; 8 | float x, y; 9 | 10 | x = crealf(z); 11 | y = cimagf(z); 12 | w = CMPLXF(1.0 - (x - y)*(x + y), -2.0*x*y); 13 | return clogf(CMPLXF(-y, x) + csqrtf(w)); 14 | } 15 | -------------------------------------------------------------------------------- /casinh.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | /* asinh(z) = -i asin(i z) */ 4 | 5 | double complex casinh(double complex z) 6 | { 7 | z = casin(CMPLX(-cimag(z), creal(z))); 8 | return CMPLX(cimag(z), -creal(z)); 9 | } 10 | -------------------------------------------------------------------------------- /casinhf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float complex casinhf(float complex z) 4 | { 5 | z = casinf(CMPLXF(-cimagf(z), crealf(z))); 6 | return CMPLXF(cimagf(z), -crealf(z)); 7 | } 8 | -------------------------------------------------------------------------------- /casinhl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex casinhl(long double complex z) 5 | { 6 | return casinh(z); 7 | } 8 | #else 9 | long double complex casinhl(long double complex z) 10 | { 11 | z = casinl(CMPLXL(-cimagl(z), creall(z))); 12 | return CMPLXL(cimagl(z), -creall(z)); 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /casinl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex casinl(long double complex z) 5 | { 6 | return casin(z); 7 | } 8 | #else 9 | // FIXME 10 | long double complex casinl(long double complex z) 11 | { 12 | long double complex w; 13 | long double x, y; 14 | 15 | x = creall(z); 16 | y = cimagl(z); 17 | w = CMPLXL(1.0 - (x - y)*(x + y), -2.0*x*y); 18 | return clogl(CMPLXL(-y, x) + csqrtl(w)); 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /catan.c: -------------------------------------------------------------------------------- 1 | /* origin: OpenBSD /usr/src/lib/libm/src/s_catan.c */ 2 | /* 3 | * Copyright (c) 2008 Stephen L. Moshier 4 | * 5 | * Permission to use, copy, modify, and distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | /* 18 | * Complex circular arc tangent 19 | * 20 | * 21 | * SYNOPSIS: 22 | * 23 | * double complex catan(); 24 | * double complex z, w; 25 | * 26 | * w = catan (z); 27 | * 28 | * 29 | * DESCRIPTION: 30 | * 31 | * If 32 | * z = x + iy, 33 | * 34 | * then 35 | * 1 ( 2x ) 36 | * Re w = - arctan(-----------) + k PI 37 | * 2 ( 2 2) 38 | * (1 - x - y ) 39 | * 40 | * ( 2 2) 41 | * 1 (x + (y+1) ) 42 | * Im w = - log(------------) 43 | * 4 ( 2 2) 44 | * (x + (y-1) ) 45 | * 46 | * Where k is an arbitrary integer. 47 | * 48 | * catan(z) = -i catanh(iz). 49 | * 50 | * ACCURACY: 51 | * 52 | * Relative error: 53 | * arithmetic domain # trials peak rms 54 | * DEC -10,+10 5900 1.3e-16 7.8e-18 55 | * IEEE -10,+10 30000 2.3e-15 8.5e-17 56 | * The check catan( ctan(z) ) = z, with |x| and |y| < PI/2, 57 | * had peak relative error 1.5e-16, rms relative error 58 | * 2.9e-17. See also clog(). 59 | */ 60 | 61 | #include "libm.h" 62 | 63 | #define MAXNUM 1.0e308 64 | 65 | static const double DP1 = 3.14159265160560607910E0; 66 | static const double DP2 = 1.98418714791870343106E-9; 67 | static const double DP3 = 1.14423774522196636802E-17; 68 | 69 | static double _redupi(double x) 70 | { 71 | double t; 72 | long i; 73 | 74 | t = x/M_PI; 75 | if (t >= 0.0) 76 | t += 0.5; 77 | else 78 | t -= 0.5; 79 | 80 | i = t; /* the multiple */ 81 | t = i; 82 | t = ((x - t * DP1) - t * DP2) - t * DP3; 83 | return t; 84 | } 85 | 86 | double complex catan(double complex z) 87 | { 88 | double complex w; 89 | double a, t, x, x2, y; 90 | 91 | x = creal(z); 92 | y = cimag(z); 93 | 94 | if (x == 0.0 && y > 1.0) 95 | goto ovrf; 96 | 97 | x2 = x * x; 98 | a = 1.0 - x2 - (y * y); 99 | if (a == 0.0) 100 | goto ovrf; 101 | 102 | t = 0.5 * atan2(2.0 * x, a); 103 | w = _redupi(t); 104 | 105 | t = y - 1.0; 106 | a = x2 + (t * t); 107 | if (a == 0.0) 108 | goto ovrf; 109 | 110 | t = y + 1.0; 111 | a = (x2 + t * t)/a; 112 | w = w + (0.25 * log(a)) * I; 113 | return w; 114 | 115 | ovrf: 116 | // FIXME 117 | w = MAXNUM + MAXNUM * I; 118 | return w; 119 | } 120 | -------------------------------------------------------------------------------- /catanf.c: -------------------------------------------------------------------------------- 1 | /* origin: OpenBSD /usr/src/lib/libm/src/s_catanf.c */ 2 | /* 3 | * Copyright (c) 2008 Stephen L. Moshier 4 | * 5 | * Permission to use, copy, modify, and distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | /* 18 | * Complex circular arc tangent 19 | * 20 | * 21 | * SYNOPSIS: 22 | * 23 | * float complex catanf(); 24 | * float complex z, w; 25 | * 26 | * w = catanf( z ); 27 | * 28 | * 29 | * DESCRIPTION: 30 | * 31 | * If 32 | * z = x + iy, 33 | * 34 | * then 35 | * 1 ( 2x ) 36 | * Re w = - arctan(-----------) + k PI 37 | * 2 ( 2 2) 38 | * (1 - x - y ) 39 | * 40 | * ( 2 2) 41 | * 1 (x + (y+1) ) 42 | * Im w = - log(------------) 43 | * 4 ( 2 2) 44 | * (x + (y-1) ) 45 | * 46 | * Where k is an arbitrary integer. 47 | * 48 | * 49 | * ACCURACY: 50 | * 51 | * Relative error: 52 | * arithmetic domain # trials peak rms 53 | * IEEE -10,+10 30000 2.3e-6 5.2e-8 54 | */ 55 | 56 | #include "libm.h" 57 | 58 | #define MAXNUMF 1.0e38F 59 | 60 | static const double DP1 = 3.140625; 61 | static const double DP2 = 9.67502593994140625E-4; 62 | static const double DP3 = 1.509957990978376432E-7; 63 | 64 | static float _redupif(float xx) 65 | { 66 | float x, t; 67 | long i; 68 | 69 | x = xx; 70 | t = x/(float)M_PI; 71 | if (t >= 0.0f) 72 | t += 0.5f; 73 | else 74 | t -= 0.5f; 75 | 76 | i = t; /* the multiple */ 77 | t = i; 78 | t = ((x - t * DP1) - t * DP2) - t * DP3; 79 | return t; 80 | } 81 | 82 | float complex catanf(float complex z) 83 | { 84 | float complex w; 85 | float a, t, x, x2, y; 86 | 87 | x = crealf(z); 88 | y = cimagf(z); 89 | 90 | if ((x == 0.0f) && (y > 1.0f)) 91 | goto ovrf; 92 | 93 | x2 = x * x; 94 | a = 1.0f - x2 - (y * y); 95 | if (a == 0.0f) 96 | goto ovrf; 97 | 98 | t = 0.5f * atan2f(2.0f * x, a); 99 | w = _redupif(t); 100 | 101 | t = y - 1.0f; 102 | a = x2 + (t * t); 103 | if (a == 0.0f) 104 | goto ovrf; 105 | 106 | t = y + 1.0f; 107 | a = (x2 + (t * t))/a; 108 | w = w + (0.25f * logf (a)) * I; 109 | return w; 110 | 111 | ovrf: 112 | // FIXME 113 | w = MAXNUMF + MAXNUMF * I; 114 | return w; 115 | } 116 | -------------------------------------------------------------------------------- /catanh.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | /* atanh = -i atan(i z) */ 4 | 5 | double complex catanh(double complex z) 6 | { 7 | z = catan(CMPLX(-cimag(z), creal(z))); 8 | return CMPLX(cimag(z), -creal(z)); 9 | } 10 | -------------------------------------------------------------------------------- /catanhf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float complex catanhf(float complex z) 4 | { 5 | z = catanf(CMPLXF(-cimagf(z), crealf(z))); 6 | return CMPLXF(cimagf(z), -crealf(z)); 7 | } 8 | -------------------------------------------------------------------------------- /catanhl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex catanhl(long double complex z) 5 | { 6 | return catanh(z); 7 | } 8 | #else 9 | long double complex catanhl(long double complex z) 10 | { 11 | z = catanl(CMPLXL(-cimagl(z), creall(z))); 12 | return CMPLXL(cimagl(z), -creall(z)); 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /catanl.c: -------------------------------------------------------------------------------- 1 | /* origin: OpenBSD /usr/src/lib/libm/src/s_catanl.c */ 2 | /* 3 | * Copyright (c) 2008 Stephen L. Moshier 4 | * 5 | * Permission to use, copy, modify, and distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | /* 18 | * Complex circular arc tangent 19 | * 20 | * 21 | * SYNOPSIS: 22 | * 23 | * long double complex catanl(); 24 | * long double complex z, w; 25 | * 26 | * w = catanl( z ); 27 | * 28 | * 29 | * DESCRIPTION: 30 | * 31 | * If 32 | * z = x + iy, 33 | * 34 | * then 35 | * 1 ( 2x ) 36 | * Re w = - arctan(-----------) + k PI 37 | * 2 ( 2 2) 38 | * (1 - x - y ) 39 | * 40 | * ( 2 2) 41 | * 1 (x + (y+1) ) 42 | * Im w = - log(------------) 43 | * 4 ( 2 2) 44 | * (x + (y-1) ) 45 | * 46 | * Where k is an arbitrary integer. 47 | * 48 | * 49 | * ACCURACY: 50 | * 51 | * Relative error: 52 | * arithmetic domain # trials peak rms 53 | * DEC -10,+10 5900 1.3e-16 7.8e-18 54 | * IEEE -10,+10 30000 2.3e-15 8.5e-17 55 | * The check catan( ctan(z) ) = z, with |x| and |y| < PI/2, 56 | * had peak relative error 1.5e-16, rms relative error 57 | * 2.9e-17. See also clog(). 58 | */ 59 | 60 | #include 61 | #include 62 | #include "libm.h" 63 | 64 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 65 | long double complex catanl(long double complex z) 66 | { 67 | return catan(z); 68 | } 69 | #else 70 | static const long double PIL = 3.141592653589793238462643383279502884197169L; 71 | static const long double DP1 = 3.14159265358979323829596852490908531763125L; 72 | static const long double DP2 = 1.6667485837041756656403424829301998703007e-19L; 73 | static const long double DP3 = 1.8830410776607851167459095484560349402753e-39L; 74 | 75 | static long double redupil(long double x) 76 | { 77 | long double t; 78 | long i; 79 | 80 | t = x / PIL; 81 | if (t >= 0.0L) 82 | t += 0.5L; 83 | else 84 | t -= 0.5L; 85 | 86 | i = t; /* the multiple */ 87 | t = i; 88 | t = ((x - t * DP1) - t * DP2) - t * DP3; 89 | return t; 90 | } 91 | 92 | long double complex catanl(long double complex z) 93 | { 94 | long double complex w; 95 | long double a, t, x, x2, y; 96 | 97 | x = creall(z); 98 | y = cimagl(z); 99 | 100 | if ((x == 0.0L) && (y > 1.0L)) 101 | goto ovrf; 102 | 103 | x2 = x * x; 104 | a = 1.0L - x2 - (y * y); 105 | if (a == 0.0L) 106 | goto ovrf; 107 | 108 | t = atan2l(2.0L * x, a) * 0.5L; 109 | w = redupil(t); 110 | 111 | t = y - 1.0L; 112 | a = x2 + (t * t); 113 | if (a == 0.0L) 114 | goto ovrf; 115 | 116 | t = y + 1.0L; 117 | a = (x2 + (t * t)) / a; 118 | w = w + (0.25L * logl(a)) * I; 119 | return w; 120 | 121 | ovrf: 122 | // FIXME 123 | w = LDBL_MAX + LDBL_MAX * I; 124 | return w; 125 | } 126 | #endif 127 | -------------------------------------------------------------------------------- /ccos.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | /* cos(z) = cosh(i z) */ 4 | 5 | double complex ccos(double complex z) 6 | { 7 | return ccosh(CMPLX(-cimag(z), creal(z))); 8 | } 9 | -------------------------------------------------------------------------------- /ccosf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float complex ccosf(float complex z) 4 | { 5 | return ccoshf(CMPLXF(-cimagf(z), crealf(z))); 6 | } 7 | -------------------------------------------------------------------------------- /ccosh.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_ccosh.c */ 2 | /*- 3 | * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice unmodified, this list of conditions, and the following 11 | * disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /* 28 | * Hyperbolic cosine of a complex argument z = x + i y. 29 | * 30 | * cosh(z) = cosh(x+iy) 31 | * = cosh(x) cos(y) + i sinh(x) sin(y). 32 | * 33 | * Exceptional values are noted in the comments within the source code. 34 | * These values and the return value were taken from n1124.pdf. 35 | */ 36 | 37 | #include "libm.h" 38 | 39 | static const double huge = 0x1p1023; 40 | 41 | double complex ccosh(double complex z) 42 | { 43 | double x, y, h; 44 | int32_t hx, hy, ix, iy, lx, ly; 45 | 46 | x = creal(z); 47 | y = cimag(z); 48 | 49 | EXTRACT_WORDS(hx, lx, x); 50 | EXTRACT_WORDS(hy, ly, y); 51 | 52 | ix = 0x7fffffff & hx; 53 | iy = 0x7fffffff & hy; 54 | 55 | /* Handle the nearly-non-exceptional cases where x and y are finite. */ 56 | if (ix < 0x7ff00000 && iy < 0x7ff00000) { 57 | if ((iy | ly) == 0) 58 | return CMPLX(cosh(x), x * y); 59 | if (ix < 0x40360000) /* small x: normal case */ 60 | return CMPLX(cosh(x) * cos(y), sinh(x) * sin(y)); 61 | 62 | /* |x| >= 22, so cosh(x) ~= exp(|x|) */ 63 | if (ix < 0x40862e42) { 64 | /* x < 710: exp(|x|) won't overflow */ 65 | h = exp(fabs(x)) * 0.5; 66 | return CMPLX(h * cos(y), copysign(h, x) * sin(y)); 67 | } else if (ix < 0x4096bbaa) { 68 | /* x < 1455: scale to avoid overflow */ 69 | z = __ldexp_cexp(CMPLX(fabs(x), y), -1); 70 | return CMPLX(creal(z), cimag(z) * copysign(1, x)); 71 | } else { 72 | /* x >= 1455: the result always overflows */ 73 | h = huge * x; 74 | return CMPLX(h * h * cos(y), h * sin(y)); 75 | } 76 | } 77 | 78 | /* 79 | * cosh(+-0 +- I Inf) = dNaN + I sign(d(+-0, dNaN))0. 80 | * The sign of 0 in the result is unspecified. Choice = normally 81 | * the same as dNaN. Raise the invalid floating-point exception. 82 | * 83 | * cosh(+-0 +- I NaN) = d(NaN) + I sign(d(+-0, NaN))0. 84 | * The sign of 0 in the result is unspecified. Choice = normally 85 | * the same as d(NaN). 86 | */ 87 | if ((ix | lx) == 0 && iy >= 0x7ff00000) 88 | return CMPLX(y - y, copysign(0, x * (y - y))); 89 | 90 | /* 91 | * cosh(+-Inf +- I 0) = +Inf + I (+-)(+-)0. 92 | * 93 | * cosh(NaN +- I 0) = d(NaN) + I sign(d(NaN, +-0))0. 94 | * The sign of 0 in the result is unspecified. 95 | */ 96 | if ((iy | ly) == 0 && ix >= 0x7ff00000) { 97 | if (((hx & 0xfffff) | lx) == 0) 98 | return CMPLX(x * x, copysign(0, x) * y); 99 | return CMPLX(x * x, copysign(0, (x + x) * y)); 100 | } 101 | 102 | /* 103 | * cosh(x +- I Inf) = dNaN + I dNaN. 104 | * Raise the invalid floating-point exception for finite nonzero x. 105 | * 106 | * cosh(x + I NaN) = d(NaN) + I d(NaN). 107 | * Optionally raises the invalid floating-point exception for finite 108 | * nonzero x. Choice = don't raise (except for signaling NaNs). 109 | */ 110 | if (ix < 0x7ff00000 && iy >= 0x7ff00000) 111 | return CMPLX(y - y, x * (y - y)); 112 | 113 | /* 114 | * cosh(+-Inf + I NaN) = +Inf + I d(NaN). 115 | * 116 | * cosh(+-Inf +- I Inf) = +Inf + I dNaN. 117 | * The sign of Inf in the result is unspecified. Choice = always +. 118 | * Raise the invalid floating-point exception. 119 | * 120 | * cosh(+-Inf + I y) = +Inf cos(y) +- I Inf sin(y) 121 | */ 122 | if (ix >= 0x7ff00000 && ((hx & 0xfffff) | lx) == 0) { 123 | if (iy >= 0x7ff00000) 124 | return CMPLX(x * x, x * (y - y)); 125 | return CMPLX((x * x) * cos(y), x * sin(y)); 126 | } 127 | 128 | /* 129 | * cosh(NaN + I NaN) = d(NaN) + I d(NaN). 130 | * 131 | * cosh(NaN +- I Inf) = d(NaN) + I d(NaN). 132 | * Optionally raises the invalid floating-point exception. 133 | * Choice = raise. 134 | * 135 | * cosh(NaN + I y) = d(NaN) + I d(NaN). 136 | * Optionally raises the invalid floating-point exception for finite 137 | * nonzero y. Choice = don't raise (except for signaling NaNs). 138 | */ 139 | return CMPLX((x * x) * (y - y), (x + x) * (y - y)); 140 | } 141 | -------------------------------------------------------------------------------- /ccoshf.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_ccoshf.c */ 2 | /*- 3 | * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice unmodified, this list of conditions, and the following 11 | * disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /* 28 | * Hyperbolic cosine of a complex argument. See s_ccosh.c for details. 29 | */ 30 | 31 | #include "libm.h" 32 | 33 | static const float huge = 0x1p127; 34 | 35 | float complex ccoshf(float complex z) 36 | { 37 | float x, y, h; 38 | int32_t hx, hy, ix, iy; 39 | 40 | x = crealf(z); 41 | y = cimagf(z); 42 | 43 | GET_FLOAT_WORD(hx, x); 44 | GET_FLOAT_WORD(hy, y); 45 | 46 | ix = 0x7fffffff & hx; 47 | iy = 0x7fffffff & hy; 48 | 49 | if (ix < 0x7f800000 && iy < 0x7f800000) { 50 | if (iy == 0) 51 | return CMPLXF(coshf(x), x * y); 52 | if (ix < 0x41100000) /* small x: normal case */ 53 | return CMPLXF(coshf(x) * cosf(y), sinhf(x) * sinf(y)); 54 | 55 | /* |x| >= 9, so cosh(x) ~= exp(|x|) */ 56 | if (ix < 0x42b17218) { 57 | /* x < 88.7: expf(|x|) won't overflow */ 58 | h = expf(fabsf(x)) * 0.5f; 59 | return CMPLXF(h * cosf(y), copysignf(h, x) * sinf(y)); 60 | } else if (ix < 0x4340b1e7) { 61 | /* x < 192.7: scale to avoid overflow */ 62 | z = __ldexp_cexpf(CMPLXF(fabsf(x), y), -1); 63 | return CMPLXF(crealf(z), cimagf(z) * copysignf(1, x)); 64 | } else { 65 | /* x >= 192.7: the result always overflows */ 66 | h = huge * x; 67 | return CMPLXF(h * h * cosf(y), h * sinf(y)); 68 | } 69 | } 70 | 71 | if (ix == 0 && iy >= 0x7f800000) 72 | return CMPLXF(y - y, copysignf(0, x * (y - y))); 73 | 74 | if (iy == 0 && ix >= 0x7f800000) { 75 | if ((hx & 0x7fffff) == 0) 76 | return CMPLXF(x * x, copysignf(0, x) * y); 77 | return CMPLXF(x * x, copysignf(0, (x + x) * y)); 78 | } 79 | 80 | if (ix < 0x7f800000 && iy >= 0x7f800000) 81 | return CMPLXF(y - y, x * (y - y)); 82 | 83 | if (ix >= 0x7f800000 && (hx & 0x7fffff) == 0) { 84 | if (iy >= 0x7f800000) 85 | return CMPLXF(x * x, x * (y - y)); 86 | return CMPLXF((x * x) * cosf(y), x * sinf(y)); 87 | } 88 | 89 | return CMPLXF((x * x) * (y - y), (x + x) * (y - y)); 90 | } 91 | -------------------------------------------------------------------------------- /ccoshl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | //FIXME 4 | long double complex ccoshl(long double complex z) 5 | { 6 | return ccosh(z); 7 | } 8 | -------------------------------------------------------------------------------- /ccosl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex ccosl(long double complex z) 5 | { 6 | return ccos(z); 7 | } 8 | #else 9 | long double complex ccosl(long double complex z) 10 | { 11 | return ccoshl(CMPLXL(-cimagl(z), creall(z))); 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /cexp.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_cexp.c */ 2 | /*- 3 | * Copyright (c) 2011 David Schultz 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | 28 | #include "libm.h" 29 | 30 | static const uint32_t 31 | exp_ovfl = 0x40862e42, /* high bits of MAX_EXP * ln2 ~= 710 */ 32 | cexp_ovfl = 0x4096b8e4; /* (MAX_EXP - MIN_DENORM_EXP) * ln2 */ 33 | 34 | double complex cexp(double complex z) 35 | { 36 | double x, y, exp_x; 37 | uint32_t hx, hy, lx, ly; 38 | 39 | x = creal(z); 40 | y = cimag(z); 41 | 42 | EXTRACT_WORDS(hy, ly, y); 43 | hy &= 0x7fffffff; 44 | 45 | /* cexp(x + I 0) = exp(x) + I 0 */ 46 | if ((hy | ly) == 0) 47 | return CMPLX(exp(x), y); 48 | EXTRACT_WORDS(hx, lx, x); 49 | /* cexp(0 + I y) = cos(y) + I sin(y) */ 50 | if (((hx & 0x7fffffff) | lx) == 0) 51 | return CMPLX(cos(y), sin(y)); 52 | 53 | if (hy >= 0x7ff00000) { 54 | if (lx != 0 || (hx & 0x7fffffff) != 0x7ff00000) { 55 | /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */ 56 | return CMPLX(y - y, y - y); 57 | } else if (hx & 0x80000000) { 58 | /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */ 59 | return CMPLX(0.0, 0.0); 60 | } else { 61 | /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */ 62 | return CMPLX(x, y - y); 63 | } 64 | } 65 | 66 | if (hx >= exp_ovfl && hx <= cexp_ovfl) { 67 | /* 68 | * x is between 709.7 and 1454.3, so we must scale to avoid 69 | * overflow in exp(x). 70 | */ 71 | return __ldexp_cexp(z, 0); 72 | } else { 73 | /* 74 | * Cases covered here: 75 | * - x < exp_ovfl and exp(x) won't overflow (common case) 76 | * - x > cexp_ovfl, so exp(x) * s overflows for all s > 0 77 | * - x = +-Inf (generated by exp()) 78 | * - x = NaN (spurious inexact exception from y) 79 | */ 80 | exp_x = exp(x); 81 | return CMPLX(exp_x * cos(y), exp_x * sin(y)); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /cexpf.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_cexpf.c */ 2 | /*- 3 | * Copyright (c) 2011 David Schultz 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | 28 | #include "libm.h" 29 | 30 | static const uint32_t 31 | exp_ovfl = 0x42b17218, /* MAX_EXP * ln2 ~= 88.722839355 */ 32 | cexp_ovfl = 0x43400074; /* (MAX_EXP - MIN_DENORM_EXP) * ln2 */ 33 | 34 | float complex cexpf(float complex z) 35 | { 36 | float x, y, exp_x; 37 | uint32_t hx, hy; 38 | 39 | x = crealf(z); 40 | y = cimagf(z); 41 | 42 | GET_FLOAT_WORD(hy, y); 43 | hy &= 0x7fffffff; 44 | 45 | /* cexp(x + I 0) = exp(x) + I 0 */ 46 | if (hy == 0) 47 | return CMPLXF(expf(x), y); 48 | GET_FLOAT_WORD(hx, x); 49 | /* cexp(0 + I y) = cos(y) + I sin(y) */ 50 | if ((hx & 0x7fffffff) == 0) 51 | return CMPLXF(cosf(y), sinf(y)); 52 | 53 | if (hy >= 0x7f800000) { 54 | if ((hx & 0x7fffffff) != 0x7f800000) { 55 | /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */ 56 | return CMPLXF(y - y, y - y); 57 | } else if (hx & 0x80000000) { 58 | /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */ 59 | return CMPLXF(0.0, 0.0); 60 | } else { 61 | /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */ 62 | return CMPLXF(x, y - y); 63 | } 64 | } 65 | 66 | if (hx >= exp_ovfl && hx <= cexp_ovfl) { 67 | /* 68 | * x is between 88.7 and 192, so we must scale to avoid 69 | * overflow in expf(x). 70 | */ 71 | return __ldexp_cexpf(z, 0); 72 | } else { 73 | /* 74 | * Cases covered here: 75 | * - x < exp_ovfl and exp(x) won't overflow (common case) 76 | * - x > cexp_ovfl, so exp(x) * s overflows for all s > 0 77 | * - x = +-Inf (generated by exp()) 78 | * - x = NaN (spurious inexact exception from y) 79 | */ 80 | exp_x = expf(x); 81 | return CMPLXF(exp_x * cosf(y), exp_x * sinf(y)); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /cexpl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | //FIXME 4 | long double complex cexpl(long double complex z) 5 | { 6 | return cexp(z); 7 | } 8 | -------------------------------------------------------------------------------- /cimag.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double (cimag)(double complex z) 4 | { 5 | return cimag(z); 6 | } 7 | -------------------------------------------------------------------------------- /cimagf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float (cimagf)(float complex z) 4 | { 5 | return cimagf(z); 6 | } 7 | -------------------------------------------------------------------------------- /cimagl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | long double (cimagl)(long double complex z) 4 | { 5 | return cimagl(z); 6 | } 7 | -------------------------------------------------------------------------------- /clog.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | // FIXME 4 | 5 | /* log(z) = log(|z|) + i arg(z) */ 6 | 7 | double complex clog(double complex z) 8 | { 9 | double r, phi; 10 | 11 | r = cabs(z); 12 | phi = carg(z); 13 | return CMPLX(log(r), phi); 14 | } 15 | -------------------------------------------------------------------------------- /clogf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | // FIXME 4 | 5 | float complex clogf(float complex z) 6 | { 7 | float r, phi; 8 | 9 | r = cabsf(z); 10 | phi = cargf(z); 11 | return CMPLXF(logf(r), phi); 12 | } 13 | -------------------------------------------------------------------------------- /clogl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex clogl(long double complex z) 5 | { 6 | return clog(z); 7 | } 8 | #else 9 | // FIXME 10 | long double complex clogl(long double complex z) 11 | { 12 | long double r, phi; 13 | 14 | r = cabsl(z); 15 | phi = cargl(z); 16 | return CMPLXL(logl(r), phi); 17 | } 18 | #endif 19 | -------------------------------------------------------------------------------- /conj.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double complex conj(double complex z) 4 | { 5 | return CMPLX(creal(z), -cimag(z)); 6 | } 7 | -------------------------------------------------------------------------------- /conjf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float complex conjf(float complex z) 4 | { 5 | return CMPLXF(crealf(z), -cimagf(z)); 6 | } 7 | -------------------------------------------------------------------------------- /conjl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | long double complex conjl(long double complex z) 4 | { 5 | return CMPLXL(creall(z), -cimagl(z)); 6 | } 7 | -------------------------------------------------------------------------------- /cpow.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | /* pow(z, c) = exp(c log(z)), See C99 G.6.4.1 */ 4 | 5 | double complex cpow(double complex z, double complex c) 6 | { 7 | return cexp(c * clog(z)); 8 | } 9 | -------------------------------------------------------------------------------- /cpowf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float complex cpowf(float complex z, float complex c) 4 | { 5 | return cexpf(c * clogf(z)); 6 | } 7 | -------------------------------------------------------------------------------- /cpowl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex cpowl(long double complex z, long double complex c) 5 | { 6 | return cpow(z, c); 7 | } 8 | #else 9 | long double complex cpowl(long double complex z, long double complex c) 10 | { 11 | return cexpl(c * clogl(z)); 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /cproj.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double complex cproj(double complex z) 4 | { 5 | if (isinf(creal(z)) || isinf(cimag(z))) 6 | return CMPLX(INFINITY, copysign(0.0, creal(z))); 7 | return z; 8 | } 9 | -------------------------------------------------------------------------------- /cprojf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float complex cprojf(float complex z) 4 | { 5 | if (isinf(crealf(z)) || isinf(cimagf(z))) 6 | return CMPLXF(INFINITY, copysignf(0.0, crealf(z))); 7 | return z; 8 | } 9 | -------------------------------------------------------------------------------- /cprojl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex cprojl(long double complex z) 5 | { 6 | return cproj(z); 7 | } 8 | #else 9 | long double complex cprojl(long double complex z) 10 | { 11 | if (isinf(creall(z)) || isinf(cimagl(z))) 12 | return CMPLXL(INFINITY, copysignl(0.0, creall(z))); 13 | return z; 14 | } 15 | #endif 16 | -------------------------------------------------------------------------------- /creal.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double (creal)(double complex z) 4 | { 5 | return creal(z); 6 | } 7 | -------------------------------------------------------------------------------- /crealf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float (crealf)(float complex z) 4 | { 5 | return crealf(z); 6 | } 7 | -------------------------------------------------------------------------------- /creall.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | long double (creall)(long double complex z) 4 | { 5 | return creall(z); 6 | } 7 | -------------------------------------------------------------------------------- /csin.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | /* sin(z) = -i sinh(i z) */ 4 | 5 | double complex csin(double complex z) 6 | { 7 | z = csinh(CMPLX(-cimag(z), creal(z))); 8 | return CMPLX(cimag(z), -creal(z)); 9 | } 10 | -------------------------------------------------------------------------------- /csinf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float complex csinf(float complex z) 4 | { 5 | z = csinhf(CMPLXF(-cimagf(z), crealf(z))); 6 | return CMPLXF(cimagf(z), -crealf(z)); 7 | } 8 | -------------------------------------------------------------------------------- /csinh.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_csinh.c */ 2 | /*- 3 | * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice unmodified, this list of conditions, and the following 11 | * disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /* 28 | * Hyperbolic sine of a complex argument z = x + i y. 29 | * 30 | * sinh(z) = sinh(x+iy) 31 | * = sinh(x) cos(y) + i cosh(x) sin(y). 32 | * 33 | * Exceptional values are noted in the comments within the source code. 34 | * These values and the return value were taken from n1124.pdf. 35 | */ 36 | 37 | #include "libm.h" 38 | 39 | static const double huge = 0x1p1023; 40 | 41 | double complex csinh(double complex z) 42 | { 43 | double x, y, h; 44 | int32_t hx, hy, ix, iy, lx, ly; 45 | 46 | x = creal(z); 47 | y = cimag(z); 48 | 49 | EXTRACT_WORDS(hx, lx, x); 50 | EXTRACT_WORDS(hy, ly, y); 51 | 52 | ix = 0x7fffffff & hx; 53 | iy = 0x7fffffff & hy; 54 | 55 | /* Handle the nearly-non-exceptional cases where x and y are finite. */ 56 | if (ix < 0x7ff00000 && iy < 0x7ff00000) { 57 | if ((iy | ly) == 0) 58 | return CMPLX(sinh(x), y); 59 | if (ix < 0x40360000) /* small x: normal case */ 60 | return CMPLX(sinh(x) * cos(y), cosh(x) * sin(y)); 61 | 62 | /* |x| >= 22, so cosh(x) ~= exp(|x|) */ 63 | if (ix < 0x40862e42) { 64 | /* x < 710: exp(|x|) won't overflow */ 65 | h = exp(fabs(x)) * 0.5; 66 | return CMPLX(copysign(h, x) * cos(y), h * sin(y)); 67 | } else if (ix < 0x4096bbaa) { 68 | /* x < 1455: scale to avoid overflow */ 69 | z = __ldexp_cexp(CMPLX(fabs(x), y), -1); 70 | return CMPLX(creal(z) * copysign(1, x), cimag(z)); 71 | } else { 72 | /* x >= 1455: the result always overflows */ 73 | h = huge * x; 74 | return CMPLX(h * cos(y), h * h * sin(y)); 75 | } 76 | } 77 | 78 | /* 79 | * sinh(+-0 +- I Inf) = sign(d(+-0, dNaN))0 + I dNaN. 80 | * The sign of 0 in the result is unspecified. Choice = normally 81 | * the same as dNaN. Raise the invalid floating-point exception. 82 | * 83 | * sinh(+-0 +- I NaN) = sign(d(+-0, NaN))0 + I d(NaN). 84 | * The sign of 0 in the result is unspecified. Choice = normally 85 | * the same as d(NaN). 86 | */ 87 | if ((ix | lx) == 0 && iy >= 0x7ff00000) 88 | return CMPLX(copysign(0, x * (y - y)), y - y); 89 | 90 | /* 91 | * sinh(+-Inf +- I 0) = +-Inf + I +-0. 92 | * 93 | * sinh(NaN +- I 0) = d(NaN) + I +-0. 94 | */ 95 | if ((iy | ly) == 0 && ix >= 0x7ff00000) { 96 | if (((hx & 0xfffff) | lx) == 0) 97 | return CMPLX(x, y); 98 | return CMPLX(x, copysign(0, y)); 99 | } 100 | 101 | /* 102 | * sinh(x +- I Inf) = dNaN + I dNaN. 103 | * Raise the invalid floating-point exception for finite nonzero x. 104 | * 105 | * sinh(x + I NaN) = d(NaN) + I d(NaN). 106 | * Optionally raises the invalid floating-point exception for finite 107 | * nonzero x. Choice = don't raise (except for signaling NaNs). 108 | */ 109 | if (ix < 0x7ff00000 && iy >= 0x7ff00000) 110 | return CMPLX(y - y, x * (y - y)); 111 | 112 | /* 113 | * sinh(+-Inf + I NaN) = +-Inf + I d(NaN). 114 | * The sign of Inf in the result is unspecified. Choice = normally 115 | * the same as d(NaN). 116 | * 117 | * sinh(+-Inf +- I Inf) = +Inf + I dNaN. 118 | * The sign of Inf in the result is unspecified. Choice = always +. 119 | * Raise the invalid floating-point exception. 120 | * 121 | * sinh(+-Inf + I y) = +-Inf cos(y) + I Inf sin(y) 122 | */ 123 | if (ix >= 0x7ff00000 && ((hx & 0xfffff) | lx) == 0) { 124 | if (iy >= 0x7ff00000) 125 | return CMPLX(x * x, x * (y - y)); 126 | return CMPLX(x * cos(y), INFINITY * sin(y)); 127 | } 128 | 129 | /* 130 | * sinh(NaN + I NaN) = d(NaN) + I d(NaN). 131 | * 132 | * sinh(NaN +- I Inf) = d(NaN) + I d(NaN). 133 | * Optionally raises the invalid floating-point exception. 134 | * Choice = raise. 135 | * 136 | * sinh(NaN + I y) = d(NaN) + I d(NaN). 137 | * Optionally raises the invalid floating-point exception for finite 138 | * nonzero y. Choice = don't raise (except for signaling NaNs). 139 | */ 140 | return CMPLX((x * x) * (y - y), (x + x) * (y - y)); 141 | } 142 | -------------------------------------------------------------------------------- /csinhf.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_csinhf.c */ 2 | /*- 3 | * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice unmodified, this list of conditions, and the following 11 | * disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /* 28 | * Hyperbolic sine of a complex argument z. See s_csinh.c for details. 29 | */ 30 | 31 | #include "libm.h" 32 | 33 | static const float huge = 0x1p127; 34 | 35 | float complex csinhf(float complex z) 36 | { 37 | float x, y, h; 38 | int32_t hx, hy, ix, iy; 39 | 40 | x = crealf(z); 41 | y = cimagf(z); 42 | 43 | GET_FLOAT_WORD(hx, x); 44 | GET_FLOAT_WORD(hy, y); 45 | 46 | ix = 0x7fffffff & hx; 47 | iy = 0x7fffffff & hy; 48 | 49 | if (ix < 0x7f800000 && iy < 0x7f800000) { 50 | if (iy == 0) 51 | return CMPLXF(sinhf(x), y); 52 | if (ix < 0x41100000) /* small x: normal case */ 53 | return CMPLXF(sinhf(x) * cosf(y), coshf(x) * sinf(y)); 54 | 55 | /* |x| >= 9, so cosh(x) ~= exp(|x|) */ 56 | if (ix < 0x42b17218) { 57 | /* x < 88.7: expf(|x|) won't overflow */ 58 | h = expf(fabsf(x)) * 0.5f; 59 | return CMPLXF(copysignf(h, x) * cosf(y), h * sinf(y)); 60 | } else if (ix < 0x4340b1e7) { 61 | /* x < 192.7: scale to avoid overflow */ 62 | z = __ldexp_cexpf(CMPLXF(fabsf(x), y), -1); 63 | return CMPLXF(crealf(z) * copysignf(1, x), cimagf(z)); 64 | } else { 65 | /* x >= 192.7: the result always overflows */ 66 | h = huge * x; 67 | return CMPLXF(h * cosf(y), h * h * sinf(y)); 68 | } 69 | } 70 | 71 | if (ix == 0 && iy >= 0x7f800000) 72 | return CMPLXF(copysignf(0, x * (y - y)), y - y); 73 | 74 | if (iy == 0 && ix >= 0x7f800000) { 75 | if ((hx & 0x7fffff) == 0) 76 | return CMPLXF(x, y); 77 | return CMPLXF(x, copysignf(0, y)); 78 | } 79 | 80 | if (ix < 0x7f800000 && iy >= 0x7f800000) 81 | return CMPLXF(y - y, x * (y - y)); 82 | 83 | if (ix >= 0x7f800000 && (hx & 0x7fffff) == 0) { 84 | if (iy >= 0x7f800000) 85 | return CMPLXF(x * x, x * (y - y)); 86 | return CMPLXF(x * cosf(y), INFINITY * sinf(y)); 87 | } 88 | 89 | return CMPLXF((x * x) * (y - y), (x + x) * (y - y)); 90 | } 91 | -------------------------------------------------------------------------------- /csinhl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | //FIXME 4 | long double complex csinhl(long double complex z) 5 | { 6 | return csinh(z); 7 | } 8 | -------------------------------------------------------------------------------- /csinl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex csinl(long double complex z) 5 | { 6 | return csin(z); 7 | } 8 | #else 9 | long double complex csinl(long double complex z) 10 | { 11 | z = csinhl(CMPLXL(-cimagl(z), creall(z))); 12 | return CMPLXL(cimagl(z), -creall(z)); 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /csqrt.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_csqrt.c */ 2 | /*- 3 | * Copyright (c) 2007 David Schultz 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | 28 | #include "libm.h" 29 | 30 | /* 31 | * gcc doesn't implement complex multiplication or division correctly, 32 | * so we need to handle infinities specially. We turn on this pragma to 33 | * notify conforming c99 compilers that the fast-but-incorrect code that 34 | * gcc generates is acceptable, since the special cases have already been 35 | * handled. 36 | */ 37 | #pragma STDC CX_LIMITED_RANGE ON 38 | 39 | /* We risk spurious overflow for components >= DBL_MAX / (1 + sqrt(2)). */ 40 | #define THRESH 0x1.a827999fcef32p+1022 41 | 42 | double complex csqrt(double complex z) 43 | { 44 | double complex result; 45 | double a, b; 46 | double t; 47 | int scale; 48 | 49 | a = creal(z); 50 | b = cimag(z); 51 | 52 | /* Handle special cases. */ 53 | if (z == 0) 54 | return CMPLX(0, b); 55 | if (isinf(b)) 56 | return CMPLX(INFINITY, b); 57 | if (isnan(a)) { 58 | t = (b - b) / (b - b); /* raise invalid if b is not a NaN */ 59 | return CMPLX(a, t); /* return NaN + NaN i */ 60 | } 61 | if (isinf(a)) { 62 | /* 63 | * csqrt(inf + NaN i) = inf + NaN i 64 | * csqrt(inf + y i) = inf + 0 i 65 | * csqrt(-inf + NaN i) = NaN +- inf i 66 | * csqrt(-inf + y i) = 0 + inf i 67 | */ 68 | if (signbit(a)) 69 | return CMPLX(fabs(b - b), copysign(a, b)); 70 | else 71 | return CMPLX(a, copysign(b - b, b)); 72 | } 73 | /* 74 | * The remaining special case (b is NaN) is handled just fine by 75 | * the normal code path below. 76 | */ 77 | 78 | /* Scale to avoid overflow. */ 79 | if (fabs(a) >= THRESH || fabs(b) >= THRESH) { 80 | a *= 0.25; 81 | b *= 0.25; 82 | scale = 1; 83 | } else { 84 | scale = 0; 85 | } 86 | 87 | /* Algorithm 312, CACM vol 10, Oct 1967. */ 88 | if (a >= 0) { 89 | t = sqrt((a + hypot(a, b)) * 0.5); 90 | result = CMPLX(t, b / (2 * t)); 91 | } else { 92 | t = sqrt((-a + hypot(a, b)) * 0.5); 93 | result = CMPLX(fabs(b) / (2 * t), copysign(t, b)); 94 | } 95 | 96 | /* Rescale. */ 97 | if (scale) 98 | result *= 2; 99 | return result; 100 | } 101 | -------------------------------------------------------------------------------- /csqrtf.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_csqrtf.c */ 2 | /*- 3 | * Copyright (c) 2007 David Schultz 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | 28 | #include "libm.h" 29 | 30 | /* 31 | * gcc doesn't implement complex multiplication or division correctly, 32 | * so we need to handle infinities specially. We turn on this pragma to 33 | * notify conforming c99 compilers that the fast-but-incorrect code that 34 | * gcc generates is acceptable, since the special cases have already been 35 | * handled. 36 | */ 37 | #pragma STDC CX_LIMITED_RANGE ON 38 | 39 | float complex csqrtf(float complex z) 40 | { 41 | float a = crealf(z), b = cimagf(z); 42 | double t; 43 | 44 | /* Handle special cases. */ 45 | if (z == 0) 46 | return CMPLXF(0, b); 47 | if (isinf(b)) 48 | return CMPLXF(INFINITY, b); 49 | if (isnan(a)) { 50 | t = (b - b) / (b - b); /* raise invalid if b is not a NaN */ 51 | return CMPLXF(a, t); /* return NaN + NaN i */ 52 | } 53 | if (isinf(a)) { 54 | /* 55 | * csqrtf(inf + NaN i) = inf + NaN i 56 | * csqrtf(inf + y i) = inf + 0 i 57 | * csqrtf(-inf + NaN i) = NaN +- inf i 58 | * csqrtf(-inf + y i) = 0 + inf i 59 | */ 60 | if (signbit(a)) 61 | return CMPLXF(fabsf(b - b), copysignf(a, b)); 62 | else 63 | return CMPLXF(a, copysignf(b - b, b)); 64 | } 65 | /* 66 | * The remaining special case (b is NaN) is handled just fine by 67 | * the normal code path below. 68 | */ 69 | 70 | /* 71 | * We compute t in double precision to avoid overflow and to 72 | * provide correct rounding in nearly all cases. 73 | * This is Algorithm 312, CACM vol 10, Oct 1967. 74 | */ 75 | if (a >= 0) { 76 | t = sqrt((a + hypot(a, b)) * 0.5); 77 | return CMPLXF(t, b / (2.0 * t)); 78 | } else { 79 | t = sqrt((-a + hypot(a, b)) * 0.5); 80 | return CMPLXF(fabsf(b) / (2.0 * t), copysignf(t, b)); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /csqrtl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | //FIXME 4 | long double complex csqrtl(long double complex z) 5 | { 6 | return csqrt(z); 7 | } 8 | -------------------------------------------------------------------------------- /ctan.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | /* tan(z) = -i tanh(i z) */ 4 | 5 | double complex ctan(double complex z) 6 | { 7 | z = ctanh(CMPLX(-cimag(z), creal(z))); 8 | return CMPLX(cimag(z), -creal(z)); 9 | } 10 | -------------------------------------------------------------------------------- /ctanf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float complex ctanf(float complex z) 4 | { 5 | z = ctanhf(CMPLXF(-cimagf(z), crealf(z))); 6 | return CMPLXF(cimagf(z), -crealf(z)); 7 | } 8 | -------------------------------------------------------------------------------- /ctanh.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_ctanh.c */ 2 | /*- 3 | * Copyright (c) 2011 David Schultz 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice unmodified, this list of conditions, and the following 11 | * disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /* 28 | * Hyperbolic tangent of a complex argument z = x + i y. 29 | * 30 | * The algorithm is from: 31 | * 32 | * W. Kahan. Branch Cuts for Complex Elementary Functions or Much 33 | * Ado About Nothing's Sign Bit. In The State of the Art in 34 | * Numerical Analysis, pp. 165 ff. Iserles and Powell, eds., 1987. 35 | * 36 | * Method: 37 | * 38 | * Let t = tan(x) 39 | * beta = 1/cos^2(y) 40 | * s = sinh(x) 41 | * rho = cosh(x) 42 | * 43 | * We have: 44 | * 45 | * tanh(z) = sinh(z) / cosh(z) 46 | * 47 | * sinh(x) cos(y) + i cosh(x) sin(y) 48 | * = --------------------------------- 49 | * cosh(x) cos(y) + i sinh(x) sin(y) 50 | * 51 | * cosh(x) sinh(x) / cos^2(y) + i tan(y) 52 | * = ------------------------------------- 53 | * 1 + sinh^2(x) / cos^2(y) 54 | * 55 | * beta rho s + i t 56 | * = ---------------- 57 | * 1 + beta s^2 58 | * 59 | * Modifications: 60 | * 61 | * I omitted the original algorithm's handling of overflow in tan(x) after 62 | * verifying with nearpi.c that this can't happen in IEEE single or double 63 | * precision. I also handle large x differently. 64 | */ 65 | 66 | #include "libm.h" 67 | 68 | double complex ctanh(double complex z) 69 | { 70 | double x, y; 71 | double t, beta, s, rho, denom; 72 | uint32_t hx, ix, lx; 73 | 74 | x = creal(z); 75 | y = cimag(z); 76 | 77 | EXTRACT_WORDS(hx, lx, x); 78 | ix = hx & 0x7fffffff; 79 | 80 | /* 81 | * ctanh(NaN + i 0) = NaN + i 0 82 | * 83 | * ctanh(NaN + i y) = NaN + i NaN for y != 0 84 | * 85 | * The imaginary part has the sign of x*sin(2*y), but there's no 86 | * special effort to get this right. 87 | * 88 | * ctanh(+-Inf +- i Inf) = +-1 +- 0 89 | * 90 | * ctanh(+-Inf + i y) = +-1 + 0 sin(2y) for y finite 91 | * 92 | * The imaginary part of the sign is unspecified. This special 93 | * case is only needed to avoid a spurious invalid exception when 94 | * y is infinite. 95 | */ 96 | if (ix >= 0x7ff00000) { 97 | if ((ix & 0xfffff) | lx) /* x is NaN */ 98 | return CMPLX(x, (y == 0 ? y : x * y)); 99 | SET_HIGH_WORD(x, hx - 0x40000000); /* x = copysign(1, x) */ 100 | return CMPLX(x, copysign(0, isinf(y) ? y : sin(y) * cos(y))); 101 | } 102 | 103 | /* 104 | * ctanh(+-0 + i NAN) = +-0 + i NaN 105 | * ctanh(+-0 +- i Inf) = +-0 + i NaN 106 | * ctanh(x + i NAN) = NaN + i NaN 107 | * ctanh(x +- i Inf) = NaN + i NaN 108 | */ 109 | if (!isfinite(y)) 110 | return CMPLX(x ? y - y : x, y - y); 111 | 112 | /* 113 | * ctanh(+-huge + i +-y) ~= +-1 +- i 2sin(2y)/exp(2x), using the 114 | * approximation sinh^2(huge) ~= exp(2*huge) / 4. 115 | * We use a modified formula to avoid spurious overflow. 116 | */ 117 | if (ix >= 0x40360000) { /* x >= 22 */ 118 | double exp_mx = exp(-fabs(x)); 119 | return CMPLX(copysign(1, x), 4 * sin(y) * cos(y) * exp_mx * exp_mx); 120 | } 121 | 122 | /* Kahan's algorithm */ 123 | t = tan(y); 124 | beta = 1.0 + t * t; /* = 1 / cos^2(y) */ 125 | s = sinh(x); 126 | rho = sqrt(1 + s * s); /* = cosh(x) */ 127 | denom = 1 + beta * s * s; 128 | return CMPLX((beta * rho * s) / denom, t / denom); 129 | } 130 | -------------------------------------------------------------------------------- /ctanhf.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_ctanhf.c */ 2 | /*- 3 | * Copyright (c) 2011 David Schultz 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice unmodified, this list of conditions, and the following 11 | * disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /* 28 | * Hyperbolic tangent of a complex argument z. See s_ctanh.c for details. 29 | */ 30 | 31 | #include "libm.h" 32 | 33 | float complex ctanhf(float complex z) 34 | { 35 | float x, y; 36 | float t, beta, s, rho, denom; 37 | uint32_t hx, ix; 38 | 39 | x = crealf(z); 40 | y = cimagf(z); 41 | 42 | GET_FLOAT_WORD(hx, x); 43 | ix = hx & 0x7fffffff; 44 | 45 | if (ix >= 0x7f800000) { 46 | if (ix & 0x7fffff) 47 | return CMPLXF(x, (y == 0 ? y : x * y)); 48 | SET_FLOAT_WORD(x, hx - 0x40000000); 49 | return CMPLXF(x, copysignf(0, isinf(y) ? y : sinf(y) * cosf(y))); 50 | } 51 | 52 | if (!isfinite(y)) 53 | return CMPLXF(ix ? y - y : x, y - y); 54 | 55 | if (ix >= 0x41300000) { /* x >= 11 */ 56 | float exp_mx = expf(-fabsf(x)); 57 | return CMPLXF(copysignf(1, x), 4 * sinf(y) * cosf(y) * exp_mx * exp_mx); 58 | } 59 | 60 | t = tanf(y); 61 | beta = 1.0 + t * t; 62 | s = sinhf(x); 63 | rho = sqrtf(1 + s * s); 64 | denom = 1 + beta * s * s; 65 | return CMPLXF((beta * rho * s) / denom, t / denom); 66 | } 67 | -------------------------------------------------------------------------------- /ctanhl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | //FIXME 4 | long double complex ctanhl(long double complex z) 5 | { 6 | return ctanh(z); 7 | } 8 | -------------------------------------------------------------------------------- /ctanl.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 4 | long double complex ctanl(long double complex z) 5 | { 6 | return ctan(z); 7 | } 8 | #else 9 | long double complex ctanl(long double complex z) 10 | { 11 | z = ctanhl(CMPLXL(-cimagl(z), creall(z))); 12 | return CMPLXL(cimagl(z), -creall(z)); 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /include/complex.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPLEX_H 2 | #define _COMPLEX_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define complex _Complex 9 | #ifdef __GNUC__ 10 | #define _Complex_I (__extension__ (0.0f+1.0fi)) 11 | #else 12 | #define _Complex_I (0.0f+1.0fi) 13 | #endif 14 | #define I _Complex_I 15 | 16 | double complex cacos(double complex); 17 | float complex cacosf(float complex); 18 | long double complex cacosl(long double complex); 19 | 20 | double complex casin(double complex); 21 | float complex casinf(float complex); 22 | long double complex casinl(long double complex); 23 | 24 | double complex catan(double complex); 25 | float complex catanf(float complex); 26 | long double complex catanl(long double complex); 27 | 28 | double complex ccos(double complex); 29 | float complex ccosf(float complex); 30 | long double complex ccosl(long double complex); 31 | 32 | double complex csin(double complex); 33 | float complex csinf(float complex); 34 | long double complex csinl(long double complex); 35 | 36 | double complex ctan(double complex); 37 | float complex ctanf(float complex); 38 | long double complex ctanl(long double complex); 39 | 40 | double complex cacosh(double complex); 41 | float complex cacoshf(float complex); 42 | long double complex cacoshl(long double complex); 43 | 44 | double complex casinh(double complex); 45 | float complex casinhf(float complex); 46 | long double complex casinhl(long double complex); 47 | 48 | double complex catanh(double complex); 49 | float complex catanhf(float complex); 50 | long double complex catanhl(long double complex); 51 | 52 | double complex ccosh(double complex); 53 | float complex ccoshf(float complex); 54 | long double complex ccoshl(long double complex); 55 | 56 | double complex csinh(double complex); 57 | float complex csinhf(float complex); 58 | long double complex csinhl(long double complex); 59 | 60 | double complex ctanh(double complex); 61 | float complex ctanhf(float complex); 62 | long double complex ctanhl(long double complex); 63 | 64 | double complex cexp(double complex); 65 | float complex cexpf(float complex); 66 | long double complex cexpl(long double complex); 67 | 68 | double complex clog(double complex); 69 | float complex clogf(float complex); 70 | long double complex clogl(long double complex); 71 | 72 | double cabs(double complex); 73 | float cabsf(float complex); 74 | long double cabsl(long double complex); 75 | 76 | double complex cpow(double complex, double complex); 77 | float complex cpowf(float complex, float complex); 78 | long double complex cpowl(long double complex, long double complex); 79 | 80 | double complex csqrt(double complex); 81 | float complex csqrtf(float complex); 82 | long double complex csqrtl(long double complex); 83 | 84 | double carg(double complex); 85 | float cargf(float complex); 86 | long double cargl(long double complex); 87 | 88 | double cimag(double complex); 89 | float cimagf(float complex); 90 | long double cimagl(long double complex); 91 | 92 | double complex conj(double complex); 93 | float complex conjf(float complex); 94 | long double complex conjl(long double complex); 95 | 96 | double complex cproj(double complex); 97 | float complex cprojf(float complex); 98 | long double complex cprojl(long double complex); 99 | 100 | double creal(double complex); 101 | float crealf(float complex); 102 | long double creall(long double complex); 103 | 104 | #ifndef __cplusplus 105 | #define __CIMAG(x, t) \ 106 | (+(union { _Complex t __z; t __xy[2]; }){(_Complex t)(x)}.__xy[1]) 107 | 108 | #define creal(x) ((double)(x)) 109 | #define crealf(x) ((float)(x)) 110 | #define creall(x) ((long double)(x)) 111 | 112 | #define cimag(x) __CIMAG(x, double) 113 | #define cimagf(x) __CIMAG(x, float) 114 | #define cimagl(x) __CIMAG(x, long double) 115 | #endif 116 | 117 | #if __STDC_VERSION__ >= 201112L 118 | #if defined(_Imaginary_I) 119 | #define __CMPLX(x, y, t) ((t)(x) + _Imaginary_I*(t)(y)) 120 | #elif defined(__clang__) 121 | #define __CMPLX(x, y, t) (+(_Complex t){ (t)(x), (t)(y) }) 122 | #else 123 | #define __CMPLX(x, y, t) (__builtin_complex((t)(x), (t)(y))) 124 | #endif 125 | #define CMPLX(x, y) __CMPLX(x, y, double) 126 | #define CMPLXF(x, y) __CMPLX(x, y, float) 127 | #define CMPLXL(x, y) __CMPLX(x, y, long double) 128 | #endif 129 | 130 | #ifdef __cplusplus 131 | } 132 | #endif 133 | #endif 134 | -------------------------------------------------------------------------------- /include/libm.h: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunPro, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | */ 12 | 13 | #ifndef _LIBM_H 14 | #define _LIBM_H 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 23 | #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN 24 | union ldshape { 25 | long double f; 26 | struct { 27 | uint64_t m; 28 | uint16_t se; 29 | } i; 30 | }; 31 | #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN 32 | union ldshape { 33 | long double f; 34 | struct { 35 | uint64_t lo; 36 | uint32_t mid; 37 | uint16_t top; 38 | uint16_t se; 39 | } i; 40 | struct { 41 | uint64_t lo; 42 | uint64_t hi; 43 | } i2; 44 | }; 45 | #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN 46 | union ldshape { 47 | long double f; 48 | struct { 49 | uint16_t se; 50 | uint16_t top; 51 | uint32_t mid; 52 | uint64_t lo; 53 | } i; 54 | struct { 55 | uint64_t hi; 56 | uint64_t lo; 57 | } i2; 58 | }; 59 | #else 60 | #error Unsupported long double representation 61 | #endif 62 | 63 | #define FORCE_EVAL(x) do { \ 64 | if (sizeof(x) == sizeof(float)) { \ 65 | volatile float __x; \ 66 | __x = (x); \ 67 | } else if (sizeof(x) == sizeof(double)) { \ 68 | volatile double __x; \ 69 | __x = (x); \ 70 | } else { \ 71 | volatile long double __x; \ 72 | __x = (x); \ 73 | } \ 74 | } while(0) 75 | 76 | /* Get two 32 bit ints from a double. */ 77 | #define EXTRACT_WORDS(hi,lo,d) \ 78 | do { \ 79 | union {double f; uint64_t i;} __u; \ 80 | __u.f = (d); \ 81 | (hi) = __u.i >> 32; \ 82 | (lo) = (uint32_t)__u.i; \ 83 | } while (0) 84 | 85 | /* Get the more significant 32 bit int from a double. */ 86 | #define GET_HIGH_WORD(hi,d) \ 87 | do { \ 88 | union {double f; uint64_t i;} __u; \ 89 | __u.f = (d); \ 90 | (hi) = __u.i >> 32; \ 91 | } while (0) 92 | 93 | /* Get the less significant 32 bit int from a double. */ 94 | #define GET_LOW_WORD(lo,d) \ 95 | do { \ 96 | union {double f; uint64_t i;} __u; \ 97 | __u.f = (d); \ 98 | (lo) = (uint32_t)__u.i; \ 99 | } while (0) 100 | 101 | /* Set a double from two 32 bit ints. */ 102 | #define INSERT_WORDS(d,hi,lo) \ 103 | do { \ 104 | union {double f; uint64_t i;} __u; \ 105 | __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo); \ 106 | (d) = __u.f; \ 107 | } while (0) 108 | 109 | /* Set the more significant 32 bits of a double from an int. */ 110 | #define SET_HIGH_WORD(d,hi) \ 111 | do { \ 112 | union {double f; uint64_t i;} __u; \ 113 | __u.f = (d); \ 114 | __u.i &= 0xffffffff; \ 115 | __u.i |= (uint64_t)(hi) << 32; \ 116 | (d) = __u.f; \ 117 | } while (0) 118 | 119 | /* Set the less significant 32 bits of a double from an int. */ 120 | #define SET_LOW_WORD(d,lo) \ 121 | do { \ 122 | union {double f; uint64_t i;} __u; \ 123 | __u.f = (d); \ 124 | __u.i &= 0xffffffff00000000ull; \ 125 | __u.i |= (uint32_t)(lo); \ 126 | (d) = __u.f; \ 127 | } while (0) 128 | 129 | /* Get a 32 bit int from a float. */ 130 | #define GET_FLOAT_WORD(w,d) \ 131 | do { \ 132 | union {float f; uint32_t i;} __u; \ 133 | __u.f = (d); \ 134 | (w) = __u.i; \ 135 | } while (0) 136 | 137 | /* Set a float from a 32 bit int. */ 138 | #define SET_FLOAT_WORD(d,w) \ 139 | do { \ 140 | union {float f; uint32_t i;} __u; \ 141 | __u.i = (w); \ 142 | (d) = __u.f; \ 143 | } while (0) 144 | 145 | #undef __CMPLX 146 | #undef CMPLX 147 | #undef CMPLXF 148 | #undef CMPLXL 149 | 150 | #define __CMPLX(x, y, t) \ 151 | ((union { _Complex t __z; t __xy[2]; }){.__xy = {(x),(y)}}.__z) 152 | 153 | #define CMPLX(x, y) __CMPLX(x, y, double) 154 | #define CMPLXF(x, y) __CMPLX(x, y, float) 155 | #define CMPLXL(x, y) __CMPLX(x, y, long double) 156 | 157 | /* fdlibm kernel functions */ 158 | 159 | int __rem_pio2_large(double*,double*,int,int,int); 160 | 161 | int __rem_pio2(double,double*); 162 | double __sin(double,double,int); 163 | double __cos(double,double); 164 | double __tan(double,double,int); 165 | double __expo2(double); 166 | double complex __ldexp_cexp(double complex,int); 167 | 168 | int __rem_pio2f(float,double*); 169 | float __sindf(double); 170 | float __cosdf(double); 171 | float __tandf(double,int); 172 | float __expo2f(float); 173 | float complex __ldexp_cexpf(float complex,int); 174 | 175 | int __rem_pio2l(long double, long double *); 176 | long double __sinl(long double, long double, int); 177 | long double __cosl(long double, long double); 178 | long double __tanl(long double, long double, int); 179 | 180 | /* polynomial evaluation */ 181 | long double __polevll(long double, const long double *, int); 182 | long double __p1evll(long double, const long double *, int); 183 | 184 | #endif 185 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -I./include -I$(SYSROOT)/usr/include -Wall -Wextra 2 | LDFLAGS += -lm 3 | 4 | SRCS=$(wildcard *.c) 5 | 6 | OBJS=$(SRCS:.c=.o) 7 | 8 | .PHONY: all 9 | 10 | all: libcomplex.a libcomplex.so 11 | 12 | libcomplex.a: $(OBJS) 13 | $(AR) $(ARFLAGS) $@ $^ 14 | $(RANLIB) $@ 15 | 16 | libcomplex.so: libcomplex.a 17 | $(CC) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive $(LDFLAGS) 18 | 19 | .PHONY: clean 20 | 21 | clean: 22 | rm -f $(OBJS) libcomplex.a libcomplex.so 23 | 24 | install: 25 | @echo "installing..." 26 | @echo "" 27 | mkdir -p $(SYSROOT)/usr/lib 28 | install -m 644 -p libcomplex.so libcomplex.a $(SYSROOT)/usr/lib 29 | install -m 644 -p include/complex.h $(SYSROOT)/usr/include 30 | --------------------------------------------------------------------------------