// This function determines if a number is prime.
// See first if statement of HavokN.
const isPrime = num => {
for(let i = 2, s = Math.sqrt(num); i <= s; i++) {
if(num % i === 0) return false;
}
return num > 1;
}
function HavokN( data, size, iterations = 0 ) {
// Calculate the size once and re-use it instead of recalculating it every
// time we need it. This should greatly improve the performance of the
// following if statement.
var exponatedSize = ((2 ** size)-1);
// Don't bother if the requested hash size is already a prime number, but
// if it isn't, keep subtracting 1 from the size until we find one that is
// prime. This is probably terribly inefficient, but it gets the job done.
if( isPrime(exponatedSize) || size == 1 ) {
prime = exponatedSize;
} else {
for ( i = exponatedSize; !isPrime(i); i-- ) {
prime = i-1;
}
}
count = data.length;
var sum1 = 0;
var sum2 = 0;
// This is where the algorithm actually starts
for ( index = 0; index < count; index++ ) {
sum1 = (sum1 + data.codePointAt(index)) % prime;
sum2 = (sum2 + sum1) % prime;
}
// '<<' is an operator that bitshifts the number on the left by the number
// on the right. It needs to be half of the length because sum1 is
// (theoretically) half the length of sum2, and we're basically just
// appending sum1 to sum2.
// Then it takes that and bitwise-or it against sum1.
combinedsum = ( sum2 << Math.floor(size/2) ) | sum1;
// This impliments a very basic iterative function TO THE FINAL CALCULATED
// CHECKSUM. This is helpful for if you want similar inputs' checksums to
// look more different from eachother.
while(iterations > 0) {
combinedsum = (combinedsum * size) % prime;
iterations--;
}
return combinedsum;
}