キャラクタの回転

8x8 dot の文字を回転する処理を動的にやる場合に必要で、1bit ずつ rotate や and をやりまくってたんだが、書籍「ハッカーのたのしみ」に使えそうなのを見つけたので記載。

begin
	a = 0b1111_1110 << 24
	a|= 0b1110_0000 << 16
	a|= 0b1110_0000 << 8
	a|= 0b1111_1100
	b = 0b1110_0000 << 24
	b|= 0b1110_0000 << 16
	b|= 0b1110_0000 << 8
	b|= 0
	
	t = transpose(a, b)
	x = t.shift
	y = t.shift
	ar = []
	ar << a
	ar << b
	ar << bitreverse_byte(x)
	ar << bitreverse_byte(y)
	ar << bitreverse_byte(bytereverse(b))
	ar << bitreverse_byte(bytereverse(a))
	ar << bytereverse(y)
	ar << bytereverse(x)
	f = File.open('t', 'wb')
	f.write(ar.pack('N*'))
	f.close
end

a, b が F の文字のキャラを 32bit ずつ持ったもの。a が上半分8x4 dot, b が下半分。文字は最初は A にしてたのだが、左右対称のため、問題を見つけるのに手間取った。もちろん上下対称(BCDE)も駄目。

まず転置を行う。これは書籍のまんま。何やってるかわかんないがそうなる。

def transpose(x, y)
	t = (x ^ (x >> 7)) & 0x00aa00aa
	x = x ^ t ^ (t << 7);
	t = (y ^ (y >> 7)) & 0x00aa00aa
	y = y ^ t ^ (t << 7);
	
	t = (x ^ (x >> 14)) & 0x0000cccc
	x = x ^ t ^ (t << 14)
	t = (y ^ (y >> 14)) & 0x0000cccc
	y = y ^ t ^ (t << 14)
	
	t = (x & 0xf0f0f0f0) | ((y >> 4) & 0x0f0f0f0f)
	y = ((x << 4) & 0xf0f0f0f0) | (y & 0x0f0f0f0f)
	x = t

	return [x, y]
end

270度回転

横に flip をかける必要がある。横に、というのは 8bit 単位で 01234567 を 76543210 にする。この処理は本に書いてあった 32bit 全て反転する処理を途中でやらなければできる、ということは自分でもわかった。

def bitreverse_byte(t)
	t = (t & 0x5555_5555) << 1 | (t & 0xaaaa_aaaa) >> 1
	t = (t & 0x3333_3333) << 2 | (t & 0xcccc_cccc) >> 2
	t = (t & 0x0f0f_0f0f) << 4 | (t & 0xf0f0_f0f0) >> 4
	return t
end

90度回転

縦に flip をかける。言葉が紛らわしいが、1byte の中の bit の並びはそのままで、 01234567 という byte の並びを 76543210 にする。前述で打ち切った処理を書けばよい。

def bytereverse(t)
	t = (t & 0x00ff_00ff) << 8 | (t & 0xff00_ff00) >> 8
	t = (t & 0x0000_ffff) <<16 | (t & 0xffff_0000) >> 16
	return t
end

この method では 32bit の並びを替えるだけなので、変数を入れる順番を交換しないといけない。

180度回転

転置は不要。32bit まるまる交換して、変数を入れる順番も交換する。

結果

処理が早い。この本、すごいんだけど高い上に使いどころがわからないので実用できたのがよかったよ。