forked from SerenityOS/serenity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
LibM: Add scalbn and associated functions
Also implement ldexp in terms of them, and add ldexpl
- Loading branch information
1 parent
8f7aa1e
commit 87b61b0
Showing
3 changed files
with
88 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/* | ||
* Copyright (c) 2018-2020, Andreas Kling <[email protected]> | ||
* Copyright (c) 2021, Mițca Dumitru <[email protected]> | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
|
@@ -263,6 +264,31 @@ static int internal_ilogb(FloatT x) NOEXCEPT | |
return (int)extractor.exponent - Extractor::exponent_bias; | ||
} | ||
|
||
template<typename FloatT> | ||
static FloatT internal_scalbn(FloatT x, int exponent) NOEXCEPT | ||
{ | ||
if (x == 0 || !isfinite(x) || isnan(x) || exponent == 0) | ||
return x; | ||
|
||
using Extractor = FloatExtractor<FloatT>; | ||
Extractor extractor; | ||
extractor.d = x; | ||
|
||
if (extractor.exponent != 0) { | ||
extractor.exponent = clamp((int)extractor.exponent + exponent, 0, (int)Extractor::exponent_max); | ||
return extractor.d; | ||
} | ||
|
||
unsigned leading_mantissa_zeroes = extractor.mantissa == 0 ? 32 : __builtin_clz(extractor.mantissa); | ||
int shift = min((int)leading_mantissa_zeroes, exponent); | ||
exponent = max(exponent - shift, 0); | ||
|
||
extractor.exponent <<= shift; | ||
extractor.exponent = exponent + 1; | ||
|
||
return extractor.d; | ||
} | ||
|
||
extern "C" { | ||
|
||
double trunc(double x) NOEXCEPT | ||
|
@@ -333,14 +359,20 @@ float powf(float x, float y) NOEXCEPT | |
return (float)pow(x, y); | ||
} | ||
|
||
// On systems where FLT_RADIX == 2, ldexp is equivalent to scalbn | ||
long double ldexpl(long double x, int exp) NOEXCEPT | ||
{ | ||
return internal_scalbn(x, exp); | ||
} | ||
|
||
double ldexp(double x, int exp) NOEXCEPT | ||
{ | ||
return x * exp2(exp); | ||
return internal_scalbn(x, exp); | ||
} | ||
|
||
float ldexpf(float x, int exp) NOEXCEPT | ||
{ | ||
return x * exp2f(exp); | ||
return internal_scalbn(x, exp); | ||
} | ||
|
||
double tanh(double x) NOEXCEPT | ||
|
@@ -822,4 +854,34 @@ double copysign(double x, double y) | |
ex.sign = ey.sign; | ||
return ex.d; | ||
} | ||
|
||
float scalbnf(float x, int exponent) NOEXCEPT | ||
{ | ||
return internal_scalbn(x, exponent); | ||
} | ||
|
||
double scalbn(double x, int exponent) NOEXCEPT | ||
{ | ||
return internal_scalbn(x, exponent); | ||
} | ||
|
||
long double scalbnl(long double x, int exponent) NOEXCEPT | ||
{ | ||
return internal_scalbn(x, exponent); | ||
} | ||
|
||
float scalbnlf(float x, long exponent) NOEXCEPT | ||
{ | ||
return internal_scalbn(x, exponent); | ||
} | ||
|
||
double scalbln(double x, long exponent) NOEXCEPT | ||
{ | ||
return internal_scalbn(x, exponent); | ||
} | ||
|
||
long double scalblnl(long double x, long exponent) NOEXCEPT | ||
{ | ||
return internal_scalbn(x, exponent); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters