/* * Tests the H.264 chroma DC 2x2 Hadamard primitive against * spec-derived expected outputs. * * f[0,0] = c[0,0] + c[0,1] + c[1,0] + c[1,1] "sum" * f[0,1] = c[0,0] - c[0,1] + c[1,0] - c[1,1] "col-diff" * f[1,0] = c[0,0] + c[0,1] - c[1,0] - c[1,1] "row-diff" * f[1,1] = c[0,0] - c[0,1] - c[1,0] + c[1,1] "anti-diag" */ #include #include #include extern void daedalus_h264_chroma_dc_hadamard_2x2_ref(int16_t c[4]); extern void daedalus_h264_chroma_dc_hadamard_2x2(int16_t c[4]); /* public API */ static int check(const char *name, int16_t in[4], int16_t expect[4]) { int16_t c[4]; memcpy(c, in, sizeof(c)); daedalus_h264_chroma_dc_hadamard_2x2_ref(c); int fail = 0; for (int i = 0; i < 4; i++) { if (c[i] != expect[i]) { fprintf(stderr, "%s: c[%d] = %d, expected %d\n", name, i, c[i], expect[i]); fail = 1; } } if (!fail) printf(" %-32s PASS\n", name); else printf(" %-32s FAIL\n", name); return fail; } int main(void) { int fail = 0; /* Test 1: All-same input. * c = [5, 5, 5, 5] * f[0,0] = 20, f[0,1] = 0, f[1,0] = 0, f[1,1] = 0 */ { int16_t in[4] = { 5, 5, 5, 5 }; int16_t ex[4] = { 20, 0, 0, 0 }; fail |= check("all-uniform 5", in, ex); } /* Test 2: Single-axis variation (col 1 = 0, col 2 = 10). * c = [0, 10, 0, 10] * f[0,0] = 0+10+0+10 = 20 * f[0,1] = 0-10+0-10 = -20 * f[1,0] = 0+10-0-10 = 0 * f[1,1] = 0-10-0+10 = 0 */ { int16_t in[4] = { 0, 10, 0, 10 }; int16_t ex[4] = { 20, -20, 0, 0 }; fail |= check("col gradient [0,10,0,10]", in, ex); } /* Test 3: Row gradient. * c = [0, 0, 10, 10] * f[0,0] = 20, f[0,1] = 0, f[1,0] = 0-20 = -20, f[1,1] = 0 */ { int16_t in[4] = { 0, 0, 10, 10 }; int16_t ex[4] = { 20, 0, -20, 0 }; fail |= check("row gradient [0,0,10,10]", in, ex); } /* Test 4: Anti-diagonal pattern. * c = [10, 0, 0, 10] * f[0,0] = 20 * f[0,1] = 10-0+0-10 = 0 * f[1,0] = 10+0-0-10 = 0 * f[1,1] = 10-0-0+10 = 20 */ { int16_t in[4] = { 10, 0, 0, 10 }; int16_t ex[4] = { 20, 0, 0, 20 }; fail |= check("anti-diagonal [10,0,0,10]", in, ex); } /* Test 5: Asymmetric — all bands non-zero. * c = [1, 2, 3, 4] * f[0,0] = 10 * f[0,1] = 1-2+3-4 = -2 * f[1,0] = 1+2-3-4 = -4 * f[1,1] = 1-2-3+4 = 0 */ { int16_t in[4] = { 1, 2, 3, 4 }; int16_t ex[4] = { 10, -2, -4, 0 }; fail |= check("asymmetric [1,2,3,4]", in, ex); } /* Test 6: Negative inputs (Hadamard is linear, so signs preserve). * c = [-5, 5, -5, 5] * f[0,0] = -5+5-5+5 = 0 * f[0,1] = -5-5-5-5 = -20 * f[1,0] = -5+5+5-5 = 0 * f[1,1] = -5-5+5+5 = 0 */ { int16_t in[4] = { -5, 5, -5, 5 }; int16_t ex[4] = { 0, -20, 0, 0 }; fail |= check("sign-alternating [-5,5,-5,5]", in, ex); } /* Test 7: Inverse-property check. H * H = 4*I for the unscaled * 2x2 Hadamard. So applying twice multiplies each by 4. * c = [1, 2, 3, 4] * First Hadamard: [10, -2, -4, 0] * Second Hadamard: [4, 8, 12, 16] */ { int16_t in[4] = { 1, 2, 3, 4 }; int16_t ex[4] = { 4, 8, 12, 16 }; int16_t c[4]; memcpy(c, in, sizeof(c)); daedalus_h264_chroma_dc_hadamard_2x2_ref(c); daedalus_h264_chroma_dc_hadamard_2x2_ref(c); int local_fail = 0; for (int i = 0; i < 4; i++) if (c[i] != ex[i]) local_fail = 1; printf(" %-32s %s\n", "double-Hadamard = 4*orig", local_fail ? "FAIL" : "PASS"); fail |= local_fail; } /* Test 8: public API parity. The public symbol must produce * byte-identical output to the test-only ref for the same input. * If the src/ Hadamard ever drifts from the spec, this catches it. */ { int16_t input[4] = { 7, -11, 23, -42 }; int16_t a[4], b[4]; memcpy(a, input, sizeof(a)); memcpy(b, input, sizeof(b)); daedalus_h264_chroma_dc_hadamard_2x2_ref(a); daedalus_h264_chroma_dc_hadamard_2x2(b); int local_fail = 0; for (int i = 0; i < 4; i++) if (a[i] != b[i]) local_fail = 1; printf(" %-32s %s\n", "public API parity vs _ref", local_fail ? "FAIL" : "PASS"); fail |= local_fail; } if (fail == 0) printf("\nALL chroma DC Hadamard tests PASS\n"); else fprintf(stderr, "\n%d test(s) FAILED\n", fail); return fail ? 1 : 0; }