about summary refs log tree commit diff stats
path: root/077hash.cc
diff options
context:
space:
mode:
Diffstat (limited to '077hash.cc')
-rw-r--r--077hash.cc36
1 files changed, 36 insertions, 0 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;
+}