Gap alignment changed. Should be consitent with other mappers now.

__kernel
void interleaveSeq(__global char const * _src, __global char * dest) {

	__global char const * src = _src + ((global_index) * ref_length);
	dest = dest + ((global_index / interleave_number) * interleave_number * ref_length) + global_index % interleave_number;

	int i = 0;
	for (i = 0; i < ref_length / 4 * 4; i += 4) {
		char4 temp = vload4(0, src);
		dest[(i) * interleave_number] = temp.s0;
		dest[(i + 1) * interleave_number] = temp.s1;
		dest[(i + 2) * interleave_number] = temp.s2;
		dest[(i + 3) * interleave_number] = temp.s3;
		src += 4;
	}

	for (; i < ref_length; i += 1) {
		dest[(i) * interleave_number] = *src++;
	}
}

#ifdef __GPU__

#ifndef __BS__
__kernel void oclSW_Score(__global char const * scaff, __global char const * read, __global short * result, __global char * matrix) {
#else
	__kernel void oclSW_Score(__global char const * scaff, __global char const * read, __global short * result, __global char * matrix, __global char const * direction) {
#endif

		matrix = matrix + ((global_index / threads_per_block) * threads_per_block * ((corridor_length + 1) * (read_length + 1))) + global_index % threads_per_block;
		read = read + (global_index * read_length);
		scaff = scaff + ((global_index / interleave_number) * interleave_number * ref_length) + global_index % interleave_number;
		result = result + result_number * global_index;

		__local
		short l_matrix_lines[MATRIX_LENGTH];
		__local
		//	short * local_matrix_line = l_matrix_lines + local_index * corridor_length;
		short * local_matrix_line = l_matrix_lines + local_index;

		//Init matrix lines
		for (short i = 0; i < corridor_length; ++i) {
			local_matrix_line[i * threads_per_block] = 0;
			matrix[i * threads_per_block] = CIGAR_STOP;
		}
		matrix[corridor_length * threads_per_block] = CIGAR_STOP;

		short curr_max = -1;
		short read_index = 0;

		//	if (read[0] != '\0') {
		//		//printf("GPU Ref : %s\n", scaff);
		//		//printf("GPU Read: %s\n", read);
		//		printf("S:\t");
		//		char c;
		//		int i = 0;
		//		while ((c = scaff[i * interleave_number]) != '\0') {
		//			printf("\t%c", c);
		//			i += 1;
		//		}
		//		printf("\n");
		//	}

		//for (char read_char_cache; (read_char_cache = *read) != line_end; read
		//		= read + threads_per_block) {
		for (char read_char_cache; (read_char_cache = *read) != line_end; ++read) {
			//						printf("%c:\t", read_char_cache);
			//						for (short i = 0; i < read_index; ++i) {
			//							printf("\t");
			//						}
			matrix += (corridor_length + 1) * threads_per_block;
			//char read_char_cache;
			//while ((read_char_cache = read[read_index]) != line_end) {
			short left_cell = 0;
			matrix[0] = CIGAR_STOP;
			for (short ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {

				//init values
				left_cell += gap_ref;
				short diag_cell = local_matrix_line[ref_index * threads_per_block];
				//			printf("%c == %c\n", read_char_cache, scaff[ref_index * interleave_number]);
				int pointer = CIGAR_X;

#ifndef __BS__
				//if (read_char_cache == scaff[ref_index * interleave_number]) {
				//	diag_cell += match;//typedef struct {
				//	pointer = CIGAR_EQ;
				//} else if (read_char_cache != 'N' && read_char_cache != line_end) {
				//	diag_cell += mismatch;
				//}
				diag_cell += scores[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
				pointer = select(CIGAR_X, CIGAR_EQ, (read_char_cache == scaff[ref_index * interleave_number]));
#else
				short score = 0;
				if(direction[global_index] == 0) {
					score = scoresTC[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
				} else {
					score = scoresAG[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
				}
				diag_cell += score;
				//pointer = select(CIGAR_X, CIGAR_EQ, (score == match));
				pointer = select(CIGAR_X, CIGAR_EQ, (read_char_cache == scaff[ref_index * interleave_number]));
#endif

				//			int eq = (read_char_cache == scaff[ref_index * interleave_number]);
				//			diag_cell += select(mismatch, match, eq);
				//			if (!eq && (read_char_cache == 'N' || read_char_cache == line_end)) {
				//				diag_cell -= mismatch;
				//			}

				short up_cell = local_matrix_line[(ref_index + 1) * threads_per_block] + gap_read;

				//find max
				short max_cell = 0;
				max_cell = max(left_cell, max_cell);
				max_cell = max(diag_cell, max_cell);
				max_cell = max(up_cell, max_cell);

				//store "pointer"
				//int pointer = 0;//typedef struct {
				//	short best_ref_index;
				//	short best_read_index;
				//} Index;
				//if (max_cell > 0) {

				//						if (max_cell == up_cell) {
				//							//pointer = 2;
				//							pointer = CIGAR_I;
				//						} else if (max_cell == left_cell) {
				//							//pointer = 1;
				//							pointer = CIGAR_D;
				//						} else if (max_cell > 0) {
				//							//pointer = 4;
				//						} else {
				//							pointer = CIGAR_STOP;
				//						}

//chr4:1,803,533-1,803,603

				if(max_cell <= 0) {
					pointer = CIGAR_STOP;
				} else if(max_cell == diag_cell ||
					 	   max_cell == (local_matrix_line[ref_index * threads_per_block] + mismatch)) {
				} else if(max_cell == up_cell) {
					pointer = CIGAR_I;
				} else {
					pointer = CIGAR_D;
				}

				//if (max_cell == up_cell && max_cell != (local_matrix_line[ref_index * threads_per_block] + mismatch)) {
				//	//pointer = 2;
				//	pointer = CIGAR_I;
				//} else if (max_cell == left_cell && max_cell != (local_matrix_line[ref_index * threads_per_block] + mismatch)) {
				//	//pointer = 1;
				//	pointer = CIGAR_D;
				//} else if (max_cell > 0 && (max_cell == diag_cell || max_cell == (local_matrix_line[ref_index * threads_per_block] + mismatch) || max_cell == (local_matrix_line[ref_index] + match))) {
				//	//pointer = 4;
				//} else {
				//	pointer = CIGAR_STOP;
				//}

				//}
				//printf("\t%d", max_cell);
				matrix[(ref_index + 1) * threads_per_block] = pointer;

				if (max_cell > curr_max) {
					curr_max = max_cell;
					result[param_best_read_index] = read_index;
					result[param_best_ref_index] = ref_index;
				}

				left_cell = max_cell;
				local_matrix_line[ref_index * threads_per_block] = max_cell;
			}
			matrix[corridor_length * threads_per_block] = CIGAR_STOP;
			scaff += interleave_number;
			read_index += 1;

			//for (short i = 0; i < corridor_length + 1; ++i) {
			//	printf("%d ", matrix[i]);
			//}
			//printf("\n");
		}
		result[qend] = read_index - result[param_best_read_index] - 1;
		if (read_index == 0) {
			result[param_best_read_index] = result[param_best_read_index] = 0;
		}
	}

#ifndef __BS__
	__kernel void oclSW(__global char const * scaff, __global char const * read, __global float * results) {
#else
		__kernel void oclSW(__global char const * scaff, __global char const * read, __global float * results, __global char const * direction) {
#endif

			read = read + (global_index * read_length);
			scaff = scaff + ((global_index / interleave_number) * interleave_number * ref_length) + (global_index % interleave_number);

			__local
			short l_matrix_lines[MATRIX_LENGTH];
			__local
			short * matrix_lines = l_matrix_lines + local_index;
			//Init matrix lines
			for (short i = 0; i < corridor_length; ++i) {
				matrix_lines[i * threads_per_block] = 0;
			}

			short curr_max = -1;

			//for (char read_char_cache; (read_char_cache = *read) != line_end; read += interleave_number) {
			for (int read_pos = 0; read_pos < read_length; ++read_pos) {
				//char read_char_cache = *read;
				//read += interleave_number;
				char read_char_cache = *read++;
				short left_cell = 0;
				//		for (int ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {
				for (int ref_index = 0; ref_index < (corridor_length - 1); ++ref_index) {

					short diag_cell = matrix_lines[ref_index * threads_per_block];

#ifndef __BS__
					//int eq = (read_char_cache == scaff[ref_index * interleave_number]) && read_char_cache != line_end;
					//diag_cell += select(mismatch, match, eq);
					//if (!eq && (read_char_cache == 'N' || read_char_cache == line_end)) {
					//	diag_cell -= mismatch;
					//}
					diag_cell += scores[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
#else
					if(direction[global_index] == 0) {
						diag_cell += scoresTC[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
					} else {
						diag_cell += scoresAG[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
					}
#endif

					//diag_cell += select(0, match, eq);
					//diag_cell += select(0, mismatch, (!eq && read_char_cache != N && read_char_cache != line_end));

					//Max can be set to left_cell because we are computing the score row-wise, so the actual max is the left_cell for the next cell
					left_cell = max(null, (short) (left_cell + gap_ref));
					left_cell = max((short) (matrix_lines[ref_index * threads_per_block + threads_per_block] + gap_read), left_cell);
					left_cell = max(diag_cell, left_cell);

					curr_max = max(curr_max, left_cell);
					matrix_lines[ref_index * threads_per_block] = left_cell;
				}
				scaff += interleave_number;
				//scaff += 1;
			}
			results[global_index] = curr_max;
		}

#endif

#ifdef __CPU__

//__kernel void interleaveSeq(__global char const * src, __global char * dest) {
//	src = src + (global_index * ref_length * 4);
//
//	dest = dest + ((global_index / interleave_number) * interleave_number * ref_length * 4)
//	+ (global_index % interleave_number) * 4;
//	for (int i = 0; i < ref_length; ++i) {
//		dest[i * interleave_number * 4] = src[0];
//		dest[i * interleave_number * 4 + 1] = src[ref_length * 1];
//		dest[i * interleave_number * 4 + 2] = src[ref_length * 2];
//		dest[i * interleave_number * 4 + 3] = src[ref_length * 3];
//		src += 1;
//	}
//}

#ifndef __BS__
		__kernel void oclSW_Score(__global char const * scaff, __global char const * read, __global short * result, __global char * matrix) {
#else
			__kernel void oclSW_Score(__global char const * scaff, __global char const * read, __global short * result, __global char * matrix, __global char const * direction) {

			int4 direction4 =  convert_int4(vload4(global_index, direction));
#endif

				matrix = matrix + (global_index * ((corridor_length + 1) * (read_length + 1)) * 4);
				read = read + (global_index * read_length * 4);
				scaff = scaff + (global_index * ref_length * 4);
				result = result + result_number * global_index * 4;

//	int corridor_lengt4 = corridor_length * 4;

				float4 best_read_index4 = null4;
				float4 best_ref_index4 = null4;
				float4 qend4 = null4;

//	for(int k = 0; k < 4; ++k) {
//		printf("Ref  (GPU) %d:", k);
//		for(int i = 0; i < read_length + corridor_length - 1; ++i) {
//			printf("%c", scaff[i + k * ref_length]);
//		}
//		printf("\n");
//		printf("Read (GPU) %d:", k);
//		for(int i = 0; i < read_length; ++i) {
//			if(read[i + k * read_length] == '\0') {
//				printf("X");
//			} else {
//				printf("%c", read[i + k * read_length]);
//			}
//		}
//		printf("\n");
//	}

				if (read[0] != line_end) {
					float4 l_matrix_lines[MATRIX_LENGTH];
					float4 * local_matrix_line = l_matrix_lines + local_index * corridor_length;

					//Init matrix lines
					for (short i = 0; i < corridor_length; ++i) {
						local_matrix_line[i] = null4;
						vstore4(CIGAR_STOP, i, matrix);
					}
					vstore4(CIGAR_STOP, corridor_length, matrix);

					float4 curr_max = -1;
					float4 read_index = null4;

					for (short read_pos = 0; read_pos < read_length; ++read_pos) {
						//		while (true) {
						//			int read_pos = 0;
						int4 read_char_cache = (int4)(trans[read[read_pos + 0 * read_length]], trans[read[read_pos + 1 * read_length]], trans[read[read_pos + 2 * read_length]], trans[read[read_pos + 3 * read_length]]);
						//			read += 1;
						//			int4 test = read_char_cache == (int4) 5;
						//			printf("%d %d %d %d\n", test.s0, test.s1, test.s2, test.s3);
						//			if (test.s0 == -1 && test.s1 == -1 && test.s2 == -1 && test.s3 == -1) {
						//				break;
						//			}

						matrix += (corridor_length + 1) * 4;

						float4 left_cell = null4;

						vstore4(CIGAR_STOP, 0, matrix);

						for (short ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {

							//
							//init values
							left_cell += gap_ref4;
#ifndef __BS__
							float4 score = (float4)(scores[read_char_cache.s0][trans[scaff[ref_index]]], scores[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scores[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scores[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]);
							float4 diag_cell = local_matrix_line[ref_index] + score;
							float4 pointerX = select(CIGAR_X4, CIGAR_EQ4, (score == match));
#else
							float4 score = select((float4)(scoresAG[read_char_cache.s0][trans[scaff[ref_index]]], scoresAG[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scoresAG[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scoresAG[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]), (float4)(scoresTC[read_char_cache.s0][trans[scaff[ref_index]]], scoresTC[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scoresTC[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scoresTC[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]), direction4 == 0);

							float4 diag_cell = local_matrix_line[ref_index] + score;
							float4 pointerX = select(CIGAR_X4, CIGAR_EQ4, (read_char_cache == (int4)(trans[scaff[ref_index]], trans[scaff[ref_index + 1 * ref_length]], trans[scaff[ref_index + 2 * ref_length]], trans[scaff[ref_index + 3 * ref_length]])));
#endif

							//int4 pointer = select(CIGAR_X, CIGAR_EQ, (score == match));
							//
							float4 up_cell = local_matrix_line[(ref_index + 1)] + gap_read4;

							//find max
							float4 max_cell = null4;
							max_cell = max(left_cell, max_cell);
							max_cell = max(diag_cell, max_cell);
							max_cell = max(up_cell, max_cell);

							//pointer = select(pointer, CIGAR_STOP, (max_cell == 0));

							float4 pointer = select(pointerX, CIGAR_D, max_cell == left_cell);
							pointer = select(pointer, CIGAR_I, max_cell == up_cell);
							pointer = select(pointer, pointerX, max_cell == diag_cell || max_cell == (local_matrix_line[ref_index * threads_per_block] + mismatch));
							pointer = select(pointer, CIGAR_STOP, max_cell <= 0);

							//max_cell > 0 && (max_cell == diag_cell || max_cell == (local_matrix_line[ref_index * threads_per_block] + mismatch) || max_cell == (local_matrix_line[ref_index] + match))

							vstore4(convert_char4(pointer), (ref_index + 1), matrix);

							best_read_index4 = select(best_read_index4, read_index, (max_cell > curr_max));
							best_ref_index4 = select(best_ref_index4, ref_index, (max_cell > curr_max));

							curr_max = max(curr_max, max_cell);

							left_cell = max_cell;

							local_matrix_line[ref_index] = max_cell;

						}
						vstore4(CIGAR_STOP, corridor_length, matrix);
						scaff += 1;
						//			read_index += 1;
						//			read_index = select(read_index + 1, read_index, test);
						read_index = select(read_index + 1, read_index, read_char_cache == (int4) 6);
						//			read_index -= convert_float4(test);
						//			read_index -= read_char_cache == 5.0;
					}
					qend4 = read_index - best_read_index4 - 1;
				}

				vstore4(convert_short4(best_read_index4), param_best_read_index, result);
				vstore4(convert_short4(best_ref_index4), param_best_ref_index, result);
				vstore4(convert_short4(qend4), qend, result);
			}

#ifndef __BS__
			__kernel void oclSW(__global char const * scaff, __global char const * read, __global float * results) {
#else
				__kernel void oclSW(__global char const * scaff, __global char const * read, __global float * results, __global char const * direction) {

				int4 direction4 =  convert_int4(vload4(global_index, direction));
#endif

					scaff = scaff + (global_index * ref_length * 4);
					read = read + (global_index * read_length * 4);

					float4 l_matrix_lines[MATRIX_LENGTH];
					float4 * matrix_lines = l_matrix_lines + local_index * corridor_length;

					float4 curr_max = (float4)(-1.0f);
					if (read[0] != line_end) {
						//printf("Ref:  %s\n", scaff);
						//printf("Read: %s\n", read);
						//Init matrix lines
						for (short i = 0; i < corridor_length; ++i) {
							matrix_lines[i] = null4;
						}
						for (int read_pos = 0; read_pos < read_length; ++read_pos) {

							int4 read_char_cache = (int4)(trans[read[read_pos]], trans[read[read_pos + 1 * read_length]], trans[read[read_pos + 2 * read_length]], trans[read[read_pos + 3 * read_length]]);

							float4 left_cell = 0;
							for (int ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {

								//Max can be set to left_cell because we are computing the score row-wise, so the actual max is the left_cell for the next cell
								left_cell = max(null4, left_cell + gap_ref);
								left_cell = max(matrix_lines[(ref_index + 1)] + gap_read, left_cell);

#ifndef __BS__
								float4 scores4 = (float4)(scores[read_char_cache.s0][trans[scaff[ref_index]]], scores[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scores[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scores[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]);
#else
								float4 scores4 = select((float4)(scoresAG[read_char_cache.s0][trans[scaff[ref_index]]], scoresAG[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scoresAG[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scoresAG[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]), (float4)(scoresTC[read_char_cache.s0][trans[scaff[ref_index]]], scoresTC[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scoresTC[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scoresTC[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]), direction4 == 0);
#endif

								left_cell = max(matrix_lines[ref_index] + scores4, left_cell);

								curr_max = max(curr_max, left_cell);

								matrix_lines[ref_index] = left_cell;
							}
							scaff += 1;
						}
					}
					vstore4(curr_max, global_index, results);

				}

				__kernel void oclSW_wSSE(__global char const * scaff, __global char const * read, __global float * results) {

					scaff = scaff + (global_index * ref_length);
					read = read + (global_index * read_length);

					float l_matrix_lines[MATRIX_LENGTH];
					float * matrix_lines = l_matrix_lines + local_index * corridor_length;

					float curr_max = -1.0f;
					if (read[0] != line_end) {
						//printf("Refxxx: %s\n", scaff);
						//Init matrix lines
						for (short i = 0; i < corridor_length; ++i) {
							matrix_lines[i] = 0.0f;
						}
						for (int read_pos = 0; read_pos < read_length; ++read_pos) {

							int read_char_cache = trans[read[read_pos]];

							float left_cell = 0.0f;
							for (int ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {

								//Max can be set to left_cell because we are computing the score row-wise, so the actual max is the left_cell for the next cell
								left_cell = max(0.0f, left_cell + gap_ref);
								left_cell = max(matrix_lines[(ref_index + 1)] + gap_read, left_cell);

								//printf("%c", 'X');
								//printf("%c == %c\n", read_char_cache, scaff[ref_index]);
								float score = scores[read_char_cache][trans[scaff[ref_index]]];

								left_cell = max(matrix_lines[ref_index] + score, left_cell);

								curr_max = max(curr_max, left_cell);

								matrix_lines[ref_index] = left_cell;
							}
							scaff += 1;
						}
					}
					results[global_index] = curr_max;

					//results[global_index] = -101.0f;
				}

//__kernel void oclSW(__global char const * _scaff, __global char const * _read, __global float * results) {
//	for (int x = 0; x < 4; ++x) {
//		__global
//		char const *scaff = _scaff + (global_index * ref_length * 4 * 4) + 4 * x * ref_length;
//		__global
//		char const *read = _read + (global_index * read_length * 4 * 4) + 4 * x * read_length;
//
//		float4 l_matrix_lines[MATRIX_LENGTH];
//		float4 * matrix_lines = l_matrix_lines + local_index * corridor_length;
//
//		float4 curr_max = (float4)(-1.0f, -1.0f, -1.0f, -1.0f);
//		if (read[0] != line_end) {
//			//printf("Ref: %s\n", scaff);
//			//Init matrix lines
//			for (short i = 0; i < corridor_length; ++i) {
//				matrix_lines[i] = null4;
//			}
//			for (int read_pos = 0; read_pos < read_length; ++read_pos) {
//
//				int4 read_char_cache = (int4)(trans[read[read_pos]], trans[read[read_pos + 1 * read_length]], trans[read[read_pos + 2 * read_length]], trans[read[read_pos + 3 * read_length]]);
//
//				float4 left_cell = 0;
//				for (int ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {
//
//					//Max can be set to left_cell because we are computing the score row-wise, so the actual max is the left_cell for the next cell
//					left_cell = max(null4, left_cell + gap_ref);
//					left_cell = max(matrix_lines[(ref_index + 1)] + gap_read, left_cell);
//
//					float4 scores4 = (float4)(scores[read_char_cache.x][trans[scaff[ref_index]]], scores[read_char_cache.y][trans[scaff[ref_index + 1 * ref_length]]], scores[read_char_cache.z][trans[scaff[ref_index + 2 * ref_length]]], scores[read_char_cache.w][trans[scaff[ref_index + 3 * ref_length]]]);
//
//					left_cell = max(matrix_lines[ref_index] + scores4, left_cell);
//
//					curr_max = max(curr_max, left_cell);
//
//					matrix_lines[ref_index] = left_cell;
//				}
//				scaff += 1;
//			}
//		}
//		vstore4(curr_max, global_index * 4, results + 4 * x);
//	}
//	//	scaff = _scaff + global_index * (ref_length * 8) + 4 * ref_length;
//	//	read = _read + global_index * (read_length * 8) + 4 * read_length;
//	//
//	//	curr_max = (float4)(-1.0f, -1.0f, -1.0f, -1.0f);
//	//	if (read[0] != line_end) {
//	//		//printf("Ref: %s\n", scaff);
//	//
//	//		float4 l_matrix_lines[MATRIX_LENGTH];
//	//		float4 * matrix_lines = l_matrix_lines + local_index * corridor_length;
//	//		//Init matrix lines
//	//		for (short i = 0; i < corridor_length; ++i) {
//	//			matrix_lines[i] = null4;
//	//		}
//	//
//	//		for (int read_pos = 0; read_pos < read_length; ++read_pos) {
//	//
//	//			int4 read_char_cache = (int4)(trans[read[read_pos]], trans[read[read_pos + 1 * read_length]], trans[read[read_pos + 2 * read_length]], trans[read[read_pos + 3 * read_length]]);
//	//
//	//			float4 left_cell = 0;
//	//			for (int ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {
//	//
//	//				//Max can be set to left_cell because we are computing the score row-wise, so the actual max is the left_cell for the next cell
//	//				left_cell = max(null4, left_cell + gap_ref);
//	//				left_cell = max(matrix_lines[(ref_index + 1)] + gap_read, left_cell);
//	//
//	//				float4 scores4 = (float4)(scores[read_char_cache.x][trans[scaff[ref_index]]], scores[read_char_cache.y][trans[scaff[ref_index + 1 * ref_length]]], scores[read_char_cache.z][trans[scaff[ref_index + 2 * ref_length]]], scores[read_char_cache.w][trans[scaff[ref_index + 3 * ref_length]]]);
//	//
//	//				left_cell = max(matrix_lines[ref_index] + scores4, left_cell);
//	//
//	//				curr_max = max(curr_max, left_cell);
//	//
//	//				matrix_lines[ref_index] = left_cell;
//	//			}
//	//			scaff += 1;
//	//		}
//	//	}
//	//	vstore4(curr_max, global_index * 2, results + 4);
//}
#endif

__kernel
void interleaveSeq(__global char const * _src, __global char * dest) {

	__global char const * src = _src + ((global_index) * ref_length);
	dest = dest + ((global_index / interleave_number) * interleave_number * ref_length) + global_index % interleave_number;

	int i = 0;
	for (i = 0; i < ref_length / 4 * 4; i += 4) {
		char4 temp = vload4(0, src);
		dest[(i) * interleave_number] = temp.s0;
		dest[(i + 1) * interleave_number] = temp.s1;
		dest[(i + 2) * interleave_number] = temp.s2;
		dest[(i + 3) * interleave_number] = temp.s3;
		src += 4;
	}

	for (; i < ref_length; i += 1) {
		dest[(i) * interleave_number] = *src++;
	}
}

#ifdef __GPU__

#ifndef __BS__
__kernel void oclSW_Score(__global char const * scaff, __global char const * read, __global short * result, __global char * matrix) {
#else
	__kernel void oclSW_Score(__global char const * scaff, __global char const * read, __global short * result, __global char * matrix, __global char const * direction) {
#endif

		matrix = matrix + ((global_index / threads_per_block) * threads_per_block * ((corridor_length + 1) * (read_length + 1))) + global_index % threads_per_block;
		read = read + (global_index * read_length);
		scaff = scaff + ((global_index / interleave_number) * interleave_number * ref_length) + global_index % interleave_number;
		result = result + result_number * global_index;

		__local
		short l_matrix_lines[MATRIX_LENGTH];
		__local
		//	short * local_matrix_line = l_matrix_lines + local_index * corridor_length;
		short * local_matrix_line = l_matrix_lines + local_index;

		//Init matrix lines
		for (short i = 0; i < corridor_length; ++i) {
			local_matrix_line[i * threads_per_block] = 0;
			matrix[i * threads_per_block] = CIGAR_STOP;
		}
		matrix[corridor_length * threads_per_block] = CIGAR_STOP;

		short curr_max = -1;
		short read_index = 0;

		//	if (read[0] != '\0') {
		//		//printf("GPU Ref : %s\n", scaff);
		//		//printf("GPU Read: %s\n", read);
		//		printf("S:\t");
		//		char c;
		//		int i = 0;
		//		while ((c = scaff[i * interleave_number]) != '\0') {
		//			printf("\t%c", c);
		//			i += 1;
		//		}
		//		printf("\n");
		//	}

		//for (char read_char_cache; (read_char_cache = *read) != line_end; read
		//		= read + threads_per_block) {
		for (char read_char_cache; (read_char_cache = *read) != line_end; ++read) {
			//						printf("%c:\t", read_char_cache);
			//						for (short i = 0; i < read_index; ++i) {
			//							printf("\t");
			//						}
			matrix += (corridor_length + 1) * threads_per_block;
			//char read_char_cache;
			//while ((read_char_cache = read[read_index]) != line_end) {
			short left_cell = 0;
			matrix[0] = CIGAR_STOP;
			for (short ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {

				//init values
				left_cell += gap_ref;
				short diag_cell = local_matrix_line[ref_index * threads_per_block];
				//			printf("%c == %c\n", read_char_cache, scaff[ref_index * interleave_number]);
				int pointer = CIGAR_X;

#ifndef __BS__
				//if (read_char_cache == scaff[ref_index * interleave_number]) {
				//	diag_cell += match;//typedef struct {
				//	pointer = CIGAR_EQ;
				//} else if (read_char_cache != 'N' && read_char_cache != line_end) {
				//	diag_cell += mismatch;
				//}
				diag_cell += scores[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
				pointer = select(CIGAR_X, CIGAR_EQ, (read_char_cache == scaff[ref_index * interleave_number]));
#else
				short score = 0;
				if(direction[global_index] == 0) {
					score = scoresTC[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
				} else {
					score = scoresAG[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
				}
				diag_cell += score;
				//pointer = select(CIGAR_X, CIGAR_EQ, (score == match));
				pointer = select(CIGAR_X, CIGAR_EQ, (read_char_cache == scaff[ref_index * interleave_number]));
#endif

				//			int eq = (read_char_cache == scaff[ref_index * interleave_number]);
				//			diag_cell += select(mismatch, match, eq);
				//			if (!eq && (read_char_cache == 'N' || read_char_cache == line_end)) {
				//				diag_cell -= mismatch;
				//			}

				short up_cell = local_matrix_line[(ref_index + 1) * threads_per_block] + gap_read;

				//find max
				short max_cell = 0;
				max_cell = max(left_cell, max_cell);
				max_cell = max(diag_cell, max_cell);
				max_cell = max(up_cell, max_cell);

				//store "pointer"
				//int pointer = 0;//typedef struct {
				//	short best_ref_index;
				//	short best_read_index;
				//} Index;
				//if (max_cell > 0) {

				//						if (max_cell == up_cell) {
				//							//pointer = 2;
				//							pointer = CIGAR_I;
				//						} else if (max_cell == left_cell) {
				//							//pointer = 1;
				//							pointer = CIGAR_D;
				//						} else if (max_cell > 0) {
				//							//pointer = 4;
				//						} else {
				//							pointer = CIGAR_STOP;
				//						}

				if (max_cell == up_cell && max_cell != (local_matrix_line[ref_index * threads_per_block] + mismatch)) {
					//pointer = 2;
					pointer = CIGAR_I;
				} else if (max_cell == left_cell && max_cell != (local_matrix_line[ref_index * threads_per_block] + mismatch)) {
					//pointer = 1;
					pointer = CIGAR_D;
				} else if (max_cell > 0 && (max_cell == diag_cell || max_cell == (local_matrix_line[ref_index * threads_per_block] + mismatch) || max_cell == (local_matrix_line[ref_index] + match))) {
					//pointer = 4;
				} else {
					pointer = CIGAR_STOP;
				}

				//}
				//printf("\t%d", max_cell);
				matrix[(ref_index + 1) * threads_per_block] = pointer;

				if (max_cell > curr_max) {
					curr_max = max_cell;
					result[param_best_read_index] = read_index;
					result[param_best_ref_index] = ref_index;
				}

				left_cell = max_cell;
				local_matrix_line[ref_index * threads_per_block] = max_cell;
			}
			matrix[corridor_length * threads_per_block] = CIGAR_STOP;
			scaff += interleave_number;
			read_index += 1;

			//for (short i = 0; i < corridor_length + 1; ++i) {
			//	printf("%d ", matrix[i]);
			//}
			//printf("\n");
		}
		result[qend] = read_index - result[param_best_read_index] - 1;
		if (read_index == 0) {
			result[param_best_read_index] = result[param_best_read_index] = 0;
		}
	}

#ifndef __BS__
	__kernel void oclSW(__global char const * scaff, __global char const * read, __global float * results) {
#else
		__kernel void oclSW(__global char const * scaff, __global char const * read, __global float * results, __global char const * direction) {
#endif

			read = read + (global_index * read_length);
			scaff = scaff + ((global_index / interleave_number) * interleave_number * ref_length) + (global_index % interleave_number);

			__local
			short l_matrix_lines[MATRIX_LENGTH];
			__local
			short * matrix_lines = l_matrix_lines + local_index;
			//Init matrix lines
			for (short i = 0; i < corridor_length; ++i) {
				matrix_lines[i * threads_per_block] = 0;
			}

			short curr_max = -1;

			//for (char read_char_cache; (read_char_cache = *read) != line_end; read += interleave_number) {
			for (int read_pos = 0; read_pos < read_length; ++read_pos) {
				//char read_char_cache = *read;
				//read += interleave_number;
				char read_char_cache = *read++;
				short left_cell = 0;
				//		for (int ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {
				for (int ref_index = 0; ref_index < (corridor_length - 1); ++ref_index) {

					short diag_cell = matrix_lines[ref_index * threads_per_block];

#ifndef __BS__
					//int eq = (read_char_cache == scaff[ref_index * interleave_number]) && read_char_cache != line_end;
					//diag_cell += select(mismatch, match, eq);
					//if (!eq && (read_char_cache == 'N' || read_char_cache == line_end)) {
					//	diag_cell -= mismatch;
					//}
					diag_cell += scores[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
#else
					if(direction[global_index] == 0) {
						diag_cell += scoresTC[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
					} else {
						diag_cell += scoresAG[trans[read_char_cache]][trans[scaff[ref_index * interleave_number]]];
					}
#endif

					//diag_cell += select(0, match, eq);
					//diag_cell += select(0, mismatch, (!eq && read_char_cache != N && read_char_cache != line_end));

					//Max can be set to left_cell because we are computing the score row-wise, so the actual max is the left_cell for the next cell
					left_cell = max(null, (short) (left_cell + gap_ref));
					left_cell = max((short) (matrix_lines[ref_index * threads_per_block + threads_per_block] + gap_read), left_cell);
					left_cell = max(diag_cell, left_cell);

					curr_max = max(curr_max, left_cell);
					matrix_lines[ref_index * threads_per_block] = left_cell;
				}
				scaff += interleave_number;
				//scaff += 1;
			}
			results[global_index] = curr_max;
		}

#endif

#ifdef __CPU__

//__kernel void interleaveSeq(__global char const * src, __global char * dest) {
//	src = src + (global_index * ref_length * 4);
//
//	dest = dest + ((global_index / interleave_number) * interleave_number * ref_length * 4)
//	+ (global_index % interleave_number) * 4;
//	for (int i = 0; i < ref_length; ++i) {
//		dest[i * interleave_number * 4] = src[0];
//		dest[i * interleave_number * 4 + 1] = src[ref_length * 1];
//		dest[i * interleave_number * 4 + 2] = src[ref_length * 2];
//		dest[i * interleave_number * 4 + 3] = src[ref_length * 3];
//		src += 1;
//	}
//}

#ifndef __BS__
		__kernel void oclSW_Score(__global char const * scaff, __global char const * read, __global short * result, __global char * matrix) {
#else
			__kernel void oclSW_Score(__global char const * scaff, __global char const * read, __global short * result, __global char * matrix, __global char const * direction) {

			int4 direction4 =  convert_int4(vload4(global_index, direction));
#endif

				matrix = matrix + (global_index * ((corridor_length + 1) * (read_length + 1)) * 4);
				read = read + (global_index * read_length * 4);
				scaff = scaff + (global_index * ref_length * 4);
				result = result + result_number * global_index * 4;

//	int corridor_lengt4 = corridor_length * 4;

				float4 best_read_index4 = null4;
				float4 best_ref_index4 = null4;
				float4 qend4 = null4;

//	for(int k = 0; k < 4; ++k) {
//		printf("Ref  (GPU) %d:", k);
//		for(int i = 0; i < read_length + corridor_length - 1; ++i) {
//			printf("%c", scaff[i + k * ref_length]);
//		}
//		printf("\n");
//		printf("Read (GPU) %d:", k);
//		for(int i = 0; i < read_length; ++i) {
//			if(read[i + k * read_length] == '\0') {
//				printf("X");
//			} else {
//				printf("%c", read[i + k * read_length]);
//			}
//		}
//		printf("\n");
//	}

				if (read[0] != line_end) {
					float4 l_matrix_lines[MATRIX_LENGTH];
					float4 * local_matrix_line = l_matrix_lines + local_index * corridor_length;

					//Init matrix lines
					for (short i = 0; i < corridor_length; ++i) {
						local_matrix_line[i] = null4;
						vstore4(CIGAR_STOP, i, matrix);
					}
					vstore4(CIGAR_STOP, corridor_length, matrix);

					float4 curr_max = -1;
					float4 read_index = null4;

					for (short read_pos = 0; read_pos < read_length; ++read_pos) {
						//		while (true) {
						//			int read_pos = 0;
						int4 read_char_cache = (int4)(trans[read[read_pos + 0 * read_length]], trans[read[read_pos + 1 * read_length]], trans[read[read_pos + 2 * read_length]], trans[read[read_pos + 3 * read_length]]);
						//			read += 1;
						//			int4 test = read_char_cache == (int4) 5;
						//			printf("%d %d %d %d\n", test.s0, test.s1, test.s2, test.s3);
						//			if (test.s0 == -1 && test.s1 == -1 && test.s2 == -1 && test.s3 == -1) {
						//				break;
						//			}

						matrix += (corridor_length + 1) * 4;

						float4 left_cell = null4;

						vstore4(CIGAR_STOP, 0, matrix);

						for (short ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {

							//
							//init values
							left_cell += gap_ref4;
#ifndef __BS__
							float4 score = (float4)(scores[read_char_cache.s0][trans[scaff[ref_index]]], scores[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scores[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scores[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]);
							float4 diag_cell = local_matrix_line[ref_index] + score;
							float4 pointer = select(CIGAR_X4, CIGAR_EQ4, (score == match));
#else
							float4 score = select((float4)(scoresAG[read_char_cache.s0][trans[scaff[ref_index]]], scoresAG[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scoresAG[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scoresAG[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]), (float4)(scoresTC[read_char_cache.s0][trans[scaff[ref_index]]], scoresTC[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scoresTC[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scoresTC[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]), direction4 == 0);

							float4 diag_cell = local_matrix_line[ref_index] + score;
							float4 pointer = select(CIGAR_X4, CIGAR_EQ4, (read_char_cache == (int4)(trans[scaff[ref_index]], trans[scaff[ref_index + 1 * ref_length]], trans[scaff[ref_index + 2 * ref_length]], trans[scaff[ref_index + 3 * ref_length]])));
#endif

							//int4 pointer = select(CIGAR_X, CIGAR_EQ, (score == match));
							//
							float4 up_cell = local_matrix_line[(ref_index + 1)] + gap_read4;

							//find max
							float4 max_cell = null4;
							max_cell = max(left_cell, max_cell);
							max_cell = max(diag_cell, max_cell);
							max_cell = max(up_cell, max_cell);

							//pointer = select(pointer, CIGAR_STOP, (max_cell == 0));

							pointer = select(CIGAR_STOP, pointer, (max_cell > 0 && (max_cell == diag_cell || max_cell == (local_matrix_line[ref_index] + mismatch) || max_cell == (local_matrix_line[ref_index] + match))));
							pointer = select(pointer, CIGAR_D, (max_cell == left_cell && max_cell != (local_matrix_line[ref_index] + mismatch)));
							pointer = select(pointer, CIGAR_I, (max_cell == up_cell && max_cell != (local_matrix_line[ref_index] + mismatch)));

							//max_cell > 0 && (max_cell == diag_cell || max_cell == (local_matrix_line[ref_index * threads_per_block] + mismatch) || max_cell == (local_matrix_line[ref_index] + match))

							vstore4(convert_char4(pointer), (ref_index + 1), matrix);

							best_read_index4 = select(best_read_index4, read_index, (max_cell > curr_max));
							best_ref_index4 = select(best_ref_index4, ref_index, (max_cell > curr_max));

							curr_max = max(curr_max, max_cell);

							left_cell = max_cell;

							local_matrix_line[ref_index] = max_cell;

						}
						vstore4(CIGAR_STOP, corridor_length, matrix);
						scaff += 1;
						//			read_index += 1;
						//			read_index = select(read_index + 1, read_index, test);
						read_index = select(read_index + 1, read_index, read_char_cache == (int4) 6);
						//			read_index -= convert_float4(test);
						//			read_index -= read_char_cache == 5.0;
					}
					qend4 = read_index - best_read_index4 - 1;
				}

				vstore4(convert_short4(best_read_index4), param_best_read_index, result);
				vstore4(convert_short4(best_ref_index4), param_best_ref_index, result);
				vstore4(convert_short4(qend4), qend, result);
			}

#ifndef __BS__
			__kernel void oclSW(__global char const * scaff, __global char const * read, __global float * results) {
#else
				__kernel void oclSW(__global char const * scaff, __global char const * read, __global float * results, __global char const * direction) {

				int4 direction4 =  convert_int4(vload4(global_index, direction));
#endif

					scaff = scaff + (global_index * ref_length * 4);
					read = read + (global_index * read_length * 4);

					float4 l_matrix_lines[MATRIX_LENGTH];
					float4 * matrix_lines = l_matrix_lines + local_index * corridor_length;

					float4 curr_max = (float4)(-1.0f);
					if (read[0] != line_end) {
						//printf("Ref:  %s\n", scaff);
						//printf("Read: %s\n", read);
						//Init matrix lines
						for (short i = 0; i < corridor_length; ++i) {
							matrix_lines[i] = null4;
						}
						for (int read_pos = 0; read_pos < read_length; ++read_pos) {

							int4 read_char_cache = (int4)(trans[read[read_pos]], trans[read[read_pos + 1 * read_length]], trans[read[read_pos + 2 * read_length]], trans[read[read_pos + 3 * read_length]]);

							float4 left_cell = 0;
							for (int ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {

								//Max can be set to left_cell because we are computing the score row-wise, so the actual max is the left_cell for the next cell
								left_cell = max(null4, left_cell + gap_ref);
								left_cell = max(matrix_lines[(ref_index + 1)] + gap_read, left_cell);

#ifndef __BS__
								float4 scores4 = (float4)(scores[read_char_cache.s0][trans[scaff[ref_index]]], scores[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scores[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scores[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]);
#else
								float4 scores4 = select((float4)(scoresAG[read_char_cache.s0][trans[scaff[ref_index]]], scoresAG[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scoresAG[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scoresAG[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]), (float4)(scoresTC[read_char_cache.s0][trans[scaff[ref_index]]], scoresTC[read_char_cache.s1][trans[scaff[ref_index + 1 * ref_length]]], scoresTC[read_char_cache.s2][trans[scaff[ref_index + 2 * ref_length]]], scoresTC[read_char_cache.s3][trans[scaff[ref_index + 3 * ref_length]]]), direction4 == 0);
#endif

								left_cell = max(matrix_lines[ref_index] + scores4, left_cell);

								curr_max = max(curr_max, left_cell);

								matrix_lines[ref_index] = left_cell;
							}
							scaff += 1;
						}
					}
					vstore4(curr_max, global_index, results);

				}

				__kernel void oclSW_wSSE(__global char const * scaff, __global char const * read, __global float * results) {

					scaff = scaff + (global_index * ref_length);
					read = read + (global_index * read_length);

					float l_matrix_lines[MATRIX_LENGTH];
					float * matrix_lines = l_matrix_lines + local_index * corridor_length;

					float curr_max = -1.0f;
					if (read[0] != line_end) {
						//printf("Refxxx: %s\n", scaff);
						//Init matrix lines
						for (short i = 0; i < corridor_length; ++i) {
							matrix_lines[i] = 0.0f;
						}
						for (int read_pos = 0; read_pos < read_length; ++read_pos) {

							int read_char_cache = trans[read[read_pos]];

							float left_cell = 0.0f;
							for (int ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {

								//Max can be set to left_cell because we are computing the score row-wise, so the actual max is the left_cell for the next cell
								left_cell = max(0.0f, left_cell + gap_ref);
								left_cell = max(matrix_lines[(ref_index + 1)] + gap_read, left_cell);

								//printf("%c", 'X');
								//printf("%c == %c\n", read_char_cache, scaff[ref_index]);
								float score = scores[read_char_cache][trans[scaff[ref_index]]];

								left_cell = max(matrix_lines[ref_index] + score, left_cell);

								curr_max = max(curr_max, left_cell);

								matrix_lines[ref_index] = left_cell;
							}
							scaff += 1;
						}
					}
					results[global_index] = curr_max;

					//results[global_index] = -101.0f;
				}

//__kernel void oclSW(__global char const * _scaff, __global char const * _read, __global float * results) {
//	for (int x = 0; x < 4; ++x) {
//		__global
//		char const *scaff = _scaff + (global_index * ref_length * 4 * 4) + 4 * x * ref_length;
//		__global
//		char const *read = _read + (global_index * read_length * 4 * 4) + 4 * x * read_length;
//
//		float4 l_matrix_lines[MATRIX_LENGTH];
//		float4 * matrix_lines = l_matrix_lines + local_index * corridor_length;
//
//		float4 curr_max = (float4)(-1.0f, -1.0f, -1.0f, -1.0f);
//		if (read[0] != line_end) {
//			//printf("Ref: %s\n", scaff);
//			//Init matrix lines
//			for (short i = 0; i < corridor_length; ++i) {
//				matrix_lines[i] = null4;
//			}
//			for (int read_pos = 0; read_pos < read_length; ++read_pos) {
//
//				int4 read_char_cache = (int4)(trans[read[read_pos]], trans[read[read_pos + 1 * read_length]], trans[read[read_pos + 2 * read_length]], trans[read[read_pos + 3 * read_length]]);
//
//				float4 left_cell = 0;
//				for (int ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {
//
//					//Max can be set to left_cell because we are computing the score row-wise, so the actual max is the left_cell for the next cell
//					left_cell = max(null4, left_cell + gap_ref);
//					left_cell = max(matrix_lines[(ref_index + 1)] + gap_read, left_cell);
//
//					float4 scores4 = (float4)(scores[read_char_cache.x][trans[scaff[ref_index]]], scores[read_char_cache.y][trans[scaff[ref_index + 1 * ref_length]]], scores[read_char_cache.z][trans[scaff[ref_index + 2 * ref_length]]], scores[read_char_cache.w][trans[scaff[ref_index + 3 * ref_length]]]);
//
//					left_cell = max(matrix_lines[ref_index] + scores4, left_cell);
//
//					curr_max = max(curr_max, left_cell);
//
//					matrix_lines[ref_index] = left_cell;
//				}
//				scaff += 1;
//			}
//		}
//		vstore4(curr_max, global_index * 4, results + 4 * x);
//	}
//	//	scaff = _scaff + global_index * (ref_length * 8) + 4 * ref_length;
//	//	read = _read + global_index * (read_length * 8) + 4 * read_length;
//	//
//	//	curr_max = (float4)(-1.0f, -1.0f, -1.0f, -1.0f);
//	//	if (read[0] != line_end) {
//	//		//printf("Ref: %s\n", scaff);
//	//
//	//		float4 l_matrix_lines[MATRIX_LENGTH];
//	//		float4 * matrix_lines = l_matrix_lines + local_index * corridor_length;
//	//		//Init matrix lines
//	//		for (short i = 0; i < corridor_length; ++i) {
//	//			matrix_lines[i] = null4;
//	//		}
//	//
//	//		for (int read_pos = 0; read_pos < read_length; ++read_pos) {
//	//
//	//			int4 read_char_cache = (int4)(trans[read[read_pos]], trans[read[read_pos + 1 * read_length]], trans[read[read_pos + 2 * read_length]], trans[read[read_pos + 3 * read_length]]);
//	//
//	//			float4 left_cell = 0;
//	//			for (int ref_index = 0; ref_index < corridor_length - 1; ++ref_index) {
//	//
//	//				//Max can be set to left_cell because we are computing the score row-wise, so the actual max is the left_cell for the next cell
//	//				left_cell = max(null4, left_cell + gap_ref);
//	//				left_cell = max(matrix_lines[(ref_index + 1)] + gap_read, left_cell);
//	//
//	//				float4 scores4 = (float4)(scores[read_char_cache.x][trans[scaff[ref_index]]], scores[read_char_cache.y][trans[scaff[ref_index + 1 * ref_length]]], scores[read_char_cache.z][trans[scaff[ref_index + 2 * ref_length]]], scores[read_char_cache.w][trans[scaff[ref_index + 3 * ref_length]]]);
//	//
//	//				left_cell = max(matrix_lines[ref_index] + scores4, left_cell);
//	//
//	//				curr_max = max(curr_max, left_cell);
//	//
//	//				matrix_lines[ref_index] = left_cell;
//	//			}
//	//			scaff += 1;
//	//		}
//	//	}
//	//	vstore4(curr_max, global_index * 2, results + 4);
//}
#endif


Remove src_pixels_per_line and pixel_step from bilinear second pass.

These were both equal to the output width and unnecessary.

#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
#pragma OPENCL EXTENSION cl_amd_printf : enable

__constant int bilinear_filters[8][2] = {
    { 128, 0},
    { 112, 16},
    { 96, 32},
    { 80, 48},
    { 64, 64},
    { 48, 80},
    { 32, 96},
    { 16, 112}
};

__constant short sub_pel_filters[8][8] = {
    //These were originally 8x6, but are padded for vector ops
    { 0, 0, 128, 0, 0, 0, 0, 0}, /* note that 1/8 pel positions are just as per alpha -0.5 bicubic */
    { 0, -6, 123, 12, -1, 0, 0, 0},
    { 2, -11, 108, 36, -8, 1, 0, 0}, /* New 1/4 pel 6 tap filter */
    { 0, -9, 93, 50, -6, 0, 0, 0},
    { 3, -16, 77, 77, -16, 3, 0, 0}, /* New 1/2 pel 6 tap filter */
    { 0, -6, 50, 93, -9, 0, 0, 0},
    { 1, -8, 36, 108, -11, 2, 0, 0}, /* New 1/4 pel 6 tap filter */
    { 0, -1, 12, 123, -6, 0, 0, 0},
};

kernel void vp8_filter_block2d_first_pass_kernel(
    __global unsigned char *src_base,
    int src_offset,
    __global int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
){
    uint tid = get_global_id(0);

    global unsigned char *src_ptr = &src_base[src_offset];
    //Note that src_offset will be reset later, which is why we use it now

    int Temp;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (tid < (output_width*output_height)){
        src_offset = tid + (tid/output_width * (src_pixels_per_line - output_width)) + 2;

        Temp = (int)(src_ptr[src_offset - 2] * vp8_filter[0]) +
           (int)(src_ptr[src_offset - 1] * vp8_filter[1]) +
           (int)(src_ptr[src_offset]     * vp8_filter[2]) +
           (int)(src_ptr[src_offset + 1] * vp8_filter[3]) +
           (int)(src_ptr[src_offset + 2] * vp8_filter[4]) +
           (int)(src_ptr[src_offset + 3] * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);      /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;

        if (Temp < 0)
            Temp = 0;
        else if ( Temp > 255 )
            Temp = 255;

        output_ptr[tid] = Temp;
    }

}

kernel void vp8_filter_block2d_second_pass_kernel
(
    __global int *src_base,
    int src_offset,
    __global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
) {

    uint i = get_global_id(0);

    global int *src_ptr = &src_base[src_offset];
    global unsigned char *output_ptr = &output_base[output_offset];

    int out_offset; //Not same as output_offset...
    int Temp;
    int PS2 = 2*(int)pixel_step;
    int PS3 = 3*(int)pixel_step;

    unsigned int src_increment = src_pixels_per_line - output_width;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (i < (output_width * output_height)){
        out_offset = i/output_width;
        src_offset = out_offset;

        src_offset = i + (src_offset * src_increment);
        out_offset = i%output_width + (out_offset * output_pitch);

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset - PS2] * vp8_filter[0]) +
           ((int)src_ptr[src_offset -(int)pixel_step] * vp8_filter[1]) +
           ((int)src_ptr[src_offset]                  * vp8_filter[2]) +
           ((int)src_ptr[src_offset + pixel_step]     * vp8_filter[3]) +
           ((int)src_ptr[src_offset + PS2]       * vp8_filter[4]) +
           ((int)src_ptr[src_offset + PS3]       * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);   /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;
        if (Temp < 0)
            Temp = 0;
        else if (Temp > 255)
            Temp = 255;

        output_ptr[out_offset] = (unsigned char)Temp;
    }
}

kernel void vp8_filter_block2d_bil_first_pass(
    __global unsigned char *src_base,
    int src_offset,
    __global int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
)
{
    uint tid = get_global_id(0);

    global unsigned char *src_ptr = &src_base[src_offset];

    unsigned int i, j;
    __constant int *vp8_filter = bilinear_filters[filter_offset];

    unsigned int out_row,out_offset;
    int src_increment = src_pixels_per_line - output_width;

    if (tid < output_width * output_height){
        for (i = 0; i < output_height; i++)
        {
            src_offset = i*(output_width+src_increment);
            out_row = output_width * i;
            for (j = 0; j < output_width; j++)
            {
                out_offset = out_row + j;

                /* Apply bilinear filter */
                output_ptr[out_offset] = (((int)src_ptr[src_offset]   * vp8_filter[0]) +
                                 ((int)src_ptr[src_offset+1] * vp8_filter[1]) +
                                 (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
                src_offset++;
            }
        }
    }
}

kernel void vp8_filter_block2d_bil_second_pass
(
    __global int *src_ptr,
    __global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
)
{

    uint tid = get_global_id(0);

    if (tid < output_width * output_height){
        global unsigned char *output_ptr = &output_base[output_offset];

        unsigned int i, j;
        int Temp;
        __constant int *vp8_filter = bilinear_filters[filter_offset];

        int out_offset;
        int src_offset;

        i = tid / output_width;
        j = tid % output_width;

        src_offset = i*(output_width) + j;
        out_offset = i*output_pitch + j;

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset]         * vp8_filter[0]) +
               ((int)src_ptr[src_offset+output_width] * vp8_filter[1]) +
               (VP8_FILTER_WEIGHT / 2);

        output_ptr[out_offset++] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
    }
}

__kernel void vp8_bilinear_predict4x4_kernel
(
        __global unsigned char *src_base,
        int src_offset,
        int src_pixels_per_line,
        int xoffset,
        int yoffset,
        __global unsigned char *dst_base,
        int dst_offset,
        int dst_pitch,
        __global int *int_mem
)
{
    int Height = 4, Width = 4;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);
}

__kernel void vp8_bilinear_predict8x8_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{
    int Height = 8, Width = 8;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);

}

__kernel void vp8_bilinear_predict8x4_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{
    int Height = 4, Width = 8;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);
}

__kernel void vp8_bilinear_predict16x16_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{

    int Height = 16, Width = 16;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);

}

//Called from reconinter_cl.c
kernel void vp8_memcpy_kernel(
    global unsigned char *src,
    int src_stride,
    global unsigned char *dst,
    int dst_stride,
    int num_bytes,
    int num_iter
){

    int i,r;
    int src_offset, dst_offset;

    r = get_global_id(1);
    if (r < get_global_size(1)){
        i = get_global_id(0);
        if (i < get_global_size(0)){
            src_offset = r*src_stride + i;
            dst_offset = r*dst_stride + i;
            dst[dst_offset] = src[src_offset];
        }
    }
}

//Not used currently.
void vp8_memset_short(
    global short *mem,
    int offset,
    short newval,
    size_t size
)
{
    int tid = get_global_id(0);

    if (tid < (size/2)){
        mem[offset+tid/2] = newval;
    }
}

//Here to EOF is old code that should be removed at end of project.
#if 0

void vp8_filter_block2d_first_pass(
    __global unsigned char *src_base,
    int src_offset,
    __private int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
){
    uint tid = get_global_id(0);
    uint i = tid;

    global unsigned char *src_ptr = &src_base[src_offset];
    //Note that src_offset will be reset later, which is why we capture it now
    src_offset = 0;

    int Temp;
    int PS2 = 2*(int)pixel_step;
    int PS3 = 3*(int)pixel_step;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (tid < (output_width*output_height)){
        for (i=0; i < output_width*output_height; i++){
            src_offset = i + (i/output_width * (src_pixels_per_line - output_width)) + PS2;

                Temp = (int)(src_ptr[src_offset - PS2]      * vp8_filter[0]) +
                   (int)(src_ptr[src_offset - (int)pixel_step] * vp8_filter[1]) +
                   (int)(src_ptr[src_offset]                * vp8_filter[2]) +
                   (int)(src_ptr[src_offset + pixel_step]   * vp8_filter[3]) +
                   (int)(src_ptr[src_offset + PS2]          * vp8_filter[4]) +
                   (int)(src_ptr[src_offset + PS3]          * vp8_filter[5]) +
                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */

            /* Normalize back to 0-255 */
            Temp = Temp >> VP8_FILTER_SHIFT;

            //Temp = (int)src_ptr[2];
            if (Temp < 0)
                Temp = 0;
            else if ( Temp > 255 )
                Temp = 255;

            output_ptr[i] = Temp;
        }
    }

    //Add a fence so that no 2nd pass stuff starts before 1st pass writes are done.
    write_mem_fence(CLK_GLOBAL_MEM_FENCE);
}

void vp8_filter_block2d_second_pass
(
    __private int *src_ptr,
    __global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
) {

    global unsigned char *output_ptr = &output_base[output_offset];

    int out_offset; //Not same as output_offset...
    int src_offset;
    int Temp;
    int PS2 = 2*(int)pixel_step;
    int PS3 = 3*(int)pixel_step;

    unsigned int src_increment = src_pixels_per_line - output_width;

    uint i = get_global_id(0);

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (i < (output_width * output_height)){
        out_offset = i/output_width;
        src_offset = out_offset;

        src_offset = i + (src_offset * src_increment);
        out_offset = i%output_width + (out_offset * output_pitch);

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset - PS2] * vp8_filter[0]) +
           ((int)src_ptr[src_offset -(int)pixel_step] * vp8_filter[1]) +
           ((int)src_ptr[src_offset]                  * vp8_filter[2]) +
           ((int)src_ptr[src_offset + pixel_step]     * vp8_filter[3]) +
           ((int)src_ptr[src_offset + PS2]       * vp8_filter[4]) +
           ((int)src_ptr[src_offset + PS3]       * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);   /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;
        if (Temp < 0)
            Temp = 0;
        else if (Temp > 255)
            Temp = 255;

        output_ptr[out_offset] = (unsigned char)Temp;
    }
}

//Used?
__kernel void vp8_block_variation_kernel
(
    __global unsigned char  *src_ptr,
    int   src_pixels_per_line,
    __global int *HVar,
    __global int *VVar
)
{
    int i, j;
    __global unsigned char *Ptr = src_ptr;

    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            *HVar += abs((int)Ptr[j] - (int)Ptr[j+1]);
            *VVar += abs((int)Ptr[j] - (int)Ptr[j+src_pixels_per_line]);
        }

        Ptr += src_pixels_per_line;
    }
}

__kernel void vp8_sixtap_predict_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch,
    __global int *int_data
        ) {

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass_kernel(src_ptr, src_offset, int_data, src_pixels_per_line, 1, 9, 4, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass_kernel(int_data, 8, dst_ptr, dst_offset, dst_pitch, 4, 4, 4, 4, yoffset);
}

__kernel void vp8_sixtap_predict8x8_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    __private int FData[13*16];   /* Temp data bufffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 13, 8, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass(&FData[16], dst_ptr, dst_offset, dst_pitch, 8, 8, 8, 8, yoffset);

}

__kernel void vp8_sixtap_predict8x4_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    __private int FData[13*16];   /* Temp data buffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 9, 8, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass(&FData[16], dst_ptr, dst_offset, dst_pitch, 8, 8, 4, 8, yoffset);
}

__kernel void vp8_sixtap_predict16x16_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    __private int FData[21*24];   /* Temp data buffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 21, 16, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass(&FData[32], dst_ptr, dst_offset, dst_pitch, 16, 16, 16, 16, yoffset);

    return;
}
#endif

#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
#pragma OPENCL EXTENSION cl_amd_printf : enable

__constant int bilinear_filters[8][2] = {
    { 128, 0},
    { 112, 16},
    { 96, 32},
    { 80, 48},
    { 64, 64},
    { 48, 80},
    { 32, 96},
    { 16, 112}
};

__constant short sub_pel_filters[8][8] = {
    //These were originally 8x6, but are padded for vector ops
    { 0, 0, 128, 0, 0, 0, 0, 0}, /* note that 1/8 pel positions are just as per alpha -0.5 bicubic */
    { 0, -6, 123, 12, -1, 0, 0, 0},
    { 2, -11, 108, 36, -8, 1, 0, 0}, /* New 1/4 pel 6 tap filter */
    { 0, -9, 93, 50, -6, 0, 0, 0},
    { 3, -16, 77, 77, -16, 3, 0, 0}, /* New 1/2 pel 6 tap filter */
    { 0, -6, 50, 93, -9, 0, 0, 0},
    { 1, -8, 36, 108, -11, 2, 0, 0}, /* New 1/4 pel 6 tap filter */
    { 0, -1, 12, 123, -6, 0, 0, 0},
};

kernel void vp8_filter_block2d_first_pass_kernel(
    __global unsigned char *src_base,
    int src_offset,
    __global int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
){
    uint tid = get_global_id(0);

    global unsigned char *src_ptr = &src_base[src_offset];
    //Note that src_offset will be reset later, which is why we use it now

    int Temp;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (tid < (output_width*output_height)){
        src_offset = tid + (tid/output_width * (src_pixels_per_line - output_width)) + 2;

        Temp = (int)(src_ptr[src_offset - 2] * vp8_filter[0]) +
           (int)(src_ptr[src_offset - 1] * vp8_filter[1]) +
           (int)(src_ptr[src_offset]     * vp8_filter[2]) +
           (int)(src_ptr[src_offset + 1] * vp8_filter[3]) +
           (int)(src_ptr[src_offset + 2] * vp8_filter[4]) +
           (int)(src_ptr[src_offset + 3] * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);      /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;

        if (Temp < 0)
            Temp = 0;
        else if ( Temp > 255 )
            Temp = 255;

        output_ptr[tid] = Temp;
    }

}

kernel void vp8_filter_block2d_second_pass_kernel
(
    __global int *src_base,
    int src_offset,
    __global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
) {

    uint i = get_global_id(0);

    global int *src_ptr = &src_base[src_offset];
    global unsigned char *output_ptr = &output_base[output_offset];

    int out_offset; //Not same as output_offset...
    int Temp;
    int PS2 = 2*(int)pixel_step;
    int PS3 = 3*(int)pixel_step;

    unsigned int src_increment = src_pixels_per_line - output_width;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (i < (output_width * output_height)){
        out_offset = i/output_width;
        src_offset = out_offset;

        src_offset = i + (src_offset * src_increment);
        out_offset = i%output_width + (out_offset * output_pitch);

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset - PS2] * vp8_filter[0]) +
           ((int)src_ptr[src_offset -(int)pixel_step] * vp8_filter[1]) +
           ((int)src_ptr[src_offset]                  * vp8_filter[2]) +
           ((int)src_ptr[src_offset + pixel_step]     * vp8_filter[3]) +
           ((int)src_ptr[src_offset + PS2]       * vp8_filter[4]) +
           ((int)src_ptr[src_offset + PS3]       * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);   /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;
        if (Temp < 0)
            Temp = 0;
        else if (Temp > 255)
            Temp = 255;

        output_ptr[out_offset] = (unsigned char)Temp;
    }
}

kernel void vp8_filter_block2d_bil_first_pass(
    __global unsigned char *src_base,
    int src_offset,
    __global int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
)
{
    uint tid = get_global_id(0);

    global unsigned char *src_ptr = &src_base[src_offset];

    unsigned int i, j;
    __constant int *vp8_filter = bilinear_filters[filter_offset];

    unsigned int out_row,out_offset;
    int src_increment = src_pixels_per_line - output_width;

    if (tid < output_width * output_height){
        for (i = 0; i < output_height; i++)
        {
            src_offset = i*(output_width+src_increment);
            out_row = output_width * i;
            for (j = 0; j < output_width; j++)
            {
                out_offset = out_row + j;

                /* Apply bilinear filter */
                output_ptr[out_offset] = (((int)src_ptr[src_offset]   * vp8_filter[0]) +
                                 ((int)src_ptr[src_offset+1] * vp8_filter[1]) +
                                 (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
                src_offset++;
            }
        }
    }
}

kernel void vp8_filter_block2d_bil_second_pass
(
    __global int *src_ptr,
    __global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
)
{

    uint tid = get_global_id(0);

    if (tid < output_width * output_height){
        global unsigned char *output_ptr = &output_base[output_offset];

        unsigned int i, j;
        int Temp;
        __constant int *vp8_filter = bilinear_filters[filter_offset];

        int out_offset;
        int src_offset;
        int src_increment;

        src_increment = src_pixels_per_line - output_width;

        i = tid / output_width;
        j = tid % output_width;

        src_offset = i*(output_width+src_increment) + j;
        out_offset = i*output_pitch + j;

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset]         * vp8_filter[0]) +
               ((int)src_ptr[src_offset+pixel_step] * vp8_filter[1]) +
               (VP8_FILTER_WEIGHT / 2);

        output_ptr[out_offset++] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
    }
}

__kernel void vp8_bilinear_predict4x4_kernel
(
        __global unsigned char *src_base,
        int src_offset,
        int src_pixels_per_line,
        int xoffset,
        int yoffset,
        __global unsigned char *dst_base,
        int dst_offset,
        int dst_pitch,
        __global int *int_mem
)
{
    int Height = 4, Width = 4;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass(int_mem, dst_base, dst_offset, dst_pitch, Width, Width, Height, Width, yoffset);
}

__kernel void vp8_bilinear_predict8x8_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{
    int Height = 8, Width = 8;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass(int_mem, dst_base, dst_offset, dst_pitch, Width, Width, Height, Width, yoffset);

}

__kernel void vp8_bilinear_predict8x4_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{
    int Height = 4, Width = 8;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass(int_mem, dst_base, dst_offset, dst_pitch, Width, Width, Height, Width, yoffset);
}

__kernel void vp8_bilinear_predict16x16_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{

    int Height = 16, Width = 16;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass(int_mem, dst_base, dst_offset, dst_pitch, Width, Width, Height, Width, yoffset);

}

//Called from reconinter_cl.c
kernel void vp8_memcpy_kernel(
    global unsigned char *src,
    int src_stride,
    global unsigned char *dst,
    int dst_stride,
    int num_bytes,
    int num_iter
){

    int i,r;
    int src_offset, dst_offset;

    r = get_global_id(1);
    if (r < get_global_size(1)){
        i = get_global_id(0);
        if (i < get_global_size(0)){
            src_offset = r*src_stride + i;
            dst_offset = r*dst_stride + i;
            dst[dst_offset] = src[src_offset];
        }
    }
}

//Not used currently.
void vp8_memset_short(
    global short *mem,
    int offset,
    short newval,
    size_t size
)
{
    int tid = get_global_id(0);

    if (tid < (size/2)){
        mem[offset+tid/2] = newval;
    }
}

//Here to EOF is old code that should be removed at end of project.
#if 0

void vp8_filter_block2d_first_pass(
    __global unsigned char *src_base,
    int src_offset,
    __private int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
){
    uint tid = get_global_id(0);
    uint i = tid;

    global unsigned char *src_ptr = &src_base[src_offset];
    //Note that src_offset will be reset later, which is why we capture it now
    src_offset = 0;

    int Temp;
    int PS2 = 2*(int)pixel_step;
    int PS3 = 3*(int)pixel_step;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (tid < (output_width*output_height)){
        for (i=0; i < output_width*output_height; i++){
            src_offset = i + (i/output_width * (src_pixels_per_line - output_width)) + PS2;

                Temp = (int)(src_ptr[src_offset - PS2]      * vp8_filter[0]) +
                   (int)(src_ptr[src_offset - (int)pixel_step] * vp8_filter[1]) +
                   (int)(src_ptr[src_offset]                * vp8_filter[2]) +
                   (int)(src_ptr[src_offset + pixel_step]   * vp8_filter[3]) +
                   (int)(src_ptr[src_offset + PS2]          * vp8_filter[4]) +
                   (int)(src_ptr[src_offset + PS3]          * vp8_filter[5]) +
                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */

            /* Normalize back to 0-255 */
            Temp = Temp >> VP8_FILTER_SHIFT;

            //Temp = (int)src_ptr[2];
            if (Temp < 0)
                Temp = 0;
            else if ( Temp > 255 )
                Temp = 255;

            output_ptr[i] = Temp;
        }
    }

    //Add a fence so that no 2nd pass stuff starts before 1st pass writes are done.
    write_mem_fence(CLK_GLOBAL_MEM_FENCE);
}

void vp8_filter_block2d_second_pass
(
    __private int *src_ptr,
    __global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
) {

    global unsigned char *output_ptr = &output_base[output_offset];

    int out_offset; //Not same as output_offset...
    int src_offset;
    int Temp;
    int PS2 = 2*(int)pixel_step;
    int PS3 = 3*(int)pixel_step;

    unsigned int src_increment = src_pixels_per_line - output_width;

    uint i = get_global_id(0);

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (i < (output_width * output_height)){
        out_offset = i/output_width;
        src_offset = out_offset;

        src_offset = i + (src_offset * src_increment);
        out_offset = i%output_width + (out_offset * output_pitch);

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset - PS2] * vp8_filter[0]) +
           ((int)src_ptr[src_offset -(int)pixel_step] * vp8_filter[1]) +
           ((int)src_ptr[src_offset]                  * vp8_filter[2]) +
           ((int)src_ptr[src_offset + pixel_step]     * vp8_filter[3]) +
           ((int)src_ptr[src_offset + PS2]       * vp8_filter[4]) +
           ((int)src_ptr[src_offset + PS3]       * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);   /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;
        if (Temp < 0)
            Temp = 0;
        else if (Temp > 255)
            Temp = 255;

        output_ptr[out_offset] = (unsigned char)Temp;
    }
}

//Used?
__kernel void vp8_block_variation_kernel
(
    __global unsigned char  *src_ptr,
    int   src_pixels_per_line,
    __global int *HVar,
    __global int *VVar
)
{
    int i, j;
    __global unsigned char *Ptr = src_ptr;

    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            *HVar += abs((int)Ptr[j] - (int)Ptr[j+1]);
            *VVar += abs((int)Ptr[j] - (int)Ptr[j+src_pixels_per_line]);
        }

        Ptr += src_pixels_per_line;
    }
}

__kernel void vp8_sixtap_predict_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch,
    __global int *int_data
        ) {

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass_kernel(src_ptr, src_offset, int_data, src_pixels_per_line, 1, 9, 4, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass_kernel(int_data, 8, dst_ptr, dst_offset, dst_pitch, 4, 4, 4, 4, yoffset);
}

__kernel void vp8_sixtap_predict8x8_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    __private int FData[13*16];   /* Temp data bufffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 13, 8, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass(&FData[16], dst_ptr, dst_offset, dst_pitch, 8, 8, 8, 8, yoffset);

}

__kernel void vp8_sixtap_predict8x4_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    __private int FData[13*16];   /* Temp data buffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 9, 8, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass(&FData[16], dst_ptr, dst_offset, dst_pitch, 8, 8, 4, 8, yoffset);
}

__kernel void vp8_sixtap_predict16x16_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    __private int FData[21*24];   /* Temp data buffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 21, 16, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass(&FData[32], dst_ptr, dst_offset, dst_pitch, 16, 16, 16, 16, yoffset);

    return;
}
#endif