#ifndef GLOBALS
#define GLOBALS 1



#if !defined(VECTORS1)
#define VECTORS1
#endif

#ifdef VECTORS4
    typedef uint4 vo;
#elif defined(VECTORS2)
    typedef uint2 vo;
#else
    typedef uint vo;
#endif


#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;

__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
};

__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
};


/*
	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*(y ## SIZE)*(x ## SIZE)
//#define CO Coord(z,x,y)

/*
volatile uint fixedWa[8] = {0x428a2f99,0xd807aa98,0xf59b89c2,0xb707775c,0xad87a3ea,0xc91b1417,0xe64fb6a2,0xe0a1adbe};
volatile uint fixedWb[8] = {0xf1374491,0x12835b01,0x73924787,0x0468c23f,0xbcb1d3a3,0xc359dce1,0xe84d923a,0x7c728e11};
volatile uint fixedWc[8] = {0xb5c0fbcf,0x243185be,0x23c6886e,0xe7e72b4c,0x7b993186,0xa83253a7,0xe93a5730,0x511c78e4};
volatile uint fixedWd[8] = {0xe9b5dba5,0x550c7dc3,0xa42ca65c,0x49e1f1a2,0x562b9420,0x3b13c12d,0x09837686,0x315b45bd};
volatile uint fixedWe[8] = {0x3956c25b,0x72be5d74,0x15ed3627,0x4b99c816,0xbff3ca0c,0x9d3d725d,0x078ff753,0xfca71413};
volatile uint fixedWf[8] = {0x59f111f1,0x80deb1fe,0x4d6edcbf,0x926d1570,0xda4b0c23,0xd9031a84,0x29833341,0xea28f96a};
volatile uint fixedWg[8] = {0x923f82a4,0x9bdc06a7,0xe28217fc,0xaa0fc072,0x6cd8711a,0xb1a03340,0xd5de0b7e,0x79703128};
volatile uint fixedWh[8] = {0xab1c5ed5,0xc19bf794,0xef02488f,0xadb36e2c,0x8f337caa,0x16f58012,0x6948ccf4,0x4e1ef848};
*/

/*
__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