mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
Core: memcnt[8,16,32]
This commit is contained in:
parent
3f37110ce6
commit
72c7cda907
4 changed files with 158 additions and 1 deletions
64
autotest/memcnt/memcnt.cpp
Normal file
64
autotest/memcnt/memcnt.cpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#include <Core/Core.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
template <class T>
|
||||
size_t memcnt_t_e(const T *p, const T& value, size_t sz)
|
||||
{
|
||||
const T *e = p + sz;
|
||||
size_t n = 0;
|
||||
while(p < e)
|
||||
n += (*p++ == value);
|
||||
return n;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
size_t memcnt_t(const T *data, dword value, size_t sz)
|
||||
{
|
||||
if(sizeof(T) == 1)
|
||||
return memcnt8(data, value, sz);
|
||||
if(sizeof(T) == 2)
|
||||
return memcnt16(data, value, sz);
|
||||
if(sizeof(T) == 4)
|
||||
return memcnt32(data, value, sz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Test(int mul) {
|
||||
const int N = 255533;
|
||||
T data[N];
|
||||
for(int i = 0; i < N; i++)
|
||||
data[i] = Random(256) * mul;
|
||||
for(int value = 0; value < 256; value++) {
|
||||
T x = mul * value;
|
||||
DLOG((int)x << " " << memcnt_t(data, x, N) << " " << memcnt_t_e(data, x, N));
|
||||
ASSERT(memcnt_t(data, x, N) == memcnt_t_e(data, x, N));
|
||||
}
|
||||
}
|
||||
|
||||
CONSOLE_APP_MAIN
|
||||
{
|
||||
StdLogSetup(LOG_COUT|LOG_FILE);
|
||||
|
||||
#if 0
|
||||
word h[] = { 0, 0, 0, 4, 4, 0, 0, 4,
|
||||
0, 4, 0 };
|
||||
|
||||
int cnt = memcnt16(h, 4, __countof(h));
|
||||
DDUMP(cnt);
|
||||
cnt = memcnt_t(h, 4, __countof(h));
|
||||
DDUMP(cnt);
|
||||
cnt = memcnt16(h, 0, __countof(h));
|
||||
DDUMP(cnt);
|
||||
|
||||
Test<word>(253);
|
||||
return;
|
||||
#endif
|
||||
|
||||
Test<byte>(1);
|
||||
Test<word>(253);
|
||||
Test<dword>(70000);
|
||||
|
||||
DLOG("========== OK");
|
||||
}
|
||||
9
autotest/memcnt/memcnt.upp
Normal file
9
autotest/memcnt/memcnt.upp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
uses
|
||||
Core;
|
||||
|
||||
file
|
||||
memcnt.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "";
|
||||
|
||||
|
|
@ -739,3 +739,75 @@ bool memeq_t(const T *p, const T *q, size_t count)
|
|||
}
|
||||
|
||||
hash_t memhash(const void *ptr, size_t count);
|
||||
|
||||
inline
|
||||
size_t memcnt8(const void *s, dword value, size_t sz)
|
||||
{
|
||||
const byte *p = (byte *)s;
|
||||
const byte *e = p + sz;
|
||||
size_t n = 0;
|
||||
|
||||
#ifdef CPU_SIMD
|
||||
const byte *e16 = p + (sz & ~15); // Process in 16-byte chunks
|
||||
if(p < e16) {
|
||||
i8x16 value16 = i8all(value);
|
||||
do {
|
||||
n += CountTrue(i8x16(p) == value16);
|
||||
p += 16;
|
||||
}
|
||||
while(p < e16);
|
||||
}
|
||||
#endif
|
||||
|
||||
while(p < e) // Process remaining bytes (less than 16)
|
||||
n += (*p++ == value);
|
||||
return n;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t memcnt16(const void *s, dword value, size_t sz)
|
||||
{
|
||||
const word *p = (word *)s;
|
||||
const word *e = p + sz;
|
||||
size_t n = 0;
|
||||
|
||||
#ifdef CPU_SIMD
|
||||
const word *e16 = p + (sz & ~7); // Process in 16-byte chunks
|
||||
if(p < e16) {
|
||||
i16x8 value8 = i16all(value);
|
||||
do {
|
||||
n += CountTrue(i16x8(p) == value8);
|
||||
p += 8;
|
||||
}
|
||||
while(p < e16);
|
||||
}
|
||||
#endif
|
||||
|
||||
while(p < e) // Process remaining bytes (less than 16)
|
||||
n += (*p++ == value);
|
||||
return n;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t memcnt32(const void *s, dword value, size_t sz)
|
||||
{
|
||||
const dword *p = (dword *)s;
|
||||
const dword *e = p + sz;
|
||||
size_t n = 0;
|
||||
|
||||
#ifdef CPU_SIMD
|
||||
const dword *e16 = p + (sz & ~3); // Process in 16-byte chunks
|
||||
if(p < e16) {
|
||||
i32x4 value4 = i32all(value);
|
||||
do {
|
||||
n += CountTrue(i32x4(p) == value4);
|
||||
p += 4;
|
||||
}
|
||||
while(p < e16);
|
||||
}
|
||||
#endif
|
||||
|
||||
while(p < e) // Process remaining bytes (less than 16)
|
||||
n += (*p++ == value);
|
||||
return n;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,12 +113,24 @@ about the same speed. Provided mostly for completeness.&]
|
|||
[*@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`:`:memcnt8`(const void`*`,dword`,size`_t`): size`_t [* memcnt8]([@(0.0.255) cons
|
||||
t] [@(0.0.255) void] [@(0.0.255) `*][*@3 s], dword [*@3 value], size`_t
|
||||
[*@3 sz])&]
|
||||
[s5;:Upp`:`:memcnt16`(const void`*`,dword`,size`_t`): size`_t [* memcnt16]([@(0.0.255) co
|
||||
nst] [@(0.0.255) void] [@(0.0.255) `*][*@3 s], dword [*@3 value], size`_t
|
||||
[*@3 sz])&]
|
||||
[s5;:Upp`:`:memcnt32`(const void`*`,dword`,size`_t`): size`_t [* memcnt32]([@(0.0.255) co
|
||||
nst] [@(0.0.255) void] [@(0.0.255) `*][*@3 s], dword [*@3 value], size`_t
|
||||
[*@3 sz])&]
|
||||
[s2;%% Counts the number of items equal to [%-*@3 value].&]
|
||||
[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. &]
|
||||
[s3;%% &]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:FoldHash`(Upp`:`:qword`): [_^Upp`:`:dword^ dword]_[* FoldHash]([_^Upp`:`:qword^ q
|
||||
word]_[*@3 h])&]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue