libroot/posix/stdio: Remove unused portions.
[haiku.git] / build / jam / MathRules
blob10f006c80796654dd917289974a7e77a1d5c2b76
1 # Rules providing basic arithmetic operations
3 HAIKU_ZERO = + 0 ;
4 HAIKU_ONE = + 1 ;
6 HAIKU_PAD_9 = 0 1 2 3 4 5 6 7 8 ;
8 # a > b <==> $(HAIKU_DIGIT_GREATER_$(a)[1$(b)])
9 HAIKU_DIGIT_GREATER_0 = $(HAIKU_PAD_9) ;
10 HAIKU_DIGIT_GREATER_1 = $(HAIKU_PAD_9) 1 ;
11 HAIKU_DIGIT_GREATER_2 = $(HAIKU_PAD_9) 1 1 ;
12 HAIKU_DIGIT_GREATER_3 = $(HAIKU_PAD_9) 1 1 1 ;
13 HAIKU_DIGIT_GREATER_4 = $(HAIKU_PAD_9) 1 1 1 1 ;
14 HAIKU_DIGIT_GREATER_5 = $(HAIKU_PAD_9) 1 1 1 1 1 ;
15 HAIKU_DIGIT_GREATER_6 = $(HAIKU_PAD_9) 1 1 1 1 1 1 ;
16 HAIKU_DIGIT_GREATER_7 = $(HAIKU_PAD_9) 1 1 1 1 1 1 1 ;
17 HAIKU_DIGIT_GREATER_8 = $(HAIKU_PAD_9) 1 1 1 1 1 1 1 1 ;
18 HAIKU_DIGIT_GREATER_9 = $(HAIKU_PAD_9) 1 1 1 1 1 1 1 1 1 ;
20 # a + b == $(HAIKU_DIGIT_ADD_$(a)[1$(b)]) (carry ignored)
21 HAIKU_DIGIT_ADD_0 = $(HAIKU_PAD_9) 0 1 2 3 4 5 6 7 8 9 ;
22 HAIKU_DIGIT_ADD_1 = $(HAIKU_PAD_9) 1 2 3 4 5 6 7 8 9 0 ;
23 HAIKU_DIGIT_ADD_2 = $(HAIKU_PAD_9) 2 3 4 5 6 7 8 9 0 1 ;
24 HAIKU_DIGIT_ADD_3 = $(HAIKU_PAD_9) 3 4 5 6 7 8 9 0 1 2 ;
25 HAIKU_DIGIT_ADD_4 = $(HAIKU_PAD_9) 4 5 6 7 8 9 0 1 2 3 ;
26 HAIKU_DIGIT_ADD_5 = $(HAIKU_PAD_9) 5 6 7 8 9 0 1 2 3 4 ;
27 HAIKU_DIGIT_ADD_6 = $(HAIKU_PAD_9) 6 7 8 9 0 1 2 3 4 5 ;
28 HAIKU_DIGIT_ADD_7 = $(HAIKU_PAD_9) 7 8 9 0 1 2 3 4 5 6 ;
29 HAIKU_DIGIT_ADD_8 = $(HAIKU_PAD_9) 8 9 0 1 2 3 4 5 6 7 ;
30 HAIKU_DIGIT_ADD_9 = $(HAIKU_PAD_9) 9 0 1 2 3 4 5 6 7 8 ;
32 # a - b == $(HAIKU_DIGIT_SUB_$(a)[1$(b)]) (carry ignored)
33 HAIKU_DIGIT_SUB_0 = $(HAIKU_PAD_9) 0 9 8 7 6 5 4 3 2 1 ;
34 HAIKU_DIGIT_SUB_1 = $(HAIKU_PAD_9) 1 0 9 8 7 6 5 4 3 2 ;
35 HAIKU_DIGIT_SUB_2 = $(HAIKU_PAD_9) 2 1 0 9 8 7 6 5 4 3 ;
36 HAIKU_DIGIT_SUB_3 = $(HAIKU_PAD_9) 3 2 1 0 9 8 7 6 5 4 ;
37 HAIKU_DIGIT_SUB_4 = $(HAIKU_PAD_9) 4 3 2 1 0 9 8 7 6 5 ;
38 HAIKU_DIGIT_SUB_5 = $(HAIKU_PAD_9) 5 4 3 2 1 0 9 8 7 6 ;
39 HAIKU_DIGIT_SUB_6 = $(HAIKU_PAD_9) 6 5 4 3 2 1 0 9 8 7 ;
40 HAIKU_DIGIT_SUB_7 = $(HAIKU_PAD_9) 7 6 5 4 3 2 1 0 9 8 ;
41 HAIKU_DIGIT_SUB_8 = $(HAIKU_PAD_9) 8 7 6 5 4 3 2 1 0 9 ;
42 HAIKU_DIGIT_SUB_9 = $(HAIKU_PAD_9) 9 8 7 6 5 4 3 2 1 0 ;
44 # a * b == $(HAIKU_DIGIT_MULT_CARRY_$(a)[1$(b)]) $(HAIKU_DIGIT_MULT_$(a)[1$(b)])
45 HAIKU_DIGIT_MULT_0 = $(HAIKU_PAD_9) 0 0 0 0 0 0 0 0 0 0 ;
46 HAIKU_DIGIT_MULT_1 = $(HAIKU_PAD_9) 0 1 2 3 4 5 6 7 8 9 ;
47 HAIKU_DIGIT_MULT_2 = $(HAIKU_PAD_9) 0 2 4 6 8 0 2 4 6 8 ;
48 HAIKU_DIGIT_MULT_3 = $(HAIKU_PAD_9) 0 3 6 9 2 5 8 1 4 7 ;
49 HAIKU_DIGIT_MULT_4 = $(HAIKU_PAD_9) 0 4 8 2 6 0 4 8 2 6 ;
50 HAIKU_DIGIT_MULT_5 = $(HAIKU_PAD_9) 0 5 0 5 0 5 0 5 0 5 ;
51 HAIKU_DIGIT_MULT_6 = $(HAIKU_PAD_9) 0 6 2 8 4 0 6 2 8 4 ;
52 HAIKU_DIGIT_MULT_7 = $(HAIKU_PAD_9) 0 7 4 1 8 5 2 9 6 3 ;
53 HAIKU_DIGIT_MULT_8 = $(HAIKU_PAD_9) 0 8 6 4 2 0 8 6 4 2 ;
54 HAIKU_DIGIT_MULT_9 = $(HAIKU_PAD_9) 0 9 8 7 6 5 4 3 2 1 ;
56 HAIKU_DIGIT_MULT_CARRY_0 = $(HAIKU_PAD_9) 0 0 0 0 0 0 0 0 0 0 ;
57 HAIKU_DIGIT_MULT_CARRY_1 = $(HAIKU_PAD_9) 0 0 0 0 0 0 0 0 0 0 ;
58 HAIKU_DIGIT_MULT_CARRY_2 = $(HAIKU_PAD_9) 0 0 0 0 0 1 1 1 1 1 ;
59 HAIKU_DIGIT_MULT_CARRY_3 = $(HAIKU_PAD_9) 0 0 0 0 1 1 1 2 2 2 ;
60 HAIKU_DIGIT_MULT_CARRY_4 = $(HAIKU_PAD_9) 0 0 0 1 1 2 2 2 3 3 ;
61 HAIKU_DIGIT_MULT_CARRY_5 = $(HAIKU_PAD_9) 0 0 1 1 2 2 3 3 4 4 ;
62 HAIKU_DIGIT_MULT_CARRY_6 = $(HAIKU_PAD_9) 0 0 1 1 2 3 3 4 4 5 ;
63 HAIKU_DIGIT_MULT_CARRY_7 = $(HAIKU_PAD_9) 0 0 1 2 2 3 4 4 5 6 ;
64 HAIKU_DIGIT_MULT_CARRY_8 = $(HAIKU_PAD_9) 0 0 1 2 3 4 4 5 6 7 ;
65 HAIKU_DIGIT_MULT_CARRY_9 = $(HAIKU_PAD_9) 0 0 1 2 3 4 5 6 7 8 ;
68 # pragma mark - Number Operations
71 rule NormalizeNum number
73         # NormalizeNum <number> ;
75         local sign ;
76         if $(number[1]) = "-" || $(number[1] = "+" {
77                 sign = $(number[1]) ;
78                 number = $(number[2-]) ;
79         } else {
80                 sign = "+" ;
81         }
83         # cut off leading zeros
84         local number = [ FReverse $(number) ] ;
85         while $(number[1]) = 0 {
86                 number = $(number[2-]) ;
87         }
88         number = [ FReverse $(number) ] ;
90         # zero is respresented as + 0
91         if ! $(number) {
92                 number = 0 ;
93                 sign = "+" ;
94         }
96         return $(sign) $(number) ;
99 rule Num string : dontExit
101         # Num <number string> [ : <dontExit> ] ;
103         # split the string into three parts: sign, digits, and remainder
104         local temp = [ Match ([^0-9]*)([0-9]+)(.*) : $(string) ] ;
106         # there must be digits, but there must not be a remainder
107         if ! $(temp[2]) || $(temp[3]) {
108                 if $(dontExit) {
109                         return ;
110                 }
111                 Exit "Not a number" ;
112         }
114         # get the sign
115         local number ;
116         if ! $(temp[1]) {
117                 number = "+" ;
118         } else if $(temp[1]) = "+" || $(temp[1]) = "-" {
119                 number = $(temp[1]) ;
120         } else {
121                 if $(dontExit) {
122                         return ;
123                 }
124                 Exit "Not a number (sign)" ;
125         }
127         # split the digits
128         temp = $(temp[2]) ;
129         while $(temp[1]) {
130                 # split off the last digit
131                 temp = [ Match (.*)([0-9]) : $(temp[1]) ] ;
132                 number += $(temp[2]) ;
133         }
135         # normalize
136         return [ NormalizeNum $(number) ] ;
139 rule Num2String number
141         # Num2String <number> ;
143         local sign = $(number[1]) ;
144         if $(sign) = "+" {
145                 sign = "" ;
146         }
148         number = [ FReverse $(number[2-]) ] ;
150         return $(sign)$(number:J=) ;
153 rule NumGreaterAbs a : b
155         # NumGreaterAbs <a> : <b> ;
157         # we compare from least to most significant digit
158         local cmp = 0 ;
159         while $(a) && $(b) {
160                 # chop off the first digit
161                 local da = $(a[1]:E=0) ;
162                 local db = $(b[1]:E=0) ;
163                 a = $(a[2-]) ;
164                 b = $(b[2-]) ;
166                 if $(da) != $(db) {
167                         if $(HAIKU_DIGIT_GREATER_$(da)[1$(db)]) {
168                                 cmp = 1 ;
169                         } else {
170                                 cmp = -1 ;
171                         }
172                 }
173         }
175         # a is greater, if b is not longer and a is either longer or equally long
176         # and greater according to the digits comparison
177         if ! $(b) && ( $(a) || $(cmp) = 1 ) {
178                 return 1 ;
179         }
180         return ;
183 rule AddNumAbs a : b
185         # AddNum <a> : <b> ;
187         local result ;
188         local carry ;
189         while $(a) || $(b) || $(carry) {
190                 # chop off the first digit
191                 local da = $(a[1]:E=0) ;
192                 local db = $(b[1]:E=0) ;
193                 a = $(a[2-]) ;
194                 b = $(b[2-]) ;
196                 # add carry to the first digit
197                 if $(carry) {
198                         local daa = $(HAIKU_DIGIT_ADD_1[1$(da)]) ;
199                         carry = $(HAIKU_DIGIT_GREATER_$(da)[1$(daa)]) ;
200                         da = $(daa) ;
201                 }
203                 # add digits
204                 local dr = $(HAIKU_DIGIT_ADD_$(da)[1$(db)]) ;
205                 if $(HAIKU_DIGIT_GREATER_$(da)[1$(dr)]) {
206                         carry = 1 ;
207                 }
209                 result += $(dr) ;
210         }
212         return $(result) ;
215 rule SubNumAbs a : b
217         # SubNum <a> : <b> ;
219         local result ;
220         local carry ;
221         while $(a) && ( $(b) || $(carry) ) {
222                 # chop off the first digit
223                 local da = $(a[1]:E=0) ;
224                 local db = $(b[1]:E=0) ;
225                 a = $(a[2-]) ;
226                 b = $(b[2-]) ;
228                 # sub carry from the first digit
229                 if $(carry) {
230                         local daa = $(HAIKU_DIGIT_SUB_$(da)[11]) ;
231                         carry = $(HAIKU_DIGIT_GREATER_$(daa)[1$(da)]) ;
232                         da = $(daa) ;
233                 }
235                 # sub digits
236                 local dr = $(HAIKU_DIGIT_SUB_$(da)[1$(db)]) ;
237                 if $(HAIKU_DIGIT_GREATER_$(dr)[1$(da)]) {
238                         carry = 1 ;
239                 }
241                 result += $(dr) ;
242         }
244         if $(b) || $(carry) {
245                 Exit "Error: SubNumAbs: Can't subtract greater from smaller number." ;
246         }
248         return $(result) ;
251 rule NegNum a
253         # NegNum <a> ;
255         if $(a[1]) = "+" {
256                 if $(a) = $(HAIKU_ZERO) {
257                         return $(a) ;
258                 }
259                 return "-" $(a[2-]) ;
260         } else {
261                 return "+" $(a[2-]) ;
262         }
265 rule AddNum a : b
267         # AddNum <a> : <b> ;
269         local signa = $(a[1]) ;
270         local signb = $(b[1]) ;
271         a = $(a[2-]) ;
272         b = $(b[2-]) ;
274         if $(signa) = $(signb) {
275                 return $(signa) [ AddNumAbs $(a) : $(b) ] ;
276         } else {
277                 local result ;
278                 if [ NumGreaterAbs $(a) : $(b) ] {
279                         result = $(signa) [ SubNumAbs $(a) : $(b) ] ;
280                 } else {
281                         result = $(signb) [ SubNumAbs $(b) : $(a) ] ;
282                 }
283                 return [ NormalizeNum $(result) ] ;
284         }
287 rule SubNum a : b
289         # SubNum <a> : <b> ;
290         return [ AddNum $(a) : [ NegNum $(b) ] ] ;
293 rule MultNumAbsDigit a : digit
295         # MultNumAbsDigit <a> : <digit> ;
297         local digitMultiples = $(HAIKU_DIGIT_MULT_$(digit)) ;
298         local digitCarries = $(HAIKU_DIGIT_MULT_CARRY_$(digit)) ;
300         local result ;
301         local carry = 0 ;
302         while $(a) || $(carry) != 0 {
303                 # chop off the first digit
304                 local da = $(a[1]:E=0) ;
305                 a = $(a[2-]) ;
307                 local dr = $(digitMultiples[1$(da)]) ;
309                 # add carry to the resulting digit
310                 if $(carry) {
311                         local dra = $(HAIKU_DIGIT_ADD_$(dr)[1$(carry)]) ;
312                         carry = $(HAIKU_DIGIT_GREATER_$(dr)[1$(dra)]:E=0) ;
313                         dr = $(dra) ;
314                 }
316                 # new carry
317                 carry = $(HAIKU_DIGIT_ADD_$(carry:E=0)[1$(digitCarries[1$(da)])]) ;
319                 result += $(dr) ;
320         }
322         return $(result) ;
325 rule MultNum a : b
327         # MultNum <a> : <b> ;
329         # If one of the factors is 0, we save us computation and normalization.
330         if $(a) = $(HAIKU_ZERO) || $(b) = $(HAIKU_ZERO) {
331                 return $(HAIKU_ZERO) ;
332         }
334         # get the sign for the result
335         local sign = "+" ;
336         if $(a[1]) != $(b[1]) {
337                 sign = "-" ;
338         }
340         a = $(a[2-]) ;
341         b = $(b[2-]) ;
343         # multiply the individual digits of b with a and add up the result
344         local result = 0 ;
345         local prefix ;
346         while $(b) {
347                 local db = $(b[1]) ;
348                 b = $(b[2-]) ;
350                 local adb = $(prefix) [ MultNumAbsDigit $(a) : $(db) ] ;
351                 result = [ AddNumAbs $(result) : $(adb) ] ;
353                 prefix += 0 ;
354         }
356         return $(sign) $(result) ;
359 rule NumGreater a : b
361         local signa = $(a[1]) ;
362         local signb = $(b[1]) ;
363         a = $(a[2-]) ;
364         b = $(b[2-]) ;
366         if $(signa) = $(signb) {
367                 if $(signa) = "+" {
368                         return [ NumGreaterAbs $(a) : $(b) ] ;
369                 } else {
370                         return [ NumGreaterAbs $(b) : $(a) ] ;
371                 }
372         } else {
373                 if $(signa) = "+" {
374                         return 1 ;
375                 } else {
376                         return ;
377                 }
378         }
382 # pragma mark - Number String Operations
385 rule Inc a
387         # Inc <number string a> ;
388         return [ Num2String [ AddNum [ Num $(a) ] : + 1 ] ] ;
391 rule Dec a
393         # Dec <number string a> ;
394         return [ Num2String [ AddNum [ Num $(a) ] : - 1 ] ] ;
397 rule Neg a
399         # Neg <number string a> ;
400         return [ Num2String [ NegNum [ Num $(a) ] ] ] ;
403 rule Add a : b
405         # Add <number string a> : <number string b> ;
406         return [ Num2String [ AddNum [ Num $(a) ] : [ Num $(b) ] ] ] ;
409 rule Sub a : b
411         # Sub <number string a> : <number string b> ;
412         return [ Num2String [ SubNum [ Num $(a) ] : [ Num $(b) ] ] ] ;
415 rule Mult a : b
417         # Mult <number string a> : <number string b> ;
418         return [ Num2String [ MultNum [ Num $(a) ] : [ Num $(b) ] ] ] ;
421 rule Equal a : b
423         # Equal <number string a> : <number string b> ;
424         if [ Num $(a) ] = [ Num $(b) ] {
425                 return 1 ;
426         }
428         return ;
431 rule Less a : b
433         # Less <number string a> : <number string b> ;
434         return [ NumGreater [ Num $(b) ] : [ Num $(a) ] ] ;
437 rule Greater a : b
439         # Greater <number string a> : <number string b> ;
440         return [ NumGreater [ Num $(a) ] : [ Num $(b) ] ] ;
443 rule LessOrEqual a : b
445         # LessOrEqual <number string a> : <number string b> ;
446         if [ NumGreater [ Num $(a) ] : [ Num $(b) ] ] {
447                 return ;
448         }
449         return 1 ;
452 rule GreaterOrEqual a : b
454         # GreaterOrEqual <number string a> : <number string b> ;
455         if [ NumGreater [ Num $(b) ] : [ Num $(a) ] ] {
456                 return ;
457         }
458         return 1 ;
462 # pragma mark - Expression Parser
465 rule ParseAtom expression
467         # ParseAtom <expression> ;
469         # expression: '(' expression ')' | number
471         if $(expression[1]) = "(" {
472                 local result = [ ParseExpression $(expression[2-]) ] ;
473                 if $(result[2]) != ")" {
474                         Exit "ParseAtom: Parse error: Expected \")\"." ;
475                 }
476                 return $(result[1]) $(result[3-]) ;
477         } else {
478                 if ! $(expression) {
479                         Exit "ParseAtom: Parse error: Unexpected end of expression." ;
480                 }
482                 local num = [ Num $(expression[1]) : 1 ] ;
483                 if ! $(num) {
484                         Exit "ParseAtom: Parse error: Expected number instead of:"
485                                 $(expression[1]) ;
486                 }
488                 return [ Num2String $(num) ] $(expression[2-]) ;
489         }
492 rule ParseUnary expression
494         # ParseUnary <expression> ;
496         # expression: ('+'/'-')* atom
498         if ! $(expression) {
499                 Exit "ParseUnary: Parse error: Unexpected end of expression." ;
500         }
502         # eat all unary "+" and "-" operations
503         local neg ;
504         while $(expression[1]) = "+" || $(expression[1]) = "-" {
505                 if $(expression[1]) = "-" {
506                         if $(neg) {
507                                 neg = ;
508                         } else {
509                                 neg = 1 ;
510                         }
511                 }
513                 expression = $(expression[2-]) ;
514         }
516         local result = [ ParseAtom $(expression) ] ;
518         if $(neg) {
519                 return [ Neg $(result[1]) ] $(result[2-]) ;
520         }
521         return $(result) ;
524 rule ParseTerm expression
526         # ParseTerm <expression> ;
528         # expression: unary ('*' unary)*
530         local result = [ ParseUnary $(expression) ] ;
531         local product = $(result[1]) ;
532         expression = $(result[2-]) ;
534         while $(expression[1]) = "*" {
535                 # get the operation
536                 local operation ;
537                 operation = Mult ;
539                 # parse the next operand
540                 result = [ ParseUnary $(expression[2-]) ] ;
541                 expression = $(result[2-]) ;
543                 # compute the product
544                 product = [ $(operation) $(product) : $(result[1]) ] ;
545         }
547         return $(product) $(expression) ;
550 rule ParseExpression expression
552         # ParseExpression <expression> ;
554         # expression: term ('+'/'-' term)*
556         local result = [ ParseTerm $(expression) ] ;
557         local sum = $(result[1]) ;
558         expression = $(result[2-]) ;
560         while $(expression[1]) = "+" || $(expression[1]) = "-" {
561                 # get the operation
562                 local operation ;
563                 if $(expression[1]) = "+" {
564                         operation = Add ;
565                 } else {
566                         operation = Sub ;
567                 }
569                 # parse the next operand
570                 result = [ ParseTerm $(expression[2-]) ] ;
571                 expression = $(result[2-]) ;
573                 # compute the sum
574                 sum = [ $(operation) $(sum) : $(result[1]) ] ;
575         }
577         return $(sum) $(expression) ;
581 rule Expr expression
583         # Expr <expression> ;
585         # tokenize the expression
586         local tokens ;
587         local string ;
588         for string in $(expression) {
589                 while $(string) {
590                         local split = [ Match "[ \t]*(-|[()+*]|[0-9]*)(.*)" : $(string) ] ;
591                         if ! $(split[1]) {
592                                 Exit "Expr: Syntax error: Invalid token: \"$(string)\"." ;
593                         }
595                         tokens += $(split[1]) ;
596                         string = $(split[2]) ;
597                 }
598         }
600         local result = [ ParseExpression $(tokens) ] ;
601         if $(result[2-]) {
602                 Exit "Expr: Garbage at end of expression:" $(result[2-]) ;
603         }
605         return $(result[1]) ;