(PC-12xx~14xx) qthsh Tanh-Sinh quadrature
|
04-08-2021, 06:17 PM
Post: #41
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-08-2021 04:27 PM)Albert Chan Wrote:(04-08-2021 01:32 PM)robve Wrote: Using exp(t) in the inner loop instead of the strength-reduced expt recurrence should be the most accurate. Try it. That's really nice. I was stating this more in "theory" that it would be most accurate, but practically makes no difference, which is really nice. On the SHARP Pocket Computers it makes a difference only because variables hold 10 digits whereas expressions are evaluated with 12 digit precision. So using EXP is a tiny bit better than repeated multiplication with a variable, e.g. we get the integral 2.0 exactly instead of 1.999999998. (04-08-2021 04:27 PM)Albert Chan Wrote: Same conclusion when I compared strength-reduced exp vs supposed more accurate expm1. I didn't think about it that way. That is a nice way to confirm. I would also like to confirm that removing if (r == 0 || r == 1) break; makes no difference with all integrals tested. Logically the loop terminates before these conditions are met. This check is redundant and can be removed as you observed correctly. One thing I am still curious about is reusing or setting fp and fm to zero. I will look into the decaying factor idea. Perhaps there is also a difference between Inf and NaN, because with Inf the limit is clearly not finite and with NaN we don't necessarily know, but reusing in that case makes sense, I think. But I may be wrong if it makes no difference. I just don't know yet. - Rob "I count on old friends to remain rational" |
|||
04-08-2021, 06:59 PM
Post: #42
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
Just to show expt make no difference, this version eliminated t = exp(h), replaced by cheaper sqrt().
Code: function qthsh3(f, a, b, c, n, eps) -- tanh-sinh quadrature lua> f = function(x) return 1/sqrt(-log(x)) end lua> qthsh (f, 0, 1) -- exp version 1.7724538240988943 6.586211614189097e-009 lua> qthsh2(f, 0, 1) -- expm1 version 1.7724538240988927 6.58621067462469e-009 lua> qthsh3(f, 0, 1) -- sqrt version 1.7724538240988927 6.586210486711807e-009 |
|||
04-08-2021, 10:43 PM
Post: #43
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-08-2021 06:17 PM)robve Wrote: Perhaps there is also a difference between Inf and NaN, because with Unless formula is very simple, there is not enough information to claim returning inf implied infinite true result. Cas> f(u) := atanh(u*u*(3-2*u)) * 6*u*(1-u) Cas> u = 1 - 10^-9 Cas> f(float(u)) → ∞ Cas> float(f(u)) → 1.23123199576e-07 |
|||
04-09-2021, 02:54 AM
Post: #44
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-08-2021 10:43 PM)Albert Chan Wrote:(04-08-2021 06:17 PM)robve Wrote: Perhaps there is also a difference between Inf and NaN, because with The function is a black box and we cannot trust ill-conditioned functions. With NaN and Inf we don't know what the cause is. Tracing the points toward an endpoint may be suggestive of the "missing" values by extrapolation (reusing the previous point). However, a small change in the bounds can make a huge difference in the result and cause Inf or NaN. For example, 1/(1+cos(x)^x) integrated on [-pi/2,pi/2] is OK but produces NaN with the inexact bounds [-1.570796327,1.570796327] see the spreadsheet row 64. Earlier I mentioned that fp and fm reuse appears to be better than zero for this function and for two other functions. But there is more noise than signal to use these examples as sufficient evidence to make a determination. I can't tell yet if a decay approach can help to control singularities at an endpoint. It may be moot attempt. If so, there is not much left that remains to do for further improvements of Tanh-Sinh. - Rob "I count on old friends to remain rational" |
|||
04-10-2021, 12:05 AM
Post: #45
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-08-2021 01:58 PM)Albert Chan Wrote:(04-08-2021 11:20 AM)emece67 Wrote: integrals (1 - sqrt(2)*cosh(x)/sqrt(cosh(2*x)), from -inf to +inf) needed one more level. Amazingly, qthsh (I picked sqrt version, for speed), does not get garbage from this. lua> f = function(x) n=n+1; return 1-sqrt(2)*cosh(x)/sqrt(cosh(2*x)) end lua> f01 = function(t) local y=t*t-t; return f((2*t-1)/y) * (2*y+1)/(y*y) end With default setting of n=6, eps=1e-9, we have: lua> Q = require 'quad' lua> n=0; print(Q.qthsh(f01, 0, 1, 1), n) -- Previous Point -0.6931471805996943 80 lua> n=0; print(Q.qthsh(f01, 0, 1, 0), n) -- Default Zero -0.6931471805582439 77 Showing running integral sum, for each level k (c=0, n=5, eps=0) lua> n=0; Q.qthsh(f01, 0, 1, 0, 5, 0) 0 -1.6568543106755638 1 -0.8783982505319032 2 -0.7037071116271125 3 -0.693194301031653 4 -0.6931471818102728 5 -0.6931471805599556 lua> n, -log(2) 99 -0.6931471805599453 |
|||
04-10-2021, 01:45 PM
(This post was last modified: 04-10-2021 02:25 PM by Albert Chan.)
Post: #46
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-08-2021 11:20 AM)emece67 Wrote: integrals (1 - sqrt(2)*cosh(x)/sqrt(cosh(2*x)), from -inf to +inf) needed one more level. The reason is not the alogrithm, but how mpmath numbers work. Because mpmath does not do overflow / underflow, the integrand may generate noise. (with IEEE double, generated Inf/NaN will allow the algorithm to fix it ...) With limits of ±∞, even slight noise will make it hard to converge. (*) >>> from mpmath import * >>> f = lambda x: 1 - sqrt(2)*cosh(x)/sqrt(cosh(2*x)) >>> for x in range(15,20): print x, f(x) ... 15 -9.37028232783632e-14 16 -1.26565424807268e-14 17 -1.99840144432528e-15 18 -2.22044604925031e-16 19 -2.22044604925031e-16 We can explicitly remove the noise, then integrate. >>> from double_exponential import * >>> f2 = lambda x: 0.0 if abs(x) > 19 else f(x) >>> double_exponential(f2, -inf, inf) (mpf('-0.69314718055994773'), mpf('3.8011316316755028e-10'), 61, 4, 2) This is almost as good as the "sharpened" version of f: >>> def f3(x): y=1/cosh(2*x); return -y/(1 + sqrt(1+y)) ... >>> double_exponential(f3, -inf, inf) (mpf('-0.69314718055994584'), mpf('3.8011260805603797e-10'), 69, 4, 2) (*) Tracing the function calls, errors started at point #10: old version: f(6704.2155162232693) → mpf('0.0') new version: f(6704.215516223293) → mpf('-2.2204460492503131e-16') The old version just get lucky ... >>> f3(6704.2155162232693) mpf('-6.1999991241406458e-5824') |
|||
04-10-2021, 04:13 PM
Post: #47
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-10-2021 12:05 AM)Albert Chan Wrote:(04-08-2021 01:58 PM)Albert Chan Wrote: I believe there is nothing to worry about. Amazing. Confirmed with the C version, reusing previous point: qthsh a NAN!!! qthsh b NAN!!! qthsh a NAN!!! qthsh b NAN!!! qthsh a NAN!!! k=5 err=1.86609e-09 pts=80 qthsh = -0.693147180599693 wp34s a NAN!!! wp34s b NAN!!! wp34s a NAN!!! wp34s b NAN!!! wp34s a NAN!!! wp34s b NAN!!! wp34s a NAN!!! wp34s b NAN!!! wp34s a NAN!!! wp34s b NAN!!! wp34s a NAN!!! wp34s b NAN!!! k=6 err=5.67726e-07 pts=139 wp34s = -0.693147748281705 Using zero as default when NaN occurs: qthsh a NAN!!! qthsh b NAN!!! k=5 err=1.80629e-09 pts=77 qthsh = -0.693147180558242 wp34s a NAN!!! wp34s b NAN!!! wp34s a NAN!!! wp34s b NAN!!! wp34s a NAN!!! wp34s b NAN!!! k=6 err=4.70357e-12 pts=133 wp34s = -0.693147180559957 Zero as default improves the result. Note that for the wp34s I had to set eps=1e-15 to prevent early termination. With qthsh with eps=1e-12: qthsh a NAN!!! qthsh b NAN!!! k=6 err=1.10518e-14 pts=155 qthsh = -0.693147180559942 - Rob "I count on old friends to remain rational" |
|||
04-11-2021, 03:05 AM
(This post was last modified: 04-11-2021 01:07 PM by robve.)
Post: #48
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
Here is my latest contribution with integrated Tanh-Sinh, Exp-Sinh, Sinh-Sinh rules. The Tanh-Sinh rule has the same Michalski & Mosig abscissas and weights, but reformulated to combine the three quadratures into one routine (see the updated doc for the formulas):
Code: // Tanh-Sinh bounded [a,b], Exp-Sinh (one inf either side), Sinh-Sinh [-inf,inf] This was highly optimized while keeping the code compact. Optimizations include strength reductions, branch eliminations, and variable reuse when possible to reduce CPU register pressure. The partially optimized code for the inner loop is perhaps a bit easier to comprehend: Code: t = eh = exp(h); I have verified the optimized routine with several examples, but more testing will be necessary to determine its numerical properties. - Rob Edit: minor change to fix mirrored bound checks. "I count on old friends to remain rational" |
|||
04-12-2021, 12:20 PM
(This post was last modified: 04-12-2021 01:08 PM by Albert Chan.)
Post: #49
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
I thought this might be interesting to others, so I am responding PM as a post
robve Wrote:I now see what the difference is between qthsh and quad, it's quite simple: qthsh uses f(a+x) while quad uses f(c-x). When a=0, the check a+x>a always succeeds for nonzero positive x, but c-x>a fails due to cancellation with c=(a+b)/2. Yes, it is more accurate interpolate from the closest edge. https://www.hpmuseum.org/forum/thread-16...#pid140084 Even if interpolate closed to center ! (c=(a+b)/2 might have rounding errors; a, b are user inputs, thus can considered exact) That's why qthsh lua implementation removed a ≤ b limitation. And, accuracy affect both edges, not just the "zero" side. Example, (code snippet from previous post) Code: else { // Exp-Sinh Note that x is interpolated from the finite edge (c), so is very accurate. With r = exp(sinh(j*h)) > 1, this x is approaching the finite edge, so it is better to test x ≠ c. If x=c, we throwaway the point. It does not meant we assume f(c)=0. Instead, we are assuming f(c) * weight = 0, since weight at the edge is miniscule. This is what "default 0.0" meant. (04-10-2021 01:45 PM)Albert Chan Wrote: With limits of ±∞, even slight noise will make it hard to converge. (*) To reduce noise, we should quit summing, if we actually hit the finite edge. So this is the proposed patch: Code: else { // Exp-Sinh |
|||
04-12-2021, 01:50 PM
Post: #50
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-12-2021 12:20 PM)Albert Chan Wrote: And, accuracy affect both edges, not just the "zero" side. An example, with both edge goes to +∞ >>> Q = require 'quad' >>> f = function(x) return 1/sqrt(1-x*x) end lua> Q.qthsh(Q.count(f), -1, 1), Q.n 3.141592644894014 59 lua> Q.quad(Q.count(f), -1, 1), Q.n 3.1415926047697873 115 This is not due to default 0.0 vs previous point. The function has sharp edges. With x in (-1,1), f(x) never returned inf. With IEEE double, this is the highest it goes: lua> f(1 - 0x1p-53) 67108864 There is no zero edge here, and midpoint of (-1,1) is exactly 0. Interpolate from the edges, qthsh use more accurate points. |
|||
04-12-2021, 03:06 PM
Post: #51
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-12-2021 12:20 PM)Albert Chan Wrote:robve Wrote:I now see what the difference is between qthsh and quad, it's quite simple: qthsh uses f(a+x) while quad uses f(c-x). When a=0, the check a+x>a always succeeds for nonzero positive x, but c-x>a fails due to cancellation with c=(a+b)/2. Let me add to my PM some context: a notable difference are the function evaluation guards at both endpoints in the different implementations which are a+d*r>a in qthsh versus c-d*r and b-d*r<b in qthsh versus c+d*r<b. If the finite endpoints a or b are zero or close to zero, then the corresponding endpoint may be more closely approached by qthsh with additional abscissas. This is important. More accurate results can be achieved with qthsh when the integrand has a significant area close to \( x=0 \), for example \( \int_0^1 1/\sqrt{x}\, dx \) gives: qthsh points=63 relative error=1e-13 quad (old version using x=c+d*r similar to WP-34S) points=115 relative errror=6e-9 Likewise, WP-34S "pure" Tanh-Sinh (C version with IEEE 754) with eps=1e-15 has a high relative error of 5e-7 after 25 points "convergence" at k=2. With eps=1e-20 WP-34S has a 2e-10 relative error after 217 points and k=5 convergence. qthsh converged quickly at level k=3 whereas quad using x=c+d*r converged at level k=4 with a larger error, requiring one more level in an attempt to produce a result within eps=1e-9. This is illustrated by the following chart (click to enlarge): This shows the point distributions of qthsh and quad for this integrand, using a log scale to emphasize the points approaching the zero endpoint a=0. (04-12-2021 12:20 PM)Albert Chan Wrote: Even if interpolate closed to center ! Yes, c can cause rounding errors and loss of precision in a+b. Whenever we add or subtract there can be a (significant) loss. In the end, IEEE 754 double precision does not help. When c is used we should also compare to c (at least in this case). To do so in the code, the Exp-Sinh and Sinh-Sinh quadratures should be split from the Tanh-Sinh computation, which I've already done in yesterday's updated document (that will continue to evolve.) (04-12-2021 12:20 PM)Albert Chan Wrote: To reduce noise, we should quit summing, if we actually hit the finite edge. Good point! It makes a lot more sense to stop Exp-Sinh at this point when x hits c for x=c+d/r and avoid using a like qthsh. The weight gets very small when approaching the finite endpoint. BTW. one trick to get a and b numerically corrected to prevent noise with c: c=(a+b)/2 d=(b-a)/2 a=c-d b=c+d This helps, but it is "iffy" to use for this algorithm, because it (slightly) changes the endpoints! In other contexts these tricks can be important, for example in numerical differentiation e.g. h=1e-3, x=a-h then h is NOT the difference between a and x exactly, but the adjusted h=a-x is. Note that the Exp-Sinh and Sinh-Sinh quadratures described in the document use a Michalski & Mosig simplification to drop \( \pi/2 \). These rules are transformations by substitution anyway. Having a few more points in the area between the endpoints looks advantageous, judging from the 818 integrals tested in the spreadsheet compared to a "pure" Tanh-Sinh rule. Other parameterizations are possible to control the point distributions, e.g. Michalski & Mosig in their paper start with h=1.5 instead of 1. An update of the document and code is forthcoming. - Rob "I count on old friends to remain rational" |
|||
04-12-2021, 03:58 PM
Post: #52
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-12-2021 12:20 PM)Albert Chan Wrote: To reduce noise, we should quit summing, if we actually hit the finite edge. And remove the guard x<b for Exp-Sinh and Sinh-Sinh: Code: x = c + d*r; "I count on old friends to remain rational" |
|||
04-13-2021, 05:19 PM
(This post was last modified: 04-15-2021 05:44 PM by robve.)
Post: #53
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
I ran 1084 test integrals on the current quad implementation: 818 definite integrals, 208 one-sided inf integrals, and 58 -inf-inf integrals (latest zip file with the results). This shows that:
- reusing previous points is better than zero default function values (58 versus 5) when hitting the endpoints - default zero function values for inf/nan singularities is better (8 versus 4) EDIT adding these additional related observations here instead of in a new post: - A decay factor of .5 or .8 (i.e. fp *= .8 and fm *= .8 when a singularity occurs) produce 8 better and 4 worse qthsh results of the 818 integrals tested. This is the same as using zero by default, which affect the same 8 and 4 integrals. This might just be noise. - With an initial h=1.5 in qthsh's first iteration instead of 1, 399 integrals are worse, 391 better with respect to the absolute error with the exact integral value. - With an initial h=0.5 in qthsh's first iteration, 45 are worse, 55 are better with respect to the absolute error with the exact integral value. However, the average number of points to converge went up from 105 to 125. - Using the pi/2 factor to reintroduce the "pure" Tanh-Sinh rule in qthshs more often produced less accurate results (417) than better results (363) like the WP-34S implementation, taking the same number of points to converge. The qthsh and quad implementations and the doc will be updated accordingly. A few more tests are in the pipeline. Almost finished - Rob "I count on old friends to remain rational" |
|||
04-14-2021, 03:17 PM
Post: #54
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
Lua implementation of quad(), using qthsh code to handle finite intervals.
Note: Q.quad is just a shorthand for Q["quad"], a function stored in table Q Code: function Q.quad(f, a, b, d, n, eps) --- I noticed exp-sinh is actually doing 2 integrals, simultaneously. \(\int_a^∞ = \int_a^{a+d} + \int_{a+d}^∞ \) Both integrals are using same number of points, but the last one is much harder. If possible, we should pick d so that first one do most of the work. This version allowed to input d, instead of hard-coded d=1. If we have a clue about the shape of curve, it helps. Example, Standard Normal Distribution. lua> Q = require 'quad' lua> k = 1/sqrt(2*pi) lua> Inf = math.huge lua> pdf = function(x) return k*exp(-x*x/2) end lua> Q.quad(Q.count(pdf), 1, Inf), Q.n 0.15865525392847651 129 lua> Q.quad(Q.count(pdf), 1, Inf, 4), Q.n 0.15865525393145705 69 Above is now as efficient as integrating closed interval of [0, 1] lua> 1/2 - Q.quad(Q.count(pdf), 0, 1), Q.n 0.15865525393145719 58 Same idea for \(\int_{-∞}^∞\), we wanted \(\int_{-d}^d\) to do the most work. lua> Q.quad(Q.count(pdf), -Inf, Inf), Q.n 0.999999999999999 119 lua> Q.quad(Q.count(pdf), -Inf, Inf, 4), Q.n 0.9999999999999996 43 Had we optimized specifically for even functions, above only need (n+1)/2 points ! |
|||
04-15-2021, 05:14 PM
Post: #55
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-12-2021 03:06 PM)robve Wrote:(04-12-2021 12:20 PM)Albert Chan Wrote: To reduce noise, we should quit summing, if we actually hit the finite edge. More importantly, infinite "edge" has weight that gets very very big. For exp-sinh, with limits of [c, d*inf], q before scaled up by cosh(j*h): q = f(c + d/r)/r + f(c + d*r)*r When r is huge, second term might generate magnified noise, messing up the sum. Example, ∫(x^-0.99, x=0..1) \(\displaystyle \int_0^1 x^{-0.99}\, dx = \int_0^∞ (e^{-y})^{-0.99} (e^{-y}\, dy) = \int_0^∞ e^{-0.01y} \, dy \) If we apply transformation without last simplifed step, integrand generate much noise. >>> Q = require 'quad' >>> f = function(x) return x^-0.99 end >>> f1 = function(y) y=exp(-y); return f(y)*y end lua> Q.quad(Q.count(f), 0, 1), Q.n 99.92043566319589 654 lua> Q.quad(Q.count(f1), 0, huge), Q.n 99.93721615545337 459 Now, try simplified form, avoiding the noise lua> f2 = function(y) return exp(-0.01*y) end lua> Q.quad(Q.count(f2), 0, huge), Q.n 99.9999999878134 237 Nice, but we can do better ! (see previous post) exp(0) = 1 exp(-0.01y) = 0.001 → -y/100 = ln(10^-3) = -3*ln(10) ≈ -3*2.3 ≈ -7 \(\int_0^∞ = \int_0^{700} + \int_{700}^∞ :\) lua> Q.quad(Q.count(f2), 0, huge, 700), Q.n 100 71 |
|||
04-15-2021, 07:02 PM
Post: #56
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-15-2021 05:14 PM)Albert Chan Wrote: Nice, but we can do better ! (see previous post) Picking a smart "central point" 'd' in Exp-Sinh (the splitting point between the two quadratures) is advantageous. A higher accuracy can also be accomplished by manually splitting up the integral into two parts by picking the splitting point smartly: \(\int_0^∞ = \int_0^{700} + \int_{700}^{701} + \int_{701}^∞ \) In this case we can also get a more accurate result, while keeping the default Exp-Sinh "central point" 700+1 (the default is d=1 versus d=700 in your example): \( \int_0^{700} e^{-0.01y}\,dy \): k=3 err=4.82092e-11 pts=58 quad = 99.9088118034444 \( \int_{700}^\infty e^{-0.01y}\,dy \): k=5 err=8.41427e-09 pts=235 quad = 0.0911881965443389 Combined \( \int_0^\infty e^{-0.01y}\,dy \) = 99.9088118034444 + 0.0911881965443389 = 99.999999999988739 Thus we get three more digits (12 digits) compared to Exp-Sinh with the default d=1 splitting point: \( \int_0^\infty e^{-0.01y}\,dy \): k=5 err=8.41426e-09 pts=237 quad = 99.9999999878134 On the other hand, the splitting point d=700 gives the exact result as you point out, which is very nice indeed: k=3 err=9.08301e-12 pts=71 quad = 100 The absolute error estimates (100*9e-12 ~ 9e-10) is in the same order (100*5e-11+0.09*8e-9 ~ 5e-9). So using this as a "black box" we won't be able to tell the difference, unless we can get the relative error further down, which seems really cheap to do as we only needed 71 points to get about 11 digits. It makes sense to specify 'd' as an optional parameter or at least say something about it in the document. Overall, these methods are interesting. But as always one needs to be smart about the type of integrand and consider splitting up integrals into parts. The 1084 integral tests to check these methods do none of that, obviously. - Rob "I count on old friends to remain rational" |
|||
04-15-2021, 09:29 PM
Post: #57
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
I should add that the choice of d=1 for Exp-Sinh and c=0 for Sinh-Sinh bothered me as well, because the Exp-Sinh and Sinh-Sinh integrals are split in two parts. I have not yet looked into articles for suggestions for these values, although for Sinh-Sinh I would expect that the best c is where f has (some) symmetry e.g. f(c+x) = f(c-x).
In the meantime, I've mostly worked on testing different parameterizations e.g. h=.5 and h=1.5 initially and compared the "pure" Tanh-Sinh with the pi/2 factors etc. (04-15-2021 05:14 PM)Albert Chan Wrote: Nice, but we can do better ! (see previous post) The derivation to select d=700 for the integrand exp(-0.01*y) is clear, except for the initial requirement that is not obvious from the integrand and interval: exp(-0.01y) = 0.001 In this case I can empirically verify this by a rough gradient search for the value of d that produce the lowest errors, but is there a general algebraic formulation using the inverse function to determine where d might be optimal? Any literature on that? - Rob "I count on old friends to remain rational" |
|||
04-15-2021, 10:38 PM
(This post was last modified: 04-16-2021 01:15 PM by Albert Chan.)
Post: #58
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-15-2021 09:29 PM)robve Wrote: The derivation to select d=700 for the integrand exp(-0.01*y) is clear, except for the My aim is to pick d such that \(\int_0^d\) covered bulk of the area, less work for \(\int_d^∞\) Based on experience with plots, if value is below 1/1000 of peak, it seems to touch the x-axis. Actual number is not that critical. Hitting exact 100 is just lucky. lua> Q = require 'quad' lua> f2 = function(x) return exp(-0.01*x) end lua> for d=500,1500,100 do print(d, Q.quad(Q.count(f2), 0, huge, d), Q.n) end 500 99.99999999999997 71 600 100 71 700 100 71 800 99.99999999999997 71 900 99.99999999999999 71 1000 99.99999999999997 71 1100 99.99999999999997 71 1200 99.99999999999997 71 1300 99.99999999999999 71 1400 99.99999999999996 71 1500 99.99999999999997 71 Note that we could accomplish the same by compressing the function, by factor d lua> x, d = 20, 512 lua> f2(x) * 100 -- exact result, for \(\int_x^∞\) 81.87307530779819 lua> f3 = function(d) return function(x) return f2(x*d)*d end end lua> Q.quad(Q.count(f3(d)), x/d, huge/d), Q.n 81.87307530779817 69 lua> Q.quad(Q.count(f2), x, huge, d), Q.n 81.87307530779817 69 Both expressions are equivalent (because I picked d = power-of-2) But setting d is cost free, and less messy. |
|||
04-17-2021, 12:03 AM
Post: #59
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
(04-15-2021 07:02 PM)robve Wrote: \( \int_0^{700} e^{-0.01y}\,dy \): We can build exp-sinh transformed integrand, and see the curve, in XCas. XCas> f(x) := exp(-0.01*x) XCas> y := d * exp(sinh(t)) XCas> g := unapply(f(y) * diff(y,t), (d,t)) XCas> g2(d) := [g(d,-t), g(d,t)] XCas> int(g2(1), t=0..5) → [0.995016625083, 99.0049833749] XCas> int(g2(700), t=0..5) → [99.9088118034, 0.0911881965555] XCas> plot(g2(700), t=0..3, color=[blue, red]) The plot showed a nice bell-shaped curve, easy to get area, simply by summing squares. see https://www.hpmuseum.org/forum/thread-13...#pid127590 \(\displaystyle\begin{align} \int_0^∞ f(x)\,dx &= \int_{-∞}^∞ g(t)\,dt = \int_{-∞}^∞ {g(t) + g(-t) \over 2} \,dt \\ &= \int_0^∞ g(-t)\,dt + \int_0^∞ g(t)\,dt \\ &= \int_0^d f(x)\,dx\;\,+ \int_d^∞ f(x)\,dx \end{align} \) Note we take advantage of even functions, and fold the integrals. see Integration trick: clever use of even and odd parts - John D. Cook |
|||
04-17-2021, 01:14 PM
Post: #60
|
|||
|
|||
RE: (PC-12xx~14xx) qthsh Tanh-Sinh quadrature
Revisiting original quad(), where we interpolate from the center, we may be able to improve it.
double_exponential.py is doing the same way, so the patch might be useful. This was the snippet from before, started with r = w = exp(t-.25/t); // = exp(sinh(j*h)) For tanh-sinh, r ← (r-1/r) / (r+1/r), which may suffer rounding errors > 1/2 ulp (04-11-2021 03:05 AM)robve Wrote: Instead, we calculate from the edge: r ← (r-1/r) / (r+1/r) = 1 - 2/(1+r*r) This is the proposed patch, where updated r should be much more accurate, at the edges. Code: if (mode == 0) { // if Tanh-Sinh (04-12-2021 01:50 PM)Albert Chan Wrote: lua> Q = require 'quad' This is still not as good as interpolate from the edge, but it improved a lot. Redoing the above example, with the proposed patch. lua> O = require 'quad0' -- original quad(), interpolate from center, but more accurate r lua> O.quad(O.count(f), -1, 1), O.n 3.1415926448906006 59 |
|||
« Next Oldest | Next Newest »
|
User(s) browsing this thread: 3 Guest(s)