| 232 | } |
| 233 | |
| 234 | static bool test_sinusoidal_pe(const std::string & ref_dir) { |
| 235 | fprintf(stderr, "\n=== Test: Sinusoidal PE ===\n"); |
| 236 | |
| 237 | struct { int H; int W; const char * name; } cases[] = { |
| 238 | {288, 288, "pe_288"}, |
| 239 | {144, 144, "pe_144"}, |
| 240 | { 72, 72, "pe_72"}, |
| 241 | { 36, 36, "pe_36"}, |
| 242 | }; |
| 243 | |
| 244 | for (auto & tc : cases) { |
| 245 | auto ref = load_ref(ref_dir + "/" + tc.name); |
| 246 | if (ref.data.empty()) continue; |
| 247 | |
| 248 | // Compute our sinusoidal PE |
| 249 | const int H = tc.H, W = tc.W, d_model = 256; |
| 250 | const int half = d_model / 2; |
| 251 | const float scale = 2.0f * (float)M_PI; |
| 252 | const float temperature = 10000.0f; |
| 253 | |
| 254 | // ref is [1, 256, H, W] in NCHW from PyTorch |
| 255 | std::vector<float> our_pe(d_model * H * W); |
| 256 | |
| 257 | for (int y = 0; y < H; ++y) { |
| 258 | for (int x = 0; x < W; ++x) { |
| 259 | float pos_y = ((float)(y + 1) / (float)(H)) * scale; |
| 260 | float pos_x = ((float)(x + 1) / (float)(W)) * scale; |
| 261 | |
| 262 | for (int i = 0; i < half; ++i) { |
| 263 | float dim_t = powf(temperature, 2.0f * (float)(i / 2) / (float)half); |
| 264 | |
| 265 | float val_x, val_y; |
| 266 | if (i % 2 == 0) { |
| 267 | val_x = sinf(pos_x / dim_t); |
| 268 | val_y = sinf(pos_y / dim_t); |
| 269 | } else { |
| 270 | val_x = cosf(pos_x / dim_t); |
| 271 | val_y = cosf(pos_y / dim_t); |
| 272 | } |
| 273 | |
| 274 | // PyTorch output is [1, 256, H, W] = [N, C, H, W] |
| 275 | // Channel layout: first half is pos_y, second half is pos_x |
| 276 | // Index: [0, c, y, x] → c * H * W + y * W + x |
| 277 | our_pe[i * H * W + y * W + x] = val_y; |
| 278 | our_pe[(i + half) * H * W + y * W + x] = val_x; |
| 279 | } |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | float max_diff = compare_tensors(our_pe.data(), ref.data.data(), d_model * H * W); |
| 284 | bool ok = max_diff < 1e-5f; |
| 285 | fprintf(stderr, " %s %s (%dx%d): max_diff=%.6e\n", |
| 286 | ok ? "[PASS]" : "[FAIL]", tc.name, tc.H, tc.W, max_diff); |
| 287 | } |
| 288 | |
| 289 | return true; |
| 290 | } |
| 291 |
no test coverage detected