digitalmars.D.learn - Please take a look
- bearophile (4/4) Dec 20 2007 I have implemented a struct, with methods, able to manage 24-bit unsigne...
- Lukas Pinkowski (10/24) Dec 21 2007 Taking a look at it, I see, you've done the following:
- bearophile (24/34) Dec 22 2007 I belive you; code similar to that ( (up << 16) | low ) was the first th...
- Lukas Pinkowski (32/34) Dec 22 2007 int main(char[][] args)
I have implemented a struct, with methods, able to manage 24-bit unsigned integers. They are slower than an uint, so they may be useful only in quite uncommon situations when you must save RAM. In the attach you can find a stripped down version where I have removed unittests, speed tests, most Ddoc comments, etc. Now I know some D, but surely there are *lot* of things I know little about still (about memory management, operator overloading, casting, the best way to use the CPU, etc). If you have a bit of free time can you please take a look at that code in attach and tell me if you like it, if you can see some things that can be done in a better way in D, in a faster way, more D-onic, if you can solve some of the little problems you can find in the comments, etc. Bye and thank you, bearophile
Dec 20 2007
bearophile wrote:I have implemented a struct, with methods, able to manage 24-bit unsigned integers. They are slower than an uint, so they may be useful only in quite uncommon situations when you must save RAM. In the attach you can find a stripped down version where I have removed unittests, speed tests, most Ddoc comments, etc. Now I know some D, but surely there are *lot* of things I know little about still (about memory management, operator overloading, casting, the best way to use the CPU, etc). If you have a bit of free time can you please take a look at that code in attach and tell me if you like it, if you can see some things that can be done in a better way in D, in a faster way, more D-onic, if you can solve some of the little problems you can find in the comments, etc. Bye and thank you, bearophileTaking a look at it, I see, you've done the following: uint opCast() { //return (up << 16) | low; // worse? return *(cast(uint*)(cast(void*)this)); } You really should uncomment the first line and remove the second, since uint* is a pointer to a 4-byte type, while your struct holds 3 bytes. Thus dereferencing the uint* will lead to a 4th byte with an arbitrary value and finally to errors.
Dec 21 2007
Lukas Pinkowski:Taking a look at it, I see, you've done the following: uint opCast() { //return (up << 16) | low; // worse? return *(cast(uint*)(cast(void*)this)); } You really should uncomment the first line and remove the second, since uint* is a pointer to a 4-byte type, while your struct holds 3 bytes. Thus dereferencing the uint* will lead to a 4th byte with an arbitrary value and finally to errors.I belive you; code similar to that ( (up << 16) | low ) was the first thing I have written. The funny thing is that (before posting the code on this newsgroup) I have written almost 200 lines of testing code along the code for those 24 bit unsigned integers, and they have failed catching the bug you talk about :-] This other piece of testing code too fails spotting the problem: import std.random, u24; int randInt(int max) { int k, n; n = max + 1; k = cast(int)(n * (rand / (uint.max + 1.0))); return (k == n) ? k - 1 : k; } void main() { Uint24[200_000] arr; assert(arr.sizeof == 200_000*3); rand_seed(10, 0); foreach(ref u; arr) u = randInt(Uint24.max); rand_seed(10, 0); foreach(i, u; arr) assert(u == randInt(Uint24.max)); } Eventually I'll probably put back code like that ( (up << 16) | low ) because I must write safe code (despite being slower) but so far I have failed finding testcases that make that double casting fail :-) Can you show me an example where if shows the bug? Bye and thank you, bearophile
Dec 22 2007
bearophile wrote:Can you show me an example where if shows the bug?int main(char[][] args) { Uint24[4] array; array[0] = 0xffffff; array[1] = 0x000000; array[2] = 0xeeeeee; array[3] = 0xffffff; uint a = array[0].val; uint b = array[1].val; uint c = array[2].val; Stdout.formatln( "{:x}", a ); Stdout.formatln( "{:x}", b ); Stdout.formatln( "{:x}", c ); assert( a == 0x00ffffff ); assert( b == 0x00000000 ); assert( c == 0x00ffffff ); return 0; } Executing gives: ffffff ee000000 ffeeeeee tango.core.Exception.AssertException bug24(62): Assertion failure As you see, taking the value of one array element will return the Uint24 value + the first byte of the next array element (shifted 24bits to the left). (the first is correct because 0xffffff + (0x000000 << 24) is 0x00ffffff)
Dec 22 2007