about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-02-15 15:28:28 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-02-15 15:28:28 -0800
commitd5fe534d12d30395def6da176149177778017fe1 (patch)
tree00a04d585f31088a9167ddcbc3cd102d3484b265
parent4637d58f6c4777f9643f73de859af23c38acca2c (diff)
downloadmu-d5fe534d12d30395def6da176149177778017fe1.tar.gz
2662 - rewrite 'hash' in C++
Since it needs specialized non-overflowing types like unsigned long
long, my plan is to eventually write it in straight machine code using
Mu primitives to make that a slightly nicer process. Hopefully we'll
need to deal with machine types only for a tiny set of crucial
primitives and it won't be too painful to drop down to machine code for
them.
-rw-r--r--077hash.cc36
-rw-r--r--077hash.mu28
2 files changed, 36 insertions, 28 deletions
diff --git a/077hash.cc b/077hash.cc
new file mode 100644
index 00000000..c60c07e6
--- /dev/null
+++ b/077hash.cc
@@ -0,0 +1,36 @@
+// From http://burtleburtle.net/bob/hash/hashfaq.html
+:(before "End Primitive Recipe Declarations")
+HASH,
+:(before "End Primitive Recipe Numbers")
+put(Recipe_ordinal, "hash", HASH);
+:(before "End Primitive Recipe Checks")
+case HASH: {
+  if (SIZE(inst.ingredients) != 1) {
+    raise_error << maybe(get(Recipe, r).name) << "'hash' takes exactly one ingredient rather than '" << inst.to_string() << "'\n" << end();
+    break;
+  }
+  if (!is_mu_string(inst.ingredients.at(0))) {
+    raise_error << maybe(get(Recipe, r).name) << "'hash' currently only supports strings (address:shared:array:character), but got " << inst.ingredients.at(0).original_string << '\n' << end();
+    break;
+  }
+  break;
+}
+:(before "End Primitive Recipe Implementations")
+case HASH: {
+  string input = read_mu_string(ingredients.at(0).at(0));
+  size_t h = 0 ;
+
+  for (long long int i = 0; i < SIZE(input); ++i) {
+    h += static_cast<size_t>(input.at(i));
+    h += (h<<10);
+    h ^= (h>>6);
+
+    h += (h<<3);
+    h ^= (h>>11);
+    h += (h<<15);
+  }
+
+  products.resize(1);
+  products.at(0).push_back(h);
+  break;
+}
diff --git a/077hash.mu b/077hash.mu
deleted file mode 100644
index 77e564d9..00000000
--- a/077hash.mu
+++ /dev/null
@@ -1,28 +0,0 @@
-# From http://burtleburtle.net/bob/hash/hashfaq.html#example
-# Though this one doesn't behave the same because mu uses doubles under the
-# hood, which wrap around at a different limit.
-recipe hash x:address:shared:array:character -> n:number [
-  local-scope
-  load-ingredients
-  n <- copy 0
-  len:number <- length *x
-  i:number <- copy 0
-  {
-    done?:boolean <- greater-or-equal i, len
-    break-if done?
-    c:character <- index *x, i
-    n <- add n, c
-    tmp1:number <- shift-left n, 10
-    n <- add n, tmp1
-    tmp2:number <- shift-right n, 6
-    n <- xor-bits n, tmp2
-    tmp3:number <- shift-left n, 3
-    n <- add n, tmp3
-    tmp4:number <- shift-right n, 11
-    n <- xor-bits n, tmp4
-    tmp5:number <- shift-left n, 15
-    n <- add n, tmp5
-    i <- add i, 1
-    loop
-  }
-]