When designing the public API of a generic library, how much of the low-level stuff that's used internally should be exposed? On the one hand, users should not depend too heavily on implementation details, and too many low-level functions/classes might clutter the API. Therefore, the knee-jerk response might be "none". On the other hand, some of the low-level functionality might be useful to people, and exposing more of it can prevent abstraction inversion (the re-implementing of low-level constructs on top of high-level constructs).
Furthermore, exposing more low-level details could provide performance shortcuts. For example, let's say you have a function to find the median of an array. The principle of least surprise says that you should duplicate the array so that users of your API don't have to care that its implementation involves the side effect of reordering elements. Should you, in this case, note that median() costs a memory allocation and provide another function that bypasses the allocation, but will arbitrarily reorder the user's input?
What are some general guidelines for how much of this kind of detail to expose?