class_docstr: This class implements "tanh-sinh" or "doubly exponential"
  quadrature. This quadrature rule is based on the Euler-Maclaurin
  integral formula. By performing a change of variables involving
  nested exponentials / hyperbolic functions (hence the name), the
  derivatives at the endpoints vanish rapidly. Since the error term
  in the Euler-Maclaurin formula depends on the derivatives at the
  endpoints, a simple step sum becomes extremely accurate. In
  practice, this means that doubling the number of evaluation
  points roughly doubles the number of accurate digits.
  
  Comparison to Gauss-Legendre:
    * Initial computation of nodes is usually faster
    * Handles endpoint singularities better
    * Handles infinite integration intervals better
    * Is slower for smooth integrands once nodes have been computed
  
  The implementation of the tanh-sinh algorithm is based on the
  description given in Borwein, Bailey & Girgensohn, "Experimentation
  in Mathematics - Computational Paths to Discovery", A K Peters,
  2003, pages 312-313. In the present implementation, a few
  improvements have been made:
  
    * A more efficient scheme is used to compute nodes (exploiting
      recurrence for the exponential function)
    * The nodes are computed successively instead of all at once
  
  **References**
  
  * [Bailey]_
  * http://users.cs.dal.ca/~jborwein/tanh-sinh.pdf
class_docstr_tok: ["This","class","implements","``","tanh-sinh","''","or","``","doubly","exponential","''","quadrature",".","This","quadrature","rule","is","based","on","the","Euler-Maclaurin","integral","formula",".","By","performing","a","change","of","variables","involving","nested","exponentials","\/","hyperbolic","functions","(","hence","the","name",")",",","the","derivatives","at","the","endpoints","vanish","rapidly",".","Since","the","error","term","in","the","Euler-Maclaurin","formula","depends","on","the","derivatives","at","the","endpoints",",","a","simple","step","sum","becomes","extremely","accurate",".","In","practice",",","this","means","that","doubling","the","number","of","evaluation","points","roughly","doubles","the","number","of","accurate","digits",".","Comparison","to","Gauss-Legendre",":","*","Initial","computation","of","nodes","is","usually","faster","*","Handles","endpoint","singularities","better","*","Handles","infinite","integration","intervals","better","*","Is","slower","for","smooth","integrands","once","nodes","have","been","computed","The","implementation","of","the","tanh-sinh","algorithm","is","based","on","the","description","given","in","Borwein",",","Bailey","&","Girgensohn",",","``","Experimentation","in","Mathematics","-","Computational","Paths","to","Discovery","''",",","A","K","Peters",",","2003",",","pages","312-313",".","In","the","present","implementation",",","a","few","improvements","have","been","made",":","*","A","more","efficient","scheme","is","used","to","compute","nodes","(","exploiting","recurrence","for","the","exponential","function",")","*","The","nodes","are","computed","successively","instead","of","all","at","once","*","*","References","*","*","*","[","Bailey","]","_","*","http",":","\/\/users.cs.dal.ca\/~jborwein\/tanh-sinh.pdf"]
docstr: The abscissas and weights for tanh-sinh quadrature of degree
  `m` are given by
  
  .. math::
  
      x_k = \tanh(\pi/2 \sinh(t_k))
  
      w_k = \pi/2 \cosh(t_k) / \cosh(\pi/2 \sinh(t_k))^2
  
  where `t_k = t_0 + hk` for a step length `h \sim 2^{-m}`. The
  list of nodes is actually infinite, but the weights die off so
  rapidly that only a few are needed.
docstr_tok: ["The","abscissas","and","weights","for","tanh-sinh","quadrature","of","degree","`","m","`","are","given","by","..","math",":",":","x_k","=","\\tanh","(","\\pi\/2","\\sinh","(","t_k",")",")","w_k","=","\\pi\/2","\\cosh","(","t_k",")","\/","\\cosh","(","\\pi\/2","\\sinh","(","t_k",")",")","^2","where","`","t_k","=","t_0","+","hk","`","for","a","step","length","`","h","\\sim","2^","{","-m","}","`",".","The","list","of","nodes","is","actually","infinite",",","but","the","weights","die","off","so","rapidly","that","only","a","few","are","needed","."]
code: def calc_nodes(self, degree, prec, verbose=False):
      r"""
      The abscissas and weights for tanh-sinh quadrature of degree
      `m` are given by
  
      .. math::
  
          x_k = \tanh(\pi/2 \sinh(t_k))
  
          w_k = \pi/2 \cosh(t_k) / \cosh(\pi/2 \sinh(t_k))^2
  
      where `t_k = t_0 + hk` for a step length `h \sim 2^{-m}`. The
      list of nodes is actually infinite, but the weights die off so
      rapidly that only a few are needed.
      """
      ctx = self.ctx
      nodes = []
  
      extra = 20
      ctx.prec += extra
      tol = ctx.ldexp(1, -prec - 10)
      pi4 = ctx.pi / 4
  
      # For simplicity, we work in steps h = 1/2^n, with the first point
      # offset so that we can reuse the sum from the previous degree
  
      # We define degree 1 to include the "degree 0" steps, including
      # the point x = 0. (It doesn't work well otherwise; not sure why.)
      t0 = ctx.ldexp(1, -degree)
      if degree == 1:
          # nodes.append((mpf(0), pi4))
          # nodes.append((-mpf(0), pi4))
          nodes.append((ctx.zero, ctx.pi / 2))
          h = t0
      else:
          h = t0 * 2
  
      # Since h is fixed, we can compute the next exponential
      # by simply multiplying by exp(h)
      expt0 = ctx.exp(t0)
      a = pi4 * expt0
      b = pi4 / expt0
      udelta = ctx.exp(h)
      urdelta = 1 / udelta
  
      for k in xrange(0, 20 * 2**degree + 1):
          # Reference implementation:
          # t = t0 + k*h
          # x = tanh(pi/2 * sinh(t))
          # w = pi/2 * cosh(t) / cosh(pi/2 * sinh(t))**2
  
          # Fast implementation. Note that c = exp(pi/2 * sinh(t))
          c = ctx.exp(a - b)
          d = 1 / c
          co = (c + d) / 2
          si = (c - d) / 2
          x = si / co
          w = (a + b) / co**2
          diff = abs(x - 1)
          if diff <= tol:
              break
  
          nodes.append((x, w))
          nodes.append((-x, w))
  
          a *= udelta
          b *= urdelta
  
          if verbose and k % 300 == 150:
              # Note: the number displayed is rather arbitrary. Should
              # figure out how to print something that looks more like a
              # percentage
              print(
                  "Calculating nodes:",
                  ctx.nstr(-ctx.log(diff, 10) / prec),
              )
  
      ctx.prec -= extra
      return nodes
  
imports: import math
  from ..libmp.backend import xrange
label_desc: Use image node_id 2 for calling the TanhSinh obj's underlying member method code with example usage: obj.calc_nodes(degree, prec, verbose) and returns: nodes