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