1f3732b5aSDavid Schultz /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 35e53a4f9SPedro F. Giffuni * 4f3732b5aSDavid Schultz * Copyright (c) 2011 David Schultz <das@FreeBSD.ORG> 5f3732b5aSDavid Schultz * All rights reserved. 6f3732b5aSDavid Schultz * 7f3732b5aSDavid Schultz * Redistribution and use in source and binary forms, with or without 8f3732b5aSDavid Schultz * modification, are permitted provided that the following conditions 9f3732b5aSDavid Schultz * are met: 10f3732b5aSDavid Schultz * 1. Redistributions of source code must retain the above copyright 11f3732b5aSDavid Schultz * notice, this list of conditions and the following disclaimer. 12f3732b5aSDavid Schultz * 2. Redistributions in binary form must reproduce the above copyright 13f3732b5aSDavid Schultz * notice, this list of conditions and the following disclaimer in the 14f3732b5aSDavid Schultz * documentation and/or other materials provided with the distribution. 15f3732b5aSDavid Schultz * 16f3732b5aSDavid Schultz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17f3732b5aSDavid Schultz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18f3732b5aSDavid Schultz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19f3732b5aSDavid Schultz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20f3732b5aSDavid Schultz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21f3732b5aSDavid Schultz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22f3732b5aSDavid Schultz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23f3732b5aSDavid Schultz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24f3732b5aSDavid Schultz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25f3732b5aSDavid Schultz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26f3732b5aSDavid Schultz * SUCH DAMAGE. 27f3732b5aSDavid Schultz */ 28f3732b5aSDavid Schultz 29f3732b5aSDavid Schultz #include <sys/cdefs.h> 30f3732b5aSDavid Schultz __FBSDID("$FreeBSD$"); 31f3732b5aSDavid Schultz 32f3732b5aSDavid Schultz #include <complex.h> 33f3732b5aSDavid Schultz #include <math.h> 34f3732b5aSDavid Schultz 35f3732b5aSDavid Schultz #include "math_private.h" 36f3732b5aSDavid Schultz 37f3732b5aSDavid Schultz static const uint32_t 38f3732b5aSDavid Schultz exp_ovfl = 0x42b17218, /* MAX_EXP * ln2 ~= 88.722839355 */ 3912188b77SDavid Schultz cexp_ovfl = 0x43400074; /* (MAX_EXP - MIN_DENORM_EXP) * ln2 */ 40f3732b5aSDavid Schultz 41f3732b5aSDavid Schultz float complex 42f3732b5aSDavid Schultz cexpf(float complex z) 43f3732b5aSDavid Schultz { 44046e2d5dSSteve Kargl float c, exp_x, s, x, y; 45f3732b5aSDavid Schultz uint32_t hx, hy; 46f3732b5aSDavid Schultz 47f3732b5aSDavid Schultz x = crealf(z); 48f3732b5aSDavid Schultz y = cimagf(z); 49f3732b5aSDavid Schultz 50f3732b5aSDavid Schultz GET_FLOAT_WORD(hy, y); 51f3732b5aSDavid Schultz hy &= 0x7fffffff; 52f3732b5aSDavid Schultz 53f3732b5aSDavid Schultz /* cexp(x + I 0) = exp(x) + I 0 */ 54f3732b5aSDavid Schultz if (hy == 0) 552cec876aSEd Schouten return (CMPLXF(expf(x), y)); 56f3732b5aSDavid Schultz GET_FLOAT_WORD(hx, x); 574ce31585SDavid Schultz /* cexp(0 + I y) = cos(y) + I sin(y) */ 58046e2d5dSSteve Kargl if ((hx & 0x7fffffff) == 0) { 59046e2d5dSSteve Kargl sincosf(y, &s, &c); 60046e2d5dSSteve Kargl return (CMPLXF(c, s)); 61046e2d5dSSteve Kargl } 624ce31585SDavid Schultz 63f3732b5aSDavid Schultz if (hy >= 0x7f800000) { 64f3732b5aSDavid Schultz if ((hx & 0x7fffffff) != 0x7f800000) { 65f3732b5aSDavid Schultz /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */ 662cec876aSEd Schouten return (CMPLXF(y - y, y - y)); 67f3732b5aSDavid Schultz } else if (hx & 0x80000000) { 68f3732b5aSDavid Schultz /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */ 692cec876aSEd Schouten return (CMPLXF(0.0, 0.0)); 70f3732b5aSDavid Schultz } else { 71f3732b5aSDavid Schultz /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */ 722cec876aSEd Schouten return (CMPLXF(x, y - y)); 73f3732b5aSDavid Schultz } 74f3732b5aSDavid Schultz } 75f3732b5aSDavid Schultz 76f3732b5aSDavid Schultz if (hx >= exp_ovfl && hx <= cexp_ovfl) { 77f3732b5aSDavid Schultz /* 78f3732b5aSDavid Schultz * x is between 88.7 and 192, so we must scale to avoid 7912188b77SDavid Schultz * overflow in expf(x). 80f3732b5aSDavid Schultz */ 8112188b77SDavid Schultz return (__ldexp_cexpf(z, 0)); 82f3732b5aSDavid Schultz } else { 83f3732b5aSDavid Schultz /* 84f3732b5aSDavid Schultz * Cases covered here: 85f3732b5aSDavid Schultz * - x < exp_ovfl and exp(x) won't overflow (common case) 86f3732b5aSDavid Schultz * - x > cexp_ovfl, so exp(x) * s overflows for all s > 0 87f3732b5aSDavid Schultz * - x = +-Inf (generated by exp()) 88f3732b5aSDavid Schultz * - x = NaN (spurious inexact exception from y) 89f3732b5aSDavid Schultz */ 90f3732b5aSDavid Schultz exp_x = expf(x); 91046e2d5dSSteve Kargl sincosf(y, &s, &c); 92046e2d5dSSteve Kargl return (CMPLXF(exp_x * c, exp_x * s)); 93f3732b5aSDavid Schultz } 94f3732b5aSDavid Schultz } 95