Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/build/v2/util/sequence.jam @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 8.3 KB
Line 
1#  (C) Copyright David Abrahams 2002. Permission to copy, use, modify, sell and
2#  distribute this software is granted provided this copyright notice appears in
3#  all copies. This software is provided "as is" without express or implied
4#  warranty, and with no claim as to its suitability for any purpose.
5
6import assert ;
7import numbers ;
8import modules ;
9
10# Note that algorithms in this module execute largely in the caller's
11# module namespace, so that local rules can be used as function
12# objects. Also note that most predicates can be multi-element
13# lists. In that case, all but the first element are prepended to the
14# first argument which is passed to the rule named by the first
15# element.
16
17# Return the elements e of $(sequence) for which [ $(predicate) e ]
18# has a non-null value.
19rule filter ( predicate + : sequence * )
20{
21    local caller = [ CALLER_MODULE ] ;
22    local result ;
23
24    for local e in $(sequence)
25    {
26        if [ modules.call-in $(caller) : $(predicate) $(e) ]
27        {
28            result += $(e) ;
29        }
30    }
31    return $(result) ;
32}
33
34# return a new sequence consisting of [ $(function) $(e) ] for each
35# element e of $(sequence).
36rule transform ( function + : sequence * )
37{
38    local caller = [ CALLER_MODULE ] ;
39    local result ;
40
41    for local e in $(sequence)
42    {
43        result += [ modules.call-in $(caller) : $(function) $(e) ] ;
44    }
45    return $(result) ;
46}
47
48
49rule less ( a b )
50{
51    if $(a) < $(b)
52    {
53        return true ;
54    }
55}
56
57# insertion-sort s using the BinaryPredicate ordered.
58rule insertion-sort ( s * : ordered * )
59{
60    if ! $(ordered)
61    {
62        return [ SORT $(s) ] ;
63    }
64    else
65    {           
66        local caller = [ CALLER_MODULE ] ;
67        ordered ?= sequence.less ;
68        local result = $(s[1]) ;
69        if $(ordered) = sequence.less
70        {
71            local head tail ;
72            for local x in $(s[2-])
73            {
74                head = ;
75                tail = $(result) ;
76                while $(tail) && ( $(tail[1]) < $(x) )
77                {
78                    head += $(tail[1]) ;
79                    tail = $(tail[2-]) ;
80                }
81                result = $(head) $(x) $(tail) ;
82            }
83        }
84        else
85        {
86            for local x in $(s[2-])
87            {
88                local head tail ;
89                tail = $(result) ;
90                while $(tail) && [ modules.call-in $(caller) : $(ordered) $(tail[1]) $(x) ]
91                {
92                    head += $(tail[1]) ;
93                    tail = $(tail[2-]) ;
94                }
95                result = $(head) $(x) $(tail) ;
96            }
97        }
98       
99        return $(result) ;
100    }   
101}
102
103# merge two ordered sequences using the BinaryPredicate ordered.
104rule merge ( s1 * : s2 * : ordered * )
105{
106    ordered ?= sequence.less ;
107    local result__ ;
108    local caller = [ CALLER_MODULE ] ;
109
110    while $(s1) && $(s2) {
111        if [ modules.call-in $(caller) : $(ordered) $(s1[1]) $(s2[1]) ]
112        {
113            result__ += $(s1[1]) ;
114            s1 = $(s1[2-]) ;
115        }
116        else if [ modules.call-in $(caller) : $(ordered) $(s2[1]) $(s1[1]) ]
117        {
118            result__ += $(s2[1]) ;
119            s2 = $(s2[2-]) ;
120        }
121        else
122        {           
123            s2 = $(s2[2-]) ;
124        }
125       
126    }
127    result__ += $(s1) ;
128    result__ += $(s2) ;
129
130    return $(result__) ;
131}
132
133# join the elements of s into one long string. If joint is supplied,
134# it is used as a separator.
135rule join ( s * : joint ? )
136{
137    joint ?= "" ;
138    return $(s:J=$(joint)) ;
139}
140
141# Find the length of any sequence in log(N) time.
142rule length ( s * )
143{
144    local length = "" ;
145    local zeros p10 d z ; # declared once for speed
146
147    # Find the power of 10 that is just less than length(s)
148    zeros = "" ;
149    p10 = 1 ;
150    while $(s[$(p10)0])
151    {
152        p10 = $(p10)0 ;
153        zeros = $(zeros[1])0 $(zeros) ;
154    }
155
156    # zeros is a list of the form  ... 000 00 0 ""
157    for z in $(zeros) # for each digit in the result
158    {
159        # Find the next digit
160        d = 0 1 2 3 4 5 6 7 8 9 ;
161        while $(s[$(d[2])$(z)])
162        {
163            d = $(d[2-]) ;
164        }
165
166        # append it to the result
167        length = $(length)$(d[1]) ;
168
169        # Explanation: $(d[1])$(z) the largest number x of the form
170        # n000..., where n is a digit, such that x <= length(s). Here
171        # we're deleting x elements from the list. Since $(s[n]-)
172        # removes n - 1 elements from the list, we chop an additional
173        # one off the end.
174        s = $(s[$(d[1])$(z)--2]) ;
175    }
176    return $(length) ;
177}
178
179rule unique ( list * )
180{
181    local result ;
182    for local f in $(list)
183    {
184        if ! $(f) in $(result)
185        {
186            result += $(f) ;
187        }
188    }
189    return $(result) ;
190}
191
192# Returns the maximum number in 'elements'. Uses 'ordered' for comparisons,
193# or 'numbers.less' is none is provided.
194rule max-element ( elements + : ordered ? )
195{
196    ordered ?= numbers.less ;
197
198    local max = $(elements[1]) ;
199    for local e in $(elements[2-])
200    {
201        if [ $(ordered) $(max) $(e) ]
202        {
203            max = $(e) ;
204        }
205    }
206    return $(max) ;           
207}
208
209# Returns all of 'elements' for which corresponding element in parallel
210# list 'rank' is equal to the maximum value in 'rank'.
211rule select-highest-ranked ( elements * : ranks * )
212{
213    if $(elements)
214    {       
215        local max-rank = [ max-element $(ranks) ] ;
216        local result ;
217        while $(elements)
218        {
219            if $(ranks[1]) = $(max-rank)
220            {
221                result += $(elements[1]) ;
222            }
223            elements = $(elements[2-]) ;
224            ranks = $(ranks[2-]) ;
225        }
226        return $(result) ;
227    }   
228}
229NATIVE_RULE sequence : select-highest-ranked ;
230
231
232local rule __test__ ( )
233{
234    # use a unique module so we can test the use of local rules.
235    module sequence.__test__
236    {
237        import assert ;
238        import sequence ;
239       
240        local rule is-even ( n )
241        {
242            if $(n) in 0 2 4 6 8
243            {
244                return true ;
245            }
246        }
247
248        assert.result 4 6 4 2 8
249          : sequence.filter is-even : 1 4 6 3 4 7 2 3 8 ;
250
251        # test that argument binding works
252        local rule is-equal-test ( x y )
253        {
254            if $(x) = $(y)
255            {
256                return true ;
257            }
258        }
259
260        assert.result 3 3 3 : sequence.filter is-equal-test 3 : 1 2 3 4 3 5 3 5 7 ;
261
262        local rule append-x ( n )
263        {
264            return $(n)x ;
265        }
266
267        assert.result 1x 2x 3x : sequence.transform append-x : 1 2 3 ;
268
269        local rule repeat2 ( x )
270        {
271            return $(x) $(x) ;
272        }
273
274        assert.result 1 1 2 2 3 3 : sequence.transform repeat2 : 1 2 3 ;
275
276        local rule test-greater ( a b )
277        {
278            if $(a) > $(b)
279            {
280                return true ;
281            }
282        }
283        assert.result 1 2 3 4 5 6 7 8 9 : sequence.insertion-sort 9 6 5 3 8 7 1 2 4 ;
284        assert.result 9 8 7 6 5 4 3 2 1 : sequence.insertion-sort 9 6 5 3 8 7 1 2 4 : test-greater ;
285        assert.result 1 2 3 4 5 6 :  sequence.merge 1 3 5 : 2 4 6 ;
286        assert.result 6 5 4 3 2 1 :  sequence.merge 5 3 1 : 6 4 2 : test-greater ;
287        assert.result 1 2 3 : sequence.merge 1 2 3 : ;
288        assert.result 1 : sequence.merge 1 : 1 ;
289
290        assert.result foo-bar-baz : sequence.join foo bar baz : - ;
291        assert.result substandard : sequence.join sub stan dard ;
292        assert.result 3.0.1 : sequence.join 3.0.1 : - ;
293
294        assert.result 0 : sequence.length ;
295        assert.result 3 : sequence.length a b c ;
296        assert.result 17 : sequence.length 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 ;
297
298        assert.result 1 : sequence.length a ;
299        assert.result 10 : sequence.length a b c d e f g h i j ;
300        assert.result 11 : sequence.length a b c d e f g h i j k ;
301        assert.result 12 : sequence.length a b c d e f g h i j k l ;
302
303        local p2 = x ;
304        for local i in 1 2 3 4 5 6 7 8
305        {
306          p2 = $(p2) $(p2) ;
307        }
308        assert.result 256 : sequence.length $(p2) ;
309
310        assert.result 1 2 3 4 5
311          : sequence.unique 1 2 3 2 4 3 3 5 5 5 ;
312               
313        assert.result 5
314          : sequence.max-element 1 3 5 0 4 ;
315       
316        assert.result e-3 h-3
317          : sequence.select-highest-ranked e-1 e-3 h-3 m-2 : 1 3 3 2 ;
318    }
319}
Note: See TracBrowser for help on using the repository browser.