summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2018-10-02 08:55:29 +0200
committerEugen Wissner <belka@caraus.de>2018-10-02 08:55:29 +0200
commit772e87739c848a10a014d3118ff14bd0ca48b2d0 (patch)
treeb567a3c6fb03d45fb7048632bdb66501e42e65d8
parent2a90a812db53728d29a3a821cb292c032437d806 (diff)
downloadtanya-772e87739c848a10a014d3118ff14bd0ca48b2d0.tar.gz
Replace memory.op.cmp with optimized equal version
Deprecate cmp. Fix #68.
-rw-r--r--arch/build.ninja4
-rw-r--r--arch/x64/linux/memory/equal.S (renamed from arch/x64/linux/memory/cmp.S)30
-rw-r--r--source/tanya/algorithm/comparison.d6
-rw-r--r--source/tanya/format.d18
-rw-r--r--source/tanya/memory/op.d136
5 files changed, 104 insertions, 90 deletions
diff --git a/arch/build.ninja b/arch/build.ninja
index 824efa4..cf05696 100644
--- a/arch/build.ninja
+++ b/arch/build.ninja
@@ -6,9 +6,9 @@ rule archive
build abs.o: gas x64/linux/math/abs.S
build log.o: gas x64/linux/math/log.S
-build cmp.o: gas x64/linux/memory/cmp.S
+build equal.o: gas x64/linux/memory/equal.S
build fill.o: gas x64/linux/memory/fill.S
build copy.o: gas x64/linux/memory/copy.S
build syscall.o: gas x64/linux/syscall.S
-build tanya.a: archive syscall.o copy.o fill.o cmp.o log.o abs.o
+build tanya.a: archive syscall.o copy.o fill.o equal.o log.o abs.o
diff --git a/arch/x64/linux/memory/cmp.S b/arch/x64/linux/memory/equal.S
index bd9f02e..37a906a 100644
--- a/arch/x64/linux/memory/cmp.S
+++ b/arch/x64/linux/memory/equal.S
@@ -1,20 +1,19 @@
.text
/*
- * cmpMemory.
+ * equalMemory.
*
* rdi - r1 length
* rsi - r1 data.
* rdx - r2 length.
* rcx - r2 data.
*/
- .globl _D5tanya6memory2op9cmpMemoryFNaNbNixAvxQdZi
- .type _D5tanya6memory2op9cmpMemoryFNaNbNixAvxQdZi, @function
-_D5tanya6memory2op9cmpMemoryFNaNbNixAvxQdZi:
+ .globl _D5tanya6memory2op11equalMemoryFNaNbNixAvxQdZb
+ .type _D5tanya6memory2op11equalMemoryFNaNbNixAvxQdZb, @function
+_D5tanya6memory2op11equalMemoryFNaNbNixAvxQdZb:
// Compare the lengths
cmp %rdx, %rdi
- jl less
- jg greater
+ jne not_equal
mov %rcx, %rdi
@@ -26,8 +25,7 @@ _D5tanya6memory2op9cmpMemoryFNaNbNixAvxQdZi:
naligned:
cmpsb
- jl less
- jg greater
+ jne not_equal
dec %rdx
test $0x07, %edi
@@ -38,8 +36,7 @@ _D5tanya6memory2op9cmpMemoryFNaNbNixAvxQdZi:
shr $0x03, %rcx
repe cmpsq
- jl less
- jg greater
+ jne not_equal
and $0x07, %edx
jz equal
@@ -49,19 +46,14 @@ _D5tanya6memory2op9cmpMemoryFNaNbNixAvxQdZi:
cmp $0x0, %rcx
repe cmpsb
- jl less
- jg greater
+ jne not_equal
equal:
- xor %rax, %rax // Return 0
- jmp end
-
- greater:
- mov $0x01, %rax
+ mov $0x01, %rax // Return 1
jmp end
- less:
- mov $-0x01, %rax
+ not_equal:
+ xor %rax, %rax // Return 0
end:
ret
diff --git a/source/tanya/algorithm/comparison.d b/source/tanya/algorithm/comparison.d
index 88f6860..904f045 100644
--- a/source/tanya/algorithm/comparison.d
+++ b/source/tanya/algorithm/comparison.d
@@ -15,8 +15,8 @@
module tanya.algorithm.comparison;
import tanya.algorithm.mutation;
-import tanya.math : isNaN;
-import tanya.memory.op;
+import tanya.math;
+static import tanya.memory.op;
import tanya.meta.metafunction;
import tanya.meta.trait;
import tanya.meta.transform;
@@ -296,7 +296,7 @@ if (allSatisfy!(isInputRange, R1, R2)
&& is(R1 == R2)
&& __traits(isPOD, ElementType!R1))
{
- return cmp(r1, r2) == 0;
+ return tanya.memory.op.equal(r1, r2);
}
else
{
diff --git a/source/tanya/format.d b/source/tanya/format.d
index 2a30822..fa46945 100644
--- a/source/tanya/format.d
+++ b/source/tanya/format.d
@@ -43,7 +43,7 @@ import tanya.algorithm.comparison;
import tanya.container.string;
import tanya.encoding.ascii;
import tanya.math;
-import tanya.memory.op;
+static import tanya.memory.op;
import tanya.meta.metafunction;
import tanya.meta.trait;
import tanya.meta.transform;
@@ -1351,7 +1351,7 @@ do
intSlice.popBack();
}
const begin = buffer.length - intSlice.length;
- copy(intSlice, buffer[begin .. $]);
+ tanya.memory.op.copy(intSlice, buffer[begin .. $]);
exponent = cast(int) (intSlice.length + mismatch);
@@ -1388,7 +1388,7 @@ do
char[21] intBuffer;
auto intSlice = integral2String(decimal, intBuffer);
- copy(intSlice, buffer);
+ tanya.memory.op.copy(intSlice, buffer);
exponent = cast(int) intSlice.length;
size_t position = exponent;
@@ -1903,7 +1903,7 @@ private char[] errol3(double value,
if (pathologies[middle].representation == bits.integral)
{
exponent = pathologies[middle].exponent;
- copy(pathologies[middle].digits, buffer);
+ tanya.memory.op.copy(pathologies[middle].digits, buffer);
return buffer[0 .. pathologies[middle].digits.length];
}
else if (pathologies[middle].representation < bits.integral)
@@ -2054,7 +2054,7 @@ if (isFloatingPoint!T)
{
length = precision + 1;
}
- realString[1 .. length].copy(bufferSlice);
+ tanya.memory.op.copy(realString[1 .. length], bufferSlice);
bufferSlice.popFrontExactly(length - 1);
// Dump the exponent.
@@ -2116,7 +2116,7 @@ if (isFloatingPoint!T)
n = precision;
}
- fill!'0'(bufferSlice[0 .. n]);
+ tanya.memory.op.fill!'0'(bufferSlice[0 .. n]);
bufferSlice.popFrontExactly(n);
if ((length + n) > precision)
@@ -2124,7 +2124,7 @@ if (isFloatingPoint!T)
length = precision - n;
}
- realString[0 .. length].copy(bufferSlice);
+ tanya.memory.op.copy(realString[0 .. length], bufferSlice);
bufferSlice.popFrontExactly(length);
}
else if (cast(uint) decimalPoint >= length)
@@ -2142,7 +2142,7 @@ if (isFloatingPoint!T)
{
n = decimalPoint - n;
- fill!'0'(bufferSlice[0 .. n]);
+ tanya.memory.op.fill!'0'(bufferSlice[0 .. n]);
bufferSlice.popFrontExactly(n);
}
if (precision != 0)
@@ -2173,7 +2173,7 @@ if (isFloatingPoint!T)
length = precision + decimalPoint;
}
- realString[n .. length].copy(bufferSlice);
+ tanya.memory.op.copy(realString[n .. length], bufferSlice);
bufferSlice.popFrontExactly(length - n);
}
}
diff --git a/source/tanya/memory/op.d b/source/tanya/memory/op.d
index 8e56c80..b411ed7 100644
--- a/source/tanya/memory/op.d
+++ b/source/tanya/memory/op.d
@@ -24,7 +24,7 @@ version (TanyaNative)
extern private void moveMemory(const void[], void[])
pure nothrow @system @nogc;
- extern private int cmpMemory(const void[], const void[])
+ extern private bool equalMemory(const void[], const void[])
pure nothrow @system @nogc;
}
else
@@ -43,7 +43,7 @@ version (TanyaNative)
@nogc nothrow pure @safe unittest
{
- assert(cmp(null, null) == 0);
+ assert(equal(null, null));
}
}
@@ -91,7 +91,7 @@ do
ubyte[9] source = [1, 2, 3, 4, 5, 6, 7, 8, 9];
ubyte[9] target;
source.copy(target);
- assert(cmp(source, target) == 0);
+ assert(equal(source, target));
}
@nogc nothrow pure @safe unittest
@@ -110,7 +110,7 @@ do
ubyte[8] source = [1, 2, 3, 4, 5, 6, 7, 8];
ubyte[8] target;
source.copy(target);
- assert(cmp(source, target) == 0);
+ assert(equal(source, target));
}
}
@@ -212,7 +212,7 @@ do
ubyte[6] expected = [ 'a', 'a', 'a', 'a', 'b', 'b' ];
copyBackward(mem[0 .. 4], mem[2 .. $]);
- assert(cmp(expected, mem) == 0);
+ assert(equal(expected, mem));
}
@nogc nothrow pure @safe unittest
@@ -221,7 +221,7 @@ do
ubyte[9] r2;
copyBackward(r1, r2);
- assert(cmp(r1, r2) == 0);
+ assert(equal(r1, r2));
}
/**
@@ -241,6 +241,7 @@ do
* negative integer if $(D_INLINECODE r2 > r1),
* `0` if $(D_INLINECODE r1 == r2).
*/
+deprecated("Use tanya.memory.op.equal() or tanya.algorithm.comparison.compare() instead")
int cmp(const void[] r1, const void[] r2) @nogc nothrow pure @trusted
in
{
@@ -249,48 +250,13 @@ in
}
do
{
- version (TanyaNative)
+ import core.stdc.string : memcmp;
+
+ if (r1.length > r2.length)
{
- return cmpMemory(r1, r2);
- }
- else
- {
- if (r1.length > r2.length)
- {
- return 1;
- }
- return r1.length < r2.length ? -1 : memcmp(r1.ptr, r2.ptr, r1.length);
+ return 1;
}
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- ubyte[4] r1 = [ 'a', 'b', 'c', 'd' ];
- ubyte[3] r2 = [ 'c', 'a', 'b' ];
-
- assert(cmp(r1[0 .. 3], r2[]) < 0);
- assert(cmp(r2[], r1[0 .. 3]) > 0);
-
- assert(cmp(r1, r2) > 0);
- assert(cmp(r2, r1) < 0);
-}
-
-@nogc nothrow pure @safe unittest
-{
- ubyte[16] r1 = [
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
- 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
- ];
- ubyte[16] r2 = [
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
- 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
- ];
-
- assert(cmp(r1, r2) == 0);
- assert(cmp(r1[1 .. $], r2[1 .. $]) == 0);
- assert(cmp(r1[0 .. $ - 1], r2[0 .. $ - 1]) == 0);
- assert(cmp(r1[0 .. 8], r2[0 .. 8]) == 0);
+ return r1.length < r2.length ? -1 : memcmp(r1.ptr, r2.ptr, r1.length);
}
/**
@@ -362,13 +328,13 @@ do
{
const ubyte[9] haystack = ['a', 'b', 'c', 'd', 'e', 'f', 'b', 'g', 'h'];
- assert(cmp(find(haystack, 'a'), haystack[]) == 0);
- assert(cmp(find(haystack, 'b'), haystack[1 .. $]) == 0);
- assert(cmp(find(haystack, 'c'), haystack[2 .. $]) == 0);
- assert(cmp(find(haystack, 'd'), haystack[3 .. $]) == 0);
- assert(cmp(find(haystack, 'e'), haystack[4 .. $]) == 0);
- assert(cmp(find(haystack, 'f'), haystack[5 .. $]) == 0);
- assert(cmp(find(haystack, 'h'), haystack[8 .. $]) == 0);
+ assert(equal(find(haystack, 'a'), haystack[]));
+ assert(equal(find(haystack, 'b'), haystack[1 .. $]));
+ assert(equal(find(haystack, 'c'), haystack[2 .. $]));
+ assert(equal(find(haystack, 'd'), haystack[3 .. $]));
+ assert(equal(find(haystack, 'e'), haystack[4 .. $]));
+ assert(equal(find(haystack, 'f'), haystack[5 .. $]));
+ assert(equal(find(haystack, 'h'), haystack[8 .. $]));
assert(find(haystack, 'i').length == 0);
assert(find(null, 'a').length == 0);
@@ -441,10 +407,66 @@ do
///
@nogc nothrow pure @safe unittest
{
- assert(cmp(findNullTerminated("abcdef\0gh"), "abcdef") == 0);
- assert(cmp(findNullTerminated("\0garbage"), "") == 0);
- assert(cmp(findNullTerminated("\0"), "") == 0);
- assert(cmp(findNullTerminated("cstring\0"), "cstring") == 0);
+ assert(equal(findNullTerminated("abcdef\0gh"), "abcdef"));
+ assert(equal(findNullTerminated("\0garbage"), ""));
+ assert(equal(findNullTerminated("\0"), ""));
+ assert(equal(findNullTerminated("cstring\0"), "cstring"));
assert(findNullTerminated(null) is null);
assert(findNullTerminated("abcdef") is null);
}
+
+/**
+ * Compares two memory areas $(D_PARAM r1) and $(D_PARAM r2) for equality.
+ *
+ * Params:
+ * haystack = First memory block.
+ * needle = First memory block.
+ *
+ * Returns: $(D_KEYWORD true) if $(D_PARAM r1) and $(D_PARAM r2) are equal,
+ * $(D_KEYWORD false) otherwise.
+ */
+bool equal(const void[] r1, const void[] r2) @nogc nothrow pure @trusted
+in
+{
+ assert(r1.length == 0 || r1.ptr !is null);
+ assert(r2.length == 0 || r2.ptr !is null);
+}
+do
+{
+ version (TanyaNative)
+ {
+ return equalMemory(r1, r2);
+ }
+ else
+ {
+ return r1.length == r2.length
+ && memcmp(r1.ptr, r2.ptr, r1.length) == 0;
+ }
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ assert(equal("asdf", "asdf"));
+ assert(!equal("asd", "asdf"));
+ assert(!equal("asdf", "asd"));
+ assert(!equal("asdf", "qwer"));
+}
+
+// Compares unanligned memory
+@nogc nothrow pure @safe unittest
+{
+ ubyte[16] r1 = [
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ ];
+ ubyte[16] r2 = [
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ ];
+
+ assert(equal(r1, r2));
+ assert(equal(r1[1 .. $], r2[1 .. $]));
+ assert(equal(r1[0 .. $ - 1], r2[0 .. $ - 1]));
+ assert(equal(r1[0 .. 8], r2[0 .. 8]));
+}