Classificators for double extended floating point numbers
This commit is contained in:
parent
27146f7e0c
commit
586d12b6c7
@ -12,6 +12,68 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.math.fp;
|
module tanya.math.fp;
|
||||||
|
|
||||||
|
import tanya.math.nbtheory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Floating-point number precisions according to IEEE-754.
|
||||||
|
*/
|
||||||
|
enum IEEEPrecision : ubyte
|
||||||
|
{
|
||||||
|
/// Single precision: 64-bit.
|
||||||
|
single = 4,
|
||||||
|
|
||||||
|
/// Single precision: 64-bit.
|
||||||
|
double_ = 8,
|
||||||
|
|
||||||
|
/// Extended precision: 80-bit.
|
||||||
|
extended = 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the precision of floating-point type $(D_PARAM F).
|
||||||
|
*
|
||||||
|
* For $(D_KEYWORD float), $(D_PSYMBOL ieeePrecision) always evaluates to
|
||||||
|
* $(D_INLINECODE IEEEPrecision.single); for $(D_KEYWORD double) - to
|
||||||
|
* $(D_INLINECODE IEEEPrecision.double). It returns different values only
|
||||||
|
* for $(D_KEYWORD real), since $(D_KEYWORD real) is a platform-dependent type.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM F) is a $(D_KEYWORD real) and the target platform isn't
|
||||||
|
* currently supported, static assertion error will be raised (you can use
|
||||||
|
* $(D_INLINECODE is(typeof(ieeePrecision!F))) for testing the platform support
|
||||||
|
* without a compilation error).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* F = Type to be tested.
|
||||||
|
*
|
||||||
|
* Returns: Precision according to IEEE-754.
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL IEEEPrecision).
|
||||||
|
*/
|
||||||
|
template ieeePrecision(F)
|
||||||
|
if (isFloatingPoint!F)
|
||||||
|
{
|
||||||
|
static if (F.sizeof == float.sizeof)
|
||||||
|
{
|
||||||
|
enum IEEEPrecision ieeePrecision = IEEEPrecision.single;
|
||||||
|
}
|
||||||
|
else static if (F.sizeof == double.sizeof)
|
||||||
|
{
|
||||||
|
enum IEEEPrecision ieeePrecision = IEEEPrecision.double_;
|
||||||
|
}
|
||||||
|
else version (X86)
|
||||||
|
{
|
||||||
|
enum IEEEPrecision ieeePrecision = IEEEPrecision.extended;
|
||||||
|
}
|
||||||
|
else version (X86_64)
|
||||||
|
{
|
||||||
|
enum IEEEPrecision ieeePrecision = IEEEPrecision.extended;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(false, "Unsupported IEEE 754 floating point precision");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private union FloatBits(F)
|
private union FloatBits(F)
|
||||||
{
|
{
|
||||||
F floating;
|
F floating;
|
||||||
@ -25,7 +87,7 @@ private union FloatBits(F)
|
|||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
||||||
{
|
{
|
||||||
struct
|
struct // Little-endian.
|
||||||
{
|
{
|
||||||
ulong mantissa;
|
ulong mantissa;
|
||||||
ushort exp;
|
ushort exp;
|
||||||
@ -33,7 +95,7 @@ private union FloatBits(F)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static assert(false, "Unsupported IEEE-754 floating point representation");
|
static assert(false, "Unsupported IEEE 754 floating point precision");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +150,25 @@ if (isFloatingPoint!F)
|
|||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
||||||
{
|
{
|
||||||
|
if (bits.exp == 0x7fff)
|
||||||
|
{
|
||||||
|
if ((bits.mantissa & 0x7fffffffffffffff) == 0)
|
||||||
|
{
|
||||||
|
return FloatingPointClass.infinite;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FloatingPointClass.nan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bits.exp == 0)
|
||||||
|
{
|
||||||
|
return FloatingPointClass.subnormal;
|
||||||
|
}
|
||||||
|
else if (bits.mantissa < 0x8000000000000000) // "Unnormal".
|
||||||
|
{
|
||||||
|
return FloatingPointClass.nan;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FloatingPointClass.normal;
|
return FloatingPointClass.normal;
|
||||||
@ -96,94 +177,87 @@ if (isFloatingPoint!F)
|
|||||||
bool isFinite(F)(F x)
|
bool isFinite(F)(F x)
|
||||||
if (isFloatingPoint!F)
|
if (isFloatingPoint!F)
|
||||||
{
|
{
|
||||||
|
FloatBits!F bits;
|
||||||
static if (ieeePrecision!F == IEEEPrecision.single)
|
static if (ieeePrecision!F == IEEEPrecision.single)
|
||||||
{
|
{
|
||||||
FloatBits!F bits;
|
|
||||||
bits.floating = x;
|
bits.floating = x;
|
||||||
bits.integral &= 0x7f800000;
|
bits.integral &= 0x7f800000;
|
||||||
return bits.integral != 0x7f800000;
|
return bits.integral != 0x7f800000;
|
||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.double_)
|
else static if (ieeePrecision!F == IEEEPrecision.double_)
|
||||||
{
|
{
|
||||||
FloatBits!F bits;
|
|
||||||
bits.floating = x;
|
bits.floating = x;
|
||||||
bits.integral &= 0x7ff0000000000000;
|
bits.integral &= 0x7ff0000000000000;
|
||||||
return bits.integral != 0x7ff0000000000000;
|
return bits.integral != 0x7ff0000000000000;
|
||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
||||||
{
|
{
|
||||||
FloatBits!F bits;
|
|
||||||
bits.floating = abs(x);
|
bits.floating = abs(x);
|
||||||
return exponent != 0x7fff;
|
return (bits.exp != 0x7fff) && (bits.mantissa >= 0x8000000000000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNaN(F)(F x)
|
bool isNaN(F)(F x)
|
||||||
if (isFloatingPoint!F)
|
if (isFloatingPoint!F)
|
||||||
{
|
{
|
||||||
static if (ieeePrecision!F == IEEEPrecision.single)
|
|
||||||
{
|
|
||||||
FloatBits!F bits;
|
FloatBits!F bits;
|
||||||
bits.floating = abs(x);
|
bits.floating = abs(x);
|
||||||
|
|
||||||
|
static if (ieeePrecision!F == IEEEPrecision.single)
|
||||||
|
{
|
||||||
return bits.integral > 0x7f800000;
|
return bits.integral > 0x7f800000;
|
||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.double_)
|
else static if (ieeePrecision!F == IEEEPrecision.double_)
|
||||||
{
|
{
|
||||||
FloatBits!F bits;
|
|
||||||
bits.floating = abs(x);
|
|
||||||
return bits.integral > 0x7ff0000000000000;
|
return bits.integral > 0x7ff0000000000000;
|
||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
||||||
{
|
{
|
||||||
FloatBits!F bits;
|
if ((bits.exp == 0x7fff && (bits.mantissa & 0x7fffffffffffffff) != 0)
|
||||||
bits.floating = abs(x);
|
|| ((bits.exp != 0) && (bits.mantissa < 0x8000000000000000)))
|
||||||
return bits.exponent == 0x7fff && bits.mantissa != 0;
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInfinity(F)(F x)
|
bool isInfinity(F)(F x)
|
||||||
if (isFloatingPoint!F)
|
if (isFloatingPoint!F)
|
||||||
{
|
{
|
||||||
static if (ieeePrecision!F == IEEEPrecision.single)
|
|
||||||
{
|
|
||||||
FloatBits!F bits;
|
FloatBits!F bits;
|
||||||
bits.floating = abs(x);
|
bits.floating = abs(x);
|
||||||
|
static if (ieeePrecision!F == IEEEPrecision.single)
|
||||||
|
{
|
||||||
return bits.integral == 0x7f800000;
|
return bits.integral == 0x7f800000;
|
||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.double_)
|
else static if (ieeePrecision!F == IEEEPrecision.double_)
|
||||||
{
|
{
|
||||||
FloatBits!F bits;
|
|
||||||
bits.floating = abs(x);
|
|
||||||
return bits.integral == 0x7ff0000000000000;
|
return bits.integral == 0x7ff0000000000000;
|
||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
||||||
{
|
{
|
||||||
FloatBits!F bits;
|
return (bits.exp == 0x7fff)
|
||||||
bits.floating = abs(x);
|
&& ((bits.mantissa & 0x7fffffffffffffff) == 0);
|
||||||
return bits.exponent == 0x7fff && bits.mantissa == 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSubnormal(F)(F x)
|
bool isSubnormal(F)(F x)
|
||||||
if (isFloatingPoint!F)
|
if (isFloatingPoint!F)
|
||||||
{
|
{
|
||||||
static if (ieeePrecision!F == IEEEPrecision.single)
|
|
||||||
{
|
|
||||||
FloatBits!F bits;
|
FloatBits!F bits;
|
||||||
bits.floating = abs(x);
|
bits.floating = abs(x);
|
||||||
|
static if (ieeePrecision!F == IEEEPrecision.single)
|
||||||
|
{
|
||||||
return bits.integral < 0x800000;
|
return bits.integral < 0x800000;
|
||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.double_)
|
else static if (ieeePrecision!F == IEEEPrecision.double_)
|
||||||
{
|
{
|
||||||
FloatBits!F bits;
|
|
||||||
bits.floating = abs(x);
|
|
||||||
return bits.integral < 0x10000000000000;
|
return bits.integral < 0x10000000000000;
|
||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
||||||
{
|
{
|
||||||
FloatBits!F bits;
|
return bits.exp == 0;
|
||||||
bits.floating = abs(x);
|
|
||||||
return bits.exponent == 0 && bits.mantissa != 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,8 +280,25 @@ if (isFloatingPoint!F)
|
|||||||
}
|
}
|
||||||
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
||||||
{
|
{
|
||||||
FloatBits!F bits;
|
return classify(x) == FloatingPointClass.normal;
|
||||||
bits.floating = abs(x);
|
}
|
||||||
return bits.exponent != 0 && exponent != 0x7fff;
|
}
|
||||||
|
|
||||||
|
bool signBit(F)(F x)
|
||||||
|
if (isFloatingPoint!F)
|
||||||
|
{
|
||||||
|
FloatBits!F bits;
|
||||||
|
bits.floating = x;
|
||||||
|
static if (ieeePrecision!F == IEEEPrecision.single)
|
||||||
|
{
|
||||||
|
return (bits.integral & (1 << 31)) != 0;
|
||||||
|
}
|
||||||
|
else static if (ieeePrecision!F == IEEEPrecision.double_)
|
||||||
|
{
|
||||||
|
return (bits.integral & (1 << 63)) != 0;
|
||||||
|
}
|
||||||
|
else static if (ieeePrecision!F == IEEEPrecision.extended)
|
||||||
|
{
|
||||||
|
return (bits.exp & (1 << 15)) != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,66 +17,6 @@ module tanya.math.nbtheory;
|
|||||||
import tanya.math.mp;
|
import tanya.math.mp;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
|
|
||||||
/**
|
|
||||||
* Floating-point number precisions according to IEEE-754.
|
|
||||||
*/
|
|
||||||
enum IEEEPrecision : ubyte
|
|
||||||
{
|
|
||||||
/// Single precision: 64-bit.
|
|
||||||
single = 4,
|
|
||||||
|
|
||||||
/// Single precision: 64-bit.
|
|
||||||
double_ = 8,
|
|
||||||
|
|
||||||
/// Extended precision: 80-bit.
|
|
||||||
extended = 10,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the precision of floating-point type $(D_PARAM F).
|
|
||||||
*
|
|
||||||
* For $(D_KEYWORD float), $(D_PSYMBOL ieeePrecision) always evaluates to
|
|
||||||
* $(D_INLINECODE IEEEPrecision.single); for $(D_KEYWORD double) - to
|
|
||||||
* $(D_INLINECODE IEEEPrecision.double). It returns different values only
|
|
||||||
* for $(D_KEYWORD real), since $(D_KEYWORD real) is a platform-dependent type.
|
|
||||||
*
|
|
||||||
* If $(D_PARAM F) is a $(D_KEYWORD real) and the target platform isn't
|
|
||||||
* currently supported, static assertion error will be raised (you can use
|
|
||||||
* $(D_INLINECODE is(typeof(ieeePrecision!F))) for testing the platform support
|
|
||||||
* without a compilation error).
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* F = Type to be tested.
|
|
||||||
*
|
|
||||||
* Returns: Precision according to IEEE-754.
|
|
||||||
*
|
|
||||||
* See_Also: $(D_PSYMBOL IEEEPrecision).
|
|
||||||
*/
|
|
||||||
template ieeePrecision(F)
|
|
||||||
if (isFloatingPoint!F)
|
|
||||||
{
|
|
||||||
static if (F.sizeof == float.sizeof)
|
|
||||||
{
|
|
||||||
enum IEEEPrecision ieeePrecision = IEEEPrecision.single;
|
|
||||||
}
|
|
||||||
else static if (F.sizeof == double.sizeof)
|
|
||||||
{
|
|
||||||
enum IEEEPrecision ieeePrecision = IEEEPrecision.double_;
|
|
||||||
}
|
|
||||||
else version (X86)
|
|
||||||
{
|
|
||||||
enum IEEEPrecision ieeePrecision = IEEEPrecision.extended;
|
|
||||||
}
|
|
||||||
else version (X86_64)
|
|
||||||
{
|
|
||||||
enum IEEEPrecision ieeePrecision = IEEEPrecision.extended;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static assert(false, "Unsupported IEEE 754 precision");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the absolute value of a number.
|
* Calculates the absolute value of a number.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user