Page 1 of 1

Strange bug...

Posted: Sat May 12, 2007 10:54 pm
by earlz
I am having a very weird problem with this program I made..

My GetBit will for whatever reason only work properly in the bottom nibble..and I guess the SetBit only works at all in the bottom nibble...it is very weird..
here is my entire code..
unsigned_pint::GetBit, SetBit, and Add is what assumingly have the problems..
I tried to debug it, but GDB crashes when I get to the buggy code, so I have no idea...

here is my complete code(right now it's just one main.cpp file..)

Code: Select all

#include <iostream>
using namespace std;

#define DEFAULT_BITS 64

class unsigned_pint{
	/**Private:**/
	//this doesn't have anything advanced but the digit number...
	unsigned int size;
	unsigned int *bits; //a pointer to an array of unsigned ints...
	public:
	inline unsigned char GetBit(unsigned int bit);
	inline unsigned char SetBit(unsigned int,unsigned char);
	inline unsigned int GetSize();
	unsigned_pint(unsigned int init_size,string init_value);
	unsigned_pint(unsigned int init_size);
	unsigned_pint();
	~unsigned_pint();
	int SetToValue(string source);
	void Add(unsigned_pint* adder);

	unsigned int tmp_get_first_int();
	void tmp_set_first_int(unsigned int value);


};
// the init_size should be in bits..

//we count in BINARY!!
//This is how we add everything!

unsigned int unsigned_pint::tmp_get_first_int(){
	return bits[0];
}

void unsigned_pint::tmp_set_first_int(unsigned int value){
	bits[0]=value;
}


int unsigned_pint::SetToValue(string source){
	cout <<"bah"<< endl;



    return 0;
}

unsigned_pint::unsigned_pint(unsigned int init_size,string init_value){
	size=init_size;
	unsigned int tmp=init_size/sizeof(int);
	if(tmp==0){tmp=4;}
	if((tmp%4)!=0){tmp++;} //round off to the nearest int, with increase
	bits=(unsigned int *)new char[tmp];
	if(bits==NULL){exit(1);}
	SetToValue(init_value);

}

unsigned_pint::unsigned_pint(unsigned int init_size){



}

unsigned_pint::unsigned_pint(){


}

unsigned_pint::~unsigned_pint(){

}

/**for whatever reason, it skips the carry of nibbles,
like 30 and 14 are added as the same number...it makes no sense
**/

void unsigned_pint::Add(unsigned_pint *adder){
	volatile unsigned char carry=0;
	unsigned int current_bit=0;
	unsigned int limit;
	if(adder->GetSize()>this->GetSize()){
		limit=this->GetSize();
	}else{
		limit=adder->GetSize();
	}
	unsigned char tmp;
	for(current_bit=0;current_bit<limit;current_bit++){
		tmp=(char)(carry<<2)|((char)adder->GetBit(current_bit)<<1)|((char)this->GetBit(current_bit));
		if((adder->GetBit(current_bit)==0xFF) || (this->GetBit(current_bit)==0xFF)){
			printf("overflow!\n");
			exit(1);
		}
		//the format of tmp is now carry|op|target|
		printf("value: %i | %i | %i \n",(int)carry,(int)adder->GetBit(current_bit),(int)GetBit(current_bit));
		printf("tmp: %i\n",tmp);
		printf("bits0: %i\n",bits[0]);
		cout << "bit: " << current_bit << endl;
		switch(tmp){
			case 0: //000
			//do nothing...with no carray or any bits set, we just leave it as 0
			break;

			case 2: //010
			case 1: //001
			SetBit(current_bit,1);
			break;

			case 3: //011
			SetBit(current_bit,0);
			carry=1;
			break;

			case 4: //100
			carry=0;
			SetBit(current_bit,1);
			break;

			case 7: //111
			carry=1;
			SetBit(current_bit,1);
			break;

			case 5: //101
			case 6: //110
			carry=1;
			SetBit(current_bit,0);
		} //really, that's it!


	}






}


inline unsigned char unsigned_pint::GetBit(unsigned int bitn){
	unsigned int array_index,bit_index;
	if(bitn>size){return 0xFF;} //if we request a bit higher than the size...
	array_index=bitn/sizeof(int);
	bit_index=bitn%sizeof(int);
	unsigned int tmp;
	tmp=bits[array_index];
	tmp=tmp&(1<<bit_index);
	if(tmp>=1){
		return 1;
	}else{
		return 0;
	}
}

inline unsigned char unsigned_pint::SetBit(unsigned int bitn,unsigned char value){
	unsigned int array_index,bit_index;
	if(bitn>size){return 0xFF;} //if we request a bit higher than the size...
	array_index=bitn/sizeof(int);
	bit_index=bitn%sizeof(int);
	unsigned int tmp_return=GetBit(bitn);
	if(value>=1){
		bits[array_index]=bits[array_index] | (1<<bit_index);
	}else{
		bits[array_index]=bits[array_index] & (unsigned int)(-1^(1<<bit_index));
		//here we use -1 as -1 will always be the highest possible number, which means all bits will be set
	}
	return tmp_return;

}

inline unsigned int unsigned_pint::GetSize(){
	return size;
}




int main(){

	unsigned_pint test(32,"28");
	unsigned_pint t2(32,"0");

	t2.tmp_set_first_int(1); //14 and 30 are considered the same!
	printf("t2: %i\n",(unsigned int)t2.tmp_get_first_int());
	test.tmp_set_first_int(30); //but here, if you set this to 30 or 14 it is properly recognized!
	test.Add(&t2);
	printf("test_value: %i\n",(int)test.tmp_get_first_int());


	cout << "Hello world!" << std::endl;
	return 0;
}



/***Just for a bit of reference, this is the truth table of adding


C=carry
___________________________
Car op1	op2		result
0	0	0		0
0	1	1		0+C
0	1	0		1
0	0	1		1
1	0	0		1
1	1	1		1+C
1	0	1		0+C
1	1	0		0+C
___________________________

**/


Posted: Sat May 12, 2007 11:28 pm
by Kevin McGuire

Code: Select all

static unsigned int *bits;

inline unsigned char GetBit(unsigned int bitIndex){
	return (bits[bitIndex/32] & (0x1 << (bitIndex - (bitIndex/32*32)))) > 0;
}

inline void SetBit(unsigned int bitIndex, unsigned char value){
	if(value == 0){
		/// and with inverse of to turn that one bit off.
		bits[bitIndex/32] &= ~((bitIndex - (bitIndex/32*32)) << 0x1);
	}else{
		/// or with the one bit to turn on.
		bits[bitIndex/32] |= 0x1 << ((bitIndex - (bitIndex/32*32)));
	}
}

#define DB for(x = 5; x > 0; --x){printf("%08x ", bits[x-1]);} printf("\n");
int main(int argc, char *argv[]){
	unsigned long x;
	bits = (unsigned int*)malloc(4 * 10);
	for(x = 0; x < 4; ++x){ bits[x] = 0; }
	DB
	SetBit(80, 1);
	printf("getbit:%x\n", GetBit(35));
	DB
	return 1;
}
I see one problem I think:

array_index=bitn/sizeof(int);

Should be something more like:

array_index=bitn/(sizeof(int) * 8);

The sizeof(x) is in bytes and you need bits to convert by using a factor eight.

bit_index = (bitn - (bitn/32*32));

Posted: Sun May 13, 2007 12:08 am
by earlz
Thanks! I bet that's it...I did that in a lot of places, I though sizeof was given in bits for some reason..

guess by learning C++, I forgot some simple C

I'll try it now..


edit:

THANKS!!
That was the problem! It works perfectly now!