diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-02-15 15:28:28 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-02-15 15:28:28 -0800 |
commit | d5fe534d12d30395def6da176149177778017fe1 (patch) | |
tree | 00a04d585f31088a9167ddcbc3cd102d3484b265 | |
parent | 4637d58f6c4777f9643f73de859af23c38acca2c (diff) | |
download | mu-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.cc | 36 | ||||
-rw-r--r-- | 077hash.mu | 28 |
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 - } -] |