-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement powi
without using MPFR
#106
Comments
P.S. One may also have a feature flag |
That sounds promising! How about introducing a module that serves non-standard or non-tightest operations, including the fast As for double-double arithmetic, https://github.com/mskashi/kv could be worth looking into, although it is written in C++. |
Unfortunately, with such a scheme, one needs to rewrite the code to change the implementation (one may imagine using the precise functions first and wanting to switch to faster but less precise ones if the code is too slow for the problem. Another possibility would be to implement these functions as various traits, the one in scope saying which version is used. This has the drawback that a prelude is desirable: if Alternatively, none of the transcendental functions are methods and one needs to |
@Chris00 Could you share some code snippets that illustrate your design ideas? |
Here is an example. In the inari library, on would define pub trait TranscendentalMPFR {
fn cos(self) -> Self;
}
pub trait TranscendentalFast {
fn cos(self) -> Self;
} and implement these traits for In the "client" code, one can write use inari::TranscendentalMPFR; or use inari::TranscendentalFast; to have access to the appropriate use inari::{Interval as I, TranscendentalMPFR};
mod Fast {
use super::I;
use inari::TranscendentalFast;
fn f(x: I) -> I {
x.cos()
}
} |
Thank you for the clarification. What if you have two or more implementations of the cosine function that vary in terms of speed and tightness trade-offs? How do we arrange such functions in traits? |
Each implementation must be in its own trait. To minimize the number of traits, these should group functions with similar characteristics. This is not much different than what you would do with modules — it's the calling (method v.s. function) that differs. |
Another possibility may be to use a phantom type to mark the kind of operations supported by the intervals. Here is some proof of concept code: struct Itv<F> {
// ...
marker: PhantomData<F>,
}
enum A {}
enum B {}
impl Itv<A> {
fn cos(self) -> Self { todo!() }
}
impl Itv<B> {
fn cos(self) -> Self { todo!() }
} In order to switch to a different implementation a zero cost conversion function |
I've implemented
powi
without the use of MPFR, using repeated squaring (distinguishing cases according to the sign of the interval bounds). It is 4.5–5 times faster than the MPFR version — something that may matter whenpowi
is a building block of code that will be run millions of times. However, the returned intervals are a few ulp larger so the tests no longer pass. One example is tests/itf1788_tests/libieeep1788_elem.rs:3567:5:where I get (with the new
Debug
printing):How important is it for the intervals to be tight? If it is, one may locally use double-doudle arithmetic to get the rounding correct. There is the qd crate that can serve as an inspiration. I think however it is better to implement the operations (we need very few of them) ourselves to
__m256d
to process two double-double simultaneously.Before doing the work, I'd like to have your opinion about this endeavor.
The text was updated successfully, but these errors were encountered: