module dlib.aliases; // import core.memory; //import std.stdint; import dlib.math; enum string NO_IMPL = "Not yet implemented."; 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; */