
// Kernel invocation: dpx <<POP_SIZE/2,MAX_THREADS_PER_BLOCK>>> (oldpop,newpop,positions,randomPC,randomPoint,
// CHROM_LEN,PROB_CROSS); 
// POP_SIZE: number of individuals of the population.
// MAX_THREADS_PER_BLOCK: constant with the maximum number of threads per block. 
// oldpop: pointer to global memory that stores the old population. 
// newpop: pointer to global memory that stores the new population.
// positions: pointer to global memory that stores the indexes of individuals for crossover
// randomPC: pointer to global memory that stores the random values for crossover.
// randomPoint: pointer to global memory that stores the random points for crossover.
// CHROM_LEN: length of the chromosome.
// PROB_CROSS: crossover probability. 

__global__ void dpx(bool *pop, bool *npop, int *pos, float *randomPC, int *randomPoint, int length, float PROB_CROSS){

   int idx = blockIdx.x;  // the number of the individual is indicated by the block number
   int ind1 = pos[2*idx];  // index of first individual for crossover
   int ind2 = pos[2*idx+1]; // index of second individual for crossover
   float pc = randomPC[idx]; // value for crossover
   int pnt1 = randomPoint[2*idx]; // first crossover point
   int pnt2 = randomPoint[2*idx+1]; // second crossover point
   int i;

   if (pc <= PROB_CROSS) {
       // Cross individuals
       for(i=threadIdx.x;i<length;i=i+MAX_THREADS_PER_BLOCK) {
             if (i<pnt1 || i>=pnt2) {
                   //copy bit from parent ind1 to child 2*idx
	       	   npop[2*idx*length+i] = pop[ind1*length+i];
		   //copy bit from parent ind2 to child 2*idx + 1
 		   npop[(2*idx+1)*length+i] = pop[ind2*length+i];
	      } else {
                   //copy bit from parent ind2 to child 2*idx	       		    
                   npop[2*idx*length+i] = pop[ind2*length+i];
		   //copy bit from parent ind1 to child 2*idx + 1
	           npop[(2*idx+1)*length+i] = pop[ind1*length+i];
	      }
	}       
    } else {
       // Copy individuals
       for(i=threadIdx.x;i<length;i=i+MAX_THREADS_PER_BLOCK) {
            //copy bit from parent ind1 to child 2*idx
	    npop[(2*idx)*length+i] = pop[ind1*length+i];
	    //copy bit from parent ind2 to child 2*idx + 1
	    npop[(2*idx+1)*length+i] = pop[ind2*length+i];
       }
    }

}


