Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to quickly replicate a 6-byte unsigned integer into a memory region?

Tags:

c++

c

memory

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?

like image 751
HEKTO Avatar asked Feb 16 '15 22:02

HEKTO


People also ask

Which data type has 6 bytes?

6 bytes is 48 bits, so you could use int64_t which is 64 bits (the clue is in the name).

What is 1 byte unsigned integer?

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.

What is unsigned integer in c++?

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.

Should you use unsigned integers?

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.


1 Answers

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 *)

like image 136
chux - Reinstate Monica Avatar answered Oct 25 '22 13:10

chux - Reinstate Monica