## rw-vector-slice.pkg
## Author: Matthias Blume (blume@tti-c.org)
# Compiled by:
#
src/lib/std/src/standard-core.sublib### "Mathematics, rightly viewed, possesses not only truth,
### but supreme beauty - a beauty cold and austere, like
### that of sculpture, without appeal to any part of our
### weaker nature, without the gorgeous trappings of painting
### or music, yet sublimely pure, and capable of a stern
### perfection such as only the greatest art can show."
###
### -- Bertrand Russell.
stipulate
package rwv = rw_vector; # rw_vector is from
src/lib/std/src/rw-vector.pkgherein
package rw_vector_slice
: (weak) Rw_Vector_Slice # Rw_Vector_Slice is from
src/lib/std/src/rw-vector-slice.api {
# inline_t is from
src/lib/core/init/built-in.pkg Slice(X) = SLICE { base: rwv::Rw_Vector(X),
start: Int,
stop: Int
};
# Fast add/subtract avoiding
# the overflow test:
#
infix my --- +++ ;
#
fun x --- y = inline_t::tu::copyt_tagged_int (inline_t::tu::copyf_tagged_int x - inline_t::tu::copyf_tagged_int y);
fun x +++ y = inline_t::tu::copyt_tagged_int (inline_t::tu::copyf_tagged_int x + inline_t::tu::copyf_tagged_int y);
unsafe_get = inline_t::poly_rw_vector::get;
unsafe_set = inline_t::poly_rw_vector::set;
ro_unsafe_get = inline_t::poly_vector::get;
rw_length = inline_t::poly_rw_vector::length;
ro_length = inline_t::poly_vector::length;
fun length (SLICE { start, stop, ... } )
=
stop --- start;
fun get (SLICE { base, start, stop }, i)
=
{ i' = start + i;
#
if (i' < start or i' >= stop) raise exception INDEX_OUT_OF_BOUNDS; fi;
#
unsafe_get (base, i');
};
fun set (SLICE { base, start, stop }, i, x)
=
{ i' = start + i;
#
if (i' < start or i' >= stop) raise exception INDEX_OUT_OF_BOUNDS; fi;
#
unsafe_set (base, i', x);
};
fun make_full_slice arr
=
SLICE { base => arr, start => 0, stop => rw_length arr };
fun make_slice (arr, start, olen)
=
{
al = rw_length arr;
SLICE { base => arr,
#
start => if (start < 0 or al < start) raise exception INDEX_OUT_OF_BOUNDS;
else start;
fi,
stop => case olen
#
NULL => al;
THE len
=>
{ stop = start +++ len;
#
if (stop < start
or al < stop
) raise exception INDEX_OUT_OF_BOUNDS;
else stop; fi;
};
esac
};
};
fun make_subslice (SLICE { base, start, stop }, i, olen)
=
{
start' = if (i < 0 or stop < i) raise exception INDEX_OUT_OF_BOUNDS;
else start +++ i;
fi;
stop' =
case olen
#
NULL => stop;
#
THE len =>
{ stop' = start' +++ len;
#
if (stop' < start' or stop < stop')
#
raise exception INDEX_OUT_OF_BOUNDS;
else
stop';
fi;
};
esac;
SLICE { base, start => start', stop => stop' };
};
fun burst_slice (SLICE { base, start, stop } )
=
(base, start, stop --- start);
fun copy { src => SLICE { base, start, stop }, dst, di }
=
{ sl = stop --- start;
de = sl + di;
fun copy_dn (s, d)
=
if (s >= start)
#
unsafe_set (dst, d, unsafe_get (base, s));
copy_dn (s --- 1, d --- 1);
fi;
fun copy_up (s, d)
=
if (s < stop)
#
unsafe_set (dst, d, unsafe_get (base, s));
copy_up (s +++ 1, d +++ 1);
fi;
if (di < 0 or de > rw_length dst) raise exception INDEX_OUT_OF_BOUNDS;
elif (di >= start) copy_dn (stop --- 1, de --- 1);
else copy_up (start, di);
fi;
};
fun copy_vec { src => vsl, dst, di }
=
{ (vector_slice::burst_slice vsl)
->
(base, start, vlen);
de = di + vlen;
fun copy_up (s, d)
=
if (d < de)
#
unsafe_set (dst, d, ro_unsafe_get (base, s));
copy_up (s +++ 1, d +++ 1);
fi;
if (di < 0 or de > rw_length dst) raise exception INDEX_OUT_OF_BOUNDS;
else copy_up (start, di); # Assume vector and rw_vector are disjoint.
fi;
};
fun is_empty (SLICE { start, stop, ... } )
=
start == stop;
fun get_item (SLICE { base, start, stop } )
=
if (start >= stop)
#
NULL;
else
THE (unsafe_get (base, start), SLICE { base, start => start +++ 1, stop } );
fi;
fun keyed_apply f (SLICE { base, start, stop } )
=
apply start
where
fun apply i
=
if (i < stop)
#
f (i --- start, unsafe_get (base, i));
apply (i +++ 1);
fi;
end;
fun apply f (SLICE { base, start, stop } )
=
apply start
where
fun apply i
=
if (i < stop)
#
f (unsafe_get (base, i));
apply (i +++ 1);
fi;
end;
fun keyed_map_in_place f (SLICE { base, start, stop } )
=
mdf start
where
fun mdf i
=
if (i < stop)
#
unsafe_set (base, i, f (i --- start, unsafe_get (base, i)));
mdf (i +++ 1);
fi;
end;
fun map_in_place f (SLICE { base, start, stop } )
=
mdf start
where
fun mdf i
=
if (i < stop)
#
unsafe_set (base, i, f (unsafe_get (base, i)));
mdf (i +++ 1);
fi;
end;
fun keyed_fold_forward f init (SLICE { base, start, stop } )
=
fold (start, init)
where
fun fold (i, a)
=
if (i >= stop) a;
else fold (i +++ 1, f (i --- start, unsafe_get (base, i), a));
fi;
end;
fun fold_forward f init (SLICE { base, start, stop } )
=
fold (start, init)
where
fun fold (i, a)
=
if (i >= stop) a;
else fold (i +++ 1, f (unsafe_get (base, i), a));
fi;
end;
fun keyed_fold_backward f init (SLICE { base, start, stop } )
=
fold (stop --- 1, init)
where
fun fold (i, a)
=
if (i < start) a;
else fold (i --- 1, f (i --- start, unsafe_get (base, i), a));
fi;
end;
fun fold_backward f init (SLICE { base, start, stop } )
=
fold (stop --- 1, init)
where
fun fold (i, a)
=
if (i < start) a;
else fold (i --- 1, f (unsafe_get (base, i), a));
fi;
end;
fun keyed_find p (SLICE { base, start, stop } )
=
fnd start
where
fun fnd i
=
if (i >= stop)
#
NULL;
else
x = unsafe_get (base, i);
#
if (p (i, x)) THE (i --- start, x);
else fnd (i +++ 1);
fi;
fi;
end;
fun find p (SLICE { base, start, stop } )
=
fnd start
where
fun fnd i
=
if (i >= stop)
#
NULL;
else
x = unsafe_get (base, i);
#
if (p x) THE x;
else fnd (i +++ 1);
fi;
fi;
end;
fun exists p (SLICE { base, start, stop } )
=
ex start
where
fun ex i
=
i < stop
and
( p (unsafe_get (base, i))
or
ex (i +++ 1)
);
end;
fun all p (SLICE { base, start, stop } )
=
al start
where
fun al i
=
i >= stop
or
( p (unsafe_get (base, i))
and
al (i +++ 1)
);
end;
fun compare_sequences c (SLICE { base => b1, start => s1, stop => e1 },
SLICE { base => b2, start => s2, stop => e2 } )
=
col (s1, s2)
where
fun col (i1, i2)
=
if (i1 >= e1)
#
if (i2 >= e2) EQUAL;
else LESS;
fi;
else
if (i2 >= e2) GREATER;
else
case (c (unsafe_get (b1, i1), unsafe_get (b2, i2)))
#
EQUAL => col (i1 +++ 1, i2 +++ 2);
unequal => unequal;
esac;
fi;
fi;
end;
# XXX BUGGO FIXME: this is inefficient (going through intermediate list)
#
fun to_vector sl
=
case (length sl)
#
0 => runtime::zero_length_vector__global;
#
len => runtime::asm::make_typeagnostic_ro_vector (len, fold_backward (!) [] sl);
esac;
};
end;