
prediction_t nonparabolic(C sortedstuff& s, double dely, double T,
				C vector2& restrict_ctr, C vector2& restrict_sz)
/* LOCAL vecpair get_nonparab_dirs(C sortedstuff& s, double dely, vector2 *maybe_dir = 0) */
{
 boom(1100);
 vector2 sum1(0.0, 0.001), sum2(0.0, 0.001), sump(0.0, 0.0);
 N2foldVec up_dir(0.0, 0.001);
 double sw1 = 0.01, sw2 = 0.01;
 int i, saw = 0;

 if(s.n() <= 2)
	return prediction_t();

 /* Accumulate info on steep direction: */
 for(i=1; i<s.n(); i++)	{
	C double w = rank_y(s, i) - rank_r(s, i, s[0].v);
	C double ew = exp(w);
	C vector2 n = normalize(s[i].v - s[0].v);
	assert(finite(n));
	sum1 += n * ew;
	sum2 += n * (1/ew);
	sump += n;	 /* Find out where most exploration was: */
	up_dir += N2fold(n) * w;
	saw += abs(w);
	sw1 += ew;
	sw2 += 1/ew;
	}


 /* Point away from worst points: */
 vector2 updir(up_dir.pos(0));
 /* Aim the steep direction as much as possible away
	from high points, toward low points, and away from points in general: */
 if(dot(updir, sum1)/sw1
		- dot(updir, sum2)/sw2
		+ dot(updir, sump)/(s.n()-1) > 0)
	updir *= -1;
 assert(finite(updir));
 assert(hypot(updir) > 0.00000001);

 C double confidence = saw/(double)(saw + s.n());
 assert(finite(updir));

 vector2 shallow = perp_to(updir);
 /* Aim the shallow direction as much as possible away
	from high points, toward low points, and away from points in general: */
 if(dot(shallow, sum1)/sw1
		- dot(shallow, sum2)/sw2
		+ dot(shallow, sump)/(s.n()-1) > 0)
	shallow *= -1;

 if(maybe_dir)
 	*maybe_dir = sum1 * (-1/sw1);

 {

 /* Now, find out a typical distance in the steep direction:
	how far can you go and still be at low altitude. */
 double sm = 0, smw = 0;
 for(i=1;i<s.n();i++)
	if(s[i].v!=s[0].v && (i==1 || finite(s[i].y)))	{
		double f = sqrt(dely/fabs(s[i].y-s[0].y));
		if(!(f<4))	f = 4;
		if(!(f>0.25))	f = 0.25;
			/* f is sort of an extrapolant to estimate how far you'd
				go until things increase by dely. */
		C double dotp = dot(updir, s[i].v-s[0].v);
		C double w = exp(fabs(dotp)/hypot(s[i].v-s[0].v));
			/* w is a weight; it's big for points nearly along updir. */
		sm += fabs(dotp)*f * w;
		smw += w;
		}
 updir *= smw!=0 ? sm/smw : 0.01;
 }

 {
 /* Now, find out a typical distance in the shallow direction:
	how far can you go and still be at low altitude. */
/* We emphasize the longest distance, relative to the calculation for the
	steep direction. */
 double sm = 0, smw = 0;
 for(i=1;i<s.n();i++)
	if(s[i].v!=s[0].v && (i==1 || finite(s[i].y)))	{
		double f = sqrt(dely/fabs(s[i].y-s[0].y));
		if(!(f<10))	f = 10;
		if(!(f>0.1))	f = 0.1; /* f is sort of an extrapolant to
									estimate how far you'd
									go until things increase by dely. */
		C double dotp = dot(shallow, s[i].v-s[0].v);
		C double w = exp(2*fabs(dotp)/hypot(s[i].v-s[0].v));
			/* w is a weight; it's big for points nearly along shallow. */
		sm += xx(dotp*f) * w;
		smw += w;
		}
 shallow *= smw!=0 ? sqrt(sm/smw) : 0.1;
 }
 BOOM;

 D fprintf(stderr, "\tnonparabolic up direction=(%f,%f), shallow=(%g,%g)\n",
				updir.x0, updir.x1, shallow.x0, shallow.x1);

 /* Swap, if necessary so that directions are rotated less than pi/4: */
 if(fabs(atan(shallow.x1/shallow.x0)) > M_PI/4)	{
	C vector2 tmp = shallow;
	shallow = updir;
	updir = tmp;
	}
 return vecpair(shallow, updir);
}






matrices_t nonlinear_matrix(C sortedstuff& ss, double e)
{
 vector2 sum1(0.0, 0.001), sum2(0.0, 0.001), sump(0.0, 0.0);
 N2foldVec up_dir(0.0, 0.001);
 double sw1 = 0.01, sw2 = 0.01;
 int i, saw = 0;

 if(s.n() <= 2)
	return matrices_t();

 /* Accumulate info on steep direction: */
 for(i=1; i<s.n(); i++)	{
	C double w = rank_y(s, i) - rank_r(s, i, s[0].v);
	C double ew = exp(w);
	C vector2 n = normalize(s[i].v - s[0].v);
	assert(finite(n));
	sum1 += n * ew;
	sum2 += n * (1/ew);
	sump += n;	 /* Find out where most exploration was: */
	up_dir += N2fold(n) * w;
	saw += abs(w);
	sw1 += ew;
	sw2 += 1/ew;
	}

 C double confidence = saw/(double)(saw + s.n());
 vector2 shallow = perp_to(updir);

 double l_steep;
 {
 /* Now, find out a typical distance in the steep direction:
	how far can you go and still be at low altitude. */
 double sm = 0, smw = 0;
 for(i=1;i<s.n();i++)
	if(s[i].v!=s[0].v && (i==1 || finite(s[i].y)))	{
		double f = sqrt(e/fabs(s[i].y-s[0].y));
		if(!(f<4))	f = 4;
		if(!(f>0.25))	f = 0.25;
			/* f is sort of an extrapolant to estimate how far you'd
				go until things increase by e. */
		C double dotp = dot(updir, s[i].v-s[0].v);
		C double w = exp(fabs(dotp)/hypot(s[i].v-s[0].v));
			/* w is a weight; it's big for points nearly along updir. */
		sm += fabs(dotp)*f * w;
		smw += w;
		}
 l_steep = smw!=0 ? sm/smw : 0.01;
 }

 double l_shallow;
 {
 /* Now, find out a typical distance in the shallow direction:
	how far can you go and still be at low altitude. */
/* We emphasize the longest distance, relative to the calculation for the
	steep direction. */
 double sm = 0, smw = 0;
 for(i=1;i<s.n();i++)
	if(s[i].v!=s[0].v && (i==1 || finite(s[i].y)))	{
		double f = sqrt(e/fabs(s[i].y-s[0].y));
		if(!(f<10))	f = 10;
		if(!(f>0.1))	f = 0.1; /* f is sort of an extrapolant to
									estimate how far you'd
									go until things increase by e. */
		C double dotp = dot(shallow, s[i].v-s[0].v);
		C double w = exp(2*fabs(dotp)/hypot(s[i].v-s[0].v));
			/* w is a weight; it's big for points nearly along shallow. */
		sm += xx(dotp*f) * w;
		smw += w;
		}
 l_shallow = smw!=0 ? sqrt(sm/smw) : 0.1;
 }

 C matrix_t stsh(updir.x0, updir.x1, shallow.x0, shallow.x1);
 matrices_t rv;
 rv.curv = stsh * matrix_t(1/xx(l_steep), 0.0, 0.0, 1/xx(l_shallow))
		* transpose(stsh);
 rv.ctr = s[0].v;
 rv.z = s[0].y;
 rv.err = ???;
 return rv;
}




