示例#1
0
/*
 * -----------------------------------------------------------------------------
 * argv[1] : Maximum number of collisions to examine (-1 == all available colls)
 * argv[2] : Maximum running time in nanoseconds (-1 == until end of file)
 * argv[3] : Name of the binary data file
 * argv[4] : How many threads OMP is going to use (-1 == all available threads)
 * argv[5] : How many procs OMPI is going to use (-1 = all available procs)
 *
 * NOTE: It is not possible to Initialize the MPI after it has been Finalized.
 * If you want to test an MPI section in comparison with a non-MPI one, just
 * uncomment the part in the main, where we run the non-MPI code.
 * If you want to test both MPI parts, you have to run the program two times.
 * -----------------------------------------------------------------------------
 */
int main(int argc, char *argv[]) {
	if(argc == 6) {
		if(check_arg_validity(argv) != SUCCESS)
			return(FAILURE);
		struct timespec start, end;
		
		
		// Run the linear (non-MPI)
		clock_gettime(CLOCK_MONOTONIC, &start);
		linear_estimation(atoi(argv[1]), atoi(argv[2]), argv[3]);
		clock_gettime(CLOCK_MONOTONIC, &end);
		printf("Non-MPI Linear motion estimation total ");
		calculate_difference(start, end, 1);

		printf("\n");
		/*
		// Run the linear (MPI)
		clock_gettime(CLOCK_MONOTONIC, &start);
		ompi_linear_estimation(atoi(argv[1]), atoi(argv[2]), argv[3]);
		clock_gettime(CLOCK_MONOTONIC, &end);
		printf("MPI Linear motion estimation total ");
		calculate_difference(start, end, 1);
		
		printf("\n");
		*/
		// Run the parallel (Non-MPI)
		clock_gettime(CLOCK_MONOTONIC, &start);
		parallel_estimation(atoi(argv[1]), atoi(argv[2]), argv[3], atoi(argv[4]));
		clock_gettime(CLOCK_MONOTONIC, &end);
		printf("Non-MPI Parallel motion estimation total ");
		calculate_difference(start, end, 1);
		/*
		printf("\n");
		
		// Run the parallel (MPI)
		clock_gettime(CLOCK_MONOTONIC, &start);
		ompi_parallel_estimation(atoi(argv[1]), atoi(argv[2]), argv[3], atoi(argv[4]));
		clock_gettime(CLOCK_MONOTONIC, &end);
		printf("MPI Parallel motion estimation total ");
		calculate_difference(start, end, 1);
		*/
		
		return(SUCCESS);
	} else {
		printf("Invalid number of arguements. Exiting.\n");
		return(FAILURE);
	}
}
示例#2
0
/* 
 * ----------------------------1st Week Progress--------------------------------
 * Find all the valid collisions from the data file given as the third argument.
 * First argument is a limitation on how many sets the function will examine.
 * Second argument is a limitation on how many nanoseconds the function will be
 * running. If the time limit is exceeded, the function will stop examining the
 * file.
 * This function does NOT use OMP or OMPI to go through the examination.
 * -----------------------------------------------------------------------------
 */
int linear_estimation(long num_coords, int max_nsecs, char *file_name) {
	FILE *file_ptr = fopen(file_name, "rb");
	if(!file_ptr) {
		printf("Unable to open file!\n");
		return(FAILURE);
	}
    
    // Calculate the total number of coordinates that are stored in the file.
    // The number is: NUM = FILE_SIZE / SIZE_OF_A_FLOAT / 3
    // A coordinate is a set of 3 floats.
    // The function will check exactly (EXAM_COORDS) collisions from the file.
	long exam_coords = fsize(file_name) / sizeof(float) / 3;
	
	long curr_coord;
	long valid_collisions=0;
	
	// If there is a limitation on how many collisions the function should go
	// through, change the value of exam_coords to that limitation.
	if(num_coords>=0 && num_coords<exam_coords)
		exam_coords=num_coords;
		
	// If the limitation exceeds the total number of coordinates stored in the
	// data file, display a message. The total number of collision, the function
	// will go through, remains the total number of coordinates available in the
	// file.	
	if(num_coords > exam_coords)
		printf("You have asked for more lines than the ones available. All the lines are going to be examined.\n");
	
	// The timespecs will keep track of the time, if a limitation has been set.
    struct timespec start, current;
    
	// Before the start of the examination, get the current time.
	clock_gettime(CLOCK_MONOTONIC, &start);
	
	// The function will check all the collisions, increasing its sum
	// (valid_collisions) every time a collision is within the limits defined in
	// the start of the code.
	// Every time it goes though one set, if there has been set a limitation on
	// how many nanoseconds the function should run, check the current time, get
	// the difference from the timestamp when the examination started running
	// and if the time limit has been exceeded, stop the loop.
	for(curr_coord=0; curr_coord<exam_coords; curr_coord++) {
		if(process_coords(file_ptr)==0)
			valid_collisions++;
		if(max_nsecs!=-1 && calculate_difference(start, current, 0)>max_nsecs){
			clock_gettime(CLOCK_MONOTONIC, &current);
			printf("Reached maximum time limit.\n");
			break;
		}
	}
	
	fclose(file_ptr);
	
	printf("Non-MPI Linear Examine -> Valid collisions: %ld\n", valid_collisions);
    
	return(SUCCESS);
}
示例#3
0
文件: cls_op.cpp 项目: CCJY/engine-1
void cls_op::do_process(const tuple_ptr tup, int)
{
	pre_process_hook(tup);

	std::vector<double> coordinates = std::vector<double>(m_value_d);
	for (int i = 0; i < m_value_d; i++)
		coordinates[i] = to_double((*tup)[i]);

	long timestamp = to_long(tup->op_arrival_time());

	std::vector<cls_snapshot_microcluster*> *smc = m_clustream->process(coordinates, timestamp);
	if (smc != NULL) {

		cls_lbgu *lbgu = new cls_lbgu(smc, m_value_k);
		lbgu->start();
		std::vector<cls_cluster*> result = lbgu->get_clusters();

		std::vector<std::pair<int, cls_cluster*> > result_list(0);
		for (int i = 0; i < m_value_k; i++)
			result_list.push_back(std::pair<int, cls_cluster*>(i, result[i]));

		m_id++;

		if (m_first_output_done) {
			m_new_list   = sort_clusters(m_old_list, result_list);
			m_difference = calculate_difference(m_old_list, m_new_list);
		} else {
			m_new_list   = result_list;
			m_difference = result_list;
			m_first_output_done = true;
		}

		std::vector<std::pair<int, cls_cluster*> > output_list;
		if (m_output_version == 0)
			output_list = m_new_list;
		else if (m_output_version == 1)
			output_list = m_difference;
		else
			output_list = m_new_list;

		for (int i = 0; i < (int) output_list.size(); i++) {
			std::vector<boost::any> data(2 + m_value_d);
			data[0] = m_id;
			data[1] = output_list[i].first;

			for (int j = 0; j < m_value_d; j++)
				data[j+2] = output_list[i].second->get_coordinate(j);

			tuple_ptr n_tuple(new tuple(data));
			publish_new(n_tuple);
		}

		m_old_list = m_new_list;
	}
}
示例#4
0
/* 
 * ----------------------------2nd Week Progress--------------------------------
 * Find all the valid collisions from the data file given as the third argument.
 * First argument is a limitation on how many sets the function will examine.
 * Second argument is a limitation on how many nanoseconds the function will be
 * running. If the time limit is exceeded, the function will stop examining the
 * file.
 * Fourth argument is the number of threads MPI should utilize.
 * This function uses OMP, but NOT OMPI to go through the examination.
 * -----------------------------------------------------------------------------
 */
int parallel_estimation(long num_coords, int max_nsecs, char *file_name, int threads) {
	// Check if file exists. If not, print a message and return !0.
	if(access(file_name, F_OK) == -1) {
		printf("File was not found!\n");
		return(FAILURE);
	}

	// Create a variable where the total number of valid collisions from all the
	// threads will be added to.
	long sum = 0;
	
	// If there is a limitation on how many threads MPI should use (-1 means all
	// available threads), apply it.
	if(threads >= 1)
		omp_set_num_threads(threads);
		
	// Start using OpenMP.
	#pragma omp parallel shared(file_name)
	{
		// Calculate the total number of coordinates that are stored in the 
		// file.
    	// The number is: NUM = FILE_SIZE / SIZE_OF_A_FLOAT / 3
    	// A coordinate is a set of 3 floats.
    	// The function will check exactly (EXAM_COORDS) collisions from the
    	// file.
		long exam_coords = fsize(file_name) / sizeof(float) / 3;
		
		// If there is a limitation on how many collisions the function should
		// go through, change the value of exam_coords to that limitation.
		if(num_coords >=0 && num_coords < exam_coords)
			exam_coords = num_coords;
			
		// If the limitation exceeds the total number of coordinates stored in the
		// data file, display a message. The total number of collision, the function
		// will go through, remains the total number of coordinates available in the
		// file.	
		if(num_coords > exam_coords)
			printf("You have asked for more lines than the ones available. All the lines are going to be examined.\n");

		// Get the total number of threads the OMP is running.
		int total_threads = omp_get_num_threads();
		
		// Get the ID of this particular thread.
		int tid = omp_get_thread_num();
		
		// Each file opens its own pointer to the data file.
		FILE *file_ptr = fopen(file_name, "rb");
		
		// Set which coords each thread will process.
		long coord_from = (int)exam_coords/total_threads * tid;
		long coord_to = (int)exam_coords/total_threads * (tid+1) - 1;
		if(tid+1 == total_threads)
			coord_to += exam_coords % total_threads;

		// Skip some bytes from the data file, in order to get to the set where
		// the thread must start examining from.
		fseek(file_ptr, 3*coord_from*sizeof(float), SEEK_SET);
		
		long coords_read;
		long valid_collisions=0;

		// The timespecs will keep track of the time, if a limitation has been
		// set.
    	struct timespec start, current;
    
		// Before the start of the examination, get the current time.
		clock_gettime(CLOCK_MONOTONIC, &start);

		// The function will check all the collisions, increasing its sum
		// (valid_collisions) every time a collision is within the limits
		// defined in the start of the code.
		// Every time it goes though one set, if there has been set a limitation
		// on how many nanoseconds the function should run, check the current 
		// time, get the difference from the timestamp when the examination
		// started running and if the time limit has been exceeded, stop the
		// loop.
		for(coords_read=coord_from; coords_read<coord_to+1; coords_read++) {
			if(process_coords(file_ptr)==0)
				valid_collisions++;
			if(max_nsecs!=-1&&calculate_difference(start,current,0)>max_nsecs){
				clock_gettime(CLOCK_MONOTONIC, &current);
				printf("Reached maximum time limit.\n");
				break;
			}
		}

		// Each threads closes its file pointer.
		fclose(file_ptr);
		
		#pragma omp barrier
		
		// Finally, add all the valid collision numbers, each thread has found
		// to the shared variable "sum".
		#pragma omp  for reduction(+:sum)
			for(tid=0;tid<total_threads;tid++)
		  		sum+=valid_collisions;
		
		#pragma omp master	
			printf("Non-MPI Parallel Examine -> Valid collisions: %ld\n", sum);
	}
	return(SUCCESS);
}
示例#5
0
/* 
 * ----------------------------4th Week Progress--------------------------------
 * Find all the valid collisions from the data file given as the third argument.
 * First argument is a limitation on how many sets the function will examine.
 * Second argument is a limitation on how many nanoseconds the function will be
 * running. If the time limit is exceeded, the function will stop examining the
 * file.
 * Fourth argument is the number of threads MPI should utilize.
 * This function uses OMP AND OMPI to go through the examination.
 * -----------------------------------------------------------------------------
 */
int ompi_parallel_estimation(long num_coords, int max_nsecs, char *file_name, int threads) {
	// Check if file exists. If not, print a message and return !0.
	if(access(file_name, F_OK) == -1) {
		printf("File was not found!\n");
		return(FAILURE);
	}
	
	// Initialize the MPI. After this line, multiple procs run at the same time.
	MPI_Init(NULL, NULL);

    // Get the total number of processes that are running.
    int total_procs;
    MPI_Comm_size(MPI_COMM_WORLD, &total_procs);    

    // Get the rank of the process
    int proc_num;
    MPI_Comm_rank(MPI_COMM_WORLD, &proc_num);
	if(proc_num>total_procs)
	{
		MPI_Finalize();
	}
    
    long *succesful_col;
	if(proc_num == 0)
		 succesful_col = malloc(sizeof(long) * total_procs); 

    // Calculate the total number of coordinates that are stored in the file.
    // The number is: NUM = FILE_SIZE / SIZE_OF_A_FLOAT / 3
    // A coordinate is a set of 3 floats.
    // The function will check exactly (EXAM_COORDS) collisions from the file.
    long exam_coords = fsize(file_name) / sizeof(float) / 3;
    
    // If there is a limitation on how many collisions the function should go
	// through, change the value of exam_coords to that limitation.
    if(num_coords >= 0 && num_coords < exam_coords)
        exam_coords = num_coords;
        
    // If the limitation exceeds the total number of coordinates stored in the
	// data file, display a message. The total number of collision, the function
	// will go through, remains the total number of coordinates available in the
	// file.	
    if(num_coords > exam_coords)
        printf("You have asked for more lines than the ones available. All the lines are going to be examined.\n");
    
    // Set which coords each PROCESS will go through. We will repeat the same
    // divison, when we distribute these coords to every THREAD that is running
    // within ever process. 
    long coord_from = (int)exam_coords/total_procs * proc_num;
    long coord_to = (int)exam_coords/total_procs * (proc_num+1) - 1;
    if(proc_num+1 == total_procs)
        coord_to += exam_coords % total_procs;

	// Create a variable where the total number of valid collisions from all the
	// threads will be added to.
	long sum = 0;
	
	// If there is a limitation on how many threads MPI should use (-1 means all
	// available threads), apply it.
	if(threads >= 1)
		omp_set_num_threads(threads);
		
	// Start using OpenMP.
	#pragma omp parallel shared(file_name)
	{
		// Get the total number of threads the OMP is running.
		int total_threads = omp_get_num_threads();
		
		// Get the ID of this particular thread.
		int tid = omp_get_thread_num();
		
		// Each file opens its own pointer to the data file.
		FILE *file_ptr = fopen(file_name, "rb");
		
		// Same when we divided the sets and distributed them to each process,
		// but this time we are doing it for ever thread within EACH process.
		long coll_from = (int)(coord_to-coord_from+1)/total_threads * tid;
		long coll_to = (int)(coord_to-coord_from+1)/total_threads * (tid+1) - 1;
		if(tid+1 == total_threads)
			coll_to += (coord_to-coord_from+1) % total_threads;

		// Skip some bytes from the data file, in order to get to the set where
		// the thread must start examining from
		fseek(file_ptr, 3*(coord_from+coll_from)*sizeof(float), SEEK_SET);
		
		long coords_read;
		long valid_collisions=0;

		// The timespecs will keep track of the time, if a limitation has been
		// set.
    	struct timespec start, current;
    
		// Before the start of the examination, get the current time.
		clock_gettime(CLOCK_MONOTONIC, &start);

		// The function will check all the collisions, increasing its sum
		// (valid_collisions) every time a collision is within the limits
		// defined in the start of the code.
		// Every time it goes though one set, if there has been set a limitation
		// on how many nanoseconds the function should run, check the current 
		// time, get the difference from the timestamp when the examination
		// started running and if the time limit has been exceeded, stop the
		// loop.
		for(coords_read=coll_from; coords_read<coll_to+1; coords_read++) {
			if(process_coords(file_ptr)==0)
				valid_collisions++;
			if(max_nsecs!=-1&&calculate_difference(start,current,0)>max_nsecs){
				clock_gettime(CLOCK_MONOTONIC, &current);
				printf("Reached maximum time limit.\n");
				break;
			}
		}

		// Each threads closes its file pointer.
		fclose(file_ptr);

		#pragma omp barrier
		
		// Finally, add all the valid collision numbers, each thread has found
		// to the shared variable "sum".
		#pragma omp  for reduction(+:sum)
			for(tid=0;tid<total_threads;tid++)
		  		sum += valid_collisions; //sums the total collisions of all threads
	}
	
	// After each process has calculated how many valid collisions there are in
	// its own section of data, the MPI adds all the different result into one
	// shared variable (final_count) with the help of MPI_Gather.
	MPI_Gather(&sum, 1, MPI_LONG, succesful_col, 1, MPI_LONG, 0, MPI_COMM_WORLD);
	if(proc_num == 0){
		long final_count = 0;
		for(int i=0; i<total_procs; i++){
			final_count+=succesful_col[i];
		}
		printf("MPI Parallel Examine -> Valid collisions: %ld", final_count); 
	}

	MPI_Finalize();
	
	return(SUCCESS);
}
surface scale_surface(surface input) {
	surface result(surface::create(input->w*2, input->h*2));

	const uint32_t* in = reinterpret_cast<const uint32_t*>(input->pixels);
	uint32_t* out = reinterpret_cast<uint32_t*>(result->pixels);
	for(int y = 0; y != input->h; ++y) {
		for(int x = 0; x != input->w; ++x) {
		  //do nearest neighbor interpolation
			out[(y*2)*result->w + x*2] = in[y*input->w + x];
			out[(y*2 + 1)*result->w + x*2] = in[y*input->w + x];
			out[(y*2 + 1)*result->w + x*2 + 1] = in[y*input->w + x];
			out[(y*2)*result->w + x*2 + 1] = in[y*input->w + x];
			
			if ((y > 0) && (y < input->h - 2) && (x > 0) && (x < input->w - 2)){
				
				
			//do additional 2xSaI interpolation
				
			//  2xSai works on a square group of sixteen pixels, rather than the square group of nine that Eagle works on.  In Eagle, the current pixel being upsized is the one in the middle of this square of nine; in 2xSai, the current pixel is the one in the upper-left of the middle four.  The other pixels in this group are all input pixels that are being examined to determine if we have an edge to smooth out.
			
			//  X X X X  |  0  1  2  3
			//  X * X X  |  4  5  6  7
			//  X X X X  |  8  9  10 11
			//  X X X X  |  12 13 14 15
						const int px[4][4] = {{	//[x][y]
							y*input->w + x - input->w - 1,
							y*input->w + x - input->w,
							y*input->w + x - input->w + 1,
							y*input->w + x - input->w + 2},
							{y*input->w + x - 1,
							y*input->w + x,
							y*input->w + x + 1,
							y*input->w + x + 2},
							{y*input->w + x + input->w - 1,
							y*input->w + x + input->w,
							y*input->w + x + input->w + 1,
							y*input->w + x + input->w + 2},
							{y*input->w + x + 2*input->w - 1,
							y*input->w + x + 2*input->w,
							y*input->w + x + 2*input->w + 1,
							y*input->w + x + 2*input->w + 2}};
						
						//these are the four output pixels corresponding to the one input pixel
						const int out_index_upper_left = (y*2)*result->w + x*2;
						const int out_index_upper_right = (y*2)*result->w + x*2 + 1;
						const int out_index_lower_left = (y*2 + 1)*result->w + x*2;
						const int out_index_lower_right = (y*2 + 1)*result->w + x*2 + 1;

						//make sure we're not going out-of-bounds
						const int max_index = input->w*input->h;
						assert(px[0][2] < max_index);
						assert(px[0][3] < max_index);
						assert(px[1][2] < max_index);
						assert(px[1][3] < max_index);
						assert(px[2][0] < max_index);
						assert(px[2][1] < max_index);
						assert(px[2][2] < max_index);
						assert(px[2][3] < max_index);
						assert(px[3][0] < max_index);
						assert(px[3][1] < max_index);
						assert(px[3][2] < max_index);
						assert(px[3][3] < max_index);

						if ( (in[px[1][1]] == in[px[2][2]]) && (in[px[1][2]] != in[px[2][1]]) ) {
							if ( ((in[px[1][1]] == in[px[0][1]]) && (in[px[1][2]] == in[px[2][3]])) || ((in[px[1][1]] == in[px[2][1]]) && (in[px[1][1]] == in[px[0][2]]) && (in[px[1][2]] != in[px[0][1]]) && (in[px[1][2]] == in[px[0][3]]))){
								out[out_index_upper_right] = in[px[1][1]];
							}else{
								if( ! ((in[px[1][1]] == in[px[0][1]])) ){
									out[out_index_upper_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]]);
								}
							}
							
							if ( ((in[px[1][1]] == in[px[1][0]]) && (in[px[2][1]] == in[px[3][2]])) || ((in[px[1][1]] == in[px[1][2]]) && (in[px[1][1]] == in[px[2][0]]) && (in[px[1][0]] != in[px[2][1]]) && (in[px[2][1]] == in[px[3][0]]))){
								out[out_index_lower_left] = in[px[1][1]];
							}else{
								if( ! ((in[px[1][1]] == in[px[1][0]])) ){
									out[out_index_lower_left] = interpolate_pixels(in[px[1][1]],in[px[2][1]]);
								}
							}
							out[out_index_lower_right] = in[px[1][1]];
						} else if ( (in[px[1][2]] == in[px[2][1]]) && (in[px[1][1]] != in[px[2][2]]) ) {
							if ( ((in[px[1][2]] == in[px[0][2]]) && (in[px[1][1]] == in[px[2][0]])) || ((in[px[1][2]] == in[px[0][1]]) && (in[px[1][2]] == in[px[2][2]]) && (in[px[1][2]] != in[px[0][2]]) && (in[px[1][1]] == in[px[0][0]]))){
								out[out_index_upper_right] = in[px[1][2]];
							}else{
								out[out_index_upper_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]]);
							}
							
							if ( ((in[px[2][1]] == in[px[2][0]]) && (in[px[1][1]] == in[px[0][2]])) || ((in[px[2][1]] == in[px[1][0]]) && (in[px[2][1]] == in[px[2][2]]) && (in[px[1][1]] != in[px[2][0]]) && (in[px[1][1]] == in[px[0][0]]))){
								out[out_index_lower_left] = in[px[2][1]];
							}else{
								out[out_index_lower_left] = interpolate_pixels(in[px[1][1]],in[px[2][1]]);
							}
							out[out_index_lower_right] = in[px[1][2]];
							
						}else if ( (in[px[1][1]] == in[px[2][2]]) && (in[px[1][2]] == in[px[2][1]]) ) {
							// these are crossed diagonal pairs of pixels in the inner, center set of four.
							// if they're the same, then we weight them against a surrounding ring of pixels, and see which
							// pair is more different from the ring.  The ring is this asterisked set of pixels:
							//  X * * X
							//  * X X *
							//  * X X *
							//  X * * X
							if (in[px[1][1]] == in[px[1][2]]){
								out[out_index_lower_right] = in[px[1][1]];
								out[out_index_lower_left] = in[px[1][1]];
								out[out_index_upper_right] = in[px[1][1]];
								out[out_index_upper_left] = in[px[1][1]];

							} else {
								
								int difference_direction = 0;
								out[out_index_upper_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]]);
								out[out_index_lower_left] = interpolate_pixels(in[px[1][1]],in[px[2][1]]);
								
								difference_direction += calculate_difference(in[px[1][2]],in[px[1][1]],in[px[0][1]],in[px[1][0]]);
								difference_direction += calculate_difference(in[px[1][2]],in[px[1][1]],in[px[0][2]],in[px[1][3]]);
								difference_direction += calculate_difference(in[px[1][2]],in[px[1][1]],in[px[3][2]],in[px[2][3]]);
								difference_direction += calculate_difference(in[px[1][2]],in[px[1][1]],in[px[2][0]],in[px[3][1]]);
								
								if (difference_direction > 0){
									out[out_index_lower_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]],in[px[1][2]],in[px[1][2]]);
									out[out_index_upper_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]],in[px[1][2]],in[px[1][2]]);
								}else if(difference_direction < 0){
									out[out_index_lower_right] = interpolate_pixels(in[px[1][1]],in[px[1][1]],in[px[1][1]],in[px[1][2]]);
									out[out_index_upper_right] = interpolate_pixels(in[px[1][1]],in[px[1][1]],in[px[1][1]],in[px[1][2]]);
								}else{
									out[out_index_lower_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]],in[px[2][1]],in[px[2][2]]);
									out[out_index_upper_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]],in[px[2][1]],in[px[2][2]]);
								}								
								
							}
						} else {
							if ( ( (in[px[1][1]] != in[px[2][1]]) || (in[px[1][1]] != in[px[0][1]]) ) && ( (in[px[0][2]] == in[px[1][2]]) && (in[px[1][2]] == in[px[2][2]]) ) ){
								out[out_index_upper_right] = interpolate_pixels(in[px[1][1]],in[px[1][1]],in[px[1][1]],in[px[1][2]]);
								out[out_index_lower_right] = interpolate_pixels(in[px[1][1]],in[px[1][1]],in[px[1][1]],in[px[1][2]]);
							}
							
							if ( ( (in[px[0][2]] == in[px[1][1]]) || (in[px[1][1]] == in[px[2][0]]) ) && ( (in[px[1][1]] != in[px[2][1]]) && (in[px[1][1]] != in[px[1][2]])) ){
								out[out_index_upper_right] = interpolate_pixels(in[px[1][1]],in[px[1][1]],in[px[1][1]],in[px[1][2]]);
								out[out_index_lower_left] = interpolate_pixels(in[px[1][1]],in[px[1][1]],in[px[1][1]],in[px[2][1]]);
								out[out_index_lower_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]],in[px[1][1]],in[px[2][1]]);
							}
							
							if ( ((in[px[1][1]] == in[px[0][0]]) && (in[px[1][1]] == in[px[1][2]])) && ( (in[px[1][1]] != in[px[1][0]]) && (in[px[1][1]] != in[px[2][1]]) ) ){
								out[out_index_upper_left] = interpolate_pixels(in[px[1][1]],in[px[1][1]],in[px[1][1]],in[px[1][0]]);
								out[out_index_lower_right] = interpolate_pixels(in[px[1][1]],in[px[1][1]],in[px[1][1]],in[px[2][1]]);
								out[out_index_lower_left] = interpolate_pixels(in[px[1][0]],in[px[2][1]]);
							}
							
							
							if ( (in[px[1][1]] == in[px[2][1]]) && (in[px[1][1]] == in[px[0][2]]) && (in[px[1][2]] != in[px[0][1]]) && (in[px[1][2]] == in[px[0][3]]) ){
								 out[out_index_upper_right] = in[px[1][1]];
							} else if ( (in[px[1][2]] == in[px[0][1]]) && (in[px[1][2]] == in[px[2][2]]) && (in[px[1][1]] != in[px[0][2]]) && (in[px[1][1]] == in[px[0][0]]) ){
								 out[out_index_upper_right] = in[px[1][2]];
							} else {
								//out[out_index_upper_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]]);
								//out[out_index_lower_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]]);
							}
							
							if ( (in[px[1][1]] == in[px[1][2]]) && (in[px[1][1]] == in[px[2][0]]) && (in[px[1][0]] != in[px[2][1]]) && (in[px[2][1]] == in[px[3][0]]) ){
								out[out_index_lower_left] = in[px[1][1]];
							} else if ( (in[px[2][1]] == in[px[1][0]]) && (in[px[2][1]] == in[px[2][2]]) && (in[px[1][1]] != in[px[2][0]]) && (in[px[1][1]] == in[px[0][0]]) ){
								out[out_index_lower_left] = in[px[2][1]];
							} else {
								//out[out_index_lower_right] = interpolate_pixels(in[px[1][1]],in[px[2][1]]);
								//out[out_index_lower_left] = interpolate_pixels(in[px[1][1]],in[px[2][1]]);
							}
							//out[out_index_lower_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]],in[px[2][1]],in[px[2][2]]);
							//out[out_index_upper_right] = interpolate_pixels(in[px[1][1]],in[px[1][2]],in[px[2][1]],in[px[2][2]]);
						}
							
			}
		}
	}

	return result;
}