#ifndef SCRYPT
#define SCRYPT 1
#include "globals.h"
#include "salsa.h"


void Shittify(__global uint16 *pad0, __global uint16 *pad1, bool opt){
	uint16 tmpa = *pad0;
	uint16 tmpb = *pad1;
	if(opt){
		tmpa = tmpa.s49e38d27c16b05af;
		tmpb = tmpb.s49e38d27c16b05af;
	}else{
		tmpa = tmpa.sc9630da741eb852f;
		tmpb = tmpb.sc9630da741eb852f;
	}
	*pad0 = EndianSwapa(tmpa);
	*pad1 = EndianSwapa(tmpb);

}

void scrypt_core(__global uint16 *lookup, uint x){
	uint idx = x<<1;
	uint16 X[2] = {lookup[idx], lookup[idx+1]};

//write portion
	for(uint y=CONCURRENT_THREADS; y<(CONCURRENT_THREADS*(__NF__/LOOKUP_GAP)); y+=CONCURRENT_THREADS){
#if (LOOKUP_GAP == 2)
		salsa(X, ONE);
#elif (LOOKUP_GAP == 1)
		salsa(X);
#else
		salsa(X, LOOKUP_GAP-ONE);
#endif
		lookup[CO_W0] = X[0];
		lookup[CO_W1] = X[1];
	}

#if (LOOKUP_GAP == 2)
	salsa(X, ONE);
#elif (LOOKUP_GAP == 1)
	salsa(X);
#else
	salsa(X, LOOKUP_GAP-ONE);
#endif

#if (LOOKUP_GAP != 1) && (LOOKUP_GAP != 2) && (LOOKUP_GAP != 4) && (LOOKUP_GAP != 8)
	{
		uint y = (__NF__/LOOKUP_GAP);
		lookup[CO_0] = X[0];
		lookup[CO_1] = X[1];
# if (LOOKUP_GAP == 3)
		salsa(X, ZERO);
# elif (LOOKUP_GAP == 5)
		salsa(X, THREE);
# elif (LOOKUP_GAP == 7)
		salsa(X, ONE);
# else
		for(uint i=0; i<nfact%LOOKUP_GAP; ++i)
			salsa(X, ZERO);
# endif
	}

#endif
// end write portion

// read portion
	for(uint i=0; i<__NF__; i++){
# if (LOOKUP_GAP == 2)
		uint j = X[1].sc & (__NF__-1);
		uint y = (j>>1);
# elif (LOOKUP_GAP == 4)
		uint j = X[1].sc & (__NF__-1);
		uint y = (j>>2);
# elif (LOOKUP_GAP == 8)
		uint j = X[1].sc & (__NF__-1);
		uint y = (j>>3);
# elif (LOOKUP_GAP != 1)
		uint j = X[1].sc & (__NF__-1);
		uint y = (j/LOOKUP_GAP);
# else
		uint y = X[1].sc & (__NF__-1);
# endif

#if (LOOKUP_GAP == 2)

		if(j&1){
			uint16 V[2] = {lookup[CO_0], lookup[CO_1]};
			salsa(V, ZERO);
			X[0] ^= V[0];
			X[1] ^= V[1];
		}else{
			X[0] ^= lookup[CO_0];
			X[1] ^= lookup[CO_1];
		}

		salsa(X, ZERO);

#elif (LOOKUP_GAP != 1)
		j -= y*LOOKUP_GAP;
		if(j){
			uint16 V[2] = {lookup[CO_0], lookup[CO_1]};
			salsa(V, j-ONE);
			X[0] ^= V[0];
			X[1] ^= V[1];
		}else{
			X[0] ^= lookup[CO_0];
			X[1] ^= lookup[CO_1];
		}
		salsa(X, ZERO);
#else
		X[0] ^= lookup[CO_0];
		X[1] ^= lookup[CO_1];

		salsa(X);
#endif

	}
// end read portion

	lookup[x<<1] = X[0];
	lookup[(x<<1)+1] = X[1];
}

#endif