2010-11-20 4 views
2

JenkinsハッシュのJavascript実装がありますか?自分で実装するのではなく、使用できますか?Jenkins HashのJavascript実装ですか?

私は自分のJSを書くために使用することができますPythonのimplemenationが存在しているはず。しかし私はJavascriptの専門家ではないので、誰かがelsesの実装を好むだろう。


アップデート:(私が変換しようとしなかったhttp://www.burtleburtle.net/bob/c/lookup3.c) アップデート2:このコードは、ほんの数でlookup3.c

var Jenkins = { 
rot: function(x,k) { 
    return (x<<k) | (x>>>(32-k)); 
}, 

mix: function(a,b,c) { 
    a = (a - c) | 0; a ^= Jenkins.rot(c, 4); c = (c + b) | 0; 
    b = (b - a) | 0; b ^= Jenkins.rot(a, 6); a = (a + c) | 0; 
    c = (c - b) | 0; c ^= Jenkins.rot(b, 8); b = (b + a) | 0; 
    a = (a - c) | 0; a ^= Jenkins.rot(c,16); c = (c + b) | 0; 
    b = (b - a) | 0; b ^= Jenkins.rot(a,19); a = (a + c) | 0; 
    c = (c - b) | 0; c ^= Jenkins.rot(b, 4); b = (b + a) | 0; 
    return {a : a, b : b, c : c}; 
}, 

final: function(a,b,c) { 
    c ^= b; c -= Jenkins.rot(b,14) | 0; 
    a ^= c; a -= Jenkins.rot(c,11) | 0; 
    b ^= a; b -= Jenkins.rot(a,25) | 0; 
    c ^= b; c -= Jenkins.rot(b,16) | 0; 
    a ^= c; a -= Jenkins.rot(c,4) | 0; 
    b ^= a; b -= Jenkins.rot(a,14) | 0; 
    c ^= b; c -= Jenkins.rot(b,24) | 0; 
    return {a : a, b : b, c : c}; 
}, 

hashlittle2: function(k, initval, initval2) { 
    var length = k.length; 
    a = b = c = 0xdeadbeef + length + initval; 
    c += initval2; 

    offset = 0; 
    while (length > 12) { 
     a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16) + (k.charCodeAt(offset+3)<<24)); a = a>>>0; 
     b += (k.charCodeAt(offset+4) + (k.charCodeAt(offset+5)<<8) + (k.charCodeAt(offset+6)<<16) + (k.charCodeAt(offset+7)<<24)); b = b>>>0; 
     c += (k.charCodeAt(offset+8) + (k.charCodeAt(offset+9)<<8) + (k.charCodeAt(offset+10)<<16) + (k.charCodeAt(offset+11)<<24)); c = c>>>0; 
     o = Jenkins.mix(a,b,c); 
     a = o.a; b = o.b; c = o.c; 
     length -= 12; 
     offset += 12; 
    } 

    switch(length) { 
     case 12: c += (k.charCodeAt(offset+8) + (k.charCodeAt(offset+9)<<8) + (k.charCodeAt(offset+10)<<16) + (k.charCodeAt(offset+11)<<24)); b += (k.charCodeAt(offset+4) + (k.charCodeAt(offset+5)<<8) + (k.charCodeAt(offset+6)<<16) + (k.charCodeAt(offset+7)<<24)); a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16) + (k.charCodeAt(offset+3)<<24)); break; 
     case 11: c += (k.charCodeAt(offset+8) + (k.charCodeAt(offset+9)<<8) + (k.charCodeAt(offset+10)<<16)); b += (k.charCodeAt(offset+4) + (k.charCodeAt(offset+5)<<8) + (k.charCodeAt(offset+6)<<16) + (k.charCodeAt(offset+7)<<24)); a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16) + (k.charCodeAt(offset+3)<<24)); break; 
     case 10: c += (k.charCodeAt(offset+8) + (k.charCodeAt(offset+9)<<8)); b += (k.charCodeAt(offset+4) + (k.charCodeAt(offset+5)<<8) + (k.charCodeAt(offset+6)<<16) + (k.charCodeAt(offset+7)<<24)); a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16) + (k.charCodeAt(offset+3)<<24)); break; 
     case 9: c += (k.charCodeAt(offset+8)); b += (k.charCodeAt(offset+4) + (k.charCodeAt(offset+5)<<8) + (k.charCodeAt(offset+6)<<16) + (k.charCodeAt(offset+7)<<24)); a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16) + (k.charCodeAt(offset+3)<<24)); break; 
     case 8: b += (k.charCodeAt(offset+4) + (k.charCodeAt(offset+5)<<8) + (k.charCodeAt(offset+6)<<16) + (k.charCodeAt(offset+7)<<24)); a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16) + (k.charCodeAt(offset+3)<<24)); break; 
     case 7: b += (k.charCodeAt(offset+4) + (k.charCodeAt(offset+5)<<8) + (k.charCodeAt(offset+6)<<16)); a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16) + (k.charCodeAt(offset+3)<<24)); break; 
     case 6: b += ((k.charCodeAt(offset+5)<<8) + k.charCodeAt(offset+4)); a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16) + (k.charCodeAt(offset+3)<<24)); break; 
     case 5: b += (k.charCodeAt(offset+4)); a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16) + (k.charCodeAt(offset+3)<<24)); break; 
     case 4: a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16) + (k.charCodeAt(offset+3)<<24)); break; 
     case 3: a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8) + (k.charCodeAt(offset+2)<<16)); break; 
     case 2: a += (k.charCodeAt(offset+0) + (k.charCodeAt(offset+1)<<8)); break; 
     case 1: a += (k.charCodeAt(offset+0)); break; 
     case 0: return {b : b, c : c}; 
    } 

    o = Jenkins.final(a,b,c); 
    a = o.a; b = o.b; c = o.c; 

    return {b : b>>>0, c : c>>>0}; 
}  

}

+0

よろしくお願いします。また、あなたがテストのための有効なデータの既存のソースを持っている場合...:P –

答えて

4

は、ここで私はJavaScriptでBloom filterを実装するための個人的なプロジェクトのためにlookup3.cでやったJavaScriptのポートです。私はそれがCコードに同じ結果を生成するかどうかを確かめることはできません。

JavaScriptに直接変換されない主なものの1つはです。キー入力へのポインタに対してが実行されます。下のコードで、offsetという単語を探して、私がどのようにそれを処理したかを見てください。

整数が符号なしであるかのように出力したい場合は、returnValue >>> 0を使用することができます。

var BloomFilter = { 
    // Convert a JavaScript string into an array of 32-bit words. 
    // This preserves the UTF-16 encoding, padding with the null character if necessary. 
    stringToWords: function(s) { 
     var b = []; 
     if(s.length & 1) { 
      s += "\u0000"; 
     } 
     for (var i = 0; i < s.length; i += 2) { 
      b.push((s.charCodeAt(i) << 16) | (s.charCodeAt(i + 1))); 
     } 
     return b; 
    }, 

    // Hash an array of multiple 32-bit words to a single word. 
    // Adapted from "lookup3.c, by Bob Jenkins, May 2006, Public Domain." 
    // as retrieved 2010-07-03 from http://burtleburtle.net/bob/c/lookup3.c 

    hashWord: function(k, initval) { 
     // definition of bitwise rotate function 
     function rot(x, k) { 
      return (x << k) | (x >>> (32 - k)); 
     } 

     // initialization 
     var a, b, c, length = k.length, offset = 0; 
     a = b = c = (0xdeadbeef + (length << 2) + initval) | 0; 

     // handle most of the key 
     while(length > 3) { 
      a = (a + k[offset]) | 0; 
      b = (b + k[offset + 1]) | 0; 
      c = (c + k[offset + 2]) | 0; 

      // mixing function 
      a = (a - c) | 0; a ^= rot(c, 4); c = (c + b) | 0; 
      b = (b - a) | 0; b ^= rot(a, 6); a = (a + c) | 0; 
      c = (c - b) | 0; c ^= rot(b, 8); b = (b + a) | 0; 
      a = (a - c) | 0; a ^= rot(c,16); c = (c + b) | 0; 
      b = (b - a) | 0; b ^= rot(a,19); a = (a + c) | 0; 
      c = (c - b) | 0; c ^= rot(b, 4); b = (b + a) | 0; 

      length -= 3; 
      offset += 3; 
     } 

     // handle the final words if left over; fall-through is intended 
     switch(length) { 
      case 3: c = (c + k[offset + 2]) | 0; 
      case 2: b = (b + k[offset + 1]) | 0; 
      case 1: a = (a + k[offset]) | 0; 

      // final mixing 
      c ^= b; c = (c - rot(b,14)) | 0; 
      a ^= c; a = (a - rot(c,11)) | 0; 
      b ^= a; b = (b - rot(a,25)) | 0; 
      c ^= b; c = (c - rot(b,16)) | 0; 
      a ^= c; a = (a - rot(c, 4)) | 0; 
      b ^= a; b = (b - rot(a,14)) | 0; 
      c ^= b; c = (c - rot(b,24)) | 0; 

      case 0: break; // nothing left to do 
     } 

     // return the result 
     return c; 
    }, 

    // Hash a string by converting to UTF-16 before using the lookup3 algorithm. 
    hashString: function(s) { 
     return BloomFilter.hashWord(BloomFilter.stringToWords(s), 0); 
    } 
} 
+0

lookup3.cとは異なる出力を持つように見えるが、他の2つのバージョンよりも速く_かなり遅いです(OPを含む)、何が問題になりましたか? – bryc

2

であなたhashlittle2と同じハッシュを与えますC code on WikipediaはJavaScriptで完全に動作します。データ型を取り除き、長さを渡す代わりにkey.lengthを使用してください。

+0

しかし、それは、「私のハッシュ」ジェンキンのプレゼントより*異なる*(とはるかに簡単な)ハッシュ次のとおりです。http://www.burtleburtle。 net/bob/hash/doobs.htmlには、他の相違点の中にミックスフェーズが含まれています。 (1つずつハッシュだけで、リンクとハッシュ議論の一つである。) –

+0

@pst:それのほとんどはJavaScriptでそのまま動作しますので、まあ、それは、まだシフトや他の算術演算子のちょうど束です。ただ、しかし、私は違いを信じる:-)それを指摘 – casablanca

+0

@casablancaは、オーバーフローの処理方法であってもよい - これは手動* JavaScriptのロジックに*追加する必要があります。 「My Hash」は符号なし4バイトを前提としており、2の補数を信じています。 –

関連する問題