285 lines
10 KiB
PostScript
285 lines
10 KiB
PostScript
% $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
|