Skip to content

expose compile-time options to R users (if possible) #41

Open

Description

@corybrunson

Ripser includes several compile-time options that ideally would be made available to R users. I can see two naïve ways that this could definitely be done, neither appropriate:

  1. Turn "on" each of the options in the source code, incurring their cumulative additional cost to all R executions.
  2. Duplicate the source code for each desired combination of settings and (internally) export separate functions to be called according to parameters passed to the user-facing R function.

I wonder if either of the following is instead possible:
3. Allow users to control these options at installation or (far preferable) at loading.
4. Iterate compilation of the source code over each desired combination of settings to produce separate compiled functions to serve as in (2).

I searched through much of the {Rcpp} documentation and SO exchanges and found no insight into this issue.

Activity

  1. corybrunson commented on Jul 5, 2025

    @corybrunson
    MemberAuthor

    @astamm, do you have any ideas?

  2. corybrunson commented on Jul 5, 2025

    @corybrunson
    MemberAuthor

    @rrrlw i don't believe you faced this issue originally, but you might well have insights i don't.

  3. rrrlw commented on Jul 5, 2025

    @rrrlw
    Member

    Faced the same issue, but I skipped the functionality I couldn't implement and found a workaround for the remaining, as follows:

    • USE_COEFFICIENTS: subjectively assumed this was an optimization (i.e., could speed up processing without affecting outputs); did not prioritize including functionality for this
    • INDICATE_PROGRESS: useful but did not prioritize including functionality for this; potential workaround is adding a boolean parameter in the C++ code (i.e., in the function that Rcpp calls) and, if true, could add an update output message in one of the for or while loops in the calculation (e.g., one output per dimension)
    • PRINT_PERSISTENCE_PAIRS: intentionally did not implement this; the persistence pairs were returned to R through Rcpp; if output was desired, could implement this in the R function
    • USE_ROBINHOOD_HASHMAP: I don't recall this being available, but it has been a few years (i.e., potentially a more recent addition to Ripser)
    • --format: worked around this; what Ripser in C++ does is take all the formats and converts to a single one (I believe lower triangular distance matrix) before actually processing; what I did was remove the C++ code for these formatting conversions from Ripser, implement them in R (e.g., using the dist function), and then only have the lower triangular distance matrix ever passed from R to C++; it all looked the same to the user but the formatting conversion was happening in R instead of C++, so the --format's functionality was still preserved (i.e., in R), but I did not need to do anything with the C++ compile-time option. In theory, you could switch it to a parameter in the C++ function that Rcpp calls and preserve all the formatting conversion code in C++.
    • --dim: believe I moved this to be a parameter of the function Rcpp called and changed the appropriate references in the C++ code from the compile-time option to the parameter
    • --threshold: same as --dim
    • --modulus: unsure if I did anything for this, but it should work the same as --dim as well
    • --ratio: I do not recall this being available, but it should work the same as --dim as well

    Please pardon any memory lapses on my part, hope above helps!

  4. corybrunson commented on Jul 5, 2025

    @corybrunson
    MemberAuthor

    @rrrlw thank you! Though i should have better articulated my interests—i'm on the train with spotty wifi.

    The execution-time options (--* ... at least this is my understanding) i think the students and i figured out how to handle properly—they're not all done yet but we think we know how to proceed.

    Of the compile time options listed on the current README, which i struggle to imagine how to make available to the R user, i'm only concerned and hopeful that we can enable arbitrary finite field coefficients. Though i wonder if the form that takes will inform an eventual solution to inserting code to collect cycle and cocycle representatives. I think these three features are essential in the medium term.

    By the way, we also plan to convert the value type for persistent pairs from floats to doubles (without an option), partly in the interest of an ongoing project that requires such precision but also because R users are accustomed to it. Do you foresee any problems doing this?

  5. SeanHersh commented on Oct 7, 2025

    @SeanHersh
    Collaborator

    Hello!

    This is a really helpful discussion to follow.

    A few approaches came up while thinking about how to handle the compile-time options:

    Option A: Separate helper functions for the key compile-time flags (e.g. one for binary coefficients, one for arbitrary), which lines up with Cory’s suggestion.

    Option B: Build each desired variant at compile time and call the appropriate compiled function.

    Option C: Add runtime toggles, which would give the most flexibility but would require more invasive refactoring.

    From the discussion so far, Option A looks like the most practical first step, since it would expose important settings (like the coefficient field) without forcing everything on or duplicating the codebase.

    Meanwhile, benchmarking is still ongoing to get a clearer picture of which flags have the biggest effect on performance. Those results should help decide which options are worth prioritizing when moving toward a more flexible interface.

  6. corybrunson commented on Oct 7, 2025

    @corybrunson
    MemberAuthor

    @SeanHersh thank you! Though could you distinguish between Options A and B? (We had an email exchange and i'm not sure whether the options here are the same as there.)

    Here's what i imagine making the most sense, based on what we've discussed—the "flag" might be USE_COEFFICIENTS or USE_ROBINHOOD_HASHMAP:

    1. Set up the source code and/or {Rcpp} to build multiple binaries using different flag settings. CRAN provides binaries but users can also install packages from source code, so this might be done at distribution or at installation.
    2. Ensure that this results in multiple compiled functions that can both be accessed through {Rcpp}. Expose these to R, but don't export them to the user.
    3. Add an argument to vietoris_rips() for each flag. Internally, but still on the R side, the value of that argument would determine which compiled function is called, using the same values of the remaining arguments.

    Does that sound right? I'm not sure how (1) and (2) would be done, but we can create a branch to experiment.

  7. corybrunson commented on Oct 8, 2025

    @corybrunson
    MemberAuthor

    @astamm might have missed the first ping—not sure you're getting notifications from this thread but would be grateful for your thoughts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is neededquestionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions