pylibsparseir 0.7.4__cp312-cp312-macosx_15_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1874 @@
1
+ #pragma once
2
+
3
+
4
+ #include <stdarg.h>
5
+ #include <stdbool.h>
6
+ #include <stdint.h>
7
+ #include <stdlib.h>
8
+
9
+ #define SPIR_ORDER_ROW_MAJOR 0
10
+
11
+ #define SPIR_ORDER_COLUMN_MAJOR 1
12
+
13
+ #define SPIR_STATISTICS_BOSONIC 0
14
+
15
+ #define SPIR_STATISTICS_FERMIONIC 1
16
+
17
+ #define SPIR_TWORK_FLOAT64 0
18
+
19
+ #define SPIR_TWORK_FLOAT64X2 1
20
+
21
+ #define SPIR_TWORK_AUTO -1
22
+
23
+ #define SPIR_SVDSTRAT_FAST 0
24
+
25
+ #define SPIR_SVDSTRAT_ACCURATE 1
26
+
27
+ #define SPIR_SVDSTRAT_AUTO -1
28
+
29
+ /**
30
+ * Opaque basis type for C API (compatible with libsparseir)
31
+ *
32
+ * Represents a finite temperature basis (IR or DLR).
33
+ *
34
+ * Note: Named `spir_basis` to match libsparseir C++ API exactly.
35
+ * The internal structure is hidden using a void pointer to prevent exposing BasisType to C.
36
+ */
37
+ typedef struct spir_basis {
38
+ const void *_private;
39
+ } spir_basis;
40
+
41
+ /**
42
+ * Opaque kernel type for C API (compatible with libsparseir)
43
+ *
44
+ * This is a tagged union that can hold either LogisticKernel or RegularizedBoseKernel.
45
+ * The actual type is determined by which constructor was used.
46
+ *
47
+ * Note: Named `spir_kernel` to match libsparseir C++ API exactly.
48
+ * The internal structure is hidden using a void pointer to prevent exposing KernelType to C.
49
+ */
50
+ typedef struct spir_kernel {
51
+ const void *_private;
52
+ } spir_kernel;
53
+
54
+ /**
55
+ * Opaque SVE result type for C API (compatible with libsparseir)
56
+ *
57
+ * Contains singular values and singular functions from SVE computation.
58
+ *
59
+ * Note: Named `spir_sve_result` to match libsparseir C++ API exactly.
60
+ * The internal structure is hidden using a void pointer to prevent exposing Arc<SVEResult> to C.
61
+ */
62
+ typedef struct spir_sve_result {
63
+ const void *_private;
64
+ } spir_sve_result;
65
+
66
+ /**
67
+ * Error codes for C API (compatible with libsparseir)
68
+ */
69
+ typedef int StatusCode;
70
+
71
+ /**
72
+ * Opaque funcs type for C API (compatible with libsparseir)
73
+ *
74
+ * Wraps piecewise Legendre polynomial representations:
75
+ * - PiecewiseLegendrePolyVector for u and v
76
+ * - PiecewiseLegendreFTVector for uhat
77
+ *
78
+ * Note: Named `spir_funcs` to match libsparseir C++ API exactly.
79
+ * The internal FuncsType is hidden using a void pointer, but beta is kept as a public field.
80
+ */
81
+ typedef struct spir_funcs {
82
+ const void *_private;
83
+ double beta;
84
+ } spir_funcs;
85
+
86
+ /**
87
+ * Opaque pointer type for GEMM backend handle
88
+ *
89
+ * This type wraps a `GemmBackendHandle` and provides a C-compatible interface.
90
+ * The handle can be created, cloned, and passed to evaluate/fit functions.
91
+ *
92
+ * Note: The internal structure is hidden using a void pointer to prevent exposing GemmBackendHandle to C.
93
+ */
94
+ typedef struct spir_gemm_backend {
95
+ const void *_private;
96
+ } spir_gemm_backend;
97
+
98
+ /**
99
+ * Complex number type for C API (compatible with C's double complex)
100
+ *
101
+ * This type is compatible with C99's `double complex` and C++'s `std::complex<double>`.
102
+ * Layout: `{double re; double im;}` with standard alignment.
103
+ */
104
+ typedef struct Complex64 {
105
+ double re;
106
+ double im;
107
+ } Complex64;
108
+
109
+ /**
110
+ * Sampling type for C API (unified type for all domains)
111
+ *
112
+ * This wraps different sampling implementations:
113
+ * - TauSampling (for tau-domain)
114
+ * - MatsubaraSampling (for Matsubara frequencies, full range or positive-only)
115
+ * The internal structure is hidden using a void pointer to prevent exposing SamplingType to C.
116
+ */
117
+ typedef struct spir_sampling {
118
+ const void *_private;
119
+ } spir_sampling;
120
+
121
+ #define SPIR_COMPUTATION_SUCCESS 0
122
+
123
+ #define SPIR_GET_IMPL_FAILED -1
124
+
125
+ #define SPIR_INVALID_DIMENSION -2
126
+
127
+ #define SPIR_INPUT_DIMENSION_MISMATCH -3
128
+
129
+ #define SPIR_OUTPUT_DIMENSION_MISMATCH -4
130
+
131
+ #define SPIR_NOT_SUPPORTED -5
132
+
133
+ #define SPIR_INVALID_ARGUMENT -6
134
+
135
+ #define SPIR_INTERNAL_ERROR -7
136
+
137
+ #ifdef __cplusplus
138
+ extern "C" {
139
+ #endif // __cplusplus
140
+
141
+ /**
142
+ * Manual release function (replaces macro-generated one)
143
+ */
144
+ void spir_basis_release(struct spir_basis *basis);
145
+
146
+ /**
147
+ * Manual clone function (replaces macro-generated one)
148
+ */
149
+ struct spir_basis *spir_basis_clone(const struct spir_basis *src);
150
+
151
+ /**
152
+ * Manual is_assigned function (replaces macro-generated one)
153
+ */
154
+ int32_t spir_basis_is_assigned(const struct spir_basis *obj);
155
+
156
+ /**
157
+ * Create a finite temperature basis (libsparseir compatible)
158
+ *
159
+ * # Arguments
160
+ * * `statistics` - 0 for Bosonic, 1 for Fermionic
161
+ * * `beta` - Inverse temperature (must be > 0)
162
+ * * `omega_max` - Frequency cutoff (must be > 0)
163
+ * * `epsilon` - Accuracy target (must be > 0)
164
+ * * `k` - Kernel object (can be NULL if sve is provided)
165
+ * * `sve` - Pre-computed SVE result (can be NULL, will compute if needed)
166
+ * * `max_size` - Maximum basis size (-1 for no limit)
167
+ * * `status` - Pointer to store status code
168
+ *
169
+ * # Returns
170
+ * * Pointer to basis object, or NULL on failure
171
+ *
172
+ * # Safety
173
+ * The caller must ensure `status` is a valid pointer.
174
+ */
175
+
176
+ struct spir_basis *spir_basis_new(int statistics,
177
+ double beta,
178
+ double omega_max,
179
+ double epsilon,
180
+ const struct spir_kernel *k,
181
+ const struct spir_sve_result *sve,
182
+ int max_size,
183
+ StatusCode *status);
184
+
185
+ /**
186
+ * Create a finite temperature basis from SVE result and custom regularizer function
187
+ *
188
+ * This function creates a basis from a pre-computed SVE result and a custom
189
+ * regularizer function. The regularizer function is used to scale the basis
190
+ * functions in the frequency domain.
191
+ *
192
+ * # Arguments
193
+ * * `statistics` - 0 for Bosonic, 1 for Fermionic
194
+ * * `beta` - Inverse temperature (must be > 0)
195
+ * * `omega_max` - Frequency cutoff (must be > 0)
196
+ * * `epsilon` - Accuracy target (must be > 0)
197
+ * * `lambda` - Kernel parameter Λ = β * ωmax (must be > 0)
198
+ * * `ypower` - Power of y in kernel (typically 0 or 1)
199
+ * * `conv_radius` - Convergence radius for Fourier transform
200
+ * * `sve` - Pre-computed SVE result (must not be NULL)
201
+ * * `regularizer_funcs` - Custom regularizer function (must not be NULL)
202
+ * * `max_size` - Maximum basis size (-1 for no limit)
203
+ * * `status` - Pointer to store status code
204
+ *
205
+ * # Returns
206
+ * * Pointer to basis object, or NULL on failure
207
+ *
208
+ * # Note
209
+ * Currently, the regularizer function is evaluated but the custom weight is not
210
+ * fully integrated into the basis construction. The basis is created using
211
+ * the standard from_sve_result method with the kernel's default regularizer.
212
+ * This is a limitation of the current Rust implementation compared to the C++ version.
213
+ *
214
+ * # Safety
215
+ * The caller must ensure `status` is a valid pointer.
216
+ */
217
+
218
+ struct spir_basis *spir_basis_new_from_sve_and_regularizer(int statistics,
219
+ double beta,
220
+ double omega_max,
221
+ double epsilon,
222
+ double lambda,
223
+ int _ypower,
224
+ double _conv_radius,
225
+ const struct spir_sve_result *sve,
226
+ const struct spir_funcs *regularizer_funcs,
227
+ int max_size,
228
+ StatusCode *status);
229
+
230
+ /**
231
+ * Get the number of basis functions
232
+ *
233
+ * # Arguments
234
+ * * `b` - Basis object
235
+ * * `size` - Pointer to store the size
236
+ *
237
+ * # Returns
238
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
239
+ * * `SPIR_INVALID_ARGUMENT` (-6) if b or size is null
240
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
241
+ */
242
+ StatusCode spir_basis_get_size(const struct spir_basis *b, int *size);
243
+
244
+ /**
245
+ * Get singular values from a basis
246
+ *
247
+ * # Arguments
248
+ * * `b` - Basis object
249
+ * * `svals` - Pre-allocated array to store singular values (size must be >= basis size)
250
+ *
251
+ * # Returns
252
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
253
+ * * `SPIR_INVALID_ARGUMENT` (-6) if b or svals is null
254
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
255
+ */
256
+ StatusCode spir_basis_get_svals(const struct spir_basis *b, double *svals);
257
+
258
+ /**
259
+ * Get statistics type (Fermionic or Bosonic) of a basis
260
+ *
261
+ * # Arguments
262
+ * * `b` - Basis object
263
+ * * `statistics` - Pointer to store statistics (0 = Bosonic, 1 = Fermionic)
264
+ *
265
+ * # Returns
266
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
267
+ * * `SPIR_INVALID_ARGUMENT` (-6) if b or statistics is null
268
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
269
+ */
270
+ StatusCode spir_basis_get_stats(const struct spir_basis *b, int *statistics);
271
+
272
+ /**
273
+ * Get singular values (alias for spir_basis_get_svals for libsparseir compatibility)
274
+ */
275
+ StatusCode spir_basis_get_singular_values(const struct spir_basis *b, double *svals);
276
+
277
+ /**
278
+ * Get the number of default tau sampling points
279
+ *
280
+ * # Arguments
281
+ * * `b` - Basis object
282
+ * * `num_points` - Pointer to store the number of points
283
+ *
284
+ * # Returns
285
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
286
+ * * `SPIR_INVALID_ARGUMENT` (-6) if b or num_points is null
287
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
288
+ */
289
+ StatusCode spir_basis_get_n_default_taus(const struct spir_basis *b, int *num_points);
290
+
291
+ /**
292
+ * Get default tau sampling points
293
+ *
294
+ * # Arguments
295
+ * * `b` - Basis object
296
+ * * `points` - Pre-allocated array to store tau points
297
+ *
298
+ * # Returns
299
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
300
+ * * `SPIR_INVALID_ARGUMENT` (-6) if b or points is null
301
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
302
+ */
303
+ StatusCode spir_basis_get_default_taus(const struct spir_basis *b, double *points);
304
+
305
+ /**
306
+ * Get the number of default Matsubara sampling points
307
+ *
308
+ * # Arguments
309
+ * * `b` - Basis object
310
+ * * `positive_only` - If true, return only positive frequencies
311
+ * * `num_points` - Pointer to store the number of points
312
+ *
313
+ * # Returns
314
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
315
+ * * `SPIR_INVALID_ARGUMENT` (-6) if b or num_points is null
316
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
317
+ */
318
+
319
+ StatusCode spir_basis_get_n_default_matsus(const struct spir_basis *b,
320
+ bool positive_only,
321
+ int *num_points);
322
+
323
+ /**
324
+ * Get default Matsubara sampling points
325
+ *
326
+ * # Arguments
327
+ * * `b` - Basis object
328
+ * * `positive_only` - If true, return only positive frequencies
329
+ * * `points` - Pre-allocated array to store Matsubara indices
330
+ *
331
+ * # Returns
332
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
333
+ * * `SPIR_INVALID_ARGUMENT` (-6) if b or points is null
334
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
335
+ */
336
+
337
+ StatusCode spir_basis_get_default_matsus(const struct spir_basis *b,
338
+ bool positive_only,
339
+ int64_t *points);
340
+
341
+ /**
342
+ * Gets the basis functions in imaginary time (τ) domain
343
+ *
344
+ * # Arguments
345
+ * * `b` - Pointer to the finite temperature basis object
346
+ * * `status` - Pointer to store the status code
347
+ *
348
+ * # Returns
349
+ * Pointer to the basis functions object (`spir_funcs`), or NULL if creation fails
350
+ *
351
+ * # Safety
352
+ * The caller must ensure that `b` is a valid pointer, and must call
353
+ * `spir_funcs_release()` on the returned pointer when done.
354
+ */
355
+ struct spir_funcs *spir_basis_get_u(const struct spir_basis *b, StatusCode *status);
356
+
357
+ /**
358
+ * Gets the basis functions in real frequency (ω) domain
359
+ *
360
+ * # Arguments
361
+ * * `b` - Pointer to the finite temperature basis object
362
+ * * `status` - Pointer to store the status code
363
+ *
364
+ * # Returns
365
+ * Pointer to the basis functions object (`spir_funcs`), or NULL if creation fails
366
+ *
367
+ * # Safety
368
+ * The caller must ensure that `b` is a valid pointer, and must call
369
+ * `spir_funcs_release()` on the returned pointer when done.
370
+ */
371
+ struct spir_funcs *spir_basis_get_v(const struct spir_basis *b, StatusCode *status);
372
+
373
+ /**
374
+ * Gets the number of default omega (real frequency) sampling points
375
+ *
376
+ * # Arguments
377
+ * * `b` - Pointer to the finite temperature basis object
378
+ * * `num_points` - Pointer to store the number of sampling points
379
+ *
380
+ * # Returns
381
+ * Status code (SPIR_COMPUTATION_SUCCESS on success)
382
+ *
383
+ * # Safety
384
+ * The caller must ensure that `b` and `num_points` are valid pointers
385
+ */
386
+ StatusCode spir_basis_get_n_default_ws(const struct spir_basis *b, int *num_points);
387
+
388
+ /**
389
+ * Gets the default omega (real frequency) sampling points
390
+ *
391
+ * # Arguments
392
+ * * `b` - Pointer to the finite temperature basis object
393
+ * * `points` - Pre-allocated array to store the omega sampling points
394
+ *
395
+ * # Returns
396
+ * Status code (SPIR_COMPUTATION_SUCCESS on success)
397
+ *
398
+ * # Safety
399
+ * The caller must ensure that `points` has size >= `spir_basis_get_n_default_ws(b)`
400
+ */
401
+ StatusCode spir_basis_get_default_ws(const struct spir_basis *b, double *points);
402
+
403
+ /**
404
+ * Gets the basis functions in Matsubara frequency domain
405
+ *
406
+ * # Arguments
407
+ * * `b` - Pointer to the finite temperature basis object
408
+ * * `status` - Pointer to store the status code
409
+ *
410
+ * # Returns
411
+ * Pointer to the basis functions object (`spir_funcs`), or NULL if creation fails
412
+ *
413
+ * # Safety
414
+ * The caller must ensure that `b` is a valid pointer, and must call
415
+ * `spir_funcs_release()` on the returned pointer when done.
416
+ */
417
+ struct spir_funcs *spir_basis_get_uhat(const struct spir_basis *b, StatusCode *status);
418
+
419
+ /**
420
+ * Gets the full (untruncated) Matsubara-frequency basis functions
421
+ *
422
+ * This function returns an object representing all basis functions
423
+ * in the Matsubara-frequency domain, including those beyond the truncation
424
+ * threshold. Unlike `spir_basis_get_uhat`, which returns only the truncated
425
+ * basis functions (up to `basis.size()`), this function returns all basis
426
+ * functions from the SVE result (up to `sve_result.s.size()`).
427
+ *
428
+ * # Arguments
429
+ * * `b` - Pointer to the finite temperature basis object (must be an IR basis)
430
+ * * `status` - Pointer to store the status code
431
+ *
432
+ * # Returns
433
+ * Pointer to the basis functions object, or NULL if creation fails
434
+ *
435
+ * # Note
436
+ * The returned object must be freed using `spir_funcs_release`
437
+ * when no longer needed
438
+ * This function is only available for IR basis objects (not DLR)
439
+ * uhat_full.size() >= uhat.size() is always true
440
+ * The first uhat.size() functions in uhat_full are identical to uhat
441
+ *
442
+ * # Safety
443
+ * The caller must ensure that `b` is a valid pointer, and must call
444
+ * `spir_funcs_release()` on the returned pointer when done.
445
+ */
446
+ struct spir_funcs *spir_basis_get_uhat_full(const struct spir_basis *b, StatusCode *status);
447
+
448
+ /**
449
+ * Get default tau sampling points with custom limit (extended version)
450
+ *
451
+ * # Arguments
452
+ * * `b` - Basis object
453
+ * * `n_points` - Maximum number of points requested
454
+ * * `points` - Pre-allocated array to store tau points (size >= n_points)
455
+ * * `n_points_returned` - Pointer to store actual number of points returned
456
+ *
457
+ * # Returns
458
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
459
+ * * `SPIR_INVALID_ARGUMENT` (-6) if any pointer is null or n_points < 0
460
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
461
+ *
462
+ * # Note
463
+ * Returns min(n_points, actual_default_points) sampling points
464
+ */
465
+
466
+ StatusCode spir_basis_get_default_taus_ext(const struct spir_basis *b,
467
+ int n_points,
468
+ double *points,
469
+ int *n_points_returned);
470
+
471
+ /**
472
+ * Get number of default Matsubara sampling points with custom limit (extended version)
473
+ *
474
+ * # Arguments
475
+ * * `b` - Basis object
476
+ * * `positive_only` - If true, return only positive frequencies
477
+ * * `mitigate` - If true, enable mitigation (fencing) to improve conditioning
478
+ * * `L` - Requested number of sampling points
479
+ * * `num_points_returned` - Pointer to store actual number of points
480
+ *
481
+ * # Returns
482
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
483
+ * * `SPIR_INVALID_ARGUMENT` (-6) if any pointer is null or L < 0
484
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
485
+ *
486
+ * # Note
487
+ * Returns the actual number of points that will be returned by
488
+ * `spir_basis_get_default_matsus_ext` with the same parameters.
489
+ * When mitigate is true, may return more points than requested due to fencing.
490
+ */
491
+
492
+ StatusCode spir_basis_get_n_default_matsus_ext(const struct spir_basis *b,
493
+ bool positive_only,
494
+ bool mitigate,
495
+ int L,
496
+ int *num_points_returned);
497
+
498
+ /**
499
+ * Get default Matsubara sampling points with custom limit (extended version)
500
+ *
501
+ * # Arguments
502
+ * * `b` - Basis object
503
+ * * `positive_only` - If true, return only positive frequencies
504
+ * * `mitigate` - If true, enable mitigation (fencing) to improve conditioning
505
+ * * `n_points` - Maximum number of points requested
506
+ * * `points` - Pre-allocated array to store Matsubara indices (size >= n_points)
507
+ * * `n_points_returned` - Pointer to store actual number of points returned
508
+ *
509
+ * # Returns
510
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
511
+ * * `SPIR_INVALID_ARGUMENT` (-6) if any pointer is null or n_points < 0
512
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
513
+ *
514
+ * # Note
515
+ * Returns the actual number of sampling points (may be more than n_points
516
+ * when mitigate is true due to fencing). The caller should call
517
+ * `spir_basis_get_n_default_matsus_ext` with the same parameters first to
518
+ * determine the required buffer size.
519
+ */
520
+
521
+ StatusCode spir_basis_get_default_matsus_ext(const struct spir_basis *b,
522
+ bool positive_only,
523
+ bool mitigate,
524
+ int n_points,
525
+ int64_t *points,
526
+ int *n_points_returned);
527
+
528
+ /**
529
+ * Creates a new DLR from an IR basis with default poles
530
+ *
531
+ * # Arguments
532
+ * * `b` - Pointer to a finite temperature basis object
533
+ * * `status` - Pointer to store the status code
534
+ *
535
+ * # Returns
536
+ * Pointer to the newly created DLR basis object, or NULL if creation fails
537
+ *
538
+ * # Safety
539
+ * Caller must ensure `b` is a valid IR basis pointer
540
+ */
541
+ struct spir_basis *spir_dlr_new(const struct spir_basis *b, StatusCode *status);
542
+
543
+ /**
544
+ * Creates a new DLR with custom poles
545
+ *
546
+ * # Arguments
547
+ * * `b` - Pointer to a finite temperature basis object
548
+ * * `npoles` - Number of poles to use
549
+ * * `poles` - Array of pole locations on the real-frequency axis
550
+ * * `status` - Pointer to store the status code
551
+ *
552
+ * # Returns
553
+ * Pointer to the newly created DLR basis object, or NULL if creation fails
554
+ *
555
+ * # Safety
556
+ * Caller must ensure `b` is valid and `poles` has `npoles` elements
557
+ */
558
+
559
+ struct spir_basis *spir_dlr_new_with_poles(const struct spir_basis *b,
560
+ int npoles,
561
+ const double *poles,
562
+ StatusCode *status);
563
+
564
+ /**
565
+ * Gets the number of poles in a DLR
566
+ *
567
+ * # Arguments
568
+ * * `dlr` - Pointer to a DLR basis object
569
+ * * `num_poles` - Pointer to store the number of poles
570
+ *
571
+ * # Returns
572
+ * Status code
573
+ *
574
+ * # Safety
575
+ * Caller must ensure `dlr` is a valid DLR basis pointer
576
+ */
577
+ StatusCode spir_dlr_get_npoles(const struct spir_basis *dlr, int *num_poles);
578
+
579
+ /**
580
+ * Gets the pole locations in a DLR
581
+ *
582
+ * # Arguments
583
+ * * `dlr` - Pointer to a DLR basis object
584
+ * * `poles` - Pre-allocated array to store pole locations
585
+ *
586
+ * # Returns
587
+ * Status code
588
+ *
589
+ * # Safety
590
+ * Caller must ensure `dlr` is valid and `poles` has sufficient size
591
+ */
592
+ StatusCode spir_dlr_get_poles(const struct spir_basis *dlr, double *poles);
593
+
594
+ /**
595
+ * Convert IR coefficients to DLR (real-valued)
596
+ *
597
+ * # Arguments
598
+ * * `dlr` - Pointer to a DLR basis object
599
+ * * `order` - Memory layout order
600
+ * * `ndim` - Number of dimensions
601
+ * * `input_dims` - Array of input dimensions
602
+ * * `target_dim` - Dimension to transform
603
+ * * `input` - IR coefficients
604
+ * * `out` - Output DLR coefficients
605
+ *
606
+ * # Returns
607
+ * Status code
608
+ *
609
+ * # Safety
610
+ * Caller must ensure pointers are valid and arrays have correct sizes
611
+ */
612
+
613
+ StatusCode spir_ir2dlr_dd(const struct spir_basis *dlr,
614
+ const struct spir_gemm_backend *backend,
615
+ int order,
616
+ int ndim,
617
+ const int *input_dims,
618
+ int target_dim,
619
+ const double *input,
620
+ double *out);
621
+
622
+ /**
623
+ * Convert IR coefficients to DLR (complex-valued)
624
+ *
625
+ * # Arguments
626
+ * * `dlr` - Pointer to a DLR basis object
627
+ * * `order` - Memory layout order
628
+ * * `ndim` - Number of dimensions
629
+ * * `input_dims` - Array of input dimensions
630
+ * * `target_dim` - Dimension to transform
631
+ * * `input` - Complex IR coefficients
632
+ * * `out` - Output complex DLR coefficients
633
+ *
634
+ * # Returns
635
+ * Status code
636
+ *
637
+ * # Safety
638
+ * Caller must ensure pointers are valid and arrays have correct sizes
639
+ */
640
+
641
+ StatusCode spir_ir2dlr_zz(const struct spir_basis *dlr,
642
+ const struct spir_gemm_backend *backend,
643
+ int order,
644
+ int ndim,
645
+ const int *input_dims,
646
+ int target_dim,
647
+ const struct Complex64 *input,
648
+ struct Complex64 *out);
649
+
650
+ /**
651
+ * Convert DLR coefficients to IR (real-valued)
652
+ *
653
+ * # Arguments
654
+ * * `dlr` - Pointer to a DLR basis object
655
+ * * `order` - Memory layout order
656
+ * * `ndim` - Number of dimensions
657
+ * * `input_dims` - Array of input dimensions
658
+ * * `target_dim` - Dimension to transform
659
+ * * `input` - DLR coefficients
660
+ * * `out` - Output IR coefficients
661
+ *
662
+ * # Returns
663
+ * Status code
664
+ *
665
+ * # Safety
666
+ * Caller must ensure pointers are valid and arrays have correct sizes
667
+ */
668
+
669
+ StatusCode spir_dlr2ir_dd(const struct spir_basis *dlr,
670
+ const struct spir_gemm_backend *backend,
671
+ int order,
672
+ int ndim,
673
+ const int *input_dims,
674
+ int target_dim,
675
+ const double *input,
676
+ double *out);
677
+
678
+ /**
679
+ * Convert DLR coefficients to IR (complex-valued)
680
+ *
681
+ * # Arguments
682
+ * * `dlr` - Pointer to a DLR basis object
683
+ * * `order` - Memory layout order
684
+ * * `ndim` - Number of dimensions
685
+ * * `input_dims` - Array of input dimensions
686
+ * * `target_dim` - Dimension to transform
687
+ * * `input` - Complex DLR coefficients
688
+ * * `out` - Output complex IR coefficients
689
+ *
690
+ * # Returns
691
+ * Status code
692
+ *
693
+ * # Safety
694
+ * Caller must ensure pointers are valid and arrays have correct sizes
695
+ */
696
+
697
+ StatusCode spir_dlr2ir_zz(const struct spir_basis *dlr,
698
+ const struct spir_gemm_backend *backend,
699
+ int order,
700
+ int ndim,
701
+ const int *input_dims,
702
+ int target_dim,
703
+ const struct Complex64 *input,
704
+ struct Complex64 *out);
705
+
706
+ /**
707
+ * Manual release function (replaces macro-generated one)
708
+ */
709
+ void spir_funcs_release(struct spir_funcs *funcs);
710
+
711
+ /**
712
+ * Manual clone function (replaces macro-generated one)
713
+ */
714
+ struct spir_funcs *spir_funcs_clone(const struct spir_funcs *src);
715
+
716
+ /**
717
+ * Manual is_assigned function (replaces macro-generated one)
718
+ */
719
+ int32_t spir_funcs_is_assigned(const struct spir_funcs *obj);
720
+
721
+ /**
722
+ * Create a spir_funcs object from piecewise Legendre polynomial coefficients
723
+ *
724
+ * Constructs a continuous function object from segments and Legendre polynomial
725
+ * expansion coefficients. The coefficients are organized per segment, with each
726
+ * segment containing nfuncs coefficients (degrees 0 to nfuncs-1).
727
+ *
728
+ * # Arguments
729
+ * * `segments` - Array of segment boundaries (n_segments+1 elements). Must be monotonically increasing.
730
+ * * `n_segments` - Number of segments (must be >= 1)
731
+ * * `coeffs` - Array of Legendre coefficients. Layout: contiguous per segment,
732
+ * coefficients for segment i are stored at indices [i*nfuncs, (i+1)*nfuncs).
733
+ * Each segment has nfuncs coefficients for Legendre degrees 0 to nfuncs-1.
734
+ * * `nfuncs` - Number of basis functions per segment (Legendre polynomial degrees 0 to nfuncs-1)
735
+ * * `order` - Order parameter (currently unused, reserved for future use)
736
+ * * `status` - Pointer to store the status code
737
+ *
738
+ * # Returns
739
+ * Pointer to the newly created funcs object, or NULL if creation fails
740
+ *
741
+ * # Note
742
+ * The function creates a single piecewise Legendre polynomial function.
743
+ * To create multiple functions, call this function multiple times.
744
+ */
745
+
746
+ struct spir_funcs *spir_funcs_from_piecewise_legendre(const double *segments,
747
+ int n_segments,
748
+ const double *coeffs,
749
+ int nfuncs,
750
+ int _order,
751
+ StatusCode *status);
752
+
753
+ /**
754
+ * Extract a subset of functions by indices
755
+ *
756
+ * # Arguments
757
+ * * `funcs` - Pointer to the source funcs object
758
+ * * `nslice` - Number of functions to select (length of indices array)
759
+ * * `indices` - Array of indices specifying which functions to include
760
+ * * `status` - Pointer to store the status code
761
+ *
762
+ * # Returns
763
+ * Pointer to a new funcs object containing only the selected functions, or null on error
764
+ *
765
+ * # Safety
766
+ * The caller must ensure that `funcs` and `indices` are valid pointers.
767
+ * The returned pointer must be freed with `spir_funcs_release()`.
768
+ */
769
+
770
+ struct spir_funcs *spir_funcs_get_slice(const struct spir_funcs *funcs,
771
+ int32_t nslice,
772
+ const int32_t *indices,
773
+ StatusCode *status);
774
+
775
+ /**
776
+ * Gets the number of basis functions
777
+ *
778
+ * # Arguments
779
+ * * `funcs` - Pointer to the funcs object
780
+ * * `size` - Pointer to store the number of functions
781
+ *
782
+ * # Returns
783
+ * Status code (SPIR_COMPUTATION_SUCCESS on success)
784
+ */
785
+ StatusCode spir_funcs_get_size(const struct spir_funcs *funcs, int *size);
786
+
787
+ /**
788
+ * Gets the number of knots for continuous functions
789
+ *
790
+ * # Arguments
791
+ * * `funcs` - Pointer to the funcs object
792
+ * * `n_knots` - Pointer to store the number of knots
793
+ *
794
+ * # Returns
795
+ * Status code (SPIR_COMPUTATION_SUCCESS on success, SPIR_NOT_SUPPORTED if not continuous)
796
+ */
797
+ StatusCode spir_funcs_get_n_knots(const struct spir_funcs *funcs, int *n_knots);
798
+
799
+ /**
800
+ * Gets the knot positions for continuous functions
801
+ *
802
+ * # Arguments
803
+ * * `funcs` - Pointer to the funcs object
804
+ * * `knots` - Pre-allocated array to store knot positions
805
+ *
806
+ * # Returns
807
+ * Status code (SPIR_COMPUTATION_SUCCESS on success, SPIR_NOT_SUPPORTED if not continuous)
808
+ *
809
+ * # Safety
810
+ * The caller must ensure that `knots` has size >= `spir_funcs_get_n_knots(funcs)`
811
+ */
812
+ StatusCode spir_funcs_get_knots(const struct spir_funcs *funcs, double *knots);
813
+
814
+ /**
815
+ * Evaluate functions at a single point (continuous functions only)
816
+ *
817
+ * # Arguments
818
+ * * `funcs` - Pointer to the funcs object
819
+ * * `x` - Point to evaluate at (tau coordinate in [-1, 1])
820
+ * * `out` - Pre-allocated array to store function values
821
+ *
822
+ * # Returns
823
+ * Status code (SPIR_COMPUTATION_SUCCESS on success, SPIR_NOT_SUPPORTED if not continuous)
824
+ *
825
+ * # Safety
826
+ * The caller must ensure that `out` has size >= `spir_funcs_get_size(funcs)`
827
+ */
828
+ StatusCode spir_funcs_eval(const struct spir_funcs *funcs, double x, double *out);
829
+
830
+ /**
831
+ * Evaluate functions at a single Matsubara frequency
832
+ *
833
+ * # Arguments
834
+ * * `funcs` - Pointer to the funcs object
835
+ * * `n` - Matsubara frequency index
836
+ * * `out` - Pre-allocated array to store complex function values
837
+ *
838
+ * # Returns
839
+ * Status code (SPIR_COMPUTATION_SUCCESS on success, SPIR_NOT_SUPPORTED if not Matsubara type)
840
+ *
841
+ * # Safety
842
+ * The caller must ensure that `out` has size >= `spir_funcs_get_size(funcs)`
843
+ * Complex numbers are laid out as [real, imag] pairs
844
+ */
845
+ StatusCode spir_funcs_eval_matsu(const struct spir_funcs *funcs, int64_t n, struct Complex64 *out);
846
+
847
+ /**
848
+ * Batch evaluate functions at multiple points (continuous functions only)
849
+ *
850
+ * # Arguments
851
+ * * `funcs` - Pointer to the funcs object
852
+ * * `order` - Memory layout: 0 for row-major, 1 for column-major
853
+ * * `num_points` - Number of evaluation points
854
+ * * `xs` - Array of points to evaluate at
855
+ * * `out` - Pre-allocated array to store results
856
+ *
857
+ * # Returns
858
+ * Status code (SPIR_COMPUTATION_SUCCESS on success, SPIR_NOT_SUPPORTED if not continuous)
859
+ *
860
+ * # Safety
861
+ * - `xs` must have size >= `num_points`
862
+ * - `out` must have size >= `num_points * spir_funcs_get_size(funcs)`
863
+ * - Layout: row-major = out[point][func], column-major = out[func][point]
864
+ */
865
+
866
+ StatusCode spir_funcs_batch_eval(const struct spir_funcs *funcs,
867
+ int order,
868
+ int num_points,
869
+ const double *xs,
870
+ double *out);
871
+
872
+ /**
873
+ * Batch evaluate functions at multiple Matsubara frequencies
874
+ *
875
+ * # Arguments
876
+ * * `funcs` - Pointer to the funcs object
877
+ * * `order` - Memory layout: 0 for row-major, 1 for column-major
878
+ * * `num_freqs` - Number of Matsubara frequencies
879
+ * * `ns` - Array of Matsubara frequency indices
880
+ * * `out` - Pre-allocated array to store complex results
881
+ *
882
+ * # Returns
883
+ * Status code (SPIR_COMPUTATION_SUCCESS on success, SPIR_NOT_SUPPORTED if not Matsubara type)
884
+ *
885
+ * # Safety
886
+ * - `ns` must have size >= `num_freqs`
887
+ * - `out` must have size >= `num_freqs * spir_funcs_get_size(funcs)`
888
+ * - Complex numbers are laid out as [real, imag] pairs
889
+ * - Layout: row-major = out[freq][func], column-major = out[func][freq]
890
+ */
891
+
892
+ StatusCode spir_funcs_batch_eval_matsu(const struct spir_funcs *funcs,
893
+ int order,
894
+ int num_freqs,
895
+ const int64_t *ns,
896
+ struct Complex64 *out);
897
+
898
+ /**
899
+ * Get default Matsubara sampling points from a Matsubara-space spir_funcs
900
+ *
901
+ * This function computes default sampling points in Matsubara frequencies (iωn) from
902
+ * a spir_funcs object that represents Matsubara-space basis functions (e.g., uhat or uhat_full).
903
+ * The statistics type (Fermionic/Bosonic) is automatically detected from the spir_funcs object type.
904
+ *
905
+ * This extracts the PiecewiseLegendreFTVector from spir_funcs and calls
906
+ * `FiniteTempBasis::default_matsubara_sampling_points_impl` from `basis.rs` (lines 332-387)
907
+ * to compute default sampling points.
908
+ *
909
+ * The implementation uses the same algorithm as defined in `sparseir-rust/src/basis.rs`,
910
+ * which selects sampling points based on sign changes or extrema of the Matsubara basis functions.
911
+ *
912
+ * # Arguments
913
+ * * `uhat` - Pointer to a spir_funcs object representing Matsubara-space basis functions
914
+ * * `l` - Number of requested sampling points
915
+ * * `positive_only` - If true, only positive frequencies are used
916
+ * * `mitigate` - If true, enable mitigation (fencing) to improve conditioning by adding oversampling points
917
+ * * `points` - Pre-allocated array to store the sampling points. The size of the array must be sufficient for the returned points (may exceed L if mitigate is true).
918
+ * * `n_points_returned` - Pointer to store the number of sampling points returned (may exceed L if mitigate is true, or approximately L/2 when positive_only=true).
919
+ *
920
+ * # Returns
921
+ * Status code:
922
+ * - SPIR_COMPUTATION_SUCCESS (0) on success
923
+ * - SPIR_INVALID_ARGUMENT if uhat, points, or n_points_returned is null
924
+ * - SPIR_NOT_SUPPORTED if uhat is not a Matsubara-space function
925
+ *
926
+ * # Note
927
+ * This function is only available for spir_funcs objects representing Matsubara-space basis functions
928
+ * The statistics type is automatically detected from the spir_funcs object type
929
+ * The default sampling points are chosen to provide near-optimal conditioning
930
+ */
931
+
932
+ StatusCode spir_uhat_get_default_matsus(const struct spir_funcs *uhat,
933
+ int l,
934
+ bool positive_only,
935
+ bool mitigate,
936
+ int64_t *points,
937
+ int *n_points_returned);
938
+
939
+ /**
940
+ * Create GEMM backend from Fortran BLAS function pointers (LP64)
941
+ *
942
+ * Creates a new backend handle from Fortran BLAS function pointers.
943
+ *
944
+ * # Arguments
945
+ * * `dgemm` - Function pointer to Fortran BLAS dgemm (double precision)
946
+ * * `zgemm` - Function pointer to Fortran BLAS zgemm (complex double precision)
947
+ *
948
+ * # Returns
949
+ * * Pointer to `spir_gemm_backend` on success
950
+ * * `NULL` if function pointers are null
951
+ *
952
+ * # Safety
953
+ * The provided function pointers must:
954
+ * - Be valid Fortran BLAS function pointers following the standard Fortran BLAS interface
955
+ * - Use 32-bit integers for all dimension parameters (LP64 interface)
956
+ * - Be thread-safe (will be called from multiple threads)
957
+ * - Remain valid for the entire lifetime of the backend handle
958
+ *
959
+ * The returned pointer must be freed with `spir_gemm_backend_free` when no longer needed.
960
+ */
961
+
962
+ struct spir_gemm_backend *spir_gemm_backend_new_from_fblas_lp64(const void *dgemm,
963
+ const void *zgemm);
964
+
965
+ /**
966
+ * Create GEMM backend from Fortran BLAS function pointers (ILP64)
967
+ *
968
+ * Creates a new backend handle from Fortran BLAS function pointers with 64-bit integers.
969
+ *
970
+ * # Arguments
971
+ * * `dgemm64` - Function pointer to Fortran BLAS dgemm (double precision, 64-bit integers)
972
+ * * `zgemm64` - Function pointer to Fortran BLAS zgemm (complex double precision, 64-bit integers)
973
+ *
974
+ * # Returns
975
+ * * Pointer to `spir_gemm_backend` on success
976
+ * * `NULL` if function pointers are null
977
+ *
978
+ * # Safety
979
+ * The provided function pointers must:
980
+ * - Be valid Fortran BLAS function pointers following the standard Fortran BLAS interface
981
+ * - Use 64-bit integers for all dimension parameters (ILP64 interface)
982
+ * - Be thread-safe (will be called from multiple threads)
983
+ * - Remain valid for the entire lifetime of the backend handle
984
+ *
985
+ * The returned pointer must be freed with `spir_gemm_backend_free` when no longer needed.
986
+ */
987
+
988
+ struct spir_gemm_backend *spir_gemm_backend_new_from_fblas_ilp64(const void *dgemm64,
989
+ const void *zgemm64);
990
+
991
+ /**
992
+ * Release GEMM backend handle
993
+ *
994
+ * Releases the memory associated with a backend handle.
995
+ *
996
+ * # Arguments
997
+ * * `backend` - Pointer to backend handle (can be NULL)
998
+ *
999
+ * # Safety
1000
+ * The pointer must have been created by `spir_gemm_backend_new_from_fblas_lp64` or
1001
+ * `spir_gemm_backend_new_from_fblas_ilp64`.
1002
+ * After calling this function, the pointer must not be used again.
1003
+ */
1004
+ void spir_gemm_backend_release(struct spir_gemm_backend *backend);
1005
+
1006
+ /**
1007
+ * Create a new Logistic kernel
1008
+ *
1009
+ * # Arguments
1010
+ * * `lambda` - The kernel parameter Λ = β * ωmax (must be > 0)
1011
+ * * `status` - Pointer to store the status code
1012
+ *
1013
+ * # Returns
1014
+ * * Pointer to the newly created kernel object, or NULL if creation fails
1015
+ *
1016
+ * # Safety
1017
+ * The caller must ensure `status` is a valid pointer.
1018
+ *
1019
+ * # Example (C)
1020
+ * ```c
1021
+ * int status;
1022
+ * spir_kernel* kernel = spir_logistic_kernel_new(10.0, &status);
1023
+ * if (kernel != NULL) {
1024
+ * // Use kernel...
1025
+ * spir_kernel_release(kernel);
1026
+ * }
1027
+ * ```
1028
+ */
1029
+ struct spir_kernel *spir_logistic_kernel_new(double lambda, StatusCode *status);
1030
+
1031
+ /**
1032
+ * Create a new RegularizedBose kernel
1033
+ *
1034
+ * # Arguments
1035
+ * * `lambda` - The kernel parameter Λ = β * ωmax (must be > 0)
1036
+ * * `status` - Pointer to store the status code
1037
+ *
1038
+ * # Returns
1039
+ * * Pointer to the newly created kernel object, or NULL if creation fails
1040
+ */
1041
+ struct spir_kernel *spir_reg_bose_kernel_new(double lambda, StatusCode *status);
1042
+
1043
+ /**
1044
+ * Get the lambda parameter of a kernel
1045
+ *
1046
+ * # Arguments
1047
+ * * `kernel` - Kernel object
1048
+ * * `lambda_out` - Pointer to store the lambda value
1049
+ *
1050
+ * # Returns
1051
+ * * `SPIR_COMPUTATION_SUCCESS` on success
1052
+ * * `SPIR_INVALID_ARGUMENT` if kernel or lambda_out is null
1053
+ * * `SPIR_INTERNAL_ERROR` if internal panic occurs
1054
+ */
1055
+ StatusCode spir_kernel_get_lambda(const struct spir_kernel *kernel, double *lambda_out);
1056
+
1057
+ /**
1058
+ * Compute kernel value K(x, y)
1059
+ *
1060
+ * # Arguments
1061
+ * * `kernel` - Kernel object
1062
+ * * `x` - First argument (typically in [-1, 1])
1063
+ * * `y` - Second argument (typically in [-1, 1])
1064
+ * * `out` - Pointer to store the result
1065
+ *
1066
+ * # Returns
1067
+ * * `SPIR_COMPUTATION_SUCCESS` on success
1068
+ * * `SPIR_INVALID_ARGUMENT` if kernel or out is null
1069
+ * * `SPIR_INTERNAL_ERROR` if internal panic occurs
1070
+ */
1071
+ StatusCode spir_kernel_compute(const struct spir_kernel *kernel, double x, double y, double *out);
1072
+
1073
+ /**
1074
+ * Manual release function (replaces macro-generated one)
1075
+ *
1076
+ * # Safety
1077
+ * This function drops the kernel. The inner KernelType data is automatically freed
1078
+ * by the Drop implementation when the spir_kernel structure is dropped.
1079
+ */
1080
+ void spir_kernel_release(struct spir_kernel *kernel);
1081
+
1082
+ /**
1083
+ * Manual clone function (replaces macro-generated one)
1084
+ */
1085
+ struct spir_kernel *spir_kernel_clone(const struct spir_kernel *src);
1086
+
1087
+ /**
1088
+ * Manual is_assigned function (replaces macro-generated one)
1089
+ */
1090
+ int32_t spir_kernel_is_assigned(const struct spir_kernel *obj);
1091
+
1092
+ /**
1093
+ * Get kernel domain boundaries
1094
+ *
1095
+ * # Arguments
1096
+ * * `k` - Kernel object
1097
+ * * `xmin` - Pointer to store minimum x value
1098
+ * * `xmax` - Pointer to store maximum x value
1099
+ * * `ymin` - Pointer to store minimum y value
1100
+ * * `ymax` - Pointer to store maximum y value
1101
+ *
1102
+ * # Returns
1103
+ * * `SPIR_COMPUTATION_SUCCESS` on success
1104
+ * * `SPIR_INVALID_ARGUMENT` if any pointer is null
1105
+ * * `SPIR_INTERNAL_ERROR` if internal panic occurs
1106
+ */
1107
+
1108
+ StatusCode spir_kernel_get_domain(const struct spir_kernel *k,
1109
+ double *xmin,
1110
+ double *xmax,
1111
+ double *ymin,
1112
+ double *ymax);
1113
+
1114
+ /**
1115
+ * Get x-segments for SVE discretization hints from a kernel
1116
+ *
1117
+ * This function should be called twice:
1118
+ * 1. First call with segments=NULL: set n_segments to the required array size
1119
+ * 2. Second call with segments allocated: fill segments[0..n_segments-1] with values
1120
+ *
1121
+ * # Arguments
1122
+ * * `k` - Kernel object
1123
+ * * `epsilon` - Accuracy target for the basis
1124
+ * * `segments` - Pointer to store segments array (NULL for first call)
1125
+ * * `n_segments` - [IN/OUT] Input: ignored when segments is NULL. Output: number of segments
1126
+ *
1127
+ * # Returns
1128
+ * * `SPIR_COMPUTATION_SUCCESS` on success
1129
+ * * `SPIR_INVALID_ARGUMENT` if k or n_segments is null, or segments array is too small
1130
+ * * `SPIR_INTERNAL_ERROR` if internal panic occurs
1131
+ */
1132
+
1133
+ StatusCode spir_kernel_get_sve_hints_segments_x(const struct spir_kernel *k,
1134
+ double epsilon,
1135
+ double *segments,
1136
+ int *n_segments);
1137
+
1138
+ /**
1139
+ * Get y-segments for SVE discretization hints from a kernel
1140
+ *
1141
+ * This function should be called twice:
1142
+ * 1. First call with segments=NULL: set n_segments to the required array size
1143
+ * 2. Second call with segments allocated: fill segments[0..n_segments-1] with values
1144
+ *
1145
+ * # Arguments
1146
+ * * `k` - Kernel object
1147
+ * * `epsilon` - Accuracy target for the basis
1148
+ * * `segments` - Pointer to store segments array (NULL for first call)
1149
+ * * `n_segments` - [IN/OUT] Input: ignored when segments is NULL. Output: number of segments
1150
+ *
1151
+ * # Returns
1152
+ * * `SPIR_COMPUTATION_SUCCESS` on success
1153
+ * * `SPIR_INVALID_ARGUMENT` if k or n_segments is null, or segments array is too small
1154
+ * * `SPIR_INTERNAL_ERROR` if internal panic occurs
1155
+ */
1156
+
1157
+ StatusCode spir_kernel_get_sve_hints_segments_y(const struct spir_kernel *k,
1158
+ double epsilon,
1159
+ double *segments,
1160
+ int *n_segments);
1161
+
1162
+ /**
1163
+ * Get the number of singular values hint from a kernel
1164
+ *
1165
+ * # Arguments
1166
+ * * `k` - Kernel object
1167
+ * * `epsilon` - Accuracy target for the basis
1168
+ * * `nsvals` - Pointer to store the number of singular values
1169
+ *
1170
+ * # Returns
1171
+ * * `SPIR_COMPUTATION_SUCCESS` on success
1172
+ * * `SPIR_INVALID_ARGUMENT` if k or nsvals is null
1173
+ * * `SPIR_INTERNAL_ERROR` if internal panic occurs
1174
+ */
1175
+
1176
+ StatusCode spir_kernel_get_sve_hints_nsvals(const struct spir_kernel *k,
1177
+ double epsilon,
1178
+ int *nsvals);
1179
+
1180
+ /**
1181
+ * Get the number of Gauss points hint from a kernel
1182
+ *
1183
+ * # Arguments
1184
+ * * `k` - Kernel object
1185
+ * * `epsilon` - Accuracy target for the basis
1186
+ * * `ngauss` - Pointer to store the number of Gauss points
1187
+ *
1188
+ * # Returns
1189
+ * * `SPIR_COMPUTATION_SUCCESS` on success
1190
+ * * `SPIR_INVALID_ARGUMENT` if k or ngauss is null
1191
+ * * `SPIR_INTERNAL_ERROR` if internal panic occurs
1192
+ */
1193
+
1194
+ StatusCode spir_kernel_get_sve_hints_ngauss(const struct spir_kernel *k,
1195
+ double epsilon,
1196
+ int *ngauss);
1197
+
1198
+ /**
1199
+ * Manual release function (replaces macro-generated one)
1200
+ */
1201
+ void spir_sampling_release(struct spir_sampling *sampling);
1202
+
1203
+ /**
1204
+ * Manual clone function (replaces macro-generated one)
1205
+ */
1206
+ struct spir_sampling *spir_sampling_clone(const struct spir_sampling *src);
1207
+
1208
+ /**
1209
+ * Manual is_assigned function (replaces macro-generated one)
1210
+ */
1211
+ int32_t spir_sampling_is_assigned(const struct spir_sampling *obj);
1212
+
1213
+ /**
1214
+ * Creates a new tau sampling object for sparse sampling in imaginary time
1215
+ *
1216
+ * # Arguments
1217
+ * * `b` - Pointer to a finite temperature basis object
1218
+ * * `num_points` - Number of sampling points
1219
+ * * `points` - Array of sampling points in imaginary time (τ)
1220
+ * * `status` - Pointer to store the status code
1221
+ *
1222
+ * # Returns
1223
+ * Pointer to the newly created sampling object, or NULL if creation fails
1224
+ *
1225
+ * # Safety
1226
+ * Caller must ensure `b` is valid and `points` has `num_points` elements
1227
+ */
1228
+
1229
+ struct spir_sampling *spir_tau_sampling_new(const struct spir_basis *b,
1230
+ int num_points,
1231
+ const double *points,
1232
+ StatusCode *status);
1233
+
1234
+ /**
1235
+ * Creates a new Matsubara sampling object for sparse sampling in Matsubara frequencies
1236
+ *
1237
+ * # Arguments
1238
+ * * `b` - Pointer to a finite temperature basis object
1239
+ * * `positive_only` - If true, only positive frequencies are used
1240
+ * * `num_points` - Number of sampling points
1241
+ * * `points` - Array of Matsubara frequency indices (n)
1242
+ * * `status` - Pointer to store the status code
1243
+ *
1244
+ * # Returns
1245
+ * Pointer to the newly created sampling object, or NULL if creation fails
1246
+ */
1247
+
1248
+ struct spir_sampling *spir_matsu_sampling_new(const struct spir_basis *b,
1249
+ bool positive_only,
1250
+ int num_points,
1251
+ const int64_t *points,
1252
+ StatusCode *status);
1253
+
1254
+ /**
1255
+ * Creates a new tau sampling object with custom sampling points and pre-computed matrix
1256
+ *
1257
+ * # Arguments
1258
+ * * `order` - Memory layout order (SPIR_ORDER_ROW_MAJOR or SPIR_ORDER_COLUMN_MAJOR)
1259
+ * * `statistics` - Statistics type (SPIR_STATISTICS_FERMIONIC or SPIR_STATISTICS_BOSONIC)
1260
+ * * `basis_size` - Basis size
1261
+ * * `num_points` - Number of sampling points
1262
+ * * `points` - Array of sampling points in imaginary time (τ)
1263
+ * * `matrix` - Pre-computed matrix for the sampling points (num_points x basis_size)
1264
+ * * `status` - Pointer to store the status code
1265
+ *
1266
+ * # Returns
1267
+ * Pointer to the newly created sampling object, or NULL if creation fails
1268
+ *
1269
+ * # Safety
1270
+ * Caller must ensure `points` and `matrix` have correct sizes
1271
+ */
1272
+
1273
+ struct spir_sampling *spir_tau_sampling_new_with_matrix(int order,
1274
+ int statistics,
1275
+ int basis_size,
1276
+ int num_points,
1277
+ const double *points,
1278
+ const double *matrix,
1279
+ StatusCode *status);
1280
+
1281
+ /**
1282
+ * Creates a new Matsubara sampling object with custom sampling points and pre-computed matrix
1283
+ *
1284
+ * # Arguments
1285
+ * * `order` - Memory layout order (SPIR_ORDER_ROW_MAJOR or SPIR_ORDER_COLUMN_MAJOR)
1286
+ * * `statistics` - Statistics type (SPIR_STATISTICS_FERMIONIC or SPIR_STATISTICS_BOSONIC)
1287
+ * * `basis_size` - Basis size
1288
+ * * `positive_only` - If true, only positive frequencies are used
1289
+ * * `num_points` - Number of sampling points
1290
+ * * `points` - Array of Matsubara frequency indices (n)
1291
+ * * `matrix` - Pre-computed complex matrix (num_points x basis_size)
1292
+ * * `status` - Pointer to store the status code
1293
+ *
1294
+ * # Returns
1295
+ * Pointer to the newly created sampling object, or NULL if creation fails
1296
+ *
1297
+ * # Safety
1298
+ * Caller must ensure `points` and `matrix` have correct sizes
1299
+ */
1300
+
1301
+ struct spir_sampling *spir_matsu_sampling_new_with_matrix(int order,
1302
+ int statistics,
1303
+ int basis_size,
1304
+ bool positive_only,
1305
+ int num_points,
1306
+ const int64_t *points,
1307
+ const struct Complex64 *matrix,
1308
+ StatusCode *status);
1309
+
1310
+ /**
1311
+ * Gets the number of sampling points in a sampling object.
1312
+ *
1313
+ * This function returns the number of sampling points used in the specified
1314
+ * sampling object. This number is needed to allocate arrays of the correct size
1315
+ * when retrieving the actual sampling points.
1316
+ *
1317
+ * # Arguments
1318
+ *
1319
+ * * `s` - Pointer to the sampling object.
1320
+ * * `num_points` - Pointer to store the number of sampling points.
1321
+ *
1322
+ * # Returns
1323
+ *
1324
+ * A status code:
1325
+ * - `0` ([`SPIR_COMPUTATION_SUCCESS`]) on success
1326
+ * - A non-zero error code on failure
1327
+ *
1328
+ * # See also
1329
+ *
1330
+ * - [`spir_sampling_get_taus`]
1331
+ * - [`spir_sampling_get_matsus`]
1332
+ */
1333
+ StatusCode spir_sampling_get_npoints(const struct spir_sampling *s, int *num_points);
1334
+
1335
+ /**
1336
+ * Gets the imaginary time (τ) sampling points used in the specified sampling object.
1337
+ *
1338
+ * This function fills the provided array with the imaginary time (τ) sampling points used in the specified sampling object.
1339
+ * The array must be pre-allocated with sufficient size (use [`spir_sampling_get_npoints`] to determine the required size).
1340
+ *
1341
+ * # Arguments
1342
+ *
1343
+ * * `s` - Pointer to the sampling object.
1344
+ * * `points` - Pre-allocated array to store the τ sampling points.
1345
+ *
1346
+ * # Returns
1347
+ *
1348
+ * An integer status code:
1349
+ * - `0` ([`SPIR_COMPUTATION_SUCCESS`]) on success
1350
+ * - A non-zero error code on failure
1351
+ *
1352
+ * # Notes
1353
+ *
1354
+ * The array must be pre-allocated with size >= [`spir_sampling_get_npoints`](spir_sampling_get_npoints).
1355
+ *
1356
+ * # See also
1357
+ *
1358
+ * - [`spir_sampling_get_npoints`]
1359
+ */
1360
+
1361
+ StatusCode spir_sampling_get_taus(const struct spir_sampling *s,
1362
+ double *points);
1363
+
1364
+ /**
1365
+ * Gets the Matsubara frequency sampling points
1366
+ */
1367
+ StatusCode spir_sampling_get_matsus(const struct spir_sampling *s, int64_t *points);
1368
+
1369
+ /**
1370
+ * Gets the condition number of the sampling matrix.
1371
+ *
1372
+ * This function returns the condition number of the sampling matrix used in the
1373
+ * specified sampling object. The condition number is a measure of how well-
1374
+ * conditioned the sampling matrix is.
1375
+ *
1376
+ * # Parameters
1377
+ * - `s`: Pointer to the sampling object.
1378
+ * - `cond_num`: Pointer to store the condition number.
1379
+ *
1380
+ * # Returns
1381
+ * An integer status code:
1382
+ * - 0 (`SPIR_COMPUTATION_SUCCESS`) on success
1383
+ * - Non-zero error code on failure
1384
+ *
1385
+ * # Notes
1386
+ * - A large condition number indicates that the sampling matrix is ill-conditioned,
1387
+ * which may lead to numerical instability in transformations.
1388
+ * - The condition number is the ratio of the largest to smallest singular value
1389
+ * of the sampling matrix.
1390
+ */
1391
+ StatusCode spir_sampling_get_cond_num(const struct spir_sampling *s, double *cond_num);
1392
+
1393
+ /**
1394
+ * Evaluates basis coefficients at sampling points (double to double version).
1395
+ *
1396
+ * Transforms basis coefficients to values at sampling points, where both input
1397
+ * and output are real (double precision) values. The operation can be performed
1398
+ * along any dimension of a multidimensional array.
1399
+ *
1400
+ * # Arguments
1401
+ *
1402
+ * * `s` - Pointer to the sampling object
1403
+ * * `order` - Memory layout order (`SPIR_ORDER_ROW_MAJOR` or `SPIR_ORDER_COLUMN_MAJOR`)
1404
+ * * `ndim` - Number of dimensions in the input/output arrays
1405
+ * * `input_dims` - Array of dimension sizes
1406
+ * * `target_dim` - Target dimension for the transformation (0-based)
1407
+ * * `input` - Input array of basis coefficients
1408
+ * * `out` - Output array for the evaluated values at sampling points
1409
+ *
1410
+ * # Returns
1411
+ *
1412
+ * An integer status code:
1413
+ * - `0` (`SPIR_COMPUTATION_SUCCESS`) on success
1414
+ * - A non-zero error code on failure
1415
+ *
1416
+ * # Notes
1417
+ *
1418
+ * - For optimal performance, the target dimension should be either the
1419
+ * first (`0`) or the last (`ndim-1`) dimension to avoid large temporary array allocations
1420
+ * - The output array must be pre-allocated with the correct size
1421
+ * - The input and output arrays must be contiguous in memory
1422
+ * - The transformation is performed using a pre-computed sampling matrix
1423
+ * that is factorized using SVD for efficiency
1424
+ *
1425
+ * # See also
1426
+ * - [`spir_sampling_eval_dz`]
1427
+ * - [`spir_sampling_eval_zz`]
1428
+ * # Note
1429
+ * Supports both row-major and column-major order. Zero-copy implementation.
1430
+ */
1431
+
1432
+ StatusCode spir_sampling_eval_dd(const struct spir_sampling *s,
1433
+ const struct spir_gemm_backend *backend,
1434
+ int order,
1435
+ int ndim,
1436
+ const int *input_dims,
1437
+ int target_dim,
1438
+ const double *input,
1439
+ double *out);
1440
+
1441
+ /**
1442
+ * Evaluate basis coefficients at sampling points (double → complex)
1443
+ *
1444
+ * For Matsubara sampling: transforms real IR coefficients to complex values.
1445
+ * Zero-copy implementation.
1446
+ */
1447
+
1448
+ StatusCode spir_sampling_eval_dz(const struct spir_sampling *s,
1449
+ const struct spir_gemm_backend *backend,
1450
+ int order,
1451
+ int ndim,
1452
+ const int *input_dims,
1453
+ int target_dim,
1454
+ const double *input,
1455
+ struct Complex64 *out);
1456
+
1457
+ /**
1458
+ * Evaluate basis coefficients at sampling points (complex → complex)
1459
+ *
1460
+ * For Matsubara sampling: transforms complex coefficients to complex values.
1461
+ * Zero-copy implementation.
1462
+ */
1463
+
1464
+ StatusCode spir_sampling_eval_zz(const struct spir_sampling *s,
1465
+ const struct spir_gemm_backend *backend,
1466
+ int order,
1467
+ int ndim,
1468
+ const int *input_dims,
1469
+ int target_dim,
1470
+ const struct Complex64 *input,
1471
+ struct Complex64 *out);
1472
+
1473
+ /**
1474
+ * Fits values at sampling points to basis coefficients (double to double version).
1475
+ *
1476
+ * Transforms values at sampling points back to basis coefficients, where both
1477
+ * input and output are real (double precision) values. The operation can be
1478
+ * performed along any dimension of a multidimensional array.
1479
+ *
1480
+ * # Arguments
1481
+ *
1482
+ * * `s` - Pointer to the sampling object
1483
+ * * `backend` - Pointer to the GEMM backend (can be null to use default)
1484
+ * * `order` - Memory layout order (SPIR_ORDER_ROW_MAJOR or SPIR_ORDER_COLUMN_MAJOR)
1485
+ * * `ndim` - Number of dimensions in the input/output arrays
1486
+ * * `input_dims` - Array of dimension sizes
1487
+ * * `target_dim` - Target dimension for the transformation (0-based)
1488
+ * * `input` - Input array of values at sampling points
1489
+ * * `out` - Output array for the fitted basis coefficients
1490
+ *
1491
+ * # Returns
1492
+ *
1493
+ * An integer status code:
1494
+ * * `0` (SPIR_COMPUTATION_SUCCESS) on success
1495
+ * * A non-zero error code on failure
1496
+ *
1497
+ * # Notes
1498
+ *
1499
+ * * The output array must be pre-allocated with the correct size
1500
+ * * This function performs the inverse operation of `spir_sampling_eval_dd`
1501
+ * * The transformation is performed using a pre-computed sampling matrix
1502
+ * that is factorized using SVD for efficiency
1503
+ * * Zero-copy implementation
1504
+ *
1505
+ * # See also
1506
+ *
1507
+ * * [`spir_sampling_eval_dd`]
1508
+ * * [`spir_sampling_fit_zz`]
1509
+ */
1510
+
1511
+ StatusCode spir_sampling_fit_dd(const struct spir_sampling *s,
1512
+ const struct spir_gemm_backend *backend,
1513
+ int order,
1514
+ int ndim,
1515
+ const int *input_dims,
1516
+ int target_dim,
1517
+ const double *input,
1518
+ double *out);
1519
+
1520
+ /**
1521
+ * Fits values at sampling points to basis coefficients (complex to complex version).
1522
+ *
1523
+ * For more details, see [`spir_sampling_fit_dd`]
1524
+ * Zero-copy implementation for Tau and Matsubara (full).
1525
+ * MatsubaraPositiveOnly requires intermediate storage for real→complex conversion.
1526
+ */
1527
+
1528
+ StatusCode spir_sampling_fit_zz(const struct spir_sampling *s,
1529
+ const struct spir_gemm_backend *backend,
1530
+ int order,
1531
+ int ndim,
1532
+ const int *input_dims,
1533
+ int target_dim,
1534
+ const struct Complex64 *input,
1535
+ struct Complex64 *out);
1536
+
1537
+ /**
1538
+ * Fit basis coefficients from Matsubara sampling points (complex input, real output)
1539
+ *
1540
+ * This function fits basis coefficients from Matsubara sampling points
1541
+ * using complex input and real output.
1542
+ *
1543
+ * # Supported Sampling Types
1544
+ *
1545
+ * - **Matsubara (full)**: ✅ Supported (takes real part of fitted complex coefficients)
1546
+ * - **Matsubara (positive_only)**: ✅ Supported
1547
+ * - **Tau**: ❌ Not supported (use `spir_sampling_fit_dd` instead)
1548
+ *
1549
+ * # Notes
1550
+ *
1551
+ * For full-range Matsubara sampling, this function fits complex coefficients
1552
+ * internally and returns their real parts. This is physically correct for
1553
+ * Green's functions where IR coefficients are guaranteed to be real by symmetry.
1554
+ *
1555
+ * Zero-copy implementation.
1556
+ *
1557
+ * # Arguments
1558
+ *
1559
+ * * `s` - Pointer to the sampling object (must be Matsubara)
1560
+ * * `backend` - Pointer to the GEMM backend (can be null to use default)
1561
+ * * `order` - Memory layout order (SPIR_ORDER_COLUMN_MAJOR or SPIR_ORDER_ROW_MAJOR)
1562
+ * * `ndim` - Number of dimensions in the input/output arrays
1563
+ * * `input_dims` - Array of dimension sizes
1564
+ * * `target_dim` - Target dimension for the transformation (0-based)
1565
+ * * `input` - Input array (complex)
1566
+ * * `out` - Output array (real)
1567
+ *
1568
+ * # Returns
1569
+ *
1570
+ * - `SPIR_COMPUTATION_SUCCESS` on success
1571
+ * - `SPIR_NOT_SUPPORTED` if the sampling type doesn't support this operation
1572
+ * - Other error codes on failure
1573
+ *
1574
+ * # See also
1575
+ *
1576
+ * * [`spir_sampling_fit_zz`]
1577
+ * * [`spir_sampling_fit_dd`]
1578
+ */
1579
+
1580
+ StatusCode spir_sampling_fit_zd(const struct spir_sampling *s,
1581
+ const struct spir_gemm_backend *backend,
1582
+ int order,
1583
+ int ndim,
1584
+ const int *input_dims,
1585
+ int target_dim,
1586
+ const struct Complex64 *input,
1587
+ double *out);
1588
+
1589
+ /**
1590
+ * Manual release function (replaces macro-generated one)
1591
+ */
1592
+ void spir_sve_result_release(struct spir_sve_result *sve);
1593
+
1594
+ /**
1595
+ * Manual clone function (replaces macro-generated one)
1596
+ */
1597
+ struct spir_sve_result *spir_sve_result_clone(const struct spir_sve_result *src);
1598
+
1599
+ /**
1600
+ * Manual is_assigned function (replaces macro-generated one)
1601
+ */
1602
+ int32_t spir_sve_result_is_assigned(const struct spir_sve_result *obj);
1603
+
1604
+ /**
1605
+ * Compute Singular Value Expansion (SVE) of a kernel (libsparseir compatible)
1606
+ *
1607
+ * # Arguments
1608
+ * * `k` - Kernel object
1609
+ * * `epsilon` - Accuracy target for the basis
1610
+ * * `lmax` - Maximum number of Legendre polynomials (currently ignored, auto-determined)
1611
+ * * `n_gauss` - Number of Gauss points for integration (currently ignored, auto-determined)
1612
+ * * `Twork` - Working precision: 0=Float64, 1=Float64x2, -1=Auto
1613
+ * * `status` - Pointer to store status code
1614
+ *
1615
+ * # Returns
1616
+ * * Pointer to SVE result, or NULL on failure
1617
+ *
1618
+ * # Safety
1619
+ * The caller must ensure `status` is a valid pointer.
1620
+ *
1621
+ * # Note
1622
+ * Parameters `lmax` and `n_gauss` are accepted for libsparseir compatibility but
1623
+ * currently ignored. The Rust implementation automatically determines optimal values.
1624
+ * The cutoff is automatically set to 2*sqrt(machine_epsilon) internally.
1625
+ */
1626
+
1627
+ struct spir_sve_result *spir_sve_result_new(const struct spir_kernel *k,
1628
+ double epsilon,
1629
+ int _lmax,
1630
+ int _n_gauss,
1631
+ int twork,
1632
+ StatusCode *status);
1633
+
1634
+ /**
1635
+ * Get the number of singular values in an SVE result
1636
+ *
1637
+ * # Arguments
1638
+ * * `sve` - SVE result object
1639
+ * * `size` - Pointer to store the size
1640
+ *
1641
+ * # Returns
1642
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
1643
+ * * `SPIR_INVALID_ARGUMENT` (-6) if sve or size is null
1644
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
1645
+ */
1646
+ StatusCode spir_sve_result_get_size(const struct spir_sve_result *sve, int *size);
1647
+
1648
+ /**
1649
+ * Truncate an SVE result based on epsilon and max_size
1650
+ *
1651
+ * This function creates a new SVE result containing only the singular values
1652
+ * that are larger than `epsilon * s[0]`, where `s[0]` is the largest singular value.
1653
+ * The result can also be limited to a maximum size.
1654
+ *
1655
+ * # Arguments
1656
+ * * `sve` - Source SVE result object
1657
+ * * `epsilon` - Relative threshold for truncation (singular values < epsilon * s[0] are removed)
1658
+ * * `max_size` - Maximum number of singular values to keep (-1 for no limit)
1659
+ * * `status` - Pointer to store status code
1660
+ *
1661
+ * # Returns
1662
+ * * Pointer to new truncated SVE result, or NULL on failure
1663
+ * * Status code:
1664
+ * - `SPIR_COMPUTATION_SUCCESS` (0) on success
1665
+ * - `SPIR_INVALID_ARGUMENT` (-6) if sve or status is null, or epsilon is invalid
1666
+ * - `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
1667
+ *
1668
+ * # Safety
1669
+ * The caller must ensure `status` is a valid pointer.
1670
+ * The returned pointer must be freed with `spir_sve_result_release()`.
1671
+ *
1672
+ * # Example (C)
1673
+ * ```c
1674
+ * spir_sve_result* sve = spir_sve_result_new(kernel, 1e-10, 0, 0, -1, &status);
1675
+ *
1676
+ * // Truncate to keep only singular values > 1e-8 * s[0], max 50 values
1677
+ * spir_sve_result* sve_truncated = spir_sve_result_truncate(sve, 1e-8, 50, &status);
1678
+ *
1679
+ * // Use truncated result...
1680
+ *
1681
+ * spir_sve_result_release(sve_truncated);
1682
+ * spir_sve_result_release(sve);
1683
+ * ```
1684
+ */
1685
+
1686
+ struct spir_sve_result *spir_sve_result_truncate(const struct spir_sve_result *sve,
1687
+ double epsilon,
1688
+ int max_size,
1689
+ StatusCode *status);
1690
+
1691
+ /**
1692
+ * Get singular values from an SVE result
1693
+ *
1694
+ * # Arguments
1695
+ * * `sve` - SVE result object
1696
+ * * `svals` - Pre-allocated array to store singular values (size must be >= result size)
1697
+ *
1698
+ * # Returns
1699
+ * * `SPIR_COMPUTATION_SUCCESS` (0) on success
1700
+ * * `SPIR_INVALID_ARGUMENT` (-6) if sve or svals is null
1701
+ * * `SPIR_INTERNAL_ERROR` (-7) if internal panic occurs
1702
+ */
1703
+ StatusCode spir_sve_result_get_svals(const struct spir_sve_result *sve, double *svals);
1704
+
1705
+ /**
1706
+ * Create a SVE result from a discretized kernel matrix
1707
+ *
1708
+ * This function performs singular value expansion (SVE) on a discretized kernel
1709
+ * matrix K. The matrix K should already be in the appropriate form (no weight
1710
+ * application needed). The function supports both double and DDouble precision
1711
+ * based on whether K_low is provided.
1712
+ *
1713
+ * # Arguments
1714
+ * * `K_high` - High part of the kernel matrix (required, size: nx * ny)
1715
+ * * `K_low` - Low part of the kernel matrix (optional, nullptr for double precision)
1716
+ * * `nx` - Number of rows in the matrix
1717
+ * * `ny` - Number of columns in the matrix
1718
+ * * `order` - Memory layout (SPIR_ORDER_ROW_MAJOR or SPIR_ORDER_COLUMN_MAJOR)
1719
+ * * `segments_x` - X-direction segments (array of boundary points, size: n_segments_x + 1)
1720
+ * * `n_segments_x` - Number of segments in x direction (boundary points - 1)
1721
+ * * `segments_y` - Y-direction segments (array of boundary points, size: n_segments_y + 1)
1722
+ * * `n_segments_y` - Number of segments in y direction (boundary points - 1)
1723
+ * * `n_gauss` - Number of Gauss points per segment
1724
+ * * `epsilon` - Target accuracy
1725
+ * * `status` - Pointer to store status code
1726
+ *
1727
+ * # Returns
1728
+ * Pointer to SVE result on success, nullptr on failure
1729
+ */
1730
+
1731
+ struct spir_sve_result *spir_sve_result_from_matrix(const double *K_high,
1732
+ const double *K_low,
1733
+ int nx,
1734
+ int ny,
1735
+ int order,
1736
+ const double *segments_x,
1737
+ int n_segments_x,
1738
+ const double *segments_y,
1739
+ int n_segments_y,
1740
+ int n_gauss,
1741
+ double epsilon,
1742
+ StatusCode *status);
1743
+
1744
+ /**
1745
+ * Create a SVE result from centrosymmetric discretized kernel matrices
1746
+ *
1747
+ * This function performs singular value expansion (SVE) on centrosymmetric
1748
+ * discretized kernel matrices using even/odd symmetry decomposition. The matrices
1749
+ * K_even and K_odd should already be in the appropriate form (no weight
1750
+ * application needed). The function supports both double and DDouble precision
1751
+ * based on whether K_low is provided.
1752
+ *
1753
+ * # Arguments
1754
+ * * `K_even_high` - High part of the even-symmetry kernel matrix (required, size: nx * ny)
1755
+ * * `K_even_low` - Low part of the even-symmetry kernel matrix (optional, nullptr for double precision)
1756
+ * * `K_odd_high` - High part of the odd-symmetry kernel matrix (required, size: nx * ny)
1757
+ * * `K_odd_low` - Low part of the odd-symmetry kernel matrix (optional, nullptr for double precision)
1758
+ * * `nx` - Number of rows in the matrix
1759
+ * * `ny` - Number of columns in the matrix
1760
+ * * `order` - Memory layout (SPIR_ORDER_ROW_MAJOR or SPIR_ORDER_COLUMN_MAJOR)
1761
+ * * `segments_x` - X-direction segments (array of boundary points, size: n_segments_x + 1)
1762
+ * * `n_segments_x` - Number of segments in x direction (boundary points - 1)
1763
+ * * `segments_y` - Y-direction segments (array of boundary points, size: n_segments_y + 1)
1764
+ * * `n_segments_y` - Number of segments in y direction (boundary points - 1)
1765
+ * * `n_gauss` - Number of Gauss points per segment
1766
+ * * `epsilon` - Target accuracy
1767
+ * * `status` - Pointer to store status code
1768
+ *
1769
+ * # Returns
1770
+ * Pointer to SVE result on success, nullptr on failure
1771
+ */
1772
+
1773
+ struct spir_sve_result *spir_sve_result_from_matrix_centrosymmetric(const double *K_even_high,
1774
+ const double *K_even_low,
1775
+ const double *K_odd_high,
1776
+ const double *K_odd_low,
1777
+ int nx,
1778
+ int ny,
1779
+ int order,
1780
+ const double *segments_x,
1781
+ int n_segments_x,
1782
+ const double *segments_y,
1783
+ int n_segments_y,
1784
+ int n_gauss,
1785
+ double epsilon,
1786
+ StatusCode *status);
1787
+
1788
+ /**
1789
+ * Choose the working type (Twork) based on epsilon value
1790
+ *
1791
+ * This function determines the appropriate working precision type based on the
1792
+ * target accuracy epsilon. It follows the same logic as SPIR_TWORK_AUTO:
1793
+ * - Returns SPIR_TWORK_FLOAT64X2 if epsilon < 1e-8 or epsilon is NaN
1794
+ * - Returns SPIR_TWORK_FLOAT64 otherwise
1795
+ *
1796
+ * # Arguments
1797
+ * * `epsilon` - Target accuracy (must be non-negative, or NaN for auto-selection)
1798
+ *
1799
+ * # Returns
1800
+ * Working type constant:
1801
+ * - SPIR_TWORK_FLOAT64 (0): Use double precision (64-bit)
1802
+ * - SPIR_TWORK_FLOAT64X2 (1): Use extended precision (128-bit)
1803
+ */
1804
+ int spir_choose_working_type(double epsilon);
1805
+
1806
+ /**
1807
+ * Compute piecewise Gauss-Legendre quadrature rule (double precision)
1808
+ *
1809
+ * Generates a piecewise Gauss-Legendre quadrature rule with n points per segment.
1810
+ * The rule is concatenated across all segments, with points and weights properly
1811
+ * scaled for each segment interval.
1812
+ *
1813
+ * # Arguments
1814
+ * * `n` - Number of Gauss points per segment (must be >= 1)
1815
+ * * `segments` - Array of segment boundaries (n_segments + 1 elements).
1816
+ * Must be monotonically increasing.
1817
+ * * `n_segments` - Number of segments (must be >= 1)
1818
+ * * `x` - Output array for Gauss points (size n * n_segments). Must be pre-allocated.
1819
+ * * `w` - Output array for Gauss weights (size n * n_segments). Must be pre-allocated.
1820
+ * * `status` - Pointer to store the status code
1821
+ *
1822
+ * # Returns
1823
+ * Status code:
1824
+ * - SPIR_COMPUTATION_SUCCESS (0) on success
1825
+ * - Non-zero error code on failure
1826
+ */
1827
+
1828
+ StatusCode spir_gauss_legendre_rule_piecewise_double(int n,
1829
+ const double *segments,
1830
+ int n_segments,
1831
+ double *x,
1832
+ double *w,
1833
+ StatusCode *status);
1834
+
1835
+ /**
1836
+ * Compute piecewise Gauss-Legendre quadrature rule (DDouble precision)
1837
+ *
1838
+ * Generates a piecewise Gauss-Legendre quadrature rule with n points per segment,
1839
+ * computed using extended precision (DDouble). Returns high and low parts separately
1840
+ * for maximum precision.
1841
+ *
1842
+ * # Arguments
1843
+ * * `n` - Number of Gauss points per segment (must be >= 1)
1844
+ * * `segments` - Array of segment boundaries (n_segments + 1 elements).
1845
+ * Must be monotonically increasing.
1846
+ * * `n_segments` - Number of segments (must be >= 1)
1847
+ * * `x_high` - Output array for high part of Gauss points (size n * n_segments).
1848
+ * Must be pre-allocated.
1849
+ * * `x_low` - Output array for low part of Gauss points (size n * n_segments).
1850
+ * Must be pre-allocated.
1851
+ * * `w_high` - Output array for high part of Gauss weights (size n * n_segments).
1852
+ * Must be pre-allocated.
1853
+ * * `w_low` - Output array for low part of Gauss weights (size n * n_segments).
1854
+ * Must be pre-allocated.
1855
+ * * `status` - Pointer to store the status code
1856
+ *
1857
+ * # Returns
1858
+ * Status code:
1859
+ * - SPIR_COMPUTATION_SUCCESS (0) on success
1860
+ * - Non-zero error code on failure
1861
+ */
1862
+
1863
+ StatusCode spir_gauss_legendre_rule_piecewise_ddouble(int n,
1864
+ const double *segments,
1865
+ int n_segments,
1866
+ double *x_high,
1867
+ double *x_low,
1868
+ double *w_high,
1869
+ double *w_low,
1870
+ StatusCode *status);
1871
+
1872
+ #ifdef __cplusplus
1873
+ } // extern "C"
1874
+ #endif // __cplusplus