Browse Source

updated mishmash - added second hash capabilities by converting Mishmash to a modified variadic function - takes and uses the accumulator if given

master
William Dillon 3 years ago
parent
commit
7bad662b17
3 changed files with 48 additions and 18 deletions
  1. 8
    0
      README.md
  2. 26
    11
      mishmash.go
  3. 14
    7
      mishmash_test.go

+ 8
- 0
README.md View File

# Mishmash

this is a non-cryptographic hash optimized for short strings.

adapted from CodeDweller/mishmash.h/cpp
https://code.microneil.com/madscientist/CodeDweller/src/branch/master

to use: use the Mishmash function. If you're in need of a second hash (or could be) keep the second value returned, that's the accumulator. Mishmash will take that in a second call, along with your string, to create a second hash.

+ 26
- 11
mishmash.go View File

// mishmash.go
// Copyright (C) 2021 MicroNeil Research Corporation.
//
// This software is released under the MIT license. See LICENSE.TXT.
//
// Mishamash is a non-cryptographic hash optimized for short strings.
package mishmash package mishmash


var primes = [256]uint32{2781111551, 4115761697, 2188512439, 3902941499, 4078728127, 2919449173, 3950407729, 4081733563, var primes = [256]uint32{2781111551, 4115761697, 2188512439, 3902941499, 4078728127, 2919449173, 3950407729, 4081733563,
return primes[n&0xff] return primes[n&0xff]
} }


func engine(buffer []byte, length int) uint64 {
var accumulator uint64 = 0
func Engine(buffer []byte, length int, accumulator uint64) uint64 {
// exported for ease of use - Mishmash below returns
// both the mishmash AND accumulator
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
b := buffer[i] b := buffer[i]
accumulator += uint64(slct(accumulator)) + uint64(b) accumulator += uint64(slct(accumulator)) + uint64(b)
return accumulator return accumulator
} }


func Mishmash(buffer []byte) uint32 {
accumulator := engine(buffer, len(buffer))
return uint32(accumulator & 0x00000000ffffffff)
func Mishmash(buffer []byte, nums ...uint64) (uint32, uint64) {
// returns mishmashHash, accumulator
var accumulator uint64
if 0 == len(nums) {
accumulator = Engine(buffer, len(buffer), 0)
} else {
accumulator = Engine(buffer, len(buffer), nums[0])
}
return uint32(accumulator & 0x00000000ffffffff), accumulator
}

// example below shows calling Mishmash on "hello world"
// and then collecting the hash and accumulator. Given
// a collision we simply call Mishmash again, giving it
// the accumulator this time, and get a second hash.
/*
func main() {
buf := []byte("Hello world")
hash, accumulator := Mishmash(buf)
fmt.Println(uint32(hash & 0x00000000ffffffff))
secondHash, accumulator := Mishmash(buf, accumulator)
fmt.Println(uint32(secondHash & 0x00000000ffffffff))
} }
*/

+ 14
- 7
mishmash_test.go View File

"testing" "testing"
) )


func TestMishmashString(t *testing.T) {
func TestMishmash(t *testing.T) {
want := "9d923077" want := "9d923077"
if got := fmt.Sprintf("%08x", Mishmash([]byte("google.com"))); want != got {
hash, _ := Mishmash([]byte("google.com"))
got := fmt.Sprintf("%08x", hash)
if want != got {
t.Error("Parse() = got", got, "want", want) t.Error("Parse() = got", got, "want", want)
} else { } else {
fmt.Println("TestMishmashString passed")
fmt.Println("TestMishmash Passed")
} }
} }
func TestMishmashUint32(t *testing.T) {
var want uint32 = 2643603575
if got := Mishmash([]byte("google.com")); want != got {

func TestSecondHash(t *testing.T) {
want := "65df1304"
_, accum := Mishmash([]byte("google.com"))
hash, accum := Mishmash([]byte("google.com"), accum)
got := fmt.Sprintf("%08x", hash)
if want != got {
t.Error("Parse() = got", got, "want", want) t.Error("Parse() = got", got, "want", want)
} else { } else {
fmt.Println("TestMishmashUint32 passed")
fmt.Println("TestSecondHash Passed")
} }

} }

Loading…
Cancel
Save