-- rnd experimental hash ( min 256 bit output )
--TODO: rewrite with arrays, only final step convert to string. + better whole accumulator

if not crypto then crypto = {} end

local rndm = 2^31 − 1; --C++11's minstd_rand
local rnda = 48271; -- generator
local rndseed = 0;
local random = function(n)
	rndseed = (rnda*rndseed)% rndm;
	return rndseed % n
end

local hash_ = function(input,seed) 
	local n = 128-32+1; -- Z_97, 97 prime
	local m = 32;
	local ret = {};input = input or "";
	rndseed = seed;
	local key = {};
	local out = {};
	for i=1, string.len(input) do 
		key[i] = random(n) -- generate keys from password
		out[i] = string.byte(input,i)-m
		if out[i] == -6 then out[i] = 96 end -- conversion back
	end
	
	local c0 = 1; -- this serves as accumulator too
	for i=1, string.len(input) do
		local offset=key[i]
		local c = out[i];
		for j = 1,string.len(input) do c0 = c0 + (out[j])^3; c0 = c0 % n end 
		c = (c+c0+offset) % n;
		out[i] = c
	end
	rndseed = rndseed+c0
	
	for i = 1, string.len(input) do
		if out[i] == 96 then out[i]=-6 end -- 32 + 96 = 128 (bad char)
		ret[#ret+1] = string.char(m+out[i])
	end
	
	return table.concat(ret,""),rndseed
end
	
crypto.rndhash = function(text)
	local length = string.len(text);
	if length<32 then text = text .. string.rep(" ", 32-length) end
	local seed = 0; -- accumulator
	local ret = text; for i = 1, 10 do ret,seed = hash_(ret,seed) end
	return ret
end