Undefined problem

F

felixnielsen

What i have is not even a real problem, but i hope someone can help
anyway, but first a piece of code_

@code start
const unsigned short Size = 2; // 2^N
std::bitset<Size*Size*Size> YZ;
std::bitset<Size*Size*Size> XZ;
std::bitset<Size*Size*Size> XY;
std::bitset<Size*Size*Size> V;
union {
struct {
unsigned z:8;
unsigned y:8;
unsigned x:8;
};
unsigned id:24;
} coords;
@code end

Some explanation migth be in place.

The var "Size" will allways be the value 2^N {1,2,4,8,16,32,64, ect.} i
have yet to find a way to it is, because when i use the obious solution
(pow()) the compiler wont accept the bitsets being initialised by the
us of "Size", wery weird.

The bitsets are just bitset, no need to explain what they are for.

the union is kinda obious, its as way to bot have the x,y,z coords by
them self and have a bombined identifier to access the right bit of the
bitsets.
Now the tricky part:
I order for this to work, the vars in the union have to alocate a
specific amount of memory.
I guess its easyly explained with some code:

@code start
union {
struct {
unsigned z:log2(Size);
unsigned y:log2(Size);
unsigned x:log2(Size);
};
unsigned id:log2(Size)*3;
} coords;
@code end

This ofcourse doesnt work, but you should understand my problem by now.

Regards
Zacariaz
 
K

Kai-Uwe Bux

What i have is not even a real problem, but i hope someone can help
anyway, but first a piece of code_

@code start
const unsigned short Size = 2; // 2^N
std::bitset<Size*Size*Size> YZ;
std::bitset<Size*Size*Size> XZ;
std::bitset<Size*Size*Size> XY;
std::bitset<Size*Size*Size> V;
union {
struct {
unsigned z:8;
unsigned y:8;
unsigned x:8;
};
unsigned id:24;
} coords;
@code end

Some explanation migth be in place.

The var "Size" will allways be the value 2^N {1,2,4,8,16,32,64, ect.} i
have yet to find a way to it is, because when i use the obious solution
(pow()) the compiler wont accept the bitsets being initialised by the
us of "Size", wery weird.

The bitsets are just bitset, no need to explain what they are for.

the union is kinda obious, its as way to bot have the x,y,z coords by
them self and have a bombined identifier to access the right bit of the
bitsets.
Now the tricky part:
I order for this to work, the vars in the union have to alocate a
specific amount of memory.
I guess its easyly explained with some code:

@code start
union {
struct {
unsigned z:log2(Size);
unsigned y:log2(Size);
unsigned x:log2(Size);
};
unsigned id:log2(Size)*3;
} coords;
@code end

This ofcourse doesnt work, but you should understand my problem by now.


What about a template:


#include <bitset>

template < unsigned int SizeLog >
struct Labyrinth3D {

static unsigned int const size_log = SizeLog;
static unsigned int const size = 2 << size_log;

std::bitset< size*size*size > yz;
std::bitset< size*size*size > xz;
std::bitset< size*size*size > xy;
std::bitset< size*size*size > v;

union {

struct {

unsigned x:size_log;
unsigned y:size_log;
unsigned z:size_log;

} dummy;

unsigned id:3*size_log;

} coords;

}; // Labyrinth3D<>



Best

Kai-Uwe Bux
 
B

Bo Persson

What i have is not even a real problem, but i hope someone can help
anyway, but first a piece of code_

@code start
const unsigned short Size = 2; // 2^N
std::bitset<Size*Size*Size> YZ;
std::bitset<Size*Size*Size> XZ;
std::bitset<Size*Size*Size> XY;
std::bitset<Size*Size*Size> V;
union {
struct {
unsigned z:8;
unsigned y:8;
unsigned x:8;
};
unsigned id:24;
} coords;
@code end

This is all very implementation defined, meaning totally non-portable.

First of all, storing into one member of a union, and then accessing
another member is not allowed! If you store one member, that member is
active and none of the others.

In practice, it just might work, but there are no guarantees what so
ever!


Next, the order of x, y, and z in your struct is totally
implementation defined, as is the possible padding between them.

Having a 24 bit unsigned is also *highly* unusual. :)

There are no guarantees than an unsigned has more than 16 bits. It
might just as well be 32, or 36, or 60, or 64, or whatever.


So, if you don't code for a specific platform, with a specific
compiler version, and some specific compiler options, this will just
not work (except sometimes, by chance). :)

What exactly are you trying to do here??


Bo Persson
 
F

felixnielsen

Thanks for the answer, ill try and understand it later. For now i have
something that really enoys me.
This compiles fine:
@code start
const unsigned short Size = 2;
unsigned short Log2 = 1;
struct something {
unsigned x:Log2;
};
@code end

This dont:
@code start
const unsigned short Size = 2; // 2^N
unsigned short Log2 = static_cast<const unsigned short>(log2(Size));
struct something {
unsigned x:Log2;
};
@code end
Compiler error: `Log2' cannot appear in a constant-expression

Why why why!!!???¿

Dont get me wrong, im very thankfull for the code above, however i am
still very unexoerienced and i would like to take a little step at the
time.
Stuff i dont understand:
tamplate<>
static
sizelog and SizeLog is some how misleading/they have no value
and whats about the moving bits stuff?

Regards
Zacariaz
 
F

felixnielsen

Bo Persson skrev:
This is all very implementation defined, meaning totally non-portable.

First of all, storing into one member of a union, and then accessing
another member is not allowed! If you store one member, that member is
active and none of the others.

In practice, it just might work, but there are no guarantees what so
ever!

I works on my computer/compiler and that good enough for a start.
Next, the order of x, y, and z in your struct is totally
implementation defined, as is the possible padding between them.

the order is not important as for the padding thats the reason for the
x,y,z:8;
I know this might not be the best way, but it work and i understand it.
Having a 24 bit unsigned is also *highly* unusual. :)

I know, but again, it work, and by the way, it has changeed to an
unsigned long long by now ;-)
There are no guarantees than an unsigned has more than 16 bits. It
might just as well be 32, or 36, or 60, or 64, or whatever.

Thas one of my bigger problems in this project as im playing around
with lots of data, that the reason for the bitsets, but the bitset it
allso a tad enoying to work with
So, if you don't code for a specific platform, with a specific
compiler version, and some specific compiler options, this will just
not work (except sometimes, by chance). :)

Again, i have had that in mind, but i am a total n00b and i cant do
better right now and understand it at the same time, sure i can post my
code here and let you do all the work, but then i aint learning
anything ;-)
What exactly are you trying to do here??

Im building a 3d maze. It a project thats not to easy and not to hard,
there is posibilitys for expansion ect. so i actually think it a great
project for someone like me.
I can easily emagine doing this code, then a GUI, then have a mouse or
two running around in it, screensaver like, the building at virtual net
of neurons ;-)

Anyway you get the point

Regards
Zacariaz
 
N

Neil Cerutti

Thanks for the answer, ill try and understand it later. For now i have
something that really enoys me.
This compiles fine:
@code start
const unsigned short Size = 2;
unsigned short Log2 = 1;
struct something {
unsigned x:Log2;
};
@code end

This dont:
@code start
const unsigned short Size = 2; // 2^N
unsigned short Log2 = static_cast<const unsigned short>(log2(Size));
struct something {
unsigned x:Log2;
};
@code end
Compiler error: `Log2' cannot appear in a constant-expression

Why why why!!!???¿

Since Log2 was the result of a function call, the value of Log2 cannot
be known until runtime, so you can't declare a bitset chunk of that
size.

You can use some template meta-programming to get the number you're
after as a compile-time constant, but unfortunately I'm not a template
meta-programmer so I can't help you with the code.
 
B

Bo Persson

Bo Persson skrev:


I works on my computer/compiler and that good enough for a start.

That's actually bad, for a start. :)

Things that seem to work are the worst, because they will just work,
and work, and work. Until one day when you find someone that is
actually willing to pay you a lot of money for your program. At that
exact moment, it will suddenly stop working!
the order is not important as for the padding thats the reason for
the
x,y,z:8;
I know this might not be the best way, but it work and i understand
it.

The problem I see is that you might get your 24 bits packed in the id,
but you can't tell in what order. To me, that makes the id pretty
useless.
I know, but again, it work, and by the way, it has changeed to an
unsigned long long by now ;-)

Is a surprise that unsigned long long is also to a standard type? :)

You are using another compiler specific extension. Change the compile
options to strict_ansi / disable_extensions, and it will disappear
again!
Thas one of my bigger problems in this project as im playing around
with lots of data, that the reason for the bitsets, but the bitset
it
allso a tad enoying to work with

On my machine, you can store hundreds of millions of ints in memory
without any problems. My advice is to not bother optimizing this until
you get there. If you don't have a *very* specific reason to chose
something else, a plain int will do most of the time. At least until
you find the good reason for another choice.

Packing and unpacking bits will cost you execution time instead of
memory. Are you sure that you have more time than space? :)
Im building a 3d maze. It a project thats not to easy and not to
hard,
there is posibilitys for expansion ect. so i actually think it a
great
project for someone like me.
I can easily emagine doing this code, then a GUI, then have a mouse
or
two running around in it, screensaver like, the building at virtual
net
of neurons ;-)

Anyway you get the point

Yes, sounds like a lot of fun. And for quite some time.


Bo Persson
 
B

Bo Persson

Bo Persson said:
Is a surprise that unsigned long long is also to a standard type?
:)

"Is it a surprise that unsigned long long is also not a standard
type?".


Out shopping for a new keyboard...

Bo Persson
 
F

felixnielsen

K, listen up, i thought i had explained that im pretty inexperinced and
that for a start i just need something that works.
However, if you are actually ready to help instead of just critisize
and offer no real solutions, here the code i have right now, it work om
my computer and compiles fine in bloodshed dev-c++.

@code start
#include <iostream>
#include <vector>
#include <bitset>
#include <ctime>
const unsigned short Size = 4; // 2^N
const unsigned short Log2 = 2; // N, log2(Size)
std::bitset<Size*Size*Size> YZ;
std::bitset<Size*Size*Size> XZ;
std::bitset<Size*Size*Size> XY;
std::bitset<Size*Size*Size> V;
struct Stack {
unsigned short z:Log2;
unsigned short y:Log2;
unsigned short x:Log2;
bool dir[6];
};
struct {
union {
struct {
unsigned short z:Log2;
unsigned short y:Log2;
unsigned short x:Log2;
};
unsigned long long id:Log2*3;
};
} pos;
short rand_int(short i) {
return rand() % i;
}
void new_grid() {
std::vector<Stack> stack(1);
bool loop = true;
YZ.set();
XZ.set();
XY.set();
V.set();
V.flip();
srand(time(0));
pos.x = rand_int(6);
pos.y = rand_int(6);
pos.z = rand_int(6);
V[pos.id] = 1;
stack.back().x = pos.x;
stack.back().y = pos.y;
stack.back().z = pos.z;
stack.resize(stack.size()+1);
while (stack.size() > 0) {
for (int choice = rand_int(6), loop = true;
loop == true;
choice = rand_int(6)) {
stack.back().dir[choice] = 1;
if (choice == 0) {
pos.x++;
if (V[pos.id] == 1) pos.x--;
else {
loop = false;
pos.x--;
YZ[pos.id] = 0;
pos.x++;
}
}
else if (choice == 1) {
pos.y++;
if (V[pos.id] == 1) pos.y--;
else {
loop = false;
pos.y--;
XZ[pos.id] = 0;
pos.y++;
}
}
else if (choice == 2) {
pos.z++;
if (V[pos.id] == 1) pos.z--;
else {
loop = false;
pos.z--;
XY[pos.id] = 0;
pos.z++;
}
}
else if (choice == 3) {
pos.x--;
if (V[pos.id] == 1) pos.x++;
else {
loop = false;
YZ[pos.id] = 0;
}
}
else if (choice == 4) {
pos.y--;
if (V[pos.id] == 1) pos.y++;
else {
loop = false;
XZ[pos.id] = 0;
}
}
else if (choice == 5) {
pos.z--;
if (V[pos.id] == 1) pos.z++;
else {
loop = false;
XY[pos.id] = 0;
}
}
if (loop == true &&
stack.back().dir[0]+stack.back().dir[1]+stack.back().dir[2]+
stack.back().dir[3]+stack.back().dir[4]+stack.back().dir[5]
== 6) {
loop = false;
stack.pop_back();
pos.x = stack.back().x;
pos.y = stack.back().y;
pos.z = stack.back().z;
}
else if (loop == false) {
V[pos.id] = 1;
stack.back().x = pos.x;
stack.back().y = pos.y;
stack.back().z = pos.z;
stack.resize(stack.size()+1);
}
}
//// temp progress overview ///////////
/**/ system("cls"); /**/
/**/ std::cout << YZ << std::endl; /**/
/**/ std::cout << XZ << std::endl; /**/
/**/ std::cout << XY << std::endl; /**/
/**/ std::cout << V; /**/
///////////////////////////////////////
}
}

int main() {
while (0==0)
new_grid();
}
@code end

You might wanna take a look on some of those links:
http://groups.google.dk/group/comp....c03?q=bitset+in+union&rnum=1#184c0945c6c25c03
http://groups.google.dk/group/comp....3d47669be?q=labyrinth&rnum=2#48702973d47669be

Not to misunderstand me, im glad that you take the time to critisize
me, but crititism doesnt do the trick by it self.

Regards
Zacariaz
 
B

Bo Persson

K, listen up, i thought i had explained that im pretty inexperinced
and
that for a start i just need something that works.

Sure, but wouldn't it be better to work for a reason, not just seem to
work? :)
However, if you are actually ready to help instead of just critisize
and offer no real solutions, here the code i have right now, it work
om
my computer and compiles fine in bloodshed dev-c++.

I'm not trying to write the code, you are. :)

As I'm not sure what you intend to do, I'm only offering some advice
on what not to do, from the parts I've seen so far.

If you don't like some of it, you are free to ignore my opinion. It's
just an opinon, right?

@code start
#include <iostream>
#include <vector>
#include <bitset>
#include <ctime>
const unsigned short Size = 4; // 2^N
const unsigned short Log2 = 2; // N, log2(Size)
std::bitset<Size*Size*Size> YZ;
std::bitset<Size*Size*Size> XZ;
std::bitset<Size*Size*Size> XY;
std::bitset<Size*Size*Size> V;
struct Stack {
unsigned short z:Log2;
unsigned short y:Log2;
unsigned short x:Log2;
bool dir[6];
};
struct {
union {
struct {
unsigned short z:Log2;
unsigned short y:Log2;
unsigned short x:Log2;
};
unsigned long long id:Log2*3;
};
} pos;
short rand_int(short i) {
return rand() % i;
}
void new_grid() {
std::vector<Stack> stack(1);
bool loop = true;
YZ.set();
XZ.set();
XY.set();
V.set();
V.flip();

This will set all bits of V, and then flip them all to zero. That's
what they were originally.
srand(time(0));
pos.x = rand_int(6);
pos.y = rand_int(6);
pos.z = rand_int(6);
V[pos.id] = 1;

Here you set the id member of the union to 1. That will loose the
contents of x, y, and z, as they cannot all exist at the same time.
stack.back().x = pos.x;
stack.back().y = pos.y;
stack.back().z = pos.z;
stack.resize(stack.size()+1);

This is a rather unusual way to use a std::vector. Much more common is
to create a data element of the type contained in the vector, and then
do a

stack.push_back(element);

This extends the vector by one position, and adds the element to it,
at the same time. This way you will not have an empty, unused element
at the end of the vector.
while (stack.size() > 0) {
for (int choice = rand_int(6), loop = true;
loop == true;
choice = rand_int(6)) {
stack.back().dir[choice] = 1;
if (choice == 0) {
pos.x++;
if (V[pos.id] == 1) pos.x--;
else {
loop = false;
pos.x--;
YZ[pos.id] = 0;
pos.x++;
}
}
else if (choice == 1) {
pos.y++;
if (V[pos.id] == 1) pos.y--;
else {
loop = false;
pos.y--;
XZ[pos.id] = 0;
pos.y++;
}
}
else if (choice == 2) {
pos.z++;
if (V[pos.id] == 1) pos.z--;
else {
loop = false;
pos.z--;
XY[pos.id] = 0;
pos.z++;
}
}
else if (choice == 3) {
pos.x--;
if (V[pos.id] == 1) pos.x++;
else {
loop = false;
YZ[pos.id] = 0;
}
}
else if (choice == 4) {
pos.y--;
if (V[pos.id] == 1) pos.y++;
else {
loop = false;
XZ[pos.id] = 0;
}
}
else if (choice == 5) {
pos.z--;
if (V[pos.id] == 1) pos.z++;
else {
loop = false;
XY[pos.id] = 0;
}
}
if (loop == true &&
stack.back().dir[0]+stack.back().dir[1]+stack.back().dir[2]+
stack.back().dir[3]+stack.back().dir[4]+stack.back().dir[5]
== 6) {
loop = false;
stack.pop_back();
pos.x = stack.back().x;
pos.y = stack.back().y;
pos.z = stack.back().z;
}
else if (loop == false) {
V[pos.id] = 1;
stack.back().x = pos.x;
stack.back().y = pos.y;
stack.back().z = pos.z;
stack.resize(stack.size()+1);
}
}
//// temp progress overview ///////////
/**/ system("cls"); /**/
/**/ std::cout << YZ << std::endl; /**/
/**/ std::cout << XZ << std::endl; /**/
/**/ std::cout << XY << std::endl; /**/
/**/ std::cout << V; /**/
///////////////////////////////////////
}
}

int main() {
while (0==0)
new_grid();
}
@code end

You might wanna take a look on some of those links:
http://groups.google.dk/group/comp....c03?q=bitset+in+union&rnum=1#184c0945c6c25c03
http://groups.google.dk/group/comp....3d47669be?q=labyrinth&rnum=2#48702973d47669be

Not to misunderstand me, im glad that you take the time to critisize
me, but crititism doesnt do the trick by it self.

See it as advice. :)

You are trying very hard to squeeze the data into a small number of
bits. This is good only if you are really short on bits. A modern PC
has billions of bits, just waste a few! :)

You are right that you should first try to get the program to run.
Only if then see that it runs too slow, or runs out of memory, should
you start to consider how to optimize this.

If you do run out of memory, you can then consider optimizing you data
structures. Or buy more memory, it is really cheap these days!

Normally, you will never have to do any of this.


Very experienced programmers sometimes can see that some resources
might be scarce, and try to optimize this from the start. Often they
are wrong!


Bo Persson
 
B

Bo Persson

Bo Persson said:
V[pos.id] = 1;

Here you set the id member of the union to 1. That will loose the
contents of x, y, and z, as they cannot all exist at the same time.

No, you don't!

It of course sets a bit in V, not in pos.id.

Sorry!


Bo Persson
 
F

felixnielsen

Bo Persson skrev:
K, listen up, i thought i had explained that im pretty inexperinced
and
that for a start i just need something that works.

Sure, but wouldn't it be better to work for a reason, not just seem to
work? :)
However, if you are actually ready to help instead of just critisize
and offer no real solutions, here the code i have right now, it work
om
my computer and compiles fine in bloodshed dev-c++.

I'm not trying to write the code, you are. :)

As I'm not sure what you intend to do, I'm only offering some advice
on what not to do, from the parts I've seen so far.

If you don't like some of it, you are free to ignore my opinion. It's
just an opinon, right?

@code start
#include <iostream>
#include <vector>
#include <bitset>
#include <ctime>
const unsigned short Size = 4; // 2^N
const unsigned short Log2 = 2; // N, log2(Size)
std::bitset<Size*Size*Size> YZ;
std::bitset<Size*Size*Size> XZ;
std::bitset<Size*Size*Size> XY;
std::bitset<Size*Size*Size> V;
struct Stack {
unsigned short z:Log2;
unsigned short y:Log2;
unsigned short x:Log2;
bool dir[6];
};
struct {
union {
struct {
unsigned short z:Log2;
unsigned short y:Log2;
unsigned short x:Log2;
};
unsigned long long id:Log2*3;
};
} pos;
short rand_int(short i) {
return rand() % i;
}
void new_grid() {
std::vector<Stack> stack(1);
bool loop = true;
YZ.set();
XZ.set();
XY.set();
V.set();
V.flip();

This will set all bits of V, and then flip them all to zero. That's
what they were originally.
srand(time(0));
pos.x = rand_int(6);
pos.y = rand_int(6);
pos.z = rand_int(6);
V[pos.id] = 1;

Here you set the id member of the union to 1. That will loose the
contents of x, y, and z, as they cannot all exist at the same time.
stack.back().x = pos.x;
stack.back().y = pos.y;
stack.back().z = pos.z;
stack.resize(stack.size()+1);

This is a rather unusual way to use a std::vector. Much more common is
to create a data element of the type contained in the vector, and then
do a

stack.push_back(element);

This extends the vector by one position, and adds the element to it,
at the same time. This way you will not have an empty, unused element
at the end of the vector.

im very much aware of that, but i had some problem whit that, so i
tryed this instead and it seems to work.
while (stack.size() > 0) {
for (int choice = rand_int(6), loop = true;
loop == true;
choice = rand_int(6)) {
stack.back().dir[choice] = 1;
if (choice == 0) {
pos.x++;
if (V[pos.id] == 1) pos.x--;
else {
loop = false;
pos.x--;
YZ[pos.id] = 0;
pos.x++;
}
}
else if (choice == 1) {
pos.y++;
if (V[pos.id] == 1) pos.y--;
else {
loop = false;
pos.y--;
XZ[pos.id] = 0;
pos.y++;
}
}
else if (choice == 2) {
pos.z++;
if (V[pos.id] == 1) pos.z--;
else {
loop = false;
pos.z--;
XY[pos.id] = 0;
pos.z++;
}
}
else if (choice == 3) {
pos.x--;
if (V[pos.id] == 1) pos.x++;
else {
loop = false;
YZ[pos.id] = 0;
}
}
else if (choice == 4) {
pos.y--;
if (V[pos.id] == 1) pos.y++;
else {
loop = false;
XZ[pos.id] = 0;
}
}
else if (choice == 5) {
pos.z--;
if (V[pos.id] == 1) pos.z++;
else {
loop = false;
XY[pos.id] = 0;
}
}
if (loop == true &&
stack.back().dir[0]+stack.back().dir[1]+stack.back().dir[2]+
stack.back().dir[3]+stack.back().dir[4]+stack.back().dir[5]
== 6) {
loop = false;
stack.pop_back();
pos.x = stack.back().x;
pos.y = stack.back().y;
pos.z = stack.back().z;
}
else if (loop == false) {
V[pos.id] = 1;
stack.back().x = pos.x;
stack.back().y = pos.y;
stack.back().z = pos.z;
stack.resize(stack.size()+1);
}
}
//// temp progress overview ///////////
/**/ system("cls"); /**/
/**/ std::cout << YZ << std::endl; /**/
/**/ std::cout << XZ << std::endl; /**/
/**/ std::cout << XY << std::endl; /**/
/**/ std::cout << V; /**/
///////////////////////////////////////
}
}

int main() {
while (0==0)
new_grid();
}
@code end

You might wanna take a look on some of those links:
http://groups.google.dk/group/comp....c03?q=bitset+in+union&rnum=1#184c0945c6c25c03
http://groups.google.dk/group/comp....3d47669be?q=labyrinth&rnum=2#48702973d47669be

Not to misunderstand me, im glad that you take the time to critisize
me, but crititism doesnt do the trick by it self.

See it as advice. :)

You are trying very hard to squeeze the data into a small number of
bits. This is good only if you are really short on bits. A modern PC
has billions of bits, just waste a few! :)

Yes i am trying to safe space, but thats not the main reason for the
way im doing it.

@code start
struct {
unsigned b:4;
} a;
a.b = 15;
a.b++;
std::cout << a.b;
@code end
and thats one of the reasons im doing it this way, the other is to make
sure the union stuff works.
You are right that you should first try to get the program to run.
Only if then see that it runs too slow, or runs out of memory, should
you start to consider how to optimize this.

As far as im concerned, software today is full of arrors and stuff that
could easily be avoided if people just did their work right, im not a
proffesionel (yet) but if i ever get that far im definently planing on
doing it right, and i dont mind putting in a little ekstra work.
If you do run out of memory, you can then consider optimizing you data
structures. Or buy more memory, it is really cheap these days!

Normally, you will never have to do any of this.
im not concerned about memory
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,196
Latest member
ScottChare

Latest Threads

Top