Add ekore_capi#537
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a new ekore_capi crate to expose ekore’s anomalous dimensions and operator matrix elements through a C ABI, and tightens internal visibility in ekore to keep implementation details private while preserving higher-level APIs.
Changes:
- Added
crates/ekore_capiwith C-ABI entrypoints for unpolarized/polarized anomalous dimensions and unpolarized space-like OMEs, plusCacheallocation/free helpers. - Adjusted visibility in
ekore(manypub→pub(super)/pub(crate), andpub mod→mod) to reduce exposed internals. - Added
cbindgen/cargo-cmetadata and updated the lockfile to include the new crate.
Reviewed changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/ekore/src/operator_matrix_elements/unpolarized/spacelike/as2.rs | Restricts OME helper function visibility to module scope. |
| crates/ekore/src/operator_matrix_elements/unpolarized/spacelike/as1.rs | Restricts OME helper function visibility to module scope. |
| crates/ekore/src/operator_matrix_elements/unpolarized/spacelike.rs | Makes as1/as2 internal modules. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as4/gqg.rs | Restricts N3LO component function visibility. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as4/gps.rs | Restricts N3LO component function visibility. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as4/gnsv.rs | Narrows visibility of gamma_nsv. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as4/gnsp.rs | Narrows visibility of gamma_nsp. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as4/gnsm.rs | Narrows visibility of gamma_nsm. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as4/ggq.rs | Restricts N3LO component function visibility. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as4/ggg.rs | Restricts N3LO component function visibility. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as4.rs | Removes public re-exports and makes singlet entry internal. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as3.rs | Restricts NNLO functions to parent module. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as2.rs | Narrows visibility of NLO functions and singlet helper pieces. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as1aem1.rs | Restricts mixed QCD×QED pieces to parent module. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as1.rs | Narrows visibility of LO helper pieces. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/aem2.rs | Restricts NLO QED pieces to parent module. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/aem1.rs | Restricts LO QED pieces to parent module. |
| crates/ekore/src/anomalous_dimensions/unpolarized/spacelike.rs | Makes most submodules internal; keeps as1/as2 crate-visible. |
| crates/ekore/src/anomalous_dimensions/polarized/spacelike/as2.rs | Restricts polarized NLO functions to parent module. |
| crates/ekore/src/anomalous_dimensions/polarized/spacelike/as1.rs | Restricts polarized LO functions to parent module. |
| crates/ekore/src/anomalous_dimensions/polarized/spacelike.rs | Makes polarized as1/as2 internal modules. |
| crates/ekore_capi/src/lib.rs | Defines C-facing ComplexF64 and Cache lifecycle API; wires C API modules. |
| crates/ekore_capi/src/ad_us.rs | Adds C ABI wrappers for unpolarized space-like anomalous dimensions (QCD and QCD×QED). |
| crates/ekore_capi/src/ad_ps.rs | Adds C ABI wrappers for polarized space-like anomalous dimensions (QCD). |
| crates/ekore_capi/src/ome_us.rs | Adds C ABI wrappers for unpolarized space-like OME towers. |
| crates/ekore_capi/README.md | Documents crate purpose and citation policy. |
| crates/ekore_capi/cbindgen.toml | Configures C header generation. |
| crates/ekore_capi/Cargo.toml | Declares new crate, crate-type, and cargo-c metadata. |
| Cargo.lock | Adds ekore_capi to the workspace lockfile. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
For change in visibility of ekore functions, I changed all of them to What I will do later:
There are a few doubts for which I want your opinion: For ekore:
For ekore_capi:
cargo cinstall --release -p ekore_capi --destdir=./crates/ekore_capi/dist --prefix=/We can then publish the dist as a GitHub release (as it is done in pineappl).
My initial thought is to make only the Other things I thought we could've done for #518, but can be done here:
Do let me know your thoughts. |
|
CoPilot reviews Summary:
My initial thought is to add safeguards and not bump the Rust version. Please let me know your thoughts too. |
|
Small note, the |
Indeed, I noticed. I hope the relevant people become aware quickly and are able to do something ... |
|
Should I fix #538 here or in a separate branch? |
felixhekhorn
left a comment
There was a problem hiding this comment.
- many comments generalize to other cases
- I think it would be a good idea to split cf61e01 into a separate PR (since it affects lot's of files and does effectively nothing) and then put this one with just the C API on top
There was a problem hiding this comment.
I wonder if we should apply some kind of meta programming ... because the function body of ad_ps_gamma_ns_qcd will look the same in all variations. The only thing that might change (and I'm not sure how that would manifest in the interface) is the maximum available order ...
There was a problem hiding this comment.
We can explore this after most of the stuff is done.
There was a problem hiding this comment.
Using macro_rules!, we can remove duplicate code. Do tell me if I should start working on that.
all these go into separate PRs; the |
I would say, let's follow our established logic, that we first expose as little as possible. In this case we have to expose
I think this requires some work, because again I want to expose as little as possible. We need to expose the PID as they are an explicit input, but I want to hide all the other things. I suggest to split the files into several parts corresponding to different math/physics and then we only expose what we need.
yes, please. Please import all tests from the Python side which are not implemented yet. My idea is to use these same tests also in the CI to test the capo.
yes, let's follow what other people do (and make our life easier)
yes, we must. If we want to provide an API we must provide the documentation along side it else it is pointless |
We can safely raise the MSRV I would say. Again, let's follow PineAPPL and they are currently at "raised MSRV to 1.91.0
I agree - I think it is the rust way to add guards |
remember that Fortran has very low priority, but all the other stuff is crucial. Now, looking at the flood of comments above I think this PR is a good start, but we should split some stuff from this PR and address problems that got revealed here first, before pushing further on this front (when we will surely discover more problems). In short, let's try to make a bunch of small PRs first instead of one big one |
Let me add a TODO as a comment here: EDIT: moved to top |
|
Is this relevant for us NNPDF/pineappl@823a4f7 ? |
felixhekhorn
left a comment
There was a problem hiding this comment.
some of the comments obviously generalise to other cases, if you agree
| - name: Get test data | ||
| id: cache-test-data | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: test-data | ||
| key: test-data-v2 | ||
| - name: Download test data | ||
| if: steps.cache-test-data.outputs.cache-hit != 'true' | ||
| run: | | ||
| ./tests/data/assets.sh |
There was a problem hiding this comment.
We don't need any data, no? so drop
| /// # Returns | ||
| /// * Returns the fixed required buffer length of `3`. | ||
| #[unsafe(no_mangle)] | ||
| pub extern "C" fn ad_ps_gamma_ns_qcd_n3lo_len() -> usize { |
There was a problem hiding this comment.
I don't think this function makes sense: n3lo_variation in ad_ps_gamma_ns_qcd must be exactly 3 and no other and users must provide exactly those and they must know what it refers to - drop
| /// | ||
| /// # Safety | ||
| /// * `c` must be a valid, non-null pointer to an initialized `Cache`. | ||
| /// * `n3lo_variation` must be a valid, non-null pointer to a buffer of `u8` elements. |
There was a problem hiding this comment.
| /// * `n3lo_variation` must be a valid, non-null pointer to a buffer of `u8` elements. | |
| /// * `n3lo_variation` must be a valid, non-null pointer to a buffer of `u8` three elements. |
| c: *mut Cache, | ||
| nf: u8, | ||
| n3lo_variation: *const u8, | ||
| n3lo_len: usize, |
There was a problem hiding this comment.
drop as discussed above - the size is (rightfully) forced here
eko/crates/ekore_capi/src/ad_us.rs
Line 82 in 76ae5bf
| /// Maximum QCD coupling power implemented. | ||
| pub const MAX_ORDER_QCD: usize = 4; | ||
| /// Maximum QED coupling power implemented. | ||
| pub const MAX_ORDER_QED: usize = 2; | ||
|
|
||
| /// singlet-like non-singlet |PID|. | ||
| pub const PID_NSP: u16 = 10101; | ||
| /// valence-like non-singlet |PID|. | ||
| pub const PID_NSM: u16 = 10201; | ||
| /// non-singlet all-valence |PID|. | ||
| pub const PID_NSV: u16 = 10200; | ||
| /// singlet-like non-singlet up-sector |PID|. | ||
| pub const PID_NSP_U: u16 = 10102; | ||
| /// singlet-like non-singlet down-sector |PID|. | ||
| pub const PID_NSP_D: u16 = 10103; | ||
| /// valence-like non-singlet up-sector |PID|. | ||
| pub const PID_NSM_U: u16 = 10202; | ||
| /// valence-like non-singlet down-sector |PID|. | ||
| pub const PID_NSM_D: u16 = 10203; | ||
|
|
||
| // Compile-time assertions to ensure C API constants remain synced with `ekore` | ||
| const _: () = { | ||
| assert!(MAX_ORDER_QCD == ekore::constants::MAX_ORDER_QCD); | ||
| assert!(MAX_ORDER_QED == ekore::constants::MAX_ORDER_QED); | ||
| assert!(PID_NSP == ekore::constants::PID_NSP); | ||
| assert!(PID_NSM == ekore::constants::PID_NSM); | ||
| assert!(PID_NSV == ekore::constants::PID_NSV); | ||
| assert!(PID_NSP_U == ekore::constants::PID_NSP_U); | ||
| assert!(PID_NSP_D == ekore::constants::PID_NSP_D); | ||
| assert!(PID_NSM_U == ekore::constants::PID_NSM_U); | ||
| assert!(PID_NSM_D == ekore::constants::PID_NSM_D); | ||
| }; |
There was a problem hiding this comment.
why are they not just re-imported in the first place? no need to define them twice, no?
There was a problem hiding this comment.
should we add a proper unit testing framework?
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
|
|
||
| static int check_len(const char *label, size_t got, size_t expected) |
There was a problem hiding this comment.
if we don't go for a proper framework, surely this belongs into utils
There was a problem hiding this comment.
this is (quasi) verbatim the same file as for .c, no? why would we do such a thing? I think C is enough and users who write C++ can use that just the same, I'd say
| - name: Enforce tag-only execution | ||
| if: github.ref_type != 'tag' | ||
| run: | | ||
| echo "Error: Manual dispatches must be run against a tag, not a branch." | ||
| exit 1 |
There was a problem hiding this comment.
This is inconvenient for debugging - can't why change it such that if it is a tag the files are uploaded there, if it is not, the files are just stored as artifacts to the job?
A step for #519 ; we explicitly shape our public API along the way #145
In this PR we:
TODO
Create and merge a PR for:
--releasetag. Fix poe compile #541ekorevisibility. Changing visibility of ekore and Splitting constants.rs #543crates/ekore/src/constants.rs#539 Changing visibility of ekore and Splitting constants.rs #543spacelike.rstests. Add tests to spacelike.rs files #546msrv.ymlAdd msrv.yml #545Only after all that, in this PR: