I need to replicate a 6-byte integer value into a memory region, starting with its beginning and as quickly as possible. If such an operation is supported in hardware, I'd like to use it (I'm on x64 processors now, compiler is GCC 4.6.3).
The memset
doesn't suit the job, because it can replicate bytes only. The std::fill
isn't good either, because I even can't define an iterator, jumping between 6 byte-width positions in the memory region.
So, I'd like to have a function:
void myMemset(void* ptr, uint64_t value, uint8_t width, size_t num)
This looks like memset
, but there is an additional argument width
to define how much bytes from the value
to replicate. If something like that could be expressed in C++, that would be even better.
I already know about obvious myMemset
implementation, which would call the memcpy
in loop with last argument (bytes to copy) equal to the width
. Also I know, that I can define a temporary memory region with size 6 * 8 = 48
bytes, fill it up with 6-byte integers and then memcpy
it to the destination area.
Can we do better?
6 bytes is 48 bits, so you could use int64_t which is 64 bits (the clue is in the name).
A 1-byte unsigned integer has a range of 0 to 255. Compare this to the 1-byte signed integer range of -128 to 127. Both can store 256 different values, but signed integers use half of their range for negative numbers, whereas unsigned integers can store positive numbers that are twice as large.
Unsigned int data type in C++ is used to store 32-bit integers. The keyword unsigned is a data type specifier, which only represents non-negative integers i.e. positive numbers and zero.
Unsigned integers are used when we know that the value that we are storing will always be non-negative (zero or positive). Note: it is almost always the case that you could use a regular integer variable in place of an unsigned integer.
Something along @Mark Ransom comment:
Copy 6 bytes, then 6, 12, 24, 48, 96, etc.
void memcpy6(void *dest, const void *src, size_t n /* number of 6 byte blocks */) {
if (n-- == 0) {
return;
}
memcpy(dest, src, 6);
size_t width = 1;
while (n >= width) {
memcpy(&((char *) dest)[width * 6], dest, width * 6);
n -= width;
width <<= 1; // double w
}
if (n > 0) {
memcpy(&((char *) dest)[width * 6], dest, n * 6);
}
}
Optimization: scale n
and width
by 6.
[Edit]
Corrected destination @SchighSchagh
Added cast (char *)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With