Thread overview | ||||||
---|---|---|---|---|---|---|
|
December 20, 2007 Please take a look | ||||
---|---|---|---|---|
| ||||
Attachments: | 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 |
December 21, 2007 Re: Please take a look | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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, > bearophile 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. |
December 22, 2007 Re: Please take a look | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lukas Pinkowski | 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
|
December 22, 2007 Re: Please take a look | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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) |
Copyright © 1999-2021 by the D Language Foundation