1
0
Fork 0
Libraries for bc and dc.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

805 lines
20 KiB

#!/usr/local/bin/bc -l
### Array.BC - tools for managing arrays
### uses the undocumented pass-by-reference for arrays
max_array_ = 4^8-1
## Conventions used in this library
/*
* All function names begin with the letter 'a'
* All array parameters have a double underscore at the end of the name
since some versions of bc are scope-confused by the undocumented pbr
* The last letter of function names indicates the type of array parameter(s)
expected. These are:
* r = range; A range of array indices will be provided by the caller and
the array type is therefore moot.
* A number before the r suggests different ranges from different
array parameters.
* Range-specifying parameters always follow the array parameter.
* 0 = zero terminated; An element of zero indicates the element after
the last in the array. First element is always index zero
Advantage: Functions have the shortest possible parameter lists.
Disadvantage: Zero can't be used within this type of array.
* b = before; All elements before a given sentinel value are treated as
the array. First element is index zero as for zero terminated.
* u = upto; only used for the aprintu function; deliberately displays the
terminator for arrays that are otherwise zero/sentinel terminated
* l = length provided; Array index zero contains the length of the rest
of the array, putting the first element at index one and the last
at the index specified by the length.
* (no last letter) = Array begins at index zero and the length will be
provided by the function caller
*/
##
## Internal functions ##
# For those functions which use start and end as parameters for a range,
# use POSIX scope to sanitise those variables
define asanerange_() {
auto t;
if(start>end){t=start;start=end;end=t}
if(start<0)start=0;
if(end>max_array_)end=max_array_;
}
define asanerange2_() {
auto start,end;
start=astart;end=aend;.=asanerange_();astart=start;aend=end
start=bstart;end=bend;.=asanerange_();bstart=start;bend=end
}
## Sorting ##
# Sort a subsection of an array
# . from index 'start' to index 'end' inclusive
define asortr(*a__[],start,end) { # non-recursive run-finding mergesort
auto r[],b__[],i,j,k,ri,p,p2,ri_p2,m,mn,mid,subend;
.=asanerange_();
r[ri=0]=start;
i=start;while(i<end){
while(i<end&&a__[j=i]<=a__[++j])i=j
if(i>r[ri])r[++ri]=++i;
while(i<end&&a__[j=i]>a__[++j])i=j
if(i>(k=r[ri])){ # reverse backward runs
j=i;while(j>k){t=a__[j];a__[j--]=a__[k];a__[k++]=t}
r[++ri]=++i;
}
}
r[++ri]=++end;
for(p=1;p<ri;p=p2){
ri_p2=ri-(p2=p+p)
for(m=0;m<=ri_p2;m=mn){
# merge a__[r[m]..r[m+p]-1] with a__[r[m+p]..a[r[m+2p]-1]
i=r[m];mid=j=r[m+p];subend=r[mn=m+p2];k=0
while(i<mid&&j<subend)
if(a__[i]<a__[j]){ b__[k++]=a__[i++]
}else{ b__[k++]=a__[j++]}
while(i<mid )b__[k++]=a__[i++]
while(k)a__[--j]=b__[--k]
}
if(m<ri){
# roll in any outlier
# merge a[r[m-p-p]..a[r[m]-1] with a[r[m]..r[ri]-1]
i=r[m-p2];mid=j=r[m];k=0
while(i<mid&&j<end)
if(a__[i]<a__[j]){b__[k++]=a__[i++]
}else{b__[k++]=a__[j++]}
while(i<mid ) b__[k++]=a__[i++]
while(k)a__[--j]=b__[--k]
r[ri=m]=end
}
}
return 0;
}
define asortr_old(*a__[],start,end) { # plain recursive mergesort
auto os,i,j,k,t,mid,b__[];
if(end==start)return 0;
.=asanerange_();
if(end-start==1){
if(a__[start]>a__[end]){t=a__[start];a__[start]=a__[end];a__[end]=t}
return 0;
}
os=scale;scale=0;mid=(start+end)/2;scale=os
i=start;j=mid+1
if(i<mid).=asortr_old(a__[],start,mid)
if(j<end).=asortr_old(a__[],mid+1,end)
k=0
while(i<=mid&&j<=end)
if(a__[i]<a__[j]){b__[k++]=a__[i++]
}else{b__[k++]=a__[j++]}
while(i<=mid )b__[k++]=a__[i++]
#while( j<=end)b__[k++]=a__[j++]
while(k>0)a__[--j]=b__[--k]
return 0;
}
# Sort all elements of array before zero terminator
define asort0(*a__[]){
auto i;
for(i=0;a__[i];i++){}
.=asortr(a__[],0,i-1)
}
# Sort all elements of array before given terminator, x
define asortb(*a__[],x){
auto i;
for(i=0;a__[i]!=x;i++){}
.=asortr(a__[],0,i-1);
}
# Sort all elements of array with length in [0]
define asortl(*a__[]){
.=asortr(a__[],1,a__[0]);
}
# Sort the first n elements of an array
define asort(*a__[],n) { .=asortr(a__[],0,n-1) }
## Unique values / Run length finding ##
# Store values from a in v & how many times they occur together in a run in r
# e.g. if a=={7,8,8,9,9,6,9}, v <- {7,8,9,6,9} and r <- {1,2,2,1,1}
define arunlengthr(*v__[],*r__[], a__[],start,end) {
auto vri,i,prev;
.=asanerange_();
if(end==start)return 0;
vri=0;prev=v__[vri]=a__[start];r__[vri]=1
for(i=start+1;i<=end;i++)if(a__[i]==prev){
.=r__[vri]++
} else {
r__[++vri]=1; prev=v__[vri]=a__[i]
}
return ++vri
}
define arunlength0(*v__[],*r__[], a__[]) {
auto vri,i,prev;
if(!a__[0])return 0;
vri=0;prev=v__[vri]=a__[0];r__[vri]=1
for(i=1;i<=max_array_&&a__[i];i++)if(a__[i]==prev){
.=r__[vri]++
} else {
r__[++vri]=1; prev=v__[vri]=a__[i]
}
.=vri++
r__[vri]=v__[vri]=0
return vri
}
define arunlengthb(*v__[],*r__[], a__[],x) {
auto vri,i,prev;
if(a__[0]==x)return 0;
vri=0;prev=v__[vri]=a__[0];r__[vri]=1
for(i=1;i<=max_array_&&a__[i]!=x;i++)if(a__[i]==prev){
.=r__[vri]++
} else {
r__[++vri]=1; prev=v__[vri]=a__[i]
}
.=vri++
r__[vri]=v__[vri]=x
return vri
}
define arunlengthl(*v__[],*r__[], a__[]) {
auto vri,i,prev;
if(!a__[0])return 0;
vri=1;prev=v__[vri]=a__[1];r__[vri]=1
for(i=2;i<=max_array_&&a__[i]!=x;i++)if(a__[i]==prev){
.=r__[vri]++
} else {
r__[++vri]=1; prev=v__[vri]=a__[i]
}
return r__[0]=v__[0]=vri
}
define arunlength(*v__[],*r__[], a__[], n) {
return arunlengthr(v__[],r__[], a__[],0,n-1)
}
# Fill v with the unique values from a. Works best on a sorted array.
define auniqr(*v__[], a__[],start,end) {
auto r[];
return arunlengthr(v__[],r[], a__[],start,end)
}
define auniq0(*v__[], a__[]) {
auto r[];
return arunlength0(v__[],r[], a__[])
}
define auniqb(*v__[], a__[],x) {
auto r[];
return arunlengthb(v__[],r[], a__[],x)
}
define auniql(*v__[], a__[]) {
auto r[];
return arunlengthl(v__[],r[], a__[])
}
define auniq(*v__[], a__[],n) {
auto r[];
return arunlengthr(v__[],r[], a__[],0,n-1)
}
## Order reversal ##
# Reverse a subsection of an array
define areverser(*a__[],start,end) {
auto t;
.=asanerange_();
if(end==start)return 0
while(start<end){t=a__[start];a__[start++]=a__[end];a__[end--]=t}
return 0;
}
# Reverse order of all elements of array before given terminator, x
define areverseb(*a__[],x){
auto i;
for(i=0;a__[i]!=x;i++){}
.=areverser(a__[],0,i-1);
}
# Reverse order of all elements of array before zero terminator
define areverse0(*a__[]){
auto i;
for(i=0;a__[i];i++){}
.=areverser(a__[],0,i-1)
}
# Reverse order of all elements of array 1 .. a[0]
define areversel(*a__[]) {
.=areverser(a__[],1,a__[0]);
}
# Reverse the first n elements of an array
define areverse(*a__[],n) { .=areverser(a__[],0,n-1) }
## Copying ##
# Make a__[astart..aend] = b__[bstart..bend]
# . Does not expand a__[] to make room if b__[bstart..bend] is too large!
define acopy2r(*a__[],astart,aend,b__[],bstart,bend){
auto i,j;
.=asanerange2_();
i=astart;j=bstart;while(i<=aend&&j<=bend)a__[i++]=b__[j++]
}
# Make a__[start..end] = b__[start..end]
define acopyr(*a__[],b__[],start,end){
auto i;
.=asanerange_();
for(i=start;i<=end;i++)a__[i]=b__[i]
}
# copy a zero-terminated array; a = b
define acopy0(*a__[],b__[]) {
auto e,i;
for(i=0;i<=max_array_&&e=b__[i];i++)a__[i]=e
if(i<=max_array_)a__[i]=0
}
# copy an x terminated array; a = b
define acopyb(*a__[],b__[],x) {
auto e,i;
for(i=0;i<=max_array_&&(e=b__[i])!=x;i++)a__[i]=e
if(i<=max_array_)a__[i]=x
}
# Copy array whose length is in element [0]
define acopyl(*a__[],b__[]){
.=acopyr(a__[],b__[],0,a__[0])
}
# Copy first 'count' elements of a from b
define acopy(*a__[],b__[],count){
auto i;
if(count<0)count=0;
if(count>max_array_)count=max_array_+1;
for(i=0;i<count;i++)a__[i]=b__[i];return 0
}
## Convert between array types ##
define aconv0fromr(*a__[], b__[],start,end){
auto i,j;
.=asanerange_();
i=0;for(j=start;j<=end;j++)a__[i++]=b__[j]
a__[i]=0
}
define aconvbfromr(*a__[],x,b__[],start,end){
auto i,j;
.=asanerange_();
i=0;for(j=start;j<=end;j++)a__[i++]=b__[j]
a__[i]=x
}
define aconvlfromr(*a__[], b__[],start,end){
auto i,j;
.=asanerange_();
i=1;for(j=start;j<=end;j++)a__[i++]=b__[j]
a__[0]=end-start+1
}
define aconvrfrom0(*a__[],start,end,b__[]){
auto i,j;
.=asanerange_();
j=0;for(i=start;i<=end&&b__[j];i++)a__[i]=b__[j++]
}
define aconvbfrom0(*a__[],x, b__[]){
auto i;
for(i=0;a__[i]=b__[i];i++){}
a__[i]=x
}
define aconvlfrom0(*a__[], b__[]){
auto i,j;
i=1;j=0;while(a__[i++]=b__[j++]){}
a__[0]=j
}
define aconv0fromb(*a__[], b__[],x){
auto i;
for(i=0;(a__[i]=b__[i])!=x;i++){}
a__[i]=0
}
define aconvrfromb(*a__[],start,end,b__[],x){
auto i,j;
.=asanerange_();
j=0;for(i=start;i<=end&&b__[j]!=x;i++)a__[i]=b__[j++]
}
define aconvlfromb(*a__[], b__[],x){
auto i,j;
i=1;j=0;while((a__[i++]=b__[j++])!=x){}
a__[0]=j
}
define aconvrfroml(*a__[],start,end,b__[]){
auto i,j;
.=asanerange_();
j=1;for(i=start;i<=end&&j<=b__[0];i++)a__[i]=b__[j++]
}
define aconv0froml(*a__[], b__[]){
auto i,j;
i=0;j=1;while(j<=b__[0])a__[i++]=b__[j++];
a__[i]=0;
}
define aconvbfroml(*a__[],x, b__[]){
auto i,j;
i=0;j=1;while(j<=b__[0])a__[i++]=b__[j++];
a__[i]=x;
}
## Copy in a small number of elements ##
define aset8(*a__[],start,a,b,c,d,e,f,g,h){
auto b[];
b[0]=a;b[1]=b;b[2]=c;b[3]=d
b[4]=e;b[5]=f;b[6]=g;b[7]=h
.=acopy2r(a__[],start,start+7,b[],0,7)
}
define aset16(*a__[],start,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){
auto b[];
b[0]=a;b[1]=b;b[2]=c;b[3]=d
b[4]=e;b[5]=f;b[6]=g;b[7]=h
b[8]=i;b[9]=j;b[A]=k;b[B]=l
b[C]=m;b[D]=n;b[E]=o;b[F]=p
.=acopy2r(a__[],start,start+F,b[],0,F)
}
## Append one array to another ##
define aappendr(*a__[],aend,b__[],bstart,bend) {
auto i,j;
if(aend>max_array_)aend=max_array_;
if(bstart>bend){j=bstart;bstart=bend;bend=j}
if(bstart<0)bstart=0;
if(bend>max_array_)bend=max_array_;
j=bstart;
for(i=aend+1;i<=max_array_&&j<=bend;i++)a__[i]=b__[j++]
}
define aappend0(*a__[],b__[]) {
auto i,j;
for(i=0;i<=max_array_&&a__[i];i++){}
if(i>max_array_)return 0;
for(j=0;i<=max_array_&&b__[j];j++)a__[i++]=b__[j]
if(i>max_array_)return 0;
a__[i]=0;
}
define aappendb(*a__[],b__[],x) {
auto i,j;
for(i=0;i<=max_array_&&a__[i]!=x;i++){}
if(i>max_array_)return 0;
for(j=0;i<=max_array_&&b__[j]!=x;j++)a__[i++]=b__[j]
if(i>max_array_)return 0;
a__[i]=x;
}
define aappendl(*a__[],b__[]) {
.=aappendr(a__[],a__[0],b__[],1,b__[0])
a__[0]+=b__[0]
}
define aappend(*a__[],aend,b__[],count) {
return aappendr(a__[],aend,b__[],0,count-1)
}
define aappendelem0(*a__[],e) {
auto i;
for(i=0;i<=max_array_&&a__[i];i++){}
if(i>max_array_)return 0;
a__[i++]=e;
if(i>max_array_)return 0;
a__[i]=0;
}
define aappendelemb(*a__[],x,e) {
auto i;
for(i=0;i<=max_array_&&a__[i]!=x;i++){}
if(i>max_array_)return 0;
a__[i++]=e;
if(i>max_array_)return 0;
a__[i]=x;
}
define aappendelem(*a__[],aend,e) {
if(++aend>max_array_)return 0;
a__[aend]=e;return 0
}
define aappendeleml(*a__[],e) {
if(++a__[0]>max_array_){a__[0]=max_array_;return 0}
a__[a__[0]]=e
}
## part a, part b, part c
define aparts3r(*a__[],astart,aend,b__[],bstart,bend,c__[],cstart,cend) {
auto i,j;
.=asanerange2_();
if(cstart>cend){i=cstart;cstart=cend;cend=i}
if(cstart<0)cstart=0;
if(cend>max_array_)cend=max_array_;
i=0;
if(astart>0)for(j=astart;j<aend;j++)if(i++<=max_array_)a__[i]=a__[j];
for(j=bstart;j<bend;j++)if(i++<=max_array_)a__[i]=b__[j];
for(j=cstart;j<cend;j++)if(i++<=max_array_)a__[i]=c__[j];
}
## Insertion of elements and other arrays ##
define ainsertatr(*a__[],astart,aend,pos,b__[],bstart,bend){
auto i;
.=asanerange2_();
if(pos>aend-astart)return aappendr(a__[],aend,b__[],bstart,bend);
if(pos<=0){
.=aappendr(b__[],bend,a__[],astart,aend);
.=acopyr(a__[],b__[],bstart,aend-astart+bend)
return 0;
}
.=aparts3r(a__[],astart,astart+pos-1,b__[],bstart,bend,a__[],astart+pos,aend);
}
define ainsertat0(*a__[],pos,b__[]){
auto i,j,alen,blen;
for(i=0;i<=max_array_&&b__[i];i++){}
blen=i
for(i=0;i<=max_array_&&a__[i];i++){}
alen=i
if(pos>=alen)return aappend0(a__[],b__[]);
if(pos<0)pos=0;
for(--i;i>=pos;i--){
if((j=blen+i)>max_array_)continue;
a__[j]=a__[i]
}
for(i=0;i<blen;i++){
if((j=pos+i)>max_array_)continue;
a__[j]=b__[i]
}
a__[alen+blen]=0
}
define ainsertatb(*a__[],pos,b__[],x){
auto i,j,alen,blen;
for(i=0;i<=max_array_&&b__[i]!=x;i++){}
blen=i
for(i=0;i<=max_array_&&a__[i]!=x;i++){}
alen=i
if(pos>=alen)return aappend0(a__[],b__[]);
if(pos<0)pos=0;
for(--i;i>=pos;i--){
if((j=blen+i)>max_array_)continue;
a__[j]=a__[i]
}
for(i=0;i<blen;i++){
if((j=pos+i)>max_array_)continue;
a__[j]=b__[i]
}
a__[alen+blen]=x
}
define ainsertatl(*a__[],pos,b__[]){
auto i;
if(pos>a__[0])return aappendl(a__[],b__[]);
if(pos<1)pos=1;
for(i=a__[0];i>=pos;i--){
if((j=b__[0]+i)>max_array_)continue;
a__[j]=a__[i]
}
for(i=1;i<=b__[0];i++){
if((j=pos+i-1)>max_array_)continue;
a__[j]=b__[i]
}
a__[0]+=b__[0]
}
define ainsertat(*a__[],acount,pos,b__[],bcount){
return ainstertatr(a__[],0,acount-1,pos,b__[],0,bcount-1);
}
define ainsertelematr(*a__[],start,end,pos,e){
auto b[];b[0]=e
return ainsertatr(a__[],start,end,pos,b[],0,0);
}
define ainsertelemat0(*a__[],pos,e){
auto b[];b[0]=e;b[1]=0
return ainsertat0(a__[],pos,b[]);
}
define ainsertelematb(*a__[],x,pos,e){
auto b[];b[0]=e;b[1]=x
return ainsertatb(a__[],pos,b[],x);
}
define ainsertelematl(*a__[],pos,e){
auto b[];b[0]=1;b[1]=e
return ainsertatl(a__[],pos,b[]);
}
define ainsertelemat(*a__[],count,pos,e){
auto b[];b[0]=e
return ainstertatr(a__[],0,count-1,pos,b[],0,0);
}
## Comparison -> Lexical ##
# Compare a__[astart..aend] and b__[bstart..bend]
define acompare2r(a__[],astart,aend,b__[],bstart,bend){
auto a,b,i,j;
.=asanerange2_();
i=astart;j=bstart;
while(i<=aend&&j<=bend){
a=a__[i++];b=b__[j++]
if(a<b)return -1;
if(a>b)return 1;
}
if(i>aend&&j>bend)return 0;#sub arrays are equivalent
if(i>aend)return -1;#left array is shorter
return 1;#right array is shorter
}
# Compare a__[start..end] and b__[start..end]
define acomparer(a__[],b__[],start,end){
auto i;
.=asanerange_();
for(i=start;i<=end;i++){
if(a__[i]<b__[i])return -1;
if(a__[i]>b__[i])return 1;
}
return 0;
}
# compare zero-terminated arrays; a <=> b
define acompare0(a__[],b__[]) {
auto i;
for(i=0;i<=max_array_&&a__[i]&&b__[i];i++){
if(a__[i]<b__[i])return -1;
if(a__[i]>b__[i])return 1;
}
if(i>max_array_||(a__[i]==0&&b__[i]==0))return 0;
if(a__[i]==0)return -1;#left array is shorter
return 1;
}
# compare x terminated arrays; a <=> b
define acompareb(a__[],b__[],x) {
auto i;
for(i=0;i<=max_array_&&a__[i]!=x&&b__[i]!=x;i++){
if(a__[i]<b__[i])return -1;
if(a__[i]>b__[i])return 1;
}
if(i>max_array_||(a__[i]==x&&b__[i]==x))return 0;
if(a__[i]==x)return -1;#left array is shorter
return 1;
}
# compare length-specified arrays; a <=> b
define acomparel(a__[],b__[]) {
auto i;
for(i=1;i<=max_array_&&i<=a__[0]&&i<=b__[0];i++){
if(a__[i]<b__[i])return -1;
if(a__[i]>b__[i])return 1;
}
if(i>max_array_||(i>a__[0]&&i>b__[0]))return 0;
if(i>a__[0])return -1;#left array is shorter
return 1;
}
# Compare first 'count' elements of a and b
define acompare(a__[],b__[],count){
auto i;
if(count<0)count=0;
if(count>max_array_)count=max_array_+1;
for(i=0;i<count;i++){
if(a__[i]<b__[i])return -1;
if(a__[i]>b__[i])return 1;
}
return 0;
}
## Comparison -> Equality ##
# Check equality of a__[astart..aend] and b__[bstart..bend]
define aequals2r(a__[],astart,aend,b__[],bstart,bend){
return !acompare2r(a__[],astart,aend,b__[],bstart,bend)}
# Check equality of a__[start..end] and b__[start..end]
define aequalsr(a__[],b__[],start,end){
return !acomparer(a__[],b__[],start,end)}
# Check equality of zero-terminated arrays; a == b
define aequals0(a__[],b__[]){
return !acompare0(a__[],b__[])}
# Check equality of x terminated arrays; a == b
define aequalsb(a__[],b__[],x){
return !acompareb(a__[],b__[],x)}
# Check equality of length specified arrays; a == b
define aequalsl(a__[],b__[]){
return !acomparel(a__[],b__[])}
# Check equality of first 'count' elements of a and b
define aequals(a__[],b__[],count){
return !acompare(a__[],b__[],count)}
## Subarray matching ##
# Returns position in large that first occurrence of small is found
# . or -1 if no match is found
define amatcharray2r(small__[],astart,aend,large__[],bstart,bend){
auto i,j;
.=asanerange2_();
if(aend-astart>bend-bstart)return -1;
i=astart;j=bstart;
while(j<=bend){
while( j<=bend&&small__[i]!=large__[j]){.=j++}
if(j>bend)return -1;
.=i++ ;.=j++
while(i<=aend&&j<=bend&&small__[i]==large__[j]){.=i++;.=j++}
if(i>aend)return j-aend+astart-1;
i=astart;.=j++
}
return -1;
}
# As above but large and small are zero terminated arrays
define amatcharray0(small__[],large__[]){
auto i,j;
for(i=0;i<=max_array_&&small__[i];i++){}
for(j=0;j<=max_array_&&large__[j];j++){}
if(i>j)return -1;
return amatcharray2r(small__[],0,i-1,large__[],0,j-1)
}
# As above but large and small are arrays terminated by x
define amatcharrayb(small__[],large__[],x){
auto i,j;
for(i=0;i<=max_array_&&small__[i]!=x;i++){}
for(j=0;j<=max_array_&&large__[j]!=x;j++){}
if(i>j)return -1;
return amatcharray2r(small__[],0,i-1,large__[],0,j-1)
}
# As above but large and small are arrays terminated by x
define amatcharrayl(small__[],large__[]){
if(small__[0]>large__[0])return -1;
return amatcharray2r(small__[],1,small__[0],large__[],1,large__[0])
}
define amatcharray(small__[],scount,large__[],lcount){
if(scount>lcount) return -1;
return amatcharray2r(small__[],0,scount-1,large__[],0,lcount-1);
}
## Single element finding ##
define amatchelementr(e,a__[],start,end){
auto i;
.=asanerange_();
for(i=start;i<=end;i++)if(a__[i]==e)return i;
return -1;
}
define amatchelement0(e,a__[]){
auto i;
for(i=0;i<=max_array_&&a__[i];i++)if(a__[i]==e)return i;
if(i<=max_array_&&e==0)return i;
return -1;
}
define amatchelementb(e,a__[],x){
auto i;
for(i=0;i<=max_array_&&a__[i]!=x;i++)if(a__[i]==e)return i;
if(i<=max_array_&&e==x)return i;
return -1;
}
define amatchelementl(e,a__[]){
auto i;
for(i=1;i<=max_array_&&i<=a__[0];i++)if(a__[i]==e)return i;
return -1;
}
define amatchelement(e,a__[],count){
return amatchelementr(e,a__[],0,count-1);
}
## Output ##
aprint_wide_=1
# Prints a__[start..end]
define aprintr(*a__[],start,end) {
auto i;
if(start>end){print"{}";return 0}
.=asanerange_();
print "{";for(i=start;i<end;i++){
print a__[i],", ";if(!aprint_wide_)print"\n "
};print a__[i],"}\n"
}
# Treats a__[] as a zero terminated array; prints all elements prior to 0
define aprint0(*a__[]) {
auto e,f,i;
print "{";
if(!(e=a__[i=0])){print "}\n";return 0}
while(++i<=max_array_&&f=a__[i]){
print e,", "
if(!aprint_wide_)print"\n "
e=f;
}
print e,"}\n"
}
# Treats a__[] as an 'x' terminated array; prints all elements [b]efore 'x'
define aprintb(*a__[],x) {
auto e,f,i;
print "{";
if(x==(e=a__[i=0])){print "}\n";return 0}
while(++i<=max_array_&&(f=a__[i])!=x){
print e,", "
if(!aprint_wide_)print"\n "
e=f;
}
print e,"}\n"
}
# Treats a__[] as an 'x' terminated array
# . but prints all elements [u]pto and including 'x'
define aprintu(*a__[],x) {
auto i;
print "{";
for(i=0;a__[i]!=x&&i<max_array_;i++) {
print a__[i],", "
if(!aprint_wide_)print"\n "
}
if(i==max_array_){print a__[i]}else{print x}
print "}\n"
}
# Treats a__[] as a length specified array and prints it
define aprintl(*a__[]) {
auto e,f,i;
if(a__[0]==0){print"{}";return 0}
print "{";
for(i=1;i<a__[0];i++) {
print a__[i],", "
if(!aprint_wide_)print"\n "
}
print a__[i],"}\n"
}
# Prints the first 'count' elements of a__[]
define aprint(*a__[],count) {
.=aprintr(a__[],0,count-1)
}