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

	uint K0, K1, K2, K3, K4, K5, K6, K7;

	if(notfresh){
		K0 = K[0];
		K1 = K[1];
		K2 = K[2];
		K3 = K[3];
		RND(A,B,C,D,E,F,G,H, B00 + K0);
		RND(H,A,B,C,D,E,F,G, B01 + K1);
		RND(G,H,A,B,C,D,E,F, B02 + K2);
		RND(F,G,H,A,B,C,D,E, B03 + K3);
	}else{
		K0 = K[63];
		K1 = K[64];
		K2 = K[65];
		K3 = K[66];
		K4 = K[67];
        K5 = K[68];
        K6 = K[69];
        K7 = K[70];

		D = K0 + B00;
		H = K1 + B00;
		C = K2 + Tr1(D) + Ch(D, K3, K4) + B01;
		G = K5 + C + Tr2(H) + Ch(H, K6, K7);
		T1x = K3;
		T1y = K4;
        K4 = K[71];
        K5 = K[72];
        K6 = K[73];
        K7 = K[74];
        K0 = K[75];
		B = K4 + Tr1(C) + Ch(C,D,K3) + B02;
		F = K5 + B + Tr2(G) + Maj(G,H, K6);
		A = K7 + Tr1(B) + Ch(B,C,D) + B03;
		E = K0 + A + Tr2(F) + Maj(F,G,H);

		//save K constants for fresh condition
		T0x = K6;
		T0y = K[77];
		T0z = K[78];
		T0w = K[79];
		T1z = K[80];
		T1w = K[81];
	}

    K0 = K[4];
    K1 = K[5];
    K2 = K[6];
    K3 = K[7];
    K4 = K[8];
    K5 = K[9];
    K6 = K[10];
    K7 = K[11];

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

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

    K7 = K[76];
    K0 = K[12];
    K1 = K[13];
    K2 = K[14];
    K3 = K[15];
    K4 = K[16];
    K5 = K[17];
    K6 = K[18];

	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 + K7);

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

    K0 = K[19];
    K1 = K[20];
    K2 = K[21];
    K3 = K[22];
    K4 = K[23];
    K5 = K[24];
    K6 = K[25];
    K7 = K[26];

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K0);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K1);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K2);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K3);

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K4);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K5);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K6);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K7);

    K0 = K[27];
    K1 = K[28];
    K2 = K[29];
    K3 = K[30];
    K4 = K[31];
    K5 = K[32];
    K6 = K[33];
    K7 = K[34];

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K0);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K1);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K2);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K3);

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K4);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K5);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K6);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K7);

    K0 = K[35];
    K1 = K[36];
    K2 = K[37];
    K3 = K[38];
    K4 = K[39];
    K5 = K[40];
    K6 = K[41];
    K7 = K[42];

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K0);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K1);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K2);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K3);

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K4);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K5);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K6);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K7);

    K0 = K[43];
    K1 = K[44];
    K2 = K[45];
    K3 = K[46];
    K4 = K[47];
    K5 = K[48];
    K6 = K[49];
    K7 = K[50];

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K0);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K1);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K2);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K3);

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K4);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K5);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K6);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K7);

    K0 = K[51];
    K1 = K[52];
    K2 = K[53];
    K3 = K[54];
    K4 = K[55];
    K5 = K[56];
    K6 = K[57];
    K7 = K[58];

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K0);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K1);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K2);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K3);

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K4);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K5);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K6);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K7);

    K4 = K[59];
    K5 = K[60];
    K6 = K[61];
    K7 = K[62];

	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