From fb1deb732f60e4d96dd1de777f5f933cc364b500 Mon Sep 17 00:00:00 2001 From: Mirek Fidler Date: Thu, 10 Apr 2025 09:36:47 +0200 Subject: [PATCH] Core: memeq8len --- autotest/memeq8len/memeq8len.cpp | 49 ++++++++++++++++++++++++++++++ autotest/memeq8len/memeq8len.upp | 9 ++++++ benchmarks/memeq8len/memeq8len.cpp | 43 ++++++++++++++++++++++++++ benchmarks/memeq8len/memeq8len.upp | 9 ++++++ uppsrc/Core/Mem.h | 45 +++++++++++++++++++++++++++ uppsrc/Core/src.tpp/Mem_en-us.tpp | 10 ++++++ 6 files changed, 165 insertions(+) create mode 100644 autotest/memeq8len/memeq8len.cpp create mode 100644 autotest/memeq8len/memeq8len.upp create mode 100644 benchmarks/memeq8len/memeq8len.cpp create mode 100644 benchmarks/memeq8len/memeq8len.upp diff --git a/autotest/memeq8len/memeq8len.cpp b/autotest/memeq8len/memeq8len.cpp new file mode 100644 index 000000000..f8f1086da --- /dev/null +++ b/autotest/memeq8len/memeq8len.cpp @@ -0,0 +1,49 @@ +#include + +using namespace Upp; + +size_t memeq8len_e(const void *p, const void *q, size_t count) +{ + const byte *t = (byte *)p; + const byte *t0 = t; + const byte *s = (byte *)q; + const byte *et = t0 + count; + + while(t < et) { + if(*t != *s) + return t - t0; + t++; + s++; + } + + return count; +} + +CONSOLE_APP_MAIN +{ + StdLogSetup(LOG_COUT|LOG_FILE); + + byte a[497], b[497]; + for(int i = 0; i < 497; i++) + a[i] = i; + + for(int i = 0; i < 497; i++) { + memcpy(a, b, 497); + b[i] = 13; + + int len, len2; + for(int n = 0; n < 497; n++) { + len = memeq8len(a, b, n); + len2 = memeq8len_e(a, b, n); + ASSERT(len == len2); + } + + for(int n = 0; n < 496; n++) { + len = memeq8len(a + 1, b + 1, n); + len2 = memeq8len_e(a + 1, b + 1, n); + ASSERT(len == len2); + } + } + + DLOG("============ OK"); +} diff --git a/autotest/memeq8len/memeq8len.upp b/autotest/memeq8len/memeq8len.upp new file mode 100644 index 000000000..90a704c92 --- /dev/null +++ b/autotest/memeq8len/memeq8len.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + memeq8len.cpp; + +mainconfig + "" = ""; + diff --git a/benchmarks/memeq8len/memeq8len.cpp b/benchmarks/memeq8len/memeq8len.cpp new file mode 100644 index 000000000..80b822824 --- /dev/null +++ b/benchmarks/memeq8len/memeq8len.cpp @@ -0,0 +1,43 @@ +#include + +using namespace Upp; + +size_t memeq8len_e(const void *p, const void *q, size_t count) +{ + const byte *t = (byte *)p; + const byte *t0 = t; + const byte *s = (byte *)q; + const byte *et = t0 + count; + + while(t < et) { + if(*t != *s) + return t - t0; + t++; + s++; + } + + return count; +} + +int len, len2; + +CONSOLE_APP_MAIN +{ + StdLogSetup(LOG_COUT|LOG_FILE); + + byte a[497], b[497]; + for(int i = 0; i < 497; i++) + a[i] = Random(); + + for(int i = 0; i < 10000; i++) + for(int i = 0; i < 497; i++) { + memcpy(a, b, 497); + b[Random(497)] = 13; + + { RTIMING("memeqlen"); len += memeq8len(a, b, 497); } + { RTIMING("memeqlen_e"); len2 += memeq8len_e(a, b, 497); } + + { RTIMING("memeqlen1"); len += memeq8len(a + 1, b + 1, 496); } + { RTIMING("memeqlen_e1"); len2 += memeq8len_e(a + 1, b + 1, 496); } + } +} diff --git a/benchmarks/memeq8len/memeq8len.upp b/benchmarks/memeq8len/memeq8len.upp new file mode 100644 index 000000000..90a704c92 --- /dev/null +++ b/benchmarks/memeq8len/memeq8len.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + memeq8len.cpp; + +mainconfig + "" = ""; + diff --git a/uppsrc/Core/Mem.h b/uppsrc/Core/Mem.h index 537e73843..0ed3677a1 100644 --- a/uppsrc/Core/Mem.h +++ b/uppsrc/Core/Mem.h @@ -448,6 +448,33 @@ bool memeq32(const void *p, const void *q, size_t count); bool memeq64(const void *p, const void *q, size_t count); bool memeq128(const void *p, const void *q, size_t count); +inline +size_t memeq8len(const void *p, const void *q, size_t count) +{ + const byte *t = (byte *)p; + const byte *t0 = t; + const byte *s = (byte *)q; + + const byte *et = t0 + (count & ~15); + + while(t < et) { + i8x16 cmp = i8x16(t) == i8x16(s); + if(!AllTrue(cmp)) + return t - t0 + FirstFalse(cmp); + t += 16; + s += 16; + } + + et = t0 + count; + while(t < et) { + if(*s != *t) + return t - t0; + s++; + t++; + } + return count; +} + #else template @@ -620,6 +647,24 @@ bool memeq128(const void *p, const void *q, size_t count) return memcmp(p, q, 16 * count) == 0; } +inline +size_t memeq8len(const void *p, const void *q, size_t count) +{ + const byte *t = (byte *)p; + const byte *t0 = t; + const byte *s = (byte *)q; + const byte *et = t0 + count; + + while(t < et) { + if(*t != *s) + return t - t0; + t++; + s++; + } + + return count; +} + #endif #if defined(CPU_LE) diff --git a/uppsrc/Core/src.tpp/Mem_en-us.tpp b/uppsrc/Core/src.tpp/Mem_en-us.tpp index 9d8065e43..a9596d59d 100644 --- a/uppsrc/Core/src.tpp/Mem_en-us.tpp +++ b/uppsrc/Core/src.tpp/Mem_en-us.tpp @@ -105,6 +105,16 @@ onst]_[@(0.0.255) void]_`*[*@3 p], [@(0.0.255) const]_[@(0.0.255) void]_`*[*@3 q about the same speed. Provided mostly for completeness.&] [s3;%% &] [s4; &] +[s5;:Upp`:`:memeq8len`(const void`*`,const void`*`,size`_t`): size`_t +[* memeq8len]([@(0.0.255) const] [@(0.0.255) void] [@(0.0.255) `*][*@3 p], +[@(0.0.255) const] [@(0.0.255) void] [@(0.0.255) `*][*@3 q], size`_t +[*@3 count])&] +[s2;%% Returns the [/ position] such that [/ position ]< [*@3 count ][@(0.0.255) `&`&] +[*@3 p][@(0.0.255) `[][/ position][@(0.0.255) `] !`=] [*@3 q][@(0.0.255) `[][/ position][@(0.0.255) `] +]. If no such position exists, returns [*@3 count]. In other words +returns count of bytes at p and q that are equal.&] +[s3; &] +[s4; &] [s5;:Upp`:`:memhash`(const void`*`,size`_t`): [_^Upp`:`:hash`_t^ hash`_t]_[* memhash]([@(0.0.255) c onst]_[@(0.0.255) void]_`*[*@3 ptr], [_^size`_t^ size`_t]_[*@3 size])&] [s2;%% Computes a non`-cryptographic hash of memory block. &]