Skip to content
This repository was archived by the owner on Dec 17, 2025. It is now read-only.

Commit eb849e7

Browse files
Merge branch 'main' into rename-c-api-kernel-domain
2 parents 7526e51 + 0e8cbc5 commit eb849e7

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

backend/cxx/include/sparseir/sparseir.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,25 @@ spir_kernel *spir_logistic_kernel_new(double lambda, int *status);
123123
*/
124124
spir_kernel *spir_reg_bose_kernel_new(double lambda, int *status);
125125

126+
/**
127+
* @brief Retrieves the cutoff parameter lambda used to construct the kernel.
128+
*
129+
* This function extracts the lambda value (Λ) associated with the provided kernel object.
130+
* The lambda parameter typically determines the cutoff scale in the analytic continuation kernels.
131+
*
132+
* @param kernel Pointer to the kernel object. Must not be NULL.
133+
* @param lambda_out Pointer to a double where the lambda value will be written. Must not be NULL.
134+
*
135+
* @return An integer status code:
136+
* - SPIR_COMPUTATION_SUCCESS (0) on success
137+
* - SPIR_INVALID_ARGUMENT if either `kernel` or `lambda_out` is NULL
138+
* - SPIR_INTERNAL_ERROR if an unexpected error occurs internally
139+
*
140+
* @note The lambda value is specific to the type of kernel and corresponds
141+
* to the cutoff parameter provided at kernel construction.
142+
*/
143+
int spir_kernel_get_lambda(const spir_kernel *kernel, double *lambda_out);
144+
126145
/**
127146
* @brief Retrieves the domain boundaries of a kernel function.
128147
*
@@ -145,6 +164,29 @@ spir_kernel *spir_reg_bose_kernel_new(double lambda, int *status);
145164
int spir_kernel_get_domain(const spir_kernel *k, double *xmin, double *xmax,
146165
double *ymin, double *ymax);
147166

167+
/**
168+
* @brief Computes the value of the kernel function K(x, y).
169+
*
170+
* This function evaluates the kernel associated with the provided kernel object
171+
* at the specified coordinates (x, y), and stores the result at the memory location
172+
* pointed to by `out`.
173+
*
174+
* @param kernel Pointer to a kernel object (must not be NULL).
175+
* @param x First coordinate for evaluation (typically in [-1, 1]; domain may vary by kernel).
176+
* @param y Second coordinate for evaluation (typically in [-1, 1]; domain may vary by kernel).
177+
* @param out Pointer to a double where the computed result will be stored (must not be NULL).
178+
*
179+
* @return An integer status code:
180+
* - 0 (SPIR_COMPUTATION_SUCCESS) on success
181+
* - SPIR_INVALID_ARGUMENT if `kernel` or `out` is NULL
182+
* - SPIR_INTERNAL_ERROR if an internal error occurs
183+
*
184+
* @note The function does not check if (x, y) is within the valid domain of the kernel;
185+
* callers should ensure that inputs are valid.
186+
* @note The kernel object must have been created by one of the kernel constructor functions.
187+
*/
188+
int spir_kernel_compute(const spir_kernel *kernel, double x, double y, double *out);
189+
148190
/**
149191
* @brief Get x-segments for SVE discretization hints from a kernel.
150192
*

backend/cxx/src/cinterface.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,25 @@ int spir_kernel_get_domain(const spir_kernel *k, double *xmin, double *xmax,
110110
}
111111
}
112112

113+
int spir_kernel_compute(const spir_kernel *kernel, double x, double y, double *out)
114+
{
115+
try {
116+
auto impl = get_impl_kernel(kernel);
117+
if (!impl) {
118+
DEBUG_LOG("Failed to get kernel implementation");
119+
return SPIR_GET_IMPL_FAILED;
120+
}
121+
*out = impl->compute(x, y);
122+
return SPIR_COMPUTATION_SUCCESS;
123+
} catch (const std::exception &e) {
124+
DEBUG_LOG("Exception in spir_kernel_compute: " + std::string(e.what()));
125+
return SPIR_INVALID_ARGUMENT;
126+
} catch (...) {
127+
DEBUG_LOG("Unknown exception in spir_kernel_compute");
128+
return SPIR_INVALID_ARGUMENT;
129+
}
130+
}
131+
113132
int spir_kernel_get_sve_hints_segments_x(const spir_kernel *k, double epsilon,
114133
double *segments, int *n_segments)
115134
{

backend/cxx/test/cinterface_core.cxx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ TEST_CASE("Kernel Accuracy Tests", "[cinterface]")
3737
REQUIRE(kernel != nullptr);
3838
}
3939

40+
SECTION("Kernel Get Lambda")
41+
{
42+
int kernel_status;
43+
spir_kernel *kernel = spir_logistic_kernel_new(9, &kernel_status);
44+
REQUIRE(kernel_status == SPIR_COMPUTATION_SUCCESS);
45+
REQUIRE(kernel != nullptr);
46+
double lambda;
47+
int lambda_status = spir_kernel_get_lambda(kernel, &lambda);
48+
REQUIRE(lambda_status == SPIR_COMPUTATION_SUCCESS);
49+
REQUIRE(lambda == 9);
50+
spir_kernel_release(kernel);
51+
}
52+
4053
SECTION("Kernel Domain")
4154
{
4255
// Create a kernel through C API
@@ -67,6 +80,26 @@ TEST_CASE("Kernel Accuracy Tests", "[cinterface]")
6780
// Clean up
6881
spir_kernel_release(kernel);
6982
}
83+
84+
SECTION("Kernel Compute")
85+
{
86+
auto cpp_kernel = sparseir::LogisticKernel(9);
87+
double x = 0.5;
88+
double y = 0.5;
89+
double out;
90+
91+
// Create a kernel through C API
92+
int kernel_status;
93+
spir_kernel *kernel = spir_logistic_kernel_new(9, &kernel_status);
94+
REQUIRE(kernel_status == SPIR_COMPUTATION_SUCCESS);
95+
REQUIRE(kernel != nullptr);
96+
int compute_status = spir_kernel_compute(kernel, x, y, &out);
97+
REQUIRE(compute_status == SPIR_COMPUTATION_SUCCESS);
98+
REQUIRE(out == Approx(cpp_kernel.compute(x, y)));
99+
100+
// Clean up
101+
spir_kernel_release(kernel);
102+
}
70103
}
71104

72105
template <typename S>

0 commit comments

Comments
 (0)