comparison libinterp/corefcn/quadcc.cc @ 15995:906ae1705522

quadcc.cc: Use heap instead of stack for large temporary variables. * libinterp/corefcn/quadcc.cc: Use heap instead of stack for large temporary variables. Use Octave coding conventions. Place debug code under #if.
author Rik <rik@octave.org>
date Mon, 04 Feb 2013 11:10:14 -0800
parents 352ef2fb3ad1
children 1aff8c38c53c
comparison
equal deleted inserted replaced
15994:352ef2fb3ad1 15995:906ae1705522
31 #include "defun.h" 31 #include "defun.h"
32 #include "error.h" 32 #include "error.h"
33 #include "oct-obj.h" 33 #include "oct-obj.h"
34 #include "utils.h" 34 #include "utils.h"
35 35
36 //#include "oct.h" 36
37 //#include "defun.h" 37 /* Extended debugging */
38 38 #define DEBUG_QUADCC 0
39 /* Define the size of the interval heap. */ 39
40 #define cquad_heapsize 50 40 /* Define the minimum size of the interval heap. */
41 #define min_cquad_heapsize 200
41 42
42 43
43 /* Data of a single interval */ 44 /* Data of a single interval */
44 typedef struct 45 typedef struct
45 { 46 {
1550 static const int idx[4] = { 0, 5, 14, 31 }; 1551 static const int idx[4] = { 0, 5, 14, 31 };
1551 static const double w = M_SQRT2 / 2; 1552 static const double w = M_SQRT2 / 2;
1552 static const int ndiv_max = 20; 1553 static const int ndiv_max = 20;
1553 1554
1554 /* The interval heap. */ 1555 /* The interval heap. */
1555 cquad_ival ivals[cquad_heapsize]; 1556 cquad_ival *ivals;
1556 int heap[cquad_heapsize]; 1557 int *heap;
1557 1558
1558 /* Arguments left and right */ 1559 /* Arguments left and right */
1559 int nargin = args.length (); 1560 int nargin = args.length ();
1560 octave_function *fcn; 1561 octave_function *fcn;
1561 double a, b, tol, iivals[cquad_heapsize], *sing; 1562 double a, b, tol, *iivals, *sing;
1562 1563
1563 /* Variables needed for transforming the integrand. */ 1564 /* Variables needed for transforming the integrand. */
1564 bool wrap = false; 1565 bool wrap = false;
1565 double xw; 1566 double xw;
1566 1567
1586 1587
1587 if (args(0).is_function_handle () || args(0).is_inline_function ()) 1588 if (args(0).is_function_handle () || args(0).is_inline_function ())
1588 fcn = args(0).function_value (); 1589 fcn = args(0).function_value ();
1589 else 1590 else
1590 { 1591 {
1591 std::string fcn_name = unique_symbol_name ("__quadcc_fcn_"); 1592 std::string fcn_name = unique_symbol_name ("__quadcc_fcn__");
1592 std::string fname = "function y = "; 1593 std::string fname = "function y = ";
1593 fname.append (fcn_name); 1594 fname.append (fcn_name);
1594 fname.append ("(x) y = "); 1595 fname.append ("(x) y = ");
1595 fcn = extract_function (args(0), "quadcc", fcn_name, fname, 1596 fcn = extract_function (args(0), "quadcc", fcn_name, fname,
1596 "; endfunction"); 1597 "; endfunction");
1597 } 1598 }
1598 1599
1599 if (!args(1).is_real_scalar ()) 1600 if (! args(1).is_real_scalar ())
1600 { 1601 {
1601 error ("quadcc: lower limit of integration (A) must be a single real scalar"); 1602 error ("quadcc: lower limit of integration (A) must be a single real scalar");
1602 return retval; 1603 return retval;
1603 } 1604 }
1604 else 1605 else
1605 a = args(1).double_value (); 1606 a = args(1).double_value ();
1606 1607
1607 if (!args(2).is_real_scalar ()) 1608 if (! args(2).is_real_scalar ())
1608 { 1609 {
1609 error ("quadcc: upper limit of integration (B) must be a single real scalar"); 1610 error ("quadcc: upper limit of integration (B) must be a single real scalar");
1610 return retval; 1611 return retval;
1611 } 1612 }
1612 else 1613 else
1613 b = args(2).double_value (); 1614 b = args(2).double_value ();
1614 1615
1615 if (nargin < 4 || args(3).is_empty ()) 1616 if (nargin < 4 || args(3).is_empty ())
1616 tol = 1.0e-6; 1617 tol = 1.0e-6;
1617 else if (!args(3).is_real_scalar () || args(3).double_value () <= 0) 1618 else if (! args(3).is_real_scalar () || args(3).double_value () <= 0)
1618 { 1619 {
1619 error ("quadcc: tolerance (TOL) must be a single real scalar > 0"); 1620 error ("quadcc: tolerance (TOL) must be a single real scalar > 0");
1620 return retval; 1621 return retval;
1621 } 1622 }
1622 else 1623 else
1623 tol = args(3).double_value (); 1624 tol = args(3).double_value ();
1624 1625
1625 if (nargin < 5) 1626 if (nargin < 5)
1626 { 1627 {
1627 nivals = 1; 1628 nivals = 1;
1628 iivals[0] = a;
1629 iivals[1] = b;
1630 } 1629 }
1631 else if (!(args(4).is_real_scalar () || args(4).is_real_matrix ())) 1630 else if (!(args(4).is_real_scalar () || args(4).is_real_matrix ()))
1632 { 1631 {
1633 error ("quadcc: list of singularities (SING) must be a vector of real values"); 1632 error ("quadcc: list of singularities (SING) must be a vector of real values");
1634 return retval; 1633 return retval;
1635 } 1634 }
1636 else 1635 else
1637 { 1636 {
1638 nivals = 1 + args(4).length (); 1637 nivals = 1 + args(4).numel ();
1639 if (nivals > cquad_heapsize) 1638 }
1640 { 1639
1641 error ("quadcc: maximum number of singular points is limited to %i", 1640 int cquad_heapsize = (nivals >= min_cquad_heapsize ? nivals + 1
1642 cquad_heapsize-1); 1641 : min_cquad_heapsize);
1643 return retval; 1642 heap = new int [cquad_heapsize];
1644 } 1643 ivals = new cquad_ival [cquad_heapsize];
1644 iivals = new double [cquad_heapsize];
1645
1646 if (nivals == 1)
1647 {
1648 iivals[0] = a;
1649 iivals[1] = b;
1650 }
1651 else
1652 {
1653 // Intervals around singularities
1645 sing = args(4).array_value ().fortran_vec (); 1654 sing = args(4).array_value ().fortran_vec ();
1646 iivals[0] = a; 1655 iivals[0] = a;
1647 for (i = 0; i < nivals - 2; i++) 1656 for (i = 0; i < nivals - 1; i++)
1648 iivals[i + 1] = sing[i]; 1657 iivals[i + 1] = sing[i];
1649 iivals[nivals] = b; 1658 iivals[nivals] = b;
1650 } 1659 }
1651 1660
1652 /* If a or b are +/-Inf, transform the integral. */ 1661 /* If a or b are +/-Inf, transform the integral. */
1653 if (xisinf (a) || xisinf (b)) 1662 if (xisinf (a) || xisinf (b))
1654 { 1663 {
1655 wrap = true; 1664 wrap = true;
1656 for (i = 0; i <= nivals; i++) 1665 for (i = 0; i < nivals + 1; i++)
1657 if (xisinf (iivals[i])) 1666 if (xisinf (iivals[i]))
1658 iivals[i] = gnulib::copysign (1.0, iivals[i]); 1667 iivals[i] = gnulib::copysign (1.0, iivals[i]);
1659 else 1668 else
1660 iivals[i] = 2.0 * atan (iivals[i]) / M_PI; 1669 iivals[i] = 2.0 * atan (iivals[i]) / M_PI;
1661 } 1670 }
1662 1671
1663 1672
1664 /* Initialize the heaps. */ 1673 /* Initialize the heaps. */
1665 for (i = 0; i < cquad_heapsize; i++) 1674 for (i = 0; i < cquad_heapsize; i++)
1666 heap[i] = i; 1675 heap[i] = i;
1667
1668 1676
1669 /* Create the first interval(s). */ 1677 /* Create the first interval(s). */
1670 igral = 0.0; 1678 igral = 0.0;
1671 err = 0.0; 1679 err = 0.0;
1672 for (j = 0; j < nivals; j++) 1680 for (j = 0; j < nivals; j++)
1679 nnans = 0; 1687 nnans = 0;
1680 ColumnVector ex (33); 1688 ColumnVector ex (33);
1681 if (wrap) 1689 if (wrap)
1682 { 1690 {
1683 for (i = 0; i <= n[3]; i++) 1691 for (i = 0; i <= n[3]; i++)
1684 ex (i) = tan (M_PI / 2 * (m + xi[i] * h)); 1692 ex(i) = tan (M_PI / 2 * (m + xi[i] * h));
1685 } 1693 }
1686 else 1694 else
1687 { 1695 {
1688 for (i = 0; i <= n[3]; i++) 1696 for (i = 0; i <= n[3]; i++)
1689 ex (i) = m + xi[i] * h; 1697 ex(i) = m + xi[i] * h;
1690 } 1698 }
1691 fargs(0) = ex; 1699 fargs(0) = ex;
1692 fvals = feval (fcn, fargs, 1); 1700 fvals = feval (fcn, fargs, 1);
1693 if (fvals.length () != 1 || !fvals(0).is_real_matrix ()) 1701 if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())
1694 { 1702 {
1695 error ("quadcc: integrand F must return a single, real-valued vector"); 1703 error ("quadcc: integrand F must return a single, real-valued vector");
1696 return retval; 1704 return retval;
1697 } 1705 }
1698 Matrix effex = fvals(0).matrix_value (); 1706 Matrix effex = fvals(0).matrix_value ();
1701 error ("quadcc: integrand F must return a single, real-valued vector of the same size as the input"); 1709 error ("quadcc: integrand F must return a single, real-valued vector of the same size as the input");
1702 return retval; 1710 return retval;
1703 } 1711 }
1704 for (i = 0; i <= n[3]; i++) 1712 for (i = 0; i <= n[3]; i++)
1705 { 1713 {
1706 iv->fx[i] = effex (i); 1714 iv->fx[i] = effex(i);
1707 if (wrap) 1715 if (wrap)
1708 { 1716 {
1709 xw = ex(i); 1717 xw = ex(i);
1710 iv->fx[i] *= (1.0 + xw * xw) * M_PI / 2; 1718 iv->fx[i] *= (1.0 + xw * xw) * M_PI / 2;
1711 } 1719 }
1712 neval++; 1720 neval++;
1713 if (!xfinite (iv->fx[i])) 1721 if (! xfinite (iv->fx[i]))
1714 { 1722 {
1715 nans[nnans++] = i; 1723 nans[nnans++] = i;
1716 iv->fx[i] = 0.0; 1724 iv->fx[i] = 0.0;
1717 } 1725 }
1718 } 1726 }
1780 /* Put our finger on the interval with the largest error. */ 1788 /* Put our finger on the interval with the largest error. */
1781 iv = &(ivals[heap[0]]); 1789 iv = &(ivals[heap[0]]);
1782 m = (iv->a + iv->b) / 2; 1790 m = (iv->a + iv->b) / 2;
1783 h = (iv->b - iv->a) / 2; 1791 h = (iv->b - iv->a) / 2;
1784 1792
1785 /* printf 1793 #if (DEBUG_QUADCC)
1794 printf
1786 ("quadcc: processing ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n", 1795 ("quadcc: processing ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n",
1787 heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, iv->depth); 1796 heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, iv->depth);
1788 */ 1797 #endif
1798
1789 /* Should we try to increase the degree? */ 1799 /* Should we try to increase the degree? */
1790 if (iv->depth < 3) 1800 if (iv->depth < 3)
1791 { 1801 {
1792 1802
1793 /* Keep tabs on some variables. */ 1803 /* Keep tabs on some variables. */
1797 { 1807 {
1798 ColumnVector ex (n[d] / 2); 1808 ColumnVector ex (n[d] / 2);
1799 if (wrap) 1809 if (wrap)
1800 { 1810 {
1801 for (i = 0; i < n[d] / 2; i++) 1811 for (i = 0; i < n[d] / 2; i++)
1802 ex (i) = 1812 ex(i) = tan (M_PI / 2 * (m + xi[(2 * i + 1) * skip[d]] * h));
1803 tan (M_PI / 2 * (m + xi[(2 * i + 1) * skip[d]] * h));
1804 } 1813 }
1805 else 1814 else
1806 { 1815 {
1807 for (i = 0; i < n[d] / 2; i++) 1816 for (i = 0; i < n[d] / 2; i++)
1808 ex (i) = m + xi[(2 * i + 1) * skip[d]] * h; 1817 ex(i) = m + xi[(2 * i + 1) * skip[d]] * h;
1809 } 1818 }
1810 fargs(0) = ex; 1819 fargs(0) = ex;
1811 fvals = feval (fcn, fargs, 1); 1820 fvals = feval (fcn, fargs, 1);
1812 if (fvals.length () != 1 || !fvals(0).is_real_matrix ()) 1821 if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())
1813 { 1822 {
1814 error ("quadcc: integrand F must return a single, real-valued vector"); 1823 error ("quadcc: integrand F must return a single, real-valued vector");
1815 return retval; 1824 return retval;
1816 } 1825 }
1817 Matrix effex = fvals(0).matrix_value (); 1826 Matrix effex = fvals(0).matrix_value ();
1822 } 1831 }
1823 neval += effex.length (); 1832 neval += effex.length ();
1824 for (i = 0; i < n[d] / 2; i++) 1833 for (i = 0; i < n[d] / 2; i++)
1825 { 1834 {
1826 j = (2 * i + 1) * skip[d]; 1835 j = (2 * i + 1) * skip[d];
1827 iv->fx[j] = effex (i); 1836 iv->fx[j] = effex(i);
1828 if (wrap) 1837 if (wrap)
1829 { 1838 {
1830 xw = ex(i); 1839 xw = ex(i);
1831 iv->fx[j] *= (1.0 + xw * xw) * M_PI / 2; 1840 iv->fx[j] *= (1.0 + xw * xw) * M_PI / 2;
1832 } 1841 }
1833 } 1842 }
1834 } 1843 }
1835 nnans = 0; 1844 nnans = 0;
1836 for (i = 0; i <= 32; i += skip[d]) 1845 for (i = 0; i <= 32; i += skip[d])
1837 { 1846 {
1838 if (!xfinite (iv->fx[i])) 1847 if (! xfinite (iv->fx[i]))
1839 { 1848 {
1840 nans[nnans++] = i; 1849 nans[nnans++] = i;
1841 iv->fx[i] = 0.0; 1850 iv->fx[i] = 0.0;
1842 } 1851 }
1843 } 1852 }
1886 if ((m + h * xi[0]) >= (m + h * xi[1]) 1895 if ((m + h * xi[0]) >= (m + h * xi[1])
1887 || (m + h * xi[31]) >= (m + h * xi[32]) 1896 || (m + h * xi[31]) >= (m + h * xi[32])
1888 || iv->err < fabs (iv->igral) * std::numeric_limits<double>::epsilon () * 10) 1897 || iv->err < fabs (iv->igral) * std::numeric_limits<double>::epsilon () * 10)
1889 { 1898 {
1890 1899
1891 /* printf 1900 #if (DEBUG_QUADCC)
1901 printf
1892 ("quadcc: dropping ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n", 1902 ("quadcc: dropping ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n",
1893 heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, 1903 heap[0], nivals, iv->a, iv->b, iv->igral, iv->err,
1894 iv->depth); 1904 iv->depth);
1895 */ 1905 #endif
1906
1896 /* Keep this interval's contribution */ 1907 /* Keep this interval's contribution */
1897 err_final += iv->err; 1908 err_final += iv->err;
1898 igral_final += iv->igral; 1909 igral_final += iv->igral;
1899 /* Swap with the last element on the heap */ 1910 /* Swap with the last element on the heap */
1900 t = heap[nivals - 1]; 1911 t = heap[nivals - 1];
1903 nivals--; 1914 nivals--;
1904 /* Fix up the heap */ 1915 /* Fix up the heap */
1905 i = 0; 1916 i = 0;
1906 while (2 * i + 1 < nivals) 1917 while (2 * i + 1 < nivals)
1907 { 1918 {
1908
1909 /* Get the kids */ 1919 /* Get the kids */
1910 j = 2 * i + 1; 1920 j = 2 * i + 1;
1911 /* If the j+1st entry exists and is larger than the jth, 1921 /* If the j+1st entry exists and is larger than the jth,
1912 use it instead. */ 1922 use it instead. */
1913 if (j + 1 < nivals 1923 if (j + 1 < nivals
1946 { 1956 {
1947 ColumnVector ex (n[0] - 1); 1957 ColumnVector ex (n[0] - 1);
1948 if (wrap) 1958 if (wrap)
1949 { 1959 {
1950 for (i = 0; i < n[0] - 1; i++) 1960 for (i = 0; i < n[0] - 1; i++)
1951 ex (i) = tan (M_PI / 2 * (ml + xi[(i + 1) * skip[0]] * hl)); 1961 ex(i) = tan (M_PI / 2 * (ml + xi[(i + 1) * skip[0]] * hl));
1952 } 1962 }
1953 else 1963 else
1954 { 1964 {
1955 for (i = 0; i < n[0] - 1; i++) 1965 for (i = 0; i < n[0] - 1; i++)
1956 ex (i) = ml + xi[(i + 1) * skip[0]] * hl; 1966 ex(i) = ml + xi[(i + 1) * skip[0]] * hl;
1957 } 1967 }
1958 fargs(0) = ex; 1968 fargs(0) = ex;
1959 fvals = feval (fcn, fargs, 1); 1969 fvals = feval (fcn, fargs, 1);
1960 if (fvals.length () != 1 || !fvals(0).is_real_matrix ()) 1970 if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())
1961 { 1971 {
1962 error ("quadcc: integrand F must return a single, real-valued vector"); 1972 error ("quadcc: integrand F must return a single, real-valued vector");
1963 return retval; 1973 return retval;
1964 } 1974 }
1965 Matrix effex = fvals(0).matrix_value (); 1975 Matrix effex = fvals(0).matrix_value ();
1970 } 1980 }
1971 neval += effex.length (); 1981 neval += effex.length ();
1972 for (i = 0; i < n[0] - 1; i++) 1982 for (i = 0; i < n[0] - 1; i++)
1973 { 1983 {
1974 j = (i + 1) * skip[0]; 1984 j = (i + 1) * skip[0];
1975 ivl->fx[j] = effex (i); 1985 ivl->fx[j] = effex(i);
1976 if (wrap) 1986 if (wrap)
1977 { 1987 {
1978 xw = ex(i); 1988 xw = ex(i);
1979 ivl->fx[j] *= (1.0 + xw * xw) * M_PI / 2; 1989 ivl->fx[j] *= (1.0 + xw * xw) * M_PI / 2;
1980 } 1990 }
1981 } 1991 }
1982 } 1992 }
1983 nnans = 0; 1993 nnans = 0;
1984 for (i = 0; i <= 32; i += skip[0]) 1994 for (i = 0; i <= 32; i += skip[0])
1985 { 1995 {
1986 if (!xfinite (ivl->fx[i])) 1996 if (! xfinite (ivl->fx[i]))
1987 { 1997 {
1988 nans[nnans++] = i; 1998 nans[nnans++] = i;
1989 ivl->fx[i] = 0.0; 1999 ivl->fx[i] = 0.0;
1990 } 2000 }
1991 } 2001 }
2042 { 2052 {
2043 ColumnVector ex (n[0] - 1); 2053 ColumnVector ex (n[0] - 1);
2044 if (wrap) 2054 if (wrap)
2045 { 2055 {
2046 for (i = 0; i < n[0] - 1; i++) 2056 for (i = 0; i < n[0] - 1; i++)
2047 ex (i) = tan (M_PI / 2 * (mr + xi[(i + 1) * skip[0]] * hr)); 2057 ex(i) = tan (M_PI / 2 * (mr + xi[(i + 1) * skip[0]] * hr));
2048 } 2058 }
2049 else 2059 else
2050 { 2060 {
2051 for (i = 0; i < n[0] - 1; i++) 2061 for (i = 0; i < n[0] - 1; i++)
2052 ex (i) = mr + xi[(i + 1) * skip[0]] * hr; 2062 ex(i) = mr + xi[(i + 1) * skip[0]] * hr;
2053 } 2063 }
2054 fargs(0) = ex; 2064 fargs(0) = ex;
2055 fvals = feval (fcn, fargs, 1); 2065 fvals = feval (fcn, fargs, 1);
2056 if (fvals.length () != 1 || !fvals(0).is_real_matrix ()) 2066 if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())
2057 { 2067 {
2058 error ("quadcc: integrand F must return a single, real-valued vector"); 2068 error ("quadcc: integrand F must return a single, real-valued vector");
2059 return retval; 2069 return retval;
2060 } 2070 }
2061 Matrix effex = fvals(0).matrix_value (); 2071 Matrix effex = fvals(0).matrix_value ();
2066 } 2076 }
2067 neval += effex.length (); 2077 neval += effex.length ();
2068 for (i = 0; i < n[0] - 1; i++) 2078 for (i = 0; i < n[0] - 1; i++)
2069 { 2079 {
2070 j = (i + 1) * skip[0]; 2080 j = (i + 1) * skip[0];
2071 ivr->fx[j] = effex (i); 2081 ivr->fx[j] = effex(i);
2072 if (wrap) 2082 if (wrap)
2073 { 2083 {
2074 xw = ex(i); 2084 xw = ex(i);
2075 ivr->fx[j] *= (1.0 + xw * xw) * M_PI / 2; 2085 ivr->fx[j] *= (1.0 + xw * xw) * M_PI / 2;
2076 } 2086 }
2077 } 2087 }
2078 } 2088 }
2079 nnans = 0; 2089 nnans = 0;
2080 for (i = 0; i <= 32; i += skip[0]) 2090 for (i = 0; i <= 32; i += skip[0])
2081 { 2091 {
2082 if (!xfinite (ivr->fx[i])) 2092 if (! xfinite (ivr->fx[i]))
2083 { 2093 {
2084 nans[nnans++] = i; 2094 nans[nnans++] = i;
2085 ivr->fx[i] = 0.0; 2095 ivr->fx[i] = 0.0;
2086 } 2096 }
2087 } 2097 }
2193 } 2203 }
2194 } 2204 }
2195 2205
2196 } 2206 }
2197 2207
2198 /* If the heap is about to overflow, remove the last two 2208 /* If the heap is about to overflow, remove the last two intervals. */
2199 intervals. */
2200 while (nivals > cquad_heapsize - 2) 2209 while (nivals > cquad_heapsize - 2)
2201 { 2210 {
2202 iv = &(ivals[heap[nivals - 1]]); 2211 iv = &(ivals[heap[nivals - 1]]);
2203 /* printf 2212 #if (DEBUG_QUADCC)
2213 printf
2204 ("quadcc: dropping ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n", 2214 ("quadcc: dropping ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n",
2205 heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, 2215 heap[0], nivals, iv->a, iv->b, iv->igral, iv->err,
2206 iv->depth); 2216 iv->depth);
2207 */ 2217 #endif
2208 err_final += iv->err; 2218 err_final += iv->err;
2209 igral_final += iv->igral; 2219 igral_final += iv->igral;
2210 nivals--; 2220 nivals--;
2211 } 2221 }
2212 2222
2220 } 2230 }
2221 2231
2222 } 2232 }
2223 2233
2224 /* Dump the contents of the heap. */ 2234 /* Dump the contents of the heap. */
2225 /* for (i = 0; i < nivals; i++) 2235 #if (DEBUG_QUADCC)
2236 for (i = 0; i < nivals; i++)
2226 { 2237 {
2227 iv = &(ivals[heap[i]]); 2238 iv = &(ivals[heap[i]]);
2228 printf 2239 printf
2229 ("quadcc: ival %i (%i) with [%e,%e], int=%e, err=%e, depth=%i, rdepth=%i, ndiv=%i\n", 2240 ("quadcc: ival %i (%i) with [%e,%e], int=%e, err=%e, depth=%i, rdepth=%i, ndiv=%i\n",
2230 i, heap[i], iv->a, iv->b, iv->igral, iv->err, iv->depth, 2241 i, heap[i], iv->a, iv->b, iv->igral, iv->err, iv->depth,
2231 iv->rdepth, iv->ndiv); 2242 iv->rdepth, iv->ndiv);
2232 } 2243 }
2233 */ 2244 #endif
2245
2246 /* Clean up heap memory */
2247 delete [] heap;
2248 delete [] ivals;
2249 delete [] iivals;
2250
2234 /* Clean up and present the results. */ 2251 /* Clean up and present the results. */
2235 if (nargout > 2) 2252 if (nargout > 2)
2236 retval(2) = neval; 2253 retval(2) = neval;
2237 if (nargout > 1) 2254 if (nargout > 1)
2238 retval(1) = err; 2255 retval(1) = err;
2263 %! y(idx < 1e-10) = NaN; 2280 %! y(idx < 1e-10) = NaN;
2264 %!endfunction 2281 %!endfunction
2265 2282
2266 %!test 2283 %!test
2267 %! [q, err, npoints] = quadcc ("__nansin", -pi, pi); 2284 %! [q, err, npoints] = quadcc ("__nansin", -pi, pi);
2268 %! assert (q, 0, eps); 2285 %! assert (q, 0, 1e-6);
2269 %! assert (err, 0, 15*eps); 2286 %! assert (err, 0, 15*eps);
2270 2287
2271 %% Test input validation 2288 %% Test input validation
2272 %!error (quadcc ()) 2289 %!error (quadcc ())
2273 %!error (quadcc (@sin)) 2290 %!error (quadcc (@sin))