440 lines
11 KiB
D
440 lines
11 KiB
D
module dlib.aliases;
|
||
|
||
// import core.memory;
|
||
//import std.stdint;
|
||
import dlib.math;
|
||
|
||
enum string NO_IMPL = "Not yet implemented.";
|
||
|
||
public import std.traits;
|
||
public import std.meta;
|
||
|
||
version(WebAssembly)
|
||
{
|
||
enum bool NativeTarget = false;
|
||
}
|
||
else
|
||
{
|
||
enum bool NativeTarget = true;
|
||
}
|
||
|
||
debug
|
||
{
|
||
const BUILD_DEBUG = true;
|
||
}
|
||
else
|
||
{
|
||
const BUILD_DEBUG = false;
|
||
}
|
||
|
||
alias i8 = byte;
|
||
alias i16 = short;
|
||
alias i32 = int;
|
||
alias i64 = long;
|
||
|
||
alias u8 = ubyte;
|
||
alias u16 = ushort;
|
||
alias u32 = uint;
|
||
alias u64 = ulong;
|
||
|
||
alias f32 = float;
|
||
alias f64 = double;
|
||
|
||
alias b32 = uint;
|
||
|
||
alias intptr = i64;
|
||
alias uintptr = u64;
|
||
|
||
alias usize = size_t;
|
||
|
||
alias Vec2 = Vector!(f32, 2);
|
||
alias Vec3 = Vector!(f32, 3);
|
||
alias Vec4 = Vector!(f32, 4);
|
||
|
||
alias DVec2 = Vector!(f64, 2);
|
||
alias DVec3 = Vector!(f64, 3);
|
||
alias DVec4 = Vector!(f64, 4);
|
||
|
||
alias IVec2 = Vector!(i32, 2);
|
||
alias IVec3 = Vector!(i32, 3);
|
||
alias IVec4 = Vector!(i32, 4);
|
||
|
||
alias I8Vec2 = Vector!(i8, 2);
|
||
alias I8Vec3 = Vector!(i8, 3);
|
||
alias I8Vec4 = Vector!(i8, 4);
|
||
|
||
alias I16Vec2 = Vector!(i16, 2);
|
||
alias I16Vec3 = Vector!(i16, 3);
|
||
alias I16Vec4 = Vector!(i16, 4);
|
||
|
||
alias I32Vec2 = IVec2;
|
||
alias I32Vec3 = IVec3;
|
||
alias I32Vec4 = IVec4;
|
||
|
||
alias I64Vec2 = Vector!(i64, 2);
|
||
alias I64Vec3 = Vector!(i64, 3);
|
||
alias I64Vec4 = Vector!(i64, 4);
|
||
|
||
alias UVec2 = Vector!(u32, 2);
|
||
alias UVec3 = Vector!(u32, 3);
|
||
alias UVec4 = Vector!(u32, 4);
|
||
|
||
alias U8Vec2 = Vector!(u8, 2);
|
||
alias U8Vec3 = Vector!(u8, 3);
|
||
alias U8Vec4 = Vector!(u8, 4);
|
||
|
||
alias U16Vec2 = Vector!(u16, 2);
|
||
alias U16Vec3 = Vector!(u16, 3);
|
||
alias U16Vec4 = Vector!(u16, 4);
|
||
|
||
alias U32Vec2 = UVec2;
|
||
alias U32Vec3 = UVec3;
|
||
alias U32Vec4 = UVec4;
|
||
|
||
alias U64Vec2 = Vector!(u64, 2);
|
||
alias U64Vec3 = Vector!(u64, 3);
|
||
alias U64Vec4 = Vector!(u64, 4);
|
||
|
||
alias Mat2 = Matrix!(f32, 2);
|
||
alias Mat3 = Matrix!(f32, 3);
|
||
alias Mat4 = Matrix!(f32, 4);
|
||
|
||
alias DMat2 = Matrix!(f64, 2);
|
||
alias DMat3 = Matrix!(f64, 3);
|
||
alias DMat4 = Matrix!(f64, 4);
|
||
|
||
/*
|
||
|
||
enum bool isFloatingPoint(T) = __traits(isFloating, T) && is(T: real);
|
||
enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T) && is(T: real);
|
||
|
||
template isIntegral(T)
|
||
{
|
||
static if(!__traits(isIntegral, T))
|
||
{
|
||
enum isIntegral = false;
|
||
}
|
||
else static if(is(T U == enum))
|
||
{
|
||
enum isIntegral = isIntegral!U;
|
||
}
|
||
else
|
||
{
|
||
enum isIntegral = __traits(isZeroInit, T) && !is(immutable T == immutable bool) && !is(T == __vector);
|
||
}
|
||
}
|
||
|
||
template isNumeric(T)
|
||
{
|
||
static if (!__traits(isArithmetic, T))
|
||
{
|
||
enum isNumeric = false;
|
||
}
|
||
else static if (__traits(isFloating, T))
|
||
{
|
||
enum isNumeric = is(T : real); // Not __vector, imaginary, or complex.
|
||
}
|
||
else static if (is(T U == enum))
|
||
{
|
||
enum isNumeric = isNumeric!U;
|
||
}
|
||
else
|
||
{
|
||
enum isNumeric = __traits(isZeroInit, T) // Not char, wchar, or dchar.
|
||
&& !is(immutable T == immutable bool) && !is(T == __vector);
|
||
}
|
||
}
|
||
|
||
enum RealFormat
|
||
{
|
||
ieeeHalf,
|
||
ieeeSingle,
|
||
ieeeDouble,
|
||
ieeeExtended, // x87 80-bit real
|
||
ieeeExtended53, // x87 real rounded to precision of double.
|
||
ibmExtended, // IBM 128-bit extended
|
||
ieeeQuadruple,
|
||
}
|
||
|
||
template floatTraits(T)
|
||
{
|
||
// EXPMASK is a ushort mask to select the exponent portion (without sign)
|
||
// EXPSHIFT is the number of bits the exponent is left-shifted by in its ushort
|
||
// EXPBIAS is the exponent bias - 1 (exp == EXPBIAS yields ×2^-1).
|
||
// EXPPOS_SHORT is the index of the exponent when represented as a ushort array.
|
||
// SIGNPOS_BYTE is the index of the sign when represented as a ubyte array.
|
||
// RECIP_EPSILON is the value such that (smallest_subnormal) * RECIP_EPSILON == T.min_normal
|
||
enum Unqual!T RECIP_EPSILON = (1/T.epsilon);
|
||
static if (T.mant_dig == 24)
|
||
{
|
||
// Single precision float
|
||
enum ushort EXPMASK = 0x7F80;
|
||
enum ushort EXPSHIFT = 7;
|
||
enum ushort EXPBIAS = 0x3F00;
|
||
enum uint EXPMASK_INT = 0x7F80_0000;
|
||
enum uint MANTISSAMASK_INT = 0x007F_FFFF;
|
||
enum realFormat = RealFormat.ieeeSingle;
|
||
version (LittleEndian)
|
||
{
|
||
enum EXPPOS_SHORT = 1;
|
||
enum SIGNPOS_BYTE = 3;
|
||
}
|
||
else
|
||
{
|
||
enum EXPPOS_SHORT = 0;
|
||
enum SIGNPOS_BYTE = 0;
|
||
}
|
||
}
|
||
else static if (T.mant_dig == 53)
|
||
{
|
||
static if (T.sizeof == 8)
|
||
{
|
||
// Double precision float, or real == double
|
||
enum ushort EXPMASK = 0x7FF0;
|
||
enum ushort EXPSHIFT = 4;
|
||
enum ushort EXPBIAS = 0x3FE0;
|
||
enum uint EXPMASK_INT = 0x7FF0_0000;
|
||
enum uint MANTISSAMASK_INT = 0x000F_FFFF; // for the MSB only
|
||
enum ulong MANTISSAMASK_LONG = 0x000F_FFFF_FFFF_FFFF;
|
||
enum realFormat = RealFormat.ieeeDouble;
|
||
version (LittleEndian)
|
||
{
|
||
enum EXPPOS_SHORT = 3;
|
||
enum SIGNPOS_BYTE = 7;
|
||
}
|
||
else
|
||
{
|
||
enum EXPPOS_SHORT = 0;
|
||
enum SIGNPOS_BYTE = 0;
|
||
}
|
||
}
|
||
else static if (T.sizeof == 12)
|
||
{
|
||
// Intel extended real80 rounded to double
|
||
enum ushort EXPMASK = 0x7FFF;
|
||
enum ushort EXPSHIFT = 0;
|
||
enum ushort EXPBIAS = 0x3FFE;
|
||
enum realFormat = RealFormat.ieeeExtended53;
|
||
version (LittleEndian)
|
||
{
|
||
enum EXPPOS_SHORT = 4;
|
||
enum SIGNPOS_BYTE = 9;
|
||
}
|
||
else
|
||
{
|
||
enum EXPPOS_SHORT = 0;
|
||
enum SIGNPOS_BYTE = 0;
|
||
}
|
||
}
|
||
else
|
||
static assert(false, "No traits support for " ~ T.stringof);
|
||
}
|
||
else static if (T.mant_dig == 64)
|
||
{
|
||
// Intel extended real80
|
||
enum ushort EXPMASK = 0x7FFF;
|
||
enum ushort EXPSHIFT = 0;
|
||
enum ushort EXPBIAS = 0x3FFE;
|
||
enum realFormat = RealFormat.ieeeExtended;
|
||
version (LittleEndian)
|
||
{
|
||
enum EXPPOS_SHORT = 4;
|
||
enum SIGNPOS_BYTE = 9;
|
||
}
|
||
else
|
||
{
|
||
enum EXPPOS_SHORT = 0;
|
||
enum SIGNPOS_BYTE = 0;
|
||
}
|
||
}
|
||
else static if (T.mant_dig == 113)
|
||
{
|
||
// Quadruple precision float
|
||
enum ushort EXPMASK = 0x7FFF;
|
||
enum ushort EXPSHIFT = 0;
|
||
enum ushort EXPBIAS = 0x3FFE;
|
||
enum realFormat = RealFormat.ieeeQuadruple;
|
||
version (LittleEndian)
|
||
{
|
||
enum EXPPOS_SHORT = 7;
|
||
enum SIGNPOS_BYTE = 15;
|
||
}
|
||
else
|
||
{
|
||
enum EXPPOS_SHORT = 0;
|
||
enum SIGNPOS_BYTE = 0;
|
||
}
|
||
}
|
||
else static if (T.mant_dig == 106)
|
||
{
|
||
// IBM Extended doubledouble
|
||
enum ushort EXPMASK = 0x7FF0;
|
||
enum ushort EXPSHIFT = 4;
|
||
enum realFormat = RealFormat.ibmExtended;
|
||
|
||
// For IBM doubledouble the larger magnitude double comes first.
|
||
// It's really a double[2] and arrays don't index differently
|
||
// between little and big-endian targets.
|
||
enum DOUBLEPAIR_MSB = 0;
|
||
enum DOUBLEPAIR_LSB = 1;
|
||
|
||
// The exponent/sign byte is for most significant part.
|
||
version (LittleEndian)
|
||
{
|
||
enum EXPPOS_SHORT = 3;
|
||
enum SIGNPOS_BYTE = 7;
|
||
}
|
||
else
|
||
{
|
||
enum EXPPOS_SHORT = 0;
|
||
enum SIGNPOS_BYTE = 0;
|
||
}
|
||
}
|
||
else
|
||
static assert(false, "No traits support for " ~ T.stringof);
|
||
}
|
||
|
||
version (StdDdoc)
|
||
{
|
||
template Unqual(T)
|
||
{
|
||
import core.internal.traits : CoreUnqual = Unqual;
|
||
alias Unqual = CoreUnqual!(T);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
import core.internal.traits : CoreUnqual = Unqual;
|
||
alias Unqual = CoreUnqual;
|
||
}
|
||
|
||
// These apply to all floating-point types
|
||
version (LittleEndian)
|
||
{
|
||
enum MANTISSA_LSB = 0;
|
||
enum MANTISSA_MSB = 1;
|
||
}
|
||
else
|
||
{
|
||
enum MANTISSA_LSB = 1;
|
||
enum MANTISSA_MSB = 0;
|
||
}
|
||
|
||
|
||
bool isInfinity(X)(X x) @nogc @trusted pure nothrow
|
||
if (isFloatingPoint!(X))
|
||
{
|
||
alias F = floatTraits!(X);
|
||
static if (F.realFormat == RealFormat.ieeeSingle)
|
||
{
|
||
return ((*cast(uint *)&x) & 0x7FFF_FFFF) == 0x7F80_0000;
|
||
}
|
||
else static if (F.realFormat == RealFormat.ieeeDouble)
|
||
{
|
||
return ((*cast(ulong *)&x) & 0x7FFF_FFFF_FFFF_FFFF)
|
||
== 0x7FF0_0000_0000_0000;
|
||
}
|
||
else static if (F.realFormat == RealFormat.ieeeExtended ||
|
||
F.realFormat == RealFormat.ieeeExtended53)
|
||
{
|
||
const ushort e = cast(ushort)(F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]);
|
||
const ulong ps = *cast(ulong *)&x;
|
||
|
||
// On Motorola 68K, infinity can have hidden bit = 1 or 0. On x86, it is always 1.
|
||
return e == F.EXPMASK && (ps & 0x7FFF_FFFF_FFFF_FFFF) == 0;
|
||
}
|
||
else static if (F.realFormat == RealFormat.ieeeQuadruple)
|
||
{
|
||
const long psLsb = (cast(long *)&x)[MANTISSA_LSB];
|
||
const long psMsb = (cast(long *)&x)[MANTISSA_MSB];
|
||
return (psLsb == 0)
|
||
&& (psMsb & 0x7FFF_FFFF_FFFF_FFFF) == 0x7FFF_0000_0000_0000;
|
||
}
|
||
else
|
||
{
|
||
return (x < -X.max) || (X.max < x);
|
||
}
|
||
}
|
||
|
||
bool isNaN(X)(X x) @nogc @trusted pure nothrow
|
||
if (isFloatingPoint!(X))
|
||
{
|
||
version (all)
|
||
{
|
||
return x != x;
|
||
}
|
||
else
|
||
{
|
||
alias F = floatTraits!(X);
|
||
static if (F.realFormat == RealFormat.ieeeSingle)
|
||
{
|
||
const uint p = *cast(uint *)&x;
|
||
// Sign bit (MSB) is irrelevant so mask it out.
|
||
// Next 8 bits should be all set.
|
||
// At least one bit among the least significant 23 bits should be set.
|
||
return (p & 0x7FFF_FFFF) > 0x7F80_0000;
|
||
}
|
||
else static if (F.realFormat == RealFormat.ieeeDouble)
|
||
{
|
||
const ulong p = *cast(ulong *)&x;
|
||
// Sign bit (MSB) is irrelevant so mask it out.
|
||
// Next 11 bits should be all set.
|
||
// At least one bit among the least significant 52 bits should be set.
|
||
return (p & 0x7FFF_FFFF_FFFF_FFFF) > 0x7FF0_0000_0000_0000;
|
||
}
|
||
else static if (F.realFormat == RealFormat.ieeeExtended ||
|
||
F.realFormat == RealFormat.ieeeExtended53)
|
||
{
|
||
const ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT];
|
||
const ulong ps = *cast(ulong *)&x;
|
||
return e == F.EXPMASK &&
|
||
ps & 0x7FFF_FFFF_FFFF_FFFF; // not infinity
|
||
}
|
||
else static if (F.realFormat == RealFormat.ieeeQuadruple)
|
||
{
|
||
const ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT];
|
||
const ulong psLsb = (cast(ulong *)&x)[MANTISSA_LSB];
|
||
const ulong psMsb = (cast(ulong *)&x)[MANTISSA_MSB];
|
||
return e == F.EXPMASK &&
|
||
(psLsb | (psMsb& 0x0000_FFFF_FFFF_FFFF)) != 0;
|
||
}
|
||
else
|
||
{
|
||
return x != x;
|
||
}
|
||
}
|
||
}
|
||
|
||
enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...);
|
||
|
||
template isInstanceOf(alias S, alias T)
|
||
{
|
||
enum impl(alias T : S!Args, Args...) = true;
|
||
enum impl(alias T) = false;
|
||
enum isInstanceOf = impl!T;
|
||
}
|
||
|
||
enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs);
|
||
enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = rvalueOf!Rhs; });
|
||
enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lvalueOf!Rhs; });
|
||
|
||
template isDynamicArray(T)
|
||
{
|
||
static if (is(T == U[], U))
|
||
enum bool isDynamicArray = true;
|
||
else static if (is(T U == enum))
|
||
// BUG: isDynamicArray / isStaticArray considers enums
|
||
// with appropriate base types as dynamic/static arrays
|
||
// Retain old behaviour for now, see
|
||
// https://github.com/dlang/phobos/pull/7574
|
||
enum bool isDynamicArray = isDynamicArray!U;
|
||
else
|
||
enum bool isDynamicArray = false;
|
||
}
|
||
|
||
enum isStaticArray(T) = __traits(isStaticArray, T);
|
||
|
||
enum isArray(T) = isStaticArray!T || isDynamicArray!T;
|
||
|
||
*/
|