xref: /netbsd-src/lib/libm/complex/csqrtf.c (revision 038de09f8aa47838312935ff9eb6b911e6aa804c)
1*038de09fSmaya /* $NetBSD: csqrtf.c,v 1.4 2017/01/01 19:32:14 maya Exp $ */
29d8b5fa7Sdrochner 
39d8b5fa7Sdrochner /*-
49d8b5fa7Sdrochner  * Copyright (c) 2007 The NetBSD Foundation, Inc.
59d8b5fa7Sdrochner  * All rights reserved.
69d8b5fa7Sdrochner  *
79d8b5fa7Sdrochner  * This code is derived from software written by Stephen L. Moshier.
89d8b5fa7Sdrochner  * It is redistributed by the NetBSD Foundation by permission of the author.
99d8b5fa7Sdrochner  *
109d8b5fa7Sdrochner  * Redistribution and use in source and binary forms, with or without
119d8b5fa7Sdrochner  * modification, are permitted provided that the following conditions
129d8b5fa7Sdrochner  * are met:
139d8b5fa7Sdrochner  * 1. Redistributions of source code must retain the above copyright
149d8b5fa7Sdrochner  *    notice, this list of conditions and the following disclaimer.
159d8b5fa7Sdrochner  * 2. Redistributions in binary form must reproduce the above copyright
169d8b5fa7Sdrochner  *    notice, this list of conditions and the following disclaimer in the
179d8b5fa7Sdrochner  *    documentation and/or other materials provided with the distribution.
189d8b5fa7Sdrochner  *
199d8b5fa7Sdrochner  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
209d8b5fa7Sdrochner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
219d8b5fa7Sdrochner  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
229d8b5fa7Sdrochner  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
239d8b5fa7Sdrochner  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
249d8b5fa7Sdrochner  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
259d8b5fa7Sdrochner  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
269d8b5fa7Sdrochner  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
279d8b5fa7Sdrochner  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
289d8b5fa7Sdrochner  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
299d8b5fa7Sdrochner  * POSSIBILITY OF SUCH DAMAGE.
309d8b5fa7Sdrochner  */
319d8b5fa7Sdrochner 
329d8b5fa7Sdrochner #include <complex.h>
339d8b5fa7Sdrochner #include <math.h>
349d8b5fa7Sdrochner 
359d8b5fa7Sdrochner float complex
csqrtf(float complex z)369d8b5fa7Sdrochner csqrtf(float complex z)
379d8b5fa7Sdrochner {
389d8b5fa7Sdrochner 	float complex w;
399d8b5fa7Sdrochner 	float x, y, r, t, scale;
409d8b5fa7Sdrochner 
419d8b5fa7Sdrochner 	x = crealf (z);
429d8b5fa7Sdrochner 	y = cimagf (z);
439d8b5fa7Sdrochner 
44*038de09fSmaya 	/*
45*038de09fSmaya 	 * input is a real number and imaginary part isn't -0.0.
46*038de09fSmaya 	 * negative zero is on the branch cut.
47*038de09fSmaya 	 */
4843e54dd9Smaya 	if ((y == 0.0f) && !signbit(y)) {
499d8b5fa7Sdrochner 		if (x < 0.0f) {
509d8b5fa7Sdrochner 			w = 0.0f + sqrtf(-x) * I;
519d8b5fa7Sdrochner 			return w;
529d8b5fa7Sdrochner 		} else if (x == 0.0f) {
539d8b5fa7Sdrochner 			return (0.0f + y * I);
549d8b5fa7Sdrochner 		} else {
559d8b5fa7Sdrochner 			w = sqrtf(x) + y * I;
569d8b5fa7Sdrochner 			return w;
579d8b5fa7Sdrochner 		}
589d8b5fa7Sdrochner 	}
599d8b5fa7Sdrochner 
609d8b5fa7Sdrochner 	if (x == 0.0f) {
61c0f2822aSmaya 		if (y > 0) {
62c0f2822aSmaya 			r = sqrtf(0.5f * y);
639d8b5fa7Sdrochner 			w = r + r * I;
64c0f2822aSmaya 		} else {
65c0f2822aSmaya 			r = sqrtf(-0.5f * y);
669d8b5fa7Sdrochner 			w = r - r * I;
67c0f2822aSmaya 		}
689d8b5fa7Sdrochner 		return w;
699d8b5fa7Sdrochner 	}
709d8b5fa7Sdrochner 
719d8b5fa7Sdrochner 	/* Rescale to avoid internal overflow or underflow.  */
729d8b5fa7Sdrochner 	if ((fabsf(x) > 4.0f) || (fabsf(y) > 4.0f)) {
739d8b5fa7Sdrochner 		x *= 0.25f;
749d8b5fa7Sdrochner 		y *= 0.25f;
759d8b5fa7Sdrochner 		scale = 2.0f;
769d8b5fa7Sdrochner 	} else {
779d8b5fa7Sdrochner #if 1
789d8b5fa7Sdrochner 		x *= 6.7108864e7f; /* 2^26 */
799d8b5fa7Sdrochner 		y *= 6.7108864e7f;
809d8b5fa7Sdrochner 		scale = 1.220703125e-4f; /* 2^-13 */
819d8b5fa7Sdrochner #else
829d8b5fa7Sdrochner 		x *= 4.0f;
839d8b5fa7Sdrochner 		y *= 4.0f;
849d8b5fa7Sdrochner 		scale = 0.5f;
859d8b5fa7Sdrochner #endif
869d8b5fa7Sdrochner 	}
879d8b5fa7Sdrochner 	w = x + y * I;
889d8b5fa7Sdrochner 	r = cabsf(w);
899d8b5fa7Sdrochner 	if( x > 0 ) {
909d8b5fa7Sdrochner 		t = sqrtf(0.5f * r + 0.5f * x);
919d8b5fa7Sdrochner 		r = scale * fabsf((0.5f * y) / t);
929d8b5fa7Sdrochner 		t *= scale;
939d8b5fa7Sdrochner 	} else {
949d8b5fa7Sdrochner 		r = sqrtf(0.5f * r - 0.5f * x);
959d8b5fa7Sdrochner 		t = scale * fabsf((0.5f * y) / r);
969d8b5fa7Sdrochner 		r *= scale;
979d8b5fa7Sdrochner 	}
989d8b5fa7Sdrochner 
99*038de09fSmaya 	if (y > 0)
1009d8b5fa7Sdrochner 		w = t + r * I;
101*038de09fSmaya 	else
102*038de09fSmaya 		w = t - r * I;
1039d8b5fa7Sdrochner 	return w;
1049d8b5fa7Sdrochner }
105