/* origin: FreeBSD /usr/src/lib/msun/src/s_cexp.c */1/*-2* Copyright (c) 2011 David Schultz <[email protected]>3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include "complex_impl.h"2829static const uint32_t30exp_ovfl = 0x40862e42, /* high bits of MAX_EXP * ln2 ~= 710 */31cexp_ovfl = 0x4096b8e4; /* (MAX_EXP - MIN_DENORM_EXP) * ln2 */3233extern double __cdecl __exp(double x, matherr_t matherr);3435static double cexp_callback( int type, const char *name, double arg1, double arg2, double retval )36{3738switch (type) {39case _DOMAIN:40errno = EDOM;41break;42case _SING:43case _OVERFLOW:44errno = ERANGE;45break;46}47return retval;48}4950_Dcomplex __cdecl cexp(_Dcomplex z)51{52_Dcomplex r;53double x, y, exp_x;54uint32_t hx, hy, lx, ly;5556x = creal(z);57y = cimag(z);5859EXTRACT_WORDS(hy, ly, y);60hy &= 0x7fffffff;6162/* cexp(x + I 0) = exp(x) + I 0 */63if ((hy | ly) == 0) {64if (isnan(x)) return CMPLX(x, y);65return CMPLX(__exp(x, cexp_callback), y);66}67EXTRACT_WORDS(hx, lx, x);68/* cexp(0 + I y) = cos(y) + I sin(y) */69if (((hx & 0x7fffffff) | lx) == 0) {70if (isinf(y)) {71errno = EDOM;72return CMPLX(NAN, NAN);73}74return CMPLX(cos(y), sin(y));75}7677if (hy >= 0x7ff00000) {78if (lx != 0 || (hx & 0x7fffffff) != 0x7ff00000) {79/* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */80if (isinf(y)) {81if (!isnan(x)) errno = EDOM;82return CMPLX(NAN, NAN);83}84return CMPLX(y - y, y - y);85} else if (hx & 0x80000000) {86/* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */87return CMPLX(0.0, copysign(0.0, y));88} else {89/* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */90if (!isnan(y)) errno = EDOM;91return CMPLX(x, NAN);92}93}9495if (hx >= exp_ovfl && hx <= cexp_ovfl) {96/*97* x is between 709.7 and 1454.3, so we must scale to avoid98* overflow in exp(x).99*/100r = __ldexp_cexp(z, 0);101if (isinf(r._Val[0])) errno = ERANGE;102return r;103} else {104/*105* Cases covered here:106* - x < exp_ovfl and exp(x) won't overflow (common case)107* - x > cexp_ovfl, so exp(x) * s overflows for all s > 0108* - x = +-Inf (generated by exp())109* - x = NaN (spurious inexact exception from y)110*/111if (isnan(x))112return CMPLX(NAN, NAN);113exp_x = __exp(x, cexp_callback);114return CMPLX(exp_x * cos(y), exp_x * sin(y));115}116}117118119