文字列リテラルのmurmurhashを即値にする
http://murmurhash.googlepages.com/
enum{ hash_m = 0x5bd1e995, hash_seed = 0xdeadbeef, hash_r = 24 }; template <int N> inline uint_t hashv(const char (&data)[N], uint_t h){ uint_t k = data[0]; k |= data[1] << 8; k |= data[2] << 16; k |= data[3] << 24; k *= hash_m; k ^= k >> hash_r; k *= hash_m; h *= hash_m; h ^= k; return hashv(reinterpret_cast<const char (&)[N-4]>(data[4]), h); } template<> inline uint_t hashv<4>(const char (&data)[4], uint_t h){ return (h ^ (data[2]<<16) ^ (data[1]<<8) ^ data[0])*hash_m; } template<> inline uint_t hashv<3>(const char (&data)[3], uint_t h){ return (h ^ (data[1]<<8) ^ data[0])*hash_m; } template<> inline uint_t hashv<2>(const char (&data)[2], uint_t h){ return (h ^ data[0])*hash_m; } template<> inline uint_t hashv<1>(const char (&data)[1], uint_t h){ return h; } template <int N> inline uint_t hash(const char (&data)[N]){ uint_t h = hashv(data, hash_seed ^ (N-1)); h ^= h >> 13; h *= hash_m; h ^= h >> 15; return h; } int main(){ uint_t n = hash("TEST"); printf("%d", n); }
VC EE 2008では即値になったようでした。
でも、コンパイラによっては、または長すぎる文字列だと即値にならないかも?
Xidを効率よくしたい
Xidというマクロは、簡単に書くと次のようになっています。
#define Xid(ident) intern(#ident, sizeof(#ident)) IDPtr intern(const char* str, int size){ strのハッシュを計算して、インターン済み文字列が格納されているハッシュテーブルを引いて、 存在したらそれを返し、存在しなければインターン済み文字列を生成して、 ハッシュテーブルに格納して、それを返す。 }
これをもっと効率よく書けないかと、頭をしぼってます。
自分のC++の知識を総動員して考えたのですが、うまい案が思いつきません。
Xid(var)が0始まりの、ユニークな整数値を返すようなマクロが書ければいいんですけども。
extern vector<IDPtr> id_list; #define Xid(ident) id_list[TO_INT(ident)]
と書けるように。
1.0.1.1
uninitialize時に、StringSpaceが持っている配列の開放時に停止する不具合を修正しました。
google group
なんか返信しても反映されない…。なんでだろう?
- -
再定義の件は、以前修正いたしました。
スレッドの件ですが、
現在スレッド切り替えは、
Xtalの仮想命令の無条件ジャンプのときに検討するようになっているのですが、
示されたコードだと、無条件ジャンプが発生しないのでそのようになってしまったようです。
スレッド切り替えの機会を増やそうと思います。
トップレベルの仕様変更
関数定義とクラス定義だけは、filelocalをつけなくとも、自動的にfilelocalにも同時に定義されるように、
そして、トップレベルの最後では自動的にfilelocalがリターンされる仕様にしました。
よって、次のように記述することができるようになります。
// aaa.xtal class Foo{ } fun boo(){ }
// bbb.xtal aaa: lib::aaa; foo: aaa::Foo(); aaa::boo();