#ifndef SHA_256
#define SHA_256 1

void SHA256(uint *D0, uint *D1, uint *D2, uint *D3, uint *D4,
		 uint *D5, uint *D6, uint *D7, uint B00, uint B01, uint B02, uint B03,
		uint B04, uint B05, uint B06, uint B07, uint B08, uint B09, uint B10, uint B11, uint B12, uint B13, uint B14, uint B15, bool notfresh){

    uint A = *D0;
    uint B = *D1;
    uint C = *D2;
    uint D = *D3;
    uint E = *D4;
    uint F = *D5;
    uint G = *D6;
    uint H = *D7;
    uint T0x = A;
    uint T0y = B;
    uint T0z = C;
    uint T0w = D;
    uint T1x = E;
    uint T1y = F;
    uint T1z = G;
    uint T1w = H;

	if(notfresh){
		RND(A,B,C,D,E,F,G,H, B00 + K[0]);
		RND(H,A,B,C,D,E,F,G, B01 + K[1]);
		RND(G,H,A,B,C,D,E,F, B02 + K[2]);
		RND(F,G,H,A,B,C,D,E, B03 + K[3]);
	}else{
		D = B00 + freshK[0];
		H = B00 + freshK[1];
		C = B01 + Tr1(D) + Ch(D, freshK[3], freshK[4]) + freshK[2];
		T1x = freshK[3];
		T1y = freshK[4];
		G = C + freshK[5] + Tr2(H) + Ch(H, freshK[6], freshK[7]);
		B = B02 + Tr1(C) + Ch(C,D, freshK[3]) + freshK[8];
		T0x = freshK[10];
		F = B + Tr2(G) + Maj(G,H, freshK[10]) + freshK[9];
		A = B03 + Tr1(B) + Ch(B,C,D) + freshK[11];
		E = A + Tr2(F) + Maj(F,G,H) + freshK[12];
		//save K constants for fresh condition
		T0y = freshK[13];
		T0z = freshK[14];
		T0w = freshK[15];
		T1z = freshK[16];
		T1w = freshK[17];
	}

    uint K0 = K[4];
    uint K1 = K[5];
    uint K2 = K[6];
    uint K3 = K[7];

	RND(E,F,G,H,A,B,C,D, B04 + K0);
	RND(D,E,F,G,H,A,B,C, B05 + K1);
	RND(C,D,E,F,G,H,A,B, B06 + K2);
	RND(B,C,D,E,F,G,H,A, B07 + K3);

	uint K4 = K[8];
	uint K5 = K[9];
	uint K6 = K[10];
	uint K7 = K[11];
	K0 = K[12];
	K1 = K[13];
	K2 = K[14];
	K3 = K[15];

	RND(A,B,C,D,E,F,G,H, B08 + K4);
	RND(H,A,B,C,D,E,F,G, B09 + K5);
	RND(G,H,A,B,C,D,E,F, B10 + K6);
	RND(F,G,H,A,B,C,D,E, B11 + K7);

	RND(E,F,G,H,A,B,C,D, B12 + K0);
	RND(D,E,F,G,H,A,B,C, B13 + K1);
	RND(C,D,E,F,G,H,A,B, B14 + K2);
	RND(B,C,D,E,F,G,H,A, B15 + K3);

	K0 = K[16];
	K1 = K[17];
	K2 = K[18];
	K3 = K[19];
	K4 = K[20];
	K5 = K[21];
	K6 = K[22];
	K7 = K[23];

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K0);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K1);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K2);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K3);

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K4);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K5);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K6);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K7);

	K0 = K[24];
	K1 = K[25];
	K2 = K[26];
	K3 = K[27];
	K4 = K[28];
	K5 = K[29];
	K6 = K[30];
	K7 = K[31];

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K0);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K1);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K2);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K3);

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K4);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K5);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K6);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K7);

	K0 = K[32];
	K1 = K[33];
	K2 = K[34];
	K3 = K[35];
	K4 = K[36];
	K5 = K[37];
	K6 = K[38];
	K7 = K[39];

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K0);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K1);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K2);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K3);

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K4);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K5);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K6);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K7);

	K0 = K[40];
	K1 = K[41];
	K2 = K[42];
	K3 = K[43];
	K4 = K[44];
	K5 = K[45];
	K6 = K[46];
	K7 = K[47];

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K0);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K1);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K2);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K3);

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K4);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K5);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K6);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K7);

	K0 = K[48];
	K1 = K[49];
	K2 = K[50];
	K3 = K[51];
	K4 = K[52];
	K5 = K[53];
	K6 = K[54];
	K7 = K[55];

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K0);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K1);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K2);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K3);

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K4);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K5);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K6);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K7);

	K0 = K[56];
	K1 = K[57];
	K2 = K[58];
	K3 = K[59];
	K4 = K[60];
	K5 = K[61];
	K6 = K[62];
	K7 = K[63];

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K0);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K1);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K2);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K3);

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K4);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K5);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K6);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K7);

	A += T0x;
	B += T0y;
	C += T0z;
	D += T0w;
	E += T1x;
	F += T1y;
	G += T1z;
	H += T1w;

	*D0 = A;
	*D1 = B;
	*D2 = C;
	*D3 = D;
	*D4 = E;
	*D5 = F;
	*D6 = G;
	*D7 = H;
}

#endif