array.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 
------------------------->  GNU Sather - sourcefile  <-------------------------
-- Copyright (C) 2000 by K Hopper, University of Waikato, New Zealand        --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute  and/or modify it under the terms of the GNU Library General --
-- Public  License (LGPL)  as published  by the  Free  Software  Foundation; --
-- either version 2 of the license, or (at your option) any later version.   --
-- This  library  is distributed  in the  hope that it will  be  useful, but --
-- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/LGPL for more details.       --
-- The license text is also available from:  Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     --
-------------->  Please email comments to <bug-sather@gnu.org>  <--------------


class ARRAY{TYP} < $ARR{TYP}

class ARRAY{TYP} < $ARR{TYP} is -- This class implements one-dimensional arrays of elements of type TYP. -- The operations provided include sorting, searching, etc. Array indices -- start at 0 and go up to `asize-1'. -- -- Most features here work when self is void. The intent is that -- a void array behaves just like a zero-sized array. Thus self may be void -- on operations which don't try to directly access specific elements since -- any such access would be out of range. -- Version 1.2 Oct 98. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 11 Jul 96 bg Original for Sather 1.1 -- 13 Jan 97 kh Changed to CARD from INT -- 4 Nov 98 kh Now as 1.2 dist, added pre/post conditions. include CONTAINER{TYP} ; private include AREF{TYP} aget -> aget, aset -> aset, asize -> asize, array_ptr -> array_ptr ; -- Note that self may not be void for these public included routines. create : SAME is --This routine creates an empty array. return SAME::create(0) end ; create(sz : CARD) : SAME is --This routine creates a new array of the given size, all of whose -- elements are void. return new(sz) end ; create(arr : ARRAY{TYP}) : SAME is --This routine creates a new array which has exactly the same contents as arr. me : SAME := create(arr.size) ; loop me.set!(arr.elt!) end ; return me end ; create_from(elems : $ELT{TYP}) : SAME is --This routine creates an array out of the elements of "elems". It is -- expensive - first converts the argument into an FLIST to determine the -- number of elements and then converts the FLIST into an array. flist : FLIST{TYP} := FLIST{TYP}::create ; loop flist := flist.push(elems.elt!) end ; me : SAME := SAME::create(flist.size) ; loop me.set!(flist.elt!) end ; return me end ; size : CARD is --This routine returns the number of elements in the array. Self may -- be void. Built-in to this implementation. builtin ARRAY_SIZE end ; clear is --This routine sets each array element to void. Built-in to this -- implementation. Self may be void. builtin ARRAY_CLEAR end ; equals(arr : $CONTAINER{TYP}) : BOOL is --This predicate returns true if and only if all elements of self are -- the same as the corresponding elements of arr. typecase arr when SAME then loop if ~elt_eq(elt!,arr.elt!) then return false end end ; return true else return false end end ; has_ind(val : CARD) : BOOL is --This predicate returns true if and only if val is a valid index for the array. return val < size end ; inds : ARRAY{CARD} pre ~void(self) post (result.size = size) is --This routine returns an index array which is the same size as self -- and is set to the values of the indices. sz : CARD := size ; res : ARRAY{CARD} := ARRAY{CARD}::create(sz) ; index : CARD := 0 ; loop until!(index >= sz) ; res[index] := ind! ; index := index + 1 end ; return res end ; resize(new_size : CARD) : SAME pre ~void(self) post (result.size = new_size) is --This routine allocates a new array and copies whatever will fit of -- self. It then returns the new array. res : SAME := SAME::create(new_size) ; loop res.set!(elt!); end ; return res end ; copy : SAME pre true post (result.size = self.size) -- (result = self) is --This routine returns a copy of self. if void(self) then return void end ; res : SAME := create(size) ; res.copy(self) ; return res end ; copy(src : SAME) pre ~void(self) and ~void(src) post true -- (self.size >= src.size) -- and {forall ind member dom.src -- | self(ind) = src(ind)} -- and {forall ind member dom.self -- and ~member dom.src -- | self(ind) = -- initial(self(ind)) -- or (self.size < src.size) -- and {forall ind member dom.self -- | self(ind) = src(ind)} is --This routine copies as many elements from src to self as will fit. -- Built-in to this implementation. builtin ARRAY_COPY end ; copy(beg : CARD, src : SAME ) pre ~void(self) and ((beg < size) or (src.size = 0)) post true -- + vdm stuff!?! is --This routine copies as many elements from src to self as will fit -- when starting at index beg of self. Self may not be void but src may -- be void. Built-in to this implementation. builtin ARRAY_COPY_BEG end ; copy(beg,num : CARD, src : SAME ) pre ~void(self)and ~void(src) and (beg<size) and (num<=size-beg) and (num <= src.size) post (self.size = initial(self.size)) is -- This routine copies num elements from src to self starting at index -- beg of self. Neither self nor src may be void. Built-in to this -- implementation. builtin ARRAY_COPY_BEG_NUM end ; copy(beg, num, srcbeg : CARD, src : SAME) pre ~void(self) and ~void(src) and (beg<size) and (num <= size-beg) and (srcbeg < src.size) and (num <= src.size-srcbeg) post (self.size = initial(self.size)) is --This routine copies num elements from src to self starting at index -- beg of self and index srcbeg of src. Neither self nor src may be void. -- Built-in to this implementation. builtin ARRAY_COPY_BEG_NUM_SRCBEG end ; slice(beg,num : CARD) : SAME pre ~void(self) and (beg<size) and (num<=size-beg) post (result.size = num) is --This routine returns a new array which is a sub-sequence of self, -- with num entries copied from self starting at beg. Self may not be void. res : SAME := new(num) ; res.copy(0,num,beg,self) ; return res end ; to_reverse is --This routine reverses the order of the elements in self. Self may be void. if ~void(self) then loop index : CARD := (size/2).times! ; up_index : CARD := size - index - 1 ; temp : TYP := [index ] ; [index] := [up_index] ; [up_index] := temp; end end; end ; reverse : SAME is --This routine returns a copy of self with all elements in reverse order. Self may be void. if void(self) then return void else res: SAME := new(size) ; if asize.is_pos then loop res.set!(asize - 1,asize, -1,elt!) end ; end; return res end end ; to(src : SAME) pre (src.size = size) post true -- (src = self) is --This routine sets self to be a copy of src. Both may be void! loop set!(src.elt!) end end ; to_val(val : TYP) pre true post void(self) or (count(val) = size) is --This routine sets each element of self to val. Self may be void. loop set!(val) end end ; append(arr : SAME) : SAME pre true post true -- + vdm stuff !?! is --This routine returns a new array consisting of self followed by arr. Both may be void. if void(self) then return arr.copy elsif void(arr) then return copy else res : SAME := new(size + arr.size) ; res.copy(self) ; res.copy(size,arr) ; return res end end ; append(arr1,arr2 : SAME) : SAME pre true post true -- + vdm stuff !?! is --This routine returns a new array consisting of self followed by -- arr1 and then arr2. This is more efficient than two appends. Any of -- the arrays may be void. if void(self) then return arr1.append(arr2) elsif void(arr1) then return append(arr2) elsif void(arr2) then return append(arr1) else res : SAME := new(size + arr1.size + arr2.size) ; res.copy(self) ; res.copy(size,arr1) ; res.copy(size + arr1.size,arr2) ; return res end end ; append(arr1,arr2,arr3 : SAME) : SAME pre true post true -- + vdm stuff !?! is --This routine returns a new array consisting of self followed by -- arr1 then arr2 and finally arr3. This is more efficient than three -- appends. Any of the arrays may be void. if void(self) then return arr1.append(arr2,arr3) elsif void(arr1) then return append(arr2,arr3) elsif void(arr2) then return append(arr1,arr3) elsif void(arr3) then return append(arr1,arr2) else res : SAME := new(size + arr1.size + arr2.size + arr3.size) ; res.copy(self) ; res.copy(size,arr1) ; res.copy(size + arr1.size,arr2) ; res.copy(size + arr1.size + arr2.size,arr3) ; return res end end ; append(elem:TYP):SAME is res:SAME:=new(size+1); res.copy(self); res[size]:=elem; return res; end; contains(elem : TYP) : BOOL is --This predicate returns true if and only if self contains an element -- for which elt_eq returns true, otherwise false. if void(self) then return false end ; loop if elt_eq(elt!,elem) then return true end end ; return false end ; has(elem : TYP ) : BOOL is --This predicate is a renaming of contains. return contains(elem) end ; count(val : TYP) : CARD pre true post true -- irrespective of result! is --This routine returns the number of array elements which are elt_eq to val. Self may be void. res : CARD := 0 ; loop if elt_eq(elt!,val) then res := res + 1 end end ; return res end ; index_of(elem : TYP) : CARD pre true post (result = CARD::nil) or (~void(self)and(count(elem) > 0)) is --This routine returns the lowest index of an element which is elt_eq to elem. -- If there is no such element then CARD::nil is returned. -- Self may be void. loop res : CARD := ind! ; if elt_eq(elem,[res]) then return res end end ; return CARD::nil end ; remove(elem : TYP) : SAME pre true post ~result.contains(elem) is --This routine returns a new array in which no elements are elt_eq to elem. Self may be void. if void(self) then return void else res : SAME := create(size - count(elem)) ; loop loc_elem : TYP := elt! ; if ~elt_eq(loc_elem,elem) then res.set!(loc_elem) end end ; return res end end ; remove_if(test : ROUT{TYP} : BOOL) : SAME pre void(self) or ~void(test) post true is --This routine returns a new array without those elements which satisfy -- the given test. Self may be void. if void(self) then return void else res : SAME := create(size - count_if(test)) ; loop elem : TYP := elt! ; if ~test.call(elem) then res.set!(elem) end end ; return res end end ; private is_sorted(lower : CARD, upper : CARD ) : BOOL is --This predicate returns true if and only if the elements of self are -- sorted according to the relation elt_lt. Self may be void. loop index : CARD := (lower + 1).upto!(upper) ; if elt_lt([index],[index - 1]) then return false end end ; return true end ; is_sorted : BOOL is --This predicate returns true if and only if the elements of self are -- sorted according to the relation elt_lt. Self may be void. if self.size<=1 then return true else return is_sorted(0,(asize - 1)) end end ; remove_duplicates : SAME pre is_sorted post (result.size <= size) is --This routine returns a new arry with only the first copy of -- duplicated elements. Self may be void. If not it must be sorted -- prior to calling this routine. if void(self) or self.size = 1 then return self end ; res : SAME := new(size) ; -- Same size as self for now... num_elems : CARD := 0 ; -- No of elems in res! prev : TYP := [0] ; loop curr : TYP := elt!(1) ; if ~elt_eq(prev,curr) then res[num_elems] := prev ; num_elems := num_elems + 1 end ; prev := curr end ; res[num_elems] := [size - 1] ; num_elems := num_elems + 1 ; return res.resize(num_elems) end ; to_replace(old, new_val : TYP) pre true post (initial(count(old)) <= count(new_val)) is --This routine replaces those elements that are elt_eq to old by -- new_val wherever the match is found. Self may be void. loop elem : TYP := elt! ; if elt_eq(elem,old) then elem := new_val end ; set!(elem) end end ; to_replace_if(test : ROUT{TYP} : BOOL, new_val : TYP) pre void(self) or ~void(test) post true is --This routine replaces all of the elements of self which satisfy -- the given test by new_val. Self may be void. loop elem : TYP := elt! ; if test.call(elem) then elem := new_val end ; set!(elem) end end ; find_if(test : ROUT{TYP} : BOOL) : TYP pre void(self) or ~void(test) post true is --Searching from the lowest index, this routine returns the first -- element which satisfies the given test. If there is no such element -- then void is returned. Self may be void. loop res : TYP := elt! ; if test.call(res) then return res end end ; return void end ; index_if(test : ROUT{TYP} : BOOL) : CARD pre void(self) or ~void(test) post (result = CARD::nil) or test.call([result]) is --This routine returns the index of the first element, searching from -- zero, which satisfies the given test. If there is no such element then -- CARD::nil is returned. Self may be void. loop res : CARD := ind! ; if test.call([res]) then return res end end ; return CARD::nil end ; mismatch(arr : SAME) : CARD pre true post (result = CARD::nil)or (result < asize) is --This routine returns the index of the first element of self which -- differs from the corresponding element of arr. If there is no such -- element or self is void or self is a prefix of arr then CARD::nil is -- returned. if void(self) then return CARD::nil end ; loop res : CARD := ind! ; if ~elt_eq([res],arr.elt!) then return res end end ; return CARD::nil end ; search(arr : SAME) : CARD pre true post (result = CARD::nil)or (result < asize) is --This routine returns the index of the first sub-array of self, -- starting at zero, which matches arr. If self is void or there is no -- match then CARD::nil is returned. if void(self) then return CARD::nil end ; loop res : CARD := 0.upto!(size - arr.size) ; match : BOOL := true ; loop if ~elt_eq(elt!(res),arr.elt!) then match := false ; break! end end ; if match then return res end end ; return CARD::nil end ; search(beg : CARD, arr : SAME) : CARD pre ~void(self) and ~void(arr) and (beg<asize) post (result = CARD::nil) or (result < asize) is --This routine returns the index of the beginning of the first -- sub-array of self which matches arr, starting at zero. If there is no -- such sub-array then CARD::nil is returned. loop res : CARD := beg.upto!(size - arr.size) ; match : BOOL := true ; loop if ~elt_eq(elt!(res),arr.elt!) then match := false ; break! end end ; if match then return res end end ; return CARD::nil end ; map(operation : ROUT{TYP} : TYP) pre ~void(operation) post true is --This routine sets each element of self to be the result of applying -- the given operation to it. Self may be void. loop set!(operation.call(elt!)) end end ; reduce(operation : ROUT{TYP,TYP} : TYP) : TYP pre ~void(operation) post true is --This routine returns the result of applying the given operation -- to self from the lowest index to the highest. Void is returned if self -- is void. if size = 0 then return void end ; val : TYP := [0] ; loop val := operation.call(val,elt!(1,size - 1)) end ; return val end ; scan(operation : ROUT{TYP,TYP} : TYP) pre ~void(operation) post true is --This routine sets each element of self to be the result of applying -- the given operation to adjacent elements of self from lowest to highest -- index. The element with index zero is not altered. Self may be void. if ~void(self) then loop index : CARD := 1.upto!(size - 1) ; [index] := operation.call([index - 1],[index]) end end end ; -- The following group of operations relate to sorted arrays insertion_sort_range(lower,upper : CARD) pre (self.size > 1) and (lower < upper) and (upper <= (asize - 1)) post is_sorted(lower,upper) is --This routine performs an insertion sort of the elements of self -- in the index range lower to upper. Ordering is defined by elt_lt. loop out_index : CARD := (lower + 1).upto!(upper) ; elem : TYP := [out_index] ; loop in_index : CARD := out_index.downto!(lower) ; if (in_index = lower) then [lower] := elem ; break! elsif (elt_lt([in_index - 1], elem)) then [in_index] := elem ; break! else [in_index] := [in_index - 1] end end end end ; private const quicksort_limit : CARD := 10 ; -- The value of this is used to stop quicksort recursion and switch to an -- insertion sort. quicksort_range(lower,upper : CARD) pre (self.size > 1) and (lower < upper) and (upper <= (asize - 1)) post is_sorted(lower,upper) is --This routine implements part of the quicksort algorithm to search -- the range of self between lower and upper according to the relation elt_lt if (upper - lower) > quicksort_limit then res : CARD := RANDOM::card(lower,upper) ; temp : TYP := [res] ; -- Swap the random element & lower [res] := [lower] ; [lower] := temp ; middle : CARD := lower ; loop index : CARD := (lower + 1).upto!(upper) ; if elt_lt([index],temp) then middle := middle + 1 ; stemp : TYP := [middle] ; [middle] := [index] ; [index ] := stemp end end ; temp := [lower] ; [lower] := [middle] ; [middle] := temp ; if (middle > 0) and (lower < (middle - 1)) then quicksort_range(lower,middle - 1) end ; if (middle + 1) < upper then quicksort_range(middle + 1,upper) end else insertion_sort_range(lower,upper) end end ; sort pre true post is_sorted is --This routine sorts the entire array using quick-sort with respect -- to elt_lt. Self may be void. if self.size > 1 then -- less than 2 is sorted! quicksort_range(0,asize - 1) end end ; stable_sort pre true post is_sorted is --This routine uses an insertion sort to permute the elements of self -- so that it is sorted with respect to elt_lt and equal elements are in -- the original order. Self may be void. if self.size > 0 then insertion_sort_range(0,asize - 1) end end ; binary_search(elem : TYP) : CARD pre is_sorted post (result = CARD::nil) or (result < asize) is --This search routine assumes that self is sorted. It returns -- the index of the element preceding the first element greater than elem -- according to elt_lt or CARD::nil if self is void or if all elements -- are greater than elem. if void(self) then return CARD::nil end ; lower : CARD := 0 ; upper : CARD := asize - 1 ; if ~elt_lt(elem,[upper]) then return upper end ; if elt_lt(elem,[lower]) then return CARD::nil end ; -- At this point [u] is always greater than elem, and [l] is not -- greater than elem. loop while!(upper > (lower + 1)) ; index : CARD := (upper + lower)/2 ; if elt_lt(elem,[index]) then upper := index else lower :=index end end ; return lower end ; is_sorted_by(order : ROUT{TYP,TYP} : BOOL) : BOOL pre void(self) or ~void(order) post true is -- This predicate returns true if and only if the elements of self are -- sorted in an order specified by the order routine which is expected to -- return true if and only if its first argument is less than its second -- argument. Self may be void. if ~void(self) and asize>1 then loop index : CARD := 1.upto!(asize - 1) ; if order.call([index],[index - 1]) then return false end end end ; return true end ; insertion_sort_by(order : ROUT{TYP,TYP} : BOOL) pre ~void(order) post is_sorted_by(order) is -- This routine sorts the elements of self using insertion sorting -- in an order specified by the order routine which is expected to return -- true if and only if its first argument is less than its second argument. -- Self may be void. if void(self) then return end ; loop out_index : CARD := 1.upto!(asize - 1) ; elem : TYP := [out_index] ; loop in_index : CARD := (out_index).downto!(0) ; if (in_index = 0) then [in_index] := elem ; break! elsif (order.call([in_index - 1], elem)) then [in_index] := elem ; break! else [in_index] := [in_index - 1] end end end end ; binary_search_by(elem : TYP,order : ROUT{TYP,TYP} : BOOL) : CARD pre ~void(order) and is_sorted_by(order) post (result = CARD::nil) or (result < asize) is --This routine returns the index of the element of self preceding -- the first element greater than elem unless self is void or all elements -- are greater then elem, when CARD::nil is returned. if void(self) then return CARD::nil end ; lower : CARD := 0 ; upper : CARD := asize - 1 ; if ~order.call(elem,[upper]) then return upper end ; if order.call(elem,[lower]) then return CARD::nil end ; -- At this point [upper] is known to be greater than elem, and -- [lower] is not greater than elem. loop while!(upper > (lower + 1)) ; index : CARD := (upper + lower)/2 ; if order.call(elem,[index]) then upper := index else lower := index end end ; return lower end ; merge_with_by(arr : SAME,order : ROUT{TYP,TYP} : BOOL) : SAME pre is_sorted_by(order) and arr.is_sorted_by(order) post result.is_sorted_by(order) is --This routine returns a new array with the elements of self merged -- together according to order which should return true if and only if its -- first argument is less than its second. if void(self) then return arr.copy end ; if void(arr) then return copy end ; res : SAME := create(size + arr.size) ; self_index, arr_index : CARD ; temp : TYP ; loop if self_index = size then temp := arr[arr_index] ; arr_index := arr_index + 1 elsif arr_index = arr.size then temp := [self_index] ; self_index := self_index + 1 elsif order.call([self_index],arr[arr_index]) then temp := [self_index] ; self_index := self_index + 1 else temp := arr[arr_index] ; arr_index := arr_index + 1 end ; res.set!(temp) end ; return res end ; select( index : CARD) pre ~void(self) and (index < size) post true is --This routine moves the elements of self so that the element with -- the given index is not elt_lt any element with lower indices and -- no element with a larger index is elt_lt it. lower : CARD := 0 ; upper : CARD := size - 1 ; loop until!(lower >= upper) ; out_index : CARD := RANDOM::card(lower,upper) ; temp : TYP := [out_index] ; [out_index] := [lower] ; [lower] := temp ; middle : CARD := lower ; loop in_index : CARD := (lower + 1).upto!(upper) ; if elt_lt([out_index],temp) then middle := middle + 1 ; temp := [middle] ; [middle] := [in_index] ; [in_index] := temp end end ; temp := [lower] ; [lower] := [middle] ; [middle] := temp ; if middle <= out_index then lower := middle + 1 end ; if middle >= out_index then upper := middle - 1 end end end ; median : TYP pre true post void(result) or self.contains(result) is --This routine returns the median of the elements contained in self -- according to the ordering relation elt_lt. This permutes the elements -- of self. Void is returned if self is void. if size = 0 then return void end ; middle : CARD := (size - 1)/2 ; select(middle) ; return [middle] end ; select_by(order : ROUT{TYP,TYP} : BOOL,index : CARD) pre ~void(self) and ~void(order) and (index < size) post true is --This routine moves the elements of self so that the element with -- the given index is not less than (as determined by the order routine, -- which is expected to return true if and only if its first argument is -- less than its second) any element with lower indices and no element with -- a larger index is less than it. lower : CARD := 0 ; upper : CARD := size - 1 ; loop until!(lower >= upper) ; out_index : CARD := RANDOM::card(lower,upper) ; temp : TYP := [out_index] ; [out_index] := [lower] ; [lower] := temp ; middle : CARD := lower ; loop in_index : CARD := (lower + 1).upto!(upper) ; if order.call([in_index],temp) then middle := middle + 1 ; temp := [middle] ; [middle] := [in_index] ; [in_index] := temp end end ; temp := [lower] ; [lower] := [middle] ; [middle] := temp ; if middle <= out_index then lower := middle + 1 end ; if middle >=out_index then upper := middle - 1 end end end ; -- The iters over array elements. elt! : TYP pre true --~void(self) post (self.contains(result)) is -- This iter yields each element of self in order. Self may be void. -- Built-in to this implementation. builtin ARRAY_ELTB end ; elt!(once beg : CARD) : TYP pre ~void(self) and (beg < asize) post contains(result) -- (result = [ind!]) is --This iter yields each element of self starting at `beg'. Self may -- not be void. Built-in to this implementation. builtin ARRAY_ELT_BEGB end ; elt!(once beg,once num : CARD) : TYP pre ~void(self) and (beg<size)and (num<= size-beg) post contains(result) -- (result = [beg + ind!]) is --This iter yields num successive elements of self starting at -- index beg. Self may not be void. Built-in to this implementation. builtin ARRAY_ELT_BEG_NUMB end ; elt!(once beg,once num : CARD,once step : INT) : TYP pre ~void(self) and is_legal_aelts_arg(beg,num,step) post contains(result) -- (result = [beg + ind!]) is --This iter yields num elements of self starting at beg and stepping -- by step which must not be zero. Self may not be void. Built-in to this -- implementation. builtin ARRAY_ELT_BEG_NUM_STEPB end ; set!(val : TYP) pre true post contains(val) -- ([ind!] = val) is --This iter sets successive elements of self to the values of val. -- Self may be void. Built_in to this implementation. builtin ARRAY_SETB end ; set!( once beg : CARD, val : TYP) pre ~void(self) and (beg < size) post contains(val) -- ([beg + ind!] = val) is --This iter sets successive elements starting at beg to the values of -- val. Self may not be void. Built-in to this implementation. builtin ARRAY_SET_BEGB end ; set!( once beg,once num : CARD,val : TYP) pre ~void(self) and (beg<size) and (num <= size-beg) post contains(val) -- ([beg + ind!] = val) is --This iter sets num successive elements of self starting at beg -- to the values of val. Self may not be void. Built-in to this -- implementation. builtin ARRAY_SET_BEG_NUMB end ; set!( once beg,once num : CARD,once step : INT,val : TYP) pre ~void(self) and is_legal_aelts_arg(beg,num,step) post contains(val) -- + vdm stuff !?! is --This iter sets num elements of self starting at beg stepping by -- step to the values of val. Step must not be zero. Self may not be void. -- Built-in to this implementation. builtin ARRAY_SET_BEG_NUM_STEPB end ; ind! : CARD pre true post (result < size) is --This iter yields the indices of self in order. Self may be void. -- Built-in to this implementation. builtin ARRAY_INDB end ; ind1! : CARD pre true post (result < size) is --This iter yields the indices of self in order. Self may be void. -- Built-in to this implementation. -- -- NOTE This is provided for consistency with ARRAY2 and ARRAY3 classes. builtin ARRAY_INDB end ; elt_rev! :TYP is -- This iter yields each element of self in reversed order. Self may be void. if ~void(self) and (size>0) then loop yield aget((size-1).downto!(0)); end; end; end; ind_rev! :CARD is --This iter yields the indices of self in reversed order. Self may be void. if ~void(self) and (size>0) then loop yield (size-1).downto!(0); end; end; end; end ; -- class ARRAY{TYP}