www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - memcpy in D

reply "Tyro[17]" <ridimz yahoo.com> writes:
What is the equivalent of memcpy

module memcopy;

immutable ADDRESS_BUS_SIZE = 20; // 2^20 address bus
byte memory[1 << ADDRESS_BUS_SIZE];

void main()
{
	ushort val = 12345;

	for (int i = 0x12340; i < 0x1234A; i+= 2) {
		memcpy (&memory[i], &val, sizeof val); // D way???
		val++;
	}

	for (int i = 0x12340; i < 0x1234A; i+= 2) {
		memcpy (&val, &memory[i], sizeof val); // D way???
		writefln("%x", val);
	}
}

achieved in D? I am trying not to use memcpy or any function from the C API.

Thanks,

-- 

Andrew Edwards
--------------------
http://www.akeron.co
auto getAddress() {
     string location = " ", period = ".";
     return ("info" ~ location ~ "afidem" ~ period ~ "org");
}
Jun 30 2013
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 30 June 2013 at 11:07:24 UTC, Tyro[17] wrote:
 What is the equivalent of memcpy

 module memcopy;

 immutable ADDRESS_BUS_SIZE = 20; // 2^20 address bus
 byte memory[1 << ADDRESS_BUS_SIZE];

 void main()
 {
 	ushort val = 12345;

 	for (int i = 0x12340; i < 0x1234A; i+= 2) {
 		memcpy (&memory[i], &val, sizeof val); // D way???
 		val++;
 	}

 	for (int i = 0x12340; i < 0x1234A; i+= 2) {
 		memcpy (&val, &memory[i], sizeof val); // D way???
 		writefln("%x", val);
 	}
 }

 achieved in D? I am trying not to use memcpy or any function 
 from the C API.

 Thanks,
You could do it with ubyte a vector copy: -------- void * dmemcpy ( void * destination, const void * source, size_t num ) pure nothrow { (cast(ubyte*)destination)[0 .. num][]=(cast(const(ubyte)*)source)[0 .. num]; return destination; } -------- Doing it this way has the advantage of being CTFE-able, and (potentially) faster, as everything I ever read about D's memcpy is that it is slow.
Jun 30 2013
next sibling parent reply David <d dav1d.de> writes:
 Doing it this way has the advantage of being CTFE-able, and
 (potentially) faster, as everything I ever read about D's memcpy is that
 it is slow.
On Windows? Doesn't memcpy use libc memcpy on Linux?
Jun 30 2013
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
30-Jun-2013 15:47, David пишет:
 Doing it this way has the advantage of being CTFE-able, and
 (potentially) faster, as everything I ever read about D's memcpy is that
 it is slow.
On Windows? Doesn't memcpy use libc memcpy on Linux?
Yup on Linux is pretty darn fast just as is with C/C++. It's the _same_ GLIBC. -- Dmitry Olshansky
Jun 30 2013
prev sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 30 June 2013 at 11:47:49 UTC, David wrote:
 Doing it this way has the advantage of being CTFE-able, and
 (potentially) faster, as everything I ever read about D's 
 memcpy is that
 it is slow.
On Windows? Doesn't memcpy use libc memcpy on Linux?
I honestly have no idea, I'm just repeating what I heard, which could very well be rumors. It could be an overhead to making the actual call? I have no idea. But I *do* know it ain't CTFE. dmemcpy is.
Jun 30 2013
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 30 Jun 2013 07:40:31 -0400, monarch_dodra <monarchdodra gmail.com>  
wrote:

 On Sunday, 30 June 2013 at 11:07:24 UTC, Tyro[17] wrote:
 What is the equivalent of memcpy

 module memcopy;

 immutable ADDRESS_BUS_SIZE = 20; // 2^20 address bus
 byte memory[1 << ADDRESS_BUS_SIZE];

 void main()
 {
 	ushort val = 12345;

 	for (int i = 0x12340; i < 0x1234A; i+= 2) {
 		memcpy (&memory[i], &val, sizeof val); // D way???
 		val++;
 	}

 	for (int i = 0x12340; i < 0x1234A; i+= 2) {
 		memcpy (&val, &memory[i], sizeof val); // D way???
 		writefln("%x", val);
 	}
 }

 achieved in D? I am trying not to use memcpy or any function from the C  
 API.

 Thanks,
You could do it with ubyte a vector copy: -------- void * dmemcpy ( void * destination, const void * source, size_t num ) pure nothrow { (cast(ubyte*)destination)[0 .. num][]=(cast(const(ubyte)*)source)[0 .. num]; return destination; } -------- Doing it this way has the advantage of being CTFE-able, and (potentially) faster, as everything I ever read about D's memcpy is that it is slow.
D's memcpy is C's memcpy. So I don't know why it would be slower. Note that with DMD on windows 32 bit, it uses DMC, which may vary in performance from MSVC memcpy. Using vector assignment may or may not use memcpy. It may be the slower one, but I don't know. If it can be inlined, it certainly would be faster for small values. -Steve
Jun 30 2013
prev sibling next sibling parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Sun, 30 Jun 2013 07:07:23 -0400
schrieb "Tyro[17]" <ridimz yahoo.com>:

 What is the equivalent of memcpy
 
 module memcopy;
 
 immutable ADDRESS_BUS_SIZE = 20; // 2^20 address bus
 byte memory[1 << ADDRESS_BUS_SIZE];
 
 void main()
 {
 	ushort val = 12345;
 
 	for (int i = 0x12340; i < 0x1234A; i+= 2) {
 		memcpy (&memory[i], &val, sizeof val); // D way???
 		val++;
 	}
 
 	for (int i = 0x12340; i < 0x1234A; i+= 2) {
 		memcpy (&val, &memory[i], sizeof val); // D way???
 		writefln("%x", val);
 	}
 }
 
 achieved in D? I am trying not to use memcpy or any function from the C API.
 
 Thanks,
While they are in the C stdlib, there is nothing really C specific about them. Just use them. In your case GCC would recognize a memcpy call with known length (2 bytes) and inline the call. From there I guess the optimizer can figure something out that runs fast. That said how about this in D: ushort val = 12345; for (int i = 0x12340; i < 0x1234A; i+= 2) *cast(ushort*) &memory[i] = val++; for (int i = 0x12340; i < 0x1234A; i+= 2) { val = *cast(ushort*) &memory[i] writefln("%04x", val); } -- Marco
Jun 30 2013
parent Marco Leise <Marco.Leise gmx.de> writes:
... or alternatively:

// Simple integers can be compile-time literals (i.e. C's #define)
enum ADDRESS_BUS_SIZE = 20; // 2^20 address bus
// In D it is more ideomatic to put the array length first.
// For example this wouldn't work: byte x, *y, memory[1 << ADDRESS_BUS_SIZE];
byte[1 << ADDRESS_BUS_SIZE] memory;

void main()
{
	ushort val = 12345;
	ushort* base = cast(ushort*) &memory[0x12340];

	foreach (i; 0 .. 5)
		base[i] = val++;
	
	foreach (i; 0 .. 5)
		writefln("%04x", base[i]);
}

-- 
Marco
Jun 30 2013
prev sibling parent reply "Tyro[17]" <ridimz yahoo.com> writes:
I'd just like to say thanks for your suggestions and quite complete 
solutions. I particularly liked the alternate implementation presented 
by Marco. I must admit that I did not understand what was happening at 
first.

So just to confirm my understanding: Because the address at memory is 
casted to ushort* in defining base, every iteration of the foreach loop 
advances the pointer two bytes into the array?

Thanks,
Andrew
Jul 01 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/01/2013 03:23 PM, Tyro[17] wrote:

 So just to confirm my understanding: Because the address at memory is
 casted to ushort* in defining base, every iteration of the foreach loop
 advances the pointer two bytes into the array?
Yes. The incerement operator on a pointer advances the pointer to point at the next element. Automatic! :) Same with arithmetic operations. (ptr + 1) is the address value that points at the next element. Ali
Jul 01 2013