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

	DecAllKA
	DecAllKB
	DecAllKC
	DecAllKD
	DecAllKE

	if(notfresh){
		RND(A,B,C,D,E,F,G,H, B00 + K00);
		RND(H,A,B,C,D,E,F,G, B01 + K01);
		RND(G,H,A,B,C,D,E,F, B02 + K02);
		RND(F,G,H,A,B,C,D,E, B03 + K03);
	}else{
		D = K63 + B00;
		H = K64 + B00;
		C = K65 + Tr1(D) + Ch(D, K66, K67) + B01;
		G = K68 + C + Tr2(H) + Ch(H, K69, K70);
		B = K71 + Tr1(C) + Ch(C,D,K66) + B02;
		F = K72 + B + Tr2(G) + Maj(G,H, K73);
		A = K74 + Tr1(B) + Ch(B,C,D) + B03;
		E = K75 + A + Tr2(F) + Maj(F,G,H);

		//save K constants for fresh condition
		T0x = K73;
		T0y = K77;
		T0z = K78;
		T0w = K79;
		T1x = K66;
		T1y = K67;
		T1z = K80;
		T1w = K81;
	}

	RND(E,F,G,H,A,B,C,D, B04 + K04);
	RND(D,E,F,G,H,A,B,C, B05 + K05);
	RND(C,D,E,F,G,H,A,B, B06 + K06);
	RND(B,C,D,E,F,G,H,A, B07 + K07);

	RND(A,B,C,D,E,F,G,H, B08 + K08);
	RND(H,A,B,C,D,E,F,G, B09 + K09);
	RND(G,H,A,B,C,D,E,F, B10 + K10);
	RND(F,G,H,A,B,C,D,E, B11 + K11);

	RND(E,F,G,H,A,B,C,D, B12 + K12);
	RND(D,E,F,G,H,A,B,C, B13 + K13);
	RND(C,D,E,F,G,H,A,B, B14 + K14);
	RND(B,C,D,E,F,G,H,A, B15 + K76);

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K15);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K16);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K17);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K18);

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K19);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K20);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K21);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K22);

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K23);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K24);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K25);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K26);

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K27);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K28);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K29);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K30);

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K31);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K32);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K33);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K34);

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K35);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K36);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K37);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K38);

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K39);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K40);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K41);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K42);

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K43);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K44);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K45);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K46);

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K47);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K48);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K49);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K50);

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K51);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K52);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K53);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K54);

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K55);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K56);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K57);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K58);

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K59);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K60);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K61);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K62);

	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