Replace tuples with custom types

This commit is contained in:
Eugen Wissner 2022-06-07 08:40:18 +02:00
parent 5453c646f6
commit 90797a48be
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
5 changed files with 28 additions and 198 deletions

View File

@ -5,7 +5,7 @@
/* /*
* Internal package used by containers that rely on entries/nodes. * Internal package used by containers that rely on entries/nodes.
* *
* Copyright: Eugene Wissner 2016-2020. * Copyright: Eugene Wissner 2016-2022.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@ -19,7 +19,6 @@ import tanya.memory.allocator;
import tanya.memory.lifetime; import tanya.memory.lifetime;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
import tanya.typecons;
package struct SEntry(T) package struct SEntry(T)
{ {
@ -54,7 +53,11 @@ package struct Bucket(K, V = void)
} }
else else
{ {
alias KV = Tuple!(K, "key", V, "value"); package struct KV
{
package K key;
package V value;
}
KV kv; KV kv;
} }
BucketStatus status = BucketStatus.empty; BucketStatus status = BucketStatus.empty;

View File

@ -38,7 +38,7 @@
* *
* More advanced formatting is currently not implemented. * More advanced formatting is currently not implemented.
* *
* Copyright: Eugene Wissner 2017-2020. * Copyright: Eugene Wissner 2017-2022.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@ -56,7 +56,6 @@ import tanya.meta.metafunction;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
import tanya.range; import tanya.range;
import tanya.typecons : Tuple;
// Returns the last part of buffer with converted number. // Returns the last part of buffer with converted number.
package(tanya) char[] integral2String(T)(T number, return ref char[21] buffer) package(tanya) char[] integral2String(T)(T number, return ref char[21] buffer)
@ -940,6 +939,12 @@ private struct uint128
{ {
ulong[2] data; ulong[2] data;
private struct DivMod
{
uint128 quotient;
uint128 remainder;
}
this(ulong upper, ulong lower) @nogc nothrow pure @safe this(ulong upper, ulong lower) @nogc nothrow pure @safe
{ {
this.data[0] = upper; this.data[0] = upper;
@ -1174,7 +1179,7 @@ private struct uint128
return this.data[1]; return this.data[1];
} }
Tuple!(uint128, uint128) divMod(ulong rhs) const @nogc nothrow pure @safe DivMod divMod(ulong rhs) const @nogc nothrow pure @safe
in in
{ {
assert(rhs != uint128(), "Division by 0"); assert(rhs != uint128(), "Division by 0");
@ -1197,22 +1202,22 @@ private struct uint128
typeof(return) result; typeof(return) result;
for (ubyte x = this.bits; x > 0; --x) for (ubyte x = this.bits; x > 0; --x)
{ {
result[0] = result[0] << 1; result.quotient = result.quotient << 1;
result[1] = result[1] << 1; result.remainder = result.remainder << 1;
if ((this >> (x - 1U)) & 1) if ((this >> (x - 1U)) & 1)
{ {
++result[1]; ++result.remainder;
} }
if (result[1] >= rhs) if (result.remainder >= rhs)
{ {
if (result[1].data[1] < rhs) if (result.remainder.data[1] < rhs)
{ {
--result[1].data[0]; --result.remainder.data[0];
} }
result[1].data[1] -= rhs; result.remainder.data[1] -= rhs;
++result[0]; ++result.quotient;
} }
} }
return result; return result;
@ -1220,12 +1225,12 @@ private struct uint128
uint128 opBinary(string op : "/")(ulong rhs) uint128 opBinary(string op : "/")(ulong rhs)
{ {
return divMod(rhs)[0]; return divMod(rhs).quotient;
} }
uint128 opBinary(string op : "%")(ulong rhs) const uint128 opBinary(string op : "%")(ulong rhs) const
{ {
return divMod(rhs)[1]; return divMod(rhs).remainder;
} }
} }
@ -1302,12 +1307,12 @@ do
enum ulong power19 = cast(ulong) 1e19; enum ulong power19 = cast(ulong) 1e19;
auto qr = leftBoundary.divMod(power19); auto qr = leftBoundary.divMod(power19);
auto low = cast(ulong) qr[1]; auto low = cast(ulong) qr.remainder;
const lowFactor = cast(ulong) (qr[0] % power19); const lowFactor = cast(ulong) (qr.quotient % power19);
qr = rightBoundary.divMod(power19); qr = rightBoundary.divMod(power19);
auto high = cast(ulong) qr[1]; auto high = cast(ulong) qr.remainder;
const highFactor = cast(ulong) (qr[0] % power19); const highFactor = cast(ulong) (qr.quotient % power19);
size_t digitIndex; size_t digitIndex;
if (lowFactor != highFactor) if (lowFactor != highFactor)

View File

@ -16,7 +16,6 @@ module tanya.math.random;
import std.typecons; import std.typecons;
import tanya.memory.allocator; import tanya.memory.allocator;
import tanya.typecons;
/// Maximum amount gathered from the entropy sources. /// Maximum amount gathered from the entropy sources.
enum maxGather = 128; enum maxGather = 128;

View File

@ -1,154 +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 constructors.
*
* This module contains templates that allow to build new types from the
* available ones.
*
* Copyright: Eugene Wissner 2017-2020.
* 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/typecons.d,
* tanya/typecons.d)
*/
module tanya.typecons;
import tanya.format;
import tanya.memory.lifetime;
import tanya.meta.metafunction;
import tanya.meta.trait;
/**
* $(D_PSYMBOL Tuple) can store two or more heterogeneous objects.
*
* The objects can by accessed by index as `obj[0]` and `obj[1]` or by optional
* names (e.g. `obj.first`).
*
* $(D_PARAM Specs) contains a list of object types and names. First
* comes the object type, then an optional string containing the name.
* If you want the object be accessible only by its index (`0` or `1`),
* just skip the name.
*
* Params:
* Specs = Field types and names.
*
* See_Also: $(D_PSYMBOL tuple).
*/
template Tuple(Specs...)
{
template parseSpecs(size_t fieldCount, Specs...)
{
static if (Specs.length == 0)
{
alias parseSpecs = AliasSeq!();
}
else static if (is(Specs[0]) && fieldCount < 2)
{
static if (is(typeof(Specs[1]) == string))
{
alias parseSpecs
= AliasSeq!(Pack!(Specs[0], Specs[1]),
parseSpecs!(fieldCount + 1, Specs[2 .. $]));
}
else
{
alias parseSpecs
= AliasSeq!(Pack!(Specs[0]),
parseSpecs!(fieldCount + 1, Specs[1 .. $]));
}
}
else
{
static assert(false, "Invalid argument: " ~ Specs[0].stringof);
}
}
alias ChooseType(alias T) = T.Seq[0];
alias ParsedSpecs = parseSpecs!(0, Specs);
static assert(ParsedSpecs.length > 1, "Invalid argument count");
private string formatAliases(size_t n, Specs...)()
{
static if (Specs.length == 0)
{
return "";
}
else
{
string fieldAlias;
static if (Specs[0].length == 2)
{
char[21] buffer;
fieldAlias = "alias " ~ Specs[0][1] ~ " = expand["
~ integral2String(n, buffer).idup ~ "];";
}
return fieldAlias ~ formatAliases!(n + 1, Specs[1 .. $])();
}
}
struct Tuple
{
/// Field types.
alias Types = Map!(ChooseType, ParsedSpecs);
// Create field aliases.
mixin(formatAliases!(0, ParsedSpecs[0 .. $])());
/// Represents the values of the $(D_PSYMBOL Tuple) as a list of values.
Types expand;
alias expand this;
}
}
///
@nogc nothrow pure @safe unittest
{
auto pair = Tuple!(int, "first", string, "second")(1, "second");
assert(pair.first == 1);
assert(pair[0] == 1);
assert(pair.second == "second");
assert(pair[1] == "second");
}
/**
* Creates a new $(D_PSYMBOL Tuple).
*
* Params:
* Names = Field names.
*
* See_Also: $(D_PSYMBOL Tuple).
*/
template tuple(Names...)
{
/**
* Creates a new $(D_PSYMBOL Tuple).
*
* Params:
* Args = Field types.
* args = Field values.
*
* Returns: Newly created $(D_PSYMBOL Tuple).
*/
auto tuple(Args...)(auto ref Args args)
if (Args.length >= Names.length && isTypeTuple!Args)
{
alias Zipped = ZipWith!(AliasSeq, Pack!Args, Pack!Names);
alias Nameless = Args[Names.length .. $];
return Tuple!(Zipped, Nameless)(forward!args);
}
}
///
@nogc nothrow pure @safe unittest
{
auto t = tuple!("one", "two")(20, 5);
assert(t.one == 20);
assert(t.two == 5);
}

View File

@ -1,23 +0,0 @@
module tanya.tests.typecons;
import tanya.test.stub;
import tanya.typecons;
@nogc nothrow pure @safe unittest
{
static assert(is(Tuple!(int, int)));
static assert(!is(Tuple!(int, 5)));
static assert(is(Tuple!(int, "first", int)));
static assert(is(Tuple!(int, "first", int, "second")));
static assert(is(Tuple!(int, "first", int)));
static assert(is(Tuple!(int, int, "second")));
static assert(!is(Tuple!("first", int, "second", int)));
static assert(!is(Tuple!(int, int, int)));
static assert(!is(Tuple!(int, "first")));
static assert(!is(Tuple!(int, double, char)));
static assert(!is(Tuple!(int, "first", double, "second", char, "third")));
}