whole_func_string: function sha256(message, debugging) {
  
  	var debugOutput = [],
  		noop = function(){},
  		out = debugging ? function() {
  			debugOutput.push(
  				[].slice.call(arguments).join(" ")
  			);
  		} : noop;
  
  	try {
  		/*
  		Initialize hash values:
  		(first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
  		h0 := 0x6a09e667
  		h1 := 0xbb67ae85
  		h2 := 0x3c6ef372
  		h3 := 0xa54ff53a
  		h4 := 0x510e527f
  		h5 := 0x9b05688c
  		h6 := 0x1f83d9ab
  		h7 := 0x5be0cd19
  		*/
  		var h0 = hex2bin(0x6a09e667),
  			h1 = hex2bin(0xbb67ae85),
  			h2 = hex2bin(0x3c6ef372),
  			h3 = hex2bin(0xa54ff53a),
  			h4 = hex2bin(0x510e527f),
  			h5 = hex2bin(0x9b05688c),
  			h6 = hex2bin(0x1f83d9ab),
  			h7 = hex2bin(0x5be0cd19);
  
  		//out("h0", bin2hex(h0), h0);
  		//out("h1", bin2hex(h1), h1);
  		//out("h2", bin2hex(h2), h2);
  		//out("h3", bin2hex(h3), h3);
  		//out("h4", bin2hex(h4), h4);
  		//out("h5", bin2hex(h5), h5);
  		//out("h6", bin2hex(h6), h6);
  		//out("h7", bin2hex(h7), h7);
  
  		/*
  		Initialize array of round constants:
  		(first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
  		k[0..63] :=
  		   0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  		   0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  		   0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  		   0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  		   0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  		   0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  		   0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  		   0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  		*/
  		var k = arrayHex2bin([
  		   0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  		   0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  		   0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  		   0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  		   0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  		   0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  		   0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  		   0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  		]);
  /*
  		k.forEach(function(val, idx) {
  			out("k"+idx, bin2hex(val), val);
  		});
  */
  		var digest = "",
  
  			arMsg = message.split(''),
  			arMsgLen = arMsg.length,
  
  			originalBits = [],
  			originalBitsLength = 0,
  
  			err = null,
  
  			i, s0, s1,
  
  			S0, S1, ch, maj, temp1, temp2,
  
  			a,b,c,d,e,f,g,h,
  
  			l,m,n,o,p,
  
  			u,v,w,x,y,z,
  
  			z1, z2, z3;
  
  		/*
  		Pre-processing:
  		begin with the original message of length L bits
  		*/
  		//out("message", message);
  		//out("arMsg", arMsg);
  		//out("arMsgLen", arMsgLen);
  		for (u=0; u<arMsgLen; u++) {
  			//out("u", u);
  			v = arMsg[u];
  			//out("v", v);
  			w = v.charCodeAt(0);
  			//out("w", w);
  			x = w.toString(2);
  			//out("x", x);
  			y = x.split('');
  			//out("y", y);
  			v = y.length;
  			w = 8 - v;
  			for (x=0; x<w; x++) {
  				//out("bit[" + x + "] =", zeroBit);
  				originalBits.push(zeroBit);
  			}
  			for (x=0; x<v; x++) {
  				z = y[x];
  				//out("bit[" + (x + w) + "] =", z);
  				originalBits.push(+z);
  			}
  		}
  		//var originalBits = message.toString(2);
  		//out("originalBits", originalBits);
  
  		originalBitsLength = originalBits.length;
  		//out("originalBitsLength", originalBitsLength);
  		/*
  		append a single '1' bit
  		*/
  		u = originalBits.slice();
  		u.push(oneBit);
  		//out("u", u);
  		/*
  		append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512
  		*/
  
  		v = u.length;
  		//out("length", v);
  		w = (v + 64);
  		//out("length + 64", w);
  		v = w % 512;
  		//out("length + 64 % 512", v);
  		//w = 512 - 64 - v;
  		w = 512 - v;
  		//out("w", w);
  		for (x=0; x<w; x++) {
  			u.push(zeroBit);
  		}
  		//out("u", u);
  		y = u.length;
  		//out("y", y);
  		/*
  		append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits
  		*/
  		//out("originalBitsLength", originalBitsLength);
  		z = originalBitsLength.toString(2).split('');
  		//out("z", z);
  		v = z.length;
  		//out("v", v);
  		w = 64 - v;
  		//out("w", w);
  		for (x=0; x<w; x++) {
  			u.push(zeroBit);
  		}
  		for (x=0; x<v; x++) {
  			u.push(+z[x]);
  		}
  		//out("u", u);
  		v = u.length;
  		//out("v", v);
  		w = v % 512;
  		//out("w", w ? "ERROR! preprocess block length invalid " + w : "Success! Block length " + v + " % 512 = " + w);
  
  		/*
  		Process the message in successive 512-bit chunks:
  		*/
  		for (x=0; x<v; x+=512) {
  				//out("chunk", x / 512, x);
  			/*
  			break message into 512-bit chunks
  			for each chunk
  		    create a 64-entry message schedule array w[0..63] of 32-bit words
  		    (The initial values in w[0..63] don't matter, so many implementations zero them here)
  		    */
  		    w = [];
  		    /*
  		    copy chunk into first 16 words w[0..15] of the message schedule array
  			*/
  			for (y=0; y<16; y++) {
  				w[y] = [];
  				for (z=0; z<32; z++) {
  					w[y].push(
  						u[x + y * 32 + z]
  					);
  				}
  				//out("w[" + y + "]", w[y], bin2hex(w[y]));
  			}
  
  			/*
  		    Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
  		    for i from 16 to 63
  		    */
  			for (i=16; i<64; i++) {
  				/*
  		        s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3)
  		        */
  		        y = w[i-15];
  		        //out(i,"y",y);
  		        z = rightrotate(y, 7);
  		        //out("z", z);
  		        z1 = rightrotate(y, 18);
  		        //out("z1", z1);
  		        z2 = rightshift(y, 3);
  		        //out("z2", z2);
  		        s0 = xor(z, z1, z2);
  		        //out("s0", s0);
  		        /*
  		        s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor (w[i-2] rightshift 10)
  		        */
  		        y = w[i-2];
  		        //out(i,"y",y);
  		        z = rightrotate(y, 17);
  		        //out("z", z);
  		        z1 = rightrotate(y, 19);
  		        //out("z1", z1);
  		        z2 = rightshift(y, 10);
  		        //out("z2", z2);
  		        s1 = xor(z, z1, z2);
  		        //out("s1", s1);
  		        /*
  		        w[i] := w[i-16] + s0 + w[i-7] + s1
  				*/
  				y = w[i-16];
  				//out("y", y);
  				z = w[i-7];
  				//out("z", z);
  				w[i] = add(y, s0, z, s1);
  				//out("w["+i+"]", w[i]);
  			}
  			/*
  		    Initialize working variables to current hash value:
  		    a := h0
  		    b := h1
  		    c := h2
  		    d := h3
  		    e := h4
  		    f := h5
  		    g := h6
  		    h := h7
  			*/
  			a = h0;
  			b = h1;
  			c = h2;
  			d = h3;
  			e = h4;
  			f = h5;
  			g = h6;
  			h = h7;
  			/*
  		    Compression function main loop:
  		    for i from 0 to 63
  		    	*/
  		    for (i=0; i<64; i++) {
  		    	/*
  		        S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
  		        */
  		        l = rightrotate(e, 6);
  		        m = rightrotate(e, 11);
  		        n = rightrotate(e, 25);
  		        S1 = xor(l, m, n);
  		        //out("S1", S1);
  		        /*
  		        ch := (e and f) xor ((not e) and g)
  		        */
  		        l = and(e, f);
  		        m = not(e);
  		        n = and(m, g);
  		        ch = xor(l, n);
  		        //out("ch", ch);
  		        /*
  		        temp1 := h + S1 + ch + k[i] + w[i]
  		        */
  		        temp1 = add(h, S1, ch, k[i], w[i]);
  		        //out("temp1", temp1);
  		        /*
  		        S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
  		        */
  		        l = rightrotate(a, 2);
  		        m = rightrotate(a, 13);
  		        n = rightrotate(a, 22);
  		        S0 = xor(l, m, n);
  		        //out("S0", S0);
  		        /*
  		        maj := (a and b) xor (a and c) xor (b and c)
  		        */
  		        l = and(a, b);
  		        m = and(a, c);
  		        n = and(b, c);
  		        maj = xor(l, m, n);
  		        //out("maj", maj);
  		        /*
  		        temp2 := S0 + maj
  		 		*/
  		 		temp2 = add(S0, maj);
  		 		//out("temp2", temp2);
  		 		/*
  		        h := g
  		        g := f
  		        f := e
  		        e := d + temp1
  		        d := c
  		        c := b
  		        b := a
  		        a := temp1 + temp2
  				*/
  				h = g;
  		        g = f;
  		        f = e;
  		        e = add(d, temp1);
  		        //out("e", e);
  		        d = c;
  		        c = b;
  		        b = a;
  		        a = add(temp1, temp2);
  		        //out("a", a);
  		        //out("t="+i, arrayBin2hex([a,b,c,d,e,f,g,h]).join(' '));
  			}
  			/*
  		    Add the compressed chunk to the current hash value:
  		    h0 := h0 + a
  		    h1 := h1 + b
  		    h2 := h2 + c
  		    h3 := h3 + d
  		    h4 := h4 + e
  		    h5 := h5 + f
  		    h6 := h6 + g
  		    h7 := h7 + h
  		    */
  		    //out("h0", bin2hex(h0), "+", bin2hex(a), "=", bin2hex(add(h0, a)));
  		    h0 = add(h0, a);
  		    //out("h1", bin2hex(h1), "+", bin2hex(b), "=", bin2hex(add(h1, b)));
  		    h1 = add(h1, b);
  		    //out("h2", bin2hex(h2), "+", bin2hex(c), "=", bin2hex(add(h2, c)));
  		    h2 = add(h2, c);
  		    //out("h3", bin2hex(h3), "+", bin2hex(d), "=", bin2hex(add(h3, d)));
  		    h3 = add(h3, d);
  		    //out("h4", bin2hex(h4), "+", bin2hex(e), "=", bin2hex(add(h4, e)));
  		    h4 = add(h4, e);
  		    //out("h5", bin2hex(h5), "+", bin2hex(f), "=", bin2hex(add(h5, f)));
  		    h5 = add(h5, f);
  		    //out("h6", bin2hex(h6), "+", bin2hex(g), "=", bin2hex(add(h6, g)));
  		    h6 = add(h6, g);
  		    //out("h7", bin2hex(h7), "+", bin2hex(h), "=", bin2hex(add(h7, h)));
  		    h7 = add(h7, h);
  		}
  		/*
  		Produce the final hash value (big-endian):
  		digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
  		*/
  		digest = arrayBin2hex([h0,h1,h2,h3,h4,h5,h6,h7]);
  	} catch (e) {
  		err = e;
  		console.error("ERROR", e);
  	} finally {
  		return debugging ? [digest.join(" "), debugOutput, err] : digest.join('');
  	}
  }
func_code_string: function sha256(message, debugging) {
  
  	var debugOutput = [],
  		noop = function(){},
  		out = debugging ? function() {
  			debugOutput.push(
  				[].slice.call(arguments).join(" ")
  			);
  		} : noop;
  
  	try {
  		/*
  		Initialize hash values:
  		(first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
  		h0 := 0x6a09e667
  		h1 := 0xbb67ae85
  		h2 := 0x3c6ef372
  		h3 := 0xa54ff53a
  		h4 := 0x510e527f
  		h5 := 0x9b05688c
  		h6 := 0x1f83d9ab
  		h7 := 0x5be0cd19
  		*/
  		var h0 = hex2bin(0x6a09e667),
  			h1 = hex2bin(0xbb67ae85),
  			h2 = hex2bin(0x3c6ef372),
  			h3 = hex2bin(0xa54ff53a),
  			h4 = hex2bin(0x510e527f),
  			h5 = hex2bin(0x9b05688c),
  			h6 = hex2bin(0x1f83d9ab),
  			h7 = hex2bin(0x5be0cd19);
  
  		//out("h0", bin2hex(h0), h0);
  		//out("h1", bin2hex(h1), h1);
  		//out("h2", bin2hex(h2), h2);
  		//out("h3", bin2hex(h3), h3);
  		//out("h4", bin2hex(h4), h4);
  		//out("h5", bin2hex(h5), h5);
  		//out("h6", bin2hex(h6), h6);
  		//out("h7", bin2hex(h7), h7);
  
  		/*
  		Initialize array of round constants:
  		(first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
  		k[0..63] :=
  		   0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  		   0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  		   0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  		   0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  		   0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  		   0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  		   0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  		   0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  		*/
  		var k = arrayHex2bin([
  		   0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  		   0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  		   0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  		   0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  		   0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  		   0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  		   0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  		   0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  		]);
  /*
  		k.forEach(function(val, idx) {
  			out("k"+idx, bin2hex(val), val);
  		});
  */
  		var digest = "",
  
  			arMsg = message.split(''),
  			arMsgLen = arMsg.length,
  
  			originalBits = [],
  			originalBitsLength = 0,
  
  			err = null,
  
  			i, s0, s1,
  
  			S0, S1, ch, maj, temp1, temp2,
  
  			a,b,c,d,e,f,g,h,
  
  			l,m,n,o,p,
  
  			u,v,w,x,y,z,
  
  			z1, z2, z3;
  
  		/*
  		Pre-processing:
  		begin with the original message of length L bits
  		*/
  		//out("message", message);
  		//out("arMsg", arMsg);
  		//out("arMsgLen", arMsgLen);
  		for (u=0; u<arMsgLen; u++) {
  			//out("u", u);
  			v = arMsg[u];
  			//out("v", v);
  			w = v.charCodeAt(0);
  			//out("w", w);
  			x = w.toString(2);
  			//out("x", x);
  			y = x.split('');
  			//out("y", y);
  			v = y.length;
  			w = 8 - v;
  			for (x=0; x<w; x++) {
  				//out("bit[" + x + "] =", zeroBit);
  				originalBits.push(zeroBit);
  			}
  			for (x=0; x<v; x++) {
  				z = y[x];
  				//out("bit[" + (x + w) + "] =", z);
  				originalBits.push(+z);
  			}
  		}
  		//var originalBits = message.toString(2);
  		//out("originalBits", originalBits);
  
  		originalBitsLength = originalBits.length;
  		//out("originalBitsLength", originalBitsLength);
  		/*
  		append a single '1' bit
  		*/
  		u = originalBits.slice();
  		u.push(oneBit);
  		//out("u", u);
  		/*
  		append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512
  		*/
  
  		v = u.length;
  		//out("length", v);
  		w = (v + 64);
  		//out("length + 64", w);
  		v = w % 512;
  		//out("length + 64 % 512", v);
  		//w = 512 - 64 - v;
  		w = 512 - v;
  		//out("w", w);
  		for (x=0; x<w; x++) {
  			u.push(zeroBit);
  		}
  		//out("u", u);
  		y = u.length;
  		//out("y", y);
  		/*
  		append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits
  		*/
  		//out("originalBitsLength", originalBitsLength);
  		z = originalBitsLength.toString(2).split('');
  		//out("z", z);
  		v = z.length;
  		//out("v", v);
  		w = 64 - v;
  		//out("w", w);
  		for (x=0; x<w; x++) {
  			u.push(zeroBit);
  		}
  		for (x=0; x<v; x++) {
  			u.push(+z[x]);
  		}
  		//out("u", u);
  		v = u.length;
  		//out("v", v);
  		w = v % 512;
  		//out("w", w ? "ERROR! preprocess block length invalid " + w : "Success! Block length " + v + " % 512 = " + w);
  
  		/*
  		Process the message in successive 512-bit chunks:
  		*/
  		for (x=0; x<v; x+=512) {
  				//out("chunk", x / 512, x);
  			/*
  			break message into 512-bit chunks
  			for each chunk
  		    create a 64-entry message schedule array w[0..63] of 32-bit words
  		    (The initial values in w[0..63] don't matter, so many implementations zero them here)
  		    */
  		    w = [];
  		    /*
  		    copy chunk into first 16 words w[0..15] of the message schedule array
  			*/
  			for (y=0; y<16; y++) {
  				w[y] = [];
  				for (z=0; z<32; z++) {
  					w[y].push(
  						u[x + y * 32 + z]
  					);
  				}
  				//out("w[" + y + "]", w[y], bin2hex(w[y]));
  			}
  
  			/*
  		    Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
  		    for i from 16 to 63
  		    */
  			for (i=16; i<64; i++) {
  				/*
  		        s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3)
  		        */
  		        y = w[i-15];
  		        //out(i,"y",y);
  		        z = rightrotate(y, 7);
  		        //out("z", z);
  		        z1 = rightrotate(y, 18);
  		        //out("z1", z1);
  		        z2 = rightshift(y, 3);
  		        //out("z2", z2);
  		        s0 = xor(z, z1, z2);
  		        //out("s0", s0);
  		        /*
  		        s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor (w[i-2] rightshift 10)
  		        */
  		        y = w[i-2];
  		        //out(i,"y",y);
  		        z = rightrotate(y, 17);
  		        //out("z", z);
  		        z1 = rightrotate(y, 19);
  		        //out("z1", z1);
  		        z2 = rightshift(y, 10);
  		        //out("z2", z2);
  		        s1 = xor(z, z1, z2);
  		        //out("s1", s1);
  		        /*
  		        w[i] := w[i-16] + s0 + w[i-7] + s1
  				*/
  				y = w[i-16];
  				//out("y", y);
  				z = w[i-7];
  				//out("z", z);
  				w[i] = add(y, s0, z, s1);
  				//out("w["+i+"]", w[i]);
  			}
  			/*
  		    Initialize working variables to current hash value:
  		    a := h0
  		    b := h1
  		    c := h2
  		    d := h3
  		    e := h4
  		    f := h5
  		    g := h6
  		    h := h7
  			*/
  			a = h0;
  			b = h1;
  			c = h2;
  			d = h3;
  			e = h4;
  			f = h5;
  			g = h6;
  			h = h7;
  			/*
  		    Compression function main loop:
  		    for i from 0 to 63
  		    	*/
  		    for (i=0; i<64; i++) {
  		    	/*
  		        S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
  		        */
  		        l = rightrotate(e, 6);
  		        m = rightrotate(e, 11);
  		        n = rightrotate(e, 25);
  		        S1 = xor(l, m, n);
  		        //out("S1", S1);
  		        /*
  		        ch := (e and f) xor ((not e) and g)
  		        */
  		        l = and(e, f);
  		        m = not(e);
  		        n = and(m, g);
  		        ch = xor(l, n);
  		        //out("ch", ch);
  		        /*
  		        temp1 := h + S1 + ch + k[i] + w[i]
  		        */
  		        temp1 = add(h, S1, ch, k[i], w[i]);
  		        //out("temp1", temp1);
  		        /*
  		        S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
  		        */
  		        l = rightrotate(a, 2);
  		        m = rightrotate(a, 13);
  		        n = rightrotate(a, 22);
  		        S0 = xor(l, m, n);
  		        //out("S0", S0);
  		        /*
  		        maj := (a and b) xor (a and c) xor (b and c)
  		        */
  		        l = and(a, b);
  		        m = and(a, c);
  		        n = and(b, c);
  		        maj = xor(l, m, n);
  		        //out("maj", maj);
  		        /*
  		        temp2 := S0 + maj
  		 		*/
  		 		temp2 = add(S0, maj);
  		 		//out("temp2", temp2);
  		 		/*
  		        h := g
  		        g := f
  		        f := e
  		        e := d + temp1
  		        d := c
  		        c := b
  		        b := a
  		        a := temp1 + temp2
  				*/
  				h = g;
  		        g = f;
  		        f = e;
  		        e = add(d, temp1);
  		        //out("e", e);
  		        d = c;
  		        c = b;
  		        b = a;
  		        a = add(temp1, temp2);
  		        //out("a", a);
  		        //out("t="+i, arrayBin2hex([a,b,c,d,e,f,g,h]).join(' '));
  			}
  			/*
  		    Add the compressed chunk to the current hash value:
  		    h0 := h0 + a
  		    h1 := h1 + b
  		    h2 := h2 + c
  		    h3 := h3 + d
  		    h4 := h4 + e
  		    h5 := h5 + f
  		    h6 := h6 + g
  		    h7 := h7 + h
  		    */
  		    //out("h0", bin2hex(h0), "+", bin2hex(a), "=", bin2hex(add(h0, a)));
  		    h0 = add(h0, a);
  		    //out("h1", bin2hex(h1), "+", bin2hex(b), "=", bin2hex(add(h1, b)));
  		    h1 = add(h1, b);
  		    //out("h2", bin2hex(h2), "+", bin2hex(c), "=", bin2hex(add(h2, c)));
  		    h2 = add(h2, c);
  		    //out("h3", bin2hex(h3), "+", bin2hex(d), "=", bin2hex(add(h3, d)));
  		    h3 = add(h3, d);
  		    //out("h4", bin2hex(h4), "+", bin2hex(e), "=", bin2hex(add(h4, e)));
  		    h4 = add(h4, e);
  		    //out("h5", bin2hex(h5), "+", bin2hex(f), "=", bin2hex(add(h5, f)));
  		    h5 = add(h5, f);
  		    //out("h6", bin2hex(h6), "+", bin2hex(g), "=", bin2hex(add(h6, g)));
  		    h6 = add(h6, g);
  		    //out("h7", bin2hex(h7), "+", bin2hex(h), "=", bin2hex(add(h7, h)));
  		    h7 = add(h7, h);
  		}
  		/*
  		Produce the final hash value (big-endian):
  		digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
  		*/
  		digest = arrayBin2hex([h0,h1,h2,h3,h4,h5,h6,h7]);
  	} catch (e) {
  		err = e;
  		console.error("ERROR", e);
  	} finally {
  		return debugging ? [digest.join(" "), debugOutput, err] : digest.join('');
  	}
  }
func_documentation_string: /* hash the message and return 256 bits in hex