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