urbit-ob

JavaScript utilities for phonemic base wrangling.
git clone git://git.jtobin.io/urbit-ob.git
Log | Files | Refs | README

muk.js (3905B)


      1 // ++  muk
      2 //
      3 // See arvo/sys/hoon.hoon.
      4 
      5 const BN = require('bn.js')
      6 
      7 const ux_FF = new BN(0xFF)
      8 const ux_FF00 = new BN(0xFF00)
      9 const u_256 = new BN(256)
     10 
     11 /**
     12  * Standard murmur3.
     13  *
     14  * @param  {Number}  syd
     15  * @param  {Number}  len
     16  * @param  {BN}  key
     17  * @return  {BN}
     18  */
     19 const muk = (syd, len, key) => {
     20   const lo = key.and(ux_FF).toNumber()
     21   const hi = key.and(ux_FF00).div(u_256).toNumber()
     22   const kee = String.fromCharCode(lo) + String.fromCharCode(hi)
     23   return new BN(murmurhash3_32_gc(kee, syd))
     24 }
     25 
     26 // see: https://github.com/garycourt/murmurhash-js
     27 //
     28 // Copyright (c) 2011 Gary Court
     29 //
     30 // Permission is hereby granted, free of charge, to any person obtaining a copy of
     31 // this software and associated documentation files (the "Software"), to deal in
     32 // the Software without restriction, including without limitation the rights to
     33 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
     34 // of the Software, and to permit persons to whom the Software is furnished to do
     35 // so, subject to the following conditions:
     36 //
     37 // The above copyright notice and this permission notice shall be included in all
     38 // copies or substantial portions of the Software.
     39 //
     40 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     41 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     42 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     43 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     44 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     45 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     46 // SOFTWARE.
     47 
     48 /**
     49  * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
     50  *
     51  * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
     52  * @see http://github.com/garycourt/murmurhash-js
     53  * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
     54  * @see http://sites.google.com/site/murmurhash/
     55  *
     56  * @param {string} key ASCII only
     57  * @param {number} seed Positive integer only
     58  * @return {number} 32-bit positive integer hash
     59  **/
     60 const murmurhash3_32_gc = (key, seed) => {
     61   // eslint-disable-next-line no-unused-vars
     62   let remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i;
     63 
     64   remainder = key.length & 3; // key.length % 4
     65   bytes = key.length - remainder;
     66   h1 = seed;
     67   c1 = 0xcc9e2d51;
     68   c2 = 0x1b873593;
     69   i = 0;
     70 
     71   while (i < bytes) {
     72       k1 =
     73         ((key.charCodeAt(i) & 0xff)) |
     74         ((key.charCodeAt(++i) & 0xff) << 8) |
     75         ((key.charCodeAt(++i) & 0xff) << 16) |
     76         ((key.charCodeAt(++i) & 0xff) << 24);
     77     ++i;
     78 
     79     k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
     80     k1 = (k1 << 15) | (k1 >>> 17);
     81     k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
     82 
     83     h1 ^= k1;
     84         h1 = (h1 << 13) | (h1 >>> 19);
     85     h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
     86     h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
     87   }
     88 
     89   k1 = 0;
     90 
     91   switch (remainder) {
     92     case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
     93     // eslint-disable-next-line no-fallthrough
     94     case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
     95     // eslint-disable-next-line no-fallthrough
     96     case 1: k1 ^= (key.charCodeAt(i) & 0xff);
     97 
     98     k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
     99     k1 = (k1 << 15) | (k1 >>> 17);
    100     k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
    101     h1 ^= k1;
    102   }
    103 
    104   h1 ^= key.length;
    105 
    106   h1 ^= h1 >>> 16;
    107   h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
    108   h1 ^= h1 >>> 13;
    109   h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
    110   h1 ^= h1 >>> 16;
    111 
    112   return h1 >>> 0;
    113 }
    114 
    115 module.exports = {
    116   muk
    117 }