9595# re-sum (paranoia about accumulated roundoff)
9696function resum (f, segs)
9797 if f isa InplaceIntegrand
98- I = f. I .= segs[1 ]. I
98+ I = f. Ik .= segs[1 ]. I
9999 E = segs[1 ]. E
100100 for i in 2 : length (segs)
101101 I .+ = segs[i]. I
@@ -119,61 +119,77 @@ realone(x::Number) = one(x) isa Real
119119# and pass transformed data to workfunc(f, s, tfunc)
120120function handle_infinities (workfunc, f, s)
121121 s1, s2 = s[1 ], s[end ]
122+ u = float (real (oneunit (s1))) # the units of the segment
122123 if realone (s1) && realone (s2) # check for infinite or semi-infinite intervals
123124 inf1, inf2 = isinf (s1), isinf (s2)
124125 if inf1 || inf2
125126 if inf1 && inf2 # x = t/(1-t^2) coordinate transformation
126- return workfunc (u -> begin t = u/ oneunit (u); t2 = t* t; den = 1 / (1 - t2);
127- f (u* den) * (1 + t2)* den* den; end ,
128- map (x -> isinf (x) ? (signbit (x) ? - oneunit (x) : oneunit (x)) : 2 x / (one (x)+ hypot (one (x),2 x/ oneunit (x))), s),
129- t -> oneunit (s1) * t / (1 - t^ 2 ))
127+ I, E = workfunc (t -> begin t2 = t* t; den = 1 / (1 - t2);
128+ f (u* t* den) * (1 + t2)* den* den; end ,
129+ map (x -> isinf (x) ? (signbit (x) ? - one (x) : one (x)) : 2 x / (oneunit (x)+ hypot (oneunit (x),2 x)), s),
130+ t -> u * t / (1 - t^ 2 ))
131+ return u * I, u * E
130132 end
131133 let (s0,si) = inf1 ? (s2,s1) : (s1,s2) # let is needed for JuliaLang/julia#15276
132134 if si < zero (si) # x = s0 - t/(1-t)
133- return workfunc (u -> begin t = u/ oneunit (u); den = 1 / (1 - t);
134- f (s0 - u* den) * den* den; end ,
135- reverse (map (x -> oneunit (x) / (1 + oneunit (x) / (s0 - x)), s)),
136- t -> s0 - oneunit (s1)* t/ (1 - t))
135+ I, E = workfunc (t -> begin den = 1 / (1 - t);
136+ f (s0 - u* t* den) * den* den; end ,
137+ reverse (map (x -> 1 / (1 + oneunit (x) / (s0 - x)), s)),
138+ t -> s0 - u* t/ (1 - t))
139+ return u * I, u * E
137140 else # x = s0 + t/(1-t)
138- return workfunc (u -> begin t = u/ oneunit (u); den = 1 / (1 - t);
139- f (s0 + u* den) * den* den; end ,
140- map (x -> oneunit (x) / (1 + oneunit (x) / (x - s0)), s),
141- t -> s0 + oneunit (s1)* t/ (1 - t))
141+ I, E = workfunc (t -> begin den = 1 / (1 - t);
142+ f (s0 + u* t* den) * den* den; end ,
143+ map (x -> 1 / (1 + oneunit (x) / (x - s0)), s),
144+ t -> s0 + u* t/ (1 - t))
145+ return u * I, u * E
142146 end
143147 end
144148 end
145149 end
146- return workfunc (f, s, identity)
150+ I, E = workfunc (f, map (x -> x/ oneunit (x), s), identity)
151+ return u * I, u * E
147152end
148153
149154function handle_infinities (workfunc, f:: InplaceIntegrand , s)
150155 s1, s2 = s[1 ], s[end ]
156+ result = f. I
157+ u = float (real (oneunit (s1))) # the units of the segment
151158 if realone (s1) && realone (s2) # check for infinite or semi-infinite intervals
152159 inf1, inf2 = isinf (s1), isinf (s2)
153160 if inf1 || inf2
154- ftmp = f. fx # original integrand may have different type
155161 if inf1 && inf2 # x = t/(1-t^2) coordinate transformation
156- return workfunc (InplaceIntegrand ((v, u) -> begin t = u/ oneunit (u); t2 = t* t; den = 1 / (1 - t2);
157- f. f! (ftmp, u* den); v .= ftmp .* ((1 + t2)* den* den); end , f. I, f. fx * float (one (s1))),
158- map (x -> isinf (x) ? (signbit (x) ? - oneunit (x) : oneunit (x)) : 2 x / (one (x)+ hypot (one (x),2 x/ oneunit (x))), s),
159- t -> oneunit (s1) * t / (1 - t^ 2 ))
162+ I, E = workfunc (InplaceIntegrand ((v, t) -> begin t2 = t* t; den = 1 / (1 - t2);
163+ f. f! (v, u* t* den); v .*= ((1 + t2)* den* den); end , f. fg, f. fk, f. Ig, f. Ik, f. fx, f. Idiff, similar (f. fx)),
164+ map (x -> isinf (x) ? (signbit (x) ? - one (x) : one (x)) : 2 x / (oneunit (x)+ hypot (oneunit (x),2 x)), s),
165+ t -> u * t / (1 - t^ 2 ))
166+ result .= u .* I
167+ return result, u * E
160168 end
161169 let (s0,si) = inf1 ? (s2,s1) : (s1,s2) # let is needed for JuliaLang/julia#15276
162170 if si < zero (si) # x = s0 - t/(1-t)
163- return workfunc (InplaceIntegrand ((v, u) -> begin t = u/ oneunit (u); den = 1 / (1 - t);
164- f. f! (ftmp, s0 - u* den); v .= ftmp .* (den * den); end , f. I, f. fx * float (one (s1))),
165- reverse (map (x -> oneunit (x) / (1 + oneunit (x) / (s0 - x)), s)),
166- t -> s0 - oneunit (s1)* t/ (1 - t))
171+ I, E = workfunc (InplaceIntegrand ((v, t) -> begin den = 1 / (1 - t);
172+ f. f! (v, s0 - u* t* den); v .*= (den * den); end , f. fg, f. fk, f. Ig, f. Ik, f. fx, f. Idiff, similar (f. fx)),
173+ reverse (map (x -> 1 / (1 + oneunit (x) / (s0 - x)), s)),
174+ t -> s0 - u* t/ (1 - t))
175+ result .= u .* I
176+ return result, u * E
167177 else # x = s0 + t/(1-t)
168- return workfunc (InplaceIntegrand ((v, u) -> begin t = u/ oneunit (u); den = 1 / (1 - t);
169- f. f! (ftmp, s0 + u* den); v .= ftmp .* (den * den); end , f. I, f. fx * float (one (s1))),
170- map (x -> oneunit (x) / (1 + oneunit (x) / (x - s0)), s),
171- t -> s0 + oneunit (s1)* t/ (1 - t))
178+ I, E = workfunc (InplaceIntegrand ((v, t) -> begin den = 1 / (1 - t);
179+ f. f! (v, s0 + u* t* den); v .*= (den * den); end , f. fg, f. fk, f. Ig, f. Ik, f. fx, f. Idiff, similar (f. fx)),
180+ map (x -> 1 / (1 + oneunit (x) / (x - s0)), s),
181+ t -> s0 + u* t/ (1 - t))
182+ result .= u .* I
183+ return result, u * E
172184 end
173185 end
174186 end
175187 end
176- return workfunc (f, s, identity)
188+ I, E = workfunc (InplaceIntegrand (f. f!, f. fg, f. fk, f. Ig, f. Ik, f. fx, f. Idiff, similar (f. fx)),
189+ map (x -> x/ oneunit (x), s),
190+ identity)
191+ result .= u .* I
192+ return result, u * E
177193end
178194
179195function check_endpoint_roundoff (a, b, x; throw_error:: Bool = false )
@@ -253,8 +269,9 @@ quadgk(f, segs...; kws...) =
253269
254270function quadgk (f, segs:: T... ;
255271 atol= nothing , rtol= nothing , maxevals= 10 ^ 7 , order= 7 , norm= norm, segbuf= nothing ) where {T}
272+ utol = isnothing (atol) ? atol : atol/ float (real (oneunit (T))) # remove units of domain
256273 handle_infinities (f, segs) do f, s, _
257- do_quadgk (f, s, order, atol , rtol, maxevals, norm, segbuf)
274+ do_quadgk (f, s, order, utol , rtol, maxevals, norm, segbuf)
258275 end
259276end
260277
0 commit comments