divsc3.c revision 222656
1166124Srafan/*===-- divsc3.c - Implement __divsc3 -------------------------------------=== 2166124Srafan * 3166124Srafan * The LLVM Compiler Infrastructure 4166124Srafan * 5166124Srafan * This file is dual licensed under the MIT and the University of Illinois Open 6166124Srafan * Source Licenses. See LICENSE.TXT for details. 7166124Srafan * 8166124Srafan * ===----------------------------------------------------------------------=== 9166124Srafan * 10166124Srafan * This file implements __divsc3 for the compiler_rt library. 11166124Srafan * 12166124Srafan *===----------------------------------------------------------------------=== 13166124Srafan */ 14166124Srafan 15166124Srafan#include "int_lib.h" 16166124Srafan#include <math.h> 17166124Srafan#include <complex.h> 18166124Srafan 19166124Srafan/* Returns: the quotient of (a + ib) / (c + id) */ 20166124Srafan 21166124Srafanfloat _Complex 22166124Srafan__divsc3(float __a, float __b, float __c, float __d) 23166124Srafan{ 24166124Srafan int __ilogbw = 0; 25166124Srafan float __logbw = logbf(fmaxf(fabsf(__c), fabsf(__d))); 26166124Srafan if (isfinite(__logbw)) 27166124Srafan { 28166124Srafan __ilogbw = (int)__logbw; 29166124Srafan __c = scalbnf(__c, -__ilogbw); 30166124Srafan __d = scalbnf(__d, -__ilogbw); 31166124Srafan } 32166124Srafan float __denom = __c * __c + __d * __d; 33166124Srafan float _Complex z; 34166124Srafan __real__ z = scalbnf((__a * __c + __b * __d) / __denom, -__ilogbw); 35166124Srafan __imag__ z = scalbnf((__b * __c - __a * __d) / __denom, -__ilogbw); 36166124Srafan if (isnan(__real__ z) && isnan(__imag__ z)) 37166124Srafan { 38166124Srafan if ((__denom == 0) && (!isnan(__a) || !isnan(__b))) 39166124Srafan { 40166124Srafan __real__ z = copysignf(INFINITY, __c) * __a; 41166124Srafan __imag__ z = copysignf(INFINITY, __c) * __b; 42166124Srafan } 43166124Srafan else if ((isinf(__a) || isinf(__b)) && isfinite(__c) && isfinite(__d)) 44166124Srafan { 45166124Srafan __a = copysignf(isinf(__a) ? 1 : 0, __a); 46166124Srafan __b = copysignf(isinf(__b) ? 1 : 0, __b); 47166124Srafan __real__ z = INFINITY * (__a * __c + __b * __d); 48166124Srafan __imag__ z = INFINITY * (__b * __c - __a * __d); 49166124Srafan } 50166124Srafan else if (isinf(__logbw) && __logbw > 0 && isfinite(__a) && isfinite(__b)) 51166124Srafan { 52166124Srafan __c = copysignf(isinf(__c) ? 1 : 0, __c); 53166124Srafan __d = copysignf(isinf(__d) ? 1 : 0, __d); 54166124Srafan __real__ z = 0 * (__a * __c + __b * __d); 55166124Srafan __imag__ z = 0 * (__b * __c - __a * __d); 56166124Srafan } 57166124Srafan } 58166124Srafan return z; 59} 60