def __init__(self, order, region=[-1., 1.], rule='GaussLegendre', uselongfloat=0): self.uselongfloat = uselongfloat if uselongfloat: region = [longfloat(region[0]), longfloat(region[1])] self.order = order self.region = region self.midpoint = (region[1] + region[0]) / 2. self.scale = (region[1] - region[0]) / 2. self.rule = rule if rule == 'GaussLegendre': x, w = self.__grule() for i in range(self.order): x[i] = x[i] * self.scale + self.midpoint w[i] = w[i] * self.scale elif rule == 'GaussHermite': raise "sorry this is not tested" x, w = self.__hrule() elif rule == 'GaussLaguerre': raise "sorry this is not tested" x, w = self.__lrule() else: raise "unknown rule", rule self.x = x self.w = w
def __hn(self, n, x): """ Evaluate the renormalized Hermite polynomials Hn(x). Regular Hn p[0] = 1 p[1] = 2*x p[i+1] = 2*x*p[i] - 2*i*p[i-1] Renormalized p[0] = 1/pi**(1/4) p[1] = sqrt(2)*x*p[0] p[i+1] = x*sqrt(2/(i+1))*p[i] - sqrt(j/(j+1))*p[j-1] """ p = range(n + 1) p[0] = 1.0 if self.uselongfloat: x = longfloat(x) p[0] = longfloat(1) if n == 0: return p p[1] = 2 * x for i in range(1, n): p[i + 1] = 2 * x * p[i] - 2 * i * p[i - 1] return p
def __hn(self, n, x): ''' Evaluate the renormalized Hermite polynomials Hn(x). Regular Hn p[0] = 1 p[1] = 2*x p[i+1] = 2*x*p[i] - 2*i*p[i-1] Renormalized p[0] = 1/pi**(1/4) p[1] = sqrt(2)*x*p[0] p[i+1] = x*sqrt(2/(i+1))*p[i] - sqrt(j/(j+1))*p[j-1] ''' p = range(n + 1) p[0] = 1.0 if self.uselongfloat: x = longfloat(x) p[0] = longfloat(1) if n == 0: return p p[1] = 2 * x for i in range(1, n): p[i + 1] = 2 * x * p[i] - 2 * i * p[i - 1] return p
def __init__(self, order, region=[-1.0, 1.0], rule="GaussLegendre", uselongfloat=0): self.uselongfloat = uselongfloat if uselongfloat: region = [longfloat(region[0]), longfloat(region[1])] self.order = order self.region = region self.midpoint = (region[1] + region[0]) / 2.0 self.scale = (region[1] - region[0]) / 2.0 self.rule = rule if rule == "GaussLegendre": x, w = self.__grule() for i in range(self.order): x[i] = x[i] * self.scale + self.midpoint w[i] = w[i] * self.scale elif rule == "GaussHermite": raise "sorry this is not tested" x, w = self.__hrule() elif rule == "GaussLaguerre": raise "sorry this is not tested" x, w = self.__lrule() else: raise "unknown rule", rule self.x = x self.w = w
def __ln(self, n, x): ''' Laguerre polyn ''' p = range(n + 1) p[0] = 1.0 if self.uselongfloat: x = longfloat(x) p[0] = longfloat(1) if n == 0: return p p[1] = 1 - x for i in range(1, n): p[i + 1] = ((2 * i + 1 - x) * p[i] - i * p[i - 1]) / (i + 1) return p
def __ln(self, n, x): """ Laguerre polyn """ p = range(n + 1) p[0] = 1.0 if self.uselongfloat: x = longfloat(x) p[0] = longfloat(1) if n == 0: return p p[1] = 1 - x for i in range(1, n): p[i + 1] = ((2 * i + 1 - x) * p[i] - i * p[i - 1]) / (i + 1) return p
def __factorial(self, n): f = 1.0 if self.uselongfloat: f = longfloat(1.0) for i in range(1, n + 1): f = f * i return f
def pnlong(x,order): ''' USE LONGFLOATS Evaluate the Legendre polynomials up to the given order at x defined on [-1,1]. ''' p = range(order+1) p[0] = longfloat(1) x = longfloat(x) if order == 0: return p p[1] = x for n in range(1,order): p[n+1] = n*(x*p[n] - p[n-1])/(n+1) + x*p[n] return p
def QuadratureTest2(uselongfloat=0): ''' Test the Gauss-Hermite quadrature on [-inf..inf] ''' maxmaxerr = 0.0 rootpi = sqrt(pi) two = 2.0 if uselongfloat: two = longfloat(2) rootpi = two.pi().sqrt() for order in range(2, 24): q = Quadrature(order, rule="GaussHermite", uselongfloat=uselongfloat) maxerr = 0.0 for power in range(0, 2 * order, 2): fstr = 'def __qtestf(x): return x**%d' % power exec(fstr) value = q.integrate(__qtestf) del (__qtestf) test = 0.5 * rootpi * 0.5**(power / 2) for i in range(power - 1, 0, -2): test = test * i maxerr = max(maxerr, abs(float(value - test) / test)) print "order %d: integrates powers up to %d with maxerr=%e" % \ (order, 2*order-2, maxerr) maxmaxerr = max(maxmaxerr, maxerr) print(' Maximum error from all orders %9.1e' % float(maxmaxerr))
def pnlong(x, order): ''' USE LONGFLOATS Evaluate the Legendre polynomials up to the given order at x defined on [-1,1]. ''' p = range(order + 1) p[0] = longfloat(1) x = longfloat(x) if order == 0: return p p[1] = x for n in range(1, order): p[n + 1] = n * (x * p[n] - p[n - 1]) / (n + 1) + x * p[n] return p
def philong(x,k): ''' USE LONGFLOATS Evaluate the shifted normalized Legendre polynomials up to the given order at x defined on [0,1]. These are also our scaling functions, phi_i(x) , i=0..k-1 In addition to forming an orthonormal basis on [0,1] we have phi_j(1/2-x) = (-1)^j phi_j(1/2+x) (the wavelets are similar with phase (-1)^(j+k)). ''' global phi_norms_long if len(phi_norms_long) == 0: for n in range(max(k+1,61)): phi_norms_long.append(longfloat(2*n+1).sqrt()) if k > 60: raise "phi_norms_long too small" order = k-1 p = pnlong(2*x-1,order) for n in range(k): p[n] = p[n]*phi_norms_long[n] # sqrt(2*n+1) return p
def philong(x, k): ''' USE LONGFLOATS Evaluate the shifted normalized Legendre polynomials up to the given order at x defined on [0,1]. These are also our scaling functions, phi_i(x) , i=0..k-1 In addition to forming an orthonormal basis on [0,1] we have phi_j(1/2-x) = (-1)^j phi_j(1/2+x) (the wavelets are similar with phase (-1)^(j+k)). ''' global phi_norms_long if len(phi_norms_long) == 0: for n in range(max(k + 1, 61)): phi_norms_long.append(longfloat(2 * n + 1).sqrt()) if k > 60: raise "phi_norms_long too small" order = k - 1 p = pnlong(2 * x - 1, order) for n in range(k): p[n] = p[n] * phi_norms_long[n] # sqrt(2*n+1) return p
def h0h1(k): ''' USE LONGFLOATS Compute the h0 & h1 two-scale coefficients h0_ij = sqrt(2)*int(phi_i(x)*phi_j(2x),x=0..1/2) h1_ij = sqrt(2)*int(phi_i(x)*phi_j(2x-1),x=1/2..1) but h1_ij = (-1)^(i+j) h0_ij from symmetry property of the phi The h0/h1 are useful because phi_i(x) = sqrt(2)*sum(j) h0_ij*phi_j(2x) + h1_ij*phi_j(2x-1) and phi_i(2x) = (1/sqrt(2))*sum(j) h0_ji*phi_j(x) + g0_ji*psi(x) phi_i(2x-1) = (1/sqrt(2))*sum(j) h1_ji*phi_j(x) + g1_ji*psi(x) ''' q = Quadrature(k, [longfloat(0), longfloat((-1, 1))], uselongfloat=1) x = q.points() w = q.weights() npt = len(x) twox = range(npt) for i in range(npt): twox[i] = x[i] + x[i] h0 = zeromatrix(k, k) h1 = zeromatrix(k, k) root2 = longfloat(2).sqrt() for t in range(npt): p = philong(x[t], k) p2 = philong(twox[t], k) for i in range(k): faci = p[i] * w[t] * root2 for j in range(k): h0[i][j] = h0[i][j] + faci * p2[j] for i in range(k): for j in range(k): h1[i][j] = ((-1)**(i + j)) * h0[i][j] return (h0, h1)
def h0h1(k): ''' USE LONGFLOATS Compute the h0 & h1 two-scale coefficients h0_ij = sqrt(2)*int(phi_i(x)*phi_j(2x),x=0..1/2) h1_ij = sqrt(2)*int(phi_i(x)*phi_j(2x-1),x=1/2..1) but h1_ij = (-1)^(i+j) h0_ij from symmetry property of the phi The h0/h1 are useful because phi_i(x) = sqrt(2)*sum(j) h0_ij*phi_j(2x) + h1_ij*phi_j(2x-1) and phi_i(2x) = (1/sqrt(2))*sum(j) h0_ji*phi_j(x) + g0_ji*psi(x) phi_i(2x-1) = (1/sqrt(2))*sum(j) h1_ji*phi_j(x) + g1_ji*psi(x) ''' q = Quadrature(k,[longfloat(0),longfloat((-1,1))],uselongfloat=1) x = q.points() w = q.weights() npt = len(x) twox = range(npt) for i in range(npt): twox[i] = x[i] + x[i] h0 = zeromatrix(k,k) h1 = zeromatrix(k,k) root2 = longfloat(2).sqrt() for t in range(npt): p = philong(x[t],k) p2= philong(twox[t],k) for i in range(k): faci = p[i]*w[t]*root2 for j in range(k): h0[i][j] = h0[i][j] + faci*p2[j] for i in range(k): for j in range(k): h1[i][j] = ((-1)**(i+j))*h0[i][j] return (h0, h1)
def __grule(self): ''' Return the Gauss Legendre quadrature weights. ''' n = self.order nbits = 52 if self.uselongfloat: nbits = longfloat.nbits acc = 0.5**(nbits / 3 + 10) if self.uselongfloat: acc = longfloat(acc) # References made to the equation numbers in Davis & Rabinowitz 2nd ed. roots = range(n) weights = range(n) for k in range(n): # Initial guess for the root using 2.7.3.3b #x = (1.0 - 1.0/(8*n*n) + 1.0/(8*n*n*n))*cos(((4*k+3.0)/(4*n+2))*pi) x = (1.0 - 1.0 / (8.0 * n * n) + 1.0 / (8.0 * n * n * n)) * cos( ((4 * k + 3.0) / (4 * n + 2)) * pi) if self.uselongfloat: x = longfloat(x) # Refine the initial guess using a 3rd-order Newton correction 2.7.3.9 # Running this six times will ensure enough precision even if we're # requesting over 1500 significant decimal figures. for iter in range(7): p = self.__pn(n, x) p0 = p[n] # Value p1 = n * (p[n - 1] - x * p[n]) / ( 1 - x * x) # First derivative ... 2.7.3.5 p2 = (2 * x * p1 - n * (n + 1) * p0) / (1 - x * x) # Second derivative delta = -(p0 / p1) * (1 + (p0 * p2) / (2 * p1 * p1)) x = x + delta if abs(delta) < acc: break if iter >= 6: raise "netwon iteration for root failed" # Compute the weight using 2.7.3.8 p = self.__pn(n, x) w = 2 * (1 - x * x) / (n * n * p[n - 1] * p[n - 1]) roots[k] = x weights[k] = w return (roots, weights)
def __grule(self): """ Return the Gauss Legendre quadrature weights. """ n = self.order nbits = 52 if self.uselongfloat: nbits = longfloat.nbits acc = 0.5 ** (nbits / 3 + 10) if self.uselongfloat: acc = longfloat(acc) # References made to the equation numbers in Davis & Rabinowitz 2nd ed. roots = range(n) weights = range(n) for k in range(n): # Initial guess for the root using 2.7.3.3b # x = (1.0 - 1.0/(8*n*n) + 1.0/(8*n*n*n))*cos(((4*k+3.0)/(4*n+2))*pi) x = (1.0 - 1.0 / (8.0 * n * n) + 1.0 / (8.0 * n * n * n)) * cos(((4 * k + 3.0) / (4 * n + 2)) * pi) if self.uselongfloat: x = longfloat(x) # Refine the initial guess using a 3rd-order Newton correction 2.7.3.9 # Running this six times will ensure enough precision even if we're # requesting over 1500 significant decimal figures. for iter in range(7): p = self.__pn(n, x) p0 = p[n] # Value p1 = n * (p[n - 1] - x * p[n]) / (1 - x * x) # First derivative ... 2.7.3.5 p2 = (2 * x * p1 - n * (n + 1) * p0) / (1 - x * x) # Second derivative delta = -(p0 / p1) * (1 + (p0 * p2) / (2 * p1 * p1)) x = x + delta if abs(delta) < acc: break if iter >= 6: raise "netwon iteration for root failed" # Compute the weight using 2.7.3.8 p = self.__pn(n, x) w = 2 * (1 - x * x) / (n * n * p[n - 1] * p[n - 1]) roots[k] = x weights[k] = w return (roots, weights)
def QuadratureTest(uselongfloat=0): """ Test the Gauss-Legendre quadrature on [0.5,1] """ maxmaxerr = 0.0 for order in range(1, 20): q = Quadrature(order, [0.5, 1.0], uselongfloat=uselongfloat) maxerr = 0.0 for power in range(2 * order): fstr = "def __qtestf(x): return x**%d" % power exec (fstr) value = q.integrate(__qtestf) del (__qtestf) if uselongfloat: test = (longfloat(1) - longfloat((-power - 1, 1))) / (power + 1.0) else: test = (1.0 - 0.5 ** (power + 1)) / (power + 1.0) maxerr = max(maxerr, abs(float(value - test))) print "order %d: integrates powers up to %d with maxerr=%e" % (order, 2 * order - 1, maxerr) maxmaxerr = max(maxmaxerr, maxerr) print (" Maximum error from all orders %9.1e" % float(maxmaxerr))
def QuadratureTest(uselongfloat=0): ''' Test the Gauss-Legendre quadrature on [0.5,1] ''' maxmaxerr = 0.0 for order in range(1, 20): q = Quadrature(order, [0.5, 1.0], uselongfloat=uselongfloat) maxerr = 0.0 for power in range(2 * order): fstr = 'def __qtestf(x): return x**%d' % power exec(fstr) value = q.integrate(__qtestf) del (__qtestf) if uselongfloat: test = (longfloat(1) - longfloat( (-power - 1, 1))) / (power + 1.0) else: test = (1.0 - 0.5**(power + 1)) / (power + 1.0) maxerr = max(maxerr, abs(float(value - test))) print "order %d: integrates powers up to %d with maxerr=%e" % \ (order, 2*order-1, maxerr) maxmaxerr = max(maxmaxerr, maxerr) print(' Maximum error from all orders %9.1e' % float(maxmaxerr))
def half_moments(maxm,k): ''' USE LONGFLOATS Compute the moments of the scaling functions computed over half over the interval. hmom1[p][j] = int(x^p * phi_j(2*x), x=0..1/2) hmom2[p][j] = int((x+0.5)^p * phi_j(2*x), x=0..1/2) hmom2 is made from hmom1 using the binomial expansion (x+a)^p = a^0*x^p + p*a^1*x^p-1 + p*(p-1)*a^2*x^p-2 / 2 + ... + a^p*x^0 From Alpert, Beylkin, Gines and Vozovoi int(x^p phi_j(x),x=0..1) = sqrt(2*j+1)*(p!)^2 / ((p-j)!(p+j+1)!) p>=j Get an extra factor of (1/2)^(m+1) from the change of scale. For completeness also record here that int((x-1)^p phi_j(x),x=0..1) = (-1)^(j+p) * . sqrt(2*j+1)*(p!)^2 / ((p-j)!(p+j+1)!) Moments with p < j are zero due to orthogonality. ''' hmom1 = zeromatrix(maxm+1,k) hmom2 = zeromatrix(maxm+1,k) factorial = range(maxm+1+k) pfac = longfloat(1) for p in range(maxm+1+k): factorial[p] = pfac pfac = pfac * (p+1) half = longfloat((-1,1)) for p in range(maxm+1): pfac2 = factorial[p]*factorial[p] scale = longfloat(half)**(p+1) for j in range(k): if p < j: hmom1[p][j] = longfloat(0) else: hmom1[p][j] = scale*(longfloat(2*j+1).sqrt())*pfac2 / \ (factorial[p-j]*factorial[p+j+1]) for p in range(maxm+1): for i in range(k): fac = longfloat(1) for q in range(p+1): hmom2[p][i] = hmom2[p][i] + fac*(half**(p-q))*hmom1[q][i] fac = fac * (p-q) / (q+1) return (hmom1, hmom2)
def half_moments(maxm, k): ''' USE LONGFLOATS Compute the moments of the scaling functions computed over half over the interval. hmom1[p][j] = int(x^p * phi_j(2*x), x=0..1/2) hmom2[p][j] = int((x+0.5)^p * phi_j(2*x), x=0..1/2) hmom2 is made from hmom1 using the binomial expansion (x+a)^p = a^0*x^p + p*a^1*x^p-1 + p*(p-1)*a^2*x^p-2 / 2 + ... + a^p*x^0 From Alpert, Beylkin, Gines and Vozovoi int(x^p phi_j(x),x=0..1) = sqrt(2*j+1)*(p!)^2 / ((p-j)!(p+j+1)!) p>=j Get an extra factor of (1/2)^(m+1) from the change of scale. For completeness also record here that int((x-1)^p phi_j(x),x=0..1) = (-1)^(j+p) * . sqrt(2*j+1)*(p!)^2 / ((p-j)!(p+j+1)!) Moments with p < j are zero due to orthogonality. ''' hmom1 = zeromatrix(maxm + 1, k) hmom2 = zeromatrix(maxm + 1, k) factorial = range(maxm + 1 + k) pfac = longfloat(1) for p in range(maxm + 1 + k): factorial[p] = pfac pfac = pfac * (p + 1) half = longfloat((-1, 1)) for p in range(maxm + 1): pfac2 = factorial[p] * factorial[p] scale = longfloat(half)**(p + 1) for j in range(k): if p < j: hmom1[p][j] = longfloat(0) else: hmom1[p][j] = scale*(longfloat(2*j+1).sqrt())*pfac2 / \ (factorial[p-j]*factorial[p+j+1]) for p in range(maxm + 1): for i in range(k): fac = longfloat(1) for q in range(p + 1): hmom2[p][i] = hmom2[p][i] + fac * (half**(p - q)) * hmom1[q][i] fac = fac * (p - q) / (q + 1) return (hmom1, hmom2)
def QuadratureTest2(uselongfloat=0): """ Test the Gauss-Hermite quadrature on [-inf..inf] """ maxmaxerr = 0.0 rootpi = sqrt(pi) two = 2.0 if uselongfloat: two = longfloat(2) rootpi = two.pi().sqrt() for order in range(2, 24): q = Quadrature(order, rule="GaussHermite", uselongfloat=uselongfloat) maxerr = 0.0 for power in range(0, 2 * order, 2): fstr = "def __qtestf(x): return x**%d" % power exec (fstr) value = q.integrate(__qtestf) del (__qtestf) test = 0.5 * rootpi * 0.5 ** (power / 2) for i in range(power - 1, 0, -2): test = test * i maxerr = max(maxerr, abs(float(value - test) / test)) print "order %d: integrates powers up to %d with maxerr=%e" % (order, 2 * order - 2, maxerr) maxmaxerr = max(maxmaxerr, maxerr) print (" Maximum error from all orders %9.1e" % float(maxmaxerr))
def g0g1(k): ''' USE LONGFLOATS Compute the g0 & g1 two-scale coefficients which define the multi-wavelet in terms of the scaling functions at the finer level. psi_i(x) = sqrt(2)*sum(j) g0_ij*phi_j(2x) + g1_ij*phi_j(2x-1) Projection with sqrt(2)*phi_j(2x) and sqrt(2)*phi_j(2x-1), which are the normalized scaling functions on the finer level, yields g0_ij = sqrt(2)*int(psi_i(x)*phi_j(2x),x=0..1/2) g1_ij = sqrt(2)*int(psi_i(x)*phi_j(2x-1),x=1/2..1) With the original Alpert conditions we have g1_ij = (-1)^(i+j+k) g0_ij from symmetry properties of the psi but you only get this if you impose the condition of additional vanishing moments. The projection of the additional moments is very numerically unstable and forces the use of higher precision for k >= 6. ''' g0 = zeromatrix(k, k) g1 = zeromatrix(k, k) # Initialize the basis rroot2 = longfloat(2).rsqrt() for i in range(0, k): g0[i][i] = rroot2 g1[i][i] = -rroot2 (h0, h1) = h0h1(k) # Project out the moments == orthog to the scaling functions. # Need to use the two-scale relation for the scaling functions. for i in range(k): for attempt in range(1): # was 2 for m in range(k): dotim = dot(g0[i], h0[m]) + dot(g1[i], h1[m]) for j in range(k): g0[i][j] = g0[i][j] - dotim * h0[m][j] g1[i][j] = g1[i][j] - dotim * h1[m][j] # Orthog to x^k, x^k+1, ... , x^2k-2 first = 0 root2 = longfloat(2).sqrt() (hmom1, hmom2) = half_moments(2 * k - 2, k) test = longfloat(1).eps().sqrt() for power in range(k, 2 * k - 1): # Transform to the wavelet basis overlap = zerovector(k) for i in range(k): for j in range(k): overlap[i] = overlap[i] + root2*\ (g0[i][j]*hmom1[power][j] + g1[i][j]*hmom2[power][j]) # Put first function with non-zero overlap in front of the list for i in range(first, k): if abs(overlap[i]) > test: # Is there a better test? (g0[first], g0[i]) = (g0[i], g0[first]) (g1[first], g1[i]) = (g1[i], g1[first]) (overlap[first], overlap[i]) = (overlap[i], overlap[first]) break # Project out the first component as necessary. if abs(overlap[first]) > test: # Is there a better test? for i in range(first + 1, k): scale = overlap[i] / overlap[first] for j in range(k): g0[i][j] = g0[i][j] - scale * g0[first][j] g1[i][j] = g1[i][j] - scale * g1[first][j] first = first + 1 orthonormalize_wavelets(g0, g1, k) return (g0, g1)
def zerovector(n): v = vector(n) for i in range(n): v[i] = longfloat(0) return v
def g0g1(k): ''' USE LONGFLOATS Compute the g0 & g1 two-scale coefficients which define the multi-wavelet in terms of the scaling functions at the finer level. psi_i(x) = sqrt(2)*sum(j) g0_ij*phi_j(2x) + g1_ij*phi_j(2x-1) Projection with sqrt(2)*phi_j(2x) and sqrt(2)*phi_j(2x-1), which are the normalized scaling functions on the finer level, yields g0_ij = sqrt(2)*int(psi_i(x)*phi_j(2x),x=0..1/2) g1_ij = sqrt(2)*int(psi_i(x)*phi_j(2x-1),x=1/2..1) With the original Alpert conditions we have g1_ij = (-1)^(i+j+k) g0_ij from symmetry properties of the psi but you only get this if you impose the condition of additional vanishing moments. The projection of the additional moments is very numerically unstable and forces the use of higher precision for k >= 6. ''' g0 = zeromatrix(k,k) g1 = zeromatrix(k,k) # Initialize the basis rroot2 = longfloat(2).rsqrt() for i in range(0,k): g0[i][i] = rroot2 g1[i][i] = -rroot2 (h0, h1) = h0h1(k) # Project out the moments == orthog to the scaling functions. # Need to use the two-scale relation for the scaling functions. for i in range(k): for attempt in range(1): # was 2 for m in range(k): dotim = dot(g0[i],h0[m])+dot(g1[i],h1[m]) for j in range(k): g0[i][j] = g0[i][j] - dotim*h0[m][j] g1[i][j] = g1[i][j] - dotim*h1[m][j] # Orthog to x^k, x^k+1, ... , x^2k-2 first = 0 root2 = longfloat(2).sqrt() (hmom1,hmom2) = half_moments(2*k-2,k) test = longfloat(1).eps().sqrt() for power in range(k,2*k-1): # Transform to the wavelet basis overlap = zerovector(k) for i in range(k): for j in range(k): overlap[i] = overlap[i] + root2*\ (g0[i][j]*hmom1[power][j] + g1[i][j]*hmom2[power][j]) # Put first function with non-zero overlap in front of the list for i in range(first,k): if abs(overlap[i]) > test: # Is there a better test? (g0[first],g0[i]) = (g0[i],g0[first]) (g1[first],g1[i]) = (g1[i],g1[first]) (overlap[first],overlap[i]) = (overlap[i],overlap[first]) break # Project out the first component as necessary. if abs(overlap[first]) > test: # Is there a better test? for i in range(first+1,k): scale = overlap[i]/overlap[first] for j in range(k): g0[i][j] = g0[i][j] - scale*g0[first][j] g1[i][j] = g1[i][j] - scale*g1[first][j] first = first + 1 orthonormalize_wavelets(g0,g1,k) return (g0, g1)
def __hrule(self): ''' Gauss-Hermite rule on [0,inf] ''' n = self.order nbits = 52 rootpi = sqrt(pi) two = 2.0 zero = 0.0 if self.uselongfloat: two = longfloat(2) zero = longfloat(0) rootpi = longfloat(1).pi().sqrt() nbits = longfloat.nbits acc = 0.5**(nbits / 3 + 10) if self.uselongfloat: acc = longfloat(acc) # Find the points which are the zeros of Hn # dH[n]/dx = 2*n*H[n-1] npt = (n - 1) / 2 + 1 roots = range(npt) weights = range(npt) nfound = 0 if n % 2: p = self.__hn(n + 1, 0.0) roots[0] = zero weights[0] = two**(n + 1) * self.__factorial(n) * rootpi / p[n + 1]**2 # !!!! Since just doing [0,inf] need to halve this weights[0] = weights[0] / two nfound = nfound + 1 guess = 0.01 if self.uselongfloat: guess = longfloat(guess) while nfound != npt: # Stupid linear search forward for sign change x = guess p = self.__hn(n, x) hh = p[n] while 1: x = x + 0.05 p = self.__hn(n, x) if hh * p[n] < 0.0: break # Cubic newton for iter in range(7): p = self.__hn(n, x) p0 = p[n] # Value p1 = 2 * n * p[n - 1] # First derivative p2 = 4 * n * (n - 1) * p[n - 2] # Second derivative delta = -(p0 / p1) * (1 + (p0 * p2) / (2 * p1 * p1)) #print "newton", x, delta x = x + delta if abs(delta) < acc: break if iter >= 6: raise "Hermite netwon iteration for root failed" new = 1 for i in range(nfound): if abs(x - roots[i]) < 1e-3: new = 0 break if not new: guess = guess + 0.1 if guess > 100.0: raise "Hermite root finder is lost" continue #print "found root", x roots[nfound] = x p = self.__hn(n + 1, x) weights[nfound] = two**( n + 1) * self.__factorial(n) * rootpi / p[n + 1]**2 nfound = nfound + 1 guess = x + 0.05 return roots, weights
def __lrule(self): """ Gauss-Laguerre rule on [0,inf] """ n = self.order nbits = 52 zero = 0.0 if self.uselongfloat: zero = longfloat(0) nbits = longfloat.nbits acc = 0.5 ** (nbits / 3 + 10) if self.uselongfloat: acc = longfloat(acc) # Find the points which are the zeros of Ln # dL[n]/dx = n*(L[n] - L[n-1])/x roots = range(n) weights = range(n) nfound = 0 guess = 0.0001 step = 0.0001 if self.uselongfloat: guess = longfloat(guess) while nfound != n: # Stupid linear search forward for sign change x = guess p = self.__ln(n, x) hh = p[n] if nfound > 1: step = 0.1 * (roots[nfound - 1] - roots[nfound - 2]) print "step", step niter = 1000 while niter: niter = niter - 1 xp = x x = x + step p = self.__ln(n, x) if hh * p[n] < 0.0: break x = (x + xp) / 2.0 if niter == 0: print nfound, x raise "Gauss Laguerre lost a root?" print "linear search found", x, hh, p[n] # Cubic newton for iter in range(7): p = self.__ln(n, x) p0 = p[n] # Value p1 = n * (p[n] - p[n - 1]) / x # First derivative pp1 = (n - 1) * (p[n - 1] - p[n - 2]) / x p2 = n * (p1 - pp1) / x - p1 / x # Second derivative delta = -(p0 / p1) * (1 + (p0 * p2) / (2 * p1 * p1)) x = x + delta if abs(delta) < acc: break if iter >= 6: raise "Laguerre netwon iteration for root failed" print "found", x new = 1 for i in range(nfound): if abs(x - roots[i]) < 1e-3: new = 0 break if not new: guess = guess + step if guess > 150.0: raise "Laguerre root finder is lost" continue p = self.__ln(n + 1, x) roots[nfound] = x weights[nfound] = x / ((n + 1) * p[n + 1]) ** 2 nfound = nfound + 1 guess = x + 0.05 return roots, weights
def __hrule(self): """ Gauss-Hermite rule on [0,inf] """ n = self.order nbits = 52 rootpi = sqrt(pi) two = 2.0 zero = 0.0 if self.uselongfloat: two = longfloat(2) zero = longfloat(0) rootpi = longfloat(1).pi().sqrt() nbits = longfloat.nbits acc = 0.5 ** (nbits / 3 + 10) if self.uselongfloat: acc = longfloat(acc) # Find the points which are the zeros of Hn # dH[n]/dx = 2*n*H[n-1] npt = (n - 1) / 2 + 1 roots = range(npt) weights = range(npt) nfound = 0 if n % 2: p = self.__hn(n + 1, 0.0) roots[0] = zero weights[0] = two ** (n + 1) * self.__factorial(n) * rootpi / p[n + 1] ** 2 # !!!! Since just doing [0,inf] need to halve this weights[0] = weights[0] / two nfound = nfound + 1 guess = 0.01 if self.uselongfloat: guess = longfloat(guess) while nfound != npt: # Stupid linear search forward for sign change x = guess p = self.__hn(n, x) hh = p[n] while 1: x = x + 0.05 p = self.__hn(n, x) if hh * p[n] < 0.0: break # Cubic newton for iter in range(7): p = self.__hn(n, x) p0 = p[n] # Value p1 = 2 * n * p[n - 1] # First derivative p2 = 4 * n * (n - 1) * p[n - 2] # Second derivative delta = -(p0 / p1) * (1 + (p0 * p2) / (2 * p1 * p1)) # print "newton", x, delta x = x + delta if abs(delta) < acc: break if iter >= 6: raise "Hermite netwon iteration for root failed" new = 1 for i in range(nfound): if abs(x - roots[i]) < 1e-3: new = 0 break if not new: guess = guess + 0.1 if guess > 100.0: raise "Hermite root finder is lost" continue # print "found root", x roots[nfound] = x p = self.__hn(n + 1, x) weights[nfound] = two ** (n + 1) * self.__factorial(n) * rootpi / p[n + 1] ** 2 nfound = nfound + 1 guess = x + 0.05 return roots, weights
def __lrule(self): ''' Gauss-Laguerre rule on [0,inf] ''' n = self.order nbits = 52 zero = 0.0 if self.uselongfloat: zero = longfloat(0) nbits = longfloat.nbits acc = 0.5**(nbits / 3 + 10) if self.uselongfloat: acc = longfloat(acc) # Find the points which are the zeros of Ln # dL[n]/dx = n*(L[n] - L[n-1])/x roots = range(n) weights = range(n) nfound = 0 guess = 0.0001 step = 0.0001 if self.uselongfloat: guess = longfloat(guess) while nfound != n: # Stupid linear search forward for sign change x = guess p = self.__ln(n, x) hh = p[n] if nfound > 1: step = 0.1 * (roots[nfound - 1] - roots[nfound - 2]) print "step", step niter = 1000 while niter: niter = niter - 1 xp = x x = x + step p = self.__ln(n, x) if hh * p[n] < 0.0: break x = (x + xp) / 2.0 if niter == 0: print nfound, x raise "Gauss Laguerre lost a root?" print "linear search found", x, hh, p[n] # Cubic newton for iter in range(7): p = self.__ln(n, x) p0 = p[n] # Value p1 = n * (p[n] - p[n - 1]) / x # First derivative pp1 = (n - 1) * (p[n - 1] - p[n - 2]) / x p2 = n * (p1 - pp1) / x - p1 / x # Second derivative delta = -(p0 / p1) * (1 + (p0 * p2) / (2 * p1 * p1)) x = x + delta if abs(delta) < acc: break if iter >= 6: raise "Laguerre netwon iteration for root failed" print "found", x new = 1 for i in range(nfound): if abs(x - roots[i]) < 1e-3: new = 0 break if not new: guess = guess + step if guess > 150.0: raise "Laguerre root finder is lost" continue p = self.__ln(n + 1, x) roots[nfound] = x weights[nfound] = x / ((n + 1) * p[n + 1])**2 nfound = nfound + 1 guess = x + 0.05 return roots, weights