// 使用自适应方法产生 y = f(x) 的图象 guide
guide plot(real f(real), real min, real max, int nplotpoints=10, int maxrec=7)
{
    if (nplotpoints < 2)
	nplotpoints = 2;
    // 描初始的 nplotpoints 个点，并估计函数变化幅度
    pair[] fpoints;
    real fmax = -infinity, fmin = infinity;
    for (int i = 0; i <= nplotpoints; ++i) {
	real x = min + i/nplotpoints * (max-min);
	pair z = (x, f(x));
	fmax = max(fmax, z.y);
	fmin = min(fmin, z.y);
	fpoints.push(z);
    }
    // 定义辅助的递归函数：在规定的递归次数之内，在两个样本点之间描新点
    // 误差 fuzz 达到函数变化幅度估计值的 1/500 为止
    // 这个误差值在一般屏幕显示上只有一两个像素
    real fuzz = max(0.002(fmax-fmin), realEpsilon);
    guide helper(int nrec, pair a, pair b)
    {
	if (nrec == 0)
	    return b;
	pair mid = (a+b)/2;
	pair z = (mid.x, f(mid.x));
	if (abs(z.y-mid.y) < fuzz)
	    return z -- b;
	else
	    return helper(nrec-1, a, z) -- helper(nrec-1, z, b);
    }
    // 递归构造 guide
    guide g = fpoints[0];
    for (int i = 0; i < nplotpoints; ++i)
	g = g -- helper(maxrec, fpoints[i], fpoints[i+1]);
    return g;
}



//////////////////////////////////////////

real f(real x) {return 2sin(x^3);}
real min = -5.0, max = 5.0;

// 用自适应方法绘制函数 f(x)
guide g = scale(1cm)*plot(f, min, max);
draw(g, red+1pt);
for (int i = 0; i < size(g); ++i) {
    draw(point(g,i), blue+2pt);
}
write(size(g));


// 用 graph 模块的默认方法（均匀取点）绘制函数 f(x)
import graph;
guide h = shift(-5cm*I)*scale(1cm)*graph(f, min, max);
draw(h, orange+1pt);
for (int i = 0; i < size(h); ++i) {
    draw(point(h,i), blue+2pt);
}
write(size(h));
