ALInterp::ALInterp(const double _q, const Vector& x, const Vector& y)
: arg(x.q_no_elems()), val(y.q_no_elems()), q(_q)
{
assure( y.q_no_elems() > 1,
"Vector y (function values) must have at least 2 points");
are_compatible(x,y);
class index_permutation
{
struct El { int x_ind; float x_to_q; }; // x_to_q = |x[x_ind]-q|
El * permutation;
const int n;
static int comparison_func(const void * ip, const void * jp)
{ return fsign(((const El*)ip)->x_to_q - ((const El*)jp)->x_to_q); }
public:
index_permutation(const double q, const Vector& x) :
permutation(new El[x.q_no_elems()]), n(x.q_no_elems())
{
register El * pp = permutation;
for(register int i=x.q_lwb(); i<=x.q_upb(); i++,pp++)
pp->x_ind = i, pp->x_to_q = fabs(q-x(i));
qsort(permutation,n,sizeof(permutation[0]),comparison_func);
}
~index_permutation(void) { delete permutation; }
// Apply the permutation to x to get arg
// and to y to get val
void apply(Vector& arg, Vector& val, const Vector& x, const Vector& y)
{
register const El* pp = permutation;
for(register int i=arg.q_lwb(); i<=arg.q_upb(); i++,pp++)
arg(i) = x(pp->x_ind), val(i) = y(pp->x_ind);
assert(pp==permutation+n);
}
};
index_permutation(q,x).apply(arg,val,x,y);
}
index_permutation
's methods are nested functions
qsort()
Again,
index_permutation
is completely local
More examples to follow: iterators/lazy objects.
I have an even crazier example with double-nested functions!