Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ Severity: 🔴 critical (memory-unsafe / silently wrong) · 🟠 high · 🟡 me
- [ ] **C4.** gemv/gemm transpose paths (`Trans='T'`; `transA×transB ∈ {N,T}²`),
non-square.
- [ ] **C5.** `ldb≠ldc` / padded `lda` for `h/q` gemm and all gemv.
- [ ] **C6.** All five rounding modes × ≥2 routines, incl. a negative operand
(now unblocked on macOS after the SIGBUS fix).
- [ ] **C7.** float128 `v[0]=lo / v[1]=hi` layout pin test.
- [x] **C6.** All five rounding modes (`n`/`z`/`u`/`d`/`a`) × `saxpy`/`sdot`/
`ddot`/`sgemv`, both signs (the negative tie distinguishes `z`/`d`/`u`/`a`).
Reduction (L1) + matrix-vector (L2), single + double. Runs on macOS now.
- [x] **C7.** float128 `v[0]=lo / v[1]=hi` layout pinned by `test_qasum_layout`.
- [~] **C8.** Complex/rot routines build + have numeric tests (q-rot family,
cscal/cswap/icamax done). **Remaining:** broaden complex coverage
(strides, NaN payloads) for `caxpy`/`ccopy`/`cdotc`.
Expand Down
4 changes: 4 additions & 0 deletions tests/blas/include/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,10 @@ MunitResult test_sgemm_transA(const MunitParameter params[], void* u);
MunitResult test_sgemm_transB(const MunitParameter params[], void* u);
MunitResult test_hgemm_ldb(const MunitParameter params[], void* u);
MunitResult test_qgemm_ldb(const MunitParameter params[], void* u);
// Rounding-mode coverage (C6): all five modes through a 2nd/3rd routine.
MunitResult test_sdot_rounding_modes(const MunitParameter params[], void* u);
MunitResult test_ddot_rounding_modes(const MunitParameter params[], void* u);
MunitResult test_sgemv_rounding_modes(const MunitParameter params[], void* u);

// Complex Level-1 (test_complex.c)
MunitResult test_caxpy_basic(const MunitParameter params[], void* u);
Expand Down
24 changes: 24 additions & 0 deletions tests/blas/level1/test_ddot.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,29 @@ MunitResult test_ddot_neg_stride(const MunitParameter params[],
free(DX);
free(DY);

return MUNIT_OK;
}

// C6: all five rounding modes, double precision. dot([1, 2^-53],[1, 1]) =
// 1 + 2^-53, an exact tie; the negative case distinguishes z/d/u/a.
MunitResult test_ddot_rounding_modes(const MunitParameter params[], void* u) {
const uint64_t ONE = 0x3ff0000000000000ull, UP = 0x3ff0000000000001ull,
NEG_ONE = 0xbff0000000000000ull, NEG_UP = 0xbff0000000000001ull;
struct { char m; uint64_t want; } pos[] = {
{'n', ONE}, {'z', ONE}, {'d', ONE}, {'u', UP}, {'a', UP} };
for (uint64_t k = 0; k < 5; k++) {
float64_t* X = dvec((double[]){ 1.0, 0x1p-53 }, 2);
float64_t* Y = dvec((double[]){ 1.0, 1.0 }, 2);
assert_ullong(ddot(2, X, 1, Y, 1, pos[k].m).v, ==, pos[k].want);
free(X); free(Y);
}
struct { char m; uint64_t want; } neg[] = {
{'n', NEG_ONE}, {'z', NEG_ONE}, {'u', NEG_ONE}, {'d', NEG_UP}, {'a', NEG_UP} };
for (uint64_t k = 0; k < 5; k++) {
float64_t* X = dvec((double[]){ -1.0, -0x1p-53 }, 2);
float64_t* Y = dvec((double[]){ 1.0, 1.0 }, 2);
assert_ullong(ddot(2, X, 1, Y, 1, neg[k].m).v, ==, neg[k].want);
free(X); free(Y);
}
return MUNIT_OK;
}
24 changes: 24 additions & 0 deletions tests/blas/level1/test_sdot.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,27 @@ MunitResult test_sdot_zero(const MunitParameter params[],
free(SX); free(SY);
return MUNIT_OK;
}

// C6: all five rounding modes through the dot accumulation. dot([1, 2^-24],
// [1, 1]) = 1 + 2^-24, an exact tie; the negative case distinguishes z/d/u/a.
MunitResult test_sdot_rounding_modes(const MunitParameter params[], void* u) {
const uint32_t ONE = 0x3f800000u, UP = 0x3f800001u,
NEG_ONE = 0xbf800000u, NEG_UP = 0xbf800001u;
struct { char m; uint32_t want; } pos[] = {
{'n', ONE}, {'z', ONE}, {'d', ONE}, {'u', UP}, {'a', UP} };
for (uint64_t k = 0; k < 5; k++) {
float32_t* X = svec((float[]){ 1.0f, 0x1p-24f }, 2);
float32_t* Y = svec((float[]){ 1.0f, 1.0f }, 2);
assert_ulong(sdot(2, X, 1, Y, 1, pos[k].m).v, ==, pos[k].want);
free(X); free(Y);
}
struct { char m; uint32_t want; } neg[] = {
{'n', NEG_ONE}, {'z', NEG_ONE}, {'u', NEG_ONE}, {'d', NEG_UP}, {'a', NEG_UP} };
for (uint64_t k = 0; k < 5; k++) {
float32_t* X = svec((float[]){ -1.0f, -0x1p-24f }, 2);
float32_t* Y = svec((float[]){ 1.0f, 1.0f }, 2);
assert_ulong(sdot(2, X, 1, Y, 1, neg[k].m).v, ==, neg[k].want);
free(X); free(Y);
}
return MUNIT_OK;
}
30 changes: 30 additions & 0 deletions tests/blas/level2/test_sgemv.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,33 @@ MunitResult test_sgemv_padlda(const MunitParameter params[], void *user_data) {
free(A); free(X); free(Y); free(RY);
return MUNIT_OK;
}

// C6: all five rounding modes through the gemv dot path. A 1x2 A=[1, 2^-24]
// times x=[1, 1] gives 1 + 2^-24, an exact tie; the negative row distinguishes
// z/d/u/a. (alpha=1, beta=0, so the tie rounding is the result.)
MunitResult test_sgemv_rounding_modes(const MunitParameter params[], void *u) {
const float32_t alpha = { SB_REAL32_ONE }, beta = { SB_REAL32_ZERO };
const uint32_t ONE = 0x3f800000u, UP = 0x3f800001u,
NEG_ONE = 0xbf800000u, NEG_UP = 0xbf800001u;
struct { char m; uint32_t want; } pos[] = {
{'n', ONE}, {'z', ONE}, {'d', ONE}, {'u', UP}, {'a', UP} };
for (uint64_t k = 0; k < 5; k++) {
float32_t* A = svec((float[]){ 1.0f, 0x1p-24f }, 2);
float32_t* X = svec((float[]){ 1.0f, 1.0f }, 2);
float32_t* Y = svec((float[]){ 0.0f }, 1);
sgemv('R', 'N', 1, 2, alpha, A, 2, X, 1, beta, Y, 1, pos[k].m);
assert_ulong(Y[0].v, ==, pos[k].want);
free(A); free(X); free(Y);
}
struct { char m; uint32_t want; } neg[] = {
{'n', NEG_ONE}, {'z', NEG_ONE}, {'u', NEG_ONE}, {'d', NEG_UP}, {'a', NEG_UP} };
for (uint64_t k = 0; k < 5; k++) {
float32_t* A = svec((float[]){ -1.0f, -0x1p-24f }, 2);
float32_t* X = svec((float[]){ 1.0f, 1.0f }, 2);
float32_t* Y = svec((float[]){ 0.0f }, 1);
sgemv('R', 'N', 1, 2, alpha, A, 2, X, 1, beta, Y, 1, neg[k].m);
assert_ulong(Y[0].v, ==, neg[k].want);
free(A); free(X); free(Y);
}
return MUNIT_OK;
}
3 changes: 3 additions & 0 deletions tests/test_all.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
{"/test_scopy_zero", test_scopy_zero, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_sscal_zero", test_sscal_zero, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_saxpy_rounding_modes", test_saxpy_rounding_modes, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_sdot_rounding_modes", test_sdot_rounding_modes, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_ddot_rounding_modes", test_ddot_rounding_modes, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_sgemv_rounding_modes", test_sgemv_rounding_modes, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_qasum_layout", test_qasum_layout, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_saxpy_nan", test_saxpy_nan, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_sdot_nan", test_sdot_nan, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
Expand Down
Loading