キャラクタの回転
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 まるまる交換して、変数を入れる順番も交換する。