clear sigma new in pre-process step

clear sigma new in pre-process step

/*  Copyright 2014 Aaron Boxer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include "ocl_platform.cl"

/*

Bit Plane Coder
===============

A. Scan Pattern

Xx4 stripes

The stripes are scanned from top to bottom, and the columns within a
stripe are scanned from left to right.

*/

#define CODEBLOCKY_QUARTER 8

#define BOUNDARY 1
#define BOUNDARY_X2 2

#define CODEBLOCKY_X4 128

#define STATE_BUFFER_SIZE 1156
#define STATE_BOTTOM_BOUNDARY_OFFSET 1124

#define STATE_BUFFER_STRIDE 34
#define STATE_BUFFER_STRIDE_X2 68
#define STATE_BUFFER_STRIDE_X3 102
#define STATE_BUFFER_STRIDE_X4 136

#define LEFT_TOP -35
#define TOP  -34
#define RIGHT_TOP -33

#define LEFT   -1
#define RIGHT   1

#define LEFT_BOTTOM  33
#define BOTTOM  34
#define RIGHT_BOTTOM  35

// bit positions (0 based indices)
#define INPUT_SIGN_BITPOS  15

#define SIGMA_NEW_BITPOS   0x1
#define SIGMA_OLD_BITPOS   0x1
#define NBH_BITPOS         0x2
#define SIGMA_OLD_TO_NBH_SHIFT 0x1
#define RLC_BITPOS         0x4
#define PIXEL_START_BITPOS 0xA
#define PIXEL_END_BITPOS   0x18
#define SIGN_BITPOS        0x19

#define SIGMA_NEW			 0x1		  //position 0
#define NOT_SIGMA_NEW        0xFFFFFFFE   // ~SIGMA_NEW
#define SIGMA_OLD			 0x10		  //position  1
#define NBH					 0x20		  //position  2
#define RLC					 0x80		  //position  4
#define RLC_D_POSITION		 0x380        //positions 6-9
#define PIXEL				 0x7FFF0000   //positions 10-24
#define SIGN				 0x2000000    //position  25

#define INPUT_TO_SIGN_SHIFT 10

CONSTANT sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE  | CLK_FILTER_NEAREST;

#define BIT(pix) (((pix)>>(bp))&1)

/**

**/

void KERNEL run(read_only image2d_t channel) {

	// state buffer
	LOCAL int state[STATE_BUFFER_SIZE];
	LOCAL int cxd[STATE_BUFFER_SIZE];

	///////////////////////////////////////////////////////////////////////////////////
	//1. Calculate MSB

	LOCAL int msbScratch[CODEBLOCKX]; // between one and 32 - zero value indicates that this code block is identically zero

	int maxSigBit;
	if (getLocalId(1) == 0) {
		int maxVal = 0;
		state[getLocalId(0)] = 0;   //top boundary
		LOCAL int* statePtr = state + (BOUNDARY + getLocalId(0));
		int2 posIn = (int2)(getGlobalId(0),  (getGlobalId(1)/8)*CODEBLOCKY);
		for (int i = 0; i < CODEBLOCKY; ++i) {
			int pixel = read_imagei(channel, sampler, posIn).x;
			pixel = (abs(pixel) << PIXEL_START_BITPOS) | ((pixel << INPUT_TO_SIGN_SHIFT) & SIGN);
			posIn.y++;
			maxVal = max(maxVal, (pixel>> PIXEL_START_BITPOS)&0x7FFF);
			statePtr[0] = pixel;
			statePtr += STATE_BUFFER_STRIDE;
		}
		state[ getLocalId(0) + STATE_BOTTOM_BOUNDARY_OFFSET] = 0;		//bottom boundary

		//initialize full left and right boundary columns
		if (getLocalId(0) == 0 || getLocalId(0) == CODEBLOCKX-1) {
			int delta = -1 + (getLocalId(0)/(CODEBLOCKX-1))*2; // -1 or +1
			statePtr = state + BOUNDARY + getLocalId(0) + delta;
			 for (int i = 0; i < CODEBLOCKY+ BOUNDARY_X2; ++i) {
				 *statePtr = 0;
				 statePtr += STATE_BUFFER_STRIDE;
			 }
		}

		// calculate column-msb
		maxSigBit = 31 - clz(maxVal);
		msbScratch[getLocalId(0)] =maxSigBit;
	}
	localMemoryFence();

	//calculate global msb
	if (getLocalId(0) + getLocalId(1) == 0) {
		int4 mx = (int4)(maxSigBit);

		LOCAL int* scratchPtr = msbScratch;
		for(int i=0; i < CODEBLOCKX; i+=4) {
			mx = max(mx,(int4)(msbScratch[i],msbScratch[i+1],msbScratch[i+2],msbScratch[i+3]));
		}
		maxSigBit = mx.x;
		maxSigBit = max(maxSigBit, mx.y);
		maxSigBit = max(maxSigBit, mx.z);
		maxSigBit = max(maxSigBit, mx.w);
		msbScratch[0] = maxSigBit;
	}
	localMemoryFence();

	if (msbScratch[0] == -1)
		return;

	int startIndex = (BOUNDARY + getLocalId(0)) + (BOUNDARY + getLocalId(1))*STATE_BUFFER_STRIDE_X4;

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 2. CUP on MSB

	//Algorithm 13 Clean-up pass on the MSB
	//1: set sigmanew := bit value
	//2: set rlcNbh :=  SUM(sigmanew) of preceding column and upper position
	//3: if rlcNbh = 0 and y-dimension of current position is a multiple of 4
	//then
	//4: execute RLC operation
	//5: end if
	//6: if rlcNbh = 1 then
	//7: execute ZC operation
	//8: end if
	//9: if sigmanew = 1 then
	//10: execute SC operation
	//11: end if

	int bp = msbScratch[0] + PIXEL_START_BITPOS;

	// set sigma_new for strip column (sigma_old is zero)
	LOCAL int* statePtr = state + startIndex;
	for (int i = 0; i < 4; ++i) {
		*statePtr |= BIT(*statePtr);
		statePtr += STATE_BUFFER_STRIDE;

	}
	localMemoryFence();

	// set rlc nbh for strip column
	statePtr = state + startIndex;
	int current = statePtr[0];
	int top = statePtr[TOP];
	int leftTop = statePtr[LEFT_TOP];
	int left = statePtr[LEFT];
	int leftBottom = statePtr[LEFT_BOTTOM];

	int rlcCount = 0;
	bool doRLC = false;
	for (int i = 0; i < 4; ++i) {
		int nbh = (BIT(top) || BIT(leftTop) || BIT(left) || BIT(leftBottom)) << NBH_BITPOS ;
		statePtr[0] |= nbh;
		int currentBit = BIT(current);

		// toggle doRLC flag
		if (i == 0 && !nbh && !currentBit ) {
			doRLC = true;
		} else if (doRLC && (nbh || currentBit) ) {
			doRLC = false;
		}

		if (doRLC) {

			rlcCount++;
		} else {
		   if (nbh) {
				//ZC
		   }
		   if (currentBit) {
		       //SC

		   }

		}

		statePtr += STATE_BUFFER_STRIDE;
		top = current;
		current = statePtr[0];
		leftTop = left;
		left = leftBottom;
		leftBottom = statePtr[LEFT_BOTTOM];
	}
	localMemoryFence();

	/////////////////////////////////////////////////////////////////////////////////////////////////
	// 3. Processs rest of bit plans
	bp--;
	LOCAL char blockVote;

	while (bp >= PIXEL_START_BITPOS) {
		blockVote = 0;

		/////////////////////////////
		// 4. pre-process bit plane

		//Algorithm 15 Bit-plane Preprocessing
		//1: //First step
		//2: set sigma_old |= sigma_new
		//3: set nbh |=  old_sigma from neighbouring positions
		//4: if sigma_old = 0 AND nbh != 0 AND bit value = 1 then
		//5: set sigma_new := 1
		//6: end if
		//7: if there is some sigma_new = 1 then
		//8: blockVote := true
		//9: end if
		//10: //Second step
		//11: while blockVote = true do
		//12: set blockVote := false //reset the voting variable
		//13: set nbh :=  sigma_new from the four previous positions
		//14: if sigma_old = 0 AND nbh != 0 AND bit value = 1 then
		//15: set sigma_new = 1
		//16: end if
		//17: if there is some sigma_new = 1 found in this iteration then
		//18: set blockVote := true
		//19: end if
		//20: end while

		// i) migrate sigma_new to sigma_old, and clear sigma new bit
		statePtr = state + startIndex;
		for (int i = 0; i < 4; ++i) {
		    int current = *statePtr;
			current |= ((current) & SIGMA_NEW) << SIGMA_OLD_BITPOS;
			current &= NOT_SIGMA_NEW;  // clear sigma new
			*statePtr = current;
			statePtr += STATE_BUFFER_STRIDE;

		}
		localMemoryFence();

		// ii) update nbh
		statePtr = state + startIndex;

		int top = statePtr[TOP];
		int leftTop = statePtr[LEFT_TOP];
		int rightTop = statePtr[RIGHT_TOP];
		int left = statePtr[LEFT];
		int current = statePtr[0];
		int right = statePtr[RIGHT];
		int leftBottom = statePtr[LEFT_BOTTOM];
		int bottom = statePtr[BOTTOM];
		int rightBottom = statePtr[RIGHT_BOTTOM];
		for (int i = 0; i < 4; ++i) {

			current |= ((leftTop & SIGMA_OLD) |
							 ( top & SIGMA_OLD) |
							 ( rightTop &  SIGMA_OLD) |
							 ( left & SIGMA_OLD) |
							 ( right & SIGMA_OLD) |
							 ( leftBottom & SIGMA_OLD) |
							 ( bottom & SIGMA_OLD) |
							 ( rightBottom & SIGMA_OLD)  ) << SIGMA_OLD_TO_NBH_SHIFT;

			if ( BIT(current) && (current & NBH) ) {
			    current |= SIGMA_NEW;
				blockVote = 1;

			}
			*statePtr = current;
			statePtr += STATE_BUFFER_STRIDE;
			top = current;
			leftTop = left;
			rightTop = right;
			left = leftBottom;
			current = statePtr[0];
			right = rightBottom;
			leftBottom = statePtr[LEFT_BOTTOM];
			bottom = statePtr[BOTTOM];
			rightBottom = statePtr[RIGHT_BOTTOM];
		}
		localMemoryFence();

		// iii) block vote on sigma new
		while (blockVote) {
		    blockVote = 0;
			localMemoryFence();

			statePtr = state + startIndex;

			int top = statePtr[TOP];
			int leftTop = statePtr[LEFT_TOP];
			int left = statePtr[LEFT];
			int current = statePtr[0];
			int leftBottom = statePtr[LEFT_BOTTOM];

			for (int i = 0; i < 4; ++i) {

				current |= ((leftTop & SIGMA_NEW) |
							( top & SIGMA_NEW) |
							( left & SIGMA_NEW) |
							( leftBottom & SIGMA_NEW) ) << NBH_BITPOS;

				if (  BIT(current) && !(current & SIGMA_NEW) && (current & NBH)) {
					current |= SIGMA_NEW;
					blockVote = 1;

				}
				statePtr[0] = current;
				statePtr += STATE_BUFFER_STRIDE;
				top = current;
				current = statePtr[0];
				leftTop = left;
				left = leftBottom;
				leftBottom = statePtr[LEFT_BOTTOM];
			}
			localMemoryFence();

		}

		/////////////////////////
		// 5. Significance
		statePtr = state + startIndex;

		top = statePtr[TOP];
		leftTop = statePtr[LEFT_TOP];
		rightTop = statePtr[RIGHT_TOP];
		left = statePtr[LEFT];
		current = statePtr[0];
		right = statePtr[RIGHT];
		leftBottom = statePtr[LEFT_BOTTOM];
		bottom = statePtr[BOTTOM];
		rightBottom = statePtr[RIGHT_BOTTOM];
		for (int i = 0; i < 4; ++i) {

			int nbh = ((leftTop & SIGMA_OLD) |
							 ( top & SIGMA_OLD) |
							 ( rightTop &  SIGMA_OLD) |
							 ( left & SIGMA_OLD) |
							 ( right & SIGMA_OLD) |
							 ( leftBottom & SIGMA_OLD) |
							 ( bottom & SIGMA_OLD) |
							 ( rightBottom & SIGMA_OLD)  ) << NBH_BITPOS;

			current |= nbh;
			if ( !(current & NBH) && nbh && BIT(current) ) {
			    current |= SIGMA_NEW;

			}
			*statePtr = current;
			statePtr += STATE_BUFFER_STRIDE;
			top = current;
			leftTop = left;
			rightTop = right;
			left = leftBottom;
			current = statePtr[0];
			right = rightBottom;
			leftBottom = statePtr[LEFT_BOTTOM];
			bottom = statePtr[BOTTOM];
			rightBottom = statePtr[RIGHT_BOTTOM];
		}
		localMemoryFence();

		//////////////////////////
		// 6. Magnitude Refinement
		statePtr = state + startIndex;

		top = statePtr[TOP];
		leftTop = statePtr[LEFT_TOP];
		rightTop = statePtr[RIGHT_TOP];
		left = statePtr[LEFT];
		current = statePtr[0];
		right = statePtr[RIGHT];
		leftBottom = statePtr[LEFT_BOTTOM];
		bottom = statePtr[BOTTOM];
		rightBottom = statePtr[RIGHT_BOTTOM];
		for (int i = 0; i < 4; ++i) {

			int nbh = ((leftTop & SIGMA_OLD) |
							 ( top & SIGMA_OLD) |
							 ( rightTop &  SIGMA_OLD) |
							 ( left & SIGMA_OLD) |
							 ( right & SIGMA_OLD) |
							 ( leftBottom & SIGMA_OLD) |
							 ( bottom & SIGMA_OLD) |
							 ( rightBottom & SIGMA_OLD)  ) << NBH_BITPOS;

			current |= nbh;
			if ( !(current & NBH) && nbh && BIT(current) ) {
			    current |= SIGMA_NEW;

			}
			*statePtr = current;
			statePtr += STATE_BUFFER_STRIDE;
			top = current;
			leftTop = left;
			rightTop = right;
			left = leftBottom;
			current = statePtr[0];
			right = rightBottom;
			leftBottom = statePtr[LEFT_BOTTOM];
			bottom = statePtr[BOTTOM];
			rightBottom = statePtr[RIGHT_BOTTOM];
		}
		localMemoryFence();

		///////////////////////
		// 7. cleanup
		statePtr = state + startIndex;

		top = statePtr[TOP];
		leftTop = statePtr[LEFT_TOP];
		rightTop = statePtr[RIGHT_TOP];
		left = statePtr[LEFT];
		current = statePtr[0];
		right = statePtr[RIGHT];
		leftBottom = statePtr[LEFT_BOTTOM];
		bottom = statePtr[BOTTOM];
		rightBottom = statePtr[RIGHT_BOTTOM];
		for (int i = 0; i < 4; ++i) {

			int nbh = ((leftTop & SIGMA_OLD) |
							 ( top & SIGMA_OLD) |
							 ( rightTop &  SIGMA_OLD) |
							 ( left & SIGMA_OLD) |
							 ( right & SIGMA_OLD) |
							 ( leftBottom & SIGMA_OLD) |
							 ( bottom & SIGMA_OLD) |
							 ( rightBottom & SIGMA_OLD)  ) << NBH_BITPOS;

			current |= nbh;
			if ( !(current & NBH) && nbh && BIT(current) ) {
			    current |= SIGMA_NEW;

			}
			*statePtr = current;
			statePtr += STATE_BUFFER_STRIDE;
			top = current;
			leftTop = left;
			rightTop = right;
			left = leftBottom;
			current = statePtr[0];
			right = rightBottom;
			leftBottom = statePtr[LEFT_BOTTOM];
			bottom = statePtr[BOTTOM];
			rightBottom = statePtr[RIGHT_BOTTOM];
		}
		localMemoryFence();

		bp--;
	}
}

/*  Copyright 2014 Aaron Boxer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include "ocl_platform.cl"

/*

Bit Plane Coder
===============

A. Scan Pattern

Xx4 stripes

The stripes are scanned from top to bottom, and the columns within a
stripe are scanned from left to right.

*/

#define CODEBLOCKY_QUARTER 8

#define BOUNDARY 1
#define BOUNDARY_X2 2

#define CODEBLOCKY_X4 128

#define STATE_BUFFER_SIZE 1156
#define STATE_BOTTOM_BOUNDARY_OFFSET 1124

#define STATE_BUFFER_STRIDE 34
#define STATE_BUFFER_STRIDE_X2 68
#define STATE_BUFFER_STRIDE_X3 102
#define STATE_BUFFER_STRIDE_X4 136

#define LEFT_TOP -35
#define TOP  -34
#define RIGHT_TOP -33

#define LEFT   -1
#define RIGHT   1

#define LEFT_BOTTOM  33
#define BOTTOM  34
#define RIGHT_BOTTOM  35

// bit positions (0 based indices)
#define INPUT_SIGN_BITPOS  15

#define SIGMA_NEW_BITPOS   0x1
#define SIGMA_OLD_BITPOS   0x1
#define NBH_BITPOS         0x2
#define SIGMA_OLD_TO_NBH_SHIFT 0x1
#define RLC_BITPOS         0x4
#define PIXEL_START_BITPOS 0xA
#define PIXEL_END_BITPOS   0x18
#define SIGN_BITPOS        0x19

#define SIGMA_NEW			 0x1		  //0
#define SIGMA_OLD			 0x10		  //1
#define NBH					 0x20		  //2
#define RLC					 0x80		  //4
#define RLC_D_POSITION		 0x380        //6-9
#define PIXEL				 0x7FFF0000   //10-24
#define SIGN				 0x2000000    //25

#define INPUT_TO_SIGN_SHIFT 10

CONSTANT sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE  | CLK_FILTER_NEAREST;

#define BIT(pix) (((pix)>>(bp))&1)

/**

**/

void KERNEL run(read_only image2d_t channel) {

	// state buffer
	LOCAL int state[STATE_BUFFER_SIZE];
	LOCAL int cxd[STATE_BUFFER_SIZE];

	///////////////////////////////////////////////////////////////////////////////////
	//1. Calculate MSB

	LOCAL int msbScratch[CODEBLOCKX]; // between one and 32 - zero value indicates that this code block is identically zero

	int maxSigBit;
	if (getLocalId(1) == 0) {
		int maxVal = 0;
		state[getLocalId(0)] = 0;   //top boundary
		LOCAL int* statePtr = state + (BOUNDARY + getLocalId(0));
		int2 posIn = (int2)(getGlobalId(0),  (getGlobalId(1)/8)*CODEBLOCKY);
		for (int i = 0; i < CODEBLOCKY; ++i) {
			int pixel = read_imagei(channel, sampler, posIn).x;
			pixel = (abs(pixel) << PIXEL_START_BITPOS) | ((pixel << INPUT_TO_SIGN_SHIFT) & SIGN);
			posIn.y++;
			maxVal = max(maxVal, (pixel>> PIXEL_START_BITPOS)&0x7FFF);
			statePtr[0] = pixel;
			statePtr += STATE_BUFFER_STRIDE;
		}
		state[ getLocalId(0) + STATE_BOTTOM_BOUNDARY_OFFSET] = 0;		//bottom boundary

		//initialize full left and right boundary columns
		if (getLocalId(0) == 0 || getLocalId(0) == CODEBLOCKX-1) {
			int delta = -1 + (getLocalId(0)/(CODEBLOCKX-1))*2; // -1 or +1
			statePtr = state + BOUNDARY + getLocalId(0) + delta;
			 for (int i = 0; i < CODEBLOCKY+ BOUNDARY_X2; ++i) {
				 *statePtr = 0;
				 statePtr += STATE_BUFFER_STRIDE;
			 }
		}

		// calculate column-msb
		maxSigBit = 31 - clz(maxVal);
		msbScratch[getLocalId(0)] =maxSigBit;
	}
	localMemoryFence();

	//calculate global msb
	if (getLocalId(0) + getLocalId(1) == 0) {
		int4 mx = (int4)(maxSigBit);

		LOCAL int* scratchPtr = msbScratch;
		for(int i=0; i < CODEBLOCKX; i+=4) {
			mx = max(mx,(int4)(msbScratch[i],msbScratch[i+1],msbScratch[i+2],msbScratch[i+3]));
		}
		maxSigBit = mx.x;
		maxSigBit = max(maxSigBit, mx.y);
		maxSigBit = max(maxSigBit, mx.z);
		maxSigBit = max(maxSigBit, mx.w);
		msbScratch[0] = maxSigBit;
	}
	localMemoryFence();

	if (msbScratch[0] == -1)
		return;

	int startIndex = (BOUNDARY + getLocalId(0)) + (BOUNDARY + getLocalId(1))*STATE_BUFFER_STRIDE_X4;

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 2. CUP on MSB

	//Algorithm 13 Clean-up pass on the MSB
	//1: set sigmanew := bit value
	//2: set rlcNbh :=  SUM(sigmanew) of preceding column and upper position
	//3: if rlcNbh = 0 and y-dimension of current position is a multiple of 4
	//then
	//4: execute RLC operation
	//5: end if
	//6: if rlcNbh = 1 then
	//7: execute ZC operation
	//8: end if
	//9: if sigmanew = 1 then
	//10: execute SC operation
	//11: end if

	int bp = msbScratch[0] + PIXEL_START_BITPOS;

	// set sigma_new for strip column (sigma_old is zero)
	LOCAL int* statePtr = state + startIndex;
	for (int i = 0; i < 4; ++i) {
		*statePtr |= BIT(*statePtr);
		statePtr += STATE_BUFFER_STRIDE;

	}
	localMemoryFence();

	// set rlc nbh for strip column
	statePtr = state + startIndex;
	int current = statePtr[0];
	int top = statePtr[TOP];
	int leftTop = statePtr[LEFT_TOP];
	int left = statePtr[LEFT];
	int leftBottom = statePtr[LEFT_BOTTOM];

	int rlcCount = 0;
	bool doRLC = false;
	for (int i = 0; i < 4; ++i) {
		int nbh = (BIT(top) || BIT(leftTop) || BIT(left) || BIT(leftBottom)) << NBH_BITPOS ;
		statePtr[0] |= nbh;
		int currentBit = BIT(current);

		// toggle doRLC flag
		if (i == 0 && !nbh && !currentBit ) {
			doRLC = true;
		} else if (doRLC && (nbh || currentBit) ) {
			doRLC = false;
		}

		if (doRLC) {

			rlcCount++;
		} else {
		   if (nbh) {
				//ZC
		   }
		   if (currentBit) {
		       //SC

		   }

		}

		statePtr += STATE_BUFFER_STRIDE;
		top = current;
		current = statePtr[0];
		leftTop = left;
		left = leftBottom;
		leftBottom = statePtr[LEFT_BOTTOM];
	}
	localMemoryFence();

	/////////////////////////////////////////////////////////////////////////////////////////////////
	// 3. Processs rest of bit plans
	bp--;
	LOCAL char blockVote;

	while (bp >= PIXEL_START_BITPOS) {
		blockVote = 0;

		/////////////////////////////
		// 4. pre-process bit plane

		//Algorithm 15 Bit-plane Preprocessing
		//1: //First step
		//2: set sigma_old |= sigma_new
		//3: set nbh |=  old_sigma from neighbouring positions
		//4: if sigma_old = 0 AND nbh != 0 AND bit value = 1 then
		//5: set sigma_new := 1
		//6: end if
		//7: if there is some sigma_new = 1 then
		//8: blockVote := true
		//9: end if
		//10: //Second step
		//11: while blockVote = true do
		//12: set blockVote := false //reset the voting variable
		//13: set nbh :=  sigma_new from the four previous positions
		//14: if sigma_old = 0 AND nbh != 0 AND bit value = 1 then
		//15: set sigma_new = 1
		//16: end if
		//17: if there is some sigma_new = 1 found in this iteration then
		//18: set blockVote := true
		//19: end if
		//20: end while

		// i) migrate sigma_new to sigma_old
		statePtr = state + startIndex;
		for (int i = 0; i < 4; ++i) {
			*statePtr |= ((*statePtr) & SIGMA_NEW) << SIGMA_OLD_BITPOS;
			statePtr += STATE_BUFFER_STRIDE;

		}
		localMemoryFence();

		// ii) update nbh
		statePtr = state + startIndex;

		int top = statePtr[TOP];
		int leftTop = statePtr[LEFT_TOP];
		int rightTop = statePtr[RIGHT_TOP];
		int left = statePtr[LEFT];
		int current = statePtr[0];
		int right = statePtr[RIGHT];
		int leftBottom = statePtr[LEFT_BOTTOM];
		int bottom = statePtr[BOTTOM];
		int rightBottom = statePtr[RIGHT_BOTTOM];
		for (int i = 0; i < 4; ++i) {

			current |= ((leftTop & SIGMA_OLD) |
							 ( top & SIGMA_OLD) |
							 ( rightTop &  SIGMA_OLD) |
							 ( left & SIGMA_OLD) |
							 ( right & SIGMA_OLD) |
							 ( leftBottom & SIGMA_OLD) |
							 ( bottom & SIGMA_OLD) |
							 ( rightBottom & SIGMA_OLD)  ) << SIGMA_OLD_TO_NBH_SHIFT;

			if ( BIT(current) && (current & NBH) ) {
			    current |= SIGMA_NEW;
				blockVote = 1;

			}
			*statePtr = current;
			statePtr += STATE_BUFFER_STRIDE;
			top = current;
			leftTop = left;
			rightTop = right;
			left = leftBottom;
			current = statePtr[0];
			right = rightBottom;
			leftBottom = statePtr[LEFT_BOTTOM];
			bottom = statePtr[BOTTOM];
			rightBottom = statePtr[RIGHT_BOTTOM];
		}
		localMemoryFence();

		// iii) block vote on sigma new
		while (blockVote) {
		    blockVote = 0;
			localMemoryFence();

			statePtr = state + startIndex;

			int top = statePtr[TOP];
			int leftTop = statePtr[LEFT_TOP];
			int left = statePtr[LEFT];
			int current = statePtr[0];
			int leftBottom = statePtr[LEFT_BOTTOM];

			for (int i = 0; i < 4; ++i) {

				current |= ((leftTop & SIGMA_NEW) |
							( top & SIGMA_NEW) |
							( left & SIGMA_NEW) |
							( leftBottom & SIGMA_NEW) ) << NBH_BITPOS;

				if (  BIT(current) && !(current & SIGMA_NEW) && (current & NBH)) {
					current |= SIGMA_NEW;
					blockVote = 1;

				}
				statePtr[0] = current;
				statePtr += STATE_BUFFER_STRIDE;
				top = current;
				current = statePtr[0];
				leftTop = left;
				left = leftBottom;
				leftBottom = statePtr[LEFT_BOTTOM];
			}
			localMemoryFence();

		}

		/////////////////////////
		// 5. Significance
		statePtr = state + startIndex;

		top = statePtr[TOP];
		leftTop = statePtr[LEFT_TOP];
		rightTop = statePtr[RIGHT_TOP];
		left = statePtr[LEFT];
		current = statePtr[0];
		right = statePtr[RIGHT];
		leftBottom = statePtr[LEFT_BOTTOM];
		bottom = statePtr[BOTTOM];
		rightBottom = statePtr[RIGHT_BOTTOM];
		for (int i = 0; i < 4; ++i) {

			int nbh = ((leftTop & SIGMA_OLD) |
							 ( top & SIGMA_OLD) |
							 ( rightTop &  SIGMA_OLD) |
							 ( left & SIGMA_OLD) |
							 ( right & SIGMA_OLD) |
							 ( leftBottom & SIGMA_OLD) |
							 ( bottom & SIGMA_OLD) |
							 ( rightBottom & SIGMA_OLD)  ) << NBH_BITPOS;

			current |= nbh;
			if ( !(current & NBH) && nbh && BIT(current) ) {
			    current |= SIGMA_NEW;

			}
			*statePtr = current;
			statePtr += STATE_BUFFER_STRIDE;
			top = current;
			leftTop = left;
			rightTop = right;
			left = leftBottom;
			current = statePtr[0];
			right = rightBottom;
			leftBottom = statePtr[LEFT_BOTTOM];
			bottom = statePtr[BOTTOM];
			rightBottom = statePtr[RIGHT_BOTTOM];
		}
		localMemoryFence();

		//////////////////////////
		// 6. Magnitude Refinement
		statePtr = state + startIndex;

		top = statePtr[TOP];
		leftTop = statePtr[LEFT_TOP];
		rightTop = statePtr[RIGHT_TOP];
		left = statePtr[LEFT];
		current = statePtr[0];
		right = statePtr[RIGHT];
		leftBottom = statePtr[LEFT_BOTTOM];
		bottom = statePtr[BOTTOM];
		rightBottom = statePtr[RIGHT_BOTTOM];
		for (int i = 0; i < 4; ++i) {

			int nbh = ((leftTop & SIGMA_OLD) |
							 ( top & SIGMA_OLD) |
							 ( rightTop &  SIGMA_OLD) |
							 ( left & SIGMA_OLD) |
							 ( right & SIGMA_OLD) |
							 ( leftBottom & SIGMA_OLD) |
							 ( bottom & SIGMA_OLD) |
							 ( rightBottom & SIGMA_OLD)  ) << NBH_BITPOS;

			current |= nbh;
			if ( !(current & NBH) && nbh && BIT(current) ) {
			    current |= SIGMA_NEW;

			}
			*statePtr = current;
			statePtr += STATE_BUFFER_STRIDE;
			top = current;
			leftTop = left;
			rightTop = right;
			left = leftBottom;
			current = statePtr[0];
			right = rightBottom;
			leftBottom = statePtr[LEFT_BOTTOM];
			bottom = statePtr[BOTTOM];
			rightBottom = statePtr[RIGHT_BOTTOM];
		}
		localMemoryFence();

		///////////////////////
		// 7. cleanup
		statePtr = state + startIndex;

		top = statePtr[TOP];
		leftTop = statePtr[LEFT_TOP];
		rightTop = statePtr[RIGHT_TOP];
		left = statePtr[LEFT];
		current = statePtr[0];
		right = statePtr[RIGHT];
		leftBottom = statePtr[LEFT_BOTTOM];
		bottom = statePtr[BOTTOM];
		rightBottom = statePtr[RIGHT_BOTTOM];
		for (int i = 0; i < 4; ++i) {

			int nbh = ((leftTop & SIGMA_OLD) |
							 ( top & SIGMA_OLD) |
							 ( rightTop &  SIGMA_OLD) |
							 ( left & SIGMA_OLD) |
							 ( right & SIGMA_OLD) |
							 ( leftBottom & SIGMA_OLD) |
							 ( bottom & SIGMA_OLD) |
							 ( rightBottom & SIGMA_OLD)  ) << NBH_BITPOS;

			current |= nbh;
			if ( !(current & NBH) && nbh && BIT(current) ) {
			    current |= SIGMA_NEW;

			}
			*statePtr = current;
			statePtr += STATE_BUFFER_STRIDE;
			top = current;
			leftTop = left;
			rightTop = right;
			left = leftBottom;
			current = statePtr[0];
			right = rightBottom;
			leftBottom = statePtr[LEFT_BOTTOM];
			bottom = statePtr[BOTTOM];
			rightBottom = statePtr[RIGHT_BOTTOM];
		}
		localMemoryFence();

		bp--;
	}
}


Fixed cfd bug.

Fixed cfd bug.

#define NDIM 3
#define NNB 4

#define RK 3	// 3rd order RK

#define GAMMA 1.4f
#define VAR_DENSITY 0
#define VAR_MOMENTUM  1
#define VAR_DENSITY_ENERGY (VAR_MOMENTUM+NDIM)
#define NVAR (VAR_DENSITY_ENERGY+1)

//extern int printf(constant char *format, ...);

void compute_flux_contribution(__private float* density, __private float3* momentum, __private float* density_energy,
		float pressure, __private float3* velocity,
		__private float3* fc_momentum_x, __private float3* fc_momentum_y, __private float3* fc_momentum_z,
		__private float3* fc_density_energy)
{
	(*fc_momentum_x).x = (*velocity).x*(*momentum).x + pressure;
	(*fc_momentum_x).y = (*velocity).x*(*momentum).y;
	(*fc_momentum_x).z = (*velocity).x*(*momentum).z;

	(*fc_momentum_y).x = (*fc_momentum_x).y;
	(*fc_momentum_y).y = (*velocity).y*(*momentum).y + pressure;
	(*fc_momentum_y).z = (*velocity).y*(*momentum).z;

	(*fc_momentum_z).x = (*fc_momentum_x).z;
	(*fc_momentum_z).y = (*fc_momentum_y).z;
	(*fc_momentum_z).z = (*velocity).z*(*momentum).z + pressure;

	float de_p = *density_energy+pressure;
	(*fc_density_energy).x = (*velocity).x*de_p;
	(*fc_density_energy).y = (*velocity).y*de_p;
	(*fc_density_energy).z = (*velocity).z*de_p;
}

void compute_velocity(float density, float3 momentum, __private float3* velocity)
{
	(*velocity).x = momentum.x / density;
	(*velocity).y = momentum.y / density;
	(*velocity).z = momentum.z / density;
}

float compute_speed_of_sound(float density, float pressure)
{
	return sqrt(GAMMA*pressure/density);
}

float compute_speed_sqd(float3 velocity)
{
	return velocity.x*velocity.x + velocity.y*velocity.y + velocity.z*velocity.z;
}

float compute_pressure(float density, float density_energy, float speed_sqd)
{
	return (GAMMA-1.0f)*(density_energy - 0.5f*density*speed_sqd);
}

__kernel void compute_flux(int nelr, __global int* elements_surrounding_elements,
		__global float* normals, __global float* variables, __global float* fc_momentum_x,
		__global float* fc_momentum_y, __global float* fc_momentum_z, __global float* fc_density_energy,
		__global float* fluxes, __global float* ff_variable, __global float3* ff_fc_momentum_x, __global float3* ff_fc_momentum_y,
		__global float3* ff_fc_momentum_z, __global float3* ff_fc_density_energy)
{
	const float smoothing_coefficient = 0.2f;
	const int i = get_global_id(0);

	int j, nb;
	float3 normal; float normal_len;
	float factor;

	float density_i = variables[i + VAR_DENSITY*nelr];
	float3 momentum_i;
	momentum_i.x = variables[i + (VAR_MOMENTUM+0)*nelr];
	momentum_i.y = variables[i + (VAR_MOMENTUM+1)*nelr];
	momentum_i.z = variables[i + (VAR_MOMENTUM+2)*nelr];

	float density_energy_i = variables[i + VAR_DENSITY_ENERGY*nelr];

	float3 velocity_i;            		   compute_velocity(density_i, momentum_i, &velocity_i);
	float speed_sqd_i                          = compute_speed_sqd(velocity_i);
	float speed_i                              = sqrt(speed_sqd_i);
	float pressure_i                           = compute_pressure(density_i, density_energy_i, speed_sqd_i);
	float speed_of_sound_i                     = compute_speed_of_sound(density_i, pressure_i);
	float3 fc_i_momentum_x, fc_i_momentum_y, fc_i_momentum_z;
	float3 fc_i_density_energy;

	fc_i_momentum_x.x = fc_momentum_x[i + 0*nelr];
	fc_i_momentum_x.y = fc_momentum_x[i + 1*nelr];
	fc_i_momentum_x.z = fc_momentum_x[i + 2*nelr];

	fc_i_momentum_y.x = fc_momentum_y[i + 0*nelr];
	fc_i_momentum_y.y = fc_momentum_y[i + 1*nelr];
	fc_i_momentum_y.z = fc_momentum_y[i + 2*nelr];

	fc_i_momentum_z.x = fc_momentum_z[i + 0*nelr];
	fc_i_momentum_z.y = fc_momentum_z[i + 1*nelr];
	fc_i_momentum_z.z = fc_momentum_z[i + 2*nelr];

	fc_i_density_energy.x = fc_density_energy[i + 0*nelr];
	fc_i_density_energy.y = fc_density_energy[i + 1*nelr];
	fc_i_density_energy.z = fc_density_energy[i + 2*nelr];

	float flux_i_density = 0.0f;
	float3 flux_i_momentum;
	flux_i_momentum.x = 0.0f;
	flux_i_momentum.y = 0.0f;
	flux_i_momentum.z = 0.0f;
	float flux_i_density_energy = 0.0f;

	float3 velocity_nb;
	float density_nb, density_energy_nb;
	float3 momentum_nb;
	float3 fc_nb_momentum_x, fc_nb_momentum_y, fc_nb_momentum_z;
	float3 fc_nb_density_energy;
	float speed_sqd_nb, speed_of_sound_nb, pressure_nb;

	for(j = 0; j < NNB; j++)
	{
		nb = elements_surrounding_elements[i + j*nelr];
		normal.x = normals[i + (j + 0*NNB)*nelr];
		normal.y = normals[i + (j + 1*NNB)*nelr];
		normal.z = normals[i + (j + 2*NNB)*nelr];
		normal_len = sqrt(normal.x*normal.x + normal.y*normal.y + normal.z*normal.z);

		if(nb >= 0) 	// a legitimate neighbor
		{
			density_nb = variables[nb + VAR_DENSITY*nelr];
			momentum_nb.x = variables[nb + (VAR_MOMENTUM+0)*nelr];
			momentum_nb.y = variables[nb + (VAR_MOMENTUM+1)*nelr];
			momentum_nb.z = variables[nb + (VAR_MOMENTUM+2)*nelr];
			density_energy_nb = variables[nb + VAR_DENSITY_ENERGY*nelr];
			compute_velocity(density_nb, momentum_nb, &velocity_nb);
			speed_sqd_nb                      = compute_speed_sqd(velocity_nb);
			pressure_nb                       = compute_pressure(density_nb, density_energy_nb, speed_sqd_nb);
			speed_of_sound_nb                 = compute_speed_of_sound(density_nb, pressure_nb);

			fc_nb_momentum_x.x = fc_momentum_x[nb + 0*nelr];
			fc_nb_momentum_x.y = fc_momentum_x[nb + 1*nelr];
			fc_nb_momentum_x.z = fc_momentum_x[nb + 2*nelr];

			fc_nb_momentum_y.x = fc_momentum_y[nb + 0*nelr];
			fc_nb_momentum_y.y = fc_momentum_y[nb + 1*nelr];
			fc_nb_momentum_y.z = fc_momentum_y[nb + 2*nelr];

			fc_nb_momentum_z.x = fc_momentum_z[nb + 0*nelr];
			fc_nb_momentum_z.y = fc_momentum_z[nb + 1*nelr];
			fc_nb_momentum_z.z = fc_momentum_z[nb + 2*nelr];

			fc_nb_density_energy.x = fc_density_energy[nb + 0*nelr];
			fc_nb_density_energy.y = fc_density_energy[nb + 1*nelr];
			fc_nb_density_energy.z = fc_density_energy[nb + 2*nelr];

			// artificial viscosity
			factor = -normal_len*smoothing_coefficient*0.5f*(speed_i + sqrt(speed_sqd_nb) + speed_of_sound_i + speed_of_sound_nb);
			flux_i_density += factor*(density_i-density_nb);
			flux_i_density_energy += factor*(density_energy_i-density_energy_nb);
			flux_i_momentum.x += factor*(momentum_i.x-momentum_nb.x);
			flux_i_momentum.y += factor*(momentum_i.y-momentum_nb.y);
			flux_i_momentum.z += factor*(momentum_i.z-momentum_nb.z);

			// accumulate cell-centered fluxes
			factor = 0.5f*normal.x;
			flux_i_density += factor*(momentum_nb.x+momentum_i.x);
			flux_i_density_energy += factor*(fc_nb_density_energy.x+fc_i_density_energy.x);
			flux_i_momentum.x += factor*(fc_nb_momentum_x.x+fc_i_momentum_x.x);
			flux_i_momentum.y += factor*(fc_nb_momentum_y.x+fc_i_momentum_y.x);
			flux_i_momentum.z += factor*(fc_nb_momentum_z.x+fc_i_momentum_z.x);

			factor = 0.5f*normal.y;
			flux_i_density += factor*(momentum_nb.y+momentum_i.y);
			flux_i_density_energy += factor*(fc_nb_density_energy.y+fc_i_density_energy.y);
			flux_i_momentum.x += factor*(fc_nb_momentum_x.y+fc_i_momentum_x.y);
			flux_i_momentum.y += factor*(fc_nb_momentum_y.y+fc_i_momentum_y.y);
			flux_i_momentum.z += factor*(fc_nb_momentum_z.y+fc_i_momentum_z.y);

			factor = 0.5f*normal.z;
			flux_i_density += factor*(momentum_nb.z+momentum_i.z);
			flux_i_density_energy += factor*(fc_nb_density_energy.z+fc_i_density_energy.z);
			flux_i_momentum.x += factor*(fc_nb_momentum_x.z+fc_i_momentum_x.z);
			flux_i_momentum.y += factor*(fc_nb_momentum_y.z+fc_i_momentum_y.z);
			flux_i_momentum.z += factor*(fc_nb_momentum_z.z+fc_i_momentum_z.z);
		}
		else if(nb == -1)	// a wing boundary
		{
			flux_i_momentum.x += normal.x*pressure_i;
			flux_i_momentum.y += normal.y*pressure_i;
			flux_i_momentum.z += normal.z*pressure_i;
		}
		else if(nb == -2) // a far field boundary
		{
			factor = 0.5f*normal.x;
			flux_i_density += factor*(ff_variable[VAR_MOMENTUM+0]+momentum_i.x);
			flux_i_density_energy += factor*(ff_fc_density_energy[0].x+fc_i_density_energy.x);
			flux_i_momentum.x += factor*(ff_fc_momentum_x[0].x + fc_i_momentum_x.x);
			flux_i_momentum.y += factor*(ff_fc_momentum_y[0].x + fc_i_momentum_y.x);
			flux_i_momentum.z += factor*(ff_fc_momentum_z[0].x + fc_i_momentum_z.x);

			factor = 0.5f*normal.y;
			flux_i_density += factor*(ff_variable[VAR_MOMENTUM+1]+momentum_i.y);
			flux_i_density_energy += factor*(ff_fc_density_energy[0].y+fc_i_density_energy.y);
			flux_i_momentum.x += factor*(ff_fc_momentum_x[0].y + fc_i_momentum_x.y);
			flux_i_momentum.y += factor*(ff_fc_momentum_y[0].y + fc_i_momentum_y.y);
			flux_i_momentum.z += factor*(ff_fc_momentum_z[0].y + fc_i_momentum_z.y);

			factor = 0.5f*normal.z;
			flux_i_density += factor*(ff_variable[VAR_MOMENTUM+2]+momentum_i.z);
			flux_i_density_energy += factor*(ff_fc_density_energy[0].z+fc_i_density_energy.z);
			flux_i_momentum.x += factor*(ff_fc_momentum_x[0].z + fc_i_momentum_x.z);
			flux_i_momentum.y += factor*(ff_fc_momentum_y[0].z + fc_i_momentum_y.z);
			flux_i_momentum.z += factor*(ff_fc_momentum_z[0].z + fc_i_momentum_z.z);

		}
	}

	fluxes[i + VAR_DENSITY*nelr] = flux_i_density;
	fluxes[i + (VAR_MOMENTUM+0)*nelr] = flux_i_momentum.x;
	fluxes[i + (VAR_MOMENTUM+1)*nelr] = flux_i_momentum.y;
	fluxes[i + (VAR_MOMENTUM+2)*nelr] = flux_i_momentum.z;
	fluxes[i + VAR_DENSITY_ENERGY*nelr] = flux_i_density_energy;
}

__kernel void compute_flux_contributions(int nelr, __global float* variables, __global float* fc_momentum_x,
		__global float* fc_momentum_y, __global float* fc_momentum_z, __global float* fc_density_energy)
{
	const int i = get_global_id(0);

	float density_i = variables[i + VAR_DENSITY*nelr];
	float3 momentum_i;
	momentum_i.x = variables[i + (VAR_MOMENTUM+0)*nelr];
	momentum_i.y = variables[i + (VAR_MOMENTUM+1)*nelr];
	momentum_i.z = variables[i + (VAR_MOMENTUM+2)*nelr];
	float density_energy_i = variables[i + VAR_DENSITY_ENERGY*nelr];

	float3 velocity_i;             				compute_velocity(density_i, momentum_i, &velocity_i);
	float speed_sqd_i                          = compute_speed_sqd(velocity_i);
	float speed_i                              = sqrt(speed_sqd_i);
	float pressure_i                           = compute_pressure(density_i, density_energy_i, speed_sqd_i);
	float speed_of_sound_i                     = compute_speed_of_sound(density_i, pressure_i);
	float3 fc_i_momentum_x, fc_i_momentum_y, fc_i_momentum_z;
	float3 fc_i_density_energy;
	compute_flux_contribution(&density_i, &momentum_i, &density_energy_i, pressure_i, &velocity_i, &fc_i_momentum_x, &fc_i_momentum_y, &fc_i_momentum_z, &fc_i_density_energy);

	fc_momentum_x[i + 0*nelr] = fc_i_momentum_x.x;
	fc_momentum_x[i + 1*nelr] = fc_i_momentum_x.y;
	fc_momentum_x[i + 2*nelr] = fc_i_momentum_x.z;

	fc_momentum_y[i + 0*nelr] = fc_i_momentum_y.x;
	fc_momentum_y[i + 1*nelr] = fc_i_momentum_y.y;
	fc_momentum_y[i + 2*nelr] = fc_i_momentum_y.z;

	fc_momentum_z[i + 0*nelr] = fc_i_momentum_z.x;
	fc_momentum_z[i + 1*nelr] = fc_i_momentum_z.y;
	fc_momentum_z[i + 2*nelr] = fc_i_momentum_z.z;

	fc_density_energy[i + 0*nelr] = fc_i_density_energy.x;
	fc_density_energy[i + 1*nelr] = fc_i_density_energy.y;
	fc_density_energy[i + 2*nelr] = fc_i_density_energy.z;
}

__kernel void compute_step_factor(int nelr, __global float* variables, __global float* areas, __global float* step_factors)
{
	const int i = get_global_id(0);

	float density = variables[i + VAR_DENSITY*nelr];
	float3 momentum;
	momentum.x = variables[i + (VAR_MOMENTUM+0)*nelr];
	momentum.y = variables[i + (VAR_MOMENTUM+1)*nelr];
	momentum.z = variables[i + (VAR_MOMENTUM+2)*nelr];

	float density_energy = variables[i + VAR_DENSITY_ENERGY*nelr];

	float3 velocity;       compute_velocity(density, momentum, &velocity);
	float speed_sqd      = compute_speed_sqd(velocity);
	float pressure       = compute_pressure(density, density_energy, speed_sqd);
	float speed_of_sound = compute_speed_of_sound(density, pressure);

	// dt = float(0.5) * sqrt(areas[i]) /  (||v|| + c).... but when we do time stepping, this later would need to be divided by the area, so we just do it all at once
	step_factors[i] = 0.5f / (sqrt(areas[i]) * (sqrt(speed_sqd) + speed_of_sound));
}

__kernel void time_step(int j, int nelr, __global float* old_variables, __global float* variables, __global float* step_factors, __global float* fluxes)
{
	const int i = get_global_id(0);

	float factor = step_factors[i]/(RK+1-j);

	variables[i + VAR_DENSITY*nelr] = old_variables[i + VAR_DENSITY*nelr] + factor*fluxes[i + VAR_DENSITY*nelr];
	variables[i + VAR_DENSITY_ENERGY*nelr] = old_variables[i + VAR_DENSITY_ENERGY*nelr] + factor*fluxes[i + VAR_DENSITY_ENERGY*nelr];
	variables[i + (VAR_MOMENTUM+0)*nelr] = old_variables[i + (VAR_MOMENTUM+0)*nelr] + factor*fluxes[i + (VAR_MOMENTUM+0)*nelr];
	variables[i + (VAR_MOMENTUM+1)*nelr] = old_variables[i + (VAR_MOMENTUM+1)*nelr] + factor*fluxes[i + (VAR_MOMENTUM+1)*nelr];
	variables[i + (VAR_MOMENTUM+2)*nelr] = old_variables[i + (VAR_MOMENTUM+2)*nelr] + factor*fluxes[i + (VAR_MOMENTUM+2)*nelr];
}

__kernel void initialize_variables(int nelr, __global float* variables, __global float* ff_variable)
{
	unsigned int i = get_global_id(0);
	for(int j = 0; j < NVAR; j++)
		variables[i + j*nelr] = ff_variable[j];
}

#define NDIM 3
#define NNB 4

#define RK 3	// 3rd order RK

#define GAMMA 1.4f
#define VAR_DENSITY 0
#define VAR_MOMENTUM  1
#define VAR_DENSITY_ENERGY (VAR_MOMENTUM+NDIM)
#define NVAR (VAR_DENSITY_ENERGY+1)

//extern int printf(constant char *format, ...);

void compute_flux_contribution(__private float* density, __private float3* momentum, __private float* density_energy,
		float pressure, __private float3* velocity,
		__private float3* fc_momentum_x, __private float3* fc_momentum_y, __private float3* fc_momentum_z,
		__private float3* fc_density_energy)
{
	(*fc_momentum_x).x = (*velocity).x*(*momentum).x + pressure;
	(*fc_momentum_x).y = (*velocity).x*(*momentum).y;
	(*fc_momentum_x).z = (*velocity).x*(*momentum).z;

	(*fc_momentum_y).x = (*fc_momentum_x).y;
	(*fc_momentum_y).y = (*velocity).y*(*momentum).y + pressure;
	(*fc_momentum_y).z = (*velocity).y*(*momentum).z;

	(*fc_momentum_z).x = (*fc_momentum_x).z;
	(*fc_momentum_z).y = (*fc_momentum_y).z;
	(*fc_momentum_z).z = (*velocity).z*(*momentum).z + pressure;

	float de_p = *density_energy+pressure;
	(*fc_density_energy).x = (*velocity).x*de_p;
	(*fc_density_energy).y = (*velocity).y*de_p;
	(*fc_density_energy).z = (*velocity).z*de_p;
}

void compute_velocity(float density, float3 momentum, __private float3* velocity)
{
	(*velocity).x = momentum.x / density;
	(*velocity).y = momentum.y / density;
	(*velocity).z = momentum.z / density;
}

float compute_speed_of_sound(float density, float pressure)
{
	return sqrt(GAMMA*pressure/density);
}

float compute_speed_sqd(float3 velocity)
{
	return velocity.x*velocity.x + velocity.y*velocity.y + velocity.z*velocity.z;
}

float compute_pressure(float density, float density_energy, float speed_sqd)
{
	return (GAMMA-1.0f)*(density_energy - 0.5f*density*speed_sqd);
}

__kernel void compute_flux(int nelr, __global int* elements_surrounding_elements,
		__global float* normals, __global float* variables, __global float* fc_momentum_x,
		__global float* fc_momentum_y, __global float* fc_momentum_z, __global float* fc_density_energy,
		__global float* fluxes, __global float* ff_variable, __global float3* ff_fc_momentum_x, __global float3* ff_fc_momentum_y,
		__global float3* ff_fc_momentum_z, __global float3* ff_fc_density_energy)
{
	const float smoothing_coefficient = 0.2f;
	const int i = get_global_id(0);

	int j, nb;
	float3 normal; float normal_len;
	float factor;

	float density_i = variables[i + VAR_DENSITY*nelr];
	float3 momentum_i;
	momentum_i.x = variables[i + (VAR_MOMENTUM+0)*nelr];
	momentum_i.y = variables[i + (VAR_MOMENTUM+1)*nelr];
	momentum_i.z = variables[i + (VAR_MOMENTUM+2)*nelr];

	float density_energy_i = variables[i + VAR_DENSITY_ENERGY*nelr];

	float3 velocity_i            		   = compute_velocity(density_i, momentum_i, &velocity_i);
	float speed_sqd_i                          = compute_speed_sqd(velocity_i);
	float speed_i                              = sqrt(speed_sqd_i);
	float pressure_i                           = compute_pressure(density_i, density_energy_i, speed_sqd_i);
	float speed_of_sound_i                     = compute_speed_of_sound(density_i, pressure_i);
	float3 fc_i_momentum_x, fc_i_momentum_y, fc_i_momentum_z;
	float3 fc_i_density_energy;

	fc_i_momentum_x.x = fc_momentum_x[i + 0*nelr];
	fc_i_momentum_x.y = fc_momentum_x[i + 1*nelr];
	fc_i_momentum_x.z = fc_momentum_x[i + 2*nelr];

	fc_i_momentum_y.x = fc_momentum_y[i + 0*nelr];
	fc_i_momentum_y.y = fc_momentum_y[i + 1*nelr];
	fc_i_momentum_y.z = fc_momentum_y[i + 2*nelr];

	fc_i_momentum_z.x = fc_momentum_z[i + 0*nelr];
	fc_i_momentum_z.y = fc_momentum_z[i + 1*nelr];
	fc_i_momentum_z.z = fc_momentum_z[i + 2*nelr];

	fc_i_density_energy.x = fc_density_energy[i + 0*nelr];
	fc_i_density_energy.y = fc_density_energy[i + 1*nelr];
	fc_i_density_energy.z = fc_density_energy[i + 2*nelr];

	float flux_i_density = 0.0f;
	float3 flux_i_momentum;
	flux_i_momentum.x = 0.0f;
	flux_i_momentum.y = 0.0f;
	flux_i_momentum.z = 0.0f;
	float flux_i_density_energy = 0.0f;

	float3 velocity_nb;
	float density_nb, density_energy_nb;
	float3 momentum_nb;
	float3 fc_nb_momentum_x, fc_nb_momentum_y, fc_nb_momentum_z;
	float3 fc_nb_density_energy;
	float speed_sqd_nb, speed_of_sound_nb, pressure_nb;

	for(j = 0; j < NNB; j++)
	{
		nb = elements_surrounding_elements[i + j*nelr];
		normal.x = normals[i + (j + 0*NNB)*nelr];
		normal.y = normals[i + (j + 1*NNB)*nelr];
		normal.z = normals[i + (j + 2*NNB)*nelr];
		normal_len = sqrt(normal.x*normal.x + normal.y*normal.y + normal.z*normal.z);

		if(nb >= 0) 	// a legitimate neighbor
		{
			density_nb = variables[nb + VAR_DENSITY*nelr];
			momentum_nb.x = variables[nb + (VAR_MOMENTUM+0)*nelr];
			momentum_nb.y = variables[nb + (VAR_MOMENTUM+1)*nelr];
			momentum_nb.z = variables[nb + (VAR_MOMENTUM+2)*nelr];
			density_energy_nb = variables[nb + VAR_DENSITY_ENERGY*nelr];
			compute_velocity(density_nb, momentum_nb, &velocity_nb);
			speed_sqd_nb                      = compute_speed_sqd(velocity_nb);
			pressure_nb                       = compute_pressure(density_nb, density_energy_nb, speed_sqd_nb);
			speed_of_sound_nb                 = compute_speed_of_sound(density_nb, pressure_nb);

			fc_nb_momentum_x.x = fc_momentum_x[nb + 0*nelr];
			fc_nb_momentum_x.y = fc_momentum_x[nb + 1*nelr];
			fc_nb_momentum_x.z = fc_momentum_x[nb + 2*nelr];

			fc_nb_momentum_y.x = fc_momentum_y[nb + 0*nelr];
			fc_nb_momentum_y.y = fc_momentum_y[nb + 1*nelr];
			fc_nb_momentum_y.z = fc_momentum_y[nb + 2*nelr];

			fc_nb_momentum_z.x = fc_momentum_z[nb + 0*nelr];
			fc_nb_momentum_z.y = fc_momentum_z[nb + 1*nelr];
			fc_nb_momentum_z.z = fc_momentum_z[nb + 2*nelr];

			fc_nb_density_energy.x = fc_density_energy[nb + 0*nelr];
			fc_nb_density_energy.y = fc_density_energy[nb + 1*nelr];
			fc_nb_density_energy.z = fc_density_energy[nb + 2*nelr];

			// artificial viscosity
			factor = -normal_len*smoothing_coefficient*0.5f*(speed_i + sqrt(speed_sqd_nb) + speed_of_sound_i + speed_of_sound_nb);
			flux_i_density += factor*(density_i-density_nb);
			flux_i_density_energy += factor*(density_energy_i-density_energy_nb);
			flux_i_momentum.x += factor*(momentum_i.x-momentum_nb.x);
			flux_i_momentum.y += factor*(momentum_i.y-momentum_nb.y);
			flux_i_momentum.z += factor*(momentum_i.z-momentum_nb.z);

			// accumulate cell-centered fluxes
			factor = 0.5f*normal.x;
			flux_i_density += factor*(momentum_nb.x+momentum_i.x);
			flux_i_density_energy += factor*(fc_nb_density_energy.x+fc_i_density_energy.x);
			flux_i_momentum.x += factor*(fc_nb_momentum_x.x+fc_i_momentum_x.x);
			flux_i_momentum.y += factor*(fc_nb_momentum_y.x+fc_i_momentum_y.x);
			flux_i_momentum.z += factor*(fc_nb_momentum_z.x+fc_i_momentum_z.x);

			factor = 0.5f*normal.y;
			flux_i_density += factor*(momentum_nb.y+momentum_i.y);
			flux_i_density_energy += factor*(fc_nb_density_energy.y+fc_i_density_energy.y);
			flux_i_momentum.x += factor*(fc_nb_momentum_x.y+fc_i_momentum_x.y);
			flux_i_momentum.y += factor*(fc_nb_momentum_y.y+fc_i_momentum_y.y);
			flux_i_momentum.z += factor*(fc_nb_momentum_z.y+fc_i_momentum_z.y);

			factor = 0.5f*normal.z;
			flux_i_density += factor*(momentum_nb.z+momentum_i.z);
			flux_i_density_energy += factor*(fc_nb_density_energy.z+fc_i_density_energy.z);
			flux_i_momentum.x += factor*(fc_nb_momentum_x.z+fc_i_momentum_x.z);
			flux_i_momentum.y += factor*(fc_nb_momentum_y.z+fc_i_momentum_y.z);
			flux_i_momentum.z += factor*(fc_nb_momentum_z.z+fc_i_momentum_z.z);
		}
		else if(nb == -1)	// a wing boundary
		{
			flux_i_momentum.x += normal.x*pressure_i;
			flux_i_momentum.y += normal.y*pressure_i;
			flux_i_momentum.z += normal.z*pressure_i;
		}
		else if(nb == -2) // a far field boundary
		{
			factor = 0.5f*normal.x;
			flux_i_density += factor*(ff_variable[VAR_MOMENTUM+0]+momentum_i.x);
			flux_i_density_energy += factor*(ff_fc_density_energy[0].x+fc_i_density_energy.x);
			flux_i_momentum.x += factor*(ff_fc_momentum_x[0].x + fc_i_momentum_x.x);
			flux_i_momentum.y += factor*(ff_fc_momentum_y[0].x + fc_i_momentum_y.x);
			flux_i_momentum.z += factor*(ff_fc_momentum_z[0].x + fc_i_momentum_z.x);

			factor = 0.5f*normal.y;
			flux_i_density += factor*(ff_variable[VAR_MOMENTUM+1]+momentum_i.y);
			flux_i_density_energy += factor*(ff_fc_density_energy[0].y+fc_i_density_energy.y);
			flux_i_momentum.x += factor*(ff_fc_momentum_x[0].y + fc_i_momentum_x.y);
			flux_i_momentum.y += factor*(ff_fc_momentum_y[0].y + fc_i_momentum_y.y);
			flux_i_momentum.z += factor*(ff_fc_momentum_z[0].y + fc_i_momentum_z.y);

			factor = 0.5f*normal.z;
			flux_i_density += factor*(ff_variable[VAR_MOMENTUM+2]+momentum_i.z);
			flux_i_density_energy += factor*(ff_fc_density_energy[0].z+fc_i_density_energy.z);
			flux_i_momentum.x += factor*(ff_fc_momentum_x[0].z + fc_i_momentum_x.z);
			flux_i_momentum.y += factor*(ff_fc_momentum_y[0].z + fc_i_momentum_y.z);
			flux_i_momentum.z += factor*(ff_fc_momentum_z[0].z + fc_i_momentum_z.z);

		}
	}

	fluxes[i + VAR_DENSITY*nelr] = flux_i_density;
	fluxes[i + (VAR_MOMENTUM+0)*nelr] = flux_i_momentum.x;
	fluxes[i + (VAR_MOMENTUM+1)*nelr] = flux_i_momentum.y;
	fluxes[i + (VAR_MOMENTUM+2)*nelr] = flux_i_momentum.z;
	fluxes[i + VAR_DENSITY_ENERGY*nelr] = flux_i_density_energy;
}

__kernel void compute_flux_contributions(int nelr, __global float* variables, __global float* fc_momentum_x,
		__global float* fc_momentum_y, __global float* fc_momentum_z, __global float* fc_density_energy)
{
	const int i = get_global_id(0);

	float density_i = variables[i + VAR_DENSITY*nelr];
	float3 momentum_i;
	momentum_i.x = variables[i + (VAR_MOMENTUM+0)*nelr];
	momentum_i.y = variables[i + (VAR_MOMENTUM+1)*nelr];
	momentum_i.z = variables[i + (VAR_MOMENTUM+2)*nelr];
	float density_energy_i = variables[i + VAR_DENSITY_ENERGY*nelr];

	float3 velocity_i;             				compute_velocity(density_i, momentum_i, &velocity_i);
	float speed_sqd_i                          = compute_speed_sqd(velocity_i);
	float speed_i                              = sqrt(speed_sqd_i);
	float pressure_i                           = compute_pressure(density_i, density_energy_i, speed_sqd_i);
	float speed_of_sound_i                     = compute_speed_of_sound(density_i, pressure_i);
	float3 fc_i_momentum_x, fc_i_momentum_y, fc_i_momentum_z;
	float3 fc_i_density_energy;
	compute_flux_contribution(&density_i, &momentum_i, &density_energy_i, pressure_i, &velocity_i, &fc_i_momentum_x, &fc_i_momentum_y, &fc_i_momentum_z, &fc_i_density_energy);

	fc_momentum_x[i + 0*nelr] = fc_i_momentum_x.x;
	fc_momentum_x[i + 1*nelr] = fc_i_momentum_x.y;
	fc_momentum_x[i + 2*nelr] = fc_i_momentum_x.z;

	fc_momentum_y[i + 0*nelr] = fc_i_momentum_y.x;
	fc_momentum_y[i + 1*nelr] = fc_i_momentum_y.y;
	fc_momentum_y[i + 2*nelr] = fc_i_momentum_y.z;

	fc_momentum_z[i + 0*nelr] = fc_i_momentum_z.x;
	fc_momentum_z[i + 1*nelr] = fc_i_momentum_z.y;
	fc_momentum_z[i + 2*nelr] = fc_i_momentum_z.z;

	fc_density_energy[i + 0*nelr] = fc_i_density_energy.x;
	fc_density_energy[i + 1*nelr] = fc_i_density_energy.y;
	fc_density_energy[i + 2*nelr] = fc_i_density_energy.z;
}

__kernel void compute_step_factor(int nelr, __global float* variables, __global float* areas, __global float* step_factors)
{
	const int i = get_global_id(0);

	float density = variables[i + VAR_DENSITY*nelr];
	float3 momentum;
	momentum.x = variables[i + (VAR_MOMENTUM+0)*nelr];
	momentum.y = variables[i + (VAR_MOMENTUM+1)*nelr];
	momentum.z = variables[i + (VAR_MOMENTUM+2)*nelr];

	float density_energy = variables[i + VAR_DENSITY_ENERGY*nelr];

	float3 velocity;       compute_velocity(density, momentum, &velocity);
	float speed_sqd      = compute_speed_sqd(velocity);
	float pressure       = compute_pressure(density, density_energy, speed_sqd);
	float speed_of_sound = compute_speed_of_sound(density, pressure);

	// dt = float(0.5) * sqrt(areas[i]) /  (||v|| + c).... but when we do time stepping, this later would need to be divided by the area, so we just do it all at once
	step_factors[i] = 0.5f / (sqrt(areas[i]) * (sqrt(speed_sqd) + speed_of_sound));
}

__kernel void time_step(int j, int nelr, __global float* old_variables, __global float* variables, __global float* step_factors, __global float* fluxes)
{
	const int i = get_global_id(0);

	float factor = step_factors[i]/(RK+1-j);

	variables[i + VAR_DENSITY*nelr] = old_variables[i + VAR_DENSITY*nelr] + factor*fluxes[i + VAR_DENSITY*nelr];
	variables[i + VAR_DENSITY_ENERGY*nelr] = old_variables[i + VAR_DENSITY_ENERGY*nelr] + factor*fluxes[i + VAR_DENSITY_ENERGY*nelr];
	variables[i + (VAR_MOMENTUM+0)*nelr] = old_variables[i + (VAR_MOMENTUM+0)*nelr] + factor*fluxes[i + (VAR_MOMENTUM+0)*nelr];
	variables[i + (VAR_MOMENTUM+1)*nelr] = old_variables[i + (VAR_MOMENTUM+1)*nelr] + factor*fluxes[i + (VAR_MOMENTUM+1)*nelr];
	variables[i + (VAR_MOMENTUM+2)*nelr] = old_variables[i + (VAR_MOMENTUM+2)*nelr] + factor*fluxes[i + (VAR_MOMENTUM+2)*nelr];
}

__kernel void initialize_variables(int nelr, __global float* variables, __global float* ff_variable)
{
	unsigned int i = get_global_id(0);
	for(int j = 0; j < NVAR; j++)
		variables[i + j*nelr] = ff_variable[j];
}


OpenCL BJDS result now correct

OpenCL BJDS result now correct

#if defined(cl_khr_fp64)
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#elif defined(cl_amd_fp64)
#pragma OPENCL EXTENSION cl_amd_fp64 : enable
#endif

#if defined(cl_intel_printf)
#pragma OPENCL EXTENSION cl_intel_printf : enable
#elif defined(cl_amd_printf)
#pragma OPENCL EXTENSION cl_amd_printf : enable
#endif

#include <cl/ghost_cl_types.h>
#include <ghost_constants.h>

kernel void BJDS_kernel(global ghost_cl_vdat_t *lhs, global ghost_cl_vdat_t *rhsVec, int options, unsigned int nRows, unsigned int nRowsPadded, global unsigned int *rowLen, global unsigned int *col, global ghost_cl_mdat_t *val, global unsigned int *chunkStart, global unsigned int *chunkLen)
{
	unsigned int i = get_global_id(0);

	if (i < nRows) {
		unsigned int cs = chunkStart[get_group_id(0)];
		unsigned int li = get_local_id(0);

		ghost_cl_vdat_t tmp = 0.0, rhs = 0.0;
		ghost_cl_mdat_t value = 0.0;

		unsigned int max = rowLen[i];
		int colidx;

		for(unsigned int j=0; j<max; ++j){
			value = val[cs + li + j*BJDS_LEN];
			colidx = col[cs + li + j*BJDS_LEN];
			rhs = rhsVec[colidx];

#ifdef GHOST_MAT_COMPLEX
#ifdef GHOST_VEC_COMPLEX
			tmp.s0 += value.s0 * rhs.s0 - value.s1 * rhs.s1;
			tmp.s1 += value.s0 * rhs.s1 + value.s1 * rhs.s0;
#else
			tmp += value.s0 * rhs;
#endif
#endif
#ifdef GHOST_MAT_REAL
#ifdef GHOST_VEC_REAL
			tmp += value*rhs;
#else
			tmp.s0 += value * rhs.s0;
			tmp.s1 += value * rhs.s1;
#endif
#endif
		}
		if (options & GHOST_SPMVM_AXPY)
			lhs[i] += tmp;
		else
			lhs[i] = tmp;
	}
}

#if defined(cl_khr_fp64)
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#elif defined(cl_amd_fp64)
#pragma OPENCL EXTENSION cl_amd_fp64 : enable
#endif

#if defined(cl_intel_printf)
#pragma OPENCL EXTENSION cl_intel_printf : enable
#elif defined(cl_amd_printf)
#pragma OPENCL EXTENSION cl_amd_printf : enable
#endif

#include <cl/ghost_cl_types.h>
#include <ghost_constants.h>

kernel void BJDS_kernel(global ghost_cl_vdat_t *lhs, global ghost_cl_vdat_t *rhsVec, int options, unsigned int nRows, unsigned int nRowsPadded, global unsigned int *rowLen, global unsigned int *col, global ghost_cl_mdat_t *val, global unsigned int *chunkStart, global unsigned int *chunkLen)
{
	unsigned int i = get_global_id(0);

	if (i < nRows) {
		unsigned int cs = chunkStart[get_group_id(0)];
		unsigned int li = get_local_id(0);

		ghost_cl_vdat_t tmp = 0.0, rhs = 0.0;
		ghost_cl_mdat_t value = 0.0;

		unsigned int max = rowLen[i];
		int colidx;

		for(unsigned int j=0; j<max; ++j){
			value = val[cs + li + j*BJDS_LEN];
			colidx = col[cs + li + j*BJDS_LEN];
			rhs = rhsVec[colidx];

#ifdef GHOST_MAT_COMPLEX
#ifdef GHOST_VEC_COMPLEX
			tmp.s0 += val[j].s0 * rhs.s0 - val[j].s1 * rhs.s1;
			tmp.s1 += val[j].s0 * rhs.s1 + val[j].s1 * rhs.s0;
#else
			tmp += val[j].s0 * rhs;
#endif
#endif
#ifdef GHOST_MAT_REAL
#ifdef GHOST_VEC_REAL
			tmp += val[j]*rhs;
#else
			tmp.s0 += val[j] * rhs.s0;
			tmp.s1 += val[j] * rhs.s1;
#endif
#endif
		}
		if (options & GHOST_SPMVM_AXPY)
			lhs[i] += tmp;
		else
			lhs[i] = tmp;
	}
}


Basic vectorization of OpenCL code.

Basic vectorization of OpenCL code.

Former-commit-id: 51f6aed191069b1297f3e8ab995b49c6c12cb4a4

//parameters
#define NUMBER_OF_CELLS 1
#define NUMBER_OF_BINS 8
#define GAUSSIAN_WEIGHTS 1
#define SPARTIAL_WEIGHTS 0
#define SIGNED_HOG 1
//parameters end

#define TOTAL_NUMBER_OF_BINS (NUMBER_OF_CELLS * NUMBER_OF_CELLS * NUMBER_OF_BINS)

//get_global_id(0): per location
//get_global_id(1): x coordinate
//get_global_id(2): y coordinate

void atomic_add_float(volatile __global float* source, float operand) {
    volatile __global int* sourceAsInt = (volatile __global int*)source;
    float oldVal;
    float newVal;
    do {
        oldVal = *source;
        newVal = oldVal + operand;
    } while (atomic_cmpxchg(sourceAsInt, as_int(oldVal), as_int(newVal)) != as_int(oldVal));
}

#define HIST_INDEX(location, celly, cellx, bin)                         \
        ( hist                                                          \
        + (location)*NUMBER_OF_CELLS*NUMBER_OF_CELLS*NUMBER_OF_BINS     \
        + (celly)*NUMBER_OF_CELLS*NUMBER_OF_BINS                        \
        + (cellx)*NUMBER_OF_BINS                                        \
        + (bin)                                                         \
        )

// OpenCL 1.1 does not have clEnqueueFillBuffer...
__kernel void fill_zeros(__global float* arr, int size) {
    int i = get_global_id(0);
    if (i < size) {
        arr[i] = 0.0f;
    }
}

//Calculates the intermediate data
__kernel void calc_histogram( const int rows, const int cols, const int step, __global const unsigned char *image
                            , const int num_locations, __global const float2 *location
                            , const float blck_size
                            , __global float *hist
                            )
{
    int i = get_global_id(0);
    if (i >= num_locations)
        return;

    int2 img_size = (int2)(cols, rows);

    float2 minloc = location[i] - blck_size / 2.0f;
    float2 maxloc = location[i] + blck_size / 2.0f;

    int2 mini = max(convert_int2_rtp(minloc), 1);
    int2 maxi = min(convert_int2_rtn(maxloc), img_size - 2);

    int2 point = mini + (int2)(get_global_id(1),get_global_id(2));

    if (!all(point <= maxi))
        return;

    //Read the image
    float mdx = image[(point.y  )*step + point.x+1] - image[(point.y  )*step + point.x-1];
    float mdy = image[(point.y+1)*step + point.x  ] - image[(point.y-1)*step + point.x  ];

    //calculate the magnitude
    float magnitude = hypot(mdx, mdy);

    //calculate the orientation
#if SIGNED_HOG
    float orientation = atan2pi(mdy, mdx) / 2.0f;
#else
    float orientation = tan2pi(mdy / mdx + DBL_EPSILON) + 0.5f;
#endif

#if GAUSSIAN_WEIGHTS
    {
        float sigma = blck_size / 2.0f;
        float sigmaSq = sigma*sigma;
        float m1p2sigmaSq = -1.0f / (2.0f * sigmaSq);
        float2 distanceSq = pown(convert_float2(point) - location[i], 2);
        magnitude *= exp(dot(distanceSq, m1p2sigmaSq));
    }
#endif
    float relative_orientation = orientation * NUMBER_OF_BINS - 0.5f;
    int bin1 = ceil(relative_orientation);
    int bin0 = bin1 - 1;
    float bin_weight0 = magnitude * (bin1 - relative_orientation);
    float bin_weight1 = magnitude * (relative_orientation - bin0);
    bin0 = (bin0 + NUMBER_OF_BINS) % NUMBER_OF_BINS;
    bin1 = (bin1 + NUMBER_OF_BINS) % NUMBER_OF_BINS;

#if SPARTIAL_WEIGHTS
    if (cellyi >= 0 && cellxi >= 0) {
        atomic_add_float( HIST_INDEX(i, cellyi  , cellxi  , bin0), yscale0 * xscale0 * bin_weight0);
        atomic_add_float( HIST_INDEX(i, cellyi  , cellxi  , bin1), yscale0 * xscale0 * bin_weight1);
    }
    if (cellyi >= 0 && cellxi < NUMBER_OF_CELLS - 1) {
        atomic_add_float( HIST_INDEX(i, cellyi  , cellxi+1, bin0), yscale0 * xscale1 * bin_weight0);
        atomic_add_float( HIST_INDEX(i, cellyi  , cellxi+1, bin1), yscale0 * xscale1 * bin_weight1);
    }
    if (cellyi < NUMBER_OF_CELLS - 1 && cellxi >= 0) {
        atomic_add_float( HIST_INDEX(i, cellyi+1, cellxi  , bin0), yscale1 * xscale0 * bin_weight0);
        atomic_add_float( HIST_INDEX(i, cellyi+1, cellxi  , bin1), yscale1 * xscale0 * bin_weight1);
    }
    if (cellyi < NUMBER_OF_CELLS - 1 && cellxi < NUMBER_OF_CELLS - 1) {
        atomic_add_float( HIST_INDEX(i, cellyi+1, cellxi+1, bin0), yscale1 * xscale1 * bin_weight0);
        atomic_add_float( HIST_INDEX(i, cellyi+1, cellxi+1, bin1), yscale1 * xscale1 * bin_weight1);
    }
#elif NUMBER_OF_CELLS == 1
    atomic_add_float( HIST_INDEX(i, 0, 0, bin0), bin_weight0);
    atomic_add_float( HIST_INDEX(i, 0, 0, bin1), bin_weight1);
#else
    int cellxi = floor((pointx - minx) / cell_size);
    int cellyi = floor((pointy - miny) / cell_size);

    atomic_add_float( HIST_INDEX(i, cellyi, cellxi, bin0), bin_weight0);
    atomic_add_float( HIST_INDEX(i, cellyi, cellxi, bin1), bin_weight1);
#endif
}

//parameters
#define NUMBER_OF_CELLS 1
#define NUMBER_OF_BINS 8
#define GAUSSIAN_WEIGHTS 1
#define SPARTIAL_WEIGHTS 0
#define SIGNED_HOG 1
//parameters end

#if SIGNED_HOG
#define BINSIZE_IN_DEGREES (360.0f / NUMBER_OF_BINS)
#else
#define BINSIZE_IN_DEGREES (180.0f / NUMBER_OF_BINS)
#endif

#ifndef M_PI
#define M_PI           3.14159265358979323846
#endif

//get_global_id(0): per location
//get_global_id(1): x coordinate
//get_global_id(2): y coordinate

void atomic_add_float(volatile __global float* source, float operand) {
    volatile __global int* sourceAsInt = (volatile __global int*)source;
    float oldVal;
    float newVal;
    do {
        oldVal = *source;
        newVal = oldVal + operand;
    } while (atomic_cmpxchg(sourceAsInt, as_int(oldVal), as_int(newVal)) != as_int(oldVal));
}

#define HIST_INDEX(location, celly, cellx, bin)                         \
        ( hist                                                          \
        + (location)*NUMBER_OF_CELLS*NUMBER_OF_CELLS*NUMBER_OF_BINS     \
        + (celly)*NUMBER_OF_CELLS*NUMBER_OF_BINS                        \
        + (cellx)*NUMBER_OF_BINS                                        \
        + (bin)                                                         \
        )

// OpenCL 1.1 does not have clEnqueueFillBuffer...
__kernel void fill_zeros(__global float* arr, int size) {
    int i = get_global_id(0);
    if (i < size) {
        arr[i] = 0.0f;
    }
}

//Calculates the intermediate data
__kernel void calc_histogram( const int rows, const int cols, const int step, __global const unsigned char *image
                            , const int num_locations, __global const float2 *location
                            , const float blck_size
                            , __global float *hist
                            )
{
    int i = get_global_id(0);
    if (i >= num_locations)
        return;

    float minx = location[i].x - blck_size / 2.0f;
    float miny = location[i].y - blck_size / 2.0f;
    float maxx = location[i].x + blck_size / 2.0f;
    float maxy = location[i].y + blck_size / 2.0f;

    int minxi = max((int)ceil(minx), 1);
    int minyi = max((int)ceil(miny), 1);
    int maxxi = min((int)floor(maxx), cols - 2);
    int maxyi = min((int)floor(maxy), rows - 2);

    int pointy = minyi + get_global_id(2); //int+size_t !!
    int pointx = minxi + get_global_id(1);

    if (pointy > maxyi || pointx > maxxi)
        return;

    //Read the image
    float mdx = image[(pointy  )*step + pointx+1] - image[(pointy  )*step + pointx-1];
    float mdy = image[(pointy+1)*step + pointx  ] - image[(pointy-1)*step + pointx  ];

    //calculate the magnitude
    float magnitude = hypot(mdx, mdy);

    //calculate the orientation
#if SIGNED_HOG
    float orientation = atan2(mdy, mdx) / (float)M_PI * 180.0f;
#else
    float orientation = tan2(mdy / mdx + DBL_EPSILON) / (float)M_PI * 180.0f + 90.0f;
#endif

#if GAUSSIAN_WEIGHTS
    {
        float sigma = blck_size / 2.0f;
        float sigmaSq = sigma*sigma;
        float m1p2sigmaSq = -1.0f / (2.0f * sigmaSq);
        float dy = pointy - location[i].y;
        float dx = pointx - location[i].x;
        float dySq = dy*dy;
        float dxSq = dx*dx;
        magnitude *= exp((dxSq+dySq) * m1p2sigmaSq);
    }
#endif
    float relative_orientation = (orientation - BINSIZE_IN_DEGREES/2.0f) / BINSIZE_IN_DEGREES;
    int bin1 = ceil(relative_orientation);
    int bin0 = bin1 - 1;
    float bin_weight0 = magnitude * (bin1 - relative_orientation);
    float bin_weight1 = magnitude * (relative_orientation - bin0);
    bin0 = (bin0 + NUMBER_OF_BINS) % NUMBER_OF_BINS;
    bin1 = (bin1 + NUMBER_OF_BINS) % NUMBER_OF_BINS;
#if SPARTIAL_WEIGHTS
    if (cellyi >= 0 && cellxi >= 0) {
        atomic_add_float( HIST_INDEX(i, cellyi  , cellxi  , bin0), yscale0 * xscale0 * bin_weight0);
        atomic_add_float( HIST_INDEX(i, cellyi  , cellxi  , bin1), yscale0 * xscale0 * bin_weight1);
    }
    if (cellyi >= 0 && cellxi < NUMBER_OF_CELLS - 1) {
        atomic_add_float( HIST_INDEX(i, cellyi  , cellxi+1, bin0), yscale0 * xscale1 * bin_weight0);
        atomic_add_float( HIST_INDEX(i, cellyi  , cellxi+1, bin1), yscale0 * xscale1 * bin_weight1);
    }
    if (cellyi < NUMBER_OF_CELLS - 1 && cellxi >= 0) {
        atomic_add_float( HIST_INDEX(i, cellyi+1, cellxi  , bin0), yscale1 * xscale0 * bin_weight0);
        atomic_add_float( HIST_INDEX(i, cellyi+1, cellxi  , bin1), yscale1 * xscale0 * bin_weight1);
    }
    if (cellyi < NUMBER_OF_CELLS - 1 && cellxi < NUMBER_OF_CELLS - 1) {
        atomic_add_float( HIST_INDEX(i, cellyi+1, cellxi+1, bin0), yscale1 * xscale1 * bin_weight0);
        atomic_add_float( HIST_INDEX(i, cellyi+1, cellxi+1, bin1), yscale1 * xscale1 * bin_weight1);
    }
#elif NUMBER_OF_CELLS == 1
    atomic_add_float( HIST_INDEX(i, 0, 0, bin0), bin_weight0);
    atomic_add_float( HIST_INDEX(i, 0, 0, bin1), bin_weight1);
#else
    int cellxi = floor((pointx - minx) / cell_size);
    int cellyi = floor((pointy - miny) / cell_size);

    atomic_add_float( HIST_INDEX(i, cellyi, cellxi, bin0), bin_weight0);
    atomic_add_float( HIST_INDEX(i, cellyi, cellxi, bin1), bin_weight1);
#endif
}


Finish adding "World's Craziest Fools"

Finish adding "World's Craziest Fools"

(in-package :user)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Feed and other options

(setq *log-rss* (merge-pathnames "rss.log" *tget-data-directory*))
(setq *log-file* (merge-pathnames "ep.log" *tget-data-directory*))

;; Wait 6 hours before downloading (most) episodes, to wait for repacks and
;; propers.
(defvar *tvt-delay* 6)

(defun tvt-rss-feed (days)
  (format nil "~a&interval=~d+days" (sys:getenv "TGET_TVT_RSS_BASE") days))

(defvar *tvt-rss* 'tvt-rss-feed)

;; custom rss feed with these options:
;; - feed name: RegularShow
;; - series: Regular Show
;; - category: Episode
;; - resolutions: 720p (less than this quality are crap)
(defvar *btn-regular-show-rss* (sys:getenv "TGET_BTN_RSS_REGULARSHOW"))

;; custom rss feed with these options:
;; - feed name: Spongebob
;; - series: Spongebob Squarepants
;; - category: Episode
;; - resolutions: 720p (less than this quality are crap)
(defvar *btn-spongebob-rss* (sys:getenv "TGET_BTN_RSS_SPONGEBOB"))

;; custom rss feed with these options:
;; - category: Episode
;; - containers: mp4
;; - codecs: x264
(defvar *btn-crazy-fools-rss* (sys:getenv "TGET_BTN_RSS_CRAZY_FOOLS"))

#+not-yet
(deftransmission ()
    :host (sys:getenv "TRANSMISSION_HOST")
    :port 9091
    :username (sys:getenv "TRANSMISSION_USER")
    :password (sys:getenv "TRANSMISSION_PASS")
    :add-paused nil
    :ratio "1.04"
    ;; Don't enable this because I like to see what's there before it's
    ;; removed.
    :remove-when-done nil)

(setq *download-root* "/me/layer/videos/")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Quality settings

(defquality :normal
    :source :hdtv
    :codec :x264
    :resolution :<720p)

(defquality :high
    :source :hdtv
    :codec :x264
    :resolution :720p)

(defquality :low
    :source :hdtv
    :codec :xvid
    :resolution :<720p)

(defun my-quality (episode)
  ;; Download :normal quality immediately.
  ;; If that's not available, then download :high quality after 12 hours
  ;; and :low quality after 2 days.  There are still some shows that never
  ;; get anything but :low, for some episodes.
  (if* (and (null
	     ;; See if there is an episode with :normal quality.  The
	     ;; :transient keyword is important, since it restricts the
	     ;; search to episodes we have *not* downloaded yet.
	     (query-episode :episode episode :quality :normal :transient t))
	    (eq :high (episode-quality episode))
	    (>= (hours-available episode) 12))
     then ;; :normal quality is not available and the :high quality episode
	  ;; has been available for 12 hours, then return...
	  :high
   elseif (and (null
		;; See if there is an episode with :normal or :high
		;; quality.
		(or
		 (query-episode :episode episode :quality :normal :transient t)
		 (query-episode :episode episode :quality :high :transient t)))
	       (eq :low (episode-quality episode))
	       (>= (hours-available episode) 48))
     then :low
     else :normal))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :adrian
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "adrian/" *download-root*))

(defseries "Phineas and Furb" :adrian)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :anh
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "anh/" *download-root*))

(defseries "Downton Abbey" :anh)
(defseries "Midsomer Murders" :anh)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "kevin/" *download-root*))

(defseries "8 Out of 10 Cats" :kevin)
(defseries "Boardwalk Empire" :kevin)
(defseries "Breaking Bad" :kevin :delay 0) ;; immediate download
(defseries "Childrens Hospital (US)" :kevin)
(defseries "Come Fly with Me (2010)" :kevin)
(defseries "Dexter" :kevin)
(defseries "Dragons Den" :kevin)
(defseries "Elementary" :kevin)
(defseries "Falling Skies" :kevin)
(defseries "Frontline" :kevin)
(defseries "Game of Thrones" :kevin :delay 0) ;; immediate download
(defseries "Homeland" :kevin)
(defseries "Justified" :kevin :delay 0) ;; immediate download
(defseries "Longmire" :kevin)
(defseries "Louis Theroux Documentaries" :kevin)
(defseries "Louis" :kevin)
(defseries "Luther" :kevin)
(defseries "Mad Men" :kevin)
(defseries "Misfits" :kevin)
(defseries "Motive" :kevin)
(defseries "Orphan Black" :kevin)
(defseries "Person of Interest" :kevin)
(defseries "Shameless (US)" :kevin)
(defseries "Sherlock" :kevin)
(defseries "Southland" :kevin)
(defseries "Strike Back" :kevin)
(defseries "The Americans (2013)" :kevin)
(defseries "The Colbert Report" :kevin)
(defseries "The Daily Show with Jon Stewart" :kevin)
(defseries "The Graham Norton Show" :kevin)
(defseries "The IT Crowd" :kevin)
(defseries "The Jeselnik Offensive" :kevin)
(defseries "The Newsroom (2012)" :kevin)
(defseries "The Ultimate Fighter" :kevin)
(defseries "The Walking Dead" :kevin :delay 0) ;; immediate download
(defseries "Tosh.0" :kevin)
(defseries "Vikings" :kevin)
(defseries "Witness (2012)" :kevin)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :adrian+kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "An Idiot Abroad" :adrian+kevin)
(defseries "Community" :adrian+kevin)
(defseries "Eagleheart" :adrian+kevin)
(defseries "Futurama" :adrian+kevin)
(defseries "James May's Man Lab" :adrian+kevin)
(defseries "Modern Family" :adrian+kevin)
(defseries "Mythbusters" :adrian+kevin)
(defseries "Nathan for You" :adrian+kevin)
(defseries "NCIS" :adrian+kevin)
(defseries "Nova" :adrian+kevin)
(defseries "Parks and Recreation" :adrian+kevin)
(defseries "Ridiculousness" :adrian+kevin)
(defseries "Shark Tank" :adrian+kevin)
(defseries "The Mentalist" :adrian+kevin)
(defseries "The Neighbors (2012)" :adrian+kevin)
(defseries "The Simpsons" :adrian+kevin)
(defseries "Top Gear" :adrian+kevin :quality :high)
(defseries "Top Gear (US)" :adrian+kevin :quality :high)
(defseries "World's Craziest Fools" :adrian+kevin)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :btn-regular-show
    :rss-url *btn-regular-show-rss*
    :ratio "-1"
    :client :transmission-rpc
    :quality t ;; built into the feed
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "Regular Show" :btn-regular-show)

(defgroup :btn-spongebob
    :rss-url *btn-spongebob-rss*
    :ratio "-1"
    :client :transmission-rpc
    :quality t ;; built into the feed
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "Spongebob Squarepants" :btn-spongebob)

(defgroup :btn-crazy-fools
    :rss-url *btn-crazy-fools-rss*
    :ratio "-1"
    :client :transmission-rpc
    :quality t ;; built into the feed
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "World's Craziest Fools" :btn-crazy-fools)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :anh+kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "anh+kevin/" *download-root*))

(defseries "Bates Motel" :anh+kevin)
(defseries "Curb your Enthusiasm" :anh+kevin)
(defseries "Doc Martin" :anh+kevin)
(defseries "The Following" :anh+kevin)
(defseries "The Good Wife" :anh+kevin)
(defseries "The Killing" :anh+kevin)
(defseries "Wallander" :anh+kevin)
(defseries "White Collar" :anh+kevin)

(in-package :user)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Feed and other options

(setq *log-rss* (merge-pathnames "rss.log" *tget-data-directory*))
(setq *log-file* (merge-pathnames "ep.log" *tget-data-directory*))

;; Wait 6 hours before downloading (most) episodes, to wait for repacks and
;; propers.
(defvar *tvt-delay* 6)

(defun tvt-rss-feed (days)
  (format nil "~a&interval=~d+days" (sys:getenv "TGET_TVT_RSS_BASE") days))

(defvar *tvt-rss* 'tvt-rss-feed)

;; custom rss feed with these options:
;; - feed name: RegularShow
;; - series: Regular Show
;; - category: Episode
;; - resolutions: 720p (less than this quality are crap)
(defvar *btn-regular-show-rss* (sys:getenv "TGET_BTN_RSS_REGULARSHOW"))

;; custom rss feed with these options:
;; - feed name: Spongebob
;; - series: Spongebob Squarepants
;; - category: Episode
;; - resolutions: 720p (less than this quality are crap)
(defvar *btn-spongebob-rss* (sys:getenv "TGET_BTN_RSS_SPONGEBOB"))

#+not-yet
(deftransmission ()
    :host (sys:getenv "TRANSMISSION_HOST")
    :port 9091
    :username (sys:getenv "TRANSMISSION_USER")
    :password (sys:getenv "TRANSMISSION_PASS")
    :add-paused nil
    :ratio "1.04"
    ;; Don't enable this because I like to see what's there before it's
    ;; removed.
    :remove-when-done nil)

(setq *download-root* "/me/layer/videos/")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Quality settings

(defquality :normal
    :source :hdtv
    :codec :x264
    :resolution :<720p)

(defquality :high
    :source :hdtv
    :codec :x264
    :resolution :720p)

(defquality :low
    :source :hdtv
    :codec :xvid
    :resolution :<720p)

(defun my-quality (episode)
  ;; Download :normal quality immediately.
  ;; If that's not available, then download :high quality after 12 hours
  ;; and :low quality after 2 days.  There are still some shows that never
  ;; get anything but :low, for some episodes.
  (if* (and (null
	     ;; See if there is an episode with :normal quality.  The
	     ;; :transient keyword is important, since it restricts the
	     ;; search to episodes we have *not* downloaded yet.
	     (query-episode :episode episode :quality :normal :transient t))
	    (eq :high (episode-quality episode))
	    (>= (hours-available episode) 12))
     then ;; :normal quality is not available and the :high quality episode
	  ;; has been available for 12 hours, then return...
	  :high
   elseif (and (null
		;; See if there is an episode with :normal or :high
		;; quality.
		(or
		 (query-episode :episode episode :quality :normal :transient t)
		 (query-episode :episode episode :quality :high :transient t)))
	       (eq :low (episode-quality episode))
	       (>= (hours-available episode) 48))
     then :low
     else :normal))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :adrian
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "adrian/" *download-root*))

(defseries "Phineas and Furb" :adrian)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :anh
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "anh/" *download-root*))

(defseries "Downton Abbey" :anh)
(defseries "Midsomer Murders" :anh)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "kevin/" *download-root*))

(defseries "8 Out of 10 Cats" :kevin)
(defseries "Boardwalk Empire" :kevin)
(defseries "Breaking Bad" :kevin :delay 0) ;; immediate download
(defseries "Childrens Hospital (US)" :kevin)
(defseries "Come Fly with Me (2010)" :kevin)
(defseries "Dexter" :kevin)
(defseries "Dragons Den" :kevin)
(defseries "Elementary" :kevin)
(defseries "Falling Skies" :kevin)
(defseries "Frontline" :kevin)
(defseries "Game of Thrones" :kevin :delay 0) ;; immediate download
(defseries "Homeland" :kevin)
(defseries "Justified" :kevin :delay 0) ;; immediate download
(defseries "Longmire" :kevin)
(defseries "Louis Theroux Documentaries" :kevin)
(defseries "Louis" :kevin)
(defseries "Luther" :kevin)
(defseries "Mad Men" :kevin)
(defseries "Misfits" :kevin)
(defseries "Motive" :kevin)
(defseries "Orphan Black" :kevin)
(defseries "Person of Interest" :kevin)
(defseries "Shameless (US)" :kevin)
(defseries "Sherlock" :kevin)
(defseries "Southland" :kevin)
(defseries "Strike Back" :kevin)
(defseries "The Americans (2013)" :kevin)
(defseries "The Colbert Report" :kevin)
(defseries "The Daily Show with Jon Stewart" :kevin)
(defseries "The Graham Norton Show" :kevin)
(defseries "The IT Crowd" :kevin)
(defseries "The Jeselnik Offensive" :kevin)
(defseries "The Newsroom (2012)" :kevin)
(defseries "The Ultimate Fighter" :kevin)
(defseries "The Walking Dead" :kevin :delay 0) ;; immediate download
(defseries "Tosh.0" :kevin)
(defseries "Vikings" :kevin)
(defseries "Witness (2012)" :kevin)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :adrian+kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "An Idiot Abroad" :adrian+kevin)
(defseries "Community" :adrian+kevin)
(defseries "Eagleheart" :adrian+kevin)
(defseries "Futurama" :adrian+kevin)
(defseries "James May's Man Lab" :adrian+kevin)
(defseries "Modern Family" :adrian+kevin)
(defseries "Mythbusters" :adrian+kevin)
(defseries "Nathan for You" :adrian+kevin)
(defseries "NCIS" :adrian+kevin)
(defseries "Nova" :adrian+kevin)
(defseries "Parks and Recreation" :adrian+kevin)
(defseries "Ridiculousness" :adrian+kevin)
(defseries "Shark Tank" :adrian+kevin)
(defseries "The Mentalist" :adrian+kevin)
(defseries "The Neighbors (2012)" :adrian+kevin)
(defseries "The Simpsons" :adrian+kevin)
(defseries "Top Gear" :adrian+kevin :quality :high)
(defseries "Top Gear (US)" :adrian+kevin :quality :high)
(defseries "World's Craziest Fools" :adrian+kevin)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :btn-regular-show
    :rss-url *btn-regular-show-rss*
    :ratio "-1"
    :client :transmission-rpc
    :quality t ;; built into the feed
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "Regular Show" :btn-regular-show)

(defgroup :btn-spongebob
    :rss-url *btn-spongebob-rss*
    :ratio "-1"
    :client :transmission-rpc
    :quality t ;; built into the feed
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "Spongebob Squarepants" :btn-spongebob)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :anh+kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "anh+kevin/" *download-root*))

(defseries "Bates Motel" :anh+kevin)
(defseries "Curb your Enthusiasm" :anh+kevin)
(defseries "Doc Martin" :anh+kevin)
(defseries "The Following" :anh+kevin)
(defseries "The Good Wife" :anh+kevin)
(defseries "The Killing" :anh+kevin)
(defseries "Wallander" :anh+kevin)
(defseries "White Collar" :anh+kevin)