summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2020-05-04 06:03:45 +0200
committerEugen Wissner <belka@caraus.de>2020-05-04 06:03:45 +0200
commitc68b8d1bddd61b06135324cdaed5eb8d7c74ea60 (patch)
tree41d71d93850088c610ed13fb517e9373028e66e9
parent048939410cb8ac3974a7d81d3873763712106a8d (diff)
downloadtanya-c68b8d1bddd61b06135324cdaed5eb8d7c74ea60.tar.gz
Update compiler, remove deprecated modulesv0.17.0
-rw-r--r--.travis.yml4
-rw-r--r--README.md2
-rw-r--r--appveyor.yml4
-rw-r--r--meta/tanya/meta/transform.d442
-rw-r--r--source/tanya/algorithm/comparison.d1
-rw-r--r--source/tanya/conv.d1
-rw-r--r--source/tanya/exception.d16
-rw-r--r--source/tanya/functional.d18
-rw-r--r--source/tanya/math/mp.d1491
-rw-r--r--source/tanya/math/nbtheory.d16
-rw-r--r--source/tanya/math/package.d68
-rw-r--r--tests/tanya/math/tests/mp.d73
-rw-r--r--tests/tanya/math/tests/package.d30
-rw-r--r--tests/tanya/meta/tests/transform.d53
14 files changed, 13 insertions, 2206 deletions
diff --git a/.travis.yml b/.travis.yml
index 8c044f5..2c531eb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,11 +7,11 @@ os:
language: d
d:
-- dmd-2.087.1
+- dmd-2.091.1
env:
global:
- - LATEST=2.087.1
+ - LATEST=2.091.1
matrix:
- ARCH=x86_64
diff --git a/README.md b/README.md
index 64106b6..32e9b19 100644
--- a/README.md
+++ b/README.md
@@ -174,7 +174,7 @@ parameter is used)
| DMD | GCC |
|:-------:|:---------:|
-| 2.087.1 | gdc trunk |
+| 2.091.1 | gdc trunk |
## Further characteristics
diff --git a/appveyor.yml b/appveyor.yml
index a5e7a14..ae78c3e 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -4,10 +4,10 @@ os: Visual Studio 2015
environment:
matrix:
- DC: dmd
- DVersion: 2.087.1
+ DVersion: 2.091.1
arch: x64
- DC: dmd
- DVersion: 2.087.1
+ DVersion: 2.091.1
arch: x86
skip_tags: true
diff --git a/meta/tanya/meta/transform.d b/meta/tanya/meta/transform.d
index 209e4fa..260ee9e 100644
--- a/meta/tanya/meta/transform.d
+++ b/meta/tanya/meta/transform.d
@@ -43,14 +43,14 @@ import tanya.meta.trait;
*/
template Unqual(T)
{
- static if (is(T U == const U)
+ static if (is(T U == shared const U)
+ || is(T U == shared inout U)
+ || is(T U == shared inout const U)
+ || is(T U == inout const U)
+ || is(T U == const U)
|| is(T U == immutable U)
|| is(T U == inout U)
- || is(T U == inout const U)
- || is(T U == shared U)
- || is(T U == shared const U)
- || is(T U == shared inout U)
- || is(T U == shared inout const U))
+ || is(T U == shared U))
{
alias Unqual = U;
}
@@ -138,8 +138,6 @@ template OriginalType(T)
* To = Target type.
*
* Returns: $(D_PARAM To) with the constness of $(D_PARAM From).
- *
- * See_Also: $(D_PSYMBOL CopyTypeQualifiers).
*/
template CopyConstness(From, To)
{
@@ -186,187 +184,6 @@ template CopyConstness(From, To)
}
/**
- * Copies type qualifiers of $(D_PARAM From) to $(D_PARAM To).
- *
- * Type qualifiers copied are:
- * $(UL
- * $(LI const)
- * $(LI immutable)
- * $(LI inout)
- * $(LI shared)
- * )
- * and combinations of these.
- *
- * Params:
- * From = Source type.
- * To = Target type.
- *
- * Returns: $(D_PARAM To) with the type qualifiers of $(D_PARAM From).
- *
- * See_Also: $(D_PSYMBOL CopyConstness).
- */
-template CopyTypeQualifiers(From, To)
-{
- static if (is(From T == immutable T))
- {
- alias CopyTypeQualifiers = immutable To;
- }
- else static if (is(From T == const T))
- {
- alias CopyTypeQualifiers = const To;
- }
- else static if (is(From T == shared T))
- {
- alias CopyTypeQualifiers = shared To;
- }
- else static if (is(From T == shared const T))
- {
- alias CopyTypeQualifiers = shared const To;
- }
- else static if (is(From T == inout T))
- {
- alias CopyTypeQualifiers = inout To;
- }
- else static if (is(From T == shared inout T))
- {
- alias CopyTypeQualifiers = shared inout To;
- }
- else static if (is(From T == inout const T))
- {
- alias CopyTypeQualifiers = inout const To;
- }
- else static if (is(From T == shared inout const T))
- {
- alias CopyTypeQualifiers = shared inout const To;
- }
- else
- {
- alias CopyTypeQualifiers = To;
- }
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- static assert(is(CopyTypeQualifiers!(int, char) == char));
- static assert(is(CopyTypeQualifiers!(const int, char) == const char));
- static assert(is(CopyTypeQualifiers!(immutable int, char) == immutable char));
- static assert(is(CopyTypeQualifiers!(inout int, char) == inout char));
- static assert(is(CopyTypeQualifiers!(inout const int, char) == inout const char));
-
- static assert(is(CopyTypeQualifiers!(shared int, char) == shared char));
- static assert(is(CopyTypeQualifiers!(shared const int, char) == shared const char));
- static assert(is(CopyTypeQualifiers!(shared inout int, char) == shared inout char));
- static assert(is(CopyTypeQualifiers!(shared inout const int, char) == shared inout const char));
-}
-
-/**
- * Evaluates to the unsigned counterpart of the integral type $(D_PARAM T) preserving all type qualifiers.
- * If $(D_PARAM T) is already unsigned, $(D_INLINECODE Unsigned!T) aliases $(D_PARAM T).
- *
- * Params:
- * T = A type.
- *
- * Returns: Unsigned counterpart of $(D_PARAM T).
- *
- * See_Also: $(D_PSYMBOL isSigned).
- */
-template Unsigned(T)
-if (isIntegral!T)
-{
- alias UnqualedType = Unqual!(OriginalType!T);
- static if (is(UnqualedType == byte))
- {
- alias Unsigned = CopyTypeQualifiers!(T, ubyte);
- }
- else static if (is(UnqualedType == short))
- {
- alias Unsigned = CopyTypeQualifiers!(T, ushort);
- }
- else static if (is(UnqualedType == int))
- {
- alias Unsigned = CopyTypeQualifiers!(T, uint);
- }
- else static if (is(UnqualedType == long))
- {
- alias Unsigned = CopyTypeQualifiers!(T, ulong);
- }
- else
- {
- alias Unsigned = T;
- }
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- static assert(is(Unsigned!byte == ubyte));
- static assert(is(Unsigned!short == ushort));
- static assert(is(Unsigned!int == uint));
- static assert(is(Unsigned!long == ulong));
-
- static assert(is(Unsigned!(const byte) == const ubyte));
- static assert(is(Unsigned!(shared byte) == shared ubyte));
- static assert(is(Unsigned!(shared const byte) == shared const ubyte));
-
- static assert(!is(Unsigned!float));
- static assert(is(Unsigned!ubyte == ubyte));
-}
-
-/**
- * Evaluates to the signed counterpart of the integral type $(D_PARAM T) preserving all type qualifiers.
- * If $(D_PARAM T) is already signed, $(D_INLINECODE Signed!T) aliases $(D_PARAM T).
- *
- * Params:
- * T = A type.
- *
- * Returns: Signed counterpart of $(D_PARAM T).
- *
- * See_Also: $(D_PSYMBOL isUnsigned).
- */
-template Signed(T)
-if (isIntegral!T)
-{
- alias UnqualedType = Unqual!(OriginalType!T);
- static if (is(UnqualedType == ubyte))
- {
- alias Signed = CopyTypeQualifiers!(T, byte);
- }
- else static if (is(UnqualedType == ushort))
- {
- alias Signed = CopyTypeQualifiers!(T, short);
- }
- else static if (is(UnqualedType == uint))
- {
- alias Signed = CopyTypeQualifiers!(T, int);
- }
- else static if (is(UnqualedType == ulong))
- {
- alias Signed = CopyTypeQualifiers!(T, long);
- }
- else
- {
- alias Signed = T;
- }
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- static assert(is(Signed!ubyte == byte));
- static assert(is(Signed!ushort == short));
- static assert(is(Signed!uint == int));
- static assert(is(Signed!ulong == long));
-
- static assert(is(Signed!(const ubyte) == const byte));
- static assert(is(Signed!(shared ubyte) == shared byte));
- static assert(is(Signed!(shared const ubyte) == shared const byte));
-
- static assert(!is(Signed!float));
- static assert(is(Signed!byte == byte));
-}
-
-/**
* Retrieves the target type `U` of a pointer `U*`.
*
* Params:
@@ -446,37 +263,6 @@ template ValueType(T)
}
/**
- * Params:
- * T = Scalar type.
- *
- * Returns: The type $(D_PARAM T) will promote to.
- *
- * See_Also: $(LINK2 https://dlang.org/spec/type.html#integer-promotions,
- * Integer Promotions).
- */
-template Promoted(T)
-if (isScalarType!T)
-{
- alias Promoted = CopyTypeQualifiers!(T, typeof(T.init + T.init));
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- static assert(is(Promoted!bool == int));
- static assert(is(Promoted!byte == int));
- static assert(is(Promoted!ubyte == int));
- static assert(is(Promoted!short == int));
- static assert(is(Promoted!ushort == int));
- static assert(is(Promoted!char == int));
- static assert(is(Promoted!wchar == int));
- static assert(is(Promoted!dchar == uint));
-
- static assert(is(Promoted!(const bool) == const int));
- static assert(is(Promoted!(shared bool) == shared int));
-}
-
-/**
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
*
* Params:
@@ -605,86 +391,6 @@ alias SharedInoutConstOf(T) = shared(inout const T);
}
/**
- * Returns a template with one argument which applies all qualifiers of
- * $(D_PARAM T) on its argument if instantiated.
- *
- * Params:
- * T = A type.
- *
- * Returns: $(D_INLINECODE shared(inout const T)).
- */
-template QualifierOf(T)
-{
- static if (is(T U == const U))
- {
- alias QualifierOf = ConstOf;
- }
- else static if (is(T U == immutable U))
- {
- alias QualifierOf = ImmutableOf;
- }
- else static if (is(T U == inout U))
- {
- alias QualifierOf = InoutOf;
- }
- else static if (is(T U == inout const U))
- {
- alias QualifierOf = InoutConstOf;
- }
- else static if (is(T U == shared U))
- {
- alias QualifierOf = SharedOf;
- }
- else static if (is(T U == shared const U))
- {
- alias QualifierOf = SharedConstOf;
- }
- else static if (is(T U == shared inout U))
- {
- alias QualifierOf = SharedInoutOf;
- }
- else static if (is(T U == shared inout const U))
- {
- alias QualifierOf = SharedInoutConstOf;
- }
- else
- {
- alias QualifierOf(T) = T;
- }
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- alias MutableOf = QualifierOf!int;
- static assert(is(MutableOf!uint == uint));
-
- alias ConstOf = QualifierOf!(const int);
- static assert(is(ConstOf!uint == const uint));
-
- alias InoutOf = QualifierOf!(inout int);
- static assert(is(InoutOf!uint == inout uint));
-
- alias InoutConstOf = QualifierOf!(inout const int);
- static assert(is(InoutConstOf!uint == inout const uint));
-
- alias ImmutableOf = QualifierOf!(immutable int);
- static assert(is(ImmutableOf!uint == immutable uint));
-
- alias SharedOf = QualifierOf!(shared int);
- static assert(is(SharedOf!uint == shared uint));
-
- alias SharedConstOf = QualifierOf!(shared const int);
- static assert(is(SharedConstOf!uint == shared const uint));
-
- alias SharedInoutOf = QualifierOf!(shared inout int);
- static assert(is(SharedInoutOf!uint == shared inout uint));
-
- alias SharedInoutConstOf = QualifierOf!(shared inout const int);
- static assert(is(SharedInoutConstOf!uint == shared inout const uint));
-}
-
-/**
* Determines the type of $(D_PARAM T). If $(D_PARAM T) is already a type,
* $(D_PSYMBOL TypeOf) aliases itself to $(D_PARAM T).
*
@@ -719,142 +425,6 @@ if (isExpressions!T || __traits(isTemplate, T))
static assert(!is(TypeOf!(tanya.meta)));
}
-// e.g. returns int for int**.
-private template FinalPointerTarget(T)
-{
- static if (isPointer!T)
- {
- alias FinalPointerTarget = FinalPointerTarget!(PointerTarget!T);
- }
- else
- {
- alias FinalPointerTarget = T;
- }
-}
-
-// Returns true if T1 is void* and T2 is some pointer.
-private template voidAndPointer(T1, T2)
-{
- enum bool voidAndPointer = is(Unqual!(PointerTarget!T1) == void)
- && isPointer!T2;
-}
-
-// Type returned by the ternary operator.
-private alias TernaryType(T, U) = typeof(true ? T.init : U.init);
-
-/**
- * Determines the type all $(D_PARAM Args) can be implicitly converted to.
- *
- * $(OL
- * $(LI If one of the arguments is $(D_KEYWORD void), the common type is
- * $(D_KEYWORD void).)
- * $(LI The common type of integers with the same sign is the type with a
- * larger size. Signed and unsigned integers don't have a common type.
- * Type qualifiers are only preserved if all arguments are the same
- * type.)
- * $(LI The common type of floating point numbers is the type with more
- * precision. Type qualifiers are only preserved if all arguments are
- * the same type.)
- * $(LI The common type of polymorphic objects is the next, more generic type
- * both objects inherit from, e.g. $(D_PSYMBOL Object).)
- * $(LI `void*` is concerned as a common type of pointers only if one of the
- * arguments is a void pointer.)
- * $(LI Other types have a common type only if their pointers have a common
- * type. It means that for example $(D_KEYWORD bool) and $(D_KEYWORD int)
- don't have a common type. If the types fullfill this condition, the
- common type is determined with the ternary operator, i.e.
- `typeof(true ? T1.init : T2.init)` is evaluated.)
- * )
- *
- * If $(D_PARAM Args) don't have a common type, $(D_PSYMBOL CommonType) is
- * $(D_KEYWORD void).
- *
- * Params:
- * Args = Type list.
- *
- * Returns: Common type for $(D_PARAM Args) or $(D_KEYWORD void) if
- * $(D_PARAM Args) don't have a common type.
- */
-template CommonType(Args...)
-if (allSatisfy!(isType, Args))
-{
- static if (Args.length == 0
- || is(Unqual!(Args[0]) == void)
- || is(Unqual!(Args[1]) == void))
- {
- alias CommonType = void;
- }
- else static if (Args.length == 1)
- {
- alias CommonType = Args[0];
- }
- else
- {
- private alias Pair = Args[0 .. 2];
- private enum bool sameSigned = allSatisfy!(isIntegral, Pair)
- && isSigned!(Args[0]) == isSigned!(Args[1]);
-
- static if (is(Args[0] == Args[1]))
- {
- alias CommonType = CommonType!(Args[0], Args[2 .. $]);
- }
- else static if (sameSigned || allSatisfy!(isFloatingPoint, Pair))
- {
- alias CommonType = CommonType!(Unqual!(Largest!Pair),
- Args[2 .. $]);
- }
- else static if (voidAndPointer!Pair
- || voidAndPointer!(Args[1], Args[0]))
- {
- // Workaround for https://issues.dlang.org/show_bug.cgi?id=15557.
- // Determine the qualifiers returned by the ternary operator as if
- // both pointers were int*. Then copy the qualifiers to void*.
- alias P1 = CopyTypeQualifiers!(FinalPointerTarget!(Args[0]), int)*;
- alias P2 = CopyTypeQualifiers!(FinalPointerTarget!(Args[1]), int)*;
- static if (is(TernaryType!(P1, P2) U))
- {
- alias CommonType = CopyTypeQualifiers!(PointerTarget!U, void)*;
- }
- else
- {
- alias CommonType = void;
- }
- }
- else static if ((isPointer!(Args[0]) || isPolymorphicType!(Args[0]))
- && is(TernaryType!Pair U))
- {
- alias CommonType = CommonType!(U, Args[2 .. $]);
- }
- else static if (is(TernaryType!(Args[0]*, Args[1]*)))
- {
- alias CommonType = CommonType!(TernaryType!Pair, Args[2 .. $]);
- }
- else
- {
- alias CommonType = void;
- }
- }
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- static assert(is(CommonType!(int, int, int) == int));
- static assert(is(CommonType!(ubyte, ushort, uint) == uint));
- static assert(is(CommonType!(int, uint) == void));
-
- static assert(is(CommonType!(int, const int) == int));
- static assert(is(CommonType!(const int, const int) == const int));
-
- static assert(is(CommonType!(int[], const(int)[]) == const(int)[]));
- static assert(is(CommonType!(string, char[]) == const(char)[]));
-
- class A
- {
- }
- static assert(is(CommonType!(const A, Object) == const Object));
-}
-
/**
* Finds the type with the smallest size in the $(D_PARAM Args) list. If
* several types have the same type, the leftmost is returned.
diff --git a/source/tanya/algorithm/comparison.d b/source/tanya/algorithm/comparison.d
index 2faeaab..aa4c34d 100644
--- a/source/tanya/algorithm/comparison.d
+++ b/source/tanya/algorithm/comparison.d
@@ -14,6 +14,7 @@
*/
module tanya.algorithm.comparison;
+import std.traits : CommonType;
import tanya.algorithm.mutation;
import tanya.math;
static import tanya.memory.op;
diff --git a/source/tanya/conv.d b/source/tanya/conv.d
index 2efeda2..a49d4db 100644
--- a/source/tanya/conv.d
+++ b/source/tanya/conv.d
@@ -14,6 +14,7 @@
*/
module tanya.conv;
+import std.traits : Unsigned;
import tanya.container.string;
import tanya.memory.allocator;
deprecated("Use tanya.memory.lifetime.emplace instead")
diff --git a/source/tanya/exception.d b/source/tanya/exception.d
deleted file mode 100644
index e8b94af..0000000
--- a/source/tanya/exception.d
+++ /dev/null
@@ -1,16 +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/. */
-
-/*
- * Copyright: Eugene Wissner 2017-2019.
- * 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/source/tanya/exception.d,
- * tanya/exception.d)
- */
-deprecated("Use tanya.memory.allocator instead")
-module tanya.exception;
-
-public import tanya.memory.allocator : onOutOfMemoryError, OutOfMemoryError;
diff --git a/source/tanya/functional.d b/source/tanya/functional.d
deleted file mode 100644
index cde1b51..0000000
--- a/source/tanya/functional.d
+++ /dev/null
@@ -1,18 +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/. */
-
-/*
- * Functions that manipulate other functions and their argument lists.
- *
- * Copyright: Eugene Wissner 2018-2019.
- * 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/source/tanya/functional.d,
- * tanya/functional.d)
- */
-deprecated("Use tanya.memory.lifetime instead")
-module tanya.functional;
-
-public import tanya.memory.lifetime : forward;
diff --git a/source/tanya/math/mp.d b/source/tanya/math/mp.d
deleted file mode 100644
index 8a4d933..0000000
--- a/source/tanya/math/mp.d
+++ /dev/null
@@ -1,1491 +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/. */
-
-/**
- * Arbitrary precision arithmetic.
- *
- * Copyright: Eugene Wissner 2016-2019.
- * 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/source/tanya/math/mp.d,
- * tanya/math/mp.d)
- */
-deprecated
-module tanya.math.mp;
-
-import tanya.algorithm.comparison;
-import tanya.algorithm.iteration;
-import tanya.algorithm.mutation;
-import tanya.container.array;
-import tanya.encoding.ascii;
-import tanya.memory.allocator;
-import tanya.memory.lifetime;
-import tanya.meta.trait;
-import tanya.meta.transform;
-import tanya.range;
-
-/**
- * Algebraic sign.
- */
-enum Sign : bool
-{
- /// The value is positive or `0`.
- positive = false,
-
- /// The value is negative.
- negative = true,
-}
-
-/**
- * Mutliple precision integer.
- */
-struct Integer
-{
- package digit[] rep;
- package ptrdiff_t size;
- package Sign sign;
-
- pure nothrow @safe @nogc invariant
- {
- assert(this.size > 0 || !this.sign, "0 should be positive.");
- }
-
- private alias digit = uint;
- private alias word = ulong;
-
- // Count of bits per digit.
- private enum : digit
- {
- digitBitCount = 28,
- mask = 0xfffffff,
- }
-
- /**
- * Creates a multiple precision integer.
- *
- * Params:
- * T = Value type.
- * value = Initial value.
- * allocator = Allocator.
- *
- * Precondition: $(D_INLINECODE allocator !is null)
- */
- this(T)(const T value, shared Allocator allocator = defaultAllocator)
- if (isIntegral!T)
- {
- this(allocator);
- this = value;
- }
-
- /// ditto
- this(T)(ref T value, shared Allocator allocator = defaultAllocator)
- if (is(Unqual!T == Integer))
- {
- this(allocator);
- this = value;
- }
-
- /// ditto
- this(T)(T value, shared Allocator allocator = defaultAllocator)
- if (is(T == Integer))
- {
- this(allocator);
- if (allocator is value.allocator)
- {
- this.rep = value.rep;
- this.size = value.size;
- this.sign = value.sign;
- value.rep = null;
- value.size = 0;
- value.sign = Sign.positive;
- }
- else
- {
- this = value;
- }
- }
-
- /// ditto
- this(shared Allocator allocator) @nogc nothrow pure @safe
- in (allocator !is null)
- {
- this.allocator_ = allocator;
- }
-
- /**
- * Constructs the integer from a sign-magnitude $(D_KEYWORD ubyte) range.
- *
- * Params:
- * R = Range type.
- * sign = Sign.
- * value = Range.
- * allocator = Allocator.
- *
- * Precondition: $(D_INLINECODE allocator !is null)
- */
- this(R)(const Sign sign,
- R value,
- shared Allocator allocator = defaultAllocator)
- if (isBidirectionalRange!R && hasLength!R
- && is(Unqual!(ElementType!R) == ubyte))
- {
- this(allocator);
- grow(value.length / (digitBitCount / 8) + 1);
-
- int bit, delta;
-
- for (; !value.empty; ++this.size)
- {
- word w;
- for (bit = delta; (bit < digitBitCount) && !value.empty; bit += 8)
- {
- w |= (cast(word) value.back) << bit;
- value.popBack();
- }
-
- delta = bit - digitBitCount;
- this.rep[this.size] |= w & mask;
-
- if (delta > 0)
- {
- this.rep[this.size + 1] = (w >> digitBitCount) & mask;
- }
- }
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- ubyte[8] range = [ 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xdd, 0xee ];
- auto integer = Integer(Sign.positive, range[]);
- assert(integer == 7383520307673030126);
- }
-
- /**
- * Constructs the integer from a two's complement representation.
- *
- * Params:
- * R = Range type.
- * value = Range.
- * allocator = Allocator.
- *
- * Precondition: $(D_INLINECODE allocator !is null)
- */
- this(R)(R value, shared Allocator allocator = defaultAllocator)
- if (isBidirectionalRange!R && hasLength!R
- && is(Unqual!(ElementType!R) == ubyte))
- {
- this(Sign.positive, value, allocator);
-
- if (!value.empty && ((value.front & 0x80) != 0))
- {
- // Negative number.
- opOpAssign!"-"(exp2(countBits()));
- }
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- {
- ubyte[8] range = [ 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xdd, 0xee ];
- auto integer = Integer(range[]);
- assert(integer == 7383520307673030126);
- }
- {
- ubyte[8] range = [ 0xe6, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xdd, 0xee ];
- auto integer = Integer(range[]);
- assert(integer == -1839851729181745682);
- }
- }
-
- /**
- * Copies the integer.
- */
- this(this) @nogc nothrow pure @safe
- {
- auto tmp = allocator.resize!digit(null, this.size);
- copy(this.rep[0 .. this.size], tmp);
- this.rep = tmp;
- }
-
- /**
- * Destroys the integer.
- */
- ~this() @nogc nothrow pure @safe
- {
- allocator.resize(this.rep, 0);
- }
-
- static private const short[16] bitCounts = [
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
- ];
-
- // Counts the number of LSBs before the first non-zero bit.
- private ptrdiff_t countLSBs() const @nogc nothrow pure @safe
- {
- if (this.size == 0)
- {
- return 0;
- }
-
- ptrdiff_t bits;
- for (bits = 0; (bits < this.size) && (this.rep[bits] == 0); ++bits)
- {
- }
- digit nonZero = this.rep[bits];
- bits *= digitBitCount;
-
- /* now scan this digit until a 1 is found */
- if ((nonZero & 0x01) == 0)
- {
- digit bitCountsPos;
- do
- {
- bitCountsPos = nonZero & 0x0f;
- bits += bitCounts[bitCountsPos];
- nonZero >>= 4;
- }
- while (bitCountsPos == 0);
- }
- return bits;
- }
-
- /**
- * Returns: Number of bytes in the two's complement representation.
- */
- @property size_t length() const @nogc nothrow pure @safe
- {
- if (this.sign)
- {
- const bc = countBits();
- auto length = bc + (8 - (bc & 0x07));
-
- if (((countLSBs() + 1) == bc) && ((bc & 0x07) == 0))
- {
- --length;
- }
- return length / 8;
- }
- else if (this.size == 0)
- {
- return 0;
- }
- else
- {
- return (countBits() / 8) + 1;
- }
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- {
- Integer i;
- assert(i.length == 0);
- }
- {
- auto i = Integer(-123456789);
- assert(i.length == 4);
- }
- }
-
- /**
- * Assigns a new value.
- *
- * Params:
- * T = Value type.
- * value = Value.
- *
- * Returns: $(D_KEYWORD this).
- */
- ref Integer opAssign(T)(const T value)
- if (isIntegral!T)
- {
- rep[0 .. this.size].fill(digit.init);
- grow(digitBitCount / 8 + 1);
-
- static if (isSigned!T)
- {
- ulong absolute;
- if (value >= 0)
- {
- absolute = value;
- this.sign = Sign.positive;
- }
- else
- {
- absolute = -value;
- this.sign = Sign.negative;
- }
- }
- else
- {
- ulong absolute = value;
- this.sign = Sign.positive;
- }
-
- for (this.size = 0; absolute; absolute >>= digitBitCount, ++this.size)
- {
- this.rep[this.size] = absolute & mask;
- }
-
- return this;
- }
-
- /// ditto
- ref Integer opAssign(T)(ref T value)
- if (is(Unqual!T == Integer))
- {
- this.rep = allocator.resize(this.rep, value.size);
- copy(value.rep[0 .. value.size], this.rep[0 .. value.size]);
- this.size = value.size;
- this.sign = value.sign;
-
- return this;
- }
-
- /// ditto
- ref Integer opAssign(T)(T value)
- if (is(T == Integer))
- {
- swap(this.rep, value.rep);
- swap(this.sign, value.sign);
- swap(this.size, value.size);
- swap(this.allocator_, value.allocator_);
- return this;
- }
-
- /**
- * Casting.
- *
- * Params:
- * T = Target type.
- *
- * Returns: Converted value.
- */
- T opCast(T : bool)() const
- {
- return this.size > 0;
- }
-
- /// ditto
- T opCast(T)() const
- if (isIntegral!T && isUnsigned!T)
- {
- T ret;
- ubyte shift;
- for (size_t i; i < this.size && shift <= T.sizeof * 8; ++i)
- {
- ret |= (cast(T) this.rep[i]) << shift;
- shift += digitBitCount;
- }
- return ret;
- }
-
- /// ditto
- T opCast(T)() const
- if (isIntegral!T && isSigned!T)
- {
- return this.sign
- ? cast(T) -(cast(Promoted!(Unsigned!T)) (cast(Unsigned!T) this))
- : cast(Unsigned!T) this;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- auto integer = Integer(79);
- assert(cast(ushort) integer == 79);
-
- integer = -79;
- assert(cast(short) integer == -79);
-
- integer = 4294967295;
- assert(cast(long) integer == 4294967295);
-
- integer = -4294967295;
- assert(cast(long) integer == -4294967295);
-
- integer = long.min;
- assert(cast(long) integer == long.min);
-
- integer = long.min + 1;
- assert(cast(long) integer == long.min + 1);
-
- integer = 0;
- assert(cast(long) integer == 0);
- }
-
- /* Trim unused digits.
- *
- * This is used to ensure that leading zero digits are
- * trimed and the leading "size" digit will be non-zero
- * Typically very fast. Also fixes the sign if there
- * are no more leading digits
- */
- void contract() @nogc nothrow pure @safe
- {
- /* decrease size while the most significant digit is
- * zero.
- */
- while ((this.size > 0) && (this.rep[this.size - 1] == 0))
- {
- --this.size;
- }
-
- /* reset the sign flag if size == 0 */
- if (this.size == 0)
- {
- this.sign = Sign.positive;
- }
- }
-
- private void grow(const size_t size) @nogc nothrow pure @safe
- {
- if (this.rep.length >= size)
- {
- return;
- }
- const oldLength = this.rep.length;
- allocator.resize(this.rep, size);
- this.rep[oldLength .. $].fill(digit.init);
- }
-
- private size_t countBits() const @nogc nothrow pure @safe
- {
- if (this.size == 0)
- {
- return 0;
- }
- auto r = (this.size - 1) * digitBitCount;
- digit q = this.rep[this.size - 1];
-
- while (q > 0)
- {
- ++r;
- q >>= (cast(digit) 1);
- }
- return r;
- }
-
- private void add(ref const Integer summand, ref Integer sum)
- const @nogc nothrow pure @safe
- {
- const(digit)[] max, min;
-
- if (this.size > summand.size)
- {
- min = summand.rep[0 .. summand.size];
- max = this.rep[0 .. this.size];
- }
- else
- {
- min = this.rep[0 .. this.size];
- max = summand.rep[0 .. summand.size];
- }
- sum.grow(max.length + 1);
-
- const oldSize = sum.size;
- sum.size = cast(int) (max.length + 1);
-
- auto result = sum.rep;
- digit carry;
- foreach (i, ref const d; min)
- {
- result.front = d + max.front + carry;
- carry = result.front >> digitBitCount;
- result.front &= mask;
-
- max.popFront();
- result.popFront();
- }
-
- // Copy higher digests if one of the summands is greater than another
- // one.
- for (; !max.empty; max.popFront(), result.popFront())
- {
- result.front = max.front + carry;
- carry = result.front >> digitBitCount;
- result.front &= mask;
- }
- result.front = carry;
-
- // Clear digits above the old size.
- for (auto i = sum.size; i < oldSize; ++i)
- {
- sum.rep[i] = 0;
- }
-
- sum.contract();
- }
-
- private void add(const digit summand, ref Integer sum)
- const @nogc nothrow pure @safe
- {
- sum.grow(this.size + 2);
-
- sum.rep[0] = this.rep[0] + summand;
- auto carry = sum.rep[0] >> digitBitCount;
- sum.rep[0] &= mask;
-
- size_t i;
- for (i = 1; i < this.size; ++i)
- {
- sum.rep[i] = this.rep[i] + carry;
- carry = sum.rep[i] >> digitBitCount;
- sum.rep[i] &= mask;
- }
- sum.rep[i++] = carry;
-
- for (; i < sum.size; ++i)
- {
- sum.rep[i] = 0;
- }
- sum.size = this.size + 1;
- sum.contract();
- }
-
- private void subtract(ref const Integer subtrahend, ref Integer difference)
- const @nogc nothrow pure @safe
- {
- difference.grow(this.size);
-
- const oldSize = difference.size;
- difference.size = this.size;
-
- size_t i;
- digit carry;
-
- for (i = 0; i < subtrahend.size; ++i)
- {
- difference.rep[i] = (this.rep[i] - subtrahend.rep[i]) - carry;
- carry = difference.rep[i] >> (cast(digit) (8 * digit.sizeof) - 1);
- difference.rep[i] &= mask;
- }
-
- // Copy higher digests if the minuend has more digits than the
- // subtrahend.
- for (; i < this.size; ++i)
- {
- difference.rep[i] = this.rep[i] - carry;
- carry = difference.rep[i] >> (cast(digit) ((8 * digit.sizeof) - 1));
- difference.rep[i] &= mask;
- }
-
- // Clear digits above the size.
- for (i = difference.size; i < oldSize; ++i)
- {
- difference.rep[i] = 0;
- }
-
- difference.contract();
- }
-
- private void subtract(const digit subtrahend, ref Integer difference)
- const @nogc nothrow pure @safe
- {
- difference.grow(this.size);
-
- const oldSize = difference.size;
-
- difference.sign = this.sign;
- difference.size = this.size;
-
- difference.rep[0] = this.rep[0] - subtrahend;
- auto carry = difference.rep[0] >> ((digit.sizeof * 8) - 1);
- difference.rep[0] &= mask;
-
- size_t i;
- for (i = 1; i < this.size; ++i)
- {
- difference.rep[i] = this.rep[i] - carry;
- carry = difference.rep[i] >> ((digit.sizeof * 8) - 1);
- difference.rep[i] &= mask;
- }
-
- for (; i < oldSize; ++i)
- {
- difference.rep[i] = 0;
- }
- difference.contract();
- }
-
- // Compare the magnitude.
- private int compare(ref const Integer that) const @nogc nothrow pure @safe
- {
- if (this.size > that.size)
- {
- return 1;
- }
- else if (this.size < that.size)
- {
- return -1;
- }
- return this.rep[0 .. this.size]
- .retro
- .compare(that.rep[0 .. that.size].retro);
- }
-
- /**
- * Comparison.
- *
- * Params:
- * I = Comparand type.
- * that = The second integer.
- *
- * Returns: A positive number if $(D_INLINECODE this > that), a negative
- * number if $(D_INLINECODE this < that), `0` otherwise.
- */
- int opCmp(I : Integer)(auto ref const I that) const
- {
- if (this.sign != that.sign)
- {
- if (this.sign == Sign.negative)
- {
- return -1;
- }
- else
- {
- return 1;
- }
- }
- if (this.sign == Sign.negative)
- {
- return that.compare(this);
- }
- else
- {
- return compare(that);
- }
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- auto integer1 = Integer(1019);
- auto integer2 = Integer(1019);
- assert(integer1 == integer2);
-
- integer2 = 3337;
- assert(integer1 < integer2);
-
- integer2 = 688;
- assert(integer1 > integer2);
-
- integer2 = -3337;
- assert(integer1 > integer2);
- }
-
- /// ditto
- int opCmp(I)(const I that) const
- if (isIntegral!I)
- {
- if (that < 0 && !this.sign)
- {
- return 1;
- }
- else if (that > 0 && this.sign)
- {
- return -1;
- }
- else if (this.size > I.sizeof)
- {
- return this.sign ? -1 : 1;
- }
-
- const diff = (cast(I) this) - that;
- if (diff > 0)
- {
- return 1;
- }
- else if (diff < 0)
- {
- return -1;
- }
- return 0;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- auto integer = Integer(1019);
-
- assert(integer == 1019);
- assert(integer < 3337);
- assert(integer > 688);
- assert(integer > -3337);
- }
-
- /**
- * Params:
- * I = Comparand type.
- * that = The second integer.
- *
- * Returns: Whether the two integers are equal.
- */
- bool opEquals(I)(auto ref const I that) const
- if (is(I : Integer) || isIntegral!I)
- {
- return opCmp!I(that) == 0;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- auto integer = Integer(1019);
-
- assert(integer == Integer(1019));
- assert(integer != Integer(109));
- }
-
- /**
- * Assignment operators with another $(D_PSYMBOL Integer).
- *
- * Params:
- * op = Operation.
- * operand = The second operand.
- *
- * Returns: $(D_KEYWORD this).
- */
- ref Integer opOpAssign(string op : "+")(auto ref const Integer operand)
- {
- if (this.sign == operand.sign)
- {
- add(operand, this);
- }
- else if (compare(operand) < 0)
- {
- this.sign = operand.sign;
- operand.subtract(this, this);
- }
- else
- {
- subtract(operand, this);
- }
- return this;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- {
- auto h1 = Integer(1019);
- auto h2 = Integer(3337);
- h1 += h2;
- assert(h1 == 4356);
- }
- {
- auto h1 = Integer(4356);
- auto h2 = Integer(2_147_483_647);
- h1 += h2;
- assert(h1 == 2147488003);
- }
- {
- auto h1 = Integer(2147488003L);
- auto h2 = Integer(2_147_483_647);
- h1 += h2;
- assert(h1 == 4294971650);
- }
- }
-
- /// ditto
- ref Integer opOpAssign(string op : "-")(auto ref const Integer operand)
- {
- if (this.sign != operand.sign)
- {
- add(operand, this);
- }
- else if (compare(operand) >= 0)
- {
- subtract(operand, this);
- }
- else
- {
- operand.subtract(this, this);
- this.sign = this.sign ? Sign.positive : Sign.negative;
- }
- return this;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- {
- auto h1 = Integer(3);
- auto h2 = Integer(4);
- h1 -= h2;
- assert(h1 == -1);
- }
- {
- auto h1 = Integer(8589934590L);
- auto h2 = Integer(2147483647);
- h1 -= h2;
- assert(h1 == 6442450943);
- }
- {
- auto h1 = Integer(6442450943);
- auto h2 = Integer(4294967294);
- h1 -= h2;
- assert(h1 == 2147483649);
- }
- {
- auto h1 = Integer(2147483649);
- auto h2 = Integer(h1);
- h1 -= h2;
- assert(h1 == 0);
- }
- }
-
- /// ditto
- ref Integer opOpAssign(string op : "*")(auto ref const Integer operand)
- {
- const digits = this.size + operand.size + 1;
-
- multiply(operand, this, digits);
-
- if (this.size > 0)
- {
- this.sign = this.sign == operand.sign ? Sign.positive : Sign.negative;
- }
-
- return this;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- auto h1 = Integer(123);
- auto h2 = Integer(456);
- h1 *= h2;
- assert(h1 == 56088);
- }
-
- /// ditto
- ref Integer opOpAssign(string op : "/")(auto ref const Integer operand)
- in (operand.length > 0, "Division by zero.")
- {
- divide(operand, this);
- return this;
- }
-
- /// ditto
- ref Integer opOpAssign(string op : "%")(auto ref const Integer operand)
- in (operand.length > 0, "Division by zero")
- {
- divide(operand, null, this);
- return this;
- }
-
- /// ditto
- ref Integer opOpAssign(string op : ">>")(const size_t operand)
- {
- if (operand == 0)
- {
- return this;
- }
- if (operand >= digitBitCount)
- {
- shiftRight(operand / digitBitCount);
- }
-
- const bit = cast(digit) (operand % digitBitCount);
- if (bit != 0)
- {
- const mask = ((cast(digit) 1) << bit) - 1;
- const shift = digitBitCount - bit;
- digit carry;
-
- foreach_reverse (ref d; this.rep[0 .. this.size])
- {
- const newCarry = d & mask;
- d = (d >> bit) | (carry << shift);
- carry = newCarry;
- }
- }
- this.contract();
- return this;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- auto integer = Integer(4294967294);
- integer >>= 10;
- assert(integer == 4194303);
-
- integer = 27336704;
- integer >>= 1;
- assert(integer == 13668352);
-
- integer = 4294967294;
- integer >>= 20;
- assert(integer == 4095);
-
- integer >>= 0;
- assert(integer == 4095);
-
- integer >>= 20;
- assert(integer == 0);
-
- integer >>= 2;
- assert(integer == 0);
-
- integer = 1431655765;
- integer >>= 16;
- assert(integer == 21845);
-
- integer >>= 16;
- assert(integer == 0);
- }
-
- /// ditto
- ref Integer opOpAssign(string op : "<<")(const size_t operand)
- {
- const step = operand / digitBitCount;
- if (this.rep.length < this.size + step + 1)
- {
- grow(this.size + step + 1);
- }
- if (operand >= digitBitCount)
- {
- shiftLeft(step);
- }
-
- const bit = cast(digit) (operand % digitBitCount);
- if (bit != 0)
- {
- const mask = ((cast(digit) 1) << bit) - 1;
- const shift = digitBitCount - bit;
- digit carry;
-
- foreach (ref d; this.rep[0 .. this.size])
- {
- const newCarry = (d >> shift) & mask;
- d = ((d << bit) | carry) & this.mask;
- carry = newCarry;
- }
-
- if (carry != 0)
- {
- this.rep[this.size++] = carry;
- }
- }
- this.contract();
- return this;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- auto integer = Integer(4294967295);
- integer <<= 1;
- assert(integer == 8589934590);
- }
-
- /**
- * Unary operators.
- *
- * Params:
- * op = Operation.
- *
- * Returns: New $(D_PSYMBOL Integer).
- */
- Integer opUnary(string op : "~")() const
- {
- auto ret = Integer(this, allocator);
- foreach (ref a; ret.rep[0 .. ret.size])
- {
- a = ~a & mask;
- }
- return ret;
- }
-
- /// ditto
- Integer opUnary(string op : "-")() const
- {
- auto ret = Integer(this, allocator);
- ret.sign = ret.sign ? Sign.positive : Sign.negative;
- return ret;
- }
-
- /**
- * Unary operators.
- *
- * Params:
- * op = Operation.
- *
- * Returns: $(D_KEYWORD this).
- */
- ref inout(Integer) opUnary(string op : "+")() inout
- {
- return this;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- auto h1 = Integer(79);
- Integer h2;
-
- h2 = +h1;
- assert(h2 == 79);
-
- h2 = -h1;
- assert(h2 == -79);
- assert(h1 == 79);
-
- h1 = -h2;
- assert(h1 == 79);
-
- h2 = ~h1;
- assert(h2 == cast(ubyte) ~79);
- }
-
- /// ditto
- ref Integer opUnary(string op : "++")()
- {
- if (this.sign)
- {
- subtract(1, this);
- }
- else
- {
- add(1, this);
- }
- return this;
- }
-
- /// ditto
- ref Integer opUnary(string op : "--")()
- {
- if (this.size == 0)
- {
- add(1, this);
- this.sign = Sign.negative;
- }
- else if (this.sign)
- {
- add(1, this);
- }
- else
- {
- subtract(1, this);
- }
- return this;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- Integer integer;
-
- ++integer;
- assert(integer == 1);
-
- --integer;
- assert(integer == 0);
-
- integer = 511;
- ++integer;
- assert(integer == 512);
-
- --integer;
- assert(integer == 511);
-
- integer = 79;
- ++integer;
- assert(integer == 80);
-
- --integer;
- assert(integer == 79);
-
- integer = -2;
- ++integer;
- assert(integer == -1);
-
- ++integer;
- assert(integer == 0);
-
- --integer;
- assert(integer == -1);
- }
-
- /**
- * Implements binary operators.
- *
- * Params:
- * op = Operation.
- * operand = The second operand.
- *
- * Returns: Result.
- */
- Integer opBinary(string op)(auto ref const Integer operand) const
- if ((op == "+" || op == "-") || (op == "*"))
- {
- mixin("return Integer(this, allocator) " ~ op ~ "= operand;");
- }
-
- /// ditto
- Integer opBinary(string op)(const auto ref Integer operand) const
- if (op == "/" || op == "%")
- in (operand.length > 0, "Division by zero")
- {
- mixin("return Integer(this, allocator) " ~ op ~ "= operand;");
- }
-
- /// ditto
- Integer opBinary(string op)(const size_t operand) const
- if (op == "<<" || op == ">>")
- {
- mixin("return Integer(this, allocator) " ~ op ~ "= operand;");
- }
-
- // Shift right a certain amount of digits.
- private void shiftRight(const size_t operand) @nogc nothrow pure @safe
- {
- if (operand == 0)
- {
- return;
- }
- if (this.size <= operand)
- {
- this = 0;
- return;
- }
- const reducedSize = this.size - operand;
-
- this.rep[operand .. this.size].copy(this.rep[0 .. reducedSize]);
- this.rep[reducedSize .. this.size].fill(digit.init);
- this.size = reducedSize;
- }
-
- // Shift left a certain amount of digits.
- private void shiftLeft(const size_t operand) @nogc nothrow pure @safe
- {
- if (operand == 0)
- {
- return;
- }
- const increasedSize = this.size + operand;
- grow(increasedSize);
-
- this.size = increasedSize;
-
- auto top = this.size - 1;
- auto bottom = this.size - 1 - operand;
-
- for (; top >= operand; --bottom, --top)
- {
- this.rep[top] = this.rep[bottom];
- }
- this.rep[0 .. operand].fill(digit.init);
- }
-
- private void multiply(const digit factor, ref Integer product)
- const @nogc nothrow pure @safe
- {
- product.grow(this.size + 1);
- product.sign = this.sign;
-
- word carry;
- size_t i;
-
- for (i = 0; i < this.size; ++i)
- {
- auto newCarry = carry + (cast(word) this.rep[i] * factor);
- product.rep[i] = newCarry & mask;
- carry = newCarry >> digitBitCount;
- }
- product.rep[i++] = carry & mask;
-
- for (; i < this.size; ++i)
- {
- product.rep[i] = 0;
- }
- product.size = this.size + 1;
- product.contract();
- }
-
- private void multiply(ref const Integer factor,
- ref Integer product,
- const size_t digits) const @nogc nothrow pure @safe
- {
- Integer intermediate;
- intermediate.grow(digits);
- intermediate.size = digits;
-
- for (size_t i; i < this.size; ++i)
- {
- const limit = min(cast(size_t) factor.size, digits - i);
- word carry;
- auto k = i;
-
- for (size_t j; j < limit; ++j, ++k)
- {
- const result = cast(word) intermediate.rep[k]
- + (cast(word) this.rep[i] * factor.rep[j])
- + carry;
- intermediate.rep[k] = result & mask;
- carry = result >> digitBitCount;
- }
- if (k < digits)
- {
- intermediate.rep[k] = carry & mask;
- }
- }
- intermediate.contract();
- swap(product, intermediate);
- }
-
- private void divide(Q, ARGS...)(ref const Integer divisor,
- auto ref Q quotient,
- ref ARGS args) const
- if ((is(Q : typeof(null))
- || (is(Q : Integer) && __traits(isRef, quotient)))
- && (ARGS.length == 0 || (ARGS.length == 1 && is(ARGS[0] : Integer))))
- in (divisor != 0, "Division by zero")
- {
- if (compare(divisor) < 0)
- {
- static if (ARGS.length == 1)
- {
- args[0] = this;
- }
- static if (!is(Q == typeof(null)))
- {
- quotient = 0;
- }
- return;
- }
-
- Integer q, t1, t2;
- q.grow(this.size + 2);
- q.size = this.size + 2;
-
- t1.grow(2);
- t2.grow(3);
-
- auto x = Integer(this);
- auto y = Integer(divisor);
-
- const sign = this.sign == divisor.sign ? Sign.positive : Sign.negative;
- x.sign = y.sign = Sign.positive;
-
- auto norm = y.countBits() % digitBitCount;
- if (norm < digitBitCount - 1)
- {
- norm = digitBitCount - 1 - norm;
- x <<= norm;
- y <<= norm;
- }
- else
- {
- norm = 0;
- }
-
- auto n = x.size - 1;
- auto t = y.size - 1;
-
- y.shiftLeft(n - t);
-
- while (x >= y)
- {
- ++q.rep[n - t];
- x -= y;
- }
-
- y.shiftRight(n - t);
-
- for (auto i = n; i >= (t + 1); --i)
- {
- if (i > x.size)
- {
- continue;
- }
- if (x.rep[i] == y.rep[t])
- {
- q.rep[(i - t) - 1] = (((cast(digit) 1) << digitBitCount) - 1);
- }
- else
- {
- word tmp = (cast(word) x.rep[i]) << digitBitCount;
- tmp |= x.rep[i - 1];
- tmp /= y.rep[t];
- if (tmp > mask)
- {
- tmp = mask;
- }
- q.rep[i - t - 1] = tmp & mask;
- }
-
- q.rep[i - t - 1] = (q.rep[i - t - 1] + 1) & mask;
- do
- {
- q.rep[i - t - 1] = (q.rep[i - t - 1] - 1) & mask;
-
- // Left hand.
- t1 = 0;
- t1.rep[0] = ((t - 1) < 0) ? 0 : y.rep[t - 1];
- t1.rep[1] = y.rep[t];
- t1.size = 2;
- t1.multiply(q.rep[i - t - 1], t1);
-
- // Right hand.
- t2.rep[0] = ((i - 2) < 0) ? 0 : x.rep[i - 2];
- t2.rep[1] = ((i - 1) < 0) ? 0 : x.rep[i - 1];
- t2.rep[2] = x.rep[i];
- t2.size = 3;
- }
- while (t1.compare(t2) > 0);
-
- y.multiply(q.rep[i - t - 1], t1);
-
- t1.shiftLeft(i - t - 1);
-
- x -= t1;
-
- if (x.sign == Sign.negative)
- {
- t1 = y;
- t1.shiftLeft(i - t - 1);
- x += t1;
-
- q.rep[i - t - 1] = (q.rep[i - t - 1] - 1) & mask;
- }
- }
-
- x.sign = (x.size == 0) ? Sign.positive : this.sign;
- static if (!is(Q == typeof(null)))
- {
- q.contract();
- swap(q, quotient);
- quotient.sign = sign;
- }
- static if (ARGS.length == 1)
- {
- x >>= norm;
- swap(x, args[0]);
- }
- }
-
- private Integer square() @nogc nothrow pure @safe
- {
- Integer result;
- const resultSize = 2 * this.size + 1;
-
- result.grow(resultSize);
- result.size = resultSize;
-
- for (size_t i; i < this.size; ++i)
- {
- const doubleI = 2 * i;
- word product = cast(word) result.rep[doubleI]
- + (cast(word) this.rep[i] * this.rep[i]);
-
- result.rep[doubleI] = product & mask;
-
- word carry = product >> digitBitCount;
- size_t k = doubleI + 1;
-
- for (auto j = i + 1; j < this.size; ++j, ++k)
- {
- product = (cast(word) this.rep[i]) * (cast(word) this.rep[j]);
- product = (cast(word) result.rep[k]) + (2 * product) + carry;
-
- result.rep[k] = product & mask;
- carry = product >> digitBitCount;
- }
- for (; carry != 0; ++k)
- {
- product = (cast(word) result.rep[k]) + carry;
- result.rep[k] = product & mask;
- carry = product >> digitBitCount;
- }
- }
- result.contract();
-
- return result;
- }
-
- // Returns 2^^n.
- private Integer exp2(size_t n) const @nogc nothrow pure @safe
- {
- auto ret = Integer(allocator);
- const bytes = n / digitBitCount;
-
- ret.grow(bytes + 1);
- ret.size = bytes + 1;
- ret.rep[bytes] = (cast(digit) 1) << (n % digitBitCount);
-
- return ret;
- }
-
- /**
- * Returns: Two's complement representation of the integer.
- */
- Array!ubyte toArray() const @nogc nothrow pure @safe
- out (array)
- {
- assert(array.length == length);
- }
- do
- {
- Array!ubyte array;
-
- if (this.size == 0)
- {
- return array;
- }
- const bc = countBits();
- const remainingBits = bc & 0x07;
-
- array.reserve(bc / 8);
- if (remainingBits == 0)
- {
- array.insertBack(ubyte.init);
-
- }
-
- Integer tmp;
- if (this.sign)
- {
- auto length = bc + (8 - remainingBits);
-
- if (((countLSBs() + 1) == bc) && (remainingBits == 0))
- {
- length -= 8;
- }
-
- tmp = exp2(length) + this;
- }
- else
- {
- tmp = this;
- }
-
- array.length = length;
- for (size_t i = array.length - 1; tmp != 0; tmp >>= 8, --i)
- {
- array[i] = (cast(ubyte) (tmp.rep[0] & 0xff));
- }
-
- return array;
- }
-
- ///
- @nogc nothrow pure @safe unittest
- {
- {
- auto integer = Integer(0x66778899aabbddee);
- ubyte[8] expected = [ 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xdd, 0xee ];
-
- auto array = integer.toArray();
- assert(equal(array[], expected[]));
- }
- }
-
- mixin DefaultAllocator;
-}
diff --git a/source/tanya/math/nbtheory.d b/source/tanya/math/nbtheory.d
index ec5d6c4..6f9fb53 100644
--- a/source/tanya/math/nbtheory.d
+++ b/source/tanya/math/nbtheory.d
@@ -14,7 +14,6 @@
*/
module tanya.math.nbtheory;
-import tanya.math.mp;
import tanya.meta.trait;
import tanya.meta.transform;
@@ -91,21 +90,6 @@ if (isFloatingPoint!T)
static assert(is(typeof(r.abs) == real));
}
-/// ditto
-T abs(T : Integer)(const auto ref T x)
-{
- auto result = Integer(x, x.allocator);
- result.sign = Sign.positive;
- return result;
-}
-
-/// ditto
-T abs(T : Integer)(T x)
-{
- x.sign = Sign.positive;
- return x;
-}
-
version (D_Ddoc)
{
/**
diff --git a/source/tanya/math/package.d b/source/tanya/math/package.d
index 28022ee..ee39ca5 100644
--- a/source/tanya/math/package.d
+++ b/source/tanya/math/package.d
@@ -21,7 +21,6 @@
*/
module tanya.math;
-import tanya.math.mp;
import tanya.math.nbtheory;
import tanya.meta.trait;
import tanya.meta.transform;
@@ -548,9 +547,6 @@ if (isFloatingPoint!F)
/**
* Computes $(D_PARAM x) to the power $(D_PARAM y) modulo $(D_PARAM z).
*
- * If $(D_PARAM I) is an $(D_PSYMBOL Integer), the allocator of $(D_PARAM x)
- * is used to allocate the result.
- *
* Params:
* I = Base type.
* G = Exponent type.
@@ -600,41 +596,6 @@ in (z > 0, "Division by zero")
return result;
}
-/// ditto
-I pow(I)(const auto ref I x, const auto ref I y, const auto ref I z)
-if (is(I == Integer))
-in (z.length > 0, "Division by zero")
-{
- size_t i;
- auto tmp1 = Integer(x, x.allocator);
- auto result = Integer(x.allocator);
-
- if (x.size == 0 && y.size != 0)
- {
- i = y.size;
- }
- else
- {
- result = 1;
- }
- while (i < y.size)
- {
- for (uint mask = 0x01; mask != 0x10000000; mask <<= 1)
- {
- if (y.rep[i] & mask)
- {
- result *= tmp1;
- result %= z;
- }
- auto tmp2 = tmp1;
- tmp1 *= tmp2;
- tmp1 %= z;
- }
- ++i;
- }
- return result;
-}
-
///
@nogc nothrow pure @safe unittest
{
@@ -648,32 +609,3 @@ in (z.length > 0, "Division by zero")
assert(pow(0, 0, 5) == 1);
assert(pow(0, 5, 5) == 0);
}
-
-///
-@nogc nothrow pure @safe unittest
-{
- assert(pow(Integer(3), Integer(5), Integer(7)) == 5);
- assert(pow(Integer(2), Integer(2), Integer(1)) == 0);
- assert(pow(Integer(3), Integer(3), Integer(3)) == 0);
- assert(pow(Integer(7), Integer(4), Integer(2)) == 1);
- assert(pow(Integer(53), Integer(0), Integer(2)) == 1);
- assert(pow(Integer(53), Integer(1), Integer(3)) == 2);
- assert(pow(Integer(53), Integer(2), Integer(5)) == 4);
- assert(pow(Integer(0), Integer(0), Integer(5)) == 1);
- assert(pow(Integer(0), Integer(5), Integer(5)) == 0);
-}
-
-deprecated
-bool isPseudoprime(ulong x) @nogc nothrow pure @safe
-{
- return pow(2, x - 1, x) == 1;
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- assert(74623.isPseudoprime);
- assert(104729.isPseudoprime);
- assert(15485867.isPseudoprime);
- assert(!15485868.isPseudoprime);
-}
diff --git a/tests/tanya/math/tests/mp.d b/tests/tanya/math/tests/mp.d
deleted file mode 100644
index 1342ef7..0000000
--- a/tests/tanya/math/tests/mp.d
+++ /dev/null
@@ -1,73 +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.math.tests.mp;
-
-import tanya.algorithm.comparison;
-import tanya.math.mp;
-
-@nogc nothrow pure @safe unittest
-{
- auto h1 = Integer(18);
- auto h2 = Integer(4);
- h1 %= h2;
- assert(h1 == 2);
-
- h1 = 8;
- h1 %= h2;
- assert(h1 == 0);
-
- h1 = 7;
- h1 %= h2;
- assert(h1 == 3);
-
- h1 = 56088;
- h2 = 456;
- h1 /= h2;
- assert(h1 == 123);
-}
-
-@nogc nothrow pure @safe unittest
-{
- Integer integer;
- assert(integer.toArray().length == 0);
-}
-
-@nogc nothrow pure @safe unittest
-{
- auto integer = Integer(0x03);
- ubyte[1] expected = [ 0x03 ];
-
- auto array = integer.toArray();
- assert(equal(array[], expected[]));
-}
-
-@nogc nothrow pure @safe unittest
-{
- ubyte[63] expected = [
- 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x3b, 0x00, 0x61, 0x62, 0x63,
- ];
- auto integer = Integer(Sign.positive, expected[]);
-
- auto array = integer.toArray();
- assert(equal(array[], expected[]));
-}
-
-@nogc nothrow pure @safe unittest
-{
- ubyte[14] expected = [
- 0x22, 0x33, 0x44, 0x55, 0x05, 0x06, 0x07,
- 0x08, 0x3a, 0x3b, 0x00, 0x61, 0x62, 0x63,
- ];
- auto integer = Integer(Sign.positive, expected[]);
-
- auto array = integer.toArray();
- assert(equal(array[], expected[]));
-}
diff --git a/tests/tanya/math/tests/package.d b/tests/tanya/math/tests/package.d
index 9b58af6..fe10efd 100644
--- a/tests/tanya/math/tests/package.d
+++ b/tests/tanya/math/tests/package.d
@@ -17,33 +17,3 @@ static if (ieeePrecision!float == IEEEPrecision.doubleExtended)
unnormal.mantissa = 0x1;
assert(classify(unnormal) == FloatingPointClass.subnormal);
}
-
-@nogc nothrow pure @safe unittest
-{
- assert(74653.isPseudoprime);
- assert(74687.isPseudoprime);
- assert(74699.isPseudoprime);
- assert(74707.isPseudoprime);
- assert(74713.isPseudoprime);
- assert(74717.isPseudoprime);
- assert(74719.isPseudoprime);
- assert(74747.isPseudoprime);
- assert(74759.isPseudoprime);
- assert(74761.isPseudoprime);
- assert(74771.isPseudoprime);
- assert(74779.isPseudoprime);
- assert(74797.isPseudoprime);
- assert(74821.isPseudoprime);
- assert(74827.isPseudoprime);
- assert(9973.isPseudoprime);
- assert(49979693.isPseudoprime);
- assert(104395303.isPseudoprime);
- assert(593441861.isPseudoprime);
- assert(104729.isPseudoprime);
- assert(15485867.isPseudoprime);
- assert(49979693.isPseudoprime);
- assert(104395303.isPseudoprime);
- assert(593441861.isPseudoprime);
- assert(899809363.isPseudoprime);
- assert(982451653.isPseudoprime);
-}
diff --git a/tests/tanya/meta/tests/transform.d b/tests/tanya/meta/tests/transform.d
deleted file mode 100644
index a864261..0000000
--- a/tests/tanya/meta/tests/transform.d
+++ /dev/null
@@ -1,53 +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.transform;
-
-import tanya.meta.transform;
-
-@nogc nothrow pure @safe unittest
-{
- static assert(is(CommonType!(void*, int*) == void*));
- static assert(is(CommonType!(void*, const(int)*) == const(void)*));
- static assert(is(CommonType!(void*, const(void)*) == const(void)*));
- static assert(is(CommonType!(int*, void*) == void*));
- static assert(is(CommonType!(const(int)*, void*) == const(void)*));
- static assert(is(CommonType!(const(void)*, void*) == const(void)*));
-
- static assert(is(CommonType!() == void));
- static assert(is(CommonType!(int*, const(int)*) == const(int)*));
- static assert(is(CommonType!(int**, const(int)**) == const(int*)*));
-
- static assert(is(CommonType!(float, double) == double));
- static assert(is(CommonType!(float, int) == void));
-
- static assert(is(CommonType!(bool, const bool) == bool));
- static assert(is(CommonType!(int, bool) == void));
- static assert(is(CommonType!(int, void) == void));
- static assert(is(CommonType!(Object, void*) == void));
-
- class A
- {
- }
- static assert(is(CommonType!(A, Object) == Object));
- static assert(is(CommonType!(const(A)*, Object*) == const(Object)*));
- static assert(is(CommonType!(A, typeof(null)) == A));
-
- class B : A
- {
- }
- class C : A
- {
- }
- static assert(is(CommonType!(B, C) == A));
-
- static struct S
- {
- int opCast(T : int)()
- {
- return 1;
- }
- }
- static assert(is(CommonType!(S, int) == void));
- static assert(is(CommonType!(const S, S) == const S));
-}