1#![allow(dead_code)]
158#![allow(clippy::type_complexity)]
159#[warn(clippy::all)]
160#[warn(missing_docs)]
161mod config;
162mod contour;
163mod core;
164mod integrable;
165mod output;
166mod solve;
167mod state;
168mod storage;
169
170pub use config::IntegratorConfig;
171pub use contour::{CircularArc, Contour, ContourSegment, IndentSide, LineSegment};
172pub use core::IntegratorError;
173pub use integrable::{ComplexScalar, FallibleIntegrable, Integrable, IntegrableFloat};
174pub use output::{ErrorNorm, IntegrationOutput};
175
176use integrable::Infallible;
177pub(crate) use state::IntegrationSummary;
178
179pub(crate) use contour::ContourPiece;
180use solve::Integrator;
181pub(crate) use state::IntegrationState;
182pub(crate) use storage::SegmentHeap;
183
184use nalgebra::ComplexField;
185use std::ops::Range;
186use trellis_runner::{
187 AbsoluteTolerancePolicy, EngineFailure, GenerateBuilderFallible, RelativeTolerancePolicy,
188 RunSummary, Termination,
189};
190
191pub struct IntegrationResult<I, O, F> {
192 pub integral: O,
193 pub error: F,
194 pub evaluations: usize,
195 pub refinements: usize,
196 pub termination: Termination,
197 pub summary: RunSummary<F>,
198 pub samples: Option<crate::core::QuadratureSamples<I, O>>,
199}
200
201impl<I, O, F> IntegrationResult<I, O, F> {
202 fn from_parts(
203 result: IntegrationSummary<I, O, F>,
204 summary: RunSummary<F>,
205 termination: Termination,
206 ) -> Self {
207 Self {
208 integral: result.integral,
209 error: result.error,
210 evaluations: result.evaluations,
211 refinements: result.refinements,
212 termination,
213 summary,
214 samples: result.samples,
215 }
216 }
217}
218
219pub fn integrate_complex<F, P>(
220 problem: P,
221 contour: Contour<F>,
222 config: IntegratorConfig<F>,
223) -> Result<
224 IntegrationResult<P::Input, P::Output, F>,
225 IntegratorError<P::Input, std::convert::Infallible>,
226>
227where
228 F: IntegrableFloat + ComplexScalar,
229 P: Integrable<Float = F, Input = <F as ComplexScalar>::Complex>,
230 <P as Integrable>::Output: IntegrationOutput<P::Input, Float = F>,
231{
232 let contour = config.deform_contour(contour);
233
234 let integrator = Integrator::complex_contour(contour, &config);
235
236 integrator
237 .build_for(Infallible(problem))
238 .with_initial_state(IntegrationState::new())
239 .and_policy(AbsoluteTolerancePolicy::new(
240 config.absolute_tolerance,
241 config.tolerance_window,
242 ))
243 .and_policy(RelativeTolerancePolicy::new(
244 config.relative_tolerance,
245 config.tolerance_window,
246 ))
247 .finalise()
248 .run()
249 .map(|output| {
250 IntegrationResult::from_parts(output.result, output.summary, output.termination)
251 })
252 .map_err(|EngineFailure::Procedure { error, state: _ }| error)
253}
254
255pub fn integrate_interval<F, P>(
256 problem: P,
257 interval: Range<F>,
258 config: IntegratorConfig<F>,
259) -> Result<IntegrationResult<F, P::Output, F>, IntegratorError<F, std::convert::Infallible>>
260where
261 F: IntegrableFloat + ComplexField<RealField = F>,
262 P: Integrable<Float = F, Input = F>,
263 <P as Integrable>::Output: IntegrationOutput<P::Input, Float = F>,
264{
265 integrate_real(problem, vec![interval.start, interval.end], config)
266}
267
268pub fn integrate_real<F, P>(
269 problem: P,
270 points: Vec<F>,
271 config: IntegratorConfig<F>,
272) -> Result<IntegrationResult<F, P::Output, F>, IntegratorError<F, std::convert::Infallible>>
273where
274 F: IntegrableFloat + ComplexField<RealField = F>,
275 P: Integrable<Float = F, Input = F>,
276 <P as Integrable>::Output: IntegrationOutput<P::Input, Float = F>,
277{
278 let integrator = Integrator::real_piecewise_linear(points, &config);
279
280 integrator
281 .build_for(Infallible(problem))
282 .with_initial_state(IntegrationState::new())
283 .and_policy(AbsoluteTolerancePolicy::new(
284 config.absolute_tolerance,
285 config.tolerance_window,
286 ))
287 .and_policy(RelativeTolerancePolicy::new(
288 config.relative_tolerance,
289 config.tolerance_window,
290 ))
291 .finalise()
292 .run()
293 .map(|output| {
294 IntegrationResult::from_parts(output.result, output.summary, output.termination)
295 })
296 .map_err(|EngineFailure::Procedure { error, state: _ }| error)
297}
298
299pub fn integrate_complex_fallible<F, P>(
300 problem: P,
301 contour: Contour<F>,
302 config: IntegratorConfig<F>,
303) -> Result<IntegrationResult<P::Input, P::Output, F>, IntegratorError<P::Input, P::Error>>
304where
305 F: IntegrableFloat + ComplexScalar,
306 P: FallibleIntegrable<Float = F, Input = <F as ComplexScalar>::Complex>,
307 <P as FallibleIntegrable>::Output: IntegrationOutput<P::Input, Float = F>,
308{
309 let contour = config.deform_contour(contour);
310
311 let integrator = Integrator::complex_contour(contour, &config);
312
313 integrator
314 .build_for(problem)
315 .with_initial_state(IntegrationState::new())
316 .and_policy(AbsoluteTolerancePolicy::new(
317 config.absolute_tolerance,
318 config.tolerance_window,
319 ))
320 .and_policy(RelativeTolerancePolicy::new(
321 config.relative_tolerance,
322 config.tolerance_window,
323 ))
324 .finalise()
325 .run()
326 .map(|output| {
327 IntegrationResult::from_parts(output.result, output.summary, output.termination)
328 })
329 .map_err(|EngineFailure::Procedure { error, state: _ }| error)
330}
331
332pub fn integrate_interval_fallible<F, P>(
333 problem: P,
334 interval: Range<F>,
335 config: IntegratorConfig<F>,
336) -> Result<IntegrationResult<F, P::Output, F>, IntegratorError<F, P::Error>>
337where
338 F: IntegrableFloat + ComplexField<RealField = F>,
339 P: FallibleIntegrable<Float = F, Input = F>,
340 <P as FallibleIntegrable>::Output: IntegrationOutput<P::Input, Float = F>,
341{
342 integrate_real_fallible(problem, vec![interval.start, interval.end], config)
343}
344
345pub fn integrate_real_fallible<F, P>(
346 problem: P,
347 points: Vec<F>,
348 config: IntegratorConfig<F>,
349) -> Result<IntegrationResult<F, P::Output, F>, IntegratorError<F, P::Error>>
350where
351 F: IntegrableFloat + ComplexField<RealField = F>,
352 P: FallibleIntegrable<Float = F, Input = F>,
353 <P as FallibleIntegrable>::Output: IntegrationOutput<P::Input, Float = F>,
354{
355 let integrator = Integrator::real_piecewise_linear(points, &config);
356
357 integrator
358 .build_for(problem)
359 .with_initial_state(IntegrationState::new())
360 .and_policy(AbsoluteTolerancePolicy::new(
361 config.absolute_tolerance,
362 config.tolerance_window,
363 ))
364 .and_policy(RelativeTolerancePolicy::new(
365 config.relative_tolerance,
366 config.tolerance_window,
367 ))
368 .finalise()
369 .run()
370 .map(|output| {
371 IntegrationResult::from_parts(output.result, output.summary, output.termination)
372 })
373 .map_err(|EngineFailure::Procedure { error, state: _ }| error)
374}