Implement auto-decoding free equal comparison

Fix #39.
This commit is contained in:
Eugen Wissner 2018-06-12 20:19:06 +02:00
parent 15f7994187
commit a86b6690f0
7 changed files with 70 additions and 5 deletions

View File

@ -47,6 +47,7 @@ _D5tanya6memory2op9cmpMemoryFNaNbNixAvxAvZi:
aligned_1: // Compare the remaining bytes aligned_1: // Compare the remaining bytes
mov %rdx, %rcx mov %rdx, %rcx
cmp $0x0, %rcx
repe cmpsb repe cmpsb
jl less jl less

View File

@ -16,6 +16,7 @@ module tanya.algorithm.comparison;
import tanya.algorithm.mutation; import tanya.algorithm.mutation;
import tanya.math : isNaN; import tanya.math : isNaN;
import tanya.memory.op;
import tanya.meta.metafunction; import tanya.meta.metafunction;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
@ -270,3 +271,63 @@ if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
assert(max(s2, s3).s == 3); assert(max(s2, s3).s == 3);
} }
} }
/**
* Compares element-wise two ranges for equality.
*
* If the ranges have different lengths, they aren't equal.
*
* Params:
* R1 = First range type.
* R2 = Second range type.
* range1 = First range.
* range2 = Second range.
*
* Returns: $(D_KEYWORD true) if both ranges are equal, $(D_KEYWORD false)
* otherwise.
*/
bool equal(R1, R2)(R1 r1, R2 r2)
if (allSatisfy!(isInputRange, R1, R2) && is(typeof(r1.front == r2.front)))
{
static if (isDynamicArray!R1
&& is(R1 == R2)
&& __traits(isPOD, ElementType!R1))
{
return cmp(r1, r2) == 0;
}
else
{
static if (hasLength!R1 && hasLength!R2)
{
if (r1.length != r2.length)
{
return false;
}
}
for (; !r1.empty && !r2.empty; r1.popFront(), r2.popFront())
{
if (r1.front != r2.front)
{
return false;
}
}
static if (hasLength!R1 && hasLength!R2)
{
return true;
}
else
{
return r1.empty && r2.empty;
}
}
}
///
@nogc nothrow pure @safe unittest
{
int[2] range1 = [1, 2];
assert(equal(range1[], range1[]));
int[3] range2 = [1, 2, 3];
assert(!equal(range1[], range2[]));
}

View File

@ -15,7 +15,6 @@
module tanya.container.array; module tanya.container.array;
import core.checkedint; import core.checkedint;
import std.algorithm.comparison : equal;
import std.algorithm.mutation : bringToFront, import std.algorithm.mutation : bringToFront,
copy, copy,
fill, fill,

View File

@ -15,7 +15,6 @@
*/ */
module tanya.container.list; module tanya.container.list;
import std.algorithm.comparison : equal;
import std.algorithm.searching; import std.algorithm.searching;
import tanya.algorithm.comparison; import tanya.algorithm.comparison;
import tanya.algorithm.mutation; import tanya.algorithm.mutation;
@ -574,7 +573,7 @@ struct SList(T)
*/ */
bool opEquals()(auto ref typeof(this) that) inout bool opEquals()(auto ref typeof(this) that) inout
{ {
return equal(this[], that[]); return equal(opIndex(), that[]);
} }
/// ///

View File

@ -26,7 +26,7 @@
*/ */
module tanya.container.string; module tanya.container.string;
import std.algorithm.comparison : cmp, equal; import std.algorithm.comparison : cmp;
import std.algorithm.mutation : bringToFront, copy; import std.algorithm.mutation : bringToFront, copy;
import std.algorithm.searching; import std.algorithm.searching;
import tanya.algorithm.comparison; import tanya.algorithm.comparison;

View File

@ -14,7 +14,7 @@
*/ */
module tanya.math.mp; module tanya.math.mp;
import std.algorithm.comparison : cmp, equal; import std.algorithm.comparison : cmp;
import std.algorithm.mutation : copy, fill, reverse; import std.algorithm.mutation : copy, fill, reverse;
import std.range; import std.range;
import tanya.algorithm.comparison; import tanya.algorithm.comparison;

View File

@ -40,6 +40,11 @@ version (TanyaNative)
fillMemory(buffer[1 .. $], 0); fillMemory(buffer[1 .. $], 0);
assert(buffer[0] == 1 && buffer[1] == 0); assert(buffer[0] == 1 && buffer[1] == 0);
} }
@nogc nothrow pure @safe unittest
{
assert(cmp(null, null) == 0);
}
} }
private enum alignMask = size_t.sizeof - 1; private enum alignMask = size_t.sizeof - 1;