6.20.6 Using Sets as Maps

In mathematics, a map is sometimes defined as a set of ordered pairs. In the Asymptote programming language, this definition can be taken literally: a Set_T of Pair_K_V objects can be used as a map from K to V, provided that the equivalence, hash, and comparison functions are configured to look only at the first element of the pair. This can be useful in particular for sorted sets, which have functionality such as atOrAfter and after that is not currently available in the Map API.

We illustrate this approach by implementing a piecewise linear function (in this case we can use the builtin pair type rather than a Pair_K_V).

from collections.btreegeneral(T=pair) access
    SortedSet_T as SortedSet_pair,
    BTreeSet_T as BTreeSet_pair;

bool keysLT(pair a, pair b) { return a.x < b.x; }
bool isnan(pair a) { return isnan(a.y); }

struct PLFunction {
  SortedSet_pair pairs = BTreeSet_pair(
    lessThan=keysLT,
    nullT=(nan,nan),
    isNullT = isnan
  );
  void operator [=] (real x, real y) {
    pairs.push((x,y));
  }
  real operator [] (real x) {
    pair p = (x, 0);
    pair left = pairs.atOrBefore(p);
    pair right = pairs.atOrAfter(p);
    if (isnan(left.y) || isnan(right.y)) {
      return nan;
    }
    if (left.x == right.x) {
      return left.y;
    }
    real t = (x - left.x) / (right.x - left.x);
    return interp(left.y, right.y, t);
  }
}

PLFunction f;
f[0] = 17;
f[1] = 18;
f[2001] = 19;

for (real x : new real[] {-1, 0, 0.5, 1, 2, 2001, 2002}) {
  write('f[' + (string)x + '] = ' + (string)f[x]);
}

outputs

f[-1] = nan
f[0] = 17
f[0.5] = 17.5
f[1] = 18
f[2] = 18.0005
f[2001] = 19
f[2002] = nan