Parcourir la source

updated mishmash - engine returns accumulator for use with Mishmash which takes it as an optional seed. Mishmash can be seeded however desired through this mechanism as well. Added simple function to decode accumulator for ease of use when we're going to be double hashing

master
William Dillon il y a 3 ans
Parent
révision
ba60fcb929
3 fichiers modifiés avec 46 ajouts et 21 suppressions
  1. 1
    1
      README.md
  2. 22
    12
      mishmash.go
  3. 23
    8
      mishmash_test.go

+ 1
- 1
README.md Voir le fichier

@@ -5,4 +5,4 @@ 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.
to use: use the Mishmash function. If you're in need of a second hash use Engine instead, which will return the accumulator. You can use the MishmashAccumulator function to mishmash your accumulator, and could also feed that accumulator back into Mishmash to double hash.

+ 22
- 12
mishmash.go Voir le fichier

@@ -39,39 +39,49 @@ func slct(n uint64) uint32 {
}

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++ {
b := buffer[i]
accumulator += uint64(slct(accumulator)) + uint64(b)
accumulator *= uint64(slct(uint64(b)))
accumulator += accumulator >> 32

}
return accumulator
}

func Mishmash(buffer []byte, nums ...uint64) (uint32, uint64) {
// returns mishmashHash, accumulator
func Mishmash(buffer []byte, nums ...uint64) uint32 {
// nums is a seed/accumulator
var accumulator uint64
if 0 == len(nums) {
// seeding with 0 by default - could be changed
accumulator = Engine(buffer, len(buffer), 0)
} else {
accumulator = Engine(buffer, len(buffer), nums[0])
}
return uint32(accumulator & 0x00000000ffffffff), accumulator
return uint32(accumulator & 0x00000000ffffffff)
}

func MishmashAccumulator(accumulator uint64) uint32 {
// use when collecting accumulators for second hash
return uint32(accumulator & 0x00000000ffffffff)
}

// example below shows calling Mishmash on "hello world"
// and then collecting the hash and accumulator. Given
// and then collecting the hash. Given
// a collision we simply call Mishmash again, giving it
// the accumulator this time, and get a second hash.
// the first hash as a seed 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))
// grab the accumulator if necessary
accum := Engine(buf, len(buf), 0)
// grab the hash - decode accumulator into hash
hash := MishmashAccumulator(accum)
fmt.Printf("%08x\n", hash)
// now get second hash - seed with accumulator
secondHash := Mishmash(buf, accum)
fmt.Printf("%08x\n", secondHash)
// you can also get a simple hash
simpleMishmash := Mishmash(buf)
fmt.Printf("%08x\n", simpleMishmash)
}
*/

+ 23
- 8
mishmash_test.go Voir le fichier

@@ -7,9 +7,7 @@ import (

func TestMishmash(t *testing.T) {
want := "9d923077"
hash, _ := Mishmash([]byte("google.com"))
got := fmt.Sprintf("%08x", hash)
if want != got {
if got := fmt.Sprintf("%08x", Mishmash([]byte("google.com"))); want != got {
t.Error("Parse() = got", got, "want", want)
} else {
fmt.Println("TestMishmash Passed")
@@ -17,14 +15,31 @@ func TestMishmash(t *testing.T) {
}

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 {
want := "3fbdb348"
hash := Mishmash([]byte("google.com"))
if got := fmt.Sprintf("%08x", Mishmash([]byte("google.com"), uint64(hash))); want != got {
t.Error("Parse() = got", got, "want", want)
} else {
fmt.Println("TestSecondHash Passed")
}
}

func TestSeedOne(t *testing.T) {
want := "cebf5691"
if got := fmt.Sprintf("%08x", Mishmash([]byte("google.com"), uint64(1))); want != got {
t.Error("Parse() = got", got, "want", want)
} else {
fmt.Println("TestSeedOne Passed")
}
}

func TestEngineAndAccumulator(t *testing.T) {
want := "65df1304"
test := []byte("google.com")
accum := Engine(test, len(test), 0)
if got := fmt.Sprintf("%08x", Mishmash(test, accum)); want != got {
t.Error("Parse() = got", got, "want", want)
} else {
fmt.Println("TestEngineAndAccumulator Passed")
}
}

Chargement…
Annuler
Enregistrer