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 c_char` 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_char, c_void};
10
11/// Parses `shim.h` + this file and asserts the two `extern "C"` surfaces
12/// match (ABI). Guards the hand-written bindings against silent drift.
13#[cfg(test)]
14mod ffi_parity;
15
16/// Opaque handle to a `torch::Tensor` on the C++ side.
17pub type FlodlTensor = *mut c_void;
18
19// --- DType constants (must match shim.h) ---
20pub const FLODL_FLOAT16: i32 = 5;
21pub const FLODL_BFLOAT16: i32 = 15;
22pub const FLODL_FLOAT32: i32 = 6;
23pub const FLODL_FLOAT64: i32 = 7;
24pub const FLODL_INT32: i32 = 3;
25pub const FLODL_INT64: i32 = 4;
26
27// --- Device constants (must match shim.h) ---
28pub const FLODL_CPU: i32 = 0;
29pub const FLODL_CUDA: i32 = 1;
30
31unsafe extern "C" {
32    // --- Tensor creation ---
33
34    pub fn flodl_zeros(
35        shape: *mut i64,
36        ndim: i32,
37        dtype: i32,
38        device_type: i32,
39        device_index: i32,
40        result: *mut FlodlTensor,
41    ) -> *mut c_char;
42
43    pub fn flodl_ones(
44        shape: *mut i64,
45        ndim: i32,
46        dtype: i32,
47        device_type: i32,
48        device_index: i32,
49        result: *mut FlodlTensor,
50    ) -> *mut c_char;
51
52    pub fn flodl_rand(
53        shape: *mut i64,
54        ndim: i32,
55        dtype: i32,
56        device_type: i32,
57        device_index: i32,
58        result: *mut FlodlTensor,
59    ) -> *mut c_char;
60
61    pub fn flodl_randn(
62        shape: *mut i64,
63        ndim: i32,
64        dtype: i32,
65        device_type: i32,
66        device_index: i32,
67        result: *mut FlodlTensor,
68    ) -> *mut c_char;
69
70    pub fn flodl_from_blob(
71        data: *mut c_void,
72        shape: *mut i64,
73        ndim: i32,
74        dtype: i32,
75        device_type: i32,
76        device_index: i32,
77        result: *mut FlodlTensor,
78    ) -> *mut c_char;
79
80    pub fn flodl_linspace(
81        start: f64,
82        end: f64,
83        steps: i64,
84        dtype: i32,
85        device_type: i32,
86        device_index: i32,
87        result: *mut FlodlTensor,
88    ) -> *mut c_char;
89
90    pub fn flodl_arange(
91        start: f64,
92        end: f64,
93        step: f64,
94        dtype: i32,
95        device_type: i32,
96        device_index: i32,
97        result: *mut FlodlTensor,
98    ) -> *mut c_char;
99
100    pub fn flodl_expand(
101        t: FlodlTensor,
102        new_shape: *mut i64,
103        ndim: i32,
104        result: *mut FlodlTensor,
105    ) -> *mut c_char;
106
107    // --- Tensor lifecycle ---
108
109    pub fn flodl_free_tensor(t: FlodlTensor);
110    pub fn flodl_shallow_clone(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
111    pub fn flodl_deep_clone(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
112
113    // --- Tensor metadata ---
114
115    pub fn flodl_ndim(t: FlodlTensor) -> i32;
116    pub fn flodl_shape(t: FlodlTensor, dim: i32) -> i64;
117    pub fn flodl_dtype(t: FlodlTensor) -> i32;
118    pub fn flodl_device_type(t: FlodlTensor) -> i32;
119    pub fn flodl_device_index(t: FlodlTensor) -> i32;
120    pub fn flodl_numel(t: FlodlTensor) -> i64;
121    pub fn flodl_storage_nbytes(t: FlodlTensor) -> i64;
122
123    // --- Data access ---
124
125    pub fn flodl_copy_data(t: FlodlTensor, buffer: *mut c_void, buffer_bytes: i64) -> *mut c_char;
126
127    // --- Arithmetic ---
128
129    pub fn flodl_add(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
130    pub fn flodl_sub(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
131    pub fn flodl_mul(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
132    pub fn flodl_div(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
133    pub fn flodl_matmul(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
134
135    pub fn flodl_add_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut c_char;
136
137    pub fn flodl_mul_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut c_char;
138
139    pub fn flodl_div_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut c_char;
140
141    pub fn flodl_neg(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
142
143    // --- Activations ---
144
145    pub fn flodl_relu(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
146    pub fn flodl_sigmoid(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
147    pub fn flodl_tanh_op(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
148    pub fn flodl_softmax(t: FlodlTensor, dim: i32, result: *mut FlodlTensor) -> *mut c_char;
149    pub fn flodl_log_softmax(t: FlodlTensor, dim: i32, result: *mut FlodlTensor) -> *mut c_char;
150    pub fn flodl_gelu(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
151    pub fn flodl_gelu_tanh(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
152    pub fn flodl_silu(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
153    pub fn flodl_leaky_relu(
154        t: FlodlTensor,
155        negative_slope: f64,
156        result: *mut FlodlTensor,
157    ) -> *mut c_char;
158    pub fn flodl_elu(t: FlodlTensor, alpha: f64, result: *mut FlodlTensor) -> *mut c_char;
159    pub fn flodl_softplus(
160        t: FlodlTensor,
161        beta: f64,
162        threshold: f64,
163        result: *mut FlodlTensor,
164    ) -> *mut c_char;
165    pub fn flodl_mish(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
166    pub fn flodl_selu(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
167    pub fn flodl_hardswish(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
168    pub fn flodl_hardsigmoid(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
169    pub fn flodl_prelu(
170        t: FlodlTensor,
171        weight: FlodlTensor,
172        result: *mut FlodlTensor,
173    ) -> *mut c_char;
174
175    // --- Layer normalization ---
176
177    pub fn flodl_native_layer_norm(
178        input: FlodlTensor,
179        weight: FlodlTensor,
180        bias: FlodlTensor,
181        normalized_size: i64,
182        eps: f64,
183        output: *mut FlodlTensor,
184        mean: *mut FlodlTensor,
185        rstd: *mut FlodlTensor,
186    ) -> *mut c_char;
187
188    // --- Group normalization ---
189
190    pub fn flodl_group_norm(
191        input: FlodlTensor,
192        num_groups: i64,
193        weight: FlodlTensor,
194        bias: FlodlTensor,
195        eps: f64,
196        result: *mut FlodlTensor,
197    ) -> *mut c_char;
198
199    // --- Element-wise math ---
200
201    pub fn flodl_exp(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
202    pub fn flodl_log(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
203    pub fn flodl_sqrt(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
204    pub fn flodl_abs(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
205    pub fn flodl_triu(t: FlodlTensor, diagonal: i64, result: *mut FlodlTensor) -> *mut c_char;
206    pub fn flodl_tril(t: FlodlTensor, diagonal: i64, result: *mut FlodlTensor) -> *mut c_char;
207
208    pub fn flodl_pow_scalar(t: FlodlTensor, exponent: f64, result: *mut FlodlTensor)
209    -> *mut c_char;
210
211    pub fn flodl_clamp(
212        t: FlodlTensor,
213        min_val: f64,
214        max_val: f64,
215        result: *mut FlodlTensor,
216    ) -> *mut c_char;
217
218    pub fn flodl_clamp_min(t: FlodlTensor, min_val: f64, result: *mut FlodlTensor) -> *mut c_char;
219
220    pub fn flodl_clamp_max(t: FlodlTensor, max_val: f64, result: *mut FlodlTensor) -> *mut c_char;
221
222    pub fn flodl_log1p(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
223    pub fn flodl_expm1(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
224    pub fn flodl_log2(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
225    pub fn flodl_log10(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
226
227    // --- Reductions ---
228
229    pub fn flodl_sum(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
230    pub fn flodl_mean(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
231
232    pub fn flodl_sum_dim(
233        t: FlodlTensor,
234        dim: i32,
235        keepdim: i32,
236        result: *mut FlodlTensor,
237    ) -> *mut c_char;
238
239    pub fn flodl_mean_dim(
240        t: FlodlTensor,
241        dim: i32,
242        keepdim: i32,
243        result: *mut FlodlTensor,
244    ) -> *mut c_char;
245
246    pub fn flodl_prod(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
247
248    pub fn flodl_prod_dim(
249        t: FlodlTensor,
250        dim: i32,
251        keepdim: i32,
252        result: *mut FlodlTensor,
253    ) -> *mut c_char;
254
255    pub fn flodl_cumsum(t: FlodlTensor, dim: i32, result: *mut FlodlTensor) -> *mut c_char;
256
257    pub fn flodl_logsumexp(
258        t: FlodlTensor,
259        dim: i32,
260        keepdim: i32,
261        result: *mut FlodlTensor,
262    ) -> *mut c_char;
263
264    pub fn flodl_min(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
265    pub fn flodl_max(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
266    pub fn flodl_norm(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
267
268    pub fn flodl_min_dim(
269        t: FlodlTensor,
270        dim: i32,
271        keepdim: i32,
272        result: *mut FlodlTensor,
273    ) -> *mut c_char;
274
275    pub fn flodl_max_dim(
276        t: FlodlTensor,
277        dim: i32,
278        keepdim: i32,
279        result: *mut FlodlTensor,
280    ) -> *mut c_char;
281
282    pub fn flodl_argmax(
283        t: FlodlTensor,
284        dim: i32,
285        keepdim: i32,
286        result: *mut FlodlTensor,
287    ) -> *mut c_char;
288
289    // --- Comparison (return float masks: 0.0 or 1.0) ---
290
291    pub fn flodl_gt_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut c_char;
292
293    pub fn flodl_ge_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut c_char;
294
295    pub fn flodl_le_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut c_char;
296
297    pub fn flodl_lt_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut c_char;
298
299    pub fn flodl_eq_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut c_char;
300
301    pub fn flodl_ne_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut c_char;
302
303    // --- Boolean / detection (return float masks) ---
304
305    pub fn flodl_isnan(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
306    pub fn flodl_isinf(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
307    pub fn flodl_logical_and(
308        a: FlodlTensor,
309        b: FlodlTensor,
310        result: *mut FlodlTensor,
311    ) -> *mut c_char;
312    pub fn flodl_logical_or(
313        a: FlodlTensor,
314        b: FlodlTensor,
315        result: *mut FlodlTensor,
316    ) -> *mut c_char;
317    pub fn flodl_logical_not(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
318    pub fn flodl_any(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
319    pub fn flodl_all(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
320
321    // --- Shape operations ---
322
323    pub fn flodl_reshape(
324        t: FlodlTensor,
325        shape: *mut i64,
326        ndim: i32,
327        result: *mut FlodlTensor,
328    ) -> *mut c_char;
329
330    pub fn flodl_transpose(
331        t: FlodlTensor,
332        dim0: i32,
333        dim1: i32,
334        result: *mut FlodlTensor,
335    ) -> *mut c_char;
336
337    pub fn flodl_permute(
338        t: FlodlTensor,
339        dims: *mut i64,
340        ndim: i32,
341        result: *mut FlodlTensor,
342    ) -> *mut c_char;
343
344    pub fn flodl_select(
345        t: FlodlTensor,
346        dim: i32,
347        index: i64,
348        result: *mut FlodlTensor,
349    ) -> *mut c_char;
350
351    pub fn flodl_narrow(
352        t: FlodlTensor,
353        dim: i32,
354        start: i64,
355        length: i64,
356        result: *mut FlodlTensor,
357    ) -> *mut c_char;
358
359    pub fn flodl_squeeze(t: FlodlTensor, dim: i32, result: *mut FlodlTensor) -> *mut c_char;
360
361    pub fn flodl_unsqueeze(t: FlodlTensor, dim: i32, result: *mut FlodlTensor) -> *mut c_char;
362
363    pub fn flodl_flatten(
364        t: FlodlTensor,
365        start_dim: i32,
366        end_dim: i32,
367        result: *mut FlodlTensor,
368    ) -> *mut c_char;
369
370    // --- Scatter ---
371
372    pub fn flodl_select_scatter(
373        input: FlodlTensor,
374        src: FlodlTensor,
375        dim: i32,
376        index: i64,
377        result: *mut FlodlTensor,
378    ) -> *mut c_char;
379
380    pub fn flodl_narrow_scatter(
381        input: FlodlTensor,
382        src: FlodlTensor,
383        dim: i32,
384        start: i64,
385        result: *mut FlodlTensor,
386    ) -> *mut c_char;
387
388    // --- Indexing ---
389
390    pub fn flodl_index_select(
391        t: FlodlTensor,
392        dim: i32,
393        index: FlodlTensor,
394        result: *mut FlodlTensor,
395    ) -> *mut c_char;
396
397    pub fn flodl_index_add(
398        t: FlodlTensor,
399        dim: i32,
400        index: FlodlTensor,
401        src: FlodlTensor,
402        result: *mut FlodlTensor,
403    ) -> *mut c_char;
404
405    // --- Concatenation ---
406
407    pub fn flodl_cat2(
408        a: FlodlTensor,
409        b: FlodlTensor,
410        dim: i32,
411        result: *mut FlodlTensor,
412    ) -> *mut c_char;
413
414    pub fn flodl_cat(
415        tensors: *mut FlodlTensor,
416        count: i32,
417        dim: i32,
418        result: *mut FlodlTensor,
419    ) -> *mut c_char;
420
421    pub fn flodl_stack(
422        tensors: *mut FlodlTensor,
423        count: i32,
424        dim: i32,
425        result: *mut FlodlTensor,
426    ) -> *mut c_char;
427
428    // --- Masking ---
429
430    pub fn flodl_masked_fill(
431        t: FlodlTensor,
432        mask: FlodlTensor,
433        value: f64,
434        result: *mut FlodlTensor,
435    ) -> *mut c_char;
436
437    // --- Conditional ---
438
439    pub fn flodl_where(
440        condition: FlodlTensor,
441        x: FlodlTensor,
442        y: FlodlTensor,
443        result: *mut FlodlTensor,
444    ) -> *mut c_char;
445
446    // --- Like constructors ---
447
448    pub fn flodl_zeros_like(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
449    pub fn flodl_ones_like(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
450    pub fn flodl_full_like(t: FlodlTensor, value: f64, result: *mut FlodlTensor) -> *mut c_char;
451    pub fn flodl_rand_like(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
452    pub fn flodl_randn_like(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
453
454    // --- Tensor creation (tier 2) ---
455
456    pub fn flodl_randint(
457        low: i64,
458        high: i64,
459        shape: *mut i64,
460        ndim: i32,
461        dtype: i32,
462        device_type: i32,
463        device_index: i32,
464        result: *mut FlodlTensor,
465    ) -> *mut c_char;
466
467    pub fn flodl_empty(
468        shape: *mut i64,
469        ndim: i32,
470        dtype: i32,
471        device_type: i32,
472        device_index: i32,
473        result: *mut FlodlTensor,
474    ) -> *mut c_char;
475
476    pub fn flodl_one_hot(t: FlodlTensor, num_classes: i64, result: *mut FlodlTensor)
477    -> *mut c_char;
478
479    pub fn flodl_bernoulli(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
480
481    // --- Convolution ---
482
483    pub fn flodl_conv2d(
484        input: FlodlTensor,
485        weight: FlodlTensor,
486        bias: FlodlTensor,
487        stride: *mut i64,
488        padding: *mut i64,
489        dilation: *mut i64,
490        groups: i64,
491        result: *mut FlodlTensor,
492    ) -> *mut c_char;
493
494    // --- 1D convolution ---
495
496    pub fn flodl_conv1d(
497        input: FlodlTensor,
498        weight: FlodlTensor,
499        bias: FlodlTensor,
500        stride: i64,
501        padding: i64,
502        dilation: i64,
503        groups: i64,
504        result: *mut FlodlTensor,
505    ) -> *mut c_char;
506
507    // --- Transposed convolution ---
508
509    pub fn flodl_conv_transpose2d(
510        input: FlodlTensor,
511        weight: FlodlTensor,
512        bias: FlodlTensor,
513        stride: *mut i64,
514        padding: *mut i64,
515        output_padding: *mut i64,
516        dilation: *mut i64,
517        groups: i64,
518        result: *mut FlodlTensor,
519    ) -> *mut c_char;
520
521    // --- Transposed 1D convolution ---
522
523    pub fn flodl_conv_transpose1d(
524        input: FlodlTensor,
525        weight: FlodlTensor,
526        bias: FlodlTensor,
527        stride: i64,
528        padding: i64,
529        output_padding: i64,
530        dilation: i64,
531        groups: i64,
532        result: *mut FlodlTensor,
533    ) -> *mut c_char;
534
535    // --- Pooling ---
536
537    pub fn flodl_max_pool2d(
538        input: FlodlTensor,
539        kernel_size: *mut i64,
540        stride: *mut i64,
541        padding: *mut i64,
542        dilation: *mut i64,
543        ceil_mode: i32,
544        result: *mut FlodlTensor,
545    ) -> *mut c_char;
546
547    pub fn flodl_avg_pool2d(
548        input: FlodlTensor,
549        kernel_size: *mut i64,
550        stride: *mut i64,
551        padding: *mut i64,
552        ceil_mode: i32,
553        count_include_pad: i32,
554        result: *mut FlodlTensor,
555    ) -> *mut c_char;
556
557    pub fn flodl_adaptive_avg_pool2d(
558        input: FlodlTensor,
559        output_size: *mut i64,
560        result: *mut FlodlTensor,
561    ) -> *mut c_char;
562
563    pub fn flodl_adaptive_max_pool2d(
564        input: FlodlTensor,
565        output_size: *mut i64,
566        result: *mut FlodlTensor,
567    ) -> *mut c_char;
568
569    // --- Unfold / Fold (im2col / col2im) ---
570
571    pub fn flodl_im2col(
572        input: FlodlTensor,
573        kernel_size: *mut i64,
574        dilation: *mut i64,
575        padding: *mut i64,
576        stride: *mut i64,
577        result: *mut FlodlTensor,
578    ) -> *mut c_char;
579
580    pub fn flodl_col2im(
581        input: FlodlTensor,
582        output_size: *mut i64,
583        kernel_size: *mut i64,
584        dilation: *mut i64,
585        padding: *mut i64,
586        stride: *mut i64,
587        result: *mut FlodlTensor,
588    ) -> *mut c_char;
589
590    // --- 3D convolution ---
591
592    pub fn flodl_conv3d(
593        input: FlodlTensor,
594        weight: FlodlTensor,
595        bias: FlodlTensor,
596        stride: *mut i64,
597        padding: *mut i64,
598        dilation: *mut i64,
599        groups: i64,
600        result: *mut FlodlTensor,
601    ) -> *mut c_char;
602
603    pub fn flodl_conv_transpose3d(
604        input: FlodlTensor,
605        weight: FlodlTensor,
606        bias: FlodlTensor,
607        stride: *mut i64,
608        padding: *mut i64,
609        output_padding: *mut i64,
610        dilation: *mut i64,
611        groups: i64,
612        result: *mut FlodlTensor,
613    ) -> *mut c_char;
614
615    // --- 1D pooling ---
616
617    pub fn flodl_max_pool1d(
618        input: FlodlTensor,
619        kernel_size: i64,
620        stride: i64,
621        padding: i64,
622        dilation: i64,
623        ceil_mode: i32,
624        result: *mut FlodlTensor,
625    ) -> *mut c_char;
626
627    pub fn flodl_avg_pool1d(
628        input: FlodlTensor,
629        kernel_size: i64,
630        stride: i64,
631        padding: i64,
632        ceil_mode: i32,
633        count_include_pad: i32,
634        result: *mut FlodlTensor,
635    ) -> *mut c_char;
636
637    // --- Instance normalization ---
638
639    pub fn flodl_instance_norm(
640        input: FlodlTensor,
641        weight: FlodlTensor,
642        bias: FlodlTensor,
643        running_mean: FlodlTensor,
644        running_var: FlodlTensor,
645        use_input_stats: i32,
646        momentum: f64,
647        eps: f64,
648        result: *mut FlodlTensor,
649    ) -> *mut c_char;
650
651    // --- PixelShuffle ---
652
653    pub fn flodl_pixel_shuffle(
654        input: FlodlTensor,
655        upscale_factor: i64,
656        result: *mut FlodlTensor,
657    ) -> *mut c_char;
658
659    pub fn flodl_pixel_unshuffle(
660        input: FlodlTensor,
661        downscale_factor: i64,
662        result: *mut FlodlTensor,
663    ) -> *mut c_char;
664
665    // --- Bilinear ---
666
667    pub fn flodl_bilinear(
668        input1: FlodlTensor,
669        input2: FlodlTensor,
670        weight: FlodlTensor,
671        bias: FlodlTensor,
672        result: *mut FlodlTensor,
673    ) -> *mut c_char;
674
675    // --- Grid sampling ---
676
677    pub fn flodl_grid_sample(
678        input: FlodlTensor,
679        grid: FlodlTensor,
680        mode: i32,
681        padding_mode: i32,
682        align_corners: i32,
683        result: *mut FlodlTensor,
684    ) -> *mut c_char;
685
686    // --- Scaled dot-product attention ---
687
688    pub fn flodl_scaled_dot_product_attention(
689        query: FlodlTensor,
690        key: FlodlTensor,
691        value: FlodlTensor,
692        attn_mask: FlodlTensor,
693        dropout_p: f64,
694        is_causal: i32,
695        scale: f64,
696        result: *mut FlodlTensor,
697    ) -> *mut c_char;
698
699    // --- Device ---
700
701    pub fn flodl_to_device(
702        t: FlodlTensor,
703        device_type: i32,
704        device_index: i32,
705        result: *mut FlodlTensor,
706    ) -> *mut c_char;
707
708    pub fn flodl_to_device_async(
709        t: FlodlTensor,
710        device_type: i32,
711        device_index: i32,
712        result: *mut FlodlTensor,
713    ) -> *mut c_char;
714
715    pub fn flodl_gpu_is_available() -> i32;
716    pub fn flodl_gpu_device_count() -> i32;
717    pub fn flodl_force_gpu_link() -> i32;
718    pub fn flodl_set_current_device(device_index: i32);
719    pub fn flodl_get_current_device() -> i32;
720    pub fn flodl_gpu_synchronize(device_index: i32);
721
722    // --- CUDA memory/utilization (monitor support) ---
723
724    pub fn flodl_gpu_mem_info(
725        device_index: i32,
726        used_bytes: *mut u64,
727        total_bytes: *mut u64,
728    ) -> *mut c_char;
729
730    pub fn flodl_gpu_alloc_bytes(device_index: i32, allocated_bytes: *mut u64) -> *mut c_char;
731
732    pub fn flodl_gpu_active_bytes(device_index: i32, active_bytes: *mut u64) -> *mut c_char;
733
734    pub fn flodl_gpu_peak_active_bytes(device_index: i32, peak_bytes: *mut u64) -> *mut c_char;
735
736    pub fn flodl_gpu_peak_reserved_bytes(device_index: i32, peak_bytes: *mut u64) -> *mut c_char;
737
738    pub fn flodl_gpu_reset_peak_stats(device_index: i32);
739
740    pub fn flodl_gpu_empty_cache();
741
742    pub fn flodl_gpu_utilization(device_index: i32) -> i32;
743
744    pub fn flodl_gpu_smi_mem_info(
745        device_index: i32,
746        used_bytes: *mut u64,
747        total_bytes: *mut u64,
748    ) -> i32;
749
750    pub fn flodl_gpu_has_primary_context(device_index: i32) -> i32;
751
752    pub fn flodl_gpu_device_name(device_index: i32, buf: *mut c_char, buf_len: i32) -> *mut c_char;
753
754    pub fn flodl_gpu_arch_name(device_index: i32, buf: *mut c_char, buf_len: i32) -> *mut c_char;
755
756    pub fn flodl_gpu_is_integrated(device_index: i32, out: *mut i32) -> *mut c_char;
757
758    pub fn flodl_cuda_compute_capability(
759        device_index: i32,
760        major: *mut i32,
761        minor: *mut i32,
762    ) -> *mut c_char;
763
764    // --- Dtype casting ---
765
766    pub fn flodl_to_dtype(t: FlodlTensor, dtype: i32, result: *mut FlodlTensor) -> *mut c_char;
767
768    pub fn flodl_all_finite(t: FlodlTensor, result: *mut i32) -> *mut c_char;
769
770    // --- Comparison (tensor-tensor, return float masks: 0.0 or 1.0) ---
771
772    pub fn flodl_gt_tensor(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor)
773    -> *mut c_char;
774
775    pub fn flodl_lt_tensor(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor)
776    -> *mut c_char;
777
778    pub fn flodl_ge_tensor(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor)
779    -> *mut c_char;
780
781    pub fn flodl_le_tensor(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor)
782    -> *mut c_char;
783
784    pub fn flodl_eq_tensor(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor)
785    -> *mut c_char;
786
787    pub fn flodl_ne_tensor(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor)
788    -> *mut c_char;
789
790    // --- Element-wise binary (differentiable) ---
791
792    pub fn flodl_atan2(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
793
794    pub fn flodl_maximum(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
795
796    pub fn flodl_minimum(a: FlodlTensor, b: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
797
798    // --- Additional reductions ---
799
800    pub fn flodl_argmin(
801        t: FlodlTensor,
802        dim: i32,
803        keepdim: i32,
804        result: *mut FlodlTensor,
805    ) -> *mut c_char;
806
807    pub fn flodl_var(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
808    pub fn flodl_std_op(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
809
810    pub fn flodl_var_dim(
811        t: FlodlTensor,
812        dim: i32,
813        keepdim: i32,
814        result: *mut FlodlTensor,
815    ) -> *mut c_char;
816
817    pub fn flodl_std_dim(
818        t: FlodlTensor,
819        dim: i32,
820        keepdim: i32,
821        result: *mut FlodlTensor,
822    ) -> *mut c_char;
823
824    pub fn flodl_cumprod(t: FlodlTensor, dim: i32, result: *mut FlodlTensor) -> *mut c_char;
825    pub fn flodl_norm_p_dim(
826        t: FlodlTensor,
827        p: f64,
828        dim: i32,
829        keepdim: i32,
830        result: *mut FlodlTensor,
831    ) -> *mut c_char;
832    pub fn flodl_sum_dims(
833        t: FlodlTensor,
834        dims: *mut i64,
835        ndims: i32,
836        keepdim: i32,
837        result: *mut FlodlTensor,
838    ) -> *mut c_char;
839    pub fn flodl_median(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
840    pub fn flodl_median_dim(
841        t: FlodlTensor,
842        dim: i32,
843        keepdim: i32,
844        values: *mut FlodlTensor,
845        indices: *mut FlodlTensor,
846    ) -> *mut c_char;
847    pub fn flodl_count_nonzero(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
848    pub fn flodl_count_nonzero_dim(
849        t: FlodlTensor,
850        dim: i32,
851        result: *mut FlodlTensor,
852    ) -> *mut c_char;
853
854    // --- Query ops ---
855
856    pub fn flodl_nonzero(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
857    pub fn flodl_unique(
858        t: FlodlTensor,
859        sorted: i32,
860        return_inverse: i32,
861        output: *mut FlodlTensor,
862        inverse_indices: *mut FlodlTensor,
863    ) -> *mut c_char;
864    pub fn flodl_unique_consecutive(
865        t: FlodlTensor,
866        return_inverse: i32,
867        output: *mut FlodlTensor,
868        inverse_indices: *mut FlodlTensor,
869    ) -> *mut c_char;
870    pub fn flodl_searchsorted(
871        sorted_seq: FlodlTensor,
872        values: FlodlTensor,
873        result: *mut FlodlTensor,
874    ) -> *mut c_char;
875
876    // --- Shape ops (advanced) ---
877
878    pub fn flodl_diagonal(
879        t: FlodlTensor,
880        offset: i64,
881        dim1: i32,
882        dim2: i32,
883        result: *mut FlodlTensor,
884    ) -> *mut c_char;
885    pub fn flodl_movedim(
886        t: FlodlTensor,
887        src: i64,
888        dst: i64,
889        result: *mut FlodlTensor,
890    ) -> *mut c_char;
891    pub fn flodl_tile(
892        t: FlodlTensor,
893        reps: *mut i64,
894        ndim: i32,
895        result: *mut FlodlTensor,
896    ) -> *mut c_char;
897
898    // --- Element-wise math (trig, rounding, sign) ---
899
900    pub fn flodl_sin(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
901    pub fn flodl_cos(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
902    pub fn flodl_tan(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
903    pub fn flodl_asin(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
904    pub fn flodl_acos(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
905    pub fn flodl_atan(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
906    pub fn flodl_sign(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
907    pub fn flodl_floor(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
908    pub fn flodl_ceil(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
909    pub fn flodl_round(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
910    pub fn flodl_reciprocal(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
911    pub fn flodl_erf(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
912    pub fn flodl_erfc(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
913    pub fn flodl_trunc(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
914    pub fn flodl_frac(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
915    pub fn flodl_fmod_scalar(t: FlodlTensor, scalar: f64, result: *mut FlodlTensor) -> *mut c_char;
916    pub fn flodl_fmod_tensor(
917        a: FlodlTensor,
918        b: FlodlTensor,
919        result: *mut FlodlTensor,
920    ) -> *mut c_char;
921    pub fn flodl_remainder_scalar(
922        t: FlodlTensor,
923        scalar: f64,
924        result: *mut FlodlTensor,
925    ) -> *mut c_char;
926    pub fn flodl_remainder_tensor(
927        a: FlodlTensor,
928        b: FlodlTensor,
929        result: *mut FlodlTensor,
930    ) -> *mut c_char;
931    pub fn flodl_lerp(
932        a: FlodlTensor,
933        b: FlodlTensor,
934        weight: f64,
935        result: *mut FlodlTensor,
936    ) -> *mut c_char;
937    pub fn flodl_lerp_tensor(
938        a: FlodlTensor,
939        b: FlodlTensor,
940        weight: FlodlTensor,
941        result: *mut FlodlTensor,
942    ) -> *mut c_char;
943    pub fn flodl_isclose(
944        a: FlodlTensor,
945        b: FlodlTensor,
946        rtol: f64,
947        atol: f64,
948        result: *mut FlodlTensor,
949    ) -> *mut c_char;
950
951    // --- Fused mul-add ---
952
953    pub fn flodl_addmm(
954        bias: FlodlTensor,
955        mat1: FlodlTensor,
956        mat2: FlodlTensor,
957        beta: f64,
958        alpha: f64,
959        result: *mut FlodlTensor,
960    ) -> *mut c_char;
961    pub fn flodl_addcmul(
962        self_: FlodlTensor,
963        t1: FlodlTensor,
964        t2: FlodlTensor,
965        value: f64,
966        result: *mut FlodlTensor,
967    ) -> *mut c_char;
968    pub fn flodl_addcdiv(
969        self_: FlodlTensor,
970        t1: FlodlTensor,
971        t2: FlodlTensor,
972        value: f64,
973        result: *mut FlodlTensor,
974    ) -> *mut c_char;
975
976    // --- Advanced indexing ---
977
978    pub fn flodl_gather(
979        t: FlodlTensor,
980        dim: i32,
981        index: FlodlTensor,
982        result: *mut FlodlTensor,
983    ) -> *mut c_char;
984
985    pub fn flodl_scatter_add(
986        t: FlodlTensor,
987        dim: i32,
988        index: FlodlTensor,
989        src: FlodlTensor,
990        result: *mut FlodlTensor,
991    ) -> *mut c_char;
992
993    // --- Sorting ---
994
995    pub fn flodl_topk(
996        t: FlodlTensor,
997        k: i64,
998        dim: i32,
999        largest: i32,
1000        sorted: i32,
1001        values: *mut FlodlTensor,
1002        indices: *mut FlodlTensor,
1003    ) -> *mut c_char;
1004
1005    pub fn flodl_sort(
1006        t: FlodlTensor,
1007        dim: i32,
1008        descending: i32,
1009        values: *mut FlodlTensor,
1010        indices: *mut FlodlTensor,
1011    ) -> *mut c_char;
1012
1013    // --- Tensor creation (additional) ---
1014
1015    pub fn flodl_eye(
1016        n: i64,
1017        dtype: i32,
1018        device_type: i32,
1019        device_index: i32,
1020        result: *mut FlodlTensor,
1021    ) -> *mut c_char;
1022
1023    pub fn flodl_full(
1024        shape: *mut i64,
1025        ndim: i32,
1026        value: f64,
1027        dtype: i32,
1028        device_type: i32,
1029        device_index: i32,
1030        result: *mut FlodlTensor,
1031    ) -> *mut c_char;
1032
1033    pub fn flodl_randperm(
1034        n: i64,
1035        dtype: i32,
1036        device_type: i32,
1037        device_index: i32,
1038        result: *mut FlodlTensor,
1039    ) -> *mut c_char;
1040
1041    pub fn flodl_multinomial(
1042        probs: FlodlTensor,
1043        num_samples: i64,
1044        replacement: i32,
1045        result: *mut FlodlTensor,
1046    ) -> *mut c_char;
1047
1048    // --- Normalization ---
1049
1050    pub fn flodl_normalize(
1051        t: FlodlTensor,
1052        p: f64,
1053        dim: i32,
1054        result: *mut FlodlTensor,
1055    ) -> *mut c_char;
1056
1057    // --- Shape operations (additional) ---
1058
1059    pub fn flodl_chunk(
1060        t: FlodlTensor,
1061        chunks: i32,
1062        dim: i32,
1063        results: *mut *mut FlodlTensor,
1064        count: *mut i32,
1065    ) -> *mut c_char;
1066
1067    pub fn flodl_repeat(
1068        t: FlodlTensor,
1069        repeats: *mut i64,
1070        ndim: i32,
1071        result: *mut FlodlTensor,
1072    ) -> *mut c_char;
1073
1074    pub fn flodl_pad(
1075        t: FlodlTensor,
1076        padding: *mut i64,
1077        pad_len: i32,
1078        value: f64,
1079        result: *mut FlodlTensor,
1080    ) -> *mut c_char;
1081
1082    // mode: 0=constant, 1=reflect, 2=replicate, 3=circular
1083    pub fn flodl_pad_mode(
1084        t: FlodlTensor,
1085        padding: *mut i64,
1086        pad_len: i32,
1087        mode: i32,
1088        value: f64,
1089        result: *mut FlodlTensor,
1090    ) -> *mut c_char;
1091
1092    // mode: 0=nearest, 1=bilinear, 2=bicubic, 3=trilinear
1093    pub fn flodl_interpolate(
1094        input: FlodlTensor,
1095        output_size: *mut i64,
1096        ndim: i32,
1097        mode: i32,
1098        align_corners: i32,
1099        result: *mut FlodlTensor,
1100    ) -> *mut c_char;
1101
1102    pub fn flodl_flip(
1103        t: FlodlTensor,
1104        dims: *mut i64,
1105        ndim: i32,
1106        result: *mut FlodlTensor,
1107    ) -> *mut c_char;
1108
1109    pub fn flodl_roll(
1110        t: FlodlTensor,
1111        shift: i64,
1112        dim: i32,
1113        result: *mut FlodlTensor,
1114    ) -> *mut c_char;
1115
1116    pub fn flodl_split(
1117        t: FlodlTensor,
1118        split_size: i64,
1119        dim: i32,
1120        results: *mut *mut FlodlTensor,
1121        count: *mut i32,
1122    ) -> *mut c_char;
1123
1124    pub fn flodl_unbind(
1125        t: FlodlTensor,
1126        dim: i32,
1127        results: *mut *mut FlodlTensor,
1128        count: *mut i32,
1129    ) -> *mut c_char;
1130
1131    pub fn flodl_contiguous(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
1132    pub fn flodl_is_contiguous(t: FlodlTensor) -> i32;
1133
1134    pub fn flodl_argsort(
1135        t: FlodlTensor,
1136        dim: i32,
1137        descending: i32,
1138        result: *mut FlodlTensor,
1139    ) -> *mut c_char;
1140
1141    pub fn flodl_scatter(
1142        t: FlodlTensor,
1143        dim: i32,
1144        index: FlodlTensor,
1145        src: FlodlTensor,
1146        result: *mut FlodlTensor,
1147    ) -> *mut c_char;
1148
1149    // --- Autograd ---
1150
1151    pub fn flodl_set_requires_grad(
1152        t: FlodlTensor,
1153        requires_grad: i32,
1154        result: *mut FlodlTensor,
1155    ) -> *mut c_char;
1156
1157    pub fn flodl_requires_grad(t: FlodlTensor) -> i32;
1158
1159    /// Force creation of the AccumulateGrad node for a leaf tensor with
1160    /// `requires_grad=true`. The node's stream is pinned to the current
1161    /// CUDA stream at the moment of this call. Use under `StreamGuard`
1162    /// to ensure DDP workers' parameters accumulate on the training
1163    /// stream, not the autograd engine's default stream.
1164    ///
1165    /// Writes an opaque handle to `*handle_out` that keeps the node
1166    /// alive. The caller must later pass it to
1167    /// [`flodl_grad_accumulator_delete`] to free it. For non-leaf or
1168    /// non-requires-grad tensors `*handle_out` is set to null.
1169    pub fn flodl_ensure_grad_accumulator(
1170        t: FlodlTensor,
1171        handle_out: *mut *mut c_void,
1172    ) -> *mut c_char;
1173
1174    /// Free a handle returned by [`flodl_ensure_grad_accumulator`].
1175    /// Safe to call with a null pointer.
1176    pub fn flodl_grad_accumulator_delete(handle: *mut c_void);
1177
1178    pub fn flodl_backward(t: FlodlTensor) -> *mut c_char;
1179
1180    pub fn flodl_grad(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
1181
1182    pub fn flodl_set_grad(t: FlodlTensor, grad: FlodlTensor) -> *mut c_char;
1183
1184    pub fn flodl_zero_grad(t: FlodlTensor) -> *mut c_char;
1185
1186    pub fn flodl_detach(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
1187
1188    pub fn flodl_detach_(t: FlodlTensor) -> *mut c_char;
1189
1190    pub fn flodl_is_leaf(t: FlodlTensor) -> i32;
1191
1192    // --- Autograd context ---
1193
1194    pub fn flodl_no_grad_guard_new() -> *mut c_void;
1195    pub fn flodl_no_grad_guard_delete(guard: *mut c_void);
1196    pub fn flodl_is_grad_enabled() -> i32;
1197
1198    // --- Autocast (automatic mixed precision) ---
1199
1200    pub fn flodl_autocast_guard_new(device_type: i32, dtype: i32) -> *mut c_void;
1201    pub fn flodl_autocast_guard_delete(guard: *mut c_void);
1202    pub fn flodl_is_autocast_enabled(device_type: i32) -> i32;
1203
1204    // --- Meshgrid ---
1205
1206    pub fn flodl_meshgrid(
1207        tensors: *mut FlodlTensor,
1208        count: i32,
1209        results: *mut *mut FlodlTensor,
1210        result_count: *mut i32,
1211    ) -> *mut c_char;
1212
1213    // --- Pairwise distance ---
1214
1215    pub fn flodl_cdist(
1216        x: FlodlTensor,
1217        y: FlodlTensor,
1218        p: f64,
1219        result: *mut FlodlTensor,
1220    ) -> *mut c_char;
1221
1222    // --- Cosine similarity ---
1223
1224    pub fn flodl_cosine_similarity(
1225        a: FlodlTensor,
1226        b: FlodlTensor,
1227        dim: i64,
1228        eps: f64,
1229        result: *mut FlodlTensor,
1230    ) -> *mut c_char;
1231
1232    // --- Fused ops ---
1233
1234    pub fn flodl_linear(
1235        input: FlodlTensor,
1236        weight: FlodlTensor,
1237        bias: FlodlTensor,
1238        result: *mut FlodlTensor,
1239    ) -> *mut c_char;
1240
1241    pub fn flodl_gru_cell(
1242        input: FlodlTensor,
1243        hx: FlodlTensor,
1244        w_ih: FlodlTensor,
1245        w_hh: FlodlTensor,
1246        b_ih: FlodlTensor,
1247        b_hh: FlodlTensor,
1248        result: *mut FlodlTensor,
1249    ) -> *mut c_char;
1250
1251    pub fn flodl_lstm_cell(
1252        input: FlodlTensor,
1253        hx: FlodlTensor,
1254        cx: FlodlTensor,
1255        w_ih: FlodlTensor,
1256        w_hh: FlodlTensor,
1257        b_ih: FlodlTensor,
1258        b_hh: FlodlTensor,
1259        h_out: *mut FlodlTensor,
1260        c_out: *mut FlodlTensor,
1261    ) -> *mut c_char;
1262
1263    // Fused sequence ops (cuDNN-accelerated)
1264    pub fn flodl_lstm(
1265        input: FlodlTensor,
1266        h_0: FlodlTensor,
1267        c_0: FlodlTensor,
1268        params: *const FlodlTensor,
1269        num_params: i64,
1270        num_layers: i64,
1271        batch_first: bool,
1272        flatten: bool,
1273        output: *mut FlodlTensor,
1274        h_n: *mut FlodlTensor,
1275        c_n: *mut FlodlTensor,
1276    ) -> *mut c_char;
1277
1278    pub fn flodl_gru(
1279        input: FlodlTensor,
1280        h_0: FlodlTensor,
1281        params: *const FlodlTensor,
1282        num_params: i64,
1283        num_layers: i64,
1284        batch_first: bool,
1285        flatten: bool,
1286        output: *mut FlodlTensor,
1287        h_n: *mut FlodlTensor,
1288    ) -> *mut c_char;
1289
1290    // Cached RNN params (zero per-forward overhead)
1291    pub fn flodl_rnn_params_create(
1292        params: *const FlodlTensor,
1293        num_params: i64,
1294        mode: i64,
1295        num_layers: i64,
1296        batch_first: bool,
1297        flatten: bool,
1298        out: *mut *mut std::os::raw::c_void,
1299    ) -> *mut c_char;
1300    pub fn flodl_rnn_params_free(rp: *mut std::os::raw::c_void);
1301    pub fn flodl_lstm_cached(
1302        input: FlodlTensor,
1303        h_0: FlodlTensor,
1304        c_0: FlodlTensor,
1305        rp: *mut std::os::raw::c_void,
1306        num_layers: i64,
1307        batch_first: bool,
1308        output: *mut FlodlTensor,
1309        h_n: *mut FlodlTensor,
1310        c_n: *mut FlodlTensor,
1311    ) -> *mut c_char;
1312    pub fn flodl_gru_cached(
1313        input: FlodlTensor,
1314        h_0: FlodlTensor,
1315        rp: *mut std::os::raw::c_void,
1316        num_layers: i64,
1317        batch_first: bool,
1318        output: *mut FlodlTensor,
1319        h_n: *mut FlodlTensor,
1320    ) -> *mut c_char;
1321
1322    // --- cuDNN benchmark ---
1323
1324    pub fn flodl_set_cudnn_benchmark(enable: i32);
1325
1326    // --- RNG seed ---
1327
1328    pub fn flodl_manual_seed(seed: u64);
1329    pub fn flodl_gpu_manual_seed_all(seed: u64);
1330
1331    // --- In-place operations ---
1332
1333    pub fn flodl_add_(t: FlodlTensor, other: FlodlTensor) -> *mut c_char;
1334    pub fn flodl_sub_(t: FlodlTensor, other: FlodlTensor) -> *mut c_char;
1335    pub fn flodl_mul_scalar_(t: FlodlTensor, scalar: f64) -> *mut c_char;
1336    pub fn flodl_add_scalar_(t: FlodlTensor, scalar: f64) -> *mut c_char;
1337    pub fn flodl_zero_(t: FlodlTensor) -> *mut c_char;
1338    pub fn flodl_mul_(t: FlodlTensor, other: FlodlTensor) -> *mut c_char;
1339    pub fn flodl_div_scalar_(t: FlodlTensor, scalar: f64) -> *mut c_char;
1340    pub fn flodl_div_(t: FlodlTensor, other: FlodlTensor) -> *mut c_char;
1341    pub fn flodl_fill_(t: FlodlTensor, value: f64) -> *mut c_char;
1342
1343    // --- Fused Adam step ---
1344
1345    pub fn flodl_adam_step(
1346        param: FlodlTensor,
1347        grad: FlodlTensor,
1348        m: FlodlTensor,
1349        v: FlodlTensor,
1350        lr: f64,
1351        beta1: f64,
1352        beta2: f64,
1353        eps: f64,
1354        weight_decay: f64,
1355        step: i64,
1356    ) -> *mut c_char;
1357
1358    // --- Batched Adam step ---
1359
1360    pub fn flodl_adam_step_batched(
1361        params: *mut FlodlTensor,
1362        grads: *mut FlodlTensor,
1363        ms: *mut FlodlTensor,
1364        vs: *mut FlodlTensor,
1365        lrs: *mut f64,
1366        count: i32,
1367        beta1: f64,
1368        beta2: f64,
1369        eps: f64,
1370        weight_decay: f64,
1371        step: i64,
1372    ) -> *mut c_char;
1373
1374    // --- Fused Adam/AdamW (multi-tensor kernel) ---
1375
1376    pub fn flodl_fused_adam_(
1377        params: *mut FlodlTensor,
1378        grads: *mut FlodlTensor,
1379        exp_avgs: *mut FlodlTensor,
1380        exp_avg_sqs: *mut FlodlTensor,
1381        count: i32,
1382        lr: f64,
1383        beta1: f64,
1384        beta2: f64,
1385        eps: f64,
1386        weight_decay: f64,
1387        steps: *const i64,
1388        grad_scale: FlodlTensor,
1389        found_inf: FlodlTensor,
1390    ) -> *mut c_char;
1391
1392    pub fn flodl_fused_adamw_(
1393        params: *mut FlodlTensor,
1394        grads: *mut FlodlTensor,
1395        exp_avgs: *mut FlodlTensor,
1396        exp_avg_sqs: *mut FlodlTensor,
1397        count: i32,
1398        lr: f64,
1399        beta1: f64,
1400        beta2: f64,
1401        eps: f64,
1402        weight_decay: f64,
1403        steps: *const i64,
1404        grad_scale: FlodlTensor,
1405        found_inf: FlodlTensor,
1406    ) -> *mut c_char;
1407
1408    // --- Pinned memory ---
1409
1410    pub fn flodl_pin_memory(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
1411    pub fn flodl_is_pinned(t: FlodlTensor) -> i32;
1412
1413    // --- Memory diagnostics ---
1414
1415    pub fn flodl_malloc_trim() -> i32;
1416
1417    // --- Zero grad (set_to_none) ---
1418
1419    pub fn flodl_zero_grad_set_to_none(t: FlodlTensor);
1420
1421    // --- Fused clip_grad_norm ---
1422
1423    pub fn flodl_clip_grad_norm(
1424        params: *mut FlodlTensor,
1425        count: i32,
1426        max_norm: f64,
1427        total_norm_out: *mut f64,
1428    ) -> *mut c_char;
1429
1430    // --- Multi-tensor foreach operations ---
1431
1432    pub fn flodl_foreach_add_scalar_(
1433        tensors: *mut FlodlTensor,
1434        count: i32,
1435        scalar: f64,
1436    ) -> *mut c_char;
1437
1438    pub fn flodl_foreach_mul_scalar_(
1439        tensors: *mut FlodlTensor,
1440        count: i32,
1441        scalar: f64,
1442    ) -> *mut c_char;
1443
1444    pub fn flodl_foreach_zero_(tensors: *mut FlodlTensor, count: i32) -> *mut c_char;
1445
1446    pub fn flodl_foreach_add_list_(
1447        tensors1: *mut FlodlTensor,
1448        tensors2: *mut FlodlTensor,
1449        count: i32,
1450        alpha: f64,
1451    ) -> *mut c_char;
1452
1453    pub fn flodl_foreach_norm(
1454        tensors: *mut FlodlTensor,
1455        count: i32,
1456        ord: f64,
1457        results: *mut FlodlTensor,
1458    ) -> *mut c_char;
1459
1460    pub fn flodl_foreach_lerp_scalar_(
1461        tensors1: *mut FlodlTensor,
1462        tensors2: *mut FlodlTensor,
1463        count: i32,
1464        weight: f64,
1465    ) -> *mut c_char;
1466
1467    pub fn flodl_foreach_sqrt_(tensors: *mut FlodlTensor, count: i32) -> *mut c_char;
1468
1469    // --- Autograd diagnostics ---
1470
1471    pub fn flodl_autograd_node_count(t: FlodlTensor) -> i64;
1472
1473    // --- Fused loss functions ---
1474
1475    pub fn flodl_mse_loss(
1476        pred: FlodlTensor,
1477        target: FlodlTensor,
1478        reduction: i64,
1479        result: *mut FlodlTensor,
1480    ) -> *mut c_char;
1481
1482    pub fn flodl_cross_entropy_loss(
1483        pred: FlodlTensor,
1484        target: FlodlTensor,
1485        reduction: i64,
1486        ignore_index: i64,
1487        label_smoothing: f64,
1488        result: *mut FlodlTensor,
1489    ) -> *mut c_char;
1490
1491    pub fn flodl_bce_with_logits_loss(
1492        pred: FlodlTensor,
1493        target: FlodlTensor,
1494        reduction: i64,
1495        result: *mut FlodlTensor,
1496    ) -> *mut c_char;
1497
1498    pub fn flodl_bce_loss(
1499        pred: FlodlTensor,
1500        target: FlodlTensor,
1501        reduction: i64,
1502        result: *mut FlodlTensor,
1503    ) -> *mut c_char;
1504
1505    pub fn flodl_l1_loss(
1506        pred: FlodlTensor,
1507        target: FlodlTensor,
1508        reduction: i64,
1509        result: *mut FlodlTensor,
1510    ) -> *mut c_char;
1511
1512    pub fn flodl_smooth_l1_loss(
1513        pred: FlodlTensor,
1514        target: FlodlTensor,
1515        reduction: i64,
1516        beta: f64,
1517        result: *mut FlodlTensor,
1518    ) -> *mut c_char;
1519
1520    pub fn flodl_kl_div_loss(
1521        input: FlodlTensor,
1522        target: FlodlTensor,
1523        reduction: i64,
1524        log_target: i32,
1525        result: *mut FlodlTensor,
1526    ) -> *mut c_char;
1527
1528    pub fn flodl_nll_loss(
1529        input: FlodlTensor,
1530        target: FlodlTensor,
1531        reduction: i64,
1532        ignore_index: i64,
1533        result: *mut FlodlTensor,
1534    ) -> *mut c_char;
1535
1536    pub fn flodl_ctc_loss(
1537        log_probs: FlodlTensor,
1538        targets: FlodlTensor,
1539        input_lengths: FlodlTensor,
1540        target_lengths: FlodlTensor,
1541        blank: i64,
1542        reduction: i64,
1543        result: *mut FlodlTensor,
1544    ) -> *mut c_char;
1545
1546    // --- Fused batch normalization ---
1547
1548    pub fn flodl_batch_norm(
1549        input: FlodlTensor,
1550        weight: FlodlTensor,
1551        bias: FlodlTensor,
1552        running_mean: FlodlTensor,
1553        running_var: FlodlTensor,
1554        training: i32,
1555        momentum: f64,
1556        eps: f64,
1557        result: *mut FlodlTensor,
1558    ) -> *mut c_char;
1559
1560    // --- Fused dropout ---
1561
1562    pub fn flodl_dropout(
1563        input: FlodlTensor,
1564        p: f64,
1565        training: i32,
1566        result: *mut FlodlTensor,
1567    ) -> *mut c_char;
1568
1569    pub fn flodl_feature_dropout(
1570        input: FlodlTensor,
1571        p: f64,
1572        training: i32,
1573        result: *mut FlodlTensor,
1574    ) -> *mut c_char;
1575
1576    // --- In-place copy ---
1577
1578    pub fn flodl_copy_(dst: FlodlTensor, src: FlodlTensor, non_blocking: i32) -> *mut c_char;
1579
1580    // --- Memory format ---
1581
1582    pub fn flodl_to_channels_last(t: FlodlTensor, result: *mut FlodlTensor) -> *mut c_char;
1583    pub fn flodl_is_channels_last(t: FlodlTensor) -> i32;
1584
1585    // --- Embedding lookup ---
1586
1587    pub fn flodl_embedding(
1588        weight: FlodlTensor,
1589        indices: FlodlTensor,
1590        padding_idx: i64,
1591        scale_grad_by_freq: i32,
1592        sparse: i32,
1593        result: *mut FlodlTensor,
1594    ) -> *mut c_char;
1595
1596    // --- Embedding bag ---
1597
1598    pub fn flodl_embedding_bag(
1599        weight: FlodlTensor,
1600        indices: FlodlTensor,
1601        offsets: FlodlTensor,
1602        mode: i64,
1603        result: *mut FlodlTensor,
1604    ) -> *mut c_char;
1605
1606    // --- CUDA Graphs ---
1607
1608    pub fn flodl_gpu_graph_new(graph_out: *mut *mut c_void) -> *mut c_char;
1609    pub fn flodl_gpu_graph_capture_begin(
1610        graph: *mut c_void,
1611        pool_hi: u64,
1612        pool_lo: u64,
1613        mode: i32,
1614    ) -> *mut c_char;
1615    pub fn flodl_gpu_graph_capture_end(graph: *mut c_void) -> *mut c_char;
1616    pub fn flodl_gpu_graph_replay(graph: *mut c_void) -> *mut c_char;
1617    pub fn flodl_gpu_graph_reset(graph: *mut c_void) -> *mut c_char;
1618    pub fn flodl_gpu_graph_delete(graph: *mut c_void);
1619    pub fn flodl_gpu_graph_pool(graph: *mut c_void, pool_hi: *mut u64, pool_lo: *mut u64);
1620    pub fn flodl_gpu_graph_pool_handle(pool_hi: *mut u64, pool_lo: *mut u64);
1621
1622    // --- CUDA Events ---
1623
1624    pub fn flodl_gpu_event_new(flags: i32, event_out: *mut *mut c_void) -> *mut c_char;
1625    pub fn flodl_gpu_event_record(event: *mut c_void) -> *mut c_char;
1626    pub fn flodl_gpu_event_record_on_stream(event: *mut c_void, stream: *mut c_void)
1627    -> *mut c_char;
1628    pub fn flodl_gpu_event_synchronize(event: *mut c_void) -> *mut c_char;
1629    pub fn flodl_gpu_event_elapsed_time(
1630        start: *mut c_void,
1631        end: *mut c_void,
1632        ms_out: *mut f32,
1633    ) -> *mut c_char;
1634    pub fn flodl_gpu_event_query(event: *mut c_void) -> i32;
1635    pub fn flodl_gpu_event_delete(event: *mut c_void);
1636
1637    // --- CUDA Streams ---
1638
1639    pub fn flodl_gpu_stream_new(
1640        device_index: i32,
1641        high_priority: i32,
1642        stream_out: *mut *mut c_void,
1643    ) -> *mut c_char;
1644    pub fn flodl_gpu_stream_synchronize(stream: *mut c_void) -> *mut c_char;
1645    pub fn flodl_gpu_stream_wait_event(stream: *mut c_void, event: *mut c_void) -> *mut c_char;
1646    pub fn flodl_tensor_record_stream(tensor: *mut c_void, stream: *mut c_void) -> *mut c_char;
1647    pub fn flodl_gpu_stream_query(stream: *mut c_void) -> i32;
1648    pub fn flodl_gpu_stream_set_current(stream: *mut c_void);
1649    pub fn flodl_gpu_stream_get_current(device_index: i32) -> *mut c_void;
1650    pub fn flodl_gpu_stream_restore_default(device_index: i32);
1651    pub fn flodl_gpu_stream_delete(stream: *mut c_void);
1652
1653    // --- NCCL Collective Operations ---
1654
1655    pub fn flodl_nccl_init(
1656        ndev: i32,
1657        devlist: *const i32,
1658        handle_out: *mut *mut c_void,
1659    ) -> *mut c_char;
1660    pub fn flodl_nccl_destroy(handle: *mut c_void);
1661    pub fn flodl_nccl_all_reduce(
1662        handle: *mut c_void,
1663        tensors: *mut FlodlTensor,
1664        streams: *mut *mut c_void,
1665        op: i32,
1666    ) -> *mut c_char;
1667    pub fn flodl_nccl_broadcast(
1668        handle: *mut c_void,
1669        tensors: *mut FlodlTensor,
1670        streams: *mut *mut c_void,
1671        root: i32,
1672    ) -> *mut c_char;
1673    pub fn flodl_nccl_size(handle: *mut c_void) -> i32;
1674
1675    // --- NCCL Per-Rank Operations ---
1676
1677    pub fn flodl_nccl_runtime_version(version_out: *mut i32) -> *mut c_char;
1678    pub fn flodl_nccl_get_unique_id(uid_out: *mut u8) -> *mut c_char;
1679    pub fn flodl_nccl_init_rank(
1680        rank: i32,
1681        nranks: i32,
1682        uid: *const u8,
1683        handle_out: *mut *mut c_void,
1684    ) -> *mut c_char;
1685    pub fn flodl_nccl_destroy_rank(handle: *mut c_void);
1686    pub fn flodl_nccl_abort_rank(handle: *mut c_void) -> *mut c_char;
1687    pub fn flodl_nccl_all_reduce_rank(
1688        handle: *mut c_void,
1689        tensors: *mut FlodlTensor,
1690        ntensors: i32,
1691        stream: *mut c_void,
1692        op: i32,
1693    ) -> *mut c_char;
1694    pub fn flodl_nccl_redop_premulsum_create_rank(
1695        handle: *mut c_void,
1696        scalar: f32,
1697        op_out: *mut i32,
1698    ) -> *mut c_char;
1699    pub fn flodl_nccl_redop_destroy_rank(handle: *mut c_void, op: i32) -> *mut c_char;
1700    pub fn flodl_nccl_broadcast_rank(
1701        handle: *mut c_void,
1702        tensors: *mut FlodlTensor,
1703        ntensors: i32,
1704        stream: *mut c_void,
1705        root: i32,
1706    ) -> *mut c_char;
1707    pub fn flodl_nccl_split_rank(
1708        group_handle: *mut c_void,
1709        rank: i32,
1710        rank_handle_out: *mut *mut c_void,
1711    ) -> *mut c_char;
1712
1713    // --- Utility ---
1714
1715    pub fn flodl_free_string(s: *mut c_char);
1716}