% $Header: /cvsroot/html2ps/postscript/array.ps,v 1.1 2005/12/18 07:21:36 Konstantin Exp $ % Actually, array-append and array-prepend should have names exchanged; % nevertheless, I don't want to track down renames all over ps files, so I've decided to % keep this as is % % Prepends item to array % % @param Item item value % @param Array source array % @return A copy of source array with Item prepended as a first element % /array-append { % => Item Array aload length 1 add array astore } def /in-array-find { % => Array Value Pos 2 index length 0 eq { pop pop pop -1 } { 2 index 0 get % => Array Value Pos A0 2 index eq { % => Array Value Pos 3 1 roll % => Pos Array Value pop pop % => Pos } { 1 add % => Array Value Pos+1 2 index array-pop-first % => Array Value Pos+1 Array' 4 3 roll pop % => Value Pos+1 Array' 3 1 roll % => Array' Value Pos+1 in-array-find } ifelse } ifelse } def /array-find { % => Array Value 0 in-array-find } def /array-insert { % => Index Value Data aload length % => Index Value A1 .. AN N 1 add % => Index Value A1 .. AN N+1 dup 2 add % => Index Value A1 .. AN N+1 N+3 dup index % => Index Value A1 .. AN N+1 N+3 Index exch % => Index Value A1 .. AN N+1 Index N+3 1 sub % => Index Value A1 .. AN N+1 Index N+2 index % => Index Value A1 .. AN N+1 Index Value exch % => Index Value A1 .. AN N+1 Value Index 2 index % => Index Value A1 .. AN N+1 Value Index N+1 1 add % => Index Value A1 .. AN N+1 Value Index N+2 exch sub % => Index Value A1 .. AN N+1 Value N-Index+2 1 % => Index Value A1 .. AN N+1 Value N-Index+2 1 roll % => Index Value A1 .. AINDEX-1 Value AINDEX .. AN N+1 array astore % => Index Value Array 3 1 roll % => Array Index Value pop pop } def % => Data' /array-last { % => Array dup length % => Array Length 1 sub % => Array Length-1 get % => Last } def /array-merge { % => A1 A2 { % => A1 A2[i] exch array-prepend % => A1' } forall % => A1' } def /array-pop-last { % => Array aload length % => A1 .. AN N 1 sub % => A1 .. AN N-1 exch pop % => A1 .. AN-1 N-1 array astore % => Array' } def /array-pop-first { % => Array aload length % => A1 .. AN N 1 sub % => A1 .. AN N-1 array astore % => A1 Array' exch pop % => Array' } def % Appends item to array % % @param Item item value % @param Array source array % @return A copy of source array with Item appended as a last element % /array-prepend { % => Item Array aload length % => Item Item1 .. ItemN N 1 add % => Item Item1 .. ItemN N+1 dup 1 add % => Item Item1 .. ItemN N+1 N+2 1 index roll % => Item1 .. ItemN N+1 Item exch % => Item1 .. ItemN Item N+1 array astore % => Array } def /array-remove { % => Array Index(ZeroBased) exch % => Index Array aload length % => Index A1 .. AN N 1 sub % => Index A1 .. AN N-1 dup 2 add % => Index A1 .. AN N-1 N+2 index % => Index A1 .. AN N-1 Index 1 index % => Index A1 .. AN N-1 Index N-1 2 add % => Index A1 .. AN N-1 Index N+1 exch sub % => Index A1 .. AN N-1 N-Index+1 dup 1 sub % => Index A1 .. AN N-1 N-Index+1 N-Index roll % => Index A1 .. AINDEX-1 AINDEX+1 .. AN N-1 AINDEX pop % => Index A1 .. AINDEX-1 AINDEX+1 .. AN N-1 array astore % => Index Array exch pop % => Array } def % Basic insertions algorithm; we're working with small arrays % and these arrays are have "good" natural order of elements, so % more complicated algorithms are not needed here % /array-sort { % => Data GtFun [] % => Data GtFun SortedData array-sort-rec % => SortedData } def /array-sort-rec { % => Data GtFun SortedData 2 index length 0 gt { 2 index 2 index array-sort-rec-select-max % => Data GtFun SortedData Data' MaxValue 5 4 roll pop % => GtFun SortedData Data' MaxValue 2 index array-prepend % => GtFun SortedData Data' SortedData' 3 2 roll pop % => GtFun Data' SortedData' exch % => GtFun SortedData' Data' 3 1 roll % => Data' GtFun SortedData' array-sort-rec } { exch pop exch pop % => SortedData } ifelse } def /array-sort-rec-select-max { % => Data GtFun 1 index 0 get % => Data GtFun E0 0 1 % => Data GtFun EMax EMaxIndex ECurIndex array-sort-rec-select-max-rec % => Data GtFun EMax EMaxIndex % remove element found from source array 3 index exch array-remove % => Data GtFun EMax Data' 4 2 roll pop pop % => EMax Data exch % => Data EMax } def /array-sort-rec-select-max-rec { % => Data GtFun EMax EMaxIndex ECurIndex % Check if we're out of source array bounds 4 index length 1 index gt { % => Data GtFun EMax EMaxIndex ECurIndex 4 index 1 index get % => Data GtFun EMax EMaxIndex ECurIndex ECur 3 index % => Data GtFun EMax EMaxIndex ECurIndex ECur EMax 5 index exec % => Data GtFun EMax EMaxIndex ECurIndex ECur>EMax { % => Data GtFun EMax EMaxIndex ECurIndex exch pop dup % => Data GtFun EMax EMaxIndex' ECurIndex 4 index 1 index get % => Data GtFun EMax EMaxIndex' ECurIndex EMax' 4 3 roll pop % => Data GtFun EMaxIndex' ECurIndex EMax' 3 1 roll % => Data GtFun EMax' EMaxIndex' ECurIndex } if % => Data GtFun EMax' EMaxIndex' ECurIndex 1 add array-sort-rec-select-max-rec } { pop } ifelse } def % => Data GtFun EMax EMaxIndex /expand-to { % => Size Array % if array have no elements - return immediately dup length 0 eq { [] % => Size Array Flags [] } { dup sum % => Size Array ASize dup 0 gt { % => Size Array ASize dup % => Size Array ASize ASize 3 index lt % => Size Array ASize { % => Size Array ASize 2 index % => Size Array ASize Size exch div % => Size Array Size/ASize map-scale % => Size Array' exch pop % => Array' } { % => Size Array ASize pop exch % => Array Size pop % => Array } ifelse % => Array } { % => Size Array ASize % No content found in some colspan columns pop % => Size Array array-pop-first array-append % => Array } ifelse } ifelse } def /expand-to-with-flags { % => Size Array Flags % if array have no elements - return immediately 1 index length 0 eq { [] % => Size Array Flags [] } { % Never decrease exising values 1 index sum % => Size Array Flags ASum 3 index % => Size Array Flags ASum Size gt { 1 index % => Size Array Flags Expanded } { % => Size Array Flags % Subtract non-modifiable values from target value 2 copy { dup not { pop } { pop pop 0 } ifelse } zip-with sum % => Size Array Flags Non-modSum 4 3 roll exch sub 3 1 roll % => Size' Array Flags % Check if there's any expandable columns 2 copy { dup { pop } { pop pop 0 } ifelse } zip-with sum % => Size Array Flags ModSum dup 0 eq { % => Size Array Flags ModSum pop % => Size Array Flags 1 index % => Size Array Flags Array 0 get 3 index add % => Size Array Flags A0' 2 index exch 0 exch put % => Size Array Flags 1 index } { % => Size Array Flags ModSum % Calculate scale koeff 3 index exch div % => Size Array Flags Koeff % Apply scale koeff 0 1 4 index length 1 sub { % => Size Array Flags Koeff I 2 index 1 index get { 3 index 1 index get % => Size Array Flags Koeff I A[i] 2 index mul % => Size Array Flags Koeff I A[i]*Koeff 4 index exch 2 index exch put % => Size Array Flags Koeff I } if pop } for % => Size Array Flags Koeff pop % => Size Array Flags 1 index } ifelse % => Size Array Flags Expanded } ifelse } ifelse % => Size Array Flags Expanded exch pop exch pop exch pop } def /in-reduce { % => A1 .. AN N Fun StartValue 2 index 0 gt { 4 3 roll % => A1 .. AN-1 N Fun StartValue AN 2 index exec % => A1 .. AN-1 N Fun (StartValue Fun AN) 3 2 roll % => A1 .. AN-1 Fun (StartValue Fun AN) N 1 sub % => A1 .. AN-1 Fun (StartValue Fun AN) N-1 3 1 roll % => A1 .. AN-1 N-1 Fun (StartValue Fun AN) in-reduce } { % => N Fun Value 3 1 roll % => Value N Fun pop pop % => Value } ifelse } def /reduce { % => Fun StartValue Array aload length % => Fun StartValue A1 .. AN N dup 3 add % => Fun StartValue A1 .. AN N N+3 1 index 1 add % => Fun StartValue A1 .. AN N N+3 N+1 roll % => A1 .. AN N Fun StartValue in-reduce } def /sum { % => Array {add} 0 % => Array {add} 0 3 2 roll % => {add} 0 Array reduce % => Sum } def