bug-coreutils
[Top][All Lists]
Advanced

[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.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]