Compass values: 6 7 8 3 4 5 0 1 2 */
| 126 | 0 1 2 |
| 127 | */ |
| 128 | Coord Polar::asCoord() const |
| 129 | { |
| 130 | // (Thanks to @Asa-Hopkins for this optimized function -- drm) |
| 131 | |
| 132 | // 3037000500 is 1/sqrt(2) in 32.32 fixed point |
| 133 | constexpr int64_t coordMags[9] = { |
| 134 | 3037000500, // SW |
| 135 | 1LL << 32, // S |
| 136 | 3037000500, // SE |
| 137 | 1LL << 32, // W |
| 138 | 0, // CENTER |
| 139 | 1LL << 32, // E |
| 140 | 3037000500, // NW |
| 141 | 1LL << 32, // N |
| 142 | 3037000500 // NE |
| 143 | }; |
| 144 | |
| 145 | int64_t len = coordMags[dir.asInt()] * mag; |
| 146 | |
| 147 | // We need correct rounding, the idea here is to add/sub 1/2 (in fixed point) |
| 148 | // and truncate. We extend the sign of the magnitude with a cast, |
| 149 | // then shift those bits into the lower half, giving 0 for mag >= 0 and |
| 150 | // -1 for mag<0. An XOR with this copies the sign onto 1/2, to be exact |
| 151 | // we'd then also subtract it, but we don't need to be that precise. |
| 152 | |
| 153 | int64_t temp = ((int64_t)mag >> 32) ^ ((1LL << 31) - 1); |
| 154 | len = (len + temp) / (1LL << 32); // Divide to make sure we get an arithmetic shift |
| 155 | |
| 156 | return NormalizedCoords[dir.asInt()] * len; |
| 157 | } |
| 158 | |
| 159 | |
| 160 | // returns -1.0 (opposite directions) .. +1.0 (same direction) |