Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

added boost

File size: 5.2 KB
Line 
1#  (C) Copyright David Abrahams 2001. 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
6digits = 0 1 2 3 4 5 6 7 8 9 ;
7powers = 1 ;
8zeros = "" ;
9natural = $(digits) ;
10positive = $(digits[2-]) ;
11incr = $(positive[2-]) ;
12znatural = $(digits) ;
13zero-test = is zero ; # if $(zero-test[$(n)]) == "is" "zero", n == 0
14
15import errors : * ;
16
17local rule extend ( )
18{
19    local next = $(digits[2-])$(znatural) ;
20    natural += $(next) ;
21    positive += $(next) ;
22    incr += $(next) ;
23    znatural = $(digits)$(znatural) ;
24}
25
26rule check ( numbers * )
27{
28    for local n in $(numbers)
29    {
30        switch $(n)
31        {
32            case *[^0-9]* :
33              error $(n) "in" $(numbers) : is not a number ;
34        }
35    }
36}
37
38rule increment ( number )
39{
40    return [ CALC $(number) + 1 ] ;
41}
42
43rule decrement ( number )
44{
45    # Previous rule did not allow decrementing zero.
46    # Is that what we want?
47    return [ CALC $(number) - 1 ] ;
48}
49
50rule range ( start finish ? : step ? )
51{
52    if ! $(finish)
53    {
54        finish = $(start) ;
55        start = 1 ;
56    }
57    step ?= 1 ;
58   
59    check $(start) $(finish) $(step) ;
60
61    if $(finish) != 0
62    {
63        while ! $(positive[$(finish)])
64        {
65            extend ;
66        }
67       
68        if $(step) = 1
69        {
70            return $(positive[$(start)-$(finish)]) ;
71        }
72        else
73        {
74            local index = [ increment $(step) ] ;
75            local by1 = $(positive[$(start)-$(finish)]) ;
76            local result ;
77            while $(by1)
78            {
79                result += $(by1[1]) ;
80                by1 = $(by1[$(index)-]) ;
81            }
82            return $(result) ;
83        }
84    }
85}
86
87rule less ( n1 n2 )
88{
89    check $(n1) $(n2) ;
90    # avoid messy 0 case by appending 1
91    local l1 = [ range 2 [ log10 $(n1)1 ] ] ;
92    local l2 = [ range 2 [ log10 $(n2)1 ] ] ;
93   
94    # number of digits mismatch?
95    if ( $(l1) < $(l2) ) || ( ( $(l1) = $(l2) ) && $(n1) < $(n2) )
96    {
97        return true ;
98    }
99}
100
101rule log10 ( number )
102{
103    switch $(number)
104    {
105        case *[^0-9]* : error $(number) is not a number ;
106        case 0 : error can't take log of zero ;
107        case [1-9] : return 0 ;
108        case [1-9]? : return 1 ;
109        case [1-9]?? : return 2 ;
110        case [1-9]??? : return 3 ;
111        case [1-9]???? : return 4 ;
112        case [1-9]????? : return 5 ;
113        case [1-9]?????? : return 6 ;
114        case [1-9]??????? : return 7 ;
115        case [1-9]???????? : return 8 ;
116        case [1-9]????????? : return 9 ;
117        case * :
118        {
119            import sequence ;
120            import string ;
121            local chars = [ string.chars $(number) ] ;
122            while $(chars[1]) = 0
123            {
124                chars = $(chars[2-]) ;
125            }
126           
127            if ! $(chars)
128            {
129                error can't take log of zero ;
130            }
131            else
132            {
133                return [ sequence.length $(chars) ] ;
134            }
135        }
136    }
137}
138
139rule __test__ ( )
140{
141    import assert ;
142   
143    assert.result 1 : increment 0 ;
144    assert.result 2 : increment 1 ;
145    assert.result 1 : decrement 2 ;
146    assert.result 0 : decrement 1 ;
147    assert.result 50 : increment 49 ;
148    assert.result 49 : decrement 50 ;
149    assert.result 99 : increment 98 ;
150    assert.result 99 : decrement 100 ;
151    assert.result 100 : increment 99 ;
152    # This just makes debugging output too large
153    # assert.result 1000 : increment 999 ;
154    # assert.result 999 : decrement 1000 ;
155   
156    assert.result 1 2 3 : range 3 ;
157    assert.result 1 2 3 4 5 6 7 8 9 10 11 12 : range 12 ;
158    assert.result 3 4 5 6 7 8 9 10 11 : range 3 11 ;
159    assert.result : range 0 ;
160    assert.result 1 4 7 10 : range 10 : 3 ;
161    assert.result 2 4 6 8 10 : range 2 10 : 2 ;
162    assert.result 25 50 75 100 : range 25 100 : 25 ;
163   
164    assert.true less 1 2 ;
165    assert.true less 1 12 ;
166    assert.true less 1 21 ;
167    assert.false less 0 0 ;
168     
169    # TEMPORARY disabled, because nested "try"/"catch" do not work, I don't the
170    # time to fix that right now.
171    if $(0)
172    {       
173    try ;
174    {
175        decrement 0 ;
176    }
177    catch can't decrement zero! ;
178   
179    try ;
180    {
181        check foo ;
182    }
183    catch : not a number ;
184   
185    try ;
186    {
187        increment foo ;
188    }
189    catch : not a number ;
190       
191    try ;
192    {
193        log10 0 ;
194    }
195    catch can't take log of zero ;
196   
197    try ;
198    {
199        log10 000 ;
200    }
201    catch can't take log of zero ;
202
203    }
204       
205    assert.result 0 : log10 1 ;
206    assert.result 0 : log10 9 ;
207    assert.result 1 : log10 10 ;
208    assert.result 1 : log10 99 ;
209    assert.result 2 : log10 125 ;
210    assert.result 11 : log10 12345678901 ;
211   
212    for local x in [ range 75 110 : 5 ]
213    {
214        for local y in [ range $(x) 111 : 3 ]
215        {
216            if $(x) != $(y)
217            {
218                assert.true less $(x) $(y) ;
219            }
220        }
221    }
222   
223    for local x in [ range 90 110 : 2 ]
224    {
225        for local y in [ range 80 $(x) : 4 ]
226        {
227            assert.false less $(x) $(y) ;
228        }
229    }
230}
Note: See TracBrowser for help on using the repository browser.