From b97048710bda91080eea0cba1b08359b9e49c74b Mon Sep 17 00:00:00 2001 From: Jackson Mowry Date: Thu, 26 Feb 2026 16:11:31 +0000 Subject: [PATCH 1/3] syr2 fixes --- src/testing_utils/testing_utils.mojo | 54 +++++++++++++++++++ test-level2.mojo | 77 ++++++++++++++++++---------- 2 files changed, 104 insertions(+), 27 deletions(-) diff --git a/src/testing_utils/testing_utils.mojo b/src/testing_utils/testing_utils.mojo index 5b97dea..32684f1 100644 --- a/src/testing_utils/testing_utils.mojo +++ b/src/testing_utils/testing_utils.mojo @@ -73,3 +73,57 @@ fn frobenius_norm[dtype: DType]( for i in range(n): sum += a[i] * a[i] return sqrt(sum) + +fn check_syr_error[dtype: DType]( + n: Int, + alpha: Scalar[dtype], + x_norm: Scalar[dtype], + y_norm: Scalar[dtype], + A_ini_norm: Scalar[dtype], + error_norm: Scalar[dtype] +) -> Bool: + + var alpha_ = max(abs(alpha), Scalar[dtype](1)) + + var denom = + Scalar[dtype](2) * alpha_ * x_norm * y_norm + + Scalar[dtype](2) * A_ini_norm + + if denom == Scalar[dtype](0): + return error_norm == Scalar[dtype](0) + + var err = error_norm / denom + + @parameter + if dtype == DType.float32: + return err < Scalar[dtype](tol32) + else: + return err < Scalar[dtype](tol64) + +fn frobenius_norm_symmetric[dtype: DType]( + C: UnsafePointer[Scalar[dtype], MutAnyOrigin], + n: Int, + ldc: Int, + lower: Int # 0 = upper triangle, 1 = lower triangle +) -> Scalar[dtype]: + + var sum = Scalar[dtype](0) + + if lower == 1: + for j in range(n): + for i in range(j, n): + var val = C[i + j*ldc] + if i == j: + sum += val * val + else: + sum += Scalar[dtype](2) * val * val + else: + for j in range(n): + for i in range(j+1): + var val = C[i + j*ldc] + if i == j: + sum += val * val + else: + sum += Scalar[dtype](2) * val * val + + return sqrt(sum) diff --git a/test-level2.mojo b/test-level2.mojo index 4120f62..acc7cb0 100644 --- a/test-level2.mojo +++ b/test-level2.mojo @@ -249,6 +249,10 @@ def syr2_test[ var alpha = generate_random_scalar[dtype](-100, 100) + var norm_A = frobenius_norm_symmetric[dtype](A.unsafe_ptr(), n * n, n, uplo) + var norm_x = frobenius_norm[dtype](x.unsafe_ptr(), n) + var norm_y = frobenius_norm[dtype](y.unsafe_ptr(), n) + blas_syr2[dtype]( uplo, n, @@ -294,37 +298,56 @@ def syr2_test[ sp_flat = sp_res.flatten() with A_d.map_to_host() as res_mojo: + var error = InlineArray[Scalar[dtype], n*n](fill=Scalar[dtype](0)) for i in range(n * n): - assert_almost_equal(res_mojo[i], Scalar[dtype](py=sp_flat[i]), atol=atol) - - -def test_gemv(): - gemv_test[DType.float32, 64, 64, False]() - gemv_test[DType.float32, 64, 64, True]() - gemv_test[DType.float64, 64, 64, False]() - gemv_test[DType.float64, 64, 64, True]() - gemv_test[DType.float32, 1024, 64, False]() - gemv_test[DType.float32, 1024, 64, True]() - gemv_test[DType.float64, 1024, 64, False]() - gemv_test[DType.float64, 1024, 64, True]() - -def test_ger(): - ger_test[DType.float32, 64, 64]() - ger_test[DType.float32, 256, 256]() - ger_test[DType.float64, 64, 64]() - ger_test[DType.float64, 256, 256]() + error[i] = res_mojo[i] - Scalar[dtype](py=sp_flat[i]) + + var error_norm = frobenius_norm_symmetric[dtype]( + error.unsafe_ptr(), + n, + n, + uplo + ) + + var passed = check_syr_error[dtype]( + n, + alpha, + norm_x, + norm_y, + norm_A, + error_norm + ) + + assert_true(passed) + + +# def test_gemv(): +# gemv_test[DType.float32, 64, 64, False]() +# gemv_test[DType.float32, 64, 64, True]() +# gemv_test[DType.float64, 64, 64, False]() +# gemv_test[DType.float64, 64, 64, True]() +# gemv_test[DType.float32, 1024, 64, False]() +# gemv_test[DType.float32, 1024, 64, True]() +# gemv_test[DType.float64, 1024, 64, False]() +# gemv_test[DType.float64, 1024, 64, True]() + +# def test_ger(): +# ger_test[DType.float32, 64, 64]() +# ger_test[DType.float32, 256, 256]() +# ger_test[DType.float64, 64, 64]() +# ger_test[DType.float64, 256, 256]() -def test_syr(): - syr_test[DType.float32, 256, 1]() - syr_test[DType.float32, 1024, 0]() - syr_test[DType.float64, 256, 0]() - syr_test[DType.float64, 1024, 1]() +# def test_syr(): +# syr_test[DType.float32, 256, 1]() +# syr_test[DType.float32, 1024, 0]() +# syr_test[DType.float64, 256, 0]() +# syr_test[DType.float64, 1024, 1]() def test_syr2(): - syr_test[DType.float32, 256, 1]() - syr_test[DType.float32, 1024, 0]() - syr_test[DType.float64, 256, 0]() - syr_test[DType.float64, 1024, 1]() + syr2_test[DType.float32, 256, 1]() + syr2_test[DType.float32, 256, 0]() + syr2_test[DType.float64, 256, 0]() + syr2_test[DType.float64, 256, 1]() def main(): print("--- MojoBLAS Level 2 routines testing ---") From ba3f6c5f2181feba082324b184994518d91b739e Mon Sep 17 00:00:00 2001 From: Jackson Mowry Date: Thu, 26 Feb 2026 16:36:54 +0000 Subject: [PATCH 2/3] Fixed syr2 tests --- src/testing_utils/testing_utils.mojo | 15 ++++++-- test-level2.mojo | 56 ++++++++++++++-------------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/testing_utils/testing_utils.mojo b/src/testing_utils/testing_utils.mojo index 32684f1..44ea985 100644 --- a/src/testing_utils/testing_utils.mojo +++ b/src/testing_utils/testing_utils.mojo @@ -1,8 +1,7 @@ from random import rand, seed from math import sqrt -comptime tol32: Float32 = 1e-8 -comptime tol64: Float64 = 1e-16 +from python import Python def generate_random_arr[ dtype: DType, @@ -47,7 +46,11 @@ fn check_gemm_error[dtype: DType]( B_norm: Scalar[dtype], C_ini_norm: Scalar[dtype], error_norm: Scalar[dtype] -) -> Bool: +) raises -> Bool: + np = Python.import_module("numpy") + tol32 = Scalar[DType.float32](py=np.finfo(np.float32).eps) + tol64 = Scalar[DType.float64](py=np.finfo(np.float64).eps) + var alpha_ = max(abs(alpha), Scalar[dtype](1)) var beta_ = max(abs(beta), Scalar[dtype](1)) var denom = sqrt(Scalar[dtype](k) + Scalar[dtype](2)) * alpha_ * A_norm * B_norm @@ -81,7 +84,10 @@ fn check_syr_error[dtype: DType]( y_norm: Scalar[dtype], A_ini_norm: Scalar[dtype], error_norm: Scalar[dtype] -) -> Bool: +) raises -> Bool: + np = Python.import_module("numpy") + tol32 = Scalar[DType.float32](py=np.finfo(np.float32).eps) + tol64 = Scalar[DType.float64](py=np.finfo(np.float64).eps) var alpha_ = max(abs(alpha), Scalar[dtype](1)) @@ -126,4 +132,5 @@ fn frobenius_norm_symmetric[dtype: DType]( else: sum += Scalar[dtype](2) * val * val + return sqrt(sum) diff --git a/test-level2.mojo b/test-level2.mojo index acc7cb0..8c05889 100644 --- a/test-level2.mojo +++ b/test-level2.mojo @@ -249,7 +249,7 @@ def syr2_test[ var alpha = generate_random_scalar[dtype](-100, 100) - var norm_A = frobenius_norm_symmetric[dtype](A.unsafe_ptr(), n * n, n, uplo) + var norm_A = frobenius_norm[dtype](A.unsafe_ptr(), n * n) var norm_x = frobenius_norm[dtype](x.unsafe_ptr(), n) var norm_y = frobenius_norm[dtype](y.unsafe_ptr(), n) @@ -302,11 +302,9 @@ def syr2_test[ for i in range(n * n): error[i] = res_mojo[i] - Scalar[dtype](py=sp_flat[i]) - var error_norm = frobenius_norm_symmetric[dtype]( + var error_norm = frobenius_norm[dtype]( error.unsafe_ptr(), - n, - n, - uplo + n*n ) var passed = check_syr_error[dtype]( @@ -321,33 +319,33 @@ def syr2_test[ assert_true(passed) -# def test_gemv(): -# gemv_test[DType.float32, 64, 64, False]() -# gemv_test[DType.float32, 64, 64, True]() -# gemv_test[DType.float64, 64, 64, False]() -# gemv_test[DType.float64, 64, 64, True]() -# gemv_test[DType.float32, 1024, 64, False]() -# gemv_test[DType.float32, 1024, 64, True]() -# gemv_test[DType.float64, 1024, 64, False]() -# gemv_test[DType.float64, 1024, 64, True]() - -# def test_ger(): -# ger_test[DType.float32, 64, 64]() -# ger_test[DType.float32, 256, 256]() -# ger_test[DType.float64, 64, 64]() -# ger_test[DType.float64, 256, 256]() +def test_gemv(): + gemv_test[DType.float32, 64, 64, False]() + gemv_test[DType.float32, 64, 64, True]() + gemv_test[DType.float64, 64, 64, False]() + gemv_test[DType.float64, 64, 64, True]() + gemv_test[DType.float32, 1024, 64, False]() + gemv_test[DType.float32, 1024, 64, True]() + gemv_test[DType.float64, 1024, 64, False]() + gemv_test[DType.float64, 1024, 64, True]() + +def test_ger(): + ger_test[DType.float32, 64, 64]() + ger_test[DType.float32, 256, 256]() + ger_test[DType.float64, 64, 64]() + ger_test[DType.float64, 256, 256]() -# def test_syr(): -# syr_test[DType.float32, 256, 1]() -# syr_test[DType.float32, 1024, 0]() -# syr_test[DType.float64, 256, 0]() -# syr_test[DType.float64, 1024, 1]() +def test_syr(): + syr_test[DType.float32, 256, 1]() + syr_test[DType.float32, 1024, 0]() + syr_test[DType.float64, 256, 0]() + syr_test[DType.float64, 1024, 1]() def test_syr2(): - syr2_test[DType.float32, 256, 1]() - syr2_test[DType.float32, 256, 0]() - syr2_test[DType.float64, 256, 0]() - syr2_test[DType.float64, 256, 1]() + syr2_test[DType.float32, 512, 1]() + syr2_test[DType.float32, 512, 0]() + syr2_test[DType.float64, 512, 0]() + syr2_test[DType.float64, 512, 1]() def main(): print("--- MojoBLAS Level 2 routines testing ---") From ad65309baf2ef11235d1afc12bcd856c5a9818f6 Mon Sep 17 00:00:00 2001 From: Jackson Mowry Date: Thu, 26 Feb 2026 16:45:32 +0000 Subject: [PATCH 3/3] Switch to using symmetric --- test-level2.mojo | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test-level2.mojo b/test-level2.mojo index 8c05889..88ba02f 100644 --- a/test-level2.mojo +++ b/test-level2.mojo @@ -249,7 +249,7 @@ def syr2_test[ var alpha = generate_random_scalar[dtype](-100, 100) - var norm_A = frobenius_norm[dtype](A.unsafe_ptr(), n * n) + var norm_A = frobenius_norm_symmetric[dtype](A.unsafe_ptr(), n, n, uplo) var norm_x = frobenius_norm[dtype](x.unsafe_ptr(), n) var norm_y = frobenius_norm[dtype](y.unsafe_ptr(), n) @@ -302,9 +302,11 @@ def syr2_test[ for i in range(n * n): error[i] = res_mojo[i] - Scalar[dtype](py=sp_flat[i]) - var error_norm = frobenius_norm[dtype]( + var error_norm = frobenius_norm_symmetric[dtype]( error.unsafe_ptr(), - n*n + n, + n, + uplo ) var passed = check_syr_error[dtype](