/* Exactness test for the integer-dot kernels: dot_i8i8 and dot_i4i8 must return * EXACTLY the same value as a plain-C reference, whatever SIMD path was compiled * in (avx512-vnni / avx2 / neon / vsx / scalar). Integer arithmetic has no * rounding, so any mismatch is a kernel bug, not noise. * * Covers: odd sizes (scalar tail), sizes below one vector, the w=-128 edge * (sign-trick kernels must treat |−128| as 128 unsigned, not saturate to 127), * and random data at qrow_i8's contract (|x| <= 127, w full int8 range). */ #define main coli_glm_main_unused #include "../glm.c" #undef main static uint32_t rng_state=0x12345678u; static uint32_t xr(void){ rng_state^=rng_state<<13; rng_state^=rng_state>>17; rng_state^=rng_state<<5; return rng_state; } static int32_t ref_i8i8(const int8_t *w, const int8_t *x, int I){ int64_t s=0; for(int i=0;i>1]; int v=(i&1)?((int)(b>>4)-8):((int)(b&0xF)-8); s+=v*x[i]; } return (int32_t)s; } /* Driver-level exactness: matmul_qt_ex on the IDOT path (allow_idot=1) must match * a plain-C reference bit-for-bit. This exercises the SMMLA 2x2-tile drivers on the * ARCH=native (i8mm) build and the SDOT drivers on the default build. The integer * dot is exact and qrow_i8 is the shared quantizer, so any float bit mismatch is a * driver bug (lane map, tiling, tail, or scale order), not rounding. */ static void fill_qt(QT *w, int fmt, int O, int I){ memset(w,0,sizeof *w); w->fmt=fmt; w->O=O; w->I=I; w->s=malloc((size_t)O*sizeof(float)); for(int o=0;os[o]=0.001f+(float)(xr()%1000)*1e-6f; if(fmt==1){ w->q8=malloc((size_t)O*I); for(int64_t i=0;i<(int64_t)O*I;i++) w->q8[i]=(int8_t)((int)(xr()%256)-128); }else{ size_t nb=(size_t)O*((I+1)/2); w->q4=malloc(nb); for(size_t i=0;iq4[i]=(uint8_t)(xr()&0xFF); } } static int check_driver(int fmt,int O,int I,int S){ QT w; fill_qt(&w,fmt,O,I); int rb=(I+1)/2; float *x=malloc((size_t)S*I*sizeof(float)); float *y=malloc((size_t)S*O*sizeof(float)); float *yref=malloc((size_t)S*O*sizeof(float)); int8_t *xqr=malloc((size_t)S*I); float *sxr=malloc((size_t)S*sizeof(float)); for(int64_t i=0;i<(int64_t)S*I;i++) x[i]=((float)(xr()%4001)-2000.f)/500.f; matmul_qt_ex(y,x,&w,S,1); for(int s=0;s