t2ex/bsd_source/lib/libc/src_bsd/complex/s_csqrt.c | bare source | permlink (0.03 seconds) |
1: /* $OpenBSD: s_csqrt.c,v 1.2 2011/07/08 19:25:31 martynas Exp $ */ 2: /* 3: * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net> 4: * 5: * Permission to use, copy, modify, and distribute this software for any 6: * purpose with or without fee is hereby granted, provided that the above 7: * copyright notice and this permission notice appear in all copies. 8: * 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16: */ 17: 18: /* LINTLIBRARY */ 19: 20: /* csqrt() 21: * 22: * Complex square root 23: * 24: * 25: * 26: * SYNOPSIS: 27: * 28: * double complex csqrt(); 29: * double complex z, w; 30: * 31: * w = csqrt (z); 32: * 33: * 34: * 35: * DESCRIPTION: 36: * 37: * 38: * If z = x + iy, r = |z|, then 39: * 40: * 1/2 41: * Re w = [ (r + x)/2 ] , 42: * 43: * 1/2 44: * Im w = [ (r - x)/2 ] . 45: * 46: * Cancellation error in r-x or r+x is avoided by using the 47: * identity 2 Re w Im w = y. 48: * 49: * Note that -w is also a square root of z. The root chosen 50: * is always in the right half plane and Im w has the same sign as y. 51: * 52: * 53: * 54: * ACCURACY: 55: * 56: * Relative error: 57: * arithmetic domain # trials peak rms 58: * DEC -10,+10 25000 3.2e-17 9.6e-18 59: * IEEE -10,+10 1,000,000 2.9e-16 6.1e-17 60: * 61: */ 62: 63: #include <sys/cdefs.h> 64: #include <complex.h> 65: #include <float.h> 66: #include <math.h> 67: 68: double complex 69: csqrt(double complex z) 70: { 71: double complex w; 72: double x, y, r, t, scale; 73: 74: x = creal (z); 75: y = cimag (z); 76: 77: if (y == 0.0) { 78: if (x == 0.0) { 79: w = 0.0 + y * I; 80: } 81: else { 82: r = fabs (x); 83: r = sqrt (r); 84: if (x < 0.0) { 85: w = 0.0 + r * I; 86: } 87: else { 88: w = r + y * I; 89: } 90: } 91: return (w); 92: } 93: if (x == 0.0) { 94: r = fabs (y); 95: r = sqrt (0.5*r); 96: if (y > 0) 97: w = r + r * I; 98: else 99: w = r - r * I; 100: return (w); 101: } 102: /* Rescale to avoid internal overflow or underflow. */ 103: if ((fabs(x) > 4.0) || (fabs(y) > 4.0)) { 104: x *= 0.25; 105: y *= 0.25; 106: scale = 2.0; 107: } 108: else { 109: x *= 1.8014398509481984e16; /* 2^54 */ 110: y *= 1.8014398509481984e16; 111: scale = 7.450580596923828125e-9; /* 2^-27 */ 112: #if 0 113: x *= 4.0; 114: y *= 4.0; 115: scale = 0.5; 116: #endif 117: } 118: w = x + y * I; 119: r = cabs(w); 120: if (x > 0) { 121: t = sqrt(0.5 * r + 0.5 * x); 122: r = scale * fabs((0.5 * y) / t); 123: t *= scale; 124: } 125: else { 126: r = sqrt( 0.5 * r - 0.5 * x ); 127: t = scale * fabs( (0.5 * y) / r ); 128: r *= scale; 129: } 130: if (y < 0) 131: w = t - r * I; 132: else 133: w = t + r * I; 134: return (w); 135: } 136: 137: #if LDBL_MANT_DIG == 53 138: #ifdef lint 139: /* PROTOLIB1 */ 140: long double complex csqrtl(long double complex); 141: #else /* lint */ 142: __weak_alias(csqrtl, csqrt); 143: #endif /* lint */ 144: #endif /* LDBL_MANT_DIG == 53 */