decrement operator c++ - n queens reduce operations

We made us two questions while we wrote this code:
http://ncomputers.org/content/code.php?src=n-queens/n-warp.cpp
Are we making an incorrect use of the increment and decrement operators?
Or is there some limitation with this operators, which we don't know yet?

For example:
h-=4-++*(pd1y1+x)-++*(pd2y1-x)-++*(pd1y+x1)-++*(pd2y-x1)+--*(pd1y+x)+--*(pd2y-x)+--*(pd1y1+x1)+--*(pd2y1-x1);

To explain why we asked us this questions, we wrote this code:
http://ncomputers.org/content/code.php?src=questions/increment_decrement_operators.cpp

Thank you for your help!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/* author: ncomputers.org */

#include<cstdlib>
#include<iostream>
using namespace std;

int main(void){
   unsigned const int queens=8;
   unsigned const int queens2m1=queens*2-1;
   unsigned const int queensm1=queens-1;

   unsigned int *const diagonal1=new unsigned int[queens2m1];
   unsigned int *const diagonal2=new unsigned int[queens2m1]+queensm1;//The address of this diagonal for each queen,
                                                      //Is always calculated so: nm1+x-y, we can reduce
                                                      //+queensnm1 operations

   unsigned int *const solution=new unsigned int[queensm1];

   unsigned int *tp1,*tp2;//temporal pointers to arrays

   unsigned int x,y,x1,y1;//values of queen(x,y) and queen(x1,y1);

   unsigned int *pd1y,*pd2y;//pointers to diagonals for y
   unsigned int *pd1y1,*pd2y1;//pointers to diagonals for y1

   for(tp1=solution,tp2=diagonal1,y=0;y<queens;*tp1++=y++,*tp2=1,tp2+=2);//initialize the solution to 1,2,3,4,5,..,n
                                                         //initialize the diagonal1 to 1,0,1,0,1,...
   *diagonal2=queens;//initialize the diagonal2 to: 0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0

   unsigned int h=8;//eight conflicts

   unsigned int temp,temp1;//used for warp

start:
   cout<<"sol:";for(tp1=solution;tp1<solution+queens;cout<<*tp1++<<",");cout<<endl;//print solution
   cout<<" d1:";for(tp1=diagonal1;tp1<diagonal1+queens2m1;cout<<*tp1++<<",");cout<<endl;//print diagonal 1
   cout<<" d2:";for(tp1=diagonal2-queensm1;tp1<diagonal2+queens;cout<<*tp1++<<",");cout<<endl;//print diagonal 2
   temp1=rand()%queens+queens;//obtain a constant point to do the warp
   y1=temp1%queens;//y1 at this point
   tp1=solution+y1;//solution at y1
   pd1y1=diagonal1+y1;//diagonal1 at y1
   pd2y1=diagonal2+y1;//diagonal2 at y1
   temp=rand()%queens;//obtain a start point to do the warp
warp:
   y=temp%queens;//y at this point
   tp2=solution+y;//solution at y
   pd1y=diagonal1+y;//diagonal1 at y
   pd2y=diagonal2+y;//diagonal2 at y
   x=*tp2;*tp2=x1=*tp1;*tp1=x;//swap queens(y,x1) and queens(y1,x)
//Now we need to update the conflicts number, put and remove the old and new queens from solution and diagonal arrays.
//just comment and uncomment the lines to test the different lines.
//our goal: If we want to warp 1,000 times a 1,000,000 queens array, we will do 1,000,000,000 this operations.
//Every operation that we can remove, will make the code faster. We want to remove the +4 operation using post decrement operators.
//This is our final goal: Why doesn't work?
   //h-=-++*(pd1y1+x)-++*(pd2y1-x)-++*(pd1y+x1)-++*(pd2y-x1)+(*(pd1y+x))--+(*(pd2y-x))--+(*(pd1y1+x1))--+(*(pd2y1-x1))--;
//the best solution we found (1,000,000,000 extra instructions):
   h-=4-++*(pd1y1+x)-++*(pd2y1-x)-++*(pd1y+x1)-++*(pd2y-x1)+--*(pd1y+x)+--*(pd2y-x)+--*(pd1y1+x1)+--*(pd2y1-x1);
//It works (two assignment instructions=1,000,000,000 extra instructions):
   //h-=4-++*(pd1y1+x)-++*(pd2y1-x)-++*(pd1y+x1)-++*(pd2y-x1);
   //h-=--*(pd1y+x)+--*(pd2y-x)+--*(pd1y1+x1)+--*(pd2y1-x1);
//it works (three assignment instructions):
   //h-=-++*(pd1y1+x)-++*(pd2y1-x)-++*(pd1y+x1)-++*(pd2y-x1);
   //h-=+(*(pd1y+x))--+(*(pd2y-x))--;
   //h-=+(*(pd1y1+x1))--+(*(pd2y1-x1))--;
//theoretically the last three lines are exactly to our goal.
//copied and pasted from the last three lines and added extra parenthesis to avoid a bad interpretation:
//It doesn't work
   //h-=-++*(pd1y1+x)-++*(pd2y1-x)-++*(pd1y+x1)-++*(pd2y-x1)+((*(pd1y+x))--)+((*(pd2y-x))--)+((*(pd1y1+x1))--)+((*(pd2y1-x1))--);
//Our conclusion: There are some limitation with the library which we use to compile this code.
//Is there some memory limitation with post in/decrement operators?
//We use: linux-headers-amd64 compiled with build-essentials
//It works (Fast our goal, but we have two assignment instructions :( 1,000,000,000 extra CPU instructions)
   //h-=-++*(pd1y1+x)-++*(pd2y1-x)-++*(pd1y+x1)-++*(pd2y-x1)+(*(pd1y+x))--+(*(pd2y-x))--;
   //h-=+(*(pd1y1+x1))--+(*(pd2y1-x1))--;
//End it works
//With more than two post decrement operators and one pre increment on same assignment instruction
//it doesn't work.
   //h-=-++*(pd1y1+x)+(*(pd1y+x))--+(*(pd2y-x))--+(*(pd2y1-x1))--;
   //h-=-++*(pd1y+x1)-++*(pd2y-x1)-++*(pd2y1-x)+(*(pd1y1+x1))--;
//End it doesn't work
//Thank you for your help!
   if(temp<temp1){temp++;goto warp;}
   else goto start;
   return 0;
};
Last edited on
Can x == x1 at line 59? If so, then ++*(pd1y1+x)-++*(pd2y1-x) is analogous to ++x - ++x, which has undefined behavior. Other than that, I don't see any reason why line 59 should work while line 57 doesn't.

Don't bother counting operators to predict how many instructions will be generated. The compiler is free to do whatever it wants to the code when optimizing. Just worry about making the code humanly comprehensible.
1
2
3
4
5
6
7
8
9
h -= 4;
h += ++pd1y1[x];
h += ++pd2y1[-x];
h += ++pd1y[x1];
h += ++pd2y[-x1];
h -= --pd1y[x];
h -= --pd2y[-x];
h -= --pd1y1[x1];
h -= --pd2y1[-x1];
For that matter, counting instructions to predict performance is almost as useless.
Helios,

Thank you very much for your time and to finally solve our question!

Can we publish a reference to your user profile in our website?

We want to publish: Thank you helios for answer our question!

We wrote this code to test your answer:

http://ncomputers.org/content/code.php?src=answers/increment_decrement_operators_limitation.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/* author: ncomputers.org */

#include<cstdlib>
#include<iostream>
using namespace std;

int main(void){
	unsigned const int queens=8;

	unsigned int diagonal1[]={1,0,1,0,1,0,1,0,1,0,1,0,1,0,1};//diagonal from down to up
	unsigned int diagonal2[]={0,0,0,0,0,0,0,8,0,0,0,0,0,0,0};//diagonal from up to down
	unsigned int solution[]={0,1,2,3,4,5,6,7};//x position of each queen

	unsigned int x,y;//stores temporally values of queen(x,y);
	unsigned int x1,y1;//stores temporally values of queen(x1,y1);

	unsigned int h=queens;//eight conflicts
	
	unsigned int iterator;//iterator variable

	srand(time(0));//seed random

	for(iterator=0;iterator<queens;iterator++){//seed solution
		y=rand()%queens;//select a queen randomly
		do{
			y1=rand()%queens;//select other queen randomly
		}while(y==y1);//y won't be equal to y1
		x=solution[y];//store the x position of the queen on y;
		x1=solution[y1];//store the x1 position of the queen on y1;
		solution[y1]=x;//swap the x value of queen on y1;
		solution[y]=x1;//swap the x value of queen on y;
		h-=-++diagonal1[x+y1];//add the new queen to its diagonal1 (x,y1)
		h-=-++diagonal2[queens-1+y1-x];//add the new queen to its diagonal2 (x,y1)
		h-=-++diagonal1[x1+y];//add the new queen to its diagonal1 (x1,y)
		h-=-++diagonal2[queens-1-x1+y];//add the new queen to its diagonal2 (x1,y)
		h-=+diagonal1[x+y]--;//remove the old queen form its diagonal1 (x,y)
		h-=+diagonal2[queens-1-x+y]--;//remove the old queen from its diagonal2 (x,y)
		h-=+diagonal1[x1+y1]--;//remove the old queen from its diagonal1 (x1,y1)
		h-=+diagonal2[queens-1-x1+y1]--;//remove the old queen from its diagonal2 (x1,y1)
	}

	while(true){
		{//start print arrays scope
			cout<<"sol:";
			for(iterator=0;iterator<queens;iterator++){
				cout<<solution[iterator];
				cout<<",";
			}
			cout<<endl;
			cout<<"dg1:";
			for(iterator=0;iterator<2*queens-1;iterator++){
				cout<<diagonal1[iterator];
				cout<<",";
			}
			cout<<endl;
			cout<<"dg2:";
			for(iterator=0;iterator<2*queens-1;iterator++){
				cout<<diagonal2[iterator];
				cout<<",";
			}
			cout<<endl;
		}//end print arrays scope
		{//start first step warp scope
			y=rand()%queens;//select a queen randomly
			do{
				y1=rand()%queens;//select other queen randomly
			}while(y==y1);//y won't be equal to y1
			x=solution[y];//store the x position of the queen on y;
			x1=solution[y1];//store the x1 position of the queen on y1;
			solution[y1]=x;//swap the x value of queen on y1;
			solution[y]=x1;//swap the x value of queen on y;
			//if(x==x1)return 1;
		}//end first step warp scope
		/*
		{//start it works scope
			h-=-++diagonal1[x+y1];//add the new queen to its diagonal1 (x,y1)
			h-=-++diagonal2[queens-1+y1-x];//add the new queen to its diagonal2 (x,y1)
			h-=-++diagonal1[x1+y];//add the new queen to its diagonal1 (x1,y)
			h-=-++diagonal2[queens-1-x1+y];//add the new queen to its diagonal2 (x1,y)
			h-=+diagonal1[x+y]--;//remove the old queen form its diagonal1 (x,y)
			h-=+diagonal2[queens-1-x+y]--;//remove the old queen from its diagonal2 (x,y)
			h-=+diagonal1[x1+y1]--;//remove the old queen from its diagonal1 (x1,y1)
			h-=+diagonal2[queens-1-x1+y1]--;//remove the old queen from its diagonal2 (x1,y1)
		}//end it works scope
		*/
		{//start it doesn't work scope
			if((x+y1)==(x1+y))return 1;//Same diagonal
			else if((queens-1-x1+y)==(queens-1-x+y1))return 1;//Same diagonal
			else if((x+y)==(x1+y1))return 1;//Same diagonal
			else if((queens-1-x1+y1)==(queens-1-x+y))return 1;//Same diagonal
			h-=//start update conflicts
			-++diagonal1[x+y1]//add the new queen to its diagonal1 (x,y1)
			-++diagonal2[queens-1+y1-x]//add the new queen to its diagonal2 (x,y1)
			-++diagonal1[x1+y]//add the new queen to its diagonal1 (x1,y)
			-++diagonal2[queens-1-x1+y]//add the new queen to its diagonal2 (x1,y)
			+diagonal1[x+y]--//remove the old queen form its diagonal1 (x,y)
			+diagonal2[queens-1-x+y]--//remove the old queen from its diagonal2 (x,y)
			+diagonal1[x1+y1]--//remove the old queen from its diagonal1 (x1,y1)
			+diagonal2[queens-1-x1+y1]--//remove the old queen from its diagonal2 (x1,y1)
			;//end update conflicts
		}//end it doesn't work scope
		/**/
	}//end while
	return 0;
};
Last edited on
Thank you very much for your time and to finally solve our question!

Can we publish a reference to your user profile in our website?

We want to publish: Thank you helios for answer our question!
Sure, I don't mind.
Answer:

Post and pre increment and decrement operators limitation due to undefined behavior:

http://ncomputers.org/content/code.php?src=answers/increment_decrement_operators_limitation.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
using namespace std;

int main(void){
	unsigned int value=1;
	unsigned int *pointer=&value;
	while(value==1){
		cout<<value<<",";
		//after this operation value won't be 1 anymore
		//this is a limitation, which we didn't know and which we'll consider starting from now
		//thank you very much!
		-++(*pointer)-++(*pointer)+(*pointer)--+(*pointer)--;
		cout<<value<<endl;
	}
	return 0;
};
Last edited on
Topic archived. No new replies allowed.