Merge os, middle and meta subpackages

This commit is contained in:
2025-08-25 16:09:03 +02:00
parent 720d259cfc
commit b8fa670c5a
37 changed files with 193 additions and 1640 deletions

View File

@@ -10,18 +10,12 @@
"targetType": "library",
"dependencies": {
"tanya:meta": "*",
"tanya:os": "*",
"tanya:middle": "*",
"tanya:test": "*",
"mir-linux-kernel": "~>1.0.0"
},
"subPackages": [
"./meta",
"./os",
"./middle",
"./test"
"./middle"
],
"configurations": [

View File

@@ -1,13 +0,0 @@
{
"name": "meta",
"description": "Template metaprogramming",
"targetType": "library",
"sourcePaths": [
"."
],
"importPaths": [
"."
],
"dflags-dmd": ["-dip1000"]
}

View File

@@ -1,22 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Template metaprogramming.
*
* This package contains utilities to acquire type information at compile-time,
* to transform from one type to another. It has also different algorithms for
* iterating, searching and modifying template arguments.
*
* Copyright: Eugene Wissner 2017-2025.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/package.d,
* tanya/meta/package.d)
*/
module tanya.meta;
public import tanya.meta.metafunction;
public import tanya.meta.trait;

View File

@@ -1,150 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Type traits.
*
* Templates in this module are used to obtain type information at compile
* time.
*
* Copyright: Eugene Wissner 2017-2025.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/trait.d,
* tanya/meta/trait.d)
*/
module tanya.meta.trait;
import std.traits : OriginalType, Unqual, isStaticArray, isUnsigned;
import tanya.meta.metafunction;
/**
* Determines whether $(D_PARAM T) is a wide string, i.e. consists of
* $(D_KEYWORD dchar).
*
* The character type of the string and the string itself can have any type
* qualifiers.
*
* Static $(D_KEYWORD dchar) arrays are not considered strings.
*
* Params:
* T = A type.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a wide string,
* $(D_KEYWORD false) otherwise.
*/
enum bool isWideString(T) = is(immutable T == immutable dchar[]);
///
@nogc nothrow pure @safe unittest
{
static assert(isWideString!(dchar[]));
static assert(!isWideString!(char[]));
static assert(!isWideString!(wchar[]));
static assert(isWideString!dstring);
static assert(!isWideString!string);
static assert(!isWideString!wstring);
static assert(isWideString!(const dstring));
static assert(!isWideString!(const string));
static assert(!isWideString!(const wstring));
static assert(isWideString!(shared dstring));
static assert(!isWideString!(shared string));
static assert(!isWideString!(shared wstring));
static assert(isWideString!(const(dchar)[]));
static assert(isWideString!(inout(dchar)[]));
static assert(isWideString!(shared(const(dchar))[]));
static assert(isWideString!(shared(dchar)[]));
static assert(!isWideString!(dchar[10]));
}
/*
* Tests whether $(D_PARAM T) is an interface.
*
* Params:
* T = A type.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is an interface,
* $(D_KEYWORD false) otherwise.
*/
private enum bool isInterface(T) = is(T == interface);
/**
* Determines whether $(D_PARAM T) is a polymorphic type, i.e. a
* $(D_KEYWORD class) or an $(D_KEYWORD interface).
*
* Params:
* T = A type.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a $(D_KEYWORD class) or an
* $(D_KEYWORD interface), $(D_KEYWORD false) otherwise.
*/
enum bool isPolymorphicType(T) = is(T == class) || is(T == interface);
///
@nogc nothrow pure @safe unittest
{
interface I
{
}
static assert(isPolymorphicType!Object);
static assert(isPolymorphicType!I);
static assert(!isPolymorphicType!short);
}
/**
* Returns the size in bytes of the state that needs to be allocated to hold an
* object of type $(D_PARAM T).
*
* There is a difference between the `.sizeof`-property and
* $(D_PSYMBOL stateSize) if $(D_PARAM T) is a class or an interface.
* `T.sizeof` is constant on the given architecture then and is the same as
* `size_t.sizeof` and `ptrdiff_t.sizeof`. This is because classes and
* interfaces are reference types and `.sizeof` returns the size of the
* reference which is the same as the size of a pointer. $(D_PSYMBOL stateSize)
* returns the size of the instance itself.
*
* The size of a dynamic array is `size_t.sizeof * 2` since a dynamic array
* stores its length and a data pointer. The size of the static arrays is
* calculated differently since they are value types. It is the array length
* multiplied by the element size.
*
* `stateSize!void` is `1` since $(D_KEYWORD void) is mostly used as a synonym
* for $(D_KEYWORD byte)/$(D_KEYWORD ubyte) in `void*`.
*
* Params:
* T = Object type.
*
* Returns: Size of an instance of type $(D_PARAM T).
*/
template stateSize(T)
{
static if (isPolymorphicType!T)
{
enum size_t stateSize = __traits(classInstanceSize, T);
}
else
{
enum size_t stateSize = T.sizeof;
}
}
///
@nogc nothrow pure @safe unittest
{
static assert(stateSize!int == 4);
static assert(stateSize!bool == 1);
static assert(stateSize!(int[]) == (size_t.sizeof * 2));
static assert(stateSize!(short[3]) == 6);
static struct Empty
{
}
static assert(stateSize!Empty == 1);
static assert(stateSize!void == 1);
}

View File

@@ -3,11 +3,6 @@
"description": "Runtime, middle-level utilities",
"targetType": "library",
"dependencies": {
"tanya:meta": "*",
"tanya:os": "*"
},
"dependencies-linux": {
"mir-linux-kernel": "~>1.0.0"
},

View File

@@ -17,9 +17,9 @@
*/
module tanya.memory.allocator;
import std.traits : hasElaborateDestructor, isAssociativeArray, isArray;
import std.traits;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
/**
* Abstract class implementing a basic allocator.

View File

@@ -14,11 +14,10 @@
*/
module tanya.memory.lifetime;
import std.traits : isInnerClass, hasElaborateAssign, hasElaborateCopyConstructor, hasElaborateDestructor,
isAssignable, isNested, isAbstractClass, isAggregateType, isStaticArray;
import std.traits;
import std.meta : AliasSeq;
import tanya.memory.allocator;
import tanya.meta.metafunction;
import tanya.meta.trait;
import tanya.meta;
package(tanya) void destroyAllImpl(R, E)(R p)
{

View File

@@ -23,10 +23,10 @@
*/
module tanya.memory.smartref;
import std.traits : isPointer, isAbstractClass, isAssociativeArray, isDynamicArray, isArray;
import std.traits;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
private template Payload(T)
{

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@
*/
module tanya.os.error;
import tanya.meta.trait;
import tanya.meta;
// Socket API error.
private template SAError(int posix, int wsa = posix)

View File

@@ -1,17 +0,0 @@
{
"name": "os",
"description": "Platform-independent interfaces to operating system functionality",
"targetType": "library",
"dependencies": {
"tanya:meta": "*"
},
"sourcePaths": [
"."
],
"importPaths": [
"."
],
"dflags-dmd": ["-dip1000"]
}

View File

@@ -20,10 +20,10 @@
*/
module tanya.algorithm.iteration;
import std.traits : Unqual, isMutable;
import std.traits;
import std.typecons;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
import tanya.range;
private struct SingletonByValue(E)

View File

@@ -14,11 +14,10 @@
*/
module tanya.algorithm.mutation;
import std.traits : Unqual, hasElaborateAssign, hasElaborateCopyConstructor, hasElaborateDestructor, isAssignable,
isDynamicArray;
import std.traits;
static import tanya.memory.lifetime;
static import tanya.memory.op;
import tanya.meta.trait;
import tanya.meta;
import tanya.range;
/**

View File

@@ -18,11 +18,11 @@ import core.checkedint;
import std.algorithm.comparison;
import std.algorithm.iteration;
import std.algorithm.mutation : bringToFront;
import std.traits : PointerTarget, Unqual, hasElaborateDestructor, isImplicitlyConvertible, isCopyable;
import std.traits;
import tanya.algorithm.mutation;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
import tanya.range;
/**

View File

@@ -16,7 +16,7 @@ module tanya.container.buffer;
import std.traits : isScalarType;
import tanya.memory.allocator;
import tanya.meta.trait;
import tanya.meta;
version (unittest)
{

View File

@@ -14,11 +14,11 @@
*/
module tanya.container.entry;
import std.traits : Unqual, hasElaborateDestructor;
import std.traits;
import tanya.container.array;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
package struct SEntry(T)
{

View File

@@ -15,14 +15,14 @@
module tanya.container.hashtable;
import std.algorithm.iteration;
import std.traits : CopyConstness, Unqual, ifTestable, isMutable;
import std.traits;
import tanya.algorithm.mutation;
import tanya.container.array;
import tanya.container.entry;
import tanya.hash.lookup;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
import tanya.range.primitive;
/**

View File

@@ -17,11 +17,11 @@ module tanya.container.list;
import std.algorithm.comparison;
import std.algorithm.iteration;
import std.traits : Unqual, isImplicitlyConvertible, isCopyable;
import std.traits;
import tanya.container.entry;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
import tanya.range.array;
import tanya.range.primitive;

View File

@@ -15,13 +15,13 @@
*/
module tanya.container.set;
import std.traits : CopyConstness, Unqual, ifTestable, isImplicitlyConvertible, isMutable;
import std.traits;
import tanya.container.array;
import tanya.container.entry;
import tanya.hash.lookup;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
import tanya.range.primitive;
/**

View File

@@ -28,12 +28,12 @@ module tanya.container.string;
import std.algorithm.comparison;
import std.algorithm.mutation : bringToFront;
import std.traits : CopyConstness, Unqual, isInstanceOf, isSomeChar, isNarrowString;
import std.traits;
import tanya.algorithm.mutation;
import tanya.hash.lookup;
import tanya.memory.allocator;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
import tanya.range.array;
import tanya.range.primitive;

View File

@@ -14,11 +14,10 @@
*/
module tanya.conv;
import std.traits : Unsigned, isNumeric, Largest, Unqual, EnumMembers, isFloatingPoint, isSomeChar, isSigned,
isUnsigned, isIntegral, isSomeString;
import std.traits;
import tanya.container.string;
import tanya.memory.allocator;
import tanya.meta.trait;
import tanya.meta;
import tanya.range;
/**

View File

@@ -49,12 +49,13 @@ module tanya.format;
import std.algorithm.comparison;
import std.ascii;
import std.traits : Unqual, isPointer, isSomeChar, isFloatingPoint, isSomeFunction, isIntegral, isSomeString;
import std.math : signbit;
import std.meta;
import std.traits;
import tanya.container.string;
import tanya.math;
static import tanya.memory.op;
import tanya.meta.metafunction;
import tanya.meta.trait;
import tanya.meta;
import tanya.range;
// Returns the last part of buffer with converted number.
@@ -1952,7 +1953,7 @@ private const(char)[] real2String(double value,
const FloatBits!double bits = { value };
exponent = (bits.integral >> 52) & 0x7ff;
sign = signBit(value);
sign = !!signbit(value);
if (sign)
{
value = -value;

View File

@@ -14,8 +14,8 @@
*/
module tanya.hash.lookup;
import std.traits : isScalarType, isPointer, isSomeChar, isArray, isIntegral, isBoolean;
import tanya.meta.trait;
import std.traits;
import tanya.meta;
import tanya.range.primitive;
private struct Hasher

View File

@@ -22,8 +22,8 @@
module tanya.math;
import std.math;
import std.traits : Unqual, isFloatingPoint;
import tanya.meta.trait;
import std.traits;
import tanya.meta;
/// Floating-point number precisions according to IEEE-754.
enum IEEEPrecision : ubyte
@@ -113,433 +113,3 @@ package(tanya) union FloatBits(F)
static assert(false, "Unsupported IEEE 754 floating point precision");
}
}
/**
* Floating-point number classifications.
*/
enum FloatingPointClass : ubyte
{
/**
* Not a Number.
*
* See_Also: $(D_PSYMBOL isNaN).
*/
nan,
/// Zero.
zero,
/**
* Infinity.
*
* See_Also: $(D_PSYMBOL isInfinity).
*/
infinite,
/**
* Denormalized number.
*
* See_Also: $(D_PSYMBOL isSubnormal).
*/
subnormal,
/**
* Normalized number.
*
* See_Also: $(D_PSYMBOL isNormal).
*/
normal,
}
/**
* Returns whether $(D_PARAM x) is a NaN, zero, infinity, subnormal or
* normalized number.
*
* This function doesn't distinguish between negative and positive infinity,
* negative and positive NaN or negative and positive zero.
*
* Params:
* F = Type of the floating point number.
* x = Floating point number.
*
* Returns: Classification of $(D_PARAM x).
*/
FloatingPointClass classify(F)(F x)
if (isFloatingPoint!F)
{
if (x == 0)
{
return FloatingPointClass.zero;
}
FloatBits!F bits;
bits.floating = abs(x);
static if (ieeePrecision!F == IEEEPrecision.single)
{
if (bits.integral > bits.expMask)
{
return FloatingPointClass.nan;
}
else if (bits.integral == bits.expMask)
{
return FloatingPointClass.infinite;
}
else if (bits.integral < (1 << 23))
{
return FloatingPointClass.subnormal;
}
}
else static if (ieeePrecision!F == IEEEPrecision.double_)
{
if (bits.integral > bits.expMask)
{
return FloatingPointClass.nan;
}
else if (bits.integral == bits.expMask)
{
return FloatingPointClass.infinite;
}
else if (bits.integral < (1L << 52))
{
return FloatingPointClass.subnormal;
}
}
else static if (ieeePrecision!F == IEEEPrecision.doubleExtended)
{
if (bits.exp == bits.expMask)
{
if ((bits.mantissa & bits.mantissaMask) == 0)
{
return FloatingPointClass.infinite;
}
else
{
return FloatingPointClass.nan;
}
}
else if (bits.exp == 0)
{
return FloatingPointClass.subnormal;
}
else if (bits.mantissa < (1L << 63)) // "Unnormal".
{
return FloatingPointClass.nan;
}
}
return FloatingPointClass.normal;
}
///
@nogc nothrow pure @safe unittest
{
assert(classify(0.0) == FloatingPointClass.zero);
assert(classify(double.nan) == FloatingPointClass.nan);
assert(classify(double.infinity) == FloatingPointClass.infinite);
assert(classify(-double.infinity) == FloatingPointClass.infinite);
assert(classify(1.4) == FloatingPointClass.normal);
assert(classify(1.11254e-307 / 10) == FloatingPointClass.subnormal);
assert(classify(0.0f) == FloatingPointClass.zero);
assert(classify(float.nan) == FloatingPointClass.nan);
assert(classify(float.infinity) == FloatingPointClass.infinite);
assert(classify(-float.infinity) == FloatingPointClass.infinite);
assert(classify(0.3) == FloatingPointClass.normal);
assert(classify(5.87747e-38f / 10) == FloatingPointClass.subnormal);
assert(classify(0.0L) == FloatingPointClass.zero);
assert(classify(real.nan) == FloatingPointClass.nan);
assert(classify(real.infinity) == FloatingPointClass.infinite);
assert(classify(-real.infinity) == FloatingPointClass.infinite);
}
/**
* Determines whether $(D_PARAM x) is a finite number.
*
* Params:
* F = Type of the floating point number.
* x = Floating point number.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM x) is a finite number,
* $(D_KEYWORD false) otherwise.
*
* See_Also: $(D_PSYMBOL isInfinity).
*/
bool isFinite(F)(F x)
if (isFloatingPoint!F)
{
FloatBits!F bits;
static if (ieeePrecision!F == IEEEPrecision.single
|| ieeePrecision!F == IEEEPrecision.double_)
{
bits.floating = x;
bits.integral &= bits.expMask;
return bits.integral != bits.expMask;
}
else static if (ieeePrecision!F == IEEEPrecision.doubleExtended)
{
bits.floating = abs(x);
return (bits.exp != bits.expMask)
&& (bits.exp == 0 || bits.mantissa >= (1L << 63));
}
}
///
@nogc nothrow pure @safe unittest
{
assert(!isFinite(float.infinity));
assert(!isFinite(-double.infinity));
assert(isFinite(0.0));
assert(!isFinite(float.nan));
assert(isFinite(5.87747e-38f / 10));
assert(isFinite(1.11254e-307 / 10));
assert(isFinite(0.5));
}
/**
* Determines whether $(D_PARAM x) is $(B n)ot $(B a) $(B n)umber (NaN).
*
* Params:
* F = Type of the floating point number.
* x = Floating point number.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM x) is not a number,
* $(D_KEYWORD false) otherwise.
*/
bool isNaN(F)(F x)
if (isFloatingPoint!F)
{
FloatBits!F bits;
bits.floating = abs(x);
static if (ieeePrecision!F == IEEEPrecision.single
|| ieeePrecision!F == IEEEPrecision.double_)
{
return bits.integral > bits.expMask;
}
else static if (ieeePrecision!F == IEEEPrecision.doubleExtended)
{
const maskedMantissa = bits.mantissa & bits.mantissaMask;
if ((bits.exp == bits.expMask && maskedMantissa != 0)
|| ((bits.exp != 0) && (bits.mantissa < (1L << 63))))
{
return true;
}
return false;
}
}
///
@nogc nothrow pure @safe unittest
{
assert(isNaN(float.init));
assert(isNaN(double.init));
assert(isNaN(real.init));
}
/**
* Determines whether $(D_PARAM x) is a positive or negative infinity.
*
* Params:
* F = Type of the floating point number.
* x = Floating point number.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM x) is infinity, $(D_KEYWORD false)
* otherwise.
*
* See_Also: $(D_PSYMBOL isFinite).
*/
bool isInfinity(F)(F x)
if (isFloatingPoint!F)
{
FloatBits!F bits;
bits.floating = abs(x);
static if (ieeePrecision!F == IEEEPrecision.single
|| ieeePrecision!F == IEEEPrecision.double_)
{
return bits.integral == bits.expMask;
}
else static if (ieeePrecision!F == IEEEPrecision.doubleExtended)
{
return (bits.exp == bits.expMask)
&& ((bits.mantissa & bits.mantissaMask) == 0);
}
}
///
@nogc nothrow pure @safe unittest
{
assert(isInfinity(float.infinity));
assert(isInfinity(-float.infinity));
assert(isInfinity(double.infinity));
assert(isInfinity(-double.infinity));
assert(isInfinity(real.infinity));
assert(isInfinity(-real.infinity));
}
/**
* Determines whether $(D_PARAM x) is a denormilized number or not.
*
* Denormalized number is a number between `0` and `1` that cannot be
* represented as
*
* <pre>
* m*2<sup>e</sup>
* </pre>
*
* where $(I m) is the mantissa and $(I e) is an exponent that fits into the
* exponent field of the type $(D_PARAM F).
*
* `0` is neither normalized nor denormalized.
*
* Params:
* F = Type of the floating point number.
* x = Floating point number.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM x) is a denormilized number,
* $(D_KEYWORD false) otherwise.
*
* See_Also: $(D_PSYMBOL isNormal).
*/
bool isSubnormal(F)(F x)
if (isFloatingPoint!F)
{
FloatBits!F bits;
bits.floating = abs(x);
static if (ieeePrecision!F == IEEEPrecision.single)
{
return bits.integral < (1 << 23) && bits.integral > 0;
}
else static if (ieeePrecision!F == IEEEPrecision.double_)
{
return bits.integral < (1L << 52) && bits.integral > 0;
}
else static if (ieeePrecision!F == IEEEPrecision.doubleExtended)
{
return bits.exp == 0 && bits.mantissa != 0;
}
}
///
@nogc nothrow pure @safe unittest
{
assert(!isSubnormal(0.0f));
assert(!isSubnormal(float.nan));
assert(!isSubnormal(float.infinity));
assert(!isSubnormal(0.3f));
assert(isSubnormal(5.87747e-38f / 10));
assert(!isSubnormal(0.0));
assert(!isSubnormal(double.nan));
assert(!isSubnormal(double.infinity));
assert(!isSubnormal(1.4));
assert(isSubnormal(1.11254e-307 / 10));
assert(!isSubnormal(0.0L));
assert(!isSubnormal(real.nan));
assert(!isSubnormal(real.infinity));
}
/**
* Determines whether $(D_PARAM x) is a normilized number or not.
*
* Normalized number is a number that can be represented as
*
* <pre>
* m*2<sup>e</sup>
* </pre>
*
* where $(I m) is the mantissa and $(I e) is an exponent that fits into the
* exponent field of the type $(D_PARAM F).
*
* `0` is neither normalized nor denormalized.
*
* Params:
* F = Type of the floating point number.
* x = Floating point number.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM x) is a normilized number,
* $(D_KEYWORD false) otherwise.
*
* See_Also: $(D_PSYMBOL isSubnormal).
*/
bool isNormal(F)(F x)
if (isFloatingPoint!F)
{
static if (ieeePrecision!F == IEEEPrecision.single
|| ieeePrecision!F == IEEEPrecision.double_)
{
FloatBits!F bits;
bits.floating = x;
bits.integral &= bits.expMask;
return bits.integral != 0 && bits.integral != bits.expMask;
}
else static if (ieeePrecision!F == IEEEPrecision.doubleExtended)
{
return classify(x) == FloatingPointClass.normal;
}
}
///
@nogc nothrow pure @safe unittest
{
assert(!isNormal(0.0f));
assert(!isNormal(float.nan));
assert(!isNormal(float.infinity));
assert(isNormal(0.3f));
assert(!isNormal(5.87747e-38f / 10));
assert(!isNormal(0.0));
assert(!isNormal(double.nan));
assert(!isNormal(double.infinity));
assert(isNormal(1.4));
assert(!isNormal(1.11254e-307 / 10));
assert(!isNormal(0.0L));
assert(!isNormal(real.nan));
assert(!isNormal(real.infinity));
}
/**
* Determines whether the sign bit of $(D_PARAM x) is set or not.
*
* If the sign bit, $(D_PARAM x) is a negative number, otherwise positive.
*
* Params:
* F = Type of the floating point number.
* x = Floating point number.
*
* Returns: $(D_KEYWORD true) if the sign bit of $(D_PARAM x) is set,
* $(D_KEYWORD false) otherwise.
*/
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 & (1L << 63)) != 0;
}
else static if (ieeePrecision!F == IEEEPrecision.doubleExtended)
{
return (bits.exp & (1 << 15)) != 0;
}
}
///
@nogc nothrow pure @safe unittest
{
assert(signBit(-1.0f));
assert(!signBit(1.0f));
assert(signBit(-1.0));
assert(!signBit(1.0));
assert(signBit(-1.0L));
assert(!signBit(1.0L));
}

View File

@@ -14,10 +14,10 @@
*/
module tanya.net.iface;
import std.traits : Unqual;
import std.traits;
import tanya.algorithm.mutation;
import tanya.container.string;
import tanya.meta.trait;
import tanya.meta;
import tanya.range;
version (Windows)

View File

@@ -14,8 +14,8 @@
*/
module tanya.net.inet;
import std.traits : Unqual, isUnsigned;
import tanya.meta.trait;
import std.traits;
import tanya.meta;
import tanya.range;
/**

View File

@@ -18,14 +18,14 @@ import std.algorithm.comparison;
import std.ascii;
import std.sumtype;
import std.typecons;
import std.traits : Unqual;
import std.traits;
import tanya.algorithm.iteration;
import tanya.algorithm.mutation;
import tanya.container.string;
import tanya.conv;
import tanya.format;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
import tanya.net.iface;
import tanya.net.inet;
import tanya.range;

View File

@@ -14,10 +14,10 @@
*/
module tanya.range.adapter;
import std.traits : hasMember, isArray;
import std.traits;
import tanya.algorithm.mutation;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
import tanya.range;
private mixin template InserterCtor()

View File

@@ -15,9 +15,9 @@
module tanya.range.primitive;
import std.algorithm.comparison;
import std.traits : FunctionAttribute, ReturnType, hasElaborateCopyConstructor, functionAttributes;
import std.traits;
import tanya.memory.lifetime;
import tanya.meta.trait;
import tanya.meta;
import tanya.range.array;
/**

View File

@@ -22,9 +22,9 @@
*/
module tanya.test.assertion;
import std.traits : isSomeFunction;
import std.traits;
import tanya.memory.allocator;
import tanya.meta.trait;
import tanya.meta;
/**
* Asserts whether the function $(D_PARAM expr) throws an exception of type

View File

@@ -91,7 +91,7 @@ struct WithLvalueElements
mixin template InputRangeStub(E = int)
{
import std.traits : hasUDA, getUDAs;
import tanya.meta.metafunction : Alias;
import std.meta : Alias;
/*
* Aliases for the attribute lookups to access them faster

View File

@@ -1,17 +0,0 @@
{
"name": "test",
"description": "Test suite for unittest-blocks",
"targetType": "library",
"dependencies": {
"tanya:middle": "*"
},
"sourcePaths": [
"."
],
"importPaths": [
"."
],
"dflags-dmd": ["-dip1000"]
}

View File

@@ -4,16 +4,3 @@
module tanya.math.tests;
import tanya.math;
static if (ieeePrecision!float == IEEEPrecision.doubleExtended)
@nogc nothrow pure @safe unittest
{
assert(classify(1.68105e-10) == FloatingPointClass.normal);
assert(classify(1.68105e-4932L) == FloatingPointClass.subnormal);
// Emulate unnormals, because they aren't generated anymore since i386
FloatBits!real unnormal;
unnormal.exp = 0x123;
unnormal.mantissa = 0x1;
assert(classify(unnormal) == FloatingPointClass.subnormal);
}

View File

@@ -3,10 +3,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module tanya.memory.tests.smartref;
import std.traits : ReturnType;
import std.traits;
import tanya.memory.allocator;
import tanya.memory.smartref;
import tanya.meta.trait;
import tanya.meta;
import tanya.test.stub;
@nogc @system unittest

View File

@@ -1,30 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module tanya.meta.tests.metafunction;
import tanya.meta.metafunction;
@nogc nothrow pure @safe unittest
{
enum cmp(int x, int y) = x - y;
static assert(isSorted!(cmp));
static assert(isSorted!(cmp, 1));
static assert(isSorted!(cmp, 1, 2, 2));
static assert(isSorted!(cmp, 1, 2, 2, 4));
static assert(isSorted!(cmp, 1, 2, 2, 4, 8));
static assert(!isSorted!(cmp, 32, 2, 2, 4, 8));
static assert(isSorted!(cmp, 32, 32));
}
@nogc nothrow pure @safe unittest
{
enum cmp(int x, int y) = x < y;
static assert(isSorted!(cmp));
static assert(isSorted!(cmp, 1));
static assert(isSorted!(cmp, 1, 2, 2));
static assert(isSorted!(cmp, 1, 2, 2, 4));
static assert(isSorted!(cmp, 1, 2, 2, 4, 8));
static assert(!isSorted!(cmp, 32, 2, 2, 4, 8));
static assert(isSorted!(cmp, 32, 32));
}