On Tuesday 27 July 2010 17:01, Cristian Ionescu-Idbohrn wrote:
> My experiments show differences to host 'dc'.
> 
> Starting with this INT64_MAX=9223372036854775807 dividend.
> bb 'dc' can't cope with such big integers:
> 
>  1. FAILED: '9223372036854775807 % 2' -> bb: 0, host: 1
>  2. FAILED: '4611686018427387903 % 2' -> bb: 0, host: 1
>  3. FAILED: '2305843009213693951 % 2' -> bb: 0, host: 1
>  4. FAILED: '1152921504606846975 % 2' -> bb: 0, host: 1
>  5. FAILED: '576460752303423487 % 2' -> bb: 0, host: 1
>  6. FAILED: '288230376151711743 % 2' -> bb: 0, host: 1
>  7. FAILED: '144115188075855871 % 2' -> bb: 0, host: 1
>  8. FAILED: '72057594037927935 % 2' -> bb: 0, host: 1
>  9. FAILED: '36028797018963967 % 2' -> bb: 0, host: 1
> 10. FAILED: '18014398509481983 % 2' -> bb: 0, host: 1
> 
> but starts working here:
> 
> 11. SUCCEDED: '9007199254740991 % 2' -> bb: 1, host: 1
> 12. SUCCEDED: '4503599627370495 % 2' -> bb: 1, host: 1
> 
> and all the way down.  Still, the unsigned int cast should prevent it
> from working until the UINT32_MAX=4294967295 dividend is reached.  True?
> 
> 
> Checking the divisor now.  Starting with 2:
> 
>  1. SUCCEDED: '18014398509481982 % 2' -> bb: 0, host: 0
>  2. SUCCEDED: '18014398509481982 % 4' -> bb: 2, host: 2
> 
> bb 'dc' copes with divisors up to 524288:
> 
> 18. SUCCEDED: '18014398509481982 % 262144' -> bb: 262142, host: 262142
> 19. SUCCEDED: '18014398509481982 % 524288' -> bb: 524286, host: 524286
> 
> works even further, but starts showing float formated numbers:
> 
> 20. FAILED: '18014398509481982 % 1048576' -> bb: 1.04857e+06, host: 1048574
> 21. FAILED: '18014398509481982 % 2097152' -> bb: 2.09715e+06, host: 2097150
> 
> up to a point INT32_MAX=2147483647:
> 
> 31. FAILED: '18014398509481982 % 2147483648' -> bb: 2.14748e+09, host: 
> 2147483646
> 
> and then, at UINT32_MAX=4294967295 divisor, stops working:
> 
> 32. FAILED: '18014398509481982 % 4294967296' -> bb: ???, host: 4294967294
> 
> But host 'dc' keeps working:
> 
> 51. FAILED: '18014398509481982 % 2251799813685248' -> bb: ???, host: 
> 2251799813685246
> 52. FAILED: '18014398509481982 % 4503599627370496' -> bb: ???, host: 
> 4503599627370494
> 53. FAILED: '18014398509481982 % 9007199254740992' -> bb: ???, host: 
> 9007199254740990
> 
> Things improve with this attempt:
> 
> --- busybox/miscutils/dc.c.orig       2010-07-27 16:22:22.000000000 +0200
> +++ busybox/miscutils/dc.c.cii2       2010-07-27 16:44:37.000000000 +0200
> @@ -73,9 +73,9 @@
> 
>  static void mod(void)
>  {
> -     unsigned d = pop();
> +     uint64_t d = (uint64_t) pop();
> 
> -     push((unsigned) pop() % d);
> +     push((uint64_t) pop() % d);
>  }
> 
>  static void and(void)
> 
> in the divisor area.  Results still show up as float formated numbers,
> but it works with big divisors:
> 
> 52. FAILED: '18014398509481982 % 4503599627370496' -> bb: 4.5036e+15, host: 
> 4503599627370494
> 53. FAILED: '18014398509481982 % 9007199254740992' -> bb: 9.0072e+15, host: 
> 9007199254740990

Try attached patch.

# ./busybox dc 18014398509481982 4503599627370496 mod p
4503599627370494
# ./busybox dc 18014398509481982 9007199254740992 mod p
9007199254740990


function                                             old     new   delta
print_base                                           176     238     +62
or                                                    91     103     +12
eor                                                   91     103     +12
and                                                   91     103     +12
not                                                   60      64      +4
mod                                                  103     105      +2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 6/0 up/down: 104/0)             Total: 104 bytes

-- 
vda
diff -ad -urpN busybox.4/miscutils/dc.c busybox.5/miscutils/dc.c
--- busybox.4/miscutils/dc.c	2010-07-25 00:17:46.000000000 +0200
+++ busybox.5/miscutils/dc.c	2010-07-29 03:53:59.000000000 +0200
@@ -8,6 +8,17 @@
 
 /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
 
+#if 0
+typedef unsigned data_t;
+#define DATA_FMT ""
+#elif 0
+typedef unsigned long data_t;
+#define DATA_FMT "l"
+#else
+typedef unsigned long long data_t;
+#define DATA_FMT "ll"
+#endif
+
 
 struct globals {
 	unsigned pointer;
@@ -73,29 +84,29 @@ static void divide(void)
 
 static void mod(void)
 {
-	unsigned d = pop();
+	data_t d = pop();
 
-	push((unsigned) pop() % d);
+	push((data_t) pop() % d);
 }
 
 static void and(void)
 {
-	push((unsigned) pop() & (unsigned) pop());
+	push((data_t) pop() & (data_t) pop());
 }
 
 static void or(void)
 {
-	push((unsigned) pop() | (unsigned) pop());
+	push((data_t) pop() | (data_t) pop());
 }
 
 static void eor(void)
 {
-	push((unsigned) pop() ^ (unsigned) pop());
+	push((data_t) pop() ^ (data_t) pop());
 }
 
 static void not(void)
 {
-	push(~(unsigned) pop());
+	push(~(data_t) pop());
 }
 
 static void set_output_base(void)
@@ -112,25 +123,30 @@ static void set_output_base(void)
 
 static void print_base(double print)
 {
-	unsigned x, i;
+	data_t x, i;
 
+	x = (data_t) print;
 	if (base == 10) {
-		printf("%g\n", print);
+		if (x == print) /* exactly representable as unsigned integer */
+			printf("%"DATA_FMT"u\n", x);
+		else
+			printf("%g\n", print);
 		return;
 	}
 
-	x = (unsigned)print;
 	switch (base) {
 	case 16:
-		printf("%x\n", x);
+		printf("%"DATA_FMT"x\n", x);
 		break;
 	case 8:
-		printf("%o\n", x);
+		printf("%"DATA_FMT"o\n", x);
 		break;
 	default: /* base 2 */
-		i = (unsigned)INT_MAX + 1;
+		i = MAXINT(data_t) - (MAXINT(data_t) >> 1);
+		/* i is 100000...00000 */
 		do {
-			if (x & i) break;
+			if (x & i)
+				break;
 			i >>= 1;
 		} while (i > 1);
 		do {
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to