#line 1074 "/home/travis/build/felix-lang/felix/src/packages/arrays.fdoc"
  Unbounded sparse psuedo-array sarray.
  This data type is not a real array because it has no bounds
  and therefore cannot support iteration.
  open class Sarray
    open Judy;
    private struct sarray_ctl[T] { a: darray[T]; j:JLArray; free:J1Array; dflt:T; };
    Type of a sarray.
    type sarray[T] = new &sarray_ctl[T];
    Construct an infinite sarray with all values set to the given default.
    ctor[T] sarray[T] (dflt:T) => _make_sarray[T]$ new sarray_ctl[T] (darray[T](), JLArray(), J1Array(),dflt);
    Get the value at the given position.
    fun get[T] (a:sarray[T], i:size) : T = {
       var pk: &word;
       var e: JError_t;
       JudyLGet ( (_repr_ a)*.j, i.word, &e, &pk);
       var r = if C_hack::isNULL pk then (_repr_ a)*.dflt else (_repr_ a)*.a.(size(*pk));
       return r;
    Set the given value at the given position.
    proc set[T] (a:sarray[T], i:size, v:T) {
      var pk: &word;
      var e: JError_t;
      JudyLGet ( (_repr_ a)*.j, i.word, &e, &pk);    // see if already in array
      if C_hack::isNULL pk do
        var idx: word = word 0;
        var b: int;
        Judy1First((_repr_ a)*.free,&idx,&e,&b);     // try to find a free slot
        if b == 0 do                                // none?
          idx = word (len (_repr_ a)*.a);
          push_back ((_repr_ a)*.a, v);              // then push onto array end
          Judy1Unset((_repr_ a)*.free,idx,&e,&b);     // remove free slot from free set
          set ((_repr_ a)*.a,size idx,v);            // store value
        JudyLIns ( (_repr_ a)*.j,i.word, &e, &pk);    // add new index to j mapping
        pk <- idx;
        set ((_repr_ a)*.a, size (*pk), v);
    Replace the value at a given position with the default.
    proc del[T] (a:sarray[T], i:size) {
      var pk: &word;
      var e: JError_t;
      JudyLGet ( (_repr_ a)*.j, i.word, &e, &pk);     // see if already in array
      if not C_hack::isNULL pk do                    // if it is
        var b:int;
        Judy1Set ((_repr_ a)*.free, i.word, &e, &b);  // add slot to free set
        set ( (_repr_ a)*.a, pk*.size, (_repr_ a)*.dflt); // replace old value with default
    Pack a sparse array.
    This is an optimisation with no semantics.
    Reorganises the sarray to reduce memory use and optimise lookup.
      // Make a new varray with max number
    // of elements in the j mapping, then fill it in order
    // of the j mapping, replacing the j value with the new index
    // finally replace the original darray with a new one made
    // from the constructed varray: this is packed and in sequence
    proc pack[T] (a:sarray[T]) {
      r := _repr_ a;
      var e: JError_t;
      var n: word;
      JudyLCount (r*.j, word 0, word (-1ul), &e, &n);
      var x = varray[T] n.size;
      var index = word 0;
      var i = 0ul;         // slot index for new array
      var slot : &word;
      JudyLFirst(r*.j, &index, &e, &slot);
      while not isNULL slot do
        push_back (x, r*.a.((*slot).size));
        slot <- i.word; ++i;
        JudyLNext(r*.j, &index, &e, &slot);
      var m : word;
      //println$ m.ulong.str + " bytes freed --> counted "+n.ulong.str;
      r.a <- darray x;