简体   繁体   中英

Jenkins Hash in Scala

I'm trying to write the Jenkins Hash ( http://burtleburtle.net/bob/hash/doobs.html ) in Scala. This bit is tricky...

   switch(len)              /* all the case statements fall through */
   {
   case 11: c+=((ub4)k[10]<<24);
   case 10: c+=((ub4)k[9]<<16);
   case 9 : c+=((ub4)k[8]<<8);
      /* the first byte of c is reserved for the length */
   case 8 : b+=((ub4)k[7]<<24);
   case 7 : b+=((ub4)k[6]<<16);
   case 6 : b+=((ub4)k[5]<<8);
   case 5 : b+=k[4];
   case 4 : a+=((ub4)k[3]<<24);
   case 3 : a+=((ub4)k[2]<<16);
   case 2 : a+=((ub4)k[1]<<8);
   case 1 : a+=k[0];
     /* case 0: nothing left to add */
   }   

match statements don't fall through in Scala (which is an excellent design decision). So best way to do this I can think of is to have one if statement per case. I'm hoping someone can see a more pithy solution…

Something like this perhaps?

        val (a,b,c) = k
            .zipWithIndex
            .foldLeft((0,0,0)) { case ((a,b,c), (v, index)) => 
                index match {
                 case i if i < 4 => (a + (v << i*8), b, c)
                 case i if i < 8 => (a, b + (v << (i-4)*8), b, c)
                 case i => (a, b, c + (v << (i-7)*8))
                }
            }

I haven't tested the result, but this is one way to implement it. Drop and take the bytes of the array needed for each value. Also fold from right in order to rotate the rightmost value from 0 to 8 to 16 to 24.

Working with unsigned in JVM is a bit cumbersome and requires that we transform it to a wider data type, ie byte to int and int to long). Therefore we use longify to convert to byte to long. We also need to account for half the byte values being negative.

val longify = ((n: Byte) => n.toLong) andThen (n => if (n < 0) n + 256 else n)
def sum(m: Int, n: Int) = 
    k.drop(m).take(n).foldRight(0L)((b, s) => longify(b) + (s << 8))
val a = sum(0, 4)
val b = sum(4, 4)
val c = (sum(9, 3) << 8) + k.size

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM