Arduboyで狙い撃つぜ!(atan2テーブルの作り方) その13
前回のコードを参考に、過去のコードを高速化した。
元のコード
raohu69.hatenablog.jp
const uint8_t atanTbl[] PROGMEM = { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, }; uint8_t getAtan2(float y, float x) { int8_t idx = 0; // 0度 if (x == 0.f && y == 0.f) return idx; // 同じ位置の時は0度とみなす float ax = abs(x); float ay = abs(y); if (ax > ay) { uint8_t ratio = ay / ax * 64; idx = pgm_read_byte(atanTbl + ratio); } else { uint8_t ratio = ax / ay * 64; idx = 16 - pgm_read_byte(atanTbl + ratio); } // idxは第1象限の値なので、実際の象限の値に調整する if (x < 0) idx = 32 - idx; if (y < 0) idx = 64 - idx; return idx; }
高速化したコード
const uint8_t atanTbl[] PROGMEM = { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, }; const int8_t atanOffset[] PROGMEM = { 0, 32, 0, 32, }; uint8_t getAtan2(float y, float x) { uint8_t idx = 0; // 0度 if (x == 0.f && y == 0.f) return idx; // 同じ位置の時は0度とみなす uint8_t offset = 0; if (x < 0.f) { x = -x; offset |= 1; } if (y < 0.f) { y = -y; offset |= 2; } if (x > y) { uint8_t ratio = y / x * 64; idx = pgm_read_byte(atanTbl + ratio); } else { uint8_t ratio = x / y * 64; idx = 16 - pgm_read_byte(atanTbl + ratio); } if (((offset + 1) & 2) != 0) { idx = -idx; } return idx + pgm_read_byte(atanOffset + offset); }
過去のコードでは象限を求めるためにif文が2回必要だったが、1回で済ますことができた。