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
16 changes: 16 additions & 0 deletions tests/blas/include/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ MunitResult test_saxpy_neg_stride(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_saxpy_rounding(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_sasum_zero(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_sdot_zero(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_snrm2_zero(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_saxpy_zero(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_scopy_zero(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_sscal_zero(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_saxpy_rounding_modes(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_qasum_layout(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_scopy_all(const MunitParameter params[],
void* user_data_or_fixture);
MunitResult test_scopy_stride(const MunitParameter params[],
Expand Down
16 changes: 16 additions & 0 deletions tests/blas/level1/test_qasum.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,19 @@ MunitResult test_qasum_negpi(const MunitParameter params[],
free(QX);
return MUNIT_OK;
}

// Pins the float128_t storage layout every q* test depends on: the sign and
// exponent live in the high word v[1]; v[0] is the low mantissa word.
MunitResult test_qasum_layout(const MunitParameter params[],
void* user_data_or_fixture) {
// 1.0 in IEEE binary128, written {lo, hi}.
float128_t one = {{ 0x0000000000000000, 0x3fff000000000000 }};
assert_ullong(one.v[0], ==, 0x0000000000000000); // low mantissa word
assert_ullong(one.v[1], ==, 0x3fff000000000000); // sign+exponent word

// A routine that reads the pair agrees: |1.0| == 1.0, bit-for-bit.
float128_t r = qasum(1, &one, 1, 'n');
assert_ullong(r.v[1], ==, 0x3fff000000000000);
assert_ullong(r.v[0], ==, 0x0000000000000000);
return MUNIT_OK;
}
10 changes: 10 additions & 0 deletions tests/blas/level1/test_sasum.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,13 @@ MunitResult test_sasum_stride(const MunitParameter params[],

return MUNIT_OK;
}

// N==0 is a no-op: returns 0, reads nothing.
MunitResult test_sasum_zero(const MunitParameter params[],
void* user_data_or_fixture) {
float32_t* SX = svec((float[]){42.0f}, 1);
float32_t r = sasum(0, SX, 1, 'n');
assert_ulong(r.v, ==, (uint32_t)SB_REAL32_ZERO);
free(SX);
return MUNIT_OK;
}
49 changes: 49 additions & 0 deletions tests/blas/level1/test_saxpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,52 @@ MunitResult test_saxpy_rounding(const MunitParameter params[],
free(SXu); free(SYu); free(SXn); free(SYn);
return MUNIT_OK;
}

// Exercises all five rounding modes on a positive and a negative half-ULP
// tie (1.0 +/- 2^-24 via saxpy). Distinguishes every mode: round-up vs
// round-down differ by sign, round-toward-zero vs round-down differ on the
// negative operand, and 'a' (ties-away) rounds outward on both ties while
// 'n' (ties-even) stays (1.0 has an even mantissa).
MunitResult test_saxpy_rounding_modes(const MunitParameter params[],
void* user_data_or_fixture) {
const float32_t SA = { SB_REAL32_ONE };
const float eps = 5.9604644775390625e-8f; // 2^-24
const uint32_t ONE = 0x3f800000, UP = 0x3f800001; // 1.0, next-above
const uint32_t NEG_ONE = 0xbf800000, NEG_UP = 0xbf800001; // -1.0, next-below

// positive tie: 1.0 + 2^-24
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[]){eps}, 1);
float32_t* Y = svec((float[]){1.0f}, 1);
saxpy(1, SA, X, 1, Y, 1, pos[k].m);
assert_ulong(Y[0].v, ==, pos[k].want);
free(X); free(Y);
}

// negative tie: -1.0 - 2^-24
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[]){-eps}, 1);
float32_t* Y = svec((float[]){-1.0f}, 1);
saxpy(1, SA, X, 1, Y, 1, neg[k].m);
assert_ulong(Y[0].v, ==, neg[k].want);
free(X); free(Y);
}
return MUNIT_OK;
}

// N==0 is a no-op: Y is left untouched.
MunitResult test_saxpy_zero(const MunitParameter params[],
void* user_data_or_fixture) {
const float32_t SA = { SB_REAL32_ONE };
float32_t* SX = svec((float[]){42.0f}, 1);
float32_t* SY = svec((float[]){7.0f}, 1);
saxpy(0, SA, SX, 1, SY, 1, 'n');
float32_t* RY = svec((float[]){7.0f}, 1);
assert_ulong(SY[0].v, ==, RY[0].v);
free(SX); free(SY); free(RY);
return MUNIT_OK;
}
12 changes: 12 additions & 0 deletions tests/blas/level1/test_scopy.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,15 @@ MunitResult test_scopy_stride(const MunitParameter params[],

return MUNIT_OK;
}

// N==0 is a no-op: Y is left untouched.
MunitResult test_scopy_zero(const MunitParameter params[],
void* user_data_or_fixture) {
float32_t* SX = svec((float[]){42.0f}, 1);
float32_t* SY = svec((float[]){7.0f}, 1);
scopy(0, SX, 1, SY, 1, 'n');
float32_t* RY = svec((float[]){7.0f}, 1);
assert_ulong(SY[0].v, ==, RY[0].v);
free(SX); free(SY); free(RY);
return MUNIT_OK;
}
11 changes: 11 additions & 0 deletions tests/blas/level1/test_sdot.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,14 @@ MunitResult test_sdot_neg_stride(const MunitParameter params[],

return MUNIT_OK;
}

// N==0 is a no-op: returns 0.
MunitResult test_sdot_zero(const MunitParameter params[],
void* user_data_or_fixture) {
float32_t* SX = svec((float[]){42.0f}, 1);
float32_t* SY = svec((float[]){7.0f}, 1);
float32_t r = sdot(0, SX, 1, SY, 1, 'n');
assert_ulong(r.v, ==, (uint32_t)SB_REAL32_ZERO);
free(SX); free(SY);
return MUNIT_OK;
}
10 changes: 10 additions & 0 deletions tests/blas/level1/test_snrm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,13 @@ MunitResult test_snrm2_stride(const MunitParameter params[],

return MUNIT_OK;
}

// N==0 is a no-op: returns 0.
MunitResult test_snrm2_zero(const MunitParameter params[],
void* user_data_or_fixture) {
float32_t* SX = svec((float[]){42.0f}, 1);
float32_t r = snrm2(0, SX, 1, 'n');
assert_ulong(r.v, ==, (uint32_t)SB_REAL32_ZERO);
free(SX);
return MUNIT_OK;
}
12 changes: 12 additions & 0 deletions tests/blas/level1/test_sscal.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,15 @@ MunitResult test_sscal_stride(const MunitParameter params[],

return MUNIT_OK;
}

// N==0 is a no-op: X is left untouched.
MunitResult test_sscal_zero(const MunitParameter params[],
void* user_data_or_fixture) {
const float32_t SA = { SB_REAL32_ZERO };
float32_t* SX = svec((float[]){42.0f}, 1);
sscal(0, SA, SX, 1, 'n');
float32_t* RX = svec((float[]){42.0f}, 1);
assert_ulong(SX[0].v, ==, RX[0].v);
free(SX); free(RX);
return MUNIT_OK;
}
8 changes: 8 additions & 0 deletions tests/test_all.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
{"/test_saxpy_stride", test_saxpy_stride, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_saxpy_neg_stride", test_saxpy_neg_stride, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_saxpy_rounding", test_saxpy_rounding, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_sasum_zero", test_sasum_zero, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_sdot_zero", test_sdot_zero, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_snrm2_zero", test_snrm2_zero, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_saxpy_zero", test_saxpy_zero, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/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_qasum_layout", test_qasum_layout, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_scopy_all", test_scopy_all, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_scopy_stride", test_scopy_stride, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/test_sdot_0", test_sdot_0, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
Expand Down
Loading