Retire rabinpoly fingerprinting code
authorJunio C Hamano <junkio@cox.net>
Thu, 27 Apr 2006 19:48:26 +0000 (12:48 -0700)
committerJunio C Hamano <junkio@cox.net>
Thu, 27 Apr 2006 19:48:26 +0000 (12:48 -0700)
For now let's retire this and reintroduce it as part of the updated
pack-objects series from Geert when it is ready.

Signed-off-by: Junio C Hamano <junkio@cox.net>
.gitignore
Makefile
gsimm.c [deleted file]
gsimm.h [deleted file]
rabinpoly.c [deleted file]
rabinpoly.h [deleted file]
test-gsimm.c [deleted file]

index cdb2d53..7906909 100644 (file)
@@ -124,7 +124,6 @@ git-core-*/?*
 test-date
 test-delta
 test-dump-cache-tree
-test-gsimm
 common-cmds.h
 *.tar.gz
 *.dsc
index 9bf6c80..d2cc01a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -614,9 +614,6 @@ test-delta$X: test-delta.c diff-delta.o patch-delta.o
 test-dump-cache-tree$X: dump-cache-tree.o $(GITLIBS)
        $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 
-test-gsimm$X: test-gsimm.c gsimm.o rabinpoly.o
-       $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^
-
 check:
        for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
 
@@ -665,7 +662,6 @@ clean:
        rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \
                $(LIB_FILE) $(XDIFF_LIB)
        rm -f $(ALL_PROGRAMS) $(BUILT_INS) git$X
-       rm -f test-date$X test-delta$X test-gsimm$X
        rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags
        rm -rf $(GIT_TARNAME)
        rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
diff --git a/gsimm.c b/gsimm.c
deleted file mode 100644 (file)
index 7024bf8..0000000
--- a/gsimm.c
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "rabinpoly.h"
-#include "gsimm.h"
-
-/* Has to be power of two. Since the Rabin hash only has 63
-   usable bits, the number of hashes is limited to 32.
-   Lower powers of two could be used for speeding up processing
-   of very large files.  */
-#define NUM_HASHES_PER_CHAR 32
-
-/* Size of cache used to eliminate duplicate substrings.
-   Make small enough to comfortably fit in L1 cache.  */
-#define DUP_CACHE_SIZE 256
-
-/* For the final counting, do not count each bit individually, but
-   group them. Must be power of two, at most NUM_HASHES_PER_CHAR.
-   However, larger sizes result in higher cache usage. Use 8 bits
-   per group for efficient processing of large files on fast machines
-   with decent caches, or 4 bits for faster processing of small files
-   and for machines with small caches.  */
-#define GROUP_BITS 4
-#define GROUP_COUNTERS (1<<GROUP_BITS)
-
-static void freq_to_md(u_char *md, int *freq)
-{ int j, k;
-
-  for (j = 0; j < MD_LENGTH; j++)
-  { u_char ch = 0;
-
-    for (k = 0; k < 8; k++) ch = 2*ch + (freq[8*j+k] > 0);
-    md[j] = ch;
-  }
-  bzero (freq, sizeof(freq[0]) * MD_BITS);
-}
-
-void gb_simm_process(u_char *data, unsigned len, u_char *md)
-{ size_t j = 0;
-  u_int32_t ofs;
-  u_int32_t dup_cache[DUP_CACHE_SIZE];
-  u_int32_t count [MD_BITS * (GROUP_COUNTERS/GROUP_BITS)];
-  int freq[MD_BITS];
-
-  bzero (freq, sizeof(freq[0]) * MD_BITS);
-  bzero (dup_cache, DUP_CACHE_SIZE * sizeof (u_int32_t));
-  bzero (count, (MD_BITS * (GROUP_COUNTERS/GROUP_BITS) * sizeof (u_int32_t)));
-
-  /* Ignore incomplete substrings */
-  while (j < len && j < RABIN_WINDOW_SIZE) rabin_slide8 (data[j++]);
-
-  while (j < len)
-  { u_int64_t hash;
-    u_int32_t ofs, sum;
-    u_char idx;
-    int k;
-
-    hash = rabin_slide8 (data[j++]);
-
-    /* In order to update a much larger frequency table
-       with only 32 bits of checksum, randomly select a
-       part of the table to update. The selection should
-       only depend on the content of the represented data,
-       and be independent of the bits used for the update.
-
-       Instead of updating 32 individual counters, process
-       the checksum in MD_BITS / GROUP_BITS groups of
-       GROUP_BITS bits, and count the frequency of each bit pattern.
-    */
-
-    idx = (hash >> 32);
-    sum = (u_int32_t) hash;
-    ofs = idx % (MD_BITS / NUM_HASHES_PER_CHAR) * NUM_HASHES_PER_CHAR;
-    idx %= DUP_CACHE_SIZE;
-    if (dup_cache[idx] != sum)
-    { dup_cache[idx] = sum;
-      for (k = 0; k < NUM_HASHES_PER_CHAR / GROUP_BITS; k++)
-      { count[ofs * GROUP_COUNTERS / GROUP_BITS + (sum % GROUP_COUNTERS)]++;
-        ofs += GROUP_BITS;
-        sum >>= GROUP_BITS;
-  } } }
-
-  /* Distribute the occurrences of each bit group over the frequency table. */
-  for (ofs = 0; ofs < MD_BITS; ofs += GROUP_BITS)
-  { int j;
-    for (j = 0; j < GROUP_COUNTERS; j++)
-    { int k;
-      for (k = 0; k < GROUP_BITS; k++)
-      { freq[ofs + k] += ((1<<k) & j)
-          ? count[ofs * GROUP_COUNTERS / GROUP_BITS + j]
-          : -count[ofs * GROUP_COUNTERS / GROUP_BITS + j];
-  } } }
-
-  if (md)
-  { rabin_reset();
-    freq_to_md (md, freq);
-} }
diff --git a/gsimm.h b/gsimm.h
deleted file mode 100644 (file)
index 4b023b9..0000000
--- a/gsimm.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef GSIMM_H
-#define GSIMM_H
-
-/* Length of file message digest (MD) in bytes. Longer MD's are
-   better, but increase processing time for diminishing returns.
-   Must be multiple of NUM_HASHES_PER_CHAR / 8, and at least 24
-   for good results
-*/
-#define MD_LENGTH 32
-#define MD_BITS (MD_LENGTH * 8)
-
-/* The MIN_FILE_SIZE indicates the absolute minimal file size that
-   can be processed. As indicated above, the first and last
-   RABIN_WINDOW_SIZE - 1 bytes are skipped.
-   In order to get at least an average of 12 samples
-   per bit in the final message digest, require at least 3 * MD_LENGTH
-   complete windows in the file.  */
-#define MIN_FILE_SIZE (3 * MD_LENGTH + 2 * (RABIN_WINDOW_SIZE - 1))
-
-/* Limit matching algorithm to files less than 256 MB, so we can use
-   32 bit integers everywhere without fear of overflow. For larger
-   files we should add logic to mmap the file by piece and accumulate
-   the frequency counts. */
-#define MAX_FILE_SIZE (256*1024*1024 - 1)
-
-void gb_simm_process(u_char *data, unsigned len, u_char *md);
-
-#endif
diff --git a/rabinpoly.c b/rabinpoly.c
deleted file mode 100644 (file)
index c26f382..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- *
- * Copyright (C) 1999 David Mazieres (dm@uun.org)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- *
- */
-
-  /* Faster generic_fls */
-  /* (c) 2002, D.Phillips and Sistina Software */
-
-#include "rabinpoly.h"
-#define MSB64 0x8000000000000000ULL
-
-static inline unsigned fls8(unsigned n)
-{
-       return n & 0xf0?
-           n & 0xc0? (n >> 7) + 7: (n >> 5) + 5:
-           n & 0x0c? (n >> 3) + 3: n - ((n + 1) >> 2);
-}
-
-static inline unsigned fls16(unsigned n)
-{
-       return n & 0xff00? fls8(n >> 8) + 8: fls8(n);
-}
-
-static inline unsigned fls32(unsigned n)
-{
-       return n & 0xffff0000? fls16(n >> 16) + 16: fls16(n);
-}
-
-static inline unsigned fls64(unsigned long long n) /* should be u64 */
-{
-       return n & 0xffffffff00000000ULL? fls32(n >> 32) + 32: fls32(n);
-}
-
-
-static u_int64_t polymod (u_int64_t nh, u_int64_t nl, u_int64_t d);
-static void      polymult (u_int64_t *php, u_int64_t *plp,
-                           u_int64_t x, u_int64_t y);
-static u_int64_t polymmult (u_int64_t x, u_int64_t y, u_int64_t d);
-
-static u_int64_t poly = 0xb15e234bd3792f63ull; // Actual polynomial
-static u_int64_t T[256];                       // Lookup table for mod
-static int shift;
-
-u_int64_t append8 (u_int64_t p, u_char m)
-{ return ((p << 8) | m) ^ T[p >> shift];
-}
-
-static u_int64_t
-polymod (u_int64_t nh, u_int64_t nl, u_int64_t d)
-{ int i, k;
-  assert (d);
-  k = fls64 (d) - 1;
-  d <<= 63 - k;
-
-  if (nh) {
-    if (nh & MSB64)
-      nh ^= d;
-    for (i = 62; i >= 0; i--)
-      if (nh & 1ULL << i) {
-       nh ^= d >> (63 - i);
-       nl ^= d << (i + 1);
-      }
-  }
-  for (i = 63; i >= k; i--)
-    if (nl & 1ULL << i)
-      nl ^= d >> (63 - i);
-  return nl;
-}
-
-static void
-polymult (u_int64_t *php, u_int64_t *plp, u_int64_t x, u_int64_t y)
-{ int i;
-  u_int64_t ph = 0, pl = 0;
-  if (x & 1)
-    pl = y;
-  for (i = 1; i < 64; i++)
-    if (x & (1ULL << i)) {
-      ph ^= y >> (64 - i);
-      pl ^= y << i;
-    }
-  if (php)
-    *php = ph;
-  if (plp)
-    *plp = pl;
-}
-
-static u_int64_t
-polymmult (u_int64_t x, u_int64_t y, u_int64_t d)
-{
-  u_int64_t h, l;
-  polymult (&h, &l, x, y);
-  return polymod (h, l, d);
-}
-
-static int size = RABIN_WINDOW_SIZE;
-static u_int64_t fingerprint = 0;
-static int bufpos = -1;
-static u_int64_t U[256];
-static u_char buf[RABIN_WINDOW_SIZE];
-
-void rabin_init ()
-{ u_int64_t sizeshift = 1;
- u_int64_t T1;
-  int xshift;
-  int i, j;
-  assert (poly >= 0x100);
-  xshift = fls64 (poly) - 1;
-  shift = xshift - 8;
-  T1 = polymod (0, 1ULL << xshift, poly);
-  for (j = 0; j < 256; j++)
-    T[j] = polymmult (j, T1, poly) | ((u_int64_t) j << xshift);
-
-  for (i = 1; i < size; i++)
-    sizeshift = append8 (sizeshift, 0);
-  for (i = 0; i < 256; i++)
-    U[i] = polymmult (i, sizeshift, poly);
-  bzero (buf, sizeof (buf));
-}
-
-void
-rabin_reset ()
-{ rabin_init();
-  fingerprint = 0;
-  bzero (buf, sizeof (buf));
-}
-
-u_int64_t
-rabin_slide8 (u_char m)
-{ u_char om;
-  if (++bufpos >= size) bufpos = 0;
-
-  om = buf[bufpos];
-  buf[bufpos] = m;
-  fingerprint = append8 (fingerprint ^ U[om], m);
-
-  return fingerprint;
-}
-
diff --git a/rabinpoly.h b/rabinpoly.h
deleted file mode 100644 (file)
index a19a097..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- * Copyright (C) 2000 David Mazieres (dm@uun.org)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- *
- * Translated to C and simplified by Geert Bosch (bosch@gnat.com)
- */
-
-#include <assert.h>
-#include <strings.h>
-#include <sys/types.h>
-
-#ifndef RABIN_WINDOW_SIZE
-#define RABIN_WINDOW_SIZE 48
-#endif
-void rabin_reset();
-u_int64_t rabin_slide8(u_char c);
diff --git a/test-gsimm.c b/test-gsimm.c
deleted file mode 100644 (file)
index bd28b7d..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <stdio.h>
-#include <assert.h>
-#include <math.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include "rabinpoly.h"
-#include "gsimm.h"
-
-#define MIN(x,y) ((y)<(x) ? (y) : (x))
-#define MAX(x,y) ((y)>(x) ? (y) : (x))
-
-/* The RABIN_WINDOW_SIZE is the size of fingerprint window used by
-   Rabin algorithm. This is not a modifiable parameter.
-
-   The first RABIN_WINDOW_SIZE - 1 bytes are skipped, in order to ensure
-   fingerprints are good hashes. This does somewhat reduce the
-   influence of the first few bytes in the file (they're part of
-   fewer windows, like the last few bytes), but that actually isn't
-   so bad as files often start with fixed content that may bias comparisons.
-*/
-
-typedef struct fileinfo
-{ char         *name;
-  size_t       length;
-  u_char       md[MD_LENGTH];
-  int          match;
-} File;
-
-int flag_verbose = 0;
-int flag_debug = 0;
-char *flag_relative = 0;
-
-char cmd[12] = "        ...";
-char md_strbuf[MD_LENGTH * 2 + 1];
-u_char relative_md [MD_LENGTH];
-
-File *file;
-int    file_count;
-size_t file_bytes;
-
-char hex[17] = "0123456789abcdef";
-
-void usage()
-{  fprintf (stderr, "usage: %s [-dhvw] [-r fingerprint] file ...\n", cmd);
-   fprintf (stderr, " -d\tdebug output, repeate for more verbosity\n");
-   fprintf (stderr, " -h\tshow this usage information\n");
-   fprintf (stderr, " -r\tshow distance relative to fingerprint "
-                    "(%u hex digits)\n", MD_LENGTH * 2);
-   fprintf (stderr, " -v\tverbose output, repeat for even more verbosity\n");
-   fprintf (stderr, " -w\tenable warnings for suspect statistics\n");
-   exit (1);
-}
-
-int dist (u_char *l, u_char *r)
-{ int j, k;
-  int d = 0;
-
-  for (j = 0; j < MD_LENGTH; j++)
-  { u_char ch = l[j] ^ r[j];
-
-    for (k = 0; k < 8; k++) d += ((ch & (1<<k)) > 0);
-  }
-
-  return d;
-}
-
-char *md_to_str(u_char *md)
-{ int j;
-
-  for (j = 0; j < MD_LENGTH; j++)
-  { u_char ch = md[j];
-
-    md_strbuf[j*2] = hex[ch >> 4];
-    md_strbuf[j*2+1] = hex[ch & 0xF];
-  }
-
-  md_strbuf[j*2] = 0;
-  return md_strbuf;
-}
-
-void process_file (char *name)
-{ int fd;
-  struct stat fs;
-  u_char *data;
-  File *fi = file+file_count;;
-
-  fd = open (name, O_RDONLY, 0);
-  if (fd < 0)
-  { perror (name);
-    exit (2);
-  }
-
-  if (fstat (fd, &fs))
-  { perror (name);
-    exit (2);
-  }
-
-  if (fs.st_size >= MIN_FILE_SIZE
-      && fs.st_size <= MAX_FILE_SIZE)
-  { fi->length = fs.st_size;
-    fi->name = name;
-
-    data = (u_char *) mmap (0, fs.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-
-    if (data == (u_char *) -1)
-    { perror (name);
-      exit (2);
-    }
-
-    gb_simm_process (data, fs.st_size, fi->md);
-    if (flag_relative)
-    { int d = dist (fi->md, relative_md);
-      double sim = 1.0 - MIN (1.0, (double) (d) / (MD_LENGTH * 4 - 1));
-      fprintf (stdout, "%s %llu %u %s %u %3.1f\n",
-               md_to_str (fi->md), (long long unsigned) 0,
-              (unsigned) fs.st_size, name,
-               d, 100.0 * sim);
-    }
-    else
-    {
-      fprintf (stdout, "%s %llu %u %s\n",
-               md_to_str (fi->md), (long long unsigned) 0,
-              (unsigned) fs.st_size, name);
-    }
-    munmap (data, fs.st_size);
-    file_bytes += fs.st_size;
-    file_count++;
-  } else if (flag_verbose)
-  { fprintf (stdout, "skipping %s (size %llu)\n", name, (long long unsigned) fs.st_size); }
-
-  close (fd);
-}
-
-u_char *str_to_md(char *str, u_char *md)
-{ int j;
-
-  if (!md || !str) return 0;
-
-  bzero (md, MD_LENGTH);
-
-  for (j = 0; j < MD_LENGTH * 2; j++)
-  { char ch = str[j];
-
-    if (ch >= '0' && ch <= '9')
-    { md [j/2] = (md [j/2] << 4) + (ch - '0');
-    }
-    else
-    { ch |= 32;
-
-      if (ch < 'a' || ch > 'f') break;
-      md [j/2] = (md[j/2] << 4) + (ch - 'a' + 10);
-  } }
-
-  return (j != MD_LENGTH * 2 || str[j] != 0) ? 0 : md;
-}
-
-int main (int argc, char *argv[])
-{ int ch, j;
-
-  strncpy (cmd, basename (argv[0]), 8);
-
-  while ((ch = getopt(argc, argv, "dhr:vw")) != -1)
-  { switch (ch)
-    { case 'd': flag_debug++;
-               break;
-      case 'r': if (!optarg)
-                { fprintf (stderr, "%s: missing argument for -r\n", cmd);
-                  return 1;
-                }
-                if (str_to_md (optarg, relative_md)) flag_relative = optarg;
-                else
-                { fprintf (stderr, "%s: not a valid fingerprint\n", optarg);
-                  return 1;
-                }
-                break;
-      case 'v': flag_verbose++;
-                break;
-      case 'w': break;
-      default : usage();
-                return (ch != 'h');
-  } }
-
-  argc -= optind;
-  argv += optind;
-
-  if (argc == 0) usage();
-
-  rabin_reset ();
-  if (flag_verbose && flag_relative)
-  { fprintf (stdout, "distances are relative to %s\n", flag_relative);
-  }
-
-  file = (File *) calloc (argc, sizeof (File));
-
-  for (j = 0; j < argc; j++) process_file (argv[j]);
-
-  if (flag_verbose)
-  { fprintf (stdout, "%li bytes in %i files\n", (long) file_bytes, file_count);
-  }
-
-  return 0;
-}