2009-08-08 04:30:09 +08:00
|
|
|
/*===-- divsc3.c - Implement __divsc3 -------------------------------------===
|
|
|
|
*
|
|
|
|
* The LLVM Compiler Infrastructure
|
|
|
|
*
|
2010-11-17 06:13:33 +08:00
|
|
|
* This file is dual licensed under the MIT and the University of Illinois Open
|
|
|
|
* Source Licenses. See LICENSE.TXT for details.
|
2009-08-08 04:30:09 +08:00
|
|
|
*
|
|
|
|
* ===----------------------------------------------------------------------===
|
|
|
|
*
|
|
|
|
* This file implements __divsc3 for the compiler_rt library.
|
|
|
|
*
|
|
|
|
*===----------------------------------------------------------------------===
|
|
|
|
*/
|
2009-06-27 00:47:03 +08:00
|
|
|
|
[compiler-rt] [builtins] Add logb/logbf/logbl methods to compiler-rt to avoid libm dependencies when possible.
Summary:
The complex division builtins (div?c3) use logb methods from libm to scale numbers during division and avoid rounding issues. However, these come from libm, meaning anyone that uses --rtlib=compiler-rt also has to include -lm. Implement logb* methods for standard ieee 754 floats so we can avoid -lm on those platforms, falling back to the old behavior (using either logb() or `__builtin_logb()`) when not supported.
These new methods are defined internally as `__compiler_rt_logb` so as not to conflict with the libm definitions in any way.
This fixes just the libm methods mentioned in PR32279 and PR28652. libc is still required, although that seems to not be an issue.
Note: this is proposed as an alternative to just adding -lm: D49330.
Reviewers: efriedma, compnerd, scanon, echristo
Reviewed By: echristo
Subscribers: jsji, echristo, nemanjai, dberris, mgorny, kbarton, delcypher, llvm-commits, #sanitizers
Differential Revision: https://reviews.llvm.org/D49514
llvm-svn: 342917
2018-09-25 04:39:19 +08:00
|
|
|
#define SINGLE_PRECISION
|
|
|
|
#include "fp_lib.h"
|
2009-06-27 00:47:03 +08:00
|
|
|
#include "int_lib.h"
|
2011-11-16 15:33:00 +08:00
|
|
|
#include "int_math.h"
|
2009-06-27 00:47:03 +08:00
|
|
|
|
2009-08-08 04:30:09 +08:00
|
|
|
/* Returns: the quotient of (a + ib) / (c + id) */
|
2009-06-27 00:47:03 +08:00
|
|
|
|
2015-10-07 10:58:07 +08:00
|
|
|
COMPILER_RT_ABI Fcomplex
|
2009-06-27 00:47:03 +08:00
|
|
|
__divsc3(float __a, float __b, float __c, float __d)
|
|
|
|
{
|
|
|
|
int __ilogbw = 0;
|
[compiler-rt] [builtins] Add logb/logbf/logbl methods to compiler-rt to avoid libm dependencies when possible.
Summary:
The complex division builtins (div?c3) use logb methods from libm to scale numbers during division and avoid rounding issues. However, these come from libm, meaning anyone that uses --rtlib=compiler-rt also has to include -lm. Implement logb* methods for standard ieee 754 floats so we can avoid -lm on those platforms, falling back to the old behavior (using either logb() or `__builtin_logb()`) when not supported.
These new methods are defined internally as `__compiler_rt_logb` so as not to conflict with the libm definitions in any way.
This fixes just the libm methods mentioned in PR32279 and PR28652. libc is still required, although that seems to not be an issue.
Note: this is proposed as an alternative to just adding -lm: D49330.
Reviewers: efriedma, compnerd, scanon, echristo
Reviewed By: echristo
Subscribers: jsji, echristo, nemanjai, dberris, mgorny, kbarton, delcypher, llvm-commits, #sanitizers
Differential Revision: https://reviews.llvm.org/D49514
llvm-svn: 342917
2018-09-25 04:39:19 +08:00
|
|
|
float __logbw =
|
|
|
|
__compiler_rt_logbf(crt_fmaxf(crt_fabsf(__c), crt_fabsf(__d)));
|
2011-11-16 15:33:00 +08:00
|
|
|
if (crt_isfinite(__logbw))
|
2009-06-27 00:47:03 +08:00
|
|
|
{
|
|
|
|
__ilogbw = (int)__logbw;
|
2011-11-16 15:33:06 +08:00
|
|
|
__c = crt_scalbnf(__c, -__ilogbw);
|
|
|
|
__d = crt_scalbnf(__d, -__ilogbw);
|
2009-06-27 00:47:03 +08:00
|
|
|
}
|
|
|
|
float __denom = __c * __c + __d * __d;
|
2015-10-07 10:58:07 +08:00
|
|
|
Fcomplex z;
|
|
|
|
COMPLEX_REAL(z) = crt_scalbnf((__a * __c + __b * __d) / __denom, -__ilogbw);
|
|
|
|
COMPLEX_IMAGINARY(z) = crt_scalbnf((__b * __c - __a * __d) / __denom, -__ilogbw);
|
|
|
|
if (crt_isnan(COMPLEX_REAL(z)) && crt_isnan(COMPLEX_IMAGINARY(z)))
|
2009-06-27 00:47:03 +08:00
|
|
|
{
|
2011-11-16 15:33:00 +08:00
|
|
|
if ((__denom == 0) && (!crt_isnan(__a) || !crt_isnan(__b)))
|
2009-06-27 00:47:03 +08:00
|
|
|
{
|
2015-10-07 10:58:07 +08:00
|
|
|
COMPLEX_REAL(z) = crt_copysignf(CRT_INFINITY, __c) * __a;
|
|
|
|
COMPLEX_IMAGINARY(z) = crt_copysignf(CRT_INFINITY, __c) * __b;
|
2009-06-27 00:47:03 +08:00
|
|
|
}
|
2011-11-16 15:33:00 +08:00
|
|
|
else if ((crt_isinf(__a) || crt_isinf(__b)) &&
|
|
|
|
crt_isfinite(__c) && crt_isfinite(__d))
|
2009-06-27 00:47:03 +08:00
|
|
|
{
|
2011-11-16 15:33:06 +08:00
|
|
|
__a = crt_copysignf(crt_isinf(__a) ? 1 : 0, __a);
|
|
|
|
__b = crt_copysignf(crt_isinf(__b) ? 1 : 0, __b);
|
2015-10-07 10:58:07 +08:00
|
|
|
COMPLEX_REAL(z) = CRT_INFINITY * (__a * __c + __b * __d);
|
|
|
|
COMPLEX_IMAGINARY(z) = CRT_INFINITY * (__b * __c - __a * __d);
|
2009-06-27 00:47:03 +08:00
|
|
|
}
|
2011-11-16 15:33:00 +08:00
|
|
|
else if (crt_isinf(__logbw) && __logbw > 0 &&
|
|
|
|
crt_isfinite(__a) && crt_isfinite(__b))
|
2009-06-27 00:47:03 +08:00
|
|
|
{
|
2011-11-16 15:33:06 +08:00
|
|
|
__c = crt_copysignf(crt_isinf(__c) ? 1 : 0, __c);
|
|
|
|
__d = crt_copysignf(crt_isinf(__d) ? 1 : 0, __d);
|
2015-10-07 10:58:07 +08:00
|
|
|
COMPLEX_REAL(z) = 0 * (__a * __c + __b * __d);
|
|
|
|
COMPLEX_IMAGINARY(z) = 0 * (__b * __c - __a * __d);
|
2009-06-27 00:47:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return z;
|
|
|
|
}
|