11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*-
2a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Copyright (c) 2011 David Schultz
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved.
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice unmodified, this list of conditions, and the following
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    disclaimer.
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    documentation and/or other materials provided with the distribution.
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
27a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
28a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Hyperbolic tangent of a complex argument z.  See s_ctanh.c for details.
29a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
30a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h>
328cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes__FBSDID("$FreeBSD: head/lib/msun/src/s_ctanhf.c 284428 2015-06-15 20:47:26Z tijl $");
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
34a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <complex.h>
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <math.h>
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
37a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include "math_private.h"
38a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
39a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesfloat complex
40a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesctanhf(float complex z)
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
42a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	float x, y;
43a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	float t, beta, s, rho, denom;
44a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	uint32_t hx, ix;
45a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
46a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	x = crealf(z);
47a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	y = cimagf(z);
48a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
49a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	GET_FLOAT_WORD(hx, x);
50a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	ix = hx & 0x7fffffff;
51a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
52a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	if (ix >= 0x7f800000) {
53a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		if (ix & 0x7fffff)
548cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes			return (CMPLXF((x + 0) * (y + 0),
558cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes			    y == 0 ? y : (x + 0) * (y + 0)));
56a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		SET_FLOAT_WORD(x, hx - 0x40000000);
578cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes		return (CMPLXF(x,
58a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		    copysignf(0, isinf(y) ? y : sinf(y) * cosf(y))));
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
60a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
61a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	if (!isfinite(y))
628cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes		return (CMPLXF(y - y, y - y));
63a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
648cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes	if (ix >= 0x41300000) {	/* |x| >= 11 */
65a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		float exp_mx = expf(-fabsf(x));
668cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes		return (CMPLXF(copysignf(1, x),
67a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		    4 * sinf(y) * cosf(y) * exp_mx * exp_mx));
68a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	}
69a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
70a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	t = tanf(y);
71a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	beta = 1.0 + t * t;
72a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	s = sinhf(x);
73a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	rho = sqrtf(1 + s * s);
74a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	denom = 1 + beta * s * s;
758cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes	return (CMPLXF((beta * rho * s) / denom, t / denom));
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
77a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
78a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesfloat complex
79a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesctanf(float complex z)
80a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{
81a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
828cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes	z = ctanhf(CMPLXF(cimagf(z), crealf(z)));
838cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes	return (CMPLXF(cimagf(z), crealf(z)));
84a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes}
85a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
86