Skip to main content

flodl_sys/
lib.rs

1//! Raw FFI bindings to the libtorch C++ shim.
2//!
3//! Every function that can fail returns a `*mut i8` error string (caller
4//! must free it with [`flodl_free_string`]). A null pointer means success.
5//!
6//! `FlodlTensor` is an opaque `*mut c_void` handle to a heap-allocated
7//! `torch::Tensor`. Caller owns it and must free with [`flodl_free_tensor`].
8
9use std::ffi::c_void;
10
11/// Opaque handle to a `torch::Tensor` on the C++ side.
12pub type FlodlTensor = *mut c_void;
13
14// --- DType constants (must match shim.h) ---
15pub const FLODL_FLOAT16: i32 = 5;
16pub const FLODL_BFLOAT16: i32 = 15;
17pub const FLODL_FLOAT32: i32 = 6;
18pub const FLODL_FLOAT64: i32 = 7;
19pub const FLODL_INT32: i32 = 3;
20pub const FLODL_INT64: i32 = 4;
21
22// --- Device constants (must match shim.h) ---
23pub const FLODL_CPU: i32 = 0;
24pub const FLODL_CUDA: i32 = 1;
25
26unsafe extern "C" {
27    // --- Tensor creation ---
28
29    pub fn flodl_zeros(
30        shape: *mut i64, ndim: i32, dtype: i32,
31        device_type: i32, device_index: i32,
32        result: *mut FlodlTensor,
33    ) -> *mut i8;
34
35    pub fn flodl_ones(
36        shape: *mut i64, ndim: i32, dtype: i32,
37        device_type: i32, device_index: i32,
38        result: *mut FlodlTensor,
39    ) -> *mut i8;
40
41    pub fn flodl_rand(
42        shape: *mut i64, ndim: i32, dtype: i32,
43        device_type: i32, device_index: i32,
44        result: *mut FlodlTensor,
45    ) -> *mut i8;
46
47    pub fn flodl_randn(
48        shape: *mut i64, ndim: i32, dtype: i32,
49        device_type: i32, device_index: i32,
50        result: *mut FlodlTensor,
51    ) -> *mut i8;
52
53    pub fn flodl_from_blob(
54        data: *mut c_void, shape: *mut i64, ndim: i32,
55        dtype: i32, device_type: i32, device_index: i32,
56        result: *mut FlodlTensor,
57    ) -> *mut i8;
58
59    pub fn flodl_linspace(
60        start: f64, end: f64, steps: i64,
61        dtype: i32, device_type: i32, device_index: i32,
62        result: *mut FlodlTensor,
63    ) -> *mut i8;
64
65    pub fn flodl_arange(
66        start: f64, end: f64, step: f64,
67        dtype: i32, device_type: i32, device_index: i32,
68        result: *mut FlodlTensor,
69    ) -> *mut i8;
70
71    pub fn flodl_expand(
72        t: FlodlTensor, new_shape: *mut i64, ndim: i32,
73        result: *mut FlodlTensor,
74    ) -> *mut i8;
75
76    // --- Tensor lifecycle ---
77
78    pub fn flodl_free_tensor(t: FlodlTensor);
79    pub fn flodl_shallow_clone(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
80
81    // --- Tensor metadata ---
82
83    pub fn flodl_ndim(t: FlodlTensor) -> i32;
84    pub fn flodl_shape(t: FlodlTensor, dim: i32) -> i64;
85    pub fn flodl_dtype(t: FlodlTensor) -> i32;
86    pub fn flodl_device_type(t: FlodlTensor) -> i32;
87    pub fn flodl_device_index(t: FlodlTensor) -> i32;
88    pub fn flodl_numel(t: FlodlTensor) -> i64;
89
90    // --- Data access ---
91
92    pub fn flodl_copy_data(
93        t: FlodlTensor, buffer: *mut c_void, buffer_bytes: i64,
94    ) -> *mut i8;
95
96    // --- Arithmetic ---
97
98    pub fn flodl_add(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
99    pub fn flodl_sub(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
100    pub fn flodl_mul(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
101    pub fn flodl_div(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
102    pub fn flodl_matmul(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
103
104    pub fn flodl_add_scalar(
105        t: FlodlTensor, scalar: f64, result: *mut FlodlTensor,
106    ) -> *mut i8;
107
108    pub fn flodl_mul_scalar(
109        t: FlodlTensor, scalar: f64, result: *mut FlodlTensor,
110    ) -> *mut i8;
111
112    pub fn flodl_div_scalar(
113        t: FlodlTensor, scalar: f64, result: *mut FlodlTensor,
114    ) -> *mut i8;
115
116    pub fn flodl_neg(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
117
118    // --- Activations ---
119
120    pub fn flodl_relu(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
121    pub fn flodl_sigmoid(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
122    pub fn flodl_tanh_op(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
123    pub fn flodl_softmax(t: FlodlTensor, dim: i32, result: *mut FlodlTensor) -> *mut i8;
124    pub fn flodl_log_softmax(t: FlodlTensor, dim: i32, result: *mut FlodlTensor) -> *mut i8;
125    pub fn flodl_gelu(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
126    pub fn flodl_gelu_tanh(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
127    pub fn flodl_silu(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
128    pub fn flodl_leaky_relu(
129        t: FlodlTensor, negative_slope: f64, result: *mut FlodlTensor,
130    ) -> *mut i8;
131    pub fn flodl_elu(t: FlodlTensor, alpha: f64, result: *mut FlodlTensor) -> *mut i8;
132    pub fn flodl_softplus(
133        t: FlodlTensor, beta: f64, threshold: f64, result: *mut FlodlTensor,
134    ) -> *mut i8;
135    pub fn flodl_mish(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
136    pub fn flodl_selu(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
137    pub fn flodl_hardswish(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
138    pub fn flodl_hardsigmoid(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
139    pub fn flodl_prelu(t: FlodlTensor, weight: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
140
141    // --- Layer normalization ---
142
143    pub fn flodl_native_layer_norm(
144        input: FlodlTensor, weight: FlodlTensor, bias: FlodlTensor,
145        normalized_size: i64, eps: f64,
146        output: *mut FlodlTensor, mean: *mut FlodlTensor, rstd: *mut FlodlTensor,
147    ) -> *mut i8;
148
149    // --- Group normalization ---
150
151    pub fn flodl_group_norm(
152        input: FlodlTensor, num_groups: i64,
153        weight: FlodlTensor, bias: FlodlTensor,
154        eps: f64, result: *mut FlodlTensor,
155    ) -> *mut i8;
156
157    // --- Element-wise math ---
158
159    pub fn flodl_exp(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
160    pub fn flodl_log(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
161    pub fn flodl_sqrt(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
162    pub fn flodl_abs(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
163    pub fn flodl_triu(t: FlodlTensor, diagonal: i64, result: *mut FlodlTensor) -> *mut i8;
164    pub fn flodl_tril(t: FlodlTensor, diagonal: i64, result: *mut FlodlTensor) -> *mut i8;
165
166    pub fn flodl_pow_scalar(
167        t: FlodlTensor, exponent: f64, result: *mut FlodlTensor,
168    ) -> *mut i8;
169
170    pub fn flodl_clamp(
171        t: FlodlTensor, min_val: f64, max_val: f64, result: *mut FlodlTensor,
172    ) -> *mut i8;
173
174    pub fn flodl_clamp_min(
175        t: FlodlTensor, min_val: f64, result: *mut FlodlTensor,
176    ) -> *mut i8;
177
178    pub fn flodl_clamp_max(
179        t: FlodlTensor, max_val: f64, result: *mut FlodlTensor,
180    ) -> *mut i8;
181
182    pub fn flodl_log1p(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
183    pub fn flodl_expm1(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
184    pub fn flodl_log2(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
185    pub fn flodl_log10(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
186
187    // --- Reductions ---
188
189    pub fn flodl_sum(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
190    pub fn flodl_mean(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
191
192    pub fn flodl_sum_dim(
193        t: FlodlTensor, dim: i32, keepdim: i32, result: *mut FlodlTensor,
194    ) -> *mut i8;
195
196    pub fn flodl_mean_dim(
197        t: FlodlTensor, dim: i32, keepdim: i32, result: *mut FlodlTensor,
198    ) -> *mut i8;
199
200    pub fn flodl_prod(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
201
202    pub fn flodl_prod_dim(
203        t: FlodlTensor, dim: i32, keepdim: i32, result: *mut FlodlTensor,
204    ) -> *mut i8;
205
206    pub fn flodl_cumsum(
207        t: FlodlTensor, dim: i32, result: *mut FlodlTensor,
208    ) -> *mut i8;
209
210    pub fn flodl_logsumexp(
211        t: FlodlTensor, dim: i32, keepdim: i32, result: *mut FlodlTensor,
212    ) -> *mut i8;
213
214    pub fn flodl_min(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
215    pub fn flodl_max(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
216    pub fn flodl_norm(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
217
218    pub fn flodl_min_dim(
219        t: FlodlTensor, dim: i32, keepdim: i32, result: *mut FlodlTensor,
220    ) -> *mut i8;
221
222    pub fn flodl_max_dim(
223        t: FlodlTensor, dim: i32, keepdim: i32, result: *mut FlodlTensor,
224    ) -> *mut i8;
225
226    pub fn flodl_argmax(
227        t: FlodlTensor, dim: i32, keepdim: i32, result: *mut FlodlTensor,
228    ) -> *mut i8;
229
230    // --- Comparison (return float masks: 0.0 or 1.0) ---
231
232    pub fn flodl_gt_scalar(
233        t: FlodlTensor, scalar: f64, result: *mut FlodlTensor,
234    ) -> *mut i8;
235
236    pub fn flodl_ge_scalar(
237        t: FlodlTensor, scalar: f64, result: *mut FlodlTensor,
238    ) -> *mut i8;
239
240    pub fn flodl_le_scalar(
241        t: FlodlTensor, scalar: f64, result: *mut FlodlTensor,
242    ) -> *mut i8;
243
244    pub fn flodl_lt_scalar(
245        t: FlodlTensor, scalar: f64, result: *mut FlodlTensor,
246    ) -> *mut i8;
247
248    pub fn flodl_eq_scalar(
249        t: FlodlTensor, scalar: f64, result: *mut FlodlTensor,
250    ) -> *mut i8;
251
252    pub fn flodl_ne_scalar(
253        t: FlodlTensor, scalar: f64, result: *mut FlodlTensor,
254    ) -> *mut i8;
255
256    // --- Boolean / detection (return float masks) ---
257
258    pub fn flodl_isnan(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
259    pub fn flodl_isinf(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
260    pub fn flodl_logical_and(
261        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
262    ) -> *mut i8;
263    pub fn flodl_logical_or(
264        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
265    ) -> *mut i8;
266    pub fn flodl_logical_not(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
267    pub fn flodl_any(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
268    pub fn flodl_all(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
269
270    // --- Shape operations ---
271
272    pub fn flodl_reshape(
273        t: FlodlTensor, shape: *mut i64, ndim: i32, result: *mut FlodlTensor,
274    ) -> *mut i8;
275
276    pub fn flodl_transpose(
277        t: FlodlTensor, dim0: i32, dim1: i32, result: *mut FlodlTensor,
278    ) -> *mut i8;
279
280    pub fn flodl_permute(
281        t: FlodlTensor, dims: *mut i64, ndim: i32, result: *mut FlodlTensor,
282    ) -> *mut i8;
283
284    pub fn flodl_select(
285        t: FlodlTensor, dim: i32, index: i64, result: *mut FlodlTensor,
286    ) -> *mut i8;
287
288    pub fn flodl_narrow(
289        t: FlodlTensor, dim: i32, start: i64, length: i64,
290        result: *mut FlodlTensor,
291    ) -> *mut i8;
292
293    pub fn flodl_squeeze(
294        t: FlodlTensor, dim: i32, result: *mut FlodlTensor,
295    ) -> *mut i8;
296
297    pub fn flodl_unsqueeze(
298        t: FlodlTensor, dim: i32, result: *mut FlodlTensor,
299    ) -> *mut i8;
300
301    pub fn flodl_flatten(
302        t: FlodlTensor, start_dim: i32, end_dim: i32, result: *mut FlodlTensor,
303    ) -> *mut i8;
304
305    // --- Scatter ---
306
307    pub fn flodl_select_scatter(
308        input: FlodlTensor, src: FlodlTensor, dim: i32, index: i64,
309        result: *mut FlodlTensor,
310    ) -> *mut i8;
311
312    pub fn flodl_narrow_scatter(
313        input: FlodlTensor, src: FlodlTensor, dim: i32, start: i64,
314        result: *mut FlodlTensor,
315    ) -> *mut i8;
316
317    // --- Indexing ---
318
319    pub fn flodl_index_select(
320        t: FlodlTensor, dim: i32, index: FlodlTensor,
321        result: *mut FlodlTensor,
322    ) -> *mut i8;
323
324    pub fn flodl_index_add(
325        t: FlodlTensor, dim: i32, index: FlodlTensor, src: FlodlTensor,
326        result: *mut FlodlTensor,
327    ) -> *mut i8;
328
329    // --- Concatenation ---
330
331    pub fn flodl_cat2(
332        a: FlodlTensor, b: FlodlTensor, dim: i32, result: *mut FlodlTensor,
333    ) -> *mut i8;
334
335    pub fn flodl_cat(
336        tensors: *mut FlodlTensor, count: i32, dim: i32, result: *mut FlodlTensor,
337    ) -> *mut i8;
338
339    pub fn flodl_stack(
340        tensors: *mut FlodlTensor, count: i32, dim: i32, result: *mut FlodlTensor,
341    ) -> *mut i8;
342
343    // --- Masking ---
344
345    pub fn flodl_masked_fill(
346        t: FlodlTensor, mask: FlodlTensor, value: f64,
347        result: *mut FlodlTensor,
348    ) -> *mut i8;
349
350    // --- Conditional ---
351
352    pub fn flodl_where(
353        condition: FlodlTensor, x: FlodlTensor, y: FlodlTensor,
354        result: *mut FlodlTensor,
355    ) -> *mut i8;
356
357    // --- Like constructors ---
358
359    pub fn flodl_zeros_like(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
360    pub fn flodl_ones_like(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
361    pub fn flodl_full_like(
362        t: FlodlTensor, value: f64, result: *mut FlodlTensor,
363    ) -> *mut i8;
364    pub fn flodl_rand_like(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
365    pub fn flodl_randn_like(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
366
367    // --- Tensor creation (tier 2) ---
368
369    pub fn flodl_randint(
370        low: i64, high: i64, shape: *mut i64, ndim: i32,
371        dtype: i32, device_type: i32, device_index: i32,
372        result: *mut FlodlTensor,
373    ) -> *mut i8;
374
375    pub fn flodl_empty(
376        shape: *mut i64, ndim: i32, dtype: i32,
377        device_type: i32, device_index: i32,
378        result: *mut FlodlTensor,
379    ) -> *mut i8;
380
381    pub fn flodl_one_hot(
382        t: FlodlTensor, num_classes: i64,
383        result: *mut FlodlTensor,
384    ) -> *mut i8;
385
386    pub fn flodl_bernoulli(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
387
388    // --- Convolution ---
389
390    pub fn flodl_conv2d(
391        input: FlodlTensor, weight: FlodlTensor, bias: FlodlTensor,
392        stride: *mut i64, padding: *mut i64, dilation: *mut i64,
393        groups: i64, result: *mut FlodlTensor,
394    ) -> *mut i8;
395
396    // --- 1D convolution ---
397
398    pub fn flodl_conv1d(
399        input: FlodlTensor, weight: FlodlTensor, bias: FlodlTensor,
400        stride: i64, padding: i64, dilation: i64,
401        groups: i64, result: *mut FlodlTensor,
402    ) -> *mut i8;
403
404    // --- Transposed convolution ---
405
406    pub fn flodl_conv_transpose2d(
407        input: FlodlTensor, weight: FlodlTensor, bias: FlodlTensor,
408        stride: *mut i64, padding: *mut i64,
409        output_padding: *mut i64, dilation: *mut i64,
410        groups: i64, result: *mut FlodlTensor,
411    ) -> *mut i8;
412
413    // --- Transposed 1D convolution ---
414
415    pub fn flodl_conv_transpose1d(
416        input: FlodlTensor, weight: FlodlTensor, bias: FlodlTensor,
417        stride: i64, padding: i64,
418        output_padding: i64, dilation: i64,
419        groups: i64, result: *mut FlodlTensor,
420    ) -> *mut i8;
421
422    // --- Pooling ---
423
424    pub fn flodl_max_pool2d(
425        input: FlodlTensor, kernel_size: *mut i64,
426        stride: *mut i64, padding: *mut i64, dilation: *mut i64,
427        ceil_mode: i32, result: *mut FlodlTensor,
428    ) -> *mut i8;
429
430    pub fn flodl_avg_pool2d(
431        input: FlodlTensor, kernel_size: *mut i64,
432        stride: *mut i64, padding: *mut i64,
433        ceil_mode: i32, count_include_pad: i32,
434        result: *mut FlodlTensor,
435    ) -> *mut i8;
436
437    pub fn flodl_adaptive_avg_pool2d(
438        input: FlodlTensor, output_size: *mut i64,
439        result: *mut FlodlTensor,
440    ) -> *mut i8;
441
442    pub fn flodl_adaptive_max_pool2d(
443        input: FlodlTensor, output_size: *mut i64,
444        result: *mut FlodlTensor,
445    ) -> *mut i8;
446
447    // --- Unfold / Fold (im2col / col2im) ---
448
449    pub fn flodl_im2col(
450        input: FlodlTensor, kernel_size: *mut i64, dilation: *mut i64,
451        padding: *mut i64, stride: *mut i64, result: *mut FlodlTensor,
452    ) -> *mut i8;
453
454    pub fn flodl_col2im(
455        input: FlodlTensor, output_size: *mut i64,
456        kernel_size: *mut i64, dilation: *mut i64,
457        padding: *mut i64, stride: *mut i64, result: *mut FlodlTensor,
458    ) -> *mut i8;
459
460    // --- 3D convolution ---
461
462    pub fn flodl_conv3d(
463        input: FlodlTensor, weight: FlodlTensor, bias: FlodlTensor,
464        stride: *mut i64, padding: *mut i64, dilation: *mut i64,
465        groups: i64, result: *mut FlodlTensor,
466    ) -> *mut i8;
467
468    pub fn flodl_conv_transpose3d(
469        input: FlodlTensor, weight: FlodlTensor, bias: FlodlTensor,
470        stride: *mut i64, padding: *mut i64, output_padding: *mut i64,
471        dilation: *mut i64, groups: i64, result: *mut FlodlTensor,
472    ) -> *mut i8;
473
474    // --- 1D pooling ---
475
476    pub fn flodl_max_pool1d(
477        input: FlodlTensor, kernel_size: i64,
478        stride: i64, padding: i64, dilation: i64,
479        ceil_mode: i32, result: *mut FlodlTensor,
480    ) -> *mut i8;
481
482    pub fn flodl_avg_pool1d(
483        input: FlodlTensor, kernel_size: i64,
484        stride: i64, padding: i64,
485        ceil_mode: i32, count_include_pad: i32,
486        result: *mut FlodlTensor,
487    ) -> *mut i8;
488
489    // --- Instance normalization ---
490
491    pub fn flodl_instance_norm(
492        input: FlodlTensor, weight: FlodlTensor, bias: FlodlTensor,
493        running_mean: FlodlTensor, running_var: FlodlTensor,
494        use_input_stats: i32, momentum: f64, eps: f64,
495        result: *mut FlodlTensor,
496    ) -> *mut i8;
497
498    // --- PixelShuffle ---
499
500    pub fn flodl_pixel_shuffle(
501        input: FlodlTensor, upscale_factor: i64, result: *mut FlodlTensor,
502    ) -> *mut i8;
503
504    pub fn flodl_pixel_unshuffle(
505        input: FlodlTensor, downscale_factor: i64, result: *mut FlodlTensor,
506    ) -> *mut i8;
507
508    // --- Bilinear ---
509
510    pub fn flodl_bilinear(
511        input1: FlodlTensor, input2: FlodlTensor,
512        weight: FlodlTensor, bias: FlodlTensor,
513        result: *mut FlodlTensor,
514    ) -> *mut i8;
515
516    // --- Grid sampling ---
517
518    pub fn flodl_grid_sample(
519        input: FlodlTensor, grid: FlodlTensor,
520        mode: i32, padding_mode: i32, align_corners: i32,
521        result: *mut FlodlTensor,
522    ) -> *mut i8;
523
524    // --- Scaled dot-product attention ---
525
526    pub fn flodl_scaled_dot_product_attention(
527        query: FlodlTensor, key: FlodlTensor, value: FlodlTensor,
528        attn_mask: FlodlTensor,
529        dropout_p: f64, is_causal: i32, scale: f64,
530        result: *mut FlodlTensor,
531    ) -> *mut i8;
532
533    // --- Device ---
534
535    pub fn flodl_to_device(
536        t: FlodlTensor, device_type: i32, device_index: i32,
537        result: *mut FlodlTensor,
538    ) -> *mut i8;
539
540    pub fn flodl_to_device_async(
541        t: FlodlTensor, device_type: i32, device_index: i32,
542        result: *mut FlodlTensor,
543    ) -> *mut i8;
544
545    pub fn flodl_cuda_is_available() -> i32;
546    pub fn flodl_cuda_device_count() -> i32;
547    pub fn flodl_force_cuda_link() -> i32;
548    pub fn flodl_set_current_device(device_index: i32);
549    pub fn flodl_get_current_device() -> i32;
550    pub fn flodl_cuda_synchronize(device_index: i32);
551
552    // --- CUDA memory/utilization (monitor support) ---
553
554    pub fn flodl_cuda_mem_info(
555        device_index: i32, used_bytes: *mut u64, total_bytes: *mut u64,
556    ) -> *mut i8;
557
558    pub fn flodl_cuda_alloc_bytes(
559        device_index: i32, allocated_bytes: *mut u64,
560    ) -> *mut i8;
561
562    pub fn flodl_cuda_active_bytes(
563        device_index: i32, active_bytes: *mut u64,
564    ) -> *mut i8;
565
566    pub fn flodl_cuda_peak_active_bytes(
567        device_index: i32, peak_bytes: *mut u64,
568    ) -> *mut i8;
569
570    pub fn flodl_cuda_peak_reserved_bytes(
571        device_index: i32, peak_bytes: *mut u64,
572    ) -> *mut i8;
573
574    pub fn flodl_cuda_reset_peak_stats(device_index: i32);
575
576    pub fn flodl_cuda_empty_cache();
577
578    pub fn flodl_cuda_utilization(device_index: i32) -> i32;
579
580    pub fn flodl_cuda_device_name(
581        device_index: i32, buf: *mut i8, buf_len: i32,
582    ) -> *mut i8;
583
584    pub fn flodl_cuda_compute_capability(
585        device_index: i32, major: *mut i32, minor: *mut i32,
586    ) -> *mut i8;
587
588    // --- Dtype casting ---
589
590    pub fn flodl_to_dtype(
591        t: FlodlTensor, dtype: i32, result: *mut FlodlTensor,
592    ) -> *mut i8;
593
594    pub fn flodl_all_finite(t: FlodlTensor, result: *mut i32) -> *mut i8;
595
596    // --- Comparison (tensor-tensor, return float masks: 0.0 or 1.0) ---
597
598    pub fn flodl_gt_tensor(
599        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
600    ) -> *mut i8;
601
602    pub fn flodl_lt_tensor(
603        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
604    ) -> *mut i8;
605
606    pub fn flodl_ge_tensor(
607        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
608    ) -> *mut i8;
609
610    pub fn flodl_le_tensor(
611        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
612    ) -> *mut i8;
613
614    pub fn flodl_eq_tensor(
615        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
616    ) -> *mut i8;
617
618    pub fn flodl_ne_tensor(
619        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
620    ) -> *mut i8;
621
622    // --- Element-wise binary (differentiable) ---
623
624    pub fn flodl_atan2(
625        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
626    ) -> *mut i8;
627
628    pub fn flodl_maximum(
629        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
630    ) -> *mut i8;
631
632    pub fn flodl_minimum(
633        a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor,
634    ) -> *mut i8;
635
636    // --- Additional reductions ---
637
638    pub fn flodl_argmin(
639        t: FlodlTensor, dim: i32, keepdim: i32, result: *mut FlodlTensor,
640    ) -> *mut i8;
641
642    pub fn flodl_var(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
643    pub fn flodl_std_op(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
644
645    pub fn flodl_var_dim(
646        t: FlodlTensor, dim: i32, keepdim: i32, result: *mut FlodlTensor,
647    ) -> *mut i8;
648
649    pub fn flodl_std_dim(
650        t: FlodlTensor, dim: i32, keepdim: i32, result: *mut FlodlTensor,
651    ) -> *mut i8;
652
653    pub fn flodl_cumprod(t: FlodlTensor, dim: i32, result: *mut FlodlTensor) -> *mut i8;
654    pub fn flodl_norm_p_dim(
655        t: FlodlTensor, p: f64, dim: i32, keepdim: i32, result: *mut FlodlTensor,
656    ) -> *mut i8;
657    pub fn flodl_sum_dims(
658        t: FlodlTensor, dims: *mut i64, ndims: i32, keepdim: i32,
659        result: *mut FlodlTensor,
660    ) -> *mut i8;
661    pub fn flodl_median(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
662    pub fn flodl_median_dim(
663        t: FlodlTensor, dim: i32, keepdim: i32,
664        values: *mut FlodlTensor, indices: *mut FlodlTensor,
665    ) -> *mut i8;
666    pub fn flodl_count_nonzero(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
667    pub fn flodl_count_nonzero_dim(
668        t: FlodlTensor, dim: i32, result: *mut FlodlTensor,
669    ) -> *mut i8;
670
671    // --- Query ops ---
672
673    pub fn flodl_nonzero(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
674    pub fn flodl_unique(
675        t: FlodlTensor, sorted: i32, return_inverse: i32,
676        output: *mut FlodlTensor, inverse_indices: *mut FlodlTensor,
677    ) -> *mut i8;
678    pub fn flodl_searchsorted(
679        sorted_seq: FlodlTensor, values: FlodlTensor,
680        result: *mut FlodlTensor,
681    ) -> *mut i8;
682
683    // --- Shape ops (advanced) ---
684
685    pub fn flodl_diagonal(
686        t: FlodlTensor, offset: i64, dim1: i32, dim2: i32,
687        result: *mut FlodlTensor,
688    ) -> *mut i8;
689    pub fn flodl_movedim(
690        t: FlodlTensor, src: i64, dst: i64, result: *mut FlodlTensor,
691    ) -> *mut i8;
692    pub fn flodl_tile(
693        t: FlodlTensor, reps: *mut i64, ndim: i32, result: *mut FlodlTensor,
694    ) -> *mut i8;
695
696    // --- Element-wise math (trig, rounding, sign) ---
697
698    pub fn flodl_sin(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
699    pub fn flodl_cos(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
700    pub fn flodl_tan(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
701    pub fn flodl_asin(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
702    pub fn flodl_acos(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
703    pub fn flodl_atan(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
704    pub fn flodl_sign(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
705    pub fn flodl_floor(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
706    pub fn flodl_ceil(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
707    pub fn flodl_round(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
708    pub fn flodl_reciprocal(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
709    pub fn flodl_erf(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
710    pub fn flodl_erfc(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
711    pub fn flodl_trunc(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
712    pub fn flodl_frac(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
713    pub fn flodl_fmod_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut i8;
714    pub fn flodl_fmod_tensor(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
715    pub fn flodl_remainder_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut i8;
716    pub fn flodl_remainder_tensor(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
717    pub fn flodl_lerp(a: FlodlTensor, b: FlodlTensor, weight: f64, result: *mut FlodlTensor) -> *mut i8;
718    pub fn flodl_lerp_tensor(a: FlodlTensor, b: FlodlTensor, weight: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
719    pub fn flodl_isclose(a: FlodlTensor, b: FlodlTensor, rtol: f64, atol: f64, result: *mut FlodlTensor) -> *mut i8;
720
721    // --- Fused mul-add ---
722
723    pub fn flodl_addmm(
724        bias: FlodlTensor, mat1: FlodlTensor, mat2: FlodlTensor,
725        beta: f64, alpha: f64, result: *mut FlodlTensor,
726    ) -> *mut i8;
727    pub fn flodl_addcmul(
728        self_: FlodlTensor, t1: FlodlTensor, t2: FlodlTensor,
729        value: f64, result: *mut FlodlTensor,
730    ) -> *mut i8;
731    pub fn flodl_addcdiv(
732        self_: FlodlTensor, t1: FlodlTensor, t2: FlodlTensor,
733        value: f64, result: *mut FlodlTensor,
734    ) -> *mut i8;
735
736    // --- Advanced indexing ---
737
738    pub fn flodl_gather(
739        t: FlodlTensor, dim: i32, index: FlodlTensor,
740        result: *mut FlodlTensor,
741    ) -> *mut i8;
742
743    pub fn flodl_scatter_add(
744        t: FlodlTensor, dim: i32, index: FlodlTensor, src: FlodlTensor,
745        result: *mut FlodlTensor,
746    ) -> *mut i8;
747
748    // --- Sorting ---
749
750    pub fn flodl_topk(
751        t: FlodlTensor, k: i64, dim: i32, largest: i32, sorted: i32,
752        values: *mut FlodlTensor, indices: *mut FlodlTensor,
753    ) -> *mut i8;
754
755    pub fn flodl_sort(
756        t: FlodlTensor, dim: i32, descending: i32,
757        values: *mut FlodlTensor, indices: *mut FlodlTensor,
758    ) -> *mut i8;
759
760    // --- Tensor creation (additional) ---
761
762    pub fn flodl_eye(
763        n: i64, dtype: i32, device_type: i32, device_index: i32,
764        result: *mut FlodlTensor,
765    ) -> *mut i8;
766
767    pub fn flodl_full(
768        shape: *mut i64, ndim: i32, value: f64, dtype: i32,
769        device_type: i32, device_index: i32,
770        result: *mut FlodlTensor,
771    ) -> *mut i8;
772
773    pub fn flodl_randperm(
774        n: i64, dtype: i32, device_type: i32, device_index: i32,
775        result: *mut FlodlTensor,
776    ) -> *mut i8;
777
778    pub fn flodl_multinomial(
779        probs: FlodlTensor, num_samples: i64, replacement: i32,
780        result: *mut FlodlTensor,
781    ) -> *mut i8;
782
783    // --- Normalization ---
784
785    pub fn flodl_normalize(
786        t: FlodlTensor, p: f64, dim: i32, result: *mut FlodlTensor,
787    ) -> *mut i8;
788
789    // --- Shape operations (additional) ---
790
791    pub fn flodl_chunk(
792        t: FlodlTensor, chunks: i32, dim: i32,
793        results: *mut *mut FlodlTensor, count: *mut i32,
794    ) -> *mut i8;
795
796    pub fn flodl_repeat(
797        t: FlodlTensor, repeats: *mut i64, ndim: i32,
798        result: *mut FlodlTensor,
799    ) -> *mut i8;
800
801    pub fn flodl_pad(
802        t: FlodlTensor, padding: *mut i64, pad_len: i32, value: f64,
803        result: *mut FlodlTensor,
804    ) -> *mut i8;
805
806    // mode: 0=constant, 1=reflect, 2=replicate, 3=circular
807    pub fn flodl_pad_mode(
808        t: FlodlTensor, padding: *mut i64, pad_len: i32,
809        mode: i32, value: f64,
810        result: *mut FlodlTensor,
811    ) -> *mut i8;
812
813    // mode: 0=nearest, 1=bilinear, 2=bicubic, 3=trilinear
814    pub fn flodl_interpolate(
815        input: FlodlTensor, output_size: *mut i64, ndim: i32,
816        mode: i32, align_corners: i32,
817        result: *mut FlodlTensor,
818    ) -> *mut i8;
819
820    pub fn flodl_flip(
821        t: FlodlTensor, dims: *mut i64, ndim: i32,
822        result: *mut FlodlTensor,
823    ) -> *mut i8;
824
825    pub fn flodl_roll(
826        t: FlodlTensor, shift: i64, dim: i32,
827        result: *mut FlodlTensor,
828    ) -> *mut i8;
829
830    pub fn flodl_split(
831        t: FlodlTensor, split_size: i64, dim: i32,
832        results: *mut *mut FlodlTensor, count: *mut i32,
833    ) -> *mut i8;
834
835    pub fn flodl_unbind(
836        t: FlodlTensor, dim: i32,
837        results: *mut *mut FlodlTensor, count: *mut i32,
838    ) -> *mut i8;
839
840    pub fn flodl_contiguous(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
841    pub fn flodl_is_contiguous(t: FlodlTensor) -> i32;
842
843    pub fn flodl_argsort(
844        t: FlodlTensor, dim: i32, descending: i32,
845        result: *mut FlodlTensor,
846    ) -> *mut i8;
847
848    pub fn flodl_scatter(
849        t: FlodlTensor, dim: i32, index: FlodlTensor, src: FlodlTensor,
850        result: *mut FlodlTensor,
851    ) -> *mut i8;
852
853    // --- Autograd ---
854
855    pub fn flodl_set_requires_grad(
856        t: FlodlTensor, requires_grad: i32, result: *mut FlodlTensor,
857    ) -> *mut i8;
858
859    pub fn flodl_requires_grad(t: FlodlTensor) -> i32;
860
861    /// Force creation of the AccumulateGrad node for a leaf tensor with
862    /// `requires_grad=true`. The node's stream is pinned to the current
863    /// CUDA stream at the moment of this call. Use under `StreamGuard`
864    /// to ensure DDP workers' parameters accumulate on the training
865    /// stream, not the autograd engine's default stream.
866    ///
867    /// Writes an opaque handle to `*handle_out` that keeps the node
868    /// alive. The caller must later pass it to
869    /// [`flodl_grad_accumulator_delete`] to free it. For non-leaf or
870    /// non-requires-grad tensors `*handle_out` is set to null.
871    pub fn flodl_ensure_grad_accumulator(
872        t: FlodlTensor, handle_out: *mut *mut c_void,
873    ) -> *mut i8;
874
875    /// Free a handle returned by [`flodl_ensure_grad_accumulator`].
876    /// Safe to call with a null pointer.
877    pub fn flodl_grad_accumulator_delete(handle: *mut c_void);
878
879    pub fn flodl_backward(t: FlodlTensor) -> *mut i8;
880
881    pub fn flodl_grad(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
882
883    pub fn flodl_set_grad(t: FlodlTensor, grad: FlodlTensor) -> *mut i8;
884
885    pub fn flodl_zero_grad(t: FlodlTensor) -> *mut i8;
886
887    pub fn flodl_detach(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
888
889    pub fn flodl_detach_(t: FlodlTensor) -> *mut i8;
890
891    pub fn flodl_is_leaf(t: FlodlTensor) -> i32;
892
893    // --- Autograd context ---
894
895    pub fn flodl_no_grad_guard_new() -> *mut c_void;
896    pub fn flodl_no_grad_guard_delete(guard: *mut c_void);
897    pub fn flodl_is_grad_enabled() -> i32;
898
899    // --- Autocast (automatic mixed precision) ---
900
901    pub fn flodl_autocast_guard_new(device_type: i32, dtype: i32) -> *mut c_void;
902    pub fn flodl_autocast_guard_delete(guard: *mut c_void);
903    pub fn flodl_is_autocast_enabled(device_type: i32) -> i32;
904
905    // --- Meshgrid ---
906
907    pub fn flodl_meshgrid(
908        tensors: *mut FlodlTensor, count: i32,
909        results: *mut *mut FlodlTensor, result_count: *mut i32,
910    ) -> *mut i8;
911
912    // --- Pairwise distance ---
913
914    pub fn flodl_cdist(
915        x: FlodlTensor, y: FlodlTensor, p: f64,
916        result: *mut FlodlTensor,
917    ) -> *mut i8;
918
919    // --- Cosine similarity ---
920
921    pub fn flodl_cosine_similarity(
922        a: FlodlTensor, b: FlodlTensor,
923        dim: i64, eps: f64,
924        result: *mut FlodlTensor,
925    ) -> *mut i8;
926
927    // --- Fused ops ---
928
929    pub fn flodl_linear(
930        input: FlodlTensor, weight: FlodlTensor, bias: FlodlTensor,
931        result: *mut FlodlTensor,
932    ) -> *mut i8;
933
934    pub fn flodl_gru_cell(
935        input: FlodlTensor, hx: FlodlTensor,
936        w_ih: FlodlTensor, w_hh: FlodlTensor,
937        b_ih: FlodlTensor, b_hh: FlodlTensor,
938        result: *mut FlodlTensor,
939    ) -> *mut i8;
940
941    pub fn flodl_lstm_cell(
942        input: FlodlTensor, hx: FlodlTensor, cx: FlodlTensor,
943        w_ih: FlodlTensor, w_hh: FlodlTensor,
944        b_ih: FlodlTensor, b_hh: FlodlTensor,
945        h_out: *mut FlodlTensor, c_out: *mut FlodlTensor,
946    ) -> *mut i8;
947
948    // Fused sequence ops (cuDNN-accelerated)
949    pub fn flodl_lstm(
950        input: FlodlTensor, h_0: FlodlTensor, c_0: FlodlTensor,
951        params: *const FlodlTensor, num_params: i64,
952        num_layers: i64, batch_first: bool, flatten: bool,
953        output: *mut FlodlTensor, h_n: *mut FlodlTensor, c_n: *mut FlodlTensor,
954    ) -> *mut i8;
955
956    pub fn flodl_gru(
957        input: FlodlTensor, h_0: FlodlTensor,
958        params: *const FlodlTensor, num_params: i64,
959        num_layers: i64, batch_first: bool, flatten: bool,
960        output: *mut FlodlTensor, h_n: *mut FlodlTensor,
961    ) -> *mut i8;
962
963    // Cached RNN params (zero per-forward overhead)
964    pub fn flodl_rnn_params_create(
965        params: *const FlodlTensor, num_params: i64,
966        mode: i64, num_layers: i64, batch_first: bool, flatten: bool,
967        out: *mut *mut std::os::raw::c_void,
968    ) -> *mut i8;
969    pub fn flodl_rnn_params_free(rp: *mut std::os::raw::c_void);
970    pub fn flodl_lstm_cached(
971        input: FlodlTensor, h_0: FlodlTensor, c_0: FlodlTensor,
972        rp: *mut std::os::raw::c_void, num_layers: i64, batch_first: bool,
973        output: *mut FlodlTensor, h_n: *mut FlodlTensor, c_n: *mut FlodlTensor,
974    ) -> *mut i8;
975    pub fn flodl_gru_cached(
976        input: FlodlTensor, h_0: FlodlTensor,
977        rp: *mut std::os::raw::c_void, num_layers: i64, batch_first: bool,
978        output: *mut FlodlTensor, h_n: *mut FlodlTensor,
979    ) -> *mut i8;
980
981    // --- cuDNN benchmark ---
982
983    pub fn flodl_set_cudnn_benchmark(enable: i32);
984
985    // --- RNG seed ---
986
987    pub fn flodl_manual_seed(seed: u64);
988    pub fn flodl_cuda_manual_seed_all(seed: u64);
989
990    // --- In-place operations ---
991
992    pub fn flodl_add_(t: FlodlTensor, other: FlodlTensor) -> *mut i8;
993    pub fn flodl_sub_(t: FlodlTensor, other: FlodlTensor) -> *mut i8;
994    pub fn flodl_mul_scalar_(t: FlodlTensor, scalar: f64) -> *mut i8;
995    pub fn flodl_add_scalar_(t: FlodlTensor, scalar: f64) -> *mut i8;
996    pub fn flodl_zero_(t: FlodlTensor) -> *mut i8;
997    pub fn flodl_mul_(t: FlodlTensor, other: FlodlTensor) -> *mut i8;
998    pub fn flodl_div_scalar_(t: FlodlTensor, scalar: f64) -> *mut i8;
999    pub fn flodl_div_(t: FlodlTensor, other: FlodlTensor) -> *mut i8;
1000    pub fn flodl_fill_(t: FlodlTensor, value: f64) -> *mut i8;
1001
1002    // --- Fused Adam step ---
1003
1004    pub fn flodl_adam_step(
1005        param: FlodlTensor, grad: FlodlTensor,
1006        m: FlodlTensor, v: FlodlTensor,
1007        lr: f64, beta1: f64, beta2: f64, eps: f64,
1008        weight_decay: f64, step: i64,
1009    ) -> *mut i8;
1010
1011    // --- Batched Adam step ---
1012
1013    pub fn flodl_adam_step_batched(
1014        params: *mut FlodlTensor, grads: *mut FlodlTensor,
1015        ms: *mut FlodlTensor, vs: *mut FlodlTensor,
1016        lrs: *mut f64, count: i32,
1017        beta1: f64, beta2: f64, eps: f64,
1018        weight_decay: f64, step: i64,
1019    ) -> *mut i8;
1020
1021    // --- Fused Adam/AdamW (multi-tensor kernel) ---
1022
1023    pub fn flodl_fused_adam_(
1024        params: *mut FlodlTensor, grads: *mut FlodlTensor,
1025        exp_avgs: *mut FlodlTensor, exp_avg_sqs: *mut FlodlTensor,
1026        count: i32, lr: f64,
1027        beta1: f64, beta2: f64, eps: f64,
1028        weight_decay: f64, step: i64,
1029        grad_scale: FlodlTensor, found_inf: FlodlTensor,
1030    ) -> *mut i8;
1031
1032    pub fn flodl_fused_adamw_(
1033        params: *mut FlodlTensor, grads: *mut FlodlTensor,
1034        exp_avgs: *mut FlodlTensor, exp_avg_sqs: *mut FlodlTensor,
1035        count: i32, lr: f64,
1036        beta1: f64, beta2: f64, eps: f64,
1037        weight_decay: f64, step: i64,
1038        grad_scale: FlodlTensor, found_inf: FlodlTensor,
1039    ) -> *mut i8;
1040
1041    // --- Pinned memory ---
1042
1043    pub fn flodl_pin_memory(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
1044    pub fn flodl_is_pinned(t: FlodlTensor) -> i32;
1045
1046    // --- Memory diagnostics ---
1047
1048    pub fn flodl_malloc_trim() -> i32;
1049
1050    // --- Zero grad (set_to_none) ---
1051
1052    pub fn flodl_zero_grad_set_to_none(t: FlodlTensor);
1053
1054    // --- Fused clip_grad_norm ---
1055
1056    pub fn flodl_clip_grad_norm(
1057        params: *mut FlodlTensor, count: i32,
1058        max_norm: f64, total_norm_out: *mut f64,
1059    ) -> *mut i8;
1060
1061    // --- Multi-tensor foreach operations ---
1062
1063    pub fn flodl_foreach_add_scalar_(
1064        tensors: *mut FlodlTensor, count: i32, scalar: f64,
1065    ) -> *mut i8;
1066
1067    pub fn flodl_foreach_mul_scalar_(
1068        tensors: *mut FlodlTensor, count: i32, scalar: f64,
1069    ) -> *mut i8;
1070
1071    pub fn flodl_foreach_zero_(
1072        tensors: *mut FlodlTensor, count: i32,
1073    ) -> *mut i8;
1074
1075    pub fn flodl_foreach_add_list_(
1076        tensors1: *mut FlodlTensor, tensors2: *mut FlodlTensor,
1077        count: i32, alpha: f64,
1078    ) -> *mut i8;
1079
1080    pub fn flodl_foreach_norm(
1081        tensors: *mut FlodlTensor, count: i32, ord: f64,
1082        results: *mut FlodlTensor,
1083    ) -> *mut i8;
1084
1085    pub fn flodl_foreach_lerp_scalar_(
1086        tensors1: *mut FlodlTensor, tensors2: *mut FlodlTensor,
1087        count: i32, weight: f64,
1088    ) -> *mut i8;
1089
1090    pub fn flodl_foreach_sqrt_(
1091        tensors: *mut FlodlTensor, count: i32,
1092    ) -> *mut i8;
1093
1094    // --- Autograd diagnostics ---
1095
1096    pub fn flodl_autograd_node_count(t: FlodlTensor) -> i64;
1097
1098    // --- Fused loss functions ---
1099
1100    pub fn flodl_mse_loss(
1101        pred: FlodlTensor, target: FlodlTensor,
1102        reduction: i64, result: *mut FlodlTensor,
1103    ) -> *mut i8;
1104
1105    pub fn flodl_cross_entropy_loss(
1106        pred: FlodlTensor, target: FlodlTensor,
1107        reduction: i64, ignore_index: i64, label_smoothing: f64,
1108        result: *mut FlodlTensor,
1109    ) -> *mut i8;
1110
1111    pub fn flodl_bce_with_logits_loss(
1112        pred: FlodlTensor, target: FlodlTensor,
1113        reduction: i64, result: *mut FlodlTensor,
1114    ) -> *mut i8;
1115
1116    pub fn flodl_bce_loss(
1117        pred: FlodlTensor, target: FlodlTensor,
1118        reduction: i64, result: *mut FlodlTensor,
1119    ) -> *mut i8;
1120
1121    pub fn flodl_l1_loss(
1122        pred: FlodlTensor, target: FlodlTensor,
1123        reduction: i64, result: *mut FlodlTensor,
1124    ) -> *mut i8;
1125
1126    pub fn flodl_smooth_l1_loss(
1127        pred: FlodlTensor, target: FlodlTensor,
1128        reduction: i64, beta: f64,
1129        result: *mut FlodlTensor,
1130    ) -> *mut i8;
1131
1132    pub fn flodl_kl_div_loss(
1133        input: FlodlTensor, target: FlodlTensor,
1134        reduction: i64, log_target: i32,
1135        result: *mut FlodlTensor,
1136    ) -> *mut i8;
1137
1138    pub fn flodl_nll_loss(
1139        input: FlodlTensor, target: FlodlTensor,
1140        reduction: i64, ignore_index: i64,
1141        result: *mut FlodlTensor,
1142    ) -> *mut i8;
1143
1144    pub fn flodl_ctc_loss(
1145        log_probs: FlodlTensor, targets: FlodlTensor,
1146        input_lengths: FlodlTensor, target_lengths: FlodlTensor,
1147        blank: i64, reduction: i64,
1148        result: *mut FlodlTensor,
1149    ) -> *mut i8;
1150
1151    // --- Fused batch normalization ---
1152
1153    pub fn flodl_batch_norm(
1154        input: FlodlTensor, weight: FlodlTensor,
1155        bias: FlodlTensor, running_mean: FlodlTensor,
1156        running_var: FlodlTensor, training: i32,
1157        momentum: f64, eps: f64,
1158        result: *mut FlodlTensor,
1159    ) -> *mut i8;
1160
1161    // --- Fused dropout ---
1162
1163    pub fn flodl_dropout(
1164        input: FlodlTensor, p: f64, training: i32,
1165        result: *mut FlodlTensor,
1166    ) -> *mut i8;
1167
1168    pub fn flodl_feature_dropout(
1169        input: FlodlTensor, p: f64, training: i32,
1170        result: *mut FlodlTensor,
1171    ) -> *mut i8;
1172
1173    // --- In-place copy ---
1174
1175    pub fn flodl_copy_(dst: FlodlTensor, src: FlodlTensor, non_blocking: i32) -> *mut i8;
1176
1177    // --- Memory format ---
1178
1179    pub fn flodl_to_channels_last(t: FlodlTensor, result: *mut FlodlTensor) -> *mut i8;
1180    pub fn flodl_is_channels_last(t: FlodlTensor) -> i32;
1181
1182    // --- Embedding lookup ---
1183
1184    pub fn flodl_embedding(
1185        weight: FlodlTensor, indices: FlodlTensor,
1186        padding_idx: i64,
1187        scale_grad_by_freq: i32, sparse: i32,
1188        result: *mut FlodlTensor,
1189    ) -> *mut i8;
1190
1191    // --- Embedding bag ---
1192
1193    pub fn flodl_embedding_bag(
1194        weight: FlodlTensor, indices: FlodlTensor, offsets: FlodlTensor,
1195        mode: i64, result: *mut FlodlTensor,
1196    ) -> *mut i8;
1197
1198    // --- CUDA Graphs ---
1199
1200    pub fn flodl_cuda_graph_new(graph_out: *mut *mut c_void) -> *mut i8;
1201    pub fn flodl_cuda_graph_capture_begin(
1202        graph: *mut c_void, pool_hi: u64, pool_lo: u64, mode: i32,
1203    ) -> *mut i8;
1204    pub fn flodl_cuda_graph_capture_end(graph: *mut c_void) -> *mut i8;
1205    pub fn flodl_cuda_graph_replay(graph: *mut c_void) -> *mut i8;
1206    pub fn flodl_cuda_graph_reset(graph: *mut c_void) -> *mut i8;
1207    pub fn flodl_cuda_graph_delete(graph: *mut c_void);
1208    pub fn flodl_cuda_graph_pool(
1209        graph: *mut c_void, pool_hi: *mut u64, pool_lo: *mut u64,
1210    );
1211    pub fn flodl_cuda_graph_pool_handle(pool_hi: *mut u64, pool_lo: *mut u64);
1212
1213    // --- CUDA Events ---
1214
1215    pub fn flodl_cuda_event_new(flags: i32, event_out: *mut *mut c_void) -> *mut i8;
1216    pub fn flodl_cuda_event_record(event: *mut c_void) -> *mut i8;
1217    pub fn flodl_cuda_event_record_on_stream(
1218        event: *mut c_void, stream: *mut c_void,
1219    ) -> *mut i8;
1220    pub fn flodl_cuda_event_synchronize(event: *mut c_void) -> *mut i8;
1221    pub fn flodl_cuda_event_elapsed_time(
1222        start: *mut c_void, end: *mut c_void, ms_out: *mut f32,
1223    ) -> *mut i8;
1224    pub fn flodl_cuda_event_query(event: *mut c_void) -> i32;
1225    pub fn flodl_cuda_event_delete(event: *mut c_void);
1226
1227    // --- CUDA Streams ---
1228
1229    pub fn flodl_cuda_stream_new(
1230        device_index: i32, high_priority: i32, stream_out: *mut *mut c_void,
1231    ) -> *mut i8;
1232    pub fn flodl_cuda_stream_synchronize(stream: *mut c_void) -> *mut i8;
1233    pub fn flodl_cuda_stream_wait_event(
1234        stream: *mut c_void, event: *mut c_void,
1235    ) -> *mut i8;
1236    pub fn flodl_cuda_stream_query(stream: *mut c_void) -> i32;
1237    pub fn flodl_cuda_stream_set_current(stream: *mut c_void);
1238    pub fn flodl_cuda_stream_get_current(device_index: i32) -> *mut c_void;
1239    pub fn flodl_cuda_stream_restore_default(device_index: i32);
1240    pub fn flodl_cuda_stream_delete(stream: *mut c_void);
1241
1242    // --- NCCL Collective Operations ---
1243
1244    pub fn flodl_nccl_init(
1245        ndev: i32, devlist: *const i32, handle_out: *mut *mut c_void,
1246    ) -> *mut i8;
1247    pub fn flodl_nccl_destroy(handle: *mut c_void);
1248    pub fn flodl_nccl_all_reduce(
1249        handle: *mut c_void, tensors: *mut FlodlTensor,
1250        streams: *mut *mut c_void, op: i32,
1251    ) -> *mut i8;
1252    pub fn flodl_nccl_broadcast(
1253        handle: *mut c_void, tensors: *mut FlodlTensor,
1254        streams: *mut *mut c_void, root: i32,
1255    ) -> *mut i8;
1256    pub fn flodl_nccl_size(handle: *mut c_void) -> i32;
1257
1258    // --- NCCL Per-Rank Operations ---
1259
1260    pub fn flodl_nccl_get_unique_id(uid_out: *mut u8) -> *mut i8;
1261    pub fn flodl_nccl_init_rank(
1262        rank: i32, nranks: i32, uid: *const u8, handle_out: *mut *mut c_void,
1263    ) -> *mut i8;
1264    pub fn flodl_nccl_destroy_rank(handle: *mut c_void);
1265    pub fn flodl_nccl_abort_rank(handle: *mut c_void) -> *mut i8;
1266    pub fn flodl_nccl_all_reduce_rank(
1267        handle: *mut c_void, tensors: *mut FlodlTensor, ntensors: i32,
1268        stream: *mut c_void, op: i32,
1269    ) -> *mut i8;
1270    pub fn flodl_nccl_split_rank(
1271        group_handle: *mut c_void, rank: i32,
1272        rank_handle_out: *mut *mut c_void,
1273    ) -> *mut i8;
1274
1275    // --- Utility ---
1276
1277    pub fn flodl_free_string(s: *mut i8);
1278}