#ifndef GLOBALS
#define GLOBALS 1

#ifndef NFACTOR
#define NFACTOR 10
#endif

#if NFACTOR == 1
#  define __NF__ 2u
#elif NFACTOR == 2
# define __NF__ 4u
#elif NFACTOR == 3
#  define __NF__ 8u
#elif NFACTOR == 4
#  define __NF__ 16u
#elif NFACTOR == 5
#  define __NF__ 32u
#elif NFACTOR == 6
#  define __NF__ 64u
#elif NFACTOR == 7
#  define __NF__ 128u
#elif NFACTOR == 8
#  define __NF__ 256u
#elif NFACTOR == 9
#  define __NF__ 512u
#elif NFACTOR == 10
#  define __NF__ 1024u
#elif NFACTOR == 11
#  define __NF__ 2048u
#elif NFACTOR == 12
#  define __NF__ 4096u
#elif NFACTOR == 13
#  define __NF__ 8192u
#elif NFACTOR == 14
#  define __NF__ 16384u
#elif NFACTOR == 15
#  define __NF__ 32768u
#elif NFACTOR == 16
#  define __NF__ 65536u
#elif NFACTOR == 17
#  define __NF__ 131072u
#elif NFACTOR == 18
#  define __NF__ 262144u
#elif NFACTOR == 19
#  define __NF__ 524288u
#elif NFACTOR == 20
#  define __NF__ 1048576u
#else
# define __NF__ 1024u
#endif

#define DEFNFACTOR(n) \
	const uint n = __NF__;

//	const uint n = (__NF__/LOOKUP_GAP+(__NF__%LOOKUP_GAP>0));


#define E0 0x00FF00FFU
#define E1 0xFF00FF00U

#define DecAllKA uint K00 = 0x428a2f98U; \
				uint K01 = 0x71374491U; \
				uint K02 = 0xb5c0fbcfU; \
				uint K03 = 0xe9b5dba5U; \
				uint K04 = 0x3956c25bU; \
				uint K05 = 0x59f111f1U; \
				uint K06 = 0x923f82a4U; \
				uint K07 = 0xab1c5ed5U; \
				uint K08 = 0xd807aa98U; \
				uint K09 = 0x12835b01U; \
				uint K10 = 0x243185beU; \
				uint K11 = 0x550c7dc3U; \
				uint K12 = 0x72be5d74U; \
				uint K13 = 0x80deb1feU; \
				uint K14 = 0x9bdc06a7U; \
				uint K76 = 0xc19bf174U; \
				uint K15 = 0xe49b69c1U;

#define DecAllKB uint K16 = 0xefbe4786U; \
				uint K17 = 0x0fc19dc6U; \
				uint K18 = 0x240ca1ccU; \
				uint K19 = 0x2de92c6fU; \
				uint K20 = 0x4a7484aaU; \
				uint K21 = 0x5cb0a9dcU; \
				uint K22 = 0x76f988daU; \
				uint K23 = 0x983e5152U; \
				uint K24 = 0xa831c66dU; \
				uint K25 = 0xb00327c8U; \
				uint K26 = 0xbf597fc7U; \
				uint K27 = 0xc6e00bf3U; \
				uint K28 = 0xd5a79147U; \
				uint K29 = 0x06ca6351U; \
				uint K30 = 0x14292967U; \
				uint K31 = 0x27b70a85U;

#define DecAllKC uint K32 = 0x2e1b2138U; \
				uint K33 = 0x4d2c6dfcU; \
				uint K34 = 0x53380d13U; \
				uint K35 = 0x650a7354U; \
				uint K36 = 0x766a0abbU; \
				uint K37 = 0x81c2c92eU; \
				uint K38 = 0x92722c85U; \
				uint K39 = 0xa2bfe8a1U; \
				uint K40 = 0xa81a664bU; \
				uint K41 = 0xc24b8b70U; \
				uint K42 = 0xc76c51a3U; \
				uint K43 = 0xd192e819U; \
				uint K44 = 0xd6990624U; \
				uint K45 = 0xf40e3585U; \
				uint K46 = 0x106aa070U; \
				uint K47 = 0x19a4c116U;

#define DecAllKD uint K48 = 0x1e376c08U; \
				uint K49 = 0x2748774cU; \
				uint K50 = 0x34b0bcb5U; \
				uint K51 = 0x391c0cb3U; \
				uint K52 = 0x4ed8aa4aU; \
				uint K53 = 0x5b9cca4fU; \
				uint K54 = 0x682e6ff3U; \
				uint K55 = 0x748f82eeU; \
				uint K56 = 0x78a5636fU; \
				uint K57 = 0x84c87814U; \
				uint K58 = 0x8cc70208U; \
				uint K59 = 0x90befffaU; \
				uint K60 = 0xa4506cebU; \
				uint K61 = 0xbef9a3f7U; \
				uint K62 = 0xc67178f2U;

#define DecAllKE uint K63 = 0x98c7e2a2U; \
				uint K64 = 0xfc08884dU; \
				uint K65 = 0xcd2a11aeU; \
				uint K66 = 0x510e527fU; \
				uint K67 = 0x9b05688cU; \
				uint K68 = 0xC3910C8EU; \
				uint K69 = 0xfb6feee7U; \
				uint K70 = 0x2a01a605U; \
				uint K71 = 0x0c2e12e0U; \
				uint K72 = 0x4498517BU; \
				uint K73 = 0x6a09e667U; \
				uint K74 = 0xa4ce148bU; \
				uint K75 = 0x95F61999U; \
				uint K77 = 0xBB67AE85U; \
				uint K78 = 0x3C6EF372U; \
				uint K79 = 0xA54FF53AU; \
				uint K80 = 0x1F83D9ABU; \
				uint K81 = 0x5BE0CD19U;


//Search constants
#define DecAllSK	uint SK00 = 0x5C5C5C5CU; \
					uint SK01 = 0x36363636U; \
					uint SK02 = 0x80000000U; \
					uint SK03 = 0x00000280U; \
					uint SK04 = 0x000004a0U; \
					uint SK05 = 0x00000300U;


#define SK00 0x80000000U
#define SK01 0x00000280U
#define SK02 0x5C5C5C5CU
#define SK03 0x36363636U
#define SK04 0x000004a0U
#define SK05 0x00000300U


//__constant uint SK00 = 0x5C5C5C5CU;
//__constant uint SK01 = 0x36363636U;
//__constant uint SK02 = 0x80000000U;
//__constant uint SK03 = 0x00000280U;
//__constant uint SK04 = 0x000004a0U;
//__constant uint SK05 = 0x00000300U;

//__constant uint (uint8)(zero, zero, zero, zero, zero, zero, zero, SK04)
//__constant uint (uint8)(SK02, zero, zero, zero, zero, zero, zero, SK05)

//__constant uint16 SK02 = {zero, zero, zero, zero, zero, zero, zero, SK04, SK02, zero, zero, zero, zero, zero, zero, SK05};

//__constant uint4 SKa = {0x80000000U, 0x00000280U, 0x5C5C5C5CU, 0x36363636U};


/*
__constant uint zero  = 0x0U;
__constant uint one   = 0x1U;
__constant uint two   = 0x2U;
__constant uint three = 0x3U;
__constant uint four  = 0x4U;
__constant uint five  = 0x5U;
__constant uint six   = 0x6U;
__constant uint seven = 0x7U;
__constant uint eight = 0x8U;
*/

#define zero   0x0U
#define one    0x1U
#define two    0x2U
#define three  0x3U
#define four   0x4U
#define five   0x5U
#define six    0x6U
#define seven  0x7U
#define eight  0x8U

//__constant uint4 SKa = {0x80000000U, 0x00000280U, 0x5C5C5C5CU, 0x36363636U};
//__constant uint8 SKb = {zero, zero, zero, zero, zero, zero, zero, 0x000004a0U};
//__constant uint8 SKc = {0x80000000U, zero, zero, zero, zero, zero, zero, 0x00000300U};


/*
__constant uint K[64] = {
	0x428a2f98U,
	0x71374491U,
	0xb5c0fbcfU,
	0xe9b5dba5U,
	0x3956c25bU,
	0x59f111f1U,
	0x923f82a4U,
	0xab1c5ed5U,
	0xd807aa98U,
	0x12835b01U,
	0x243185beU, // 10
	0x550c7dc3U,
	0x72be5d74U,
	0x80deb1feU,
	0x9bdc06a7U,
	0xc19bf174U,
	0xe49b69c1U,
	0xefbe4786U,
	0x0fc19dc6U,
	0x240ca1ccU,
	0x2de92c6fU, // 20
	0x4a7484aaU, //
	0x5cb0a9dcU,
	0x76f988daU,
	0x983e5152U,
	0xa831c66dU,
	0xb00327c8U,
	0xbf597fc7U,
	0xc6e00bf3U,
	0xd5a79147U,
	0x06ca6351U, // 30
	0x14292967U, //
	0x27b70a85U,
	0x2e1b2138U,
	0x4d2c6dfcU,
	0x53380d13U,
	0x650a7354U,
	0x766a0abbU,
	0x81c2c92eU,
	0x92722c85U,
	0xa2bfe8a1U, // 40
	0xa81a664bU, //
	0xc24b8b70U,
	0xc76c51a3U,
	0xd192e819U,
	0xd6990624U,
	0xf40e3585U,
	0x106aa070U,
	0x19a4c116U,
	0x1e376c08U,
	0x2748774cU, // 50
	0x34b0bcb5U, //
	0x391c0cb3U,
	0x4ed8aa4aU,
	0x5b9cca4fU,
	0x682e6ff3U,
	0x748f82eeU,
	0x78a5636fU,
	0x84c87814U,
	0x8cc70208U,
	0x90befffaU, // 60
	0xa4506cebU, //
	0xbef9a3f7U,
	0xc67178f2U
};

*/


#define K00 0x428a2f98U
#define K01 0x71374491U
#define K02 0xb5c0fbcfU
#define K03 0xe9b5dba5U
#define K04 0x3956c25bU
#define K05 0x59f111f1U
#define K06 0x923f82a4U
#define K07 0xab1c5ed5U
#define K08 0xd807aa98U
#define K09 0x12835b01U
#define K10 0x243185beU
#define K11 0x550c7dc3U
#define K12 0x72be5d74U
#define K13 0x80deb1feU
#define K14 0x9bdc06a7U
#define K15 0xc19bf174U
#define K16 0xe49b69c1U
#define K17 0xefbe4786U
#define K18 0x0fc19dc6U
#define K19 0x240ca1ccU
#define K20 0x2de92c6fU
#define K21 0x4a7484aaU
#define K22 0x5cb0a9dcU
#define K23 0x76f988daU
#define K24 0x983e5152U
#define K25 0xa831c66dU
#define K26 0xb00327c8U
#define K27 0xbf597fc7U
#define K28 0xc6e00bf3U
#define K29 0xd5a79147U
#define K30 0x06ca6351U
#define K31 0x14292967U
#define K32 0x27b70a85U
#define K33 0x2e1b2138U
#define K34 0x4d2c6dfcU
#define K35 0x53380d13U
#define K36 0x650a7354U
#define K37 0x766a0abbU
#define K38 0x81c2c92eU
#define K39 0x92722c85U
#define K40 0xa2bfe8a1U
#define K41 0xa81a664bU
#define K42 0xc24b8b70U
#define K43 0xc76c51a3U
#define K44 0xd192e819U
#define K45 0xd6990624U
#define K46 0xf40e3585U
#define K47 0x106aa070U
#define K48 0x19a4c116U
#define K49 0x1e376c08U
#define K50 0x2748774cU
#define K51 0x34b0bcb5U
#define K52 0x391c0cb3U
#define K53 0x4ed8aa4aU
#define K54 0x5b9cca4fU
#define K55 0x682e6ff3U
#define K56 0x748f82eeU
#define K57 0x78a5636fU
#define K58 0x84c87814U
#define K59 0x8cc70208U
#define K60 0x90befffaU
#define K61 0xa4506cebU
#define K62 0xbef9a3f7U
#define K63 0xc67178f2U


/*
__constant uint freshK[18] = {
	0x98c7e2a2U, //63
	0xfc08884dU,
	0xcd2a11aeU,
	0x510e527fU,
	0x9b05688cU,
	0xC3910C8EU,
	0xfb6feee7U,
	0x2a01a605U, // 70
	0x0c2e12e0U,
	0x4498517BU,
	0x6a09e667U, // 10
	0xa4ce148bU,
	0x95F61999U,
//	0xc19bf174U, //76 removed
	0xBB67AE85U,
	0x3C6EF372U,
	0xA54FF53AU,
	0x1F83D9ABU, // 80
	0x5BE0CD19U
};
*/

//__constant uint16 FreshK = {0x6a09e667U, 0xBB67AE85U, 0x3C6EF372U, 0xA54FF53AU, 0x510e527fU, 0x9b05688cU, 0x1F83D9ABU, 0x5BE0CD19U,
//							0xcd2a11aeU, 0xC3910C8EU, 0xfb6feee7U, 0x2a01a605U, 0x0c2e12e0U, 0x4498517BU, 0xa4ce148bU, 0x95F61999U};

//__constant uint8 FreshA = {0x510e527fU, 0x9b05688cU, 0x6a09e667U, 0xBB67AE85U, 0x3C6EF372U, 0xA54FF53AU, 0x1F83D9ABU, 0x5BE0CD19U};
//__constant uint8 FreshB = {0x98c7e2a2U, 0xfc08884dU, 0xcd2a11aeU, 0xC3910C8EU, 0xfb6feee7U, 0x2a01a605U, 0x0c2e12e0U, 0x4498517BU, 0xa4ce148bU, 0x95F61999U};

//__constant uint16 FreshK = {0xcd2a11aeU, 0x510e527fU, 0x9b05688cU, 0xC3910C8EU, 0xfb6feee7U, 0x2a01a605U, 0x0c2e12e0U, 0x4498517BU,
//							0x6a09e667U, 0xa4ce148bU, 0x95F61999U, 0xBB67AE85U, 0x3C6EF372U, 0xA54FF53AU, 0x1F83D9ABU, 0x5BE0CD19U};


//__constant uint16 FreshK = {0x510e527fU, 0x9b05688cU, 0x6a09e667U, 0xBB67AE85U, 0x3C6EF372U, 0xA54FF53AU, 0x1F83D9ABU, 0x5BE0CD19U,
//							0xcd2a11aeU, 0xC3910C8EU, 0xfb6feee7U, 0x2a01a605U, 0x0c2e12e0U, 0x4498517BU, 0xa4ce148bU, 0x95F61999U};


/*
	0x5C5C5C5CU,
	0x36363636U,
	0x80000000U,
//	0x000003FFU, //never used
	0x00000280U,
	0x000004a0U,
	0x00000300U
};
*/

#define FOURdeclare(myvar, v1, v2, v3, v4) uint myvar ## 1 = v1; \
                                           uint myvar ## 2 = v2; \
                                           uint myvar ## 3 = v3; \
                                           uint myvar ## 4 = v4;

#define FOURassign(myvar, v1, v2, v3, v4) myvar ## 1 = v1; \
                                          myvar ## 2 = v2; \
                                          myvar ## 3 = v3; \
                                          myvar ## 4 = v4;

#define FOURcopy(var1, var2) var1 ## 1 = var2 ## 1; \
                             var1 ## 2 = var2 ## 2; \
                             var1 ## 3 = var2 ## 3; \
                             var1 ## 4 = var2 ## 4;

#define FOURtovec(var1, var2) var1.x = var2 ## 1; \
                              var1.y = var2 ## 2; \
                              var1.z = var2 ## 3; \
                              var1.w = var2 ## 4;

#define FOURfromvec(var1, var2) var1 ## 1 = var2.x; \
                                var1 ## 2 = var2.y; \
                                var1 ## 3 = var2.z; \
                                var1 ## 4 = var2.w;

#define UNROLL_FACTOR 2


#define rotl(x,y) rotate(x,y)
#define Ch(x,y,z) bitselect(z,y,x)
#define Maj(x,y,z) Ch((x^z),y,z)

#define EndianSwapa(n) (Ch(E0, rotl(n, 8U), rotl(n, 24U)))
#define EndianSwapb(n) (rotl(n & E0, 24U)|rotl(n & E1, 8U))

#define Tr2(x)		(rotl(x, 30U) ^ rotl(x, 19U) ^ rotl(x, 10U))
#define Tr1(x)		(rotl(x, 26U) ^ rotl(x, 21U) ^ rotl(x, 7U))
#define Wr2(x)		(rotl(x, 25U) ^ rotl(x, 14U) ^ (x>>3U))
#define Wr1(x)		(rotl(x, 15U) ^ rotl(x, 13U) ^ (x>>10U))

#define RND(a, b, c, d, e, f, g, h, k)  \
	h += Tr1(e); 			\
	h += Ch(e, f, g); 		\
	h += k;				\
	d += h;				\
	h += Tr2(a); 			\
	h += Maj(a, b, c);

//#define zSIZE 8
//#define Coord(x,y,z) z+(x<<3)+((uint)(y*CONCURRENT_THREADS)<<3)
//#define Coord(x,y,z) (x<<3)+((y<<3)*CONCURRENT_THREADS)+z
//#define Coord(x,y,z) x*(z ## SIZE)+y*(CONCURRENT_THREADS)*(z ## SIZE)+z


//#define Coord(x,y,z) x*(z ## SIZE)+y*(x ## SIZE)*(z ## SIZE)+z
//#define CO Coord(x,y,z)

//#define Coord(x,y,z) x+y*(x ## SIZE)*(z ## SIZE)+z


//#define Coord(x,y,o) x+y*(x ## SIZE)+o
//#define Coord(x,y,z) x*zSIZE+y*(x ## SIZE)*zSIZE+z
//#define CO_0 Coord(x,y,0)
//#define CO_1 Coord(x,y,1)


//#define CO_0 (y*xSIZE+x)
//#define CO_1 ((y*xSIZE+x)+offset)


#define CLSIZE 64


#if (CLSIZE == 64)
//# define CO_0 ((y*xSIZE+x)<<1)
//# define CO_1 ((y*xSIZE+x)<<1)+1

//# define CO_W0 (y+x)<<1
//# define CO_W1 ((y+x)<<1)+1

# define CO_W0 (idx=(y+x)<<1)
# define CO_W1 idx+1

# define CO_0 (idx=(y*xSIZE+x)<<1)
# define CO_1 idx+1

#else

//# define CO (idx+z)
# define CO ((y*xSIZE+x)<<2)+z
//# define CO_0 ((y*xSIZE+x)<<2)
//# define CO_1 ((y*xSIZE+x)<<2)+1
//# define CO_2 ((y*xSIZE+x)<<2)+2
//# define CO_3 ((y*xSIZE+x)<<2)+3

#endif


//#define CO_1 ((y*xSIZE)<<1)+x

//#define CO_0 y*x+xSIZE
//#define CO_1 y*x+xSIZE+1


//#define CO y*xSIZE+x+z

//#define Coord(x,y,z) x+y*(x ## SIZE)+z*(y ## SIZE)*(x ## SIZE)
//#define CO Coord(z,x,y)


__constant uint fixedWa[8] = {0x428a2f99U,0xd807aa98U,0xf59b89c2U,0xb707775cU,0xad87a3eaU,0xc91b1417U,0xe64fb6a2U,0xe0a1adbeU};
__constant uint fixedWb[8] = {0xf1374491U,0x12835b01U,0x73924787U,0x0468c23fU,0xbcb1d3a3U,0xc359dce1U,0xe84d923aU,0x7c728e11U};
__constant uint fixedWc[8] = {0xb5c0fbcfU,0x243185beU,0x23c6886eU,0xe7e72b4cU,0x7b993186U,0xa83253a7U,0xe93a5730U,0x511c78e4U};
__constant uint fixedWd[8] = {0xe9b5dba5U,0x550c7dc3U,0xa42ca65cU,0x49e1f1a2U,0x562b9420U,0x3b13c12dU,0x09837686U,0x315b45bdU};
__constant uint fixedWe[8] = {0x3956c25bU,0x72be5d74U,0x15ed3627U,0x4b99c816U,0xbff3ca0cU,0x9d3d725dU,0x078ff753U,0xfca71413U};
__constant uint fixedWf[8] = {0x59f111f1U,0x80deb1feU,0x4d6edcbfU,0x926d1570U,0xda4b0c23U,0xd9031a84U,0x29833341U,0xea28f96aU};
__constant uint fixedWg[8] = {0x923f82a4U,0x9bdc06a7U,0xe28217fcU,0xaa0fc072U,0x6cd8711aU,0xb1a03340U,0xd5de0b7eU,0x79703128U};
__constant uint fixedWh[8] = {0xab1c5ed5U,0xc19bf794U,0xef02488fU,0xadb36e2cU,0x8f337caaU,0x16f58012U,0x6948ccf4U,0x4e1ef848U};


/*
__constant uint8 fixedW[8] = {(uint8)(0x428a2f99U,0xf1374491U,0xb5c0fbcfU,0xe9b5dba5U,0x3956c25bU,0x59f111f1U,0x923f82a4U,0xab1c5ed5U),
								(uint8)(0xd807aa98U,0x12835b01U,0x243185beU,0x550c7dc3U,0x72be5d74U,0x80deb1feU,0x9bdc06a7U,0xc19bf794U),
								(uint8)(0xf59b89c2U,0x73924787U,0x23c6886eU,0xa42ca65cU,0x15ed3627U,0x4d6edcbfU,0xe28217fcU,0xef02488fU),
								(uint8)(0xb707775cU,0x0468c23fU,0xe7e72b4cU,0x49e1f1a2U,0x4b99c816U,0x926d1570U,0xaa0fc072U,0xadb36e2cU),
								(uint8)(0xad87a3eaU,0xbcb1d3a3U,0x7b993186U,0x562b9420U,0xbff3ca0cU,0xda4b0c23U,0x6cd8711aU,0x8f337caaU),
								(uint8)(0xc91b1417U,0xc359dce1U,0xa83253a7U,0x3b13c12dU,0x9d3d725dU,0xd9031a84U,0xb1a03340U,0x16f58012U),
								(uint8)(0xe64fb6a2U,0xe84d923aU,0xe93a5730U,0x09837686U,0x078ff753U,0x29833341U,0xd5de0b7eU,0x6948ccf4U),
								(uint8)(0xe0a1adbeU,0x7c728e11U,0x511c78e4U,0x315b45bdU,0xfca71413U,0xea28f96aU,0x79703128U,0x4e1ef848U)};

*/

/*
__constant uint sK[6] = {
    0x5C5C5C5CU, //82
    0x36363636U,
    0x80000000U,
//  0x000003FFU, //never used
    0x00000280U,
    0x000004a0U,
    0x00000300U
};
*/

#define FOUND (0xFF)
#define SETFOUND(Xnonce) output[output[FOUND]++] = Xnonce

#endif