dlib/aliases.d

440 lines
11 KiB
D
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
*/