diff --git a/src/pylibsparseir/basis.py b/src/pylibsparseir/basis.py index ac9aca2..8ab93e1 100644 --- a/src/pylibsparseir/basis.py +++ b/src/pylibsparseir/basis.py @@ -13,7 +13,7 @@ class FiniteTempBasis(AbstractBasis): """Finite temperature basis for intermediate representation.""" - def __init__(self, statistics: str, beta: float, wmax: float, eps: float, sve_result: Optional[SVEResult] = None): + def __init__(self, statistics: str, beta: float, wmax: float, eps: float, sve_result: Optional[SVEResult] = None, max_size: int =-1): """ Initialize finite temperature basis. @@ -47,7 +47,7 @@ def __init__(self, statistics: str, beta: float, wmax: float, eps: float, sve_re # Create basis stats_int = STATISTICS_FERMIONIC if statistics == 'F' else STATISTICS_BOSONIC - self._ptr = basis_new(stats_int, self._beta, self._wmax, self._kernel._ptr, self._sve._ptr) + self._ptr = basis_new(stats_int, self._beta, self._wmax, self._kernel._ptr, self._sve._ptr, max_size) u_funcs = FunctionSet(basis_get_u(self._ptr)) v_funcs = FunctionSet(basis_get_v(self._ptr)) diff --git a/src/pylibsparseir/constants.py b/src/pylibsparseir/constants.py index f9cc04d..6f6a9ce 100644 --- a/src/pylibsparseir/constants.py +++ b/src/pylibsparseir/constants.py @@ -32,4 +32,8 @@ # Make sure these are available at module level SPIR_ORDER_ROW_MAJOR = 0 -SPIR_ORDER_COLUMN_MAJOR = 1 \ No newline at end of file +SPIR_ORDER_COLUMN_MAJOR = 1 + +# SVE Twork constants +SPIR_TWORK_FLOAT64 = 0 +SPIR_TWORK_FLOAT64X2 = 1 diff --git a/src/pylibsparseir/core.py b/src/pylibsparseir/core.py index a48462d..e18e72f 100644 --- a/src/pylibsparseir/core.py +++ b/src/pylibsparseir/core.py @@ -10,7 +10,7 @@ import numpy as np from .ctypes_wrapper import spir_kernel, spir_sve_result, spir_basis, spir_funcs, spir_sampling -from .constants import COMPUTATION_SUCCESS, ORDER_ROW_MAJOR +from .constants import COMPUTATION_SUCCESS, ORDER_ROW_MAJOR, SPIR_TWORK_FLOAT64, SPIR_TWORK_FLOAT64X2 def _find_library(): """Find the SparseIR shared library.""" @@ -68,7 +68,7 @@ def _setup_prototypes(): _lib.spir_kernel_domain.restype = c_int # SVE result functions - _lib.spir_sve_result_new.argtypes = [spir_kernel, c_double, POINTER(c_int)] + _lib.spir_sve_result_new.argtypes = [spir_kernel, c_double, c_double, c_int, c_int, c_int, POINTER(c_int)] _lib.spir_sve_result_new.restype = spir_sve_result _lib.spir_sve_result_get_size.argtypes = [spir_sve_result, POINTER(c_int)] @@ -79,7 +79,7 @@ def _setup_prototypes(): # Basis functions _lib.spir_basis_new.argtypes = [ - c_int, c_double, c_double, spir_kernel, spir_sve_result, POINTER(c_int) + c_int, c_double, c_double, spir_kernel, spir_sve_result, c_int, POINTER(c_int) ] _lib.spir_basis_new.restype = spir_basis @@ -262,14 +262,23 @@ def reg_bose_kernel_new(lambda_val): raise RuntimeError(f"Failed to create regularized bosonic kernel: {status.value}") return kernel -def sve_result_new(kernel, epsilon): +def sve_result_new(kernel, epsilon, cutoff=None, lmax=None, n_gauss=None, Twork=None): """Create a new SVE result.""" # Validate epsilon if epsilon <= 0: raise RuntimeError(f"Failed to create SVE result: epsilon must be positive, got {epsilon}") + if cutoff is None: + cutoff = -1.0 + if lmax is None: + lmax = -1 + if n_gauss is None: + n_gauss = -1 + if Twork is None: + Twork = SPIR_TWORK_FLOAT64X2 + status = c_int() - sve = _lib.spir_sve_result_new(kernel, epsilon, byref(status)) + sve = _lib.spir_sve_result_new(kernel, epsilon, cutoff, lmax, n_gauss, Twork, byref(status)) if status.value != COMPUTATION_SUCCESS: raise RuntimeError(f"Failed to create SVE result: {status.value}") return sve @@ -291,11 +300,11 @@ def sve_result_get_svals(sve): raise RuntimeError(f"Failed to get singular values: {status}") return svals -def basis_new(statistics, beta, omega_max, kernel, sve): +def basis_new(statistics, beta, omega_max, kernel, sve, max_size): """Create a new basis.""" status = c_int() basis = _lib.spir_basis_new( - statistics, beta, omega_max, kernel, sve, byref(status) + statistics, beta, omega_max, kernel, sve, max_size, byref(status) ) if status.value != COMPUTATION_SUCCESS: raise RuntimeError(f"Failed to create basis: {status.value}") diff --git a/tests/c_api/core_tests.py b/tests/c_api/core_tests.py index e09cbfd..3ab62c0 100644 --- a/tests/c_api/core_tests.py +++ b/tests/c_api/core_tests.py @@ -12,7 +12,7 @@ class TestCAPICoreFixed: """Test core C API functions with correct signatures""" - + def test_kernel_creation_and_domain(self): """Test kernel operations and domain retrieval""" # Test logistic kernel @@ -20,53 +20,57 @@ def test_kernel_creation_and_domain(self): kernel = _lib.spir_logistic_kernel_new(c_double(10.0), byref(status)) assert status.value == COMPUTATION_SUCCESS assert kernel is not None - + # Test kernel domain xmin = c_double() xmax = c_double() ymin = c_double() ymax = c_double() - status_val = _lib.spir_kernel_domain(kernel, byref(xmin), byref(xmax), + status_val = _lib.spir_kernel_domain(kernel, byref(xmin), byref(xmax), byref(ymin), byref(ymax)) assert status_val == COMPUTATION_SUCCESS assert xmin.value == pytest.approx(-1.0) assert xmax.value == pytest.approx(1.0) - + # Release kernel _lib.spir_kernel_release(kernel) - + # Test regularized boson kernel kernel = _lib.spir_reg_bose_kernel_new(c_double(10.0), byref(status)) assert status.value == COMPUTATION_SUCCESS assert kernel is not None - - _lib.spir_kernel_domain(kernel, byref(xmin), byref(xmax), + + _lib.spir_kernel_domain(kernel, byref(xmin), byref(xmax), byref(ymin), byref(ymax)) assert status_val == COMPUTATION_SUCCESS assert xmin.value == pytest.approx(-1.0) assert xmax.value == pytest.approx(1.0) - + _lib.spir_kernel_release(kernel) - + def test_sve_computation(self): """Test SVE computation""" status = c_int() - + # Create kernel kernel = _lib.spir_logistic_kernel_new(c_double(10.0), byref(status)) assert status.value == COMPUTATION_SUCCESS - + # Compute SVE - sve = _lib.spir_sve_result_new(kernel, c_double(1e-6), byref(status)) + cutoff = -1.0 + lmax = -1 + n_gauss = -1 + Twork = SPIR_TWORK_FLOAT64X2 + sve = _lib.spir_sve_result_new(kernel, c_double(1e-6), c_double(cutoff), c_int(lmax), c_int(n_gauss), c_int(Twork), byref(status)) assert status.value == COMPUTATION_SUCCESS assert sve is not None - + # Get SVE size size = c_int() status_val = _lib.spir_sve_result_get_size(sve, byref(size)) assert status_val == COMPUTATION_SUCCESS assert size.value > 0 - + # Get singular values svals = np.zeros(size.value, dtype=np.float64) status_val = _lib.spir_sve_result_get_svals(sve, svals.ctypes.data_as(POINTER(c_double))) @@ -74,221 +78,249 @@ def test_sve_computation(self): assert not np.any(np.isnan(svals)) assert np.all(svals > 0) # Singular values should be positive assert np.all(np.diff(svals) <= 0) # Should be in descending order - + # Cleanup _lib.spir_sve_result_release(sve) _lib.spir_kernel_release(kernel) - + def test_basis_constructors(self): """Test basis construction for different statistics""" - for stats, stats_val in [("fermionic", STATISTICS_FERMIONIC), + for stats, stats_val in [("fermionic", STATISTICS_FERMIONIC), ("bosonic", STATISTICS_BOSONIC)]: status = c_int() beta = 2.0 wmax = 1.0 - + # Create kernel kernel = _lib.spir_logistic_kernel_new(c_double(beta * wmax), byref(status)) assert status.value == COMPUTATION_SUCCESS - + # Compute SVE - sve = _lib.spir_sve_result_new(kernel, c_double(1e-10), byref(status)) + cutoff = -1.0 + lmax = -1 + n_gauss = -1 + Twork = SPIR_TWORK_FLOAT64X2 + sve = _lib.spir_sve_result_new(kernel, c_double(1e-10), c_double(cutoff), c_int(lmax), c_int(n_gauss), c_int(Twork), byref(status)) assert status.value == COMPUTATION_SUCCESS - + # Create basis - basis = _lib.spir_basis_new(c_int(stats_val), c_double(beta), c_double(wmax), - kernel, sve, byref(status)) + max_size = -1 + basis = _lib.spir_basis_new(c_int(stats_val), c_double(beta), c_double(wmax), + kernel, sve, max_size, byref(status)) assert status.value == COMPUTATION_SUCCESS assert basis is not None - + # Check basis properties size = c_int() status_val = _lib.spir_basis_get_size(basis, byref(size)) assert status_val == COMPUTATION_SUCCESS assert size.value > 0 - + retrieved_stats = c_int() status_val = _lib.spir_basis_get_stats(basis, byref(retrieved_stats)) assert status_val == COMPUTATION_SUCCESS assert retrieved_stats.value == stats_val - + # Get singular values svals = np.zeros(size.value, dtype=np.float64) status_val = _lib.spir_basis_get_svals(basis, svals.ctypes.data_as(POINTER(c_double))) assert status_val == COMPUTATION_SUCCESS assert not np.any(np.isnan(svals)) - + # Cleanup _lib.spir_basis_release(basis) _lib.spir_sve_result_release(sve) _lib.spir_kernel_release(kernel) - + def test_tau_sampling_creation_and_properties(self): """Test TauSampling creation and basic properties""" status = c_int() beta = 10.0 wmax = 1.0 - + # Create basis kernel = _lib.spir_logistic_kernel_new(c_double(beta * wmax), byref(status)) - sve = _lib.spir_sve_result_new(kernel, c_double(1e-10), byref(status)) - basis = _lib.spir_basis_new(c_int(STATISTICS_FERMIONIC), c_double(beta), - c_double(wmax), kernel, sve, byref(status)) - + cutoff = -1.0 + lmax = -1 + n_gauss = -1 + Twork = SPIR_TWORK_FLOAT64X2 + max_size = -1 + sve = _lib.spir_sve_result_new(kernel, c_double(1e-10), c_double(cutoff), c_int(lmax), c_int(n_gauss), c_int(Twork), byref(status)) + basis = _lib.spir_basis_new(c_int(STATISTICS_FERMIONIC), c_double(beta), + c_double(wmax), kernel, sve, max_size, byref(status)) + # Get default tau points n_tau = c_int() status_val = _lib.spir_basis_get_n_default_taus(basis, byref(n_tau)) assert status_val == COMPUTATION_SUCCESS assert n_tau.value > 0 - + default_taus = np.zeros(n_tau.value, dtype=np.float64) - status_val = _lib.spir_basis_get_default_taus(basis, + status_val = _lib.spir_basis_get_default_taus(basis, default_taus.ctypes.data_as(POINTER(c_double))) assert status_val == COMPUTATION_SUCCESS - + # Create tau sampling - tau_sampling = _lib.spir_tau_sampling_new(basis, n_tau.value, - default_taus.ctypes.data_as(POINTER(c_double)), + tau_sampling = _lib.spir_tau_sampling_new(basis, n_tau.value, + default_taus.ctypes.data_as(POINTER(c_double)), byref(status)) assert status.value == COMPUTATION_SUCCESS assert tau_sampling is not None - + # Verify tau points are in valid range [0, beta] assert np.all(default_taus >= -beta/2) # Transformed coordinates assert np.all(default_taus <= beta/2) - + # Cleanup _lib.spir_sampling_release(tau_sampling) _lib.spir_basis_release(basis) _lib.spir_sve_result_release(sve) _lib.spir_kernel_release(kernel) - + def test_matsubara_sampling_creation(self): """Test MatsubaraSampling creation""" status = c_int() beta = 10.0 wmax = 1.0 - + max_size = -1 + # Create basis kernel = _lib.spir_logistic_kernel_new(c_double(beta * wmax), byref(status)) - sve = _lib.spir_sve_result_new(kernel, c_double(1e-10), byref(status)) - basis = _lib.spir_basis_new(c_int(STATISTICS_FERMIONIC), c_double(beta), - c_double(wmax), kernel, sve, byref(status)) - + cutoff = -1.0 + lmax = -1 + n_gauss = -1 + Twork = SPIR_TWORK_FLOAT64X2 + sve = _lib.spir_sve_result_new(kernel, c_double(1e-10), c_double(cutoff), c_int(lmax), c_int(n_gauss), c_int(Twork), byref(status)) + basis = _lib.spir_basis_new(c_int(STATISTICS_FERMIONIC), c_double(beta), + c_double(wmax), kernel, sve, max_size, byref(status)) + # Get default Matsubara points n_matsu = c_int() status_val = _lib.spir_basis_get_n_default_matsus(basis, c_bool(False), byref(n_matsu)) assert status_val == COMPUTATION_SUCCESS assert n_matsu.value > 0 - + default_matsus = np.zeros(n_matsu.value, dtype=np.int64) - status_val = _lib.spir_basis_get_default_matsus(basis, c_bool(False), + status_val = _lib.spir_basis_get_default_matsus(basis, c_bool(False), default_matsus.ctypes.data_as(POINTER(c_int64))) assert status_val == COMPUTATION_SUCCESS - + # Create Matsubara sampling matsu_sampling = _lib.spir_matsu_sampling_new(basis, c_bool(False), n_matsu.value, - default_matsus.ctypes.data_as(POINTER(c_int64)), + default_matsus.ctypes.data_as(POINTER(c_int64)), byref(status)) assert status.value == COMPUTATION_SUCCESS assert matsu_sampling is not None - + # Cleanup _lib.spir_sampling_release(matsu_sampling) _lib.spir_basis_release(basis) _lib.spir_sve_result_release(sve) _lib.spir_kernel_release(kernel) - + def test_basis_functions_u(self): """Test u basis functions retrieval""" status = c_int() beta = 5.0 wmax = 1.0 - + # Create basis kernel = _lib.spir_logistic_kernel_new(c_double(beta * wmax), byref(status)) - sve = _lib.spir_sve_result_new(kernel, c_double(1e-10), byref(status)) - basis = _lib.spir_basis_new(c_int(STATISTICS_FERMIONIC), c_double(beta), - c_double(wmax), kernel, sve, byref(status)) - + cutoff = -1.0 + lmax = -1 + n_gauss = -1 + Twork = SPIR_TWORK_FLOAT64X2 + max_size = -1 + sve = _lib.spir_sve_result_new(kernel, c_double(1e-10), c_double(cutoff), c_int(lmax), c_int(n_gauss), c_int(Twork), byref(status)) + basis = _lib.spir_basis_new(c_int(STATISTICS_FERMIONIC), c_double(beta), + c_double(wmax), kernel, sve, max_size, byref(status)) + # Get u functions u_funcs = _lib.spir_basis_get_u(basis, byref(status)) assert status.value == COMPUTATION_SUCCESS assert u_funcs is not None - + # Get function size funcs_size = c_int() status_val = _lib.spir_funcs_get_size(u_funcs, byref(funcs_size)) assert status_val == COMPUTATION_SUCCESS assert funcs_size.value > 0 - + # Cleanup _lib.spir_funcs_release(u_funcs) _lib.spir_basis_release(basis) _lib.spir_sve_result_release(sve) _lib.spir_kernel_release(kernel) - + def test_memory_management(self): """Test that all release functions work without segfaults""" status = c_int() - + # Create full setup kernel = _lib.spir_logistic_kernel_new(c_double(10.0), byref(status)) - sve = _lib.spir_sve_result_new(kernel, c_double(1e-10), byref(status)) - basis = _lib.spir_basis_new(c_int(STATISTICS_FERMIONIC), c_double(10.0), - c_double(1.0), kernel, sve, byref(status)) - + cutoff = -1.0 + lmax = -1 + n_gauss = -1 + Twork = SPIR_TWORK_FLOAT64X2 + sve = _lib.spir_sve_result_new(kernel, c_double(1e-10), c_double(cutoff), c_int(lmax), c_int(n_gauss), c_int(Twork), byref(status)) + basis = _lib.spir_basis_new(c_int(STATISTICS_FERMIONIC), c_double(10.0), + c_double(1.0), kernel, sve, -1, byref(status)) + u_funcs = _lib.spir_basis_get_u(basis, byref(status)) - + n_tau = c_int() _lib.spir_basis_get_n_default_taus(basis, byref(n_tau)) tau_points = np.zeros(n_tau.value, dtype=np.float64) _lib.spir_basis_get_default_taus(basis, tau_points.ctypes.data_as(POINTER(c_double))) - tau_sampling = _lib.spir_tau_sampling_new(basis, n_tau.value, - tau_points.ctypes.data_as(POINTER(c_double)), + tau_sampling = _lib.spir_tau_sampling_new(basis, n_tau.value, + tau_points.ctypes.data_as(POINTER(c_double)), byref(status)) - + # Release everything in correct order _lib.spir_sampling_release(tau_sampling) _lib.spir_funcs_release(u_funcs) _lib.spir_basis_release(basis) _lib.spir_sve_result_release(sve) _lib.spir_kernel_release(kernel) - + # Test should complete without segfault assert True class TestBasisFunctionEvaluation: """Comprehensive basis function evaluation tests matching LibSparseIR.jl coverage""" - + def _spir_basis_new(self, statistics, beta, wmax, epsilon): """Helper function equivalent to C++ _spir_basis_new""" status = c_int() - + max_size = c_int(-1) # Create logistic kernel kernel = _lib.spir_logistic_kernel_new(c_double(beta * wmax), byref(status)) if status.value != COMPUTATION_SUCCESS or kernel is None: return None, status.value - + # Create SVE result - sve = _lib.spir_sve_result_new(kernel, c_double(epsilon), byref(status)) + cutoff = -1.0 + lmax = -1 + n_gauss = -1 + Twork = SPIR_TWORK_FLOAT64X2 + sve = _lib.spir_sve_result_new(kernel, c_double(epsilon), c_double(cutoff), c_int(lmax), c_int(n_gauss), c_int(Twork), byref(status)) if status.value != COMPUTATION_SUCCESS or sve is None: _lib.spir_kernel_release(kernel) return None, status.value - + # Create basis - basis = _lib.spir_basis_new(c_int(statistics), c_double(beta), c_double(wmax), - kernel, sve, byref(status)) + basis = _lib.spir_basis_new(c_int(statistics), c_double(beta), c_double(wmax), + kernel, sve, max_size, byref(status)) if status.value != COMPUTATION_SUCCESS or basis is None: _lib.spir_sve_result_release(sve) _lib.spir_kernel_release(kernel) return None, status.value - + # Clean up intermediate objects (like C++ version) _lib.spir_sve_result_release(sve) _lib.spir_kernel_release(kernel) - + return basis, COMPUTATION_SUCCESS @pytest.mark.parametrize("statistics", [STATISTICS_FERMIONIC, STATISTICS_BOSONIC]) @@ -297,65 +329,65 @@ def test_basis_functions_comprehensive(self, statistics): beta = 2.0 wmax = 5.0 epsilon = 1e-6 - + # Create basis using helper function (equivalent to C++ _spir_basis_new) basis, basis_status = self._spir_basis_new(statistics, beta, wmax, epsilon) assert basis_status == COMPUTATION_SUCCESS assert basis is not None - + # Get basis size basis_size = c_int() size_status = _lib.spir_basis_get_size(basis, byref(basis_size)) assert size_status == COMPUTATION_SUCCESS size = basis_size.value - + # Get u basis functions u_status = c_int() u = _lib.spir_basis_get_u(basis, byref(u_status)) assert u_status.value == COMPUTATION_SUCCESS assert u is not None - - # Get uhat basis functions + + # Get uhat basis functions uhat_status = c_int() uhat = _lib.spir_basis_get_uhat(basis, byref(uhat_status)) assert uhat_status.value == COMPUTATION_SUCCESS assert uhat is not None - + # Get v basis functions v_status = c_int() v = _lib.spir_basis_get_v(basis, byref(v_status)) assert v_status.value == COMPUTATION_SUCCESS assert v is not None - + # Test single point evaluation for u basis x = 0.5 # Test point for u basis (imaginary time) out = np.zeros(size, dtype=np.float64) eval_status = _lib.spir_funcs_eval(u, c_double(x), out.ctypes.data_as(POINTER(c_double))) assert eval_status == COMPUTATION_SUCCESS - + # Check that we got reasonable values assert np.all(np.isfinite(out)) - + # Test single point evaluation for v basis y = 0.5 * wmax # Test point for v basis (real frequency) eval_status = _lib.spir_funcs_eval(v, c_double(y), out.ctypes.data_as(POINTER(c_double))) assert eval_status == COMPUTATION_SUCCESS assert np.all(np.isfinite(out)) - + # Test batch evaluation num_points = 5 xs = np.array([0.2 * (i+1) for i in range(num_points)], dtype=np.float64) # Points at 0.2, 0.4, 0.6, 0.8, 1.0 batch_out = np.zeros(num_points * size, dtype=np.float64) - + # Test row-major order for u basis batch_status = _lib.spir_funcs_batch_eval( - u, ORDER_ROW_MAJOR, num_points, + u, ORDER_ROW_MAJOR, num_points, xs.ctypes.data_as(POINTER(c_double)), batch_out.ctypes.data_as(POINTER(c_double)) ) assert batch_status == COMPUTATION_SUCCESS assert np.all(np.isfinite(batch_out)) - + # Test column-major order for u basis batch_status = _lib.spir_funcs_batch_eval( u, ORDER_COLUMN_MAJOR, num_points, @@ -364,7 +396,7 @@ def test_basis_functions_comprehensive(self, statistics): ) assert batch_status == COMPUTATION_SUCCESS assert np.all(np.isfinite(batch_out)) - + # Test row-major order for v basis batch_status = _lib.spir_funcs_batch_eval( v, ORDER_ROW_MAJOR, num_points, @@ -373,7 +405,7 @@ def test_basis_functions_comprehensive(self, statistics): ) assert batch_status == COMPUTATION_SUCCESS assert np.all(np.isfinite(batch_out)) - + # Test column-major order for v basis batch_status = _lib.spir_funcs_batch_eval( v, ORDER_COLUMN_MAJOR, num_points, @@ -382,12 +414,12 @@ def test_basis_functions_comprehensive(self, statistics): ) assert batch_status == COMPUTATION_SUCCESS assert np.all(np.isfinite(batch_out)) - + # Test error cases (corresponds to C++ error case testing) # Test with null function pointer eval_status = _lib.spir_funcs_eval(None, c_double(x), out.ctypes.data_as(POINTER(c_double))) assert eval_status != COMPUTATION_SUCCESS - + # Test batch evaluation error cases batch_status = _lib.spir_funcs_batch_eval( None, ORDER_ROW_MAJOR, num_points, @@ -395,7 +427,7 @@ def test_basis_functions_comprehensive(self, statistics): batch_out.ctypes.data_as(POINTER(c_double)) ) assert batch_status != COMPUTATION_SUCCESS - + # Clean up _lib.spir_funcs_release(u) _lib.spir_funcs_release(v) @@ -404,22 +436,22 @@ def test_basis_functions_comprehensive(self, statistics): def test_basis_statistics_verification(self): """Test basis statistics retrieval for both fermionic and bosonic cases""" - for stats_val, expected in [(STATISTICS_FERMIONIC, STATISTICS_FERMIONIC), + for stats_val, expected in [(STATISTICS_FERMIONIC, STATISTICS_FERMIONIC), (STATISTICS_BOSONIC, STATISTICS_BOSONIC)]: beta = 2.0 wmax = 1.0 epsilon = 1e-6 - + basis, basis_status = self._spir_basis_new(stats_val, beta, wmax, epsilon) assert basis_status == COMPUTATION_SUCCESS assert basis is not None - + # Check statistics stats = c_int() stats_status = _lib.spir_basis_get_stats(basis, byref(stats)) assert stats_status == COMPUTATION_SUCCESS assert stats.value == expected - + _lib.spir_basis_release(basis) def test_basis_constructor_with_sve_patterns(self): @@ -428,12 +460,12 @@ def test_basis_constructor_with_sve_patterns(self): for use_reg_bose in [False, True]: if use_reg_bose and statistics == STATISTICS_FERMIONIC: continue # Skip invalid combination - + beta = 2.0 wmax = 5.0 Lambda = 10.0 epsilon = 1e-6 - + # Create kernel kernel_status = c_int() if use_reg_bose: @@ -442,26 +474,31 @@ def test_basis_constructor_with_sve_patterns(self): kernel = _lib.spir_logistic_kernel_new(c_double(Lambda), byref(kernel_status)) assert kernel_status.value == COMPUTATION_SUCCESS assert kernel is not None - + # Create SVE result + cutoff = -1.0 + lmax = -1 + n_gauss = -1 + Twork = SPIR_TWORK_FLOAT64X2 sve_status = c_int() - sve_result = _lib.spir_sve_result_new(kernel, c_double(epsilon), byref(sve_status)) + sve_result = _lib.spir_sve_result_new(kernel, c_double(epsilon), c_double(cutoff), c_int(lmax), c_int(n_gauss), c_int(Twork), byref(sve_status)) assert sve_status.value == COMPUTATION_SUCCESS assert sve_result is not None - + # Create basis with SVE + max_size = -1 basis_status = c_int() - basis = _lib.spir_basis_new(c_int(statistics), c_double(beta), c_double(wmax), - kernel, sve_result, byref(basis_status)) + basis = _lib.spir_basis_new(c_int(statistics), c_double(beta), c_double(wmax), + kernel, sve_result, max_size, byref(basis_status)) assert basis_status.value == COMPUTATION_SUCCESS assert basis is not None - + # Check statistics stats = c_int() stats_status = _lib.spir_basis_get_stats(basis, byref(stats)) assert stats_status == COMPUTATION_SUCCESS assert stats.value == statistics - + # Clean up _lib.spir_kernel_release(kernel) _lib.spir_sve_result_release(sve_result) diff --git a/tests/c_api/dlr_tests.py b/tests/c_api/dlr_tests.py index 0093266..eb87db6 100644 --- a/tests/c_api/dlr_tests.py +++ b/tests/c_api/dlr_tests.py @@ -33,7 +33,8 @@ def _spir_basis_new(stat, beta, wmax, epsilon): sve = sve_result_new(kernel, epsilon) # Create basis - basis = basis_new(stat, beta, wmax, kernel, sve) + max_size = -1 + basis = basis_new(stat, beta, wmax, kernel, sve, max_size) return basis diff --git a/tests/c_api/integration_tests.py b/tests/c_api/integration_tests.py index 64c27b8..489ad9b 100644 --- a/tests/c_api/integration_tests.py +++ b/tests/c_api/integration_tests.py @@ -34,7 +34,8 @@ def _spir_basis_new(stat, beta, wmax, epsilon): sve = sve_result_new(kernel, epsilon) # Create basis - basis = basis_new(stat, beta, wmax, kernel, sve) + max_size = -1 + basis = basis_new(stat, beta, wmax, kernel, sve, max_size) return basis diff --git a/tests/c_api/sampling_tests.py b/tests/c_api/sampling_tests.py index e9b4c67..47faf04 100644 --- a/tests/c_api/sampling_tests.py +++ b/tests/c_api/sampling_tests.py @@ -33,7 +33,8 @@ def _spir_basis_new(stat, beta, wmax, epsilon): sve = sve_result_new(kernel, epsilon) # Create basis - basis = basis_new(stat, beta, wmax, kernel, sve) + max_size = -1 + basis = basis_new(stat, beta, wmax, kernel, sve, max_size) return basis diff --git a/tests/test_core.py b/tests/test_core.py index b84aaee..1082571 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -53,7 +53,8 @@ def test_basis_creation(self): sve = sve_result_new(kernel, 1e-6) # Test fermion basis - basis_f = basis_new(1, 10.0, 8.0, kernel, sve) # 1 = fermion + max_size = -1 + basis_f = basis_new(1, 10.0, 8.0, kernel, sve, max_size) # 1 = fermion assert basis_f is not None size_f = basis_get_size(basis_f) @@ -66,7 +67,7 @@ def test_basis_creation(self): assert len(svals_f) == size_f # Test boson basis - basis_b = basis_new(0, 10.0, 8.0, kernel, sve) # 0 = boson + basis_b = basis_new(0, 10.0, 8.0, kernel, sve, max_size) # 0 = boson stats_b = basis_get_stats(basis_b) assert stats_b == 0 # Boson @@ -74,7 +75,8 @@ def test_basis_functions(self): """Test basis function objects.""" kernel = logistic_kernel_new(80.0) sve = sve_result_new(kernel, 1e-6) - basis = basis_new(1, 10.0, 8.0, kernel, sve) + max_size = -1 + basis = basis_new(1, 10.0, 8.0, kernel, sve, max_size) # Test getting function objects u_funcs = basis_get_u(basis) @@ -90,7 +92,8 @@ def test_default_sampling_points(self): """Test default sampling point functions.""" kernel = logistic_kernel_new(80.0) sve = sve_result_new(kernel, 1e-6) - basis = basis_new(1, 10.0, 8.0, kernel, sve) + max_size = -1 + basis = basis_new(1, 10.0, 8.0, kernel, sve, max_size) # Test tau sampling points tau_points = basis_get_default_tau_sampling_points(basis) @@ -109,7 +112,8 @@ def test_sampling_objects(self): """Test sampling object creation.""" kernel = logistic_kernel_new(80.0) sve = sve_result_new(kernel, 1e-6) - basis = basis_new(1, 10.0, 8.0, kernel, sve) + max_size = -1 + basis = basis_new(1, 10.0, 8.0, kernel, sve, max_size) # Test tau sampling tau_points = basis_get_default_tau_sampling_points(basis)