github.com/afumu/libc@v0.0.6/musl/src/complex/cexpf.c (about)

     1  /* origin: FreeBSD /usr/src/lib/msun/src/s_cexpf.c */
     2  /*-
     3   * Copyright (c) 2011 David Schultz <das@FreeBSD.ORG>
     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 "complex_impl.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  }