cgubbin / quad-rs

Adaptive Gauss-Kronrod Integration in Rust
MIT License
1 stars 1 forks source link

Not possible to set max. number of iterations manually #1

Closed StefanMathis closed 2 years ago

StefanMathis commented 2 years ago

Hello,

I stumbled upon the following problem with quad-rs version 0.1.1:

fn integrand(x: f64) -> f64 {
    x.exp()
}

fn main() {
    let integrator = GaussKronrod::default();
    let range = -1f64..1f64;
    let integrator = integrator.with_maximum_iterations(200); // <== Compiler complains "type annotations needed - cannot satisfy `_: ComplexField`

    let result = integrator
                .integrate(&integrand, range, None)
            .unwrap();
}

Am I doing something wrong? I didn't find any tests where the method with_maximum_iterations is actually used, therefore I can't tell ...

Thanks a lot for your help!

cgubbin commented 2 years ago

Hey, thank you for finding this. It's an irritating error actually, I think it's because the set methods only depend on the RealField, while the integrate methods depend on the ComplexField. In this version both groups of methods are bundled into the same trait, so when you call the set method the compiler gets upset because it can only work out some of the trait boundaries it needs. I think anyway, I would have assumed the compiler would be able to work it out when you call integrate later. Maybe I am missing something.

Anyway, I have fixed this in #2 by splitting the methods, keeping an Integrate trait to run the integrals, and creating a new IntegrationSettings trait which sets the maximum iterations and tolerances. As this has bloated the API a little bit I moved these and the integrator into a prelude. You should be able to run your example if you utilise the latest version (0.1.2) as

use quad_rs::prelude::*;

fn integrand(x: f64) -> f64 {
    x.exp()
}

fn main() {
    let mut integrator = GaussKronrod::default()
         .with_maximum_function_evaluations(200);  // <== Compiler is hopefully happy
    let range = -1f64..1f64;

    let result = integrator.integrate(&integrand, range, None).unwrap();
}

Note that in the new version the set function is now called with_maximum_function_evaluations rather than with_maximum_iterations, as this is really what the method is constraining.

Does this work now?