Skip to content

Commit 1d4bee2

Browse files
committed
applying reviews
1 parent 784a75f commit 1d4bee2

2 files changed

Lines changed: 45 additions & 6 deletions

File tree

src/csrc/quadblas_interface.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ qblas_gemv(char layout, char trans, size_t m, size_t n,
6161
}
6262
return 0;
6363
}
64-
if (!alpha || !A || !x || !beta || !y) {
64+
if (!alpha || !A || !x || !y) {
6565
return -1;
6666
}
6767
cblas_qgemv(to_layout(layout), to_trans(trans),

tests/test_dot.py

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,16 +1058,14 @@ def _layout(a, kind):
10581058
return np.ascontiguousarray(a)
10591059
if kind == "F":
10601060
return np.asfortranarray(a)
1061-
if kind == "T":
1062-
return np.ascontiguousarray(a.T).T
10631061
if kind == "S":
10641062
big = np.zeros((a.shape[0] * 2, a.shape[1] * 2), dtype=a.dtype)
10651063
big[::2, ::2] = a
10661064
return big[::2, ::2]
10671065
raise ValueError(kind)
10681066

1069-
@pytest.mark.parametrize("a_kind", ["C", "F", "T", "S"])
1070-
@pytest.mark.parametrize("b_kind", ["C", "F", "T", "S"])
1067+
@pytest.mark.parametrize("a_kind", ["C", "F", "S"])
1068+
@pytest.mark.parametrize("b_kind", ["C", "F", "S"])
10711069
def test_gemm_all_layout_combinations(self, a_kind, b_kind):
10721070
rng = np.random.default_rng(seed=100)
10731071
A_f = rng.standard_normal((4, 3))
@@ -1076,6 +1074,16 @@ def test_gemm_all_layout_combinations(self, a_kind, b_kind):
10761074
B_q = self._layout(_qnd(B_f), b_kind)
10771075
_assert_matmul_matches_float64(A_q, B_q, A_f, B_f)
10781076

1077+
def test_transposed_view_operands(self):
1078+
"""Genuine transposed views (``a.T``) are zero-copy views that share
1079+
memory with the source array, unlike the F-order *copies* produced by
1080+
``np.asfortranarray``. They exercise the transa/transb BLAS dispatch on
1081+
col-major views."""
1082+
rng = np.random.default_rng(seed=104)
1083+
A_f = rng.standard_normal((3, 4))
1084+
B_f = rng.standard_normal((5, 3))
1085+
_assert_matmul_matches_float64(_qnd(A_f).T, _qnd(B_f).T, A_f.T, B_f.T)
1086+
10791087
@pytest.mark.parametrize("out_kind", ["C", "F"])
10801088
def test_gemm_output_layout(self, out_kind):
10811089
rng = np.random.default_rng(seed=101)
@@ -1091,7 +1099,7 @@ def test_gemm_output_layout(self, out_kind):
10911099
for j in range(5):
10921100
assert abs(float(out[i, j]) - ref[i, j]) <= 1e-13 + 1e-13 * max(abs(ref[i, j]), 1.0)
10931101

1094-
@pytest.mark.parametrize("a_kind", ["C", "F", "T", "S"])
1102+
@pytest.mark.parametrize("a_kind", ["C", "F", "S"])
10951103
def test_gemv_all_layouts(self, a_kind):
10961104
rng = np.random.default_rng(seed=102)
10971105
A_f = rng.standard_normal((5, 4))
@@ -1117,6 +1125,16 @@ def test_empty_core_dims_match_float64(self, A_shape, B_shape):
11171125
B_f = np.ones(B_shape)
11181126
_assert_matmul_matches_float64(_qnd(A_f), _qnd(B_f), A_f, B_f)
11191127

1128+
def test_matmul_zero_contracted_dim(self):
1129+
"""Contracted dimension of zero: ``(m, 0) @ (0, n)`` is the all-zeros
1130+
``(m, n)`` matrix (empty sum). Matches NumPy/float64."""
1131+
A_f = np.zeros((4, 0))
1132+
B_f = np.zeros((0, 5))
1133+
got = np.matmul(_qnd(A_f), _qnd(B_f))
1134+
assert got.shape == (4, 5)
1135+
assert np.all(got.astype(np.float64) == 0.0)
1136+
_assert_matmul_matches_float64(_qnd(A_f), _qnd(B_f), A_f, B_f)
1137+
11201138

11211139
class TestMatmulCopyPath:
11221140
"""Issue #89 Tier 2: layouts that are not directly BLAS-able (fully strided,
@@ -1137,6 +1155,13 @@ def test_negative_stride_input(self):
11371155
B_f = rng.standard_normal((5, 7))
11381156
_assert_matmul_matches_float64(_qnd(A_f)[::-1], _qnd(B_f), A_f[::-1], B_f)
11391157

1158+
def test_negative_column_stride_input(self):
1159+
rng = np.random.default_rng(seed=205)
1160+
A_f = rng.standard_normal((6, 5))
1161+
B_f = rng.standard_normal((5, 7))
1162+
_assert_matmul_matches_float64(_qnd(A_f)[:, ::-1], _qnd(B_f),
1163+
A_f[:, ::-1], B_f)
1164+
11401165
def test_strided_A_fortran_B_fortran_out_three_temps(self):
11411166
rng = np.random.default_rng(seed=202)
11421167
A_f = rng.standard_normal((20, 7))
@@ -1160,3 +1185,17 @@ def test_gemv_negative_stride_vector(self):
11601185
A_f = rng.standard_normal((5, 6))
11611186
x_f = rng.standard_normal((6,))
11621187
_assert_matmul_matches_float64(_qnd(A_f), _qnd(x_f)[::-1], A_f, x_f[::-1])
1188+
1189+
def test_strided_out_vector(self):
1190+
"""Strided output buffer for the gemv path: ``out`` has a column stride
1191+
of two elements, so QBLAS must honour ``incy`` (or the scatter fallback)
1192+
when writing results back."""
1193+
rng = np.random.default_rng(seed=206)
1194+
A_f = rng.standard_normal((7, 5))
1195+
x_f = rng.standard_normal((5,))
1196+
out = np.empty(14, dtype=QuadPrecDType())[::2]
1197+
np.matmul(_qnd(A_f), _qnd(x_f), out=out)
1198+
ref = A_f @ x_f
1199+
assert out.shape == (7,)
1200+
for i in range(7):
1201+
assert abs(float(out[i]) - ref[i]) <= 1e-13 + 1e-13 * max(abs(ref[i]), 1.0)

0 commit comments

Comments
 (0)