Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Third Party Musl
提交
da7458a6
T
Third Party Musl
项目概览
OpenHarmony
/
Third Party Musl
1 年多 前同步成功
通知
37
Star
125
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
Third Party Musl
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
da7458a6
编写于
3月 19, 2012
作者:
R
Rich Felker
浏览文件
操作
浏览文件
下载
差异文件
Merge remote branch 'nsz/master'
上级
be5b01f8
8051e08e
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
208 addition
and
163 deletion
+208
-163
src/math/fma.c
src/math/fma.c
+139
-7
src/math/fmal.c
src/math/fmal.c
+4
-4
src/math/scalbn.c
src/math/scalbn.c
+21
-55
src/math/scalbnf.c
src/math/scalbnf.c
+22
-48
src/math/scalbnl.c
src/math/scalbnl.c
+22
-49
未找到文件。
src/math/fma.c
浏览文件 @
da7458a6
#include <fenv.h>
#include "libm.h"
#if LDBL_MANT_DIG==64 && LDBL_MAX_EXP==16384
union
ld80
{
long
double
x
;
struct
{
uint64_t
m
;
uint16_t
e
:
15
;
uint16_t
s
:
1
;
uint16_t
pad
;
}
bits
;
};
/* exact add, assumes exponent_x >= exponent_y */
static
void
add
(
long
double
*
hi
,
long
double
*
lo
,
long
double
x
,
long
double
y
)
{
long
double
r
;
r
=
x
+
y
;
*
hi
=
r
;
r
-=
x
;
*
lo
=
y
-
r
;
}
/* exact mul, assumes no over/underflow */
static
void
mul
(
long
double
*
hi
,
long
double
*
lo
,
long
double
x
,
long
double
y
)
{
static
const
long
double
c
=
1
.
0
+
0x1
p32L
;
long
double
cx
,
xh
,
xl
,
cy
,
yh
,
yl
;
cx
=
c
*
x
;
xh
=
(
x
-
cx
)
+
cx
;
xl
=
x
-
xh
;
cy
=
c
*
y
;
yh
=
(
y
-
cy
)
+
cy
;
yl
=
y
-
yh
;
*
hi
=
x
*
y
;
*
lo
=
(
xh
*
yh
-
*
hi
)
+
xh
*
yl
+
xl
*
yh
+
xl
*
yl
;
}
/*
assume (long double)(hi+lo) == hi
return an adjusted hi so that rounding it to double is correct
*/
static
long
double
adjust
(
long
double
hi
,
long
double
lo
)
{
union
ld80
uhi
,
ulo
;
if
(
lo
==
0
)
return
hi
;
uhi
.
x
=
hi
;
if
(
uhi
.
bits
.
m
&
0x3ff
)
return
hi
;
ulo
.
x
=
lo
;
if
(
uhi
.
bits
.
s
==
ulo
.
bits
.
s
)
uhi
.
bits
.
m
++
;
else
uhi
.
bits
.
m
--
;
return
uhi
.
x
;
}
static
long
double
dadd
(
long
double
x
,
long
double
y
)
{
add
(
&
x
,
&
y
,
x
,
y
);
return
adjust
(
x
,
y
);
}
static
long
double
dmul
(
long
double
x
,
long
double
y
)
{
mul
(
&
x
,
&
y
,
x
,
y
);
return
adjust
(
x
,
y
);
}
static
int
getexp
(
long
double
x
)
{
union
ld80
u
;
u
.
x
=
x
;
return
u
.
bits
.
e
;
}
double
fma
(
double
x
,
double
y
,
double
z
)
{
long
double
hi
,
lo1
,
lo2
,
xy
;
int
round
,
ez
,
exy
;
/* handle +-inf,nan */
if
(
!
isfinite
(
x
)
||
!
isfinite
(
y
))
return
x
*
y
+
z
;
if
(
!
isfinite
(
z
))
return
z
;
/* handle +-0 */
if
(
x
==
0
.
0
||
y
==
0
.
0
)
return
x
*
y
+
z
;
round
=
fegetround
();
if
(
z
==
0
.
0
)
{
if
(
round
==
FE_TONEAREST
)
return
dmul
(
x
,
y
);
return
x
*
y
;
}
/* exact mul and add require nearest rounding */
/* spurious inexact exceptions may be raised */
fesetround
(
FE_TONEAREST
);
mul
(
&
xy
,
&
lo1
,
x
,
y
);
exy
=
getexp
(
xy
);
ez
=
getexp
(
z
);
if
(
ez
>
exy
)
{
add
(
&
hi
,
&
lo2
,
z
,
xy
);
}
else
if
(
ez
>
exy
-
12
)
{
add
(
&
hi
,
&
lo2
,
xy
,
z
);
if
(
hi
==
0
)
{
fesetround
(
round
);
/* make sure that the sign of 0 is correct */
return
(
xy
+
z
)
+
lo1
;
}
}
else
{
/*
ez <= exy - 12
the 12 extra bits (1guard, 11round+sticky) are needed so with
lo = dadd(lo1, lo2)
elo <= ehi - 11, and we use the last 10 bits in adjust so
dadd(hi, lo)
gives correct result when rounded to double
*/
hi
=
xy
;
lo2
=
z
;
}
fesetround
(
round
);
if
(
round
==
FE_TONEAREST
)
return
dadd
(
hi
,
dadd
(
lo1
,
lo2
));
return
hi
+
(
lo1
+
lo2
);
}
#else
/* origin: FreeBSD /usr/src/lib/msun/src/s_fma.c */
/*-
* Copyright (c) 2005-2011 David Schultz <das@FreeBSD.ORG>
...
...
@@ -25,9 +159,6 @@
* SUCH DAMAGE.
*/
#include <fenv.h>
#include "libm.h"
/*
* A struct dd represents a floating-point number with twice the precision
* of a double. We maintain the invariant that "hi" stores the 53 high-order
...
...
@@ -178,14 +309,14 @@ double fma(double x, double y, double z)
* return values here are crucial in handling special cases involving
* infinities, NaNs, overflows, and signed zeroes correctly.
*/
if
(
x
==
0
.
0
||
y
==
0
.
0
)
return
(
x
*
y
+
z
);
if
(
z
==
0
.
0
)
return
(
x
*
y
);
if
(
!
isfinite
(
x
)
||
!
isfinite
(
y
))
return
(
x
*
y
+
z
);
if
(
!
isfinite
(
z
))
return
(
z
);
if
(
x
==
0
.
0
||
y
==
0
.
0
)
return
(
x
*
y
+
z
);
if
(
z
==
0
.
0
)
return
(
x
*
y
);
xs
=
frexp
(
x
,
&
ex
);
ys
=
frexp
(
y
,
&
ey
);
...
...
@@ -278,3 +409,4 @@ double fma(double x, double y, double z)
else
return
(
add_and_denormalize
(
r
.
hi
,
adj
,
spread
));
}
#endif
src/math/fmal.c
浏览文件 @
da7458a6
...
...
@@ -173,14 +173,14 @@ long double fmal(long double x, long double y, long double z)
* return values here are crucial in handling special cases involving
* infinities, NaNs, overflows, and signed zeroes correctly.
*/
if
(
x
==
0
.
0
||
y
==
0
.
0
)
return
(
x
*
y
+
z
);
if
(
z
==
0
.
0
)
return
(
x
*
y
);
if
(
!
isfinite
(
x
)
||
!
isfinite
(
y
))
return
(
x
*
y
+
z
);
if
(
!
isfinite
(
z
))
return
(
z
);
if
(
x
==
0
.
0
||
y
==
0
.
0
)
return
(
x
*
y
+
z
);
if
(
z
==
0
.
0
)
return
(
x
*
y
);
xs
=
frexpl
(
x
,
&
ex
);
ys
=
frexpl
(
y
,
&
ey
);
...
...
src/math/scalbn.c
浏览文件 @
da7458a6
/* origin: FreeBSD /usr/src/lib/msun/src/s_scalbn.c */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* scalbn (double x, int n)
* scalbn(x,n) returns x* 2**n computed by exponent
* manipulation rather than by actually performing an
* exponentiation or a multiplication.
*/
#include "libm.h"
static
const
double
two54
=
1.80143985094819840000e+16
,
/* 0x43500000, 0x00000000 */
twom54
=
5.55111512312578270212e-17
,
/* 0x3C900000, 0x00000000 */
huge
=
1.0e+300
,
tiny
=
1.0e-300
;
double
scalbn
(
double
x
,
int
n
)
{
// FIXME: k+n check depends on signed int overflow.. use unsigned hx
// TODO: when long != int:
// scalbln(x,long n) { if(n>9999)n=9999; else if(n<-9999)n=-9999; return scalbn(x,n); }
// TODO: n < -50000 ...
int32_t
k
,
hx
,
lx
;
double
scale
;
EXTRACT_WORDS
(
hx
,
lx
,
x
);
k
=
(
hx
&
0x7ff00000
)
>>
20
;
/* extract exponent */
if
(
k
==
0
)
{
/* 0 or subnormal x */
if
((
lx
|
(
hx
&
0x7fffffff
))
==
0
)
/* +-0 */
return
x
;
x
*=
two54
;
GET_HIGH_WORD
(
hx
,
x
);
k
=
((
hx
&
0x7ff00000
)
>>
20
)
-
54
;
if
(
n
<
-
50000
)
return
tiny
*
x
;
/*underflow*/
}
if
(
k
==
0x7ff
)
/* NaN or Inf */
return
x
+
x
;
k
=
k
+
n
;
if
(
k
>
0x7fe
)
return
huge
*
copysign
(
huge
,
x
);
/* overflow */
if
(
k
>
0
)
{
/* normal result */
SET_HIGH_WORD
(
x
,
(
hx
&
0x800fffff
)
|
(
k
<<
20
));
return
x
;
if
(
n
>
1023
)
{
x
*=
0x1
p1023
;
n
-=
1023
;
if
(
n
>
1023
)
{
x
*=
0x1
p1023
;
n
-=
1023
;
if
(
n
>
1023
)
return
x
*
0x1
p1023
;
}
}
else
if
(
n
<
-
1022
)
{
x
*=
0x1
p
-
1022
;
n
+=
1022
;
if
(
n
<
-
1022
)
{
x
*=
0x1
p
-
1022
;
n
+=
1022
;
if
(
n
<
-
1022
)
return
x
*
0x1
p
-
1022
;
}
}
if
(
k
<=
-
54
)
if
(
n
>
50000
)
/* in case integer overflow in n+k */
return
huge
*
copysign
(
huge
,
x
);
/*overflow*/
return
tiny
*
copysign
(
tiny
,
x
);
/*underflow*/
k
+=
54
;
/* subnormal result */
SET_HIGH_WORD
(
x
,
(
hx
&
0x800fffff
)
|
(
k
<<
20
));
return
x
*
twom54
;
INSERT_WORDS
(
scale
,
(
uint32_t
)(
0x3ff
+
n
)
<<
20
,
0
);
return
x
*
scale
;
}
src/math/scalbnf.c
浏览文件 @
da7458a6
/* origin: FreeBSD /usr/src/lib/msun/src/s_scalbnf.c */
/*
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
*/
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#include "libm.h"
static
const
float
two25
=
3.355443200e+07
,
/* 0x4c000000 */
twom25
=
2.9802322388e-08
,
/* 0x33000000 */
huge
=
1.0e+30
,
tiny
=
1.0e-30
;
float
scalbnf
(
float
x
,
int
n
)
{
int32_t
k
,
ix
;
GET_FLOAT_WORD
(
ix
,
x
);
k
=
(
ix
&
0x7f800000
)
>>
23
;
/* extract exponent */
if
(
k
==
0
)
{
/* 0 or subnormal x */
if
((
ix
&
0x7fffffff
)
==
0
)
/* +-0 */
return
x
;
x
*=
two25
;
GET_FLOAT_WORD
(
ix
,
x
)
;
k
=
((
ix
&
0x7f800000
)
>>
23
)
-
25
;
if
(
n
<
-
50000
)
return
tiny
*
x
;
/*underflow*/
}
if
(
k
==
0xff
)
/* NaN or Inf */
return
x
+
x
;
k
=
k
+
n
;
if
(
k
>
0xfe
)
return
huge
*
copysignf
(
huge
,
x
);
/* overflow */
if
(
k
>
0
)
{
/* normal result */
SET_FLOAT_WORD
(
x
,
(
ix
&
0x807fffff
)
|
(
k
<<
23
))
;
return
x
;
float
scale
;
if
(
n
>
127
)
{
x
*=
0x1
p127f
;
n
-=
127
;
if
(
n
>
127
)
{
x
*=
0x1
p127f
;
n
-=
127
;
if
(
n
>
127
)
return
x
*
0x1
p127f
;
}
}
else
if
(
n
<
-
126
)
{
x
*=
0x1
p
-
126
f
;
n
+=
126
;
if
(
n
<
-
126
)
{
x
*=
0x1
p
-
126
f
;
n
+=
126
;
if
(
n
<
-
126
)
return
x
*
0x1
p
-
126
f
;
}
}
if
(
k
<=
-
25
)
if
(
n
>
50000
)
/* in case integer overflow in n+k */
return
huge
*
copysignf
(
huge
,
x
);
/*overflow*/
return
tiny
*
copysignf
(
tiny
,
x
);
/*underflow*/
k
+=
25
;
/* subnormal result */
SET_FLOAT_WORD
(
x
,
(
ix
&
0x807fffff
)
|
(
k
<<
23
));
return
x
*
twom25
;
SET_FLOAT_WORD
(
scale
,
(
uint32_t
)(
0x7f
+
n
)
<<
23
);
return
x
*
scale
;
}
src/math/scalbnl.c
浏览文件 @
da7458a6
/* origin: FreeBSD /usr/src/lib/msun/src/s_scalbnl.c */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* scalbnl (long double x, int n)
* scalbnl(x,n) returns x* 2**n computed by exponent
* manipulation rather than by actually performing an
* exponentiation or a multiplication.
*/
#include "libm.h"
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
...
...
@@ -24,40 +6,31 @@ long double scalbnl(long double x, int n)
return
scalbn
(
x
,
n
);
}
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
static
const
long
double
huge
=
0x1
p16000L
,
tiny
=
0x1
p
-
16000L
;
long
double
scalbnl
(
long
double
x
,
int
n
)
{
union
IEEEl2bits
u
;
int
k
;
union
IEEEl2bits
scale
;
u
.
e
=
x
;
k
=
u
.
bits
.
exp
;
/* extract exponent */
if
(
k
==
0
)
{
/* 0 or subnormal x */
if
(
(
u
.
bits
.
manh
|
u
.
bits
.
manl
)
==
0
)
/* +-0 */
return
x
;
u
.
e
*=
0x1
p128
;
k
=
u
.
bits
.
exp
-
128
;
if
(
n
<
-
50000
)
return
tiny
*
x
;
/*underflow*/
}
if
(
k
==
0x7fff
)
/* NaN or Inf */
return
x
+
x
;
k
=
k
+
n
;
if
(
k
>=
0x7fff
)
return
huge
*
copysignl
(
huge
,
x
);
/* overflow */
if
(
k
>
0
)
{
/* normal result */
u
.
bits
.
exp
=
k
;
return
u
.
e
;
if
(
n
>
16383
)
{
x
*=
0x1
p16383L
;
n
-=
16383
;
if
(
n
>
16383
)
{
x
*=
0x1
p16383L
;
n
-=
16383
;
if
(
n
>
16383
)
return
x
*
0x1
p16383L
;
}
}
else
if
(
n
<
-
16382
)
{
x
*=
0x1
p
-
16382L
;
n
+=
16382
;
if
(
n
<
-
16382
)
{
x
*=
0x1
p
-
16382L
;
n
+=
16382
;
if
(
n
<
-
16382
)
return
x
*
0x1
p
-
16382L
;
}
}
if
(
k
<=
-
128
)
if
(
n
>
50000
)
/* in case integer overflow in n+k */
return
huge
*
copysign
(
huge
,
x
);
/*overflow*/
return
tiny
*
copysign
(
tiny
,
x
);
/*underflow*/
k
+=
128
;
/* subnormal result */
u
.
bits
.
exp
=
k
;
return
u
.
e
*
0x1
p
-
128
;
scale
.
e
=
1
.
0L
;
scale
.
bits
.
exp
=
0x3fff
+
n
;
return
x
*
scale
.
e
;
}
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录