JuliaMath / QuadGK.jl

adaptive 1d numerical Gauss–Kronrod integration in Julia
MIT License
268 stars 37 forks source link

Handle units consistently in handle_infinites #96

Open lxvm opened 9 months ago

lxvm commented 9 months ago

Fixes #95 This pr changes handle_infinities to always pass limits with units to do_quadgk so that the same segbuf can be used with finite and infinite limits. It also adds some tests to check this works for inplace and batched integrands.

Unfortunately, the endpoints of the segments in a segbuf don't correspond to the intervals used in the original domain when using the infinity transformation. However, changing that would be a lot more involved than what is needed for this pr.

codecov[bot] commented 9 months ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Comparison is base (135432c) 98.21% compared to head (f328bd7) 98.27%.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## master #96 +/- ## ========================================== + Coverage 98.21% 98.27% +0.06% ========================================== Files 6 6 Lines 615 637 +22 ========================================== + Hits 604 626 +22 Misses 11 11 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

lxvm commented 8 months ago

@stevengj this pr is now updated to pass unitless limits to do_quadgk and the new tests are more careful about verifying this behavior. Here are also timings on Julia 1.10 that show a median slowdown under 2.5% in general:

branch integrand median time
pr x 35.839 ns
master x 35.007 ns
pr sin(100x) 11.965 μs
master sin(100x) 11.762 μs
benchmark for this pr ```julia julia> using BenchmarkTools julia> using QuadGK julia> @benchmark quadgk(x -> x, 0, 1) # zero-cost integrand, no subdivisions BenchmarkTools.Trial: 10000 samples with 993 evaluations. Range (min … max): 35.383 ns … 107.806 ns ┊ GC (min … max): 0.00% … 0.00% Time (median): 35.839 ns ┊ GC (median): 0.00% Time (mean ± σ): 36.505 ns ± 4.703 ns ┊ GC (mean ± σ): 0.00% ± 0.00% █▄ ██▃▃▂▂▂▂▂▂▁▂▂▂▁▂▁▂▁▁▁▁▁▁▂▁▁▂▁▁▂▂▁▁▂▂▂▂▁▁▂▂▂▂▂▂▂▂▂▂▂▁▂▂▂▁▁▁▂▂ ▂ 35.4 ns Histogram: frequency by time 63.2 ns < Memory estimate: 0 bytes, allocs estimate: 0. julia> @benchmark quadgk(x -> sin(100x), 0, 1) # low-cost integrand with subdivisions BenchmarkTools.Trial: 10000 samples with 1 evaluation. Range (min … max): 11.611 μs … 55.500 μs ┊ GC (min … max): 0.00% … 0.00% Time (median): 11.965 μs ┊ GC (median): 0.00% Time (mean ± σ): 12.100 μs ± 1.526 μs ┊ GC (mean ± σ): 0.00% ± 0.00% ▃█▇█▅▄▂▁ ▂▂▂▂▂▂▂▁▂▁▁▂▁▁▁▂▁▂▂▃▅█████████▇▆▆▅▄▄▃▃▃▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ ▃ 11.6 μs Histogram: frequency by time 12.4 μs < Memory estimate: 1.69 KiB, allocs estimate: 3. ```
benchmark on master ```julia julia> using BenchmarkTools julia> using QuadGK julia> @benchmark quadgk(x -> x, 0, 1) # zero-cost integrand, no subdivisions BenchmarkTools.Trial: 10000 samples with 992 evaluations. Range (min … max): 33.998 ns … 402.374 ns ┊ GC (min … max): 0.00% … 0.00% Time (median): 35.007 ns ┊ GC (median): 0.00% Time (mean ± σ): 36.006 ns ± 7.741 ns ┊ GC (mean ± σ): 0.00% ± 0.00% ▃█ ██▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▁ 34 ns Histogram: frequency by time 70.1 ns < Memory estimate: 0 bytes, allocs estimate: 0. julia> @benchmark quadgk(x -> sin(100x), 0, 1) # low-cost integrand with subdivisions BenchmarkTools.Trial: 10000 samples with 1 evaluation. Range (min … max): 11.362 μs … 57.351 μs ┊ GC (min … max): 0.00% … 0.00% Time (median): 11.762 μs ┊ GC (median): 0.00% Time (mean ± σ): 12.303 μs ± 1.512 μs ┊ GC (mean ± σ): 0.00% ± 0.00% █▄ ▇▅▂██▃▂▂▂▂▁▁▁▂▃▄▃▃▇▆▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▂▁▂▁▂▂▂▂▂▂▂▂▁▂▂▁▁▂▁▁▁▂ ▃ 11.4 μs Histogram: frequency by time 17 μs < Memory estimate: 1.69 KiB, allocs estimate: 3. ```

I think this is ready and could be a patch release