tenferro_tropical_capi/lib.rs
1//! C-API (FFI) for tropical semiring tensor operations.
2//!
3//! Extends [`tenferro_capi`] with tropical einsum functions for three
4//! semirings: MaxPlus (⊕=max, ⊗=+), MinPlus (⊕=min, ⊗=+), and
5//! MaxMul (⊕=max, ⊗=×).
6//!
7//! # Design
8//!
9//! - **Reuses [`TfeTensorF64`]** handles from `tenferro-capi`. Since
10//! `MaxPlus<f64>` is `#[repr(transparent)]`, it has the same memory
11//! layout as `f64`. Tropical functions accept f64 tensor handles,
12//! internally wrap data as `MaxPlus<f64>` (or `MinPlus`/`MaxMul`),
13//! perform the tropical einsum, and unwrap the result back to f64.
14//! - **No new handle type** — the algebra is selected by the function
15//! name, not the tensor type.
16//! - **Naming convention**: `tfe_tropical_einsum_<algebra>_f64`.
17//!
18//! # Linking
19//!
20//! This crate produces a separate shared library from `tenferro-capi`.
21//! C/Julia/Python consumers load both:
22//!
23//! ```c
24//! // Core tensor operations
25//! tfe_tensor_f64 *t = tfe_tensor_f64_from_data(...);
26//!
27//! // Tropical einsum (from tenferro-tropical-capi)
28//! const tfe_tensor_f64 *ops[] = {a, b};
29//! tfe_tensor_f64 *c = tfe_tropical_einsum_maxplus_f64("ij,jk->ik", ops, 2, &status);
30//! ```
31//!
32//! # Example (C pseudocode)
33//!
34//! ```c
35//! #include "tenferro.h"
36//! #include "tenferro_tropical.h"
37//!
38//! tfe_status_t status;
39//! size_t shape[] = {3, 4};
40//! double data_a[12] = { /* ... */ };
41//! double data_b[12] = { /* ... */ };
42//!
43//! tfe_tensor_f64 *a = tfe_tensor_f64_from_data(data_a, 12, shape, 2, &status);
44//! tfe_tensor_f64 *b = tfe_tensor_f64_from_data(data_b, 12, shape, 2, &status);
45//!
46//! // MaxPlus tropical einsum: C[i,k] = max_j (A[i,j] + B[j,k])
47//! const tfe_tensor_f64 *ops[] = {a, b};
48//! tfe_tensor_f64 *c = tfe_tropical_einsum_maxplus_f64("ij,jk->ik", ops, 2, &status);
49//! assert(status == TFE_SUCCESS);
50//!
51//! tfe_tensor_f64_release(c);
52//! tfe_tensor_f64_release(b);
53//! tfe_tensor_f64_release(a);
54//! ```
55
56#![allow(clippy::missing_safety_doc)]
57#![allow(non_camel_case_types)]
58
59use std::os::raw::c_char;
60
61use tenferro_capi::{tfe_status_t, TfeTensorF64};
62
63// ============================================================================
64// MaxPlus einsum
65// ============================================================================
66
67/// Execute tropical einsum under MaxPlus algebra (⊕=max, ⊗=+).
68///
69/// Accepts standard `TfeTensorF64` handles. Data is interpreted as
70/// `MaxPlus<f64>` internally: addition becomes `max`, multiplication
71/// becomes ordinary `+`.
72///
73/// Returns a new tensor. The caller must release it with
74/// `tfe_tensor_f64_release`.
75///
76/// # Safety
77///
78/// - `subscripts` must be a valid null-terminated C string.
79/// - `operands` must point to an array of `num_operands` valid tensor pointers.
80/// - `status` must be a valid, non-null pointer.
81///
82/// # Examples (C)
83///
84/// ```c
85/// const tfe_tensor_f64 *ops[] = {a, b};
86/// tfe_status_t status;
87/// // C[i,k] = max_j (A[i,j] + B[j,k])
88/// tfe_tensor_f64 *c = tfe_tropical_einsum_maxplus_f64("ij,jk->ik", ops, 2, &status);
89/// tfe_tensor_f64_release(c);
90/// ```
91#[no_mangle]
92pub unsafe extern "C" fn tfe_tropical_einsum_maxplus_f64(
93 _subscripts: *const c_char,
94 _operands: *const *const TfeTensorF64,
95 _num_operands: usize,
96 _status: *mut tfe_status_t,
97) -> *mut TfeTensorF64 {
98 todo!()
99}
100
101/// Reverse-mode rule (VJP) for MaxPlus tropical einsum.
102///
103/// Computes one gradient tensor per input operand given the output
104/// cotangent. The caller must provide `grads_out` as a pre-allocated
105/// array of `num_operands` pointers.
106///
107/// # Safety
108///
109/// - `subscripts` must be a valid null-terminated C string.
110/// - `operands` must point to an array of `num_operands` valid tensor pointers.
111/// - `cotangent` must be a valid, non-null tensor pointer.
112/// - `grads_out` must point to a caller-allocated array of `num_operands`
113/// mutable `*mut TfeTensorF64` pointers.
114/// - `status` must be a valid, non-null pointer.
115///
116/// # Examples (C)
117///
118/// ```c
119/// tfe_tensor_f64 *grads[2];
120/// tfe_status_t status;
121/// const tfe_tensor_f64 *ops[] = {a, b};
122/// tfe_tropical_einsum_rrule_maxplus_f64("ij,jk->ik", ops, 2, grad_c, grads, &status);
123/// tfe_tensor_f64_release(grads[0]);
124/// tfe_tensor_f64_release(grads[1]);
125/// ```
126#[no_mangle]
127pub unsafe extern "C" fn tfe_tropical_einsum_rrule_maxplus_f64(
128 _subscripts: *const c_char,
129 _operands: *const *const TfeTensorF64,
130 _num_operands: usize,
131 _cotangent: *const TfeTensorF64,
132 _grads_out: *mut *mut TfeTensorF64,
133 _status: *mut tfe_status_t,
134) {
135 todo!()
136}
137
138/// Forward-mode rule (JVP) for MaxPlus tropical einsum.
139///
140/// Returns the output tangent. Elements of `tangents` may be null
141/// (interpreted as zero tangent for that operand).
142///
143/// # Safety
144///
145/// - `subscripts` must be a valid null-terminated C string.
146/// - `primals` must point to an array of `num_operands` valid tensor pointers.
147/// - `tangents` must point to an array of `num_operands` tensor pointers
148/// (elements may be null).
149/// - `status` must be a valid, non-null pointer.
150///
151/// # Examples (C)
152///
153/// ```c
154/// const tfe_tensor_f64 *primals[] = {a, b};
155/// const tfe_tensor_f64 *tangents[] = {da, NULL};
156/// tfe_status_t status;
157/// tfe_tensor_f64 *dc = tfe_tropical_einsum_frule_maxplus_f64(
158/// "ij,jk->ik", primals, 2, tangents, &status);
159/// tfe_tensor_f64_release(dc);
160/// ```
161#[no_mangle]
162pub unsafe extern "C" fn tfe_tropical_einsum_frule_maxplus_f64(
163 _subscripts: *const c_char,
164 _primals: *const *const TfeTensorF64,
165 _num_operands: usize,
166 _tangents: *const *const TfeTensorF64,
167 _status: *mut tfe_status_t,
168) -> *mut TfeTensorF64 {
169 todo!()
170}
171
172// ============================================================================
173// MinPlus einsum
174// ============================================================================
175
176/// Execute tropical einsum under MinPlus algebra (⊕=min, ⊗=+).
177///
178/// Same interface as [`tfe_tropical_einsum_maxplus_f64`] but uses
179/// min-plus semantics: addition becomes `min`, multiplication becomes `+`.
180///
181/// # Safety
182///
183/// Same as [`tfe_tropical_einsum_maxplus_f64`].
184///
185/// # Examples (C)
186///
187/// ```c
188/// const tfe_tensor_f64 *ops[] = {a, b};
189/// tfe_status_t status;
190/// // C[i,k] = min_j (A[i,j] + B[j,k])
191/// tfe_tensor_f64 *c = tfe_tropical_einsum_minplus_f64("ij,jk->ik", ops, 2, &status);
192/// tfe_tensor_f64_release(c);
193/// ```
194#[no_mangle]
195pub unsafe extern "C" fn tfe_tropical_einsum_minplus_f64(
196 _subscripts: *const c_char,
197 _operands: *const *const TfeTensorF64,
198 _num_operands: usize,
199 _status: *mut tfe_status_t,
200) -> *mut TfeTensorF64 {
201 todo!()
202}
203
204/// Reverse-mode rule (VJP) for MinPlus tropical einsum.
205///
206/// # Safety
207///
208/// Same as [`tfe_tropical_einsum_rrule_maxplus_f64`].
209#[no_mangle]
210pub unsafe extern "C" fn tfe_tropical_einsum_rrule_minplus_f64(
211 _subscripts: *const c_char,
212 _operands: *const *const TfeTensorF64,
213 _num_operands: usize,
214 _cotangent: *const TfeTensorF64,
215 _grads_out: *mut *mut TfeTensorF64,
216 _status: *mut tfe_status_t,
217) {
218 todo!()
219}
220
221/// Forward-mode rule (JVP) for MinPlus tropical einsum.
222///
223/// # Safety
224///
225/// Same as [`tfe_tropical_einsum_frule_maxplus_f64`].
226#[no_mangle]
227pub unsafe extern "C" fn tfe_tropical_einsum_frule_minplus_f64(
228 _subscripts: *const c_char,
229 _primals: *const *const TfeTensorF64,
230 _num_operands: usize,
231 _tangents: *const *const TfeTensorF64,
232 _status: *mut tfe_status_t,
233) -> *mut TfeTensorF64 {
234 todo!()
235}
236
237// ============================================================================
238// MaxMul einsum
239// ============================================================================
240
241/// Execute tropical einsum under MaxMul algebra (⊕=max, ⊗=×).
242///
243/// Same interface as [`tfe_tropical_einsum_maxplus_f64`] but uses
244/// max-times semantics: addition becomes `max`, multiplication becomes `×`.
245///
246/// # Safety
247///
248/// Same as [`tfe_tropical_einsum_maxplus_f64`].
249///
250/// # Examples (C)
251///
252/// ```c
253/// const tfe_tensor_f64 *ops[] = {a, b};
254/// tfe_status_t status;
255/// // C[i,k] = max_j (A[i,j] * B[j,k])
256/// tfe_tensor_f64 *c = tfe_tropical_einsum_maxmul_f64("ij,jk->ik", ops, 2, &status);
257/// tfe_tensor_f64_release(c);
258/// ```
259#[no_mangle]
260pub unsafe extern "C" fn tfe_tropical_einsum_maxmul_f64(
261 _subscripts: *const c_char,
262 _operands: *const *const TfeTensorF64,
263 _num_operands: usize,
264 _status: *mut tfe_status_t,
265) -> *mut TfeTensorF64 {
266 todo!()
267}
268
269/// Reverse-mode rule (VJP) for MaxMul tropical einsum.
270///
271/// # Safety
272///
273/// Same as [`tfe_tropical_einsum_rrule_maxplus_f64`].
274#[no_mangle]
275pub unsafe extern "C" fn tfe_tropical_einsum_rrule_maxmul_f64(
276 _subscripts: *const c_char,
277 _operands: *const *const TfeTensorF64,
278 _num_operands: usize,
279 _cotangent: *const TfeTensorF64,
280 _grads_out: *mut *mut TfeTensorF64,
281 _status: *mut tfe_status_t,
282) {
283 todo!()
284}
285
286/// Forward-mode rule (JVP) for MaxMul tropical einsum.
287///
288/// # Safety
289///
290/// Same as [`tfe_tropical_einsum_frule_maxplus_f64`].
291#[no_mangle]
292pub unsafe extern "C" fn tfe_tropical_einsum_frule_maxmul_f64(
293 _subscripts: *const c_char,
294 _primals: *const *const TfeTensorF64,
295 _num_operands: usize,
296 _tangents: *const *const TfeTensorF64,
297 _status: *mut tfe_status_t,
298) -> *mut TfeTensorF64 {
299 todo!()
300}