文字列リテラルの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)]

と書けるように。

google group

なんか返信しても反映されない…。なんでだろう?

  • -

再定義の件は、以前修正いたしました。

スレッドの件ですが、
現在スレッド切り替えは、
Xtalの仮想命令の無条件ジャンプのときに検討するようになっているのですが、
示されたコードだと、無条件ジャンプが発生しないのでそのようになってしまったようです。

スレッド切り替えの機会を増やそうと思います。

バインドの仕様変更

C++のクラスをバインドした場合、自動的にcppという名前空間に登録される仕様にしました。
C++のクラスを楽に参照することができます。

// main.cpp

struct Vector{
  float x, y;
};

XTAL_PREBIND(Foo){
  it->def_ctor0<Foo>();
}

XTAL_BIND(Foo){
  it->def_var("x", &Foo::x);
  it->def_var("y", &Foo::y);
}
// test.xtal

foo: cpp::Foo();
foo.x = 10;

トップレベルの仕様変更

関数定義とクラス定義だけは、filelocalをつけなくとも、自動的にfilelocalにも同時に定義されるように、
そして、トップレベルの最後では自動的にfilelocalがリターンされる仕様にしました。
よって、次のように記述することができるようになります。

// aaa.xtal

class Foo{

}

fun boo(){

}
// bbb.xtal

aaa: lib::aaa;

foo: aaa::Foo();

aaa::boo();