[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re6: coreutils v5.2.1 - stat.c
From: |
ThMO |
Subject: |
Re6: coreutils v5.2.1 - stat.c |
Date: |
Fri, 30 Sep 2005 20:00:03 +0200 |
Hello Paul and others listening,
> >> Patches would we welcome here.
> >
>
> Sorry, I should have been clearer.
>
> By "patch" I meant the output of "diff -pu" for all the files you
> changed, along with ChangeLog entries appropriate for each file. We
> should be able to take the existing source code, apply your patch by
> using "patch -p0", and then do a "make check" and everything should
> work just fine. You can see an example patch here:
> <http://lists.gnu.org/archive/html/bug-coreutils/2005-09/msg00202.html>.
>
> Typically the hardest part of writing a patch is the documentation.
> Then the test cases. The source code is the easiest.
I've attached a small ``diff -pu'' file patching 3 files:
· src/factor.c
· test/factor/basic
· Changelog
against coreutils v5.2.1 enhancing factor in order to factorize negative
values too.
Locally it works as expected without any compile-time warning using gcc's
-Wall option along with heavy optimizing.
The things I've added are commented, so you should be able to immediately
see, what's going on.
One word, before you're going to blame me - it's coded with my longstanding
coding style, but if you're willing to integrate it, it should be no problem
to run it through `indent' in order to be compatible with the GNU coding
style, which I dislike.
I've commented out one test inside the perl-script, as I don't know how
to do programming in perl, but I'm sure, that you're able to make even this
test case work.
Also I've added two lines to the Changelog file reflecting the changes.
As I see it, you'll be not able to directly apply this patch againts the
current CVS version, since many things have changed.
THX for listening.
CU Tom.
(Thomas M.Ott)
Germany
--- coreutils-5.2.1/src/factor.c.orig 2004-01-21 23:27:02.000000000 +0100
+++ coreutils-5.2.1/src/factor.c 2005-09-30 19:25:37.000000000 +0200
@@ -91,10 +91,99 @@
exit (status);
}
+/* using a union simplifies cast orgies in order to omit warnings (ThMO) */
+
+union factor {
+ intmax_t sfac;
+ uintmax_t ufac;
+ };
+
+#if HAVE_LONG_LONG
+ #define ONE 1LL
+#else
+ #define ONE 1L
+#endif
+
+/* sfactor(): factorize signed long (long) ints -- (ThMO) */
+
+static int
+sfactor( const intmax_t sn0, const size_t max_n_factors, union factor *factors)
+{
+ intmax_t sn;
+ uintmax_t n, d, q;
+ int n_factors;
+ const unsigned int *w;
+
+ n_factors= 0;
+ switch ( sn= sn0)
+ {
+ case 0: case 1: case -1:
+ return( n_factors);
+
+ case ONE << ( sizeof( sn)* CHAR_BIT- 1):
+ /* handle special case of smallest long (long) int */
+ assert( 2 < max_n_factors);
+ factors[ n_factors++].sfac= -1,
+ factors[ n_factors++].sfac= 2;
+ sn= ONE << ( sizeof( sn)* CHAR_BIT- 2);
+ break;
+
+ default:
+ if ( sn < 0)
+ {
+ assert( 1 < max_n_factors);
+ factors[ n_factors++].sfac= -1;
+ sn= -sn;
+ }
+ break;
+ }
+
+ /* from now on the value is guaranteed to be positive, so force further
+ * calculations with unsigned quantities, since the evaluation of the
+ * remainder from a division will always have the correct sign, unlike
+ * the signed modulus operation - furthermore unsigned division is mostly
+ * somewhat faster than signed division -- (ThMO)
+ */
+ for ( n= (uintmax_t) sn; ( n & 1) == 0; n >>= 1)
+ {
+ /* factorize by 2 the easy way... */
+ assert( n_factors < max_n_factors);
+ factors[ n_factors++].ufac= 2;
+ }
+
+ if ( n >= ( d= 3))
+ {
+ /* this is basically the same algorithm as below - only we'll use
+ * the modulo operator (%), as the remainder will be delivered for
+ * free during division
+ */
+ w= &wheel_tab[ 1];
+ do
+ {
+ while ( q= n/ d, n % d == 0)
+ {
+ assert( n_factors < max_n_factors);
+ factors[ n_factors++].ufac= d;
+ n= q;
+ }
+ d += *w++;
+ if ( w == WHEEL_END)
+ w -= WHEEL_END- WHEEL_START;
+ }
+ while ( d <= q);
+ if ( n > 1)
+ {
+ assert( n_factors < max_n_factors);
+ factors[ n_factors++].ufac= n;
+ }
+ }
+ return( n_factors);
+}
+
/* FIXME: comment */
static int
-factor (uintmax_t n0, int max_n_factors, uintmax_t *factors)
+factor (uintmax_t n0, int max_n_factors, union factor *factors)
{
register uintmax_t n = n0, d, q;
int n_factors = 0;
@@ -118,7 +207,7 @@
while (n == q * d)
{
assert (n_factors < max_n_factors);
- factors[n_factors++] = d;
+ factors[n_factors++].ufac = d;
n = q;
q = n / d;
}
@@ -128,10 +217,10 @@
}
while (d <= q);
- if (n != 1 || n0 == 1)
+ if (n != 1) /* || n0 == 1 <-- can't happen -- (ThMO) */
{
assert (n_factors < max_n_factors);
- factors[n_factors++] = n;
+ factors[n_factors++].ufac = n;
}
return n_factors;
@@ -139,16 +228,41 @@
/* FIXME: comment */
+#define ary_size( t) ( sizeof( (t))/ sizeof( (t)[ 0]) )
+
static int
print_factors (const char *s)
{
- uintmax_t factors[MAX_N_FACTORS];
+ union factor factors[ MAX_N_FACTORS+ 1];
+ intmax_t sn;
uintmax_t n;
int n_factors;
int i;
- char buf[INT_BUFSIZE_BOUND (uintmax_t)];
+ char buf[ 1+ INT_BUFSIZE_BOUND (uintmax_t)];
strtol_error err;
+ if ( ( err= xstrtoimax( s, NULL, 10, &sn, "")) == LONGINT_OK)
+ {
+ /* factorize signed long (long) ints */
+ n_factors= sfactor( sn, ary_size( factors), factors);
+ printf( "%s:", imaxtostr( sn, buf));
+ for ( i= 0; i < n_factors; i++)
+ printf( " %s", imaxtostr( factors[ i].sfac, buf));
+ printf( "\n");
+ return( 0);
+ }
+ else if ( err != LONGINT_OVERFLOW)
+ {
+ error( 0, 0, _( "%s is not a valid integer"), s);
+ return( 1);
+ }
+ else if ( sn < 0) /* --> underflow */
+ {
+ error( 0, 0, _( "%s is too small"), s);
+ return( 1);
+ }
+
+ /* overflowing a signed long (long) int -> try it unsigned then */
if ((err = xstrtoumax (s, NULL, 10, &n, "")) != LONGINT_OK)
{
if (err == LONGINT_OVERFLOW)
@@ -160,7 +274,7 @@
n_factors = factor (n, MAX_N_FACTORS, factors);
printf ("%s:", umaxtostr (n, buf));
for (i = 0; i < n_factors; i++)
- printf (" %s", umaxtostr (factors[i], buf));
+ printf (" %s", umaxtostr (factors[i].ufac, buf));
putchar ('\n');
return 0;
}
--- coreutils-5.2.1/tests/factor/basic.orig 2003-04-08 12:36:44.000000000
+0200
+++ coreutils-5.2.1/tests/factor/basic 2005-09-30 19:27:26.000000000 +0200
@@ -54,10 +54,42 @@ $PERL -e 1 > /dev/null 2>&1 || {
['w', '4294966464', {OUT => '2 2 2 2 2 2 3 3 3 2485513'}],
['x', '4294966896', {OUT => '2 2 2 2 3 3 3 11 607 1489'}],
['y', '4294966998', {OUT => '2 3 7 3917 26107'}],
- ['z', '-1',
- {ERR => "$prog: `-1' is not a valid positive integer\n"
- . "Try `$prog --help' for more information.\n"},
- {EXIT => 1}],
+# ['z', '-1',
+# {ERR => "$prog: `-1' is not a valid positive integer\n"
+# . "Try `$prog --help' for more information.\n"},
+# {EXIT => 1}],
+
+ ['M1', '-9', {OUT => '-1 3 3'}],
+ ['M1a', '-7', {OUT => '-1 7'}],
+ ['M2', '-4294967291', {OUT => '-1 4294967291'}],
+ ['M3', '-4294967292', {OUT => '-1 2 2 3 3 7 11 31 151 331'}],
+ ['M4', '-4294967293', {OUT => '-1 9241 464773'}],
+
+ ['Ma', '-4294966201', {OUT => '-1 12197 352133'}],
+ ['Mb', '-4294966339', {OUT => '-1 13187 325697'}],
+ ['Mc', '-4294966631', {OUT => '-1 13729 312839'}],
+ ['Md', '-4294966457', {OUT => '-1 14891 288427'}],
+ ['Me', '-4294966759', {OUT => '-1 21649 198391'}],
+ ['Mf', '-4294966573', {OUT => '-1 23071 186163'}],
+ ['Mg', '-4294967101', {OUT => '-1 23603 181967'}],
+ ['Mh', '-4294966519', {OUT => '-1 34583 124193'}],
+ ['Mi', '-4294966561', {OUT => '-1 36067 119083'}],
+ ['Mj', '-4294966901', {OUT => '-1 37747 113783'}],
+ ['Mk', '-4294966691', {OUT => '-1 39241 109451'}],
+ ['Ml', '-4294966969', {OUT => '-1 44201 97169'}],
+ ['Mm', '-4294967099', {OUT => '-1 44483 96553'}],
+ ['Mn', '-4294966271', {OUT => '-1 44617 96263'}],
+ ['Mo', '-4294966789', {OUT => '-1 50411 85199'}],
+ ['Mp', '-4294966189', {OUT => '-1 53197 80737'}],
+ ['Mq', '-4294967213', {OUT => '-1 57139 75167'}],
+ ['Ms', '-4294967071', {OUT => '-1 65521 65551'}],
+ ['Mt', '-4294966194', {OUT => '-1 2 3 3 3 3 3 3 3 53 97 191'}],
+ ['Mu', '-4294966272', {OUT => '-1 2 2 2 2 2 2 2 2 2 2 3 23 89 683'}],
+ ['Mv', '-4294966400', {OUT => '-1 2 2 2 2 2 2 2 5 5 1342177'}],
+ ['Mw', '-4294966464', {OUT => '-1 2 2 2 2 2 2 3 3 3 2485513'}],
+ ['Mx', '-4294966896', {OUT => '-1 2 2 2 2 3 3 3 11 607 1489'}],
+ ['My', '-4294966998', {OUT => '-1 2 3 7 3917 26107'}],
+ ['Mz', '-2147483648', {OUT => '-1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2'}],
);
# Prepend the command line argument and append a newline to end
--- coreutils-5.2.1/ChangeLog.orig 2004-03-12 20:03:44.000000000 +0100
+++ coreutils-5.2.1/ChangeLog 2005-09-30 19:30:24.000000000 +0200
@@ -1,3 +1,8 @@
+2005-09-30 Thomas M. Ott <address@hidden>
+
+ * src/factor.c: added factorizing of negative values
+ * test/factor/basic: add some test clauses
+
2004-03-12 Jim Meyering <address@hidden>
* Version 5.2.1.
- Re: Re2: coreutils v5.2.1 - stat.c, (continued)
- Re: Re2: coreutils v5.2.1 - stat.c, Bob Proulx, 2005/09/29
- Re3: coreutils v5.2.1 - stat.c, ThMO, 2005/09/29
- Re: Re3: coreutils v5.2.1 - stat.c, Paul Eggert, 2005/09/29
- Re4: coreutils v5.2.1 - stat.c, ThMO, 2005/09/29
- Re: Re4: coreutils v5.2.1 - stat.c, Paul Eggert, 2005/09/29
- coreutils man pages "info sort" -> "info coreutils sort", Paul Eggert, 2005/09/29
- Re: coreutils man pages "info sort" -> "info coreutils sort", Jim Meyering, 2005/09/29
- Re: coreutils man pages "info sort" -> "info coreutils sort", ThMO, 2005/09/29
- Re: coreutils man pages "info sort" -> "info coreutils sort", ThMO, 2005/09/29
- Re: Re3: coreutils v5.2.1 - stat.c, Paul Eggert, 2005/09/29
- Re6: coreutils v5.2.1 - stat.c,
ThMO <=
- Re: Re6: coreutils v5.2.1 - stat.c, Paul Eggert, 2005/09/30